mirror of
https://github.com/lubosz/overte.git
synced 2025-04-08 20:22:34 +02:00
Disable head ik while reacting
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().
This commit is contained in:
parent
7486e906eb
commit
2f949a4d4d
7 changed files with 96 additions and 58 deletions
|
@ -125,16 +125,25 @@ QString userRecenterModelToString(MyAvatar::SitStandModelType model) {
|
|||
}
|
||||
}
|
||||
|
||||
static const QStringList REACTION_NAMES = {
|
||||
static const QStringList TRIGGER_REACTION_NAMES = {
|
||||
QString("positive"),
|
||||
QString("negative"),
|
||||
QString("negative")
|
||||
};
|
||||
|
||||
static const QStringList BEGIN_END_REACTION_NAMES = {
|
||||
QString("raiseHand"),
|
||||
QString("applaud"),
|
||||
QString("point")
|
||||
};
|
||||
|
||||
static int reactionNameToIndex(const QString& reactionName) {
|
||||
return REACTION_NAMES.indexOf(reactionName);
|
||||
static int triggerReactionNameToIndex(const QString& reactionName) {
|
||||
assert(NUM_AVATAR_TRIGGER_REACTIONS == TRIGGER_REACTION_NAMES.size());
|
||||
return TRIGGER_REACTION_NAMES.indexOf(reactionName);
|
||||
}
|
||||
|
||||
static int beginEndReactionNameToIndex(const QString& reactionName) {
|
||||
assert(NUM_AVATAR_BEGIN_END_REACTIONS == TRIGGER_REACTION_NAMES.size());
|
||||
return BEGIN_END_REACTION_NAMES.indexOf(reactionName);
|
||||
}
|
||||
|
||||
MyAvatar::MyAvatar(QThread* thread) :
|
||||
|
@ -5824,13 +5833,17 @@ void MyAvatar::setModelScale(float scale) {
|
|||
}
|
||||
}
|
||||
|
||||
QStringList MyAvatar::getReactions() const {
|
||||
return REACTION_NAMES;
|
||||
QStringList MyAvatar::getBeginEndReactions() const {
|
||||
return BEGIN_END_REACTION_NAMES;
|
||||
}
|
||||
|
||||
QStringList MyAvatar::getTriggerReactions() const {
|
||||
return TRIGGER_REACTION_NAMES;
|
||||
}
|
||||
|
||||
bool MyAvatar::triggerReaction(QString reactionName) {
|
||||
int reactionIndex = reactionNameToIndex(reactionName);
|
||||
if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_REACTIONS) {
|
||||
int reactionIndex = triggerReactionNameToIndex(reactionName);
|
||||
if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_TRIGGER_REACTIONS) {
|
||||
std::lock_guard<std::mutex> guard(_reactionLock);
|
||||
_reactionTriggers[reactionIndex] = true;
|
||||
return true;
|
||||
|
@ -5839,8 +5852,8 @@ bool MyAvatar::triggerReaction(QString reactionName) {
|
|||
}
|
||||
|
||||
bool MyAvatar::beginReaction(QString reactionName) {
|
||||
int reactionIndex = reactionNameToIndex(reactionName);
|
||||
if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_REACTIONS) {
|
||||
int reactionIndex = beginEndReactionNameToIndex(reactionName);
|
||||
if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_BEGIN_END_REACTIONS) {
|
||||
std::lock_guard<std::mutex> guard(_reactionLock);
|
||||
_reactionEnabledRefCounts[reactionIndex]++;
|
||||
return true;
|
||||
|
@ -5849,8 +5862,8 @@ bool MyAvatar::beginReaction(QString reactionName) {
|
|||
}
|
||||
|
||||
bool MyAvatar::endReaction(QString reactionName) {
|
||||
int reactionIndex = reactionNameToIndex(reactionName);
|
||||
if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_REACTIONS) {
|
||||
int reactionIndex = beginEndReactionNameToIndex(reactionName);
|
||||
if (reactionIndex >= 0 && reactionIndex < (int)NUM_AVATAR_BEGIN_END_REACTIONS) {
|
||||
std::lock_guard<std::mutex> guard(_reactionLock);
|
||||
_reactionEnabledRefCounts[reactionIndex]--;
|
||||
return true;
|
||||
|
@ -5860,12 +5873,17 @@ bool MyAvatar::endReaction(QString reactionName) {
|
|||
|
||||
void MyAvatar::updateRigControllerParameters(Rig::ControllerParameters& params) {
|
||||
std::lock_guard<std::mutex> guard(_reactionLock);
|
||||
for (int i = 0; i < NUM_AVATAR_REACTIONS; i++) {
|
||||
|
||||
for (int i = 0; i < TRIGGER_REACTION_NAMES.size(); i++) {
|
||||
params.reactionTriggers[i] = _reactionTriggers[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < BEGIN_END_REACTION_NAMES.size(); i++) {
|
||||
// copy current state into params.
|
||||
params.reactionEnabledFlags[i] = _reactionEnabledRefCounts[i] > 0;
|
||||
params.reactionTriggers[i] = _reactionTriggers[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i < TRIGGER_REACTION_NAMES.size(); i++) {
|
||||
// clear reaction triggers here as well
|
||||
_reactionTriggers[i] = false;
|
||||
}
|
||||
|
|
|
@ -2213,13 +2213,23 @@ public slots:
|
|||
virtual void setModelScale(float scale) override;
|
||||
|
||||
/**jsdoc
|
||||
* MyAvatar.getReactions
|
||||
* MyAvatar.getTriggerReactions
|
||||
* Returns a list of reactions names that can be triggered using MyAvatar.triggerReaction().
|
||||
* @returns {string[]} Array of reaction names.
|
||||
*/
|
||||
QStringList getReactions() const;
|
||||
QStringList getTriggerReactions() const;
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* MyAvatar.getBeginReactions
|
||||
* Returns a list of reactions names that can be enabled using MyAvatar.beginReaction() and MyAvatar.endReaction().
|
||||
* @returns {string[]} Array of reaction names.
|
||||
*/
|
||||
QStringList getBeginEndReactions() const;
|
||||
|
||||
/**jsdoc
|
||||
* MyAvatar.triggerReaction
|
||||
* 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.
|
||||
* @param {string} reactionName - reaction name
|
||||
* @returns {bool} false if the given reaction is not supported.
|
||||
*/
|
||||
|
@ -2227,6 +2237,9 @@ public slots:
|
|||
|
||||
/**jsdoc
|
||||
* MyAvatar.beginReaction
|
||||
* 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.
|
||||
* Only reaction names returned from MyAvatar.getBeginEndReactions() are available.
|
||||
* NOTE: the caller is responsible for calling the corresponding MyAvatar.endReaction(), otherwise the avatar might become stuck in the reaction forever.
|
||||
* @param {string} reactionName - reaction name
|
||||
* @returns {bool} false if the given reaction is not supported.
|
||||
*/
|
||||
|
@ -2234,6 +2247,7 @@ public slots:
|
|||
|
||||
/**jsdoc
|
||||
* MyAvatar.endReaction
|
||||
* Used to stop a given reaction that was started via MyAvatar.beginReaction().
|
||||
* @param {string} reactionName - reaction name
|
||||
* @returns {bool} false if the given reaction is not supported.
|
||||
*/
|
||||
|
@ -2872,8 +2886,9 @@ private:
|
|||
QScriptEngine* _scriptEngine { nullptr };
|
||||
bool _needToSaveAvatarEntitySettings { false };
|
||||
|
||||
int _reactionEnabledRefCounts[NUM_AVATAR_REACTIONS] { 0, 0, 0, 0, 0 };
|
||||
bool _reactionTriggers[NUM_AVATAR_REACTIONS] { false, false, false, false, false };
|
||||
bool _reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS] { false, false };
|
||||
int _reactionEnabledRefCounts[NUM_AVATAR_BEGIN_END_REACTIONS] { 0, 0, 0 };
|
||||
|
||||
mutable std::mutex _reactionLock;
|
||||
};
|
||||
|
||||
|
|
|
@ -95,6 +95,15 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co
|
|||
return _poses;
|
||||
}
|
||||
|
||||
const QString& AnimStateMachine::getCurrentStateID() const {
|
||||
if (_currentState) {
|
||||
return _currentState->getID();
|
||||
} else {
|
||||
static QString emptyString;
|
||||
return emptyString;
|
||||
}
|
||||
}
|
||||
|
||||
void AnimStateMachine::setCurrentState(State::Pointer state) {
|
||||
_previousState = _currentState ? _currentState : state;
|
||||
_currentState = state;
|
||||
|
|
|
@ -116,6 +116,7 @@ public:
|
|||
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override;
|
||||
|
||||
void setCurrentStateVar(QString& currentStateVar) { _currentStateVar = currentStateVar; }
|
||||
const QString& getCurrentStateID() const;
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "AnimInverseKinematics.h"
|
||||
#include "AnimOverlay.h"
|
||||
#include "AnimSkeleton.h"
|
||||
#include "AnimStateMachine.h"
|
||||
#include "AnimUtil.h"
|
||||
#include "AvatarConstants.h"
|
||||
#include "IKTarget.h"
|
||||
|
@ -1906,28 +1907,7 @@ void Rig::updateFeet(bool leftFootEnabled, bool rightFootEnabled, bool headEnabl
|
|||
|
||||
void Rig::updateReactions(const ControllerParameters& params) {
|
||||
|
||||
// enable/disable animVars
|
||||
bool enabled = params.reactionEnabledFlags[AVATAR_REACTION_POSITIVE];
|
||||
_animVars.set("reactionPositiveEnabled", enabled);
|
||||
_animVars.set("reactionPositiveDisabled", !enabled);
|
||||
|
||||
enabled = params.reactionEnabledFlags[AVATAR_REACTION_NEGATIVE];
|
||||
_animVars.set("reactionNegativeEnabled", enabled);
|
||||
_animVars.set("reactionNegativeDisabled", !enabled);
|
||||
|
||||
enabled = params.reactionEnabledFlags[AVATAR_REACTION_RAISE_HAND];
|
||||
_animVars.set("reactionRaiseHandEnabled", enabled);
|
||||
_animVars.set("reactionRaiseHandDisabled", !enabled);
|
||||
|
||||
enabled = params.reactionEnabledFlags[AVATAR_REACTION_APPLAUD];
|
||||
_animVars.set("reactionApplaudEnabled", enabled);
|
||||
_animVars.set("reactionApplaudDisabled", !enabled);
|
||||
|
||||
enabled = params.reactionEnabledFlags[AVATAR_REACTION_POINT];
|
||||
_animVars.set("reactionPointEnabled", enabled);
|
||||
_animVars.set("reactionPointDisabled", !enabled);
|
||||
|
||||
// trigger animVars
|
||||
// trigger reactions
|
||||
if (params.reactionTriggers[AVATAR_REACTION_POSITIVE]) {
|
||||
_animVars.set("reactionPositiveTrigger", true);
|
||||
} else {
|
||||
|
@ -1940,22 +1920,33 @@ void Rig::updateReactions(const ControllerParameters& params) {
|
|||
_animVars.set("reactionNegativeTrigger", false);
|
||||
}
|
||||
|
||||
if (params.reactionTriggers[AVATAR_REACTION_RAISE_HAND]) {
|
||||
_animVars.set("reactionRaiseHandTrigger", true);
|
||||
} else {
|
||||
_animVars.set("reactionRaiseHandTrigger", false);
|
||||
}
|
||||
// begin end reactions
|
||||
bool enabled = params.reactionEnabledFlags[AVATAR_REACTION_RAISE_HAND];
|
||||
_animVars.set("reactionRaiseHandEnabled", enabled);
|
||||
_animVars.set("reactionRaiseHandDisabled", !enabled);
|
||||
|
||||
if (params.reactionTriggers[AVATAR_REACTION_APPLAUD]) {
|
||||
_animVars.set("reactionApplaudTrigger", true);
|
||||
} else {
|
||||
_animVars.set("reactionApplaudTrigger", false);
|
||||
}
|
||||
enabled = params.reactionEnabledFlags[AVATAR_REACTION_APPLAUD];
|
||||
_animVars.set("reactionApplaudEnabled", enabled);
|
||||
_animVars.set("reactionApplaudDisabled", !enabled);
|
||||
|
||||
if (params.reactionTriggers[AVATAR_REACTION_POINT]) {
|
||||
_animVars.set("reactionPointTrigger", true);
|
||||
} else {
|
||||
_animVars.set("reactionPointTrigger", false);
|
||||
enabled = params.reactionEnabledFlags[AVATAR_REACTION_POINT];
|
||||
_animVars.set("reactionPointEnabled", enabled);
|
||||
_animVars.set("reactionPointDisabled", !enabled);
|
||||
|
||||
// determine if we should ramp off IK
|
||||
if (_enableInverseKinematics) {
|
||||
bool reactionPlaying = false;
|
||||
std::shared_ptr<AnimStateMachine> mainStateMachine = std::dynamic_pointer_cast<AnimStateMachine>(_animNode->findByName("mainStateMachine"));
|
||||
std::shared_ptr<AnimStateMachine> idleStateMachine = std::dynamic_pointer_cast<AnimStateMachine>(_animNode->findByName("idle"));
|
||||
if (mainStateMachine && mainStateMachine->getCurrentStateID() == "idle" && idleStateMachine) {
|
||||
reactionPlaying = idleStateMachine->getCurrentStateID().startsWith("reaction");
|
||||
}
|
||||
|
||||
bool hipsEnabled = params.primaryControllerFlags[PrimaryControllerType_Hips] & (uint8_t)ControllerFlags::Enabled;
|
||||
if (reactionPlaying && !hipsEnabled) {
|
||||
// disable head IK while reaction is playing, but only in "desktop" mode.
|
||||
_animVars.set("headType", (int)IKTarget::Type::Unknown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,8 +88,8 @@ public:
|
|||
AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space
|
||||
uint8_t secondaryControllerFlags[NumSecondaryControllerTypes];
|
||||
bool isTalking;
|
||||
bool reactionEnabledFlags[NUM_AVATAR_REACTIONS];
|
||||
bool reactionTriggers[NUM_AVATAR_REACTIONS];
|
||||
bool reactionEnabledFlags[NUM_AVATAR_BEGIN_END_REACTIONS];
|
||||
bool reactionTriggers[NUM_AVATAR_TRIGGER_REACTIONS];
|
||||
HFMJointShapeInfo hipsShapeInfo;
|
||||
HFMJointShapeInfo spineShapeInfo;
|
||||
HFMJointShapeInfo spine1ShapeInfo;
|
||||
|
|
|
@ -106,13 +106,17 @@ static const float AVATAR_WALK_SPEED_SCALAR = 1.0f;
|
|||
static const float AVATAR_DESKTOP_SPRINT_SPEED_SCALAR = 3.0f;
|
||||
static const float AVATAR_HMD_SPRINT_SPEED_SCALAR = 2.0f;
|
||||
|
||||
enum AvatarReaction {
|
||||
enum AvatarTriggerReaction {
|
||||
AVATAR_REACTION_POSITIVE = 0,
|
||||
AVATAR_REACTION_NEGATIVE,
|
||||
NUM_AVATAR_TRIGGER_REACTIONS
|
||||
};
|
||||
|
||||
enum AvatarBeginEndReaction {
|
||||
AVATAR_REACTION_RAISE_HAND,
|
||||
AVATAR_REACTION_APPLAUD,
|
||||
AVATAR_REACTION_POINT,
|
||||
NUM_AVATAR_REACTIONS
|
||||
NUM_AVATAR_BEGIN_END_REACTIONS
|
||||
};
|
||||
|
||||
#endif // hifi_AvatarConstants_h
|
||||
|
|
Loading…
Reference in a new issue