/*! \file valuenode_animated.cpp
** \brief Template File
**
-** $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 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
*/
/* ========================================================================= */
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;
{
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)
// that we support is linear.
second.t1()=
second.t2()=subtract_func(second.p2(),second.p1());
-
+
second.sync();
}
> curve_list_type;
curve_list_type curve_list;
-
+
// Bounds of this curve
Time r,s;
-
+
public:
ValueNode* clone(const GUID& deriv_guid)const
{
// 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;
}
//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;
}
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());
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;
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)
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());
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);
// 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;
}
}
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
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);
// 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() *=
+ // (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() *=
+ // (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
curve_list.push_back(curve);
}
}
-
+
virtual ValueBase operator()(Time t)const
{
if(waypoint_list_.empty())
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
if(iter==curve_list.end())
return waypoint_list_.back().get_value(t);
return iter->resolve(t);
- }
-};
+ }
+};
template<typename T>
//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;
Waypoint waypoint(value_node,t);
waypoint.set_parent_value_node(this);
-
+
waypoint_list_.push_back(waypoint);
WaypointList::iterator ret=waypoint_list_.end();
--ret;
virtual void on_changed()
{
ValueNode_Animated::on_changed();
-
+
if(waypoint_list_.size()<=1)
return;
std::sort(waypoint_list_.begin(),waypoint_list_.end());
// 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;
Waypoint waypoint(value_node,t);
waypoint.set_parent_value_node(this);
-
+
waypoint_list_.push_back(waypoint);
WaypointList::iterator ret=waypoint_list_.end();
--ret;
virtual void on_changed()
{
ValueNode_Animated::on_changed();
-
+
if(waypoint_list_.size()<=1)
return;
std::sort(waypoint_list_.begin(),waypoint_list_.end());
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);
{
Time curr_time(begin);
int ret(0);
-
+
// try to grab first waypoint
try
{
ret++;
}
catch(...) { }
-
+
try
{
WaypointList::iterator iter;
}
}
catch(...) { }
-
+
return ret;
}
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
waypoint.make_unique();
}
catch(...)
- {
+ {
if(waypoint_list().empty())
{
waypoint.set_value((*this)(time));
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;
closest=prev;
else
closest=next;
-
+
for(iter=waypoint_list().begin();iter!=waypoint_list().end();++iter)
{
const Real dist(abs(iter->get_time()-time));
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)
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;
}
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()));
}
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()));
*/
}
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()));
}
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:
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();
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;
}