xoreos  0.0.5
animationchannel.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include "src/common/maths.h"
26 
31 
32 namespace Graphics {
33 
34 namespace Aurora {
35 
37  : _model(model),
38  _currentAnimation(0),
39  _nextAnimation(0),
40  _animationSpeed(1.0f),
41  _animationLength(1.0f),
42  _animationTime(0.0f),
43  _animationLoopLength(1.0f),
44  _animationLoopTime(0.0f),
45  _manageSem(true) {
46 }
47 
48 void AnimationChannel::playAnimation(const Common::UString &anim, bool restart, float length, float speed) {
49  Animation *animation = _model->getAnimation(anim);
50  if (!animation || speed <= 0.0f)
51  return;
52 
53  if (length == 0.0f)
54  length = animation->getLength() / speed;
55 
56  _manageSem.lock();
57 
58  _animationSpeed = speed;
59  _animationLength = length;
60  _animationTime = 0.0f;
61  _animationLoopLength = animation->getLength();
62 
63  if (restart || _currentAnimation != animation)
64  _nextAnimation = animation;
65 
67 }
68 
69 void AnimationChannel::playAnimationCount(const Common::UString &anim, bool restart, int32 loopCount) {
70  Animation *animation = _model->getAnimation(anim);
71  if (!animation)
72  return;
73 
74  float length = -1.0f;
75  if (loopCount >= 0)
76  length = (loopCount + 1) * animation->getLength();
77 
78  playAnimation(anim, restart, length, 1.0f);
79 }
80 
82  _manageSem.lock();
83  _defaultAnimations.clear();
85 }
86 
88  Animation *animation = _model->getAnimation(anim);
89  if (!animation)
90  return;
91 
93  da.animation = animation;
94  da.probability = probability;
95 
96  _manageSem.lock();
97  _defaultAnimations.push_back(da);
99 }
100 
102  _manageSem.lock();
104  _manageSem.unlock();
105 }
106 
108  _manageSem.lock();
109 
110  float lastFrame = _animationLoopTime;
111  float nextFrame = _animationLoopTime + _animationSpeed * dt;
112 
113  // No animation and no new one scheduled? Select a default one
116 
117  // Start a new animation if scheduled, interrupting the currently playing animation
118  if (_nextAnimation) {
120  _nextAnimation = 0;
121 
122  dt = 0.0f;
123  lastFrame = 0.0f;
124  nextFrame = 0.0f;
125  }
126 
127  if (!_currentAnimation) {
128  _manageSem.unlock();
129  return;
130  }
131 
132  // The loop of the animation ended: make sure to play the last frame
133  if (lastFrame < _animationLoopLength && nextFrame >= _animationLoopLength) {
135 
136  _animationTime += dt;
138  _manageSem.unlock();
139  return;
140  }
141 
142  // The animation has run its requested course: return to the default animation.
146  _nextAnimation = 0;
147 
148  if (_currentAnimation)
150 
151  _model->createBound();
152  _manageSem.unlock();
153  return;
154  }
155 
156  // Start the next loop of the animation
157  if (lastFrame >= _animationLoopLength) {
159 
160  lastFrame = 0.0f;
161  nextFrame = _animationSpeed * dt;
162 
163  _model->createBound();
164  }
165 
166  // Update the animation
167  _currentAnimation->update(_model, lastFrame, nextFrame, _modelNodeMap);
168 
169  _animationTime += dt;
170  _animationLoopTime = nextFrame;
171 
172  if (nextFrame == 0.0f)
173  _model->createBound();
174 
175  _manageSem.unlock();
176 }
177 
180  if (_currentAnimation == anim)
181  return;
182 
183  _nextAnimation = anim;
184  _animationSpeed = 1.0f;
185  _animationLength = 1.0f;
186  _animationTime = 0.0f;
187  _animationLoopLength = 1.0f;
188  _animationLoopTime = 0.0f;
189 
190  if (_nextAnimation) {
193  }
194 }
195 
197  uint8 pick = std::rand() % 100;
198  for (DefaultAnimations::const_iterator a = _defaultAnimations.begin();
199  a != _defaultAnimations.end(); ++a) {
200  if (pick < a->probability)
201  return a->animation;
202 
203  pick -= a->probability;
204  }
205 
206  return 0;
207 }
208 
210  if (!_model->_currentState)
211  return;
212 
213  _currentAnimation = anim;
214  _animationLoopTime = 0.0f;
215 
216  if (_currentAnimation)
218 }
219 
221  const std::list<AnimNode *> &animNodes = _currentAnimation->getNodes();
222  int maxNodeNumber = -1;
223 
224  for (std::list<AnimNode *>::const_iterator n = animNodes.begin();
225  n != animNodes.end(); ++n) {
226  int nodeNumber = (*n)->getNodeData()->getNodeNumber();
227  if (nodeNumber > maxNodeNumber)
228  maxNodeNumber = nodeNumber;
229  }
230 
231  _modelNodeMap.clear();
232 
233  if (maxNodeNumber == -1)
234  return;
235 
236  _modelNodeMap.resize(maxNodeNumber + 1, 0);
237 
238  for (std::list<AnimNode *>::const_iterator an = animNodes.begin();
239  an != animNodes.end(); ++an) {
240  ModelNode *animNode = (*an)->getNodeData();
241  int nodeNumber = animNode->getNodeNumber();
242  const Common::UString &animNodeName = animNode->getName();
243 
244  // Search for the corresponding node in this model
245  Model::NodeMap::iterator n = _model->_currentState->nodeMap.find(animNodeName);
246  if (n != _model->_currentState->nodeMap.end()) {
247  _modelNodeMap[nodeNumber] = n->second;
248  continue;
249  }
250 
251  // Search for the corresponding node in this model's attached models
252  for (std::map<Common::UString, Model *>::iterator m = _model->_attachedModels.begin();
253  m != _model->_attachedModels.end(); ++m) {
254  Model::State *state = m->second->_currentState;
255  if (!state)
256  continue;
257 
258  n = state->nodeMap.find(animNodeName);
259  if (n != state->nodeMap.end()) {
260  _modelNodeMap[nodeNumber] = n->second;
261  break;
262  }
263  }
264 
265  // Search for the corresponding node in this model's super model
266  if (_model->_superModel && !_modelNodeMap[nodeNumber])
267  _modelNodeMap[nodeNumber] = _model->_superModel->getNode(animNodeName);
268  }
269 }
270 
271 } // End of namespace Aurora
272 
273 } // End of namespace Graphics
A node within an animation.
NodeMap nodeMap
The nodes within the state, indexed by name.
Definition: model.h:207
void playAnimation(const Common::UString &anim, bool restart=true, float length=0.0f, float speed=1.0f)
Play a named animation.
float _animationLoopTime
The time the current loop of the current animation has played.
float _animationSpeed
The speed the current animation should run at.
float _animationTime
The time the current animation has played.
A class holding an UTF-8 string.
Definition: ustring.h:48
void update(Model *model, float lastFrame, float nextFrame, const std::vector< ModelNode *> &modelNodeMap)
Update the model position and orientation.
Definition: animation.cpp:74
An animation to be applied to a model.
uint8_t uint8
Definition: types.h:200
std::map< Common::UString, Model * > _attachedModels
Definition: model.h:282
Mathematical helpers.
State * _currentState
The current state.
Definition: model.h:227
bool lock(uint32 timeout=0)
Definition: mutex.cpp:60
void addDefaultAnimation(const Common::UString &name, uint8 probability)
float _animationLoopLength
The length of one loop of the current animation.
float _animationLength
The time the current animation should run for.
Animation * _currentAnimation
The currently playing animation.
const std::list< AnimNode * > & getNodes() const
Get all animation nodes.
Definition: animation.cpp:125
A 3D model of an object.
Animation * _nextAnimation
The animation that&#39;s scheduled next.
void createBound()
Create the model&#39;s bounding box.
Definition: model.cpp:848
std::vector< ModelNode * > _modelNodeMap
float getLength() const
Get the animations length.
Definition: animation.cpp:66
const Common::UString & getName() const
Get the node&#39;s name.
Definition: modelnode.cpp:156
Model * _superModel
The actual super model.
Definition: model.h:223
uint8 probability
The probability (in percent) this animation is selected.
void unlock()
Definition: mutex.cpp:75
uint16 getNodeNumber() const
Definition: modelnode.cpp:213
Animation * getAnimation(const Common::UString &anim)
Get the animation from its name.
Definition: model.cpp:496
Animation channel.
ModelNode * getNode(const Common::UString &node)
Get the specified node, from the current state.
Definition: model.cpp:379
void playAnimationCount(const Common::UString &anim, bool restart=true, int32 loopCount=0)
Play a named animation a number of loop iterations.
void setCurrentAnimation(Animation *anim)
int32_t int32
Definition: types.h:203