diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 2fd7364434..215e0095c0 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -604,6 +605,42 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos _lastPosition = worldPosition; } +void Rig::addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList) { + _stateHandlers = handler; +} +void Rig::removeAnimationStateHandler(QScriptValue handler) { + _stateHandlersResultsToRemove = _stateHandlersResults; + _stateHandlers = _stateHandlersResults = QScriptValue(); +} +void Rig::cleanupAnimationStateHandler() { + if (!_stateHandlersResultsToRemove.isValid()) { + return; + } + QScriptValueIterator property(_stateHandlersResultsToRemove); + while (property.hasNext()) { + property.next(); + _animVars.unset(property.name()); + } + _stateHandlersResultsToRemove = QScriptValue(); +} +void Rig::updateAnimationStateHandlers() { + if (!_stateHandlers.isValid()) { + return; + } + // TODO: iterate multiple handlers, but with one shared arg. + // TODO: fill the properties based on the union of requested properties. (Keep all properties objs and compute new union when add/remove handler.) + // TODO: check QScriptEngine::hasUncaughtException() + // TODO: call asynchronously (through a signal on script), so that each script is single threaded, and so we never block here. + // This will require inboundMaps to be kept in the list of per-handler data. + QScriptEngine* engine = _stateHandlers.engine(); + QScriptValue outboundMap = _animVars.animVariantMapToScriptValue(engine); + QScriptValueList args; + args << outboundMap; + _stateHandlersResults = _stateHandlers.call(QScriptValue(), args); + _animVars.animVariantMapFromScriptValue(_stateHandlersResults); + //qCDebug(animation) << _animVars.lookup("foo", QString("not set")); +} + void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) { if (_enableAnimGraph) { @@ -611,20 +648,7 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) { return; } - if (_stateHandlers.isValid()) { - // TODO: iterate multiple handlers, but with one shared arg. - // TODO: fill the properties based on the union of requested properties. (Keep all properties objs and compute new union when add/remove handler.) - // TODO: check QScriptEngine::hasUncaughtException() - // TODO: call asynchronously (through a signal on script), so that each script is single threaded, and so we never block here. - // This will require inboundMaps to be kept in the list of per-handler data. - QScriptEngine* engine = _stateHandlers.engine(); - QScriptValue outboundMap = _animVars.animVariantMapToScriptValue(engine); - QScriptValueList args; - args << outboundMap; - _stateHandlersResults = _stateHandlers.call(QScriptValue(), args); - _animVars.animVariantMapFromScriptValue(_stateHandlersResults); - //qCDebug(animation) << _animVars.lookup("foo", QString("not set")); - } + updateAnimationStateHandlers(); // evaluate the animation AnimNode::Triggers triggersOut; AnimPoseVec poses = _animNode->evaluate(_animVars, deltaTime, triggersOut); @@ -1201,9 +1225,7 @@ void Rig::updateFromHandParameters(const HandParameters& params, float dt) { _animVars.set("leftHandType", (int)IKTarget::Type::HipsRelativeRotationAndPosition); } if (params.isRightEnabled) { - if (!_stateHandlersResults.property("rightHandPosition", QScriptValue::ResolveLocal).isValid()) { - _animVars.set("rightHandPosition", rootBindPose.trans + rootBindPose.rot * yFlipHACK * params.rightPosition); - } + _animVars.set("rightHandPosition", rootBindPose.trans + rootBindPose.rot * yFlipHACK * params.rightPosition); _animVars.set("rightHandRotation", rootBindPose.rot * yFlipHACK * params.rightOrientation); _animVars.set("rightHandType", (int)IKTarget::Type::RotationAndPosition); } else { diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 89fde9002f..3f68deef1a 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -200,12 +200,14 @@ public: AnimNode::ConstPointer getAnimNode() const { return _animNode; } AnimSkeleton::ConstPointer getAnimSkeleton() const { return _animSkeleton; } bool disableHands {false}; // should go away with rig animation (and Rig::inverseKinematics) - void addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList) { _stateHandlers = handler; } - void removeAnimationStateHandler(QScriptValue handler) { _stateHandlers = QScriptValue(); } + void addAnimationStateHandler(QScriptValue handler, QScriptValue propertiesList); + void removeAnimationStateHandler(QScriptValue handler); + void cleanupAnimationStateHandler(); bool getModelOffset(glm::vec3& modelOffsetOut) const; protected: + void updateAnimationStateHandlers(); void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist); void updateNeckJoint(int index, const HeadParameters& params); @@ -248,6 +250,7 @@ public: private: QScriptValue _stateHandlers {}; QScriptValue _stateHandlersResults {}; + QScriptValue _stateHandlersResultsToRemove {}; }; #endif /* defined(__hifi__Rig__) */