From 351c6097f3f3c5be2aa2962f841c58810f4dbfd6 Mon Sep 17 00:00:00 2001 From: goynov Date: Tue, 11 Nov 2025 15:15:13 +0200 Subject: [PATCH] change event dispatcher --- .../InteractiveObjects/GenenricObject.js | 6 ++- .../InteractiveObjects/InteractiveObject.js | 38 ++++++------------- .../MazeQuizGame/MazeQuizGame.js | 5 ++- .../InteractiveObjects/PuzzleGame1.js | 9 +++-- .../InteractiveObjects/PuzzleGame2.js | 9 +++-- .../InteractiveObjects/PuzzleGame4.js | 2 +- .../InteractiveObjects/VideoPlayer.js | 23 ++++++----- src/lib/Dashboard.js | 31 +++++++++------ src/lib/GameEngine.js | 6 +-- src/mixins/GameEnvironmentMixin.js | 9 ++--- 10 files changed, 71 insertions(+), 67 deletions(-) diff --git a/src/components/InteractiveObjects/GenenricObject.js b/src/components/InteractiveObjects/GenenricObject.js index 767e590..719caac 100644 --- a/src/components/InteractiveObjects/GenenricObject.js +++ b/src/components/InteractiveObjects/GenenricObject.js @@ -1,7 +1,9 @@ import { getBoundingBox, getBoundingBoxCenterPoint, getBoundingBoxMaxLength, centerOrigin } from "@/lib/MeshUtils"; +import { EventDispatcher } from "three"; -class GenericObject{ +class GenericObject extends EventDispatcher{ constructor(engine, data){ + super(); return new Promise(async(resolve, reject)=>{ this.source = await engine.load(data.$go.asset.name); this.object = centerOrigin(this.source.scene) @@ -34,7 +36,7 @@ class GenericObject{ } if (data.description){ engine.dashboard.updateText(this.object._active ? data.description : '', (d)=>{ - console.log('DONETEXT', d) + d && this.dispatchEvent({type:'finish'}) }) } } diff --git a/src/components/InteractiveObjects/InteractiveObject.js b/src/components/InteractiveObjects/InteractiveObject.js index 7218a0d..b4beb2a 100644 --- a/src/components/InteractiveObjects/InteractiveObject.js +++ b/src/components/InteractiveObjects/InteractiveObject.js @@ -1,4 +1,4 @@ -import { Group } from "three"; +import { Group, EventDispatcher } from "three"; import { GenericObject } from "./GenenricObject"; import { TextObject } from "./TextObject"; @@ -16,12 +16,13 @@ import { Particles } from "./Particles"; import { assignMaterial, assignParams } from "@/lib/MeshUtils"; const InteractiveObjectsImports = { - PuzzleGame1, PuzzleGame2, PuzzleGame4, VideoPlayer, - GenericObject, CharacterObject, MazeQuizGame, Particles + GenericObject, CharacterObject, TextObject, ImageObject, VideoPlayer, Particles, + PuzzleGame1, PuzzleGame2, PuzzleGame4, MazeQuizGame }; -class InteractiveObject { +class InteractiveObject extends EventDispatcher{ constructor(gameEngine, obj) { + super(); this.name = obj.name; return new Promise(async (resolve, reject) => { switch (obj.type || 'GenericObject') { @@ -32,14 +33,6 @@ class InteractiveObject { this.object.add(gameMesh.object); } break; - case 'Text': - this.source = new TextObject(gameEngine, obj); - this.object = this.source.object; - break; - case 'Image': - this.source = new ImageObject(gameEngine, obj); - this.object = this.source.object; - break; case 'Gltf': let gltf = await gameEngine.load(obj.value, ''); let gltfObj = gltf.scene; @@ -63,27 +56,20 @@ class InteractiveObject { this.object = gltfObj; this.source = gltf; break; + + case 'Text': + case 'Image': case 'GenericObject': case 'CharacterObject': - let go = await new InteractiveObjectsImports[obj.type](gameEngine, obj) //await gameEngine.load(obj.$go.asset.name); - this.source = go.source; - this.object = go.object; - break; - case 'PuzzleGame3': - case 'PuzzleGame4': - case 'PuzzleGame5': - case 'PuzzleGame6': - let game = new InteractiveObjectsImports[obj.type](gameEngine, obj.args[0], obj.args[1], obj.args[2]); - this.object = game.object; - this.object.game = game; - break; case 'VideoPlayer': case 'PuzzleGame1': case 'PuzzleGame2': case 'MazeQuizGame': case 'Particles': - this.source = await new InteractiveObjectsImports[obj.type](gameEngine, obj); - this.object = this.source.object; + this.io = await new InteractiveObjectsImports[obj.type](gameEngine, obj); + this.source = this.io.source || this.io; + this.object = this.io.object; + this.io.addEventListener?.('finish', this.dispatchEvent.bind(this)) break; } assignParams(this.object, obj); diff --git a/src/components/InteractiveObjects/MazeQuizGame/MazeQuizGame.js b/src/components/InteractiveObjects/MazeQuizGame/MazeQuizGame.js index 311b9b6..b720b39 100644 --- a/src/components/InteractiveObjects/MazeQuizGame/MazeQuizGame.js +++ b/src/components/InteractiveObjects/MazeQuizGame/MazeQuizGame.js @@ -1,5 +1,6 @@ import { MazeObject } from "./MazeObject"; import Utils from "@/lib/Utils"; +import { EventDispatcher } from "three"; const params = { scale: 5, @@ -34,7 +35,7 @@ const defaults = { const tl = 4; -class MazeQuizGame { +class MazeQuizGame extends EventDispatcher { constructor(engine, data) { data.noPhysics = true; return new Promise(async (resolve, reject)=>{ @@ -57,7 +58,7 @@ class MazeQuizGame { engine.hero.characterControls.direction += Math.PI; //engine.hero.model.rotation.y += Math.PI; await Utils.wait(10000); - this.onfinish?.() + this.dispatchEvent({type:'finish'}) }else{ engine.hero.animationsMap.idle = engine.hero.animationsMap._idle engine.hero.characterControls.cameraDelta = 0 diff --git a/src/components/InteractiveObjects/PuzzleGame1.js b/src/components/InteractiveObjects/PuzzleGame1.js index 9171a54..1007d10 100644 --- a/src/components/InteractiveObjects/PuzzleGame1.js +++ b/src/components/InteractiveObjects/PuzzleGame1.js @@ -1,9 +1,10 @@ -import { BoxGeometry, Mesh, MeshStandardMaterial, Group } from 'three'; +import { BoxGeometry, Mesh, MeshStandardMaterial, Group, EventDispatcher } from 'three'; import { MotionEngine } from '../../lib/MotionEngine'; import { centerOrigin } from '@/lib/MeshUtils'; -class PuzzleGame1 { +class PuzzleGame1 extends EventDispatcher { constructor(engine, data) { + super(); return new Promise(async (resolve, reject)=>{ let w = data.w, h = data.h, wh = w*h; let container = new Group(); @@ -92,7 +93,9 @@ class PuzzleGame1 { o: c, a: { position: { x: i % w, y: Math.trunc(i/w)} }, t: 1, - f: i == 0 && this.onfinish || undefined + f: i == 0 ? ()=>{ + this.dispatchEvent({type:'finish'}) + } : undefined }); }); //engine.dashboard.addPoints(10); diff --git a/src/components/InteractiveObjects/PuzzleGame2.js b/src/components/InteractiveObjects/PuzzleGame2.js index 9bb8b08..c20d87a 100644 --- a/src/components/InteractiveObjects/PuzzleGame2.js +++ b/src/components/InteractiveObjects/PuzzleGame2.js @@ -1,9 +1,10 @@ -import { BoxGeometry, Mesh, MeshBasicMaterial, Group } from 'three'; +import { BoxGeometry, Mesh, MeshBasicMaterial, Group, EventDispatcher } from 'three'; import { MotionEngine } from '../../lib/MotionEngine'; import { centerOrigin } from '@/lib/MeshUtils'; -class PuzzleGame2 { +class PuzzleGame2 extends EventDispatcher { constructor(engine, data) { + super(); return new Promise(async (resolve, reject)=>{ let w = data.w, h = data.h, wh = w*h; const texture = await engine.loadTexture(data.$go.asset.name); @@ -137,7 +138,9 @@ class PuzzleGame2 { o: c, a: { position: { x: i % w, y: ~~(i / h) } }, t: 1, - f: i == 0 ? this.onfinish : undefined + f: i == 0 ? ()=>{ + this.dispatchEvent({type:'finish'}) + } : undefined }); }); //engine.dashboard.addPoints(10); diff --git a/src/components/InteractiveObjects/PuzzleGame4.js b/src/components/InteractiveObjects/PuzzleGame4.js index 56e148d..3f8457f 100644 --- a/src/components/InteractiveObjects/PuzzleGame4.js +++ b/src/components/InteractiveObjects/PuzzleGame4.js @@ -115,7 +115,7 @@ var PuzzleGame4 = function(context, gltf, w, h){ d:1+0.1*i }) }) - this.onfinish && this.onfinish(); + this.dispatchEvent({type:'finish'}) //context.dashboard.addPoints(10); } } diff --git a/src/components/InteractiveObjects/VideoPlayer.js b/src/components/InteractiveObjects/VideoPlayer.js index b8e23c5..3eecf96 100644 --- a/src/components/InteractiveObjects/VideoPlayer.js +++ b/src/components/InteractiveObjects/VideoPlayer.js @@ -1,25 +1,28 @@ -import * as THREE from 'three'; +import { + PlaneGeometry, MeshStandardMaterial, SRGBColorSpace, + VideoTexture, DoubleSide, Mesh, EventDispatcher +} from 'three'; - -class VideoPlayer { +class VideoPlayer extends EventDispatcher { constructor(engine, data){ + super(); let vi, plane; return new Promise((resolve, reject)=>{ vi = document.createElement('video'); vi.src = engine.assetPath + data.$go.asset.name; vi.addEventListener('loadedmetadata', ()=>{ this.aspect = vi.videoWidth / vi.videoHeight; - let geometry = new THREE.PlaneGeometry( this.aspect, 1 ); - let map = new THREE.VideoTexture( vi ); - map.colorSpace = THREE.SRGBColorSpace; - let material = new THREE.MeshStandardMaterial( { + let geometry = new PlaneGeometry( this.aspect, 1 ); + let map = new VideoTexture( vi ); + map.colorSpace = SRGBColorSpace; + let material = new MeshStandardMaterial( { color: 0xffffff, map, transparent: true, opacity: 0.5, - side: THREE.DoubleSide + side: DoubleSide } ); - plane = new THREE.Mesh( geometry, material ); + plane = new Mesh( geometry, material ); this.object = plane; engine.clickable.add(plane, ()=>{ if (vi.paused){ @@ -46,7 +49,7 @@ class VideoPlayer { } }) vi.addEventListener('ended', ()=>{ - this.onfinish?.(); + this.dispatchEvent({type:'finish'}) }) this.video = vi; diff --git a/src/lib/Dashboard.js b/src/lib/Dashboard.js index 3f43da8..bb6a236 100644 --- a/src/lib/Dashboard.js +++ b/src/lib/Dashboard.js @@ -53,11 +53,13 @@ class DashBoard { const loadingPlane = new Mesh( new PlaneGeometry(engine.aspect, 1), - new MeshBasicMaterial({ - color:0xFAFAFA, + new MeshStandardMaterial({ + color:0xffffff, + opacity:0, transparent:true, + roughness:0, metalness:0.1 }) ); - const loadingProgress = new ProgressBar(); + const loadingProgress = new ProgressBar(engine); loadingProgress.object.scale.set(engine.aspect*0.8, 0.05, 0.05) loadingProgress.object.position.set(-engine.aspect/2 + engine.aspect*0.1, 0, 0.1) loadingPlane.add(loadingProgress.object); @@ -135,7 +137,7 @@ class DashBoard { }) } - levelProgress = new ProgressBar({}) + levelProgress = new ProgressBar(engine) dash.add(levelProgress.object); levelProgress.object.position.set(-engine.aspect/2 + engine.aspect/30, 0.45, -0.01) levelProgress.object.scale.set(engine.aspect/3, 0.02, 0.02) @@ -230,11 +232,11 @@ class DashBoard { hudAnimation = null; } - this.loading = function(progress){ + this.loading = function(progress, tt){ loadingPlane.visible = progress > 0 && progress < 1; - loadingProgress.update(progress) + loadingProgress.update(progress, tt) } - this.loading(1); + this.loading(0,0); } get active(){ @@ -247,7 +249,7 @@ class DashBoard { } class ProgressBar{ - constructor(params = {}){ + constructor(engine, params = {}){ this.object = new Group(); const geometry = new CylinderGeometry( 0.5, 0.5, 1, 3, 1, false, 0, Math.PI ); const staticCylinder = new Mesh( geometry, new MeshStandardMaterial({ @@ -263,10 +265,17 @@ class ProgressBar{ progressCylinder.rotation.set(Math.PI/2, 0, Math.PI/2,) this.object.add( progressCylinder ); - this.update = function(value){ + this.update = function(value, transitionTime = 0.5){ progressCylinder.visible = !!value; - progressCylinder.scale.y = value; - progressCylinder.position.x = progressCylinder.scale.y / 2 + engine.motionQueue.clear(progressCylinder); + engine.motionQueue.add({ + o: progressCylinder, + a: { + scale: {y: value}, + position: {x: value / 2} + }, + t: transitionTime + }) } this.update(0) diff --git a/src/lib/GameEngine.js b/src/lib/GameEngine.js index dc9c2ad..895c369 100644 --- a/src/lib/GameEngine.js +++ b/src/lib/GameEngine.js @@ -99,12 +99,12 @@ class GameEngine extends THREE.EventDispatcher{ this.stereo = new StereoEffect(renderer); this.stereo.setSize(this.w, this.h); - const dashboard = new DashBoard(this); - this.dashboard = dashboard; - this.motionQueue = new MotionEngine(); this.assetPath = assetPath; + const dashboard = new DashBoard(this); + this.dashboard = dashboard; + this.activeObjects = new THREE.Group(); scene.add(this.activeObjects); diff --git a/src/mixins/GameEnvironmentMixin.js b/src/mixins/GameEnvironmentMixin.js index d53cdbb..3159bfc 100644 --- a/src/mixins/GameEnvironmentMixin.js +++ b/src/mixins/GameEnvironmentMixin.js @@ -119,7 +119,7 @@ export default { //await gameEngine.loadPanorama(`/asset/default/43.webp`); gameEngine.clearScene(); gameEngine.activeObjects.visible = false; - gameEngine.dashboard?.loading(0); + gameEngine.dashboard?.loading(0,0); await this.expandScenarioData(scene); gameEngine.dashboard?.loading(0.1); @@ -147,9 +147,6 @@ export default { let loaded = 0; for (let i of this.scene.data.items) { let io = await new InteractiveObject(gameEngine, i.data) - - //let gltf = await gameEngine.load(`/asset/default/${i.data.$go.asset.name}`); - //console.log(i.data, io.object) this.setObjectAttributes(l, i.data, io.object, io.source, 1); gameEngine.activeObjects.add(io.object); if (this.env == 'GamePlaying'){ @@ -169,10 +166,10 @@ export default { }) } } - io.onfinish=()=>{ + io.addEventListener('finish', ()=>{ gameEngine.dashboard?.addPoints(i.data.points) i.data.points = 0; - } + }) } loaded += 1/this.scene.data.items.length gameEngine.dashboard?.loading(0.1 + 0.89*loaded);