1 /***************************************************************************
2  *   Copyright (C) 2006-2012 by the FIFE team                              *
3  *   http://www.fifengine.net                                              *
4  *   This file is part of FIFE.                                            *
5  *                                                                         *
6  *   FIFE is free software; you can redistribute it and/or                 *
7  *   modify it under the terms of the GNU Lesser General Public            *
8  *   License as published by the Free Software Foundation; either          *
9  *   version 2.1 of the License, or (at your option) any later version.    *
10  *                                                                         *
11  *   This library 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.  See the GNU     *
14  *   Lesser General Public License for more details.                       *
15  *                                                                         *
16  *   You should have received a copy of the GNU Lesser General Public      *
17  *   License along with this library; if not, write to the                 *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 
24 // 3rd party library includes
25 
26 // FIFE includes
27 // These includes are split up in two parts, separated by one empty line
28 // First block: files included from the FIFE root src directory
29 // Second block: files included from the same folder
30 #include "util/base/exception.h"
31 
32 #include "object.h"
33 #include "action.h"
34 #include "ipather.h"
35 
36 namespace FIFE {
37 
BasicObjectProperty()38 	Object::BasicObjectProperty::BasicObjectProperty():
39 		m_area(""),
40 		m_actions(NULL),
41 		m_defaultAction(NULL),
42 		m_blocking(false),
43 		m_static(false),
44 		m_cellStack(0) {
45 	}
~BasicObjectProperty()46 	Object::BasicObjectProperty::~BasicObjectProperty() {
47 		if (m_actions) {
48 			std::map<std::string, Action*>::const_iterator i(m_actions->begin());
49 			while (i != m_actions->end()) {
50 				delete i->second;
51 				++i;
52 			}
53 			delete m_actions;
54 		}
55 	}
56 
MovableObjectProperty()57 	Object::MovableObjectProperty::MovableObjectProperty():
58 		m_pather(NULL),
59 		m_costId(""),
60 		m_cost(1.0),
61 		m_speed(1.0),
62 		m_zRange(0) {
63 	}
~MovableObjectProperty()64 	Object::MovableObjectProperty::~MovableObjectProperty() {
65 	}
66 
MultiObjectProperty()67 	Object::MultiObjectProperty::MultiObjectProperty():
68 		m_multiPart(false),
69 		m_restrictedRotation(false) {
70 	}
~MultiObjectProperty()71 	Object::MultiObjectProperty::~MultiObjectProperty() {
72 	}
73 
Object(const std::string & identifier,const std::string & name_space,Object * inherited)74 	Object::Object(const std::string& identifier, const std::string& name_space, Object* inherited):
75 		m_id(identifier),
76 		m_namespace(name_space),
77 		m_filename(""),
78 		m_inherited(inherited),
79 		m_visual(NULL),
80 		m_basicProperty(NULL),
81 		m_moveProperty(NULL),
82 		m_multiProperty(NULL) {
83 	}
84 
~Object()85 	Object::~Object() {
86 		delete m_visual;
87 		delete m_basicProperty;
88 		delete m_moveProperty;
89 		delete m_multiProperty;
90 	}
91 
createAction(const std::string & identifier,bool is_default)92 	Action* Object::createAction(const std::string& identifier, bool is_default) {
93 		std::map<std::string, Action*>* actions;
94 		if (!m_basicProperty) {
95 			m_basicProperty = new BasicObjectProperty();
96 		}
97 
98 		if (!m_basicProperty->m_actions) {
99 			m_basicProperty->m_actions = new std::map<std::string, Action*>;
100 		}
101 		actions = m_basicProperty->m_actions;
102 
103 		std::map<std::string, Action*>::const_iterator it = actions->begin();
104 		for(; it != actions->end(); ++it) {
105 			if(identifier == it->second->getId()) {
106 				throw NameClash(identifier);
107 			}
108 		}
109 
110 		Action* a = getAction(identifier, false);
111 		if (!a) {
112 			a = new Action(identifier);
113 			(*actions)[identifier] = a;
114 			if (is_default || (!m_basicProperty->m_defaultAction)) {
115 				m_basicProperty->m_defaultAction = a;
116 			}
117 		}
118 		return a;
119 	}
120 
getAction(const std::string & identifier,bool deepsearch) const121 	Action* Object::getAction(const std::string& identifier, bool deepsearch) const {
122 		std::map<std::string, Action*>* actions = NULL;
123 		if (m_basicProperty) {
124 			actions = m_basicProperty->m_actions;
125 		}
126 
127 		std::map<std::string, Action*>::const_iterator i;
128 		if (actions) {
129 			i = actions->find(identifier);
130 		}
131 		if ((!actions) || (i == actions->end())) {
132 			if (m_inherited && deepsearch) {
133 				return m_inherited->getAction(identifier);
134 			}
135 			return NULL;
136 		}
137 		return i->second;
138 	}
139 
getActionIds() const140 	std::list<std::string> Object::getActionIds() const {
141 		std::map<std::string, Action*>* actions = NULL;
142 		if (m_basicProperty) {
143 			actions = m_basicProperty->m_actions;
144 		}
145 		std::list<std::string> action_ids;
146 		if (actions) {
147 			std::map<std::string, Action*>::const_iterator actions_it = actions->begin();
148 			for(; actions_it != actions->end(); ++actions_it) {
149 				action_ids.push_back(actions_it->first);
150 			}
151 		}
152 		return action_ids;
153 	}
154 
setDefaultAction(const std::string & identifier)155 	void Object::setDefaultAction(const std::string& identifier) {
156 		std::map<std::string, Action*>::const_iterator i;
157 		Action* action = NULL;
158 		std::map<std::string, Action*>* actions = NULL;
159 		if (m_basicProperty) {
160 			actions = m_basicProperty->m_actions;
161 		}
162 		if (actions) {
163 			i = actions->find(identifier);
164 		}
165 		if ((!actions) || (i == actions->end())) {
166 			if (m_inherited) {
167 				action = m_inherited->getAction(identifier);
168 			}
169 		} else {
170 			action = i->second;
171 		}
172 
173 		if (action && m_basicProperty) {
174 			m_basicProperty->m_defaultAction = action;
175 		}
176 	}
177 
getDefaultAction() const178 	Action* Object::getDefaultAction() const {
179 		if (m_basicProperty) {
180 			return m_basicProperty->m_defaultAction;
181 		}
182 		if (m_inherited) {
183 			return m_inherited->getDefaultAction();
184 		}
185 		return NULL;
186 	}
187 
setPather(IPather * pather)188 	void Object::setPather(IPather* pather) {
189 		if (!m_moveProperty) {
190 			m_moveProperty = new MovableObjectProperty();
191 		}
192 		m_moveProperty->m_pather = pather;
193 	}
194 
getPather() const195 	IPather* Object::getPather() const {
196 		if (m_moveProperty) {
197 			return m_moveProperty->m_pather;
198 		}
199 		if (m_inherited) {
200 			return m_inherited->getPather();
201 		}
202 		return NULL;
203 	}
204 
getInherited() const205 	Object* Object::getInherited() const {
206 		return m_inherited;
207 	}
208 
adoptVisual(IVisual * visual)209 	void Object::adoptVisual(IVisual* visual) {
210 		if (m_visual && m_visual != visual) {
211 			delete m_visual;
212 		}
213 		m_visual = visual;
214 	}
215 
setBlocking(bool blocking)216 	void Object::setBlocking(bool blocking) {
217 		if (!m_basicProperty) {
218 			m_basicProperty = new BasicObjectProperty();
219 		}
220 		m_basicProperty->m_blocking = blocking;
221 	}
222 
isBlocking() const223 	bool Object::isBlocking() const {
224 		if (m_basicProperty) {
225 			return m_basicProperty->m_blocking;
226 		}
227 		if (m_inherited) {
228 			return m_inherited->isBlocking();
229 		}
230 		return false;
231 	}
232 
setStatic(bool stat)233 	void Object::setStatic(bool stat) {
234 		if (!m_basicProperty) {
235 			m_basicProperty = new BasicObjectProperty();
236 		}
237 		m_basicProperty->m_static = stat;
238 	}
239 
isStatic() const240 	bool Object::isStatic() const {
241 		if (!m_basicProperty) {
242 			if (m_inherited) {
243 				return m_inherited->isStatic();
244 			}
245 			return false;
246 		}
247 		return m_basicProperty->m_static;
248 	}
249 
setFilename(const std::string & file)250 	void Object::setFilename(const std::string& file) {
251 		m_filename = file;
252 	}
253 
getFilename() const254 	const std::string& Object::getFilename() const {
255 		return m_filename;
256 	}
257 
setCellStackPosition(uint8_t position)258 	void Object::setCellStackPosition(uint8_t position) {
259 		if (!m_basicProperty) {
260 			m_basicProperty = new BasicObjectProperty();
261 		}
262 		m_basicProperty->m_cellStack = position;
263 	}
264 
getCellStackPosition() const265 	uint8_t Object::getCellStackPosition() const {
266 		if (m_basicProperty) {
267 			return m_basicProperty->m_cellStack;
268 		}
269 		if (m_inherited) {
270 			return m_inherited->getCellStackPosition();
271 		}
272 		return 0;
273 	}
274 
isSpecialCost() const275 	bool Object::isSpecialCost() const {
276 		if (m_moveProperty) {
277 			return m_moveProperty->m_costId != "";
278 		}
279 		if (m_inherited) {
280 			return m_inherited->isSpecialCost();
281 		}
282 		return false;
283 	}
284 
setCostId(const std::string & cost)285 	void Object::setCostId(const std::string& cost) {
286 		if (!m_moveProperty) {
287 			m_moveProperty = new MovableObjectProperty();
288 		}
289 		m_moveProperty->m_costId = cost;
290 	}
291 
getCostId() const292 	std::string Object::getCostId() const {
293 		if (m_moveProperty) {
294 			return m_moveProperty->m_costId;
295 		}
296 		if (m_inherited) {
297 			return m_inherited->getCostId();
298 		}
299 		return "";
300 	}
301 
setCost(double cost)302 	void Object::setCost(double cost) {
303 		if (!m_moveProperty) {
304 			m_moveProperty = new MovableObjectProperty();
305 		}
306 		m_moveProperty->m_cost = cost;
307 	}
308 
getCost() const309 	double Object::getCost() const {
310 		if (m_moveProperty) {
311 			return m_moveProperty->m_cost;
312 		}
313 		if (m_inherited) {
314 			return m_inherited->getCost();
315 		}
316 		return 1.0;
317 	}
318 
isSpecialSpeed() const319 	bool Object::isSpecialSpeed() const {
320 		if (m_moveProperty) {
321 			return !Mathd::Equal(m_moveProperty->m_speed, 1.0);
322 		}
323 		if (m_inherited) {
324 			return m_inherited->isSpecialSpeed();
325 		}
326 		return false;
327 	}
328 
setSpeed(double speed)329 	void Object::setSpeed(double speed) {
330 		if (!m_moveProperty) {
331 			m_moveProperty = new MovableObjectProperty();
332 		}
333 		m_moveProperty->m_speed = speed;
334 	}
335 
getSpeed() const336 	double Object::getSpeed() const {
337 		if (m_moveProperty) {
338 			return m_moveProperty->m_speed;
339 		}
340 		if (m_inherited) {
341 			return m_inherited->getSpeed();
342 		}
343 		return 1.0;
344 	}
345 
isMultiObject() const346 	bool Object::isMultiObject() const {
347 		if (m_multiProperty) {
348 			return !m_multiProperty->m_multiPartIds.empty();
349 		}
350 		if (m_inherited) {
351 			return m_inherited->isMultiObject();
352 		}
353 		return false;
354 	}
355 
addMultiPartId(const std::string & partId)356 	void Object::addMultiPartId(const std::string& partId) {
357 		if (!m_multiProperty) {
358 			m_multiProperty = new MultiObjectProperty();
359 		}
360 		m_multiProperty->m_multiPartIds.push_back(partId);
361 	}
362 
getMultiPartIds() const363 	std::list<std::string> Object::getMultiPartIds() const {
364 		if (m_multiProperty) {
365 			return m_multiProperty->m_multiPartIds;
366 		}
367 		if (m_inherited) {
368 			return m_inherited->getMultiPartIds();
369 		}
370 		return std::list<std::string>();
371 	}
372 
removeMultiPartId(const std::string & partId)373 	void Object::removeMultiPartId(const std::string& partId) {
374 		if (!m_multiProperty) {
375 			return;
376 		}
377 		std::list<std::string>::iterator it = m_multiProperty->m_multiPartIds.begin();
378 		for (; it != m_multiProperty->m_multiPartIds.end(); ++it) {
379 			if (*it == partId) {
380 				m_multiProperty->m_multiPartIds.erase(it);
381 				break;
382 			}
383 		}
384 	}
385 
removeAllMultiPartIds()386 	void Object::removeAllMultiPartIds() {
387 		if (!m_multiProperty) {
388 			return;
389 		}
390 		m_multiProperty->m_multiPartIds.clear();
391 	}
392 
isMultiPart() const393 	bool Object::isMultiPart() const {
394 		if (m_multiProperty) {
395 			return m_multiProperty->m_multiPart;
396 		}
397 		if (m_inherited) {
398 			return m_inherited->isMultiPart();
399 		}
400 		return false;
401 	}
402 
setMultiPart(bool part)403 	void Object::setMultiPart(bool part) {
404 		if (!m_multiProperty) {
405 			m_multiProperty = new MultiObjectProperty();
406 		}
407 		m_multiProperty->m_multiPart = part;
408 	}
409 
addMultiPart(Object * obj)410 	void Object::addMultiPart(Object* obj) {
411 		if (!m_multiProperty) {
412 			m_multiProperty = new MultiObjectProperty();
413 		}
414 		m_multiProperty->m_multiParts.insert(obj);
415 	}
416 
getMultiParts() const417 	std::set<Object*> Object::getMultiParts() const {
418 		if (m_multiProperty) {
419 			return m_multiProperty->m_multiParts;
420 		}
421 		if (m_inherited) {
422 			return m_inherited->getMultiParts();
423 		}
424 		return std::set<Object*>();
425 	}
426 
removeMultiPart(Object * obj)427 	void Object::removeMultiPart(Object* obj) {
428 		if (!m_multiProperty) {
429 			return;
430 		}
431 		m_multiProperty->m_multiParts.erase(obj);
432 
433 	}
434 
removeMultiParts()435 	void Object::removeMultiParts() {
436 		if (!m_multiProperty) {
437 			return;
438 		}
439 		m_multiProperty->m_multiParts.clear();
440 	}
441 
addMultiPartCoordinate(int32_t rotation,ModelCoordinate coord)442 	void Object::addMultiPartCoordinate(int32_t rotation, ModelCoordinate coord) {
443 		if (!m_multiProperty) {
444 			m_multiProperty = new MultiObjectProperty();
445 		}
446 		m_multiProperty->m_multiPartCoordinates.insert(std::pair<int32_t, ModelCoordinate>(rotation, coord));
447 		m_multiProperty->m_partAngleMap[rotation] = rotation;
448 	}
449 
getMultiPartCoordinates() const450 	std::multimap<int32_t, ModelCoordinate> Object::getMultiPartCoordinates() const {
451 		if (m_multiProperty) {
452 			return m_multiProperty->m_multiPartCoordinates;
453 		}
454 		if (m_inherited) {
455 			return m_inherited->getMultiPartCoordinates();
456 		}
457 		return std::multimap<int32_t, ModelCoordinate>();
458 	}
459 
getMultiPartCoordinates(int32_t rotation) const460 	std::vector<ModelCoordinate> Object::getMultiPartCoordinates(int32_t rotation) const {
461 		std::vector<ModelCoordinate> coordinates;
462 
463 		if (m_multiProperty) {
464 			int32_t closest = 0;
465 			getIndexByAngle(rotation, m_multiProperty->m_partAngleMap, closest);
466 			std::pair<std::multimap<int32_t, ModelCoordinate>::iterator,
467 				std::multimap<int32_t, ModelCoordinate>::iterator> result = m_multiProperty->m_multiPartCoordinates.equal_range(closest);
468 			std::multimap<int32_t, ModelCoordinate>::iterator it = result.first;
469 			for (; it != result.second; ++it) {
470 				coordinates.push_back((*it).second);
471 			}
472 		} else if (m_inherited) {
473 			return m_inherited->getMultiPartCoordinates(rotation);
474 		}
475 		return coordinates;
476 	}
477 
getMultiObjectCoordinates(int32_t rotation) const478 	std::vector<ModelCoordinate> Object::getMultiObjectCoordinates(int32_t rotation) const {
479 		std::vector<ModelCoordinate> coordinates;
480 		if (m_multiProperty) {
481 			if (m_multiProperty->m_multiObjectCoordinates.empty()) {
482 				std::set<Object*>::iterator subit = m_multiProperty->m_multiParts.begin();
483 				for (; subit != m_multiProperty->m_multiParts.end(); ++subit) {
484 					const std::multimap<int32_t, ModelCoordinate>& subcoords = (*subit)->getMultiPartCoordinates();
485 					m_multiProperty->m_multiObjectCoordinates.insert(subcoords.begin(), subcoords.end());
486 				}
487 				std::multimap<int32_t, ModelCoordinate>::iterator it = m_multiProperty->m_multiObjectCoordinates.begin();
488 				for (; it != m_multiProperty->m_multiObjectCoordinates.end(); ++it) {
489 					m_multiProperty->m_multiAngleMap[(*it).first] = (*it).first;
490 				}
491 			}
492 			int32_t closest = 0;
493 			getIndexByAngle(rotation, m_multiProperty->m_multiAngleMap, closest);
494 			std::pair<std::multimap<int32_t, ModelCoordinate>::iterator,
495 				std::multimap<int32_t, ModelCoordinate>::iterator> result = m_multiProperty->m_multiObjectCoordinates.equal_range(closest);
496 			std::multimap<int32_t, ModelCoordinate>::iterator it = result.first;
497 			ModelCoordinate parent(0,0);
498 			coordinates.push_back(parent);
499 			for (; it != result.second; ++it) {
500 				coordinates.push_back((*it).second);
501 			}
502 		} else if (m_inherited) {
503 			return m_inherited->getMultiObjectCoordinates(rotation);
504 		}
505 		return coordinates;
506 	}
507 
setRotationAnchor(const ExactModelCoordinate & anchor)508 	void Object::setRotationAnchor(const ExactModelCoordinate& anchor) {
509 		if (!m_multiProperty) {
510 			m_multiProperty = new MultiObjectProperty();
511 		}
512 		m_multiProperty->m_rotationAnchor = anchor;
513 	}
514 
getRotationAnchor() const515 	ExactModelCoordinate Object::getRotationAnchor() const {
516 		if (m_multiProperty) {
517 			return m_multiProperty->m_rotationAnchor;
518 		}
519 		if (m_inherited) {
520 			return m_inherited->getRotationAnchor();
521 		}
522 		return ExactModelCoordinate();
523 	}
524 
setRestrictedRotation(bool restrict)525 	void Object::setRestrictedRotation(bool restrict) {
526 		if (!m_multiProperty) {
527 			m_multiProperty = new MultiObjectProperty();
528 		}
529 		m_multiProperty->m_restrictedRotation = restrict;
530 	}
531 
isRestrictedRotation() const532 	bool Object::isRestrictedRotation() const {
533 		if (m_multiProperty) {
534 			return m_multiProperty->m_restrictedRotation;
535 		}
536 		if (m_inherited) {
537 			return m_inherited->isRestrictedRotation();
538 		}
539 		return false;
540 	}
541 
getRestrictedRotation(int32_t rotation)542 	int32_t Object::getRestrictedRotation(int32_t rotation) {
543 		int32_t closest = rotation;
544 		if (m_multiProperty) {
545 			if (!m_multiProperty->m_multiAngleMap.empty()) {
546 				getIndexByAngle(rotation, m_multiProperty->m_multiAngleMap, closest);
547 			} else if (!m_multiProperty->m_partAngleMap.empty()) {
548 				getIndexByAngle(rotation, m_multiProperty->m_partAngleMap, closest);
549 			}
550 		} else if (m_inherited) {
551 			return m_inherited->getRestrictedRotation(rotation);
552 		}
553 		return closest;
554 	}
555 
setZStepRange(int32_t zRange)556 	void Object::setZStepRange(int32_t zRange) {
557 		if (!m_moveProperty) {
558 			m_moveProperty = new MovableObjectProperty();
559 		}
560 		m_moveProperty->m_zRange = zRange;
561 	}
562 
getZStepRange() const563 	int32_t Object::getZStepRange() const {
564 		if (m_moveProperty) {
565 			return m_moveProperty->m_zRange;
566 		}
567 		if (m_inherited) {
568 			return m_inherited->getZStepRange();
569 		}
570 		return 0;
571 	}
572 
setArea(const std::string & id)573 	void Object::setArea(const std::string& id) {
574 		if (!m_basicProperty) {
575 			m_basicProperty = new BasicObjectProperty();
576 		}
577 		m_basicProperty->m_area = id;
578 	}
579 
getArea() const580 	std::string Object::getArea() const {
581 		if (m_basicProperty) {
582 			return m_basicProperty->m_area;
583 		}
584 		if (m_inherited) {
585 			return m_inherited->getArea();
586 		}
587 		return "";
588 	}
589 
addWalkableArea(const std::string & id)590 	void Object::addWalkableArea(const std::string& id) {
591 		if (!m_moveProperty) {
592 			m_moveProperty = new MovableObjectProperty();
593 		}
594 		m_moveProperty->m_walkableAreas.push_back(id);
595 		m_moveProperty->m_walkableAreas.sort();
596 		m_moveProperty->m_walkableAreas.unique();
597 	}
598 
removeWalkableArea(const std::string & id)599 	void Object::removeWalkableArea(const std::string& id) {
600 		if (!m_moveProperty) {
601 			return;
602 		}
603 		m_moveProperty->	m_walkableAreas.remove(id);
604 	}
605 
getWalkableAreas() const606 	std::list<std::string> Object::getWalkableAreas() const {
607 		if (m_moveProperty) {
608 			return m_moveProperty->m_walkableAreas;
609 		}
610 		if (m_inherited) {
611 			return m_inherited->getWalkableAreas();
612 		}
613 		return std::list<std::string>();
614 	}
615 
operator ==(const Object & obj) const616 	bool Object::operator==(const Object& obj) const {
617 		return m_id == obj.getId() && m_namespace == obj.getNamespace();
618 	}
619 
operator !=(const Object & obj) const620 	bool Object::operator!=(const Object& obj) const {
621 		return m_id != obj.getId() || m_namespace != obj.getNamespace();
622 	}
623 
624 }
625