]> git.tdb.fi Git - libs/gl.git/commitdiff
Fix a stale pointer issue with Animation
authorMikko Rasa <tdb@tdb.fi>
Wed, 2 May 2018 19:22:23 +0000 (22:22 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 2 May 2018 19:22:23 +0000 (22:22 +0300)
Now that keyframe information is stored in a vector it's no longer
guaranteed that pointers to them stay valid after push_back.  Re-link
all TimedKeyFrames if the vector gets reallocated.

source/animation.cpp
source/animation.h

index 61c21ce8611c88f40694efedea9a35f2d687a65e..ccd37bca5e0daec3d782cfd8504827efca53b922 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(*this));
+       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)
        {
@@ -334,11 +349,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)
index 929cb13f497318c3a91492cc1cf18d36584f267e..a5f77b46c4eb185a733a4f65355f4c67526e1545 100644 (file)
@@ -120,6 +120,7 @@ public:
 
        void add_keyframe(const Time::TimeDelta &, const KeyFrame &);
 private:
+       void add_keyframe(const Time::TimeDelta &, const RefPtr<const KeyFrame> &);
        void prepare_keyframe(TimedKeyFrame &);
 
 public: