]> git.tdb.fi Git - libs/gl.git/blobdiff - source/animation.cpp
Refactor the Animation reference out of TimedKeyFrame
[libs/gl.git] / source / animation.cpp
index 1e2dda900fafc0d580bf84cb648772ccf7747ac3..2f78d1eafad574b4d1c060a8209d0527309cc393 100644 (file)
@@ -42,16 +42,33 @@ const string &Animation::get_uniform_name(unsigned i) const
 }
 
 void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf)
+{
+       RefPtr<const KeyFrame> kfr(&kf);
+       kfr.keep();
+       add_keyframe(t, kfr);
+}
+
+void Animation::add_keyframe(const Time::TimeDelta &t, const RefPtr<const KeyFrame> &kf)
 {
        if(!keyframes.empty() && t<keyframes.back().time)
                throw invalid_argument("Animation::add_keyframe");
 
-       TimedKeyFrame tkf(*this);
+       bool realloc = (keyframes.size()>=keyframes.capacity());
+
+       keyframes.push_back(TimedKeyFrame());
+       TimedKeyFrame &tkf = keyframes.back();
        tkf.time = t;
-       tkf.keyframe = &kf;
-       tkf.keyframe.keep();
+       tkf.keyframe = kf;
+
+       if(realloc)
+       {
+               for(unsigned i=1; i<keyframes.size(); ++i)
+                       keyframes[i].prev = &keyframes[i-1];
+       }
+       else if(keyframes.size()>1)
+               tkf.prev = &tkf-1;
+
        prepare_keyframe(tkf);
-       keyframes.push_back(tkf);
 }
 
 void Animation::set_looping(bool l)
@@ -61,8 +78,6 @@ void Animation::set_looping(bool l)
 
 void Animation::prepare_keyframe(TimedKeyFrame &tkf)
 {
-       tkf.prev = (keyframes.empty() ? 0 : &keyframes.back());
-
        const KeyFrame::UniformMap &kf_uniforms = tkf.keyframe->get_uniforms();
        for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
        {
@@ -79,7 +94,7 @@ void Animation::prepare_keyframe(TimedKeyFrame &tkf)
                        uniforms.push_back(UniformInfo(i->first, i->second.size));
        }
 
-       tkf.prepare();
+       tkf.prepare(*this);
 }
 
 
@@ -170,12 +185,11 @@ Matrix Animation::MatrixInterpolation::get(float t) const
 }
 
 
-Animation::TimedKeyFrame::TimedKeyFrame(const Animation &a):
-       animation(a),
+Animation::TimedKeyFrame::TimedKeyFrame():
        prev(0)
 { }
 
-void Animation::TimedKeyFrame::prepare()
+void Animation::TimedKeyFrame::prepare(const Animation &animation)
 {
        const KeyFrame::UniformMap &kf_uniforms = keyframe->get_uniforms();
        for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
@@ -218,8 +232,8 @@ Animation::UniformInfo::UniformInfo(const string &n, unsigned s):
 
 
 Animation::Iterator::Iterator(const Animation &a):
-       animation(a),
-       iter(animation.keyframes.begin()),
+       animation(&a),
+       iter(animation->keyframes.begin()),
        end(false)
 { }
 
@@ -228,12 +242,12 @@ Animation::Iterator &Animation::Iterator::operator+=(const Time::TimeDelta &t)
        time_since_keyframe += t;
        while(time_since_keyframe>iter->delta_t)
        {
-               KeyFrameList::const_iterator next = iter;
+               vector<TimedKeyFrame>::const_iterator next = iter;
                ++next;
-               if(next==animation.keyframes.end())
+               if(next==animation->keyframes.end())
                {
-                       if(animation.looping)
-                               next = animation.keyframes.begin();
+                       if(animation->looping)
+                               next = animation->keyframes.begin();
                        else
                        {
                                end = true;
@@ -264,10 +278,10 @@ KeyFrame::AnimatedUniform Animation::Iterator::get_uniform(unsigned i) const
                if(iter->uniforms.size()>i)
                        return iter->uniforms[i];
                else
-                       return KeyFrame::AnimatedUniform(animation.uniforms[i].size, 0.0f);
+                       return KeyFrame::AnimatedUniform(animation->uniforms[i].size, 0.0f);
        }
 
-       unsigned size = animation.uniforms[i].size;
+       unsigned size = animation->uniforms[i].size;
        float t = time_since_keyframe/iter->delta_t;
        KeyFrame::AnimatedUniform result(size, 0.0f);
        for(unsigned j=0; j<size; ++j)
@@ -277,9 +291,9 @@ KeyFrame::AnimatedUniform Animation::Iterator::get_uniform(unsigned i) const
 
 Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
 {
-       if(!animation.armature)
+       if(!animation->armature)
                throw invalid_operation("Animation::Iterator::get_pose_matrix");
-       if(link>animation.armature->get_max_link_index())
+       if(link>animation->armature->get_max_link_index())
                throw out_of_range("Animation::Iterator::get_pose_matrix");
 
        if(!iter->prev)
@@ -293,7 +307,7 @@ Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
        // We must redo the base point correction since interpolation throws if off
        // XXX This should probably be done on local matrices
        Matrix result = iter->pose_matrices[link].get(time_since_keyframe/iter->delta_t);
-       const Vector3 &base = animation.armature->get_link(link).get_base();
+       const Vector3 &base = animation->armature->get_link(link).get_base();
        Vector3 new_base = result*base;
        result = Matrix::translation(base-new_base)*result;
        return result;
@@ -334,11 +348,7 @@ void Animation::Loader::keyframe_inline()
        else
                load_sub(*kf);
 
-       TimedKeyFrame tkf(obj);
-       tkf.time = current_time;
-       tkf.keyframe = kf;
-       obj.prepare_keyframe(tkf);
-       obj.keyframes.push_back(tkf);
+       obj.add_keyframe(current_time, kf);
 }
 
 void Animation::Loader::interval(float t)