root/OpenSceneGraph/branches/OpenSceneGraph-osgWidget-dev/examples/osganimationtimeline/osganimationtimeline.cpp @ 9151

Revision 9151, 7.5 kB (checked in by cedricpinson, 5 years ago)

add an example how to change duration of animation

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