1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
12 */
13
14 #include <osg/Sequence>
15 #include <osg/Notify>
16
17 using namespace osg;
18
19 /**
20 * Sequence constructor.
21 */
Sequence()22 Sequence::Sequence() :
23 Group(),
24 _value(-1),
25 _now(0.0),
26 _start(-1.0),
27 _totalTime(0.),
28 _resetTotalTime(true),
29 _loopMode(LOOP),
30 _begin(0),
31 _end(-1),
32 _speed(0),
33 _nreps(-1),
34 _nrepsRemain(-1),
35 _step(0),
36 _defaultTime(1.),
37 _lastFrameTime(0.),
38 _saveRealLastFrameTime(-1.),
39 _saveRealLastFrameValue(0),
40 _mode(STOP),
41 _sync(false),
42 _clearOnStop(false)
43
44 {
45 setNumChildrenRequiringUpdateTraversal(1);
46 }
47
Sequence(const Sequence & seq,const CopyOp & copyop)48 Sequence::Sequence(const Sequence& seq, const CopyOp& copyop) :
49 Group(seq, copyop),
50 _value(seq._value),
51 _now(seq._now),
52 _start(seq._start),
53 _frameTime(seq._frameTime),
54 _totalTime(seq._totalTime),
55 _resetTotalTime(seq._resetTotalTime),
56 _loopMode(seq._loopMode),
57 _begin(seq._begin),
58 _end(seq._end),
59 _speed(seq._speed),
60 _nreps(seq._nreps),
61 _nrepsRemain(seq._nrepsRemain),
62 _step(seq._step),
63 _defaultTime(seq._defaultTime),
64 _lastFrameTime(seq._lastFrameTime),
65 _saveRealLastFrameTime(seq._saveRealLastFrameTime),
66 _saveRealLastFrameValue(seq._saveRealLastFrameValue),
67 _mode(seq._mode),
68 _sync(seq._sync),
69 _clearOnStop(seq._clearOnStop)
70 {
71 setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1);
72 }
73
addChild(Node * child)74 bool Sequence::addChild( Node *child)
75 {
76 return Sequence::insertChild( _children.size(), child, _defaultTime);
77 }
78
addChild(Node * child,double t)79 bool Sequence::addChild( Node *child, double t)
80 {
81 return Sequence::insertChild( _children.size(), child, t);
82 }
83
insertChild(unsigned int index,Node * child)84 bool Sequence::insertChild( unsigned int index, Node *child)
85 {
86 return Sequence::insertChild(index, child, _defaultTime);
87 }
88
insertChild(unsigned int index,Node * child,double t)89 bool Sequence::insertChild( unsigned int index, Node *child, double t)
90 {
91 if (Group::insertChild(index,child))
92 {
93 if (index>=_frameTime.size())
94 {
95 Sequence::setTime(index, t);
96 }
97 _resetTotalTime = true;
98 return true;
99 }
100 return false;
101 }
102
removeChild(Node * child)103 bool Sequence::removeChild( Node *child )
104 {
105 if (Group::removeChild(child ))
106 {
107 unsigned int pos = getChildIndex(child);
108 if (pos < _children.size())
109 return Sequence::removeChildren(pos,1);
110 else
111 return false;
112 }
113 else
114 return false;
115 }
116
removeChildren(unsigned int pos,unsigned int numChildrenToRemove)117 bool Sequence::removeChildren(unsigned int pos,unsigned int numChildrenToRemove)
118 {
119 if (pos<_frameTime.size())
120 _frameTime.erase(_frameTime.begin()+pos,
121 osg::minimum(_frameTime.begin()+(pos+numChildrenToRemove),
122 _frameTime.end()) );
123 _resetTotalTime = true;
124 return Group::removeChildren(pos,numChildrenToRemove);
125 }
126
127
128 // if frame >= _frameTime.size() then extend _frameTime to have frame-1 items
129 // a time <0 will get set to 0
setTime(unsigned int frame,double t)130 void Sequence::setTime(unsigned int frame, double t)
131 {
132 if (t<0.) t = 0.0;
133 unsigned int sz = _frameTime.size();
134 if (frame < sz)
135 {
136 _frameTime[frame] = t;
137 }
138 else
139 {
140 for (unsigned int i = sz; i <= frame; i++)
141 {
142 _frameTime.push_back(t);
143 }
144 }
145
146 }
147
148 // returns a frame time of -1 if frame is out of range
getTime(unsigned int frame) const149 double Sequence::getTime(unsigned int frame) const
150 {
151 if (frame < _frameTime.size())
152 return _frameTime[frame];
153 else
154 return -1.0f;
155 }
156
setInterval(LoopMode mode,int begin,int end)157 void Sequence::setInterval(LoopMode mode, int begin, int end)
158 {
159 _loopMode = mode;
160 _end = end;
161 _begin = begin;
162
163 // _value based on _begin & _end
164 _value = -1;
165
166 _resetTotalTime = true;
167
168 }
169
setDuration(float speed,int nreps)170 void Sequence::setDuration(float speed, int nreps)
171 {
172 _speed = speed;
173 // -1 means loop forever
174 _nreps = (nreps < 0 ? -1:nreps);
175 // countdown of laps around the track
176 _nrepsRemain = _nreps;
177 }
178
setMode(SequenceMode mode)179 void Sequence::setMode(SequenceMode mode)
180 {
181 int ubegin, uend;
182
183 switch (mode)
184 {
185 case START:
186 // restarts sequence from beginning
187 _value = -1;
188
189 // Figure out which direction to start stepping the sequence
190 ubegin = (_begin < 0 ? (int)_frameTime.size()-1: _begin);
191 uend = (_end < 0 ? (int)_frameTime.size()-1: _end);
192 _step = (ubegin > uend ? -1 : 1);
193
194 _start = -1.0;
195 _mode = mode;
196 if (_saveRealLastFrameTime>=0.)
197 {
198 _frameTime[_saveRealLastFrameValue] = _saveRealLastFrameTime;
199 _saveRealLastFrameTime = -1.;
200 }
201 break;
202 case STOP:
203 _mode = mode;
204 break;
205 case PAUSE:
206 if (_mode == START)
207 _mode = PAUSE;
208 break;
209 case RESUME:
210 if (_mode == PAUSE)
211 _mode = START;
212 break;
213 }
214 }
215
traverse(NodeVisitor & nv)216 void Sequence::traverse(NodeVisitor& nv)
217 {
218 if (getNumChildren()==0) return;
219
220 const FrameStamp* framestamp = nv.getFrameStamp();
221 if (framestamp)
222 {
223 _now = framestamp->getSimulationTime();
224 }
225
226
227 if (nv.getVisitorType()==NodeVisitor::UPDATE_VISITOR &&
228 _mode == START &&
229 !_frameTime.empty() && getNumChildren()!=0)
230 {
231
232 // if begin or end < 0, make it last frame
233 int _ubegin = (_begin < 0 ? (int)_frameTime.size()-1: _begin);
234 int _uend = (_end < 0 ? (int)_frameTime.size()-1: _end);
235
236 int _sbegin = osg::minimum(_ubegin,_uend);
237 int _send = osg::maximum(_ubegin,_uend);
238
239 if (framestamp)
240 {
241 // hack for last frame time
242 if (_lastFrameTime>0. && _nrepsRemain==1 && _saveRealLastFrameTime<0.)
243 {
244 if ( _loopMode == LOOP)
245 {
246 if ((_step>0 && _value!=_send) || (_step<0 && _value!=_sbegin))
247 {
248 _saveRealLastFrameTime=_frameTime[_uend];
249 _saveRealLastFrameValue = _uend;
250 _frameTime[_uend] = _lastFrameTime;
251 _resetTotalTime = true;
252 }
253 }
254 else
255 {
256 if (_step>0 && _value!=_sbegin)
257 {
258 _saveRealLastFrameTime=_frameTime[_send];
259 _saveRealLastFrameValue = _send;
260 _frameTime[_send] = _lastFrameTime;
261 _resetTotalTime = true;
262 }
263 else if (_step<0 && _value!=_send)
264 {
265 _saveRealLastFrameTime=_frameTime[_sbegin];
266 _saveRealLastFrameValue = _sbegin;
267 _frameTime[_sbegin] = _lastFrameTime;
268 _resetTotalTime = true;
269 }
270 }
271 }
272
273 // I never know when to stop!
274 // more fun for last frame time
275 if (_nrepsRemain==0)
276 {
277 if (!_clearOnStop)
278 {
279 _mode = STOP;
280 }
281 else
282 {
283 if ( (_loopMode == LOOP) &&
284 ( (_step>0 && _value!=_send) ||
285 (_step<0 && _value!=_sbegin)))
286 {
287 _mode = STOP;
288 }
289 else if ( (_loopMode == SWING) &&
290 ( (_step<0 && _value!=_send) ||
291 (_step>0 && _value!=_sbegin)))
292 {
293 _mode = STOP;
294 }
295
296 }
297 }
298
299 // update local variables
300 _update();
301
302
303 // now for the heavy lifting! three options
304 // 1) still in the same frame, so have nothing to do
305 // 2) just in the next frame
306 // 3) need to calculate everything based on elapsed time
307 if ((_now - _start) > _frameTime[_value]*osg::absolute(_speed))
308 { // case 2 or case 3
309 // most of the time it's just the next frame in the sequence
310 int nextValue = _getNextValue();
311 if (!_sync ||
312 ((_now - _start) <= (_frameTime[_value]+_frameTime[nextValue])*osg::absolute(_speed)) )
313 {
314 _start += _frameTime[_value]*osg::absolute(_speed);
315 // repeat or change directions?
316 if ( (_step>0 && nextValue==_send) ||
317 (_step<0 && nextValue==_sbegin))
318 {
319 if (_nreps>0)
320 _nrepsRemain--;
321
322 // change direction
323 if (_loopMode == SWING)
324 _step = -_step;
325
326 }
327 _value = nextValue;
328 }
329 else // case 3
330 {
331 // recalculate everything based on elapsed time
332
333 // elapsed time from start of the frame
334 double deltaT = _now - _start;
335
336 // factors _speed into account
337 double adjTotalTime = _totalTime*osg::absolute(_speed);
338
339 // how many laps?
340 int loops = (int)(deltaT/adjTotalTime);
341
342
343 // adjust reps & quick check to see if done because reps used up
344
345 if (_nreps>0)
346 {
347 if (_loopMode == LOOP)
348 _nrepsRemain -= loops;
349 else
350 _nrepsRemain -= 2*loops;
351
352 if (_nrepsRemain<=0)
353 {
354 _nrepsRemain = 0;
355 _mode = STOP;
356 OSG_WARN << "stopping because elapsed time greater or equal to time remaining to repeat the sequence\n";
357 }
358 }
359
360 // deduct off time for laps- _value shouldn't change as it's modulo the total time
361 double jumpStart = ((double)loops * adjTotalTime);
362
363 // step through frames one at a time until caught up
364 while (deltaT-jumpStart > _frameTime[_value]*osg::absolute(_speed))
365 {
366 jumpStart += _frameTime[_value]*osg::absolute(_speed );
367 _value = _getNextValue();
368 }
369
370 // set start time
371 _start += jumpStart;
372 }
373 }
374 }
375 else
376 OSG_WARN << "osg::Sequence::traverse(NodeVisitor&) requires a valid FrameStamp to function, sequence not updated.\n";
377
378 }
379
380 // now do the traversal
381 if (nv.getTraversalMode()==NodeVisitor::TRAVERSE_ACTIVE_CHILDREN)
382 {
383 if ( !((_mode == STOP) && _clearOnStop) &&
384 (getValue()>=0 && getValue()<(int)_children.size()) )
385 {
386 _children[getValue()]->accept(nv);
387 }
388 }
389 else
390 {
391 Group::traverse(nv);
392 }
393
394 }
395
_getNextValue()396 int Sequence::_getNextValue()
397 {
398 if (_frameTime.empty() || getNumChildren()==0) return 0;
399
400 // if begin or end < 0, make it last frame
401 int _ubegin = (_begin < 0 ? (int)_frameTime.size()-1: _begin);
402 int _uend = (_end < 0 ? (int)_frameTime.size()-1: _end);
403
404 int _sbegin = osg::minimum(_ubegin,_uend);
405 int _send = osg::maximum(_ubegin,_uend);
406
407 int v = _value + _step * static_cast<int>(osg::sign(_speed));
408
409 if (_sbegin==_send)
410 {
411 return _sbegin;
412 }
413 else if (v<=_send && v>=_sbegin)
414 {
415 return v;
416 }
417 else
418 {
419 int vs = _send - _sbegin + 1;
420 if (_loopMode == LOOP)
421 {
422 v = ((v-_sbegin)%vs) + _sbegin;
423 if (v<_sbegin)
424 {
425 v+=vs;
426 }
427
428 return v;
429 }
430 else // SWING
431 {
432 if (v>_send)
433 return (2*_send-v);
434 else
435 return (2*_sbegin-v);
436
437 }
438 }
439
440 }
441
_update()442 void Sequence::_update()
443 {
444 if (_frameTime.empty()) return;
445
446 // if begin or end < 0, make it last frame
447 int _ubegin = (_begin < 0 ? (int)_frameTime.size()-1: _begin);
448 int _uend = (_end < 0 ? (int)_frameTime.size()-1: _end);
449
450 int _sbegin = osg::minimum(_ubegin,_uend);
451 int _send = osg::maximum(_ubegin,_uend);
452
453 // if _value<0, new or restarted
454 if (_value<0)
455 {
456 _value = (_begin < 0 ? (int)_frameTime.size()-1: _begin);
457 _resetTotalTime = true;
458 }
459
460 // if _start<0, new or restarted
461 if (_start<0)
462 {
463 _start = _now;
464 _resetTotalTime = true;
465 }
466
467 // need to calculate time of a complete sequence?
468 // time is different depending on loop mode
469 if (_resetTotalTime)
470 {
471 if (_loopMode == LOOP)
472 {
473 _totalTime = 0.0;
474 for (int i=_sbegin; i<=_send; i++)
475 {
476 _totalTime += _frameTime[i];
477 }
478 }
479 else //SWING
480 {
481 _totalTime = _frameTime[_sbegin];
482 // ones in the middle get counted twice: 0 1 2 3 4 3 2 1 0
483 for (int i=_sbegin+1; i<_send; i++)
484 {
485 _totalTime += 2*_frameTime[i];
486 }
487 if (_sbegin != _send)
488 {
489 _totalTime += _frameTime[_send];
490 }
491 }
492
493 _resetTotalTime = false;
494 }
495
496 }
497