forked from 0ad/0ad
Adapt Atlas to the new pathfinder. Fixes #3298
This was SVN commit r16824.
This commit is contained in:
parent
6a9019564e
commit
30e5f032d8
@ -1024,7 +1024,7 @@ public:
|
||||
LoadPathfinderClasses(state);
|
||||
std::map<std::string, pass_class_t> passClassMasks;
|
||||
if (cmpPathfinder)
|
||||
passClassMasks = cmpPathfinder->GetPathfindingPassabilityClasses();
|
||||
passClassMasks = cmpPathfinder->GetPassabilityClasses(true);
|
||||
|
||||
m_Worker.RunGamestateInit(scriptInterface.WriteStructuredClone(state), *passabilityMap, *territoryMap, passClassMasks);
|
||||
}
|
||||
@ -1076,7 +1076,7 @@ public:
|
||||
LoadPathfinderClasses(state);
|
||||
std::map<std::string, pass_class_t> passClassMasks;
|
||||
if (cmpPathfinder)
|
||||
passClassMasks = cmpPathfinder->GetPathfindingPassabilityClasses();
|
||||
passClassMasks = cmpPathfinder->GetPassabilityClasses(true);
|
||||
|
||||
m_Worker.StartComputation(scriptInterface.WriteStructuredClone(state),
|
||||
*passabilityMap, dirtinessInformations,
|
||||
|
@ -57,6 +57,7 @@ void CCmpPathfinder::Init(const CParamNode& UNUSED(paramNode))
|
||||
m_NextAsyncTicket = 1;
|
||||
|
||||
m_DebugOverlay = false;
|
||||
m_AtlasOverlay = NULL;
|
||||
|
||||
m_SameTurnMovesCount = 0;
|
||||
|
||||
@ -102,6 +103,7 @@ void CCmpPathfinder::Init(const CParamNode& UNUSED(paramNode))
|
||||
void CCmpPathfinder::Deinit()
|
||||
{
|
||||
SetDebugOverlay(false); // cleans up memory
|
||||
SAFE_DELETE(m_AtlasOverlay);
|
||||
|
||||
SAFE_DELETE(m_Grid);
|
||||
SAFE_DELETE(m_TerrainOnlyGrid);
|
||||
@ -171,6 +173,9 @@ void CCmpPathfinder::HandleMessage(const CMessage& msg, bool UNUSED(global))
|
||||
case MT_WaterChanged:
|
||||
case MT_ObstructionMapShapeChanged:
|
||||
m_TerrainDirty = true;
|
||||
// TODO: this can be optimized by only updating a part of the terrain grid
|
||||
// using the TerrainChanged message data.
|
||||
MinimalTerrainUpdate();
|
||||
break;
|
||||
case MT_TurnStart:
|
||||
m_SameTurnMovesCount = 0;
|
||||
@ -186,6 +191,17 @@ void CCmpPathfinder::RenderSubmit(SceneCollector& collector)
|
||||
m_LongPathfinder.HierarchicalRenderSubmit(collector);
|
||||
}
|
||||
|
||||
void CCmpPathfinder::SetAtlasOverlay(bool enable, pass_class_t passClass)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
if (!m_AtlasOverlay)
|
||||
m_AtlasOverlay = new AtlasOverlay(this, passClass);
|
||||
m_AtlasOverlay->m_PassClass = passClass;
|
||||
}
|
||||
else
|
||||
SAFE_DELETE(m_AtlasOverlay);
|
||||
}
|
||||
|
||||
pass_class_t CCmpPathfinder::GetPassabilityClass(const std::string& name)
|
||||
{
|
||||
@ -203,14 +219,14 @@ std::map<std::string, pass_class_t> CCmpPathfinder::GetPassabilityClasses()
|
||||
return m_PassClassMasks;
|
||||
}
|
||||
|
||||
std::map<std::string, pass_class_t> CCmpPathfinder::GetPathfindingPassabilityClasses()
|
||||
std::map<std::string, pass_class_t> CCmpPathfinder::GetPassabilityClasses(bool pathfindingClasses)
|
||||
{
|
||||
std::map<std::string, pass_class_t> pathfindingClasses;
|
||||
std::map<std::string, pass_class_t> passabilityClasses;
|
||||
for (auto& pair : m_PassClassMasks)
|
||||
if (GetPassabilityFromMask(pair.second)->m_Obstructions == PathfinderPassability::PATHFINDING)
|
||||
pathfindingClasses[pair.first] = pair.second;
|
||||
if ((GetPassabilityFromMask(pair.second)->m_Obstructions == PathfinderPassability::PATHFINDING) == pathfindingClasses)
|
||||
passabilityClasses[pair.first] = pair.second;
|
||||
|
||||
return pathfindingClasses;
|
||||
return passabilityClasses;
|
||||
}
|
||||
|
||||
const PathfinderPassability* CCmpPathfinder::GetPassabilityFromMask(pass_class_t passClass) const
|
||||
@ -423,58 +439,6 @@ Grid<u16> CCmpPathfinder::ComputeShoreGrid(bool expandOnWater)
|
||||
return shoreGrid;
|
||||
}
|
||||
|
||||
void CCmpPathfinder::ComputeTerrainPassabilityGrid(const Grid<u16>& shoreGrid)
|
||||
{
|
||||
PROFILE3("terrain passability");
|
||||
|
||||
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY);
|
||||
|
||||
CTerrain& terrain = GetSimContext().GetTerrain();
|
||||
|
||||
// Compute initial terrain-dependent passability
|
||||
for (int j = 0; j < m_MapSize * Pathfinding::NAVCELLS_PER_TILE; ++j)
|
||||
{
|
||||
for (int i = 0; i < m_MapSize * Pathfinding::NAVCELLS_PER_TILE; ++i)
|
||||
{
|
||||
// World-space coordinates for this navcell
|
||||
fixed x, z;
|
||||
Pathfinding::NavcellCenter(i, j, x, z);
|
||||
|
||||
// Terrain-tile coordinates for this navcell
|
||||
int itile = i / Pathfinding::NAVCELLS_PER_TILE;
|
||||
int jtile = j / Pathfinding::NAVCELLS_PER_TILE;
|
||||
|
||||
// Gather all the data potentially needed to determine passability:
|
||||
|
||||
fixed height = terrain.GetExactGroundLevelFixed(x, z);
|
||||
|
||||
fixed water;
|
||||
if (cmpWaterManager)
|
||||
water = cmpWaterManager->GetWaterLevel(x, z);
|
||||
|
||||
fixed depth = water - height;
|
||||
|
||||
//fixed slope = terrain.GetExactSlopeFixed(x, z);
|
||||
// Exact slopes give kind of weird output, so just use rough tile-based slopes
|
||||
fixed slope = terrain.GetSlopeFixed(itile, jtile);
|
||||
|
||||
// Get world-space coordinates from shoreGrid (which uses terrain tiles)
|
||||
fixed shoredist = fixed::FromInt(shoreGrid.get(itile, jtile)).MultiplyClamp(TERRAIN_TILE_SIZE);
|
||||
|
||||
// Compute the passability for every class for this cell:
|
||||
|
||||
NavcellData t = 0;
|
||||
for (PathfinderPassability& passability : m_PassClasses)
|
||||
{
|
||||
if (!passability.IsPassable(depth, slope, shoredist))
|
||||
t |= passability.m_Mask;
|
||||
}
|
||||
|
||||
m_Grid->set(i, j, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCmpPathfinder::UpdateGrid()
|
||||
{
|
||||
PROFILE3("UpdateGrid");
|
||||
@ -519,74 +483,9 @@ void CCmpPathfinder::UpdateGrid()
|
||||
// Else, use data from m_TerrainOnlyGrid and add obstructions
|
||||
if (m_TerrainDirty)
|
||||
{
|
||||
Grid<u16> shoreGrid = ComputeShoreGrid();
|
||||
TerrainUpdateHelper();
|
||||
|
||||
ComputeTerrainPassabilityGrid(shoreGrid);
|
||||
|
||||
// Compute off-world passability
|
||||
// WARNING: CCmpRangeManager::LosIsOffWorld needs to be kept in sync with this
|
||||
|
||||
const int edgeSize = 3 * Pathfinding::NAVCELLS_PER_TILE; // number of tiles around the edge that will be off-world
|
||||
|
||||
NavcellData edgeMask = 0;
|
||||
for (PathfinderPassability& passability : m_PassClasses)
|
||||
edgeMask |= passability.m_Mask;
|
||||
|
||||
int w = m_Grid->m_W;
|
||||
int h = m_Grid->m_H;
|
||||
|
||||
if (cmpObstructionManager->GetPassabilityCircular())
|
||||
{
|
||||
for (int j = 0; j < h; ++j)
|
||||
{
|
||||
for (int i = 0; i < w; ++i)
|
||||
{
|
||||
// Based on CCmpRangeManager::LosIsOffWorld
|
||||
// but tweaked since it's tile-based instead.
|
||||
// (We double all the values so we can handle half-tile coordinates.)
|
||||
// This needs to be slightly tighter than the LOS circle,
|
||||
// else units might get themselves lost in the SoD around the edge.
|
||||
|
||||
int dist2 = (i*2 + 1 - w)*(i*2 + 1 - w)
|
||||
+ (j*2 + 1 - h)*(j*2 + 1 - h);
|
||||
|
||||
if (dist2 >= (w - 2*edgeSize) * (h - 2*edgeSize))
|
||||
m_Grid->set(i, j, m_Grid->get(i, j) | edgeMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u16 j = 0; j < h; ++j)
|
||||
for (u16 i = 0; i < edgeSize; ++i)
|
||||
m_Grid->set(i, j, m_Grid->get(i, j) | edgeMask);
|
||||
for (u16 j = 0; j < h; ++j)
|
||||
for (u16 i = w-edgeSize+1; i < w; ++i)
|
||||
m_Grid->set(i, j, m_Grid->get(i, j) | edgeMask);
|
||||
for (u16 j = 0; j < edgeSize; ++j)
|
||||
for (u16 i = edgeSize; i < w-edgeSize+1; ++i)
|
||||
m_Grid->set(i, j, m_Grid->get(i, j) | edgeMask);
|
||||
for (u16 j = h-edgeSize+1; j < h; ++j)
|
||||
for (u16 i = edgeSize; i < w-edgeSize+1; ++i)
|
||||
m_Grid->set(i, j, m_Grid->get(i, j) | edgeMask);
|
||||
}
|
||||
|
||||
// Expand the impassability grid, for any class with non-zero clearance,
|
||||
// so that we can stop units getting too close to impassable navcells.
|
||||
// Note: It's not possible to perform this expansion once for all passabilities
|
||||
// with the same clearance, because the impassable cells are not necessarily the
|
||||
// same for all these passabilities.
|
||||
for (PathfinderPassability& passability : m_PassClasses)
|
||||
{
|
||||
if (passability.m_Clearance == fixed::Zero())
|
||||
continue;
|
||||
|
||||
int clearance = (passability.m_Clearance / Pathfinding::NAVCELL_SIZE).ToInt_RoundToInfinity();
|
||||
ExpandImpassableCells(*m_Grid, clearance, passability.m_Mask);
|
||||
}
|
||||
|
||||
// Store the updated terrain-only grid
|
||||
*m_TerrainOnlyGrid = *m_Grid;
|
||||
*m_Grid = *m_TerrainOnlyGrid;
|
||||
|
||||
m_TerrainDirty = false;
|
||||
m_ObstructionsDirty.globalRecompute = true;
|
||||
@ -615,11 +514,143 @@ void CCmpPathfinder::UpdateGrid()
|
||||
|
||||
// Update the long-range pathfinder
|
||||
if (m_ObstructionsDirty.globallyDirty)
|
||||
m_LongPathfinder.Reload(GetPathfindingPassabilityClasses(), m_Grid);
|
||||
m_LongPathfinder.Reload(GetPassabilityClasses(true), m_Grid);
|
||||
else
|
||||
m_LongPathfinder.Update(m_Grid, m_ObstructionsDirty.dirtinessGrid);
|
||||
}
|
||||
|
||||
void CCmpPathfinder::MinimalTerrainUpdate()
|
||||
{
|
||||
TerrainUpdateHelper();
|
||||
}
|
||||
|
||||
void CCmpPathfinder::TerrainUpdateHelper()
|
||||
{
|
||||
PROFILE3("TerrainUpdateHelper");
|
||||
|
||||
CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSimContext(), SYSTEM_ENTITY);
|
||||
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSimContext(), SYSTEM_ENTITY);
|
||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
|
||||
CTerrain& terrain = GetSimContext().GetTerrain();
|
||||
|
||||
if (!cmpTerrain || !cmpObstructionManager)
|
||||
return;
|
||||
|
||||
u16 terrainSize = cmpTerrain->GetTilesPerSide();
|
||||
if (terrainSize == 0)
|
||||
return;
|
||||
|
||||
if (!m_TerrainOnlyGrid || m_MapSize != terrainSize)
|
||||
{
|
||||
m_MapSize = terrainSize;
|
||||
|
||||
SAFE_DELETE(m_TerrainOnlyGrid);
|
||||
m_TerrainOnlyGrid = new Grid<NavcellData>(m_MapSize * Pathfinding::NAVCELLS_PER_TILE, m_MapSize * Pathfinding::NAVCELLS_PER_TILE);
|
||||
}
|
||||
|
||||
Grid<u16> shoreGrid = ComputeShoreGrid();
|
||||
|
||||
// Compute initial terrain-dependent passability
|
||||
for (int j = 0; j < m_MapSize * Pathfinding::NAVCELLS_PER_TILE; ++j)
|
||||
{
|
||||
for (int i = 0; i < m_MapSize * Pathfinding::NAVCELLS_PER_TILE; ++i)
|
||||
{
|
||||
// World-space coordinates for this navcell
|
||||
fixed x, z;
|
||||
Pathfinding::NavcellCenter(i, j, x, z);
|
||||
|
||||
// Terrain-tile coordinates for this navcell
|
||||
int itile = i / Pathfinding::NAVCELLS_PER_TILE;
|
||||
int jtile = j / Pathfinding::NAVCELLS_PER_TILE;
|
||||
|
||||
// Gather all the data potentially needed to determine passability:
|
||||
|
||||
fixed height = terrain.GetExactGroundLevelFixed(x, z);
|
||||
|
||||
fixed water;
|
||||
if (cmpWaterManager)
|
||||
water = cmpWaterManager->GetWaterLevel(x, z);
|
||||
|
||||
fixed depth = water - height;
|
||||
|
||||
// Exact slopes give kind of weird output, so just use rough tile-based slopes
|
||||
fixed slope = terrain.GetSlopeFixed(itile, jtile);
|
||||
|
||||
// Get world-space coordinates from shoreGrid (which uses terrain tiles)
|
||||
fixed shoredist = fixed::FromInt(shoreGrid.get(itile, jtile)).MultiplyClamp(TERRAIN_TILE_SIZE);
|
||||
|
||||
// Compute the passability for every class for this cell
|
||||
NavcellData t = 0;
|
||||
for (PathfinderPassability& passability : m_PassClasses)
|
||||
if (!passability.IsPassable(depth, slope, shoredist))
|
||||
t |= passability.m_Mask;
|
||||
|
||||
m_TerrainOnlyGrid->set(i, j, t);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute off-world passability
|
||||
// WARNING: CCmpRangeManager::LosIsOffWorld needs to be kept in sync with this
|
||||
const int edgeSize = 3 * Pathfinding::NAVCELLS_PER_TILE; // number of tiles around the edge that will be off-world
|
||||
|
||||
NavcellData edgeMask = 0;
|
||||
for (PathfinderPassability& passability : m_PassClasses)
|
||||
edgeMask |= passability.m_Mask;
|
||||
|
||||
int w = m_TerrainOnlyGrid->m_W;
|
||||
int h = m_TerrainOnlyGrid->m_H;
|
||||
|
||||
if (cmpObstructionManager->GetPassabilityCircular())
|
||||
{
|
||||
for (int j = 0; j < h; ++j)
|
||||
{
|
||||
for (int i = 0; i < w; ++i)
|
||||
{
|
||||
// Based on CCmpRangeManager::LosIsOffWorld
|
||||
// but tweaked since it's tile-based instead.
|
||||
// (We double all the values so we can handle half-tile coordinates.)
|
||||
// This needs to be slightly tighter than the LOS circle,
|
||||
// else units might get themselves lost in the SoD around the edge.
|
||||
|
||||
int dist2 = (i*2 + 1 - w)*(i*2 + 1 - w)
|
||||
+ (j*2 + 1 - h)*(j*2 + 1 - h);
|
||||
|
||||
if (dist2 >= (w - 2*edgeSize) * (h - 2*edgeSize))
|
||||
m_TerrainOnlyGrid->set(i, j, m_TerrainOnlyGrid->get(i, j) | edgeMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (u16 j = 0; j < h; ++j)
|
||||
for (u16 i = 0; i < edgeSize; ++i)
|
||||
m_TerrainOnlyGrid->set(i, j, m_TerrainOnlyGrid->get(i, j) | edgeMask);
|
||||
for (u16 j = 0; j < h; ++j)
|
||||
for (u16 i = w-edgeSize+1; i < w; ++i)
|
||||
m_TerrainOnlyGrid->set(i, j, m_TerrainOnlyGrid->get(i, j) | edgeMask);
|
||||
for (u16 j = 0; j < edgeSize; ++j)
|
||||
for (u16 i = edgeSize; i < w-edgeSize+1; ++i)
|
||||
m_TerrainOnlyGrid->set(i, j, m_TerrainOnlyGrid->get(i, j) | edgeMask);
|
||||
for (u16 j = h-edgeSize+1; j < h; ++j)
|
||||
for (u16 i = edgeSize; i < w-edgeSize+1; ++i)
|
||||
m_TerrainOnlyGrid->set(i, j, m_TerrainOnlyGrid->get(i, j) | edgeMask);
|
||||
}
|
||||
|
||||
// Expand the impassability grid, for any class with non-zero clearance,
|
||||
// so that we can stop units getting too close to impassable navcells.
|
||||
// Note: It's not possible to perform this expansion once for all passabilities
|
||||
// with the same clearance, because the impassable cells are not necessarily the
|
||||
// same for all these passabilities.
|
||||
for (PathfinderPassability& passability : m_PassClasses)
|
||||
{
|
||||
if (passability.m_Clearance == fixed::Zero())
|
||||
continue;
|
||||
|
||||
int clearance = (passability.m_Clearance / Pathfinding::NAVCELL_SIZE).ToInt_RoundToInfinity();
|
||||
ExpandImpassableCells(*m_TerrainOnlyGrid, clearance, passability.m_Mask);
|
||||
}
|
||||
}
|
||||
|
||||
const GridUpdateInformation& CCmpPathfinder::GetDirtinessData() const
|
||||
{
|
||||
return m_ObstructionsDirty;
|
||||
@ -811,15 +842,14 @@ ICmpObstruction::EFoundationCheck CCmpPathfinder::CheckBuildingPlacement(const I
|
||||
i16 j = span.j;
|
||||
|
||||
// Fail if any span extends outside the grid
|
||||
if (i0 < 0 || i1 > m_Grid->m_W || j < 0 || j > m_Grid->m_H)
|
||||
if (i0 < 0 || i1 > m_TerrainOnlyGrid->m_W || j < 0 || j > m_TerrainOnlyGrid->m_H)
|
||||
return ICmpObstruction::FOUNDATION_CHECK_FAIL_TERRAIN_CLASS;
|
||||
|
||||
// Fail if any span includes an impassable tile
|
||||
for (i16 i = i0; i < i1; ++i)
|
||||
if (!IS_PASSABLE(m_Grid->get(i, j), passClass))
|
||||
if (!IS_PASSABLE(m_TerrainOnlyGrid->get(i, j), passClass))
|
||||
return ICmpObstruction::FOUNDATION_CHECK_FAIL_TERRAIN_CLASS;
|
||||
}
|
||||
|
||||
return ICmpObstruction::FOUNDATION_CHECK_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "simulation2/helpers/LongPathfinder.h"
|
||||
|
||||
class SceneCollector;
|
||||
class AtlasOverlay;
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define PATHFIND_DEBUG 0
|
||||
@ -124,6 +125,7 @@ public:
|
||||
|
||||
bool m_DebugOverlay;
|
||||
std::vector<SOverlayLine> m_DebugOverlayShortPathLines;
|
||||
AtlasOverlay* m_AtlasOverlay;
|
||||
|
||||
static std::string GetSchema()
|
||||
{
|
||||
@ -143,8 +145,7 @@ public:
|
||||
virtual pass_class_t GetPassabilityClass(const std::string& name);
|
||||
|
||||
virtual std::map<std::string, pass_class_t> GetPassabilityClasses();
|
||||
|
||||
virtual std::map<std::string, pass_class_t> GetPathfindingPassabilityClasses();
|
||||
virtual std::map<std::string, pass_class_t> GetPassabilityClasses(bool pathfindingClasses);
|
||||
|
||||
const PathfinderPassability* GetPassabilityFromMask(pass_class_t passClass) const;
|
||||
|
||||
@ -206,6 +207,8 @@ public:
|
||||
m_LongPathfinder.GetDebugData(steps, time, grid);
|
||||
}
|
||||
|
||||
virtual void SetAtlasOverlay(bool enable, pass_class_t passClass = 0);
|
||||
|
||||
virtual bool CheckMovement(const IObstructionTestFilter& filter, entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1, entity_pos_t r, pass_class_t passClass);
|
||||
|
||||
virtual ICmpObstruction::EFoundationCheck CheckUnitPlacement(const IObstructionTestFilter& filter, entity_pos_t x, entity_pos_t z, entity_pos_t r, pass_class_t passClass, bool onlyCenterPoint);
|
||||
@ -227,9 +230,50 @@ public:
|
||||
*/
|
||||
virtual void UpdateGrid();
|
||||
|
||||
void ComputeTerrainPassabilityGrid(const Grid<u16>& shoreGrid);
|
||||
/**
|
||||
* Updates the terrain-only grid without updating the dirtiness informations.
|
||||
* Useful for fast passability updates in Atlas.
|
||||
*/
|
||||
void MinimalTerrainUpdate();
|
||||
|
||||
/**
|
||||
* Regenerates the terrain-only grid.
|
||||
*/
|
||||
void TerrainUpdateHelper();
|
||||
|
||||
void RenderSubmit(SceneCollector& collector);
|
||||
};
|
||||
|
||||
class AtlasOverlay : public TerrainTextureOverlay
|
||||
{
|
||||
public:
|
||||
const CCmpPathfinder* m_Pathfinder;
|
||||
pass_class_t m_PassClass;
|
||||
|
||||
AtlasOverlay(const CCmpPathfinder* pathfinder, pass_class_t passClass) :
|
||||
TerrainTextureOverlay(Pathfinding::NAVCELLS_PER_TILE), m_Pathfinder(pathfinder), m_PassClass(passClass)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void BuildTextureRGBA(u8* data, size_t w, size_t h)
|
||||
{
|
||||
// Render navcell passability, based on the terrain-only grid
|
||||
u8* p = data;
|
||||
for (size_t j = 0; j < h; ++j)
|
||||
{
|
||||
for (size_t i = 0; i < w; ++i)
|
||||
{
|
||||
SColor4ub color(0, 0, 0, 0);
|
||||
if (!IS_PASSABLE(m_Pathfinder->m_TerrainOnlyGrid->get((int)i, (int)j), m_PassClass))
|
||||
color = SColor4ub(255, 0, 0, 127);
|
||||
|
||||
*p++ = color.R;
|
||||
*p++ = color.G;
|
||||
*p++ = color.B;
|
||||
*p++ = color.A;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // INCLUDED_CCMPPATHFINDER_COMMON
|
||||
|
@ -95,6 +95,9 @@ public:
|
||||
virtual u16 GetTilesPerSide()
|
||||
{
|
||||
ssize_t tiles = m_Terrain->GetTilesPerSide();
|
||||
|
||||
if (tiles == -1)
|
||||
return 0;
|
||||
ENSURE(1 <= tiles && tiles <= 65535);
|
||||
return (u16)tiles;
|
||||
}
|
||||
|
@ -56,9 +56,9 @@ public:
|
||||
virtual std::map<std::string, pass_class_t> GetPassabilityClasses() = 0;
|
||||
|
||||
/**
|
||||
* Get the list of pathfinding passability classes.
|
||||
* Get the list of pathfinding passability classes, or all others.
|
||||
*/
|
||||
virtual std::map<std::string, pass_class_t> GetPathfindingPassabilityClasses() = 0;
|
||||
virtual std::map<std::string, pass_class_t> GetPassabilityClasses(bool pathfindingClasses) = 0;
|
||||
|
||||
/**
|
||||
* Get the tag for a given passability class name.
|
||||
@ -186,6 +186,11 @@ public:
|
||||
*/
|
||||
virtual void GetDebugData(u32& steps, double& time, Grid<u8>& grid) = 0;
|
||||
|
||||
/**
|
||||
* Sets up the pathfinder passability overlay in Atlas.
|
||||
*/
|
||||
virtual void SetAtlasOverlay(bool enable, pass_class_t passClass = 0) = 0;
|
||||
|
||||
DECLARE_INTERFACE_TYPE(Pathfinder)
|
||||
};
|
||||
|
||||
|
@ -137,7 +137,7 @@ QUERYHANDLER(GetTerrainPassabilityClasses)
|
||||
CmpPtr<ICmpPathfinder> cmpPathfinder(*AtlasView::GetView_Game()->GetSimulation2(), SYSTEM_ENTITY);
|
||||
if (cmpPathfinder)
|
||||
{
|
||||
std::map<std::string, pass_class_t> classes = cmpPathfinder->GetPassabilityClasses();
|
||||
std::map<std::string, pass_class_t> classes = cmpPathfinder->GetPassabilityClasses(false);
|
||||
|
||||
std::vector<std::wstring> classNames;
|
||||
for (std::map<std::string, pass_class_t>::iterator it = classes.begin(); it != classes.end(); ++it)
|
||||
|
@ -236,26 +236,6 @@ void AtlasViewGame::Render()
|
||||
camera.SetProjection(g_Game->GetView()->GetNear(), g_Game->GetView()->GetFar(), g_Game->GetView()->GetFOV());
|
||||
camera.UpdateFrustum();
|
||||
|
||||
// Update the pathfinder display if necessary
|
||||
if (!m_DisplayPassability.empty())
|
||||
{
|
||||
CmpPtr<ICmpObstructionManager> cmpObstructionManager(*GetSimulation2(), SYSTEM_ENTITY);
|
||||
if (cmpObstructionManager)
|
||||
{
|
||||
cmpObstructionManager->SetDebugOverlay(true);
|
||||
}
|
||||
|
||||
CmpPtr<ICmpPathfinder> cmpPathfinder(*GetSimulation2(), SYSTEM_ENTITY);
|
||||
if (cmpPathfinder)
|
||||
{
|
||||
cmpPathfinder->SetDebugOverlay(true);
|
||||
// Kind of a hack to make it update the terrain grid
|
||||
PathGoal goal = { PathGoal::POINT, fixed::Zero(), fixed::Zero() };
|
||||
pass_class_t passClass = cmpPathfinder->GetPassabilityClass(m_DisplayPassability);
|
||||
cmpPathfinder->SetDebugPath(fixed::Zero(), fixed::Zero(), goal, passClass);
|
||||
}
|
||||
}
|
||||
|
||||
::Render();
|
||||
Atlas_GLSwapBuffers((void*)g_AtlasGameLoop->glCanvas);
|
||||
}
|
||||
@ -315,13 +295,14 @@ void AtlasViewGame::SetParam(const std::wstring& name, const std::wstring& value
|
||||
{
|
||||
m_DisplayPassability = CStrW(value).ToUTF8();
|
||||
|
||||
CmpPtr<ICmpObstructionManager> cmpObstructionManager(*GetSimulation2(), SYSTEM_ENTITY);
|
||||
if (cmpObstructionManager)
|
||||
cmpObstructionManager->SetDebugOverlay(!value.empty());
|
||||
|
||||
CmpPtr<ICmpPathfinder> cmpPathfinder(*GetSimulation2(), SYSTEM_ENTITY);
|
||||
if (cmpPathfinder)
|
||||
cmpPathfinder->SetDebugOverlay(!value.empty());
|
||||
{
|
||||
if (!value.empty())
|
||||
cmpPathfinder->SetAtlasOverlay(true, cmpPathfinder->GetPassabilityClass(m_DisplayPassability));
|
||||
else
|
||||
cmpPathfinder->SetAtlasOverlay(false);
|
||||
}
|
||||
}
|
||||
else if (name == L"renderpath")
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user