diff --git a/OpenRA.Game/Graphics/TerrainRenderer.cs b/OpenRA.Game/Graphics/TerrainRenderer.cs index a6011527b0..c46cd9a4f2 100644 --- a/OpenRA.Game/Graphics/TerrainRenderer.cs +++ b/OpenRA.Game/Graphics/TerrainRenderer.cs @@ -9,25 +9,32 @@ #endregion using System; +using System.Collections.Generic; using OpenRA.Traits; namespace OpenRA.Graphics { sealed class TerrainRenderer : IDisposable { - readonly TerrainSpriteLayer terrain; + readonly World world; + readonly Dictionary spriteLayers = new Dictionary(); readonly Theater theater; readonly CellLayer mapTiles; readonly CellLayer mapHeight; public TerrainRenderer(World world, WorldRenderer wr) { + this.world = world; theater = wr.Theater; mapTiles = world.Map.MapTiles.Value; mapHeight = world.Map.MapHeight.Value; - terrain = new TerrainSpriteLayer(world, wr, theater.Sheet, BlendMode.Alpha, - wr.Palette("terrain"), wr.World.Type != WorldType.Editor); + foreach (var template in world.TileSet.Templates) + { + var palette = template.Value.Palette ?? TileSet.TerrainPaletteInternalName; + spriteLayers.GetOrAdd(palette, pal => + new TerrainSpriteLayer(world, wr, theater.Sheet, BlendMode.Alpha, wr.Palette(palette), wr.World.Type != WorldType.Editor)); + } foreach (var cell in world.Map.AllCells) UpdateCell(cell); @@ -38,12 +45,18 @@ namespace OpenRA.Graphics public void UpdateCell(CPos cell) { - terrain.Update(cell, theater.TileSprite(mapTiles[cell])); + var tile = mapTiles[cell]; + var palette = world.TileSet.Templates[tile.Type].Palette ?? TileSet.TerrainPaletteInternalName; + var sprite = theater.TileSprite(tile); + foreach (var kv in spriteLayers) + kv.Value.Update(cell, palette == kv.Key ? sprite : null); } public void Draw(WorldRenderer wr, Viewport viewport) { - terrain.Draw(viewport); + foreach (var kv in spriteLayers.Values) + kv.Draw(wr.Viewport); + foreach (var r in wr.World.WorldActor.TraitsImplementing()) r.Render(wr); } @@ -52,7 +65,9 @@ namespace OpenRA.Graphics { mapTiles.CellEntryChanged -= UpdateCell; mapHeight.CellEntryChanged -= UpdateCell; - terrain.Dispose(); + + foreach (var kv in spriteLayers.Values) + kv.Dispose(); } } } diff --git a/OpenRA.Game/Map/TileSet.cs b/OpenRA.Game/Map/TileSet.cs index c886fd1ed4..438131a2a8 100644 --- a/OpenRA.Game/Map/TileSet.cs +++ b/OpenRA.Game/Map/TileSet.cs @@ -73,6 +73,7 @@ namespace OpenRA public readonly int2 Size; public readonly bool PickAny; public readonly string Category; + public readonly string Palette; readonly TerrainTileInfo[] tileInfo; @@ -166,6 +167,8 @@ namespace OpenRA public class TileSet { + public const string TerrainPaletteInternalName = "terrain"; + public readonly string Name; public readonly string Id; public readonly int SheetSize = 512; diff --git a/OpenRA.Game/Traits/Player/FixedColorPalette.cs b/OpenRA.Game/Traits/Player/FixedColorPalette.cs index 5997f777f4..aaa551222b 100644 --- a/OpenRA.Game/Traits/Player/FixedColorPalette.cs +++ b/OpenRA.Game/Traits/Player/FixedColorPalette.cs @@ -16,7 +16,7 @@ namespace OpenRA.Traits public class FixedColorPaletteInfo : ITraitInfo { [Desc("The name of the palette to base off.")] - [PaletteReference] public readonly string Base = "terrain"; + [PaletteReference] public readonly string Base = TileSet.TerrainPaletteInternalName; [Desc("The name of the resulting palette")] [PaletteDefinition] public readonly string Name = "resources"; diff --git a/OpenRA.Game/Traits/World/ResourceType.cs b/OpenRA.Game/Traits/World/ResourceType.cs index 850d5645dc..e3268b5d53 100644 --- a/OpenRA.Game/Traits/World/ResourceType.cs +++ b/OpenRA.Game/Traits/World/ResourceType.cs @@ -17,7 +17,7 @@ namespace OpenRA.Traits { public readonly string Sequence = "resources"; [SequenceReference("Sequence")] public readonly string[] Variants = { }; - [PaletteReference] public readonly string Palette = "terrain"; + [PaletteReference] public readonly string Palette = TileSet.TerrainPaletteInternalName; public readonly int ResourceType = 1; public readonly int ValuePerUnit = 0; diff --git a/OpenRA.Mods.Common/Traits/Buildings/Bib.cs b/OpenRA.Mods.Common/Traits/Buildings/Bib.cs index 4ec09d3bfb..43ea569d05 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Bib.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Bib.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.Common.Traits public class BibInfo : ITraitInfo, Requires, IRenderActorPreviewSpritesInfo, Requires { [SequenceReference] public readonly string Sequence = "bib"; - [PaletteReference] public readonly string Palette = "terrain"; + [PaletteReference] public readonly string Palette = TileSet.TerrainPaletteInternalName; public readonly bool HasMinibib = false; public object Create(ActorInitializer init) { return new Bib(init.Self, this); } diff --git a/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs b/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs index f6971dc45b..7ec7e03ccb 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs @@ -192,7 +192,7 @@ namespace OpenRA.Mods.Common.Traits { if (!initialized) { - var palette = wr.Palette("terrain"); + var palette = wr.Palette(TileSet.TerrainPaletteInternalName); renderables = new Dictionary(); foreach (var t in info.Templates) renderables.Add(t.First, TemplateRenderables(wr, palette, t.First)); diff --git a/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs b/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs index c4e5a92d3c..8a6337f40e 100644 --- a/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs +++ b/OpenRA.Mods.Common/Traits/Player/PlaceBuilding.cs @@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Traits public class PlaceBuildingInfo : ITraitInfo { [Desc("Palette to use for rendering the placement sprite.")] - [PaletteReference] public readonly string Palette = "terrain"; + [PaletteReference] public readonly string Palette = TileSet.TerrainPaletteInternalName; [Desc("Play NewOptionsNotification this many ticks after building placement.")] public readonly int NewOptionsNotificationDelay = 10; diff --git a/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs b/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs index 73c34759b9..4b2cf10e46 100644 --- a/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs +++ b/OpenRA.Mods.Common/Traits/SupportPowers/GrantUpgradePower.cs @@ -149,7 +149,7 @@ namespace OpenRA.Mods.Common.Traits public IEnumerable Render(WorldRenderer wr, World world) { var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos); - var pal = wr.Palette("terrain"); + var pal = wr.Palette(TileSet.TerrainPaletteInternalName); foreach (var t in world.Map.FindTilesInCircle(xy, range)) yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, pal, 1f, true); diff --git a/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs b/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs index 74eb68d455..396380577d 100644 --- a/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/EditorSelectionLayer.cs @@ -25,7 +25,7 @@ namespace OpenRA.Mods.Common.Traits { [PaletteReference] [Desc("Palette to use for rendering the placement sprite.")] - public readonly string Palette = "terrain"; + public readonly string Palette = TileSet.TerrainPaletteInternalName; [Desc("Sequence image where the selection overlay types are defined.")] public readonly string Image = "editor-overlay"; diff --git a/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs b/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs index fb82c9e082..b1329df415 100644 --- a/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs +++ b/OpenRA.Mods.Common/Traits/World/SmudgeLayer.cs @@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Traits [PaletteReference] public readonly string SmokePalette = "effect"; - [PaletteReference] public readonly string Palette = "terrain"; + [PaletteReference] public readonly string Palette = TileSet.TerrainPaletteInternalName; public object Create(ActorInitializer init) { return new SmudgeLayer(init.Self, this); } } diff --git a/OpenRA.Mods.Common/Widgets/TerrainTemplatePreviewWidget.cs b/OpenRA.Mods.Common/Widgets/TerrainTemplatePreviewWidget.cs index 70bf4aa7bc..bafeb36e53 100644 --- a/OpenRA.Mods.Common/Widgets/TerrainTemplatePreviewWidget.cs +++ b/OpenRA.Mods.Common/Widgets/TerrainTemplatePreviewWidget.cs @@ -18,7 +18,6 @@ namespace OpenRA.Mods.Common.Widgets public class TerrainTemplatePreviewWidget : Widget { public Func GetScale = () => 1f; - public string Palette = "terrain"; readonly WorldRenderer worldRenderer; readonly TileSet tileset; @@ -93,7 +92,8 @@ namespace OpenRA.Mods.Common.Widgets var u = gridType == MapGridType.Rectangular ? x : (x - y) / 2f; var v = gridType == MapGridType.Rectangular ? y : (x + y) / 2f; var pos = origin + scale * (new float2(u * ts.Width, (v - 0.5f * tileInfo.Height) * ts.Height) - 0.5f * sprite.Size); - Game.Renderer.SpriteRenderer.DrawSprite(sprite, pos, worldRenderer.Palette(Palette), size); + var palette = Template.Palette ?? TileSet.TerrainPaletteInternalName; + Game.Renderer.SpriteRenderer.DrawSprite(sprite, pos, worldRenderer.Palette(palette), size); } } } diff --git a/OpenRA.Mods.D2k/Traits/World/BuildableTerrainLayer.cs b/OpenRA.Mods.D2k/Traits/World/BuildableTerrainLayer.cs index 3555380ba4..1593df75f0 100644 --- a/OpenRA.Mods.D2k/Traits/World/BuildableTerrainLayer.cs +++ b/OpenRA.Mods.D2k/Traits/World/BuildableTerrainLayer.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.D2k.Traits public class BuildableTerrainLayerInfo : ITraitInfo { [Desc("Palette to render the layer sprites in.")] - public readonly string Palette = "terrain"; + public readonly string Palette = TileSet.TerrainPaletteInternalName; public object Create(ActorInitializer init) { return new BuildableTerrainLayer(init.Self, this); } } diff --git a/OpenRA.Mods.RA/Traits/Minelayer.cs b/OpenRA.Mods.RA/Traits/Minelayer.cs index 8234b54023..d9c084c1dd 100644 --- a/OpenRA.Mods.RA/Traits/Minelayer.cs +++ b/OpenRA.Mods.RA/Traits/Minelayer.cs @@ -121,7 +121,7 @@ namespace OpenRA.Mods.RA.Traits if (self.Owner != self.World.LocalPlayer || Minefield == null) yield break; - var pal = wr.Palette("terrain"); + var pal = wr.Palette(TileSet.TerrainPaletteInternalName); foreach (var c in Minefield) yield return new SpriteRenderable(tile, self.World.Map.CenterOfCell(c), WVec.Zero, -511, pal, 1f, true); @@ -181,7 +181,7 @@ namespace OpenRA.Mods.RA.Traits var minefield = GetMinefieldCells(minefieldStart, lastMousePos, minelayer.Info.TraitInfo().MinefieldDepth); - var pal = wr.Palette("terrain"); + var pal = wr.Palette(TileSet.TerrainPaletteInternalName); foreach (var c in minefield) { var tile = movement.CanEnterCell(c, null, false) ? tileOk : tileBlocked; diff --git a/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs b/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs index 09f590eb32..554dd6df4c 100644 --- a/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs +++ b/OpenRA.Mods.RA/Traits/SupportPowers/ChronoshiftPower.cs @@ -145,7 +145,7 @@ namespace OpenRA.Mods.RA.Traits { var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos); var tiles = world.Map.FindTilesInCircle(xy, range); - var pal = wr.Palette("terrain"); + var pal = wr.Palette(TileSet.TerrainPaletteInternalName); foreach (var t in tiles) yield return new SpriteRenderable(tile, wr.World.Map.CenterOfCell(t), WVec.Zero, -511, pal, 1f, true); } @@ -224,7 +224,7 @@ namespace OpenRA.Mods.RA.Traits public IEnumerable Render(WorldRenderer wr, World world) { var xy = wr.Viewport.ViewToWorld(Viewport.LastMousePos); - var pal = wr.Palette("terrain"); + var pal = wr.Palette(TileSet.TerrainPaletteInternalName); // Source tiles foreach (var t in world.Map.FindTilesInCircle(sourceLocation, range))