diff --git a/examples/kneel.js b/examples/kneel.js new file mode 100644 index 0000000000..2ba029677a --- /dev/null +++ b/examples/kneel.js @@ -0,0 +1,89 @@ +// +// kneel.js +// examples +// +// Created by Anthony Thibault on 11/9/2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// Example of how to play an animation on an avatar. +// + +var buttonImageUrl = "https://s3.amazonaws.com/hifi-public/images/tools/kneel.svg"; +var windowDimensions = Controller.getViewportDimensions(); + +var buttonWidth = 37; +var buttonHeight = 46; +var buttonPadding = 10; + +var buttonPositionX = windowDimensions.x - buttonPadding - buttonWidth; +var buttonPositionY = (windowDimensions.y - buttonHeight) / 2 - (buttonHeight + buttonPadding); + +var kneelDownImageOverlay = { + x: buttonPositionX, + y: buttonPositionY, + width: buttonWidth, + height: buttonHeight, + subImage: { x: 0, y: buttonHeight, width: buttonWidth, height: buttonHeight }, + imageURL: buttonImageUrl, + visible: true, + alpha: 1.0 +}; + +var standUpImageOverlay = { + x: buttonPositionX, + y: buttonPositionY, + width: buttonWidth, + height: buttonHeight, + subImage: { x: buttonWidth, y: buttonHeight, width: buttonWidth, height: buttonHeight }, + imageURL: buttonImageUrl, + visible: false, + alpha: 1.0 +}; + +var kneelDownButton = Overlays.addOverlay("image", kneelDownImageOverlay); +var standUpButton = Overlays.addOverlay("image", standUpImageOverlay); +var kneeling = false; + +var KNEEL_ANIM_URL = "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx"; + +function kneelDown() { + kneeling = true; + + var playbackRate = 30; // 30 fps is normal speed. + var priority = 0; // obsolete + var loopFlag = false; + var holdFlag = false; // obsolete + var startFrame = 0; + var endFrame = 82; + var maskedJoints = []; // obsolete + MyAvatar.startAnimation(KNEEL_ANIM_URL, playbackRate, priority, loopFlag, holdFlag, startFrame, endFrame, maskedJoints); + + Overlays.editOverlay(kneelDownButton, { visible: false }); + Overlays.editOverlay(standUpButton, { visible: true }); +} + +function standUp() { + kneeling = false; + + MyAvatar.stopAnimation(KNEEL_ANIM_URL); + + Overlays.editOverlay(standUpButton, { visible: false }); + Overlays.editOverlay(kneelDownButton, { visible: true }); +} + +Controller.mousePressEvent.connect(function (event) { + var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); + if (clickedOverlay == kneelDownButton) { + kneelDown(); + } else if (clickedOverlay == standUpButton) { + standUp(); + } +}); + +Script.scriptEnding.connect(function() { + Overlays.deleteOverlay(kneelDownButton); + Overlays.deleteOverlay(standUpButton); +}); diff --git a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json index df8b9b16c8..8e5953fa69 100644 --- a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json +++ b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json @@ -1,297 +1,184 @@ { "version": "1.0", "root": { - "id": "ikOverlay", - "type": "overlay", + "id": "userAnimStateMachine", + "type": "stateMachine", "data": { - "alpha": 1.0, - "alphaVar": "ikOverlayAlpha", - "boneSet": "fullBody" + "currentState": "userAnimNone", + "states": [ + { + "id": "userAnimNone", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "userAnimA", "state": "userAnimA" }, + { "var": "userAnimB", "state": "userAnimB" } + ] + }, + { + "id": "userAnimA", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "userAnimNone", "state": "userAnimNone" }, + { "var": "userAnimB", "state": "userAnimB" } + ] + }, + { + "id": "userAnimB", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "userAnimNone", "state": "userAnimNone" }, + { "var": "userAnimA", "state": "userAnimA" } + ] + } + ] }, "children": [ { - "id": "ik", - "type": "inverseKinematics", - "data": { - "targets": [ - { - "jointName": "RightHand", - "positionVar": "rightHandPosition", - "rotationVar": "rightHandRotation", - "typeVar": "rightHandType" - }, - { - "jointName": "LeftHand", - "positionVar": "leftHandPosition", - "rotationVar": "leftHandRotation", - "typeVar": "leftHandType" - }, - { - "jointName": "RightFoot", - "positionVar": "rightFootPosition", - "rotationVar": "rightFootRotation", - "typeVar": "rightFootType" - }, - { - "jointName": "LeftFoot", - "positionVar": "leftFootPosition", - "rotationVar": "leftFootRotation", - "typeVar": "leftFootType" - }, - { - "jointName": "Neck", - "positionVar": "neckPosition", - "rotationVar": "neckRotation", - "typeVar": "neckType" - }, - { - "jointName": "Head", - "positionVar": "headPosition", - "rotationVar": "headRotation", - "typeVar": "headType" - } - ] - }, - "children": [] - }, - { - "id": "manipulatorOverlay", + "id": "userAnimNone", "type": "overlay", "data": { "alpha": 1.0, - "boneSet": "spineOnly" + "alphaVar": "ikOverlayAlpha", + "boneSet": "fullBody" }, "children": [ { - "id": "spineLean", - "type": "manipulator", + "id": "ik", + "type": "inverseKinematics", "data": { - "alpha": 0.0, - "joints": [ - { "var": "lean", "jointName": "Spine" } + "targets": [ + { + "jointName": "RightHand", + "positionVar": "rightHandPosition", + "rotationVar": "rightHandRotation", + "typeVar": "rightHandType" + }, + { + "jointName": "LeftHand", + "positionVar": "leftHandPosition", + "rotationVar": "leftHandRotation", + "typeVar": "leftHandType" + }, + { + "jointName": "RightFoot", + "positionVar": "rightFootPosition", + "rotationVar": "rightFootRotation", + "typeVar": "rightFootType" + }, + { + "jointName": "LeftFoot", + "positionVar": "leftFootPosition", + "rotationVar": "leftFootRotation", + "typeVar": "leftFootType" + }, + { + "jointName": "Neck", + "positionVar": "neckPosition", + "rotationVar": "neckRotation", + "typeVar": "neckType" + }, + { + "jointName": "Head", + "positionVar": "headPosition", + "rotationVar": "headRotation", + "typeVar": "headType" + } ] }, "children": [] }, { - "id": "rightHandOverlay", + "id": "manipulatorOverlay", "type": "overlay", "data": { "alpha": 1.0, - "boneSet": "rightHand", - "alphaVar": "rightHandOverlayAlpha" + "boneSet": "spineOnly" }, "children": [ { - "id": "rightHandStateMachine", - "type": "stateMachine", + "id": "spineLean", + "type": "manipulator", "data": { - "currentState": "rightHandIdle", - "states": [ - { - "id": "rightHandIdle", - "interpTarget": 3, - "interpDuration": 3, - "transitions": [ - { "var": "isRightHandPoint", "state": "rightHandPointIntro" }, - { "var": "isRightHandGrab", "state": "rightHandGrab" } - ] - }, - { - "id": "rightHandPointIntro", - "interpTarget": 3, - "interpDuration": 3, - "transitions": [ - { "var": "isRightHandIdle", "state": "rightHandIdle" }, - { "var": "isRightHandPointIntroOnDone", "state": "rightHandPointHold" }, - { "var": "isRightHandGrab", "state": "rightHandGrab" } - ] - }, - { - "id": "rightHandPointHold", - "interpTarget": 3, - "interpDuration": 3, - "transitions": [ - { "var": "isRightHandIdle", "state": "rightHandPointOutro" }, - { "var": "isRightHandGrab", "state": "rightHandGrab" } - ] - }, - { - "id": "rightHandPointOutro", - "interpTarget": 3, - "interpDuration": 3, - "transitions": [ - { "var": "isRightHandPointOutroOnDone", "state": "rightHandIdle" }, - { "var": "isRightHandGrab", "state": "rightHandGrab" }, - { "var": "isRightHandPoint", "state": "rightHandPointHold" } - ] - }, - { - "id": "rightHandGrab", - "interpTarget": 3, - "interpDuration": 3, - "transitions": [ - { "var": "isRightHandIdle", "state": "rightHandIdle" }, - { "var": "isRightHandPoint_DISABLED", "state": "rightHandPointHold" } - ] - } + "alpha": 0.0, + "joints": [ + { "var": "lean", "jointName": "Spine" } ] }, - "children": [ - { - "id": "rightHandIdle", - "type": "clip", - "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx", - "startFrame": 0.0, - "endFrame": 0.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] - }, - { - "id": "rightHandPointHold", - "type": "clip", - "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx", - "startFrame": 12.0, - "endFrame": 12.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] - }, - { - "id": "rightHandPointIntro", - "type": "clip", - "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx", - "startFrame": 0.0, - "endFrame": 12.0, - "timeScale": 1.0, - "loopFlag": false - }, - "children": [] - }, - { - "id": "rightHandPointOutro", - "type": "clip", - "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx", - "startFrame": 12.0, - "endFrame": 65.0, - "timeScale": 1.0, - "loopFlag": false - }, - "children": [] - }, - { - "id": "rightHandGrab", - "type": "blendLinear", - "data": { - "alpha": 0.0, - "alphaVar": "rightHandGrabBlend" - }, - "children": [ - { - "id": "rightHandOpen", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_right.fbx", - "startFrame": 0.0, - "endFrame": 0.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] - }, - { - "id": "rightHandClose", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_right.fbx", - "startFrame": 10.0, - "endFrame": 10.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] - } - ] - } - ] + "children": [] }, { - "id": "leftHandOverlay", + "id": "rightHandOverlay", "type": "overlay", "data": { "alpha": 1.0, - "boneSet": "leftHand", - "alphaVar" : "leftHandOverlay" + "boneSet": "rightHand", + "alphaVar": "rightHandOverlayAlpha" }, "children": [ { - "id": "leftHandStateMachine", + "id": "rightHandStateMachine", "type": "stateMachine", "data": { - "currentState": "leftHandIdle", + "currentState": "rightHandIdle", "states": [ { - "id": "leftHandIdle", + "id": "rightHandIdle", "interpTarget": 3, "interpDuration": 3, "transitions": [ - { "var": "isLeftHandPoint", "state": "leftHandPointIntro" }, - { "var": "isLeftHandGrab", "state": "leftHandGrab" } + { "var": "isRightHandPoint", "state": "rightHandPointIntro" }, + { "var": "isRightHandGrab", "state": "rightHandGrab" } ] }, { - "id": "leftHandPointIntro", + "id": "rightHandPointIntro", "interpTarget": 3, "interpDuration": 3, "transitions": [ - { "var": "isLeftHandIdle", "state": "leftHandIdle" }, - { "var": "isLeftHandPointIntroOnDone", "state": "leftHandPointHold" }, - { "var": "isLeftHandGrab", "state": "leftHandGrab" } + { "var": "isRightHandIdle", "state": "rightHandIdle" }, + { "var": "isRightHandPointIntroOnDone", "state": "rightHandPointHold" }, + { "var": "isRightHandGrab", "state": "rightHandGrab" } ] }, { - "id": "leftHandPointHold", + "id": "rightHandPointHold", "interpTarget": 3, "interpDuration": 3, "transitions": [ - { "var": "isLeftHandIdle", "state": "leftHandPointOutro" }, - { "var": "isLeftHandGrab", "state": "leftHandGrab" } + { "var": "isRightHandIdle", "state": "rightHandPointOutro" }, + { "var": "isRightHandGrab", "state": "rightHandGrab" } ] }, { - "id": "leftHandPointOutro", + "id": "rightHandPointOutro", "interpTarget": 3, "interpDuration": 3, "transitions": [ - { "var": "isLeftHandPointOutroOnDone", "state": "leftHandIdle" }, - { "var": "isLeftHandGrab", "state": "leftHandGrab" }, - { "var": "isLeftHandPoint", "state": "leftHandPointHold" } + { "var": "isRightHandPointOutroOnDone", "state": "rightHandIdle" }, + { "var": "isRightHandGrab", "state": "rightHandGrab" }, + { "var": "isRightHandPoint", "state": "rightHandPointHold" } ] }, { - "id": "leftHandGrab", + "id": "rightHandGrab", "interpTarget": 3, "interpDuration": 3, "transitions": [ - { "var": "isLeftHandIdle", "state": "leftHandIdle" }, - { "var": "isLeftHandPoint_DISABLED", "state": "leftHandPointHold" } + { "var": "isRightHandIdle", "state": "rightHandIdle" }, + { "var": "isRightHandPoint_DISABLED", "state": "rightHandPointHold" } ] } ] }, "children": [ { - "id": "leftHandIdle", + "id": "rightHandIdle", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx", + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx", "startFrame": 0.0, "endFrame": 0.0, "timeScale": 1.0, @@ -300,10 +187,10 @@ "children": [] }, { - "id": "leftHandPointHold", + "id": "rightHandPointHold", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx", + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx", "startFrame": 12.0, "endFrame": 12.0, "timeScale": 1.0, @@ -312,10 +199,10 @@ "children": [] }, { - "id": "leftHandPointIntro", + "id": "rightHandPointIntro", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx", + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx", "startFrame": 0.0, "endFrame": 12.0, "timeScale": 1.0, @@ -324,10 +211,10 @@ "children": [] }, { - "id": "leftHandPointOutro", + "id": "rightHandPointOutro", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx", + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx", "startFrame": 12.0, "endFrame": 65.0, "timeScale": 1.0, @@ -336,18 +223,18 @@ "children": [] }, { - "id": "leftHandGrab", + "id": "rightHandGrab", "type": "blendLinear", "data": { "alpha": 0.0, - "alphaVar": "leftHandGrabBlend" + "alphaVar": "rightHandGrabBlend" }, "children": [ { - "id": "leftHandOpen", + "id": "rightHandOpen", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_left.fbx", + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_right.fbx", "startFrame": 0.0, "endFrame": 0.0, "timeScale": 1.0, @@ -356,10 +243,10 @@ "children": [] }, { - "id": "leftHandClose", + "id": "rightHandClose", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_left.fbx", + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_right.fbx", "startFrame": 10.0, "endFrame": 10.0, "timeScale": 1.0, @@ -372,313 +259,427 @@ ] }, { - "id": "mainStateMachine", - "type": "stateMachine", + "id": "leftHandOverlay", + "type": "overlay", "data": { - "currentState": "idle", - "states": [ - { - "id": "idle", - "interpTarget": 15, - "interpDuration": 15, - "transitions": [ - { "var": "isMovingForward", "state": "walkFwd" }, - { "var": "isMovingBackward", "state": "walkBwd" }, - { "var": "isMovingRight", "state": "strafeRight" }, - { "var": "isMovingLeft", "state": "strafeLeft" }, - { "var": "isTurningRight", "state": "turnRight" }, - { "var": "isTurningLeft", "state": "turnLeft" }, - { "var": "isAway", "state": "awayIntro" } - ] - }, - { - "id": "walkFwd", - "interpTarget": 6, - "interpDuration": 6, - "transitions": [ - { "var": "isNotMoving", "state": "idle" }, - { "var": "isMovingBackward", "state": "walkBwd" }, - { "var": "isMovingRight", "state": "strafeRight" }, - { "var": "isMovingLeft", "state": "strafeLeft" }, - { "var": "isTurningRight", "state": "turnRight" }, - { "var": "isTurningLeft", "state": "turnLeft" }, - { "var": "isAway", "state": "awayIntro" } - ] - }, - { - "id": "walkBwd", - "interpTarget": 6, - "interpDuration": 6, - "transitions": [ - { "var": "isNotMoving", "state": "idle" }, - { "var": "isMovingForward", "state": "walkFwd" }, - { "var": "isMovingRight", "state": "strafeRight" }, - { "var": "isMovingLeft", "state": "strafeLeft" }, - { "var": "isTurningRight", "state": "turnRight" }, - { "var": "isTurningLeft", "state": "turnLeft" }, - { "var": "isAway", "state": "awayIntro" } - ] - }, - { - "id": "strafeRight", - "interpTarget": 6, - "interpDuration": 6, - "transitions": [ - { "var": "isNotMoving", "state": "idle" }, - { "var": "isMovingForward", "state": "walkFwd" }, - { "var": "isMovingBackward", "state": "walkBwd" }, - { "var": "isMovingLeft", "state": "strafeLeft" }, - { "var": "isTurningRight", "state": "turnRight" }, - { "var": "isTurningLeft", "state": "turnLeft" }, - { "var": "isAway", "state": "awayIntro" } - ] - }, - { - "id": "strafeLeft", - "interpTarget": 6, - "interpDuration": 6, - "transitions": [ - { "var": "isNotMoving", "state": "idle" }, - { "var": "isMovingForward", "state": "walkFwd" }, - { "var": "isMovingBackward", "state": "walkBwd" }, - { "var": "isMovingRight", "state": "strafeRight" }, - { "var": "isTurningRight", "state": "turnRight" }, - { "var": "isTurningLeft", "state": "turnLeft" }, - { "var": "isAway", "state": "awayIntro" } - ] - }, - { - "id": "turnRight", - "interpTarget": 6, - "interpDuration": 6, - "transitions": [ - { "var": "isNotTurning", "state": "idle" }, - { "var": "isMovingForward", "state": "walkFwd" }, - { "var": "isMovingBackward", "state": "walkBwd" }, - { "var": "isMovingRight", "state": "strafeRight" }, - { "var": "isMovingLeft", "state": "strafeLeft" }, - { "var": "isTurningLeft", "state": "turnLeft" }, - { "var": "isAway", "state": "awayIntro" } - ] - }, - { - "id": "turnLeft", - "interpTarget": 6, - "interpDuration": 6, - "transitions": [ - { "var": "isNotTurning", "state": "idle" }, - { "var": "isMovingForward", "state": "walkFwd" }, - { "var": "isMovingBackward", "state": "walkBwd" }, - { "var": "isMovingRight", "state": "strafeRight" }, - { "var": "isMovingLeft", "state": "strafeLeft" }, - { "var": "isTurningRight", "state": "turnRight" }, - { "var": "isAway", "state": "awayIntro" } - ] - }, - { - "id": "awayIntro", - "interpTarget": 30, - "interpDuration": 30, - "transitions": [ - { "var": "awayIntroOnDone", "state": "away"} - ] - }, - { - "id": "away", - "interpTarget": 3, - "interpDuration": 3, - "transitions": [ - { "var": "isNotAway", "state": "awayOutro" } - ] - }, - { - "id": "awayOutro", - "interpTarget": 3, - "interpDuration": 3, - "transitions": [ - { "var": "awayOutroOnDone", "state": "idle" } - ] - } - ] + "alpha": 1.0, + "boneSet": "leftHand", + "alphaVar" : "leftHandOverlay" }, "children": [ { - "id": "idle", + "id": "leftHandStateMachine", "type": "stateMachine", "data": { - "currentState": "idleStand", + "currentState": "leftHandIdle", "states": [ { - "id": "idleStand", - "interpTarget": 6, - "interpDuration": 6, + "id": "leftHandIdle", + "interpTarget": 3, + "interpDuration": 3, "transitions": [ - { "var": "isTalking", "state": "idleTalk" } + { "var": "isLeftHandPoint", "state": "leftHandPointIntro" }, + { "var": "isLeftHandGrab", "state": "leftHandGrab" } ] }, { - "id": "idleTalk", - "interpTarget": 6, - "interpDuration": 6, + "id": "leftHandPointIntro", + "interpTarget": 3, + "interpDuration": 3, "transitions": [ - { "var": "notIsTalking", "state": "idleStand" } + { "var": "isLeftHandIdle", "state": "leftHandIdle" }, + { "var": "isLeftHandPointIntroOnDone", "state": "leftHandPointHold" }, + { "var": "isLeftHandGrab", "state": "leftHandGrab" } + ] + }, + { + "id": "leftHandPointHold", + "interpTarget": 3, + "interpDuration": 3, + "transitions": [ + { "var": "isLeftHandIdle", "state": "leftHandPointOutro" }, + { "var": "isLeftHandGrab", "state": "leftHandGrab" } + ] + }, + { + "id": "leftHandPointOutro", + "interpTarget": 3, + "interpDuration": 3, + "transitions": [ + { "var": "isLeftHandPointOutroOnDone", "state": "leftHandIdle" }, + { "var": "isLeftHandGrab", "state": "leftHandGrab" }, + { "var": "isLeftHandPoint", "state": "leftHandPointHold" } + ] + }, + { + "id": "leftHandGrab", + "interpTarget": 3, + "interpDuration": 3, + "transitions": [ + { "var": "isLeftHandIdle", "state": "leftHandIdle" }, + { "var": "isLeftHandPoint_DISABLED", "state": "leftHandPointHold" } ] } ] }, "children": [ { - "id": "idleStand", + "id": "leftHandIdle", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx", + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx", "startFrame": 0.0, - "endFrame": 90.0, + "endFrame": 0.0, "timeScale": 1.0, "loopFlag": true }, "children": [] }, { - "id": "idleTalk", + "id": "leftHandPointHold", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/talk/talk.fbx", - "startFrame": 0.0, - "endFrame": 801.0, + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx", + "startFrame": 12.0, + "endFrame": 12.0, "timeScale": 1.0, "loopFlag": true }, "children": [] + }, + { + "id": "leftHandPointIntro", + "type": "clip", + "data": { + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx", + "startFrame": 0.0, + "endFrame": 12.0, + "timeScale": 1.0, + "loopFlag": false + }, + "children": [] + }, + { + "id": "leftHandPointOutro", + "type": "clip", + "data": { + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx", + "startFrame": 12.0, + "endFrame": 65.0, + "timeScale": 1.0, + "loopFlag": false + }, + "children": [] + }, + { + "id": "leftHandGrab", + "type": "blendLinear", + "data": { + "alpha": 0.0, + "alphaVar": "leftHandGrabBlend" + }, + "children": [ + { + "id": "leftHandOpen", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_left.fbx", + "startFrame": 0.0, + "endFrame": 0.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "leftHandClose", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/grab/grab_left.fbx", + "startFrame": 10.0, + "endFrame": 10.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + } + ] } ] }, { - "id": "walkFwd", - "type": "blendLinearMove", + "id": "mainStateMachine", + "type": "stateMachine", "data": { - "alpha": 0.0, - "desiredSpeed": 1.4, - "characteristicSpeeds": [0.5, 1.4, 4.5], - "alphaVar": "moveForwardAlpha", - "desiredSpeedVar": "moveForwardSpeed" + "currentState": "idle", + "states": [ + { + "id": "idle", + "interpTarget": 15, + "interpDuration": 15, + "transitions": [ + { "var": "isMovingForward", "state": "walkFwd" }, + { "var": "isMovingBackward", "state": "walkBwd" }, + { "var": "isMovingRight", "state": "strafeRight" }, + { "var": "isMovingLeft", "state": "strafeLeft" }, + { "var": "isTurningRight", "state": "turnRight" }, + { "var": "isTurningLeft", "state": "turnLeft" }, + { "var": "isAway", "state": "awayIntro" } + ] + }, + { + "id": "walkFwd", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isNotMoving", "state": "idle" }, + { "var": "isMovingBackward", "state": "walkBwd" }, + { "var": "isMovingRight", "state": "strafeRight" }, + { "var": "isMovingLeft", "state": "strafeLeft" }, + { "var": "isTurningRight", "state": "turnRight" }, + { "var": "isTurningLeft", "state": "turnLeft" }, + { "var": "isAway", "state": "awayIntro" } + ] + }, + { + "id": "walkBwd", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isNotMoving", "state": "idle" }, + { "var": "isMovingForward", "state": "walkFwd" }, + { "var": "isMovingRight", "state": "strafeRight" }, + { "var": "isMovingLeft", "state": "strafeLeft" }, + { "var": "isTurningRight", "state": "turnRight" }, + { "var": "isTurningLeft", "state": "turnLeft" }, + { "var": "isAway", "state": "awayIntro" } + ] + }, + { + "id": "strafeRight", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isNotMoving", "state": "idle" }, + { "var": "isMovingForward", "state": "walkFwd" }, + { "var": "isMovingBackward", "state": "walkBwd" }, + { "var": "isMovingLeft", "state": "strafeLeft" }, + { "var": "isTurningRight", "state": "turnRight" }, + { "var": "isTurningLeft", "state": "turnLeft" }, + { "var": "isAway", "state": "awayIntro" } + ] + }, + { + "id": "strafeLeft", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isNotMoving", "state": "idle" }, + { "var": "isMovingForward", "state": "walkFwd" }, + { "var": "isMovingBackward", "state": "walkBwd" }, + { "var": "isMovingRight", "state": "strafeRight" }, + { "var": "isTurningRight", "state": "turnRight" }, + { "var": "isTurningLeft", "state": "turnLeft" }, + { "var": "isAway", "state": "awayIntro" } + ] + }, + { + "id": "turnRight", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isNotTurning", "state": "idle" }, + { "var": "isMovingForward", "state": "walkFwd" }, + { "var": "isMovingBackward", "state": "walkBwd" }, + { "var": "isMovingRight", "state": "strafeRight" }, + { "var": "isMovingLeft", "state": "strafeLeft" }, + { "var": "isTurningLeft", "state": "turnLeft" }, + { "var": "isAway", "state": "awayIntro" } + ] + }, + { + "id": "turnLeft", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isNotTurning", "state": "idle" }, + { "var": "isMovingForward", "state": "walkFwd" }, + { "var": "isMovingBackward", "state": "walkBwd" }, + { "var": "isMovingRight", "state": "strafeRight" }, + { "var": "isMovingLeft", "state": "strafeLeft" }, + { "var": "isTurningRight", "state": "turnRight" }, + { "var": "isAway", "state": "awayIntro" } + ] + }, + { + "id": "awayIntro", + "interpTarget": 30, + "interpDuration": 30, + "transitions": [ + { "var": "awayIntroOnDone", "state": "away"} + ] + }, + { + "id": "away", + "interpTarget": 3, + "interpDuration": 3, + "transitions": [ + { "var": "isNotAway", "state": "awayOutro" } + ] + }, + { + "id": "awayOutro", + "interpTarget": 3, + "interpDuration": 3, + "transitions": [ + { "var": "awayOutroOnDone", "state": "idle" } + ] + } + ] }, "children": [ { - "id": "walkFwdShort", - "type": "clip", + "id": "idle", + "type": "stateMachine", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_short_fwd.fbx", - "startFrame": 0.0, - "endFrame": 39.0, - "timeScale": 1.0, - "loopFlag": true + "currentState": "idleStand", + "states": [ + { + "id": "idleStand", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "isTalking", "state": "idleTalk" } + ] + }, + { + "id": "idleTalk", + "interpTarget": 6, + "interpDuration": 6, + "transitions": [ + { "var": "notIsTalking", "state": "idleStand" } + ] + } + ] }, - "children": [] + "children": [ + { + "id": "idleStand", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx", + "startFrame": 0.0, + "endFrame": 90.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "idleTalk", + "type": "clip", + "data": { + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/talk/talk.fbx", + "startFrame": 0.0, + "endFrame": 801.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + } + ] }, { - "id": "walkFwdNormal", - "type": "clip", + "id": "walkFwd", + "type": "blendLinearMove", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_fwd.fbx", - "startFrame": 0.0, - "endFrame": 35.0, - "timeScale": 1.0, - "loopFlag": true + "alpha": 0.0, + "desiredSpeed": 1.4, + "characteristicSpeeds": [0.5, 1.4, 4.5], + "alphaVar": "moveForwardAlpha", + "desiredSpeedVar": "moveForwardSpeed" }, - "children": [] + "children": [ + { + "id": "walkFwdShort", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_short_fwd.fbx", + "startFrame": 0.0, + "endFrame": 39.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "walkFwdNormal", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_fwd.fbx", + "startFrame": 0.0, + "endFrame": 35.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "walkFwdRun", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/run_fwd.fbx", + "startFrame": 0.0, + "endFrame": 21.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + } + ] }, { - "id": "walkFwdRun", - "type": "clip", + "id": "walkBwd", + "type": "blendLinearMove", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/run_fwd.fbx", - "startFrame": 0.0, - "endFrame": 21.0, - "timeScale": 1.0, - "loopFlag": true + "alpha": 0.0, + "desiredSpeed": 1.4, + "characteristicSpeeds": [0.6, 1.45], + "alphaVar": "moveBackwardAlpha", + "desiredSpeedVar": "moveBackwardSpeed" }, - "children": [] - } - ] - }, - { - "id": "walkBwd", - "type": "blendLinearMove", - "data": { - "alpha": 0.0, - "desiredSpeed": 1.4, - "characteristicSpeeds": [0.6, 1.45], - "alphaVar": "moveBackwardAlpha", - "desiredSpeedVar": "moveBackwardSpeed" - }, - "children": [ - { - "id": "walkBwdShort", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_short_bwd.fbx", - "startFrame": 0.0, - "endFrame": 38.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] + "children": [ + { + "id": "walkBwdShort", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_short_bwd.fbx", + "startFrame": 0.0, + "endFrame": 38.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "walkBwdNormal", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_bwd.fbx", + "startFrame": 0.0, + "endFrame": 36.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + } + ] }, { - "id": "walkBwdNormal", + "id": "turnLeft", "type": "clip", "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_bwd.fbx", - "startFrame": 0.0, - "endFrame": 36.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] - } - ] - }, - { - "id": "turnLeft", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_left.fbx", - "startFrame": 0.0, - "endFrame": 28.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] - }, - { - "id": "turnRight", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_right.fbx", - "startFrame": 0.0, - "endFrame": 30.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] - }, - { - "id": "strafeLeft", - "type": "blendLinearMove", - "data": { - "alpha": 0.0, - "desiredSpeed": 1.4, - "characteristicSpeeds": [0.2, 0.65], - "alphaVar": "moveLateralAlpha", - "desiredSpeedVar": "moveLateralSpeed" - }, - "children": [ - { - "id": "strafeLeftShort", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_short_left.fbx", + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_left.fbx", "startFrame": 0.0, "endFrame": 28.0, "timeScale": 1.0, @@ -687,91 +688,128 @@ "children": [] }, { - "id": "strafeLeftNormal", + "id": "turnRight", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_left.fbx", + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_right.fbx", "startFrame": 0.0, "endFrame": 30.0, "timeScale": 1.0, "loopFlag": true }, "children": [] - } - ] - }, - { - "id": "strafeRight", - "type": "blendLinearMove", - "data": { - "alpha": 0.0, - "desiredSpeed": 1.4, - "characteristicSpeeds": [0.2, 0.65], - "alphaVar": "moveLateralAlpha", - "desiredSpeedVar": "moveLateralSpeed" - }, - "children": [ - { - "id": "strafeRightShort", - "type": "clip", - "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_short_right.fbx", - "startFrame": 0.0, - "endFrame": 28.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] }, { - "id": "strafeRightNormal", + "id": "strafeLeft", + "type": "blendLinearMove", + "data": { + "alpha": 0.0, + "desiredSpeed": 1.4, + "characteristicSpeeds": [0.2, 0.65], + "alphaVar": "moveLateralAlpha", + "desiredSpeedVar": "moveLateralSpeed" + }, + "children": [ + { + "id": "strafeLeftShort", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_short_left.fbx", + "startFrame": 0.0, + "endFrame": 28.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "strafeLeftNormal", + "type": "clip", + "data": { + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_left.fbx", + "startFrame": 0.0, + "endFrame": 30.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + } + ] + }, + { + "id": "strafeRight", + "type": "blendLinearMove", + "data": { + "alpha": 0.0, + "desiredSpeed": 1.4, + "characteristicSpeeds": [0.2, 0.65], + "alphaVar": "moveLateralAlpha", + "desiredSpeedVar": "moveLateralSpeed" + }, + "children": [ + { + "id": "strafeRightShort", + "type": "clip", + "data": { + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_short_right.fbx", + "startFrame": 0.0, + "endFrame": 28.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "strafeRightNormal", + "type": "clip", + "data": { + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_right.fbx", + "startFrame": 0.0, + "endFrame": 30.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + } + ] + }, + { + "id": "awayIntro", "type": "clip", "data": { - "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/side_step_right.fbx", + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx", "startFrame": 0.0, - "endFrame": 30.0, + "endFrame": 83.0, + "timeScale": 1.0, + "loopFlag": false + }, + "children": [] + }, + { + "id": "away", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx", + "startFrame": 83.0, + "endFrame": 84.0, "timeScale": 1.0, "loopFlag": true }, "children": [] + }, + { + "id": "awayOutro", + "type": "clip", + "data": { + "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx", + "startFrame": 84.0, + "endFrame": 167.0, + "timeScale": 1.0, + "loopFlag": false + }, + "children": [] } ] - }, - { - "id": "awayIntro", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx", - "startFrame": 0.0, - "endFrame": 83.0, - "timeScale": 1.0, - "loopFlag": false - }, - "children": [] - }, - { - "id": "away", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx", - "startFrame": 83.0, - "endFrame": 84.0, - "timeScale": 1.0, - "loopFlag": true - }, - "children": [] - }, - { - "id": "awayOutro", - "type": "clip", - "data": { - "url": "https://hifi-public.s3.amazonaws.com/ozan/anim/kneel/kneel.fbx", - "startFrame": 84.0, - "endFrame": 167.0, - "timeScale": 1.0, - "loopFlag": false - }, - "children": [] } ] } @@ -780,6 +818,30 @@ ] } ] + }, + { + "id": "userAnimA", + "type": "clip", + "data": { + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx", + "startFrame": 0.0, + "endFrame": 90.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] + }, + { + "id": "userAnimB", + "type": "clip", + "data": { + "url": "http://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx", + "startFrame": 0.0, + "endFrame": 90.0, + "timeScale": 1.0, + "loopFlag": true + }, + "children": [] } ] } diff --git a/libraries/animation/src/AnimClip.h b/libraries/animation/src/AnimClip.h index 36867e622b..934f3f3ed8 100644 --- a/libraries/animation/src/AnimClip.h +++ b/libraries/animation/src/AnimClip.h @@ -37,13 +37,18 @@ public: void setFrameVar(const QString& frameVar) { _frameVar = frameVar; } float getStartFrame() const { return _startFrame; } + void setStartFrame(float startFrame) { _startFrame = startFrame; } float getEndFrame() const { return _endFrame; } + void setEndFrame(float endFrame) { _endFrame = endFrame; } void setTimeScale(float timeScale) { _timeScale = timeScale; } float getTimeScale() const { return _timeScale; } -protected: + bool getLoopFlag() const { return _loopFlag; } + void setLoopFlag(bool loopFlag) { _loopFlag = loopFlag; } + void loadURL(const QString& url); +protected: virtual void setCurrentFrameInternal(float frame) override; diff --git a/libraries/animation/src/AnimUtil.cpp b/libraries/animation/src/AnimUtil.cpp index e9e5ea95de..eb01bc31c2 100644 --- a/libraries/animation/src/AnimUtil.cpp +++ b/libraries/animation/src/AnimUtil.cpp @@ -18,8 +18,17 @@ void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, A for (size_t i = 0; i < numPoses; i++) { const AnimPose& aPose = a[i]; const AnimPose& bPose = b[i]; + + // adjust signs if necessary + const glm::quat& q1 = aPose.rot; + glm::quat q2 = bPose.rot; + float dot = glm::dot(q1, q2); + if (dot < 0.0f) { + q2 = -q2; + } + result[i].scale = lerp(aPose.scale, bPose.scale, alpha); - result[i].rot = glm::normalize(glm::lerp(aPose.rot, bPose.rot, alpha)); + result[i].rot = glm::normalize(glm::lerp(aPose.rot, q2, alpha)); result[i].trans = lerp(aPose.trans, bPose.trans, alpha); } } diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 7926b268b5..72a1eeae5c 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -21,6 +21,7 @@ #include "AnimationHandle.h" #include "AnimationLogging.h" #include "AnimSkeleton.h" +#include "AnimClip.h" #include "IKTarget.h" void insertSorted(QList& handles, const AnimationHandlePointer& handle) { @@ -45,28 +46,61 @@ void Rig::removeAnimationHandle(const AnimationHandlePointer& handle) { } void Rig::startAnimation(const QString& url, float fps, float priority, - bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints) { - // This is different than startAnimationByRole, in which we use the existing values if the animation already exists. - // Here we reuse the animation handle if possible, but in any case, we set the values to those given (or defaulted). - AnimationHandlePointer handle = nullptr; - foreach (const AnimationHandlePointer& candidate, _animationHandles) { - if (candidate->getURL() == url) { - handle = candidate; + bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints) { + if (_enableAnimGraph) { + + // NOTE: mask joints are unsupported, priority is now meaningless, hold flag is essentially always true + // when using the AnimGraph system. + + // find an unused AnimClip clipNode + std::shared_ptr clip; + if (_userAnimState == UserAnimState::None || _userAnimState == UserAnimState::B) { + _userAnimState = UserAnimState::A; + clip = std::dynamic_pointer_cast(_animNode->getChild((int)_userAnimState)); + } else if (_userAnimState == UserAnimState::A) { + _userAnimState = UserAnimState::B; + clip = std::dynamic_pointer_cast(_animNode->getChild((int)_userAnimState)); } + + // set parameters + clip->setLoopFlag(loop); + clip->setStartFrame(firstFrame); + clip->setEndFrame(lastFrame); + const float REFERENCE_FRAMES_PER_SECOND = 30.0f; + clip->setTimeScale(fps / REFERENCE_FRAMES_PER_SECOND); + clip->loadURL(url); + + _currentUserAnimURL = url; + + // notify the userAnimStateMachine the desired state. + _animVars.set("userAnimNone", false); + _animVars.set("userAnimA", _userAnimState == UserAnimState::A); + _animVars.set("userAnimB", _userAnimState == UserAnimState::B); + + } else { + + // This is different than startAnimationByRole, in which we use the existing values if the animation already exists. + // Here we reuse the animation handle if possible, but in any case, we set the values to those given (or defaulted). + AnimationHandlePointer handle = nullptr; + foreach (const AnimationHandlePointer& candidate, _animationHandles) { + if (candidate->getURL() == url) { + handle = candidate; + } + } + if (!handle) { + handle = createAnimationHandle(); + handle->setURL(url); + } + handle->setFade(1.0f); // If you want to fade, use the startAnimationByRole system. + handle->setFPS(fps); + handle->setPriority(priority); + handle->setLoop(loop); + handle->setHold(hold); + handle->setFirstFrame(firstFrame); + handle->setLastFrame(lastFrame); + handle->setMaskedJoints(maskedJoints); + handle->start(); } - if (!handle) { - handle = createAnimationHandle(); - handle->setURL(url); - } - handle->setFade(1.0f); // If you want to fade, use the startAnimationByRole system. - handle->setFPS(fps); - handle->setPriority(priority); - handle->setLoop(loop); - handle->setHold(hold); - handle->setFirstFrame(firstFrame); - handle->setLastFrame(lastFrame); - handle->setMaskedJoints(maskedJoints); - handle->start(); } AnimationHandlePointer Rig::addAnimationByRole(const QString& role, const QString& url, float fps, float priority, @@ -138,10 +172,20 @@ void Rig::stopAnimationByRole(const QString& role) { } void Rig::stopAnimation(const QString& url) { - foreach (const AnimationHandlePointer& handle, getRunningAnimations()) { - if (handle->getURL() == url) { - handle->setFade(0.0f); // right away. Will be remove during updateAnimations, without locking - handle->setFadePerSecond(-(FRAMES_PER_SECOND / FADE_FRAMES)); // so that the updateAnimation code notices + if (_enableAnimGraph) { + if (url == _currentUserAnimURL) { + _currentUserAnimURL = ""; + // notify the userAnimStateMachine the desired state. + _animVars.set("userAnimNone", true); + _animVars.set("userAnimA", false); + _animVars.set("userAnimB", false); + } + } else { + foreach (const AnimationHandlePointer& handle, getRunningAnimations()) { + if (handle->getURL() == url) { + handle->setFade(0.0f); // right away. Will be remove during updateAnimations, without locking + handle->setFadePerSecond(-(FRAMES_PER_SECOND / FADE_FRAMES)); // so that the updateAnimation code notices + } } } } diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 98847b9915..e086b81e39 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -223,21 +223,21 @@ public: void calcAnimAlpha(float speed, const std::vector& referenceSpeeds, float* alphaOut) const; QVector _jointStates; - int _rootJointIndex = -1; + int _rootJointIndex { -1 }; - int _leftHandJointIndex = -1; - int _leftElbowJointIndex = -1; - int _leftShoulderJointIndex = -1; + int _leftHandJointIndex { -1 }; + int _leftElbowJointIndex { -1 }; + int _leftShoulderJointIndex { -1 }; - int _rightHandJointIndex = -1; - int _rightElbowJointIndex = -1; - int _rightShoulderJointIndex = -1; + int _rightHandJointIndex { -1 }; + int _rightElbowJointIndex { -1 }; + int _rightShoulderJointIndex { -1 }; QList _animationHandles; QList _runningAnimations; - bool _enableRig = false; - bool _enableAnimGraph = false; + bool _enableRig { false }; + bool _enableAnimGraph { false }; glm::vec3 _lastFront; glm::vec3 _lastPosition; glm::vec3 _lastVelocity; @@ -251,18 +251,25 @@ public: Turn, Move }; - RigRole _state = RigRole::Idle; - RigRole _desiredState = RigRole::Idle; - float _desiredStateAge = 0.0f; - float _leftHandOverlayAlpha = 0.0f; - float _rightHandOverlayAlpha = 0.0f; + RigRole _state { RigRole::Idle }; + RigRole _desiredState { RigRole::Idle }; + float _desiredStateAge { 0.0f }; + enum class UserAnimState { + None = 0, + A, + B + }; + UserAnimState _userAnimState { UserAnimState::None }; + QString _currentUserAnimURL; + float _leftHandOverlayAlpha { 0.0f }; + float _rightHandOverlayAlpha { 0.0f }; - SimpleMovingAverage _averageForwardSpeed{ 10 }; - SimpleMovingAverage _averageLateralSpeed{ 10 }; + SimpleMovingAverage _averageForwardSpeed { 10 }; + SimpleMovingAverage _averageLateralSpeed { 10 }; private: QMap _stateHandlers; - int _nextStateHandlerId {0}; + int _nextStateHandlerId { 0 }; QMutex _stateMutex; };