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