]> git.mxchange.org Git - simgear.git/blob - simgear/props/PropertyInterpolationMgr.cxx
Remove unecessary dependency from libSimGearCore on libSimGearScene.
[simgear.git] / simgear / props / PropertyInterpolationMgr.cxx
1 // Subsystem that manages interpolation of properties.
2 //
3 // Copyright (C) 2013  Thomas Geymayer <tomgey@gmail.com>
4 //
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.
9 //
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.
14 //
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
18
19 #include "PropertyInterpolationMgr.hxx"
20 #include "PropertyInterpolator.hxx"
21 #include "props.hxx"
22
23 #include <algorithm>
24
25 namespace simgear
26 {
27
28   //----------------------------------------------------------------------------
29   PropertyInterpolationMgr::PropertyInterpolationMgr()
30   {
31     addInterpolatorFactory<NumericInterpolator>("numeric");
32
33     for( size_t i = 0; easing_functions[i].name; ++i )
34       addEasingFunction
35       (
36         easing_functions[i].name,
37         easing_functions[i].func
38       );
39   }
40
41   //----------------------------------------------------------------------------
42   void PropertyInterpolationMgr::update(double dt)
43   {
44     for( InterpolatorList::iterator it = _interpolators.begin();
45                                     it != _interpolators.end();
46                                   ++it )
47     {
48       for(double unused_time = dt;;)
49       {
50         PropertyInterpolatorRef interp = it->second;
51         unused_time = interp->update(it->first, unused_time);
52
53         if( unused_time <= 0.0 )
54           // No time left for next animation
55           break;
56
57         if( interp->_next )
58         {
59           // Step to next animation. Note that we do not invalidate or delete
60           // the current interpolator to allow for looped animations.
61           it->second = interp->_next;
62         }
63         else
64         {
65           // No more animations so just remove it
66           it = _interpolators.erase(it);
67           break;
68         }
69       }
70     }
71   }
72
73   //----------------------------------------------------------------------------
74   struct PropertyInterpolationMgr::PredicateIsSameProp
75   {
76     public:
77       PredicateIsSameProp(SGPropertyNode* node):
78         _node(node)
79       {}
80       bool operator()(const PropertyInterpolatorPair& interp) const
81       {
82         return interp.first == _node;
83       }
84     protected:
85       SGPropertyNode *_node;
86   };
87
88   //----------------------------------------------------------------------------
89   PropertyInterpolatorRef
90   PropertyInterpolationMgr::createInterpolator( const std::string& type,
91                                                 const SGPropertyNode* target,
92                                                 double duration,
93                                                 const std::string& easing )
94   {
95     InterpolatorFactoryMap::iterator interpolator_factory =
96       _interpolator_factories.find(type);
97     if( interpolator_factory == _interpolator_factories.end() )
98     {
99       SG_LOG
100       (
101         SG_GENERAL,
102         SG_WARN,
103         "PropertyInterpolationMgr: no factory found for type '" << type << "'"
104       );
105       return 0;
106     }
107
108     EasingFunctionMap::iterator easing_func = _easing_functions.find(easing);
109     if( easing_func == _easing_functions.end() )
110     {
111       SG_LOG
112       (
113         SG_GENERAL,
114         SG_WARN,
115         "PropertyInterpolationMgr: no such easing '" << type << "'"
116       );
117       return 0;
118     }
119
120     PropertyInterpolatorRef interp;
121     interp = (*interpolator_factory->second)();
122     interp->reset(target);
123     interp->_type = type;
124     interp->_duration = duration;
125     interp->_easing = easing_func->second;
126
127     return interp;
128   }
129
130   //----------------------------------------------------------------------------
131   void PropertyInterpolationMgr::interpolate( SGPropertyNode* prop,
132                                               PropertyInterpolatorRef interp )
133   {
134     // Search for active interpolator on given property
135     InterpolatorList::iterator it = std::find_if
136     (
137       _interpolators.begin(),
138       _interpolators.end(),
139       PredicateIsSameProp(prop)
140     );
141
142     if( it != _interpolators.end() )
143     {
144       // Ensure no circular reference is left
145       it->second->_next = 0;
146
147       // and now safely replace old interpolator
148       // TODO maybe cache somewhere for reuse or use allocator?
149       it->second = interp;
150     }
151     else
152       _interpolators.push_front( std::make_pair(prop, interp) );
153   }
154
155   //----------------------------------------------------------------------------
156   void PropertyInterpolationMgr::addInterpolatorFactory
157   (
158     const std::string& type,
159     InterpolatorFactory factory
160   )
161   {
162     if( _interpolator_factories.find(type) != _interpolator_factories.end() )
163       SG_LOG
164       (
165         SG_GENERAL,
166         SG_WARN,
167         "PropertyInterpolationMgr: replace existing factor for type " << type
168       );
169
170     _interpolator_factories[type] = factory;
171   }
172
173   //----------------------------------------------------------------------------
174   void PropertyInterpolationMgr::addEasingFunction( const std::string& type,
175                                                     easing_func_t func )
176   {
177     // TODO it's probably time for a generic factory map
178     if( _easing_functions.find(type) != _easing_functions.end() )
179       SG_LOG
180       (
181         SG_GENERAL,
182         SG_WARN,
183         "PropertyInterpolationMgr: replace existing easing function " << type
184       );
185
186     _easing_functions[type] = func;
187   }
188
189 } // namespace simgear