Replace Map.CustomTerrain radar colors with IRadarTerrainLayer.
* TSVeinsRenderer now shows border cells on the radar * BuildableTerrainLayer now uses the radar colors defined on the individual tiles * CliffBackImpassabilityLayer no longer overrides the underlying terrain color.
This commit is contained in:
@@ -675,16 +675,10 @@ namespace OpenRA
|
|||||||
|
|
||||||
public (Color Left, Color Right) GetTerrainColorPair(MPos uv)
|
public (Color Left, Color Right) GetTerrainColorPair(MPos uv)
|
||||||
{
|
{
|
||||||
Color left, right;
|
|
||||||
var terrainInfo = Rules.TerrainInfo;
|
var terrainInfo = Rules.TerrainInfo;
|
||||||
var type = terrainInfo.GetTerrainInfo(Tiles[uv]);
|
var type = terrainInfo.GetTerrainInfo(Tiles[uv]);
|
||||||
if (type.MinColor != type.MaxColor)
|
var left = type.GetColor(Game.CosmeticRandom);
|
||||||
{
|
var right = type.GetColor(Game.CosmeticRandom);
|
||||||
left = Exts.ColorLerp(Game.CosmeticRandom.NextFloat(), type.MinColor, type.MaxColor);
|
|
||||||
right = Exts.ColorLerp(Game.CosmeticRandom.NextFloat(), type.MinColor, type.MaxColor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
left = right = type.MinColor;
|
|
||||||
|
|
||||||
if (terrainInfo.MinHeightColorBrightness != 1.0f || terrainInfo.MaxHeightColorBrightness != 1.0f)
|
if (terrainInfo.MinHeightColorBrightness != 1.0f || terrainInfo.MaxHeightColorBrightness != 1.0f)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using OpenRA.FileSystem;
|
using OpenRA.FileSystem;
|
||||||
using OpenRA.Primitives;
|
using OpenRA.Primitives;
|
||||||
|
using OpenRA.Support;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA
|
namespace OpenRA
|
||||||
@@ -45,6 +46,14 @@ namespace OpenRA
|
|||||||
public readonly byte RampType;
|
public readonly byte RampType;
|
||||||
public readonly Color MinColor;
|
public readonly Color MinColor;
|
||||||
public readonly Color MaxColor;
|
public readonly Color MaxColor;
|
||||||
|
|
||||||
|
public Color GetColor(MersenneTwister random)
|
||||||
|
{
|
||||||
|
if (MinColor != MaxColor)
|
||||||
|
return Exts.ColorLerp(random.NextFloat(), MinColor, MaxColor);
|
||||||
|
|
||||||
|
return MinColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TerrainTypeInfo
|
public class TerrainTypeInfo
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Mods.Common;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Primitives;
|
using OpenRA.Primitives;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
@@ -20,7 +21,7 @@ using OpenRA.Traits;
|
|||||||
namespace OpenRA.Mods.Cnc.Traits
|
namespace OpenRA.Mods.Cnc.Traits
|
||||||
{
|
{
|
||||||
[Desc("Renders the Tiberian Sun Vein resources.", "Attach this to the world actor")]
|
[Desc("Renders the Tiberian Sun Vein resources.", "Attach this to the world actor")]
|
||||||
public class TSVeinsRendererInfo : TraitInfo, Requires<IResourceLayerInfo>
|
public class TSVeinsRendererInfo : TraitInfo, Requires<IResourceLayerInfo>, IMapPreviewSignatureInfo
|
||||||
{
|
{
|
||||||
[FieldLoader.Require]
|
[FieldLoader.Require]
|
||||||
[Desc("Resource type used for veins.")]
|
[Desc("Resource type used for veins.")]
|
||||||
@@ -45,10 +46,69 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
[Desc("Actor types that should be treated as veins for adjacency.")]
|
[Desc("Actor types that should be treated as veins for adjacency.")]
|
||||||
public readonly HashSet<string> VeinholeActors = new HashSet<string> { };
|
public readonly HashSet<string> VeinholeActors = new HashSet<string> { };
|
||||||
|
|
||||||
|
void IMapPreviewSignatureInfo.PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<(MPos, Color)> destinationBuffer)
|
||||||
|
{
|
||||||
|
var resourceLayer = ai.TraitInfoOrDefault<IResourceLayerInfo>();
|
||||||
|
if (resourceLayer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!resourceLayer.TryGetResourceIndex(ResourceType, out var resourceIndex) || !resourceLayer.TryGetTerrainType(ResourceType, out var terrainType))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var veinholeCells = new HashSet<CPos>();
|
||||||
|
|
||||||
|
foreach (var kv in map.ActorDefinitions)
|
||||||
|
{
|
||||||
|
var type = kv.Value.Value;
|
||||||
|
if (!VeinholeActors.Contains(type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var actorReference = new ActorReference(type, kv.Value.ToDictionary());
|
||||||
|
var location = actorReference.Get<LocationInit>();
|
||||||
|
var veinholeInfo = map.Rules.Actors[actorReference.Type];
|
||||||
|
foreach (var cell in veinholeInfo.TraitInfo<IOccupySpaceInfo>().OccupiedCells(veinholeInfo, location.Value))
|
||||||
|
veinholeCells.Add(cell.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
var terrainInfo = map.Rules.TerrainInfo;
|
||||||
|
var info = terrainInfo.TerrainTypes[terrainInfo.GetTerrainIndex(terrainType)];
|
||||||
|
|
||||||
|
for (var i = 0; i < map.MapSize.X; i++)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < map.MapSize.Y; j++)
|
||||||
|
{
|
||||||
|
var uv = new MPos(i, j);
|
||||||
|
|
||||||
|
// Cell contains veins
|
||||||
|
if (map.Resources[uv].Type == resourceIndex)
|
||||||
|
{
|
||||||
|
destinationBuffer.Add((uv, info.Color));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cell is a vein border if it is flat and adjacent to at least one cell
|
||||||
|
// that is also flat and contains veins (borders are not drawn next to slope vein cells)
|
||||||
|
var isBorder = map.Ramp[uv] == 0 && Common.Util.ExpandFootprint(uv.ToCPos(map), false).Any(c =>
|
||||||
|
{
|
||||||
|
if (!map.Resources.Contains(c))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (veinholeCells.Contains(c))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return map.Resources[c].Type == resourceIndex && map.Ramp[c] == 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isBorder)
|
||||||
|
destinationBuffer.Add((uv, info.Color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new TSVeinsRenderer(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new TSVeinsRenderer(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TSVeinsRenderer : IResourceRenderer, IWorldLoaded, IRenderOverlay, ITickRender, INotifyActorDisposing
|
public class TSVeinsRenderer : IResourceRenderer, IWorldLoaded, IRenderOverlay, ITickRender, INotifyActorDisposing, IRadarTerrainLayer
|
||||||
{
|
{
|
||||||
[Flags]
|
[Flags]
|
||||||
enum Adjacency : byte
|
enum Adjacency : byte
|
||||||
@@ -95,6 +155,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
readonly Queue<CPos> cleanDirty = new Queue<CPos>();
|
readonly Queue<CPos> cleanDirty = new Queue<CPos>();
|
||||||
readonly HashSet<CPos> veinholeCells = new HashSet<CPos>();
|
readonly HashSet<CPos> veinholeCells = new HashSet<CPos>();
|
||||||
readonly int maxDensity;
|
readonly int maxDensity;
|
||||||
|
readonly Color veinRadarColor;
|
||||||
|
|
||||||
ISpriteSequence veinSequence;
|
ISpriteSequence veinSequence;
|
||||||
PaletteReference veinPalette;
|
PaletteReference veinPalette;
|
||||||
@@ -109,6 +170,10 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
resourceLayer.CellChanged += AddDirtyCell;
|
resourceLayer.CellChanged += AddDirtyCell;
|
||||||
maxDensity = resourceLayer.GetMaxDensity(info.ResourceType);
|
maxDensity = resourceLayer.GetMaxDensity(info.ResourceType);
|
||||||
|
|
||||||
|
var terrainInfo = self.World.Map.Rules.TerrainInfo;
|
||||||
|
resourceLayer.Info.TryGetTerrainType(info.ResourceType, out var terrainType);
|
||||||
|
veinRadarColor = terrainInfo.TerrainTypes[terrainInfo.GetTerrainIndex(terrainType)].Color;
|
||||||
|
|
||||||
renderIndices = new CellLayer<int[]>(world.Map);
|
renderIndices = new CellLayer<int[]>(world.Map);
|
||||||
borders = new CellLayer<Adjacency>(world.Map);
|
borders = new CellLayer<Adjacency>(world.Map);
|
||||||
}
|
}
|
||||||
@@ -334,5 +399,30 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
var tintModifiers = veinSequence.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None;
|
var tintModifiers = veinSequence.IgnoreWorldTint ? TintModifiers.IgnoreWorldTint : TintModifiers.None;
|
||||||
yield return new SpriteRenderable(sprite, origin, WVec.Zero, 0, palette, veinSequence.Scale, alpha, float3.Ones, tintModifiers, false);
|
yield return new SpriteRenderable(sprite, origin, WVec.Zero, 0, palette, veinSequence.Scale, alpha, float3.Ones, tintModifiers, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event Action<CPos> IRadarTerrainLayer.CellEntryChanged
|
||||||
|
{
|
||||||
|
add
|
||||||
|
{
|
||||||
|
renderIndices.CellEntryChanged += value;
|
||||||
|
borders.CellEntryChanged += value;
|
||||||
|
}
|
||||||
|
remove
|
||||||
|
{
|
||||||
|
renderIndices.CellEntryChanged -= value;
|
||||||
|
borders.CellEntryChanged -= value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRadarTerrainLayer.TryGetTerrainColorPair(MPos uv, out (Color Left, Color Right) value)
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
|
||||||
|
if (borders[uv] == Adjacency.None && renderIndices[uv] == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
value = (veinRadarColor, veinRadarColor);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Bridge : IRender, INotifyDamageStateChanged
|
class Bridge : IRender, INotifyDamageStateChanged, IRadarSignature
|
||||||
{
|
{
|
||||||
readonly BuildingInfo buildingInfo;
|
readonly BuildingInfo buildingInfo;
|
||||||
readonly Bridge[] neighbours = new Bridge[2];
|
readonly Bridge[] neighbours = new Bridge[2];
|
||||||
@@ -108,6 +108,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
readonly Lazy<bool> isDangling;
|
readonly Lazy<bool> isDangling;
|
||||||
ushort template;
|
ushort template;
|
||||||
Dictionary<CPos, byte> footprint;
|
Dictionary<CPos, byte> footprint;
|
||||||
|
(CPos Cell, Color Color)[] radarSignature;
|
||||||
|
|
||||||
public LegacyBridgeHut Hut { get; private set; }
|
public LegacyBridgeHut Hut { get; private set; }
|
||||||
public bool IsDangling => isDangling.Value;
|
public bool IsDangling => isDangling.Value;
|
||||||
@@ -147,17 +148,23 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.footprint = footprint;
|
this.footprint = footprint;
|
||||||
|
radarSignature = new (CPos Cell, Color Color)[footprint.Keys.Count];
|
||||||
|
|
||||||
// Set the initial custom terrain types
|
// Set the initial state
|
||||||
|
var i = 0;
|
||||||
foreach (var c in footprint.Keys)
|
foreach (var c in footprint.Keys)
|
||||||
self.World.Map.CustomTerrain[c] = GetTerrainType(c);
|
{
|
||||||
|
var tileInfo = GetTerrainInfo(c);
|
||||||
|
self.World.Map.CustomTerrain[c] = tileInfo.TerrainType;
|
||||||
|
radarSignature[i++] = (c, tileInfo.GetColor(self.World.LocalRandom));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
byte GetTerrainType(CPos cell)
|
TerrainTileInfo GetTerrainInfo(CPos cell)
|
||||||
{
|
{
|
||||||
var dx = cell - self.Location;
|
var dx = cell - self.Location;
|
||||||
var index = dx.X + terrainInfo.Templates[template].Size.X * dx.Y;
|
var index = dx.X + terrainInfo.Templates[template].Size.X * dx.Y;
|
||||||
return terrainInfo.GetTerrainIndex(new TerrainTile(template, (byte)index));
|
return terrainInfo.GetTerrainInfo(new TerrainTile(template, (byte)index));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LinkNeighbouringBridges(World world, LegacyBridgeLayer bridges)
|
public void LinkNeighbouringBridges(World world, LegacyBridgeLayer bridges)
|
||||||
@@ -308,8 +315,13 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Update map
|
// Update map
|
||||||
|
var i = 0;
|
||||||
foreach (var c in footprint.Keys)
|
foreach (var c in footprint.Keys)
|
||||||
self.World.Map.CustomTerrain[c] = GetTerrainType(c);
|
{
|
||||||
|
var tileInfo = GetTerrainInfo(c);
|
||||||
|
self.World.Map.CustomTerrain[c] = tileInfo.TerrainType;
|
||||||
|
radarSignature[i++] = (c, tileInfo.GetColor(self.World.LocalRandom));
|
||||||
|
}
|
||||||
|
|
||||||
// If this bridge repair operation connects two pathfinding domains,
|
// If this bridge repair operation connects two pathfinding domains,
|
||||||
// update the domain index.
|
// update the domain index.
|
||||||
@@ -401,5 +413,10 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
neighbours[direction].Demolish(saboteur, direction, damageTypes))));
|
neighbours[direction].Demolish(saboteur, direction, damageTypes))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IRadarSignature.PopulateRadarSignatureCells(Actor self, List<(CPos Cell, Color Color)> destinationBuffer)
|
||||||
|
{
|
||||||
|
destinationBuffer.AddRange(radarSignature);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public bool IsInitialized { get; private set; }
|
public bool IsInitialized { get; private set; }
|
||||||
|
|
||||||
readonly World world;
|
readonly World world;
|
||||||
|
IRadarTerrainLayer[] radarTerrainLayers;
|
||||||
CellLayer<(int, int)> terrainColor;
|
CellLayer<(int, int)> terrainColor;
|
||||||
readonly Shroud shroud;
|
readonly Shroud shroud;
|
||||||
|
|
||||||
@@ -50,22 +52,20 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
void UpdateTerrainCell(MPos uv)
|
void UpdateTerrainCell(MPos uv)
|
||||||
{
|
{
|
||||||
if (!world.Map.CustomTerrain.Contains(uv))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (shroud.IsVisible(uv))
|
if (shroud.IsVisible(uv))
|
||||||
UpdateTerrainCellColor(uv);
|
UpdateTerrainCellColor(uv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateTerrainCellColor(MPos uv)
|
void UpdateTerrainCellColor(MPos uv)
|
||||||
{
|
{
|
||||||
terrainColor[uv] = GetColor(world.Map, uv);
|
terrainColor[uv] = GetColor(world.Map, radarTerrainLayers, uv);
|
||||||
|
|
||||||
CellTerrainColorChanged?.Invoke(uv);
|
CellTerrainColorChanged?.Invoke(uv);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WorldLoaded(World w, WorldRenderer wr)
|
public void WorldLoaded(World w, WorldRenderer wr)
|
||||||
{
|
{
|
||||||
|
radarTerrainLayers = w.WorldActor.TraitsImplementing<IRadarTerrainLayer>().ToArray();
|
||||||
terrainColor = new CellLayer<(int, int)>(w.Map);
|
terrainColor = new CellLayer<(int, int)>(w.Map);
|
||||||
|
|
||||||
w.AddFrameEndTask(_ =>
|
w.AddFrameEndTask(_ =>
|
||||||
@@ -75,7 +75,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
UpdateTerrainCellColor(uv);
|
UpdateTerrainCellColor(uv);
|
||||||
|
|
||||||
world.Map.Tiles.CellEntryChanged += cell => UpdateTerrainCell(cell.ToMPos(world.Map));
|
world.Map.Tiles.CellEntryChanged += cell => UpdateTerrainCell(cell.ToMPos(world.Map));
|
||||||
world.Map.CustomTerrain.CellEntryChanged += cell => UpdateTerrainCell(cell.ToMPos(world.Map));
|
foreach (var rtl in radarTerrainLayers)
|
||||||
|
rtl.CellEntryChanged += cell => UpdateTerrainCell(cell.ToMPos(world.Map));
|
||||||
|
|
||||||
IsInitialized = true;
|
IsInitialized = true;
|
||||||
});
|
});
|
||||||
@@ -83,14 +84,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public (int Left, int Right) this[MPos uv] => terrainColor[uv];
|
public (int Left, int Right) this[MPos uv] => terrainColor[uv];
|
||||||
|
|
||||||
public static (int Left, int Right) GetColor(Map map, MPos uv)
|
public static (int Left, int Right) GetColor(Map map, IRadarTerrainLayer[] radarTerrainLayers, MPos uv)
|
||||||
{
|
{
|
||||||
var custom = map.CustomTerrain[uv];
|
foreach (var rtl in radarTerrainLayers)
|
||||||
if (custom != byte.MaxValue)
|
if (rtl.TryGetTerrainColorPair(uv, out var c))
|
||||||
{
|
return (c.Left.ToArgb(), c.Right.ToArgb());
|
||||||
var c = map.Rules.TerrainInfo.TerrainTypes[custom].Color.ToArgb();
|
|
||||||
return (c, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
var tc = map.GetTerrainColorPair(uv);
|
var tc = map.GetTerrainColorPair(uv);
|
||||||
return (tc.Left.ToArgb(), tc.Right.ToArgb());
|
return (tc.Left.ToArgb(), tc.Right.ToArgb());
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
[TraitLocation(SystemActors.EditorWorld)]
|
[TraitLocation(SystemActors.EditorWorld)]
|
||||||
[Desc("Required for the map editor to work. Attach this to the world actor.")]
|
[Desc("Required for the map editor to work. Attach this to the world actor.")]
|
||||||
public class EditorResourceLayerInfo : TraitInfo, IResourceLayerInfo, IMapPreviewSignatureInfo
|
public class EditorResourceLayerInfo : TraitInfo, IResourceLayerInfo
|
||||||
{
|
{
|
||||||
[FieldLoader.LoadUsing(nameof(LoadResourceTypes))]
|
[FieldLoader.LoadUsing(nameof(LoadResourceTypes))]
|
||||||
public readonly Dictionary<string, ResourceLayerInfo.ResourceTypeInfo> ResourceTypes = null;
|
public readonly Dictionary<string, ResourceLayerInfo.ResourceTypeInfo> ResourceTypes = null;
|
||||||
@@ -40,9 +40,28 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
[Desc("Override the density saved in maps with values calculated based on the number of neighbouring resource cells.")]
|
[Desc("Override the density saved in maps with values calculated based on the number of neighbouring resource cells.")]
|
||||||
public readonly bool RecalculateResourceDensity = false;
|
public readonly bool RecalculateResourceDensity = false;
|
||||||
|
|
||||||
void IMapPreviewSignatureInfo.PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<(MPos, Color)> destinationBuffer)
|
bool IResourceLayerInfo.TryGetTerrainType(string resourceType, out string terrainType)
|
||||||
{
|
{
|
||||||
ResourceLayerInfo.PopulateMapPreviewSignatureCells(map, ResourceTypes, destinationBuffer);
|
if (resourceType == null || !ResourceTypes.TryGetValue(resourceType, out var resourceInfo))
|
||||||
|
{
|
||||||
|
terrainType = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
terrainType = resourceInfo.TerrainType;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IResourceLayerInfo.TryGetResourceIndex(string resourceType, out byte index)
|
||||||
|
{
|
||||||
|
if (resourceType == null || !ResourceTypes.TryGetValue(resourceType, out var resourceInfo))
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = resourceInfo.ResourceIndex;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new EditorResourceLayer(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new EditorResourceLayer(init.Self, this); }
|
||||||
@@ -74,6 +93,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
void IResourceLayer.ClearResources(CPos cell) { ClearResources(cell); }
|
void IResourceLayer.ClearResources(CPos cell) { ClearResources(cell); }
|
||||||
bool IResourceLayer.IsVisible(CPos cell) { return Map.Contains(cell); }
|
bool IResourceLayer.IsVisible(CPos cell) { return Map.Contains(cell); }
|
||||||
bool IResourceLayer.IsEmpty => false;
|
bool IResourceLayer.IsEmpty => false;
|
||||||
|
IResourceLayerInfo IResourceLayer.Info => info;
|
||||||
|
|
||||||
public EditorResourceLayer(Actor self, EditorResourceLayerInfo info)
|
public EditorResourceLayer(Actor self, EditorResourceLayerInfo info)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
[TraitLocation(SystemActors.World)]
|
[TraitLocation(SystemActors.World)]
|
||||||
[Desc("Attach this to the world actor.")]
|
[Desc("Attach this to the world actor.")]
|
||||||
public class ResourceLayerInfo : TraitInfo, IResourceLayerInfo, Requires<BuildingInfluenceInfo>, IMapPreviewSignatureInfo
|
public class ResourceLayerInfo : TraitInfo, IResourceLayerInfo, Requires<BuildingInfluenceInfo>
|
||||||
{
|
{
|
||||||
public class ResourceTypeInfo
|
public class ResourceTypeInfo
|
||||||
{
|
{
|
||||||
@@ -76,27 +76,28 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PopulateMapPreviewSignatureCells(Map map, Dictionary<string, ResourceTypeInfo> resources, List<(MPos, Color)> destinationBuffer)
|
bool IResourceLayerInfo.TryGetTerrainType(string resourceType, out string terrainType)
|
||||||
{
|
{
|
||||||
var terrainInfo = map.Rules.TerrainInfo;
|
if (resourceType == null || !ResourceTypes.TryGetValue(resourceType, out var resourceInfo))
|
||||||
var colors = resources.Values.ToDictionary(
|
|
||||||
r => r.ResourceIndex,
|
|
||||||
r => terrainInfo.TerrainTypes[terrainInfo.GetTerrainIndex(r.TerrainType)].Color);
|
|
||||||
|
|
||||||
for (var i = 0; i < map.MapSize.X; i++)
|
|
||||||
{
|
{
|
||||||
for (var j = 0; j < map.MapSize.Y; j++)
|
terrainType = null;
|
||||||
{
|
return false;
|
||||||
var cell = new MPos(i, j);
|
|
||||||
if (colors.TryGetValue(map.Resources[cell].Type, out var color))
|
|
||||||
destinationBuffer.Add((cell, color));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
terrainType = resourceInfo.TerrainType;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMapPreviewSignatureInfo.PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<(MPos, Color)> destinationBuffer)
|
bool IResourceLayerInfo.TryGetResourceIndex(string resourceType, out byte index)
|
||||||
{
|
{
|
||||||
PopulateMapPreviewSignatureCells(map, ResourceTypes, destinationBuffer);
|
if (resourceType == null || !ResourceTypes.TryGetValue(resourceType, out var resourceInfo))
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = resourceInfo.ResourceIndex;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new ResourceLayer(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new ResourceLayer(init.Self, this); }
|
||||||
@@ -299,5 +300,6 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
void IResourceLayer.ClearResources(CPos cell) { ClearResources(cell); }
|
void IResourceLayer.ClearResources(CPos cell) { ClearResources(cell); }
|
||||||
bool IResourceLayer.IsVisible(CPos cell) { return !world.FogObscures(cell); }
|
bool IResourceLayer.IsVisible(CPos cell) { return !world.FogObscures(cell); }
|
||||||
bool IResourceLayer.IsEmpty => resCells < 1;
|
bool IResourceLayer.IsEmpty => resCells < 1;
|
||||||
|
IResourceLayerInfo IResourceLayer.Info => info;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -20,7 +21,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
|
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
|
||||||
[Desc("Visualizes the state of the `ResourceLayer`.", " Attach this to the world actor.")]
|
[Desc("Visualizes the state of the `ResourceLayer`.", " Attach this to the world actor.")]
|
||||||
public class ResourceRendererInfo : TraitInfo, Requires<IResourceLayerInfo>
|
public class ResourceRendererInfo : TraitInfo, Requires<IResourceLayerInfo>, IMapPreviewSignatureInfo
|
||||||
{
|
{
|
||||||
public class ResourceTypeInfo
|
public class ResourceTypeInfo
|
||||||
{
|
{
|
||||||
@@ -61,10 +62,38 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IMapPreviewSignatureInfo.PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<(MPos, Color)> destinationBuffer)
|
||||||
|
{
|
||||||
|
var resourceLayer = ai.TraitInfoOrDefault<IResourceLayerInfo>();
|
||||||
|
if (resourceLayer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var terrainInfo = map.Rules.TerrainInfo;
|
||||||
|
var colors = new Dictionary<byte, Color>();
|
||||||
|
foreach (var r in ResourceTypes.Keys)
|
||||||
|
{
|
||||||
|
if (!resourceLayer.TryGetResourceIndex(r, out var resourceIndex) || !resourceLayer.TryGetTerrainType(r, out var terrainType))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var info = terrainInfo.TerrainTypes[terrainInfo.GetTerrainIndex(terrainType)];
|
||||||
|
colors.Add(resourceIndex, info.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 (colors.TryGetValue(map.Resources[cell].Type, out var color))
|
||||||
|
destinationBuffer.Add((cell, color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override object Create(ActorInitializer init) { return new ResourceRenderer(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new ResourceRenderer(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ResourceRenderer : IResourceRenderer, IWorldLoaded, IRenderOverlay, ITickRender, INotifyActorDisposing
|
public class ResourceRenderer : IResourceRenderer, IWorldLoaded, IRenderOverlay, ITickRender, INotifyActorDisposing, IRadarTerrainLayer
|
||||||
{
|
{
|
||||||
protected readonly ResourceRendererInfo Info;
|
protected readonly ResourceRendererInfo Info;
|
||||||
protected readonly IResourceLayer ResourceLayer;
|
protected readonly IResourceLayer ResourceLayer;
|
||||||
@@ -284,6 +313,30 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
yield return new SpriteRenderable(sprite, origin, WVec.Zero, 0, palette, sequence.Scale, alpha, float3.Ones, tintModifiers, false);
|
yield return new SpriteRenderable(sprite, origin, WVec.Zero, 0, palette, sequence.Scale, alpha, float3.Ones, tintModifiers, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event Action<CPos> IRadarTerrainLayer.CellEntryChanged
|
||||||
|
{
|
||||||
|
add => RenderContents.CellEntryChanged += value;
|
||||||
|
remove => RenderContents.CellEntryChanged -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRadarTerrainLayer.TryGetTerrainColorPair(MPos uv, out (Color Left, Color Right) value)
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
|
||||||
|
var type = RenderContents[uv].Type;
|
||||||
|
if (type == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ResourceLayer.Info.TryGetTerrainType(type, out var terrainType))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var terrainInfo = World.Map.Rules.TerrainInfo;
|
||||||
|
var info = terrainInfo.TerrainTypes[terrainInfo.GetTerrainIndex(terrainType)];
|
||||||
|
|
||||||
|
value = (info.Color, info.Color);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public readonly struct RendererCellContents
|
public readonly struct RendererCellContents
|
||||||
{
|
{
|
||||||
public readonly string Type;
|
public readonly string Type;
|
||||||
|
|||||||
@@ -677,7 +677,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
IEnumerable<IRenderable> RenderPreview(WorldRenderer wr, TerrainTemplateInfo template, WPos origin);
|
IEnumerable<IRenderable> RenderPreview(WorldRenderer wr, TerrainTemplateInfo template, WPos origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IResourceLayerInfo : ITraitInfoInterface { }
|
public interface IResourceLayerInfo : ITraitInfoInterface
|
||||||
|
{
|
||||||
|
bool TryGetTerrainType(string resourceType, out string terrainType);
|
||||||
|
bool TryGetResourceIndex(string resourceType, out byte index);
|
||||||
|
}
|
||||||
|
|
||||||
[RequireExplicitImplementation]
|
[RequireExplicitImplementation]
|
||||||
public interface IResourceLayer
|
public interface IResourceLayer
|
||||||
@@ -692,6 +696,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
bool IsVisible(CPos cell);
|
bool IsVisible(CPos cell);
|
||||||
bool IsEmpty { get; }
|
bool IsEmpty { get; }
|
||||||
|
IResourceLayerInfo Info { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[RequireExplicitImplementation]
|
[RequireExplicitImplementation]
|
||||||
@@ -703,4 +708,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
IEnumerable<IRenderable> RenderUIPreview(WorldRenderer wr, string resourceType, int2 origin, float scale);
|
IEnumerable<IRenderable> RenderUIPreview(WorldRenderer wr, string resourceType, int2 origin, float scale);
|
||||||
IEnumerable<IRenderable> RenderPreview(WorldRenderer wr, string resourceType, WPos origin);
|
IEnumerable<IRenderable> RenderPreview(WorldRenderer wr, string resourceType, WPos origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[RequireExplicitImplementation]
|
||||||
|
public interface IRadarTerrainLayer
|
||||||
|
{
|
||||||
|
event Action<CPos> CellEntryChanged;
|
||||||
|
bool TryGetTerrainColorPair(MPos uv, out (Color Left, Color Right) value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
readonly World world;
|
readonly World world;
|
||||||
readonly WorldRenderer worldRenderer;
|
readonly WorldRenderer worldRenderer;
|
||||||
readonly RadarPings radarPings;
|
readonly RadarPings radarPings;
|
||||||
|
readonly IRadarTerrainLayer[] radarTerrainLayers;
|
||||||
readonly bool isRectangularIsometric;
|
readonly bool isRectangularIsometric;
|
||||||
readonly int cellWidth;
|
readonly int cellWidth;
|
||||||
readonly int previewWidth;
|
readonly int previewWidth;
|
||||||
@@ -69,7 +70,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
this.worldRenderer = worldRenderer;
|
this.worldRenderer = worldRenderer;
|
||||||
|
|
||||||
radarPings = world.WorldActor.TraitOrDefault<RadarPings>();
|
radarPings = world.WorldActor.TraitOrDefault<RadarPings>();
|
||||||
|
radarTerrainLayers = world.WorldActor.TraitsImplementing<IRadarTerrainLayer>().ToArray();
|
||||||
isRectangularIsometric = world.Map.Grid.Type == MapGridType.RectangularIsometric;
|
isRectangularIsometric = world.Map.Grid.Type == MapGridType.RectangularIsometric;
|
||||||
cellWidth = isRectangularIsometric ? 2 : 1;
|
cellWidth = isRectangularIsometric ? 2 : 1;
|
||||||
previewWidth = world.Map.MapSize.X;
|
previewWidth = world.Map.MapSize.X;
|
||||||
@@ -152,7 +153,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
world.Map.Tiles.CellEntryChanged -= CellTerrainColorChanged;
|
world.Map.Tiles.CellEntryChanged -= CellTerrainColorChanged;
|
||||||
world.Map.CustomTerrain.CellEntryChanged -= CellTerrainColorChanged;
|
foreach (var rtl in radarTerrainLayers)
|
||||||
|
rtl.CellEntryChanged -= CellTerrainColorChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newPlayerRadarTerrain != null)
|
if (newPlayerRadarTerrain != null)
|
||||||
@@ -160,7 +162,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
world.Map.Tiles.CellEntryChanged += CellTerrainColorChanged;
|
world.Map.Tiles.CellEntryChanged += CellTerrainColorChanged;
|
||||||
world.Map.CustomTerrain.CellEntryChanged += CellTerrainColorChanged;
|
foreach (var rtl in radarTerrainLayers)
|
||||||
|
rtl.CellEntryChanged += CellTerrainColorChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerRadarTerrain = newPlayerRadarTerrain;
|
playerRadarTerrain = newPlayerRadarTerrain;
|
||||||
@@ -206,7 +209,8 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
void UpdateTerrainColor(MPos uv)
|
void UpdateTerrainColor(MPos uv)
|
||||||
{
|
{
|
||||||
var colorPair = playerRadarTerrain != null && playerRadarTerrain.IsInitialized ? playerRadarTerrain[uv] : PlayerRadarTerrain.GetColor(world.Map, uv);
|
var colorPair = playerRadarTerrain != null && playerRadarTerrain.IsInitialized ?
|
||||||
|
playerRadarTerrain[uv] : PlayerRadarTerrain.GetColor(world.Map, radarTerrainLayers, uv);
|
||||||
var leftColor = colorPair.Left;
|
var leftColor = colorPair.Left;
|
||||||
var rightColor = colorPair.Right;
|
var rightColor = colorPair.Right;
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,12 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
using OpenRA.Primitives;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.D2k.Traits
|
namespace OpenRA.Mods.D2k.Traits
|
||||||
@@ -30,13 +32,14 @@ namespace OpenRA.Mods.D2k.Traits
|
|||||||
public override object Create(ActorInitializer init) { return new BuildableTerrainLayer(init.Self, this); }
|
public override object Create(ActorInitializer init) { return new BuildableTerrainLayer(init.Self, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BuildableTerrainLayer : IRenderOverlay, IWorldLoaded, ITickRender, INotifyActorDisposing
|
public class BuildableTerrainLayer : IRenderOverlay, IWorldLoaded, ITickRender, IRadarTerrainLayer, INotifyActorDisposing
|
||||||
{
|
{
|
||||||
readonly BuildableTerrainLayerInfo info;
|
readonly BuildableTerrainLayerInfo info;
|
||||||
readonly Dictionary<CPos, TerrainTile?> dirty = new Dictionary<CPos, TerrainTile?>();
|
readonly Dictionary<CPos, TerrainTile?> dirty = new Dictionary<CPos, TerrainTile?>();
|
||||||
readonly ITiledTerrainRenderer terrainRenderer;
|
readonly ITiledTerrainRenderer terrainRenderer;
|
||||||
readonly World world;
|
readonly World world;
|
||||||
readonly CellLayer<int> strength;
|
readonly CellLayer<int> strength;
|
||||||
|
readonly CellLayer<(Color, Color)> radarColor;
|
||||||
|
|
||||||
TerrainSpriteLayer render;
|
TerrainSpriteLayer render;
|
||||||
PaletteReference paletteReference;
|
PaletteReference paletteReference;
|
||||||
@@ -47,6 +50,7 @@ namespace OpenRA.Mods.D2k.Traits
|
|||||||
this.info = info;
|
this.info = info;
|
||||||
world = self.World;
|
world = self.World;
|
||||||
strength = new CellLayer<int>(world.Map);
|
strength = new CellLayer<int>(world.Map);
|
||||||
|
radarColor = new CellLayer<(Color, Color)>(world.Map);
|
||||||
terrainRenderer = self.Trait<ITiledTerrainRenderer>();
|
terrainRenderer = self.Trait<ITiledTerrainRenderer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,8 +65,11 @@ namespace OpenRA.Mods.D2k.Traits
|
|||||||
if (!strength.Contains(cell))
|
if (!strength.Contains(cell))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
world.Map.CustomTerrain[cell] = world.Map.Rules.TerrainInfo.GetTerrainIndex(tile);
|
var uv = cell.ToMPos(world.Map);
|
||||||
strength[cell] = info.MaxStrength;
|
var tileInfo = world.Map.Rules.TerrainInfo.GetTerrainInfo(tile);
|
||||||
|
world.Map.CustomTerrain[uv] = tileInfo.TerrainType;
|
||||||
|
strength[uv] = info.MaxStrength;
|
||||||
|
radarColor[uv] = (tileInfo.GetColor(world.LocalRandom), tileInfo.GetColor(world.LocalRandom));
|
||||||
dirty[cell] = tile;
|
dirty[cell] = tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,8 +92,10 @@ namespace OpenRA.Mods.D2k.Traits
|
|||||||
if (!strength.Contains(cell))
|
if (!strength.Contains(cell))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
world.Map.CustomTerrain[cell] = byte.MaxValue;
|
var uv = cell.ToMPos(world.Map);
|
||||||
|
world.Map.CustomTerrain[uv] = byte.MaxValue;
|
||||||
strength[cell] = 0;
|
strength[cell] = 0;
|
||||||
|
radarColor[uv] = (Color.Transparent, Color.Transparent);
|
||||||
dirty[cell] = null;
|
dirty[cell] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +130,18 @@ namespace OpenRA.Mods.D2k.Traits
|
|||||||
render.Draw(wr.Viewport);
|
render.Draw(wr.Viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event Action<CPos> IRadarTerrainLayer.CellEntryChanged
|
||||||
|
{
|
||||||
|
add => radarColor.CellEntryChanged += value;
|
||||||
|
remove => radarColor.CellEntryChanged -= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRadarTerrainLayer.TryGetTerrainColorPair(MPos uv, out (Color Left, Color Right) value)
|
||||||
|
{
|
||||||
|
value = radarColor[uv];
|
||||||
|
return strength[uv] > 0;
|
||||||
|
}
|
||||||
|
|
||||||
void INotifyActorDisposing.Disposing(Actor self)
|
void INotifyActorDisposing.Disposing(Actor self)
|
||||||
{
|
{
|
||||||
if (disposed)
|
if (disposed)
|
||||||
|
|||||||
Reference in New Issue
Block a user