From c611cb6439323a73de3206118de784e670df5c0b Mon Sep 17 00:00:00 2001 From: goynov Date: Sat, 18 Apr 2026 15:23:49 +0300 Subject: [PATCH] refactor XR controller handling in design mode --- .env | 5 +- backend/app/Config.js | 6 +- src/components/GameDesigner/GameDesigner.vue | 42 +++++++++++-- src/components/GamePlay/GamePlay.vue | 1 - src/components/GamePreview/GamePreview.vue | 3 +- src/lib/Clickable.js | 3 +- src/lib/Dashboard.js | 8 +-- src/lib/Draggable.js | 3 +- src/lib/GameEngine.js | 64 ++++++-------------- src/lib/Hero.js | 2 +- vite.config.mjs | 6 +- 11 files changed, 78 insertions(+), 65 deletions(-) diff --git a/.env b/.env index 758a290..013172b 100644 --- a/.env +++ b/.env @@ -1,3 +1,6 @@ NODE_ENV=development SRV_PORT=3000 -SRV_SSL=1 \ No newline at end of file +SRV_SSL=1 +DB_NAME="pronature_beta" +DB_URL="mongodb://127.0.0.1:27017/pronature" +FS_REPO="C:/IMI/ProNature/production/repo/" \ No newline at end of file diff --git a/backend/app/Config.js b/backend/app/Config.js index 3406714..f65d7c3 100644 --- a/backend/app/Config.js +++ b/backend/app/Config.js @@ -16,7 +16,7 @@ class Config{ * @type {string} * @memberof FileSystemOptions */ - repo: null + repo: pe.FS_REPO || null } /** @@ -29,13 +29,13 @@ class Config{ * @type {string} * @memberof DatabaseOptions */ - name:'pronature', + name:pe.DB_NAME || 'pronature', /** Database connection string, данни за свързване с базата от данни * @type {string} * @memberof DatabaseOptions */ - url: "mongodb://127.0.0.1:27017/pronature" + url: pe.DB_URL || "mongodb://127.0.0.1:27017/pronature" } /** diff --git a/src/components/GameDesigner/GameDesigner.vue b/src/components/GameDesigner/GameDesigner.vue index 1073580..7ce7e77 100644 --- a/src/components/GameDesigner/GameDesigner.vue +++ b/src/components/GameDesigner/GameDesigner.vue @@ -148,6 +148,7 @@ export default { value: s.data.id })) window.addEventListener('resize', this.resize); + engine.addEventListener('controller', this.onController); }, async unmounted(){ @@ -249,14 +250,45 @@ export default { })); }, + onController(event){ + engine.transformControls.getRaycaster().setFromXRController(event.data.target); + switch (event.data.type) { + case 'selectstart': + engine.transformControls.pointerDown(null); + break; + case 'selectend': + engine.transformControls.pointerUp(null); + break; + case 'move': + engine.transformControls.pointerHover(null); + engine.transformControls.pointerMove(null); + break; + case 'select': + this.intersect(); + break; + } + }, + targetClick(e){ if (performance.now() - this.pointerDownTime < 200){ - let intersects = engine.intersect(e, this.$refs.target, this.flatObjects.map(o=>o.value.__o), true); - if (intersects.length){ - this.selectObject(intersects[0].object.__pn_id) - }else{ - engine.transformControls.detach(); + let mouse = engine.getMouseVector(e, this.$refs.target); + engine.transformControls.getRaycaster().setFromCamera(mouse, engine.camera); + this.intersect() + } + }, + + intersect(){ + let objects = this.flatObjects.map(o=>o.value.__o).filter(o => o.visible); + let intersects = engine.transformControls.getRaycaster().intersectObjects(objects, true); + intersects.forEach(o => { + while (o.object && !objects.includes(o.object)) { + o.object = o.object.parent; } + }) + if (intersects.length){ + this.selectObject(intersects[0].object.__pn_id) + }else{ + engine.transformControls.detach(); } }, diff --git a/src/components/GamePlay/GamePlay.vue b/src/components/GamePlay/GamePlay.vue index 56c1b9f..7c07390 100644 --- a/src/components/GamePlay/GamePlay.vue +++ b/src/components/GamePlay/GamePlay.vue @@ -53,7 +53,6 @@ export default { resize(){ let r = this.$refs.target; - this.debug('resizing', r.clientWidth, r.clientHeight, r) engine.resize(r.clientWidth, r.clientHeight); }, diff --git a/src/components/GamePreview/GamePreview.vue b/src/components/GamePreview/GamePreview.vue index dd9bfb9..f4c4bad 100644 --- a/src/components/GamePreview/GamePreview.vue +++ b/src/components/GamePreview/GamePreview.vue @@ -40,7 +40,7 @@ export default { xr: true, gizmo: false, stats: true, - depthSense: this.store.prefs.xr.depthSense, + //depthSense: this.store.prefs.xr.depthSense, mode: 'GamePreview' }); manager = await new GameManager(engine, this.id); @@ -75,7 +75,6 @@ export default { }, resize(){ let r = this.$refs.target; - this.debug('resizing', r.clientWidth, r.clientHeight, r) engine.resize(r.clientWidth, r.clientHeight); }, diff --git a/src/lib/Clickable.js b/src/lib/Clickable.js index 54cd63a..3c7b785 100644 --- a/src/lib/Clickable.js +++ b/src/lib/Clickable.js @@ -33,7 +33,8 @@ class Clickable { this.handle = function(){ let forExecute = []; - engine.hero.model.getWorldPosition(cv); + let target = engine.hero?.model || engine.cameraWorld; + target.getWorldPosition(cv); objects.filter(o=>{ do { if (o.__active === false || o.visible === false) return false; diff --git a/src/lib/Dashboard.js b/src/lib/Dashboard.js index 0644cb8..6737b8e 100644 --- a/src/lib/Dashboard.js +++ b/src/lib/Dashboard.js @@ -28,7 +28,7 @@ class DashBoard extends EventManager { dash.renderOrder = 1000; const k = 3.11; const dashWidth = engine.aspect * k, dashHeight = k; - const dashDistance = 0.11; + const dashDistance = -0.2; this.width = dashWidth; this.height = dashHeight; @@ -119,15 +119,15 @@ class DashBoard extends EventManager { engine.renderer.xr.addEventListener('sessionstart', this.orient) this.orient = function(){ - let object = engine.camera, dk = 1; + let object = engine.camera, dd = dashDistance; if (engine.renderer.xr.isPresenting){ - dk = 17; + dd = 1.55; } // dash.quaternion.copy(object.quaternion) dash.rotation.y = object.rotation.y; dash.position.copy(object.position) //dash.position.set(0,0,0); - dash.translateZ(-dashDistance * dk -(dashHeight/2)/Math.tan(engine.camera.fov/2 * Math.PI/180) * engine.camera.zoom); + dash.translateZ(-dd -(dashHeight/2)/Math.tan(engine.camera.fov/2 * Math.PI/180) * engine.camera.zoom); } this.orient(); diff --git a/src/lib/Draggable.js b/src/lib/Draggable.js index 559ab07..4502ebe 100644 --- a/src/lib/Draggable.js +++ b/src/lib/Draggable.js @@ -29,7 +29,8 @@ class Draggable{ this.handle = function(action){ if (['start', 'selectstart'].includes(action)){ let forExecute = []; - engine.hero.model.getWorldPosition(cv); + let target = engine.hero?.model || engine.cameraWorld; + target.getWorldPosition(cv); objects.filter(o=>{ do { if (o.__active === false || o.visible === false) return false; diff --git a/src/lib/GameEngine.js b/src/lib/GameEngine.js index 84d8077..0349e91 100644 --- a/src/lib/GameEngine.js +++ b/src/lib/GameEngine.js @@ -199,7 +199,7 @@ class GameEngine extends EventManager{ this.renderType = 'ST'; - this.handleXrAction = ['ObjectPreview', 'DesignMode'].includes(opts.mode) ? this.handleXrActionDesignMode : this.handleXrActionGameMode; + this.handleXrAction = ['ObjectPreview', 'GameDesigner'].includes(opts.mode) ? this.handleXrActionDesignMode : this.handleXrActionGameMode; if (opts.stats){ this.stats = new Stats(); @@ -281,22 +281,9 @@ class GameEngine extends EventManager{ onControllerEvent: (event=>{ const controller = event.target; if (!controller.userData?.active) return; + this.dispatchEvent({type: 'controller', data: event}) - if (this.opts.designMode){ - this.transformControls.getRaycaster().setFromXRController(controller); - switch (event.type) { - case 'selectstart': - this.transformControls.pointerDown(null); - break; - case 'selectend': - this.transformControls.pointerUp(null); - break; - case 'move': - this.transformControls.pointerHover(null); - this.transformControls.pointerMove(null); - break; - } - }else{ + if (this.opts.mode != 'GameDesigner'){ this.draggable?.handleController(controller, event.type) } }).bind(this), @@ -316,22 +303,9 @@ class GameEngine extends EventManager{ this.xrController2.add(this.controllerLine); } - if (this.opts.designMode){ - this.raycaster.setFromXRController(controller); - const intersects = this.raycaster.intersectObjects(this.activeObjects.children, true); + this.dispatchEvent({type: 'controller', data: event}) - intersects.forEach(o => { - while (o.object && !this.activeObjects.children.includes(o.object)) { - o.object = o.object.parent; - } - }) - - if (intersects.length > 0) { - setTimeout(() => { - this.transformControls.attach(intersects[0].object); - }, 100); - } - }else{ + if (this.opts.mode != 'GameDesigner'){ this.clickable.handleController(controller, event); } }).bind(this), @@ -535,20 +509,20 @@ class GameEngine extends EventManager{ return mouse; } - intersect(mouseEvent, domElement, objects, recursive = false, returnInputObjects = true) { - let mouse = this.getMouseVector(mouseEvent, domElement); - this.raycaster.setFromCamera(mouse, this.camera); - let intersects = this.raycaster.intersectObjects(objects.filter(o => o.visible), recursive); - if (returnInputObjects && recursive) { - intersects.forEach(o => { - while (o.object && !objects.includes(o.object)) { - o.object = o.object.parent; - } - }) - } - //console.log('intersects', intersects); - return intersects; - } + // intersect(mouseEvent, domElement, objects, recursive = false, returnInputObjects = true) { + // let mouse = this.getMouseVector(mouseEvent, domElement); + // this.raycaster.setFromCamera(mouse, this.camera); + // let intersects = this.raycaster.intersectObjects(objects.filter(o => o.visible), recursive); + // if (returnInputObjects && recursive) { + // intersects.forEach(o => { + // while (o.object && !objects.includes(o.object)) { + // o.object = o.object.parent; + // } + // }) + // } + // //console.log('intersects', intersects); + // return intersects; + // } onClick(mouseEvent, domElement){ let mouse; diff --git a/src/lib/Hero.js b/src/lib/Hero.js index d92dcf1..db64a2b 100644 --- a/src/lib/Hero.js +++ b/src/lib/Hero.js @@ -83,7 +83,7 @@ class Hero{ this.cameraYBase = this.size.y / this.engine.scale; this.cameraZMin = 0.25 / this.engine.scale; this.cameraZMax = 12 / this.engine.scale; - this.#cameraZ = this.cameraZDefault = 2 / this.engine.scale; + this.#cameraZ = this.cameraZDefault = 3.77 / this.engine.scale; // let center = getBoundingBoxCenterPoint(bb, io.object.position) diff --git a/vite.config.mjs b/vite.config.mjs index 272c2f7..05389cc 100644 --- a/vite.config.mjs +++ b/vite.config.mjs @@ -76,7 +76,7 @@ export default defineConfig({ }, hmr:true, strictPort: true, - host:'192.168.31.137', //'192.168.193.225', //'192.168.83.59',//'127.0.0.1',// + host:'192.168.31.137', //'0.0.0.0', //'192.168.193.225', //'192.168.83.59',//'127.0.0.1',// proxy:{ '/api': { target: 'https://localhost:3000', @@ -95,5 +95,9 @@ export default defineConfig({ rewrite: (path) => path.replace(/^\/proxied/, ''), }, } + }, + preview:{ + host: '0.0.0.0', + port: 5173 } })