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