Hi Paul, I don't feel this change is appropriate, one can't keep breaking OSG interfaces each time a 3rd party C headers introduces a problem define. Rather end user code that includes both the offending X headers should include osgAnimatiom headers first.
Robert. On Sat, May 16, 2009 at 9:39 PM, p...@tcl3d <[email protected]> wrote: > Hello Robert, > > I would recommend to rename the 2 enumerations called "Status" back to their > previous name "State". > > I got strange compile errors when trying to compile my code (which ran fine > with 2.8) with the current head on Linux. > After some investigation I found out, that in several X header files, there > are statements like this: > > #define Status int > > which causes the preprocessor to change the enum definitions: > enum Status > { > Play, > Stop > }; > > to > enum int > { > Play, > Stop > }; > > I know, that's not the fault of OSG, but bad design in the X code. > > Regards, > > Paul Obermeier > > /* -*-c++-*- > * Copyright (C) 2008 Cedric Pinson <[email protected]> > * > * 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. > */ > > #ifndef OSGANIMATION_TIMELINE_H > #define OSGANIMATION_TIMELINE_H > > #include <osgAnimation/Export> > #include <osg/Object> > #include <map> > #include <vector> > #include <osg/Notify> > #include <osg/Group> > #include <osgAnimation/Animation> > #include <osgAnimation/AnimationManagerBase> > > namespace osgAnimation > { > > class Action : public osg::Object > { > public: > > class Callback : public osg::Object > { > public: > Callback(){} > Callback(const Callback&,const osg::CopyOp&) {} > > META_Object(osgAnimation,Callback); > > virtual void operator()(Action* /*action*/) {} > > void addNestedCallback(Callback* callback) > { > if (_nested.valid()) > _nested->addNestedCallback(callback); > else > _nested = callback; > } > > protected: > osg::ref_ptr<Callback> _nested; > }; > > > typedef std::map<unsigned int, osg::ref_ptr<Callback> > > FrameCallback; > > META_Object(osgAnimation, Action); > > Action() > { > _numberFrame = 25; > _fps = 25; > _speed = 1.0; > _loop = 1; > } > > Action(const Action&,const osg::CopyOp&) {} > > void setCallback(double when, Callback* callback) > { > setCallback(static_cast<unsigned int>(floor(when*_fps)), > callback); > } > > void setCallback(unsigned int frame, Callback* callback) > { > if (_framesCallback[frame].valid()) > _framesCallback[frame]->addNestedCallback(callback); > else > _framesCallback[frame] = callback; > } > Callback* getCallback(unsigned int frame) > { > if (_framesCallback.find(frame) == _framesCallback.end()) > return 0; > return _framesCallback[frame].get(); > } > > void setNumFrames(unsigned int numFrames) { _numberFrame = > numFrames;} > void setDuration(double duration) { _numberFrame = > static_cast<unsigned int>(floor(duration * _fps)); } > > unsigned int getNumFrames() const { return _numberFrame;} > double getDuration() const { return _numberFrame * 1.0 / _fps; } > > // 0 means infini else it's the number of loop > virtual void setLoop(int nb) { _loop = nb; } > virtual unsigned int getLoop() const { return _loop;} > > // get the number of loop, the frame relative to loop. > // return true if in range, and false if out of range. > bool evaluateFrame(unsigned int frame, unsigned int& resultframe, > unsigned int& nbloop ) > { > nbloop = frame / getNumFrames(); > resultframe = frame; > > if (frame > getNumFrames()-1) > { > if (!getLoop()) > resultframe = frame % getNumFrames(); > else > { > if (nbloop >= getLoop()) > return false; > else > resultframe = frame % getNumFrames(); > } > } > return true; > } > > virtual void evaluate(unsigned int frame) > { > unsigned int frameInAction; > unsigned int loopDone; > if (!evaluateFrame(frame, frameInAction, loopDone)) > osg::notify(osg::DEBUG_INFO) << getName() << " Action frame " > << frameInAction << " finished" << std::endl; > else > osg::notify(osg::DEBUG_INFO) << getName() << " Action frame " > << frame << " relative to loop " << frameInAction << " no loop " << > loopDone<< std::endl; > } > > virtual void evaluateCallback(unsigned int frame) > { > unsigned int frameInAction; > unsigned int loopDone; > if (!evaluateFrame(frame, frameInAction, loopDone)) > return; > > frame = frameInAction; > if (_framesCallback.find(frame) != _framesCallback.end()) > { > std::cout << getName() << " evaluate callback " << > _framesCallback[frame]->getName() << " at " << frame << std::endl; > (*_framesCallback[frame])(this); > } > } > > protected: > FrameCallback _framesCallback; > > double _speed; > unsigned int _fps; > unsigned int _numberFrame; > unsigned int _loop; > > enum State > { > Play, > Stop > }; > > State _state; > }; > > > class OSGANIMATION_EXPORT Timeline : public osg::Object > { > public: > > META_Object(osgAnimation, Timeline); > > Timeline(); > Timeline(const Timeline& nc,const osg::CopyOp& op = > osg::CopyOp::SHALLOW_COPY); > > enum State > { > Play, > Stop > }; > > State getStatus() const { return _state; } > > typedef std::pair<unsigned int, osg::ref_ptr<Action> > FrameAction; > typedef std::vector<FrameAction> ActionList; > typedef std::map<int, ActionList> ActionLayers; > > const ActionList& getActionLayer(int i) > { > return _actions[i]; > } > unsigned int getCurrentFrame() const { return _currentFrame;} > double getCurrentTime() const { return _currentFrame * 1.0 / _fps;} > > void play() { _state = Play; } > void gotoFrame(unsigned int frame) { _currentFrame = frame; } > void stop() { _state = Stop; } > bool getEvaluating() const { return _evaluating;} > > bool isActive(Action* activeAction) > { > // update from high priority to low priority > for( ActionLayers::iterator iterAnim = _actions.begin(); iterAnim > != _actions.end(); ++iterAnim ) > { > // update all animation > ActionList& list = iterAnim->second; > for (unsigned int i = 0; i < list.size(); i++) > { > Action* action = list[i].second.get(); > if (action == activeAction) > { > unsigned int firstFrame = list[i].first; > // check if current frame of timeline hit an action > interval > if (_currentFrame >= firstFrame && > _currentFrame < (firstFrame + > action->getNumFrames()) ) > return true; > } > } > } > return false; > } > > void removeAction(Action* action) > { > if (getEvaluating()) > _removeActionOperations.push_back(FrameAction(0, action)); > else > internalRemoveAction(action); > } > > virtual void addActionAt(unsigned int frame, Action* action, int > priority = 0) > { > if (getEvaluating()) > > _addActionOperations.push_back(Command(priority,FrameAction(frame, > action))); > else > internalAddAction(priority, FrameAction(frame, action)); > } > virtual void addActionAt(double t, Action* action, int priority = 0) > { > unsigned int frame = static_cast<unsigned int>(floor(t * _fps)); > addActionAt(frame, action, priority); > } > > virtual void evaluate(unsigned int frame) > { > setEvaluating(true); > osg::notify(osg::DEBUG_INFO) << getName() << " evaluate frame " > << _currentFrame << std::endl; > > // update from high priority to low priority > for( ActionLayers::reverse_iterator iterAnim = _actions.rbegin(); > iterAnim != _actions.rend(); ++iterAnim ) > { > // update all animation > ActionList& list = iterAnim->second; > for (unsigned int i = 0; i < list.size(); i++) > { > unsigned int firstFrame = list[i].first; > Action* action = list[i].second.get(); > // check if current frame of timeline hit an action > interval > if (frame >= firstFrame && > frame < (firstFrame + action->getNumFrames()) ) > action->evaluate(frame - firstFrame); > } > } > setEvaluating(false); > > // evaluate callback after updating all animation > evaluateCallback(frame); > _previousFrameEvaluated = frame; > } > > virtual void evaluateCallback(unsigned int frame) > { > // update from high priority to low priority > for( ActionLayers::reverse_iterator iterAnim = _actions.rbegin(); > iterAnim != _actions.rend(); ++iterAnim ) > { > // update all animation > ActionList& list = iterAnim->second; > for (unsigned int i = 0; i < list.size(); i++) > { > unsigned int firstFrame = list[i].first; > Action* action = list[i].second.get(); > // check if current frame of timeline hit an action > interval > if (frame >= firstFrame && > frame < (firstFrame + action->getNumFrames()) ) > action->evaluateCallback(frame - firstFrame); > } > } > processPendingOperation(); > } > > virtual void update(double simulationTime) > { > // first time we call update we generate one frame > if (!_initFirstFrame) > { > _lastUpdate = simulationTime; > _initFirstFrame = true; > evaluate(_currentFrame); > } > > // find the number of frame pass since the last update > double delta = (simulationTime - _lastUpdate); > double nbframes = delta * _fps * _speed; > unsigned int nb = static_cast<unsigned int>(floor(nbframes)); > > for (unsigned int i = 0; i < nb; i++) > { > if (_state == Play) > _currentFrame++; > evaluate(_currentFrame); > } > if (nb) > { > _lastUpdate += ((double)nb) / _fps; > } > } > > protected: > > > ActionLayers _actions; > double _lastUpdate; > double _speed; > unsigned int _currentFrame; > unsigned int _fps; > unsigned int _numberFrame; > unsigned int _previousFrameEvaluated; > bool _loop; > bool _initFirstFrame; > > State _state; > > // to manage pending operation > bool _evaluating; > > struct Command > { > Command():_priority(0) {} > Command(int priority, const FrameAction& action) : > _priority(priority), _action(action) {} > int _priority; > FrameAction _action; > }; > > typedef std::vector<Command> CommandList; > CommandList _addActionOperations; > ActionList _removeActionOperations; > > void setEvaluating(bool state) { _evaluating = state;} > void processPendingOperation() > { > // process all pending add action operation > while( !_addActionOperations.empty()) > { > internalAddAction(_addActionOperations.back()._priority, > _addActionOperations.back()._action); > _addActionOperations.pop_back(); > } > > // process all pending remove action operation > while( !_removeActionOperations.empty()) > { > > internalRemoveAction(_removeActionOperations.back().second.get()); > _removeActionOperations.pop_back(); > } > } > > void internalRemoveAction(Action* action) > { > for (ActionLayers::iterator it = _actions.begin(); it != > _actions.end(); it++) > { > ActionList& fa = it->second; > for (unsigned int i = 0; i < fa.size(); i++) > if (fa[i].second.get() == action) > { > fa.erase(fa.begin() + i); > return; > } > } > } > void internalAddAction(int priority, const FrameAction& ftl) > { > _actions[priority].push_back(ftl); > } > > }; > > > > // blend in from 0 to weight in duration > class BlendIn : public Action > { > double _weight; > osg::ref_ptr<Animation> _animation; > > public: > BlendIn(Animation* animation, double duration, double weight) > { > _animation = animation; > _weight = weight; > float d = duration * _fps; > setNumFrames(static_cast<unsigned int>(floor(d)) + 1); > setName("BlendIn"); > } > double getWeight() const { return _weight;} > virtual void evaluate(unsigned int frame) > { > Action::evaluate(frame); > // frame + 1 because the start is 0 and we want to start the > blend in at the first > // frame. > double ratio = ( (frame+1) * 1.0 / (getNumFrames()) ); > double w = _weight; > if (frame < getNumFrames() -1 ) // the last frame we set the > target weight the user asked > w = _weight * ratio; > _animation->setWeight(w); > } > }; > > // blend in from 0 to weight in duration > class BlendOut : public Action > { > double _weight; > osg::ref_ptr<Animation> _animation; > public: > BlendOut(Animation* animation, double duration) > { > _animation = animation; > float d = duration * _fps; > setNumFrames(static_cast<unsigned int>(floor(d) + 1)); > _weight = 1.0; > setName("BlendOut"); > } > double getWeight() const { return _weight;} > virtual void evaluate(unsigned int frame) > { > Action::evaluate(frame); > // frame + 1 because the start is 0 and we want to start the > blend in at the first > // frame. > double ratio = ( (frame+1) * 1.0 / (getNumFrames()) ); > double w = 0.0; > if (frame < getNumFrames() -1 ) // the last frame we set the > target weight the user asked > w = _weight * (1.0-ratio); > _animation->setWeight(w); > } > }; > > > class ActionAnimation : public Action > { > public: > ActionAnimation(Animation* animation) : _animation(animation) > { > setDuration(animation->getDuration()); > setName(animation->getName()); > } > virtual void evaluate(unsigned int frame) > { > Action::evaluate(frame); > _animation->update(frame * 1.0/_fps); > } > Animation* getAnimation() { return _animation.get(); } > protected: > osg::ref_ptr<Animation> _animation; > }; > > > // encapsulate animation with blend in blend out for classic usage > class StripAnimation : public Action > { > protected: > typedef std::pair<unsigned int, osg::ref_ptr<Action> > FrameAction; > > public: > StripAnimation(Animation* animation, double blendInDuration, double > blendOutDuration, double blendInWeightTarget = 1.0 ) > { > _blendIn = new BlendIn(animation, blendInDuration, > blendInWeightTarget); > _animation = new ActionAnimation(animation); > unsigned int start = static_cast<unsigned > int>(floor((_animation->getDuration() - blendOutDuration) * _fps)); > _blendOut = FrameAction(start, new BlendOut(animation, > blendOutDuration)); > setName(animation->getName() + "_Strip"); > _blendIn->setName(_animation->getName() + "_" + > _blendIn->getName()); > _blendOut.second->setName(_animation->getName() + "_" + > _blendOut.second->getName()); > setDuration(animation->getDuration()); > } > > ActionAnimation* getActionAnimation() { return _animation.get(); } > BlendIn* getBlendIn() { return _blendIn.get(); } > BlendOut* getBlendOut() { return > dynamic_cast<BlendOut*>(_blendOut.second.get()); } > const ActionAnimation* getActionAnimation() const { return > _animation.get(); } > const BlendIn* getBlendIn() const { return _blendIn.get(); } > const BlendOut* getBlendOut() const { return > dynamic_cast<BlendOut*>(_blendOut.second.get()); } > > unsigned int getLoop() const { return _animation->getLoop(); } > void setLoop(unsigned int loop) > { > _animation->setLoop(loop); > if (!loop) > setDuration(-1); > else > setDuration(loop * _animation->getDuration()); > > // duration changed re evaluate the blendout duration > unsigned int start = static_cast<unsigned > int>(floor((getDuration() - _blendOut.second->getDuration()) * _fps)); > _blendOut = FrameAction(start, _blendOut.second); > } > > virtual void evaluate(unsigned int frame) > { > if (frame > getNumFrames() - 1) > return; > > Action::evaluate(frame); > if (frame < _blendIn->getNumFrames()) > _blendIn->evaluate(frame); > if (frame >= _blendOut.first) > _blendOut.second->evaluate(frame - _blendOut.first); > _animation->evaluate(frame); > } > > protected: > osg::ref_ptr<BlendIn> _blendIn; > FrameAction _blendOut; > osg::ref_ptr<ActionAnimation> _animation; > }; > > > class RunAction : public Action::Callback > { > protected: > osg::ref_ptr<Timeline> _tm; > osg::ref_ptr<Action> _action; > > public: > RunAction(Timeline* tm, Action* a) : _tm(tm), _action(a) {} > virtual void operator()(Action* /*action*/) > { > _tm->addActionAt(_tm->getCurrentFrame(), _action.get()); // > warning we are trsversing the vector > } > }; > > > > } > > #endif > > _______________________________________________ > osg-submissions mailing list > [email protected] > http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org > > _______________________________________________ osg-submissions mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
