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

Reply via email to