1 /*************************************************************************** 2 * Copyright (C) 2005-2019 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 #include <iostream> 24 25 // 3rd party library includes 26 //#include <SDL.h> 27 28 // FIFE includes 29 // These includes are split up in two parts, separated by one empty line 30 // First block: files included from the FIFE root src directory 31 // Second block: files included from the same folder 32 #include "audio/soundsource.h" 33 #include "util/log/logger.h" 34 #include "util/base/exception.h" 35 #include "util/math/fife_math.h" 36 #include "util/time/timemanager.h" 37 #include "model/metamodel/grids/cellgrid.h" 38 #include "model/metamodel/ipather.h" 39 #include "model/metamodel/action.h" 40 #include "model/metamodel/timeprovider.h" 41 #include "model/structures/layer.h" 42 #include "model/structures/map.h" 43 #include "model/structures/instancetree.h" 44 #include "view/visual.h" 45 #include "pathfinder/route.h" 46 47 #include "instance.h" 48 49 namespace FIFE { 50 static Logger _log(LM_INSTANCE); 51 52 class ActionInfo { 53 public: ActionInfo(IPather * pather,const Location & curloc)54 ActionInfo(IPather* pather, const Location& curloc): 55 m_action(NULL), 56 m_target(NULL), 57 m_speed(0), 58 m_repeating(false), 59 m_action_start_time(0), 60 m_action_offset_time(0), 61 m_prev_call_time(0), 62 m_pather(pather), 63 m_leader(NULL), 64 m_route(NULL), 65 m_delete_route(true) {} 66 ~ActionInfo()67 ~ActionInfo() { 68 if (m_route && m_delete_route) { 69 int32_t sessionId = m_route->getSessionId(); 70 if (sessionId != -1) { 71 m_pather->cancelSession(sessionId); 72 } 73 delete m_route; 74 } 75 delete m_target; 76 } 77 78 // Current action, owned by object 79 Action* m_action; 80 // target location for ongoing movement 81 Location* m_target; 82 // current movement speed 83 double m_speed; 84 // should action be repeated? used only for non-moving actions, moving ones repeat until movement is finished 85 bool m_repeating; 86 // action start time (ticks) 87 uint32_t m_action_start_time; 88 // action offset time (ticks) for resuming an action 89 uint32_t m_action_offset_time; 90 // ticks since last call 91 uint32_t m_prev_call_time; 92 // pather 93 IPather* m_pather; 94 // leader for follow activity 95 Instance* m_leader; 96 // pointer to route that contain path and additional information 97 Route* m_route; 98 bool m_delete_route; 99 }; 100 101 class SayInfo { 102 public: SayInfo(const std::string & txt,uint32_t duration)103 SayInfo(const std::string& txt, uint32_t duration): 104 m_txt(txt), 105 m_duration(duration), 106 m_start_time(0) {} 107 108 std::string m_txt; 109 uint32_t m_duration; 110 uint32_t m_start_time; 111 }; 112 InstanceActivity(Instance & source)113 Instance::InstanceActivity::InstanceActivity(Instance& source): 114 m_location(source.m_location), 115 m_oldLocation(source.m_location), 116 m_rotation(source.m_rotation), 117 m_oldRotation(source.m_rotation), 118 m_action(NULL), 119 m_soundSource(NULL), 120 m_speed(0), 121 m_timeMultiplier(1.0), 122 m_sayText(""), 123 m_changeListeners(), 124 m_actionListeners(), 125 m_actionInfo(NULL), 126 m_sayInfo(NULL), 127 m_timeProvider(NULL), 128 m_blocking(source.m_blocking), 129 m_additional(ICHANGE_NO_CHANGES) { 130 } 131 ~InstanceActivity()132 Instance::InstanceActivity::~InstanceActivity() { 133 delete m_actionInfo; 134 delete m_sayInfo; 135 delete m_timeProvider; 136 delete m_soundSource; 137 } 138 update(Instance & source)139 void Instance::InstanceActivity::update(Instance& source) { 140 source.m_changeInfo = ICHANGE_NO_CHANGES; 141 if (m_additional != ICHANGE_NO_CHANGES) { 142 source.m_changeInfo = m_additional; 143 m_additional = ICHANGE_NO_CHANGES; 144 } 145 if (m_location != source.m_location) { 146 source.m_changeInfo |= ICHANGE_LOC; 147 if (m_location.getLayerCoordinates() != source.m_location.getLayerCoordinates()) { 148 m_oldLocation.setLayer(m_location.getLayer()); 149 m_oldLocation.setLayerCoordinates(m_location.getLayerCoordinates()); 150 source.m_changeInfo |= ICHANGE_CELL; 151 } 152 m_location = source.m_location; 153 } 154 if (m_rotation != source.m_rotation) { 155 m_oldRotation = m_rotation; 156 source.m_changeInfo |= ICHANGE_ROTATION; 157 m_rotation = source.m_rotation; 158 } 159 if (m_actionInfo && (m_speed != m_actionInfo->m_speed)) { 160 source.m_changeInfo |= ICHANGE_SPEED; 161 m_speed = m_actionInfo->m_speed; 162 } 163 if (m_actionInfo && (m_action != m_actionInfo->m_action)) { 164 source.m_changeInfo |= ICHANGE_ACTION; 165 m_action = m_actionInfo->m_action; 166 } 167 if (m_timeProvider && (m_timeMultiplier != m_timeProvider->getMultiplier())) { 168 source.m_changeInfo |= ICHANGE_TIME_MULTIPLIER; 169 m_timeMultiplier = m_timeProvider->getMultiplier(); 170 } 171 if (m_sayInfo && (m_sayText != m_sayInfo->m_txt)) { 172 source.m_changeInfo |= ICHANGE_SAYTEXT; 173 m_sayText = m_sayInfo->m_txt; 174 } 175 if (m_blocking != source.m_blocking) { 176 source.m_changeInfo |= ICHANGE_BLOCK; 177 m_blocking = source.m_blocking; 178 } 179 180 if (source.m_changeInfo != ICHANGE_NO_CHANGES) { 181 std::vector<InstanceChangeListener*>::iterator i = m_changeListeners.begin(); 182 while (i != m_changeListeners.end()) { 183 if (NULL != *i) 184 { 185 (*i)->onInstanceChanged(&source, source.m_changeInfo); 186 } 187 ++i; 188 } 189 // Really remove "removed" listeners. 190 m_changeListeners.erase( 191 std::remove(m_changeListeners.begin(),m_changeListeners.end(), 192 (InstanceChangeListener*)NULL), 193 m_changeListeners.end()); 194 } 195 } 196 Instance(Object * object,const Location & location,const std::string & identifier)197 Instance::Instance(Object* object, const Location& location, const std::string& identifier): 198 m_id(identifier), 199 m_rotation(0), 200 m_activity(NULL), 201 m_changeInfo(ICHANGE_NO_CHANGES), 202 m_object(object), 203 m_ownObject(false), 204 m_location(location), 205 m_visual(NULL), 206 m_blocking(object->isBlocking()), 207 m_overrideBlocking(false), 208 m_cellStackPos(object->getCellStackPosition()), 209 m_specialCost(object->isSpecialCost()), 210 m_cost(object->getCost()), 211 m_costId(object->getCostId()), 212 m_mainMultiInstance(NULL) { 213 // create multi object instances 214 if (object->isMultiObject()) { 215 m_mainMultiInstance = this; 216 uint32_t count = 0; 217 Layer* layer = m_location.getLayer(); 218 const ExactModelCoordinate& emc = m_location.getExactLayerCoordinatesRef(); 219 const std::set<Object*>& multis = object->getMultiParts(); 220 std::set<Object*>::const_iterator it = multis.begin(); 221 for (; it != multis.end(); ++it, ++count) { 222 if (*it == m_object) { 223 continue; 224 } 225 std::vector<ModelCoordinate> partcoords = (*it)->getMultiPartCoordinates(m_rotation); 226 std::vector<ModelCoordinate>::iterator coordit = partcoords.begin(); 227 for (; coordit != partcoords.end(); ++coordit) { 228 ExactModelCoordinate tmp_emc(emc.x+(*coordit).x, emc.y+(*coordit).y, emc.z+(*coordit).z); 229 std::ostringstream counter; 230 counter << count; 231 Instance* instance = layer->createInstance(*it, tmp_emc, identifier+counter.str()); 232 InstanceVisual::create(instance); 233 m_multiInstances.push_back(instance); 234 instance->addDeleteListener(this); 235 instance->setMainMultiInstance(this); 236 } 237 } 238 } 239 } 240 ~Instance()241 Instance::~Instance() { 242 std::vector<InstanceDeleteListener *>::iterator itor; 243 for(itor = m_deleteListeners.begin(); itor != m_deleteListeners.end(); ++itor) { 244 if (*itor != NULL) { 245 (*itor)->onInstanceDeleted(this); 246 } 247 } 248 249 if(m_activity && m_activity->m_actionInfo) { 250 // Don't ditribute onActionFinished in case we're already 251 // deleting. 252 m_activity->m_actionListeners.clear(); 253 finalizeAction(); 254 } 255 256 if (!m_multiInstances.empty()) { 257 std::vector<Instance*>::iterator it = m_multiInstances.begin(); 258 for (; it != m_multiInstances.end(); ++it) { 259 (*it)->removeDeleteListener(this); 260 (*it)->setMainMultiInstance(NULL); 261 } 262 } 263 264 delete m_activity; 265 delete m_visual; 266 if (m_ownObject) { 267 delete m_object; 268 } 269 } 270 initializeChanges()271 void Instance::initializeChanges() { 272 if (!m_activity) { 273 m_activity = new InstanceActivity(*this); 274 } 275 if (m_location.getLayer()) { 276 m_location.getLayer()->setInstanceActivityStatus(this, true); 277 } 278 } 279 prepareForUpdate()280 void Instance::prepareForUpdate() { 281 if (isActive()) { 282 refresh(); 283 } else { 284 initializeChanges(); 285 } 286 } 287 isActive() const288 bool Instance::isActive() const { 289 return (m_activity != 0); 290 } 291 getObject()292 Object* Instance::getObject() { 293 return m_object; 294 } 295 setLocation(const Location & loc)296 void Instance::setLocation(const Location& loc) { 297 // ToDo: Handle the case when the layers are different 298 if(m_location != loc) { 299 prepareForUpdate(); 300 301 if (m_location.getLayerCoordinates() != loc.getLayerCoordinates()) { 302 m_location.getLayer()->getInstanceTree()->removeInstance(this); 303 m_location = loc; 304 m_location.getLayer()->getInstanceTree()->addInstance(this); 305 } else { 306 m_location = loc; 307 } 308 } 309 } 310 getLocation() const311 Location Instance::getLocation() const { 312 return m_location; 313 } 314 getLocationRef()315 Location& Instance::getLocationRef() { 316 return m_location; 317 } 318 setRotation(int32_t rotation)319 void Instance::setRotation(int32_t rotation) { 320 while (rotation < 0) { 321 rotation += 360; 322 } 323 rotation %= 360; 324 if(m_rotation != rotation) { 325 prepareForUpdate(); 326 m_rotation = rotation; 327 } 328 } 329 getRotation() const330 int32_t Instance::getRotation() const { 331 return m_rotation; 332 } 333 setId(const std::string & identifier)334 void Instance::setId(const std::string& identifier) { 335 m_id = identifier; 336 } 337 getId()338 const std::string& Instance::getId() { 339 return m_id; 340 } 341 setBlocking(bool blocking)342 void Instance::setBlocking(bool blocking) { 343 if (m_overrideBlocking) { 344 prepareForUpdate(); 345 m_blocking = blocking; 346 } 347 } 348 isBlocking() const349 bool Instance::isBlocking() const { 350 return m_blocking; 351 } 352 setOverrideBlocking(bool overblock)353 void Instance::setOverrideBlocking(bool overblock) { 354 m_overrideBlocking = overblock; 355 } 356 isOverrideBlocking() const357 bool Instance::isOverrideBlocking() const { 358 return m_overrideBlocking; 359 } 360 addActionListener(InstanceActionListener * listener)361 void Instance::addActionListener(InstanceActionListener* listener) { 362 initializeChanges(); 363 m_activity->m_actionListeners.push_back(listener); 364 } 365 removeActionListener(InstanceActionListener * listener)366 void Instance::removeActionListener(InstanceActionListener* listener) { 367 if (!m_activity) { 368 return; 369 } 370 std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionListeners.begin(); 371 while (i != m_activity->m_actionListeners.end()) { 372 if ((*i) == listener) { 373 *i = NULL; 374 return; 375 } 376 ++i; 377 } 378 FL_WARN(_log, "Cannot remove unknown listener"); 379 } 380 addChangeListener(InstanceChangeListener * listener)381 void Instance::addChangeListener(InstanceChangeListener* listener) { 382 initializeChanges(); 383 m_activity->m_changeListeners.push_back(listener); 384 } 385 callOnActionFrame(Action * action,int32_t frame)386 void Instance::callOnActionFrame(Action* action, int32_t frame) { 387 if (!m_activity) { 388 return; 389 } 390 391 std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionListeners.begin(); 392 while (i != m_activity->m_actionListeners.end()) { 393 if(*i) { 394 (*i)->onInstanceActionFrame(this, action, frame); 395 } 396 ++i; 397 } 398 } 399 removeChangeListener(InstanceChangeListener * listener)400 void Instance::removeChangeListener(InstanceChangeListener* listener) { 401 if (!m_activity) { 402 return; 403 } 404 std::vector<InstanceChangeListener*>::iterator i = m_activity->m_changeListeners.begin(); 405 while (i != m_activity->m_changeListeners.end()) { 406 if ((*i) == listener) { 407 *i = NULL; 408 return; 409 } 410 ++i; 411 } 412 FL_WARN(_log, "Cannot remove unknown listener"); 413 } 414 initializeAction(const std::string & actionName)415 void Instance::initializeAction(const std::string& actionName) { 416 assert(m_object); 417 418 initializeChanges(); 419 const Action *old_action = m_activity->m_actionInfo ? m_activity->m_actionInfo->m_action : NULL; 420 if (m_activity->m_actionInfo) { 421 cancelAction(); 422 } 423 m_activity->m_actionInfo = new ActionInfo(m_object->getPather(), m_location); 424 m_activity->m_actionInfo->m_action = m_object->getAction(actionName); 425 if (!m_activity->m_actionInfo->m_action) { 426 delete m_activity->m_actionInfo; 427 m_activity->m_actionInfo = NULL; 428 throw NotFound(std::string("action ") + actionName + " not found"); 429 } 430 m_activity->m_actionInfo->m_prev_call_time = getRuntime(); 431 if (m_activity->m_actionInfo->m_action != old_action) { 432 m_activity->m_actionInfo->m_action_start_time = m_activity->m_actionInfo->m_prev_call_time; 433 } 434 // start sound 435 if (m_activity->m_actionInfo->m_action->getAudio()) { 436 if (!m_activity->m_soundSource) { 437 m_activity->m_soundSource = new SoundSource(this); 438 } 439 m_activity->m_soundSource->setActionAudio(m_activity->m_actionInfo->m_action->getAudio()); 440 } else if (old_action && old_action->getAudio()) { 441 m_activity->m_soundSource->setActionAudio(NULL); 442 } 443 444 if (isMultiObject()) { 445 std::vector<Instance*>::iterator multi_it = m_multiInstances.begin(); 446 for (; multi_it != m_multiInstances.end(); ++multi_it) { 447 (*multi_it)->initializeAction(actionName); 448 } 449 } 450 } 451 move(const std::string & actionName,const Location & target,const double speed,const std::string & costId)452 void Instance::move(const std::string& actionName, const Location& target, const double speed, const std::string& costId) { 453 // if new move is identical with the old then return 454 if (m_activity) { 455 if (m_activity->m_actionInfo) { 456 if (m_activity->m_actionInfo->m_target) { 457 if (m_activity->m_actionInfo->m_target->getLayerCoordinates() == target.getLayerCoordinates() && 458 Mathd::Equal(speed, m_activity->m_actionInfo->m_speed) && 459 m_activity->m_actionInfo->m_action == m_object->getAction(actionName) && 460 costId == m_activity->m_actionInfo->m_route->getCostId()) { 461 462 return; 463 } 464 } 465 } 466 } 467 initializeAction(actionName); 468 m_activity->m_actionInfo->m_target = new Location(target); 469 m_activity->m_actionInfo->m_speed = speed; 470 FL_DBG(_log, LMsg("starting action ") << actionName << " from" << m_location << " to " << target << " with speed " << speed); 471 472 Route* route = m_activity->m_actionInfo->m_route; 473 if (!route) { 474 route = new Route(m_location, *m_activity->m_actionInfo->m_target); 475 route->setRotation(getRotation()); 476 if (costId != "") { 477 route->setCostId(costId); 478 } 479 if (isMultiCell()) { 480 route->setObject(m_object); 481 route->setOccupiedArea(m_location.getLayer()->getCellGrid()-> 482 toMultiCoordinates(m_location.getLayerCoordinates(), m_object->getMultiObjectCoordinates(m_rotation))); 483 } else if (m_object->getZStepRange() != -1 || !m_object->getWalkableAreas().empty()) { 484 route->setObject(m_object); 485 } 486 m_activity->m_actionInfo->m_route = route; 487 if (!m_activity->m_actionInfo->m_pather->solveRoute(route)) { 488 setFacingLocation(target); 489 finalizeAction(); 490 } 491 } 492 } 493 follow(const std::string & actionName,Instance * leader,const double speed)494 void Instance::follow(const std::string& actionName, Instance* leader, const double speed) { 495 initializeAction(actionName); 496 m_activity->m_actionInfo->m_target = new Location(leader->getLocationRef()); 497 m_activity->m_actionInfo->m_speed = speed; 498 m_activity->m_actionInfo->m_leader = leader; 499 leader->addDeleteListener(this); 500 FL_DBG(_log, LMsg("starting action ") << actionName << " from" << m_location << " to " << *m_activity->m_actionInfo->m_target << " with speed " << speed); 501 } 502 follow(const std::string & actionName,Route * route,const double speed)503 void Instance::follow(const std::string& actionName, Route* route, const double speed) { 504 initializeAction(actionName); 505 m_activity->m_actionInfo->m_target = new Location(route->getEndNode()); 506 m_activity->m_actionInfo->m_speed = speed; 507 m_activity->m_actionInfo->m_route = route; 508 m_activity->m_actionInfo->m_delete_route = false; 509 if (isMultiCell()) { 510 route->setObject(m_object); 511 route->setOccupiedArea(m_location.getLayer()->getCellGrid()-> 512 toMultiCoordinates(m_location.getLayerCoordinates(), m_object->getMultiObjectCoordinates(m_rotation))); 513 } else if (m_object->getZStepRange() != -1 || !m_object->getWalkableAreas().empty()) { 514 route->setObject(m_object); 515 } 516 FL_DBG(_log, LMsg("starting action ") << actionName << " from" << m_location << " to " << *m_activity->m_actionInfo->m_target << " with speed " << speed); 517 } 518 cancelMovement(uint32_t length)519 void Instance::cancelMovement(uint32_t length) { 520 if (m_activity) { 521 ActionInfo* info = m_activity->m_actionInfo; 522 if (info) { 523 Route* route = info->m_route; 524 if (route) { 525 route->cutPath(length); 526 } 527 } 528 } 529 } 530 getRoute()531 Route* Instance::getRoute() { 532 if (m_activity) { 533 ActionInfo* info = m_activity->m_actionInfo; 534 if (info) { 535 return info->m_route; 536 } 537 } 538 return NULL; 539 } 540 setCellStackPosition(uint8_t stack)541 void Instance::setCellStackPosition(uint8_t stack) { 542 m_cellStackPos = stack; 543 } 544 getCellStackPosition()545 uint8_t Instance::getCellStackPosition() { 546 return m_cellStackPos; 547 } 548 isSpecialCost()549 bool Instance::isSpecialCost() { 550 return m_specialCost; 551 } 552 getMultiInstances()553 const std::vector<Instance*>& Instance::getMultiInstances() { 554 return m_multiInstances; 555 } 556 setMainMultiInstance(Instance * main)557 void Instance::setMainMultiInstance(Instance* main) { 558 m_mainMultiInstance = main; 559 } 560 getMainMultiInstance()561 Instance* Instance::getMainMultiInstance() { 562 return m_mainMultiInstance; 563 } 564 actOnce(const std::string & actionName,const Location & direction)565 void Instance::actOnce(const std::string& actionName, const Location& direction) { 566 initializeAction(actionName); 567 m_activity->m_actionInfo->m_repeating = false; 568 setFacingLocation(direction); 569 } 570 actOnce(const std::string & actionName,int32_t rotation)571 void Instance::actOnce(const std::string& actionName, int32_t rotation) { 572 initializeAction(actionName); 573 m_activity->m_actionInfo->m_repeating = false; 574 setRotation(rotation); 575 } 576 actOnce(const std::string & actionName)577 void Instance::actOnce(const std::string& actionName) { 578 initializeAction(actionName); 579 m_activity->m_actionInfo->m_repeating = false; 580 } 581 actRepeat(const std::string & actionName,const Location & direction)582 void Instance::actRepeat(const std::string& actionName, const Location& direction) { 583 initializeAction(actionName); 584 m_activity->m_actionInfo->m_repeating = true; 585 setFacingLocation(direction); 586 } 587 actRepeat(const std::string & actionName,int32_t rotation)588 void Instance::actRepeat(const std::string& actionName, int32_t rotation) { 589 initializeAction(actionName); 590 m_activity->m_actionInfo->m_repeating = true; 591 setRotation(rotation); 592 } 593 actRepeat(const std::string & actionName)594 void Instance::actRepeat(const std::string& actionName) { 595 initializeAction(actionName); 596 m_activity->m_actionInfo->m_repeating = true; 597 } 598 say(const std::string & text,uint32_t duration)599 void Instance::say(const std::string& text, uint32_t duration) { 600 initializeChanges(); 601 delete m_activity->m_sayInfo; 602 m_activity->m_sayInfo = NULL; 603 604 if (text != "") { 605 m_activity->m_sayInfo = new SayInfo(text, duration); 606 m_activity->m_sayInfo->m_start_time = getRuntime(); 607 } 608 } 609 getSayText() const610 const std::string* Instance::getSayText() const { 611 if (m_activity && m_activity->m_sayInfo) { 612 return &m_activity->m_sayInfo->m_txt; 613 } 614 return NULL; 615 } 616 processMovement()617 bool Instance::processMovement() { 618 ActionInfo* info = m_activity->m_actionInfo; 619 Route* route = info->m_route; 620 Location target; 621 if (info->m_leader) { 622 target = info->m_leader->getLocationRef(); 623 } else { 624 target = *info->m_target; 625 } 626 if (!route) { 627 route = new Route(m_location, *info->m_target); 628 route->setRotation(getRotation()); 629 info->m_route = route; 630 if (isMultiCell()) { 631 route->setObject(m_object); 632 route->setOccupiedArea(m_location.getLayer()->getCellGrid()-> 633 toMultiCoordinates(m_location.getLayerCoordinates(), m_object->getMultiObjectCoordinates(m_rotation))); 634 } else if (m_object->getZStepRange() != -1 || !m_object->getWalkableAreas().empty()) { 635 route->setObject(m_object); 636 } 637 if (!info->m_pather->solveRoute(route)) { 638 setFacingLocation(target); 639 return true; 640 } 641 // update target if needed 642 } else if (route->getEndNode().getLayerCoordinates() != target.getLayerCoordinates()) { 643 if (route->isReplanned() || isMultiCell()) { 644 *info->m_target = route->getEndNode(); 645 route->setReplanned(false); 646 if (isMultiCell()) { 647 route->setOccupiedArea(m_location.getLayer()->getCellGrid()-> 648 toMultiCoordinates(m_location.getLayerCoordinates(), m_object->getMultiObjectCoordinates(m_rotation))); 649 } 650 } else { 651 if (route->getPathLength() == 0) { 652 route->setStartNode(m_location); 653 } else { 654 route->setStartNode(route->getCurrentNode()); 655 } 656 route->setEndNode(target); 657 if (!info->m_pather->solveRoute(route)) { 658 setFacingLocation(target); 659 return true; 660 } 661 } 662 } 663 664 if (route->getRouteStatus() == ROUTE_SOLVED) { 665 // timeslice for this movement 666 uint32_t timedelta = m_activity->m_timeProvider->getGameTime() - info->m_prev_call_time; 667 // how far we can travel 668 double distance_to_travel = (static_cast<double>(timedelta) / 1000.0) * info->m_speed; 669 // location for this movement 670 Location nextLocation = m_location; 671 bool can_follow = info->m_pather->followRoute(m_location, route, distance_to_travel, nextLocation); 672 if (can_follow) { 673 setRotation(route->getRotation()); 674 // move to another layer 675 if (m_location.getLayer() != nextLocation.getLayer()) { 676 m_location.getLayer()->getMap()->addInstanceForTransfer(this, nextLocation); 677 if (!m_multiInstances.empty()) { 678 std::vector<Instance*>::iterator it = m_multiInstances.begin(); 679 for (; it != m_multiInstances.end(); ++it) { 680 Location newloc = nextLocation; 681 std::vector<ModelCoordinate> tmpcoords = m_location.getLayer()->getCellGrid()-> 682 toMultiCoordinates(nextLocation.getLayerCoordinates(), (*it)->getObject()->getMultiPartCoordinates(m_rotation)); 683 newloc.setLayerCoordinates(tmpcoords.front()); 684 m_location.getLayer()->getMap()->addInstanceForTransfer(*it, newloc); 685 } 686 } 687 return false; 688 } 689 setLocation(nextLocation); 690 return false; 691 } 692 // move to another layer 693 if (m_location.getLayer() != nextLocation.getLayer()) { 694 m_location.getLayer()->getMap()->addInstanceForTransfer(this, nextLocation); 695 if (!m_multiInstances.empty()) { 696 std::vector<Instance*>::iterator it = m_multiInstances.begin(); 697 for (; it != m_multiInstances.end(); ++it) { 698 Location newloc = nextLocation; 699 std::vector<ModelCoordinate> tmpcoords = m_location.getLayer()->getCellGrid()-> 700 toMultiCoordinates(nextLocation.getLayerCoordinates(), (*it)->getObject()->getMultiPartCoordinates(m_rotation)); 701 newloc.setLayerCoordinates(tmpcoords.front()); 702 m_location.getLayer()->getMap()->addInstanceForTransfer(*it, newloc); 703 } 704 } 705 return true; 706 } 707 setLocation(nextLocation); 708 // need new route? 709 if (route->getEndNode().getLayerCoordinates() != m_location.getLayerCoordinates()) { 710 if (m_location.getLayerDistanceTo(target) > 1.5) { 711 if (route->getPathLength() == 0) { 712 route->setStartNode(m_location); 713 } else { 714 route->setStartNode(route->getPreviousNode()); 715 } 716 route->setEndNode(target); 717 route->setOccupiedArea(m_location.getLayer()->getCellGrid()-> 718 toMultiCoordinates(m_location.getLayerCoordinates(), m_object->getMultiObjectCoordinates(m_rotation))); 719 return !info->m_pather->solveRoute(route); 720 } 721 setFacingLocation(target); 722 } 723 return true; 724 } else if (route->getRouteStatus() == ROUTE_FAILED) { 725 return true; 726 } 727 return false; 728 } 729 update()730 InstanceChangeInfo Instance::update() { 731 if (!m_activity) { 732 return ICHANGE_NO_CHANGES; 733 } 734 // remove DeleteListeners 735 m_deleteListeners.erase(std::remove(m_deleteListeners.begin(),m_deleteListeners.end(), 736 (InstanceDeleteListener*)NULL), m_deleteListeners.end()); 737 738 if (!m_activity->m_timeProvider) { 739 bindTimeProvider(); 740 } 741 ActionInfo* info = m_activity->m_actionInfo; 742 if (info) { 743 // FL_DBG(_log, "updating instance"); 744 745 if (info->m_target) { 746 // FL_DBG(_log, "action contains target for movement"); 747 bool movement_finished = processMovement(); 748 if (movement_finished) { 749 // FL_DBG(_log, "movement finished"); 750 finalizeAction(); 751 } 752 } else { 753 // FL_DBG(_log, "action does not contain target for movement"); 754 if (m_activity->m_timeProvider->getGameTime() - info->m_action_start_time + info->m_action_offset_time >= info->m_action->getDuration()) { 755 if (info->m_repeating) { 756 info->m_action_start_time = m_activity->m_timeProvider->getGameTime(); 757 // prock: offset no longer needed 758 info->m_action_offset_time = 0; 759 } else if (!m_object->isMultiPart()) { 760 finalizeAction(); 761 } 762 } 763 } 764 765 // previous code may invalidate actioninfo. 766 if( m_activity->m_actionInfo ) { 767 m_activity->m_actionInfo->m_prev_call_time = m_activity->m_timeProvider->getGameTime(); 768 } 769 } 770 m_activity->update(*this); 771 if (m_activity->m_sayInfo) { 772 if (m_activity->m_sayInfo->m_duration > 0) { 773 if (m_activity->m_timeProvider->getGameTime() >= m_activity->m_sayInfo->m_start_time + m_activity->m_sayInfo->m_duration) { 774 say(""); 775 } 776 } 777 } else if (!m_activity->m_actionInfo && m_changeInfo == ICHANGE_NO_CHANGES && m_activity->m_actionListeners.empty() && m_activity->m_changeListeners.empty()) { 778 // delete superfluous activity 779 delete m_activity; 780 m_activity = 0; 781 return ICHANGE_NO_CHANGES; 782 } 783 return m_changeInfo; 784 } 785 finalizeAction()786 void Instance::finalizeAction() { 787 FL_DBG(_log, "finalizing action"); 788 assert(m_activity); 789 assert(m_activity->m_actionInfo); 790 791 if( m_activity->m_actionInfo->m_leader ) { 792 m_activity->m_actionInfo->m_leader->removeDeleteListener(this); 793 } 794 795 Action* action = m_activity->m_actionInfo->m_action; 796 delete m_activity->m_actionInfo; 797 m_activity->m_actionInfo = NULL; 798 // this is needed in case the new action is set on the same pump and 799 // it is the same action as the finalized action 800 m_activity->m_action = NULL; 801 802 // stop audio 803 if (action->getAudio() && m_activity->m_soundSource) { 804 m_activity->m_soundSource->setActionAudio(NULL); 805 } 806 807 if (isMultiObject()) { 808 std::vector<Instance*>::iterator multi_it = m_multiInstances.begin(); 809 for (; multi_it != m_multiInstances.end(); ++multi_it) { 810 (*multi_it)->finalizeAction(); 811 } 812 } 813 std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionListeners.begin(); 814 while (i != m_activity->m_actionListeners.end()) { 815 if(*i) 816 (*i)->onInstanceActionFinished(this, action); 817 ++i; 818 } 819 m_activity->m_actionListeners.erase( 820 std::remove(m_activity->m_actionListeners.begin(), 821 m_activity->m_actionListeners.end(), 822 (InstanceActionListener*)NULL), 823 m_activity->m_actionListeners.end()); 824 } 825 cancelAction()826 void Instance::cancelAction() { 827 FL_DBG(_log, "cancel action"); 828 assert(m_activity); 829 assert(m_activity->m_actionInfo); 830 831 if( m_activity->m_actionInfo->m_leader ) { 832 m_activity->m_actionInfo->m_leader->removeDeleteListener(this); 833 } 834 835 Action* action = m_activity->m_actionInfo->m_action; 836 delete m_activity->m_actionInfo; 837 m_activity->m_actionInfo = NULL; 838 // this is needed in case the new action is set on the same pump and 839 // it is the same action as the canceled action 840 m_activity->m_action = NULL; 841 842 if (isMultiObject()) { 843 std::vector<Instance*>::iterator multi_it = m_multiInstances.begin(); 844 for (; multi_it != m_multiInstances.end(); ++multi_it) { 845 (*multi_it)->cancelAction(); 846 } 847 } 848 std::vector<InstanceActionListener*>::iterator i = m_activity->m_actionListeners.begin(); 849 while (i != m_activity->m_actionListeners.end()) { 850 if(*i) 851 (*i)->onInstanceActionCancelled(this, action); 852 ++i; 853 } 854 m_activity->m_actionListeners.erase( 855 std::remove(m_activity->m_actionListeners.begin(), 856 m_activity->m_actionListeners.end(), 857 (InstanceActionListener*)NULL), 858 m_activity->m_actionListeners.end()); 859 } 860 getCurrentAction() const861 Action* Instance::getCurrentAction() const { 862 if (m_activity && m_activity->m_actionInfo) { 863 return m_activity->m_actionInfo->m_action; 864 } 865 return NULL; 866 } 867 getTargetLocation() const868 Location Instance::getTargetLocation() const { 869 if (m_activity && m_activity->m_actionInfo && m_activity->m_actionInfo->m_target) { 870 return *m_activity->m_actionInfo->m_target; 871 } 872 return m_location; 873 } 874 getMovementSpeed() const875 double Instance::getMovementSpeed() const { 876 if (m_activity && m_activity->m_actionInfo) { 877 return m_activity->m_actionInfo->m_speed; 878 } 879 return 0; 880 } 881 setFacingLocation(const Location & loc)882 void Instance::setFacingLocation(const Location& loc) { 883 setRotation(getAngleBetween(m_location, loc)); 884 } 885 getFacingLocation()886 Location Instance::getFacingLocation() { 887 return getFacing(m_location, m_rotation); 888 } 889 getOldLocationRef()890 Location& Instance::getOldLocationRef() { 891 if (m_activity) { 892 return m_activity->m_oldLocation; 893 } 894 return m_location; 895 } 896 getOldRotation() const897 int32_t Instance::getOldRotation() const { 898 if (m_activity) { 899 return m_activity->m_oldRotation; 900 } 901 return m_rotation; 902 } 903 getActionRuntime()904 uint32_t Instance::getActionRuntime() { 905 if (m_activity && m_activity->m_actionInfo) { 906 if(!m_activity->m_timeProvider) 907 bindTimeProvider(); 908 return m_activity->m_timeProvider->getGameTime() - m_activity->m_actionInfo->m_action_start_time + m_activity->m_actionInfo->m_action_offset_time; 909 } 910 return getRuntime(); 911 } 912 setActionRuntime(uint32_t time_offset)913 void Instance::setActionRuntime(uint32_t time_offset) { 914 m_activity->m_actionInfo->m_action_offset_time = time_offset; 915 } 916 bindTimeProvider()917 void Instance::bindTimeProvider() { 918 float multiplier = 1.0; 919 if (m_activity->m_timeProvider) { 920 multiplier = m_activity->m_timeProvider->getMultiplier(); 921 } 922 delete m_activity->m_timeProvider; 923 m_activity->m_timeProvider = NULL; 924 925 if (m_location.getLayer()) { 926 Map* map = m_location.getLayer()->getMap(); 927 if (map) { 928 m_activity->m_timeProvider = new TimeProvider(map->getTimeProvider()); 929 } 930 } 931 if (!m_activity->m_timeProvider) { 932 m_activity->m_timeProvider = new TimeProvider(NULL); 933 } 934 m_activity->m_timeProvider->setMultiplier(multiplier); 935 } 936 refresh()937 void Instance::refresh() { 938 initializeChanges(); 939 bindTimeProvider(); 940 } 941 getChangeInfo()942 InstanceChangeInfo Instance::getChangeInfo() { 943 if (m_activity) { 944 return m_changeInfo; 945 } 946 return ICHANGE_NO_CHANGES; 947 } 948 callOnTransparencyChange()949 void Instance::callOnTransparencyChange() { 950 prepareForUpdate(); 951 m_activity->m_additional |= ICHANGE_TRANSPARENCY; 952 } 953 callOnVisibleChange()954 void Instance::callOnVisibleChange() { 955 prepareForUpdate(); 956 m_activity->m_additional |= ICHANGE_VISIBLE; 957 } 958 callOnStackPositionChange()959 void Instance::callOnStackPositionChange() { 960 prepareForUpdate(); 961 m_activity->m_additional |= ICHANGE_STACKPOS; 962 } 963 setTimeMultiplier(float multip)964 void Instance::setTimeMultiplier(float multip) { 965 initializeChanges(); 966 if (!m_activity->m_timeProvider) { 967 bindTimeProvider(); 968 } 969 m_activity->m_timeProvider->setMultiplier(multip); 970 } 971 getTimeMultiplier()972 float Instance::getTimeMultiplier() { 973 if (m_activity && m_activity->m_timeProvider) { 974 return m_activity->m_timeProvider->getMultiplier(); 975 } 976 return 1.0; 977 } 978 getTotalTimeMultiplier()979 float Instance::getTotalTimeMultiplier() { 980 if (m_activity && m_activity->m_timeProvider) { 981 return m_activity->m_timeProvider->getTotalMultiplier(); 982 } 983 if (m_location.getLayer()) { 984 Map* map = m_location.getLayer()->getMap(); 985 if (map && map->getTimeProvider()) { 986 return map->getTimeProvider()->getTotalMultiplier(); 987 } 988 } 989 return 1.0; 990 } 991 getRuntime()992 uint32_t Instance::getRuntime() { 993 if (m_activity) { 994 if(!m_activity->m_timeProvider) 995 bindTimeProvider(); 996 return m_activity->m_timeProvider->getGameTime(); 997 } 998 if (m_location.getLayer()) { 999 Map* map = m_location.getLayer()->getMap(); 1000 if (map && map->getTimeProvider()) { 1001 return map->getTimeProvider()->getGameTime(); 1002 } 1003 } 1004 return TimeManager::instance()->getTime(); 1005 } 1006 setCost(const std::string & id,double cost)1007 void Instance::setCost(const std::string& id, double cost) { 1008 m_specialCost = true; 1009 m_costId = id; 1010 m_cost = cost; 1011 } 1012 resetCost()1013 void Instance::resetCost() { 1014 m_specialCost = false; 1015 } 1016 getCost()1017 double Instance::getCost() { 1018 if (m_specialCost) { 1019 return m_cost; 1020 } 1021 return m_object->getCost(); 1022 } 1023 getCostId()1024 std::string Instance::getCostId() { 1025 if (m_specialCost) { 1026 return m_costId; 1027 } 1028 return m_object->getCostId(); 1029 } 1030 getSpeed()1031 double Instance::getSpeed() { 1032 return m_object->getSpeed(); 1033 } 1034 isSpecialSpeed()1035 bool Instance::isSpecialSpeed() { 1036 return m_object->isSpecialSpeed(); 1037 } 1038 isMultiCell()1039 bool Instance::isMultiCell() { 1040 return m_object->isMultiObject(); 1041 } 1042 isMultiObject()1043 bool Instance::isMultiObject() { 1044 return !m_multiInstances.empty(); 1045 } 1046 updateMultiInstances()1047 void Instance::updateMultiInstances() { 1048 if (!m_multiInstances.empty()) { 1049 // use map coords for rotation and movement 1050 // instances are changed on InstanceTree but not on CellCache 1051 Location loc = m_location; 1052 const ExactModelCoordinate anchor = m_location.getMapCoordinates(); 1053 const ExactModelCoordinate& offset = m_object->getRotationAnchor(); 1054 loc.setExactLayerCoordinates(offset); 1055 const ExactModelCoordinate anchor_offset = loc.getMapCoordinates(); 1056 int32_t rot = m_rotation; 1057 if (m_object->isRestrictedRotation()) { 1058 rot = m_object->getRestrictedRotation(m_rotation); 1059 } 1060 double mcos = Mathd::Cos(double(rot) * (Mathd::pi()/180.0)); 1061 double msin = Mathd::Sin(double(rot) * (Mathd::pi()/180.0)); 1062 std::vector<Instance*>::iterator it = m_multiInstances.begin(); 1063 for (; it != m_multiInstances.end(); ++it) { 1064 // use rotation 0 to get the "default" coordinate 1065 std::vector<ModelCoordinate> mcv = (*it)->getObject()->getMultiPartCoordinates(0); 1066 loc.setLayerCoordinates(mcv.front()); 1067 ExactModelCoordinate emc = loc.getMapCoordinates(); 1068 ExactModelCoordinate nemc(emc.x-anchor_offset.x, emc.y-anchor_offset.y); 1069 emc.x = ((nemc.x * mcos + nemc.y * msin) + anchor_offset.x) + anchor.x; 1070 emc.y = ((-nemc.x * msin + nemc.y * mcos) + anchor_offset.y) + anchor.y; 1071 loc.setMapCoordinates(emc); 1072 (*it)->setLocation(loc); 1073 (*it)->setRotation(rot); 1074 } 1075 } 1076 } 1077 addStaticColorOverlay(uint32_t angle,const OverlayColors & colors)1078 void Instance::addStaticColorOverlay(uint32_t angle, const OverlayColors& colors) { 1079 if (!m_ownObject) { 1080 createOwnObject(); 1081 } 1082 ObjectVisual* objVis = m_object->getVisual<ObjectVisual>(); 1083 objVis->addStaticColorOverlay(angle, colors); 1084 prepareForUpdate(); 1085 m_activity->m_additional |= ICHANGE_VISUAL; 1086 } 1087 getStaticColorOverlay(int32_t angle)1088 OverlayColors* Instance::getStaticColorOverlay(int32_t angle) { 1089 if (!m_ownObject) { 1090 return 0; 1091 } 1092 ObjectVisual* objVis = m_object->getVisual<ObjectVisual>(); 1093 return objVis->getStaticColorOverlay(angle); 1094 } 1095 removeStaticColorOverlay(int32_t angle)1096 void Instance::removeStaticColorOverlay(int32_t angle) { 1097 if (m_ownObject) { 1098 ObjectVisual* objVis = m_object->getVisual<ObjectVisual>(); 1099 objVis->removeStaticColorOverlay(angle); 1100 prepareForUpdate(); 1101 m_activity->m_additional |= ICHANGE_VISUAL; 1102 } 1103 } 1104 isStaticColorOverlay()1105 bool Instance::isStaticColorOverlay() { 1106 if (!m_ownObject) { 1107 return false; 1108 } 1109 ObjectVisual* objVis = m_object->getVisual<ObjectVisual>(); 1110 return objVis->isColorOverlay(); 1111 } 1112 addColorOverlay(const std::string & actionName,uint32_t angle,const OverlayColors & colors)1113 void Instance::addColorOverlay(const std::string& actionName, uint32_t angle, const OverlayColors& colors) { 1114 ActionVisual* visual = getActionVisual(actionName, true); 1115 if (visual) { 1116 visual->addColorOverlay(angle, colors); 1117 prepareForUpdate(); 1118 m_activity->m_additional |= ICHANGE_VISUAL; 1119 } 1120 } 1121 getColorOverlay(const std::string & actionName,uint32_t angle)1122 OverlayColors* Instance::getColorOverlay(const std::string& actionName, uint32_t angle) { 1123 ActionVisual* visual = getActionVisual(actionName, false); 1124 if (visual) { 1125 return visual->getColorOverlay(angle); 1126 } 1127 return NULL; 1128 } 1129 removeColorOverlay(const std::string & actionName,int32_t angle)1130 void Instance::removeColorOverlay(const std::string& actionName, int32_t angle) { 1131 ActionVisual* visual = getActionVisual(actionName, false); 1132 if (visual) { 1133 visual->removeColorOverlay(angle); 1134 prepareForUpdate(); 1135 m_activity->m_additional |= ICHANGE_VISUAL; 1136 } 1137 } 1138 addAnimationOverlay(const std::string & actionName,uint32_t angle,int32_t order,const AnimationPtr & animationptr)1139 void Instance::addAnimationOverlay(const std::string& actionName, uint32_t angle, int32_t order, const AnimationPtr& animationptr) { 1140 ActionVisual* visual = getActionVisual(actionName, true); 1141 if (visual) { 1142 visual->addAnimationOverlay(angle, order, animationptr); 1143 prepareForUpdate(); 1144 m_activity->m_additional |= ICHANGE_VISUAL; 1145 } 1146 } 1147 getAnimationOverlay(const std::string & actionName,int32_t angle)1148 std::map<int32_t, AnimationPtr> Instance::getAnimationOverlay(const std::string& actionName, int32_t angle) { 1149 ActionVisual* visual = getActionVisual(actionName, false); 1150 if (visual) { 1151 return visual->getAnimationOverlay(angle); 1152 } 1153 return std::map<int32_t, AnimationPtr>(); 1154 } 1155 removeAnimationOverlay(const std::string & actionName,uint32_t angle,int32_t order)1156 void Instance::removeAnimationOverlay(const std::string& actionName, uint32_t angle, int32_t order) { 1157 ActionVisual* visual = getActionVisual(actionName, false); 1158 if (visual) { 1159 visual->removeAnimationOverlay(angle, order); 1160 prepareForUpdate(); 1161 m_activity->m_additional |= ICHANGE_VISUAL; 1162 } 1163 } 1164 addColorOverlay(const std::string & actionName,uint32_t angle,int32_t order,const OverlayColors & colors)1165 void Instance::addColorOverlay(const std::string& actionName, uint32_t angle, int32_t order, const OverlayColors& colors) { 1166 ActionVisual* visual = getActionVisual(actionName, true); 1167 if (visual) { 1168 visual->addColorOverlay(angle, order, colors); 1169 prepareForUpdate(); 1170 m_activity->m_additional |= ICHANGE_VISUAL; 1171 } 1172 } 1173 getColorOverlay(const std::string & actionName,uint32_t angle,int32_t order)1174 OverlayColors* Instance::getColorOverlay(const std::string& actionName, uint32_t angle, int32_t order) { 1175 ActionVisual* visual = getActionVisual(actionName, false); 1176 if (visual) { 1177 return visual->getColorOverlay(angle, order); 1178 } 1179 return NULL; 1180 } 1181 removeColorOverlay(const std::string & actionName,int32_t angle,int32_t order)1182 void Instance::removeColorOverlay(const std::string& actionName, int32_t angle, int32_t order) { 1183 ActionVisual* visual = getActionVisual(actionName, false); 1184 if (visual) { 1185 visual->removeColorOverlay(angle, order); 1186 prepareForUpdate(); 1187 m_activity->m_additional |= ICHANGE_VISUAL; 1188 } 1189 } 1190 isAnimationOverlay(const std::string & actionName)1191 bool Instance::isAnimationOverlay(const std::string& actionName) { 1192 ActionVisual* visual = getActionVisual(actionName, false); 1193 if (visual) { 1194 return visual->isAnimationOverlay(); 1195 } 1196 return false; 1197 } 1198 isColorOverlay(const std::string & actionName)1199 bool Instance::isColorOverlay(const std::string& actionName) { 1200 ActionVisual* visual = getActionVisual(actionName, false); 1201 if (visual) { 1202 return visual->isColorOverlay(); 1203 } 1204 return false; 1205 } 1206 convertToOverlays(const std::string & actionName,bool color)1207 void Instance::convertToOverlays(const std::string& actionName, bool color) { 1208 ActionVisual* visual = getActionVisual(actionName, true); 1209 visual->convertToOverlays(color); 1210 } 1211 createOwnObject()1212 void Instance::createOwnObject() { 1213 if (!m_ownObject) { 1214 m_ownObject = true; 1215 ObjectVisual* ov = m_object->getVisual<ObjectVisual>(); 1216 ObjectVisual* nov = 0; 1217 m_object = new Object(m_object->getId(), m_object->getNamespace(), m_object); 1218 if (!ov) { 1219 ObjectVisual::create(m_object); 1220 } else { 1221 nov = new ObjectVisual(*ov); 1222 m_object->adoptVisual(nov); 1223 } 1224 } 1225 } 1226 getActionVisual(const std::string & actionName,bool create)1227 ActionVisual* Instance::getActionVisual(const std::string& actionName, bool create) { 1228 ActionVisual* nav = NULL; 1229 if (!m_ownObject) { 1230 createOwnObject(); 1231 } 1232 Action* action = m_object->getAction(actionName, false); 1233 if (!action) { 1234 action = m_object->getAction(actionName); 1235 if (!action) { 1236 throw NotFound(std::string("action ") + actionName + " not found"); 1237 } else if (create) { 1238 // if we change the current action then we have to replace the pointer 1239 bool replace = getCurrentAction() == action; 1240 // check if its the default action 1241 bool defaultAction = m_object->getDefaultAction() == action; 1242 ActionVisual* av = action->getVisual<ActionVisual>(); 1243 action = m_object->createAction(actionName, defaultAction); 1244 nav = new ActionVisual(*av); 1245 action->adoptVisual(nav); 1246 if (replace) { 1247 m_activity->m_actionInfo->m_action = action; 1248 } 1249 } 1250 } else { 1251 nav = action->getVisual<ActionVisual>(); 1252 } 1253 return nav; 1254 } 1255 addDeleteListener(InstanceDeleteListener * listener)1256 void Instance::addDeleteListener(InstanceDeleteListener *listener) { 1257 m_deleteListeners.push_back(listener); 1258 } 1259 removeDeleteListener(InstanceDeleteListener * listener)1260 void Instance::removeDeleteListener(InstanceDeleteListener *listener) { 1261 if (!m_deleteListeners.empty()) { 1262 std::vector<InstanceDeleteListener*>::iterator itor; 1263 itor = std::find(m_deleteListeners.begin(), m_deleteListeners.end(), listener); 1264 if(itor != m_deleteListeners.end()) { 1265 if ((*itor) == listener) { 1266 *itor = NULL; 1267 return; 1268 } 1269 } else { 1270 FL_WARN(_log, "Cannot remove unknown listener"); 1271 } 1272 } 1273 } 1274 onInstanceDeleted(Instance * instance)1275 void Instance::onInstanceDeleted(Instance* instance) { 1276 if(m_activity && m_activity->m_actionInfo && 1277 m_activity->m_actionInfo->m_leader == instance) { 1278 m_activity->m_actionInfo->m_leader = NULL; 1279 } 1280 if (isMultiObject()) { 1281 std::vector<Instance*>::iterator multi_it = m_multiInstances.begin(); 1282 for (; multi_it != m_multiInstances.end(); ++multi_it) { 1283 if (*multi_it == instance) { 1284 m_multiInstances.erase(multi_it); 1285 break; 1286 } 1287 } 1288 } 1289 } 1290 } 1291