diff --git a/code/FBXAnimation.cpp b/code/FBXAnimation.cpp index 5d3b60458..ccf1d82f4 100644 --- a/code/FBXAnimation.cpp +++ b/code/FBXAnimation.cpp @@ -98,41 +98,14 @@ 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, + const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/) : Object(id, element, name) , target() +, doc(doc) { const Scope& sc = GetRequiredScope(element); - props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false); - - { - // resolve attached animation curves - const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve"); - - BOOST_FOREACH(const Connection* con, conns) { - - // link should go for a property - if (!con->PropertyName().length()) { - continue; - } - - const Object* const ob = con->SourceObject(); - if(!ob) { - DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element); - continue; - } - - const AnimationCurve* const anim = dynamic_cast(ob); - if(!anim) { - DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element); - continue; - } - - curves[con->PropertyName()] = anim; - } - - }{ - + // find target node const char* whitelist[] = {"Model","NodeAttribute"}; const std::vector& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2); @@ -144,6 +117,21 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons continue; } + if(target_prop_whitelist) { + const char* const s = con->PropertyName().c_str(); + bool ok = false; + for (size_t i = 0; i < whitelist_size; ++i) { + if (!strcmp(s, target_prop_whitelist[i])) { + ok = true; + break; + } + } + + if (!ok) { + throw std::range_error("AnimationCurveNode target property is not in whitelist"); + } + } + const Object* const ob = con->DestinationObject(); if(!ob) { DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element); @@ -160,10 +148,12 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons prop = con->PropertyName(); break; } - } + if(!target) { DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element); } + + props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false); } @@ -174,14 +164,64 @@ AnimationCurveNode::~AnimationCurveNode() } +// ------------------------------------------------------------------------------------------------ +const AnimationCurveMap& AnimationCurveNode::Curves() const +{ + if(curves.empty()) { + // resolve attached animation curves + const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve"); + + BOOST_FOREACH(const Connection* con, conns) { + + // link should go for a property + if (!con->PropertyName().length()) { + continue; + } + + const Object* const ob = con->SourceObject(); + if(!ob) { + DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element); + continue; + } + + const AnimationCurve* const anim = dynamic_cast(ob); + if(!anim) { + DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element); + continue; + } + + curves[con->PropertyName()] = anim; + } + } + + return curves; +} + + // ------------------------------------------------------------------------------------------------ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc) : Object(id, element, name) +, doc(doc) { const Scope& sc = GetRequiredScope(element); // note: the props table here bears little importance and is usually absent props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true); +} + + +// ------------------------------------------------------------------------------------------------ +AnimationLayer::~AnimationLayer() +{ + +} + + +// ------------------------------------------------------------------------------------------------ +AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/, + size_t whitelist_size /*= 0*/) const +{ + AnimationCurveNodeList nodes; // resolve attached animation nodes const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode"); @@ -205,15 +245,24 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::s DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element); continue; } + + if(target_prop_whitelist) { + const char* s = anim->TargetProperty().c_str(); + bool ok = false; + for (size_t i = 0; i < whitelist_size; ++i) { + if (!strcmp(s, target_prop_whitelist[i])) { + ok = true; + break; + } + } + if(!ok) { + continue; + } + } nodes.push_back(anim); } -} - - -// ------------------------------------------------------------------------------------------------ -AnimationLayer::~AnimationLayer() -{ + return nodes; // pray for NRVO } // ------------------------------------------------------------------------------------------------ diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 190f4a7ff..be7902efe 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -1745,11 +1745,17 @@ private: // reverse mapping from curves to layers, much faster than querying // the FBX DOM for it. LayerMap layer_map; + + const char* prop_whitelist[] = { + "Lcl Scaling", + "Lcl Rotation", + "Lcl Translation" + }; BOOST_FOREACH(const AnimationLayer* layer, layers) { ai_assert(layer); - const AnimationCurveNodeList& nodes = layer->Nodes(); + const AnimationCurveNodeList& nodes = layer->Nodes(prop_whitelist, 3); BOOST_FOREACH(const AnimationCurveNode* node, nodes) { ai_assert(node); diff --git a/code/FBXDocument.h b/code/FBXDocument.h index 2a0e59673..5b1b49307 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -845,7 +845,12 @@ class AnimationCurveNode : public Object { public: - AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc); + /* the optional whitelist specifies a list of property names for which the caller + wants animations for. If the curve node does not match one of these, std::range_error + will be thrown. */ + AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc, + const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0); + ~AnimationCurveNode(); public: @@ -856,9 +861,7 @@ public: } - const AnimationCurveMap Curves() const { - return curves; - } + const AnimationCurveMap& Curves() const; /** Object the curve is assigned to, this can be NULL if the * target object has no DOM representation or could not @@ -884,9 +887,10 @@ private: const Object* target; boost::shared_ptr props; - AnimationCurveMap curves; + mutable AnimationCurveMap curves; std::string prop; + const Document& doc; }; typedef std::vector AnimationCurveNodeList; @@ -897,6 +901,7 @@ class AnimationLayer : public Object { public: + AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc); ~AnimationLayer(); @@ -907,14 +912,15 @@ public: return *props.get(); } - const AnimationCurveNodeList& Nodes() const { - return nodes; - } + /* the optional whitelist specifies a list of property names for which the caller + wants animations for. Curves not matching this list will not be added to the + animation layer. */ + AnimationCurveNodeList Nodes(const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0) const; private: boost::shared_ptr props; - AnimationCurveNodeList nodes; + const Document& doc; };