diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index a5ad73eb5e..3d5cf4b459 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -646,8 +646,24 @@ namespace OpenRA public byte[] SavePreview() { var tileset = Rules.TileSet; - var resources = Rules.Actors["world"].TraitInfos() - .ToDictionary(r => r.ResourceType, r => r.TerrainType); + var actorTypes = Rules.Actors.Values.Where(a => a.HasTraitInfo()); + var actors = ActorDefinitions.Where(a => actorTypes.Where(ai => ai.Name == a.Value.Value).Any()); + var positions = new List>(); + foreach (var actor in actors) + { + var s = new ActorReference(actor.Value.Value, actor.Value.ToDictionary()); + + var ai = Rules.Actors[actor.Value.Value]; + var impsis = ai.TraitInfos(); + foreach (var impsi in impsis) + impsi.PopulateMapPreviewSignatureCells(this, ai, s, positions); + } + + // ResourceLayer is on world actor, which isn't caught above, so an extra check for it. + var worldActorInfo = Rules.Actors["world"]; + var worldimpsis = worldActorInfo.TraitInfos(); + foreach (var worldimpsi in worldimpsis) + worldimpsi.PopulateMapPreviewSignatureCells(this, worldActorInfo, null, positions); using (var stream = new MemoryStream()) { @@ -672,15 +688,10 @@ namespace OpenRA for (var x = 0; x < width; x++) { var uv = new MPos(x + Bounds.Left, y + Bounds.Top); - var resourceType = Resources[uv].Type; - if (resourceType != 0) + var actorsThere = positions.Where(ap => ap.First == uv); + if (actorsThere.Any()) { - // Cell contains resources - string res; - if (!resources.TryGetValue(resourceType, out res)) - continue; - - leftColor = rightColor = tileset[tileset.GetTerrainIndex(res)].Color; + leftColor = rightColor = actorsThere.First().Second; } else { diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index ebe19e6bd2..626cefa408 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -181,7 +181,6 @@ - diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index a9a7e00c93..d1f9df8fc1 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -287,6 +287,11 @@ namespace OpenRA.Traits public interface ISelectionDecorations { void DrawRollover(Actor self, WorldRenderer worldRenderer); } + public interface IMapPreviewSignatureInfo : ITraitInfoInterface + { + void PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List> destinationBuffer); + } + public interface IOccupySpaceInfo : ITraitInfoInterface { IReadOnlyDictionary OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any); diff --git a/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs b/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs index 0794c27196..a5a8847cc7 100644 --- a/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs +++ b/OpenRA.Mods.Common/EditorBrushes/EditorResourceBrush.cs @@ -11,7 +11,7 @@ using System.Linq; using OpenRA.Graphics; -using OpenRA.Traits; +using OpenRA.Mods.Common.Traits; namespace OpenRA.Mods.Common.Widgets { diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 38b8def78d..7a2daf08fb 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -280,6 +280,7 @@ + @@ -565,6 +566,7 @@ + diff --git a/OpenRA.Mods.Common/Traits/AppearsOnMapPreview.cs b/OpenRA.Mods.Common/Traits/AppearsOnMapPreview.cs new file mode 100644 index 0000000000..cc3ca64d19 --- /dev/null +++ b/OpenRA.Mods.Common/Traits/AppearsOnMapPreview.cs @@ -0,0 +1,59 @@ +#region Copyright & License Information +/* + * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; +using OpenRA.Graphics; +using OpenRA.Primitives; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Traits +{ + [Desc("Render this actor when creating the minimap while saving the map.")] + public class AppearsOnMapPreviewInfo : TraitInfo, IMapPreviewSignatureInfo, Requires + { + [Desc("Use this color to render the actor, instead of owner player color.")] + public readonly Color Color = new Color(); + + [Desc("Use this terrain color to render the actor, instead of owner player color.", + "Overrides `Color` if both set.")] + public readonly string Terrain = null; + + void IMapPreviewSignatureInfo.PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List> destinationBuffer) + { + var tileSet = map.Rules.TileSet; + + Color color; + if (!string.IsNullOrEmpty(Terrain)) + { + color = tileSet[tileSet.GetTerrainIndex(Terrain)].Color; + } + else if (Color != new Color()) + { + color = Color; + } + else + { + var owner = map.PlayerDefinitions.Where(p => s.InitDict.Get().PlayerName == p.Value.Nodes.First(k => k.Key == "Name").Value.Value).First(); + var colorValue = owner.Value.Nodes.Where(n => n.Key == "Color"); + var ownerColor = colorValue.Any() ? colorValue.First().Value.Value : "FFFFFF"; + Color.TryParse(ownerColor, out color); + } + + var ios = ai.TraitInfo(); + var cells = ios.OccupiedCells(ai, s.InitDict.Get().Value(null)); + foreach (var cell in cells) + destinationBuffer.Add(new Pair(cell.Key.ToMPos(map), color)); + } + } + + public class AppearsOnMapPreview { } +} diff --git a/OpenRA.Game/Traits/World/ResourceType.cs b/OpenRA.Mods.Common/Traits/World/ResourceType.cs similarity index 80% rename from OpenRA.Game/Traits/World/ResourceType.cs rename to OpenRA.Mods.Common/Traits/World/ResourceType.cs index 6e8b26f392..1cf5417138 100644 --- a/OpenRA.Game/Traits/World/ResourceType.cs +++ b/OpenRA.Mods.Common/Traits/World/ResourceType.cs @@ -11,10 +11,12 @@ using System.Collections.Generic; using OpenRA.Graphics; +using OpenRA.Primitives; +using OpenRA.Traits; -namespace OpenRA.Traits +namespace OpenRA.Mods.Common.Traits { - public class ResourceTypeInfo : ITraitInfo + public class ResourceTypeInfo : ITraitInfo, IMapPreviewSignatureInfo { [Desc("Sequence image that holds the different variants.")] public readonly string Image = "resources"; @@ -64,6 +66,22 @@ namespace OpenRA.Traits [Desc("Harvester content pip color.")] public PipType PipColor = PipType.Yellow; + void IMapPreviewSignatureInfo.PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List> destinationBuffer) + { + var tileSet = map.Rules.TileSet; + var color = tileSet[tileSet.GetTerrainIndex(TerrainType)].Color; + + for (var i = 0; i < map.MapSize.X; i++) + { + for (var j = 0; j < map.MapSize.Y; j++) + { + var cell = new MPos(i, j); + if (map.Resources[cell].Type == ResourceType) + destinationBuffer.Add(new Pair(cell, color)); + } + } + } + public object Create(ActorInitializer init) { return new ResourceType(this, init.World); } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs index 87a78f9955..ed28e5537d 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/LayerSelectorLogic.cs @@ -11,7 +11,7 @@ using System.Linq; using OpenRA.Graphics; -using OpenRA.Traits; +using OpenRA.Mods.Common.Traits; using OpenRA.Widgets; namespace OpenRA.Mods.Common.Widgets.Logic