Improve performance of copy-paste in map editor.
- EditorActorLayer now tracks previews on map with a SpatiallyPartitioned instead of a Dictionary. This allows the copy-paste logic to call an efficient PreviewsInCellRegion method, instead of asking for previews cell-by-cell. - EditorActorPreview subscribes to the CellEntryChanged methods on the map. Previously the preview was refreshed regardless of which cell changed. Now the preview only regenerates if the preview's footprint has been affected.
This commit is contained in:
@@ -64,6 +64,11 @@ namespace OpenRA
|
|||||||
BottomRight = bottomRight;
|
BottomRight = bottomRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool Contains(CPos cell)
|
||||||
|
{
|
||||||
|
return cell.X >= TopLeft.X && cell.X <= BottomRight.X && cell.Y >= TopLeft.Y && cell.Y <= BottomRight.Y;
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{TopLeft}->{BottomRight}";
|
return $"{TopLeft}->{BottomRight}";
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Cell is automatically valid if it contains a veinhole actor
|
// Cell is automatically valid if it contains a veinhole actor
|
||||||
if (actorLayer.PreviewsAt(neighbour).Any(a => info.VeinholeActors.Contains(a.Info.Name)))
|
if (actorLayer.PreviewsAtCell(neighbour).Any(a => info.VeinholeActors.Contains(a.Info.Name)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Neighbour must be flat or a cardinal slope, unless the resource cell itself is a slope
|
// Neighbour must be flat or a cardinal slope, unless the resource cell itself is a slope
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
tiles.Add(cell, new ClipboardTile(mapTiles[cell], mapResources[cell], resourceLayerContents, mapHeight[cell]));
|
tiles.Add(cell, new ClipboardTile(mapTiles[cell], mapResources[cell], resourceLayerContents, mapHeight[cell]));
|
||||||
|
|
||||||
if (copyFilters.HasFlag(MapCopyFilters.Actors))
|
if (copyFilters.HasFlag(MapCopyFilters.Actors))
|
||||||
foreach (var preview in selection.CellCoords.SelectMany(editorActorLayer.PreviewsAt).Distinct())
|
foreach (var preview in editorActorLayer.PreviewsInCellRegion(selection.CellCoords))
|
||||||
previews.TryAdd(preview.ID, preview);
|
previews.TryAdd(preview.ID, preview);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
// Clear any existing actors in the paste cells.
|
// Clear any existing actors in the paste cells.
|
||||||
var selectionSize = clipboard.CellRegion.BottomRight - clipboard.CellRegion.TopLeft;
|
var selectionSize = clipboard.CellRegion.BottomRight - clipboard.CellRegion.TopLeft;
|
||||||
var pasteRegion = new CellRegion(map.Grid.Type, pastePosition, pastePosition + selectionSize);
|
var pasteRegion = new CellRegion(map.Grid.Type, pastePosition, pastePosition + selectionSize);
|
||||||
foreach (var regionActor in pasteRegion.CellCoords.SelectMany(editorActorLayer.PreviewsAt).ToHashSet())
|
foreach (var regionActor in editorActorLayer.PreviewsInCellRegion(pasteRegion.CellCoords).ToList())
|
||||||
editorActorLayer.Remove(regionActor);
|
editorActorLayer.Remove(regionActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
if (copyFilters.HasFlag(MapCopyFilters.Actors))
|
if (copyFilters.HasFlag(MapCopyFilters.Actors))
|
||||||
{
|
{
|
||||||
// Clear existing actors.
|
// Clear existing actors.
|
||||||
foreach (var regionActor in undoClipboard.CellRegion.CellCoords.SelectMany(editorActorLayer.PreviewsAt).Distinct().ToList())
|
foreach (var regionActor in editorActorLayer.PreviewsInCellRegion(undoClipboard.CellRegion.CellCoords).ToList())
|
||||||
editorActorLayer.Remove(regionActor);
|
editorActorLayer.Remove(regionActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
worldPixel = worldRenderer.Viewport.ViewToWorldPx(mi.Location);
|
worldPixel = worldRenderer.Viewport.ViewToWorldPx(mi.Location);
|
||||||
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
var cell = worldRenderer.Viewport.ViewToWorld(mi.Location);
|
||||||
|
|
||||||
var underCursor = editorLayer.PreviewsAt(worldPixel).MinByOrDefault(CalculateActorSelectionPriority);
|
var underCursor = editorLayer.PreviewsAtWorldPixel(worldPixel).MinByOrDefault(CalculateActorSelectionPriority);
|
||||||
var resourceUnderCursor = resourceLayer?.GetResource(cell).Type;
|
var resourceUnderCursor = resourceLayer?.GetResource(cell).Type;
|
||||||
|
|
||||||
if (underCursor != null)
|
if (underCursor != null)
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
readonly EditorActorLayerInfo info;
|
readonly EditorActorLayerInfo info;
|
||||||
readonly List<EditorActorPreview> previews = new();
|
readonly List<EditorActorPreview> previews = new();
|
||||||
readonly Dictionary<CPos, List<EditorActorPreview>> cellMap = new();
|
|
||||||
|
|
||||||
|
int2 cellOffset;
|
||||||
|
SpatiallyPartitioned<EditorActorPreview> cellMap;
|
||||||
SpatiallyPartitioned<EditorActorPreview> screenMap;
|
SpatiallyPartitioned<EditorActorPreview> screenMap;
|
||||||
WorldRenderer worldRenderer;
|
WorldRenderer worldRenderer;
|
||||||
|
|
||||||
@@ -74,6 +75,12 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
foreach (var pr in Players.Players.Values)
|
foreach (var pr in Players.Players.Values)
|
||||||
wr.UpdatePalettesForPlayer(pr.Name, pr.Color, false);
|
wr.UpdatePalettesForPlayer(pr.Name, pr.Color, false);
|
||||||
|
|
||||||
|
cellOffset = new int2(world.Map.AllCells.Min(c => c.X), world.Map.AllCells.Min((c) => c.Y));
|
||||||
|
var cellOffsetMax = new int2(world.Map.AllCells.Max(c => c.X), world.Map.AllCells.Max((c) => c.Y));
|
||||||
|
var mapCellSize = cellOffsetMax - cellOffset;
|
||||||
|
cellMap = new SpatiallyPartitioned<EditorActorPreview>(
|
||||||
|
mapCellSize.X, mapCellSize.Y, Exts.IntegerDivisionRoundingAwayFromZero(info.BinSize, world.Map.Grid.TileSize.Width));
|
||||||
|
|
||||||
var ts = world.Map.Grid.TileSize;
|
var ts = world.Map.Grid.TileSize;
|
||||||
var width = world.Map.MapSize.X * ts.Width;
|
var width = world.Map.MapSize.X * ts.Width;
|
||||||
var height = world.Map.MapSize.Y * ts.Height;
|
var height = world.Map.MapSize.Y * ts.Height;
|
||||||
@@ -102,7 +109,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (wr.World.Type != WorldType.Editor)
|
if (wr.World.Type != WorldType.Editor)
|
||||||
return NoRenderables;
|
return NoRenderables;
|
||||||
|
|
||||||
return PreviewsInBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight)
|
return PreviewsInScreenBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight)
|
||||||
.SelectMany(p => p.Render());
|
.SelectMany(p => p.Render());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +124,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (wr.World.Type != WorldType.Editor)
|
if (wr.World.Type != WorldType.Editor)
|
||||||
return NoRenderables;
|
return NoRenderables;
|
||||||
|
|
||||||
return PreviewsInBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight)
|
return PreviewsInScreenBox(wr.Viewport.TopLeft, wr.Viewport.BottomRight)
|
||||||
.SelectMany(p => p.RenderAnnotations());
|
.SelectMany(p => p.RenderAnnotations());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,13 +154,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (!preview.Bounds.IsEmpty)
|
if (!preview.Bounds.IsEmpty)
|
||||||
screenMap.Add(preview, preview.Bounds);
|
screenMap.Add(preview, preview.Bounds);
|
||||||
|
|
||||||
// Fallback to the actor's CenterPosition for the ActorMap if it has no Footprint
|
var cellFootprintBounds = Footprint(preview).Select(
|
||||||
var footprint = preview.Footprint.Select(kv => kv.Key).ToArray();
|
cell => new Rectangle(cell.X - cellOffset.X, cell.Y - cellOffset.Y, 1, 1)).Union();
|
||||||
if (footprint.Length == 0)
|
cellMap.Add(preview, cellFootprintBounds);
|
||||||
footprint = new[] { worldRenderer.World.Map.CellContaining(preview.CenterPosition) };
|
|
||||||
|
|
||||||
foreach (var cell in footprint)
|
|
||||||
AddPreviewLocation(preview, cell);
|
|
||||||
|
|
||||||
preview.AddedToEditor();
|
preview.AddedToEditor();
|
||||||
|
|
||||||
@@ -166,26 +169,20 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IEnumerable<CPos> Footprint(EditorActorPreview preview)
|
||||||
|
{
|
||||||
|
// Fallback to the actor's CenterPosition for the ActorMap if it has no Footprint
|
||||||
|
if (preview.Footprint.Count == 0)
|
||||||
|
return new[] { worldRenderer.World.Map.CellContaining(preview.CenterPosition) };
|
||||||
|
return preview.Footprint.Keys;
|
||||||
|
}
|
||||||
|
|
||||||
public void Remove(EditorActorPreview preview)
|
public void Remove(EditorActorPreview preview)
|
||||||
{
|
{
|
||||||
previews.Remove(preview);
|
previews.Remove(preview);
|
||||||
screenMap.Remove(preview);
|
screenMap.Remove(preview);
|
||||||
|
|
||||||
// Fallback to the actor's CenterPosition for the ActorMap if it has no Footprint
|
cellMap.Remove(preview);
|
||||||
var footprint = preview.Footprint.Select(kv => kv.Key).ToArray();
|
|
||||||
if (footprint.Length == 0)
|
|
||||||
footprint = new[] { worldRenderer.World.Map.CellContaining(preview.CenterPosition) };
|
|
||||||
|
|
||||||
foreach (var cell in footprint)
|
|
||||||
{
|
|
||||||
if (!cellMap.TryGetValue(cell, out var list))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
list.Remove(preview);
|
|
||||||
|
|
||||||
if (list.Count == 0)
|
|
||||||
cellMap.Remove(cell);
|
|
||||||
}
|
|
||||||
|
|
||||||
preview.RemovedFromEditor();
|
preview.RemovedFromEditor();
|
||||||
UpdateNeighbours(preview.Footprint);
|
UpdateNeighbours(preview.Footprint);
|
||||||
@@ -236,49 +233,46 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
// Include actors inside the footprint too
|
// Include actors inside the footprint too
|
||||||
var cells = Util.ExpandFootprint(footprint.Keys, true);
|
var cells = Util.ExpandFootprint(footprint.Keys, true);
|
||||||
foreach (var p in cells.SelectMany(c => PreviewsAt(c)))
|
foreach (var p in cells.SelectMany(PreviewsAtCell))
|
||||||
p.ReplaceInit(new RuntimeNeighbourInit(NeighbouringPreviews(p.Footprint)));
|
p.ReplaceInit(new RuntimeNeighbourInit(NeighbouringPreviews(p.Footprint)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPreviewLocation(EditorActorPreview preview, CPos location)
|
|
||||||
{
|
|
||||||
if (!cellMap.TryGetValue(location, out var list))
|
|
||||||
{
|
|
||||||
list = new List<EditorActorPreview>();
|
|
||||||
cellMap.Add(location, list);
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Add(preview);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary<CPos, string[]> NeighbouringPreviews(IReadOnlyDictionary<CPos, SubCell> footprint)
|
Dictionary<CPos, string[]> NeighbouringPreviews(IReadOnlyDictionary<CPos, SubCell> footprint)
|
||||||
{
|
{
|
||||||
var cells = Util.ExpandFootprint(footprint.Keys, true).Except(footprint.Keys);
|
var cells = Util.ExpandFootprint(footprint.Keys, true).Except(footprint.Keys);
|
||||||
return cells.ToDictionary(c => c, c => PreviewsAt(c).Select(p => p.Info.Name).ToArray());
|
return cells.ToDictionary(c => c, c => PreviewsAtCell(c).Select(p => p.Info.Name).ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<EditorActorPreview> PreviewsInBox(int2 a, int2 b)
|
public IEnumerable<EditorActorPreview> PreviewsInScreenBox(int2 a, int2 b)
|
||||||
{
|
{
|
||||||
return screenMap.InBox(Rectangle.FromLTRB(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y), Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)));
|
return PreviewsInScreenBox(Rectangle.FromLTRB(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y), Math.Max(a.X, b.X), Math.Max(a.Y, b.Y)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<EditorActorPreview> PreviewsInBox(Rectangle r)
|
public IEnumerable<EditorActorPreview> PreviewsInScreenBox(Rectangle r)
|
||||||
{
|
{
|
||||||
return screenMap.InBox(r);
|
return screenMap.InBox(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<EditorActorPreview> PreviewsAt(CPos cell)
|
public IEnumerable<EditorActorPreview> PreviewsInCellRegion(CellCoordsRegion region)
|
||||||
{
|
{
|
||||||
if (cellMap.TryGetValue(cell, out var list))
|
return cellMap.InBox(Rectangle.FromLTRB(
|
||||||
return list;
|
region.TopLeft.X - cellOffset.X,
|
||||||
|
region.TopLeft.Y - cellOffset.Y,
|
||||||
|
region.BottomRight.X - cellOffset.X + 1,
|
||||||
|
region.BottomRight.Y - cellOffset.Y + 1))
|
||||||
|
.Where(p => Footprint(p).Any(region.Contains));
|
||||||
|
}
|
||||||
|
|
||||||
return Enumerable.Empty<EditorActorPreview>();
|
public IEnumerable<EditorActorPreview> PreviewsAtCell(CPos cell)
|
||||||
|
{
|
||||||
|
return cellMap.At(new int2(cell.X - cellOffset.X, cell.Y - cellOffset.Y))
|
||||||
|
.Where(p => Footprint(p).Any(fp => fp == cell));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubCell FreeSubCellAt(CPos cell)
|
public SubCell FreeSubCellAt(CPos cell)
|
||||||
{
|
{
|
||||||
var map = worldRenderer.World.Map;
|
var map = worldRenderer.World.Map;
|
||||||
var previews = PreviewsAt(cell).ToList();
|
var previews = PreviewsAtCell(cell).ToList();
|
||||||
if (previews.Count == 0)
|
if (previews.Count == 0)
|
||||||
return map.Grid.DefaultSubCell;
|
return map.Grid.DefaultSubCell;
|
||||||
|
|
||||||
@@ -293,7 +287,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return SubCell.Invalid;
|
return SubCell.Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<EditorActorPreview> PreviewsAt(int2 worldPx)
|
public IEnumerable<EditorActorPreview> PreviewsAtWorldPixel(int2 worldPx)
|
||||||
{
|
{
|
||||||
return screenMap.At(worldPx);
|
return screenMap.At(worldPx);
|
||||||
}
|
}
|
||||||
@@ -325,9 +319,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public void PopulateRadarSignatureCells(Actor self, List<(CPos Cell, Color Color)> destinationBuffer)
|
public void PopulateRadarSignatureCells(Actor self, List<(CPos Cell, Color Color)> destinationBuffer)
|
||||||
{
|
{
|
||||||
foreach (var previewsForCell in cellMap)
|
foreach (var preview in cellMap.Items)
|
||||||
foreach (var preview in previewsForCell.Value)
|
foreach (var cell in Footprint(preview))
|
||||||
destinationBuffer.Add((previewsForCell.Key, preview.RadarColor));
|
destinationBuffer.Add((cell, preview.RadarColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
public EditorActorPreview this[string id]
|
public EditorActorPreview this[string id]
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (!world.Map.Rules.Actors.TryGetValue(reference.Type.ToLowerInvariant(), out Info))
|
if (!world.Map.Rules.Actors.TryGetValue(reference.Type.ToLowerInvariant(), out Info))
|
||||||
throw new InvalidDataException($"Actor {id} of unknown type {reference.Type.ToLowerInvariant()}");
|
throw new InvalidDataException($"Actor {id} of unknown type {reference.Type.ToLowerInvariant()}");
|
||||||
|
|
||||||
UpdateFromCellChange();
|
|
||||||
GenerateFootprint();
|
GenerateFootprint();
|
||||||
|
UpdateFromCellChange(null);
|
||||||
|
|
||||||
tooltip = Info.TraitInfos<EditorOnlyTooltipInfo>().FirstOrDefault(info => info.EnabledByDefault) as TooltipInfoBase
|
tooltip = Info.TraitInfos<EditorOnlyTooltipInfo>().FirstOrDefault(info => info.EnabledByDefault) as TooltipInfoBase
|
||||||
?? Info.TraitInfos<TooltipInfo>().FirstOrDefault(info => info.EnabledByDefault);
|
?? Info.TraitInfos<TooltipInfo>().FirstOrDefault(info => info.EnabledByDefault);
|
||||||
@@ -79,8 +79,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
terrainRadarColorInfo = Info.TraitInfoOrDefault<RadarColorFromTerrainInfo>();
|
terrainRadarColorInfo = Info.TraitInfoOrDefault<RadarColorFromTerrainInfo>();
|
||||||
UpdateRadarColor();
|
UpdateRadarColor();
|
||||||
|
|
||||||
// TODO: updating all actors on the map is not very efficient.
|
onCellEntryChanged = cell => UpdateFromCellChange(cell);
|
||||||
onCellEntryChanged = _ => UpdateFromCellChange();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EditorActorPreview WithId(string id)
|
public EditorActorPreview WithId(string id)
|
||||||
@@ -88,8 +87,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return new EditorActorPreview(worldRenderer, id, reference.Clone(), Owner);
|
return new EditorActorPreview(worldRenderer, id, reference.Clone(), Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateFromCellChange()
|
void UpdateFromCellChange(CPos? cellChanged)
|
||||||
{
|
{
|
||||||
|
if (cellChanged != null && !Footprint.ContainsKey(cellChanged.Value))
|
||||||
|
return;
|
||||||
|
|
||||||
CenterPosition = PreviewPosition(worldRenderer.World, reference);
|
CenterPosition = PreviewPosition(worldRenderer.World, reference);
|
||||||
GeneratePreviews();
|
GeneratePreviews();
|
||||||
GenerateBounds();
|
GenerateBounds();
|
||||||
@@ -169,8 +171,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
foreach (var notify in Info.TraitInfos<INotifyEditorPlacementInfo>())
|
foreach (var notify in Info.TraitInfos<INotifyEditorPlacementInfo>())
|
||||||
editorData[notify] = notify.AddedToEditor(this, worldRenderer.World);
|
editorData[notify] = notify.AddedToEditor(this, worldRenderer.World);
|
||||||
|
|
||||||
// TODO: this should subscribe to ramp cell map as well.
|
|
||||||
worldRenderer.World.Map.Height.CellEntryChanged += onCellEntryChanged;
|
worldRenderer.World.Map.Height.CellEntryChanged += onCellEntryChanged;
|
||||||
|
worldRenderer.World.Map.Ramp.CellEntryChanged += onCellEntryChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemovedFromEditor()
|
public void RemovedFromEditor()
|
||||||
@@ -179,6 +181,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
kv.Key.RemovedFromEditor(this, worldRenderer.World, kv.Value);
|
kv.Key.RemovedFromEditor(this, worldRenderer.World, kv.Value);
|
||||||
|
|
||||||
worldRenderer.World.Map.Height.CellEntryChanged -= onCellEntryChanged;
|
worldRenderer.World.Map.Height.CellEntryChanged -= onCellEntryChanged;
|
||||||
|
worldRenderer.World.Map.Ramp.CellEntryChanged -= onCellEntryChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddInit<T>(T init) where T : ActorInit
|
public void AddInit<T>(T init) where T : ActorInit
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.EditorBrushes;
|
using OpenRA.Mods.Common.EditorBrushes;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
@@ -123,7 +122,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
tiles.Add(cell, new ClipboardTile(mapTiles[cell], mapResources[cell], resourceLayer?.GetResource(cell), mapHeight[cell]));
|
tiles.Add(cell, new ClipboardTile(mapTiles[cell], mapResources[cell], resourceLayer?.GetResource(cell), mapHeight[cell]));
|
||||||
|
|
||||||
if (copyFilters.HasFlag(MapCopyFilters.Actors))
|
if (copyFilters.HasFlag(MapCopyFilters.Actors))
|
||||||
foreach (var preview in selection.CellCoords.SelectMany(editorActorLayer.PreviewsAt).Distinct())
|
foreach (var preview in editorActorLayer.PreviewsInCellRegion(selection.CellCoords))
|
||||||
previews.TryAdd(preview.ID, preview);
|
previews.TryAdd(preview.ID, preview);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user