1 /* === S I N F G =========================================================== */
2 /*! \file valuenode_animated.cpp
3 ** \brief Template File
5 ** $Id: valuenode_animated.cpp,v 1.1.1.1 2005/01/04 01:23:15 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
38 #include <ETL/hermite>
48 #include "valuenode_animated.h"
49 #include "valuenode_const.h"
50 #include "exception.h"
55 /* === U S I N G =========================================================== */
59 using namespace sinfg;
61 /* === M A C R O S ========================================================= */
63 // Fast binary search implementation
65 template<typename I, typename T> inline I
66 binary_find(I begin, I end, const T& value)
68 I iter(begin+(end-begin)/2);
70 while(end-begin>1 && !(*iter==value))
72 ((*iter<value)?begin:end) = iter;
74 iter = begin+(end-begin)/2;
81 template<typename T> String tangent_info(T a, T b, T v)
86 String tangent_info(Vector a, Vector b, Vector v)
89 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]);
91 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]);
96 struct subtractor : public std::binary_function<T, T, T>
98 T operator()(const T &a,const T &b)const
105 struct subtractor<Angle> : public std::binary_function<Angle, Angle, Angle>
107 Angle operator()(const Angle &a,const Angle &b)const
114 struct magnitude : public std::unary_function<float, T>
116 float operator()(const T &a)const
123 struct magnitude<Angle> : public std::unary_function<float, Angle>
125 float operator()(const Angle &a)const
127 return abs(Angle::rad(a).get());
132 struct magnitude<Vector> : public std::unary_function<float, Vector>
134 float operator()(const Vector &a)const
141 struct magnitude<Color> : public std::unary_function<float, Color>
143 float operator()(const Color &a)const
145 return abs(a.get_y());
156 bool operator()()const
163 struct is_angle_type<Angle>
165 bool operator()()const
171 /* === G L O B A L S ======================================================= */
173 /* === C L A S S E S ======================================================= */
176 class _Hermite : public sinfg::ValueNode_Animated
179 typedef T value_type;
180 affine_combo<value_type,Time> affine_combo_func;
181 subtractor<value_type> subtract_func;
182 magnitude<value_type> magnitude_func;
183 is_angle_type<value_type> is_angle;
187 is_angle_type<value_type> is_angle;
188 subtractor<value_type> subtract_func;
190 mutable hermite<Time,Time> first;
191 mutable hermite<value_type,Time> second;
192 WaypointList::iterator start;
193 WaypointList::iterator end;
195 value_type resolve(const Time &t)const
197 bool start_static(start->is_static());
198 bool end_static(end->is_static());
200 if(!start_static || !end_static)
203 second.p1()=start->get_value(t).get(value_type());
204 if(start->get_after()==INTERPOLATION_CONSTANT || end->get_before()==INTERPOLATION_CONSTANT)
207 second.p2()=end->get_value(t).get(value_type());
209 // At the moment, the only type of non-constant interpolation
210 // that we support is linear.
212 second.t2()=subtract_func(second.p2(),second.p1());
217 return second(first(t));
225 hermite<value_type,Time>
230 curve_list_type curve_list;
232 // Bounds of this curve
236 ValueNode* clone(const GUID& deriv_guid)const
238 { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
239 _Hermite<T>* ret(new _Hermite<T>());
240 ret->set_guid(get_guid()^deriv_guid);
241 for(WaypointList::const_iterator iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
242 ret->add(iter->clone(deriv_guid));
248 set_type(ValueBase(value_type()).get_type());
251 virtual WaypointList::iterator new_waypoint(Time t, ValueBase value)
253 // Make sure we are getting data of the correct type
254 //if(data.type!=type)
255 // return waypoint_list_type::iterator();
257 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
258 Waypoint waypoint(value,t);
259 waypoint.set_parent_value_node(this);
261 waypoint_list_.push_back(waypoint);
262 WaypointList::iterator ret=waypoint_list_.end();
267 ret->set_before(INTERPOLATION_LINEAR);
268 ret->set_after(INTERPOLATION_LINEAR);
276 virtual WaypointList::iterator new_waypoint(Time t, ValueNode::Handle value_node)
278 // Make sure we are getting data of the correct type
279 //if(data.type!=type)
280 // return waypoint_list_type::iterator();
281 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
283 Waypoint waypoint(value_node,t);
284 waypoint.set_parent_value_node(this);
286 waypoint_list_.push_back(waypoint);
287 WaypointList::iterator ret=waypoint_list_.end();
292 ret->set_before(INTERPOLATION_LINEAR);
293 ret->set_after(INTERPOLATION_LINEAR);
301 virtual void on_changed()
303 ValueNode_Animated::on_changed();
305 if(waypoint_list_.size()<=1)
307 std::sort(waypoint_list_.begin(),waypoint_list_.end());
308 //waypoint_list_.sort();
310 r=waypoint_list_.front().get_time();
311 s=waypoint_list_.back().get_time();
315 WaypointList::iterator prev,iter,next=waypoint_list_.begin();
318 for(iter=next++;iter!=waypoint_list_.end() && next!=waypoint_list_.end();prev=iter,iter=next++,i++)
320 typename curve_list_type::value_type curve;
321 WaypointList::iterator after_next(next);
327 // Set up the positions
328 curve.first.set_rs(iter->get_time(), next->get_time());
329 curve.second.set_rs(iter->get_time(), next->get_time());
331 Waypoint::Interpolation iter_get_after(iter->get_after());
332 Waypoint::Interpolation next_get_after(next->get_after());
333 Waypoint::Interpolation iter_get_before(iter->get_before());
334 Waypoint::Interpolation next_get_before(next->get_before());
338 if(iter_get_after==INTERPOLATION_TCB)
339 iter_get_after=INTERPOLATION_LINEAR;
340 if(next_get_after==INTERPOLATION_TCB)
341 next_get_after=INTERPOLATION_LINEAR;
342 if(iter_get_before==INTERPOLATION_TCB)
343 iter_get_before=INTERPOLATION_LINEAR;
344 if(next_get_before==INTERPOLATION_TCB)
345 next_get_before=INTERPOLATION_LINEAR;
348 if(iter->is_static() && next->is_static())
350 curve.second.p1()=iter->get_value().get(T());
351 curve.second.p2()=next->get_value().get(T());
352 if(iter_get_after==INTERPOLATION_CONSTANT || next_get_before==INTERPOLATION_CONSTANT)
354 // Sections must be constant on both sides.
355 // NOTE: this is commented out because of some
356 // user interface issues. Namely, if a section is
357 // constant and the user turns off the constant on
358 // one waypoint, this will end up turning it back on.
360 //iter->get_after()=next->get_before()=INTERPOLATION_CONSTANT;
362 curve.second.p2()=iter->get_value().get(T());
364 curve.second.t2()=subtract_func(curve.second.p1(),curve.second.p2());
368 if(iter_get_after==INTERPOLATION_TCB && iter!=waypoint_list_.begin() && !is_angle())
370 if(iter->get_before()!=INTERPOLATION_TCB && !curve_list.empty())
372 curve.second.t1()=curve_list.back().second.t2();
377 const Real& t(iter->get_tension()); // Tension
378 const Real& c(iter->get_continuity()); // Continuity
379 const Real& b(iter->get_bias()); // Bias
381 // The folloing line works where the previous line fails.
382 value_type Pp; Pp=curve_list.back().second.p1(); // P_{i-1}
384 const value_type& Pc(curve.second.p1()); // P_i
385 const value_type& Pn(curve.second.p2()); // P_{i+1}
388 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)));
391 //value_type vect=(value_type)((Pn-Pp)*(1.0-t));
394 //value_type vect=(value_type)(Pn-Pc);
397 //sinfg::info("%d:t1: %s",i,tangent_info(Pp,Pn,vect).c_str());
400 //vect=value_type(vect*(curve.second.get_dt()*2.0)/(curve.second.get_dt()+curve_list.back().second.get_dt()));
401 //vect=value_type(vect*(curve.second.get_dt())/(curve_list.back().second.get_dt()));
403 curve.second.t1()=vect;
407 iter_get_after==INTERPOLATION_LINEAR || iter_get_after==INTERPOLATION_HALT ||
408 (iter_get_after==INTERPOLATION_TCB && iter==waypoint_list_.begin()))
410 curve.second.t1()=subtract_func(curve.second.p2(),curve.second.p1());
413 if(iter_get_before==INTERPOLATION_TCB && iter->get_after()!=INTERPOLATION_TCB && !curve_list.empty())
415 curve_list.back().second.t2()=curve.second.t1();
416 curve_list.back().second.sync();
420 if(next_get_before==INTERPOLATION_TCB && after_next!=waypoint_list_.end() && !is_angle())
422 const Real &t(next->get_tension()); // Tension
423 const Real &c(next->get_continuity()); // Continuity
424 const Real &b(next->get_bias()); // Bias
425 const value_type &Pp(curve.second.p1()); // P_{i-1}
426 const value_type &Pc(curve.second.p2()); // P_i
427 value_type Pn; Pn=after_next->get_value().get(T()); // P_{i+1}
430 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)));
433 //value_type vect((value_type)((Pn-Pp)*(1.0-t)));
436 //value_type vect=(value_type)(Pc-Pp);
439 //sinfg::info("%d:t2: %s",i,tangent_info(Pp,Pn,vect).c_str());
442 //vect=value_type(vect*(curve.second.get_dt()*2.0)/(curve.second.get_dt()+(after_next->get_time()-next->get_time())));
443 //vect=value_type(vect*(curve.second.get_dt()/((after_next->get_time()-next->get_time()))));
445 curve.second.t2()=vect;
448 next_get_before==INTERPOLATION_LINEAR || next_get_before==INTERPOLATION_HALT ||
449 (next_get_before==INTERPOLATION_TCB && after_next==waypoint_list_.end()))
451 curve.second.t2()=subtract_func(curve.second.p2(),curve.second.p1());
455 const float timeadjust(0.5);
457 if(!curve_list.empty())
458 curve.second.t1()*=(curve.second.get_dt()*(timeadjust+1))/(curve.second.get_dt()*timeadjust+curve_list.back().second.get_dt());
459 if(after_next!=waypoint_list_.end())
460 curve.second.t2()*=(curve.second.get_dt()*(timeadjust+1))/(curve.second.get_dt()*timeadjust+(after_next->get_time()-next->get_time()));
462 if(iter_get_after==INTERPOLATION_HALT)
463 curve.second.t1()*=0;
465 if(next_get_before==INTERPOLATION_HALT)
466 curve.second.t2()*=0;
470 // Set up the time to the default stuff
471 curve.first.set_rs(iter->get_time(), next->get_time());
472 curve.first.p1()=iter->get_time();
473 curve.first.p2()=next->get_time();
474 curve.first.t1()=(curve.first.p2()-curve.first.p1())*(1.0f-iter->get_time_tension());
475 curve.first.t2()=(curve.first.p2()-curve.first.p1())*(1.0f-next->get_time_tension());
481 curve_list.push_back(curve);
485 virtual ValueBase operator()(Time t)const
487 if(waypoint_list_.empty())
488 return value_type(); //! \todo Perhaps we should throw something here?
489 if(waypoint_list_.size()==1)
490 return waypoint_list_.front().get_value(t);
492 return waypoint_list_.front().get_value(t);
494 return waypoint_list_.back().get_value(t);
496 typename curve_list_type::const_iterator iter;
498 // This next line will set iter to the
499 // correct iterator for the given time.
500 for(iter=curve_list.begin();iter<curve_list.end() && t>=iter->first.get_s();++iter)
502 if(iter==curve_list.end())
503 return waypoint_list_.back().get_value(t);
504 return iter->resolve(t);
510 class _Constant : public sinfg::ValueNode_Animated
513 typedef T value_type;
517 // Bounds of this curve
521 ValueNode* clone(const GUID& deriv_guid)const
523 { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
524 _Constant<T>* ret(new _Constant<T>());
525 ret->set_guid(get_guid()^deriv_guid);
526 for(WaypointList::const_iterator iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
527 ret->add(iter->clone(deriv_guid));
533 set_type(ValueBase(value_type()).get_type());
536 virtual WaypointList::iterator new_waypoint(Time t, ValueBase value)
538 // Make sure we are getting data of the correct type
539 //if(data.type!=type)
540 // return waypoint_list_type::iterator();
541 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
543 Waypoint waypoint(value,t);
544 waypoint.set_parent_value_node(this);
546 waypoint_list_.push_back(waypoint);
547 WaypointList::iterator ret=waypoint_list_.end();
554 virtual WaypointList::iterator new_waypoint(Time t, ValueNode::Handle value_node)
556 // Make sure we are getting data of the correct type
557 //if(data.type!=type)
558 // return waypoint_list_type::iterator();
559 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
561 Waypoint waypoint(value_node,t);
562 waypoint.set_parent_value_node(this);
564 waypoint_list_.push_back(waypoint);
565 WaypointList::iterator ret=waypoint_list_.end();
572 virtual void on_changed()
574 ValueNode_Animated::on_changed();
576 if(waypoint_list_.size()<=1)
578 std::sort(waypoint_list_.begin(),waypoint_list_.end());
579 //waypoint_list_.sort();
580 r=waypoint_list_.front().get_time();
581 s=waypoint_list_.back().get_time();
585 virtual ValueBase operator()(Time t)const
587 if(waypoint_list_.size()==1)
588 return waypoint_list_.front().get_value(t);
589 if(waypoint_list_.empty())
592 return waypoint_list_.front().get_value(t);
594 return waypoint_list_.back().get_value(t);
596 typename WaypointList::const_iterator iter;
597 typename WaypointList::const_iterator next;
599 // This next line will set iter to the
600 // correct iterator for the given time.
601 for(next=waypoint_list_.begin(),iter=next++;next!=waypoint_list_.end() && t>=next->get_time();iter=next++)
604 return iter->get_value(t);
608 class _AnimBool : public sinfg::ValueNode_Animated
611 typedef bool value_type;
615 // Bounds of this curve
619 ValueNode* clone(const GUID& deriv_guid)const
621 { ValueNode* x(find_value_node(get_guid()^deriv_guid).get()); if(x)return x; }
622 _AnimBool* ret(new _AnimBool());
623 ret->set_guid(get_guid()^deriv_guid);
624 for(WaypointList::const_iterator iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
625 ret->add(iter->clone(deriv_guid));
631 set_type(ValueBase(value_type()).get_type());
634 virtual WaypointList::iterator new_waypoint(Time t, ValueBase value)
636 // Make sure we are getting data of the correct type
637 //if(data.type!=type)
638 // return waypoint_list_type::iterator();
639 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
642 Waypoint waypoint(value,t);
643 waypoint.set_parent_value_node(this);
645 waypoint_list_.push_back(waypoint);
646 WaypointList::iterator ret=waypoint_list_.end();
653 virtual WaypointList::iterator new_waypoint(Time t, ValueNode::Handle value_node)
655 // Make sure we are getting data of the correct type
656 //if(data.type!=type)
657 // return waypoint_list_type::iterator();
658 try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
660 Waypoint waypoint(value_node,t);
661 waypoint.set_parent_value_node(this);
663 waypoint_list_.push_back(waypoint);
664 WaypointList::iterator ret=waypoint_list_.end();
671 virtual void on_changed()
673 ValueNode_Animated::on_changed();
675 if(waypoint_list_.size()<=1)
677 std::sort(waypoint_list_.begin(),waypoint_list_.end());
678 //waypoint_list_.sort();
679 r=waypoint_list_.front().get_time();
680 s=waypoint_list_.back().get_time();
684 virtual ValueBase operator()(Time t)const
686 if(waypoint_list_.size()==1)
687 return waypoint_list_.front().get_value(t);
688 if(waypoint_list_.empty())
691 return waypoint_list_.front().get_value(t);
693 return waypoint_list_.back().get_value(t);
695 WaypointList::const_iterator iter;
696 WaypointList::const_iterator next;
698 // This next line will set iter to the
699 // correct iterator for the given time.
700 for(next=waypoint_list_.begin(),iter=next++;next!=waypoint_list_.end() && t>=next->get_time();iter=next++)
701 if(iter->get_time()==t)
702 return iter->get_value(t);
704 if(iter->get_time()==t)
705 return iter->get_value(t);
707 if(next!=waypoint_list_.end())
708 return iter->get_value(t).get(bool()) || next->get_value(t).get(bool());
709 return iter->get_value(t);
713 /* === M E T H O D S ======================================================= */
715 ValueNode_Animated::ValueNode_Animated()
721 ValueNode_Animated::find(const Time& begin,const Time& end,std::vector<Waypoint*>& selected)
723 Time curr_time(begin);
726 // try to grab first waypoint
729 WaypointList::iterator iter;
730 iter=find(curr_time);
731 selected.push_back(&*iter);
738 WaypointList::iterator iter;
741 iter=find_next(curr_time);
742 curr_time=iter->get_time();
745 selected.push_back(&*iter);
756 ValueNode_Animated::manipulate_time(const Time& old_begin,const Time& old_end,const Time& new_begin,const Time& new_end)
758 #define old_2_new(x) (((x)-old_begin)/(old_end-old_begin)*(new_end-new_begin)+new_begin)
759 std::vector<Waypoint*> selected;
760 std::vector<Waypoint*>::iterator iter;
762 if(find(old_begin,old_end,selected))
764 // check to make sure this operation is OK
765 for(iter=selected.begin();iter!=selected.end();++iter)
769 Time new_time(old_2_new((*iter)->get_time()));
770 if(new_time>=old_begin && new_time<old_end)
773 // If we found a waypoint already at that time, then
775 throw Exception::BadTime(_("Waypoint Conflict"));
777 catch(Exception::NotFound) { }
779 selected.back()->set_time(old_2_new(selected.back()->get_time()));
784 while(!selected.empty())
786 selected.back()->set_time(old_2_new(selected.back()->get_time()));
797 ValueNode_Animated::new_waypoint_at_time(const Time& time)const
802 // Trivial case, we are sitting on a waypoint
803 waypoint=*find(time);
804 waypoint.make_unique();
808 if(waypoint_list().empty())
810 waypoint.set_value((*this)(time));
814 WaypointList::const_iterator prev;
815 WaypointList::const_iterator next;
817 bool has_prev(false), has_next(false);
819 try { prev=find_prev(time); has_prev=true; } catch(...) { }
820 try { next=find_next(time); has_next=true; } catch(...) { }
823 WaypointList::const_iterator closest;
825 if(has_prev&&!has_next)
827 else if(has_next&&!has_prev)
829 else if(time-prev->get_time()<next->get_time()-time)
834 for(iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
836 const Real dist(abs(iter->get_time()-time));
837 if(dist<abs(closest->get_time()-time))
842 if(has_prev && !prev->is_static())
843 waypoint.set_value_node(prev->get_value_node());
844 if(has_next && !next->is_static())
845 waypoint.set_value_node(next->get_value_node());
847 waypoint.set_value((*this)(time));
850 waypoint.set_after(prev->get_before());
852 waypoint.set_before(next->get_after());
856 waypoint.set_time(time);
857 waypoint.set_parent_value_node(const_cast<ValueNode_Animated*>(this));
858 // sinfg::info("waypoint.get_after()=set to %d",waypoint.get_after());
859 // sinfg::info("waypoint.get_before()=set to %d",waypoint.get_before());
864 ValueNode_Animated::WaypointList::iterator
865 ValueNode_Animated::find(const UniqueID &x)
867 ValueNode_Animated::WaypointList::iterator iter;
868 iter=std::find(waypoint_list().begin(),waypoint_list().end(),x);
869 if(iter==waypoint_list().end() || iter->get_uid()!=x.get_uid())
870 throw Exception::NotFound(strprintf("ValueNode_Animated::find(): Can't find UniqueID %d",x.get_uid()));
874 ValueNode_Animated::WaypointList::const_iterator
875 ValueNode_Animated::find(const UniqueID &x)const
877 return const_cast<ValueNode_Animated*>(this)->find(x);
879 ValueNode_Animated::WaypointList::const_iterator iter;
880 iter=std::find(waypoint_list().begin(),waypoint_list().end(),x);
881 if(iter!=waypoint_list().end() && iter->get_uid()!=x.get_uid())
882 throw Exception::NotFound(strprintf("ValueNode_Animated::find()const: Can't find UniqueID %d",x.get_uid()));
887 ValueNode_Animated::WaypointList::iterator
888 ValueNode_Animated::find(const Time &x)
890 WaypointList::iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
892 if(iter!=waypoint_list().end() && x.is_equal(iter->get_time()))
895 throw Exception::NotFound(strprintf("ValueNode_Animated::find(): Can't find Waypoint at %s",x.get_string().c_str()));
898 ValueNode_Animated::WaypointList::const_iterator
899 ValueNode_Animated::find(const Time &x)const
901 return const_cast<ValueNode_Animated*>(this)->find(x);
903 WaypointList::const_iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
905 if(iter!=waypoint_list().end() && x.is_equal(iter->get_time()))
908 throw Exception::NotFound(strprintf("ValueNode_Animated::find(): Can't find Waypoint at %s",x.get_string().c_str()));
912 ValueNode_Animated::WaypointList::iterator
913 ValueNode_Animated::find_next(const Time &x)
915 WaypointList::iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
917 if(iter!=waypoint_list().end())
919 if(iter->get_time().is_more_than(x))
922 if(iter!=waypoint_list().end() && iter->get_time().is_more_than(x))
926 throw Exception::NotFound(strprintf("ValueNode_Animated::find_next(): Can't find Waypoint after %s",x.get_string().c_str()));
929 ValueNode_Animated::WaypointList::const_iterator
930 ValueNode_Animated::find_next(const Time &x)const
932 return const_cast<ValueNode_Animated*>(this)->find_next(x);
934 WaypointList::const_iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
936 if(iter!=waypoint_list().end())
938 if(iter->get_time()-Time::epsilon()>x)
941 if(iter!=waypoint_list().end() && iter->get_time()-Time::epsilon()>x)
945 throw Exception::NotFound(strprintf("ValueNode_Animated::find_next(): Can't find Waypoint after %s",x.get_string().c_str()));
949 ValueNode_Animated::WaypointList::iterator
950 ValueNode_Animated::find_prev(const Time &x)
952 WaypointList::iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
954 if(iter!=waypoint_list().end())
956 if(iter->get_time().is_less_than(x))
958 if(iter!=waypoint_list().begin() && (--iter)->get_time().is_less_than(x))
962 throw Exception::NotFound(strprintf("ValueNode_Animated::find_prev(): Can't find Waypoint after %s",x.get_string().c_str()));
965 ValueNode_Animated::WaypointList::const_iterator
966 ValueNode_Animated::find_prev(const Time &x)const
968 return const_cast<ValueNode_Animated*>(this)->find_prev(x);
970 WaypointList::const_iterator iter(binary_find(waypoint_list().begin(),waypoint_list().end(),x));
972 if(iter!=waypoint_list().end())
974 if(iter->get_time()+Time::epsilon()<x)
976 if(iter!=waypoint_list().begin() && (--iter)->get_time()+Time::epsilon()<x)
979 throw Exception::NotFound(strprintf("ValueNode_Animated::find_prev(): Can't find Waypoint after %s",x.get_string().c_str()));
984 ValueNode_Animated::erase(const UniqueID &x)
986 waypoint_list().erase(find(x));
989 ValueNode_Animated::WaypointList::iterator
990 ValueNode_Animated::add(const Waypoint &x)
992 Waypoint waypoint(x);
993 waypoint.set_parent_value_node(this);
994 waypoint_list_.push_back(waypoint);
995 //assert(waypoint_list_.back().get_parent_value_node()==this);
996 WaypointList::iterator ret=waypoint_list_.end();
1003 ValueNode_Animated::set_type(ValueBase::Type t)
1005 ValueNode::set_type(t);
1008 ValueNode_Animated::Handle
1009 sinfg::ValueNode_Animated::create(ValueBase::Type type)
1013 case ValueBase::TYPE_TIME:
1014 return ValueNode_Animated::Handle(new _Hermite<Time>);
1015 case ValueBase::TYPE_REAL:
1016 return ValueNode_Animated::Handle(new _Hermite<Vector::value_type>);
1017 case ValueBase::TYPE_INTEGER:
1018 return ValueNode_Animated::Handle(new _Hermite<int>);
1019 case ValueBase::TYPE_ANGLE:
1020 return ValueNode_Animated::Handle(new _Hermite<Angle>);
1021 case ValueBase::TYPE_VECTOR:
1022 return ValueNode_Animated::Handle(new _Hermite<Vector>);
1023 case ValueBase::TYPE_COLOR:
1024 return ValueNode_Animated::Handle(new _Hermite<Color>);
1026 case ValueBase::TYPE_STRING:
1027 return ValueNode_Animated::Handle(new _Constant<String>);
1028 case ValueBase::TYPE_GRADIENT:
1029 return ValueNode_Animated::Handle(new _Constant<Gradient>);
1030 case ValueBase::TYPE_BOOL:
1031 return ValueNode_Animated::Handle(new _AnimBool);
1032 case ValueBase::TYPE_CANVAS:
1033 return ValueNode_Animated::Handle(new _Constant<Canvas::LooseHandle>);
1036 Exception::BadType(strprintf(_("%s: You cannot use a %s in an animated ValueNode"),"sinfg::ValueNode_Animated::create()",
1037 ValueBase::type_name(type).c_str())
1041 return ValueNode_Animated::Handle();
1044 ValueNode_Animated::Handle
1045 ValueNode_Animated::create(const ValueBase& value, const Time& time)
1047 return create(ValueNode::Handle(ValueNode_Const::create(value)),time);
1050 ValueNode_Animated::Handle
1051 ValueNode_Animated::create(ValueNode::Handle value_node, const Time& time)
1053 ValueNode_Animated::Handle ret(create(value_node->get_type()));
1054 ret->new_waypoint(time,value_node);
1058 ValueNode_Animated::~ValueNode_Animated()
1063 ValueNode_Animated::get_name()const
1069 ValueNode_Animated::get_local_name()const
1071 return _("Animated");
1074 void ValueNode_Animated::get_times_vfunc(Node::time_set &set) const
1076 //add all the way point times to the value node...
1078 WaypointList::const_iterator i = waypoint_list().begin(),
1079 end = waypoint_list().end();
1081 for(; i != end; ++i)
1084 t.set_time(i->get_time());
1085 t.set_before(i->get_before());
1086 t.set_after(i->get_after());
1087 t.set_guid(i->get_guid());
1095 timecmp(const Time &c) :t(c) {}
1097 bool operator()(const Waypoint &rhs) const
1099 return t.is_equal(rhs.get_time());
1103 ValueNode_Animated::findresult
1104 ValueNode_Animated::find_uid(const UniqueID &x)
1109 //search for it... and set the bool part of the return value to true if we found it!
1110 f.first = std::find(waypoint_list_.begin(), waypoint_list_.end(), x);
1111 if(f.first != waypoint_list_.end())
1117 ValueNode_Animated::const_findresult
1118 ValueNode_Animated::find_uid(const UniqueID &x)const
1123 //search for it... and set the bool part of the return value to true if we found it!
1124 f.first = std::find(waypoint_list_.begin(), waypoint_list_.end(), x);
1125 if(f.first != waypoint_list_.end())
1131 ValueNode_Animated::findresult
1132 ValueNode_Animated::find_time(const Time &x)
1137 //search for it... and set the bool part of the return value to true if we found it!
1138 f.first = std::find_if(waypoint_list_.begin(), waypoint_list_.end(), timecmp(x));
1139 if(f.first != waypoint_list_.end())
1145 ValueNode_Animated::const_findresult
1146 ValueNode_Animated::find_time(const Time &x)const
1151 //search for it... and set the bool part of the return value to true if we found it!
1152 f.first = std::find_if(waypoint_list_.begin(), waypoint_list_.end(), timecmp(x));
1153 if(f.first != waypoint_list_.end())
1160 ValueNode_Animated::insert_time(const Time& location, const Time& delta)
1166 WaypointList::iterator iter(find_next(location));
1167 for(;iter!=waypoint_list().end();++iter)
1169 iter->set_time(iter->get_time()+delta);
1173 catch(Exception::NotFound) { }