From f69a8259e13be19c1c1ba308e44335d0e814874d Mon Sep 17 00:00:00 2001
From: Chris Robinson <chris.kcat@gmail.com>
Date: Sun, 7 Apr 2013 13:46:29 -0700
Subject: [PATCH] Update animation source controller targets

---
 apps/openmw/mwrender/animation.cpp   | 14 ++++++++++++++
 components/nifogre/ogrenifloader.cpp |  9 ++++-----
 components/nifogre/ogrenifloader.hpp | 18 ++++++++++++++++++
 3 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp
index 686fbbb84..f3ecbd6a5 100644
--- a/apps/openmw/mwrender/animation.cpp
+++ b/apps/openmw/mwrender/animation.cpp
@@ -78,6 +78,7 @@ void Animation::setAnimationSources(const std::vector<std::string> &names)
         destroyObjectList(sceneMgr, mAnimationSources[i]);
     mAnimationSources.clear();
 
+    Ogre::SkeletonInstance *skelinst = mObjectList.mSkelBase->getSkeleton();
     std::vector<std::string>::const_iterator nameiter;
     for(nameiter = names.begin();nameiter != names.end();nameiter++)
     {
@@ -89,6 +90,19 @@ void Animation::setAnimationSources(const std::vector<std::string> &names)
             mAnimationSources.pop_back();
             continue;
         }
+        const NifOgre::ObjectList &objects = mAnimationSources.back();
+
+        for(size_t i = 0;i < objects.mControllers.size();i++)
+        {
+            NifOgre::NodeTargetValue<Ogre::Real> *dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(objects.mControllers[i].getDestination().getPointer());
+            if(!dstval) continue;
+
+            const Ogre::String &trgtname = dstval->getNode()->getName();
+            if(!skelinst->hasBone(trgtname)) continue;
+
+            Ogre::Bone *bone = skelinst->getBone(trgtname);
+            dstval->setNode(bone);
+        }
 
         Ogre::Entity *ent = mAnimationSources.back().mSkelBase;
         Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(ent->getSkeleton()->getName());
diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp
index d02c0816e..a0aefaccc 100644
--- a/components/nifogre/ogrenifloader.cpp
+++ b/components/nifogre/ogrenifloader.cpp
@@ -108,10 +108,9 @@ public:
 class VisController
 {
 public:
-    class Value : public Ogre::ControllerValue<Ogre::Real>
+    class Value : public NodeTargetValue<Ogre::Real>
     {
     private:
-        Ogre::Bone *mTarget;
         std::vector<Nif::NiVisData::VisData> mData;
 
         virtual bool calculate(Ogre::Real time)
@@ -149,8 +148,8 @@ public:
         }
 
     public:
-        Value(Ogre::Bone *target, const Nif::NiVisData *data)
-          : mTarget(target)
+        Value(Ogre::Node *target, const Nif::NiVisData *data)
+          : NodeTargetValue<Ogre::Real>(target)
           , mData(data->mVis)
         { }
 
@@ -163,7 +162,7 @@ public:
         virtual void setValue(Ogre::Real time)
         {
             bool vis = calculate(time);
-            setVisible(mTarget, vis);
+            setVisible(mNode, vis);
         }
     };
 
diff --git a/components/nifogre/ogrenifloader.hpp b/components/nifogre/ogrenifloader.hpp
index 3a7a22f8b..18bbf0200 100644
--- a/components/nifogre/ogrenifloader.hpp
+++ b/components/nifogre/ogrenifloader.hpp
@@ -74,6 +74,24 @@ public:
                                        const std::string &group="General");
 };
 
+// FIXME: Should be with other general Ogre extensions.
+template<typename T>
+class NodeTargetValue : public Ogre::ControllerValue<T>
+{
+protected:
+    Ogre::Node *mNode;
+
+public:
+    NodeTargetValue(Ogre::Node *target) : mNode(target)
+    { }
+
+    void setNode(Ogre::Node *target)
+    { mNode = target; }
+    Ogre::Node *getNode() const
+    { return mNode; }
+};
+typedef Ogre::SharedPtr<NodeTargetValue<Ogre::Real> > NodeTargetValueRealPtr;
+
 }
 
 namespace std