mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-23 22:34:01 +02:00
Added overrideNetworkAnimation and restoreNetworkAnimation methods
This commit is contained in:
parent
e1c760b566
commit
afc76fec72
6 changed files with 275 additions and 144 deletions
|
@ -1,7 +1,43 @@
|
||||||
{
|
{
|
||||||
"version": "1.1",
|
"version": "1.1",
|
||||||
"root": {
|
"root": {
|
||||||
"id": "userAnimStateMachine",
|
"id": "networkAnimStateMachine",
|
||||||
|
"type": "stateMachine",
|
||||||
|
"data": {
|
||||||
|
"currentState": "transitAnimStateMachine",
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"id": "transitAnimStateMachine",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "userNetworkAnimA", "state": "userNetworkAnimA" },
|
||||||
|
{ "var": "userNetworkAnimB", "state": "userNetworkAnimB" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "userNetworkAnimA",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "transitAnimStateMachine", "state": "transitAnimStateMachine" },
|
||||||
|
{ "var": "userNetworkAnimB", "state": "userNetworkAnimB" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "userNetworkAnimB",
|
||||||
|
"interpTarget": 6,
|
||||||
|
"interpDuration": 6,
|
||||||
|
"transitions": [
|
||||||
|
{ "var": "transitAnimStateMachine", "state": "transitAnimStateMachine" },
|
||||||
|
{ "var": "userNetworkAnimA", "state": "userNetworkAnimA" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "transitAnimStateMachine",
|
||||||
"type": "stateMachine",
|
"type": "stateMachine",
|
||||||
"data": {
|
"data": {
|
||||||
"currentState": "idleAnim",
|
"currentState": "idleAnim",
|
||||||
|
@ -41,28 +77,10 @@
|
||||||
{ "var": "transitAnim", "state": "transitAnim" },
|
{ "var": "transitAnim", "state": "transitAnim" },
|
||||||
{ "var": "idleAnim", "state": "idleAnim" }
|
{ "var": "idleAnim", "state": "idleAnim" }
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "userAnimA",
|
|
||||||
"interpTarget": 6,
|
|
||||||
"interpDuration": 6,
|
|
||||||
"transitions": [
|
|
||||||
{ "var": "idleAnim", "state": "idleAnim" },
|
|
||||||
{ "var": "userAnimB", "state": "userAnimB" }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "userAnimB",
|
|
||||||
"interpTarget": 6,
|
|
||||||
"interpDuration": 6,
|
|
||||||
"transitions": [
|
|
||||||
{ "var": "idleAnim", "state": "idleAnim" },
|
|
||||||
{ "var": "userAnimA", "state": "userAnimA" }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"children": [
|
"children" : [
|
||||||
{
|
{
|
||||||
"id": "idleAnim",
|
"id": "idleAnim",
|
||||||
"type": "clip",
|
"type": "clip",
|
||||||
|
@ -110,9 +128,11 @@
|
||||||
"loopFlag": false
|
"loopFlag": false
|
||||||
},
|
},
|
||||||
"children": []
|
"children": []
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "userAnimA",
|
"id": "userNetworkAnimA",
|
||||||
"type": "clip",
|
"type": "clip",
|
||||||
"data": {
|
"data": {
|
||||||
"url": "qrc:///avatar/animations/idle.fbx",
|
"url": "qrc:///avatar/animations/idle.fbx",
|
||||||
|
@ -124,7 +144,7 @@
|
||||||
"children": []
|
"children": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "userAnimB",
|
"id": "userNetworkAnimB",
|
||||||
"type": "clip",
|
"type": "clip",
|
||||||
"data": {
|
"data": {
|
||||||
"url": "qrc:///avatar/animations/idle.fbx",
|
"url": "qrc:///avatar/animations/idle.fbx",
|
||||||
|
|
|
@ -128,19 +128,19 @@ void AvatarManager::handleTransitAnimations(AvatarTransit::Status status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case AvatarTransit::Status::STARTED:
|
case AvatarTransit::Status::STARTED:
|
||||||
qDebug() << "START_FRAME";
|
qDebug() << "START_FRAME";
|
||||||
_myAvatar->getSkeletonModel()->getRig().triggerNetworkAnimation("preTransitAnim");
|
_myAvatar->getSkeletonModel()->getRig().triggerNetworkRole("preTransitAnim");
|
||||||
break;
|
break;
|
||||||
case AvatarTransit::Status::START_TRANSIT:
|
case AvatarTransit::Status::START_TRANSIT:
|
||||||
qDebug() << "START_TRANSIT";
|
qDebug() << "START_TRANSIT";
|
||||||
_myAvatar->getSkeletonModel()->getRig().triggerNetworkAnimation("transitAnim");
|
_myAvatar->getSkeletonModel()->getRig().triggerNetworkRole("transitAnim");
|
||||||
break;
|
break;
|
||||||
case AvatarTransit::Status::END_TRANSIT:
|
case AvatarTransit::Status::END_TRANSIT:
|
||||||
qDebug() << "END_TRANSIT";
|
qDebug() << "END_TRANSIT";
|
||||||
_myAvatar->getSkeletonModel()->getRig().triggerNetworkAnimation("postTransitAnim");
|
_myAvatar->getSkeletonModel()->getRig().triggerNetworkRole("postTransitAnim");
|
||||||
break;
|
break;
|
||||||
case AvatarTransit::Status::ENDED:
|
case AvatarTransit::Status::ENDED:
|
||||||
qDebug() << "END_FRAME";
|
qDebug() << "END_FRAME";
|
||||||
_myAvatar->getSkeletonModel()->getRig().triggerNetworkAnimation("idleAnim");
|
_myAvatar->getSkeletonModel()->getRig().triggerNetworkRole("idleAnim");
|
||||||
break;
|
break;
|
||||||
case AvatarTransit::Status::PRE_TRANSIT:
|
case AvatarTransit::Status::PRE_TRANSIT:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1162,6 +1162,15 @@ void MyAvatar::overrideAnimation(const QString& url, float fps, bool loop, float
|
||||||
_skeletonModel->getRig().overrideAnimation(url, fps, loop, firstFrame, lastFrame);
|
_skeletonModel->getRig().overrideAnimation(url, fps, loop, firstFrame, lastFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::overrideNetworkAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "overrideNetworkAnimation", Q_ARG(const QString&, url), Q_ARG(float, fps),
|
||||||
|
Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_skeletonModel->getRig().overrideNetworkAnimation(url, fps, loop, firstFrame, lastFrame);
|
||||||
|
}
|
||||||
|
|
||||||
void MyAvatar::restoreAnimation() {
|
void MyAvatar::restoreAnimation() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "restoreAnimation");
|
QMetaObject::invokeMethod(this, "restoreAnimation");
|
||||||
|
@ -1170,6 +1179,14 @@ void MyAvatar::restoreAnimation() {
|
||||||
_skeletonModel->getRig().restoreAnimation();
|
_skeletonModel->getRig().restoreAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::restoreNetworkAnimation() {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "restoreNetworkAnimation");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_skeletonModel->getRig().restoreNetworkAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
QStringList MyAvatar::getAnimationRoles() {
|
QStringList MyAvatar::getAnimationRoles() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QStringList result;
|
QStringList result;
|
||||||
|
|
|
@ -393,6 +393,47 @@ public:
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void restoreAnimation();
|
Q_INVOKABLE void restoreAnimation();
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Similarly to {@link MyAvatar.overrideAnimation}, this function will override the default avatar animations,
|
||||||
|
* but only affecting the data the gets sent to other clients over the network. In the client, the avatar will move according
|
||||||
|
* to the default animations but other clients will render your avatar movements according to the new animation.
|
||||||
|
* To continue sending the default animations, use {@link MyAvatar.restoreNetworkAnimation}.<br />
|
||||||
|
* <p>Note: When using pre-built animation data, it's critical that the joint orientation of the source animation and target
|
||||||
|
* rig are equivalent, since the animation data applies absolute values onto the joints. If the orientations are different,
|
||||||
|
* the avatar will move in unpredictable ways. For more information about avatar joint orientation standards, see
|
||||||
|
* <a href="https://docs.highfidelity.com/create-and-explore/avatars/avatar-standards">Avatar Standards</a>.</p>
|
||||||
|
* @function MyAvatar.overrideNetworkAnimation
|
||||||
|
* @param url {string} The URL to the animation file. Animation files need to be .FBX format, but only need to contain the
|
||||||
|
* avatar skeleton and animation data.
|
||||||
|
* @param fps {number} The frames per second (FPS) rate for the animation playback. 30 FPS is normal speed.
|
||||||
|
* @param loop {boolean} Set to true if the animation should loop.
|
||||||
|
* @param firstFrame {number} The frame the animation should start at.
|
||||||
|
* @param lastFrame {number} The frame the animation should end at.
|
||||||
|
* @example <caption> Make your avatar clap only on other clients for three seconds. </caption>
|
||||||
|
* // Clap your hands for 3 seconds then restore animation back to the avatar.
|
||||||
|
* var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx";
|
||||||
|
* MyAvatar.overrideNetworkAnimation(ANIM_URL, 30, true, 0, 53);
|
||||||
|
* Script.setTimeout(function () {
|
||||||
|
* MyAvatar.restoreNetworkAnimation();
|
||||||
|
* }, 3000);
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE void overrideNetworkAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Similarly to {@link MyAvatar.restoreAnimation} restoreNetworkAnimation() will restore any network animation
|
||||||
|
* that was previously overriten using the function {@link MyAvatar.overrideNetworkAnimation}
|
||||||
|
* If you aren't currently playing an override network animation, this function will have no effect.
|
||||||
|
* @function MyAvatar.restoreNetworkAnimation
|
||||||
|
* @example <caption> Make your avatar clap only on other clients for three seconds. </caption>
|
||||||
|
* // Clap your hands for 3 seconds then restore animation back to the avatar.
|
||||||
|
* var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx";
|
||||||
|
* MyAvatar.overrideNetworkAnimation(ANIM_URL, 30, true, 0, 53);
|
||||||
|
* Script.setTimeout(function () {
|
||||||
|
* MyAvatar.restoreNetworkAnimation();
|
||||||
|
* }, 3000);
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE void restoreNetworkAnimation();
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Each avatar has an avatar-animation.json file that defines which animations are used and how they are blended together with procedural data
|
* Each avatar has an avatar-animation.json file that defines which animations are used and how they are blended together with procedural data
|
||||||
* (such as look at vectors, hand sensors etc.). Each animation specified in the avatar-animation.json file is known as an animation role.
|
* (such as look at vectors, hand sensors etc.). Each animation specified in the avatar-animation.json file is known as an animation role.
|
||||||
|
|
|
@ -134,30 +134,6 @@ void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firs
|
||||||
_animVars.set("userAnimB", clipNodeEnum == UserAnimState::B);
|
_animVars.set("userAnimB", clipNodeEnum == UserAnimState::B);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::triggerNetworkAnimation(const QString& animName) {
|
|
||||||
_networkVars.set("idleAnim", false);
|
|
||||||
_networkVars.set("preTransitAnim", false);
|
|
||||||
_networkVars.set("transitAnim", false);
|
|
||||||
_networkVars.set("postTransitAnim", false);
|
|
||||||
_sendNetworkNode = true;
|
|
||||||
|
|
||||||
if (animName == "idleAnim") {
|
|
||||||
_networkVars.set("idleAnim", true);
|
|
||||||
_networkAnimState.clipNodeEnum = NetworkAnimState::Idle;
|
|
||||||
_sendNetworkNode = false;
|
|
||||||
} else if (animName == "preTransitAnim") {
|
|
||||||
_networkVars.set("preTransitAnim", true);
|
|
||||||
_networkAnimState.clipNodeEnum = NetworkAnimState::PreTransit;
|
|
||||||
} else if (animName == "transitAnim") {
|
|
||||||
_networkVars.set("transitAnim", true);
|
|
||||||
_networkAnimState.clipNodeEnum = NetworkAnimState::Transit;
|
|
||||||
} else if (animName == "postTransitAnim") {
|
|
||||||
_networkVars.set("postTransitAnim", true);
|
|
||||||
_networkAnimState.clipNodeEnum = NetworkAnimState::PostTransit;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rig::restoreAnimation() {
|
void Rig::restoreAnimation() {
|
||||||
if (_userAnimState.clipNodeEnum != UserAnimState::None) {
|
if (_userAnimState.clipNodeEnum != UserAnimState::None) {
|
||||||
_userAnimState.clipNodeEnum = UserAnimState::None;
|
_userAnimState.clipNodeEnum = UserAnimState::None;
|
||||||
|
@ -169,13 +145,87 @@ void Rig::restoreAnimation() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::restoreNetworkAnimation() {
|
void Rig::overrideNetworkAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
||||||
if (_networkAnimState.clipNodeEnum != NetworkAnimState::Idle) {
|
|
||||||
_networkAnimState.clipNodeEnum = NetworkAnimState::Idle;
|
NetworkAnimState::ClipNodeEnum clipNodeEnum;
|
||||||
_networkVars.set("idleAnim", true);
|
if (_networkAnimState.clipNodeEnum == NetworkAnimState::None || _networkAnimState.clipNodeEnum == NetworkAnimState::B) {
|
||||||
|
clipNodeEnum = NetworkAnimState::A;
|
||||||
|
} else if (_networkAnimState.clipNodeEnum == NetworkAnimState::A) {
|
||||||
|
clipNodeEnum = NetworkAnimState::B;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_networkNode) {
|
||||||
|
// find an unused AnimClip clipNode
|
||||||
|
std::shared_ptr<AnimClip> clip;
|
||||||
|
if (clipNodeEnum == NetworkAnimState::A) {
|
||||||
|
clip = std::dynamic_pointer_cast<AnimClip>(_networkNode->findByName("userNetworkAnimA"));
|
||||||
|
} else {
|
||||||
|
clip = std::dynamic_pointer_cast<AnimClip>(_networkNode->findByName("userNetworkAnimB"));
|
||||||
|
}
|
||||||
|
if (clip) {
|
||||||
|
// set parameters
|
||||||
|
clip->setLoopFlag(loop);
|
||||||
|
clip->setStartFrame(firstFrame);
|
||||||
|
clip->setEndFrame(lastFrame);
|
||||||
|
const float REFERENCE_FRAMES_PER_SECOND = 30.0f;
|
||||||
|
float timeScale = fps / REFERENCE_FRAMES_PER_SECOND;
|
||||||
|
clip->setTimeScale(timeScale);
|
||||||
|
clip->loadURL(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// store current user anim state.
|
||||||
|
_networkAnimState = { clipNodeEnum, url, fps, loop, firstFrame, lastFrame };
|
||||||
|
|
||||||
|
// notify the userAnimStateMachine the desired state.
|
||||||
|
_networkVars.set("transitAnimStateMachine", false);
|
||||||
|
_networkVars.set("userNetworkAnimA", clipNodeEnum == NetworkAnimState::A);
|
||||||
|
_networkVars.set("userNetworkAnimB", clipNodeEnum == NetworkAnimState::B);
|
||||||
|
if (!_computeNetworkAnimation) {
|
||||||
|
_networkAnimState.blendTime = 0.0f;
|
||||||
|
_computeNetworkAnimation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rig::triggerNetworkRole(const QString& role) {
|
||||||
|
_networkVars.set("transitAnimStateMachine", false);
|
||||||
|
_networkVars.set("idleAnim", false);
|
||||||
|
_networkVars.set("userNetworkAnimA", false);
|
||||||
|
_networkVars.set("userNetworkAnimB", false);
|
||||||
|
_networkVars.set("preTransitAnim", false);
|
||||||
_networkVars.set("preTransitAnim", false);
|
_networkVars.set("preTransitAnim", false);
|
||||||
_networkVars.set("transitAnim", false);
|
_networkVars.set("transitAnim", false);
|
||||||
_networkVars.set("postTransitAnim", false);
|
_networkVars.set("postTransitAnim", false);
|
||||||
|
_computeNetworkAnimation = true;
|
||||||
|
if (role == "idleAnim") {
|
||||||
|
_networkVars.set("idleAnim", true);
|
||||||
|
_networkAnimState.clipNodeEnum = NetworkAnimState::None;
|
||||||
|
_computeNetworkAnimation = false;
|
||||||
|
_networkAnimState.blendTime = 0.0f;
|
||||||
|
} else if (role == "preTransitAnim") {
|
||||||
|
_networkVars.set("preTransitAnim", true);
|
||||||
|
_networkAnimState.clipNodeEnum = NetworkAnimState::PreTransit;
|
||||||
|
_networkAnimState.blendTime = 0.0f;
|
||||||
|
} else if (role == "transitAnim") {
|
||||||
|
_networkVars.set("transitAnim", true);
|
||||||
|
_networkAnimState.clipNodeEnum = NetworkAnimState::Transit;
|
||||||
|
} else if (role == "postTransitAnim") {
|
||||||
|
_networkVars.set("postTransitAnim", true);
|
||||||
|
_networkAnimState.clipNodeEnum = NetworkAnimState::PostTransit;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rig::restoreNetworkAnimation() {
|
||||||
|
if (_networkAnimState.clipNodeEnum != NetworkAnimState::None) {
|
||||||
|
if (_computeNetworkAnimation) {
|
||||||
|
_networkAnimState.blendTime = 0.0f;
|
||||||
|
_computeNetworkAnimation = false;
|
||||||
|
}
|
||||||
|
_networkAnimState.clipNodeEnum = NetworkAnimState::None;
|
||||||
|
_networkVars.set("transitAnimStateMachine", true);
|
||||||
|
_networkVars.set("userNetworkAnimA", false);
|
||||||
|
_networkVars.set("userNetworkAnimB", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1123,23 +1173,20 @@ void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, cons
|
||||||
AnimVariantMap networkTriggersOut;
|
AnimVariantMap networkTriggersOut;
|
||||||
_internalPoseSet._relativePoses = _animNode->evaluate(_animVars, context, deltaTime, triggersOut);
|
_internalPoseSet._relativePoses = _animNode->evaluate(_animVars, context, deltaTime, triggersOut);
|
||||||
if (_networkNode) {
|
if (_networkNode) {
|
||||||
_networkPoseSet._relativePoses = _networkNode->evaluate(_networkVars, context, deltaTime, networkTriggersOut);
|
|
||||||
float alpha = 1.0f;
|
float alpha = 1.0f;
|
||||||
std::shared_ptr<AnimClip> clip;
|
std::shared_ptr<AnimClip> clip;
|
||||||
if (_networkAnimState.clipNodeEnum == NetworkAnimState::PreTransit) {
|
|
||||||
clip = std::dynamic_pointer_cast<AnimClip>(_networkNode->findByName("preTransitAnim"));
|
const float TOTAL_BLEND_TIME = 0.2f;
|
||||||
if (clip) {
|
_sendNetworkNode = _computeNetworkAnimation || _networkAnimState.blendTime < TOTAL_BLEND_TIME;
|
||||||
alpha = (clip->getFrame() - clip->getStartFrame()) / 6.0f;
|
|
||||||
}
|
|
||||||
} else if (_networkAnimState.clipNodeEnum == NetworkAnimState::PostTransit) {
|
|
||||||
clip = std::dynamic_pointer_cast<AnimClip>(_networkNode->findByName("postTransitAnim"));
|
|
||||||
if (clip) {
|
|
||||||
alpha = (clip->getEndFrame() - clip->getFrame()) / 6.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_sendNetworkNode) {
|
if (_sendNetworkNode) {
|
||||||
|
_networkPoseSet._relativePoses = _networkNode->evaluate(_networkVars, context, deltaTime, networkTriggersOut);
|
||||||
|
_networkAnimState.blendTime += deltaTime;
|
||||||
|
alpha = _computeNetworkAnimation ? (_networkAnimState.blendTime / TOTAL_BLEND_TIME) : (1.0f - (_networkAnimState.blendTime / TOTAL_BLEND_TIME));
|
||||||
|
alpha = alpha > 1.0f ? 1.0f : alpha;
|
||||||
|
alpha = alpha < 0.0f ? 0.0f : alpha;
|
||||||
for (size_t i = 0; i < _networkPoseSet._relativePoses.size(); i++) {
|
for (size_t i = 0; i < _networkPoseSet._relativePoses.size(); i++) {
|
||||||
_networkPoseSet._relativePoses[i].blend(_internalPoseSet._relativePoses[i], (alpha > 1.0f ? 1.0f : alpha));
|
_networkPoseSet._relativePoses[i].blend(_internalPoseSet._relativePoses[i], alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1809,16 +1856,16 @@ void Rig::initAnimGraph(const QUrl& url) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_networkNode->setSkeleton(sharedSkeletonPtr);
|
_networkNode->setSkeleton(sharedSkeletonPtr);
|
||||||
if (_networkAnimState.clipNodeEnum != NetworkAnimState::Idle) {
|
if (_networkAnimState.clipNodeEnum != NetworkAnimState::None) {
|
||||||
// restore the user animation we had before reset.
|
// restore the user animation we had before reset.
|
||||||
NetworkAnimState origState = _networkAnimState;
|
NetworkAnimState origState = _networkAnimState;
|
||||||
_networkAnimState = { NetworkAnimState::Idle, "", 30.0f, false, 0.0f, 0.0f };
|
_networkAnimState = { NetworkAnimState::None, "", 30.0f, false, 0.0f, 0.0f };
|
||||||
if (_networkAnimState.clipNodeEnum == NetworkAnimState::PreTransit) {
|
if (_networkAnimState.clipNodeEnum == NetworkAnimState::PreTransit) {
|
||||||
triggerNetworkAnimation("preTransitAnim");
|
triggerNetworkRole("preTransitAnim");
|
||||||
} else if (_networkAnimState.clipNodeEnum == NetworkAnimState::Transit) {
|
} else if (_networkAnimState.clipNodeEnum == NetworkAnimState::Transit) {
|
||||||
triggerNetworkAnimation("transitAnim");
|
triggerNetworkRole("transitAnim");
|
||||||
} else if (_networkAnimState.clipNodeEnum == NetworkAnimState::PostTransit) {
|
} else if (_networkAnimState.clipNodeEnum == NetworkAnimState::PostTransit) {
|
||||||
triggerNetworkAnimation("postTransitAnim");
|
triggerNetworkRole("postTransitAnim");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,8 +113,10 @@ public:
|
||||||
void destroyAnimGraph();
|
void destroyAnimGraph();
|
||||||
|
|
||||||
void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
||||||
void triggerNetworkAnimation(const QString& animName);
|
|
||||||
void restoreAnimation();
|
void restoreAnimation();
|
||||||
|
|
||||||
|
void overrideNetworkAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
||||||
|
void triggerNetworkRole(const QString& role);
|
||||||
void restoreNetworkAnimation();
|
void restoreNetworkAnimation();
|
||||||
|
|
||||||
QStringList getAnimationRoles() const;
|
QStringList getAnimationRoles() const;
|
||||||
|
@ -325,12 +327,14 @@ protected:
|
||||||
|
|
||||||
struct NetworkAnimState {
|
struct NetworkAnimState {
|
||||||
enum ClipNodeEnum {
|
enum ClipNodeEnum {
|
||||||
Idle = 0,
|
None = 0,
|
||||||
PreTransit,
|
PreTransit,
|
||||||
Transit,
|
Transit,
|
||||||
PostTransit
|
PostTransit,
|
||||||
|
A,
|
||||||
|
B
|
||||||
};
|
};
|
||||||
NetworkAnimState() : clipNodeEnum(NetworkAnimState::Idle) {}
|
NetworkAnimState() : clipNodeEnum(NetworkAnimState::None) {}
|
||||||
NetworkAnimState(ClipNodeEnum clipNodeEnumIn, const QString& urlIn, float fpsIn, bool loopIn, float firstFrameIn, float lastFrameIn) :
|
NetworkAnimState(ClipNodeEnum clipNodeEnumIn, const QString& urlIn, float fpsIn, bool loopIn, float firstFrameIn, float lastFrameIn) :
|
||||||
clipNodeEnum(clipNodeEnumIn), url(urlIn), fps(fpsIn), loop(loopIn), firstFrame(firstFrameIn), lastFrame(lastFrameIn) {}
|
clipNodeEnum(clipNodeEnumIn), url(urlIn), fps(fpsIn), loop(loopIn), firstFrame(firstFrameIn), lastFrame(lastFrameIn) {}
|
||||||
|
|
||||||
|
@ -340,6 +344,7 @@ protected:
|
||||||
bool loop;
|
bool loop;
|
||||||
float firstFrame;
|
float firstFrame;
|
||||||
float lastFrame;
|
float lastFrame;
|
||||||
|
float blendTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UserAnimState {
|
struct UserAnimState {
|
||||||
|
@ -409,6 +414,7 @@ protected:
|
||||||
|
|
||||||
int _rigId;
|
int _rigId;
|
||||||
bool _headEnabled { false };
|
bool _headEnabled { false };
|
||||||
|
bool _computeNetworkAnimation { false };
|
||||||
bool _sendNetworkNode { false };
|
bool _sendNetworkNode { false };
|
||||||
|
|
||||||
AnimContext _lastContext;
|
AnimContext _lastContext;
|
||||||
|
|
Loading…
Reference in a new issue