diff --git a/character-controller.js b/character-controller.js index 2f1b7b0048..a38fe8311d 100644 --- a/character-controller.js +++ b/character-controller.js @@ -1136,31 +1136,39 @@ class LocalPlayer extends UninterpolatedPlayer { }); } grab(app, hand = 'left') { - const {position, quaternion} = _getSession() ? - localPlayer[hand === 'left' ? 'leftHand' : 'rightHand'] - : - camera; - - app.updateMatrixWorld(); - app.savedRotation = app.rotation.clone(); - app.startQuaternion = quaternion.clone(); - - const grabAction = { - type: 'grab', - hand, - instanceId: app.instanceId, - matrix: localMatrix.copy(app.matrixWorld) - .premultiply(localMatrix2.compose(position, quaternion, localVector.set(1, 1, 1)).invert()) - .toArray() - }; - this.addAction(grabAction); - - physicsScene.disableAppPhysics(app) + if(this instanceof LocalPlayer) { + let position = null, quaternion = null; - app.dispatchEvent({ - type: 'grabupdate', - grab: true, - }); + if(_getSession()) { + const h = this[hand === 'left' ? 'leftHand' : 'rightHand']; + position = h.position; + quaternion = h.quaternion; + } else { + position = this.position; + quaternion = camera.quaternion; + } + + app.updateMatrixWorld(); + app.savedRotation = app.rotation.clone(); + app.startQuaternion = quaternion.clone(); + + const grabAction = { + type: 'grab', + hand, + instanceId: app.instanceId, + matrix: localMatrix.copy(app.matrixWorld) + .premultiply(localMatrix2.compose(position, quaternion, localVector.set(1, 1, 1)).invert()) + .toArray() + }; + this.addAction(grabAction); + + physicsScene.disableAppPhysics(app) + + app.dispatchEvent({ + type: 'grabupdate', + grab: true, + }); + } } ungrab() { const actions = Array.from(this.getActionsState()); diff --git a/game.js b/game.js index aead8b33ac..0465af80e5 100644 --- a/game.js +++ b/game.js @@ -4,28 +4,46 @@ general game logic goes here. usually, code starts here and is migrated to an appropriate manager. */ -import * as THREE from 'three'; -import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'; -import physx from './physx.js'; -import cameraManager from './camera-manager.js'; -import ioManager from './io-manager.js'; -import dioramaManager from './diorama.js'; -import {world} from './world.js'; -import {buildMaterial, highlightMaterial, selectMaterial, hoverMaterial, hoverEquipmentMaterial} from './shaders.js'; -import {getRenderer, sceneLowPriority, camera} from './renderer.js'; -import {downloadFile, snapPosition, getDropUrl, handleDropJsonItem} from './util.js'; -import {maxGrabDistance, throwReleaseTime, storageHost, minFov, maxFov, throwAnimationDuration} from './constants.js'; -import metaversefileApi from './metaversefile-api.js'; -import * as metaverseModules from './metaverse-modules.js'; -import loadoutManager from './loadout-manager.js'; -import * as sounds from './sounds.js'; -import {playersManager} from './players-manager.js'; -import physicsManager from './physics-manager.js'; -import npcManager from './npc-manager.js'; -import raycastManager from './raycast-manager.js'; -import zTargeting from './z-targeting.js'; -import Avatar from './avatars/avatars.js'; -import {makeId} from './util.js' +import * as THREE from "three"; +import * as BufferGeometryUtils from "three/examples/jsm/utils/BufferGeometryUtils.js"; +import physx from "./physx.js"; +import cameraManager from "./camera-manager.js"; +import ioManager from "./io-manager.js"; +import dioramaManager from "./diorama.js"; +import { world } from "./world.js"; +import { + buildMaterial, + highlightMaterial, + selectMaterial, + hoverMaterial, + hoverEquipmentMaterial, +} from "./shaders.js"; +import { getRenderer, sceneLowPriority, camera } from "./renderer.js"; +import { + downloadFile, + snapPosition, + getDropUrl, + handleDropJsonItem, +} from "./util.js"; +import { + maxGrabDistance, + throwReleaseTime, + storageHost, + minFov, + maxFov, + throwAnimationDuration, +} from "./constants.js"; +import metaversefileApi from "./metaversefile-api.js"; +import * as metaverseModules from "./metaverse-modules.js"; +import loadoutManager from "./loadout-manager.js"; +import * as sounds from "./sounds.js"; +import { playersManager } from "./players-manager.js"; +import physicsManager from "./physics-manager.js"; +import npcManager from "./npc-manager.js"; +import raycastManager from "./raycast-manager.js"; +import zTargeting from "./z-targeting.js"; +import Avatar from "./avatars/avatars.js"; +import { makeId } from "./util.js"; const localVector = new THREE.Vector3(); const localVector2 = new THREE.Vector3(); @@ -33,10 +51,14 @@ const localVector3 = new THREE.Vector3(); const localVector4 = new THREE.Vector3(); const localVector5 = new THREE.Vector3(); const localVector6 = new THREE.Vector3(); +const localVector7 = new THREE.Vector3(); +const localVector8 = new THREE.Vector3(); +const localVector9 = new THREE.Vector3(); // const localVector2D = new THREE.Vector2(); const localQuaternion = new THREE.Quaternion(); const localQuaternion2 = new THREE.Quaternion(); const localQuaternion3 = new THREE.Quaternion(); +const localQuaternion4 = new THREE.Quaternion(); const localEuler = new THREE.Euler(); const localMatrix = new THREE.Matrix4(); const localMatrix2 = new THREE.Matrix4(); @@ -54,55 +76,85 @@ let isMouseUp = false; // const cubicBezier = easing(0, 1, 0, 1); // let redMesh = null; -const _getGrabAction = i => { - const targetHand = i === 0 ? 'left' : 'right'; +const _getGrabAction = (i) => { + const targetHand = i === 0 ? "left" : "right"; const localPlayer = playersManager.getLocalPlayer(); - const grabAction = localPlayer.findAction(action => action.type === 'grab' && action.hand === targetHand); + const grabAction = localPlayer.findAction( + (action) => action.type === "grab" && action.hand === targetHand + ); return grabAction; }; -const _getGrabbedObject = i => { +const _getGrabbedObject = (i) => { const grabAction = _getGrabAction(i); const grabbedObjectInstanceId = grabAction?.instanceId; - const result = grabbedObjectInstanceId ? metaversefileApi.getAppByInstanceId(grabbedObjectInstanceId) : null; + const result = grabbedObjectInstanceId + ? metaversefileApi.getAppByInstanceId(grabbedObjectInstanceId) + : null; return result; }; const _unwearAppIfHasSitComponent = (player) => { - const wearActions = player.getActionsByType('wear'); + const wearActions = player.getActionsByType("wear"); for (const wearAction of wearActions) { const instanceId = wearAction.instanceId; const app = metaversefileApi.getAppByInstanceId(instanceId); - const hasSitComponent = app.hasComponent('sit'); + const hasSitComponent = app.hasComponent("sit"); if (hasSitComponent) { app.unwear(); } } -} +}; // returns whether we actually snapped -function updateGrabbedObject(o, grabMatrix, offsetMatrix, {collisionEnabled, handSnapEnabled, physx, gridSnap}) { +function updateGrabbedObject( + o, + grabMatrix, + offsetMatrix, + { collisionEnabled, handSnapEnabled, physx, gridSnap } +) { grabMatrix.decompose(localVector, localQuaternion, localVector2); offsetMatrix.decompose(localVector3, localQuaternion2, localVector4); const offset = localVector3.length(); - localMatrix.multiplyMatrices(grabMatrix, offsetMatrix) + localMatrix + .multiplyMatrices(grabMatrix, offsetMatrix) .decompose(localVector5, localQuaternion3, localVector6); - let collision = collisionEnabled && physicsScene.raycast(localVector, localQuaternion); - if (collision) { - // console.log('got collision', collision); - const {point} = collision; - o.position.fromArray(point) - // .add(localVector2.set(0, 0.01, 0)); + const collision = + collisionEnabled && physicsScene.raycast(localVector, localQuaternion); + localQuaternion4.setFromAxisAngle(localVector2.set(1, 0, 0), -Math.PI * 0.5); + const downCollision = + collisionEnabled && physicsScene.raycast(localVector5, localQuaternion4); - if (o.position.distanceTo(localVector) > offset) { - collision = null; - } + if (!!collision.meshId) { + const { point } = collision; + localVector6.fromArray(point); } - if (!collision) { - o.position.copy(localVector5); + + if (!!downCollision.meshId) { + const { point } = downCollision; + localVector4.fromArray(point); + if (ioManager.keys.shift) { + o.position.copy(localVector5.setY(localVector4.y)); + } else { + // if collision point is closer to the player than the grab offset and collisionDown point + // is below collision point then place the object at collision point + if ( + localVector.distanceTo(localVector6) < offset && + localVector4.y < localVector6.y + ) + localVector5.copy(localVector6); + + // if grabbed object would go below another object then place object at downCollision point + if (localVector5.y < localVector4.y) localVector5.setY(localVector4.y); + o.position.copy(localVector5); + } } - const handSnap = !handSnapEnabled || offset >= maxGrabDistance || !!collision; + const handSnap = + !handSnapEnabled || + offset >= maxGrabDistance || + !!collision || + !!downCollision; if (handSnap) { snapPosition(o, gridSnap); o.quaternion.setFromEuler(o.savedRotation); @@ -110,17 +162,19 @@ function updateGrabbedObject(o, grabMatrix, offsetMatrix, {collisionEnabled, han o.quaternion.copy(localQuaternion3); } + o.updateMatrixWorld(); + return { handSnap, }; } const _getCurrentGrabAnimation = () => { - let currentAnimation = ''; + let currentAnimation = ""; const localPlayer = playersManager.getLocalPlayer(); - const wearComponent = grabUseMesh.targetApp.getComponent('wear'); - if (wearComponent && wearComponent.grabAnimation === 'pick_up') { + const wearComponent = grabUseMesh.targetApp.getComponent("wear"); + if (wearComponent && wearComponent.grabAnimation === "pick_up") { currentAnimation = wearComponent.grabAnimation; } else { const grabUseMeshPosition = grabUseMesh.position; @@ -128,54 +182,64 @@ const _getCurrentGrabAnimation = () => { // Forward { - localVector.set(0, -0.5, -0.5).applyQuaternion(localPlayer.quaternion) + localVector + .set(0, -0.5, -0.5) + .applyQuaternion(localPlayer.quaternion) .add(localPlayer.position); const distance = grabUseMeshPosition.distanceTo(localVector); currentDistance = distance; - currentAnimation = 'grab_forward'; + currentAnimation = "grab_forward"; } // Down { - localVector.set(0, -1.2, -0.5).applyQuaternion(localPlayer.quaternion) + localVector + .set(0, -1.2, -0.5) + .applyQuaternion(localPlayer.quaternion) .add(localPlayer.position); const distance = grabUseMeshPosition.distanceTo(localVector); if (distance < currentDistance) { currentDistance = distance; - currentAnimation = 'grab_down'; + currentAnimation = "grab_down"; } } // Up { - localVector.set(0, 0.0, -0.5).applyQuaternion(localPlayer.quaternion) + localVector + .set(0, 0.0, -0.5) + .applyQuaternion(localPlayer.quaternion) .add(localPlayer.position); const distance = grabUseMeshPosition.distanceTo(localVector); if (distance < currentDistance) { currentDistance = distance; - currentAnimation = 'grab_up'; + currentAnimation = "grab_up"; } } // Left { - localVector.set(-0.8, -0.5, -0.5).applyQuaternion(localPlayer.quaternion) + localVector + .set(-0.8, -0.5, -0.5) + .applyQuaternion(localPlayer.quaternion) .add(localPlayer.position); const distance = grabUseMeshPosition.distanceTo(localVector); if (distance < currentDistance) { currentDistance = distance; - currentAnimation = 'grab_left'; + currentAnimation = "grab_left"; } } - + // Right { - localVector.set(0.8, -0.5, -0.5).applyQuaternion(localPlayer.quaternion) + localVector + .set(0.8, -0.5, -0.5) + .applyQuaternion(localPlayer.quaternion) .add(localPlayer.position); const distance = grabUseMeshPosition.distanceTo(localVector); if (distance < currentDistance) { currentDistance = distance; - currentAnimation = 'grab_right'; + currentAnimation = "grab_right"; } } } @@ -186,45 +250,152 @@ const _getCurrentGrabAnimation = () => { const _makeTargetMesh = (() => { const targetMeshGeometry = (() => { const targetGeometry = BufferGeometryUtils.mergeBufferGeometries([ + new THREE.BoxBufferGeometry(0.03, 0.2, 0.03).applyMatrix4( + new THREE.Matrix4().makeTranslation(0, -0.1, 0) + ), new THREE.BoxBufferGeometry(0.03, 0.2, 0.03) - .applyMatrix4(new THREE.Matrix4().makeTranslation(0, -0.1, 0)), - new THREE.BoxBufferGeometry(0.03, 0.2, 0.03) - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, -1, 0), new THREE.Vector3(0, 0, 1)))) + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(0, -1, 0), + new THREE.Vector3(0, 0, 1) + ) + ) + ) .applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0, 0.1)), new THREE.BoxBufferGeometry(0.03, 0.2, 0.03) - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, -1, 0), new THREE.Vector3(1, 0, 0)))) + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(0, -1, 0), + new THREE.Vector3(1, 0, 0) + ) + ) + ) .applyMatrix4(new THREE.Matrix4().makeTranslation(0.1, 0, 0)), ]); return BufferGeometryUtils.mergeBufferGeometries([ - targetGeometry.clone() + targetGeometry + .clone() .applyMatrix4(new THREE.Matrix4().makeTranslation(-0.5, 0.5, -0.5)), - targetGeometry.clone() - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 0, -1), new THREE.Vector3(0, -1, 0)))) + targetGeometry + .clone() + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(0, 0, -1), + new THREE.Vector3(0, -1, 0) + ) + ) + ) .applyMatrix4(new THREE.Matrix4().makeTranslation(-0.5, -0.5, -0.5)), - targetGeometry.clone() - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 0, 1)))) + targetGeometry + .clone() + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(0, 1, 0), + new THREE.Vector3(0, 0, 1) + ) + ) + ) .applyMatrix4(new THREE.Matrix4().makeTranslation(-0.5, 0.5, 0.5)), - targetGeometry.clone() - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 1, 0), new THREE.Vector3(1, 0, 0)))) + targetGeometry + .clone() + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(0, 1, 0), + new THREE.Vector3(1, 0, 0) + ) + ) + ) .applyMatrix4(new THREE.Matrix4().makeTranslation(0.5, 0.5, -0.5)), - targetGeometry.clone() - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 1, 0), new THREE.Vector3(1, 0, 0)))) - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 0, 1)))) + targetGeometry + .clone() + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(0, 1, 0), + new THREE.Vector3(1, 0, 0) + ) + ) + ) + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(0, 1, 0), + new THREE.Vector3(0, 0, 1) + ) + ) + ) .applyMatrix4(new THREE.Matrix4().makeTranslation(0.5, 0.5, 0.5)), - targetGeometry.clone() - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 0, 1)))) - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(-1, 0, 0), new THREE.Vector3(0, -1, 0)))) + targetGeometry + .clone() + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(0, 1, 0), + new THREE.Vector3(0, 0, 1) + ) + ) + ) + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(-1, 0, 0), + new THREE.Vector3(0, -1, 0) + ) + ) + ) .applyMatrix4(new THREE.Matrix4().makeTranslation(-0.5, -0.5, 0.5)), - targetGeometry.clone() - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 1, 0), new THREE.Vector3(1, 0, 0)))) - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, -1, 0)))) + targetGeometry + .clone() + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(0, 1, 0), + new THREE.Vector3(1, 0, 0) + ) + ) + ) + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(1, 0, 0), + new THREE.Vector3(0, -1, 0) + ) + ) + ) .applyMatrix4(new THREE.Matrix4().makeTranslation(0.5, -0.5, -0.5)), - targetGeometry.clone() - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(-1, 1, 0).normalize(), new THREE.Vector3(1, 1, 0).normalize()))) - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, -1, 0).normalize(), new THREE.Vector3(0, 0, -1).normalize()))) - .applyMatrix4(new THREE.Matrix4().makeRotationFromQuaternion(new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(-1, 0, 0).normalize(), new THREE.Vector3(0, 1, 0).normalize()))) + targetGeometry + .clone() + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(-1, 1, 0).normalize(), + new THREE.Vector3(1, 1, 0).normalize() + ) + ) + ) + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(0, -1, 0).normalize(), + new THREE.Vector3(0, 0, -1).normalize() + ) + ) + ) + .applyMatrix4( + new THREE.Matrix4().makeRotationFromQuaternion( + new THREE.Quaternion().setFromUnitVectors( + new THREE.Vector3(-1, 0, 0).normalize(), + new THREE.Vector3(0, 1, 0).normalize() + ) + ) + ) .applyMatrix4(new THREE.Matrix4().makeTranslation(0.5, -0.5, 0.5)), - ])// .applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0.5, 0)); + ]); // .applyMatrix4(new THREE.Matrix4().makeTranslation(0, 0.5, 0)); })(); const targetVsh = ` #define M_PI 3.1415926535897932384626433832795 @@ -239,14 +410,14 @@ const _makeTargetMesh = (() => { uniform float uHighlight; uniform float uTime; - const vec3 c = vec3(${new THREE.Color(0x29b6f6).toArray().join(', ')}); + const vec3 c = vec3(${new THREE.Color(0x29b6f6).toArray().join(", ")}); void main() { float f = max(1.0 - sign(uTime) * pow(abs(uTime), 0.5), 0.1); gl_FragColor = vec4(vec3(c * f * uHighlight), 1.0); } `; - return p => { + return (p) => { const geometry = targetMeshGeometry; const material = new THREE.ShaderMaterial({ uniforms: { @@ -268,7 +439,7 @@ const _makeTargetMesh = (() => { return mesh; }; })(); -const _makeHighlightPhysicsMesh = material => { +const _makeHighlightPhysicsMesh = (material) => { const geometry = new THREE.BoxBufferGeometry(1, 1, 1); material = material.clone(); const mesh = new THREE.Mesh(geometry, material); @@ -308,7 +479,9 @@ sceneLowPriority.add(mouseDomHoverPhysicsMesh); let mouseDomHoverObject = null; let mouseDomHoverPhysicsId = 0; -const mouseDomEquipmentHoverPhysicsMesh = _makeHighlightPhysicsMesh(hoverEquipmentMaterial); +const mouseDomEquipmentHoverPhysicsMesh = _makeHighlightPhysicsMesh( + hoverEquipmentMaterial +); mouseDomEquipmentHoverPhysicsMesh.visible = false; sceneLowPriority.add(mouseDomEquipmentHoverPhysicsMesh); let mouseDomEquipmentHoverObject = null; @@ -319,26 +492,32 @@ let mouseDomEquipmentHoverPhysicsId = 0; const _use = () => { if (gameManager.getMenu() === 3) { const itemSpec = itemSpecs3[selectedItemIndex]; - let {start_url, filename, content} = itemSpec; + let { start_url, filename, content } = itemSpec; if (start_url) { // start_url = new URL(start_url, srcUrl).href; // filename = start_url; } else if (filename && content) { const blob = new Blob([content], { - type: 'application/octet-stream', + type: "application/octet-stream", }); start_url = URL.createObjectURL(blob); - start_url += '/' + filename; + start_url += "/" + filename; } - world.appManager.addTrackedApp(start_url, null, deployMesh.position, deployMesh.quaternion, deployMesh.scale); + world.appManager.addTrackedApp( + start_url, + null, + deployMesh.position, + deployMesh.quaternion, + deployMesh.scale + ); gameManager.setMenu(0); cameraManager.requestPointerLock(); } else if (highlightedObject /* && !editedObject */) { _grab(highlightedObject); highlightedObject = null; - + gameManager.setMenu(0); cameraManager.requestPointerLock(); } else if (gameManager.getMenu() === 1) { @@ -348,7 +527,13 @@ const _use = () => { const inventory = loginManager.getInventory(); const itemSpec = inventory[selectedItemIndex]; - world.appManager.addTrackedApp(itemSpec.id, null, deployMesh.position, deployMesh.quaternion, deployMesh.scale); + world.appManager.addTrackedApp( + itemSpec.id, + null, + deployMesh.position, + deployMesh.quaternion, + deployMesh.scale + ); gameManager.setMenu(0); cameraManager.requestPointerLock(); @@ -359,23 +544,21 @@ const _delete = () => { if (grabbedObject) { const localPlayer = playersManager.getLocalPlayer(); localPlayer.ungrab(); - - world.appManager.removeTrackedApp(grabbedObject.instanceId); + world.appManager.removeTrackedApp(grabbedObject.instanceId); } else if (highlightedPhysicsObject) { world.appManager.removeTrackedApp(highlightedPhysicsObject.instanceId); highlightedPhysicsObject = null; - } else if (mouseSelectedObject) { world.appManager.removeTrackedApp(mouseSelectedObject.instanceId); - + if (mouseHoverObject === mouseSelectedObject) { gameManager.setMouseHoverObject(null); } gameManager.setMouseSelectedObject(null); } }; -const _click = e => { +const _click = (e) => { if (_getGrabbedObject(0)) { const localPlayer = playersManager.getLocalPlayer(); localPlayer.ungrab(); @@ -386,26 +569,36 @@ const _click = e => { } }; let lastUseIndex = 0; -const _getNextUseIndex = animationCombo => { +const _getNextUseIndex = (animationCombo) => { if (Array.isArray(animationCombo)) { - return (lastUseIndex++) % animationCombo.length; + return lastUseIndex++ % animationCombo.length; } else { return 0; } -} +}; const _startUse = () => { const wearApp = loadoutManager.getSelectedApp(); if (wearApp) { - const useComponent = wearApp.getComponent('use'); + const useComponent = wearApp.getComponent("use"); if (useComponent) { const localPlayer = playersManager.getLocalPlayer(); - const useAction = localPlayer.getAction('use'); + const useAction = localPlayer.getAction("use"); if (!useAction) { - const {instanceId} = wearApp; - const {boneAttachment, animation, animationCombo, animationEnvelope, ik, behavior, position, quaternion, scale} = useComponent; + const { instanceId } = wearApp; + const { + boneAttachment, + animation, + animationCombo, + animationEnvelope, + ik, + behavior, + position, + quaternion, + scale, + } = useComponent; const index = _getNextUseIndex(animationCombo); const newUseAction = { - type: 'use', + type: "use", instanceId, animation, animationCombo, @@ -428,14 +621,14 @@ const _startUse = () => { }; const _endUse = () => { const localPlayer = playersManager.getLocalPlayer(); - const useAction = localPlayer.getAction('use'); + const useAction = localPlayer.getAction("use"); if (useAction) { const app = metaversefileApi.getAppByInstanceId(useAction.instanceId); app.dispatchEvent({ - type: 'use', + type: "use", use: false, }); - localPlayer.removeAction('use'); + localPlayer.removeAction("use"); } }; const _mousedown = () => { @@ -445,10 +638,10 @@ const _mouseup = () => { isMouseUp = true; }; -const _grab = object => { +const _grab = (object) => { const localPlayer = playersManager.getLocalPlayer(); localPlayer.grab(object); - + gameManager.gridSnap = 0; gameManager.editMode = false; }; @@ -477,16 +670,15 @@ const _gameInit = () => { grabUseMesh = metaversefileApi.createApp(); (async () => { await metaverseModules.waitForLoad(); - const {modules} = metaversefileApi.useDefaultModules(); - const m = modules['button']; + const { modules } = metaversefileApi.useDefaultModules(); + const m = modules["button"]; await grabUseMesh.addModule(m); })(); grabUseMesh.targetApp = null; grabUseMesh.targetPhysicsId = -1; sceneLowPriority.add(grabUseMesh); }; -Promise.resolve() - .then(_gameInit); +Promise.resolve().then(_gameInit); let lastActivated = false; let lastThrowing = false; @@ -508,30 +700,53 @@ const _gameUpdate = (timestamp, timeDiff) => { const _updateGrab = () => { const renderer = getRenderer(); - const _isWear = o => localPlayer.findAction(action => action.type === 'wear' && action.instanceId === o.instanceId); + const _isWear = (o) => + localPlayer.findAction( + (action) => action.type === "wear" && action.instanceId === o.instanceId + ); grabUseMesh.visible = false; if (!gameManager.editMode) { const avatarHeight = localPlayer.avatar ? localPlayer.avatar.height : 0; - localVector.copy(localPlayer.position) - .add(localVector2.set(0, avatarHeight * (1 - localPlayer.getCrouchFactor()) * 0.5, -0.3).applyQuaternion(localPlayer.quaternion)); - + localVector + .copy(localPlayer.position) + .add( + localVector2 + .set( + 0, + avatarHeight * (1 - localPlayer.getCrouchFactor()) * 0.5, + -0.3 + ) + .applyQuaternion(localPlayer.quaternion) + ); + const radius = 1; const halfHeight = 0.1; - const collision = physicsScene.getCollisionObject(radius, halfHeight, localVector, localPlayer.quaternion); + const collision = physicsScene.getCollisionObject( + radius, + halfHeight, + localVector, + localPlayer.quaternion + ); if (collision) { const physicsId = collision.objectId; const object = metaversefileApi.getAppByPhysicsId(physicsId); // console.log('got collision', physicsId, object); - const physicsObject = metaversefileApi.getPhysicsObjectByPhysicsId(physicsId); + const physicsObject = + metaversefileApi.getPhysicsObjectByPhysicsId(physicsId); if (object && !_isWear(object) && physicsObject) { - grabUseMesh.position.setFromMatrixPosition(physicsObject.physicsMesh.matrixWorld); + grabUseMesh.position.setFromMatrixPosition( + physicsObject.physicsMesh.matrixWorld + ); grabUseMesh.quaternion.copy(camera.quaternion); grabUseMesh.updateMatrixWorld(); grabUseMesh.targetApp = object; grabUseMesh.targetPhysicsId = physicsId; - grabUseMesh.setComponent('value', localPlayer.actionInterpolants.activate.getNormalized()); - + grabUseMesh.setComponent( + "value", + localPlayer.actionInterpolants.activate.getNormalized() + ); + grabUseMesh.visible = true; } } @@ -541,18 +756,36 @@ const _gameUpdate = (timestamp, timeDiff) => { const grabAction = _getGrabAction(i); const grabbedObject = _getGrabbedObject(i); if (grabbedObject && !_isWear(grabbedObject)) { - const {position, quaternion} = renderer.xr.getSession() ? localPlayer[hand === 'left' ? 'leftHand' : 'rightHand'] : camera; + const avatarHeight = localPlayer.avatar ? localPlayer.avatar.height : 0; + let position = null, + quaternion = null; + if (renderer.xr.getSession()) { + const h = localPlayer[hand === "left" ? "leftHand" : "rightHand"]; + position = h.position; + quaternion = h.quaternion; + } else { + position = localVector2.copy(localPlayer.position); + quaternion = camera.quaternion; + } + localMatrix.compose(position, quaternion, localVector.set(1, 1, 1)); - grabbedObject.updateMatrixWorld(); - updateGrabbedObject(grabbedObject, localMatrix, localMatrix3.fromArray(grabAction.matrix), { - collisionEnabled: true, - handSnapEnabled: true, - physx, - gridSnap: gameManager.getGridSnap(), - }); + updateGrabbedObject( + grabbedObject, + localMatrix, + localMatrix3.fromArray(grabAction.matrix), + { + collisionEnabled: true, + handSnapEnabled: true, + physx, + gridSnap: gameManager.getGridSnap(), + } + ); - grabUseMesh.setComponent('value', localPlayer.actionInterpolants.activate.getNormalized()); + grabUseMesh.setComponent( + "value", + localPlayer.actionInterpolants.activate.getNormalized() + ); } } }; @@ -561,9 +794,9 @@ const _gameUpdate = (timestamp, timeDiff) => { zTargeting.update(timestamp, timeDiff); const _handlePickUp = () => { - const pickUpAction = localPlayer.getAction('pickUp'); + const pickUpAction = localPlayer.getAction("pickUp"); if (pickUpAction) { - const {instanceId} = pickUpAction; + const { instanceId } = pickUpAction; const app = metaversefileApi.getAppByInstanceId(instanceId); const _removeApp = () => { @@ -580,7 +813,9 @@ const _gameUpdate = (timestamp, timeDiff) => { _removeApp(); const animations = Avatar.getAnimations(); - const pickUpZeldaAnimation = animations.find(a => a.name === 'pick_up_zelda.fbx'); + const pickUpZeldaAnimation = animations.find( + (a) => a.name === "pick_up_zelda.fbx" + ); const pickUpTime = localPlayer.actionInterpolants.pickUp.get(); const pickUpTimeS = pickUpTime / 1000; if (pickUpTimeS < pickUpZeldaAnimation.duration) { @@ -590,12 +825,19 @@ const _gameUpdate = (timestamp, timeDiff) => { _addApp(); - const handsAveragePosition = localVector.setFromMatrixPosition(localPlayer.avatar.modelBones.Left_wrist.matrixWorld) - .add(localVector2.setFromMatrixPosition(localPlayer.avatar.modelBones.Right_wrist.matrixWorld)) + const handsAveragePosition = localVector + .setFromMatrixPosition( + localPlayer.avatar.modelBones.Left_wrist.matrixWorld + ) + .add( + localVector2.setFromMatrixPosition( + localPlayer.avatar.modelBones.Right_wrist.matrixWorld + ) + ) .divideScalar(2) .add(localVector2.set(0, 0.2, 0)); app.position.copy(handsAveragePosition); - localEuler.setFromQuaternion(localPlayer.quaternion, 'YXZ'); + localEuler.setFromQuaternion(localPlayer.quaternion, "YXZ"); localEuler.x = 0; localEuler.y += Math.PI; localEuler.z = 0; @@ -609,18 +851,21 @@ const _gameUpdate = (timestamp, timeDiff) => { } */ ioManager.setMovementEnabled(!pickUpAction); - } + }; _handlePickUp(); const _handlePhysicsHighlight = () => { highlightedPhysicsObject = null; if (gameManager.editMode) { - const {position, quaternion} = renderer.xr.getSession() ? localPlayer.leftHand : camera; + const { position, quaternion } = renderer.xr.getSession() + ? localPlayer.leftHand + : camera; const collision = physicsScene.raycast(position, quaternion); if (collision) { const physicsId = collision.objectId; - highlightedPhysicsObject = metaversefileApi.getAppByPhysicsId(physicsId); + highlightedPhysicsObject = + metaversefileApi.getAppByPhysicsId(physicsId); highlightedPhysicsId = physicsId; } } @@ -635,16 +880,25 @@ const _gameUpdate = (timestamp, timeDiff) => { highlightedPhysicsObject.updateMatrixWorld(); - const physicsObject = metaversefileApi.getPhysicsObjectByPhysicsId(physicsId); + const physicsObject = + metaversefileApi.getPhysicsObjectByPhysicsId(physicsId); if (physicsObject) { - const {physicsMesh} = physicsObject; + const { physicsMesh } = physicsObject; highlightPhysicsMesh.geometry = physicsMesh.geometry; - highlightPhysicsMesh.matrixWorld.copy(physicsMesh.matrixWorld) - .decompose(highlightPhysicsMesh.position, highlightPhysicsMesh.quaternion, highlightPhysicsMesh.scale); + highlightPhysicsMesh.matrixWorld + .copy(physicsMesh.matrixWorld) + .decompose( + highlightPhysicsMesh.position, + highlightPhysicsMesh.quaternion, + highlightPhysicsMesh.scale + ); - highlightPhysicsMesh.material.uniforms.uTime.value = (now%1500)/1500; + highlightPhysicsMesh.material.uniforms.uTime.value = + (now % 1500) / 1500; highlightPhysicsMesh.material.uniforms.uTime.needsUpdate = true; - highlightPhysicsMesh.material.uniforms.uColor.value.setHex(buildMaterial.uniforms.uColor.value.getHex()); + highlightPhysicsMesh.material.uniforms.uColor.value.setHex( + buildMaterial.uniforms.uColor.value.getHex() + ); highlightPhysicsMesh.material.uniforms.uColor.needsUpdate = true; highlightPhysicsMesh.visible = true; highlightPhysicsMesh.updateMatrixWorld(); @@ -659,23 +913,33 @@ const _gameUpdate = (timestamp, timeDiff) => { if (gameManager.hoverEnabled) { const collision = raycastManager.getCollision(); if (collision) { - const {physicsObject/*, physicsId*/} = collision; - const {physicsMesh} = physicsObject; + const { physicsObject /*, physicsId*/ } = collision; + const { physicsMesh } = physicsObject; mouseHighlightPhysicsMesh.geometry = physicsMesh.geometry; - localMatrix2.copy(physicsMesh.matrixWorld) + localMatrix2 + .copy(physicsMesh.matrixWorld) // .premultiply(localMatrix3.copy(mouseHoverObject.matrixWorld).invert()) - .decompose(mouseHighlightPhysicsMesh.position, mouseHighlightPhysicsMesh.quaternion, mouseHighlightPhysicsMesh.scale); - mouseHighlightPhysicsMesh.material.uniforms.uTime.value = (now%1500)/1500; + .decompose( + mouseHighlightPhysicsMesh.position, + mouseHighlightPhysicsMesh.quaternion, + mouseHighlightPhysicsMesh.scale + ); + mouseHighlightPhysicsMesh.material.uniforms.uTime.value = + (now % 1500) / 1500; mouseHighlightPhysicsMesh.material.uniforms.uTime.needsUpdate = true; mouseHighlightPhysicsMesh.updateMatrixWorld(); mouseHighlightPhysicsMesh.visible = true; - gameManager.setMouseHoverObject(collision.app, collision.physicsId, collision.point); + gameManager.setMouseHoverObject( + collision.app, + collision.physicsId, + collision.point + ); } } }; _updateMouseHighlight(); - + const _updateMouseSelect = () => { mouseSelectPhysicsMesh.visible = false; @@ -683,16 +947,22 @@ const _gameUpdate = (timestamp, timeDiff) => { if (o) { const physicsId = mouseSelectedPhysicsId; - const physicsObject = metaversefileApi.getPhysicsObjectByPhysicsId(physicsId); + const physicsObject = + metaversefileApi.getPhysicsObjectByPhysicsId(physicsId); if (physicsObject) { - const {physicsMesh} = physicsObject; + const { physicsMesh } = physicsObject; mouseSelectPhysicsMesh.geometry = physicsMesh.geometry; - + // update matrix { - localMatrix2.copy(physicsMesh.matrixWorld) + localMatrix2 + .copy(physicsMesh.matrixWorld) // .premultiply(localMatrix3.copy(mouseSelectedObject.matrixWorld).invert()) - .decompose(mouseSelectPhysicsMesh.position, mouseSelectPhysicsMesh.quaternion, mouseSelectPhysicsMesh.scale); + .decompose( + mouseSelectPhysicsMesh.position, + mouseSelectPhysicsMesh.quaternion, + mouseSelectPhysicsMesh.scale + ); // console.log('decompose', mouseSelectPhysicsMesh.position.toArray().join(','), mouseSelectPhysicsMesh.quaternion.toArray().join(','), mouseSelectPhysicsMesh.scale.toArray().join(',')); // debugger; // mouseSelectPhysicsMesh.position.set(0, 0, 0); @@ -700,13 +970,12 @@ const _gameUpdate = (timestamp, timeDiff) => { // mouseSelectPhysicsMesh.scale.set(1, 1, 1); mouseSelectPhysicsMesh.visible = true; mouseSelectPhysicsMesh.updateMatrixWorld(); - } // update uniforms { - mouseSelectPhysicsMesh.material.uniforms.uTime.value = (now%1500)/1500; + mouseSelectPhysicsMesh.material.uniforms.uTime.value = + (now % 1500) / 1500; mouseSelectPhysicsMesh.material.uniforms.uTime.needsUpdate = true; - } } /* else { console.warn('no physics transform for object', o, physicsId, physicsTransform); @@ -714,21 +983,28 @@ const _gameUpdate = (timestamp, timeDiff) => { } }; _updateMouseSelect(); - + const _updateMouseDomHover = () => { mouseDomHoverPhysicsMesh.visible = false; if (mouseDomHoverObject && !mouseSelectedObject) { const physicsId = mouseDomHoverPhysicsId; - const physicsObject = metaversefileApi.getPhysicsObjectByPhysicsId(physicsId); + const physicsObject = + metaversefileApi.getPhysicsObjectByPhysicsId(physicsId); if (physicsObject) { - const {physicsMesh} = physicsObject; + const { physicsMesh } = physicsObject; mouseDomHoverPhysicsMesh.geometry = physicsMesh.geometry; - localMatrix2.copy(physicsMesh.matrixWorld) + localMatrix2 + .copy(physicsMesh.matrixWorld) // .premultiply(localMatrix3.copy(mouseHoverObject.matrixWorld).invert()) - .decompose(mouseDomHoverPhysicsMesh.position, mouseDomHoverPhysicsMesh.quaternion, mouseDomHoverPhysicsMesh.scale); - mouseDomHoverPhysicsMesh.material.uniforms.uTime.value = (now%1500)/1500; + .decompose( + mouseDomHoverPhysicsMesh.position, + mouseDomHoverPhysicsMesh.quaternion, + mouseDomHoverPhysicsMesh.scale + ); + mouseDomHoverPhysicsMesh.material.uniforms.uTime.value = + (now % 1500) / 1500; mouseDomHoverPhysicsMesh.material.uniforms.uTime.needsUpdate = true; mouseDomHoverPhysicsMesh.visible = true; mouseDomHoverPhysicsMesh.updateMatrixWorld(); @@ -736,21 +1012,28 @@ const _gameUpdate = (timestamp, timeDiff) => { } }; _updateMouseDomHover(); - + const _updateMouseDomEquipmentHover = () => { mouseDomEquipmentHoverPhysicsMesh.visible = false; if (mouseDomEquipmentHoverObject && !mouseSelectedObject) { const physicsId = mouseDomEquipmentHoverPhysicsId; - const physicsObject = metaversefileApi.getPhysicsObjectByPhysicsId(physicsId); + const physicsObject = + metaversefileApi.getPhysicsObjectByPhysicsId(physicsId); if (physicsObject) { - const {physicsMesh} = physicsObject; + const { physicsMesh } = physicsObject; mouseDomEquipmentHoverPhysicsMesh.geometry = physicsMesh.geometry; - localMatrix2.copy(physicsMesh.matrixWorld) + localMatrix2 + .copy(physicsMesh.matrixWorld) // .premultiply(localMatrix3.copy(mouseHoverObject.matrixWorld).invert()) - .decompose(mouseDomEquipmentHoverPhysicsMesh.position, mouseDomEquipmentHoverPhysicsMesh.quaternion, mouseDomEquipmentHoverPhysicsMesh.scale); - mouseDomEquipmentHoverPhysicsMesh.material.uniforms.uTime.value = (now%1500)/1500; + .decompose( + mouseDomEquipmentHoverPhysicsMesh.position, + mouseDomEquipmentHoverPhysicsMesh.quaternion, + mouseDomEquipmentHoverPhysicsMesh.scale + ); + mouseDomEquipmentHoverPhysicsMesh.material.uniforms.uTime.value = + (now % 1500) / 1500; mouseDomEquipmentHoverPhysicsMesh.material.uniforms.uTime.needsUpdate = true; mouseDomEquipmentHoverPhysicsMesh.visible = true; mouseDomEquipmentHoverPhysicsMesh.updateMatrixWorld(); @@ -763,49 +1046,60 @@ const _gameUpdate = (timestamp, timeDiff) => { const apps = world.appManager.apps; if (apps.length > 0) { let closestObject; - + if (!gameManager.getMouseSelectedObject() && !gameManager.contextMenu) { - if (/*controlsManager.isPossessed() &&*/ cameraManager.getMode() !== 'firstperson') { + if ( + /*controlsManager.isPossessed() &&*/ cameraManager.getMode() !== + "firstperson" + ) { localPlayer.matrixWorld.decompose( localVector, localQuaternion, localVector2 ); - const avatarHeight = localPlayer.avatar ? localPlayer.avatar.height : 0; + const avatarHeight = localPlayer.avatar + ? localPlayer.avatar.height + : 0; localVector.y -= avatarHeight / 2; - const distanceSpecs = apps.map(object => { - let distance = object.position.distanceTo(localVector); - if (distance > 30) { - distance = Infinity; - } - return { - distance, - object, - }; - }).sort((a, b) => a.distance - b.distance); + const distanceSpecs = apps + .map((object) => { + let distance = object.position.distanceTo(localVector); + if (distance > 30) { + distance = Infinity; + } + return { + distance, + object, + }; + }) + .sort((a, b) => a.distance - b.distance); const closestDistanceSpec = distanceSpecs[0]; if (isFinite(closestDistanceSpec.distance)) { closestObject = closestDistanceSpec.object; } } else { - if ((!!localPlayer.avatar && /*controlsManager.isPossessed() &&*/ cameraManager.getMode()) === 'firstperson' /*|| gameManager.dragging*/) { + if ( + (!!localPlayer.avatar && + /*controlsManager.isPossessed() &&*/ cameraManager.getMode()) === + "firstperson" /*|| gameManager.dragging*/ + ) { localRay.set( camera.position, - localVector.set(0, 0, -1) - .applyQuaternion(camera.quaternion) + localVector.set(0, 0, -1).applyQuaternion(camera.quaternion) ); - - const distanceSpecs = apps.map(object => { - const distance = - object.position.distanceTo(camera.position) < 8 ? - localRay.distanceToPoint(object.position) - : - Infinity; - return { - distance, - object, - }; - }).sort((a, b) => a.distance - b.distance); + + const distanceSpecs = apps + .map((object) => { + const distance = + object.position.distanceTo(camera.position) < 8 + ? localRay.distanceToPoint(object.position) + : Infinity; + return { + distance, + object, + }; + }) + .sort((a, b) => a.distance - b.distance); const closestDistanceSpec = distanceSpecs[0]; if (isFinite(closestDistanceSpec.distance)) { closestObject = closestDistanceSpec.object; @@ -817,17 +1111,17 @@ const _gameUpdate = (timestamp, timeDiff) => { } else { closestObject = null; } - + gameManager.closestObject = closestObject; } }; _handleClosestObject(); - + const _handleUsableObject = () => { const apps = world.appManager.apps; if (apps.length > 0) { let usableObject; - + if ( !gameManager.getMouseSelectedObject() && !gameManager.contextMenu /* && @@ -840,16 +1134,18 @@ const _gameUpdate = (timestamp, timeDiff) => { ); const avatarHeight = localPlayer.avatar ? localPlayer.avatar.height : 0; localVector.y -= avatarHeight / 2; - const distanceSpecs = apps.map(object => { - let distance = object.position.distanceTo(localVector); - if (distance > 3) { - distance = Infinity; - } - return { - distance, - object, - }; - }).sort((a, b) => a.distance - b.distance); + const distanceSpecs = apps + .map((object) => { + let distance = object.position.distanceTo(localVector); + if (distance > 3) { + distance = Infinity; + } + return { + distance, + object, + }; + }) + .sort((a, b) => a.distance - b.distance); const closestDistanceSpec = distanceSpecs[0]; if (isFinite(closestDistanceSpec.distance)) { usableObject = closestDistanceSpec.object; @@ -857,12 +1153,12 @@ const _gameUpdate = (timestamp, timeDiff) => { } else { usableObject = null; } - + gameManager.usableObject = usableObject; } }; _handleUsableObject(); - + /* const _updateDrags = () => { const {draggingRight} = gameManager; if (draggingRight !== lastDraggingRight) { @@ -887,25 +1183,25 @@ const _gameUpdate = (timestamp, timeDiff) => { lastDraggingRight = draggingRight; }; _updateDrags(); */ - + const _updateActivate = () => { const v = localPlayer.actionInterpolants.activate.getNormalized(); const currentActivated = v >= 1; - + if (currentActivated && !lastActivated) { if (grabUseMesh.targetApp) { grabUseMesh.targetApp.activate({ physicsId: grabUseMesh.targetPhysicsId, }); } - localPlayer.removeAction('activate'); + localPlayer.removeAction("activate"); } lastActivated = currentActivated; }; _updateActivate(); const _updateThirdPerson = () => { - const firstPerson = cameraManager.getMode() === 'firstperson'; + const firstPerson = cameraManager.getMode() === "firstperson"; if (firstPerson !== lastFirstPerson) { _setFirstPersonAction(firstPerson); lastFirstPerson = firstPerson; @@ -914,8 +1210,8 @@ const _gameUpdate = (timestamp, timeDiff) => { _updateThirdPerson(); const _updateThrow = () => { - const useAction = localPlayer.getAction('use'); - if (useAction && useAction.behavior === 'throw') { + const useAction = localPlayer.getAction("use"); + if (useAction && useAction.behavior === "throw") { const v = localPlayer.actionInterpolants.use.get() / throwReleaseTime; const currentThrowing = v >= 1; @@ -924,9 +1220,17 @@ const _gameUpdate = (timestamp, timeDiff) => { const app = metaversefileApi.getAppByInstanceId(useAction.instanceId); localPlayer.unwear(app, { - dropStartPosition: localVector.copy(localPlayer.position) - .add(localVector2.set(0, 0.5, -1).applyQuaternion(localPlayer.quaternion)), - dropDirection: localVector2.set(0, 0.2, -1).normalize().applyQuaternion(localPlayer.quaternion), + dropStartPosition: localVector + .copy(localPlayer.position) + .add( + localVector2 + .set(0, 0.5, -1) + .applyQuaternion(localPlayer.quaternion) + ), + dropDirection: localVector2 + .set(0, 0.2, -1) + .normalize() + .applyQuaternion(localPlayer.quaternion), }); } lastThrowing = currentThrowing; @@ -935,14 +1239,19 @@ const _gameUpdate = (timestamp, timeDiff) => { _updateThrow(); const _updateBehavior = () => { - const useAction = localPlayer.getAction('use'); + const useAction = localPlayer.getAction("use"); if (useAction) { const _handleSword = () => { - localVector.copy(localPlayer.position) - .add(localVector2.set(0, 0, -hitboxOffsetDistance).applyQuaternion(localPlayer.quaternion)); + localVector + .copy(localPlayer.position) + .add( + localVector2 + .set(0, 0, -hitboxOffsetDistance) + .applyQuaternion(localPlayer.quaternion) + ); localPlayer.characterHitter.attemptHit({ - type: 'sword', + type: "sword", args: { hitRadius, hitHalfHeight, @@ -954,7 +1263,7 @@ const _gameUpdate = (timestamp, timeDiff) => { }; switch (useAction.behavior) { - case 'sword': { + case "sword": { _handleSword(); break; } @@ -965,7 +1274,7 @@ const _gameUpdate = (timestamp, timeDiff) => { } }; _updateBehavior(); - + const _updateLook = () => { if (localPlayer.avatar) { if (mouseSelectedObject && mouseSelectedPosition) { @@ -973,11 +1282,20 @@ const _gameUpdate = (timestamp, timeDiff) => { localPlayer.headTarget.copy(mouseSelectedPosition); localPlayer.headTargetInverted = true; localPlayer.headTargetEnabled = true; - } else if (!cameraManager.pointerLockElement && !cameraManager.target && raycastManager.lastMouseEvent) { + } else if ( + !cameraManager.pointerLockElement && + !cameraManager.target && + raycastManager.lastMouseEvent + ) { const renderer = getRenderer(); const size = renderer.getSize(localVector); - - localPlayer.headTarget.set(-(raycastManager.lastMouseEvent.clientX/size.x-0.5), (raycastManager.lastMouseEvent.clientY/size.y-0.5), 1) + + localPlayer.headTarget + .set( + -(raycastManager.lastMouseEvent.clientX / size.x - 0.5), + raycastManager.lastMouseEvent.clientY / size.y - 0.5, + 1 + ) .unproject(camera); localPlayer.headTargetInverted = false; localPlayer.headTargetEnabled = true; @@ -990,18 +1308,22 @@ const _gameUpdate = (timestamp, timeDiff) => { }; _updateLook(); - const crosshairEl = document.getElementById('crosshair'); + const crosshairEl = document.getElementById("crosshair"); if (crosshairEl) { - const visible = !!cameraManager.pointerLockElement && - (['camera', 'firstperson', 'thirdperson'].includes(cameraManager.getMode()) || localPlayer.hasAction('aim')) && + const visible = + !!cameraManager.pointerLockElement && + (["camera", "firstperson", "thirdperson"].includes( + cameraManager.getMode() + ) || + localPlayer.hasAction("aim")) && !_getGrabbedObject(0); - crosshairEl.style.visibility = visible ? null : 'hidden'; + crosshairEl.style.visibility = visible ? null : "hidden"; } const _updateUse = () => { - const useAction = localPlayer.getAction('use'); + const useAction = localPlayer.getAction("use"); if (useAction) { - if (useAction.animation === 'pickUpThrow') { + if (useAction.animation === "pickUpThrow") { const useTime = localPlayer.actionInterpolants.use.get(); if (useTime / 1000 >= throwAnimationDuration) { _endUse(); @@ -1009,7 +1331,6 @@ const _gameUpdate = (timestamp, timeDiff) => { } else if (isMouseUp) { _endUse(); } - } isMouseUp = false; }; @@ -1017,7 +1338,7 @@ const _gameUpdate = (timestamp, timeDiff) => { }; const _pushAppUpdates = () => { world.appManager.pushAppUpdates(); - + for (const remotePlayer in playersManager.getRemotePlayers()) { remotePlayer.appManager.pushAppUpdates(); } @@ -1027,7 +1348,7 @@ const _pushPlayerUpdates = () => { localPlayer.pushPlayerUpdates(); }; -const rotationSnap = Math.PI/6; +const rotationSnap = Math.PI / 6; /* const metaverseUi = { makeArrowLoader() { @@ -1043,8 +1364,8 @@ const rotationSnap = Math.PI/6; }; */ const _bindPointerLock = () => { - cameraManager.addEventListener('pointerlockchange', e => { - const {pointerLockElement} = e.data; + cameraManager.addEventListener("pointerlockchange", (e) => { + const { pointerLockElement } = e.data; gameManager.setMouseHoverObject(null); if (!pointerLockElement) { @@ -1054,20 +1375,20 @@ const _bindPointerLock = () => { }; _bindPointerLock(); -const _setFirstPersonAction = firstPerson => { +const _setFirstPersonAction = (firstPerson) => { const localPlayer = playersManager.getLocalPlayer(); if (firstPerson) { - if (!localPlayer.hasAction('firstperson')) { + if (!localPlayer.hasAction("firstperson")) { const aimAction = { - type: 'firstperson', + type: "firstperson", }; localPlayer.addAction(aimAction); } } else { - localPlayer.removeAction('firstperson'); + localPlayer.removeAction("firstperson"); } }; -let lastFirstPerson = cameraManager.getMode() === 'firstperson'; +let lastFirstPerson = cameraManager.getMode() === "firstperson"; _setFirstPersonAction(lastFirstPerson); /* cameraManager.addEventListener('modechange', e => { // XXX need to do this in the frame loop instead @@ -1137,23 +1458,30 @@ class GameManager extends EventTarget { } menuAim() { const localPlayer = playersManager.getLocalPlayer(); - if (!localPlayer.hasAction('aim')) { + if (!localPlayer.hasAction("aim")) { const wearApp = loadoutManager.getSelectedApp(); const wearAimApp = (() => { if (wearApp) { - const aimComponent = wearApp.getComponent('aim'); + const aimComponent = wearApp.getComponent("aim"); if (aimComponent) { return wearApp; } } return null; })(); - const wearAimComponent = wearAimApp?.getComponent('aim'); + const wearAimComponent = wearAimApp?.getComponent("aim"); - const {instanceId} = wearAimApp ?? {}; - const {appAnimation, playerAnimation, boneAttachment, position, quaternion, scale} = wearAimComponent ?? {}; + const { instanceId } = wearAimApp ?? {}; + const { + appAnimation, + playerAnimation, + boneAttachment, + position, + quaternion, + scale, + } = wearAimComponent ?? {}; const aimAction = { - type: 'aim', + type: "aim", instanceId, appAnimation, playerAnimation, @@ -1167,9 +1495,9 @@ class GameManager extends EventTarget { } menuUnaim() { const localPlayer = playersManager.getLocalPlayer(); - const aimAction = localPlayer.getAction('aim'); + const aimAction = localPlayer.getAction("aim"); if (aimAction) { - localPlayer.removeAction('aim'); + localPlayer.removeAction("aim"); } } menuMiddleDown() { @@ -1199,7 +1527,7 @@ class GameManager extends EventTarget { zTargeting.handleUp(); // this.dragging = false; - + /* world.appManager.dispatchEvent(new MessageEvent('dragchange', { data: { dragging: this.dragging, @@ -1228,7 +1556,10 @@ class GameManager extends EventTarget { menuMesh.paste(s); } inputFocused() { - return !!document.activeElement && ['INPUT', 'TEXTAREA'].includes(document.activeElement.nodeName); + return ( + !!document.activeElement && + ["INPUT", "TEXTAREA"].includes(document.activeElement.nodeName) + ); } canGrab() { return !!highlightedObject /*&& !editedObject*/; @@ -1270,17 +1601,18 @@ class GameManager extends EventTarget { } menuPush(direction) { const localPlayer = playersManager.getLocalPlayer(); - const grabAction = localPlayer.findAction(action => action.type === 'grab' && action.hand === 'left'); + const grabAction = localPlayer.findAction( + (action) => action.type === "grab" && action.hand === "left" + ); if (grabAction) { const matrix = localMatrix.fromArray(grabAction.matrix); - matrix - .decompose(localVector, localQuaternion, localVector2); + matrix.decompose(localVector, localQuaternion, localVector2); localVector.z += direction * 0.1; matrix .compose(localVector, localQuaternion, localVector2) .toArray(grabAction.matrix); } else { - console.warn('trying to push with no grab object'); + console.warn("trying to push with no grab object"); } } menuGridSnap() { @@ -1297,7 +1629,7 @@ class GameManager extends EventTarget { if (this.gridSnap === 0) { return 0; } else { - return 4/this.gridSnap; + return 4 / this.gridSnap; } } @@ -1306,41 +1638,41 @@ class GameManager extends EventTarget { if (_getGrabbedObject(0)) { this.menuGridSnap(); } else { - localPlayer.removeAction('dance'); + localPlayer.removeAction("dance"); const newAction = { - type: 'dance', - animation: 'dansu', + type: "dance", + animation: "dansu", }; localPlayer.addAction(newAction); } } menuVUp() { const localPlayer = playersManager.getLocalPlayer(); - localPlayer.removeAction('dance'); + localPlayer.removeAction("dance"); } menuBDown() { const localPlayer = playersManager.getLocalPlayer(); - const sssAction = localPlayer.getAction('sss'); + const sssAction = localPlayer.getAction("sss"); if (!sssAction) { const newSssAction = { - type: 'sss', + type: "sss", }; localPlayer.addAction(newSssAction); - sounds.playSoundName('limitBreak'); + sounds.playSoundName("limitBreak"); - localPlayer.removeAction('dance'); + localPlayer.removeAction("dance"); const newDanceAction = { - type: 'dance', - animation: 'powerup', + type: "dance", + animation: "powerup", // time: 0, }; localPlayer.addAction(newDanceAction); } else { - localPlayer.removeAction('sss'); - localPlayer.removeAction('dance'); + localPlayer.removeAction("sss"); + localPlayer.removeAction("dance"); } /* if (e.ctrlKey) { @@ -1349,18 +1681,18 @@ class GameManager extends EventTarget { } menuBUp() { const localPlayer = playersManager.getLocalPlayer(); - localPlayer.removeAction('dance'); - + localPlayer.removeAction("dance"); + // physicsManager.setThrowState(null); } menuDoubleTap() { if (!this.isCrouched()) { const localPlayer = playersManager.getLocalPlayer(); - const narutoRunAction = localPlayer.getAction('narutoRun'); + const narutoRunAction = localPlayer.getAction("narutoRun"); if (!narutoRunAction) { const newNarutoRunAction = { - type: 'narutoRun', + type: "narutoRun", // time: 0, }; localPlayer.addAction(newNarutoRunAction); @@ -1369,18 +1701,18 @@ class GameManager extends EventTarget { } menuUnDoubleTap() { const localPlayer = playersManager.getLocalPlayer(); - const narutoRunAction = localPlayer.getAction('narutoRun'); + const narutoRunAction = localPlayer.getAction("narutoRun"); if (narutoRunAction) { - localPlayer.removeAction('narutoRun'); + localPlayer.removeAction("narutoRun"); } } menuSwitchCharacter() { - sounds.playSoundName('menuReady'); + sounds.playSoundName("menuReady"); const npc = npcManager.npcs[0]; if (npc) { // console.log('check npc', npc); - + const localPlayer = playersManager.getLocalPlayer(); localPlayer.isLocalPlayer = false; localPlayer.isNpcPlayer = true; @@ -1396,19 +1728,19 @@ class GameManager extends EventTarget { } isFlying() { const localPlayer = playersManager.getLocalPlayer(); - return localPlayer.hasAction('fly'); + return localPlayer.hasAction("fly"); } toggleFly() { const localPlayer = playersManager.getLocalPlayer(); - const flyAction = localPlayer.getAction('fly'); + const flyAction = localPlayer.getAction("fly"); if (flyAction) { - localPlayer.removeAction('fly'); + localPlayer.removeAction("fly"); if (!localPlayer.characterPhysics.lastGrounded) { - localPlayer.setControlAction({type: 'fallLoop'}); + localPlayer.setControlAction({ type: "fallLoop" }); } } else { const flyAction = { - type: 'fly', + type: "fly", time: 0, }; @@ -1419,24 +1751,24 @@ class GameManager extends EventTarget { } isCrouched() { const localPlayer = playersManager.getLocalPlayer(); - return localPlayer.hasAction('crouch'); + return localPlayer.hasAction("crouch"); } isSwimming() { const localPlayer = playersManager.getLocalPlayer(); - return localPlayer.hasAction('swim'); + return localPlayer.hasAction("swim"); } isFlying() { const localPlayer = playersManager.getLocalPlayer(); - return localPlayer.hasAction('fly'); + return localPlayer.hasAction("fly"); } toggleCrouch() { const localPlayer = playersManager.getLocalPlayer(); - let crouchAction = localPlayer.getAction('crouch'); + let crouchAction = localPlayer.getAction("crouch"); if (crouchAction) { - localPlayer.removeAction('crouch'); + localPlayer.removeAction("crouch"); } else { const crouchAction = { - type: 'crouch', + type: "crouch", }; localPlayer.addAction(crouchAction); } @@ -1457,7 +1789,7 @@ class GameManager extends EventTarget { async handleDropUrlToPlayer(u, index, position) { const app = await metaversefileApi.createAppAsync({ start_url: u, - position: position + position: position, }); app.instanceId = makeId(5); world.appManager.importApp(app); @@ -1471,7 +1803,7 @@ class GameManager extends EventTarget { return false; // !!world.appManager.grabbedObjects[0]; // || (editedObject && editedObject.isBuild); } toggleAxis() { - console.log('toggle axis'); + console.log("toggle axis"); } async toggleEditMode() { this.editMode = !this.editMode; @@ -1485,27 +1817,33 @@ class GameManager extends EventTarget { if (_getGrabbedObject(0)) { const localPlayer = playersManager.getLocalPlayer(); localPlayer.ungrab(); - } + } } } isJumping() { const localPlayer = playersManager.getLocalPlayer(); - return localPlayer.hasAction('jump'); + return localPlayer.hasAction("jump"); } isDoubleJumping() { const localPlayer = playersManager.getLocalPlayer(); - return localPlayer.hasAction('doubleJump'); + return localPlayer.hasAction("doubleJump"); } ensureJump(trigger) { const localPlayer = playersManager.getLocalPlayer(); _unwearAppIfHasSitComponent(localPlayer); - if (!localPlayer.hasAction('jump') && !localPlayer.hasAction('fly') && !localPlayer.hasAction('fallLoop') && !localPlayer.hasAction('swim')) { + if ( + !localPlayer.hasAction("jump") && + !localPlayer.hasAction("fly") && + !localPlayer.hasAction("fallLoop") && + !localPlayer.hasAction("swim") + ) { const newJumpAction = { - type: 'jump', - trigger:trigger, - startPositionY: localPlayer.characterPhysics.characterController.position.y, + type: "jump", + trigger: trigger, + startPositionY: + localPlayer.characterPhysics.characterController.position.y, // time: 0, }; localPlayer.setControlAction(newJumpAction); @@ -1518,16 +1856,16 @@ class GameManager extends EventTarget { // update velocity // const localPlayer = playersManager.getLocalPlayer(); // localPlayer.characterPhysics.velocity.y += 6; // currently using aesthetic jump movement - + // play sound // soundManager.play('jump'); - } doubleJump() { const localPlayer = playersManager.getLocalPlayer(); localPlayer.addAction({ - type: 'doubleJump', - startPositionY: localPlayer.characterPhysics.characterController.position.y, + type: "doubleJump", + startPositionY: + localPlayer.characterPhysics.characterController.position.y, }); } isMovingBackward() { @@ -1542,11 +1880,11 @@ class GameManager extends EventTarget { } isAiming() { const localPlayer = playersManager.getLocalPlayer(); - return localPlayer.hasAction('aim'); + return localPlayer.hasAction("aim"); } isSitting() { const localPlayer = playersManager.getLocalPlayer(); - return localPlayer.hasAction('sit'); + return localPlayer.hasAction("sit"); } isGrounded() { const localPlayer = playersManager.getLocalPlayer(); @@ -1564,7 +1902,8 @@ class GameManager extends EventTarget { setHoverEnabled(hoverEnabled) { this.hoverEnabled = hoverEnabled; } - setMouseHoverObject(o, physicsId, position) { // XXX must be triggered + setMouseHoverObject(o, physicsId, position) { + // XXX must be triggered mouseHoverObject = o; mouseHoverPhysicsId = physicsId; if (mouseHoverObject && position) { @@ -1572,15 +1911,17 @@ class GameManager extends EventTarget { } else { mouseHoverPosition = null; } - + // console.log('set mouse hover', !!mouseHoverObject); - world.appManager.dispatchEvent(new MessageEvent('hoverchange', { - data: { - app: mouseHoverObject, - physicsId: mouseHoverPhysicsId, - position: mouseHoverPosition, - }, - })); + world.appManager.dispatchEvent( + new MessageEvent("hoverchange", { + data: { + app: mouseHoverObject, + physicsId: mouseHoverPhysicsId, + position: mouseHoverPosition, + }, + }) + ); } getMouseSelectedObject() { return mouseSelectedObject; @@ -1599,14 +1940,16 @@ class GameManager extends EventTarget { } else { mouseSelectedPosition = null; } - - world.appManager.dispatchEvent(new MessageEvent('selectchange', { - data: { - app: mouseSelectedObject, - physicsId: mouseSelectedPhysicsId, - position: mouseSelectedPosition, - }, - })); + + world.appManager.dispatchEvent( + new MessageEvent("selectchange", { + data: { + app: mouseSelectedObject, + physicsId: mouseSelectedPhysicsId, + position: mouseSelectedPosition, + }, + }) + ); } getMouseDomHoverObject() { return mouseDomHoverObject; @@ -1624,7 +1967,7 @@ class GameManager extends EventTarget { } getSpeed() { let speed = 0; - + const walkSpeed = 0.075; const flySpeed = walkSpeed * 2; const defaultCrouchSpeed = walkSpeed * 0.7; @@ -1640,15 +1983,19 @@ class GameManager extends EventTarget { speed = walkSpeed; } const localPlayer = playersManager.getLocalPlayer(); - const sprintMultiplier = (ioManager.keys.shift && !isCrouched) ? - (localPlayer.hasAction('narutoRun') ? 20 : 3) - : - ((isSwimming && !isFlying) ? 5 - localPlayer.getAction('swim').swimDamping : 1); + const sprintMultiplier = + ioManager.keys.shift && !isCrouched + ? localPlayer.hasAction("narutoRun") + ? 20 + : 3 + : isSwimming && !isFlying + ? 5 - localPlayer.getAction("swim").swimDamping + : 1; speed *= sprintMultiplier; - + const backwardMultiplier = isMovingBackward ? 0.7 : 1; speed *= backwardMultiplier; - + return speed; } getClosestObject() { @@ -1663,11 +2010,11 @@ class GameManager extends EventTarget { menuActivateDown() { if (grabUseMesh.visible) { const localPlayer = playersManager.getLocalPlayer(); - const activateAction = localPlayer.getAction('activate'); + const activateAction = localPlayer.getAction("activate"); if (!activateAction) { const animationName = _getCurrentGrabAnimation(); const newActivateAction = { - type: 'activate', + type: "activate", animationName, }; localPlayer.addAction(newActivateAction); @@ -1676,7 +2023,7 @@ class GameManager extends EventTarget { } menuActivateUp() { const localPlayer = playersManager.getLocalPlayer(); - localPlayer.removeAction('activate'); + localPlayer.removeAction("activate"); } setAvatarQuality(quality) { const localPlayer = playersManager.getLocalPlayer(); @@ -1694,13 +2041,11 @@ class GameManager extends EventTarget { grassBackground: true, // glyphBackground: true, }); - localPlayer.addEventListener('avatarchange', e => { + localPlayer.addEventListener("avatarchange", (e) => { const localPlayer = playersManager.getLocalPlayer(); this.playerDiorama.setTarget(localPlayer); - this.playerDiorama.setObjects([ - e.avatar.model, - ]); - }) + this.playerDiorama.setObjects([e.avatar.model]); + }); } async setVoicePack(voicePack) { const localPlayer = metaversefileApi.useLocalPlayer(); @@ -1714,9 +2059,9 @@ class GameManager extends EventTarget { const scene = world.appManager.exportJSON(); const s = JSON.stringify(scene, null, 2); const blob = new Blob([s], { - type: 'application/json', + type: "application/json", }); - downloadFile(blob, 'scene.json'); + downloadFile(blob, "scene.json"); // console.log('got scene', scene); } update = _gameUpdate; @@ -1724,4 +2069,4 @@ class GameManager extends EventTarget { pushPlayerUpdates = _pushPlayerUpdates; } const gameManager = new GameManager(); -export default gameManager; \ No newline at end of file +export default gameManager;