1 /*  -*-c++-*-
2  *  Copyright (C) 2008 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 #include <osgAnimation/Animation>
16 
17 using namespace osgAnimation;
18 
Animation(const osgAnimation::Animation & anim,const osg::CopyOp & copyop)19 Animation::Animation(const osgAnimation::Animation& anim, const osg::CopyOp& copyop): osg::Object(anim, copyop),
20     _duration(anim._duration),
21     _originalDuration(anim._originalDuration),
22     _weight(anim._weight),
23     _startTime(anim._startTime),
24     _playmode(anim._playmode)
25 {
26     const ChannelList& cl = anim.getChannels();
27     for (ChannelList::const_iterator it = cl.begin(); it != cl.end(); ++it)
28     {
29         addChannel(it->get()->clone());
30     }
31 }
32 
33 
addChannel(Channel * pChannel)34 void Animation::addChannel(Channel* pChannel)
35 {
36     _channels.push_back(pChannel);
37     if (_duration == _originalDuration)
38         computeDuration();
39     else
40         _originalDuration = computeDurationFromChannels();
41 }
42 
43 
removeChannel(Channel * pChannel)44 void Animation::removeChannel(Channel* pChannel)
45 {
46     ChannelList::iterator it = _channels.begin();
47     while(it != _channels.end() && it->get() != pChannel)
48     {
49         ++ it;
50     }
51 
52     if (it != _channels.end())
53     {
54         _channels.erase(it);
55     }
56     computeDuration();
57 }
58 
computeDurationFromChannels() const59 double Animation::computeDurationFromChannels() const
60 {
61     if(_channels.empty())
62         return 0;
63 
64     double tmin = 1e5;
65     double tmax = -1e5;
66     ChannelList::const_iterator chan;
67     for( chan=_channels.begin(); chan!=_channels.end(); chan++ )
68     {
69         float min = (*chan)->getStartTime();
70         if (min < tmin)
71             tmin = min;
72         float max = (*chan)->getEndTime();
73         if (max > tmax)
74             tmax = max;
75     }
76     return tmax-tmin;
77 }
78 
computeDuration()79 void Animation::computeDuration()
80 {
81     _duration = computeDurationFromChannels();
82     _originalDuration = _duration;
83 }
84 
getChannels()85 osgAnimation::ChannelList& Animation::getChannels()
86 {
87     return _channels;
88 }
89 
getChannels() const90 const osgAnimation::ChannelList& Animation::getChannels() const
91 {
92     return _channels;
93 }
94 
95 
setDuration(double duration)96 void Animation::setDuration(double duration)
97 {
98     _originalDuration = computeDurationFromChannels();
99     _duration = duration;
100 }
101 
getDuration() const102 double Animation::getDuration() const
103 {
104     return _duration;
105 }
106 
getWeight() const107 float Animation::getWeight () const
108 {
109     return _weight;
110 }
111 
setWeight(float weight)112 void Animation::setWeight (float weight)
113 {
114     _weight = weight;
115 }
116 
update(double time,int priority)117 bool Animation::update (double time, int priority)
118 {
119     if (!_duration) // if not initialized then do it
120         computeDuration();
121 
122     double ratio = _originalDuration / _duration;
123 
124     double t = (time - _startTime) * ratio;
125     switch (_playmode)
126     {
127     case ONCE:
128         if (t > _originalDuration)
129         {
130             for (ChannelList::const_iterator chan = _channels.begin();
131                      chan != _channels.end(); ++chan)
132                 (*chan)->update(_originalDuration, _weight, priority);
133 
134             return false;
135         }
136         break;
137     case STAY:
138         if (t > _originalDuration)
139             t = _originalDuration;
140         break;
141     case LOOP:
142         if (!_originalDuration)
143             t = _startTime;
144         else if (t > _originalDuration)
145             t = fmod(t, _originalDuration);
146         //      std::cout << "t " << t << " duration " << _duration << std::endl;
147         break;
148     case PPONG:
149         if (!_originalDuration)
150             t = _startTime;
151         else
152         {
153             int tt = (int) (t / _originalDuration);
154             t = fmod(t, _originalDuration);
155             if (tt%2)
156                 t = _originalDuration - t;
157         }
158         break;
159     }
160 
161     ChannelList::const_iterator chan;
162     for( chan=_channels.begin(); chan!=_channels.end(); ++chan)
163     {
164         (*chan)->update(t, _weight, priority);
165     }
166     return true;
167 }
168 
resetTargets()169 void Animation::resetTargets()
170 {
171     ChannelList::const_iterator chan;
172     for( chan=_channels.begin(); chan!=_channels.end(); ++chan)
173         (*chan)->reset();
174 }
175