1 /* === S Y N F I G ========================================================= */
2 /*! \file valuenode_animated.cpp
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
10 ** This package is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU General Public License as
12 ** published by the Free Software Foundation; either version 2 of
13 ** the License, or (at your option) any later version.
15 ** This package is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** General Public License for more details.
21 /* ========================================================================= */
23 /* === H E A D E R S ======================================================= */
39 #include <ETL/hermite>
49 #include "valuenode_animated.h"
50 #include "valuenode_const.h"
51 #include "exception.h"
56 /* === U S I N G =========================================================== */
60 using namespace synfig;
62 /* === M A C R O S ========================================================= */
64 // Fast binary search implementation
66 template<typename I, typename T> inline I
67 binary_find(I begin, I end, const T& value)
69 I iter(begin+(end-begin)/2);
71 while(end-begin>1 && !(*iter==value))
73 ((*iter<value)?begin:end) = iter;
75 iter = begin+(end-begin)/2;
82 template<typename T> String tangent_info(T a, T b, T v)
87 String tangent_info(Vector a, Vector b, Vector v)
90 return strprintf("(should be zero) T=[%f,%f], Pp=[%f,%f], Pn=[%f,%f]",v[0],v[1],a[0],a[1],b[0],b[1]);
92 return strprintf("(should NOT be zero) T=[%f,%f], Pp=[%f,%f], Pn=[%f,%f]",v[0],v[1],a[0],a[1],b[0],b[1]);
97 struct subtractor : public std::binary_function<T, T, T>
99 T operator()(const T &a,const T &b)const
106 struct subtractor<Angle> : public std::binary_function<Angle, Angle, Angle>
108 Angle operator()(const Angle &a,const Angle &b)const
115 struct magnitude : public std::unary_function<float, T>
117 float operator()(const T &a)const
124 struct magnitude<Angle> : public std::unary_function<float, Angle>
126 float operator()(const Angle &a)const
128 return abs(Angle::rad(a).get());
133 struct magnitude<Vector> : public std::unary_function<float, Vector>
135 float operator()(const Vector &a)const
142 struct magnitude<Color> : public std::unary_function<float, Color>
144 float operator()(const Color &a)const
146 return abs(a.get_y());
157 bool operator()()const
164 struct is_angle_type<Angle>
166 bool operator()()const
172 /* === G L O B A L S ======================================================= */
174 /* === C L A S S E S ======================================================= */
177 class _Hermite : public synfig::ValueNode_Animated
180 typedef T value_type;
181 affine_combo<value_type,Time> affine_combo_func;
182 subtractor<value_type> subtract_func;
183 magnitude<value_type> magnitude_func;
184 is_angle_type<value_type> is_angle;
188 is_angle_type<value_type> is_angle;
189 subtractor<value_type> subtract_func;
191 mutable hermite<Time,Time> first;
192 mutable hermite<value_type,Time> second;
193 WaypointList::iterator start;
194 WaypointList::iterator end;
196 value_type resolve(const Time &t)const
198 bool start_static(start->is_static());
199 bool end_static(end->is_static());
201 if(!start_static || !end_static)
204 second.p1()=start->get_value(t).get(value_type());
205 if(start->get_after()==INTERPOLATION_CONSTANT || end->get_before()==INTERPOLATION_CONSTANT)
208 second.p2()=end->get_value(t).get(value_type());
210 // At the moment, the only type of non-constant interpolation
211 // that we support is linear.
213 second.t2()=subtract_func(second.p2(),second.p1());
218 return second(first(t));
226 hermite<value_type,Time>
231 curve_list_type curve_list;
233 // Bounds of this curve
237 ValueNode* clone(const GUID& deriv_guid)const
239 { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
240 _Hermite<T>* ret(new _Hermite<T>());
241 ret->set_guid(get_guid()^deriv_guid);
242 for(WaypointList::const_iterator iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
243 ret->add(iter->clone(deriv_guid));
249 set_type(ValueBase(value_type()).get_type());
252 virtual WaypointList::iterator new_waypoint(Time t, ValueBase value)
254 // Make sure we are getting data of the correct type
255 //if(data.type!=type)
256 // return waypoint_list_type::iterator();
258 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
259 Waypoint waypoint(value,t);
260 waypoint.set_parent_value_node(this);
262 waypoint_list_.push_back(waypoint);
263 WaypointList::iterator ret=waypoint_list_.end();
268 ret->set_before(INTERPOLATION_LINEAR);
269 ret->set_after(INTERPOLATION_LINEAR);
277 virtual WaypointList::iterator new_waypoint(Time t, ValueNode::Handle value_node)
279 // Make sure we are getting data of the correct type
280 //if(data.type!=type)
281 // return waypoint_list_type::iterator();
282 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
284 Waypoint waypoint(value_node,t);
285 waypoint.set_parent_value_node(this);
287 waypoint_list_.push_back(waypoint);
288 WaypointList::iterator ret=waypoint_list_.end();
293 ret->set_before(INTERPOLATION_LINEAR);
294 ret->set_after(INTERPOLATION_LINEAR);
302 virtual void on_changed()
304 ValueNode_Animated::on_changed();
306 if(waypoint_list_.size()<=1)
308 std::sort(waypoint_list_.begin(),waypoint_list_.end());
309 //waypoint_list_.sort();
311 r=waypoint_list_.front().get_time();
312 s=waypoint_list_.back().get_time();
316 WaypointList::iterator prev,iter,next=waypoint_list_.begin();
319 for(iter=next++;iter!=waypoint_list_.end() && next!=waypoint_list_.end();prev=iter,iter=next++,i++)
321 typename curve_list_type::value_type curve;
322 WaypointList::iterator after_next(next);
328 // Set up the positions
329 curve.first.set_rs(iter->get_time(), next->get_time());
330 curve.second.set_rs(iter->get_time(), next->get_time());
332 Waypoint::Interpolation iter_get_after(iter->get_after());
333 Waypoint::Interpolation next_get_after(next->get_after());
334 Waypoint::Interpolation iter_get_before(iter->get_before());
335 Waypoint::Interpolation next_get_before(next->get_before());
339 if(iter_get_after==INTERPOLATION_TCB)
340 iter_get_after=INTERPOLATION_LINEAR;
341 if(next_get_after==INTERPOLATION_TCB)
342 next_get_after=INTERPOLATION_LINEAR;
343 if(iter_get_before==INTERPOLATION_TCB)
344 iter_get_before=INTERPOLATION_LINEAR;
345 if(next_get_before==INTERPOLATION_TCB)
346 next_get_before=INTERPOLATION_LINEAR;
349 if(iter->is_static() && next->is_static())
351 curve.second.p1()=iter->get_value().get(T());
352 curve.second.p2()=next->get_value().get(T());
353 if(iter_get_after==INTERPOLATION_CONSTANT || next_get_before==INTERPOLATION_CONSTANT)
355 // Sections must be constant on both sides.
356 // NOTE: this is commented out because of some
357 // user interface issues. Namely, if a section is
358 // constant and the user turns off the constant on
359 // one waypoint, this will end up turning it back on.
361 //iter->get_after()=next->get_before()=INTERPOLATION_CONSTANT;
363 curve.second.p2()=iter->get_value().get(T());
365 curve.second.t2()=subtract_func(curve.second.p1(),curve.second.p2());
369 if(iter_get_after==INTERPOLATION_TCB && iter!=waypoint_list_.begin() && !is_angle())
371 if(iter->get_before()!=INTERPOLATION_TCB && !curve_list.empty())
373 curve.second.t1()=curve_list.back().second.t2();
378 const Real& t(iter->get_tension()); // Tension
379 const Real& c(iter->get_continuity()); // Continuity
380 const Real& b(iter->get_bias()); // Bias
382 // The folloing line works where the previous line fails.
383 value_type Pp; Pp=curve_list.back().second.p1(); // P_{i-1}
385 const value_type& Pc(curve.second.p1()); // P_i
386 const value_type& Pn(curve.second.p2()); // P_{i+1}
389 value_type vect(static_cast<value_type>(subtract_func(Pc,Pp)*(((1.0-t)*(1.0+c)*(1.0+b))/2.0)+(Pn-Pc)*(((1.0-t)*(1.0-c)*(1.0-b))/2.0)));
392 //value_type vect=(value_type)((Pn-Pp)*(1.0-t));
395 //value_type vect=(value_type)(Pn-Pc);
398 //synfig::info("%d:t1: %s",i,tangent_info(Pp,Pn,vect).c_str());
401 //vect=value_type(vect*(curve.second.get_dt()*2.0)/(curve.second.get_dt()+curve_list.back().second.get_dt()));
402 //vect=value_type(vect*(curve.second.get_dt())/(curve_list.back().second.get_dt()));
404 curve.second.t1()=vect;
408 iter_get_after==INTERPOLATION_LINEAR || iter_get_after==INTERPOLATION_HALT ||
409 (iter_get_after==INTERPOLATION_TCB && iter==waypoint_list_.begin()))
411 curve.second.t1()=subtract_func(curve.second.p2(),curve.second.p1());
414 if(iter_get_before==INTERPOLATION_TCB && iter->get_after()!=INTERPOLATION_TCB && !curve_list.empty())
416 curve_list.back().second.t2()=curve.second.t1();
417 curve_list.back().second.sync();
421 if(next_get_before==INTERPOLATION_TCB && after_next!=waypoint_list_.end() && !is_angle())
423 const Real &t(next->get_tension()); // Tension
424 const Real &c(next->get_continuity()); // Continuity
425 const Real &b(next->get_bias()); // Bias
426 const value_type &Pp(curve.second.p1()); // P_{i-1}
427 const value_type &Pc(curve.second.p2()); // P_i
428 value_type Pn; Pn=after_next->get_value().get(T()); // P_{i+1}
431 value_type vect(static_cast<value_type>(subtract_func(Pc,Pp) * (((1.0-t)*(1.0-c)*(1.0+b))/2.0) +
432 (Pn-Pc) * (((1.0-t)*(1.0+c)*(1.0-b))/2.0)));
435 //value_type vect((value_type)((Pn-Pp)*(1.0-t)));
438 //value_type vect=(value_type)(Pc-Pp);
441 //synfig::info("%d:t2: %s",i,tangent_info(Pp,Pn,vect).c_str());
444 //vect=value_type(vect*(curve.second.get_dt()*2.0)/(curve.second.get_dt()+(after_next->get_time()-next->get_time())));
445 //vect=value_type(vect*(curve.second.get_dt()/((after_next->get_time()-next->get_time()))));
447 curve.second.t2()=vect;
450 next_get_before==INTERPOLATION_LINEAR || next_get_before==INTERPOLATION_HALT ||
451 (next_get_before==INTERPOLATION_TCB && after_next==waypoint_list_.end()))
453 curve.second.t2()=subtract_func(curve.second.p2(),curve.second.p1());
457 const float timeadjust(0.5);
459 if(iter_get_after==INTERPOLATION_HALT)
460 curve.second.t1()*=0;
461 // if this isn't the first curve
462 else if(iter_get_after != INTERPOLATION_LINEAR && !curve_list.empty())
463 // adjust it for the curve that came before it
465 // (time span of this curve) * 1.5
466 // -----------------------------------------------------------------
467 // ((time span of this curve) * 0.5) + (time span of previous curve)
468 (curve.second.get_dt()*(timeadjust+1)) /
469 (curve.second.get_dt()*timeadjust + curve_list.back().second.get_dt());
471 if(next_get_before==INTERPOLATION_HALT)
472 curve.second.t2()*=0;
473 // if this isn't the last curve
474 else if(next_get_before != INTERPOLATION_LINEAR && after_next!=waypoint_list_.end())
475 // adjust it for the curve that came after it
477 // (time span of this curve) * 1.5
478 // -------------------------------------------------------------
479 // ((time span of this curve) * 0.5) + (time span of next curve)
480 (curve.second.get_dt()*(timeadjust+1)) /
481 (curve.second.get_dt()*timeadjust+(after_next->get_time()-next->get_time()));
485 // Set up the time to the default stuff
486 curve.first.set_rs(iter->get_time(), next->get_time());
487 curve.first.p1()=iter->get_time();
488 curve.first.p2()=next->get_time();
489 curve.first.t1()=(curve.first.p2()-curve.first.p1())*(1.0f-iter->get_time_tension());
490 curve.first.t2()=(curve.first.p2()-curve.first.p1())*(1.0f-next->get_time_tension());
496 curve_list.push_back(curve);
500 virtual ValueBase operator()(Time t)const
502 if(waypoint_list_.empty())
503 return value_type(); //! \todo Perhaps we should throw something here?
504 if(waypoint_list_.size()==1)
505 return waypoint_list_.front().get_value(t);
507 return waypoint_list_.front().get_value(t);
509 return waypoint_list_.back().get_value(t);
511 typename curve_list_type::const_iterator iter;
513 // This next line will set iter to the
514 // correct iterator for the given time.
515 for(iter=curve_list.begin();iter<curve_list.end() && t>=iter->first.get_s();++iter)
517 if(iter==curve_list.end())
518 return waypoint_list_.back().get_value(t);
519 return iter->resolve(t);
525 class _Constant : public synfig::ValueNode_Animated
528 typedef T value_type;
532 // Bounds of this curve
536 ValueNode* clone(const GUID& deriv_guid)const
538 { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
539 _Constant<T>* ret(new _Constant<T>());
540 ret->set_guid(get_guid()^deriv_guid);
541 for(WaypointList::const_iterator iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
542 ret->add(iter->clone(deriv_guid));
548 set_type(ValueBase(value_type()).get_type());
551 virtual WaypointList::iterator new_waypoint(Time t, ValueBase value)
553 // Make sure we are getting data of the correct type
554 //if(data.type!=type)
555 // return waypoint_list_type::iterator();
556 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
558 Waypoint waypoint(value,t);
559 waypoint.set_parent_value_node(this);
561 waypoint_list_.push_back(waypoint);
562 WaypointList::iterator ret=waypoint_list_.end();
569 virtual WaypointList::iterator new_waypoint(Time t, ValueNode::Handle value_node)
571 // Make sure we are getting data of the correct type
572 //if(data.type!=type)
573 // return waypoint_list_type::iterator();
574 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
576 Waypoint waypoint(value_node,t);
577 waypoint.set_parent_value_node(this);
579 waypoint_list_.push_back(waypoint);
580 WaypointList::iterator ret=waypoint_list_.end();
587 virtual void on_changed()
589 ValueNode_Animated::on_changed();
591 if(waypoint_list_.size()<=1)
593 std::sort(waypoint_list_.begin(),waypoint_list_.end());
594 //waypoint_list_.sort();
595 r=waypoint_list_.front().get_time();
596 s=waypoint_list_.back().get_time();
600 virtual ValueBase operator()(Time t)const
602 if(waypoint_list_.size()==1)
603 return waypoint_list_.front().get_value(t);
604 if(waypoint_list_.empty())
607 return waypoint_list_.front().get_value(t);
609 return waypoint_list_.back().get_value(t);
611 typename WaypointList::const_iterator iter;
612 typename WaypointList::const_iterator next;
614 // This next line will set iter to the
615 // correct iterator for the given time.
616 for(next=waypoint_list_.begin(),iter=next++;next!=waypoint_list_.end() && t>=next->get_time();iter=next++)
619 return iter->get_value(t);
623 class _AnimBool : public synfig::ValueNode_Animated
626 typedef bool value_type;
630 // Bounds of this curve
634 ValueNode* clone(const GUID& deriv_guid)const
636 { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
637 _AnimBool* ret(new _AnimBool());
638 ret->set_guid(get_guid()^deriv_guid);
639 for(WaypointList::const_iterator iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
640 ret->add(iter->clone(deriv_guid));
646 set_type(ValueBase(value_type()).get_type());
649 virtual WaypointList::iterator new_waypoint(Time t, ValueBase value)
651 // Make sure we are getting data of the correct type
652 //if(data.type!=type)
653 // return waypoint_list_type::iterator();
654 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
657 Waypoint waypoint(value,t);
658 waypoint.set_parent_value_node(this);
660 waypoint_list_.push_back(waypoint);
661 WaypointList::iterator ret=waypoint_list_.end();
668 virtual WaypointList::iterator new_waypoint(Time t, ValueNode::Handle value_node)
670 // Make sure we are getting data of the correct type
671 //if(data.type!=type)
672 // return waypoint_list_type::iterator();
673 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
675 Waypoint waypoint(value_node,t);
676 waypoint.set_parent_value_node(this);
678 waypoint_list_.push_back(waypoint);
679 WaypointList::iterator ret=waypoint_list_.end();
686 virtual void on_changed()
688 ValueNode_Animated::on_changed();
690 if(waypoint_list_.size()<=1)
692 std::sort(waypoint_list_.begin(),waypoint_list_.end());
693 //waypoint_list_.sort();
694 r=waypoint_list_.front().get_time();
695 s=waypoint_list_.back().get_time();
699 virtual ValueBase operator()(Time t)const
701 if(waypoint_list_.size()==1)
702 return waypoint_list_.front().get_value(t);
703 if(waypoint_list_.empty())
706 return waypoint_list_.front().get_value(t);
708 return waypoint_list_.back().get_value(t);
710 WaypointList::const_iterator iter;
711 WaypointList::const_iterator next;
713 // This next line will set iter to the
714 // correct iterator for the given time.
715 for(next=waypoint_list_.begin(),iter=next++;next!=waypoint_list_.end() && t>=next->get_time();iter=next++)
716 if(iter->get_time()==t)
717 return iter->get_value(t);
719 if(iter->get_time()==t)
720 return iter->get_value(t);
722 if(next!=waypoint_list_.end())
723 return iter->get_value(t).get(bool()) || next->get_value(t).get(bool());
724 return iter->get_value(t);
728 /* === M E T H O D S ======================================================= */
730 ValueNode_Animated::ValueNode_Animated()
736 ValueNode_Animated::find(const Time& begin,const Time& end,std::vector<Waypoint*>& selected)
738 Time curr_time(begin);
741 // try to grab first waypoint
744 WaypointList::iterator iter;
745 iter=find(curr_time);
746 selected.push_back(&*iter);
753 WaypointList::iterator iter;
756 iter=find_next(curr_time);
757 curr_time=iter->get_time();
760 selected.push_back(&*iter);
771 ValueNode_Animated::manipulate_time(const Time& old_begin,const Time& old_end,const Time& new_begin,const Time& new_end)
773 #define old_2_new(x) (((x)-old_begin)/(old_end-old_begin)*(new_end-new_begin)+new_begin)
774 std::vector<Waypoint*> selected;
775 std::vector<Waypoint*>::iterator iter;
777 if(find(old_begin,old_end,selected))
779 // check to make sure this operation is OK
780 for(iter=selected.begin();iter!=selected.end();++iter)
784 Time new_time(old_2_new((*iter)->get_time()));
785 if(new_time>=old_begin && new_time<old_end)
788 // If we found a waypoint already at that time, then
790 throw Exception::BadTime(_("Waypoint Conflict"));
792 catch(Exception::NotFound) { }
794 selected.back()->set_time(old_2_new(selected.back()->get_time()));
799 while(!selected.empty())
801 selected.back()->set_time(old_2_new(selected.back()->get_time()));
812 ValueNode_Animated::new_waypoint_at_time(const Time& time)const
817 // Trivial case, we are sitting on a waypoint
818 waypoint=*find(time);
819 waypoint.make_unique();
823 if(waypoint_list().empty())
825 waypoint.set_value((*this)(time));
829 WaypointList::const_iterator prev;
830 WaypointList::const_iterator next;
832 bool has_prev(false), has_next(false);
834 try { prev=find_prev(time); has_prev=true; } catch(...) { }
835 try { next=find_next(time); has_next=true; } catch(...) { }
838 WaypointList::const_iterator closest;
840 if(has_prev&&!has_next)
842 else if(has_next&&!has_prev)
844 else if(time-prev->get_time()<next->get_time()-time)
849 for(iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
851 const Real dist(abs(iter->get_time()-time));
852 if(dist<abs(closest->get_time()-time))
857 if(has_prev && !prev->is_static())
858 waypoint.set_value_node(prev->get_value_node());
859 if(has_next && !next->is_static())
860 waypoint.set_value_node(next->get_value_node());
862 waypoint.set_value((*this)(time));
865 waypoint.set_after(prev->get_before());
867 waypoint.set_before(next->get_after());
871 waypoint.set_time(time);
872 waypoint.set_parent_value_node(const_cast<ValueNode_Animated*>(this));
873 // synfig::info("waypoint.get_after()=set to %d",waypoint.get_after());
874 // synfig::info("waypoint.get_before()=set to %d",waypoint.get_before());
879 ValueNode_Animated::WaypointList::iterator
880 ValueNode_Animated::find(const UniqueID &x)
882 ValueNode_Animated::WaypointList::iterator iter;
883 iter=std::find(waypoint_list().begin(),waypoint_list().end(),x);
884 if(iter==waypoint_list().end() || iter->get_uid()!=x.get_uid())
885 throw Exception::NotFound(strprintf("ValueNode_Animated::find(): Can't find UniqueID %d",x.get_uid()));
889 ValueNode_Animated::WaypointList::const_iterator
890 ValueNode_Animated::find(const UniqueID &x)const
892 return const_cast<ValueNode_Animated*>(this)->find(x);
894 ValueNode_Animated::WaypointList::const_iterator iter;
895 iter=std::find(waypoint_list().begin(),waypoint_list().end(),x);
896 if(iter!=waypoint_list().end() && iter->get_uid()!=x.get_uid())
897 throw Exception::NotFound(strprintf("ValueNode_Animated::find()const: Can't find UniqueID %d",x.get_uid()));
902 ValueNode_Animated::WaypointList::iterator
903 ValueNode_Animated::find(const Time &x)
905 WaypointList::iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
907 if(iter!=waypoint_list().end() && x.is_equal(iter->get_time()))
910 throw Exception::NotFound(strprintf("ValueNode_Animated::find(): Can't find Waypoint at %s",x.get_string().c_str()));
913 ValueNode_Animated::WaypointList::const_iterator
914 ValueNode_Animated::find(const Time &x)const
916 return const_cast<ValueNode_Animated*>(this)->find(x);
918 WaypointList::const_iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
920 if(iter!=waypoint_list().end() && x.is_equal(iter->get_time()))
923 throw Exception::NotFound(strprintf("ValueNode_Animated::find(): Can't find Waypoint at %s",x.get_string().c_str()));
927 ValueNode_Animated::WaypointList::iterator
928 ValueNode_Animated::find_next(const Time &x)
930 WaypointList::iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
932 if(iter!=waypoint_list().end())
934 if(iter->get_time().is_more_than(x))
937 if(iter!=waypoint_list().end() && iter->get_time().is_more_than(x))
941 throw Exception::NotFound(strprintf("ValueNode_Animated::find_next(): Can't find Waypoint after %s",x.get_string().c_str()));
944 ValueNode_Animated::WaypointList::const_iterator
945 ValueNode_Animated::find_next(const Time &x)const
947 return const_cast<ValueNode_Animated*>(this)->find_next(x);
949 WaypointList::const_iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
951 if(iter!=waypoint_list().end())
953 if(iter->get_time()-Time::epsilon()>x)
956 if(iter!=waypoint_list().end() && iter->get_time()-Time::epsilon()>x)
960 throw Exception::NotFound(strprintf("ValueNode_Animated::find_next(): Can't find Waypoint after %s",x.get_string().c_str()));
964 ValueNode_Animated::WaypointList::iterator
965 ValueNode_Animated::find_prev(const Time &x)
967 WaypointList::iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
969 if(iter!=waypoint_list().end())
971 if(iter->get_time().is_less_than(x))
973 if(iter!=waypoint_list().begin() && (--iter)->get_time().is_less_than(x))
977 throw Exception::NotFound(strprintf("ValueNode_Animated::find_prev(): Can't find Waypoint after %s",x.get_string().c_str()));
980 ValueNode_Animated::WaypointList::const_iterator
981 ValueNode_Animated::find_prev(const Time &x)const
983 return const_cast<ValueNode_Animated*>(this)->find_prev(x);
985 WaypointList::const_iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
987 if(iter!=waypoint_list().end())
989 if(iter->get_time()+Time::epsilon()<x)
991 if(iter!=waypoint_list().begin() && (--iter)->get_time()+Time::epsilon()<x)
994 throw Exception::NotFound(strprintf("ValueNode_Animated::find_prev(): Can't find Waypoint after %s",x.get_string().c_str()));
999 ValueNode_Animated::erase(const UniqueID &x)
1001 waypoint_list().erase(find(x));
1004 ValueNode_Animated::WaypointList::iterator
1005 ValueNode_Animated::add(const Waypoint &x)
1007 Waypoint waypoint(x);
1008 waypoint.set_parent_value_node(this);
1009 waypoint_list_.push_back(waypoint);
1010 //assert(waypoint_list_.back().get_parent_value_node()==this);
1011 WaypointList::iterator ret=waypoint_list_.end();
1018 ValueNode_Animated::set_type(ValueBase::Type t)
1020 ValueNode::set_type(t);
1023 ValueNode_Animated::Handle
1024 synfig::ValueNode_Animated::create(ValueBase::Type type)
1028 case ValueBase::TYPE_TIME:
1029 return ValueNode_Animated::Handle(new _Hermite<Time>);
1030 case ValueBase::TYPE_REAL:
1031 return ValueNode_Animated::Handle(new _Hermite<Vector::value_type>);
1032 case ValueBase::TYPE_INTEGER:
1033 return ValueNode_Animated::Handle(new _Hermite<int>);
1034 case ValueBase::TYPE_ANGLE:
1035 return ValueNode_Animated::Handle(new _Hermite<Angle>);
1036 case ValueBase::TYPE_VECTOR:
1037 return ValueNode_Animated::Handle(new _Hermite<Vector>);
1038 case ValueBase::TYPE_COLOR:
1039 return ValueNode_Animated::Handle(new _Hermite<Color>);
1041 case ValueBase::TYPE_STRING:
1042 return ValueNode_Animated::Handle(new _Constant<String>);
1043 case ValueBase::TYPE_GRADIENT:
1044 return ValueNode_Animated::Handle(new _Hermite<Gradient>);
1045 case ValueBase::TYPE_BOOL:
1046 return ValueNode_Animated::Handle(new _AnimBool);
1047 case ValueBase::TYPE_CANVAS:
1048 return ValueNode_Animated::Handle(new _Constant<Canvas::LooseHandle>);
1051 Exception::BadType(strprintf(_("%s: You cannot use a %s in an animated ValueNode"),"synfig::ValueNode_Animated::create()",
1052 ValueBase::type_name(type).c_str())
1056 return ValueNode_Animated::Handle();
1059 ValueNode_Animated::Handle
1060 ValueNode_Animated::create(const ValueBase& value, const Time& time)
1062 return create(ValueNode::Handle(ValueNode_Const::create(value)),time);
1065 ValueNode_Animated::Handle
1066 ValueNode_Animated::create(ValueNode::Handle value_node, const Time& time)
1068 ValueNode_Animated::Handle ret(create(value_node->get_type()));
1069 ret->new_waypoint(time,value_node);
1073 ValueNode_Animated::~ValueNode_Animated()
1078 ValueNode_Animated::get_name()const
1084 ValueNode_Animated::get_local_name()const
1086 return _("Animated");
1089 void ValueNode_Animated::get_times_vfunc(Node::time_set &set) const
1091 //add all the way point times to the value node...
1093 WaypointList::const_iterator i = waypoint_list().begin(),
1094 end = waypoint_list().end();
1096 for(; i != end; ++i)
1099 t.set_time(i->get_time());
1100 t.set_before(i->get_before());
1101 t.set_after(i->get_after());
1102 t.set_guid(i->get_guid());
1110 timecmp(const Time &c) :t(c) {}
1112 bool operator()(const Waypoint &rhs) const
1114 return t.is_equal(rhs.get_time());
1118 ValueNode_Animated::findresult
1119 ValueNode_Animated::find_uid(const UniqueID &x)
1124 //search for it... and set the bool part of the return value to true if we found it!
1125 f.first = std::find(waypoint_list_.begin(), waypoint_list_.end(), x);
1126 if(f.first != waypoint_list_.end())
1132 ValueNode_Animated::const_findresult
1133 ValueNode_Animated::find_uid(const UniqueID &x)const
1138 //search for it... and set the bool part of the return value to true if we found it!
1139 f.first = std::find(waypoint_list_.begin(), waypoint_list_.end(), x);
1140 if(f.first != waypoint_list_.end())
1146 ValueNode_Animated::findresult
1147 ValueNode_Animated::find_time(const Time &x)
1152 //search for it... and set the bool part of the return value to true if we found it!
1153 f.first = std::find_if(waypoint_list_.begin(), waypoint_list_.end(), timecmp(x));
1154 if(f.first != waypoint_list_.end())
1160 ValueNode_Animated::const_findresult
1161 ValueNode_Animated::find_time(const Time &x)const
1166 //search for it... and set the bool part of the return value to true if we found it!
1167 f.first = std::find_if(waypoint_list_.begin(), waypoint_list_.end(), timecmp(x));
1168 if(f.first != waypoint_list_.end())
1175 ValueNode_Animated::insert_time(const Time& location, const Time& delta)
1181 WaypointList::iterator iter(find_next(location));
1182 for(;iter!=waypoint_list().end();++iter)
1184 iter->set_time(iter->get_time()+delta);
1188 catch(Exception::NotFound) { }