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