From 378bc93593a658880a3d135eb7d205cf9a65ff54 Mon Sep 17 00:00:00 2001 From: Alexander Gessler Date: Sat, 21 Jul 2012 17:12:04 +0200 Subject: [PATCH] - fbx: resolve target node for node animations. --- code/FBXAnimation.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++- code/FBXDocument.cpp | 28 +++++++++++++++++++++++++++- code/FBXDocument.h | 17 ++++++++++++++--- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/code/FBXAnimation.cpp b/code/FBXAnimation.cpp index 8d553b053..deb13ac50 100644 --- a/code/FBXAnimation.cpp +++ b/code/FBXAnimation.cpp @@ -98,6 +98,7 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons : Object(id, element, name) , target() { + { // resolve attached animation curves const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID()); @@ -119,9 +120,49 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element); continue; } + + curves[con->PropertyName()] = anim; + } + + }{ + + // find target node + const std::vector& conns = doc.GetConnectionsBySourceSequenced(ID()); + + BOOST_FOREACH(const Connection* con, conns) { + + // link should go for a property + if (con->PropertyName().length()) { + continue; + } + + // note: the implicit rule in all DOM classes is to always resolve + // from destination to source (since the FBX object hierarchy is, + // with very few exceptions, a DAG, this avoids cycles). Since + // it goes the other way round, we have to cope with the case + // that the destination is not fully constructed yet. + LazyObject& lob = con->LazyDestinationObject(); + if(lob.IsBeingConstructed()) { + continue; + } + + const Object* ob = lob.Get(); + if(!ob) { + DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element); + continue; + } + + target = dynamic_cast(ob); + if(!target) { + continue; + } prop = con->PropertyName(); - curves[prop] = anim; + break; + } + } + if(!target) { + DOMError("failed to resolve target model for animation node",&element); } } diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index 3562ebf9c..8326d921e 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -390,6 +390,7 @@ LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) : doc(doc) , element(element) , id(id) +, being_constructed() { } @@ -425,7 +426,8 @@ const Object* LazyObject::Get() DOMError(err,&element); } - // XXX prevent recursive calls + // prevent recursive calls + being_constructed = true; // this needs to be relatively fast since it happens a lot, // so avoid constructing strings all the time. @@ -462,6 +464,7 @@ const Object* LazyObject::Get() //DOMError("failed to convert element to DOM object, class: " + classtag + ", name: " + name,&element); } + being_constructed = false; return object.get(); } @@ -697,6 +700,7 @@ void Document::ReadConnections() } } + // ------------------------------------------------------------------------------------------------ const std::vector& Document::AnimationStacks() const { @@ -718,6 +722,7 @@ const std::vector& Document::AnimationStacks() const return animationStacksResolved; } + // ------------------------------------------------------------------------------------------------ LazyObject* Document::GetObject(uint64_t id) const { @@ -725,6 +730,7 @@ LazyObject* Document::GetObject(uint64_t id) const return it == objects.end() ? NULL : (*it).second; } + // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsBySourceSequenced(uint64_t source) const { @@ -762,6 +768,7 @@ std::vector Document::GetConnectionsByDestinationSequenced(ui return temp; // NRVO should handle this } + // ------------------------------------------------------------------------------------------------ Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, const Document& doc) : insertionOrder(insertionOrder) @@ -783,6 +790,24 @@ Connection::~Connection() } +// ------------------------------------------------------------------------------------------------ +LazyObject& Connection::LazySourceObject() const +{ + LazyObject* const lazy = doc.GetObject(src); + ai_assert(lazy); + return *lazy; +} + + +// ------------------------------------------------------------------------------------------------ +LazyObject& Connection::LazyDestinationObject() const +{ + LazyObject* const lazy = doc.GetObject(dest); + ai_assert(lazy); + return *lazy; +} + + // ------------------------------------------------------------------------------------------------ const Object* Connection::SourceObject() const { @@ -791,6 +816,7 @@ const Object* Connection::SourceObject() const return lazy->Get(); } + // ------------------------------------------------------------------------------------------------ const Object* Connection::DestinationObject() const { diff --git a/code/FBXDocument.h b/code/FBXDocument.h index 179a02c1e..a2cf8a811 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -85,6 +85,10 @@ public: return id; } + bool IsBeingConstructed() const { + return being_constructed; + } + private: const Document& doc; @@ -92,6 +96,7 @@ private: boost::scoped_ptr object; const uint64_t id; + bool being_constructed; }; @@ -469,11 +474,12 @@ public: return curves; } - + /** Model instance the curve is assigned to, this is always non-NULL */ const Model* TargetNode() const { return target; } + /** Property of TargetNode() that is being animated*/ const std::string& TargetProperty() const { return prop; } @@ -562,8 +568,13 @@ public: const Object* SourceObject() const; const Object* DestinationObject() const; - // return the name of the property the connection is attached to. - // this is an empty string for object to object (OO) connections. + // these, however, are always guaranteed to be valid + LazyObject& LazySourceObject() const; + LazyObject& LazyDestinationObject() const; + + + /** return the name of the property the connection is attached to. + * this is an empty string for object to object (OO) connections. */ const std::string& PropertyName() const { return prop; }