From 9e9cc7859cee5d930fb03531794c5b1e499ade6b Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Sun, 17 Mar 2013 23:48:01 +0100 Subject: [PATCH] Interpolation system tweaking and add helpers to SGPropertyNode to interpolate its value --- simgear/props/PropertyInterpolationMgr.cxx | 44 ++++++++++++++++++-- simgear/props/PropertyInterpolationMgr.hxx | 25 +++++++++--- simgear/props/props.cxx | 47 ++++++++++++++++++++++ simgear/props/props.hxx | 37 +++++++++++++++++ 4 files changed, 144 insertions(+), 9 deletions(-) diff --git a/simgear/props/PropertyInterpolationMgr.cxx b/simgear/props/PropertyInterpolationMgr.cxx index e0591e60..0ec4ad79 100644 --- a/simgear/props/PropertyInterpolationMgr.cxx +++ b/simgear/props/PropertyInterpolationMgr.cxx @@ -41,6 +41,9 @@ namespace simgear //---------------------------------------------------------------------------- void PropertyInterpolationMgr::update(double dt) { + if( _rt_prop ) + dt = _rt_prop->getDoubleValue(); + for( InterpolatorList::iterator it = _interpolators.begin(); it != _interpolators.end(); ++it ) @@ -128,9 +131,12 @@ namespace simgear } //---------------------------------------------------------------------------- - void PropertyInterpolationMgr::interpolate( SGPropertyNode* prop, + bool PropertyInterpolationMgr::interpolate( SGPropertyNode* prop, PropertyInterpolatorRef interp ) { + if( !prop ) + return false; + // Search for active interpolator on given property InterpolatorList::iterator it = std::find_if ( @@ -139,6 +145,14 @@ namespace simgear PredicateIsSameProp(prop) ); + if( !interp ) + { + // Without new interpolator just remove old one + if( it != _interpolators.end() ) + _interpolators.erase(it); + return true; + } + if( it != _interpolators.end() ) { // Ensure no circular reference is left @@ -150,10 +164,26 @@ namespace simgear } else _interpolators.push_front( std::make_pair(prop, interp) ); + + return true; + } + + //---------------------------------------------------------------------------- + bool PropertyInterpolationMgr::interpolate( SGPropertyNode* prop, + const std::string& type, + const SGPropertyNode& target, + double duration, + const std::string& easing ) + { + return interpolate + ( + prop, + createInterpolator(type, target, duration, easing) + ); } //---------------------------------------------------------------------------- - void PropertyInterpolationMgr::interpolate( SGPropertyNode* prop, + bool PropertyInterpolationMgr::interpolate( SGPropertyNode* prop, const std::string& type, const PropertyList& values, const double_list& deltas, @@ -166,7 +196,7 @@ namespace simgear if( !num_values ) { SG_LOG(SG_GENERAL, SG_WARN, "interpolate: no values"); - return; + return false; } PropertyInterpolatorRef first_interp, cur_interp; @@ -185,7 +215,7 @@ namespace simgear cur_interp = interp; } - interpolate(prop, first_interp); + return interpolate(prop, first_interp); } //---------------------------------------------------------------------------- @@ -222,4 +252,10 @@ namespace simgear _easing_functions[type] = func; } + //---------------------------------------------------------------------------- + void PropertyInterpolationMgr::setRealtimeProperty(SGPropertyNode* node) + { + _rt_prop = node; + } + } // namespace simgear diff --git a/simgear/props/PropertyInterpolationMgr.hxx b/simgear/props/PropertyInterpolationMgr.hxx index a703158f..446fad94 100644 --- a/simgear/props/PropertyInterpolationMgr.hxx +++ b/simgear/props/PropertyInterpolationMgr.hxx @@ -72,8 +72,8 @@ namespace simgear PropertyInterpolator* createInterpolator( const std::string& type, const SGPropertyNode& target, - double duration = 1.0, - const std::string& easing = "swing" ); + double duration, + const std::string& easing ); /** * Add animation of the given property from current its current value to @@ -82,14 +82,20 @@ namespace simgear * @param prop Property to be interpolated * @param interp Interpolator used for interpolation */ - void interpolate( SGPropertyNode* prop, + bool interpolate( SGPropertyNode* prop, PropertyInterpolatorRef interp ); - void interpolate( SGPropertyNode* prop, + bool interpolate( SGPropertyNode* prop, + const std::string& type, + const SGPropertyNode& target, + double duration, + const std::string& easing ); + + bool interpolate( SGPropertyNode* prop, const std::string& type, const PropertyList& values, const double_list& deltas, - const std::string& easing = "linear" ); + const std::string& easing ); /** * Register factory for interpolation type. @@ -111,6 +117,13 @@ namespace simgear */ void addEasingFunction(const std::string& type, easing_func_t func); + /** + * Set property containing real time delta (not sim time) + * + * TODO better pass both deltas to all update methods... + */ + void setRealtimeProperty(SGPropertyNode* node); + protected: typedef std::map InterpolatorFactoryMap; @@ -124,6 +137,8 @@ namespace simgear InterpolatorFactoryMap _interpolator_factories; EasingFunctionMap _easing_functions; InterpolatorList _interpolators; + + SGPropertyNode_ptr _rt_prop; }; } // namespace simgear diff --git a/simgear/props/props.cxx b/simgear/props/props.cxx index f5484568..5b778a7a 100644 --- a/simgear/props/props.cxx +++ b/simgear/props/props.cxx @@ -11,6 +11,7 @@ #endif #include "props.hxx" +#include "PropertyInterpolationMgr.hxx" #include "vectorPropTemplates.hxx" #include @@ -1654,6 +1655,52 @@ SGPropertyNode::setUnspecifiedValue (const char * value) return result; } +//------------------------------------------------------------------------------ +bool SGPropertyNode::interpolate( const std::string& type, + const SGPropertyNode& target, + double duration, + const std::string& easing ) +{ + if( !_interpolation_mgr ) + { + SG_LOG(SG_GENERAL, SG_WARN, "No property interpolator available"); + + // no interpolation possible -> set to target immediately + setUnspecifiedValue( target.getStringValue() ); + return false; + } + + return _interpolation_mgr->interpolate(this, type, target, duration, easing); +} + +//------------------------------------------------------------------------------ +bool SGPropertyNode::interpolate( const std::string& type, + const PropertyList& values, + const double_list& deltas, + const std::string& easing ) +{ + if( !_interpolation_mgr ) + { + SG_LOG(SG_GENERAL, SG_WARN, "No property interpolator available"); + + // no interpolation possible -> set to last value immediately + if( !values.empty() ) + setUnspecifiedValue(values.back()->getStringValue()); + return false; + } + + return _interpolation_mgr->interpolate(this, type, values, deltas, easing); +} + +//------------------------------------------------------------------------------ +void SGPropertyNode::setInterpolationMgr(simgear::PropertyInterpolationMgr* mgr) +{ + _interpolation_mgr = mgr; +} + +simgear::PropertyInterpolationMgr* SGPropertyNode::_interpolation_mgr = 0; + +//------------------------------------------------------------------------------ std::ostream& SGPropertyNode::printOn(std::ostream& stream) const { if (!getAttribute(READ)) diff --git a/simgear/props/props.hxx b/simgear/props/props.hxx index eaf5fe14..d06f4855 100644 --- a/simgear/props/props.hxx +++ b/simgear/props/props.hxx @@ -31,6 +31,7 @@ #include +#include #include #include @@ -39,6 +40,9 @@ namespace simgear { + + class PropertyInterpolationMgr; + template std::istream& readFrom(std::istream& stream, T& result) { @@ -1237,6 +1241,37 @@ public: return setValue(&val[0]); } + /** + * Interpolate current value to target value within given time. + * + * @param type Type of interpolation ("numeric", "color", etc.) + * @param target Node containing target value + * @param duration Duration of interpolation (in seconds) + * @param easing Easing function (http://easings.net/) + */ + bool interpolate( const std::string& type, + const SGPropertyNode& target, + double duration = 0.6, + const std::string& easing = "swing" ); + + /** + * Interpolate current value to a series of values within given durations. + * + * @param type Type of interpolation ("numeric", "color", etc.) + * @param values Nodes containing intermediate and target values + * @param duration Durations for each interpolation step (in seconds) + * @param easing Easing function (http://easings.net/) + */ + bool interpolate( const std::string& type, + const simgear::PropertyList& values, + const double_list& deltas, + const std::string& easing = "swing" ); + + /** + * Set the interpolation manager used by the interpolate methods. + */ + static void setInterpolationMgr(simgear::PropertyInterpolationMgr* mgr); + /** * Print the value of the property to a stream. */ @@ -1650,6 +1685,8 @@ protected: template SGPropertyNode (Itr begin, Itr end, int index, SGPropertyNode * parent); + static simgear::PropertyInterpolationMgr* _interpolation_mgr; + private: // Get the raw value -- 2.39.5