211 lines
5.6 KiB
C++
211 lines
5.6 KiB
C++
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
|
|
*
|
|
* This library is open source and may be redistributed and/or modified under
|
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
|
* (at your option) any later version. The full license is in LICENSE file
|
|
* included with this distribution, and on the openscenegraph.org website.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* OpenSceneGraph Public License for more details.
|
|
*/
|
|
|
|
#include <osg/Sequence>
|
|
#include <osg/Notify>
|
|
|
|
using namespace osg;
|
|
|
|
/**
|
|
* Sequence constructor.
|
|
*/
|
|
Sequence::Sequence() :
|
|
Group(),
|
|
_value(-1),
|
|
_last(-1.0f),
|
|
_step(1),
|
|
_loopMode(LOOP),
|
|
_begin(0),
|
|
_end(-1),
|
|
_speed(0),
|
|
_nreps(0),
|
|
_nrepsremain(0),
|
|
_mode(STOP)
|
|
{
|
|
setNumChildrenRequiringUpdateTraversal(1);
|
|
}
|
|
|
|
Sequence::Sequence(const Sequence& seq, const CopyOp& copyop) :
|
|
Group(seq, copyop),
|
|
_value(seq._value),
|
|
_last(seq._last),
|
|
_frameTime(seq._frameTime),
|
|
_step(seq._step),
|
|
_loopMode(seq._loopMode),
|
|
_begin(seq._begin),
|
|
_end(seq._end),
|
|
_speed(seq._speed),
|
|
_nreps(seq._nreps),
|
|
_nrepsremain(seq._nrepsremain),
|
|
_mode(seq._mode)
|
|
{
|
|
setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1);
|
|
}
|
|
|
|
void Sequence::setTime(int frame, float t)
|
|
{
|
|
int sz = _frameTime.size();
|
|
//cerr << "sz=" << sz << " frame=" << frame << endl;
|
|
if (frame < sz)
|
|
_frameTime[frame] = t;
|
|
else
|
|
for (int i = sz; i < (frame+1); i++) {
|
|
_frameTime.push_back(t);
|
|
}
|
|
}
|
|
|
|
float Sequence::getTime(int frame) const
|
|
{
|
|
if (frame >= 0 && frame < (int) _frameTime.size())
|
|
return _frameTime[frame];
|
|
else
|
|
return -1.0f;
|
|
}
|
|
|
|
void Sequence::setInterval(LoopMode mode, int begin, int end)
|
|
{
|
|
_loopMode = mode;
|
|
_begin = begin;
|
|
_end = end;
|
|
|
|
// switch to beginning of interval
|
|
unsigned int nch = getNumChildren();
|
|
begin = (_begin < 0 ? nch + _begin : _begin);
|
|
end = (_end < 0 ? nch + _end : _end);
|
|
|
|
setValue(begin);
|
|
_step = (begin < end ? 1 : -1);
|
|
}
|
|
|
|
void Sequence::setDuration(float speed, int nreps)
|
|
{
|
|
_speed = (speed <= 0.0f ? 0.0f : speed);
|
|
_nreps = (nreps < 0 ? -1 : nreps);
|
|
_nrepsremain = _nreps;
|
|
}
|
|
|
|
void Sequence::setMode(SequenceMode mode)
|
|
{
|
|
switch (mode) {
|
|
case START:
|
|
// restarts sequence in 'traverse'
|
|
setValue(-1);
|
|
_mode = mode;
|
|
break;
|
|
case STOP:
|
|
_mode = mode;
|
|
break;
|
|
case PAUSE:
|
|
if (_mode == START)
|
|
_mode = PAUSE;
|
|
break;
|
|
case RESUME:
|
|
if (_mode == PAUSE)
|
|
_mode = START;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Sequence::traverse(NodeVisitor& nv)
|
|
{
|
|
// if app traversal update the frame count.
|
|
if (nv.getVisitorType()==NodeVisitor::UPDATE_VISITOR && _mode == START && _nrepsremain)
|
|
{
|
|
const FrameStamp* framestamp = nv.getFrameStamp();
|
|
if (framestamp)
|
|
{
|
|
|
|
double t = framestamp->getReferenceTime();
|
|
if (_last == -1.0)
|
|
_last = t;
|
|
|
|
// first and last frame of interval
|
|
unsigned int nch = getNumChildren();
|
|
int begin = (_begin < 0 ? nch + _begin : _begin);
|
|
int end = (_end < 0 ? nch + _end : _end);
|
|
|
|
int sw = getValue();
|
|
if (sw<0)
|
|
{
|
|
sw = begin;
|
|
_step = (begin < end ? 1 : -1);
|
|
}
|
|
|
|
// default timeout for unset values
|
|
if (sw >= (int) _frameTime.size())
|
|
{
|
|
setTime(sw, 1.0f);
|
|
}
|
|
|
|
// frame time-out?
|
|
float dur = _frameTime[sw] * _speed;
|
|
if ((t - _last) > dur) {
|
|
|
|
sw += _step;
|
|
|
|
// check interval
|
|
int ibegin = (begin < end ? begin : end);
|
|
int iend = (end > begin ? end : begin);
|
|
//cerr << this << " interval " << ibegin << "," << iend << endl;
|
|
|
|
if (sw < ibegin || sw > iend) {
|
|
// stop at last frame
|
|
if (sw < ibegin)
|
|
sw = ibegin;
|
|
else
|
|
sw = iend;
|
|
|
|
// repeat counter
|
|
if (_nrepsremain > 0)
|
|
_nrepsremain--;
|
|
|
|
if (_nrepsremain == 0) {
|
|
// stop
|
|
setMode(STOP);
|
|
}
|
|
else {
|
|
// wrap around
|
|
switch (_loopMode) {
|
|
case LOOP:
|
|
//cerr << this << " loop" << endl;
|
|
sw = begin;
|
|
break;
|
|
case SWING:
|
|
//cerr << this << " swing" << endl;
|
|
_step = -_step;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
_last = t;
|
|
}
|
|
setValue(sw);
|
|
}
|
|
else
|
|
{
|
|
osg::notify(osg::WARN) << "osg::Sequence::traverse(NodeVisitor&) requires a valid FrameStamp to function, sequence not updated.\n";
|
|
}
|
|
}
|
|
|
|
// now do the traversal
|
|
if (nv.getTraversalMode()==NodeVisitor::TRAVERSE_ACTIVE_CHILDREN)
|
|
{
|
|
if (getValue()>=0 && getValue()<(int)_children.size()) _children[getValue()]->accept(nv);
|
|
}
|
|
else
|
|
{
|
|
Group::traverse(nv);
|
|
}
|
|
}
|