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