- fbx: resolve target node for node animations.

pull/14/head
Alexander Gessler 2012-07-21 17:12:04 +02:00
parent ae3007b42b
commit 378bc93593
3 changed files with 83 additions and 5 deletions

View File

@ -97,6 +97,7 @@ AnimationCurve::~AnimationCurve()
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc) AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc)
: Object(id, element, name) : Object(id, element, name)
, target() , target()
{
{ {
// resolve attached animation curves // resolve attached animation curves
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID()); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
@ -120,8 +121,48 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
continue; continue;
} }
curves[con->PropertyName()] = anim;
}
}{
// find target node
const std::vector<const Connection*>& 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<const Model*>(ob);
if(!target) {
continue;
}
prop = con->PropertyName(); prop = con->PropertyName();
curves[prop] = anim; break;
}
}
if(!target) {
DOMError("failed to resolve target model for animation node",&element);
} }
} }

View File

@ -390,6 +390,7 @@ LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
: doc(doc) : doc(doc)
, element(element) , element(element)
, id(id) , id(id)
, being_constructed()
{ {
} }
@ -425,7 +426,8 @@ const Object* LazyObject::Get()
DOMError(err,&element); DOMError(err,&element);
} }
// XXX prevent recursive calls // prevent recursive calls
being_constructed = true;
// this needs to be relatively fast since it happens a lot, // this needs to be relatively fast since it happens a lot,
// so avoid constructing strings all the time. // 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); //DOMError("failed to convert element to DOM object, class: " + classtag + ", name: " + name,&element);
} }
being_constructed = false;
return object.get(); return object.get();
} }
@ -697,6 +700,7 @@ void Document::ReadConnections()
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const std::vector<const AnimationStack*>& Document::AnimationStacks() const const std::vector<const AnimationStack*>& Document::AnimationStacks() const
{ {
@ -718,6 +722,7 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
return animationStacksResolved; return animationStacksResolved;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
LazyObject* Document::GetObject(uint64_t id) const 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; return it == objects.end() ? NULL : (*it).second;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
{ {
@ -762,6 +768,7 @@ std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(ui
return temp; // NRVO should handle this return temp; // NRVO should handle this
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, const Document& doc) Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, const Document& doc)
: insertionOrder(insertionOrder) : 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 const Object* Connection::SourceObject() const
{ {
@ -791,6 +816,7 @@ const Object* Connection::SourceObject() const
return lazy->Get(); return lazy->Get();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const Object* Connection::DestinationObject() const const Object* Connection::DestinationObject() const
{ {

View File

@ -85,6 +85,10 @@ public:
return id; return id;
} }
bool IsBeingConstructed() const {
return being_constructed;
}
private: private:
const Document& doc; const Document& doc;
@ -92,6 +96,7 @@ private:
boost::scoped_ptr<const Object> object; boost::scoped_ptr<const Object> object;
const uint64_t id; const uint64_t id;
bool being_constructed;
}; };
@ -469,11 +474,12 @@ public:
return curves; return curves;
} }
/** Model instance the curve is assigned to, this is always non-NULL */
const Model* TargetNode() const { const Model* TargetNode() const {
return target; return target;
} }
/** Property of TargetNode() that is being animated*/
const std::string& TargetProperty() const { const std::string& TargetProperty() const {
return prop; return prop;
} }
@ -562,8 +568,13 @@ public:
const Object* SourceObject() const; const Object* SourceObject() const;
const Object* DestinationObject() const; const Object* DestinationObject() const;
// return the name of the property the connection is attached to. // these, however, are always guaranteed to be valid
// this is an empty string for object to object (OO) connections. 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 { const std::string& PropertyName() const {
return prop; return prop;
} }