Ticket #2022: Territory_Memfrag.patch
File Territory_Memfrag.patch, 22.8 KB (added by , 11 years ago) |
---|
-
source/simulation2/helpers/Grid.h
80 80 memset(m_Data, 0, m_W*m_H*sizeof(T)); 81 81 } 82 82 83 void set( int i,int j, const T& value)83 void set(const int i, const int j, const T& value) 84 84 { 85 85 #if GRID_BOUNDS_DEBUG 86 86 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H); 87 87 #endif 88 88 m_Data[j*m_W + i] = value; 89 89 } 90 91 void add(const int i, const int j, T val) 92 { 93 #if GRID_BOUNDS_DEBUG 94 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H); 95 #endif 96 m_Data[j*m_W + i] += val; 97 } 98 void getPtr(const int i, const int j) 99 { 100 #if GRID_BOUNDS_DEBUG 101 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H); 102 #endif 103 return m_Data[j*m_W + i]; 104 } 90 105 91 T& get( int i,int j) const106 T& get(const int i, const int j) const 92 107 { 93 108 #if GRID_BOUNDS_DEBUG 94 109 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H); … … 113 128 114 129 enum { BucketBits = 4, BucketSize = 1 << BucketBits }; 115 130 116 T* GetBucket( int i,int j)131 T* GetBucket(const int i, const int j) 117 132 { 118 size_t b = (j >> BucketBits) * m_BW + (i >> BucketBits);133 const size_t b = (j >> BucketBits) * m_BW + (i >> BucketBits); 119 134 if (!m_Data[b]) 120 135 { 121 m_Data[b] = new T[BucketSize*BucketSize]; 136 if (m_Reserve.empty()) 137 { 138 m_Data[b] = new T[BucketSize*BucketSize]; 139 } 140 else 141 { 142 m_Data[b] = m_Reserve.back(); 143 m_Reserve.pop_back(); 144 } 122 145 memset(m_Data[b], 0, BucketSize*BucketSize*sizeof(T)); 123 146 } 124 147 return m_Data[b]; … … 134 157 135 158 m_Data = new T*[m_BW*m_BH]; 136 159 memset(m_Data, 0, m_BW*m_BH*sizeof(T*)); 160 137 161 } 138 162 139 163 ~SparseGrid() 140 164 { 141 reset(); 165 //reset(); 166 for (size_t i = 0; i < (size_t)(m_BW*m_BH); ++i) 167 delete[] m_Data[i]; 142 168 delete[] m_Data; 143 169 } 144 170 145 171 void reset() 146 172 { 147 173 for (size_t i = 0; i < (size_t)(m_BW*m_BH); ++i) 148 delete[] m_Data[i]; 174 { 175 if (m_Data[i]) 176 { 177 m_Reserve.push_back(m_Data[i]); 178 } 179 } 149 180 150 181 memset(m_Data, 0, m_BW*m_BH*sizeof(T*)); 151 182 } 152 183 153 void set( int i,int j, const T& value)184 void set(const int i, const int j, const T& value) 154 185 { 155 186 #if GRID_BOUNDS_DEBUG 156 187 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H); … … 158 189 GetBucket(i, j)[(j % BucketSize)*BucketSize + (i % BucketSize)] = value; 159 190 } 160 191 161 T& get( int i,int j)192 T& get(const int i, const int j) 162 193 { 163 194 #if GRID_BOUNDS_DEBUG 164 195 ENSURE(0 <= i && i < m_W && 0 <= j && j < m_H); … … 169 200 u16 m_W, m_H; 170 201 u16 m_BW, m_BH; 171 202 T** m_Data; 203 std::deque < T* > m_Reserve; 172 204 173 205 size_t m_DirtyID; // if this is < the id maintained by ICmpObstructionManager then it needs to be updated 174 206 }; -
source/simulation2/components/CCmpTerritoryManager.cpp
56 56 57 57 TerritoryOverlay(CCmpTerritoryManager& manager); 58 58 virtual void StartRender(); 59 virtual void ProcessTile( ssize_t i,ssize_t j);59 virtual void ProcessTile(const ssize_t i, const ssize_t j); 60 60 }; 61 61 62 62 class CCmpTerritoryManager : public ICmpTerritoryManager … … 88 88 // connected flag in bit 6 (TERRITORY_CONNECTED_MASK); 89 89 // processed flag in bit 7 (TERRITORY_PROCESSED_MASK) 90 90 Grid<u8>* m_Territories; 91 Grid<u8>* m_Territories_Data; 92 Grid<u8>* m_InfluenceGrid; 91 93 94 u16 m_TilesW; 95 u16 m_TilesH; 96 // For each player, store the sum of influences on each tile 97 std::vector<std::pair<player_id_t, Grid<u32>* > > playerGrids; 98 99 std::map<player_id_t, std::vector<entity_id_t> > influenceEntities; 100 std::vector<entity_id_t> rootInfluenceEntities; 101 102 std::vector<std::pair<u16, u16> > tileStack; 103 104 std::deque<Grid<u32>* > grid32Pool; 105 92 106 // Set to true when territories change; will send a TerritoriesChanged message 93 107 // during the Update phase 94 108 bool m_TriggerEvent; … … 113 127 virtual void Init(const CParamNode& UNUSED(paramNode)) 114 128 { 115 129 m_Territories = NULL; 130 m_Territories_Data = NULL; 131 m_InfluenceGrid = NULL; 116 132 m_DebugOverlay = NULL; 117 133 // m_DebugOverlay = new TerritoryOverlay(*this); 118 134 m_BoundaryLinesDirty = true; … … 120 136 m_EnableLineDebugOverlays = false; 121 137 m_DirtyID = 1; 122 138 139 m_TilesW = 0; 140 m_TilesH = 0; 123 141 m_AnimTime = 0.0; 124 142 125 143 CParamNode externalParamNode; … … 134 152 135 153 virtual void Deinit() 136 154 { 137 SAFE_DELETE(m_Territories); 155 SAFE_DELETE(m_Territories_Data); 156 SAFE_DELETE(m_InfluenceGrid); 138 157 SAFE_DELETE(m_DebugOverlay); 158 for(std::deque<Grid<u32>* >::iterator it = grid32Pool.begin(); it != grid32Pool.end(); ++it ) 159 delete *it; 139 160 } 140 161 Grid<u32>* getPooledGrid32() 162 { 163 if (grid32Pool.empty()) 164 { 165 return new Grid<u32>(m_TilesW, m_TilesH); 166 } 167 Grid<u32>* ret = grid32Pool.back(); 168 grid32Pool.pop_back(); 169 ret->reset(); 170 return ret; 171 } 172 void returnPooledGrid32(Grid<u32>* ret) 173 { 174 grid32Pool.push_back(ret); 175 } 141 176 virtual void Serialize(ISerializer& UNUSED(serialize)) 142 177 { 143 178 // Territory state can be recomputed as required, so we don't need to serialize any of it. … … 233 268 234 269 void MakeDirty() 235 270 { 236 SAFE_DELETE(m_Territories);271 m_Territories = NULL; 237 272 ++m_DirtyID; 238 273 m_BoundaryLinesDirty = true; 239 274 m_TriggerEvent = true; … … 256 291 * a TerritoryInfluence component. Grid cells are 0 if no influence, 257 292 * or 1+c if the influence have cost c (assumed between 0 and 254). 258 293 */ 259 void RasteriseInfluences( CComponentManager::InterfaceList& infls, Grid<u8>& grid);294 void RasteriseInfluences(const CComponentManager::InterfaceList& infls, Grid<u8>& grid); 260 295 261 296 std::vector<STerritoryBoundary> ComputeBoundaries(); 262 297 … … 279 314 280 315 typedef PriorityQueueHeap<std::pair<u16, u16>, u32, std::greater<u32> > OpenQueue; 281 316 282 static void ProcessNeighbour( u32 falloff, u16 i, u16 j,u32 pg, bool diagonal,317 static void ProcessNeighbour(const u32 falloff, const u16 i, const u16 j, const u32 pg, bool diagonal, 283 318 Grid<u32>& grid, OpenQueue& queue, const Grid<u8>& costGrid) 284 319 { 285 320 u32 dg = falloff * costGrid.get(i, j); … … 291 326 if (pg <= grid.get(i, j) + dg) 292 327 return; 293 328 294 u32 g = pg - dg; // cost to this tile = cost to predecessor - falloff from predecessor329 const u32 g = pg - dg; // cost to this tile = cost to predecessor - falloff from predecessor 295 330 296 331 grid.set(i, j, g); 297 332 OpenQueue::Item tile = { std::make_pair(i, j), g }; 298 333 queue.push(tile); 299 334 } 300 335 301 static void FloodFill(Grid<u32>& grid, Grid<u8>& costGrid, OpenQueue& openTiles, u32 falloff)336 static void FloodFill(Grid<u32>& grid, Grid<u8>& costGrid, OpenQueue& openTiles, const u32 falloff) 302 337 { 303 u16 tilesW = grid.m_W;304 u16 tilesH = grid.m_H;338 const u16 tilesW = grid.m_W; 339 const u16 tilesH = grid.m_H; 305 340 306 341 while (!openTiles.empty()) 307 342 { 308 343 OpenQueue::Item tile = openTiles.pop(); 309 344 310 345 // Process neighbours (if they're not off the edge of the map) 311 u16 x = tile.id.first; 312 u16 z = tile.id.second; 313 if (x > 0) 346 const u16 x = tile.id.first; 347 const u16 z = tile.id.second; 314 348 ProcessNeighbour(falloff, (u16)(x-1), z, tile.rank, false, grid, openTiles, costGrid); 315 if (x < tilesW-1) 349 if (x < tilesW-1){ 316 350 ProcessNeighbour(falloff, (u16)(x+1), z, tile.rank, false, grid, openTiles, costGrid); 317 if (z > 0) 351 ProcessNeighbour(falloff, (u16)(x+1), (u16)(z-1), tile.rank, true, grid, openTiles, costGrid); 352 } 318 353 ProcessNeighbour(falloff, x, (u16)(z-1), tile.rank, false, grid, openTiles, costGrid); 319 if (z < tilesH-1) 354 if (z < tilesH-1){ 320 355 ProcessNeighbour(falloff, x, (u16)(z+1), tile.rank, false, grid, openTiles, costGrid); 321 if (x > 0 && z > 0) 356 ProcessNeighbour(falloff, (u16)(x-1), (u16)(z+1), tile.rank, true, grid, openTiles, costGrid); 357 } 322 358 ProcessNeighbour(falloff, (u16)(x-1), (u16)(z-1), tile.rank, true, grid, openTiles, costGrid); 323 if (x > 0 && z < tilesH-1) 324 ProcessNeighbour(falloff, (u16)(x-1), (u16)(z+1), tile.rank, true, grid, openTiles, costGrid); 325 if (x < tilesW-1 && z > 0) 326 ProcessNeighbour(falloff, (u16)(x+1), (u16)(z-1), tile.rank, true, grid, openTiles, costGrid); 359 327 360 if (x < tilesW-1 && z < tilesH-1) 328 361 ProcessNeighbour(falloff, (u16)(x+1), (u16)(z+1), tile.rank, true, grid, openTiles, costGrid); 329 362 } … … 343 376 if (!cmpTerrain->IsLoaded()) 344 377 return; 345 378 346 u16 tilesW = cmpTerrain->GetTilesPerSide(); 347 u16 tilesH = cmpTerrain->GetTilesPerSide(); 379 const u16 tilesW = cmpTerrain->GetTilesPerSide(); 380 const u16 tilesH = cmpTerrain->GetTilesPerSide(); 381 382 if (!m_Territories_Data) 383 { 384 m_TilesW = tilesW; 385 m_TilesH = tilesH; 386 m_Territories_Data = new Grid<u8>(tilesW, tilesH); 387 } 388 ENSURE(m_TilesW == tilesW); 389 ENSURE(m_TilesH == tilesH); 390 391 const u32 gridSize = tilesH * tilesW; 348 392 349 m_Territories = new Grid<u8>(tilesW, tilesH); 393 m_Territories = m_Territories_Data; 394 m_Territories->reset(); 350 395 351 396 // Compute terrain-passability-dependent costs per tile 352 Grid<u8> influenceGrid(tilesW, tilesH); 397 if (!m_InfluenceGrid) 398 m_InfluenceGrid = new Grid<u8>(tilesW, tilesH); 399 Grid<u8>* influenceGrid = m_InfluenceGrid; 400 influenceGrid->reset(); 353 401 354 402 CmpPtr<ICmpPathfinder> cmpPathfinder(GetSimContext(), SYSTEM_ENTITY); 355 ICmpPathfinder::pass_class_t passClassDefault = cmpPathfinder->GetPassabilityClass("default");356 ICmpPathfinder::pass_class_t passClassUnrestricted = cmpPathfinder->GetPassabilityClass("unrestricted");403 const ICmpPathfinder::pass_class_t passClassDefault = cmpPathfinder->GetPassabilityClass("default"); 404 const ICmpPathfinder::pass_class_t passClassUnrestricted = cmpPathfinder->GetPassabilityClass("unrestricted"); 357 405 358 406 const Grid<u16>& passGrid = cmpPathfinder->GetPassabilityGrid(); 359 for (u16 j = 0; j < tilesH; ++j)360 407 { 361 for (u16 i = 0; i < tilesW; ++i) 408 u8* const __restrict inflgridData = influenceGrid->m_Data; 409 const u16* const __restrict passgridData = passGrid.m_Data; 410 for (u32 k = 0; k < gridSize; ++k) 362 411 { 363 u16 g = passGrid.get(i, j);412 const u16 g = passgridData[k]; 364 413 u8 cost; 365 414 if (g & passClassUnrestricted) 366 415 cost = 255; // off the world; use maximum cost … … 368 417 cost = m_ImpassableCost; 369 418 else 370 419 cost = 1; 371 infl uenceGrid.set(i, j, cost);420 inflgridData[k] = cost; 372 421 } 373 422 } 374 423 … … 376 425 CComponentManager::InterfaceList influences = GetSimContext().GetComponentManager().GetEntitiesWithInterface(IID_TerritoryInfluence); 377 426 378 427 // Allow influence entities to override the terrain costs 379 RasteriseInfluences(influences, influenceGrid);428 RasteriseInfluences(influences, *influenceGrid); 380 429 381 430 // Split influence entities into per-player lists, ignoring any with invalid properties 382 std::map<player_id_t, std::vector<entity_id_t> > influenceEntities; 383 std::vector<entity_id_t> rootInfluenceEntities; 384 for (CComponentManager::InterfaceList::iterator it = influences.begin(); it != influences.end(); ++it) 431 influenceEntities.clear(); 432 rootInfluenceEntities.clear(); 433 const CComponentManager::InterfaceList::const_iterator itiEnd = influences.end(); 434 for (CComponentManager::InterfaceList::const_iterator it = influences.begin(); it != itiEnd; ++it) 385 435 { 386 436 // Ignore any with no weight or radius (to avoid divide-by-zero later) 387 437 ICmpTerritoryInfluence* cmpTerritoryInfluence = static_cast<ICmpTerritoryInfluence*>(it->second); … … 393 443 continue; 394 444 395 445 // Ignore Gaia and unassigned 396 player_id_t owner = cmpOwnership->GetOwner();446 const player_id_t owner = cmpOwnership->GetOwner(); 397 447 if (owner <= 0) 398 448 continue; 399 449 … … 412 462 rootInfluenceEntities.push_back(it->first); 413 463 } 414 464 415 // For each player, store the sum of influences on each tile 416 std::vector<std::pair<player_id_t, Grid<u32> > > playerGrids; 465 playerGrids.clear(); 417 466 // TODO: this is a large waste of memory; we don't really need to store 418 467 // all the intermediate grids 419 468 420 for (std::map<player_id_t, std::vector<entity_id_t> >::iterator it = influenceEntities.begin(); it != influenceEntities.end(); ++it) 469 470 OpenQueue openTiles; 471 Grid<u32>* entityGrid = getPooledGrid32(); 472 const std::map<player_id_t, std::vector<entity_id_t> >::iterator itieEnd = influenceEntities.end(); 473 for (std::map<player_id_t, std::vector<entity_id_t> >::iterator it = influenceEntities.begin(); it != itieEnd; ++it) 421 474 { 422 Grid<u32> playerGrid(tilesW, tilesH);475 Grid<u32>* playerGrid = getPooledGrid32(); 423 476 424 std::vector<entity_id_t>& ents = it->second; 425 for (std::vector<entity_id_t>::iterator eit = ents.begin(); eit != ents.end(); ++eit) 477 const std::vector<entity_id_t>& ents = it->second; 478 const std::vector<entity_id_t>::const_iterator eitEnd = ents.end(); 479 for (std::vector<entity_id_t>::const_iterator eit = ents.begin(); eit != eitEnd; ++eit) 426 480 { 427 481 // Compute the influence map of the current entity, then add it to the player grid 482 entityGrid->reset(); 428 483 429 Grid<u32> entityGrid(tilesW, tilesH); 484 { 485 CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), *eit); 486 const CFixedVector2D pos = cmpPosition->GetPosition2D(); 487 const u16 i = (u16)clamp((pos.X / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(), 0, tilesW-1); 488 const u16 j = (u16)clamp((pos.Y / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(), 0, tilesH-1); 430 489 431 CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), *eit);432 CFixedVector2D pos = cmpPosition->GetPosition2D();433 u16 i = (u16)clamp((pos.X / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(), 0, tilesW-1);434 u16 j = (u16)clamp((pos.Y / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(), 0, tilesH-1);490 CmpPtr<ICmpTerritoryInfluence> cmpTerritoryInfluence(GetSimContext(), *eit); 491 const u32 weight = cmpTerritoryInfluence->GetWeight(); 492 const u32 radius = cmpTerritoryInfluence->GetRadius() / TERRAIN_TILE_SIZE; 493 const u32 falloff = weight / radius; // earlier check for GetRadius() == 0 prevents divide-by-zero 435 494 436 CmpPtr<ICmpTerritoryInfluence> cmpTerritoryInfluence(GetSimContext(), *eit); 437 u32 weight = cmpTerritoryInfluence->GetWeight(); 438 u32 radius = cmpTerritoryInfluence->GetRadius() / TERRAIN_TILE_SIZE; 439 u32 falloff = weight / radius; // earlier check for GetRadius() == 0 prevents divide-by-zero 495 // TODO: we should have some maximum value on weight, to avoid overflow 496 // when doing all the sums 440 497 441 // TODO: we should have some maximum value on weight, to avoid overflow 442 // when doing all the sums 498 // Initialise the tile under the entity 499 entityGrid->set(i, j, weight); 500 OpenQueue::Item tile = { std::make_pair(i, j), weight }; 501 openTiles.push(tile); 443 502 444 // Initialise the tile under the entity 445 entityGrid.set(i, j, weight); 446 OpenQueue openTiles; 447 OpenQueue::Item tile = { std::make_pair((u16)i, (i16)j), weight }; 448 openTiles.push(tile); 449 450 // Expand influences outwards 451 FloodFill(entityGrid, influenceGrid, openTiles, falloff); 452 503 // Expand influences outwards 504 FloodFill(*entityGrid, *influenceGrid, openTiles, falloff); 505 } 453 506 // TODO: we should do a sparse grid and only add the non-zero regions, for performance 454 for (u16 j = 0; j < entityGrid.m_H; ++j) 455 for (u16 i = 0; i < entityGrid.m_W; ++i) 456 playerGrid.set(i, j, playerGrid.get(i, j) + entityGrid.get(i, j)); 507 const u32* const __restrict eData = entityGrid->m_Data; 508 u32* const __restrict pData = playerGrid->m_Data; 509 for(u32 k = 0; k < gridSize; k++) 510 pData[k] += eData[k]; 457 511 } 458 512 459 513 playerGrids.push_back(std::make_pair(it->first, playerGrid)); … … 467 521 u32 bestWeight = 0; 468 522 for (size_t k = 0; k < playerGrids.size(); ++k) 469 523 { 470 u32 w = playerGrids[k].second .get(i, j);524 u32 w = playerGrids[k].second->get(i, j); 471 525 if (w > bestWeight) 472 526 { 473 player_id_t id = playerGrids[k].first;527 const player_id_t id = playerGrids[k].first; 474 528 m_Territories->set(i, j, (u8)id); 475 529 bestWeight = w; 476 530 } … … 479 533 } 480 534 481 535 // Detect territories connected to a 'root' influence (typically a civ center) 482 // belonging to their player, and mark them with the connected flag 483 for (std::vector<entity_id_t>::iterator it = rootInfluenceEntities.begin(); it != rootInfluenceEntities.end(); ++it) 536 // belonging to their player, and mark them with the connected flag, 537 538 Grid<u8>& grid = *m_Territories; 539 const u16 maxi = (u16)(grid.m_W-1); 540 const u16 maxj = (u16)(grid.m_H-1); 541 std::vector<entity_id_t>::const_iterator itrEnd = rootInfluenceEntities.end(); 542 for (std::vector<entity_id_t>::const_iterator it = rootInfluenceEntities.begin(); it != itrEnd; ++it) 484 543 { 485 544 // (These components must be valid else the entities wouldn't be added to this list) 486 545 CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), *it); 487 546 CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), *it); 488 547 489 CFixedVector2D pos = cmpPosition->GetPosition2D();490 u16 i = (u16)clamp((pos.X / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(), 0, tilesW-1);491 u16 j = (u16)clamp((pos.Y / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(), 0, tilesH-1);548 const CFixedVector2D pos = cmpPosition->GetPosition2D(); 549 const u16 i = (u16)clamp((pos.X / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(), 0, tilesW-1); 550 const u16 j = (u16)clamp((pos.Y / (int)TERRAIN_TILE_SIZE).ToInt_RoundToNegInfinity(), 0, tilesH-1); 492 551 493 u8 owner = (u8)cmpOwnership->GetOwner();552 const u8 owner = (u8)cmpOwnership->GetOwner(); 494 553 495 if ( m_Territories->get(i, j) != owner)554 if (grid.get(i, j) != owner) 496 555 continue; 497 556 498 557 // TODO: would be nice to refactor some of the many flood fill 499 558 // algorithms in this component 500 501 Grid<u8>& grid = *m_Territories;502 503 u16 maxi = (u16)(grid.m_W-1);504 u16 maxj = (u16)(grid.m_H-1);505 506 std::vector<std::pair<u16, u16> > tileStack;507 508 559 #define MARK_AND_PUSH(i, j) STMT(grid.set(i, j, owner | TERRITORY_CONNECTED_MASK); tileStack.push_back(std::make_pair(i, j)); ) 509 560 510 561 MARK_AND_PUSH(i, j); 511 562 while (!tileStack.empty()) 512 563 { 513 intti = tileStack.back().first;514 inttj = tileStack.back().second;564 const u16 ti = tileStack.back().first; 565 const u16 tj = tileStack.back().second; 515 566 tileStack.pop_back(); 516 567 517 568 if (ti > 0 && grid.get(ti-1, tj) == owner) … … 540 591 /** 541 592 * Compute the tile indexes on the grid nearest to a given point 542 593 */ 543 static void NearestTile( entity_pos_t x, entity_pos_t z, u16& i, u16& j, u16 w,u16 h)594 static void NearestTile(const entity_pos_t x, const entity_pos_t z, u16& i, u16& j, const u16 w, const u16 h) 544 595 { 545 596 i = (u16)clamp((x / (int)TERRAIN_TILE_SIZE).ToInt_RoundToZero(), 0, w-1); 546 597 j = (u16)clamp((z / (int)TERRAIN_TILE_SIZE).ToInt_RoundToZero(), 0, h-1); … … 549 600 /** 550 601 * Returns the position of the center of the given tile 551 602 */ 552 static void TileCenter( u16 i,u16 j, entity_pos_t& x, entity_pos_t& z)603 static void TileCenter(const u16 i, const u16 j, entity_pos_t& x, entity_pos_t& z) 553 604 { 554 605 x = entity_pos_t::FromInt(i*(int)TERRAIN_TILE_SIZE + (int)TERRAIN_TILE_SIZE/2); 555 606 z = entity_pos_t::FromInt(j*(int)TERRAIN_TILE_SIZE + (int)TERRAIN_TILE_SIZE/2); … … 558 609 // TODO: would be nice not to duplicate those two functions from CCmpObstructionManager.cpp 559 610 560 611 561 void CCmpTerritoryManager::RasteriseInfluences( CComponentManager::InterfaceList& infls, Grid<u8>& grid)612 void CCmpTerritoryManager::RasteriseInfluences(const CComponentManager::InterfaceList& infls, Grid<u8>& grid) 562 613 { 563 for (CComponentManager::InterfaceList::iterator it = infls.begin(); it != infls.end(); ++it) 614 615 const CComponentManager::InterfaceList::const_iterator itEnd = infls.end(); 616 for (CComponentManager::InterfaceList::const_iterator it = infls.begin(); it != itEnd; ++it) 564 617 { 565 618 ICmpTerritoryInfluence* cmpTerritoryInfluence = static_cast<ICmpTerritoryInfluence*>(it->second); 566 619 567 i32 cost = cmpTerritoryInfluence->GetCost();620 const i32 cost = cmpTerritoryInfluence->GetCost(); 568 621 if (cost == -1) 569 622 continue; 570 623 … … 576 629 if (!cmpObstruction->GetObstructionSquare(square)) 577 630 continue; 578 631 579 CFixedVector2D halfSize(square.hw, square.hh);580 CFixedVector2D halfBound = Geometry::GetHalfBoundingBox(square.u, square.v, halfSize);632 const CFixedVector2D halfSize(square.hw, square.hh); 633 const CFixedVector2D halfBound = Geometry::GetHalfBoundingBox(square.u, square.v, halfSize); 581 634 582 635 u16 i0, j0, i1, j1; 583 636 NearestTile(square.x - halfBound.X, square.z - halfBound.Y, i0, j0, grid.m_W, grid.m_H); … … 691 744 m_BoundaryLinesDirty = false; 692 745 } 693 746 694 for (size_t i = 0; i < m_BoundaryLines.size(); ++i) 747 const float alpha = 0.2f + 0.8f * fabsf((float)cos(m_AnimTime * M_PI));// TODO: should let artists tweak this 748 const std::vector<SBoundaryLine>::iterator itEnd = m_BoundaryLines.end(); 749 for (std::vector<SBoundaryLine>::iterator it = m_BoundaryLines.begin(); it != itEnd; ++it) 695 750 { 696 if (!m_BoundaryLines[i].connected) 751 SBoundaryLine& boundaryline = *it; 752 if (!boundaryline.connected) 697 753 { 698 CColor c = m_BoundaryLines[i].color;699 c.a *= 0.2f + 0.8f * fabsf((float)cos(m_AnimTime * M_PI)); // TODO: should let artists tweak this700 m_BoundaryLines[i].overlay.m_Color = c;754 CColor c (boundaryline.color); 755 c.a *= alpha; 756 boundaryline.overlay.m_Color = c; 701 757 } 702 758 } 703 759 } 704 760 705 761 void CCmpTerritoryManager::RenderSubmit(SceneCollector& collector) 706 762 { 707 for (size_t i = 0; i < m_BoundaryLines.size(); ++i) 708 collector.Submit(&m_BoundaryLines[i].overlay); 709 710 for (size_t i = 0; i < m_DebugBoundaryLineNodes.size(); ++i) 711 collector.Submit(&m_DebugBoundaryLineNodes[i]); 763 { 764 const std::vector<SBoundaryLine>::iterator itEnd = m_BoundaryLines.end(); 765 for (std::vector<SBoundaryLine>::iterator it = m_BoundaryLines.begin(); 766 it != itEnd; ++it) 767 { 768 SBoundaryLine& boundaryline = *it; 769 collector.Submit(&boundaryline.overlay); 770 } 771 } 712 772 773 { 774 const std::vector<SOverlayLine>::iterator itEnd = m_DebugBoundaryLineNodes.end(); 775 for (std::vector<SOverlayLine>::iterator it = m_DebugBoundaryLineNodes.begin(); 776 it != itEnd; ++it) 777 { 778 SOverlayLine& overlayLine = *it; 779 collector.Submit(&overlayLine); 780 } 781 } 713 782 } 714 783 715 784 player_id_t CCmpTerritoryManager::GetOwner(entity_pos_t x, entity_pos_t z) 716 785 { 717 u16 i, j;718 786 CalculateTerritories(); 719 787 if (!m_Territories) 720 788 return 0; 721 789 790 u16 i, j; 722 791 NearestTile(x, z, i, j, m_Territories->m_W, m_Territories->m_H); 723 792 return m_Territories->get(i, j) & TERRITORY_PLAYER_MASK; 724 793 } 725 794 726 795 bool CCmpTerritoryManager::IsConnected(entity_pos_t x, entity_pos_t z) 727 796 { 728 u16 i, j;729 797 CalculateTerritories(); 730 798 if (!m_Territories) 731 799 return false; 732 800 801 u16 i, j; 733 802 NearestTile(x, z, i, j, m_Territories->m_W, m_Territories->m_H); 734 803 return (m_Territories->get(i, j) & TERRITORY_CONNECTED_MASK) != 0; 735 804 } … … 743 812 m_TerritoryManager.CalculateTerritories(); 744 813 } 745 814 746 void TerritoryOverlay::ProcessTile( ssize_t i,ssize_t j)815 void TerritoryOverlay::ProcessTile(const ssize_t i, const ssize_t j) 747 816 { 748 817 if (!m_TerritoryManager.m_Territories) 749 818 return; 750 819 751 u8 id = (m_TerritoryManager.m_Territories->get((int) i, (int) j) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK);820 const u8 id = (m_TerritoryManager.m_Territories->get((int) i, (int) j) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK); 752 821 753 float a = 0.2f;822 const float a = 0.2f; 754 823 switch (id) 755 824 { 756 825 case 0: break; … … 762 831 case 6: RenderTile(CColor(1, 0, 1, a), false); break; 763 832 default: RenderTile(CColor(1, 1, 1, a), false); break; 764 833 } 765 } 834 } 835 No newline at end of file