refactor XR controller handling in design mode

This commit is contained in:
2026-04-18 15:23:49 +03:00
parent 99ba537c66
commit c611cb6439
11 changed files with 78 additions and 65 deletions
+3
View File
@@ -1,3 +1,6 @@
NODE_ENV=development
SRV_PORT=3000
SRV_SSL=1
DB_NAME="pronature_beta"
DB_URL="mongodb://127.0.0.1:27017/pronature"
FS_REPO="C:/IMI/ProNature/production/repo/"
+3 -3
View File
@@ -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"
}
/**
+34 -2
View File
@@ -148,6 +148,7 @@ export default {
value: s.data.id
}))
window.addEventListener('resize', this.resize);
engine.addEventListener('controller', this.onController);
},
async unmounted(){
@@ -249,15 +250,46 @@ 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);
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();
}
}
},
targetPointerDown(){
-1
View File
@@ -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);
},
+1 -2
View File
@@ -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);
},
+2 -1
View File
@@ -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;
+4 -4
View File
@@ -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();
+2 -1
View File
@@ -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;
+19 -45
View File
@@ -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;
+1 -1
View File
@@ -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)
+5 -1
View File
@@ -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
}
})