From 67a5d7ddc604578f69e5add5210f084b9d28addc Mon Sep 17 00:00:00 2001 From: Janne Kangas Date: Fri, 26 Jul 2019 14:49:10 +0300 Subject: Stop animation when property is controlled by datainput MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disable animation for the target property when datainput value is set. This is to prevent running animations from overriding datainput control, which happens by default in runtime engine due to ordering of scene update sequence. Change-Id: I148d7fd80ad01f4ec5ad1d5ba69ecc74865d27fb Task-id: QT3DS-3896 Reviewed-by: Tomi Korpipää Reviewed-by: Miikka Heikkinen --- src/runtime/Qt3DSAnimationSystem.cpp | 28 ++++++++++++++++++++++++++++ src/runtime/Qt3DSAnimationSystem.h | 2 ++ src/runtime/Qt3DSElementSystem.cpp | 18 ++++++++++++++++++ src/runtime/Qt3DSElementSystem.h | 3 +++ 4 files changed, 51 insertions(+) diff --git a/src/runtime/Qt3DSAnimationSystem.cpp b/src/runtime/Qt3DSAnimationSystem.cpp index b4074f8..199b7f2 100644 --- a/src/runtime/Qt3DSAnimationSystem.cpp +++ b/src/runtime/Qt3DSAnimationSystem.cpp @@ -163,6 +163,11 @@ struct SAnimSystem : public IAnimationSystem NVDataRef m_LoadData; QT3DSI32 m_NextTrackId; QT3DSI32 m_RefCount; + // Keep element handle to track mapping so that we can query if an element has animation tracks, + // and can turn them on/off. Combine element and property id:s to a single 64 bit hash + // so we can utilise nvhash_map and allocators without needing to implement multimap, + // or resort to Qt containers. (Single element can have several animation tracks associated.) + nvhash_map m_ElemPropsToActiveTracks; SAnimSystem(NVFoundationBase &inFoundation) : m_Foundation(inFoundation) @@ -175,6 +180,7 @@ struct SAnimSystem : public IAnimationSystem , m_ActiveSet(inFoundation.getAllocator(), "m_ActiveSet") , m_NextTrackId(1) , m_RefCount(0) + , m_ElemPropsToActiveTracks(inFoundation.getAllocator(), "m_ElemPropsToActiveTracks") { } @@ -223,6 +229,11 @@ struct SAnimSystem : public IAnimationSystem new (theNewTrack) SAnimationTrack(inElement, inserter.first->first, *theIndex, inDynamic); inserter.first->second = theNewTrack; m_LastInsertedTrack = theNewTrack; + + m_ElemPropsToActiveTracks.insert( + eastl::make_pair(static_cast(inElement.m_Handle) << 32 + | static_cast(inPropertyName), + theNewTrack)); ++m_NextTrackId; return inserter.first->first; } @@ -376,6 +387,23 @@ struct SAnimSystem : public IAnimationSystem m_ActiveSet.remove(*theTrack); } } + + QT3DSI32 getActiveTrackForElemProp( + element::SElement *inElement, QT3DSU32 inPropertyHash) override + { + nvhash_map::iterator iter + = m_ElemPropsToActiveTracks.find(static_cast(inElement->m_Handle) << 32 + | static_cast(inPropertyHash)); + if (iter == m_ElemPropsToActiveTracks.end()) + return 0; + + // Only return track if it is actually active + if (!m_ActiveSet.contains(*iter->second)) + return 0; + + return iter->second->m_Id; + } + //============================================================================== /** * Recomputes control point values for Studio animation based off of new start diff --git a/src/runtime/Qt3DSAnimationSystem.h b/src/runtime/Qt3DSAnimationSystem.h index 24542ad..d8ee501 100644 --- a/src/runtime/Qt3DSAnimationSystem.h +++ b/src/runtime/Qt3DSAnimationSystem.h @@ -59,6 +59,8 @@ namespace runtime { virtual void Update() = 0; virtual void SetActive(QT3DSI32 inTrackId, bool inActive) = 0; virtual void UpdateDynamicKey(QT3DSI32 inTrackId) = 0; + virtual QT3DSI32 getActiveTrackForElemProp(element::SElement *inElement, + QT3DSU32 inPropertyName) = 0; static IAnimationSystem &CreateAnimationSystem(NVFoundationBase &inFoundation); }; diff --git a/src/runtime/Qt3DSElementSystem.cpp b/src/runtime/Qt3DSElementSystem.cpp index f77bac5..81a27b1 100644 --- a/src/runtime/Qt3DSElementSystem.cpp +++ b/src/runtime/Qt3DSElementSystem.cpp @@ -43,6 +43,7 @@ #include "foundation/SerializationTypes.h" #include "foundation/IOStreams.h" #include "foundation/Qt3DSIndexableLinkedList.h" +#include "Qt3DSAnimationSystem.h" using namespace qt3ds::runtime::element; using namespace qt3ds; @@ -651,12 +652,29 @@ void SElement::SetAttribute(const Q3DStudio::TAttributeHash inKey, SetAttribute(*existing, inValue); } +void SElement::stopAnimations(QT3DSU32 propHash) +{ + QT3DSI32 animTrack = m_BelongedPresentation->GetAnimationSystem().getActiveTrackForElemProp( + this, propHash); + + if (animTrack != 0) { + qWarning() << "Property animation in element" << m_Name.c_str() + << "stopped due to datainput or setAttribute targeting the same property"; + + m_BelongedPresentation->GetAnimationSystem().SetActive(animTrack, false); + } +} void SElement::SetAttribute(TPropertyDescAndValuePtr inKey, const Q3DStudio::UVariant inValue, bool forceSet) { Q3DStudio::EAttributeType theType = inKey.first.m_Type; Q3DStudio::UVariant *currentValue = inKey.second; QT3DSU32 attHash = inKey.first.GetNameHash(); + + // If there is an active animation for this property, disable it. Otherwise the set value + // gets overwritten immediately as animation update takes place. + // Do this even if the value gets rejected in the code below. + stopAnimations(attHash); if (!forceSet) { switch (theType) { case Q3DStudio::ATTRIBUTETYPE_FLOAT: // Early return diff --git a/src/runtime/Qt3DSElementSystem.h b/src/runtime/Qt3DSElementSystem.h index 6e61a02..15895c0 100644 --- a/src/runtime/Qt3DSElementSystem.h +++ b/src/runtime/Qt3DSElementSystem.h @@ -519,6 +519,9 @@ namespace runtime { child = child->m_Sibling; } } + + // Sets animation on property to inactive. + void stopAnimations(QT3DSU32 propHash); }; struct SGetElementNodeDirtyIndex -- cgit v1.2.3