Adds the camera to available APIs with retrieving of the worldView
This commit is contained in:
parent
99dfd77600
commit
5b6a8ca4d7
@ -69,7 +69,7 @@ You need to wait for the end of the initialization before calling `WA.player.get
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
WA.onInit().then(() => {
|
WA.onInit().then(() => {
|
||||||
console.log('Tags: ', WA.player.getPosition());
|
console.log('Position: ', WA.player.getPosition());
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
18
front/src/Api/Events/HasCameraMovedEvent.ts
Normal file
18
front/src/Api/Events/HasCameraMovedEvent.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const isHasCameraMovedEvent = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
x: tg.isNumber,
|
||||||
|
y: tg.isNumber,
|
||||||
|
width: tg.isNumber,
|
||||||
|
height: tg.isNumber,
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message sent from the game to the iFrame to notify a movement from the camera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type HasCameraMovedEvent = tg.GuardedType<typeof isHasCameraMovedEvent>;
|
||||||
|
|
||||||
|
export type HasCameraMovedEventCallback = (event: HasCameraMovedEvent) => void;
|
@ -30,6 +30,7 @@ import type { MenuRegisterEvent, UnregisterMenuEvent } from "./ui/MenuRegisterEv
|
|||||||
import type { ChangeLayerEvent } from "./ChangeLayerEvent";
|
import type { ChangeLayerEvent } from "./ChangeLayerEvent";
|
||||||
import { isPlayerPropertyEvent } from "./PlayerPropertyEvent";
|
import { isPlayerPropertyEvent } from "./PlayerPropertyEvent";
|
||||||
import { isPlayerPosition } from "./PlayerPosition";
|
import { isPlayerPosition } from "./PlayerPosition";
|
||||||
|
import type { HasCameraMovedEvent } from "./HasCameraMovedEvent";
|
||||||
|
|
||||||
export interface TypedMessageEvent<T> extends MessageEvent {
|
export interface TypedMessageEvent<T> extends MessageEvent {
|
||||||
data: T;
|
data: T;
|
||||||
@ -50,6 +51,7 @@ export type IframeEventMap = {
|
|||||||
displayBubble: null;
|
displayBubble: null;
|
||||||
removeBubble: null;
|
removeBubble: null;
|
||||||
onPlayerMove: undefined;
|
onPlayerMove: undefined;
|
||||||
|
onCameraMove: undefined;
|
||||||
showLayer: LayerEvent;
|
showLayer: LayerEvent;
|
||||||
hideLayer: LayerEvent;
|
hideLayer: LayerEvent;
|
||||||
setProperty: SetPropertyEvent;
|
setProperty: SetPropertyEvent;
|
||||||
@ -80,6 +82,7 @@ export interface IframeResponseEventMap {
|
|||||||
leaveLayerEvent: ChangeLayerEvent;
|
leaveLayerEvent: ChangeLayerEvent;
|
||||||
buttonClickedEvent: ButtonClickedEvent;
|
buttonClickedEvent: ButtonClickedEvent;
|
||||||
hasPlayerMoved: HasPlayerMovedEvent;
|
hasPlayerMoved: HasPlayerMovedEvent;
|
||||||
|
hasCameraMoved: HasCameraMovedEvent;
|
||||||
menuItemClicked: MenuItemClickedEvent;
|
menuItemClicked: MenuItemClickedEvent;
|
||||||
setVariable: SetVariableEvent;
|
setVariable: SetVariableEvent;
|
||||||
messageTriggered: MessageReferenceEvent;
|
messageTriggered: MessageReferenceEvent;
|
||||||
|
@ -31,6 +31,7 @@ import type { SetVariableEvent } from "./Events/SetVariableEvent";
|
|||||||
import { ModifyEmbeddedWebsiteEvent, isEmbeddedWebsiteEvent } from "./Events/EmbeddedWebsiteEvent";
|
import { ModifyEmbeddedWebsiteEvent, isEmbeddedWebsiteEvent } from "./Events/EmbeddedWebsiteEvent";
|
||||||
import { handleMenuRegistrationEvent, handleMenuUnregisterEvent } from "../Stores/MenuStore";
|
import { handleMenuRegistrationEvent, handleMenuUnregisterEvent } from "../Stores/MenuStore";
|
||||||
import type { ChangeLayerEvent } from "./Events/ChangeLayerEvent";
|
import type { ChangeLayerEvent } from "./Events/ChangeLayerEvent";
|
||||||
|
import type { HasCameraMovedEvent } from "./Events/HasCameraMovedEvent";
|
||||||
|
|
||||||
type AnswererCallback<T extends keyof IframeQueryMap> = (
|
type AnswererCallback<T extends keyof IframeQueryMap> = (
|
||||||
query: IframeQueryMap[T]["query"],
|
query: IframeQueryMap[T]["query"],
|
||||||
@ -94,6 +95,7 @@ class IframeListener {
|
|||||||
private readonly iframeCloseCallbacks = new Map<HTMLIFrameElement, (() => void)[]>();
|
private readonly iframeCloseCallbacks = new Map<HTMLIFrameElement, (() => void)[]>();
|
||||||
private readonly scripts = new Map<string, HTMLIFrameElement>();
|
private readonly scripts = new Map<string, HTMLIFrameElement>();
|
||||||
private sendPlayerMove: boolean = false;
|
private sendPlayerMove: boolean = false;
|
||||||
|
private sendCameraMove: boolean = false;
|
||||||
|
|
||||||
// Note: we are forced to type this in unknown and later cast with "as" because of https://github.com/microsoft/TypeScript/issues/31904
|
// Note: we are forced to type this in unknown and later cast with "as" because of https://github.com/microsoft/TypeScript/issues/31904
|
||||||
private answerers: {
|
private answerers: {
|
||||||
@ -225,6 +227,8 @@ class IframeListener {
|
|||||||
this._removeBubbleStream.next();
|
this._removeBubbleStream.next();
|
||||||
} else if (payload.type == "onPlayerMove") {
|
} else if (payload.type == "onPlayerMove") {
|
||||||
this.sendPlayerMove = true;
|
this.sendPlayerMove = true;
|
||||||
|
} else if (payload.type == "onCameraMove") {
|
||||||
|
this.sendCameraMove = true;
|
||||||
} else if (payload.type == "setTiles" && isSetTilesEvent(payload.data)) {
|
} else if (payload.type == "setTiles" && isSetTilesEvent(payload.data)) {
|
||||||
this._setTilesStream.next(payload.data);
|
this._setTilesStream.next(payload.data);
|
||||||
} else if (payload.type == "modifyEmbeddedWebsite" && isEmbeddedWebsiteEvent(payload.data)) {
|
} else if (payload.type == "modifyEmbeddedWebsite" && isEmbeddedWebsiteEvent(payload.data)) {
|
||||||
@ -423,6 +427,15 @@ class IframeListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasCameraMoved(event: HasCameraMovedEvent) {
|
||||||
|
if (this.sendCameraMove) {
|
||||||
|
this.postMessage({
|
||||||
|
type: "hasCameraMoved",
|
||||||
|
data: event,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sendButtonClickedEvent(popupId: number, buttonId: number): void {
|
sendButtonClickedEvent(popupId: number, buttonId: number): void {
|
||||||
this.postMessage({
|
this.postMessage({
|
||||||
type: "buttonClickedEvent",
|
type: "buttonClickedEvent",
|
||||||
|
@ -13,7 +13,7 @@ export class EmbeddedWebsite {
|
|||||||
private _allowApi: boolean;
|
private _allowApi: boolean;
|
||||||
private _position: Rectangle;
|
private _position: Rectangle;
|
||||||
private readonly origin: "map" | "player" | undefined;
|
private readonly origin: "map" | "player" | undefined;
|
||||||
private _scale: number | undefined;
|
private _scale: number;
|
||||||
|
|
||||||
constructor(private config: CreateEmbeddedWebsiteEvent) {
|
constructor(private config: CreateEmbeddedWebsiteEvent) {
|
||||||
this.name = config.name;
|
this.name = config.name;
|
||||||
@ -23,7 +23,7 @@ export class EmbeddedWebsite {
|
|||||||
this._allowApi = config.allowApi ?? false;
|
this._allowApi = config.allowApi ?? false;
|
||||||
this._position = config.position;
|
this._position = config.position;
|
||||||
this.origin = config.origin;
|
this.origin = config.origin;
|
||||||
this._scale = config.scale;
|
this._scale = config.scale ?? 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get url() {
|
public get url() {
|
||||||
@ -116,7 +116,7 @@ export class EmbeddedWebsite {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public get scale() {
|
public get scale(): number {
|
||||||
return this._scale;
|
return this._scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
front/src/Api/iframe/camera.ts
Normal file
29
front/src/Api/iframe/camera.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution";
|
||||||
|
import { Subject } from "rxjs";
|
||||||
|
import type { HasCameraMovedEvent, HasCameraMovedEventCallback } from "../Events/HasCameraMovedEvent";
|
||||||
|
import { apiCallback } from "./registeredCallbacks";
|
||||||
|
import { isHasCameraMovedEvent } from "../Events/HasCameraMovedEvent";
|
||||||
|
|
||||||
|
const moveStream = new Subject<HasCameraMovedEvent>();
|
||||||
|
|
||||||
|
export class WorkAdventureCameraCommands extends IframeApiContribution<WorkAdventureCameraCommands> {
|
||||||
|
callbacks = [
|
||||||
|
apiCallback({
|
||||||
|
type: "hasCameraMoved",
|
||||||
|
typeChecker: isHasCameraMovedEvent,
|
||||||
|
callback: (payloadData) => {
|
||||||
|
moveStream.next(payloadData);
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
onCameraMove(callback: HasCameraMovedEventCallback): void {
|
||||||
|
moveStream.subscribe(callback);
|
||||||
|
sendToWorkadventure({
|
||||||
|
type: "onCameraMove",
|
||||||
|
data: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new WorkAdventureCameraCommands();
|
@ -30,6 +30,7 @@ export class EmbeddedWebsiteManager {
|
|||||||
height: rect["height"],
|
height: rect["height"],
|
||||||
},
|
},
|
||||||
origin: website.origin,
|
origin: website.origin,
|
||||||
|
scale: website.scale,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -89,6 +89,8 @@ import { get } from "svelte/store";
|
|||||||
import { contactPageStore } from "../../Stores/MenuStore";
|
import { contactPageStore } from "../../Stores/MenuStore";
|
||||||
import { GameMapProperties } from "./GameMapProperties";
|
import { GameMapProperties } from "./GameMapProperties";
|
||||||
import SpriteSheetFile = Phaser.Loader.FileTypes.SpriteSheetFile;
|
import SpriteSheetFile = Phaser.Loader.FileTypes.SpriteSheetFile;
|
||||||
|
import Camera = Phaser.Cameras.Scene2D.Camera;
|
||||||
|
import type { HasCameraMovedEvent } from "../../Api/Events/HasCameraMovedEvent";
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface | null;
|
initPosition: PointInterface | null;
|
||||||
@ -750,6 +752,17 @@ export class GameScene extends DirtyScene {
|
|||||||
this.gameMap.setPosition(event.x, event.y);
|
this.gameMap.setPosition(event.x, event.y);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//listen event to share the actual worldView when the camera is updated
|
||||||
|
this.cameras.main.on("followupdate", (camera: Camera) => {
|
||||||
|
const worldView: HasCameraMovedEvent = {
|
||||||
|
x: camera.worldView.x,
|
||||||
|
y: camera.worldView.y,
|
||||||
|
width: camera.worldView.width,
|
||||||
|
height: camera.worldView.height,
|
||||||
|
};
|
||||||
|
iframeListener.hasCameraMoved(worldView);
|
||||||
|
});
|
||||||
|
|
||||||
// Set up variables manager
|
// Set up variables manager
|
||||||
this.sharedVariablesManager = new SharedVariablesManager(
|
this.sharedVariablesManager = new SharedVariablesManager(
|
||||||
this.connection,
|
this.connection,
|
||||||
|
@ -20,6 +20,7 @@ import type { ButtonDescriptor } from "./Api/iframe/Ui/ButtonDescriptor";
|
|||||||
import type { Popup } from "./Api/iframe/Ui/Popup";
|
import type { Popup } from "./Api/iframe/Ui/Popup";
|
||||||
import type { Sound } from "./Api/iframe/Sound/Sound";
|
import type { Sound } from "./Api/iframe/Sound/Sound";
|
||||||
import { answerPromises, queryWorkadventure } from "./Api/iframe/IframeApiContribution";
|
import { answerPromises, queryWorkadventure } from "./Api/iframe/IframeApiContribution";
|
||||||
|
import camera from "./Api/iframe/camera";
|
||||||
|
|
||||||
const globalState = createState("global");
|
const globalState = createState("global");
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ const wa = {
|
|||||||
sound,
|
sound,
|
||||||
room,
|
room,
|
||||||
player,
|
player,
|
||||||
|
camera,
|
||||||
state: globalState,
|
state: globalState,
|
||||||
|
|
||||||
onInit(): Promise<void> {
|
onInit(): Promise<void> {
|
||||||
|
Loading…
Reference in New Issue
Block a user