1/*  -*-c++-*-
2 *  Copyright (C) 2009 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#ifndef OSGANIMATION_ACTION_H
16#define OSGANIMATION_ACTION_H
17
18#include <osgAnimation/Export>
19#include <osgAnimation/Animation>
20#include <osgAnimation/ActionVisitor>
21#include <osgAnimation/FrameAction>
22#include <iostream>
23
24#define META_Action(library,name) \
25        virtual osg::Object* cloneType() const { return new name (); } \
26        virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new name (*this,copyop); } \
27        virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const name *>(obj)!=NULL; } \
28        virtual const char* className() const { return #name; } \
29        virtual const char* libraryName() const { return #library; } \
30        virtual void accept(osgAnimation::ActionVisitor& nv) { nv.apply(*this); } \
31
32
33namespace osgAnimation
34{
35
36    class OSGANIMATION_EXPORT Action : public osg::Object
37    {
38    public:
39
40        class Callback : public osg::Object
41        {
42        public:
43            Callback(){}
44            Callback(const Callback& nc,const osg::CopyOp&) :
45                _nestedCallback(nc._nestedCallback) {}
46
47            META_Object(osgAnimation,Callback);
48
49            virtual void operator()(Action* /*action*/, osgAnimation::ActionVisitor* /*nv*/) {}
50
51            Callback* getNestedCallback() { return _nestedCallback.get(); }
52            void addNestedCallback(Callback* callback)
53            {
54                if (callback) {
55                    if (_nestedCallback.valid())
56                        _nestedCallback->addNestedCallback(callback);
57                    else
58                        _nestedCallback = callback;
59                }
60            }
61
62            void removeCallback(Callback* cb)
63            {
64                if (!cb)
65                    return;
66
67                if (_nestedCallback.get() == cb)
68                    _nestedCallback = _nestedCallback->getNestedCallback();
69                else if (_nestedCallback.valid())
70                    _nestedCallback->removeCallback(cb);
71            }
72
73        protected:
74            osg::ref_ptr<Callback> _nestedCallback;
75        };
76
77
78        typedef std::map<unsigned int, osg::ref_ptr<Callback> > FrameCallback;
79
80        META_Action(osgAnimation, Action);
81
82        Action();
83        Action(const Action&,const osg::CopyOp&);
84
85        void setCallback(double when, Callback* callback)
86        {
87            setCallback(static_cast<unsigned int>(floor(when*_fps)), callback);
88        }
89
90        void setCallback(unsigned int frame, Callback* callback)
91        {
92            if (_framesCallback[frame].valid())
93                _framesCallback[frame]->addNestedCallback(callback);
94            else
95                _framesCallback[frame] = callback;
96        }
97        Callback* getCallback(unsigned int frame)
98        {
99            if (_framesCallback.find(frame) == _framesCallback.end())
100                return 0;
101            return _framesCallback[frame].get();
102        }
103
104        void removeCallback(Callback*);
105
106        Callback* getFrameCallback(unsigned int frame);
107        Callback* getFrameCallback(double time);
108        unsigned int getFramesPerSecond() const { return _fps; }
109
110        void setNumFrames(unsigned int numFrames) { _numberFrame = numFrames;}
111        void setDuration(double duration) { _numberFrame = static_cast<unsigned int>(floor(duration * _fps)); }
112        unsigned int getNumFrames() const { return _numberFrame;}
113        double getDuration() const { return _numberFrame * 1.0 / _fps; }
114
115        // 0 means infinite else it's the number of loop
116        virtual void setLoop(unsigned int nb) { _loop = nb; }
117        virtual unsigned int getLoop() const { return _loop;}
118
119        // get the number of loop, the frame relative to loop.
120        // return true if in range, and false if out of range.
121        bool evaluateFrame(unsigned int frame, unsigned int& resultframe, unsigned int& nbloop );
122        virtual void traverse(ActionVisitor& /*visitor*/) {}
123        //virtual void evaluate(unsigned int frame);
124
125    protected:
126        FrameCallback _framesCallback;
127
128        double _speed;
129        unsigned int _fps;
130        unsigned int _numberFrame;
131        unsigned int _loop;
132
133        enum Status
134        {
135            Play,
136            Stop
137        };
138
139        Status _state;
140    };
141
142
143
144
145}
146
147#endif
148