Added copyright lines for files I've edited this year.
[synfig.git] / synfig-core / trunk / src / synfig / valuenode_animated.cpp
index b68149a..c2d70a1 100644 (file)
@@ -1,20 +1,22 @@
 /* === S Y N F I G ========================================================= */
 /*!    \file valuenode_animated.cpp
-**     \brief Template File
+**     \brief Implementation of the "Animated" valuenode conversion.
 **
-**     $Id: valuenode_animated.cpp,v 1.1.1.1 2005/01/04 01:23:15 darco Exp $
+**     $Id$
 **
 **     \legal
-**     Copyright (c) 2002 Robert B. Quattlebaum Jr.
+**     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**     Copyright (c) 2007, 2008 Chris Moore
 **
-**     This software and associated documentation
-**     are CONFIDENTIAL and PROPRIETARY property of
-**     the above-mentioned copyright holder.
+**     This package is free software; you can redistribute it and/or
+**     modify it under the terms of the GNU General Public License as
+**     published by the Free Software Foundation; either version 2 of
+**     the License, or (at your option) any later version.
 **
-**     You may not copy, print, publish, or in any
-**     other way distribute this software without
-**     a prior written agreement with
-**     the copyright holder.
+**     This package is distributed in the hope that it will be useful,
+**     but WITHOUT ANY WARRANTY; without even the implied warranty of
+**     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+**     General Public License for more details.
 **     \endlegal
 */
 /* ========================================================================= */
@@ -66,11 +68,11 @@ template<typename I, typename T> inline I
 binary_find(I begin, I end, const T& value)
 {
        I iter(begin+(end-begin)/2);
-       
+
        while(end-begin>1 && !(*iter==value))
        {
                ((*iter<value)?begin:end) = iter;
-               
+
                iter = begin+(end-begin)/2;
        }
        return iter;
@@ -159,6 +161,7 @@ struct is_angle_type
        }
 };
 
+#ifdef ANGLES_USE_LINEAR_INTERPOLATION
 template <>
 struct is_angle_type<Angle>
 {
@@ -167,6 +170,7 @@ struct is_angle_type<Angle>
                return true;
        }
 };
+#endif // ANGLES_USE_LINEAR_INTERPOLATION
 
 /* === G L O B A L S ======================================================= */
 
@@ -186,21 +190,21 @@ private:
        {
                is_angle_type<value_type>       is_angle;
                subtractor<value_type>  subtract_func;
-               
+
                mutable hermite<Time,Time> first;
                mutable hermite<value_type,Time> second;
                WaypointList::iterator start;
                WaypointList::iterator end;
-               
+
                value_type resolve(const Time &t)const
                {
                        bool start_static(start->is_static());
                        bool end_static(end->is_static());
-                       
+
                        if(!start_static || !end_static)
                        {
                                //if(!start_static)
-                                       second.p1()=start->get_value(t).get(value_type());                                      
+                                       second.p1()=start->get_value(t).get(value_type());
                                if(start->get_after()==INTERPOLATION_CONSTANT || end->get_before()==INTERPOLATION_CONSTANT)
                                        return second.p1();
                                //if(!end_static)
@@ -210,7 +214,7 @@ private:
                                // that we support is linear.
                                second.t1()=
                                second.t2()=subtract_func(second.p2(),second.p1());
-                               
+
                                second.sync();
                        }
 
@@ -228,10 +232,10 @@ private:
        > curve_list_type;
 
        curve_list_type curve_list;
-               
+
        // Bounds of this curve
        Time r,s;
-       
+
 public:
        ValueNode* clone(const GUID& deriv_guid)const
        {
@@ -253,23 +257,23 @@ public:
                // Make sure we are getting data of the correct type
                //if(data.type!=type)
                //      return waypoint_list_type::iterator();
-               
+
                try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
                Waypoint waypoint(value,t);
                waypoint.set_parent_value_node(this);
-               
+
                waypoint_list_.push_back(waypoint);
                WaypointList::iterator ret=waypoint_list_.end();
                --ret;
-               
+
                if(is_angle())
                {
                        ret->set_before(INTERPOLATION_LINEAR);
                        ret->set_after(INTERPOLATION_LINEAR);
                }
-               
+
                changed();
-               
+
                return ret;
        }
 
@@ -279,10 +283,10 @@ public:
                //if(data.type!=type)
                //      return waypoint_list_type::iterator();
                try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
-               
+
                Waypoint waypoint(value_node,t);
                waypoint.set_parent_value_node(this);
-               
+
                waypoint_list_.push_back(waypoint);
                WaypointList::iterator ret=waypoint_list_.end();
                --ret;
@@ -294,14 +298,14 @@ public:
                }
 
                changed();
-               
+
                return ret;
        }
-       
+
        virtual void on_changed()
        {
                ValueNode_Animated::on_changed();
-               
+
                if(waypoint_list_.size()<=1)
                        return;
                std::sort(waypoint_list_.begin(),waypoint_list_.end());
@@ -309,12 +313,12 @@ public:
 
                r=waypoint_list_.front().get_time();
                s=waypoint_list_.back().get_time();
-               
+
                curve_list.clear();
-               
+
                WaypointList::iterator prev,iter,next=waypoint_list_.begin();
                int i=0;
-               
+
                for(iter=next++;iter!=waypoint_list_.end() && next!=waypoint_list_.end();prev=iter,iter=next++,i++)
                {
                        typename curve_list_type::value_type curve;
@@ -323,16 +327,16 @@ public:
 
                        curve.start=iter;
                        curve.end=next;
-                       
+
                        // Set up the positions
                        curve.first.set_rs(iter->get_time(), next->get_time());
                        curve.second.set_rs(iter->get_time(), next->get_time());
-                       
+
                        Waypoint::Interpolation iter_get_after(iter->get_after());
                        Waypoint::Interpolation next_get_after(next->get_after());
                        Waypoint::Interpolation iter_get_before(iter->get_before());
                        Waypoint::Interpolation next_get_before(next->get_before());
-                       
+
                        if(is_angle())
                        {
                                if(iter_get_after==INTERPOLATION_TCB)
@@ -344,7 +348,7 @@ public:
                                if(next_get_before==INTERPOLATION_TCB)
                                        next_get_before=INTERPOLATION_LINEAR;
                        }
-                       
+
                        if(iter->is_static() && next->is_static())
                        {
                                curve.second.p1()=iter->get_value().get(T());
@@ -373,34 +377,36 @@ public:
                                                }
                                                else
                                                {
+                                                       const Real& t(iter->get_tension());             // Tension
+                                                       const Real& c(iter->get_continuity());  // Continuity
+                                                       const Real& b(iter->get_bias());                // Bias
 
-                                               const Real& t(iter->get_tension());             // Tension
-                                               const Real& c(iter->get_continuity());  // Continuity
-                                               const Real& b(iter->get_bias());                        // Bias
-                                               
-                                               // The folloing line works where the previous line fails.
-                                               value_type Pp; Pp=curve_list.back().second.p1();        // P_{i-1}
-                                               
-                                               const value_type& Pc(curve.second.p1());        // P_i
-                                               const value_type& Pn(curve.second.p2());        // P_{i+1}
-                                               
-                                               // TCB
-                                               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)));
-                                               
-                                               // Tension Only
-                                               //value_type vect=(value_type)((Pn-Pp)*(1.0-t));
-                                               
-                                               // Linear
-                                               //value_type vect=(value_type)(Pn-Pc);
+                                                       // The following line works where the previous line fails.
+                                                       value_type Pp; Pp=curve_list.back().second.p1();        // P_{i-1}
 
-                                               // Debugging stuff
-                                               //synfig::info("%d:t1: %s",i,tangent_info(Pp,Pn,vect).c_str());
-       
-                                               // Adjust for time
-                                               //vect=value_type(vect*(curve.second.get_dt()*2.0)/(curve.second.get_dt()+curve_list.back().second.get_dt()));
-                                               //vect=value_type(vect*(curve.second.get_dt())/(curve_list.back().second.get_dt()));
-       
-                                               curve.second.t1()=vect;
+                                                       const value_type& Pc(curve.second.p1());        // P_i
+                                                       const value_type& Pn(curve.second.p2());        // P_{i+1}
+
+                                                       // TCB
+                                                       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)));
+
+                                                       // Tension Only
+                                                       //value_type vect=(value_type)((Pn-Pp)*(1.0-t));
+
+                                                       // Linear
+                                                       //value_type vect=(value_type)(Pn-Pc);
+
+                                                       // Debugging stuff
+                                                       //synfig::info("%d:t1: %s",i,tangent_info(Pp,Pn,vect).c_str());
+
+                                                       // Adjust for time
+                                                       //vect=value_type(vect*(curve.second.get_dt()*2.0)/(curve.second.get_dt()+curve_list.back().second.get_dt()));
+                                                       //vect=value_type(vect*(curve.second.get_dt())/(curve_list.back().second.get_dt()));
+
+                                                       curve.second.t1()=vect;
                                                }
                                        }
                                        else if(
@@ -416,7 +422,7 @@ public:
                                                curve_list.back().second.sync();
                                        }
 
-                                       
+
                                        if(next_get_before==INTERPOLATION_TCB && after_next!=waypoint_list_.end()  && !is_angle())
                                        {
                                                const Real &t(next->get_tension());             // Tension
@@ -425,13 +431,14 @@ public:
                                                const value_type &Pp(curve.second.p1());        // P_{i-1}
                                                const value_type &Pc(curve.second.p2());        // P_i
                                                value_type Pn; Pn=after_next->get_value().get(T());     // P_{i+1}
-                                               
+
                                                // TCB
-                                               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)));
+                                               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)));
 
                                                // Tension Only
                                                //value_type vect((value_type)((Pn-Pp)*(1.0-t)));
-                                               
+
                                                // Linear
                                                //value_type vect=(value_type)(Pc-Pp);
 
@@ -453,18 +460,31 @@ public:
 
                                        // Adjust for time
                                        const float timeadjust(0.5);
-                                       
-                                       if(!curve_list.empty())
-                                               curve.second.t1()*=(curve.second.get_dt()*(timeadjust+1))/(curve.second.get_dt()*timeadjust+curve_list.back().second.get_dt());
-                                       if(after_next!=waypoint_list_.end())
-                                               curve.second.t2()*=(curve.second.get_dt()*(timeadjust+1))/(curve.second.get_dt()*timeadjust+(after_next->get_time()-next->get_time()));
 
                                        if(iter_get_after==INTERPOLATION_HALT)
                                                curve.second.t1()*=0;
-               
+                                       // if this isn't the first curve
+                                       else if(iter_get_after != INTERPOLATION_LINEAR && !curve_list.empty())
+                                               // adjust it for the curve that came before it
+                                               curve.second.t1() = static_cast<T>(curve.second.t1() * // cast to prevent warning
+                                                       //                  (time span of this curve) * 1.5
+                                                       // -----------------------------------------------------------------
+                                                       // ((time span of this curve) * 0.5) + (time span of previous curve)
+                                                         (curve.second.get_dt()*(timeadjust+1)) /
+                                                         (curve.second.get_dt()*timeadjust + curve_list.back().second.get_dt()));
+
                                        if(next_get_before==INTERPOLATION_HALT)
-                                               curve.second.t2()*=0;                                   
-                               }
+                                               curve.second.t2()*=0;
+                                       // if this isn't the last curve
+                                       else if(next_get_before != INTERPOLATION_LINEAR && after_next!=waypoint_list_.end())
+                                               // adjust it for the curve that came after it
+                                               curve.second.t2() = static_cast<T>(curve.second.t2() * // cast to prevent warning
+                                                       //                (time span of this curve) * 1.5
+                                                       // -------------------------------------------------------------
+                                                       // ((time span of this curve) * 0.5) + (time span of next curve)
+                                                         (curve.second.get_dt()*(timeadjust+1)) /
+                                                         (curve.second.get_dt()*timeadjust+(after_next->get_time()-next->get_time())));
+                               } // not CONSTANT
                        }
 
                        // Set up the time to the default stuff
@@ -481,7 +501,7 @@ public:
                        curve_list.push_back(curve);
                }
        }
-       
+
        virtual ValueBase operator()(Time t)const
        {
                if(waypoint_list_.empty())
@@ -492,7 +512,7 @@ public:
                        return waypoint_list_.front().get_value(t);
                if(t>=s)
                        return waypoint_list_.back().get_value(t);
-                                               
+
                typename curve_list_type::const_iterator iter;
 
                // This next line will set iter to the
@@ -502,8 +522,8 @@ public:
                if(iter==curve_list.end())
                        return waypoint_list_.back().get_value(t);
                return iter->resolve(t);
-       }       
-};  
+       }
+};
 
 
 template<typename T>
@@ -539,10 +559,10 @@ public:
                //if(data.type!=type)
                //      return waypoint_list_type::iterator();
                try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
-               
+
                Waypoint waypoint(value,t);
                waypoint.set_parent_value_node(this);
-               
+
                waypoint_list_.push_back(waypoint);
                WaypointList::iterator ret=waypoint_list_.end();
                --ret;
@@ -560,7 +580,7 @@ public:
 
                Waypoint waypoint(value_node,t);
                waypoint.set_parent_value_node(this);
-               
+
                waypoint_list_.push_back(waypoint);
                WaypointList::iterator ret=waypoint_list_.end();
                --ret;
@@ -572,7 +592,7 @@ public:
        virtual void on_changed()
        {
                ValueNode_Animated::on_changed();
-               
+
                if(waypoint_list_.size()<=1)
                        return;
                std::sort(waypoint_list_.begin(),waypoint_list_.end());
@@ -638,10 +658,10 @@ public:
                //      return waypoint_list_type::iterator();
                try { find(t); throw Exception::BadTime(_("A waypoint already exists at this point in time")); } catch(Exception::NotFound) { };
 
-               
+
                Waypoint waypoint(value,t);
                waypoint.set_parent_value_node(this);
-               
+
                waypoint_list_.push_back(waypoint);
                WaypointList::iterator ret=waypoint_list_.end();
                --ret;
@@ -659,7 +679,7 @@ public:
 
                Waypoint waypoint(value_node,t);
                waypoint.set_parent_value_node(this);
-               
+
                waypoint_list_.push_back(waypoint);
                WaypointList::iterator ret=waypoint_list_.end();
                --ret;
@@ -671,7 +691,7 @@ public:
        virtual void on_changed()
        {
                ValueNode_Animated::on_changed();
-               
+
                if(waypoint_list_.size()<=1)
                        return;
                std::sort(waypoint_list_.begin(),waypoint_list_.end());
@@ -703,7 +723,7 @@ public:
 
                if(iter->get_time()==t)
                        return iter->get_value(t);
-               
+
                if(next!=waypoint_list_.end())
                        return iter->get_value(t).get(bool()) || next->get_value(t).get(bool());
                return iter->get_value(t);
@@ -722,7 +742,7 @@ ValueNode_Animated::find(const Time& begin,const Time& end,std::vector<Waypoint*
 {
        Time curr_time(begin);
        int ret(0);
-       
+
        // try to grab first waypoint
        try
        {
@@ -732,7 +752,7 @@ ValueNode_Animated::find(const Time& begin,const Time& end,std::vector<Waypoint*
                ret++;
        }
        catch(...) { }
-       
+
        try
        {
                WaypointList::iterator iter;
@@ -747,7 +767,7 @@ ValueNode_Animated::find(const Time& begin,const Time& end,std::vector<Waypoint*
                }
        }
        catch(...) { }
-       
+
        return ret;
 }
 
@@ -775,18 +795,18 @@ ValueNode_Animated::manipulate_time(const Time& old_begin,const Time& old_end,co
                                throw Exception::BadTime(_("Waypoint Conflict"));
                        }
                        catch(Exception::NotFound) { }
-                       
+
                        selected.back()->set_time(old_2_new(selected.back()->get_time()));
                        selected.pop_back();
                }
-       
-               
+
+
                while(!selected.empty())
                {
                        selected.back()->set_time(old_2_new(selected.back()->get_time()));
                        selected.pop_back();
                }
-               
+
                changed();
        }
 #undef old_2_new
@@ -804,7 +824,7 @@ ValueNode_Animated::new_waypoint_at_time(const Time& time)const
                waypoint.make_unique();
        }
        catch(...)
-       {       
+       {
                if(waypoint_list().empty())
                {
                        waypoint.set_value((*this)(time));
@@ -815,10 +835,10 @@ ValueNode_Animated::new_waypoint_at_time(const Time& time)const
                        WaypointList::const_iterator next;
 
                        bool has_prev(false), has_next(false);
-                       
+
                        try { prev=find_prev(time); has_prev=true; } catch(...) { }
                        try { next=find_next(time); has_next=true; } catch(...) { }
-                       
+
                        /*
                        WaypointList::const_iterator closest;
 
@@ -830,7 +850,7 @@ ValueNode_Animated::new_waypoint_at_time(const Time& time)const
                                closest=prev;
                        else
                                closest=next;
-                               
+
                        for(iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
                        {
                                const Real dist(abs(iter->get_time()-time));
@@ -838,14 +858,14 @@ ValueNode_Animated::new_waypoint_at_time(const Time& time)const
                                        closest=iter;
                        }
                        */
-                       
+
                        if(has_prev && !prev->is_static())
                                waypoint.set_value_node(prev->get_value_node());
                        if(has_next && !next->is_static())
                                waypoint.set_value_node(next->get_value_node());
                        else
                                waypoint.set_value((*this)(time));
-                       
+
                        /*if(has_prev)
                                waypoint.set_after(prev->get_before());
                        if(has_next)
@@ -857,7 +877,7 @@ ValueNode_Animated::new_waypoint_at_time(const Time& time)const
        waypoint.set_parent_value_node(const_cast<ValueNode_Animated*>(this));
 //     synfig::info("waypoint.get_after()=set to %d",waypoint.get_after());
 //     synfig::info("waypoint.get_before()=set to %d",waypoint.get_before());
-       
+
        return waypoint;
 }
 
@@ -922,7 +942,7 @@ ValueNode_Animated::find_next(const Time &x)
                if(iter!=waypoint_list().end() && iter->get_time().is_more_than(x))
                        return iter;
        }
-       
+
        throw Exception::NotFound(strprintf("ValueNode_Animated::find_next(): Can't find Waypoint after %s",x.get_string().c_str()));
 }
 
@@ -941,7 +961,7 @@ ValueNode_Animated::find_next(const Time &x)const
                if(iter!=waypoint_list().end() && iter->get_time()-Time::epsilon()>x)
                        return iter;
        }
-       
+
        throw Exception::NotFound(strprintf("ValueNode_Animated::find_next(): Can't find Waypoint after %s",x.get_string().c_str()));
 */
 }
@@ -958,7 +978,7 @@ ValueNode_Animated::find_prev(const Time &x)
                if(iter!=waypoint_list().begin() && (--iter)->get_time().is_less_than(x))
                        return iter;
        }
-       
+
        throw Exception::NotFound(strprintf("ValueNode_Animated::find_prev(): Can't find Waypoint after %s",x.get_string().c_str()));
 }
 
@@ -1022,11 +1042,11 @@ synfig::ValueNode_Animated::create(ValueBase::Type type)
                        return ValueNode_Animated::Handle(new _Hermite<Vector>);
                case ValueBase::TYPE_COLOR:
                        return ValueNode_Animated::Handle(new _Hermite<Color>);
-                       
+
                case ValueBase::TYPE_STRING:
                        return ValueNode_Animated::Handle(new _Constant<String>);
                case ValueBase::TYPE_GRADIENT:
-                       return ValueNode_Animated::Handle(new _Constant<Gradient>);
+                       return ValueNode_Animated::Handle(new _Hermite<Gradient>);
                case ValueBase::TYPE_BOOL:
                        return ValueNode_Animated::Handle(new _AnimBool);
                case ValueBase::TYPE_CANVAS:
@@ -1034,7 +1054,7 @@ synfig::ValueNode_Animated::create(ValueBase::Type type)
                default:
                        throw
                                Exception::BadType(strprintf(_("%s: You cannot use a %s in an animated ValueNode"),"synfig::ValueNode_Animated::create()",
-                                       ValueBase::type_name(type).c_str())
+                                       ValueBase::type_local_name(type).c_str())
                                );
                        break;
        }
@@ -1074,7 +1094,7 @@ ValueNode_Animated::get_local_name()const
 void ValueNode_Animated::get_times_vfunc(Node::time_set &set) const
 {
        //add all the way point times to the value node...
-       
+
        WaypointList::const_iterator    i = waypoint_list().begin(),
                                                                        end = waypoint_list().end();
 
@@ -1091,68 +1111,68 @@ void ValueNode_Animated::get_times_vfunc(Node::time_set &set) const
 struct timecmp
  {
        Time t;
+
        timecmp(const Time &c) :t(c) {}
+
        bool operator()(const Waypoint &rhs) const
        {
                return t.is_equal(rhs.get_time());
        }
  };
+
  ValueNode_Animated::findresult
  ValueNode_Animated::find_uid(const UniqueID &x)
  {
        findresult      f;
        f.second = false;
-       
+
        //search for it... and set the bool part of the return value to true if we found it!
        f.first = std::find(waypoint_list_.begin(), waypoint_list_.end(), x);
        if(f.first != waypoint_list_.end())
                f.second = true;
-               
+
        return f;
  }
+
  ValueNode_Animated::const_findresult
  ValueNode_Animated::find_uid(const UniqueID &x)const
  {
        const_findresult        f;
        f.second = false;
-       
+
        //search for it... and set the bool part of the return value to true if we found it!
        f.first = std::find(waypoint_list_.begin(), waypoint_list_.end(), x);
        if(f.first != waypoint_list_.end())
                f.second = true;
-               
+
        return f;
  }
- ValueNode_Animated::findresult        
+
+ ValueNode_Animated::findresult
  ValueNode_Animated::find_time(const Time &x)
  {
        findresult      f;
        f.second = false;
-       
+
        //search for it... and set the bool part of the return value to true if we found it!
        f.first = std::find_if(waypoint_list_.begin(), waypoint_list_.end(), timecmp(x));
        if(f.first != waypoint_list_.end())
                f.second = true;
-               
+
        return f;
  }
+
 ValueNode_Animated::const_findresult
 ValueNode_Animated::find_time(const Time &x)const
 {
        const_findresult        f;
        f.second = false;
-       
+
        //search for it... and set the bool part of the return value to true if we found it!
        f.first = std::find_if(waypoint_list_.begin(), waypoint_list_.end(), timecmp(x));
        if(f.first != waypoint_list_.end())
                f.second = true;
-               
+
        return f;
 }