Also, split getReactions() API into two calls * getTriggerReactions() - lists all reactions that can be triggered with MyAvatar.triggerReaction(). * getBeginReactions() - lists all reactions that can be used with MyAvatar.beginReaction() and MyAvatar.endReaction().
Unified · Split
| @@ -125,16 +125,25 @@ QString userRecenterModelToString(MyAvatar::SitStandModelType model) { · 124 unmodified lines | |||
| 125 | } | 125 | } |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | static const QStringList REACTION_NAMES = { | 128 | static const QStringList TRIGGER_REACTION_NAMES = { |
| 129 | QString("positive"), | 129 | QString("positive"), |
| 130 | QString("negative"), | 130 | QString("negative") |
| 131 | }; | ||
| 132 | |||
| 133 | static const QStringList BEGIN_END_REACTION_NAMES = { | ||
| 131 | QString("raiseHand"), | 134 | QString("raiseHand"), |
| 132 | QString("applaud"), | 135 | QString("applaud"), |
| 133 | QString("point") | 136 | QString("point") |
| 134 | }; | 137 | }; |
| 135 | 138 | ||
| 136 | static int reactionNameToIndex(const QString& reactionName) { | 139 | static int triggerReactionNameToIndex(const QString& reactionName) { |
| 137 | return REACTION_NAMES.indexOf(reactionName); | 140 | assert(NUM_AVATAR_TRIGGER_REACTIONS == TRIGGER_REACTION_NAMES.size()); |
| 141 | return TRIGGER_REACTION_NAMES.indexOf(reactionName); | ||
| 142 | } | ||
| 143 | |||
| 144 | static int beginEndReactionNameToIndex(const QString& reactionName) { | ||
| 145 | assert(NUM_AVATAR_BEGIN_END_REACTIONS == TRIGGER_REACTION_NAMES.size()); | ||
| 146 | return BEGIN_END_REACTION_NAMES.indexOf(reactionName); | ||
| 138 | } | 147 | } |
| 139 | 148 | ||
| 140 | MyAvatar::MyAvatar(QThread* thread) : | 149 | MyAvatar::MyAvatar(QThread* thread) : |
| @@ -5824,13 +5833,17 @@ void MyAvatar::setModelScale(float scale) { · 5683 unmodified lines | |||
| 5824 | } | 5833 | } |
| 5825 | } | 5834 | } |
| 5826 | 5835 | ||
| 5827 | QStringList MyAvatar::getReactions() const { | 5836 | QStringList MyAvatar::getBeginEndReactions() const { |
| 5828 | return REACTION_NAMES; | 5837 | return BEGIN_END_REACTION_NAMES; |
| 5838 | } | ||
| 5839 | |||
| 5840 | QStringList MyAvatar::getTriggerReactions() const { | ||
| 5841 | return TRIGGER_REACTION_NAMES; | ||
| 5829 | } | 5842 | } |
| 5830 | 5843 | ||
| 5831 | bool MyAvatar::triggerReaction(QString reactionName) { | 5844 | bool MyAvatar::triggerReaction(QString reactionName) { |
| 5832 | int reactionIndex = reactionNameToIndex(reactionName); | 5845 | int reactionIndex = triggerReactionNameToIndex(reactionName); |
| 5833 | if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_REACTIONS) { | 5846 | if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_TRIGGER_REACTIONS) { |
| 5834 | std::lock_guard<std::mutex> guard(_reactionLock); | 5847 | std::lock_guard<std::mutex> guard(_reactionLock); |
| 5835 | _reactionTriggers[reactionIndex] = true; | 5848 | _reactionTriggers[reactionIndex] = true; |
| 5836 | return true; | 5849 | return true; |
| @@ -5839,8 +5852,8 @@ bool MyAvatar::triggerReaction(QString reactionName) { · 2 unmodified lines | |||
| 5839 | } | 5852 | } |
| 5840 | 5853 | ||
| 5841 | bool MyAvatar::beginReaction(QString reactionName) { | 5854 | bool MyAvatar::beginReaction(QString reactionName) { |
| 5842 | int reactionIndex = reactionNameToIndex(reactionName); | 5855 | int reactionIndex = beginEndReactionNameToIndex(reactionName); |
| 5843 | if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_REACTIONS) { | 5856 | if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_BEGIN_END_REACTIONS) { |
| 5844 | std::lock_guard<std::mutex> guard(_reactionLock); | 5857 | std::lock_guard<std::mutex> guard(_reactionLock); |
| 5845 | _reactionEnabledRefCounts[reactionIndex]++; | 5858 | _reactionEnabledRefCounts[reactionIndex]++; |
| 5846 | return true; | 5859 | return true; |
| @@ -5849,8 +5862,8 @@ bool MyAvatar::beginReaction(QString reactionName) { · 2 unmodified lines | |||
| 5849 | } | 5862 | } |
| 5850 | 5863 | ||
| 5851 | bool MyAvatar::endReaction(QString reactionName) { | 5864 | bool MyAvatar::endReaction(QString reactionName) { |
| 5852 | int reactionIndex = reactionNameToIndex(reactionName); | 5865 | int reactionIndex = beginEndReactionNameToIndex(reactionName); |
| 5853 | if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_REACTIONS) { | 5866 | if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_BEGIN_END_REACTIONS) { |
| 5854 | std::lock_guard<std::mutex> guard(_reactionLock); | 5867 | std::lock_guard<std::mutex> guard(_reactionLock); |
| 5855 | _reactionEnabledRefCounts[reactionIndex]--; | 5868 | _reactionEnabledRefCounts[reactionIndex]--; |
| 5856 | return true; | 5869 | return true; |
| @@ -5860,12 +5873,17 @@ bool MyAvatar::endReaction(QString reactionName) { · 3 unmodified lines | |||
| 5860 | 5873 | ||
| 5861 | void MyAvatar::updateRigControllerParameters(Rig::ControllerParameters& params) { | 5874 | void MyAvatar::updateRigControllerParameters(Rig::ControllerParameters& params) { |
| 5862 | std::lock_guard<std::mutex> guard(_reactionLock); | 5875 | std::lock_guard<std::mutex> guard(_reactionLock); |
| 5863 | for (int i = 0; i < NUM_AVATAR_REACTIONS; i++) { | ||
| 5864 | 5876 | ||
| 5877 | for (int i = 0; i < TRIGGER_REACTION_NAMES.size(); i++) { | ||
| 5878 | params.reactionTriggers[i] = _reactionTriggers[i]; | ||
| 5879 | } | ||
| 5880 | |||
| 5881 | for (int i = 0; i < BEGIN_END_REACTION_NAMES.size(); i++) { | ||
| 5865 | // copy current state into params. | 5882 | // copy current state into params. |
| 5866 | params.reactionEnabledFlags[i] = _reactionEnabledRefCounts[i] > 0; | 5883 | params.reactionEnabledFlags[i] = _reactionEnabledRefCounts[i] > 0; |
| 5867 | params.reactionTriggers[i] = _reactionTriggers[i]; | 5884 | } |
| 5868 | 5885 | ||
| 5886 | for (int i = 0; i < TRIGGER_REACTION_NAMES.size(); i++) { | ||
| 5869 | // clear reaction triggers here as well | 5887 | // clear reaction triggers here as well |
| 5870 | _reactionTriggers[i] = false; | 5888 | _reactionTriggers[i] = false; |
| 5871 | } | 5889 | } |
| @@ -2213,13 +2213,23 @@ public slots: · 2212 unmodified lines | |||
| 2213 | virtual void setModelScale(float scale) override; | 2213 | virtual void setModelScale(float scale) override; |
| 2214 | 2214 | ||
| 2215 | /**jsdoc | 2215 | /**jsdoc |
| 2216 | * MyAvatar.getReactions | 2216 | * MyAvatar.getTriggerReactions |
| 2217 | * Returns a list of reactions names that can be triggered using MyAvatar.triggerReaction(). | ||
| 2217 | * @returns {string[]} Array of reaction names. | 2218 | * @returns {string[]} Array of reaction names. |
| 2218 | */ | 2219 | */ |
| 2219 | QStringList getReactions() const; | 2220 | QStringList getTriggerReactions() const; |
| 2221 | |||
| 2222 | |||
| 2223 | /**jsdoc | ||
| 2224 | * MyAvatar.getBeginReactions | ||
| 2225 | * Returns a list of reactions names that can be enabled using MyAvatar.beginReaction() and MyAvatar.endReaction(). | ||
| 2226 | * @returns {string[]} Array of reaction names. | ||
| 2227 | */ | ||
| 2228 | QStringList getBeginEndReactions() const; | ||
| 2220 | 2229 | ||
| 2221 | /**jsdoc | 2230 | /**jsdoc |
| 2222 | * MyAvatar.triggerReaction | 2231 | * MyAvatar.triggerReaction |
| 2232 | * Plays the given reaction on the avatar, once the reaction is complete it will automatically complete. Only reaction names returned from MyAvatar.getTriggerReactions() are available. | ||
| 2223 | * @param {string} reactionName - reaction name | 2233 | * @param {string} reactionName - reaction name |
| 2224 | * @returns {bool} false if the given reaction is not supported. | 2234 | * @returns {bool} false if the given reaction is not supported. |
| 2225 | */ | 2235 | */ |
| @@ -2227,6 +2237,9 @@ public slots: · 1 unmodified line | |||
| 2227 | 2237 | ||
| 2228 | /**jsdoc | 2238 | /**jsdoc |
| 2229 | * MyAvatar.beginReaction | 2239 | * MyAvatar.beginReaction |
| 2240 | * Plays the given reaction on the avatar. The avatar will continue to play the reaction until stopped via the MyAvatar.endReaction() call or superseeded by another reaction. | ||
| 2241 | * Only reaction names returned from MyAvatar.getBeginEndReactions() are available. | ||
| 2242 | * NOTE: the caller is responsible for calling the corresponding MyAvatar.endReaction(), otherwise the avatar might become stuck in the reaction forever. | ||
| 2230 | * @param {string} reactionName - reaction name | 2243 | * @param {string} reactionName - reaction name |
| 2231 | * @returns {bool} false if the given reaction is not supported. | 2244 | * @returns {bool} false if the given reaction is not supported. |
| 2232 | */ | 2245 | */ |
| @@ -2234,6 +2247,7 @@ public slots: · 1 unmodified line | |||
| 2234 | 2247 | ||
| 2235 | /**jsdoc | 2248 | /**jsdoc |
| 2236 | * MyAvatar.endReaction | 2249 | * MyAvatar.endReaction |
| 2250 | * Used to stop a given reaction that was started via MyAvatar.beginReaction(). | ||
| 2237 | * @param {string} reactionName - reaction name | 2251 | * @param {string} reactionName - reaction name |
| 2238 | * @returns {bool} false if the given reaction is not supported. | 2252 | * @returns {bool} false if the given reaction is not supported. |
| 2239 | */ | 2253 | */ |
| @@ -2872,8 +2886,9 @@ private: · 632 unmodified lines | |||
| 2872 | QScriptEngine* _scriptEngine { nullptr }; | 2886 | QScriptEngine* _scriptEngine { nullptr }; |
| 2873 | bool _needToSaveAvatarEntitySettings { false }; | 2887 | bool _needToSaveAvatarEntitySettings { false }; |
| 2874 | 2888 | ||
| 2875 | int _reactionEnabledRefCounts[NUM_AVATAR_REACTIONS] { 0, 0, 0, 0, 0 }; | 2889 | bool _reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS] { false, false }; |
| 2876 | bool _reactionTriggers[NUM_AVATAR_REACTIONS] { false, false, false, false, false }; | 2890 | int _reactionEnabledRefCounts[NUM_AVATAR_BEGIN_END_REACTIONS] { 0, 0, 0 }; |
| 2891 | |||
| 2877 | mutable std::mutex _reactionLock; | 2892 | mutable std::mutex _reactionLock; |
| 2878 | }; | 2893 | }; |
| 2879 | 2894 | ||
| @@ -95,6 +95,15 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co · 94 unmodified lines | |||
| 95 | return _poses; | 95 | return _poses; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | const QString& AnimStateMachine::getCurrentStateID() const { | ||
| 99 | if (_currentState) { | ||
| 100 | return _currentState->getID(); | ||
| 101 | } else { | ||
| 102 | static QString emptyString; | ||
| 103 | return emptyString; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 98 | void AnimStateMachine::setCurrentState(State::Pointer state) { | 107 | void AnimStateMachine::setCurrentState(State::Pointer state) { |
| 99 | _previousState = _currentState ? _currentState : state; | 108 | _previousState = _currentState ? _currentState : state; |
| 100 | _currentState = state; | 109 | _currentState = state; |
| @@ -116,6 +116,7 @@ public: · 115 unmodified lines | |||
| 116 | virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override; | 116 | virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override; |
| 117 | 117 | ||
| 118 | void setCurrentStateVar(QString& currentStateVar) { _currentStateVar = currentStateVar; } | 118 | void setCurrentStateVar(QString& currentStateVar) { _currentStateVar = currentStateVar; } |
| 119 | const QString& getCurrentStateID() const; | ||
| 119 | 120 | ||
| 120 | protected: | 121 | protected: |
| 121 | 122 | ||
| @@ -29,6 +29,7 @@ · 28 unmodified lines | |||
| 29 | #include "AnimInverseKinematics.h" | 29 | #include "AnimInverseKinematics.h" |
| 30 | #include "AnimOverlay.h" | 30 | #include "AnimOverlay.h" |
| 31 | #include "AnimSkeleton.h" | 31 | #include "AnimSkeleton.h" |
| 32 | #include "AnimStateMachine.h" | ||
| 32 | #include "AnimUtil.h" | 33 | #include "AnimUtil.h" |
| 33 | #include "AvatarConstants.h" | 34 | #include "AvatarConstants.h" |
| 34 | #include "IKTarget.h" | 35 | #include "IKTarget.h" |
| @@ -1906,28 +1907,7 @@ void Rig::updateFeet(bool leftFootEnabled, bool rightFootEnabled, bool headEnabl · 1871 unmodified lines | |||
| 1906 | 1907 | ||
| 1907 | void Rig::updateReactions(const ControllerParameters& params) { | 1908 | void Rig::updateReactions(const ControllerParameters& params) { |
| 1908 | 1909 | ||
| 1909 | // enable/disable animVars | 1910 | // trigger reactions |
| 1910 | bool enabled = params.reactionEnabledFlags[AVATAR_REACTION_POSITIVE]; | ||
| 1911 | _animVars.set("reactionPositiveEnabled", enabled); | ||
| 1912 | _animVars.set("reactionPositiveDisabled", !enabled); | ||
| 1913 | |||
| 1914 | enabled = params.reactionEnabledFlags[AVATAR_REACTION_NEGATIVE]; | ||
| 1915 | _animVars.set("reactionNegativeEnabled", enabled); | ||
| 1916 | _animVars.set("reactionNegativeDisabled", !enabled); | ||
| 1917 | |||
| 1918 | enabled = params.reactionEnabledFlags[AVATAR_REACTION_RAISE_HAND]; | ||
| 1919 | _animVars.set("reactionRaiseHandEnabled", enabled); | ||
| 1920 | _animVars.set("reactionRaiseHandDisabled", !enabled); | ||
| 1921 | |||
| 1922 | enabled = params.reactionEnabledFlags[AVATAR_REACTION_APPLAUD]; | ||
| 1923 | _animVars.set("reactionApplaudEnabled", enabled); | ||
| 1924 | _animVars.set("reactionApplaudDisabled", !enabled); | ||
| 1925 | |||
| 1926 | enabled = params.reactionEnabledFlags[AVATAR_REACTION_POINT]; | ||
| 1927 | _animVars.set("reactionPointEnabled", enabled); | ||
| 1928 | _animVars.set("reactionPointDisabled", !enabled); | ||
| 1929 | |||
| 1930 | // trigger animVars | ||
| 1931 | if (params.reactionTriggers[AVATAR_REACTION_POSITIVE]) { | 1911 | if (params.reactionTriggers[AVATAR_REACTION_POSITIVE]) { |
| 1932 | _animVars.set("reactionPositiveTrigger", true); | 1912 | _animVars.set("reactionPositiveTrigger", true); |
| 1933 | } else { | 1913 | } else { |
| @@ -1940,22 +1920,33 @@ void Rig::updateReactions(const ControllerParameters& params) { · 6 unmodified lines | |||
| 1940 | _animVars.set("reactionNegativeTrigger", false); | 1920 | _animVars.set("reactionNegativeTrigger", false); |
| 1941 | } | 1921 | } |
| 1942 | 1922 | ||
| 1943 | if (params.reactionTriggers[AVATAR_REACTION_RAISE_HAND]) { | 1923 | // begin end reactions |
| 1944 | _animVars.set("reactionRaiseHandTrigger", true); | 1924 | bool enabled = params.reactionEnabledFlags[AVATAR_REACTION_RAISE_HAND]; |
| 1945 | } else { | 1925 | _animVars.set("reactionRaiseHandEnabled", enabled); |
| 1946 | _animVars.set("reactionRaiseHandTrigger", false); | 1926 | _animVars.set("reactionRaiseHandDisabled", !enabled); |
| 1947 | } | ||
| 1948 | 1927 | ||
| 1949 | if (params.reactionTriggers[AVATAR_REACTION_APPLAUD]) { | 1928 | enabled = params.reactionEnabledFlags[AVATAR_REACTION_APPLAUD]; |
| 1950 | _animVars.set("reactionApplaudTrigger", true); | 1929 | _animVars.set("reactionApplaudEnabled", enabled); |
| 1951 | } else { | 1930 | _animVars.set("reactionApplaudDisabled", !enabled); |
| 1952 | _animVars.set("reactionApplaudTrigger", false); | ||
| 1953 | } | ||
| 1954 | 1931 | ||
| 1955 | if (params.reactionTriggers[AVATAR_REACTION_POINT]) { | 1932 | enabled = params.reactionEnabledFlags[AVATAR_REACTION_POINT]; |
| 1956 | _animVars.set("reactionPointTrigger", true); | 1933 | _animVars.set("reactionPointEnabled", enabled); |
| 1957 | } else { | 1934 | _animVars.set("reactionPointDisabled", !enabled); |
| 1958 | _animVars.set("reactionPointTrigger", false); | 1935 | |
| 1936 | // determine if we should ramp off IK | ||
| 1937 | if (_enableInverseKinematics) { | ||
| 1938 | bool reactionPlaying = false; | ||
| 1939 | std::shared_ptr<AnimStateMachine> mainStateMachine = std::dynamic_pointer_cast<AnimStateMachine>(_animNode->findByName("mainStateMachine")); | ||
| 1940 | std::shared_ptr<AnimStateMachine> idleStateMachine = std::dynamic_pointer_cast<AnimStateMachine>(_animNode->findByName("idle")); | ||
| 1941 | if (mainStateMachine && mainStateMachine->getCurrentStateID() == "idle" && idleStateMachine) { | ||
| 1942 | reactionPlaying = idleStateMachine->getCurrentStateID().startsWith("reaction"); | ||
| 1943 | } | ||
| 1944 | |||
| 1945 | bool hipsEnabled = params.primaryControllerFlags[PrimaryControllerType_Hips] & (uint8_t)ControllerFlags::Enabled; | ||
| 1946 | if (reactionPlaying && !hipsEnabled) { | ||
| 1947 | // disable head IK while reaction is playing, but only in "desktop" mode. | ||
| 1948 | _animVars.set("headType", (int)IKTarget::Type::Unknown); | ||
| 1949 | } | ||
| 1959 | } | 1950 | } |
| 1960 | } | 1951 | } |
| 1961 | 1952 | ||
| @@ -88,8 +88,8 @@ public: · 87 unmodified lines | |||
| 88 | AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space | 88 | AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space |
| 89 | uint8_t secondaryControllerFlags[NumSecondaryControllerTypes]; | 89 | uint8_t secondaryControllerFlags[NumSecondaryControllerTypes]; |
| 90 | bool isTalking; | 90 | bool isTalking; |
| 91 | bool reactionEnabledFlags[NUM_AVATAR_REACTIONS]; | 91 | bool reactionEnabledFlags[NUM_AVATAR_BEGIN_END_REACTIONS]; |
| 92 | bool reactionTriggers[NUM_AVATAR_REACTIONS]; | 92 | bool reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS]; |
| 93 | HFMJointShapeInfo hipsShapeInfo; | 93 | HFMJointShapeInfo hipsShapeInfo; |
| 94 | HFMJointShapeInfo spineShapeInfo; | 94 | HFMJointShapeInfo spineShapeInfo; |
| 95 | HFMJointShapeInfo spine1ShapeInfo; | 95 | HFMJointShapeInfo spine1ShapeInfo; |
| @@ -106,13 +106,17 @@ static const float AVATAR_WALK_SPEED_SCALAR = 1.0f; · 105 unmodified lines | |||
| 106 | static const float AVATAR_DESKTOP_SPRINT_SPEED_SCALAR = 3.0f; | 106 | static const float AVATAR_DESKTOP_SPRINT_SPEED_SCALAR = 3.0f; |
| 107 | static const float AVATAR_HMD_SPRINT_SPEED_SCALAR = 2.0f; | 107 | static const float AVATAR_HMD_SPRINT_SPEED_SCALAR = 2.0f; |
| 108 | 108 | ||
| 109 | enum AvatarReaction { | 109 | enum AvatarTriggerReaction { |
| 110 | AVATAR_REACTION_POSITIVE = 0, | 110 | AVATAR_REACTION_POSITIVE = 0, |
| 111 | AVATAR_REACTION_NEGATIVE, | 111 | AVATAR_REACTION_NEGATIVE, |
| 112 | NUM_AVATAR_TRIGGER_REACTIONS | ||
| 113 | }; | ||
| 114 | |||
| 115 | enum AvatarBeginEndReaction { | ||
| 112 | AVATAR_REACTION_RAISE_HAND, | 116 | AVATAR_REACTION_RAISE_HAND, |
| 113 | AVATAR_REACTION_APPLAUD, | 117 | AVATAR_REACTION_APPLAUD, |
| 114 | AVATAR_REACTION_POINT, | 118 | AVATAR_REACTION_POINT, |
| 115 | NUM_AVATAR_REACTIONS | 119 | NUM_AVATAR_BEGIN_END_REACTIONS |
| 116 | }; | 120 | }; |
| 117 | 121 | ||
| 118 | #endif // hifi_AvatarConstants_h | 122 | #endif // hifi_AvatarConstants_h |