Tweak interpolator and allow passing list of interpolation steps
This commit is contained in:
parent
40be69ae8e
commit
8898f5fe52
@ -48,7 +48,7 @@ namespace simgear
|
||||
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
|
||||
@ -86,9 +86,9 @@ namespace simgear
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
PropertyInterpolatorRef
|
||||
PropertyInterpolator*
|
||||
PropertyInterpolationMgr::createInterpolator( const std::string& type,
|
||||
const SGPropertyNode* target,
|
||||
const SGPropertyNode& target,
|
||||
double duration,
|
||||
const std::string& easing )
|
||||
{
|
||||
@ -117,7 +117,7 @@ namespace simgear
|
||||
return 0;
|
||||
}
|
||||
|
||||
PropertyInterpolatorRef interp;
|
||||
PropertyInterpolator* interp;
|
||||
interp = (*interpolator_factory->second)();
|
||||
interp->reset(target);
|
||||
interp->_type = type;
|
||||
@ -152,6 +152,42 @@ namespace simgear
|
||||
_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
|
||||
(
|
||||
|
@ -21,7 +21,9 @@
|
||||
|
||||
#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>
|
||||
@ -67,9 +69,9 @@ namespace simgear
|
||||
* @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" );
|
||||
|
||||
@ -83,6 +85,12 @@ namespace simgear
|
||||
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.
|
||||
*/
|
||||
|
@ -32,7 +32,7 @@ namespace simgear
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void PropertyInterpolator::reset(const SGPropertyNode* target)
|
||||
void PropertyInterpolator::reset(const SGPropertyNode& target)
|
||||
{
|
||||
_cur_t = 0;
|
||||
setTarget(target);
|
||||
@ -45,7 +45,7 @@ namespace simgear
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double PropertyInterpolator::update(SGPropertyNode* prop, double dt)
|
||||
double PropertyInterpolator::update(SGPropertyNode& prop, double dt)
|
||||
{
|
||||
if( _cur_t == 0 )
|
||||
init(prop);
|
||||
@ -74,31 +74,31 @@ namespace simgear
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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
|
||||
|
@ -47,7 +47,7 @@ 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.
|
||||
@ -63,7 +63,7 @@ namespace simgear
|
||||
* 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; }
|
||||
|
||||
@ -78,9 +78,9 @@ namespace simgear
|
||||
|
||||
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:
|
||||
@ -90,9 +90,9 @@ namespace simgear
|
||||
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
|
||||
|
@ -25,9 +25,9 @@ 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."
|
||||
@ -35,10 +35,10 @@ namespace simgear
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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;
|
||||
|
||||
@ -46,7 +46,7 @@ namespace simgear
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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;
|
||||
@ -68,7 +68,7 @@ namespace simgear
|
||||
|
||||
strm << ')';
|
||||
|
||||
prop->setStringValue(strm.str());
|
||||
prop.setStringValue(strm.str());
|
||||
}
|
||||
|
||||
} // namespace simgear
|
||||
|
@ -37,9 +37,9 @@ 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);
|
||||
|
||||
|
||||
};
|
||||
|
@ -42,29 +42,29 @@ int main (int ac, char ** av)
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user