diff --git a/src/components/InteractiveObjects/PairMatchingGame.js b/src/components/InteractiveObjects/PairMatchingGame.js index ddfd403..a0c91dd 100644 --- a/src/components/InteractiveObjects/PairMatchingGame.js +++ b/src/components/InteractiveObjects/PairMatchingGame.js @@ -48,7 +48,7 @@ class PairMatchingGame extends EventManager { uv[xi].array[8 * i + 7] = s[1]; } let mesh = new Mesh(b[xi], material.clone()); - mesh.position.set(xi * dx, o[xi][i] * dy, 0); + mesh.position.set(xi * dx + Math.random() * (xi+0.5) * dx, o[xi][i] * dy, Math.random() * (xi+0.5) * dx); mesh.userData.gd = { pair: xi, id: i @@ -75,7 +75,7 @@ class PairMatchingGame extends EventManager { let actionDef = {material:{emissiveIntensity:k=>(1+Math.sin((k*2+1.5)*Math.PI))*4 }}; - let clickFn = (i) => { + var clickFn = (i) => { this.dispatchEvent({type:'interaction'}); let oc = clicked; if (done.includes(i.object.userData.gd.id)) return; diff --git a/src/lib/Clickable.js b/src/lib/Clickable.js index a273b0a..9b2dde7 100644 --- a/src/lib/Clickable.js +++ b/src/lib/Clickable.js @@ -1,7 +1,7 @@ import { Raycaster, Vector3 } from "three" class Clickable { - constructor(defaultDistance) { + constructor(engine, defaultDistance) { const objects = []; const raycaster = new Raycaster(); let v = new Vector3; @@ -21,34 +21,39 @@ class Clickable { objects.splice(0, objects.length); } - this.update = function (mouse, camera, event) { - raycaster.setFromCamera(mouse, camera); + this.handleController = function(controller){ + raycaster.setFromXRController(controller); + this.handle(); + } + + this.handleMouse = function (mouse, event) { + raycaster.setFromCamera(mouse, engine.camera); + this.handle(); + }; + + this.handle = function(){ let forExecute = []; objects.filter(o=>{ do { - if (o.__active === false) return false; + if (o.__active === false || o.visible === false) return false; o = o.parent; } while (o); return true; }).forEach(o => { o.getWorldPosition(v); - if (camera.position.distanceTo(v) <= o._clickable.distance && o.visible) { + if (engine.cameraWorld.position.distanceTo(v) <= o._clickable.distance) { const intersects = raycaster.intersectObject(o); - // intersects.forEach(i=>{ - // forExecute.push({o, i}) - // }) - if (intersects[0]) forExecute.push({ o, i: intersects[0] }); + if (intersects[0]) { + forExecute.push({ o, i: intersects[0] }); + } } }); if (forExecute[0]) { let sorted = forExecute.sort((a, b) => a.i.distance - b.i.distance); sorted[0].o._clickable.fn(sorted[0].i); - if (this.onclick) { - this.onclick(sorted[0].o, sorted[0].i, event); - } } - }; + } } } -export {Clickable} \ No newline at end of file +export { Clickable } \ No newline at end of file diff --git a/src/lib/Dashboard.js b/src/lib/Dashboard.js index 2c2b556..35200d1 100644 --- a/src/lib/Dashboard.js +++ b/src/lib/Dashboard.js @@ -29,7 +29,7 @@ class DashBoard extends EventManager { dash.visible = false; const k = 3.11; const dashWidth = engine.aspect * k, dashHeight = k; - const dashDistance = 2.5; + const dashDistance = 1.77; this.width = dashWidth; this.height = dashHeight; @@ -202,7 +202,7 @@ class DashBoard extends EventManager { //dashPlacement, rotate = false, plane = false this.attach = (object, opts = {})=>{ this.cameraFix = engine.hero.cameraZ; - engine.hero.cameraZ = 12; + engine.hero.cameraZ = 6; hud.visible = true; hudPlane.visible = !!opts.plane; if (opts.plane){ diff --git a/src/lib/Draggable.js b/src/lib/Draggable.js index 941c321..ad9ecc0 100644 --- a/src/lib/Draggable.js +++ b/src/lib/Draggable.js @@ -1,7 +1,7 @@ import { Raycaster, Vector3 } from "three" class Draggable{ - constructor(defaultDistance){ + constructor(engine, defaultDistance){ const objects = []; const raycaster = new Raycaster(); let v = new Vector3; @@ -16,13 +16,22 @@ class Draggable{ objects.splice(objects.indexOf(object), 1); } - this.update = function(pointer, camera, action){ - raycaster.setFromCamera(pointer, camera); - if (action == 'start'){ + this.handleController = function(controller, action){ + raycaster.setFromXRController(controller); + this.handle(action); + } + + this.handleMouse = function (mouse, action) { + raycaster.setFromCamera(mouse, engine.camera); + this.handle(action); + }; + + this.handle = function(action){ + if (['start', 'selectstart'].includes(action)){ let forExecute = []; objects.forEach(o=>{ o.getWorldPosition(v); - if (camera.position.distanceTo(v) <= o._draggable.distance && o.visible){ + if (engine.cameraWorld.position.distanceTo(v) <= o._draggable.distance && o.visible){ const intersects = raycaster.intersectObject(o); if (intersects[0]) forExecute.push({o, i:intersects[0]}) } @@ -34,10 +43,10 @@ class Draggable{ dragging = s; dragging.zone = raycaster.intersectObject(s.o._draggable.dragZone)[0]; } - }else if (action == 'end' && dragging){ + }else if (['end', 'selectend'].includes(action) && dragging){ dragging.o._draggable.fn.end && dragging.o._draggable.fn.end(dragging); dragging = null; - }else if(action == 'drag' && dragging){ + }else if(['drag', 'move'].includes(action) && dragging){ const intersect = raycaster.intersectObject(dragging.o._draggable.dragZone)[0]; if (intersect?.uv && dragging.zone?.uv){ dragging.o.position.x += -4*(dragging.zone.uv.x - intersect.uv.x); diff --git a/src/lib/GameEngine.js b/src/lib/GameEngine.js index 4d2d700..765267b 100644 --- a/src/lib/GameEngine.js +++ b/src/lib/GameEngine.js @@ -245,8 +245,8 @@ class GameEngine extends EventManager{ this.initXr(); } - this.clickable = new Clickable(20); - this.draggable = new Draggable(20); + this.clickable = new Clickable(this, 20); + this.draggable = new Draggable(this, 20); } initXr() { @@ -261,7 +261,7 @@ class GameEngine extends EventManager{ // this.session = this.renderer.xr.getSession(); // this.session.addEventListener('selectstart', this.onControllerEvent.bind(this)); }) - this.scene.add(c1); + this.cameraRig.add(c1); let c2 = this.renderer.xr.getController(1); c2.addEventListener('select', this.onSelect.bind(this)); @@ -272,17 +272,17 @@ class GameEngine extends EventManager{ c2.addEventListener('connected', e => { c2.gamepad = e.data.gamepad; }) - this.scene.add(c2); + this.cameraRig.add(c2); const controllerModelFactory = new XRControllerModelFactory(); let controllerGrip1 = this.renderer.xr.getControllerGrip(0); controllerGrip1.add(controllerModelFactory.createControllerModel(controllerGrip1)); - this.scene.add(controllerGrip1); + this.cameraRig.add(controllerGrip1); let controllerGrip2 = this.renderer.xr.getControllerGrip(1); controllerGrip2.add(controllerModelFactory.createControllerModel(controllerGrip2)); - this.scene.add(controllerGrip2); + this.cameraRig.add(controllerGrip2); const geometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, - 1)]); @@ -379,14 +379,10 @@ class GameEngine extends EventManager{ } onControllerEvent(event) { - //this.handleXrAction(event, this); - //event.type !== 'move' && console.log(event) const controller = event.target; - //console.log(event) + if (!controller.userData?.active) return; if (this.opts.designMode){ - if (!controller.userData) return - if (controller.userData.active === false) return; this.transformControls.getRaycaster().setFromXRController(controller); switch (event.type) { case 'selectstart': @@ -400,26 +396,27 @@ class GameEngine extends EventManager{ this.transformControls.pointerMove(null); break; } + }else{ + this.draggable?.handleController(controller, event.type) } } onSelect(event) { const controller = event.target; + this.xrController1.userData.active = false; + this.xrController2.userData.active = false; + + if (controller === this.xrController1) { + this.xrController1.userData.active = true; + this.xrController1.add(this.controllerLine); + } + + if (controller === this.xrController2) { + this.xrController2.userData.active = true; + this.xrController2.add(this.controllerLine); + } if (this.opts.designMode){ - this.xrController1.userData.active = false; - this.xrController2.userData.active = false; - - if (controller === this.xrController1) { - this.xrController1.userData.active = true; - this.xrController1.add(this.controllerLine); - } - - if (controller === this.xrController2) { - this.xrController2.userData.active = true; - this.xrController2.add(this.controllerLine); - } - this.raycaster.setFromXRController(controller); const intersects = this.raycaster.intersectObjects(this.activeObjects.children, true); @@ -434,6 +431,8 @@ class GameEngine extends EventManager{ this.transformControls.attach(intersects[0].object); }, 100); } + }else{ + this.clickable.handleController(controller, event); } } @@ -525,14 +524,14 @@ class GameEngine extends EventManager{ onClick(mouseEvent, domElement){ let mouse = this.getMouseVector(mouseEvent, domElement); - this.raycaster.setFromCamera(mouse, this.camera); - this.clickable.update(mouse, this.camera, mouseEvent); + //this.raycaster.setFromCamera(mouse, this.camera); + this.clickable.handleMouse(mouse, mouseEvent); this.hero?.idleReset(); } onPointer(mouseEvent, domElement, type){ let mouse = this.getMouseVector(mouseEvent, domElement); - this.draggable?.update(mouse, this.camera, type); + this.draggable?.handleMouse(mouse, type); } setCamera(camera) { diff --git a/src/lib/Hero.js b/src/lib/Hero.js index c25ac67..7da6249 100644 --- a/src/lib/Hero.js +++ b/src/lib/Hero.js @@ -95,11 +95,13 @@ class Hero{ this.updateCharacterControls(delta) if (this.engine.renderer.xr.isPresenting){ this.cameraMode = 'fixed' + this.cameraY = this.size.y * 1; //this.camera = this.engine.cameraWorld; // this.engine.activeObjects.position.x = -this.camera.position.x; // this.engine.activeObjects.position.z = -this.camera.position.z; }else{ this.cameraMode = 'rotate' + this.cameraY = this.size.y * 1.5; // this.camera = this.engine.cameraWorld; // this.engine.camera.position.set(0,0,0); // this.engine.camera.rotation.set(0,0,0); @@ -163,7 +165,7 @@ class Hero{ this.fadeDuration = 1; } - if (this.currentAction.startsWith('idle') && play != 'idle' && !pc.isLocked){ + if (this.currentAction.startsWith('idle') && play != 'idle' && !pc.isLocked && !this.engine.renderer.xr.isPresenting){ this.cameraIdleDelta += delta * 0.33; }else { this.cameraIdleDelta = 0; @@ -261,7 +263,7 @@ class Hero{ ) } - cameraPosition.lerp(cameraDesiredPosition, this.cameraMode == 'fixed' ? 1 : delta*2) + cameraPosition.lerp(cameraDesiredPosition, this.cameraMode == 'fixed' ? delta*2 : delta*2) this.camera.position.copy(cameraPosition) if (!pc.isLocked){ this.camera.lookAt( diff --git a/src/styles/style.scss b/src/styles/style.scss index 5a3d006..efb72f8 100644 --- a/src/styles/style.scss +++ b/src/styles/style.scss @@ -127,7 +127,8 @@ video{ .canvas-wrapper{ width: 100%; max-width: 100vw; - height: calc(100vh - 288px); + //height: calc(100vh - 288px); + aspect-ratio: 16 / 9; } .canvas-wrapper:has(canvas:fullscreen){