1 // Subsystem that manages interpolation of properties.
3 // Copyright (C) 2013 Thomas Geymayer <tomgey@gmail.com>
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Library General Public
7 // License as published by the Free Software Foundation; either
8 // version 2 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Library General Public License for more details.
15 // You should have received a copy of the GNU Library General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "PropertyInterpolationMgr.hxx"
20 #include "PropertyInterpolator.hxx"
28 //----------------------------------------------------------------------------
29 PropertyInterpolationMgr::PropertyInterpolationMgr()
31 addInterpolatorFactory<NumericInterpolator>("numeric");
33 for( size_t i = 0; easing_functions[i].name; ++i )
36 easing_functions[i].name,
37 easing_functions[i].func
41 //----------------------------------------------------------------------------
42 void PropertyInterpolationMgr::update(double dt)
45 dt = _rt_prop->getDoubleValue();
47 for( InterpolatorList::iterator it = _interpolators.begin();
48 it != _interpolators.end();
51 for(double unused_time = dt;;)
53 PropertyInterpolatorRef interp = it->second;
54 unused_time = interp->update(*it->first, unused_time);
56 if( unused_time <= 0.0 )
57 // No time left for next animation
62 // Step to next animation. Note that we do not invalidate or delete
63 // the current interpolator to allow for looped animations.
64 it->second = interp->_next;
68 // No more animations so just remove it
69 it = _interpolators.erase(it);
76 //----------------------------------------------------------------------------
77 struct PropertyInterpolationMgr::PredicateIsSameProp
80 PredicateIsSameProp(SGPropertyNode* node):
83 bool operator()(const PropertyInterpolatorPair& interp) const
85 return interp.first == _node;
88 SGPropertyNode *_node;
91 //----------------------------------------------------------------------------
93 PropertyInterpolationMgr::createInterpolator( const std::string& type,
94 const SGPropertyNode& target,
96 const std::string& easing )
98 InterpolatorFactoryMap::iterator interpolator_factory =
99 _interpolator_factories.find(type);
100 if( interpolator_factory == _interpolator_factories.end() )
106 "PropertyInterpolationMgr: no factory found for type '" << type << "'"
111 EasingFunctionMap::iterator easing_func = _easing_functions.find(easing);
112 if( easing_func == _easing_functions.end() )
118 "PropertyInterpolationMgr: no such easing '" << type << "'"
123 PropertyInterpolator* interp;
124 interp = (*interpolator_factory->second)();
125 interp->reset(target);
126 interp->_type = type;
127 interp->_duration = duration;
128 interp->_easing = easing_func->second;
133 //----------------------------------------------------------------------------
134 bool PropertyInterpolationMgr::interpolate( SGPropertyNode* prop,
135 PropertyInterpolatorRef interp )
140 // Search for active interpolator on given property
141 InterpolatorList::iterator it = std::find_if
143 _interpolators.begin(),
144 _interpolators.end(),
145 PredicateIsSameProp(prop)
150 // Without new interpolator just remove old one
151 if( it != _interpolators.end() )
152 _interpolators.erase(it);
156 if( it != _interpolators.end() )
158 // Ensure no circular reference is left
159 it->second->_next = 0;
161 // and now safely replace old interpolator
162 // TODO maybe cache somewhere for reuse or use allocator?
166 _interpolators.push_front( std::make_pair(prop, interp) );
171 //----------------------------------------------------------------------------
172 bool PropertyInterpolationMgr::interpolate( SGPropertyNode* prop,
173 const std::string& type,
174 const SGPropertyNode& target,
176 const std::string& easing )
181 createInterpolator(type, target, duration, easing)
185 //----------------------------------------------------------------------------
186 bool PropertyInterpolationMgr::interpolate( SGPropertyNode* prop,
187 const std::string& type,
188 const PropertyList& values,
189 const double_list& deltas,
190 const std::string& easing )
192 if( values.size() != deltas.size() )
193 SG_LOG(SG_GENERAL, SG_WARN, "interpolate: sizes do not match");
195 size_t num_values = std::min(values.size(), deltas.size());
196 PropertyInterpolatorRef first_interp, cur_interp;
197 for(size_t i = 0; i < num_values; ++i)
201 PropertyInterpolator* interp =
202 createInterpolator(type, *values[i], deltas[i], easing);
205 first_interp = interp;
207 cur_interp->_next = interp;
212 return interpolate(prop, first_interp);
215 //----------------------------------------------------------------------------
216 void PropertyInterpolationMgr::addInterpolatorFactory
218 const std::string& type,
219 InterpolatorFactory factory
222 if( _interpolator_factories.find(type) != _interpolator_factories.end() )
227 "PropertyInterpolationMgr: replace existing factor for type " << type
230 _interpolator_factories[type] = factory;
233 //----------------------------------------------------------------------------
234 void PropertyInterpolationMgr::addEasingFunction( const std::string& type,
237 // TODO it's probably time for a generic factory map
238 if( _easing_functions.find(type) != _easing_functions.end() )
243 "PropertyInterpolationMgr: replace existing easing function " << type
246 _easing_functions[type] = func;
249 //----------------------------------------------------------------------------
250 void PropertyInterpolationMgr::setRealtimeProperty(SGPropertyNode* node)
255 } // namespace simgear