mirror of
https://github.com/lubosz/overte.git
synced 2025-08-05 19:11:35 +02:00
New MyAvatar animation JS interface
JavaScript changes: * removed MyAvatar.playAnimation * removed MyAvatar.stopAnimation * removed MyAVatar.getGetAnimationDetails * removed MyAvatar.startAnimationByRole * removed MyAvatar.stopAnimationByRole * removed MyAVatar.getGetAnimationDetailsByRole * removed MyAVatar.clearJointPriorities * added MyAvatar.overrideAnimation(url, fps, loop, firstFrame, lastFrame) * added MyAvatar.restoreAnimation() * added MyAvatar.getAnimationRoles() * added MyAvatar.overrideRoleAnimation(role, url, fps, loop, firstFrame, lastFrame) * added MyAvatar.restoreRoleAnimation(role) * added MyAvatar.prefetchAnimation(url) * update kneel.js with new api. * added theBird.js to test role override api. C++ changes: * Added getParent() and replaceChild() to AnimNode * Added findByName() and traverse() to AnimNode * Changed AnimStateMachine to hold nodes by childIndex instead of smart pointer. This allows script to replace nodes dynamically via overrideRoleAnimation
This commit is contained in:
parent
eacc2cae0c
commit
936c55a94e
11 changed files with 128 additions and 64 deletions
|
@ -57,7 +57,7 @@ function kneelDown() {
|
||||||
var startFrame = 0;
|
var startFrame = 0;
|
||||||
var endFrame = 82;
|
var endFrame = 82;
|
||||||
|
|
||||||
MyAvatar.startAnimation(KNEEL_ANIM_URL, playbackRate, loopFlag, startFrame, endFrame);
|
MyAvatar.overrideAnimation(KNEEL_ANIM_URL, playbackRate, loopFlag, startFrame, endFrame);
|
||||||
|
|
||||||
Overlays.editOverlay(kneelDownButton, { visible: false });
|
Overlays.editOverlay(kneelDownButton, { visible: false });
|
||||||
Overlays.editOverlay(standUpButton, { visible: true });
|
Overlays.editOverlay(standUpButton, { visible: true });
|
||||||
|
@ -66,7 +66,7 @@ function kneelDown() {
|
||||||
function standUp() {
|
function standUp() {
|
||||||
kneeling = false;
|
kneeling = false;
|
||||||
|
|
||||||
MyAvatar.stopAnimation();
|
MyAvatar.restoreAnimation();
|
||||||
|
|
||||||
Overlays.editOverlay(standUpButton, { visible: false });
|
Overlays.editOverlay(standUpButton, { visible: false });
|
||||||
Overlays.editOverlay(kneelDownButton, { visible: true });
|
Overlays.editOverlay(kneelDownButton, { visible: true });
|
||||||
|
|
32
examples/theBird.js
Normal file
32
examples/theBird.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// theBird.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 THE_BIRD_RIGHT_URL = "https://hifi-public.s3.amazonaws.com/ozan/anim/the_bird/the_bird_right.fbx";
|
||||||
|
|
||||||
|
var roles = MyAvatar.getAnimationRoles();
|
||||||
|
var i, l = roles.length
|
||||||
|
print("getAnimationRoles()");
|
||||||
|
for (i = 0; i < l; i++) {
|
||||||
|
print(roles[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// replace point with the bird!
|
||||||
|
MyAvatar.overrideRoleAnimation("rightHandPointIntro", THE_BIRD_RIGHT_URL, 30, false, 0, 12);
|
||||||
|
MyAvatar.overrideRoleAnimation("rightHandPointHold", THE_BIRD_RIGHT_URL, 30, false, 12, 12);
|
||||||
|
MyAvatar.overrideRoleAnimation("rightHandPointOutro", THE_BIRD_RIGHT_URL, 30, false, 19, 30);
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(function() {
|
||||||
|
MyAvatar.restoreRoleAnimation("rightHandPointIntro");
|
||||||
|
MyAvatar.restoreRoleAnimation("rightHandPointHold");
|
||||||
|
MyAvatar.restoreRoleAnimation("rightHandPointOutro");
|
||||||
|
});
|
|
@ -657,21 +657,21 @@ void MyAvatar::loadLastRecording() {
|
||||||
_player->loadRecording(_recorder->getRecording());
|
_player->loadRecording(_recorder->getRecording());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::startAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
void MyAvatar::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "startAnimation", Q_ARG(const QString&, url), Q_ARG(float, fps),
|
QMetaObject::invokeMethod(this, "overrideAnimation", Q_ARG(const QString&, url), Q_ARG(float, fps),
|
||||||
Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame));
|
Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_rig->startAnimation(url, fps, loop, firstFrame, lastFrame);
|
_rig->overrideAnimation(url, fps, loop, firstFrame, lastFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::stopAnimation() {
|
void MyAvatar::restoreAnimation() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "stopAnimation");
|
QMetaObject::invokeMethod(this, "restoreAnimation");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_rig->stopAnimation();
|
_rig->restoreAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList MyAvatar::getAnimationRoles() {
|
QStringList MyAvatar::getAnimationRoles() {
|
||||||
|
@ -683,22 +683,22 @@ QStringList MyAvatar::getAnimationRoles() {
|
||||||
return _rig->getAnimationRoles();
|
return _rig->getAnimationRoles();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::overrideAnimationRole(const QString& role, const QString& url, float fps, bool loop,
|
void MyAvatar::overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop,
|
||||||
float firstFrame, float lastFrame) {
|
float firstFrame, float lastFrame) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "overrideAnimationRole", Q_ARG(const QString&, role), Q_ARG(const QString&, url),
|
QMetaObject::invokeMethod(this, "overrideRoleAnimation", Q_ARG(const QString&, role), Q_ARG(const QString&, url),
|
||||||
Q_ARG(float, fps), Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame));
|
Q_ARG(float, fps), Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_rig->overrideAnimationRole(role, url, fps, loop, firstFrame, lastFrame);
|
_rig->overrideRoleAnimation(role, url, fps, loop, firstFrame, lastFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::restoreAnimationRole(const QString& role) {
|
void MyAvatar::restoreRoleAnimation(const QString& role) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "restoreAnimationRole", Q_ARG(const QString&, role));
|
QMetaObject::invokeMethod(this, "restoreRoleAnimation", Q_ARG(const QString&, role));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_rig->restoreAnimationRole(role);
|
_rig->restoreRoleAnimation(role);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::prefetchAnimation(const QString& url) {
|
void MyAvatar::prefetchAnimation(const QString& url) {
|
||||||
|
|
|
@ -119,19 +119,19 @@ public:
|
||||||
void removeAnimationHandle(const AnimationHandlePointer& handle) { _rig->removeAnimationHandle(handle); }
|
void removeAnimationHandle(const AnimationHandlePointer& handle) { _rig->removeAnimationHandle(handle); }
|
||||||
|
|
||||||
// Interrupt the current animation with a custom animation.
|
// Interrupt the current animation with a custom animation.
|
||||||
Q_INVOKABLE void startAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
Q_INVOKABLE void overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
||||||
|
|
||||||
// Stops the animation that was started with startAnimation and go back to the standard animation.
|
// Stop the animation that was started with overrideAnimation and go back to the standard animation.
|
||||||
Q_INVOKABLE void stopAnimation();
|
Q_INVOKABLE void restoreAnimation();
|
||||||
|
|
||||||
// Returns a list of all clips that are available
|
// Returns a list of all clips that are available
|
||||||
Q_INVOKABLE QStringList getAnimationRoles();
|
Q_INVOKABLE QStringList getAnimationRoles();
|
||||||
|
|
||||||
// Replace an existing standard role animation with a custom one.
|
// Replace an existing standard role animation with a custom one.
|
||||||
Q_INVOKABLE void overrideAnimationRole(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
Q_INVOKABLE void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
||||||
|
|
||||||
// remove an animation role override and return to the standard animation.
|
// remove an animation role override and return to the standard animation.
|
||||||
Q_INVOKABLE void restoreAnimationRole(const QString& role);
|
Q_INVOKABLE void restoreRoleAnimation(const QString& role);
|
||||||
|
|
||||||
// prefetch animation
|
// prefetch animation
|
||||||
Q_INVOKABLE void prefetchAnimation(const QString& url);
|
Q_INVOKABLE void prefetchAnimation(const QString& url);
|
||||||
|
|
|
@ -8,12 +8,35 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
#include "AnimNode.h"
|
#include "AnimNode.h"
|
||||||
|
|
||||||
void AnimNode::removeChild(AnimNode::Pointer child) {
|
AnimNode::Pointer AnimNode::getParent() {
|
||||||
|
return _parent.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimNode::addChild(Pointer child) {
|
||||||
|
_children.push_back(child);
|
||||||
|
child->_parent = shared_from_this();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimNode::removeChild(Pointer child) {
|
||||||
auto iter = std::find(_children.begin(), _children.end(), child);
|
auto iter = std::find(_children.begin(), _children.end(), child);
|
||||||
if (iter != _children.end()) {
|
if (iter != _children.end()) {
|
||||||
_children.erase(iter);
|
_children.erase(iter);
|
||||||
|
child->_parent.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimNode::replaceChild(Pointer oldChild, Pointer newChild) {
|
||||||
|
auto iter = std::find(_children.begin(), _children.end(), oldChild);
|
||||||
|
if (iter != _children.end()) {
|
||||||
|
oldChild->_parent.reset();
|
||||||
|
newChild->_parent = shared_from_this();
|
||||||
|
if (_skeleton) {
|
||||||
|
newChild->setSkeleton(_skeleton);
|
||||||
|
}
|
||||||
|
*iter = newChild;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +45,7 @@ AnimNode::Pointer AnimNode::getChild(int i) const {
|
||||||
return _children[i];
|
return _children[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimNode::setSkeleton(const AnimSkeleton::Pointer skeleton) {
|
void AnimNode::setSkeleton(AnimSkeleton::ConstPointer skeleton) {
|
||||||
setSkeletonInternal(skeleton);
|
setSkeletonInternal(skeleton);
|
||||||
for (auto&& child : _children) {
|
for (auto&& child : _children) {
|
||||||
child->setSkeleton(skeleton);
|
child->setSkeleton(skeleton);
|
||||||
|
|
|
@ -60,14 +60,15 @@ public:
|
||||||
Type getType() const { return _type; }
|
Type getType() const { return _type; }
|
||||||
|
|
||||||
// hierarchy accessors
|
// hierarchy accessors
|
||||||
void addChild(Pointer child) { _children.push_back(child); }
|
Pointer getParent();
|
||||||
|
void addChild(Pointer child);
|
||||||
void removeChild(Pointer child);
|
void removeChild(Pointer child);
|
||||||
|
void replaceChild(Pointer oldChild, Pointer newChild);
|
||||||
Pointer getChild(int i) const;
|
Pointer getChild(int i) const;
|
||||||
int getChildCount() const { return (int)_children.size(); }
|
int getChildCount() const { return (int)_children.size(); }
|
||||||
|
|
||||||
// pair this AnimNode graph with a skeleton.
|
// pair this AnimNode graph with a skeleton.
|
||||||
void setSkeleton(const AnimSkeleton::Pointer skeleton);
|
void setSkeleton(AnimSkeleton::ConstPointer skeleton);
|
||||||
|
|
||||||
AnimSkeleton::ConstPointer getSkeleton() const { return _skeleton; }
|
AnimSkeleton::ConstPointer getSkeleton() const { return _skeleton; }
|
||||||
|
|
||||||
|
@ -95,9 +96,9 @@ public:
|
||||||
traverse([&](Pointer node) {
|
traverse([&](Pointer node) {
|
||||||
if (id == node->getID()) {
|
if (id == node->getID()) {
|
||||||
result = node;
|
result = node;
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
return true;
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +115,7 @@ protected:
|
||||||
QString _id;
|
QString _id;
|
||||||
std::vector<AnimNode::Pointer> _children;
|
std::vector<AnimNode::Pointer> _children;
|
||||||
AnimSkeleton::ConstPointer _skeleton;
|
AnimSkeleton::ConstPointer _skeleton;
|
||||||
|
std::weak_ptr<AnimNode> _parent;
|
||||||
|
|
||||||
// no copies
|
// no copies
|
||||||
AnimNode(const AnimNode&) = delete;
|
AnimNode(const AnimNode&) = delete;
|
||||||
|
|
|
@ -393,9 +393,9 @@ AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QS
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildChildMap(std::map<QString, AnimNode::Pointer>& map, AnimNode::Pointer node) {
|
void buildChildMap(std::map<QString, int>& map, AnimNode::Pointer node) {
|
||||||
for ( auto child : node->_children ) {
|
for (int i = 0; i < (int)node->getChildCount(); ++i) {
|
||||||
map.insert(std::pair<QString, AnimNode::Pointer>(child->_id, child));
|
map.insert(std::pair<QString, int>(node->getChild(i)->getID(), i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,7 +412,7 @@ bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj,
|
||||||
}
|
}
|
||||||
|
|
||||||
// build a map for all children by name.
|
// build a map for all children by name.
|
||||||
std::map<QString, AnimNode::Pointer> childMap;
|
std::map<QString, int> childMap;
|
||||||
buildChildMap(childMap, node);
|
buildChildMap(childMap, node);
|
||||||
|
|
||||||
// first pass parse all the states and build up the state and transition map.
|
// first pass parse all the states and build up the state and transition map.
|
||||||
|
|
|
@ -46,7 +46,7 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, fl
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(_currentState);
|
assert(_currentState);
|
||||||
auto currentStateNode = _currentState->getNode();
|
auto currentStateNode = _children[_currentState->getChildIndex()];
|
||||||
assert(currentStateNode);
|
assert(currentStateNode);
|
||||||
|
|
||||||
if (_duringInterp) {
|
if (_duringInterp) {
|
||||||
|
@ -79,8 +79,8 @@ void AnimStateMachine::switchState(const AnimVariantMap& animVars, State::Pointe
|
||||||
|
|
||||||
const float FRAMES_PER_SECOND = 30.0f;
|
const float FRAMES_PER_SECOND = 30.0f;
|
||||||
|
|
||||||
auto prevStateNode = _currentState->getNode();
|
auto prevStateNode = _children[_currentState->getChildIndex()];
|
||||||
auto nextStateNode = desiredState->getNode();
|
auto nextStateNode = _children[desiredState->getChildIndex()];
|
||||||
|
|
||||||
_duringInterp = true;
|
_duringInterp = true;
|
||||||
_alpha = 0.0f;
|
_alpha = 0.0f;
|
||||||
|
|
|
@ -55,16 +55,16 @@ protected:
|
||||||
State::Pointer _state;
|
State::Pointer _state;
|
||||||
};
|
};
|
||||||
|
|
||||||
State(const QString& id, AnimNode::Pointer node, float interpTarget, float interpDuration) :
|
State(const QString& id, int childIndex, float interpTarget, float interpDuration) :
|
||||||
_id(id),
|
_id(id),
|
||||||
_node(node),
|
_childIndex(childIndex),
|
||||||
_interpTarget(interpTarget),
|
_interpTarget(interpTarget),
|
||||||
_interpDuration(interpDuration) {}
|
_interpDuration(interpDuration) {}
|
||||||
|
|
||||||
void setInterpTargetVar(const QString& interpTargetVar) { _interpTargetVar = interpTargetVar; }
|
void setInterpTargetVar(const QString& interpTargetVar) { _interpTargetVar = interpTargetVar; }
|
||||||
void setInterpDurationVar(const QString& interpDurationVar) { _interpDurationVar = interpDurationVar; }
|
void setInterpDurationVar(const QString& interpDurationVar) { _interpDurationVar = interpDurationVar; }
|
||||||
|
|
||||||
AnimNode::Pointer getNode() const { return _node; }
|
int getChildIndex() const { return _childIndex; }
|
||||||
const QString& getID() const { return _id; }
|
const QString& getID() const { return _id; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -75,7 +75,7 @@ protected:
|
||||||
void addTransition(const Transition& transition) { _transitions.push_back(transition); }
|
void addTransition(const Transition& transition) { _transitions.push_back(transition); }
|
||||||
|
|
||||||
QString _id;
|
QString _id;
|
||||||
AnimNode::Pointer _node;
|
int _childIndex;
|
||||||
float _interpTarget; // frames
|
float _interpTarget; // frames
|
||||||
float _interpDuration; // frames
|
float _interpDuration; // frames
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ void Rig::removeAnimationHandle(const AnimationHandlePointer& handle) {
|
||||||
_animationHandles.removeOne(handle);
|
_animationHandles.removeOne(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::startAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
void Rig::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
||||||
if (_enableAnimGraph) {
|
if (_enableAnimGraph) {
|
||||||
|
|
||||||
// find an unused AnimClip clipNode
|
// find an unused AnimClip clipNode
|
||||||
|
@ -63,7 +63,8 @@ void Rig::startAnimation(const QString& url, float fps, bool loop, float firstFr
|
||||||
clip->setStartFrame(firstFrame);
|
clip->setStartFrame(firstFrame);
|
||||||
clip->setEndFrame(lastFrame);
|
clip->setEndFrame(lastFrame);
|
||||||
const float REFERENCE_FRAMES_PER_SECOND = 30.0f;
|
const float REFERENCE_FRAMES_PER_SECOND = 30.0f;
|
||||||
clip->setTimeScale(fps / REFERENCE_FRAMES_PER_SECOND);
|
float timeScale = fps / REFERENCE_FRAMES_PER_SECOND;
|
||||||
|
clip->setTimeScale(timeScale);
|
||||||
clip->loadURL(url);
|
clip->loadURL(url);
|
||||||
|
|
||||||
_currentUserAnimURL = url;
|
_currentUserAnimURL = url;
|
||||||
|
@ -107,7 +108,7 @@ void Rig::startAnimation(const QString& url, float fps, bool loop, float firstFr
|
||||||
const float FRAMES_PER_SECOND = 30.0f;
|
const float FRAMES_PER_SECOND = 30.0f;
|
||||||
const float FADE_FRAMES = 30.0f;
|
const float FADE_FRAMES = 30.0f;
|
||||||
|
|
||||||
void Rig::stopAnimation() {
|
void Rig::restoreAnimation() {
|
||||||
if (_enableAnimGraph) {
|
if (_enableAnimGraph) {
|
||||||
if (_currentUserAnimURL != "") {
|
if (_currentUserAnimURL != "") {
|
||||||
_currentUserAnimURL = "";
|
_currentUserAnimURL = "";
|
||||||
|
@ -130,7 +131,14 @@ QStringList Rig::getAnimationRoles() const {
|
||||||
if (_enableAnimGraph && _animNode) {
|
if (_enableAnimGraph && _animNode) {
|
||||||
QStringList list;
|
QStringList list;
|
||||||
_animNode->traverse([&](AnimNode::Pointer node) {
|
_animNode->traverse([&](AnimNode::Pointer node) {
|
||||||
list.append(node->getID());
|
// only report clip nodes as valid roles.
|
||||||
|
auto clipNode = std::dynamic_pointer_cast<AnimClip>(node);
|
||||||
|
if (clipNode) {
|
||||||
|
// filter out the userAnims, they are for internal use only.
|
||||||
|
if (!clipNode->getID().startsWith("userAnim")) {
|
||||||
|
list.append(node->getID());
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
return list;
|
return list;
|
||||||
|
@ -139,36 +147,33 @@ QStringList Rig::getAnimationRoles() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::overrideAnimationRole(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
void Rig::overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
||||||
if (_enableAnimGraph && _animNode) {
|
if (_enableAnimGraph && _animNode) {
|
||||||
AnimNode::Pointer node = _animNode->findByName(role);
|
AnimNode::Pointer node = _animNode->findByName(role);
|
||||||
if (node) {
|
if (node) {
|
||||||
//_previousRoleAnimations[role] = node;
|
_origRoleAnimations[role] = node;
|
||||||
// TODO: create clip node.
|
const float REFERENCE_FRAMES_PER_SECOND = 30.0f;
|
||||||
// TODO: AnimNode needs the following methods.
|
float timeScale = fps / REFERENCE_FRAMES_PER_SECOND;
|
||||||
// Pointer getParent() const;
|
auto clipNode = std::make_shared<AnimClip>(role, url, firstFrame, lastFrame, timeScale, loop);
|
||||||
// void swapChild(Pointer child, Pointer newChild);
|
AnimNode::Pointer parent = node->getParent();
|
||||||
//
|
parent->replaceChild(node, clipNode);
|
||||||
// pseudo code
|
|
||||||
//
|
|
||||||
// auto clipNode = std::make_shared<AnimClip>(role, url, fps, firstFrame, lastFrame, loop);
|
|
||||||
// node->getParent()->swapChild(node, clipNode);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
qCWarning(animation) << "Rig::overrideAnimationRole could not find role " << role;
|
qCWarning(animation) << "Rig::overrideRoleAnimation could not find role " << role;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::restoreAnimationRole(const QString& role) {
|
void Rig::restoreRoleAnimation(const QString& role) {
|
||||||
if (_enableAnimGraph && _animNode) {
|
if (_enableAnimGraph && _animNode) {
|
||||||
AnimNode::Pointer node = _animNode->findByName(role);
|
AnimNode::Pointer node = _animNode->findByName(role);
|
||||||
if (node) {
|
if (node) {
|
||||||
// TODO: pseudo code
|
auto iter = _origRoleAnimations.find(role);
|
||||||
// origNode = _previousRoleAnimations.find(role);
|
if (iter != _origRoleAnimations.end()) {
|
||||||
// if (origNode) {
|
node->getParent()->replaceChild(node, iter->second);
|
||||||
// node->getParent()->swapChild(node, origNode);
|
_origRoleAnimations.erase(iter);
|
||||||
// }
|
} else {
|
||||||
|
qCWarning(animation) << "Rig::restoreRoleAnimation could not find role " << role;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,11 +114,11 @@ public:
|
||||||
void destroyAnimGraph();
|
void destroyAnimGraph();
|
||||||
const QList<AnimationHandlePointer>& getAnimationHandles() const { return _animationHandles; }
|
const QList<AnimationHandlePointer>& getAnimationHandles() const { return _animationHandles; }
|
||||||
|
|
||||||
void startAnimation(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 stopAnimation();
|
void restoreAnimation();
|
||||||
QStringList getAnimationRoles() const;
|
QStringList getAnimationRoles() const;
|
||||||
void overrideAnimationRole(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
void overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
||||||
void restoreAnimationRole(const QString& role);
|
void restoreRoleAnimation(const QString& role);
|
||||||
void prefetchAnimation(const QString& url);
|
void prefetchAnimation(const QString& url);
|
||||||
|
|
||||||
void initJointStates(QVector<JointState> states, glm::mat4 rootTransform,
|
void initJointStates(QVector<JointState> states, glm::mat4 rootTransform,
|
||||||
|
@ -264,6 +264,8 @@ public:
|
||||||
SimpleMovingAverage _averageForwardSpeed { 10 };
|
SimpleMovingAverage _averageForwardSpeed { 10 };
|
||||||
SimpleMovingAverage _averageLateralSpeed { 10 };
|
SimpleMovingAverage _averageLateralSpeed { 10 };
|
||||||
|
|
||||||
|
std::map<QString, AnimNode::Pointer> _origRoleAnimations;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMap<int, StateHandler> _stateHandlers;
|
QMap<int, StateHandler> _stateHandlers;
|
||||||
int _nextStateHandlerId { 0 };
|
int _nextStateHandlerId { 0 };
|
||||||
|
|
Loading…
Reference in a new issue