1 /* === S Y N F I G ========================================================= */
2 /*! \file valuenode_animated.cpp
3 ** \brief Implementation of the "Animated" valuenode conversion.
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007, 2008 Chris Moore
11 ** This package is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU General Public License as
13 ** published by the Free Software Foundation; either version 2 of
14 ** the License, or (at your option) any later version.
16 ** This package is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** General Public License for more details.
22 /* ========================================================================= */
24 /* === H E A D E R S ======================================================= */
40 #include <ETL/hermite>
50 #include "valuenode_animated.h"
51 #include "valuenode_const.h"
52 #include "exception.h"
57 /* === U S I N G =========================================================== */
61 using namespace synfig;
63 /* === M A C R O S ========================================================= */
66 template<typename T> String tangent_info(T a, T b, T v)
71 String tangent_info(Vector a, Vector b, Vector v)
74 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]);
76 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]);
81 struct subtractor : public std::binary_function<T, T, T>
83 T operator()(const T &a,const T &b)const
90 struct subtractor<Angle> : public std::binary_function<Angle, Angle, Angle>
92 Angle operator()(const Angle &a,const Angle &b)const
99 struct magnitude : public std::unary_function<float, T>
101 float operator()(const T &a)const
108 struct magnitude<Angle> : public std::unary_function<float, Angle>
110 float operator()(const Angle &a)const
112 return abs(Angle::rad(a).get());
117 struct magnitude<Vector> : public std::unary_function<float, Vector>
119 float operator()(const Vector &a)const
126 struct magnitude<Color> : public std::unary_function<float, Color>
128 float operator()(const Color &a)const
130 return abs(a.get_y());
137 bool operator()()const
143 #ifdef ANGLES_USE_LINEAR_INTERPOLATION
145 struct is_angle_type<Angle>
147 bool operator()()const
152 #endif // ANGLES_USE_LINEAR_INTERPOLATION
154 /* === G L O B A L S ======================================================= */
156 /* === C L A S S E S ======================================================= */
159 class _Hermite : public synfig::ValueNode_Animated
162 typedef T value_type;
163 affine_combo<value_type,Time> affine_combo_func;
164 subtractor<value_type> subtract_func;
165 magnitude<value_type> magnitude_func;
166 is_angle_type<value_type> is_angle;
170 is_angle_type<value_type> is_angle;
171 subtractor<value_type> subtract_func;
173 mutable hermite<Time,Time> first;
174 mutable hermite<value_type,Time> second;
175 WaypointList::iterator start;
176 WaypointList::iterator end;
178 value_type resolve(const Time &t)const
180 bool start_static(start->is_static());
181 bool end_static(end->is_static());
183 if(!start_static || !end_static)
186 second.p1()=start->get_value(t).get(value_type());
187 if(start->get_after()==INTERPOLATION_CONSTANT || end->get_before()==INTERPOLATION_CONSTANT)
190 second.p2()=end->get_value(t).get(value_type());
192 // At the moment, the only type of non-constant interpolation
193 // that we support is linear.
195 second.t2()=subtract_func(second.p2(),second.p1());
200 return second(first(t));
208 hermite<value_type,Time>
213 curve_list_type curve_list;
215 // Bounds of this curve
219 ValueNode* clone(const synfig::GUID& deriv_guid)const
221 { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
222 _Hermite<T>* ret(new _Hermite<T>());
223 ret->set_guid(get_guid()^deriv_guid);
224 for(WaypointList::const_iterator iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
225 ret->add(iter->clone(deriv_guid));
231 set_type(ValueBase(value_type()).get_type());
234 virtual WaypointList::iterator new_waypoint(Time t, ValueBase value)
236 // Make sure we are getting data of the correct type
237 //if(data.type!=type)
238 // return waypoint_list_type::iterator();
240 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
241 Waypoint waypoint(value,t);
242 waypoint.set_parent_value_node(this);
244 waypoint_list_.push_back(waypoint);
245 WaypointList::iterator ret=waypoint_list_.end();
250 ret->set_before(INTERPOLATION_LINEAR);
251 ret->set_after(INTERPOLATION_LINEAR);
259 virtual WaypointList::iterator new_waypoint(Time t, ValueNode::Handle value_node)
261 // Make sure we are getting data of the correct type
262 //if(data.type!=type)
263 // return waypoint_list_type::iterator();
264 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
266 Waypoint waypoint(value_node,t);
267 waypoint.set_parent_value_node(this);
269 waypoint_list_.push_back(waypoint);
270 WaypointList::iterator ret=waypoint_list_.end();
275 ret->set_before(INTERPOLATION_LINEAR);
276 ret->set_after(INTERPOLATION_LINEAR);
284 virtual void on_changed()
286 ValueNode_Animated::on_changed();
288 if(waypoint_list_.size()<=1)
290 std::sort(waypoint_list_.begin(),waypoint_list_.end());
291 //waypoint_list_.sort();
293 r=waypoint_list_.front().get_time();
294 s=waypoint_list_.back().get_time();
298 WaypointList::iterator prev,iter,next=waypoint_list_.begin();
301 for(iter=next++;iter!=waypoint_list_.end() && next!=waypoint_list_.end();prev=iter,iter=next++,i++)
303 typename curve_list_type::value_type curve;
304 WaypointList::iterator after_next(next);
310 // Set up the positions
311 curve.first.set_rs(iter->get_time(), next->get_time());
312 curve.second.set_rs(iter->get_time(), next->get_time());
314 Waypoint::Interpolation iter_get_after(iter->get_after());
315 Waypoint::Interpolation next_get_after(next->get_after());
316 Waypoint::Interpolation iter_get_before(iter->get_before());
317 Waypoint::Interpolation next_get_before(next->get_before());
321 if(iter_get_after==INTERPOLATION_TCB)
322 iter_get_after=INTERPOLATION_LINEAR;
323 if(next_get_after==INTERPOLATION_TCB)
324 next_get_after=INTERPOLATION_LINEAR;
325 if(iter_get_before==INTERPOLATION_TCB)
326 iter_get_before=INTERPOLATION_LINEAR;
327 if(next_get_before==INTERPOLATION_TCB)
328 next_get_before=INTERPOLATION_LINEAR;
331 if(iter->is_static() && next->is_static())
333 curve.second.p1()=iter->get_value().get(T());
334 curve.second.p2()=next->get_value().get(T());
335 if(iter_get_after==INTERPOLATION_CONSTANT || next_get_before==INTERPOLATION_CONSTANT)
337 // Sections must be constant on both sides.
338 // NOTE: this is commented out because of some
339 // user interface issues. Namely, if a section is
340 // constant and the user turns off the constant on
341 // one waypoint, this will end up turning it back on.
343 //iter->get_after()=next->get_before()=INTERPOLATION_CONSTANT;
345 curve.second.p2()=iter->get_value().get(T());
347 curve.second.t2()=subtract_func(curve.second.p1(),curve.second.p2());
351 if(iter_get_after==INTERPOLATION_TCB && iter!=waypoint_list_.begin() && !is_angle())
353 if(iter->get_before()!=INTERPOLATION_TCB && !curve_list.empty())
355 curve.second.t1()=curve_list.back().second.t2();
359 const Real& t(iter->get_tension()); // Tension
360 const Real& c(iter->get_continuity()); // Continuity
361 const Real& b(iter->get_bias()); // Bias
363 // The following line works where the previous line fails.
364 value_type Pp; Pp=curve_list.back().second.p1(); // P_{i-1}
366 const value_type& Pc(curve.second.p1()); // P_i
367 const value_type& Pn(curve.second.p2()); // P_{i+1}
370 value_type vect(static_cast<value_type>
371 (subtract_func(Pc,Pp) *
372 (((1.0-t) * (1.0+c) * (1.0+b)) / 2.0) +
373 (Pn-Pc) * (((1.0-t) * (1.0-c) * (1.0-b)) / 2.0)));
376 //value_type vect=(value_type)((Pn-Pp)*(1.0-t));
379 //value_type vect=(value_type)(Pn-Pc);
382 //synfig::info("%d:t1: %s",i,tangent_info(Pp,Pn,vect).c_str());
385 //vect=value_type(vect*(curve.second.get_dt()*2.0)/(curve.second.get_dt()+curve_list.back().second.get_dt()));
386 //vect=value_type(vect*(curve.second.get_dt())/(curve_list.back().second.get_dt()));
388 curve.second.t1()=vect;
392 iter_get_after==INTERPOLATION_LINEAR || iter_get_after==INTERPOLATION_HALT ||
393 (iter_get_after==INTERPOLATION_TCB && iter==waypoint_list_.begin()))
395 curve.second.t1()=subtract_func(curve.second.p2(),curve.second.p1());
398 if(iter_get_before==INTERPOLATION_TCB && iter->get_after()!=INTERPOLATION_TCB && !curve_list.empty())
400 curve_list.back().second.t2()=curve.second.t1();
401 curve_list.back().second.sync();
405 if(next_get_before==INTERPOLATION_TCB && after_next!=waypoint_list_.end() && !is_angle())
407 const Real &t(next->get_tension()); // Tension
408 const Real &c(next->get_continuity()); // Continuity
409 const Real &b(next->get_bias()); // Bias
410 const value_type &Pp(curve.second.p1()); // P_{i-1}
411 const value_type &Pc(curve.second.p2()); // P_i
412 value_type Pn; Pn=after_next->get_value().get(T()); // P_{i+1}
415 value_type vect(static_cast<value_type>(subtract_func(Pc,Pp) * (((1.0-t)*(1.0-c)*(1.0+b))/2.0) +
416 (Pn-Pc) * (((1.0-t)*(1.0+c)*(1.0-b))/2.0)));
419 //value_type vect((value_type)((Pn-Pp)*(1.0-t)));
422 //value_type vect=(value_type)(Pc-Pp);
425 //synfig::info("%d:t2: %s",i,tangent_info(Pp,Pn,vect).c_str());
428 //vect=value_type(vect*(curve.second.get_dt()*2.0)/(curve.second.get_dt()+(after_next->get_time()-next->get_time())));
429 //vect=value_type(vect*(curve.second.get_dt()/((after_next->get_time()-next->get_time()))));
431 curve.second.t2()=vect;
434 next_get_before==INTERPOLATION_LINEAR || next_get_before==INTERPOLATION_HALT ||
435 (next_get_before==INTERPOLATION_TCB && after_next==waypoint_list_.end()))
437 curve.second.t2()=subtract_func(curve.second.p2(),curve.second.p1());
441 const float timeadjust(0.5);
443 if(iter_get_after==INTERPOLATION_HALT)
444 curve.second.t1()*=0;
445 // if this isn't the first curve
446 else if(iter_get_after != INTERPOLATION_LINEAR && !curve_list.empty())
447 // adjust it for the curve that came before it
448 curve.second.t1() = static_cast<T>(curve.second.t1() * // cast to prevent warning
449 // (time span of this curve) * 1.5
450 // -----------------------------------------------------------------
451 // ((time span of this curve) * 0.5) + (time span of previous curve)
452 (curve.second.get_dt()*(timeadjust+1)) /
453 (curve.second.get_dt()*timeadjust + curve_list.back().second.get_dt()));
455 if(next_get_before==INTERPOLATION_HALT)
456 curve.second.t2()*=0;
457 // if this isn't the last curve
458 else if(next_get_before != INTERPOLATION_LINEAR && after_next!=waypoint_list_.end())
459 // adjust it for the curve that came after it
460 curve.second.t2() = static_cast<T>(curve.second.t2() * // cast to prevent warning
461 // (time span of this curve) * 1.5
462 // -------------------------------------------------------------
463 // ((time span of this curve) * 0.5) + (time span of next curve)
464 (curve.second.get_dt()*(timeadjust+1)) /
465 (curve.second.get_dt()*timeadjust+(after_next->get_time()-next->get_time())));
469 // Set up the time to the default stuff
470 curve.first.set_rs(iter->get_time(), next->get_time());
471 curve.first.p1()=iter->get_time();
472 curve.first.p2()=next->get_time();
473 curve.first.t1()=(curve.first.p2()-curve.first.p1())*(1.0f-iter->get_temporal_tension());
474 curve.first.t2()=(curve.first.p2()-curve.first.p1())*(1.0f-next->get_temporal_tension());
480 curve_list.push_back(curve);
484 virtual ValueBase operator()(Time t)const
486 if(waypoint_list_.empty())
487 return value_type(); //! \todo Perhaps we should throw something here?
488 if(waypoint_list_.size()==1)
489 return waypoint_list_.front().get_value(t);
491 return waypoint_list_.front().get_value(t);
493 return waypoint_list_.back().get_value(t);
495 typename curve_list_type::const_iterator iter;
497 // This next line will set iter to the
498 // correct iterator for the given time.
499 for(iter=curve_list.begin();iter<curve_list.end() && t>=iter->first.get_s();++iter)
501 if(iter==curve_list.end())
502 return waypoint_list_.back().get_value(t);
503 return iter->resolve(t);
509 class _Constant : public synfig::ValueNode_Animated
512 typedef T value_type;
516 // Bounds of this curve
520 ValueNode* clone(const synfig::GUID& deriv_guid)const
522 { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
523 _Constant<T>* ret(new _Constant<T>());
524 ret->set_guid(get_guid()^deriv_guid);
525 for(WaypointList::const_iterator iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
526 ret->add(iter->clone(deriv_guid));
532 set_type(ValueBase(value_type()).get_type());
535 virtual WaypointList::iterator new_waypoint(Time t, ValueBase value)
537 // Make sure we are getting data of the correct type
538 //if(data.type!=type)
539 // return waypoint_list_type::iterator();
540 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
542 Waypoint waypoint(value,t);
543 waypoint.set_parent_value_node(this);
545 waypoint_list_.push_back(waypoint);
546 WaypointList::iterator ret=waypoint_list_.end();
553 virtual WaypointList::iterator new_waypoint(Time t, ValueNode::Handle value_node)
555 // Make sure we are getting data of the correct type
556 //if(data.type!=type)
557 // return waypoint_list_type::iterator();
558 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
560 Waypoint waypoint(value_node,t);
561 waypoint.set_parent_value_node(this);
563 waypoint_list_.push_back(waypoint);
564 WaypointList::iterator ret=waypoint_list_.end();
571 virtual void on_changed()
573 ValueNode_Animated::on_changed();
575 if(waypoint_list_.size()<=1)
577 std::sort(waypoint_list_.begin(),waypoint_list_.end());
578 //waypoint_list_.sort();
579 r=waypoint_list_.front().get_time();
580 s=waypoint_list_.back().get_time();
584 virtual ValueBase operator()(Time t)const
586 if(waypoint_list_.size()==1)
587 return waypoint_list_.front().get_value(t);
588 if(waypoint_list_.empty())
591 return waypoint_list_.front().get_value(t);
593 return waypoint_list_.back().get_value(t);
595 typename WaypointList::const_iterator iter;
596 typename WaypointList::const_iterator next;
598 // This next line will set iter to the
599 // correct iterator for the given time.
600 for(next=waypoint_list_.begin(),iter=next++;next!=waypoint_list_.end() && t>=next->get_time();iter=next++)
603 return iter->get_value(t);
607 class _AnimBool : public synfig::ValueNode_Animated
610 typedef bool value_type;
614 // Bounds of this curve
618 ValueNode* clone(const synfig::GUID& deriv_guid)const
620 { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
621 _AnimBool* ret(new _AnimBool());
622 ret->set_guid(get_guid()^deriv_guid);
623 for(WaypointList::const_iterator iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
624 ret->add(iter->clone(deriv_guid));
630 set_type(ValueBase(value_type()).get_type());
633 virtual WaypointList::iterator new_waypoint(Time t, ValueBase value)
635 // Make sure we are getting data of the correct type
636 //if(data.type!=type)
637 // return waypoint_list_type::iterator();
638 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
641 Waypoint waypoint(value,t);
642 waypoint.set_parent_value_node(this);
644 waypoint_list_.push_back(waypoint);
645 WaypointList::iterator ret=waypoint_list_.end();
652 virtual WaypointList::iterator new_waypoint(Time t, ValueNode::Handle value_node)
654 // Make sure we are getting data of the correct type
655 //if(data.type!=type)
656 // return waypoint_list_type::iterator();
657 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
659 Waypoint waypoint(value_node,t);
660 waypoint.set_parent_value_node(this);
662 waypoint_list_.push_back(waypoint);
663 WaypointList::iterator ret=waypoint_list_.end();
670 virtual void on_changed()
672 ValueNode_Animated::on_changed();
674 if(waypoint_list_.size()<=1)
676 std::sort(waypoint_list_.begin(),waypoint_list_.end());
677 //waypoint_list_.sort();
678 r=waypoint_list_.front().get_time();
679 s=waypoint_list_.back().get_time();
683 virtual ValueBase operator()(Time t)const
685 if(waypoint_list_.size()==1)
686 return waypoint_list_.front().get_value(t);
687 if(waypoint_list_.empty())
690 return waypoint_list_.front().get_value(t);
692 return waypoint_list_.back().get_value(t);
694 WaypointList::const_iterator iter;
695 WaypointList::const_iterator next;
697 // This next line will set iter to the
698 // correct iterator for the given time.
699 for(next=waypoint_list_.begin(),iter=next++;next!=waypoint_list_.end() && t>=next->get_time();iter=next++)
700 if(iter->get_time()==t)
701 return iter->get_value(t);
703 if(iter->get_time()==t)
704 return iter->get_value(t);
706 if(next!=waypoint_list_.end())
707 return iter->get_value(t).get(bool()) || next->get_value(t).get(bool());
708 return iter->get_value(t);
712 /* === M E T H O D S ======================================================= */
714 ValueNode_Animated::ValueNode_Animated()
719 ValueNode_Animated::find(const Time& begin,const Time& end,std::vector<Waypoint*>& selected)
721 Time curr_time(begin);
724 // try to grab first waypoint
727 WaypointList::iterator iter;
728 iter=find(curr_time);
729 selected.push_back(&*iter);
736 WaypointList::iterator iter;
739 iter=find_next(curr_time);
740 curr_time=iter->get_time();
743 selected.push_back(&*iter);
752 /** This code seems to be designed to move selected waypoints to other
753 * place. Probably it was commented out because the conflict when other
754 * waypoints are found in the target time. It was also defined and now commented
755 * in valuenode_dynamiclist.h
757 ValueNode_Animated::manipulate_time(const Time& old_begin,const Time& old_end,const Time& new_begin,const Time& new_end)
759 #define old_2_new(x) (((x)-old_begin)/(old_end-old_begin)*(new_end-new_begin)+new_begin)
760 std::vector<Waypoint*> selected;
761 std::vector<Waypoint*>::iterator iter;
763 if(find(old_begin,old_end,selected))
765 // check to make sure this operation is OK
766 for(iter=selected.begin();iter!=selected.end();++iter)
770 Time new_time(old_2_new((*iter)->get_time()));
771 if(new_time>=old_begin && new_time<old_end)
774 // If we found a waypoint already at that time, then
776 throw Exception::BadTime(_("Waypoint Conflict"));
778 catch(Exception::NotFound) { }
780 selected.back()->set_time(old_2_new(selected.back()->get_time()));
785 while(!selected.empty())
787 selected.back()->set_time(old_2_new(selected.back()->get_time()));
798 ValueNode_Animated::new_waypoint_at_time(const Time& time)const
803 // Trivial case, we are sitting on a waypoint
804 waypoint=*find(time);
805 waypoint.make_unique();
809 if(waypoint_list().empty())
811 waypoint.set_value((*this)(time));
815 WaypointList::const_iterator prev;
816 WaypointList::const_iterator next;
818 bool has_prev(false), has_next(false);
820 try { prev=find_prev(time); has_prev=true; } catch(...) { }
821 try { next=find_next(time); has_next=true; } catch(...) { }
823 if(has_prev && !prev->is_static())
824 waypoint.set_value_node(prev->get_value_node());
825 if(has_next && !next->is_static())
826 waypoint.set_value_node(next->get_value_node());
828 waypoint.set_value((*this)(time));
832 waypoint.set_time(time);
833 waypoint.set_parent_value_node(const_cast<ValueNode_Animated*>(this));
834 // synfig::info("waypoint.get_after()=set to %d",waypoint.get_after());
835 // synfig::info("waypoint.get_before()=set to %d",waypoint.get_before());
840 ValueNode_Animated::WaypointList::iterator
841 ValueNode_Animated::find(const UniqueID &x)
843 ValueNode_Animated::WaypointList::iterator iter;
844 iter=std::find(waypoint_list().begin(),waypoint_list().end(),x);
845 if(iter==waypoint_list().end() || iter->get_uid()!=x.get_uid())
846 throw Exception::NotFound(strprintf("ValueNode_Animated::find(): Can't find UniqueID %d",x.get_uid()));
850 ValueNode_Animated::WaypointList::const_iterator
851 ValueNode_Animated::find(const UniqueID &x)const
853 return const_cast<ValueNode_Animated*>(this)->find(x);
856 ValueNode_Animated::WaypointList::iterator
857 ValueNode_Animated::find(const Time &x)
859 WaypointList::iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
861 if(iter!=waypoint_list().end() && x.is_equal(iter->get_time()))
864 throw Exception::NotFound(strprintf("ValueNode_Animated::find(): Can't find Waypoint at %s",x.get_string().c_str()));
867 ValueNode_Animated::WaypointList::const_iterator
868 ValueNode_Animated::find(const Time &x)const
870 return const_cast<ValueNode_Animated*>(this)->find(x);
873 ValueNode_Animated::WaypointList::iterator
874 ValueNode_Animated::find_next(const Time &x)
876 WaypointList::iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
878 if(iter!=waypoint_list().end())
880 if(iter->get_time().is_more_than(x))
883 if(iter!=waypoint_list().end() && iter->get_time().is_more_than(x))
887 throw Exception::NotFound(strprintf("ValueNode_Animated::find_next(): Can't find Waypoint after %s",x.get_string().c_str()));
890 ValueNode_Animated::WaypointList::const_iterator
891 ValueNode_Animated::find_next(const Time &x)const
893 return const_cast<ValueNode_Animated*>(this)->find_next(x);
896 ValueNode_Animated::WaypointList::iterator
897 ValueNode_Animated::find_prev(const Time &x)
899 WaypointList::iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
901 if(iter!=waypoint_list().end())
903 if(iter->get_time().is_less_than(x))
905 if(iter!=waypoint_list().begin() && (--iter)->get_time().is_less_than(x))
909 throw Exception::NotFound(strprintf("ValueNode_Animated::find_prev(): Can't find Waypoint after %s",x.get_string().c_str()));
912 ValueNode_Animated::WaypointList::const_iterator
913 ValueNode_Animated::find_prev(const Time &x)const
915 return const_cast<ValueNode_Animated*>(this)->find_prev(x);
919 ValueNode_Animated::erase(const UniqueID &x)
921 waypoint_list().erase(find(x));
924 ValueNode_Animated::WaypointList::iterator
925 ValueNode_Animated::add(const Waypoint &x)
927 Waypoint waypoint(x);
928 waypoint.set_parent_value_node(this);
929 waypoint_list_.push_back(waypoint);
930 //assert(waypoint_list_.back().get_parent_value_node()==this);
931 WaypointList::iterator ret=waypoint_list_.end();
938 ValueNode_Animated::set_type(ValueBase::Type t)
940 ValueNode::set_type(t);
943 ValueNode_Animated::Handle
944 synfig::ValueNode_Animated::create(ValueBase::Type type)
948 case ValueBase::TYPE_TIME:
949 return ValueNode_Animated::Handle(new _Hermite<Time>);
950 case ValueBase::TYPE_REAL:
951 return ValueNode_Animated::Handle(new _Hermite<Vector::value_type>);
952 case ValueBase::TYPE_INTEGER:
953 return ValueNode_Animated::Handle(new _Hermite<int>);
954 case ValueBase::TYPE_ANGLE:
955 return ValueNode_Animated::Handle(new _Hermite<Angle>);
956 case ValueBase::TYPE_VECTOR:
957 return ValueNode_Animated::Handle(new _Hermite<Vector>);
958 case ValueBase::TYPE_COLOR:
959 return ValueNode_Animated::Handle(new _Hermite<Color>);
961 case ValueBase::TYPE_STRING:
962 return ValueNode_Animated::Handle(new _Constant<String>);
963 case ValueBase::TYPE_GRADIENT:
964 return ValueNode_Animated::Handle(new _Hermite<Gradient>);
965 case ValueBase::TYPE_BOOL:
966 return ValueNode_Animated::Handle(new _AnimBool);
967 case ValueBase::TYPE_CANVAS:
968 return ValueNode_Animated::Handle(new _Constant<Canvas::LooseHandle>);
971 Exception::BadType(strprintf(_("%s: You cannot use a %s in an animated ValueNode"),"synfig::ValueNode_Animated::create()",
972 ValueBase::type_local_name(type).c_str())
976 return ValueNode_Animated::Handle();
979 ValueNode_Animated::Handle
980 ValueNode_Animated::create(const ValueBase& value, const Time& time)
982 return create(ValueNode::Handle(ValueNode_Const::create(value)),time);
985 ValueNode_Animated::Handle
986 ValueNode_Animated::create(ValueNode::Handle value_node, const Time& time)
988 ValueNode_Animated::Handle ret(create(value_node->get_type()));
989 ret->new_waypoint(time,value_node);
993 ValueNode_Animated::~ValueNode_Animated()
998 ValueNode_Animated::get_name()const
1004 ValueNode_Animated::get_local_name()const
1006 return _("Animated");
1009 void ValueNode_Animated::get_times_vfunc(Node::time_set &set) const
1011 //add all the way point times to the value node...
1013 WaypointList::const_iterator i = waypoint_list().begin(),
1014 end = waypoint_list().end();
1016 for(; i != end; ++i)
1019 t.set_time(i->get_time());
1020 t.set_before(i->get_before());
1021 t.set_after(i->get_after());
1022 t.set_guid(i->get_guid());
1030 timecmp(const Time &c) :t(c) {}
1032 bool operator()(const Waypoint &rhs) const
1034 return t.is_equal(rhs.get_time());
1038 ValueNode_Animated::findresult
1039 ValueNode_Animated::find_uid(const UniqueID &x)
1044 //search for it... and set the bool part of the return value to true if we found it!
1045 f.first = std::find(waypoint_list_.begin(), waypoint_list_.end(), x);
1046 if(f.first != waypoint_list_.end())
1052 ValueNode_Animated::const_findresult
1053 ValueNode_Animated::find_uid(const UniqueID &x)const
1058 //search for it... and set the bool part of the return value to true if we found it!
1059 f.first = std::find(waypoint_list_.begin(), waypoint_list_.end(), x);
1060 if(f.first != waypoint_list_.end())
1066 ValueNode_Animated::findresult
1067 ValueNode_Animated::find_time(const Time &x)
1072 //search for it... and set the bool part of the return value to true if we found it!
1073 f.first = std::find_if(waypoint_list_.begin(), waypoint_list_.end(), timecmp(x));
1074 if(f.first != waypoint_list_.end())
1080 ValueNode_Animated::const_findresult
1081 ValueNode_Animated::find_time(const Time &x)const
1086 //search for it... and set the bool part of the return value to true if we found it!
1087 f.first = std::find_if(waypoint_list_.begin(), waypoint_list_.end(), timecmp(x));
1088 if(f.first != waypoint_list_.end())
1095 ValueNode_Animated::insert_time(const Time& location, const Time& delta)
1101 WaypointList::iterator iter(find_next(location));
1102 for(;iter!=waypoint_list().end();++iter)
1104 iter->set_time(iter->get_time()+delta);
1108 catch(Exception::NotFound) { }