diff --git a/front/src/Api/Events/WasCameraUpdatedEvent.ts b/front/src/Api/Events/WasCameraUpdatedEvent.ts index 8f37753c..34e39a84 100644 --- a/front/src/Api/Events/WasCameraUpdatedEvent.ts +++ b/front/src/Api/Events/WasCameraUpdatedEvent.ts @@ -6,6 +6,7 @@ export const isWasCameraUpdatedEvent = new tg.IsInterface() y: tg.isNumber, width: tg.isNumber, height: tg.isNumber, + zoom: tg.isNumber, }) .get(); diff --git a/front/src/Api/IframeListener.ts b/front/src/Api/IframeListener.ts index b790c0ca..3c79bbe2 100644 --- a/front/src/Api/IframeListener.ts +++ b/front/src/Api/IframeListener.ts @@ -87,6 +87,9 @@ class IframeListener { private readonly _loadSoundStream: Subject = new Subject(); public readonly loadSoundStream = this._loadSoundStream.asObservable(); + private readonly _trackCameraUpdateStream: Subject = new Subject(); + public readonly trackCameraUpdateStream = this._trackCameraUpdateStream.asObservable(); + private readonly _setTilesStream: Subject = new Subject(); public readonly setTilesStream = this._setTilesStream.asObservable(); @@ -97,7 +100,6 @@ class IframeListener { private readonly iframeCloseCallbacks = new Map void)[]>(); private readonly scripts = new Map(); private sendPlayerMove: boolean = false; - private sendCameraUpdate: 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 private answerers: { @@ -230,7 +232,7 @@ class IframeListener { } else if (payload.type == "onPlayerMove") { this.sendPlayerMove = true; } else if (payload.type == "onCameraUpdate") { - this.sendCameraUpdate = true; + this._trackCameraUpdateStream.next(); } else if (payload.type == "setTiles" && isSetTilesEvent(payload.data)) { this._setTilesStream.next(payload.data); } else if (payload.type == "modifyEmbeddedWebsite" && isEmbeddedWebsiteEvent(payload.data)) { @@ -448,12 +450,10 @@ class IframeListener { } sendCameraUpdated(event: WasCameraUpdatedEvent) { - if (this.sendCameraUpdate) { - this.postMessage({ - type: "wasCameraUpdated", - data: event, - }); - } + this.postMessage({ + type: "wasCameraUpdated", + data: event, + }); } sendButtonClickedEvent(popupId: number, buttonId: number): void { diff --git a/front/src/Phaser/Game/EmbeddedWebsiteManager.ts b/front/src/Phaser/Game/EmbeddedWebsiteManager.ts index d58d7eaf..387940c7 100644 --- a/front/src/Phaser/Game/EmbeddedWebsiteManager.ts +++ b/front/src/Phaser/Game/EmbeddedWebsiteManager.ts @@ -16,7 +16,8 @@ export class EmbeddedWebsiteManager { if (website === undefined) { throw new Error('Cannot find embedded website with name "' + name + '"'); } - const rect = website.iframe.getBoundingClientRect(); + + const scale = website.scale ?? 1; return { url: website.url, name: website.name, @@ -26,8 +27,8 @@ export class EmbeddedWebsiteManager { position: { x: website.phaserObject.x, y: website.phaserObject.y, - width: website.phaserObject.width, - height: website.phaserObject.height, + width: website.phaserObject.width * scale, + height: website.phaserObject.height * scale, }, origin: website.origin, scale: website.scale, diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 55599510..ec12aae8 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -212,6 +212,8 @@ export class GameScene extends DirtyScene { private objectsByType = new Map(); private embeddedWebsiteManager!: EmbeddedWebsiteManager; private loader: Loader; + private lastCameraEvent: WasCameraUpdatedEvent | undefined; + private firstCameraUpdateSent: boolean = false; constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) { super({ @@ -785,17 +787,6 @@ export class GameScene extends DirtyScene { 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 cameraEvent: WasCameraUpdatedEvent = { - x: camera.worldView.x, - y: camera.worldView.y, - width: camera.worldView.width, - height: camera.worldView.height, - }; - iframeListener.sendCameraUpdated(cameraEvent); - }); - // Set up variables manager this.sharedVariablesManager = new SharedVariablesManager( this.connection, @@ -1115,9 +1106,33 @@ ${escapedMessage} ); this.iframeSubscriptionList.push( - iframeListener.stopSoundStream.subscribe((stopSoundEvent) => { - const url = new URL(stopSoundEvent.url, this.MapUrlFile); - soundManager.stopSound(this.sound, url.toString()); + iframeListener.trackCameraUpdateStream.subscribe(() => { + if (!this.firstCameraUpdateSent) { + this.cameras.main.on("followupdate", (camera: Camera) => { + const cameraEvent: WasCameraUpdatedEvent = { + x: camera.worldView.x, + y: camera.worldView.y, + width: camera.worldView.width, + height: camera.worldView.height, + zoom: camera.scaleManager.zoom, + }; + if ( + this.lastCameraEvent?.x == cameraEvent.x && + this.lastCameraEvent?.y == cameraEvent.y && + this.lastCameraEvent?.width == cameraEvent.width && + this.lastCameraEvent?.height == cameraEvent.height && + this.lastCameraEvent?.zoom == cameraEvent.zoom + ) { + return; + } + + this.lastCameraEvent = cameraEvent; + iframeListener.sendCameraUpdated(cameraEvent); + this.firstCameraUpdateSent = true; + }); + + iframeListener.sendCameraUpdated(this.cameras.main); + } }) ); @@ -1180,6 +1195,12 @@ ${escapedMessage} }) ); + this.iframeSubscriptionList.push( + iframeListener.setPropertyStream.subscribe((setProperty) => { + this.setPropertyLayer(setProperty.layerName, setProperty.propertyName, setProperty.propertyValue); + }) + ); + iframeListener.registerAnswerer("openCoWebsite", async (openCoWebsite, source) => { if (!source) { throw new Error("Unknown query source"); @@ -1986,6 +2007,7 @@ ${escapedMessage} this.loader.resize(); } + private getObjectLayerData(objectName: string): ITiledMapObject | undefined { for (const layer of this.mapFile.layers) { if (layer.type === "objectgroup" && layer.name === "floorLayer") { @@ -1998,6 +2020,7 @@ ${escapedMessage} } return undefined; } + private reposition(): void { // Recompute camera offset if needed biggestAvailableAreaStore.recompute();