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 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/log/logger.h" 31 #include "view/visual.h" 32 33 #include "cell.h" 34 #include "cellcache.h" 35 #include "instance.h" 36 #include "layer.h" 37 38 namespace FIFE { 39 40 static Logger _log(LM_STRUCTURES); 41 Cell(int32_t coordint,ModelCoordinate coordinate,Layer * layer)42 Cell::Cell(int32_t coordint, ModelCoordinate coordinate, Layer* layer): 43 m_coordId(coordint), 44 m_coordinate(coordinate), 45 m_layer(layer), 46 m_zone(NULL), 47 m_transition(NULL), 48 m_inserted(false), 49 m_protect(false) { 50 } 51 ~Cell()52 Cell::~Cell() { 53 // calls CellDeleteListener, e.g. for transition 54 if (!m_deleteListeners.empty()) { 55 std::vector<CellDeleteListener*>::iterator it = m_deleteListeners.begin(); 56 for (; it != m_deleteListeners.end(); ++it) { 57 if (*it) { 58 (*it)->onCellDeleted(this); 59 } 60 } 61 } 62 // remove cell from zone 63 if (m_zone) { 64 m_zone->removeCell(this); 65 } 66 // delete m_transition; 67 if (m_transition) { 68 deleteTransition(); 69 } 70 // remove cell from cache (costs, narrow, area) 71 m_layer->getCellCache()->removeCell(this); 72 } 73 addInstances(const std::list<Instance * > & instances)74 void Cell::addInstances(const std::list<Instance*>& instances) { 75 CellCache* cache = m_layer->getCellCache(); 76 for (std::list<Instance*>::const_iterator it = instances.begin(); it != instances.end(); ++it) { 77 std::pair<std::set<Instance*>::iterator, bool> ret = m_instances.insert(*it); 78 if (ret.second) { 79 if ((*it)->isSpecialCost()) { 80 cache->registerCost((*it)->getCostId(), (*it)->getCost()); 81 cache->addCellToCost((*it)->getCostId(), this); 82 } 83 if ((*it)->isSpecialSpeed()) { 84 cache->setSpeedMultiplier(this, (*it)->getSpeed()); 85 } 86 if ((*it)->getObject()->getArea() != "") { 87 cache->addCellToArea((*it)->getObject()->getArea(), this); 88 } 89 callOnInstanceEntered(*it); 90 } 91 } 92 updateCellBlockingInfo(); 93 } 94 addInstance(Instance * instance)95 void Cell::addInstance(Instance* instance) { 96 std::pair<std::set<Instance*>::iterator, bool> ret = m_instances.insert(instance); 97 if (ret.second) { 98 CellCache* cache = m_layer->getCellCache(); 99 if (instance->isSpecialCost()) { 100 cache->registerCost(instance->getCostId(), instance->getCost()); 101 cache->addCellToCost(instance->getCostId(), this); 102 } 103 if (instance->isSpecialSpeed()) { 104 cache->setSpeedMultiplier(this, instance->getSpeed()); 105 } 106 if (instance->getObject()->getArea() != "") { 107 cache->addCellToArea(instance->getObject()->getArea(), this); 108 } 109 callOnInstanceEntered(instance); 110 updateCellBlockingInfo(); 111 } 112 } 113 changeInstance(Instance * instance)114 void Cell::changeInstance(Instance* instance) { 115 updateCellBlockingInfo(); 116 } 117 removeInstance(Instance * instance)118 void Cell::removeInstance(Instance* instance) { 119 if (m_instances.erase(instance) == 0) { 120 FL_ERR(_log, "Tried to remove an instance from cell, but given instance could not be found."); 121 return; 122 } 123 CellCache* cache = m_layer->getCellCache(); 124 if (instance->isSpecialCost()) { 125 cache->removeCellFromCost(instance->getCostId(), this); 126 } 127 if (instance->isSpecialSpeed()) { 128 cache->resetSpeedMultiplier(this); 129 // try to find other speed value 130 if (!m_instances.empty()) { 131 std::set<Instance*>::iterator it = m_instances.begin(); 132 for (; it != m_instances.end(); ++it) { 133 if ((*it)->isSpecialSpeed()) { 134 cache->setSpeedMultiplier(this, (*it)->getSpeed()); 135 break; 136 } 137 } 138 } 139 } 140 if (instance->getObject()->getArea() != "") { 141 cache->removeCellFromArea(instance->getObject()->getArea(), this); 142 } 143 callOnInstanceExited(instance); 144 updateCellBlockingInfo(); 145 } 146 isNeighbor(Cell * cell)147 bool Cell::isNeighbor(Cell* cell) { 148 std::vector<Cell*>::iterator it = m_neighbors.begin(); 149 for (; it != m_neighbors.end(); ++it) { 150 if (*it == cell) { 151 return true; 152 } 153 } 154 return false; 155 } 156 updateCellBlockingInfo()157 void Cell::updateCellBlockingInfo() { 158 CellTypeInfo old_type = m_type; 159 m_coordinate.z = MIN_CELL_Z; 160 if (!m_instances.empty()) { 161 int32_t pos = -1; 162 bool cellblock = (m_type == CTYPE_CELL_NO_BLOCKER || m_type == CTYPE_CELL_BLOCKER); 163 for (std::set<Instance*>::iterator it = m_instances.begin(); it != m_instances.end(); ++it) { 164 if (cellblock) { 165 continue; 166 } 167 uint8_t stackpos = (*it)->getCellStackPosition(); 168 if (stackpos < pos) { 169 continue; 170 } 171 // update cell z 172 if (m_coordinate.z < (*it)->getLocationRef().getLayerCoordinates().z && (*it)->getObject()->isStatic()) { 173 m_coordinate.z = (*it)->getLocationRef().getLayerCoordinates().z; 174 } 175 if ((*it)->getCellStackPosition() > pos) { 176 pos = (*it)->getCellStackPosition(); 177 if ((*it)->isBlocking()) { 178 if (!(*it)->getObject()->isStatic()) { 179 m_type = CTYPE_DYNAMIC_BLOCKER; 180 } else { 181 m_type = CTYPE_STATIC_BLOCKER; 182 } 183 } else { 184 m_type = CTYPE_NO_BLOCKER; 185 } 186 } else { 187 // if positions are equal then static_blockers win 188 if ((*it)->isBlocking() && m_type != CTYPE_STATIC_BLOCKER) { 189 if (!(*it)->getObject()->isStatic()) { 190 m_type = CTYPE_DYNAMIC_BLOCKER; 191 } else { 192 m_type = CTYPE_STATIC_BLOCKER; 193 } 194 } 195 } 196 } 197 } else { 198 if (m_type == CTYPE_STATIC_BLOCKER || m_type == CTYPE_DYNAMIC_BLOCKER) { 199 m_type = CTYPE_NO_BLOCKER; 200 } 201 } 202 if (Mathd::Equal(m_coordinate.z, MIN_CELL_Z)) { 203 m_coordinate.z = 0; 204 } 205 206 if (old_type != m_type) { 207 bool block = (m_type == CTYPE_STATIC_BLOCKER || 208 m_type == CTYPE_DYNAMIC_BLOCKER || m_type == CTYPE_CELL_BLOCKER); 209 m_layer->getCellCache()->setBlockingUpdate(true); 210 callOnBlockingChanged(block); 211 } 212 } 213 updateCellInfo()214 void Cell::updateCellInfo() { 215 updateCellBlockingInfo(); 216 217 if (!m_deleteListeners.empty()) { 218 m_deleteListeners.erase( 219 std::remove(m_deleteListeners.begin(), m_deleteListeners.end(), 220 (CellDeleteListener*)NULL), m_deleteListeners.end()); 221 } 222 if (!m_changeListeners.empty()) { 223 m_changeListeners.erase( 224 std::remove(m_changeListeners.begin(), m_changeListeners.end(), 225 (CellChangeListener*)NULL), m_changeListeners.end()); 226 } 227 } 228 defaultCost()229 bool Cell::defaultCost() { 230 return m_layer->getCellCache()->isDefaultCost(this); 231 } 232 setCostMultiplier(double multi)233 void Cell::setCostMultiplier(double multi) { 234 m_layer->getCellCache()->setCostMultiplier(this, multi); 235 } 236 getCostMultiplier()237 double Cell::getCostMultiplier() { 238 return m_layer->getCellCache()->getCostMultiplier(this); 239 } 240 resetCostMultiplier()241 void Cell::resetCostMultiplier() { 242 m_layer->getCellCache()->resetCostMultiplier(this); 243 } 244 defaultSpeed()245 bool Cell::defaultSpeed() { 246 return m_layer->getCellCache()->isDefaultSpeed(this); 247 } 248 setSpeedMultiplier(double multi)249 void Cell::setSpeedMultiplier(double multi) { 250 m_layer->getCellCache()->setSpeedMultiplier(this, multi); 251 } 252 getSpeedMultiplier()253 double Cell::getSpeedMultiplier() { 254 return m_layer->getCellCache()->getSpeedMultiplier(this); 255 } 256 resetSpeedMultiplier()257 void Cell::resetSpeedMultiplier() { 258 m_layer->getCellCache()->resetSpeedMultiplier(this); 259 } 260 getZone()261 Zone* Cell::getZone() { 262 return m_zone; 263 } 264 setZone(Zone * zone)265 void Cell::setZone(Zone* zone) { 266 m_zone = zone; 267 } 268 resetZone()269 void Cell::resetZone() { 270 m_inserted = false; 271 m_zone = NULL; 272 } 273 isInserted()274 bool Cell::isInserted() { 275 return m_inserted; 276 } 277 setInserted(bool inserted)278 void Cell::setInserted(bool inserted) { 279 m_inserted = inserted; 280 } 281 isZoneProtected()282 bool Cell::isZoneProtected() { 283 return m_protect; 284 } 285 setZoneProtected(bool protect)286 void Cell::setZoneProtected(bool protect) { 287 m_protect = protect; 288 } 289 getCellType()290 CellTypeInfo Cell::getCellType() { 291 return m_type; 292 } 293 setCellType(CellTypeInfo type)294 void Cell::setCellType(CellTypeInfo type) { 295 m_type = type; 296 } 297 getInstances()298 const std::set<Instance*>& Cell::getInstances() { 299 return m_instances; 300 } 301 setCellId(int32_t id)302 void Cell::setCellId(int32_t id) { 303 m_coordId = id; 304 } 305 getCellId()306 int32_t Cell::getCellId() { 307 return m_coordId; 308 } 309 getLayerCoordinates() const310 const ModelCoordinate Cell::getLayerCoordinates() const { 311 return m_coordinate; 312 } 313 addNeighbor(Cell * cell)314 void Cell::addNeighbor(Cell* cell) { 315 m_neighbors.push_back(cell); 316 } 317 getNeighbors()318 const std::vector<Cell*>& Cell::getNeighbors() { 319 return m_neighbors; 320 } 321 resetNeighbors()322 void Cell::resetNeighbors() { 323 m_neighbors.clear(); 324 if (m_transition) { 325 CellCache* cache = m_transition->m_layer->getCellCache(); 326 if (cache) { 327 Cell* cell = cache->getCell(m_transition->m_mc); 328 if (cell) { 329 m_neighbors.push_back(cell); 330 } 331 } 332 } 333 } 334 getLayer()335 Layer* Cell::getLayer() { 336 return m_layer; 337 } 338 createTransition(Layer * layer,const ModelCoordinate & mc,bool immediate)339 void Cell::createTransition(Layer* layer, const ModelCoordinate& mc, bool immediate) { 340 TransitionInfo* trans = new TransitionInfo(layer); 341 // if layers are the same then it's a portal 342 if (layer != m_layer) { 343 trans->m_difflayer = true; 344 } 345 trans->m_immediate = immediate; 346 trans->m_mc = mc; 347 348 deleteTransition(); 349 350 m_transition = trans; 351 352 Cell* c = layer->getCellCache()->getCell(mc); 353 if (c) { 354 m_neighbors.push_back(c); 355 c->addDeleteListener(this); 356 m_layer->getCellCache()->addTransition(this); 357 } else { 358 delete m_transition; 359 m_transition = NULL; 360 } 361 } 362 deleteTransition()363 void Cell::deleteTransition() { 364 if (m_transition) { 365 Cell* oldc = m_transition->m_layer->getCellCache()->getCell(m_transition->m_mc); 366 std::vector<Cell*>::iterator it = m_neighbors.begin(); 367 for (; it != m_neighbors.end(); ++it) { 368 if (*it == oldc) { 369 m_neighbors.erase(it); 370 break; 371 } 372 } 373 oldc->removeDeleteListener(this); 374 m_layer->getCellCache()->removeTransition(this); 375 delete m_transition; 376 m_transition = NULL; 377 } 378 } 379 getTransition()380 TransitionInfo* Cell::getTransition() { 381 return m_transition; 382 } 383 addDeleteListener(CellDeleteListener * listener)384 void Cell::addDeleteListener(CellDeleteListener* listener) { 385 m_deleteListeners.push_back(listener); 386 } 387 removeDeleteListener(CellDeleteListener * listener)388 void Cell::removeDeleteListener(CellDeleteListener* listener) { 389 std::vector<CellDeleteListener*>::iterator it = m_deleteListeners.begin(); 390 for (; it != m_deleteListeners.end(); ++it) { 391 if (*it == listener) { 392 *it = NULL; 393 break; 394 } 395 } 396 } 397 onCellDeleted(Cell * cell)398 void Cell::onCellDeleted(Cell* cell) { 399 std::vector<Cell*>::iterator it = m_neighbors.begin(); 400 for (; it != m_neighbors.end(); ++it) { 401 if (*it == cell) { 402 deleteTransition(); 403 break; 404 } 405 } 406 } 407 addChangeListener(CellChangeListener * listener)408 void Cell::addChangeListener(CellChangeListener* listener) { 409 m_changeListeners.push_back(listener); 410 } 411 removeChangeListener(CellChangeListener * listener)412 void Cell::removeChangeListener(CellChangeListener* listener) { 413 std::vector<CellChangeListener*>::iterator it = m_changeListeners.begin(); 414 for (; it != m_changeListeners.end(); ++it) { 415 if (*it == listener) { 416 *it = NULL; 417 break; 418 } 419 } 420 } 421 callOnInstanceEntered(Instance * instance)422 void Cell::callOnInstanceEntered(Instance* instance) { 423 if (m_changeListeners.empty()) { 424 return; 425 } 426 427 std::vector<CellChangeListener*>::iterator i = m_changeListeners.begin(); 428 while (i != m_changeListeners.end()) { 429 if (*i) { 430 (*i)->onInstanceEnteredCell(this, instance); 431 } 432 ++i; 433 } 434 } 435 callOnInstanceExited(Instance * instance)436 void Cell::callOnInstanceExited(Instance* instance) { 437 if (m_changeListeners.empty()) { 438 return; 439 } 440 441 std::vector<CellChangeListener*>::iterator i = m_changeListeners.begin(); 442 while (i != m_changeListeners.end()) { 443 if (*i) { 444 (*i)->onInstanceExitedCell(this, instance); 445 } 446 ++i; 447 } 448 } 449 callOnBlockingChanged(bool blocks)450 void Cell::callOnBlockingChanged(bool blocks) { 451 if (m_changeListeners.empty()) { 452 return; 453 } 454 455 std::vector<CellChangeListener*>::iterator i = m_changeListeners.begin(); 456 while (i != m_changeListeners.end()) { 457 if (*i) { 458 (*i)->onBlockingChangedCell(this, m_type, blocks); 459 } 460 ++i; 461 } 462 } 463 } // FIFE 464