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

Revision 13041, 7.4 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1/*  -*-c++-*-
2 *  Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
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>
16#include <osgAnimation/StatsVisitor>
17#include <limits.h>
18
19using namespace osgAnimation;
20
21
22Timeline::Timeline()
23{
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;
32    _numberFrame = UINT_MAX; // something like infinity
33    _collectStats = false;
34    _stats = new osg::Stats("Timeline");
35    setName("Timeline");
36}
37
38Timeline::Timeline(const Timeline& nc,const osg::CopyOp& op)
39    : Action(nc, op),
40      _actions(nc._actions)
41{
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;
50    _numberFrame = UINT_MAX; // something like infinity
51    _collectStats = false;
52    _stats = new osg::Stats("Timeline");
53    setName("Timeline");
54}
55
56void Timeline::setAnimationManager(AnimationManagerBase* manager)
57{
58    _animationManager = manager;
59}
60
61void Timeline::traverse(ActionVisitor& visitor)
62{
63    int layer = visitor.getCurrentLayer();
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    {
68        visitor.setCurrentLayer(iterAnim->first);
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();
78    visitor.setCurrentLayer(layer);
79}
80
81
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(); }
86
87void Timeline::clearActions()
88{
89    _actions.clear();
90    _addActionOperations.clear();
91    _removeActionOperations.clear();
92}
93
94void Timeline::update(double simulationTime)
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
103
104        _animationManager->clearTargets();
105        updateTimeline.setFrame(_currentFrame);
106        accept(updateTimeline);
107
108        if (_collectStats)
109        {
110            if (!_statsVisitor)
111                _statsVisitor = new StatsActionVisitor();
112            _statsVisitor->setStats(_stats.get());
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
131        _animationManager->clearTargets();
132        updateTimeline.setFrame(_currentFrame);
133        accept(updateTimeline);
134        if (_collectStats)
135        {
136            if (!_statsVisitor)
137                _statsVisitor = new StatsActionVisitor;
138            _statsVisitor->setStats(_stats.get());
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
152void Timeline::removeAction(Action* action)
153{
154    if (getEvaluating())
155        _removeActionOperations.push_back(FrameAction(0, action));
156    else
157        internalRemoveAction(action);
158}
159
160void Timeline::addActionAt(unsigned int frame, Action* action, int priority)
161{
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_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_INFO << "Timeline::addActionAt command " << action->getName() << " already active, remove the old" << std::endl;
175        removeAction(action);
176    }
177
178    if (getEvaluating())
179        _addActionOperations.push_back(Command(priority,FrameAction(frame, action)));
180    else
181        internalAddAction(priority, FrameAction(frame, action));
182}
183void Timeline::addActionAt(double t, Action* action, int priority)
184{
185    unsigned int frame = static_cast<unsigned int>(floor(t * _fps));
186    addActionAt(frame, action, priority);
187}
188
189void Timeline::addActionNow(Action* action, int priority)
190{
191    addActionAt(getCurrentFrame()+1, action, priority);
192}
193
194void Timeline::processPendingOperation()
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
211void Timeline::internalRemoveAction(Action* action)
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
225void Timeline::internalAddAction(int priority, const FrameAction& ftl)
226{
227    _actions[priority].insert(_actions[priority].begin(), ftl);
228}
229
230bool Timeline::isActive(Action* activeAction)
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.