root/OpenSceneGraph/trunk/src/osg/Sequence.cpp @ 13041

Revision 13041, 13.2 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

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