1 /*
2 Copyright (C) 2007, 2010 - Bit-Blot
3
4 This file is part of Aquaria.
5
6 Aquaria is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
15 See the 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 #include "StateManager.h"
22 #include "Core.h"
23
24 StateManager *stateManager = 0;
25
26 //========[ StateObject ]========//
StateObject()27 StateObject::StateObject() : ActionMapper()
28 {
29 }
30
registerState(StateObject * sb,const std::string & name)31 void StateObject::registerState(StateObject *sb, const std::string &name)
32 {
33 core->registerStateObject(sb, name);
34 }
35
~StateObject()36 StateObject::~StateObject()
37 {
38 }
39
removeState()40 void StateObject::removeState()
41 {
42 clearActions();
43 clearCreatedEvents();
44 //stateManager->getState(name)->eraseRenderObjects();
45 }
46
addRenderObject(RenderObject * renderObject,int layer)47 void StateObject::addRenderObject(RenderObject *renderObject, int layer)
48 {
49 stateManager->getState(name)->addRenderObject(renderObject, layer);
50 }
51
removeRenderObject(RenderObject * renderObject)52 void StateObject::removeRenderObject(RenderObject *renderObject)
53 {
54 stateManager->getState(name)->removeRenderObject(renderObject);
55 }
56
action(int id,int state)57 void StateObject::action(int id, int state)
58 {
59 }
60
update(float dt)61 void StateObject::update(float dt)
62 {
63 ActionMapper::onUpdate(dt);
64 }
65
66 //========[ STATEDATA ]========//
StateData()67 StateData::StateData()
68 {
69 stateObject = 0;
70 }
71
~StateData()72 StateData::~StateData()
73 {
74 /*
75 std::ostringstream os;
76 os << "removing " << renderObjects.size() << " render Objects";
77 MessageBox(0,os.str().c_str(),"",MB_OK);
78 */
79 for (int i = 0; i < renderObjects.size(); i++)
80 {
81 removeRenderObject (renderObjects[i]);
82 delete renderObjects[i];
83 }
84 }
85
addRenderObject(RenderObject * renderObject,int layer)86 void StateData::addRenderObject(RenderObject *renderObject, int layer)
87 {
88 core->addRenderObject(renderObject, layer);
89 renderObjects.push_back (renderObject);
90 renderObject->setStateDataObject(this);
91 renderObject->layer = layer;
92 }
93
removeRenderObject(RenderObject * renderObject)94 void StateData::removeRenderObject(RenderObject *renderObject)
95 {
96 core->enqueueRenderObjectDeletion(renderObject);
97
98 removeRenderObjectFromList(renderObject);
99 }
100
removeRenderObjectFromList(RenderObject * renderObject)101 void StateData::removeRenderObjectFromList(RenderObject *renderObject)
102 {
103 for (std::vector<RenderObject*>::iterator i = renderObjects.begin(); i != renderObjects.end(); )
104 {
105 if ((*i) == renderObject)
106 {
107 i = renderObjects.erase(i);
108 }
109 else
110 {
111 i ++;
112 }
113 }
114 }
115
116 // assume this only happens on render state end
eraseRenderObjects()117 void StateData::eraseRenderObjects()
118 {
119 // why clear garbage here?
120 //core->clearGarbage();
121
122 for (int i = 0; i < renderObjects.size(); i++)
123 {
124 RenderObject *r = renderObjects[i];
125 if (r && !r->isDead())
126 {
127 core->enqueueRenderObjectDeletion(renderObjects[i]);
128 }
129 }
130 renderObjects.clear();
131 }
132
133 //========[ STATEMANAGER ]========//
134
StateManager()135 StateManager::StateManager()
136 {
137 stateManager = this;
138 stateChangeFlag = false;
139 enqueuedStateStage = -1;
140 statesTopIndex = -1;
141 }
142
~StateManager()143 StateManager::~StateManager()
144 {
145 clearStateObjects();
146 }
147
getState(const std::string & state)148 StateData *StateManager::getState (const std::string &state)
149 {
150 for (int i = 0; i <= statesTopIndex; i++) {
151 StateData *s = states[i];
152 if (s->name == state)
153 return s;
154 }
155
156 return 0;
157 }
158
removeState(std::string state)159 void StateManager::removeState(std::string state)
160 {
161 getState(state)->eraseRenderObjects();
162 }
163
jumpState(const std::string & state)164 void StateManager::jumpState (const std::string &state)
165 {
166 if (canChangeState())
167 {
168 popAllStates();
169 pushState(state);
170 }
171 }
172
173 /*
174 enqueueJumpState
175 force will force the state change regardless of the result of canChangeState()
176 staged = if true, the manager will pop all the states and allow the system to clear garbage before pushing the new state
177 */
enqueueJumpState(const std::string & state,bool force,bool staged)178 void StateManager::enqueueJumpState (const std::string &state, bool force, bool staged)
179 {
180 if (force || canChangeState())
181 {
182 enqueuedJumpState = state;
183 if (staged)
184 {
185 enqueuedStateStage = 0;
186 }
187 else
188 {
189 enqueuedStateStage = -1;
190 }
191 }
192 }
193
isStateJumpPending()194 bool StateManager::isStateJumpPending()
195 {
196 return !enqueuedJumpState.empty();
197 }
198
pushState(const std::string & s)199 void StateManager::pushState(const std::string &s)
200 {
201 std::string state = s;
202 stringToLower(state);
203
204 if (canChangeState())
205 {
206 if (states_full())
207 {
208 debugLog("state stack overflow!!");
209 return;
210 }
211 StateData *s = new StateData;
212 s->name = state;
213 states[++statesTopIndex] = s;
214
215 applyState(state);
216
217 if (stateObjects[state])
218 {
219 s->stateObject = stateObjects[state];
220 stateObjects[state]->applyState();
221 }
222
223 stateChangeFlag = true;
224 }
225 }
226
popAllStates()227 void StateManager::popAllStates()
228 {
229 if (!states_empty())
230 {
231 popState();
232 popAllStates();
233 }
234 }
235
popState()236 void StateManager::popState()
237 {
238 if (canChangeState() && !states_empty())
239 {
240 if (stateObjects[(*(states_top())).name])
241 stateObjects[(*(states_top())).name]->removeState();
242 //states_top()->eraseRenderObjects();
243 std::string n = (*(states_top())).name;
244 removeState(n);
245 delete states_top();
246 if (core->getNestedMains()==1)
247 core->clearGarbage();
248 statesTopIndex--;
249 stateChangeFlag = true;
250 }
251 }
252
getNameFromDerivedClassTypeName(const std::string & typeidName)253 std::string StateManager::getNameFromDerivedClassTypeName(const std::string &typeidName)
254 {
255 /*
256 int loc = typeidName.find_last_of("class ");
257 if (loc != std::string::npos)
258 {
259 std::string tmp = typeidName.substr(6, typeidName.length());
260 int loc2 = tmp.find_last_of("::");
261 if (loc2 != std::string::npos)
262 return tmp.substr(loc2+1, tmp.size());
263 else
264 return tmp;
265 }
266 else
267 return typeidName;
268 */
269 return "";
270 }
271
registerStateObject(StateObject * stateObject,const std::string & name)272 void StateManager::registerStateObject(StateObject *stateObject, const std::string &name)
273 {
274 //const char *c = typeid(*stateObject).name();
275
276 stateObject->name = name;
277 stringToLower(stateObject->name);
278
279 //getNameFromDerivedClassTypeName(c);
280 if (stateObject->name.empty())
281 {
282 exit_error("StateManager::registerStateObject - Empty name.");
283 }
284
285 if (!stateObjects[stateObject->name])
286 stateObjects[stateObject->name] = stateObject;
287 /*
288 if (c)
289 free((void*)c);
290 */
291 }
292
addStateInstance(StateObject * s)293 StateObject *StateManager::addStateInstance(StateObject *s)
294 {
295 stateInstances.push_back(s);
296 return s;
297 }
298
clearStateInstances()299 void StateManager::clearStateInstances()
300 {
301 for (int i = 0; i < stateInstances.size(); i++)
302 {
303 StateObject *obj = stateInstances[i];
304 delete obj;
305 }
306 stateInstances.clear();
307 }
308
309
clearStateObjects()310 void StateManager::clearStateObjects()
311 {
312
313 stateObjects.clear();
314 }
315
onUpdate(float dt)316 void StateManager::onUpdate(float dt)
317 {
318 for (int i = 0; i <= statesTopIndex; i++)
319 {
320 StateObject *obj = stateObjects[states[i]->name];
321 if (obj)
322 obj->update(dt);
323 }
324
325 if (canChangeState() && !enqueuedJumpState.empty())
326 {
327 if (enqueuedStateStage == 0)
328 {
329 enqueuedStateStage = -1;
330 popAllStates();
331 }
332 else if (enqueuedStateStage == -1)
333 {
334 std::string copy = enqueuedJumpState;
335 enqueuedJumpState = "";
336 jumpState(copy);
337 }
338 }
339 }
340
getTopStateData()341 StateData *StateManager::getTopStateData()
342 {
343 if (!states_empty())
344 return states_top();
345 else
346 return 0;
347 }
348
getTopStateObject()349 StateObject *StateManager::getTopStateObject()
350 {
351 StateData *s = getTopStateData();
352 if (s)
353 {
354 return s->stateObject;
355 }
356 else
357 return 0;
358 }
359