mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 18:50:00 +02:00
WIP checkpoint
This commit is contained in:
parent
af2b3bb9d5
commit
eacc2cae0c
7 changed files with 140 additions and 176 deletions
|
@ -66,7 +66,7 @@ function kneelDown() {
|
||||||
function standUp() {
|
function standUp() {
|
||||||
kneeling = false;
|
kneeling = false;
|
||||||
|
|
||||||
MyAvatar.stopAnimation(KNEEL_ANIM_URL);
|
MyAvatar.stopAnimation();
|
||||||
|
|
||||||
Overlays.editOverlay(standUpButton, { visible: false });
|
Overlays.editOverlay(standUpButton, { visible: false });
|
||||||
Overlays.editOverlay(kneelDownButton, { visible: true });
|
Overlays.editOverlay(kneelDownButton, { visible: true });
|
||||||
|
|
|
@ -4294,10 +4294,6 @@ void Application::stopAllScripts(bool restart) {
|
||||||
it.value()->stop();
|
it.value()->stop();
|
||||||
qCDebug(interfaceapp) << "stopping script..." << it.key();
|
qCDebug(interfaceapp) << "stopping script..." << it.key();
|
||||||
}
|
}
|
||||||
// HACK: ATM scripts cannot set/get their animation priorities, so we clear priorities
|
|
||||||
// whenever a script stops in case it happened to have been setting joint rotations.
|
|
||||||
// TODO: expose animation priorities and provide a layered animation control system.
|
|
||||||
getMyAvatar()->clearJointAnimationPriorities();
|
|
||||||
getMyAvatar()->clearScriptableSettings();
|
getMyAvatar()->clearScriptableSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4313,10 +4309,6 @@ bool Application::stopScript(const QString& scriptHash, bool restart) {
|
||||||
scriptEngine->stop();
|
scriptEngine->stop();
|
||||||
stoppedScript = true;
|
stoppedScript = true;
|
||||||
qCDebug(interfaceapp) << "stopping script..." << scriptHash;
|
qCDebug(interfaceapp) << "stopping script..." << scriptHash;
|
||||||
// HACK: ATM scripts cannot set/get their animation priorities, so we clear priorities
|
|
||||||
// whenever a script stops in case it happened to have been setting joint rotations.
|
|
||||||
// TODO: expose animation priorities and provide a layered animation control system.
|
|
||||||
getMyAvatar()->clearJointAnimationPriorities();
|
|
||||||
}
|
}
|
||||||
if (_scriptEnginesHash.empty()) {
|
if (_scriptEnginesHash.empty()) {
|
||||||
getMyAvatar()->clearScriptableSettings();
|
getMyAvatar()->clearScriptableSettings();
|
||||||
|
|
|
@ -666,65 +666,47 @@ void MyAvatar::startAnimation(const QString& url, float fps, bool loop, float fi
|
||||||
_rig->startAnimation(url, fps, loop, firstFrame, lastFrame);
|
_rig->startAnimation(url, fps, loop, firstFrame, lastFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::startAnimationByRole(const QString& role, const QString& url, float fps, float priority,
|
void MyAvatar::stopAnimation() {
|
||||||
bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "startAnimationByRole", Q_ARG(const QString&, role), Q_ARG(const QString&, url),
|
QMetaObject::invokeMethod(this, "stopAnimation");
|
||||||
Q_ARG(float, fps), Q_ARG(float, priority), Q_ARG(bool, loop), Q_ARG(bool, hold), Q_ARG(float, firstFrame),
|
|
||||||
Q_ARG(float, lastFrame), Q_ARG(const QStringList&, maskedJoints));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_rig->startAnimationByRole(role, url, fps, priority, loop, hold, firstFrame, lastFrame, maskedJoints);
|
_rig->stopAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::stopAnimationByRole(const QString& role) {
|
QStringList MyAvatar::getAnimationRoles() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "stopAnimationByRole", Q_ARG(const QString&, role));
|
QStringList result;
|
||||||
return;
|
QMetaObject::invokeMethod(this, "getAnimationRoles", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QStringList, result));
|
||||||
}
|
|
||||||
_rig->stopAnimationByRole(role);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MyAvatar::stopAnimation(const QString& url) {
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QMetaObject::invokeMethod(this, "stopAnimation", Q_ARG(const QString&, url));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_rig->stopAnimation(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationDetails MyAvatar::getAnimationDetailsByRole(const QString& role) {
|
|
||||||
AnimationDetails result;
|
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QMetaObject::invokeMethod(this, "getAnimationDetailsByRole", Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(AnimationDetails, result),
|
|
||||||
Q_ARG(const QString&, role));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
foreach (const AnimationHandlePointer& handle, _rig->getRunningAnimations()) {
|
return _rig->getAnimationRoles();
|
||||||
if (handle->getRole() == role) {
|
|
||||||
result = handle->getAnimationDetails();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationDetails MyAvatar::getAnimationDetails(const QString& url) {
|
void MyAvatar::overrideAnimationRole(const QString& role, const QString& url, float fps, bool loop,
|
||||||
AnimationDetails result;
|
float firstFrame, float lastFrame) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "getAnimationDetails", Qt::BlockingQueuedConnection,
|
QMetaObject::invokeMethod(this, "overrideAnimationRole", Q_ARG(const QString&, role), Q_ARG(const QString&, url),
|
||||||
Q_RETURN_ARG(AnimationDetails, result),
|
Q_ARG(float, fps), Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame));
|
||||||
Q_ARG(const QString&, url));
|
return;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
foreach (const AnimationHandlePointer& handle, _rig->getRunningAnimations()) {
|
_rig->overrideAnimationRole(role, url, fps, loop, firstFrame, lastFrame);
|
||||||
if (handle->getURL() == url) {
|
}
|
||||||
result = handle->getAnimationDetails();
|
|
||||||
break;
|
void MyAvatar::restoreAnimationRole(const QString& role) {
|
||||||
}
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "restoreAnimationRole", Q_ARG(const QString&, role));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return result;
|
_rig->restoreAnimationRole(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyAvatar::prefetchAnimation(const QString& url) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "prefetchAnimation", Q_ARG(const QString&, url));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_rig->prefetchAnimation(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::saveData() {
|
void MyAvatar::saveData() {
|
||||||
|
@ -797,6 +779,7 @@ float loadSetting(QSettings& settings, const char* name, float defaultValue) {
|
||||||
// If we demand the animation from the update thread while we're locked, we'll deadlock.
|
// If we demand the animation from the update thread while we're locked, we'll deadlock.
|
||||||
// Until we untangle this, code puts the updates back on the main thread temporarilly and starts all the loading.
|
// Until we untangle this, code puts the updates back on the main thread temporarilly and starts all the loading.
|
||||||
void MyAvatar::safelyLoadAnimations() {
|
void MyAvatar::safelyLoadAnimations() {
|
||||||
|
/*
|
||||||
_rig->addAnimationByRole("idle");
|
_rig->addAnimationByRole("idle");
|
||||||
_rig->addAnimationByRole("walk");
|
_rig->addAnimationByRole("walk");
|
||||||
_rig->addAnimationByRole("backup");
|
_rig->addAnimationByRole("backup");
|
||||||
|
@ -804,6 +787,7 @@ void MyAvatar::safelyLoadAnimations() {
|
||||||
_rig->addAnimationByRole("rightTurn");
|
_rig->addAnimationByRole("rightTurn");
|
||||||
_rig->addAnimationByRole("leftStrafe");
|
_rig->addAnimationByRole("leftStrafe");
|
||||||
_rig->addAnimationByRole("rightStrafe");
|
_rig->addAnimationByRole("rightStrafe");
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::setEnableRigAnimations(bool isEnabled) {
|
void MyAvatar::setEnableRigAnimations(bool isEnabled) {
|
||||||
|
@ -905,23 +889,6 @@ void MyAvatar::loadData() {
|
||||||
settings.endArray();
|
settings.endArray();
|
||||||
setAttachmentData(attachmentData);
|
setAttachmentData(attachmentData);
|
||||||
|
|
||||||
int animationCount = settings.beginReadArray("animationHandles");
|
|
||||||
_rig->deleteAnimations();
|
|
||||||
for (int i = 0; i < animationCount; i++) {
|
|
||||||
settings.setArrayIndex(i);
|
|
||||||
_rig->addAnimationByRole(settings.value("role", "idle").toString(),
|
|
||||||
settings.value("url").toString(),
|
|
||||||
loadSetting(settings, "fps", 30.0f),
|
|
||||||
loadSetting(settings, "priority", 1.0f),
|
|
||||||
settings.value("loop", true).toBool(),
|
|
||||||
settings.value("hold", false).toBool(),
|
|
||||||
settings.value("firstFrame", 0.0f).toFloat(),
|
|
||||||
settings.value("lastFrame", INT_MAX).toFloat(),
|
|
||||||
settings.value("maskedJoints").toStringList(),
|
|
||||||
settings.value("startAutomatically", true).toBool());
|
|
||||||
}
|
|
||||||
settings.endArray();
|
|
||||||
|
|
||||||
setDisplayName(settings.value("displayName").toString());
|
setDisplayName(settings.value("displayName").toString());
|
||||||
setCollisionSoundURL(settings.value("collisionSoundURL", DEFAULT_AVATAR_COLLISION_SOUND_URL).toString());
|
setCollisionSoundURL(settings.value("collisionSoundURL", DEFAULT_AVATAR_COLLISION_SOUND_URL).toString());
|
||||||
|
|
||||||
|
@ -1177,14 +1144,7 @@ void MyAvatar::clearJointData(int index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::clearJointsData() {
|
void MyAvatar::clearJointsData() {
|
||||||
clearJointAnimationPriorities();
|
//clearJointAnimationPriorities();
|
||||||
}
|
|
||||||
|
|
||||||
void MyAvatar::clearJointAnimationPriorities() {
|
|
||||||
int numStates = _skeletonModel.getJointStateCount();
|
|
||||||
for (int i = 0; i < numStates; ++i) {
|
|
||||||
_rig->clearJointAnimationPriority(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) {
|
void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) {
|
||||||
|
@ -1382,7 +1342,6 @@ void MyAvatar::setScriptedMotorFrame(QString frame) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::clearScriptableSettings() {
|
void MyAvatar::clearScriptableSettings() {
|
||||||
clearJointAnimationPriorities();
|
|
||||||
_scriptedMotorVelocity = glm::vec3(0.0f);
|
_scriptedMotorVelocity = glm::vec3(0.0f);
|
||||||
_scriptedMotorTimescale = DEFAULT_SCRIPTED_MOTOR_TIMESCALE;
|
_scriptedMotorTimescale = DEFAULT_SCRIPTED_MOTOR_TIMESCALE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,22 +117,25 @@ public:
|
||||||
const QList<AnimationHandlePointer>& getAnimationHandles() const { return _rig->getAnimationHandles(); }
|
const QList<AnimationHandlePointer>& getAnimationHandles() const { return _rig->getAnimationHandles(); }
|
||||||
AnimationHandlePointer addAnimationHandle() { return _rig->createAnimationHandle(); }
|
AnimationHandlePointer addAnimationHandle() { return _rig->createAnimationHandle(); }
|
||||||
void removeAnimationHandle(const AnimationHandlePointer& handle) { _rig->removeAnimationHandle(handle); }
|
void removeAnimationHandle(const AnimationHandlePointer& handle) { _rig->removeAnimationHandle(handle); }
|
||||||
/// Allows scripts to run animations.
|
|
||||||
|
// 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 startAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
||||||
|
|
||||||
/// Stops an animation as identified by a URL.
|
// Stops the animation that was started with startAnimation and go back to the standard animation.
|
||||||
Q_INVOKABLE void stopAnimation(const QString& url);
|
Q_INVOKABLE void stopAnimation();
|
||||||
|
|
||||||
|
// Returns a list of all clips that are available
|
||||||
|
Q_INVOKABLE QStringList getAnimationRoles();
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// remove an animation role override and return to the standard animation.
|
||||||
|
Q_INVOKABLE void restoreAnimationRole(const QString& role);
|
||||||
|
|
||||||
|
// prefetch animation
|
||||||
|
Q_INVOKABLE void prefetchAnimation(const QString& url);
|
||||||
|
|
||||||
/// Starts an animation by its role, using the provided URL and parameters if the avatar doesn't have a custom
|
|
||||||
/// animation for the role.
|
|
||||||
Q_INVOKABLE void startAnimationByRole(const QString& role, const QString& url = QString(), float fps = 30.0f,
|
|
||||||
float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f,
|
|
||||||
float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList());
|
|
||||||
/// Stops an animation identified by its role.
|
|
||||||
Q_INVOKABLE void stopAnimationByRole(const QString& role);
|
|
||||||
Q_INVOKABLE AnimationDetails getAnimationDetailsByRole(const QString& role);
|
|
||||||
Q_INVOKABLE AnimationDetails getAnimationDetails(const QString& url);
|
|
||||||
void clearJointAnimationPriorities();
|
|
||||||
// Adds handler(animStateDictionaryIn) => animStateDictionaryOut, which will be invoked just before each animGraph state update.
|
// Adds handler(animStateDictionaryIn) => animStateDictionaryOut, which will be invoked just before each animGraph state update.
|
||||||
// The handler will be called with an animStateDictionaryIn that has all those properties specified by the (possibly empty)
|
// The handler will be called with an animStateDictionaryIn that has all those properties specified by the (possibly empty)
|
||||||
// propertiesList argument. However for debugging, if the properties argument is null, all internal animGraph state is provided.
|
// propertiesList argument. However for debugging, if the properties argument is null, all internal animGraph state is provided.
|
||||||
|
|
|
@ -33,7 +33,7 @@ class QJsonObject;
|
||||||
// * evaluate method, perform actual joint manipulations here and return result by reference.
|
// * evaluate method, perform actual joint manipulations here and return result by reference.
|
||||||
// Also, append any triggers that are detected during evaluation.
|
// Also, append any triggers that are detected during evaluation.
|
||||||
|
|
||||||
class AnimNode {
|
class AnimNode : public std::enable_shared_from_this<AnimNode> {
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
enum class Type {
|
||||||
Clip = 0,
|
Clip = 0,
|
||||||
|
@ -78,6 +78,30 @@ public:
|
||||||
|
|
||||||
void setCurrentFrame(float frame);
|
void setCurrentFrame(float frame);
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
bool traverse(F func) {
|
||||||
|
if (func(shared_from_this())) {
|
||||||
|
for (auto&& child : _children) {
|
||||||
|
if (!child->traverse(func)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pointer findByName(const QString& id) {
|
||||||
|
Pointer result;
|
||||||
|
traverse([&](Pointer node) {
|
||||||
|
if (id == node->getID()) {
|
||||||
|
result = node;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void setCurrentFrameInternal(float frame) {}
|
virtual void setCurrentFrameInternal(float frame) {}
|
||||||
|
|
|
@ -79,6 +79,8 @@ void Rig::startAnimation(const QString& url, float fps, bool loop, float firstFr
|
||||||
bool hold = true;
|
bool hold = true;
|
||||||
QStringList maskedJoints;
|
QStringList maskedJoints;
|
||||||
|
|
||||||
|
_currentUserAnimURL = url;
|
||||||
|
|
||||||
// This is different than startAnimationByRole, in which we use the existing values if the animation already exists.
|
// This is different than startAnimationByRole, in which we use the existing values if the animation already exists.
|
||||||
// Here we reuse the animation handle if possible, but in any case, we set the values to those given (or defaulted).
|
// Here we reuse the animation handle if possible, but in any case, we set the values to those given (or defaulted).
|
||||||
AnimationHandlePointer handle = nullptr;
|
AnimationHandlePointer handle = nullptr;
|
||||||
|
@ -102,79 +104,12 @@ void Rig::startAnimation(const QString& url, float fps, bool loop, float firstFr
|
||||||
handle->start();
|
handle->start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationHandlePointer Rig::addAnimationByRole(const QString& role, const QString& url, float fps, float priority,
|
|
||||||
bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints, bool startAutomatically) {
|
|
||||||
|
|
||||||
// check for a configured animation for the role
|
|
||||||
//qCDebug(animation) << "addAnimationByRole" << role << url << fps << priority << loop << hold << firstFrame << lastFrame << maskedJoints << startAutomatically;
|
|
||||||
foreach (const AnimationHandlePointer& candidate, _animationHandles) {
|
|
||||||
if (candidate->getRole() == role) {
|
|
||||||
if (startAutomatically) {
|
|
||||||
candidate->start();
|
|
||||||
}
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AnimationHandlePointer handle = createAnimationHandle();
|
|
||||||
QString standard = "";
|
|
||||||
if (url.isEmpty()) { // Default animations for fight club
|
|
||||||
const QString& base = "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/";
|
|
||||||
if (role == "walk") {
|
|
||||||
standard = base + "walk_fwd.fbx";
|
|
||||||
} else if (role == "backup") {
|
|
||||||
standard = base + "walk_bwd.fbx";
|
|
||||||
} else if (role == "leftTurn") {
|
|
||||||
standard = base + "turn_left.fbx";
|
|
||||||
} else if (role == "rightTurn") {
|
|
||||||
standard = base + "turn_right.fbx";
|
|
||||||
} else if (role == "leftStrafe") {
|
|
||||||
standard = base + "strafe_left.fbx";
|
|
||||||
} else if (role == "rightStrafe") {
|
|
||||||
standard = base + "strafe_right.fbx";
|
|
||||||
} else if (role == "idle") {
|
|
||||||
standard = base + "idle.fbx";
|
|
||||||
fps = 25.0f;
|
|
||||||
}
|
|
||||||
if (!standard.isEmpty()) {
|
|
||||||
loop = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handle->setRole(role);
|
|
||||||
handle->setURL(url.isEmpty() ? standard : url);
|
|
||||||
handle->setFPS(fps);
|
|
||||||
handle->setPriority(priority);
|
|
||||||
handle->setLoop(loop);
|
|
||||||
handle->setHold(hold);
|
|
||||||
handle->setFirstFrame(firstFrame);
|
|
||||||
handle->setLastFrame(lastFrame);
|
|
||||||
handle->setMaskedJoints(maskedJoints);
|
|
||||||
if (startAutomatically) {
|
|
||||||
handle->start();
|
|
||||||
}
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float FADE_FRAMES = 30.0f;
|
|
||||||
const float FRAMES_PER_SECOND = 30.0f;
|
const float FRAMES_PER_SECOND = 30.0f;
|
||||||
|
const float FADE_FRAMES = 30.0f;
|
||||||
|
|
||||||
void Rig::startAnimationByRole(const QString& role, const QString& url, float fps, float priority,
|
void Rig::stopAnimation() {
|
||||||
bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints) {
|
|
||||||
AnimationHandlePointer handle = addAnimationByRole(role, url, fps, priority, loop, hold, firstFrame, lastFrame, maskedJoints, true);
|
|
||||||
handle->setFadePerSecond(FRAMES_PER_SECOND / FADE_FRAMES); // For now. Could be individualized later.
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rig::stopAnimationByRole(const QString& role) {
|
|
||||||
foreach (const AnimationHandlePointer& handle, getRunningAnimations()) {
|
|
||||||
if (handle->getRole() == role) {
|
|
||||||
handle->setFadePerSecond(-(FRAMES_PER_SECOND / FADE_FRAMES)); // For now. Could be individualized later.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Rig::stopAnimation(const QString& url) {
|
|
||||||
if (_enableAnimGraph) {
|
if (_enableAnimGraph) {
|
||||||
if (url == _currentUserAnimURL) {
|
if (_currentUserAnimURL != "") {
|
||||||
_currentUserAnimURL = "";
|
_currentUserAnimURL = "";
|
||||||
// notify the userAnimStateMachine the desired state.
|
// notify the userAnimStateMachine the desired state.
|
||||||
_animVars.set("userAnimNone", true);
|
_animVars.set("userAnimNone", true);
|
||||||
|
@ -183,7 +118,7 @@ void Rig::stopAnimation(const QString& url) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
foreach (const AnimationHandlePointer& handle, getRunningAnimations()) {
|
foreach (const AnimationHandlePointer& handle, getRunningAnimations()) {
|
||||||
if (handle->getURL() == url) {
|
if (handle->getURL() == _currentUserAnimURL) {
|
||||||
handle->setFade(0.0f); // right away. Will be remove during updateAnimations, without locking
|
handle->setFade(0.0f); // right away. Will be remove during updateAnimations, without locking
|
||||||
handle->setFadePerSecond(-(FRAMES_PER_SECOND / FADE_FRAMES)); // so that the updateAnimation code notices
|
handle->setFadePerSecond(-(FRAMES_PER_SECOND / FADE_FRAMES)); // so that the updateAnimation code notices
|
||||||
}
|
}
|
||||||
|
@ -191,6 +126,59 @@ void Rig::stopAnimation(const QString& url) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList Rig::getAnimationRoles() const {
|
||||||
|
if (_enableAnimGraph && _animNode) {
|
||||||
|
QStringList list;
|
||||||
|
_animNode->traverse([&](AnimNode::Pointer node) {
|
||||||
|
list.append(node->getID());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
} else {
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rig::overrideAnimationRole(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame) {
|
||||||
|
if (_enableAnimGraph && _animNode) {
|
||||||
|
AnimNode::Pointer node = _animNode->findByName(role);
|
||||||
|
if (node) {
|
||||||
|
//_previousRoleAnimations[role] = node;
|
||||||
|
// TODO: create clip node.
|
||||||
|
// TODO: AnimNode needs the following methods.
|
||||||
|
// Pointer getParent() const;
|
||||||
|
// void swapChild(Pointer child, Pointer newChild);
|
||||||
|
//
|
||||||
|
// pseudo code
|
||||||
|
//
|
||||||
|
// auto clipNode = std::make_shared<AnimClip>(role, url, fps, firstFrame, lastFrame, loop);
|
||||||
|
// node->getParent()->swapChild(node, clipNode);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
qCWarning(animation) << "Rig::overrideAnimationRole could not find role " << role;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rig::restoreAnimationRole(const QString& role) {
|
||||||
|
if (_enableAnimGraph && _animNode) {
|
||||||
|
AnimNode::Pointer node = _animNode->findByName(role);
|
||||||
|
if (node) {
|
||||||
|
// TODO: pseudo code
|
||||||
|
// origNode = _previousRoleAnimations.find(role);
|
||||||
|
// if (origNode) {
|
||||||
|
// node->getParent()->swapChild(node, origNode);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rig::prefetchAnimation(const QString& url) {
|
||||||
|
if (_enableAnimGraph) {
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Rig::removeRunningAnimation(AnimationHandlePointer animationHandle) {
|
bool Rig::removeRunningAnimation(AnimationHandlePointer animationHandle) {
|
||||||
return _runningAnimations.removeOne(animationHandle);
|
return _runningAnimations.removeOne(animationHandle);
|
||||||
}
|
}
|
||||||
|
@ -661,13 +649,13 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
if (isOn) {
|
if (isOn) {
|
||||||
if (!isRunningRole(role)) {
|
if (!isRunningRole(role)) {
|
||||||
qCDebug(animation) << "Rig STARTING" << role;
|
qCDebug(animation) << "Rig STARTING" << role;
|
||||||
startAnimationByRole(role);
|
//startAnimationByRole(role);
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isRunningRole(role)) {
|
if (isRunningRole(role)) {
|
||||||
qCDebug(animation) << "Rig stopping" << role;
|
qCDebug(animation) << "Rig stopping" << role;
|
||||||
stopAnimationByRole(role);
|
//stopAnimationByRole(role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -113,15 +113,13 @@ public:
|
||||||
void deleteAnimations();
|
void deleteAnimations();
|
||||||
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 startAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
||||||
void stopAnimation(const QString& url);
|
void stopAnimation();
|
||||||
void startAnimationByRole(const QString& role, const QString& url = QString(), float fps = 30.0f,
|
QStringList getAnimationRoles() const;
|
||||||
float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f,
|
void overrideAnimationRole(const QString& role, const QString& url, float fps, bool loop, float firstFrame, float lastFrame);
|
||||||
float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList());
|
void restoreAnimationRole(const QString& role);
|
||||||
void stopAnimationByRole(const QString& role);
|
void prefetchAnimation(const QString& url);
|
||||||
AnimationHandlePointer addAnimationByRole(const QString& role, const QString& url = QString(), float fps = 30.0f,
|
|
||||||
float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f,
|
|
||||||
float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList(), bool startAutomatically = false);
|
|
||||||
|
|
||||||
void initJointStates(QVector<JointState> states, glm::mat4 rootTransform,
|
void initJointStates(QVector<JointState> states, glm::mat4 rootTransform,
|
||||||
int rootJointIndex,
|
int rootJointIndex,
|
||||||
|
|
Loading…
Reference in a new issue