From 8898f5fe52001cefb8a0b74093d4176c68404361 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Sat, 16 Mar 2013 16:36:20 +0100 Subject: [PATCH] Tweak interpolator and allow passing list of interpolation steps --- simgear/props/PropertyInterpolationMgr.cxx | 44 ++++++++++++++++++++-- simgear/props/PropertyInterpolationMgr.hxx | 12 +++++- simgear/props/PropertyInterpolator.cxx | 22 +++++------ simgear/props/PropertyInterpolator.hxx | 16 ++++---- simgear/scene/util/ColorInterpolator.cxx | 12 +++--- simgear/scene/util/ColorInterpolator.hxx | 6 +-- simgear/scene/util/parse_color_test.cxx | 16 ++++---- 7 files changed, 86 insertions(+), 42 deletions(-) diff --git a/simgear/props/PropertyInterpolationMgr.cxx b/simgear/props/PropertyInterpolationMgr.cxx index 60ff3224..e0591e60 100644 --- a/simgear/props/PropertyInterpolationMgr.cxx +++ b/simgear/props/PropertyInterpolationMgr.cxx @@ -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 ( diff --git a/simgear/props/PropertyInterpolationMgr.hxx b/simgear/props/PropertyInterpolationMgr.hxx index 96e942c1..a703158f 100644 --- a/simgear/props/PropertyInterpolationMgr.hxx +++ b/simgear/props/PropertyInterpolationMgr.hxx @@ -21,7 +21,9 @@ #include "PropertyInterpolator.hxx" +#include #include +#include #include #include @@ -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. */ diff --git a/simgear/props/PropertyInterpolator.cxx b/simgear/props/PropertyInterpolator.cxx index 79b830ca..dd010641 100644 --- a/simgear/props/PropertyInterpolator.cxx +++ b/simgear/props/PropertyInterpolator.cxx @@ -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(std::floor(cur + 0.5)) ); + if( prop.getType() == props::INT || prop.getType() == props::LONG ) + prop.setLongValue( static_cast(std::floor(cur + 0.5)) ); else - prop->setDoubleValue(cur); + prop.setDoubleValue(cur); } } // namespace simgear diff --git a/simgear/props/PropertyInterpolator.hxx b/simgear/props/PropertyInterpolator.hxx index a89b3e2d..b3bd6f8c 100644 --- a/simgear/props/PropertyInterpolator.hxx +++ b/simgear/props/PropertyInterpolator.hxx @@ -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 diff --git a/simgear/scene/util/ColorInterpolator.cxx b/simgear/scene/util/ColorInterpolator.cxx index 6abe2e11..fd2edbfc 100644 --- a/simgear/scene/util/ColorInterpolator.cxx +++ b/simgear/scene/util/ColorInterpolator.cxx @@ -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 diff --git a/simgear/scene/util/ColorInterpolator.hxx b/simgear/scene/util/ColorInterpolator.hxx index 0fad5659..568ffa04 100644 --- a/simgear/scene/util/ColorInterpolator.hxx +++ b/simgear/scene/util/ColorInterpolator.hxx @@ -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); }; diff --git a/simgear/scene/util/parse_color_test.cxx b/simgear/scene/util/parse_color_test.cxx index e82884a7..36ec882f 100644 --- a/simgear/scene/util/parse_color_test.cxx +++ b/simgear/scene/util/parse_color_test.cxx @@ -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; -- 2.39.5