1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program 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 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program 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 this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 /*
24  * This file is based on WME.
25  * http://dead-code.org/redir.php?target=wme
26  * Copyright (c) 2003-2013 Jan Nedoma and contributors
27  */
28 
29 #include "engines/wintermute/base/base_game.h"
30 #include "engines/wintermute/base/gfx/x/animation_set.h"
31 #include "engines/wintermute/base/gfx/x/modelx.h"
32 #include "engines/wintermute/base/gfx/x/loader_x.h"
33 #include "engines/wintermute/dcgf.h"
34 
35 namespace Wintermute {
36 
37 //////////////////////////////////////////////////////////////////////////
AnimationSet(BaseGame * inGame,ModelX * model)38 AnimationSet::AnimationSet(BaseGame *inGame, ModelX *model) : BaseNamedObject(inGame),
39 	_looping(false), _frameTime(-1), _totalTime(0), _model(model) {
40 }
41 
42 //////////////////////////////////////////////////////////////////////////
~AnimationSet()43 AnimationSet::~AnimationSet() {
44 	// remove child animations
45 	for (uint32 i = 0; i < _animations.size(); i++) {
46 		delete _animations[i];
47 	}
48 	_animations.clear();
49 
50 	// remove events
51 	for (uint32 i = 0; i < _events.size(); i++) {
52 		delete _events[i];
53 	}
54 	_events.clear();
55 }
56 
loadFromX(XFileLexer & lexer,const Common::String & filename)57 bool AnimationSet::loadFromX(XFileLexer &lexer, const Common::String &filename) {
58 	if (lexer.tokenIsIdentifier()) {
59 		setName(lexer.tokenToString().c_str());
60 		lexer.advanceToNextToken();
61 	} else {
62 		Common::String name = filename + "_animation";
63 		setName(name.c_str());
64 	}
65 
66 	lexer.advanceToNextToken();
67 
68 	bool ret = true;
69 
70 	while (!lexer.eof()) {
71 		if (lexer.tokenIsIdentifier("Animation")) {
72 			lexer.advanceToNextToken();
73 
74 			Animation *animation = new Animation(_gameRef);
75 			animation->loadFromX(lexer, this);
76 			_animations.add(animation);
77 		} else if (lexer.reachedClosedBraces()) {
78 			lexer.advanceToNextToken(); // skip closed braces
79 			break;
80 		} else {
81 			warning("AnimationSet::loadFromX unexpected token");
82 			ret = false;
83 			break;
84 		}
85 	}
86 
87 	return ret;
88 }
89 
90 //////////////////////////////////////////////////////////////////////////
findBones(FrameNode * rootFrame)91 bool AnimationSet::findBones(FrameNode *rootFrame) {
92 	for (uint32 i = 0; i < _animations.size(); i++) {
93 		_animations[i]->findBone(rootFrame);
94 	}
95 	return true;
96 }
97 
98 //////////////////////////////////////////////////////////////////////////
addAnimation(Animation * anim)99 bool AnimationSet::addAnimation(Animation *anim) {
100 	if (!anim) {
101 		return false;
102 	} else {
103 		_animations.add(anim);
104 		return true;
105 	}
106 }
107 
108 //////////////////////////////////////////////////////////////////////////
addEvent(AnimationEvent * event)109 bool AnimationSet::addEvent(AnimationEvent *event) {
110 	if (!event) {
111 		return false;
112 	} else {
113 		int frameTime = getFrameTime();
114 		if (frameTime < 0) {
115 			_gameRef->LOG(0, "Error adding animation event %s, no keyframes found", event->_eventName);
116 			delete event;
117 			return false;
118 		}
119 
120 		int totalFrames = 0;
121 		if (frameTime > 0)
122 			totalFrames = getTotalTime() / frameTime + 1;
123 
124 		if (event->_frame < 1)
125 			event->_frame = 1;
126 		if (event->_frame > totalFrames)
127 			event->_frame = totalFrames;
128 
129 		_events.add(event);
130 		return true;
131 	}
132 }
133 
134 //////////////////////////////////////////////////////////////////////////
update(int slot,uint32 localTime,float lerpValue)135 bool AnimationSet::update(int slot, uint32 localTime, float lerpValue) {
136 	bool res;
137 	for (uint32 i = 0; i < _animations.size(); i++) {
138 		res = _animations[i]->update(slot, localTime * ((float)_model->_ticksPerSecond / 1000.0f), lerpValue);
139 		if (!res) {
140 			return res;
141 		}
142 	}
143 	return true;
144 }
145 
146 //////////////////////////////////////////////////////////////////////////
getFrameTime()147 int AnimationSet::getFrameTime() {
148 	if (_frameTime >= 0) {
149 		return _frameTime;
150 	}
151 
152 	_frameTime = 0;
153 
154 	for (uint32 i = 0; i < _animations.size(); i++) {
155 		int frameTime = _animations[i]->getFrameTime();
156 		if (_frameTime == 0) {
157 			_frameTime = frameTime / ((float)_model->_ticksPerSecond / 1000.0f);
158 		} else if (frameTime > 0) {
159 			_frameTime = MIN(float(_frameTime), frameTime / ((float)_model->_ticksPerSecond / 1000.0f));
160 		}
161 	}
162 	return _frameTime;
163 }
164 
165 //////////////////////////////////////////////////////////////////////////
getTotalTime()166 uint32 AnimationSet::getTotalTime() {
167 	if (_totalTime > 0) {
168 		return _totalTime;
169 	}
170 
171 	_totalTime = 0;
172 
173 	for (uint32 i = 0; i < _animations.size(); i++) {
174 		_totalTime = MAX((float)_totalTime, _animations[i]->getTotalTime() / ((float)_model->_ticksPerSecond / 1000.0f));
175 	}
176 	return _totalTime;
177 }
178 
179 //////////////////////////////////////////////////////////////////////////
onFrameChanged(int currentFrame,int prevFrame)180 bool AnimationSet::onFrameChanged(int currentFrame, int prevFrame) {
181 	if (!_model || !_model->_owner) {
182 		return true;
183 	}
184 
185 	if (prevFrame > currentFrame) {
186 		for (uint32 i = 0; i < _events.size(); i++) {
187 			if (_events[i]->_frame > prevFrame) {
188 				_model->_owner->applyEvent(_events[i]->_eventName);
189 			}
190 		}
191 		prevFrame = -1;
192 	}
193 
194 	for (uint32 i = 0; i < _events.size(); i++) {
195 		if (_events[i]->_frame > prevFrame && _events[i]->_frame <= currentFrame) {
196 			_model->_owner->applyEvent(_events[i]->_eventName);
197 		}
198 	}
199 	return true;
200 }
201 
202 //////////////////////////////////////////////////////////////////////////
persist(BasePersistenceManager * persistMgr)203 bool AnimationSet::persist(BasePersistenceManager *persistMgr) {
204 	persistMgr->transferBool(TMEMBER(_looping));
205 
206 	// persist events
207 	int32 numEvents;
208 	if (persistMgr->getIsSaving()) {
209 		numEvents = _events.size();
210 	}
211 
212 	persistMgr->transferSint32(TMEMBER(numEvents));
213 
214 	for (int i = 0; i < numEvents; i++) {
215 		if (persistMgr->getIsSaving()) {
216 			_events[i]->persist(persistMgr);
217 		} else {
218 			AnimationEvent *rvent = new AnimationEvent();
219 			rvent->persist(persistMgr);
220 			_events.add(rvent);
221 		}
222 	}
223 
224 	return true;
225 }
226 
227 } // namespace Wintermute
228