Sleeping Wombat Common Library  0.50.0
swCommonLibrary
KeySet.h
Go to the documentation of this file.
1 #pragma once
2 
9 #include "Key.h"
12 
13 #include <vector>
14 #include <algorithm>
15 #include <assert.h>
16 
17 
24 template< typename KeyType >
25 struct KeySet
26 {
27 public:
29 public:
30  std::vector< Key< KeyType > > Keys;
31  std::vector< UPtr< Interpolator > > Interpolators;
32 
33 public:
35  explicit KeySet ();
36 
37  Key< KeyType >* GetKey ( TimeType time );
38  bool AddKey ( TimeType time, const KeyType& value );
39  bool AddKey ( TimeType time, const KeyType& value, InterpolatorType type );
40  bool UpdateKey ( TimeType time, const KeyType& value );
41  bool RemoveKey ( TimeType time );
42 
43  KeyType Evaluate ( TimeType time );
44 
45  bool ChangeInterpolator ( Size idx, UPtr< Interpolator >&& interpolator );
46 
47 private:
48 
49  typename std::vector< Key< KeyType > >::iterator FindKey ( TimeType time );
50  typename std::vector< Key< KeyType > >::iterator FindPlace ( TimeType time );
51 
55  void AddDefaultInterpolator ( Size keyIndex );
57  void UpdateInterpolator ( Size index );
58 };
59 
60 
61 //====================================================================================//
62 // Implementation
63 //====================================================================================//
64 
65 extern const TimeType epsilon;
66 
67 // ================================ //
68 //
69 template< typename KeyType, template< typename KeyType > class InterpolatorType >
70 UPtr< const IInterpolator< KeyType > > CastConst ( UPtr< InterpolatorType< KeyType > >& interpolator )
71 {
72  return std::static_pointer_cast< const IInterpolator< KeyType > >( interpolator );
73 }
74 
75 // ================================ //
76 //
77 template< typename KeyType >
79 {
80  Key< KeyType > firstKey;
81  firstKey.Time = TimeType( 0.0 );
82  firstKey.Value = KeyType();
83 
84  Keys.push_back( std::move( firstKey ) );
85 }
86 
87 // ================================ //
88 //
89 template< typename KeyType >
90 inline Key< KeyType >* KeySet< KeyType >::GetKey ( TimeType time )
91 {
92  auto iter = FindKey( time );
93  if( iter != Keys.end() )
94  return &( *iter );
95  return nullptr;
96 }
97 
101 template< typename KeyType >
102 inline bool KeySet< KeyType >::AddKey ( TimeType time, const KeyType& value )
103 {
104  auto iter = FindPlace( time );
105 
106  if( iter == Keys.end() )
107  {
108  Keys.push_back( Key< KeyType >( time, value ) );
109  AddDefaultInterpolator( Keys.size() - 1 );
110 
111  return true;
112  }
113 
114  // Key exists. Update it.
115  if( abs( iter->Time - time ) < epsilon )
116  {
117  iter->Value = value;
118  return false;
119  }
120 
121  // Add new key in the middle of vector.
122  iter = Keys.insert( iter, Key< KeyType >( time, value ) );
123  AddDefaultInterpolator( std::distance( Keys.begin(), iter ) );
124 
125  return true;
126 }
127 
133 template< typename KeyType >
134 inline bool KeySet< KeyType >::AddKey ( TimeType time, const KeyType& value, InterpolatorType type )
135 {
136  return false;
137 }
138 
141 template< typename KeyType >
142 inline bool KeySet< KeyType >::UpdateKey ( TimeType time, const KeyType& value )
143 {
144  auto iter = FindKey( time );
145  if( iter == Keys.end() )
146  return false;
147 
148  iter->Value = value;
149 
150  auto keyIdx = std::distance( Keys.begin(), iter );
151  UpdateInterpolator( keyIdx );
152  UpdateInterpolator( keyIdx - 1 );
153 
154  return true;
155 }
156 
161 template< typename KeyType >
162 inline bool KeySet< KeyType >::RemoveKey ( TimeType time )
163 {
164  if( Keys.size() <= 1 )
165  return false;
166 
167  auto iter = FindKey( time );
168  if( iter == Keys.end() )
169  return false;
170 
171  iter = Keys.erase( iter );
172 
173  // Remove interplator.
174  auto keyIdx = std::distance( Keys.begin(), iter );
175  auto interIter = Interpolators.erase( Interpolators.begin() + keyIdx );
176 
177  Size interpolatorIdx = std::distance( Interpolators.begin(), interIter );
178  UpdateInterpolator( interpolatorIdx );
179  UpdateInterpolator( interpolatorIdx - 1 );
180 
181  return true;
182 }
183 
184 // ================================ //
185 //
186 template< typename KeyType >
187 inline KeyType KeySet< KeyType >::Evaluate ( TimeType time )
188 {
189  if( Keys.size() == 1 )
190  return Keys[ 0 ].Value;
191 
194  auto iter = Keys.begin();
195  for( ; iter != Keys.end(); ++iter )
196  {
197  if( iter->Time > time )
198  break;
199  }
200 
201  Size keyIdx = std::distance( Keys.begin(), iter );
202 
203  if( keyIdx >= Keys.size() )
204  return Keys.back().Value;
205  if( keyIdx == 0 )
206  return Keys[ 0 ].Value;
207 
208  return Interpolators[ keyIdx - 1 ]->Interpolate( time, Keys[ keyIdx - 1 ], Keys[ keyIdx ] );
209 }
210 
211 // ================================ //
212 //
213 template< typename KeyType>
214 inline bool KeySet< KeyType >::ChangeInterpolator ( Size idx, UPtr< Interpolator >&& interpolator )
215 {
216  if( idx < Interpolators.size() )
217  {
218  Interpolators[ idx ] = std::move( interpolator );
219  UpdateInterpolator( idx );
220 
221  return true;
222  }
223 
224  return false;
225 }
226 
227 //====================================================================================//
228 // Internal functions
229 //====================================================================================//
230 
231 
232 // ================================ //
233 //
234 template< typename KeyType >
235 inline typename std::vector< Key< KeyType > >::iterator KeySet< KeyType >::FindKey ( TimeType time )
236 {
237  Key< KeyType > fakeKey;
238  fakeKey.Time = time;
239 
240  auto iterRange = std::equal_range( Keys.begin(), Keys.end(), fakeKey );
241 
242  assert( std::distance( iterRange.first, iterRange.second ) <= 1 );
243  if( std::distance( iterRange.first, iterRange.second ) == 1 )
244  return iterRange.first;
245  else
246  return Keys.end();
247 }
248 
249 // ================================ //
250 //
251 template< typename KeyType >
252 inline typename std::vector< Key< KeyType > >::iterator KeySet< KeyType >::FindPlace ( TimeType time )
253 {
254  Key< KeyType > fakeKey;
255  fakeKey.Time = time;
256 
257  auto iter = std::lower_bound( Keys.begin(), Keys.end(), fakeKey );
258  return iter;
259 }
260 
261 // ================================ //
262 //
263 template< typename KeyType >
264 inline void KeySet< KeyType >::AddDefaultInterpolator ( Size keyIndex )
265 {
266  Size leftKeyIdx;
267  Size rightKeyIdx;
268 
269  if( keyIndex == Keys.size() - 1 )
270  {
271  leftKeyIdx = keyIndex - 1;
272  rightKeyIdx = keyIndex;
273  }
274  else
275  {
276  leftKeyIdx = keyIndex;
277  rightKeyIdx = keyIndex + 1;
278  }
279 
280 
281  // We always have at least one key and we already added the second.
282  auto& leftKey = Keys[ leftKeyIdx ];
283  auto& rightKey = Keys[ rightKeyIdx ];
284 
285  // Create new interpolator.
286  auto& leftInterpolator = keyIndex > 0 && keyIndex < Interpolators.size() ? Interpolators[ keyIndex - 1 ] : MakeUPtr< DummyInterpolator< KeyType > >();
287  auto& rightInterpolator = keyIndex < Interpolators.size() ? Interpolators[ keyIndex ] : MakeUPtr< DummyInterpolator< KeyType > >();
288 
289  auto interpolator = DefaultInterpolators::Create< KeyType >( leftKey, rightKey, CastConst( leftInterpolator ), CastConst( rightInterpolator ) );
290 
291  // Add interpolator
292  if( keyIndex == Keys.size() - 1 )
293  Interpolators.push_back( std::move( interpolator ) );
294  else
295  Interpolators.insert( Interpolators.begin() + keyIndex, std::move( interpolator ) );
296 
297 
298  // Update sourrounding interpolators
299  UpdateInterpolator( keyIndex - 1 );
300  UpdateInterpolator( keyIndex + 1 ); // Note: We inserted interpolator under keyIndex.
301 }
302 
303 // ================================ //
304 //
305 template< typename KeyType >
306 inline void KeySet< KeyType >::UpdateInterpolator ( Size index )
307 {
308  // Updated interpolator must exist. Note: index is unsigned and is always greater than zero.
309  if( index >= Interpolators.size() )
310  return;
311 
312  // KeySet is in proper state.
313  assert( Keys.size() == Interpolators.size() + 1 );
314 
315  auto& leftInterpolator = index >= 1 ? CastConst( Interpolators[ index - 1 ] ) : CastConst( MakeUPtr< DummyInterpolator< KeyType > >() );
316  auto& rightInterpolator = index + 1 < Interpolators.size() ? CastConst( Interpolators[ index + 1 ] ) : CastConst( MakeUPtr< DummyInterpolator< KeyType > >() );
317 
318  auto& leftKey = Keys[ index ];
319  auto& rightKey = Keys[ index + 1 ];
320 
321  auto& interpolator = Interpolators[ index ];
322 
323  interpolator->Update( leftKey, rightKey, leftInterpolator, rightInterpolator );
324 }
Base class for interpolators.
Definition: IInterpolator.h:38
Definition: UPtr.h:10
bool AddKey(TimeType time, const KeyType &value)
Adds key. If key exists updates this key.
Definition: KeySet.h:102
void UpdateInterpolator(Size index)
Updates interpolator under index. If interpolator doesn't exists, nothing bad happens.
Definition: KeySet.h:306
bool UpdateKey(TimeType time, const KeyType &value)
Updates key.
Definition: KeySet.h:142
KeyType Evaluate(TimeType time)
Definition: KeySet.h:187
Animation key.
Definition: IInterpolator.h:21
Set of animation keys and interpolators.
Definition: KeySet.h:25
KeySet()
Constructor insert default KeyType in time 0.0;.
Definition: KeySet.h:78
void AddDefaultInterpolator(Size keyIndex)
Adds default interpolator for given type. Adds interpolator defined by function DefaultInterpolators:...
Definition: KeySet.h:264
bool RemoveKey(TimeType time)
Removes key. Last key can't be removed.
Definition: KeySet.h:162
Temporary interpolator for internal use.
Definition: IInterpolator.h:67