for(double unused_time = dt;;)
{
PropertyInterpolatorRef interp = it->second;
- unused_time = interp->update(it->first, unused_time);
+ unused_time = interp->update(*it->first, unused_time);
if( unused_time <= 0.0 )
// No time left for next animation
};
//----------------------------------------------------------------------------
- PropertyInterpolatorRef
+ PropertyInterpolator*
PropertyInterpolationMgr::createInterpolator( const std::string& type,
- const SGPropertyNode* target,
+ const SGPropertyNode& target,
double duration,
const std::string& easing )
{
return 0;
}
- PropertyInterpolatorRef interp;
+ PropertyInterpolator* interp;
interp = (*interpolator_factory->second)();
interp->reset(target);
interp->_type = type;
_interpolators.push_front( std::make_pair(prop, interp) );
}
+ //----------------------------------------------------------------------------
+ void PropertyInterpolationMgr::interpolate( SGPropertyNode* prop,
+ const std::string& type,
+ const PropertyList& values,
+ const double_list& deltas,
+ const std::string& easing )
+ {
+ if( values.size() != deltas.size() )
+ SG_LOG(SG_GENERAL, SG_WARN, "interpolate: sizes do not match");
+
+ size_t num_values = std::min(values.size(), deltas.size());
+ if( !num_values )
+ {
+ SG_LOG(SG_GENERAL, SG_WARN, "interpolate: no values");
+ return;
+ }
+
+ PropertyInterpolatorRef first_interp, cur_interp;
+ for(size_t i = 0; i < num_values; ++i)
+ {
+ assert(values[i]);
+
+ PropertyInterpolator* interp =
+ createInterpolator(type, *values[i], deltas[i], easing);
+
+ if( !first_interp )
+ first_interp = interp;
+ else
+ cur_interp->_next = interp;
+
+ cur_interp = interp;
+ }
+
+ interpolate(prop, first_interp);
+ }
+
//----------------------------------------------------------------------------
void PropertyInterpolationMgr::addInterpolatorFactory
(
#include "PropertyInterpolator.hxx"
+#include <simgear/math/sg_types.hxx>
#include <simgear/misc/make_new.hxx>
+#include <simgear/props/props.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <list>
* @param duration Duration if the animation (in seconds)
* @param easing Type of easing ("linear", "swing", etc.)
*/
- PropertyInterpolatorRef
+ PropertyInterpolator*
createInterpolator( const std::string& type,
- const SGPropertyNode* target,
+ const SGPropertyNode& target,
double duration = 1.0,
const std::string& easing = "swing" );
void interpolate( SGPropertyNode* prop,
PropertyInterpolatorRef interp );
+ void interpolate( SGPropertyNode* prop,
+ const std::string& type,
+ const PropertyList& values,
+ const double_list& deltas,
+ const std::string& easing = "linear" );
+
/**
* Register factory for interpolation type.
*/
}
//----------------------------------------------------------------------------
- void PropertyInterpolator::reset(const SGPropertyNode* target)
+ void PropertyInterpolator::reset(const SGPropertyNode& target)
{
_cur_t = 0;
setTarget(target);
}
//----------------------------------------------------------------------------
- double PropertyInterpolator::update(SGPropertyNode* prop, double dt)
+ double PropertyInterpolator::update(SGPropertyNode& prop, double dt)
{
if( _cur_t == 0 )
init(prop);
}
//----------------------------------------------------------------------------
- void NumericInterpolator::setTarget(const SGPropertyNode* target)
+ void NumericInterpolator::setTarget(const SGPropertyNode& target)
{
- _end = target->getDoubleValue();
+ _end = target.getDoubleValue();
}
//----------------------------------------------------------------------------
- void NumericInterpolator::init(const SGPropertyNode* prop)
+ void NumericInterpolator::init(const SGPropertyNode& prop)
{
// If unable to get start value, immediately change to target value
- double value_start = prop->getType() == props::NONE
+ double value_start = prop.getType() == props::NONE
? _end
- : prop->getDoubleValue();
+ : prop.getDoubleValue();
_diff = _end - value_start;
}
//----------------------------------------------------------------------------
- void NumericInterpolator::write(SGPropertyNode* prop, double t)
+ void NumericInterpolator::write(SGPropertyNode& prop, double t)
{
double cur = _end - (1 - t) * _diff;
- if( prop->getType() == props::INT || prop->getType() == props::LONG )
- prop->setLongValue( static_cast<long>(std::floor(cur + 0.5)) );
+ if( prop.getType() == props::INT || prop.getType() == props::LONG )
+ prop.setLongValue( static_cast<long>(std::floor(cur + 0.5)) );
else
- prop->setDoubleValue(cur);
+ prop.setDoubleValue(cur);
}
} // namespace simgear
* Resets animation timer to zero and prepares for interpolation to new
* target value.
*/
- void reset(const SGPropertyNode* target);
+ void reset(const SGPropertyNode& target);
/**
* Set easing function to be used for interpolation.
* else time is negative indicating the remaining time until
* finished)
*/
- double update(SGPropertyNode* prop, double dt);
+ double update(SGPropertyNode& prop, double dt);
const std::string& getType() const { return _type; }
PropertyInterpolator();
- virtual void setTarget(const SGPropertyNode* target) = 0;
- virtual void init(const SGPropertyNode* prop) = 0;
- virtual void write(SGPropertyNode* prop, double t) = 0;
+ virtual void setTarget(const SGPropertyNode& target) = 0;
+ virtual void init(const SGPropertyNode& prop) = 0;
+ virtual void write(SGPropertyNode& prop, double t) = 0;
};
class NumericInterpolator:
double _end,
_diff;
- virtual void setTarget(const SGPropertyNode* target);
- virtual void init(const SGPropertyNode* prop);
- virtual void write(SGPropertyNode* prop, double t);
+ virtual void setTarget(const SGPropertyNode& target);
+ virtual void init(const SGPropertyNode& prop);
+ virtual void write(SGPropertyNode& prop, double t);
};
} // namespace simgear
{
//----------------------------------------------------------------------------
- void ColorInterpolator::setTarget(const SGPropertyNode* target)
+ void ColorInterpolator::setTarget(const SGPropertyNode& target)
{
- if( !parseColor(target->getStringValue(), _color_end) )
+ if( !parseColor(target.getStringValue(), _color_end) )
SG_LOG
(
SG_GENERAL, SG_WARN, "ColorInterpolator: failed to parse end color."
}
//----------------------------------------------------------------------------
- void ColorInterpolator::init(const SGPropertyNode* prop)
+ void ColorInterpolator::init(const SGPropertyNode& prop)
{
osg::Vec4 color_start;
- if( !parseColor(prop->getStringValue(), color_start) )
+ if( !parseColor(prop.getStringValue(), color_start) )
// If unable to get current color, immediately change to target color
color_start = _color_end;
}
//----------------------------------------------------------------------------
- void ColorInterpolator::write(SGPropertyNode* prop, double t)
+ void ColorInterpolator::write(SGPropertyNode& prop, double t)
{
osg::Vec4 color_cur = _color_end - _color_diff * (1 - t);
bool has_alpha = color_cur.a() < 0.999;
strm << ')';
- prop->setStringValue(strm.str());
+ prop.setStringValue(strm.str());
}
} // namespace simgear
osg::Vec4 _color_end,
_color_diff;
- virtual void setTarget(const SGPropertyNode* target);
- virtual void init(const SGPropertyNode* prop);
- virtual void write(SGPropertyNode* prop, double t);
+ virtual void setTarget(const SGPropertyNode& target);
+ virtual void init(const SGPropertyNode& prop);
+ virtual void write(SGPropertyNode& prop, double t);
};
color_arg.setStringValue("#000000");
simgear::PropertyInterpolator* interp = new simgear::ColorInterpolator;
- interp->reset(&color_arg);
+ interp->reset(color_arg);
- interp->update(&color_node, 0.5); // with no color it should immediately set to the target
+ interp->update(color_node, 0.5); // with no color it should immediately set to the target
VERIFY_NODE_STR(color_node, "rgb(0,0,0)");
color_arg.setStringValue("rgba(255,0,0,0.5)");
- interp->reset(&color_arg);
+ interp->reset(color_arg);
- interp->update(&color_node, 0.5);
+ interp->update(color_node, 0.5);
VERIFY_NODE_STR(color_node, "rgba(127,0,0,0.75)");
- interp->update(&color_node, 0.5);
+ interp->update(color_node, 0.5);
VERIFY_NODE_STR(color_node, "rgba(255,0,0,0.5)");
// Animation has already completed and therefore should be reset and start a
// new animation starting with the current value of the animation. As this
// is already the same as the target value, nothing should change.
- interp->update(&color_node, 0.5);
+ interp->update(color_node, 0.5);
VERIFY_NODE_STR(color_node, "rgba(255,0,0,0.5)");
color_arg.setStringValue("#00ff00");
- interp->reset(&color_arg);
- interp->update(&color_node, 1.0);
+ interp->reset(color_arg);
+ interp->update(color_node, 1.0);
VERIFY_NODE_STR(color_node, "rgb(0,255,0)");
std::cout << "all tests passed successfully!" << std::endl;