void UpdateProjection(CPos cell) { MPos uv; if (Grid.MaximumTerrainHeight == 0) { uv = cell.ToMPos(Grid.Type); cellProjection[cell] = new[] { (PPos)uv }; var inverse = inverseCellProjection[uv]; inverse.Clear(); inverse.Add(uv); return; } if (!initializedCellProjection) { InitializeCellProjection(); } uv = cell.ToMPos(Grid.Type); // Remove old reverse projection foreach (var puv in cellProjection[uv]) { var temp = (MPos)puv; inverseCellProjection[temp].Remove(uv); projectedHeight[temp] = ProjectedCellHeightInner(puv); } var projected = ProjectCellInner(uv); cellProjection[uv] = projected; foreach (var puv in projected) { var temp = (MPos)puv; inverseCellProjection[temp].Add(uv); var height = ProjectedCellHeightInner(puv); projectedHeight[temp] = height; // Propagate height up cliff faces while (true) { temp = new MPos(temp.U, temp.V - 1); if (!inverseCellProjection.Contains(temp) || inverseCellProjection[temp].Any()) { break; } projectedHeight[temp] = height; } } }
void UpdateProjection(CPos cell) { if (MaximumTerrainHeight == 0) { return; } if (!initializedCellProjection) { InitializeCellProjection(); } var uv = cell.ToMPos(TileShape); // Remove old reverse projection foreach (var puv in cellProjection[uv]) { inverseCellProjection[(MPos)puv].Remove(uv); } var projected = ProjectCellInner(uv); cellProjection[uv] = projected; foreach (var puv in projected) { inverseCellProjection[(MPos)puv].Add(uv); } }
public byte GetTerrainIndex(CPos cell) { var uv = cell.ToMPos(this); var custom = CustomTerrain[uv]; return(custom != byte.MaxValue ? custom : cachedTileSet.Value.GetTerrainIndex(MapTiles.Value[uv])); }
public byte GetTerrainIndex(CPos cell) { const short InvalidCachedTerrainIndex = -1; // Lazily initialize a cache for terrain indexes. if (cachedTerrainIndexes == null) { cachedTerrainIndexes = new CellLayer <short>(this); cachedTerrainIndexes.Clear(InvalidCachedTerrainIndex); // Invalidate the entry for a cell if anything could cause the terrain index to change. Action <CPos> invalidateTerrainIndex = c => cachedTerrainIndexes[c] = InvalidCachedTerrainIndex; CustomTerrain.CellEntryChanged += invalidateTerrainIndex; Tiles.CellEntryChanged += invalidateTerrainIndex; } var uv = cell.ToMPos(this); var terrainIndex = cachedTerrainIndexes[uv]; // PERF: Cache terrain indexes per cell on demand. if (terrainIndex == InvalidCachedTerrainIndex) { var custom = CustomTerrain[uv]; terrainIndex = cachedTerrainIndexes[uv] = custom != byte.MaxValue ? custom : Rules.TileSet.GetTerrainIndex(Tiles[uv]); } return((byte)terrainIndex); }
public CPos ChooseClosestEdgeCell(CPos pos) { var mpos = pos.ToMPos(this); var horizontalBound = ((mpos.U - Bounds.Left) < Bounds.Width / 2) ? Bounds.Left : Bounds.Right; var verticalBound = ((mpos.V - Bounds.Top) < Bounds.Height / 2) ? Bounds.Top : Bounds.Bottom; var distX = Math.Abs(horizontalBound - mpos.U); var distY = Math.Abs(verticalBound - mpos.V); return(distX < distY ? new MPos(horizontalBound, mpos.V).ToCPos(this) : new MPos(mpos.U, verticalBound).ToCPos(this)); }
public bool Contains(CPos cell) { // .ToMPos() returns the same result if the X and Y coordinates // are switched. X < Y is invalid in the Diamond coordinate system, // so we pre-filter these to avoid returning the wrong result if (Shape == TileShape.Diamond && cell.X < cell.Y) { return(false); } return(Contains(cell.ToMPos(Shape))); }
public bool Contains(CPos cell) { // .ToMPos() returns the same result if the X and Y coordinates // are switched. X < Y is invalid in the RectangularIsometric coordinate system, // so we pre-filter these to avoid returning the wrong result if (GridType == MapGridType.RectangularIsometric && cell.X < cell.Y) { return(false); } return(Contains(cell.ToMPos(GridType))); }
void UpdateProjection(CPos cell) { MPos uv; if (Grid.MaximumTerrainHeight == 0) { uv = cell.ToMPos(Grid.Type); cellProjection[cell] = new[] { (PPos)uv }; var inverse = inverseCellProjection[uv]; inverse.Clear(); inverse.Add(uv); return; } if (!initializedCellProjection) { InitializeCellProjection(); } uv = cell.ToMPos(Grid.Type); // Remove old reverse projection foreach (var puv in cellProjection[uv]) { inverseCellProjection[(MPos)puv].Remove(uv); } var projected = ProjectCellInner(uv); cellProjection[uv] = projected; foreach (var puv in projected) { inverseCellProjection[(MPos)puv].Add(uv); } }
public CPos ChooseClosestEdgeCell(CPos cell) { return(ChooseClosestEdgeCell(cell.ToMPos(Grid.Type)).ToCPos(Grid.Type)); }
void UpdateProjection(CPos cell) { MPos uv; if (Grid.MaximumTerrainHeight == 0) { uv = cell.ToMPos(Grid.Type); cellProjection[cell] = new[] { (PPos)uv }; var inverse = inverseCellProjection[uv]; inverse.Clear(); inverse.Add(uv); return; } if (!initializedCellProjection) InitializeCellProjection(); uv = cell.ToMPos(Grid.Type); // Remove old reverse projection foreach (var puv in cellProjection[uv]) inverseCellProjection[(MPos)puv].Remove(uv); var projected = ProjectCellInner(uv); cellProjection[uv] = projected; foreach (var puv in projected) inverseCellProjection[(MPos)puv].Add(uv); }
public CPos Clamp(CPos cell) { return(Clamp(cell.ToMPos(this)).ToCPos(this)); }
public CPos Clamp(CPos cell) { var bounds = new Rectangle(Bounds.X, Bounds.Y, Bounds.Width - 1, Bounds.Height - 1); return(cell.ToMPos(this).Clamp(bounds).ToCPos(this)); }
void UpdateProjection(CPos cell) { MPos uv; if (Grid.MaximumTerrainHeight == 0) { uv = cell.ToMPos(Grid.Type); cellProjection[cell] = new[] { (PPos)uv }; var inverse = inverseCellProjection[uv]; inverse.Clear(); inverse.Add(uv); return; } if (!initializedCellProjection) InitializeCellProjection(); uv = cell.ToMPos(Grid.Type); // Remove old reverse projection foreach (var puv in cellProjection[uv]) { var temp = (MPos)puv; inverseCellProjection[temp].Remove(uv); projectedHeight[temp] = ProjectedCellHeightInner(puv); } var projected = ProjectCellInner(uv); cellProjection[uv] = projected; foreach (var puv in projected) { var temp = (MPos)puv; inverseCellProjection[temp].Add(uv); var height = ProjectedCellHeightInner(puv); projectedHeight[temp] = height; // Propagate height up cliff faces while (true) { temp = new MPos(temp.U, temp.V - 1); if (!inverseCellProjection.Contains(temp) || inverseCellProjection[temp].Any()) break; projectedHeight[temp] = height; } } }
public bool Contains(CPos cell) { return(Contains(cell.ToMPos(this))); }
public CPos ChooseClosestEdgeCell(CPos cell) { return ChooseClosestEdgeCell(cell.ToMPos(Grid.Type)).ToCPos(Grid.Type); }
public bool Contains(CPos cell) { return Contains(cell.ToMPos(this)); }
public byte GetTerrainIndex(CPos cell) { var uv = cell.ToMPos(this); var custom = CustomTerrain[uv]; return custom != byte.MaxValue ? custom : cachedTileSet.Value.GetTerrainIndex(MapTiles.Value[uv]); }
public CPos Clamp(CPos uv) { return(Clamp(uv.ToMPos(GridType)).ToCPos(GridType)); }
public CPos Clamp(CPos cell) { return Clamp(cell.ToMPos(this)).ToCPos(this); }
public bool Contains(CPos cell) { // .ToMPos() returns the same result if the X and Y coordinates // are switched. X < Y is invalid in the RectangularIsometric coordinate system, // so we pre-filter these to avoid returning the wrong result if (Grid.Type == MapGridType.RectangularIsometric && cell.X < cell.Y) return false; return Contains(cell.ToMPos(this)); }
public bool Contains(CPos cell) { // .ToMPos() returns the same result if the X and Y coordinates // are switched. X < Y is invalid in the Diamond coordinate system, // so we pre-filter these to avoid returning the wrong result if (TileShape == TileShape.Diamond && cell.X < cell.Y) return false; return Contains(cell.ToMPos(this)); }
// Resolve an array index from cell coordinates int Index(CPos cell) { return(Index(cell.ToMPos(Shape))); }
public CPos Clamp(CPos uv) { return(Clamp(uv.ToMPos(Shape)).ToCPos(Shape)); }
public byte GetTerrainIndex(CPos cell) { const short InvalidCachedTerrainIndex = -1; // Lazily initialize a cache for terrain indexes. if (cachedTerrainIndexes == null) { cachedTerrainIndexes = new CellLayer<short>(this); cachedTerrainIndexes.Clear(InvalidCachedTerrainIndex); // Invalidate the entry for a cell if anything could cause the terrain index to change. Action<CPos> invalidateTerrainIndex = c => cachedTerrainIndexes[c] = InvalidCachedTerrainIndex; CustomTerrain.CellEntryChanged += invalidateTerrainIndex; Tiles.CellEntryChanged += invalidateTerrainIndex; } var uv = cell.ToMPos(this); var terrainIndex = cachedTerrainIndexes[uv]; // PERF: Cache terrain indexes per cell on demand. if (terrainIndex == InvalidCachedTerrainIndex) { var custom = CustomTerrain[uv]; terrainIndex = cachedTerrainIndexes[uv] = custom != byte.MaxValue ? custom : Rules.TileSet.GetTerrainIndex(Tiles[uv]); } return (byte)terrainIndex; }
public CPos ChooseClosestEdgeCell(CPos pos) { var mpos = pos.ToMPos(this); var horizontalBound = ((mpos.U - Bounds.Left) < Bounds.Width / 2) ? Bounds.Left : Bounds.Right; var verticalBound = ((mpos.V - Bounds.Top) < Bounds.Height / 2) ? Bounds.Top : Bounds.Bottom; var distX = Math.Abs(horizontalBound - mpos.U); var distY = Math.Abs(verticalBound - mpos.V); return distX < distY ? new MPos(horizontalBound, mpos.V).ToCPos(this) : new MPos(mpos.U, verticalBound).ToCPos(this); }
public CPos Clamp(CPos cell) { var bounds = new Rectangle(Bounds.X, Bounds.Y, Bounds.Width - 1, Bounds.Height - 1); return cell.ToMPos(this).Clamp(bounds).ToCPos(this); }
// Resolve an array index from cell coordinates int Index(CPos cell) { return(Index(cell.ToMPos(GridType))); }
public CPos ChooseClosestEdgeCell(CPos cell) { return(ChooseClosestEdgeCell(cell.ToMPos(TileShape)).ToCPos(TileShape)); }