Recovered flood fill functionality from the old editor
This commit is contained in:
@@ -8,6 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
@@ -74,20 +76,36 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
if (!painting)
|
if (!painting)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (mi.Event != MouseInputEvent.Down && mi.Event != MouseInputEvent.Move)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
||||||
|
var isMoving = mi.Event == MouseInputEvent.Move;
|
||||||
|
|
||||||
|
if (mi.Modifiers.HasModifier(Modifiers.Shift))
|
||||||
|
{
|
||||||
|
FloodFillWithBrush(cell, isMoving);
|
||||||
|
painting = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PaintCell(cell, isMoving);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PaintCell(CPos cell, bool isMoving)
|
||||||
|
{
|
||||||
var map = world.Map;
|
var map = world.Map;
|
||||||
var mapTiles = map.MapTiles.Value;
|
var mapTiles = map.MapTiles.Value;
|
||||||
var mapHeight = map.MapHeight.Value;
|
var mapHeight = map.MapHeight.Value;
|
||||||
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
|
||||||
|
|
||||||
if (mi.Event != MouseInputEvent.Down && mi.Event != MouseInputEvent.Move)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
var rules = map.Rules;
|
var rules = map.Rules;
|
||||||
var tileset = rules.TileSets[map.Tileset];
|
var tileset = rules.TileSets[map.Tileset];
|
||||||
var template = tileset.Templates[Template];
|
var template = tileset.Templates[Template];
|
||||||
var baseHeight = mapHeight.Contains(cell) ? mapHeight[cell] : (byte)0;
|
var baseHeight = mapHeight.Contains(cell) ? mapHeight[cell] : (byte)0;
|
||||||
if (mi.Event == MouseInputEvent.Move && PlacementOverlapsSameTemplate(template, cell))
|
|
||||||
return true;
|
if (isMoving && PlacementOverlapsSameTemplate(template, cell))
|
||||||
|
return;
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
for (var y = 0; y < template.Size.Y; y++)
|
for (var y = 0; y < template.Size.Y; y++)
|
||||||
@@ -106,8 +124,80 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FloodFillWithBrush(CPos cell, bool isMoving)
|
||||||
|
{
|
||||||
|
var map = world.Map;
|
||||||
|
var mapTiles = map.MapTiles.Value;
|
||||||
|
var replace = mapTiles[cell];
|
||||||
|
|
||||||
|
if (replace.Type == Template)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var queue = new Queue<CPos>();
|
||||||
|
var touched = new bool[map.MapSize.X, map.MapSize.Y];
|
||||||
|
|
||||||
|
var rules = map.Rules;
|
||||||
|
var tileset = rules.TileSets[map.Tileset];
|
||||||
|
var template = tileset.Templates[Template];
|
||||||
|
|
||||||
|
Action<CPos> maybeEnqueue = (newCell) =>
|
||||||
|
{
|
||||||
|
if (map.Contains(cell) && !touched[newCell.X, newCell.Y])
|
||||||
|
{
|
||||||
|
queue.Enqueue(newCell);
|
||||||
|
touched[newCell.X, newCell.Y] = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Func<CPos, bool> shouldPaint = (cellToCheck) =>
|
||||||
|
{
|
||||||
|
for (var y = 0; y < template.Size.Y; y++)
|
||||||
|
{
|
||||||
|
for (var x = 0; x < template.Size.X; x++)
|
||||||
|
{
|
||||||
|
var c = cellToCheck + new CVec(x, y);
|
||||||
|
if (!map.Contains(c) || mapTiles[c].Type != replace.Type)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Func<CPos, CVec, CPos> findEdge = (refCell, direction) =>
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
var newCell = refCell + direction;
|
||||||
|
if (!shouldPaint(newCell))
|
||||||
|
return refCell;
|
||||||
|
refCell = newCell;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
queue.Enqueue(cell);
|
||||||
|
while (queue.Count > 0)
|
||||||
|
{
|
||||||
|
var queuedCell = queue.Dequeue();
|
||||||
|
if (!shouldPaint(queuedCell))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var previousCell = findEdge(queuedCell, new CVec(-1 * template.Size.X, 0));
|
||||||
|
var nextCell = findEdge(queuedCell, new CVec(1 * template.Size.X, 0));
|
||||||
|
|
||||||
|
for (var x = previousCell.X; x <= nextCell.X; x += template.Size.X)
|
||||||
|
{
|
||||||
|
PaintCell(new CPos(x, queuedCell.Y), isMoving);
|
||||||
|
var upperCell = new CPos(x, queuedCell.Y - (1 * template.Size.Y));
|
||||||
|
var lowerCell = new CPos(x, queuedCell.Y + (1 * template.Size.Y));
|
||||||
|
|
||||||
|
if (shouldPaint(upperCell))
|
||||||
|
maybeEnqueue(upperCell);
|
||||||
|
if (shouldPaint(lowerCell))
|
||||||
|
maybeEnqueue(lowerCell);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PlacementOverlapsSameTemplate(TerrainTemplateInfo template, CPos cell)
|
bool PlacementOverlapsSameTemplate(TerrainTemplateInfo template, CPos cell)
|
||||||
|
|||||||
Reference in New Issue
Block a user