diff --git a/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs b/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs index 0471818f36..8c282d2659 100644 --- a/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs +++ b/OpenRA.Mods.Common/EditorBrushes/EditorDefaultBrush.cs @@ -31,8 +31,8 @@ namespace OpenRA.Mods.Common.Widgets readonly World world; readonly EditorViewportControllerWidget editorWidget; readonly EditorActorLayer editorLayer; - readonly Dictionary resources; readonly EditorActionManager editorActionManager; + readonly IResourceLayer resourceLayer; public EditorActorPreview SelectedActor; int2 worldPixel; @@ -44,10 +44,8 @@ namespace OpenRA.Mods.Common.Widgets world = wr.World; editorLayer = world.WorldActor.Trait(); - resources = world.WorldActor.TraitsImplementing() - .ToDictionary(r => r.Info.ResourceType, r => r); - editorActionManager = world.WorldActor.Trait(); + resourceLayer = world.WorldActor.Trait(); } long CalculateActorSelectionPriority(EditorActorPreview actor) @@ -75,13 +73,12 @@ namespace OpenRA.Mods.Common.Widgets var cell = worldRenderer.Viewport.ViewToWorld(mi.Location); var underCursor = editorLayer.PreviewsAt(worldPixel).MinByOrDefault(CalculateActorSelectionPriority); + var resourceUnderCursor = resourceLayer.GetResource(cell).Type; - var mapResources = world.Map.Resources; - ResourceType type = null; if (underCursor != null) editorWidget.SetTooltip(underCursor.Tooltip); - else if (mapResources.Contains(cell) && resources.TryGetValue(mapResources[cell].Type, out type)) - editorWidget.SetTooltip(type.Info.Type); + else if (resourceUnderCursor != null) + editorWidget.SetTooltip(resourceUnderCursor.Info.Type); else editorWidget.SetTooltip(null); @@ -102,8 +99,8 @@ namespace OpenRA.Mods.Common.Widgets if (underCursor != null && underCursor != SelectedActor) editorActionManager.Add(new RemoveActorAction(editorLayer, underCursor)); - if (type != null && mapResources.Contains(cell) && mapResources[cell].Type != 0) - editorActionManager.Add(new RemoveResourceAction(mapResources, cell, type)); + if (resourceUnderCursor != null) + editorActionManager.Add(new RemoveResourceAction(resourceLayer, cell, resourceUnderCursor)); } return true; @@ -148,14 +145,14 @@ namespace OpenRA.Mods.Common.Widgets { public string Text { get; private set; } - readonly CellLayer mapResources; + readonly IResourceLayer resourceLayer; readonly CPos cell; - ResourceTile resourceTile; + ResourceLayerContents resourceContents; - public RemoveResourceAction(CellLayer mapResources, CPos cell, ResourceType type) + public RemoveResourceAction(IResourceLayer resourceLayer, CPos cell, ResourceType type) { - this.mapResources = mapResources; + this.resourceLayer = resourceLayer; this.cell = cell; Text = "Removed {0}".F(type.Info.TerrainType); @@ -168,13 +165,14 @@ namespace OpenRA.Mods.Common.Widgets public void Do() { - resourceTile = mapResources[cell]; - mapResources[cell] = default(ResourceTile); + resourceContents = resourceLayer.GetResource(cell); + resourceLayer.ClearResources(cell); } public void Undo() { - mapResources[cell] = resourceTile; + resourceLayer.ClearResources(cell); + resourceLayer.AddResource(resourceContents.Type, cell, resourceContents.Density); } } } diff --git a/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs b/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs index 525f83b726..b83766cb44 100644 --- a/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs +++ b/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs @@ -17,13 +17,14 @@ namespace OpenRA.Mods.Common.Widgets { public sealed class EditorResourceBrush : IEditorBrush { - public readonly ResourceTypeInfo ResourceType; + public readonly ResourceType ResourceType; readonly WorldRenderer worldRenderer; readonly World world; readonly EditorViewportControllerWidget editorWidget; readonly EditorActionManager editorActionManager; readonly EditorCursorLayer editorCursor; + readonly IResourceLayer resourceLayer; readonly int cursorToken; AddResourcesEditorAction action; @@ -37,9 +38,10 @@ namespace OpenRA.Mods.Common.Widgets world = wr.World; editorActionManager = world.WorldActor.Trait(); editorCursor = world.WorldActor.Trait(); - action = new AddResourcesEditorAction(world.Map, ResourceType); + resourceLayer = world.WorldActor.Trait(); + action = new AddResourcesEditorAction(world.Map, resourceLayer, resource); - cursorToken = editorCursor.SetResource(wr, resource); + cursorToken = editorCursor.SetResource(wr, resource.Info); } public bool HandleMouseInput(MouseInput mi) @@ -64,42 +66,21 @@ namespace OpenRA.Mods.Common.Widgets var cell = worldRenderer.Viewport.ViewToWorld(mi.Location); - if (mi.Button == MouseButton.Left && mi.Event != MouseInputEvent.Up && AllowResourceAt(cell)) + if (mi.Button == MouseButton.Left && mi.Event != MouseInputEvent.Up && resourceLayer.CanAddResource(ResourceType, cell)) { - var type = (byte)ResourceType.ResourceType; - var index = (byte)ResourceType.MaxDensity; - action.Add(new CellResource(cell, world.Map.Resources[cell], new ResourceTile(type, index))); + action.Add(new CellResource(cell, resourceLayer.GetResource(cell), ResourceType)); resourceAdded = true; } else if (resourceAdded && mi.Button == MouseButton.Left && mi.Event == MouseInputEvent.Up) { editorActionManager.Add(action); - action = new AddResourcesEditorAction(world.Map, ResourceType); + action = new AddResourcesEditorAction(world.Map, resourceLayer, ResourceType); resourceAdded = false; } return true; } - public bool AllowResourceAt(CPos cell) - { - var mapResources = world.Map.Resources; - if (!mapResources.Contains(cell)) - return false; - - var tile = world.Map.Tiles[cell]; - var tileInfo = world.Map.Rules.TerrainInfo.GetTerrainInfo(tile); - var terrainType = world.Map.Rules.TerrainInfo.TerrainTypes[tileInfo.TerrainType]; - - if (mapResources[cell].Type == ResourceType.ResourceType) - return false; - - if (!ResourceType.AllowedTerrainTypes.Contains(terrainType.Type)) - return false; - - return ResourceType.AllowOnRamps || tileInfo.RampType == 0; - } - public void Tick() { } public void Dispose() @@ -111,14 +92,14 @@ namespace OpenRA.Mods.Common.Widgets readonly struct CellResource { public readonly CPos Cell; - public readonly ResourceTile ResourceTile; - public readonly ResourceTile NewResourceTile; + public readonly ResourceLayerContents OldResourceTile; + public readonly ResourceType NewResourceType; - public CellResource(CPos cell, ResourceTile resourceTile, ResourceTile newResourceTile) + public CellResource(CPos cell, ResourceLayerContents oldResourceTile, ResourceType newResourceType) { Cell = cell; - ResourceTile = resourceTile; - NewResourceTile = newResourceTile; + OldResourceTile = oldResourceTile; + NewResourceType = newResourceType; } } @@ -127,12 +108,14 @@ namespace OpenRA.Mods.Common.Widgets public string Text { get; private set; } readonly Map map; - readonly ResourceTypeInfo resourceType; + readonly IResourceLayer resourceLayer; + readonly ResourceType resourceType; readonly List cellResources = new List(); - public AddResourcesEditorAction(Map map, ResourceTypeInfo resourceType) + public AddResourcesEditorAction(Map map, IResourceLayer resourceLayer, ResourceType resourceType) { this.map = map; + this.resourceLayer = resourceLayer; this.resourceType = resourceType; } @@ -143,27 +126,30 @@ namespace OpenRA.Mods.Common.Widgets public void Do() { foreach (var resourceCell in cellResources) - SetTile(resourceCell.Cell, resourceCell.NewResourceTile); - } - - void SetTile(CPos cell, ResourceTile tile) - { - map.Resources[cell] = tile; + { + resourceLayer.ClearResources(resourceCell.Cell); + resourceLayer.AddResource(resourceCell.NewResourceType, resourceCell.Cell, resourceCell.NewResourceType.Info.MaxDensity); + } } public void Undo() { foreach (var resourceCell in cellResources) - SetTile(resourceCell.Cell, resourceCell.ResourceTile); + { + resourceLayer.ClearResources(resourceCell.Cell); + if (resourceCell.OldResourceTile.Type != null) + resourceLayer.AddResource(resourceCell.OldResourceTile.Type, resourceCell.Cell, resourceCell.OldResourceTile.Density); + } } - public void Add(CellResource cellResource) + public void Add(CellResource resourceCell) { - SetTile(cellResource.Cell, cellResource.NewResourceTile); - cellResources.Add(cellResource); + resourceLayer.ClearResources(resourceCell.Cell); + resourceLayer.AddResource(resourceCell.NewResourceType, resourceCell.Cell, resourceCell.NewResourceType.Info.MaxDensity); + cellResources.Add(resourceCell); var cellText = cellResources.Count != 1 ? "cells" : "cell"; - Text = "Added {0} {1} of {2}".F(cellResources.Count, cellText, resourceType.TerrainType); + Text = "Added {0} {1} of {2}".F(cellResources.Count, cellText, resourceType.Info.TerrainType); } } } diff --git a/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs b/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs index 6c0f954b67..ee47d882c8 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorResourceLayer.cs @@ -146,7 +146,10 @@ namespace OpenRA.Mods.Common.Traits if (!mapResources.Contains(cell)) return false; - if (!rt.Info.AllowedTerrainTypes.Contains(Map.GetTerrainInfo(cell).Type)) + // Ignore custom terrain types when spawning resources in the editor + var terrainInfo = Map.Rules.TerrainInfo; + var terrainType = terrainInfo.TerrainTypes[terrainInfo.GetTerrainInfo(Map.Tiles[cell]).TerrainType].Type; + if (!rt.Info.AllowedTerrainTypes.Contains(terrainType)) return false; // TODO: Check against actors in the EditorActorLayer @@ -159,14 +162,13 @@ namespace OpenRA.Mods.Common.Traits if (!resources.Contains(cell)) return false; + // The editor allows the user to replace one resource type with another, so treat mismatching resource type as an empty cell var content = resources[cell]; - if (content.Type == 0) + if (content.Type != resourceType.Info.ResourceType) return amount <= resourceType.Info.MaxDensity && AllowResourceAt(resourceType, cell); - if (content.Type != resourceType.Info.ResourceType) - return false; - - return content.Index + amount <= resourceType.Info.MaxDensity; + var oldDensity = content.Type == resourceType.Info.ResourceType ? content.Index : 0; + return oldDensity + amount <= resourceType.Info.MaxDensity; } int AddResource(ResourceType resourceType, CPos cell, int amount = 1) @@ -175,11 +177,9 @@ namespace OpenRA.Mods.Common.Traits if (!resources.Contains(cell)) return 0; + // The editor allows the user to replace one resource type with another, so treat mismatching resource type as an empty cell var content = resources[cell]; - if (content.Type != 0 && content.Type != resourceType.Info.ResourceType) - return 0; - - var oldDensity = content.Index; + var oldDensity = content.Type == resourceType.Info.ResourceType ? content.Index : 0; var density = (byte)Math.Min(resourceType.Info.MaxDensity, oldDensity + amount); Map.Resources[cell] = new ResourceTile((byte)resourceType.Info.ResourceType, density);