diff --git a/avatars/avatars.js b/avatars/avatars.js index 36e440f07b..c1869eb2bf 100644 --- a/avatars/avatars.js +++ b/avatars/avatars.js @@ -389,7 +389,11 @@ const loadPromise = (async () => { crouch: animations.find(a => a.isCrouch), }; activateAnimations = { - activate: animations.find(a => a.isActivate), + grab_forward: {animation:animations.find(a => a.name === 'grab_forward.fbx'), speedFactor: 1.2}, + grab_down: {animation:animations.find(a => a.name === 'grab_down.fbx'), speedFactor: 1.7}, + grab_up: {animation:animations.find(a => a.name === 'grab_up.fbx'), speedFactor: 1.2}, + grab_left: {animation:animations.find(a => a.name === 'grab_left.fbx'), speedFactor: 1.2}, + grab_right: {animation:animations.find(a => a.name === 'grab_right.fbx'), speedFactor: 1.2}, }; narutoRunAnimations = { narutoRun: animations.find(a => a.isNarutoRun), @@ -2062,21 +2066,6 @@ class Avatar { dst.fromArray(v2); } } - if (this.activateTime > 0) { - return spec => { - const { - animationTrackName: k, - dst, - isTop, - } = spec; - const activateAnimation = activateAnimations[defaultActivateAnimation]; - const src2 = activateAnimation.interpolants[k]; - const t2 = Math.pow(this.activateTime/1000*activateAnimation.duration/2, 0.5); - const v2 = src2.evaluate(t2); - - dst.fromArray(v2); - }; - } if (this.narutoRunState) { return spec => { const { @@ -2353,6 +2342,41 @@ class Avatar { ); } }; + + const _blendActivateAction = spec => { + const { + animationTrackName: k, + dst, + isTop, + lerpFn, + } = spec; + + if (this.activateTime > 0) { + + const localPlayer = metaversefile.useLocalPlayer(); + + let defaultAnimation = "grab_forward"; + + if (localPlayer.getAction('activate').animationName) { + defaultAnimation = localPlayer.getAction('activate').animationName; + } + + const activateAnimation = activateAnimations[defaultAnimation].animation; + const src2 = activateAnimation.interpolants[k]; + const t2 = ((this.activateTime / 1000) * activateAnimations[defaultAnimation].speedFactor) % activateAnimation.duration; + const v2 = src2.evaluate(t2); + + const f = this.activateTime > 0 ? Math.min(cubicBezier(t2), 1) : (1 - Math.min(cubicBezier(t2), 1)); + + lerpFn + .call( + dst, + localQuaternion.fromArray(v2), + f + ); + } + }; + for (const spec of this.animationMappings) { const { animationTrackName: k, @@ -2363,6 +2387,7 @@ class Avatar { applyFn(spec); _blendFly(spec); + _blendActivateAction(spec); // ignore all animation position except y if (isPosition) { diff --git a/character-controller.js b/character-controller.js index 2a5feac2f2..c2cde1a989 100644 --- a/character-controller.js +++ b/character-controller.js @@ -978,7 +978,7 @@ class RemotePlayer extends InterpolatedPlayer { function getPlayerCrouchFactor(player) { let factor = 1; factor *= 1 - 0.4 * player.actionInterpolants.crouch.getNormalized(); - factor *= 1 - 0.8 * Math.min(player.actionInterpolants.activate.getNormalized() * 1.5, 1); + //factor *= 1 - 0.8 * Math.min(player.actionInterpolants.activate.getNormalized() * 1.5, 1); return factor; }; diff --git a/game.js b/game.js index 1beddfc12a..bf8c567753 100644 --- a/game.js +++ b/game.js @@ -705,6 +705,61 @@ const _gameUpdate = (timestamp, timeDiff) => { }; _handlePush(); + const _updateActivateAnimation = (grabUseMeshPosition) => { + + let currentDistance = 100; + let currentAnimation = "grab_forward"; + let distance = 0; + + // Forward + localVector.set(0, -0.5, -0.5).applyQuaternion(localPlayer.quaternion) + .add(localPlayer.position); + currentDistance = grabUseMeshPosition.distanceTo(localVector); + + // Down + localVector.set(0, -1.2, -0.5).applyQuaternion(localPlayer.quaternion) + .add(localPlayer.position); + distance = grabUseMeshPosition.distanceTo(localVector); + if (distance < currentDistance) { + currentDistance = distance; + currentAnimation = "grab_down"; + } + + // Up + localVector.set(0, 0.0, -0.5).applyQuaternion(localPlayer.quaternion) + .add(localPlayer.position); + distance = grabUseMeshPosition.distanceTo(localVector); + if (distance < currentDistance) { + currentDistance = distance; + currentAnimation = "grab_up"; + } + + // Left + localVector.set(-0.8, -0.5, -0.5).applyQuaternion(localPlayer.quaternion) + .add(localPlayer.position); + distance = grabUseMeshPosition.distanceTo(localVector); + if (distance < currentDistance) { + currentDistance = distance; + currentAnimation = "grab_left"; + } + + // Right + localVector.set(0.8, -0.5, -0.5).applyQuaternion(localPlayer.quaternion) + .add(localPlayer.position); + distance = grabUseMeshPosition.distanceTo(localVector); + if (distance < currentDistance) { + currentDistance = distance; + currentAnimation = "grab_right"; + } + + if (localPlayer.getAction('activate')) { + localPlayer.getAction('activate').animationName = currentAnimation; + } + + return (currentDistance < 0.8); + + }; + const _updateGrab = () => { // moveMesh.visible = false; @@ -759,9 +814,12 @@ const _gameUpdate = (timestamp, timeDiff) => { grabUseMesh.quaternion.copy(camera.quaternion); // grabUseMesh.scale.copy(grabbedObject.scale); grabUseMesh.updateMatrixWorld(); - grabUseMesh.visible = true; + //grabUseMesh.visible = true; grabUseMesh.target = object; grabUseMesh.setComponent('value', localPlayer.actionInterpolants.activate.getNormalized()); + + grabUseMesh.visible = _updateActivateAnimation(grabUseMesh.position); + } } } diff --git a/package-lock.json b/package-lock.json index 5efeb5cb2d..9c56470669 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10774,7 +10774,8 @@ "quicktype": "^15.0.258" }, "peerDependencies": { - "@types/three": "^0.131.0" + "@types/three": "^0.131.0", + "three": "^0.133.0" } }, "packages/totum": { diff --git a/player-avatar-binding.js b/player-avatar-binding.js index 9978c6ecec..20448b2477 100644 --- a/player-avatar-binding.js +++ b/player-avatar-binding.js @@ -28,6 +28,9 @@ export function applyPlayerModesToAvatar(player, session, rig) { for (const action of player.getActionsState()) { if (action.type === 'wear') { const app = player.appManager.getAppByInstanceId(action.instanceId); + if (!app) { + return null; + } for (const {key, value} of app.components) { if (key === 'aim') { return value; diff --git a/public/animations/Gathering Objects.fbx b/public/animations/Gathering Objects.fbx deleted file mode 100644 index 65b0fae116..0000000000 Binary files a/public/animations/Gathering Objects.fbx and /dev/null differ diff --git a/public/animations/animations.cbor b/public/animations/animations.cbor index 5ad508fe26..20dbc117cc 100644 Binary files a/public/animations/animations.cbor and b/public/animations/animations.cbor differ diff --git a/public/animations/grab_down.fbx b/public/animations/grab_down.fbx new file mode 100644 index 0000000000..32df4de13b Binary files /dev/null and b/public/animations/grab_down.fbx differ diff --git a/public/animations/grab_forward.fbx b/public/animations/grab_forward.fbx new file mode 100644 index 0000000000..83a048de13 Binary files /dev/null and b/public/animations/grab_forward.fbx differ diff --git a/public/animations/grab_left.fbx b/public/animations/grab_left.fbx new file mode 100644 index 0000000000..5c227c70a7 Binary files /dev/null and b/public/animations/grab_left.fbx differ diff --git a/public/animations/grab_right.fbx b/public/animations/grab_right.fbx new file mode 100644 index 0000000000..caffdb1baa Binary files /dev/null and b/public/animations/grab_right.fbx differ diff --git a/public/animations/grab_up.fbx b/public/animations/grab_up.fbx new file mode 100644 index 0000000000..5525584cae Binary files /dev/null and b/public/animations/grab_up.fbx differ