From a53d007c3383668e7582d7cd163d30358c00414c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 3 Jul 2014 11:59:18 -0700 Subject: [PATCH 1/3] add support for getting current animation details for running avatar animations --- interface/src/avatar/MyAvatar.cpp | 34 ++++++++++++++++++++ interface/src/avatar/MyAvatar.h | 3 ++ interface/src/renderer/Model.h | 9 ++++++ libraries/animation/src/AnimationCache.cpp | 24 ++++++++++++++ libraries/animation/src/AnimationCache.h | 33 +++++++++++++++++++ libraries/script-engine/src/ScriptEngine.cpp | 2 ++ 6 files changed, 105 insertions(+) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 7599baf7da..6cb6ba6840 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -551,6 +551,40 @@ void MyAvatar::stopAnimation(const QString& 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; + } + foreach (const AnimationHandlePointer& handle, _skeletonModel.getRunningAnimations()) { + if (handle->getRole() == role) { + result = handle->getAnimationDetails(); + break; + } + } + return result; +} + +AnimationDetails MyAvatar::getAnimationDetails(const QString& url) { + AnimationDetails result; + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "getAnimationDetails", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(AnimationDetails, result), + Q_ARG(const QString&, url)); + return result; + } + foreach (const AnimationHandlePointer& handle, _skeletonModel.getRunningAnimations()) { + if (handle->getURL() == url) { + result = handle->getAnimationDetails(); + break; + } + } + return result; +} + void MyAvatar::saveData(QSettings* settings) { settings->beginGroup("Avatar"); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 0ee76c6b45..0b2254bafa 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -83,6 +83,9 @@ public: /// 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); // get/set avatar data void saveData(QSettings* settings); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 835207b7eb..538babb541 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -354,6 +354,15 @@ public: void setRunning(bool running); bool isRunning() const { return _running; } + void setFrameIndex(float frameIndex) { _frameIndex = glm::clamp(_frameIndex, _firstFrame, _lastFrame); } + float getFrameIndex() const { return _frameIndex; } + + AnimationDetails getAnimationDetails() const { + AnimationDetails details(_role, _url, _fps, _priority, _loop, _hold, + _startAutomatically, _firstFrame, _lastFrame, _running, _frameIndex); + return details; + } + signals: void runningChanged(bool running); diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index ce7e4cdf36..ddf27af352 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -102,3 +102,27 @@ void Animation::downloadFinished(QNetworkReply* reply) { QThreadPool::globalInstance()->start(new AnimationReader(_self, reply)); } + +QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& details) { + QScriptValue obj = engine->newObject(); + obj.setProperty("role", details.role); + obj.setProperty("url", details.url.toString()); + obj.setProperty("fps", details.fps); + obj.setProperty("priority", details.priority); + obj.setProperty("loop", details.loop); + obj.setProperty("hold", details.hold); + obj.setProperty("startAutomatically", details.startAutomatically); + obj.setProperty("firstFrame", details.firstFrame); + obj.setProperty("lastFrame", details.lastFrame); + obj.setProperty("running", details.running); + obj.setProperty("frameIndex", details.frameIndex); + + + + return obj; +} + +void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& details) { + // nothing for now... +} + diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index 392443e7b5..b4aee5f9e3 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -12,6 +12,9 @@ #ifndef hifi_AnimationCache_h #define hifi_AnimationCache_h +#include +#include + #include #include @@ -68,4 +71,34 @@ private: bool _isValid; }; + +class AnimationDetails { +public: + AnimationDetails() : + role(), url(), fps(0.0f), priority(0.0f), loop(false), hold(false), + startAutomatically(false), firstFrame(0.0f), lastFrame(0.0f), running(false), frameIndex(0.0f) { } + + AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop, + bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float frameIndex) : + role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold), + startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame), + running(running), frameIndex(frameIndex) { } + + QString role; + QUrl url; + float fps; + float priority; + bool loop; + bool hold; + bool startAutomatically; + float firstFrame; + float lastFrame; + bool running; + float frameIndex; +}; +Q_DECLARE_METATYPE(AnimationDetails); +QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& event); +void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& event); + + #endif // hifi_AnimationCache_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index daf66dafbe..254eda1011 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -254,6 +254,8 @@ void ScriptEngine::init() { qScriptRegisterMetaType(&_engine, injectorToScriptValue, injectorFromScriptValue); + qScriptRegisterMetaType(&_engine, animationDetailsToScriptValue, animationDetailsFromScriptValue); + registerGlobalObject("Script", this); registerGlobalObject("Audio", &_audioScriptingInterface); registerGlobalObject("Controller", _controllerScriptingInterface); From 59e8a984127ca4a5b5440c4d4bae5dfff4ade0ca Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 3 Jul 2014 12:05:18 -0700 Subject: [PATCH 2/3] added example script --- examples/animationStateExample.js | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 examples/animationStateExample.js diff --git a/examples/animationStateExample.js b/examples/animationStateExample.js new file mode 100644 index 0000000000..c6987c8626 --- /dev/null +++ b/examples/animationStateExample.js @@ -0,0 +1,32 @@ +// +// animationStateExample.js +// examples +// +// Created by Brad Hefta-Gaub on 7/3/14. +// Copyright 2014 High Fidelity, Inc. +// +// This is an example script that runs in a loop and displays a counter to the log +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +// + +var count = 0; + +function displayAnimationDetails(deltaTime) { + print("count =" + count + " deltaTime=" + deltaTime); + count++; + var animationDetails = MyAvatar.getAnimationDetailsByRole("idle"); + print("animationDetails.frameIndex=" + animationDetails.frameIndex); +} + +function scriptEnding() { + print("SCRIPT ENDNG!!!\n"); +} + +// register the call back so it fires before each data send +Script.update.connect(displayAnimationDetails); + +// register our scriptEnding callback +Script.scriptEnding.connect(scriptEnding); From 8755e2d42e05468bd3c782fb13020179b9d2f373 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 3 Jul 2014 13:38:52 -0700 Subject: [PATCH 3/3] CR feedback --- interface/src/renderer/Model.cpp | 7 +++++++ interface/src/renderer/Model.h | 6 +----- libraries/animation/src/AnimationCache.cpp | 18 +++++++++++++++--- libraries/animation/src/AnimationCache.h | 10 ++-------- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 86d742c949..723297f6b4 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1701,6 +1701,13 @@ AnimationHandle::AnimationHandle(Model* model) : _running(false) { } +AnimationDetails AnimationHandle::getAnimationDetails() const { + AnimationDetails details(_role, _url, _fps, _priority, _loop, _hold, + _startAutomatically, _firstFrame, _lastFrame, _running, _frameIndex); + return details; +} + + void AnimationHandle::simulate(float deltaTime) { _frameIndex += deltaTime * _fps; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 538babb541..5e29b869e0 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -357,11 +357,7 @@ public: void setFrameIndex(float frameIndex) { _frameIndex = glm::clamp(_frameIndex, _firstFrame, _lastFrame); } float getFrameIndex() const { return _frameIndex; } - AnimationDetails getAnimationDetails() const { - AnimationDetails details(_role, _url, _fps, _priority, _loop, _hold, - _startAutomatically, _firstFrame, _lastFrame, _running, _frameIndex); - return details; - } + AnimationDetails getAnimationDetails() const; signals: diff --git a/libraries/animation/src/AnimationCache.cpp b/libraries/animation/src/AnimationCache.cpp index ddf27af352..1a68aeb908 100644 --- a/libraries/animation/src/AnimationCache.cpp +++ b/libraries/animation/src/AnimationCache.cpp @@ -103,6 +103,21 @@ void Animation::downloadFinished(QNetworkReply* reply) { } +AnimationDetails::AnimationDetails() : + role(), url(), fps(0.0f), priority(0.0f), loop(false), hold(false), + startAutomatically(false), firstFrame(0.0f), lastFrame(0.0f), running(false), frameIndex(0.0f) +{ +} + +AnimationDetails::AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop, + bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float frameIndex) : + role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold), + startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame), + running(running), frameIndex(frameIndex) +{ +} + + QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& details) { QScriptValue obj = engine->newObject(); obj.setProperty("role", details.role); @@ -116,9 +131,6 @@ QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const Animatio obj.setProperty("lastFrame", details.lastFrame); obj.setProperty("running", details.running); obj.setProperty("frameIndex", details.frameIndex); - - - return obj; } diff --git a/libraries/animation/src/AnimationCache.h b/libraries/animation/src/AnimationCache.h index b4aee5f9e3..4af9f0a83f 100644 --- a/libraries/animation/src/AnimationCache.h +++ b/libraries/animation/src/AnimationCache.h @@ -74,15 +74,9 @@ private: class AnimationDetails { public: - AnimationDetails() : - role(), url(), fps(0.0f), priority(0.0f), loop(false), hold(false), - startAutomatically(false), firstFrame(0.0f), lastFrame(0.0f), running(false), frameIndex(0.0f) { } - + AnimationDetails(); AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop, - bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float frameIndex) : - role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold), - startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame), - running(running), frameIndex(frameIndex) { } + bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float frameIndex); QString role; QUrl url;