root/OpenSceneGraph/trunk/src/osgAnimation/Timeline.cpp @ 10904

Revision 10904, 7.4 kB (checked in by cedricpinson, 4 years ago)

From Cedric Pinson, remove unused file Skinning, cleanup file Timeline.cpp

RevLine 
[9093]1/*  -*-c++-*-
[10561]2 *  Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
[9093]3 *
4 * This library is open source and may be redistributed and/or modified under 
5 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
6 * (at your option) any later version.  The full license is in LICENSE file
7 * included with this distribution, and on the openscenegraph.org website.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * OpenSceneGraph Public License for more details.
13*/
14
15#include <osgAnimation/Timeline>
[10344]16#include <osgAnimation/StatsVisitor>
[9628]17#include <limits.h>
[9093]18
19using namespace osgAnimation;
20
[9150]21
[10904]22Timeline::Timeline()
[9150]23{
[9370]24    _lastUpdate = 0;
25    _currentFrame = 0;
26    _fps = 25;
27    _speed = 1.0;
28    _state = Stop;
29    _initFirstFrame = false;
30    _previousFrameEvaluated = 0;
31    _evaluating = 0;
[9628]32    _numberFrame = UINT_MAX; // something like infinity
[10344]33    _collectStats = false;
34    _stats = new osg::Stats("Timeline");
[9370]35    setName("Timeline");
[9093]36}
[9150]37
[10904]38Timeline::Timeline(const Timeline& nc,const osg::CopyOp& op)
[10386]39    : Action(nc, op),
40      _actions(nc._actions)
[9150]41{
[9370]42    _lastUpdate = 0;
43    _currentFrame = 0;
44    _fps = 25;
45    _speed = 1.0;
46    _state = Stop;
47    _initFirstFrame = false;
48    _previousFrameEvaluated = 0;
49    _evaluating = 0;
[9628]50    _numberFrame = UINT_MAX; // something like infinity
[10344]51    _collectStats = false;
52    _stats = new osg::Stats("Timeline");
[9370]53    setName("Timeline");
[9150]54}
[10344]55
[10878]56void Timeline::setAnimationManager(AnimationManagerBase* manager)
57{
58    _animationManager = manager;
59}
60
[10904]61void Timeline::traverse(ActionVisitor& visitor)
[10344]62{
[10561]63    int layer = visitor.getCurrentLayer();
[10344]64    visitor.pushTimelineOnStack(this);
65    // update from high priority to low priority
66    for( ActionLayers::reverse_iterator iterAnim = _actions.rbegin(); iterAnim != _actions.rend(); ++iterAnim )
67    {
[10561]68        visitor.setCurrentLayer(iterAnim->first);
[10344]69        ActionList& list = iterAnim->second;
70        for (unsigned int i = 0; i < list.size(); i++)
71        {
72            visitor.pushFrameActionOnStack(list[i]);
73            if (list[i].second) list[i].second->accept(visitor);
74            visitor.popFrameAction();
75        }
76    }
77    visitor.popTimeline();
[10561]78    visitor.setCurrentLayer(layer);
[10344]79}
80
81
[10904]82void Timeline::setStats(osg::Stats* stats) { _stats = stats;}
83osg::Stats* Timeline::getStats() { return _stats.get();}
84void Timeline::collectStats(bool state) { _collectStats = state;}
85StatsActionVisitor* Timeline::getStatsVisitor() { return _statsVisitor.get(); }
[10344]86
[10904]87void Timeline::clearActions()
[10344]88{
89    _actions.clear();
90    _addActionOperations.clear();
91    _removeActionOperations.clear();
92}
93
[10904]94void Timeline::update(double simulationTime)
[10344]95{
96    // first time we call update we generate one frame
97    UpdateActionVisitor updateTimeline;
98    if (!_initFirstFrame)
99    {
100        _lastUpdate = simulationTime;
101        _initFirstFrame = true;
102
[10878]103
104        _animationManager->clearTargets();
[10344]105        updateTimeline.setFrame(_currentFrame);
106        accept(updateTimeline);
107
108        if (_collectStats)
109        {
110            if (!_statsVisitor)
[10904]111                _statsVisitor = new StatsActionVisitor();
[10351]112            _statsVisitor->setStats(_stats.get());
[10344]113            _statsVisitor->setFrame(_currentFrame);
114            _statsVisitor->reset();
115            accept(*_statsVisitor);
116        }
117
118        processPendingOperation();
119    }
120
121    // find the number of frame pass since the last update
122    double delta = (simulationTime - _lastUpdate);
123    double nbframes = delta * _fps * _speed;
124    unsigned int nb = static_cast<unsigned int>(floor(nbframes));
125
126    for (unsigned int i = 0; i < nb; i++)
127    {
128        if (_state == Play)
129            _currentFrame++;
130
[10878]131        _animationManager->clearTargets();
[10344]132        updateTimeline.setFrame(_currentFrame);
133        accept(updateTimeline);
134        if (_collectStats)
135        {
136            if (!_statsVisitor)
137                _statsVisitor = new StatsActionVisitor;
[10351]138            _statsVisitor->setStats(_stats.get());
[10344]139            _statsVisitor->setFrame(_currentFrame);
140            _statsVisitor->reset();
141            accept(*_statsVisitor);
142        }
143
144        processPendingOperation();
145    }
146    if (nb)
147    {
148        _lastUpdate += ((double)nb) / _fps;
149    }
150}
151
[10904]152void Timeline::removeAction(Action* action)
[10344]153{
154    if (getEvaluating())
155        _removeActionOperations.push_back(FrameAction(0, action));
156    else
157        internalRemoveAction(action);
158}
159
[10904]160void Timeline::addActionAt(unsigned int frame, Action* action, int priority)
[10344]161{
[10878]162    // skip if this action has already been added this frame
163    for (CommandList::iterator it = _addActionOperations.begin(); it != _addActionOperations.end(); ++it)
164    {
165        Command& command = *it;
166        if (command._action.second.get() == action) {
167            osg::notify(osg::INFO) << "Timeline::addActionAt command " << action->getName() << " already added this frame, declined" << std::endl;
168            return;
169        }
170    }
171
172    if (isActive(action))
173    {
174        osg::notify(osg::INFO) << "Timeline::addActionAt command " << action->getName() << " already active, remove the old" << std::endl;
175        removeAction(action);
176    }
177
[10344]178    if (getEvaluating())
179        _addActionOperations.push_back(Command(priority,FrameAction(frame, action)));
180    else
181        internalAddAction(priority, FrameAction(frame, action));
182}
[10904]183void Timeline::addActionAt(double t, Action* action, int priority)
[10344]184{
185    unsigned int frame = static_cast<unsigned int>(floor(t * _fps));
186    addActionAt(frame, action, priority);
187}
188
[10904]189void Timeline::addActionNow(Action* action, int priority)
[10344]190{
[10394]191    addActionAt(getCurrentFrame()+1, action, priority);
[10344]192}
193
[10904]194void Timeline::processPendingOperation()
[10344]195{
196    // process all pending add action operation
197    while( !_addActionOperations.empty())
198    {
199        internalAddAction(_addActionOperations.back()._priority, _addActionOperations.back()._action);
200        _addActionOperations.pop_back();
201    }
202
203    // process all pending remove action operation
204    while( !_removeActionOperations.empty())
205    {
206        internalRemoveAction(_removeActionOperations.back().second.get());
207        _removeActionOperations.pop_back();
208    }
209}
210
[10904]211void Timeline::internalRemoveAction(Action* action)
[10344]212{
213    for (ActionLayers::iterator it = _actions.begin(); it != _actions.end(); it++)
214    {
215        ActionList& fa = it->second;
216        for (unsigned int i = 0; i < fa.size(); i++)
217            if (fa[i].second.get() == action)
218            {
219                fa.erase(fa.begin() + i);
220                return;
221            }
222    }
223}
224
[10904]225void Timeline::internalAddAction(int priority, const FrameAction& ftl)
[10344]226{
227    _actions[priority].insert(_actions[priority].begin(), ftl);
228}
229
[10904]230bool Timeline::isActive(Action* activeAction)
[10344]231{
232    // update from high priority to low priority
233    for( ActionLayers::iterator iterAnim = _actions.begin(); iterAnim != _actions.end(); ++iterAnim )
234    {
235        // update all animation
236        ActionList& list = iterAnim->second;
237        for (unsigned int i = 0; i < list.size(); i++)
238        {
239            Action* action = list[i].second.get();
240            if (action == activeAction)
241            {
242                unsigned int firstFrame = list[i].first;
243                // check if current frame of timeline hit an action interval
244                if (_currentFrame >= firstFrame &&
245                    _currentFrame < (firstFrame + action->getNumFrames()) )
246                    return true;
247            }
248        }
249    }
250    return false;
251}
Note: See TracBrowser for help on using the browser.