diff --git a/packages/client/public/bin/geometry.wasm b/packages/client/public/bin/geometry.wasm index 7a0511b14..da65b4dc2 100755 Binary files a/packages/client/public/bin/geometry.wasm and b/packages/client/public/bin/geometry.wasm differ diff --git a/packages/client/public/core-modules/phone-edit-tool/index.js b/packages/client/public/core-modules/phone-edit-tool/index.js index d13d7c91a..33f00e369 100644 --- a/packages/client/public/core-modules/phone-edit-tool/index.js +++ b/packages/client/public/core-modules/phone-edit-tool/index.js @@ -141,6 +141,7 @@ const beamShaderMaterial = new THREE.ShaderMaterial({ export default e => { const app = useApp(); + app.visible = false; const physics = usePhysics() const localPlayer = useLocalPlayer(); @@ -152,9 +153,6 @@ export default e => { e.waitUntil((async () => { let u2 = baseUrl + 'assets/iphone.glb'; - if (/^https?:/.test(u2)) { - u2 = '/@proxy/' + u2; - } const phoneModel = await metaversefile.import(u2); phoneApp = metaversefile.createApp({ name: u2, @@ -171,16 +169,17 @@ export default e => { phoneApp.setComponent(key, value); } await phoneApp.addModule(phoneModel); + phoneApp.getPhysicsObjects().forEach(physicsObject => { + physics.disableActor(physicsObject); + }); let u3 = baseUrl + 'assets/cone.glb'; - if (/^https?:/.test(u3)) { - u3 = '/@proxy/' + u3; - } const coneModel = await metaversefile.import(u3); beamApp = metaversefile.createApp({ name: u3, }); beamApp.name = 'beam effect'; + beamApp.visible = false; app.add(beamApp); beamApp.updateMatrixWorld(); @@ -195,13 +194,16 @@ export default e => { coneMesh.rotation.x = -Math.PI / 2; coneMesh.castShadow = false; coneMesh.receiveShadow = false; + beamApp.getPhysicsObjects().forEach(physicsObject => { + physics.disableActor(physicsObject); + }); })()); - let wearing = false; - useWear(e => { - const {wear} = e; - wearing = !!wear; - }); + // let wearing = false; + // useWear(e => { + // const {wear} = e; + // wearing = !!wear; + // }); let using = false; useUse(e => { @@ -231,24 +233,41 @@ export default e => { }; useFrame(({timestamp}) => { - const grabAction = localPlayer.getAction('grab'); - if(wearing && grabAction && coneMesh) { - beamApp.matrixWorld.decompose(localVector2, localQuaternion, localVector3); - const o = getAppByInstanceId(grabAction.instanceId); - const box = getPhysicalBoundingBox(o); - const center = getBBCenter(box); - - beamApp.lookAt(center); - const distance = localVector2.distanceTo(center); - beamApp.scale.set(1, 1, distance).divideScalar(2); - beamApp.updateMatrixWorld(); - - coneMesh.material.uniforms.uTime.value = timestamp / 1000; - coneMesh.material.uniforms.iResolution.value.set(window.innerWidth, window.innerHeight, 1); - coneMesh.material.uniforms.distance.value = distance; - } else if(!grabAction && coneMesh && coneMesh.material.uniforms.uTime.value > 0) { - coneMesh.material.uniforms.uTime.value = 0; - coneMesh.material.uniforms.iResolution.value.set(0, 0, 0); + if (physics.getActionInterpolant(localPlayer, 'readyGrab') > 0) { + const grabAction = localPlayer.getAction('grab'); + if(grabAction && coneMesh) { + beamApp.matrixWorld.decompose(localVector2, localQuaternion, localVector3); + const o = getAppByInstanceId(grabAction.instanceId); + const box = getPhysicalBoundingBox(o); + const center = getBBCenter(box); + + beamApp.lookAt(center); + const distance = localVector2.distanceTo(center); + beamApp.scale.set(1, 1, distance).divideScalar(2); + beamApp.updateMatrixWorld(); + + coneMesh.material.uniforms.uTime.value = timestamp / 1000; + coneMesh.material.uniforms.iResolution.value.set(window.innerWidth, window.innerHeight, 1); + coneMesh.material.uniforms.distance.value = distance; + + beamApp.visible = true; + } else if(!grabAction && coneMesh && coneMesh.material.uniforms.uTime.value > 0) { + // coneMesh.material.uniforms.uTime.value = 0; + // coneMesh.material.uniforms.iResolution.value.set(0, 0, 0); + + beamApp.visible = false; + } + + if (app) { + localPlayer.avatar.foundModelBones.Right_wrist.matrixWorld.decompose(app.position, app.quaternion, localVector); + app.position.add(localVector.set(-0.03, -0.05, -0.02).applyQuaternion(app.quaternion)); + app.quaternion.multiply(localQuaternion.set(0.6272114, -0.3265056, 0.3265056, 0.6272114)); + app.updateMatrixWorld(); + } + + app.visible = true; + } else { + app.visible = false; } }); diff --git a/packages/engine-wasm/AnimationSystem/AnimationSystem.cc b/packages/engine-wasm/AnimationSystem/AnimationSystem.cc index d85e70569..7b57bc124 100644 --- a/packages/engine-wasm/AnimationSystem/AnimationSystem.cc +++ b/packages/engine-wasm/AnimationSystem/AnimationSystem.cc @@ -221,6 +221,7 @@ namespace AnimationSystem { avatar->actionInterpolants["fallLoop"] = new InfiniteActionInterpolant(0); avatar->actionInterpolants["fallLoopTransition"] = new BiActionInterpolant(0, 300); avatar->actionInterpolants["hurt"] = new InfiniteActionInterpolant(0); + avatar->actionInterpolants["readyGrab"] = new BiActionInterpolant(0, animationGroups[animationGroupIndexes.Single][singleAnimationIndexes.ReadyGrab]->duration * 1000); avatar->actionInterpolants["aimRightTransition"] = new BiActionInterpolant(0, 150); avatar->actionInterpolants["aimLeftTransition"] = new BiActionInterpolant(0, 150); avatar->actionInterpolants["sprint"] = new BiActionInterpolant(0, 200); @@ -371,6 +372,7 @@ namespace AnimationSystem { this->actionInterpolants["fallLoop"]->update(timeDiff, this->fallLoopState); this->actionInterpolants["fallLoopTransition"]->update(timeDiff, this->fallLoopState); this->actionInterpolants["hurt"]->update(timeDiff, this->hurtState); + this->actionInterpolants["readyGrab"]->update(timeDiff, this->readyGrabState); this->actionInterpolants["aimRightTransition"]->update(timeDiff, this->aimState && this->rightHandState); this->actionInterpolants["aimLeftTransition"]->update(timeDiff, this->aimState && this->leftHandState); this->actionInterpolants["sprint"]->update(timeDiff, this->sprintState); @@ -466,6 +468,8 @@ namespace AnimationSystem { this->hurtTime = this->actionInterpolants["hurt"]->get(); + this->readyGrabTime = this->actionInterpolants["readyGrab"]->get(); + float sprintTime = this->actionInterpolants["sprint"]->get(); this->sprintFactor = fmin(fmax(sprintTime / 200, 0), 1); @@ -565,6 +569,8 @@ namespace AnimationSystem { this->emoteState = true; } else if (j["type"] == "hurt") { this->hurtState = true; + } else if (j["type"] == "readyGrab") { + this->readyGrabState = true; } else if (j["type"] == "rightHand") { this->rightHandState = true; } else if (j["type"] == "leftHand") { @@ -624,6 +630,8 @@ namespace AnimationSystem { this->emoteState = false; } else if (j["type"] == "hurt") { this->hurtState = false; + } else if (j["type"] == "readyGrab") { + this->readyGrabState = false; } else if (j["type"] == "rightHand") { this->rightHandState = false; } else if (j["type"] == "leftHand") { @@ -652,6 +660,82 @@ namespace AnimationSystem { } return -1; } + void Avatar::getValues(float *scratchStack) { + unsigned int index = 0; + scratchStack[index++] = this->activateTime; + scratchStack[index++] = this->landTime; + scratchStack[index++] = this->fallLoopFactor; + scratchStack[index++] = this->fallLoopTime; + scratchStack[index++] = this->skydiveTime; + scratchStack[index++] = this->gliderTime; + scratchStack[index++] = this->flyTime; + scratchStack[index++] = this->doubleJumpTime; + scratchStack[index++] = this->jumpTime; + scratchStack[index++] = this->narutoRunTime; + scratchStack[index++] = this->danceFactor; + scratchStack[index++] = this->emoteFactor; + scratchStack[index++] = this->lastEmoteTime; + scratchStack[index++] = this->idleWalkFactor; + scratchStack[index++] = this->useTime; + scratchStack[index++] = this->useAnimationEnvelopeLength; + scratchStack[index++] = this->hurtTime; + scratchStack[index++] = this->readyGrabTime; + scratchStack[index++] = this->unuseTime; + scratchStack[index++] = this->aimTime; + scratchStack[index++] = this->aimMaxTime; + scratchStack[index++] = this->walkRunFactor; + scratchStack[index++] = this->crouchFactor; + scratchStack[index++] = this->pickUpTime; + scratchStack[index++] = this->forwardFactor; + scratchStack[index++] = this->backwardFactor; + scratchStack[index++] = this->leftFactor; + scratchStack[index++] = this->rightFactor; + scratchStack[index++] = this->mirrorLeftFactorReverse; + scratchStack[index++] = this->mirrorLeftFactor; + scratchStack[index++] = this->mirrorRightFactorReverse; + scratchStack[index++] = this->mirrorRightFactor; + scratchStack[index++] = this->landTimeS; + scratchStack[index++] = this->timeSinceLastMoveS; + scratchStack[index++] = this->swimTime; + scratchStack[index++] = this->movementsTime; + scratchStack[index++] = this->sprintFactor; + scratchStack[index++] = this->movementsTransitionFactor; + scratchStack[index++] = this->jumpState; + scratchStack[index++] = this->doubleJumpState; + scratchStack[index++] = this->landState; + scratchStack[index++] = this->flyState; + scratchStack[index++] = this->crouchState; + scratchStack[index++] = this->narutoRunState; + scratchStack[index++] = this->sitState; + scratchStack[index++] = this->holdState; + scratchStack[index++] = this->pickUpState; + scratchStack[index++] = this->swimState; + scratchStack[index++] = this->activateState; + scratchStack[index++] = this->useState; + scratchStack[index++] = this->aimState; + scratchStack[index++] = this->fallLoopState; + scratchStack[index++] = this->skydiveState; + scratchStack[index++] = this->gliderState; + scratchStack[index++] = this->danceState; + scratchStack[index++] = this->emoteState; + scratchStack[index++] = this->hurtState; + scratchStack[index++] = this->readyGrabState; + scratchStack[index++] = this->rightHandState; + scratchStack[index++] = this->leftHandState; + scratchStack[index++] = this->sprintState; + scratchStack[index++] = this->movementsState; + scratchStack[index++] = this->landWithMoving; + scratchStack[index++] = this->fallLoopFromJump; + scratchStack[index++] = this->activateAnimationIndex; + scratchStack[index++] = this->sitAnimationIndex; + scratchStack[index++] = this->danceAnimationIndex; + scratchStack[index++] = this->emoteAnimationIndex; + scratchStack[index++] = this->useAnimationIndex; + scratchStack[index++] = this->useAnimationComboIndex; + scratchStack[index++] = this->hurtAnimationIndex; + scratchStack[index++] = this->unuseAnimationIndex; + scratchStack[index++] = this->aimAnimationIndex; + } AnimationMixer *createAnimationMixer() { AnimationMixer *animationMixer = new AnimationMixer(); _animationMixers.push_back(animationMixer); @@ -1013,6 +1097,33 @@ namespace AnimationSystem { } } + void _blendReadyGrab(AnimationMapping &spec, Avatar *avatar) { + _handleDefault(spec, avatar); + + Animation *readyGrabAnimation = animationGroups[animationGroupIndexes.Single][singleAnimationIndexes.ReadyGrab]; + float t2 = avatar->readyGrabTime / 1000; + float *v2 = evaluateInterpolant(readyGrabAnimation, spec.index, t2); + + // copyValue(spec.dst, v2, spec.isPosition); + float f = clamp(avatar->readyGrabTime / 200, 0, 1); + + if (spec.index == boneIndexes.Spine || spec.index == boneIndexes.Chest || spec.index == boneIndexes.UpperChest || spec.index == boneIndexes.Neck || spec.index == boneIndexes.Head) { + if (!spec.isPosition) { + multiplyQuaternionsFlat(spec.dst, 0, v2, 0, spec.dst, 0); + } else { + interpolateFlat(spec.dst, 0, spec.dst, 0, v2, 0, f, spec.isPosition); + } + } else { + if (!spec.isTop) { + f *= (1 - avatar->idleWalkFactor); + } + + interpolateFlat(spec.dst, 0, spec.dst, 0, v2, 0, f, spec.isPosition); + } + + // _clearXZ(spec.dst, spec.isPosition); + } + void _blendAim(AnimationMapping &spec, Avatar *avatar) { _handleDefault(spec, avatar); @@ -1343,6 +1454,8 @@ namespace AnimationSystem { _blendHold(spec, this->avatar); } else if (avatar->pickUpState) { _blendPickUp(spec, this->avatar); + } else if (avatar->readyGrabTime > 0) { + _blendReadyGrab(spec, this->avatar); } else { _handleDefault(spec, this->avatar); } diff --git a/packages/engine-wasm/AnimationSystem/AnimationSystem.h b/packages/engine-wasm/AnimationSystem/AnimationSystem.h index 7ea279901..80439d721 100644 --- a/packages/engine-wasm/AnimationSystem/AnimationSystem.h +++ b/packages/engine-wasm/AnimationSystem/AnimationSystem.h @@ -119,6 +119,7 @@ namespace AnimationSystem { float useTime; float useAnimationEnvelopeLength; float hurtTime; + float readyGrabTime; float unuseTime; float aimTime; float aimMaxTime; @@ -160,6 +161,7 @@ namespace AnimationSystem { bool danceState; bool emoteState; bool hurtState; + bool readyGrabState; bool rightHandState; bool leftHandState; bool sprintState; @@ -188,6 +190,7 @@ namespace AnimationSystem { void addAction(char *scratchStack, unsigned int stringByteLength); void removeAction(char *scratchStack, unsigned int stringByteLength); float getActionInterpolant(char *scratchStack, unsigned int stringByteLength, unsigned int type = 0); // 0: get(), 1: getNormalized(), 2: getInverse() + void getValues(float *scratchStack); }; class AnimationMixer { public: diff --git a/packages/engine-wasm/AnimationSystem/constants.h b/packages/engine-wasm/AnimationSystem/constants.h index 71761c66b..ff6602cd3 100644 --- a/packages/engine-wasm/AnimationSystem/constants.h +++ b/packages/engine-wasm/AnimationSystem/constants.h @@ -122,6 +122,7 @@ class SingleAnimationIndexes { int DoubleJump; int FallLoop; int Float; // note: Have to use upper case. Otherwise will cause error "error: cannot combine with previous 'int' declaration specifier `int float`;" . + int ReadyGrab; }; SingleAnimationIndexes singleAnimationIndexes; @@ -371,6 +372,11 @@ AnimationGroupDeclarations declarations = { singleAnimationIndexes.Float = singleAnimationIota++, "treading water.fbx" }, + { + "readyGrab", + singleAnimationIndexes.ReadyGrab = singleAnimationIota++, + "cellphone_draw.fbx" + } } }, // @@ -933,4 +939,4 @@ AnimationGroupDeclarations declarations = { }, } }, -}; \ No newline at end of file +}; diff --git a/packages/engine/character-fx.js b/packages/engine/character-fx.js index e4ae70aaa..f1e66e407 100644 --- a/packages/engine/character-fx.js +++ b/packages/engine/character-fx.js @@ -17,6 +17,7 @@ export class AvatarCharacterFx { this.sonicBoom = null; this.healEffect = null; this.healEffectInited = false; + this.phoneEditTool = false; } update(timestamp, timeDiffS) { @@ -36,6 +37,21 @@ export class AvatarCharacterFx { // } // }; // _updateSonicBoomMesh(); + + const _updatePhoneEditToolMesh = () => { + if (!this.phoneEditTool && this.character.getControlMode() === 'controlled') { + this.phoneEditTool = metaversefile.createApp(); + this.phoneEditTool.setComponent('player', this.character); + (async () => { + const {importModule} = metaversefile.useDefaultModules(); + const m = await importModule('phoneEditTool'); + await this.phoneEditTool.addModule(m); + })(); + sceneLowPriority.add(this.phoneEditTool); + } + }; + _updatePhoneEditToolMesh(); + const _updateNameplate = () => { if(!this.nameplate && this.character.getControlMode() === 'remote'){ (async () => { @@ -80,6 +96,11 @@ export class AvatarCharacterFx { // this.sonicBoom.destroy(); // this.sonicBoom = null; // } + if (this.phoneEditTool) { + sceneLowPriority.remove(this.phoneEditTool); + this.phoneEditTool.destroy(); + this.phoneEditTool = null; + } // if (this.nameplate) { // sceneLowPriority.remove(this.nameplate); // this.nameplate = null; diff --git a/packages/engine/core-modules.js b/packages/engine/core-modules.js index 4b50a151b..a92efd947 100644 --- a/packages/engine/core-modules.js +++ b/packages/engine/core-modules.js @@ -32,6 +32,7 @@ const moduleUrls = { meshLodItem: `${baseUrl}mesh-lod-item/`, transformIndicators: `${baseUrl}transform-indicators/`, glider: `${baseUrl}glider/`, + phoneEditTool: `${baseUrl}phone-edit-tool/`, }; const importModule = async moduleName => { const moduleUrl = moduleUrls[moduleName]; diff --git a/packages/engine/grab-manager.js b/packages/engine/grab-manager.js index 594a3523e..cfeb0dcb9 100644 --- a/packages/engine/grab-manager.js +++ b/packages/engine/grab-manager.js @@ -400,7 +400,7 @@ class Grabmanager extends EventTarget { if (collision) { const physicsId = collision.objectId; const app = metaversefileApi.getAppByPhysicsId(physicsId); - if(!app.getComponent('invincible')) { + if(app && !app.getComponent('invincible')) { highlightedPhysicsObject = app; highlightedPhysicsId = physicsId; }