root/OpenSceneGraph/trunk/examples/osganimationtimeline/osganimationtimeline.cpp @ 10625

Revision 10625, 7.9 kB (checked in by robert, 5 years ago)

From Cedric Pinson, "Here an update of osganimationtimeline example, the callback did not
follow the callback api, i updated to fix this, then the callback are
called correctly."

RevLine 
[9150]1/*  -*-c++-*-
[10487]2 *  Copyright (C) 2008 Cedric Pinson <cedric.pinson@plopbyte.net>
[9150]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 <iostream>
16#include <osgDB/ReadFile>
17#include <osgViewer/ViewerEventHandlers>
18#include <osgGA/TrackballManipulator>
19#include <osgGA/FlightManipulator>
20#include <osgGA/DriveManipulator>
21#include <osgGA/KeySwitchMatrixManipulator>
22#include <osgGA/StateSetManipulator>
23#include <osgGA/AnimationPathManipulator>
24#include <osgGA/TerrainManipulator>
25
26#include <osgAnimation/Bone>
27#include <osgAnimation/Skeleton>
28#include <osgAnimation/RigGeometry>
29#include <osgAnimation/Skinning>
30#include <osgAnimation/Timeline>
31#include <osgAnimation/AnimationManagerBase>
[9370]32#include <osgAnimation/TimelineAnimationManager>
[9150]33
34
35struct NoseBegin : public osgAnimation::Action::Callback
36{
[10625]37    virtual void operator()(osgAnimation::Action* action, osgAnimation::ActionVisitor* nv)
[9150]38    {
39        std::cout << "sacrebleu, it scratches my nose, let me scratch it" << std::endl;
40        std::cout << "process NoseBegin call back " << action->getName() << std::endl << std::endl;
41    }
42};
43
44struct NoseEnd : public osgAnimation::Action::Callback
45{
[10625]46    virtual void operator()(osgAnimation::Action* action, osgAnimation::ActionVisitor* nv)
[9150]47    {
48        std::cout << "shhhrt shrrrrt shhhhhhrrrrt, haaa it's better"<< std::endl;
49        std::cout << "process NoseEnd call back " << action->getName() << std::endl << std::endl;
50    }
51};
52
53struct ExampleTimelineUsage : public osgGA::GUIEventHandler
54{
55    osg::ref_ptr<osgAnimation::StripAnimation> _mainLoop;
56    osg::ref_ptr<osgAnimation::StripAnimation> _scratchHead;
57    osg::ref_ptr<osgAnimation::StripAnimation> _scratchNose;
[9370]58    osg::ref_ptr<osgAnimation::TimelineAnimationManager> _manager;
[9150]59
60    bool _releaseKey;
61
[9370]62    ExampleTimelineUsage(osgAnimation::TimelineAnimationManager* manager)
[9150]63    {
64        _releaseKey = false;
65        _manager = manager;
66
[9370]67        const osgAnimation::AnimationList& list = _manager->getAnimationList();
68        osgAnimation::AnimationMap map;
69        for (osgAnimation::AnimationList::const_iterator it = list.begin(); it != list.end(); it++)
70            map[(*it)->getName()] = *it;
71
[9150]72        _mainLoop = new osgAnimation::StripAnimation(map["Idle_Main"].get(),0.0,0.0);
73        _mainLoop->setLoop(0); // means forever
74
75        _scratchHead = new osgAnimation::StripAnimation(map["Idle_Head_Scratch.02"].get(),0.2,0.3);
76        _scratchHead->setLoop(1); // one time
77
[9151]78        map["Idle_Nose_Scratch.01"]->setDuration(10.0); // set this animation duration to 10 seconds
[9150]79        _scratchNose = new osgAnimation::StripAnimation(map["Idle_Nose_Scratch.01"].get(),0.2,0.3);
[9151]80        _scratchNose->setLoop(1); // one time
[9150]81
82        // add the main loop at priority 0 at time 0.
83       
84        osgAnimation::Timeline* tml = _manager->getTimeline();
85        tml->play();
86        tml->addActionAt(0.0, _mainLoop.get(), 0);
87
88
89        // add a scratch head priority 1 at 3.0 second.
90        tml->addActionAt(5.0, _scratchHead.get(), 1);
91
92        // populate time with scratch head
93        for (int i = 1; i < 20; i++)
94        {
95            // we add a scratch head priority 1 each 10 second
96            // note:
97            //      it's possible to add the same instance more then once on the timeline
98            //      the only things you need to take care is if you remove it. It will remove
99            //      all instance that exist on the timeline. If you need to differtiate
100            //      it's better to create a new instance
101            tml->addActionAt(5.0 + 10.0 * i, _scratchHead.get(), 1);
102        }
103
104        // we will add the scratch nose action only when the player hit a key
105        // in the operator()
106
107        // now we will add callback at end and begin of animation of Idle_Nose_Scratch.02
108        _scratchNose->setCallback(0.0, new NoseBegin);
109        _scratchNose->setCallback(_scratchNose->getNumFrames()-1, new NoseEnd);
110    }
111
[9459]112    bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&)
[9150]113    {
114        if (ea.getEventType() == osgGA::GUIEventAdapter::KEYUP)
115        {
116            _releaseKey = true;
117        }
118        return false;
119    }
120
121    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
122    {
123        if (nv && nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
124        {
125            if (_releaseKey) // we hit a key and release it execute an action
126            {
127                osgAnimation::Timeline* tml = _manager->getTimeline();
128                // dont play if already playing
129                if (!tml->isActive(_scratchNose.get()))
130                {
131                    // add this animation on top of two other
132                    // we add one to evaluate the animation at the next frame, else we
133                    // will miss the current frame
134                    tml->addActionAt(tml->getCurrentFrame() + 1, _scratchNose.get(), 2);
135                }
136                _releaseKey = false;
137            }
138        }
139        else
140        {
141            osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(nv);
142            if (ev && ev->getActionAdapter() && !ev->getEvents().empty())
143            {
144                for(osgGA::EventQueue::Events::iterator itr = ev->getEvents().begin();
145                    itr != ev->getEvents().end();
146                    ++itr)
147                {
148                    handleWithCheckAgainstIgnoreHandledEventsMask(*(*itr), *(ev->getActionAdapter()), node, nv);
149                }
150            }
151        }           
152        traverse(node, nv);
153    }
154
155};
156
157
158int main (int argc, char* argv[])
159{
[10487]160    std::cerr << "This example works only with nathan.osg" << std::endl;
[9150]161
162    osg::ArgumentParser psr(&argc, argv);
163
164    osgViewer::Viewer viewer(psr);
165
[10487]166    std::string file = "nathan.osg";
[9150]167    if(argc >= 2)
168        file = psr[1];
169
170    // replace the manager
[9370]171    osg::Group* root = dynamic_cast<osg::Group*>(osgDB::readNodeFile(file));
[10487]172    if (!root) {
173        osg::notify(osg::FATAL) << "can't read file " << file << std::endl;
174        return 1;
175    }
[9370]176    osgAnimation::AnimationManagerBase* animationManager = dynamic_cast<osgAnimation::AnimationManagerBase*>(root->getUpdateCallback());
[9150]177    if(!animationManager)
178    {
[10487]179        osg::notify(osg::FATAL) << "Did not find AnimationManagerBase updateCallback needed to animate elements" << std::endl;
[9150]180        return 1;
181    }
182
[9370]183    osg::ref_ptr<osgAnimation::TimelineAnimationManager> tl = new osgAnimation::TimelineAnimationManager(*animationManager);
[9371]184    root->setUpdateCallback(tl.get());
185   
[9150]186    ExampleTimelineUsage* callback = new ExampleTimelineUsage(tl.get());
[9370]187    root->setEventCallback(callback);
188    root->getUpdateCallback()->addNestedCallback(callback);
189       
[9150]190
191
192    // add the state manipulator
193    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
194   
195    // add the thread model handler
196    viewer.addEventHandler(new osgViewer::ThreadingHandler);
197
198    // add the window size toggle handler
199    viewer.addEventHandler(new osgViewer::WindowSizeHandler);
200       
201    // add the stats handler
202    viewer.addEventHandler(new osgViewer::StatsHandler);
203
204    // add the help handler
205    viewer.addEventHandler(new osgViewer::HelpHandler(psr.getApplicationUsage()));
206
207    // add the LOD Scale handler
208    viewer.addEventHandler(new osgViewer::LODScaleHandler);
209
210    // add the screen capture handler
211    viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);
212
[9370]213    viewer.setSceneData(root);
[9150]214
215    return viewer.run();
216}
217
Note: See TracBrowser for help on using the browser.