diff --git a/OpenRA.Editor/Form1.cs b/OpenRA.Editor/Form1.cs index c108f0b690..79a948774a 100644 --- a/OpenRA.Editor/Form1.cs +++ b/OpenRA.Editor/Form1.cs @@ -153,11 +153,11 @@ namespace OpenRA.Editor tileset = Program.Rules.TileSets[map.Tileset]; tilesetRenderer = new TileSetRenderer(tileset, modData.Manifest.TileSize); var shadowIndex = new int[] { 3, 4 }; - var palette = new Palette(GlobalFileSystem.Open(tileset.Palette), shadowIndex); + var palette = new ImmutablePalette(GlobalFileSystem.Open(tileset.Palette), shadowIndex); // required for desert terrain in RA var playerPalette = tileset.PlayerPalette ?? tileset.Palette; - var shadowedPalette = new Palette(GlobalFileSystem.Open(playerPalette), shadowIndex); + var shadowedPalette = new ImmutablePalette(GlobalFileSystem.Open(playerPalette), shadowIndex); surface1.Bind(map, tileset, tilesetRenderer, palette, shadowedPalette); diff --git a/OpenRA.Editor/RenderUtils.cs b/OpenRA.Editor/RenderUtils.cs index ca7c0ca71c..7abd148fab 100644 --- a/OpenRA.Editor/RenderUtils.cs +++ b/OpenRA.Editor/RenderUtils.cs @@ -20,7 +20,7 @@ namespace OpenRA.Editor { static class RenderUtils { - static Bitmap RenderShp(ISpriteSource shp, Palette p) + static Bitmap RenderShp(ISpriteSource shp, IPalette p) { var frame = shp.Frames.First(); @@ -45,7 +45,7 @@ namespace OpenRA.Editor return bitmap; } - public static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, Palette p) + public static ActorTemplate RenderActor(ActorInfo info, TileSet tileset, IPalette p) { var image = RenderSprites.GetImage(info); @@ -76,7 +76,7 @@ namespace OpenRA.Editor } } - public static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, Palette p) + public static ResourceTemplate RenderResourceType(ResourceTypeInfo info, string[] exts, IPalette p) { var image = info.EditorSprite; using (var s = GlobalFileSystem.OpenWithExts(image, exts)) diff --git a/OpenRA.Editor/Surface.cs b/OpenRA.Editor/Surface.cs index 16fcb1f678..20b317ee2b 100644 --- a/OpenRA.Editor/Surface.cs +++ b/OpenRA.Editor/Surface.cs @@ -45,8 +45,8 @@ namespace OpenRA.Editor public Map Map { get; private set; } public TileSet TileSet { get; private set; } public TileSetRenderer TileSetRenderer { get; private set; } - public Palette Palette { get; private set; } - public Palette PlayerPalette { get; private set; } + public IPalette Palette { get; private set; } + public IPalette PlayerPalette { get; private set; } public int2 Offset; public int2 GetOffset() { return Offset; } @@ -81,7 +81,7 @@ namespace OpenRA.Editor public Keys GetModifiers() { return ModifierKeys; } - public void Bind(Map m, TileSet ts, TileSetRenderer tsr, Palette p, Palette pp) + public void Bind(Map m, TileSet ts, TileSetRenderer tsr, IPalette p, IPalette pp) { Map = m; TileSet = ts; @@ -381,7 +381,7 @@ namespace OpenRA.Editor var pr = Map.Players[name]; var pcpi = Program.Rules.Actors["player"].Traits.Get(); var remap = new PlayerColorRemap(pcpi.RemapIndex, pr.Color, pcpi.Ramp); - return new Palette(PlayerPalette, remap).AsSystemPalette(); + return new ImmutablePalette(PlayerPalette, remap).AsSystemPalette(); } Cache playerPalettes; diff --git a/OpenRA.Editor/TileSetRenderer.cs b/OpenRA.Editor/TileSetRenderer.cs index 06db47d678..60a6101c74 100644 --- a/OpenRA.Editor/TileSetRenderer.cs +++ b/OpenRA.Editor/TileSetRenderer.cs @@ -82,7 +82,7 @@ namespace OpenRA.Editor templates.Add(t.Key, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames)); } - public Bitmap RenderTemplate(ushort id, Palette p) + public Bitmap RenderTemplate(ushort id, IPalette p) { var template = TileSet.Templates[id]; var templateData = templates[id]; diff --git a/OpenRA.Game/Graphics/CursorProvider.cs b/OpenRA.Game/Graphics/CursorProvider.cs index abb792777d..05a3f082ec 100644 --- a/OpenRA.Game/Graphics/CursorProvider.cs +++ b/OpenRA.Game/Graphics/CursorProvider.cs @@ -41,7 +41,7 @@ namespace OpenRA.Graphics palette = new HardwarePalette(); foreach (var p in nodesDict["Palettes"].Nodes) - palette.AddPalette(p.Key, new Palette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false); + palette.AddPalette(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false); var spriteLoader = new SpriteLoader(new string[0], new SheetBuilder(SheetType.Indexed)); foreach (var s in nodesDict["Cursors"].Nodes) @@ -53,9 +53,6 @@ namespace OpenRA.Graphics PaletteReference CreatePaletteReference(string name) { var pal = palette.GetPalette(name); - if (pal == null) - throw new InvalidOperationException("Palette `{0}` does not exist".F(name)); - return new PaletteReference(name, palette.GetPaletteIndex(name), pal); } diff --git a/OpenRA.Game/Graphics/HardwarePalette.cs b/OpenRA.Game/Graphics/HardwarePalette.cs index fa2bf91cea..00b48749db 100644 --- a/OpenRA.Game/Graphics/HardwarePalette.cs +++ b/OpenRA.Game/Graphics/HardwarePalette.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 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. For more information, @@ -10,7 +10,6 @@ using System; using System.Collections.Generic; -using System.Linq; using OpenRA.Traits; namespace OpenRA.Graphics @@ -18,70 +17,101 @@ namespace OpenRA.Graphics public class HardwarePalette { public const int MaxPalettes = 256; - int allocated = 0; public ITexture Texture { get; private set; } - Dictionary palettes; - Dictionary indices; - Dictionary allowsMods; + readonly Dictionary palettes = new Dictionary(); + readonly Dictionary modifiablePalettes = new Dictionary(); + readonly IReadOnlyDictionary readOnlyModifiablePalettes; + readonly Dictionary indices = new Dictionary(); + readonly uint[,] buffer = new uint[Palette.Size, MaxPalettes]; public HardwarePalette() { - palettes = new Dictionary(); - indices = new Dictionary(); - allowsMods = new Dictionary(); Texture = Game.Renderer.Device.CreateTexture(); + readOnlyModifiablePalettes = modifiablePalettes.AsReadOnly(); } - public Palette GetPalette(string name) + public IPalette GetPalette(string name) { - Palette ret; - if (!palettes.TryGetValue(name,out ret)) - throw new InvalidOperationException("Palette `{0}` does not exist".F(name)); - return ret; + MutablePalette mutable; + if (modifiablePalettes.TryGetValue(name, out mutable)) + return mutable.AsReadOnly(); + ImmutablePalette immutable; + if (palettes.TryGetValue(name, out immutable)) + return immutable; + throw new InvalidOperationException("Palette `{0}` does not exist".F(name)); } public int GetPaletteIndex(string name) { int ret; - if (!indices.TryGetValue(name,out ret)) + if (!indices.TryGetValue(name, out ret)) throw new InvalidOperationException("Palette `{0}` does not exist".F(name)); return ret; } - public void AddPalette(string name, Palette p, bool allowModifiers) + public void AddPalette(string name, ImmutablePalette p, bool allowModifiers) { + if (palettes.Count >= MaxPalettes) + throw new InvalidOperationException("Limit of {0} palettes reached. Cannot add {1}.".F(MaxPalettes, name)); if (palettes.ContainsKey(name)) throw new InvalidOperationException("Palette {0} has already been defined".F(name)); + int index = palettes.Count; + indices.Add(name, index); palettes.Add(name, p); - indices.Add(name, allocated++); - allowsMods.Add(name, allowModifiers); + if (allowModifiers) + modifiablePalettes.Add(name, new MutablePalette(p)); + else + CopyPaletteToBuffer(index, p); } - uint[,] data = new uint[MaxPalettes, 256]; - public void ApplyModifiers(IEnumerable paletteMods) + public void ReplacePalette(string name, IPalette p) { - var copy = palettes.ToDictionary(p => p.Key, p => new Palette(p.Value)); - var modifiable = copy.Where(p => allowsMods[p.Key]).ToDictionary(p => p.Key, p => p.Value); - - foreach (var mod in paletteMods) - mod.AdjustPalette(modifiable); - - foreach (var pal in copy) - { - var j = indices[pal.Key]; - var c = pal.Value.Values; - for (var i = 0; i < 256; i++) - data[j,i] = c[i]; - } - - Texture.SetData(data); + if (modifiablePalettes.ContainsKey(name)) + CopyPaletteToBuffer(indices[name], modifiablePalettes[name] = new MutablePalette(p)); + else if (palettes.ContainsKey(name)) + CopyPaletteToBuffer(indices[name], palettes[name] = new ImmutablePalette(p)); + else + throw new InvalidOperationException("Palette `{0}` does not exist".F(name)); + Texture.SetData(buffer); } public void Initialize() { - ApplyModifiers(new IPaletteModifier[] {}); + CopyModifiablePalettesToBuffer(); + Texture.SetData(buffer); + } + + void CopyPaletteToBuffer(int index, IPalette p) + { + for (var i = 0; i < Palette.Size; i++) + buffer[i, index] = p[i]; + } + + void CopyModifiablePalettesToBuffer() + { + foreach (var kvp in modifiablePalettes) + CopyPaletteToBuffer(indices[kvp.Key], kvp.Value); + } + + public void ApplyModifiers(IEnumerable paletteMods) + { + foreach (var mod in paletteMods) + mod.AdjustPalette(readOnlyModifiablePalettes); + + // Update our texture with the changes. + CopyModifiablePalettesToBuffer(); + Texture.SetData(buffer); + + // Reset modified palettes back to their original colors, ready for next time. + foreach (var kvp in modifiablePalettes) + { + var originalPalette = palettes[kvp.Key]; + var modifiedPalette = kvp.Value; + for (var i = 0; i < Palette.Size; i++) + modifiedPalette[i] = originalPalette[i]; + } } } } diff --git a/OpenRA.Game/Graphics/Palette.cs b/OpenRA.Game/Graphics/Palette.cs index cd0eeec9ad..8f0689d89f 100644 --- a/OpenRA.Game/Graphics/Palette.cs +++ b/OpenRA.Game/Graphics/Palette.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2012 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 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. For more information, @@ -8,94 +8,35 @@ */ #endregion +using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Reflection; +using System.Runtime.InteropServices; namespace OpenRA.Graphics { - public class Palette + public interface IPalette { uint this[int index] { get; } } + public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); } + + public static class Palette { - public static Palette Load(string filename, int[] remap) + public const int Size = 256; + + public static Color GetColor(this IPalette palette, int index) { - using (var s = File.OpenRead(filename)) - return new Palette(s, remap); + return Color.FromArgb((int)palette[index]); } - uint[] colors; - public Color GetColor(int index) - { - return Color.FromArgb((int)colors[index]); - } - - public void SetColor(int index, Color color) - { - colors[index] = (uint)color.ToArgb(); - } - - public void SetColor(int index, uint color) - { - colors[index] = (uint)color; - } - - public uint[] Values - { - get { return colors; } - } - - public void ApplyRemap(IPaletteRemap r) - { - for (var i = 0; i < 256; i++) - colors[i] = (uint)r.GetRemappedColor(Color.FromArgb((int)colors[i]), i).ToArgb(); - } - - public Palette(Stream s, int[] remapShadow) - { - colors = new uint[256]; - - using (var reader = new BinaryReader(s)) - { - for (var i = 0; i < 256; i++) - { - var r = (byte)(reader.ReadByte() << 2); - var g = (byte)(reader.ReadByte() << 2); - var b = (byte)(reader.ReadByte() << 2); - colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b); - } - } - - colors[0] = 0; // convert black background to transparency - foreach (var i in remapShadow) - colors[i] = 140u << 24; - } - - public Palette(Palette p, IPaletteRemap r) - { - colors = (uint[])p.colors.Clone(); - ApplyRemap(r); - } - - public Palette(Palette p) - { - colors = (uint[])p.colors.Clone(); - } - - public Palette(uint[] data) - { - if (data.Length != 256) - throw new InvalidDataException("Attempting to create palette with incorrect array size"); - colors = (uint[])data.Clone(); - } - - public ColorPalette AsSystemPalette() + public static ColorPalette AsSystemPalette(this IPalette palette) { ColorPalette pal; using (var b = new Bitmap(1, 1, PixelFormat.Format8bppIndexed)) pal = b.Palette; - for (var i = 0; i < 256; i++) - pal.Entries[i] = GetColor(i); + for (var i = 0; i < Size; i++) + pal.Entries[i] = palette.GetColor(i); // hack around a mono bug -- the palette flags get set wrong. if (Platform.CurrentPlatform != PlatformType.Windows) @@ -105,22 +46,116 @@ namespace OpenRA.Graphics return pal; } - public Bitmap AsBitmap() + public static Bitmap AsBitmap(this IPalette palette) { - var b = new Bitmap(256, 1, PixelFormat.Format32bppArgb); + var b = new Bitmap(Size, 1, PixelFormat.Format32bppArgb); var data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); - unsafe - { - var c = (uint*)data.Scan0; - for (var x = 0; x < 256; x++) - *(c + x) = colors[x]; - } - + var temp = new uint[Palette.Size]; + for (int i = 0; i < temp.Length; i++) + temp[i] = palette[i]; + Marshal.Copy((int[])(object)temp, 0, data.Scan0, Size); b.UnlockBits(data); return b; } + + public static IPalette AsReadOnly(this IPalette palette) + { + if (palette is ImmutablePalette) + return palette; + return new ReadOnlyPalette(palette); + } + + class ReadOnlyPalette : IPalette + { + IPalette palette; + public ReadOnlyPalette(IPalette palette) { this.palette = palette; } + public uint this[int index] { get { return palette[index]; } } + } } - public interface IPaletteRemap { Color GetRemappedColor(Color original, int index); } + public class ImmutablePalette : IPalette + { + readonly uint[] colors = new uint[Palette.Size]; + + public uint this[int index] + { + get { return colors[index]; } + } + + public ImmutablePalette(string filename, int[] remap) + { + using (var s = File.OpenRead(filename)) + LoadFromStream(s, remap); + } + + public ImmutablePalette(Stream s, int[] remapShadow) + { + LoadFromStream(s, remapShadow); + } + + void LoadFromStream(Stream s, int[] remapShadow) + { + using (var reader = new BinaryReader(s)) + for (var i = 0; i < Palette.Size; i++) + { + var r = (byte)(reader.ReadByte() << 2); + var g = (byte)(reader.ReadByte() << 2); + var b = (byte)(reader.ReadByte() << 2); + colors[i] = (uint)((255 << 24) | (r << 16) | (g << 8) | b); + } + + colors[0] = 0; // Convert black background to transparency. + foreach (var i in remapShadow) + colors[i] = 140u << 24; + } + + public ImmutablePalette(IPalette p, IPaletteRemap r) + : this(p) + { + for (var i = 0; i < Palette.Size; i++) + colors[i] = (uint)r.GetRemappedColor(this.GetColor(i), i).ToArgb(); + } + + public ImmutablePalette(IPalette p) + { + for (int i = 0; i < Palette.Size; i++) + colors[i] = p[i]; + } + + public ImmutablePalette(IEnumerable sourceColors) + { + var i = 0; + foreach (var sourceColor in sourceColors) + colors[i++] = sourceColor; + } + } + + public class MutablePalette : IPalette + { + readonly uint[] colors = new uint[Palette.Size]; + + public uint this[int index] + { + get { return colors[index]; } + set { colors[index] = value; } + } + + public MutablePalette(IPalette p) + { + for (int i = 0; i < Palette.Size; i++) + this[i] = p[i]; + } + + public void SetColor(int index, Color color) + { + colors[index] = (uint)color.ToArgb(); + } + + public void ApplyRemap(IPaletteRemap r) + { + for (var i = 0; i < Palette.Size; i++) + colors[i] = (uint)r.GetRemappedColor(this.GetColor(i), i).ToArgb(); + } + } } diff --git a/OpenRA.Game/Graphics/Sheet.cs b/OpenRA.Game/Graphics/Sheet.cs index cefac9e7de..893d585300 100644 --- a/OpenRA.Game/Graphics/Sheet.cs +++ b/OpenRA.Game/Graphics/Sheet.cs @@ -96,7 +96,7 @@ namespace OpenRA.Graphics return bitmap; } - public Bitmap AsBitmap(TextureChannel channel, Palette pal) + public Bitmap AsBitmap(TextureChannel channel, IPalette pal) { var d = Data; var dataStride = 4 * Size.Width; @@ -115,7 +115,7 @@ namespace OpenRA.Graphics for (var x = 0; x < Size.Width; x++) { var paletteIndex = d[dataRowIndex + 4 * x]; - colors[bdRowIndex + x] = pal.Values[paletteIndex]; + colors[bdRowIndex + x] = pal[paletteIndex]; } } } diff --git a/OpenRA.Game/Graphics/WorldRenderer.cs b/OpenRA.Game/Graphics/WorldRenderer.cs index f5f297a7e5..a92a1f9485 100644 --- a/OpenRA.Game/Graphics/WorldRenderer.cs +++ b/OpenRA.Game/Graphics/WorldRenderer.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * Copyright 2007-2014 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. For more information, @@ -12,7 +12,6 @@ using System; using System.Collections.Generic; using System.Drawing; using System.Linq; -using OpenRA.Primitives; using OpenRA.Traits; namespace OpenRA.Graphics @@ -21,8 +20,8 @@ namespace OpenRA.Graphics { public readonly string Name; public readonly int Index; - public readonly Palette Palette; - public PaletteReference(string name, int index, Palette palette) + public IPalette Palette { get; internal set; } + public PaletteReference(string name, int index, IPalette palette) { Name = name; Index = index; @@ -36,10 +35,10 @@ namespace OpenRA.Graphics public readonly Theater Theater; public Viewport Viewport { get; private set; } - internal readonly TerrainRenderer terrainRenderer; - internal readonly HardwarePalette palette; - internal Cache palettes; - Lazy devTrait; + readonly TerrainRenderer terrainRenderer; + readonly HardwarePalette palette; + readonly Dictionary palettes; + readonly Lazy devTrait; internal WorldRenderer(World world) { @@ -47,9 +46,9 @@ namespace OpenRA.Graphics Viewport = new Viewport(this, world.Map); palette = new HardwarePalette(); - palettes = new Cache(CreatePaletteReference); - foreach (var pal in world.traitDict.ActorsWithTrait()) - pal.Trait.InitPalette(this); + palettes = new Dictionary(); + foreach (var pal in world.traitDict.ActorsWithTrait()) + pal.Trait.LoadPalettes(this); palette.Initialize(); @@ -62,14 +61,13 @@ namespace OpenRA.Graphics PaletteReference CreatePaletteReference(string name) { var pal = palette.GetPalette(name); - if (pal == null) - throw new InvalidOperationException("Palette `{0}` does not exist".F(name)); - return new PaletteReference(name, palette.GetPaletteIndex(name), pal); } - public PaletteReference Palette(string name) { return palettes[name]; } - public void AddPalette(string name, Palette pal, bool allowModifiers) { palette.AddPalette(name, pal, allowModifiers); } + public PaletteReference Palette(string name) { return palettes.GetOrAdd(name, CreatePaletteReference); } + public void AddPalette(string name, ImmutablePalette pal) { palette.AddPalette(name, pal, false); } + public void AddPalette(string name, ImmutablePalette pal, bool allowModifiers) { palette.AddPalette(name, pal, allowModifiers); } + public void ReplacePalette(string name, IPalette pal) { palette.ReplacePalette(name, pal); palettes[name].Palette = pal; } List GenerateRenderables() { diff --git a/OpenRA.Game/Primitives/ReadOnlyDictionary.cs b/OpenRA.Game/Primitives/ReadOnlyDictionary.cs index f4cb20e686..dd6af84646 100644 --- a/OpenRA.Game/Primitives/ReadOnlyDictionary.cs +++ b/OpenRA.Game/Primitives/ReadOnlyDictionary.cs @@ -32,6 +32,14 @@ namespace OpenRA bool TryGetValue(TKey key, out TValue value); } + public static class ReadOnlyDictionary + { + public static IReadOnlyDictionary AsReadOnly(this IDictionary dict) + { + return dict as IReadOnlyDictionary ?? new ReadOnlyDictionary(dict); + } + } + /// /// A minimal read only dictionary for .NET 4 implemented as a wrapper /// around an IDictionary. diff --git a/OpenRA.Game/Traits/Player/FixedColorPalette.cs b/OpenRA.Game/Traits/Player/FixedColorPalette.cs index 8eb15423f5..9635e71dbd 100644 --- a/OpenRA.Game/Traits/Player/FixedColorPalette.cs +++ b/OpenRA.Game/Traits/Player/FixedColorPalette.cs @@ -31,7 +31,7 @@ namespace OpenRA.Traits public object Create(ActorInitializer init) { return new FixedColorPalette(this); } } - public class FixedColorPalette : IPalette + public class FixedColorPalette : ILoadsPalettes { readonly FixedColorPaletteInfo info; @@ -40,10 +40,10 @@ namespace OpenRA.Traits this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { var remap = new PlayerColorRemap(info.RemapIndex, info.Color, info.Ramp); - wr.AddPalette(info.Name, new Palette(wr.Palette(info.Base).Palette, remap), info.AllowModifiers); + wr.AddPalette(info.Name, new ImmutablePalette(wr.Palette(info.Base).Palette, remap), info.AllowModifiers); } } } diff --git a/OpenRA.Game/Traits/Player/PlayerColorPalette.cs b/OpenRA.Game/Traits/Player/PlayerColorPalette.cs index 43e0f48bdb..58d93f9a00 100644 --- a/OpenRA.Game/Traits/Player/PlayerColorPalette.cs +++ b/OpenRA.Game/Traits/Player/PlayerColorPalette.cs @@ -29,7 +29,7 @@ namespace OpenRA.Traits public object Create(ActorInitializer init) { return new PlayerColorPalette(init.self.Owner, this); } } - public class PlayerColorPalette : IPalette + public class PlayerColorPalette : ILoadsPalettes { readonly Player owner; readonly PlayerColorPaletteInfo info; @@ -40,10 +40,10 @@ namespace OpenRA.Traits this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { var remap = new PlayerColorRemap(info.RemapIndex, owner.Color, info.Ramp); - wr.AddPalette(info.BaseName + owner.InternalName, new Palette(wr.Palette(info.BasePalette).Palette, remap), info.AllowModifiers); + wr.AddPalette(info.BaseName + owner.InternalName, new ImmutablePalette(wr.Palette(info.BasePalette).Palette, remap), info.AllowModifiers); } } } diff --git a/OpenRA.Game/Traits/Player/PlayerHighlightPalette.cs b/OpenRA.Game/Traits/Player/PlayerHighlightPalette.cs index c14de183dc..3f991944c9 100644 --- a/OpenRA.Game/Traits/Player/PlayerHighlightPalette.cs +++ b/OpenRA.Game/Traits/Player/PlayerHighlightPalette.cs @@ -9,6 +9,7 @@ #endregion using System.Drawing; +using System.Linq; using OpenRA.Graphics; namespace OpenRA.Traits @@ -22,7 +23,7 @@ namespace OpenRA.Traits public object Create(ActorInitializer init) { return new PlayerHighlightPalette(init.self.Owner, this); } } - public class PlayerHighlightPalette : IPalette + public class PlayerHighlightPalette : ILoadsPalettes { readonly Player owner; readonly PlayerHighlightPaletteInfo info; @@ -33,10 +34,10 @@ namespace OpenRA.Traits this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { var argb = (uint)Color.FromArgb(128, owner.Color.RGB).ToArgb(); - wr.AddPalette(info.BaseName + owner.InternalName, new Palette(Exts.MakeArray(256, i => i == 0 ? 0 : argb)), false); + wr.AddPalette(info.BaseName + owner.InternalName, new ImmutablePalette(Enumerable.Range(0, Palette.Size).Select(i => i == 0 ? 0 : argb))); } } } diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index 8b179e4dab..ae952393bb 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -150,8 +150,8 @@ namespace OpenRA.Traits public interface IDamageModifier { float GetDamageModifier(Actor attacker, WarheadInfo warhead); } public interface ISpeedModifier { decimal GetSpeedModifier(); } public interface IFirepowerModifier { float GetFirepowerModifier(); } - public interface IPalette { void InitPalette(WorldRenderer wr); } - public interface IPaletteModifier { void AdjustPalette(Dictionary b); } + public interface ILoadsPalettes { void LoadPalettes(WorldRenderer wr); } + public interface IPaletteModifier { void AdjustPalette(IReadOnlyDictionary b); } public interface IPips { IEnumerable GetPips(Actor self); } public interface ITags { IEnumerable GetTags(); } public interface ISelectionBar { float GetValue(); Color GetColor(); } diff --git a/OpenRA.Mods.D2k/FogPaletteFromR8.cs b/OpenRA.Mods.D2k/FogPaletteFromR8.cs index 35aa81c048..2fb6793777 100644 --- a/OpenRA.Mods.D2k/FogPaletteFromR8.cs +++ b/OpenRA.Mods.D2k/FogPaletteFromR8.cs @@ -29,19 +29,19 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new FogPaletteFromR8(this); } } - class FogPaletteFromR8 : IPalette + class FogPaletteFromR8 : ILoadsPalettes { readonly FogPaletteFromR8Info info; public FogPaletteFromR8(FogPaletteFromR8Info info) { this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { - var colors = new uint[256]; + var colors = new uint[Palette.Size]; using (var s = GlobalFileSystem.Open(info.Filename)) { s.Seek(info.Offset, SeekOrigin.Begin); - for (var i = 0; i < 256; i++) + for (var i = 0; i < Palette.Size; i++) { var packed = s.ReadUInt16(); @@ -53,7 +53,7 @@ namespace OpenRA.Mods.RA } } - wr.AddPalette(info.Name, new Palette(colors), info.AllowModifiers); + wr.AddPalette(info.Name, new ImmutablePalette(colors), info.AllowModifiers); } } } diff --git a/OpenRA.Mods.D2k/PaletteFromR8.cs b/OpenRA.Mods.D2k/PaletteFromR8.cs index c878623e30..45df340ec2 100644 --- a/OpenRA.Mods.D2k/PaletteFromR8.cs +++ b/OpenRA.Mods.D2k/PaletteFromR8.cs @@ -29,19 +29,19 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new PaletteFromR8(this); } } - class PaletteFromR8 : IPalette + class PaletteFromR8 : ILoadsPalettes { readonly PaletteFromR8Info info; public PaletteFromR8(PaletteFromR8Info info) { this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { - var colors = new uint[256]; + var colors = new uint[Palette.Size]; using (var s = GlobalFileSystem.Open(info.Filename)) { s.Seek(info.Offset, SeekOrigin.Begin); - for (var i = 0; i < 256; i++) + for (var i = 0; i < Palette.Size; i++) { var packed = s.ReadUInt16(); colors[i] = (uint)((255 << 24) | ((packed & 0xF800) << 8) | ((packed & 0x7E0) << 5) | ((packed & 0x1f) << 3)); @@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA } } - wr.AddPalette(info.Name, new Palette(colors), info.AllowModifiers); + wr.AddPalette(info.Name, new ImmutablePalette(colors), info.AllowModifiers); } } } diff --git a/OpenRA.Mods.D2k/PaletteFromScaledPalette.cs b/OpenRA.Mods.D2k/PaletteFromScaledPalette.cs index a5fe8f4af1..ab8a0e0da6 100644 --- a/OpenRA.Mods.D2k/PaletteFromScaledPalette.cs +++ b/OpenRA.Mods.D2k/PaletteFromScaledPalette.cs @@ -35,15 +35,15 @@ namespace OpenRA.Mods.D2k public object Create(ActorInitializer init) { return new PaletteFromScaledPalette(this); } } - class PaletteFromScaledPalette : IPalette + class PaletteFromScaledPalette : ILoadsPalettes { readonly PaletteFromScaledPaletteInfo info; public PaletteFromScaledPalette(PaletteFromScaledPaletteInfo info) { this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { var remap = new ScaledPaletteRemap(info.Scale, info.Offset); - wr.AddPalette(info.Name, new Palette(wr.Palette(info.BasePalette).Palette, remap), info.AllowModifiers); + wr.AddPalette(info.Name, new ImmutablePalette(wr.Palette(info.BasePalette).Palette, remap), info.AllowModifiers); } } diff --git a/OpenRA.Mods.RA/ChronoshiftPaletteEffect.cs b/OpenRA.Mods.RA/ChronoshiftPaletteEffect.cs index 6dd2d35ef0..9565e37892 100644 --- a/OpenRA.Mods.RA/ChronoshiftPaletteEffect.cs +++ b/OpenRA.Mods.RA/ChronoshiftPaletteEffect.cs @@ -33,16 +33,16 @@ namespace OpenRA.Mods.RA remainingFrames--; } - public void AdjustPalette(Dictionary palettes) + public void AdjustPalette(IReadOnlyDictionary palettes) { if (remainingFrames == 0) return; var frac = (float)remainingFrames / chronoEffectLength; - + foreach (var pal in palettes) { - for (var x = 0; x < 256; x++) + for (var x = 0; x < Palette.Size; x++) { var orig = pal.Value.GetColor(x); var lum = (int)(255 * orig.GetBrightness()); diff --git a/OpenRA.Mods.RA/CloakPaletteEffect.cs b/OpenRA.Mods.RA/CloakPaletteEffect.cs index b8dfd61cd4..d7da7419b6 100644 --- a/OpenRA.Mods.RA/CloakPaletteEffect.cs +++ b/OpenRA.Mods.RA/CloakPaletteEffect.cs @@ -15,7 +15,7 @@ using OpenRA.Traits; namespace OpenRA.Mods.RA { - public class CloakPaletteEffectInfo : TraitInfo {} + public class CloakPaletteEffectInfo : TraitInfo { } public class CloakPaletteEffect : IPaletteModifier, ITick { @@ -29,23 +29,22 @@ namespace OpenRA.Mods.RA Color.FromArgb(178, 205, 250, 220), }; - public void AdjustPalette(Dictionary b) + public void AdjustPalette(IReadOnlyDictionary b) { var i = (int)t; var p = b[paletteName]; - for (var j = 0; j < colors.Length; j++ ) + for (var j = 0; j < colors.Length; j++) { - var k = (i+j) % 16 + 0xb0; - p.SetColor(k, colors[j]); + var k = (i + j) % 16 + 0xb0; + p.SetColor(k, colors[j]); } } - public void Tick (Actor self) + public void Tick(Actor self) { t += 0.25f; if (t >= 256) t = 0; } } } - diff --git a/OpenRA.Mods.RA/LightPaletteRotator.cs b/OpenRA.Mods.RA/LightPaletteRotator.cs index 34cbba5828..49033f0e48 100644 --- a/OpenRA.Mods.RA/LightPaletteRotator.cs +++ b/OpenRA.Mods.RA/LightPaletteRotator.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.RA [Desc("Palette effect used for blinking \"animations\" on actors.")] class LightPaletteRotatorInfo : ITraitInfo { - public readonly string[] ExcludePalettes = {}; + public readonly string[] ExcludePalettes = { }; public object Create(ActorInitializer init) { return new LightPaletteRotator(this); } } @@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA this.info = info; } - public void AdjustPalette(Dictionary palettes) + public void AdjustPalette(IReadOnlyDictionary palettes) { foreach (var pal in palettes) { @@ -49,7 +49,7 @@ namespace OpenRA.Mods.RA if (rotate > 9) rotate = 18 - rotate; - pal.Value.SetColor(0x67, pal.Value.GetColor(230+rotate)); + pal.Value.SetColor(0x67, pal.Value.GetColor(230 + rotate)); } } } diff --git a/OpenRA.Mods.RA/MenuPaletteEffect.cs b/OpenRA.Mods.RA/MenuPaletteEffect.cs index 1a1060ad2e..feee5ea158 100644 --- a/OpenRA.Mods.RA/MenuPaletteEffect.cs +++ b/OpenRA.Mods.RA/MenuPaletteEffect.cs @@ -66,24 +66,24 @@ namespace OpenRA.Mods.RA } } - public void AdjustPalette(Dictionary palettes) + public void AdjustPalette(IReadOnlyDictionary palettes) { if (to == EffectType.None && remainingFrames == 0) return; - foreach (var pal in palettes) + foreach (var pal in palettes.Values) { - for (var x = 0; x < 256; x++) + for (var x = 0; x < Palette.Size; x++) { - var orig = pal.Value.GetColor(x); + var orig = pal.GetColor(x); var t = ColorForEffect(to, orig); if (remainingFrames == 0) - pal.Value.SetColor(x, t); + pal.SetColor(x, t); else { var f = ColorForEffect(from, orig); - pal.Value.SetColor(x, Exts.ColorLerp((float)remainingFrames / Info.FadeLength, t, f)); + pal.SetColor(x, Exts.ColorLerp((float)remainingFrames / Info.FadeLength, t, f)); } } } diff --git a/OpenRA.Mods.RA/NukePaletteEffect.cs b/OpenRA.Mods.RA/NukePaletteEffect.cs index fede11b76a..b028c06757 100644 --- a/OpenRA.Mods.RA/NukePaletteEffect.cs +++ b/OpenRA.Mods.RA/NukePaletteEffect.cs @@ -33,7 +33,7 @@ namespace OpenRA.Mods.RA remainingFrames--; } - public void AdjustPalette(Dictionary palettes) + public void AdjustPalette(IReadOnlyDictionary palettes) { if (remainingFrames == 0) return; @@ -42,11 +42,11 @@ namespace OpenRA.Mods.RA foreach (var pal in palettes) { - for (var x = 0; x < 256; x++) + for (var x = 0; x < Palette.Size; x++) { var orig = pal.Value.GetColor(x); var white = Color.FromArgb(orig.A, 255, 255, 255); - pal.Value.SetColor(x, Exts.ColorLerp(frac,orig,white)); + pal.Value.SetColor(x, Exts.ColorLerp(frac, orig, white)); } } } diff --git a/OpenRA.Mods.RA/PaletteFromCurrentTileset.cs b/OpenRA.Mods.RA/PaletteFromCurrentTileset.cs index 641a01cc72..3c1612db78 100644 --- a/OpenRA.Mods.RA/PaletteFromCurrentTileset.cs +++ b/OpenRA.Mods.RA/PaletteFromCurrentTileset.cs @@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new PaletteFromCurrentTileset(init.world, this); } } - class PaletteFromCurrentTileset : IPalette + class PaletteFromCurrentTileset : ILoadsPalettes { readonly World world; readonly PaletteFromCurrentTilesetInfo info; @@ -37,9 +37,9 @@ namespace OpenRA.Mods.RA this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { - wr.AddPalette(info.Name, new Palette(GlobalFileSystem.Open(world.TileSet.Palette), info.ShadowIndex), info.AllowModifiers); + wr.AddPalette(info.Name, new ImmutablePalette(GlobalFileSystem.Open(world.TileSet.Palette), info.ShadowIndex), info.AllowModifiers); } } } diff --git a/OpenRA.Mods.RA/PaletteFromFile.cs b/OpenRA.Mods.RA/PaletteFromFile.cs index ddf4f98e83..ea6fab6284 100644 --- a/OpenRA.Mods.RA/PaletteFromFile.cs +++ b/OpenRA.Mods.RA/PaletteFromFile.cs @@ -29,7 +29,7 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new PaletteFromFile(init.world, this); } } - class PaletteFromFile : IPalette + class PaletteFromFile : ILoadsPalettes { readonly World world; readonly PaletteFromFileInfo info; @@ -39,10 +39,10 @@ namespace OpenRA.Mods.RA this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { if (info.Tileset == null || info.Tileset.ToLowerInvariant() == world.Map.Tileset.ToLowerInvariant()) - wr.AddPalette(info.Name, new Palette(GlobalFileSystem.Open(info.Filename), info.ShadowIndex), info.AllowModifiers); + wr.AddPalette(info.Name, new ImmutablePalette(GlobalFileSystem.Open(info.Filename), info.ShadowIndex), info.AllowModifiers); } public string Filename diff --git a/OpenRA.Mods.RA/PaletteFromRGBA.cs b/OpenRA.Mods.RA/PaletteFromRGBA.cs index 190c5667e9..6e212314ff 100644 --- a/OpenRA.Mods.RA/PaletteFromRGBA.cs +++ b/OpenRA.Mods.RA/PaletteFromRGBA.cs @@ -8,6 +8,7 @@ */ #endregion +using System.Linq; using OpenRA.Graphics; using OpenRA.Traits; @@ -33,7 +34,7 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new PaletteFromRGBA(init.world, this); } } - class PaletteFromRGBA : IPalette + class PaletteFromRGBA : ILoadsPalettes { readonly World world; readonly PaletteFromRGBAInfo info; @@ -43,14 +44,14 @@ namespace OpenRA.Mods.RA this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { // Enable palette only for a specific tileset if (info.Tileset != null && info.Tileset.ToLowerInvariant() != world.Map.Tileset.ToLowerInvariant()) return; var c = (uint)((info.A << 24) | (info.R << 16) | (info.G << 8) | info.B); - wr.AddPalette(info.Name, new Palette(Exts.MakeArray(256, i => (i == 0) ? 0 : c)), info.AllowModifiers); + wr.AddPalette(info.Name, new ImmutablePalette(Enumerable.Range(0, Palette.Size).Select(i => (i == 0) ? 0 : c)), info.AllowModifiers); } } } diff --git a/OpenRA.Mods.RA/PlayerPaletteFromCurrentTileset.cs b/OpenRA.Mods.RA/PlayerPaletteFromCurrentTileset.cs index 6e42aa0722..4f8b50cce2 100644 --- a/OpenRA.Mods.RA/PlayerPaletteFromCurrentTileset.cs +++ b/OpenRA.Mods.RA/PlayerPaletteFromCurrentTileset.cs @@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new PlayerPaletteFromCurrentTileset(init.world, this); } } - class PlayerPaletteFromCurrentTileset : IPalette + class PlayerPaletteFromCurrentTileset : ILoadsPalettes { readonly World world; readonly PlayerPaletteFromCurrentTilesetInfo info; @@ -37,10 +37,10 @@ namespace OpenRA.Mods.RA this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { var filename = world.TileSet.PlayerPalette ?? world.TileSet.Palette; - wr.AddPalette(info.Name, new Palette(GlobalFileSystem.Open(filename), info.ShadowIndex), info.AllowModifiers); + wr.AddPalette(info.Name, new ImmutablePalette(GlobalFileSystem.Open(filename), info.ShadowIndex), info.AllowModifiers); } } } diff --git a/OpenRA.Mods.RA/ShroudPalette.cs b/OpenRA.Mods.RA/ShroudPalette.cs index 3e1ec4e83f..6b75e92db3 100644 --- a/OpenRA.Mods.RA/ShroudPalette.cs +++ b/OpenRA.Mods.RA/ShroudPalette.cs @@ -9,6 +9,7 @@ #endregion using System.Drawing; +using System.Linq; using OpenRA.Graphics; using OpenRA.Traits; @@ -26,16 +27,16 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new ShroudPalette(this); } } - class ShroudPalette : IPalette + class ShroudPalette : ILoadsPalettes { readonly ShroudPaletteInfo info; public ShroudPalette(ShroudPaletteInfo info) { this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { var c = info.Fog ? Fog : Shroud; - wr.AddPalette(info.Name, new Palette(Exts.MakeArray(256, i => (uint)c[i % 8].ToArgb())), false); + wr.AddPalette(info.Name, new ImmutablePalette(Enumerable.Range(0, Palette.Size).Select(i => (uint)c[i % 8].ToArgb()))); } static Color[] Fog = new[] { diff --git a/OpenRA.Mods.RA/VoxelNormalsPalette.cs b/OpenRA.Mods.RA/VoxelNormalsPalette.cs index 9c18029495..76227f05a1 100644 --- a/OpenRA.Mods.RA/VoxelNormalsPalette.cs +++ b/OpenRA.Mods.RA/VoxelNormalsPalette.cs @@ -22,7 +22,7 @@ namespace OpenRA.Mods.RA public object Create(ActorInitializer init) { return new VoxelNormalsPalette(this); } } - public class VoxelNormalsPalette : IPalette + public class VoxelNormalsPalette : ILoadsPalettes { readonly VoxelNormalsPaletteInfo info; @@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { // Rotate vectors to expected orientation // Voxel coordinates are x=forward, y=right, z=up @@ -40,7 +40,7 @@ namespace OpenRA.Mods.RA // Map normals into color range // Introduces a maximum error of ~0.5% - var data = new uint[256]; + var data = new uint[Palette.Size]; for (var i = 0; i < n.Length / 3; i++) { data[i] = 0xFF000000; @@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA } } - wr.AddPalette(info.Name, new Palette(data), false); + wr.AddPalette(info.Name, new ImmutablePalette(data)); } // Normal vector tables from http://www.sleipnirstuff.com/forum/viewtopic.php?t=8048 diff --git a/OpenRA.Mods.RA/WaterPaletteRotation.cs b/OpenRA.Mods.RA/WaterPaletteRotation.cs index 11ded18ce4..9437b64384 100644 --- a/OpenRA.Mods.RA/WaterPaletteRotation.cs +++ b/OpenRA.Mods.RA/WaterPaletteRotation.cs @@ -18,7 +18,7 @@ namespace OpenRA.Mods.RA [Desc("Palette effect used for sprinkle \"animations\" on terrain tiles.")] class WaterPaletteRotationInfo : ITraitInfo { - public readonly string[] ExcludePalettes = {}; + public readonly string[] ExcludePalettes = { }; public object Create(ActorInitializer init) { return new WaterPaletteRotation(init.world, this); } } @@ -38,23 +38,26 @@ namespace OpenRA.Mods.RA public void Tick(Actor self) { t += .25f; } - static uint[] temp = new uint[7]; /* allocating this on the fly actually hurts our profile */ + uint[] temp = new uint[7]; /* allocating this on the fly actually hurts our profile */ - public void AdjustPalette(Dictionary palettes) + public void AdjustPalette(IReadOnlyDictionary palettes) { - foreach (var pal in palettes) + var rotate = (int)t % 7; + if (rotate == 0) + return; + + foreach (var kvp in palettes) { - if (info.ExcludePalettes.Contains(pal.Key)) + if (info.ExcludePalettes.Contains(kvp.Key)) continue; - var colors = pal.Value.Values; - var rotate = (int)t % 7; + var palette = kvp.Value; for (var i = 0; i < 7; i++) - temp[(rotate + i) % 7] = colors[world.TileSet.WaterPaletteRotationBase + i]; + temp[(rotate + i) % 7] = palette[world.TileSet.WaterPaletteRotationBase + i]; for (var i = 0; i < 7; i++) - pal.Value.SetColor(world.TileSet.WaterPaletteRotationBase + i, temp[i]); + palette[world.TileSet.WaterPaletteRotationBase + i] = temp[i]; } } } diff --git a/OpenRA.Mods.RA/Widgets/ColorPreviewManagerWidget.cs b/OpenRA.Mods.RA/Widgets/ColorPreviewManagerWidget.cs index 76ee3a0f7a..dcb2d7b64f 100755 --- a/OpenRA.Mods.RA/Widgets/ColorPreviewManagerWidget.cs +++ b/OpenRA.Mods.RA/Widgets/ColorPreviewManagerWidget.cs @@ -16,14 +16,14 @@ namespace OpenRA.Mods.RA.Widgets { public class ColorPreviewManagerWidget : Widget { - public readonly string Palette = "colorpicker"; + public readonly string PaletteName = "colorpicker"; public readonly int[] RemapIndices = ChromeMetrics.Get("ColorPickerRemapIndices"); public readonly float Ramp = 0.05f; public HSLColor Color; HSLColor cachedColor; WorldRenderer worldRenderer; - Palette preview; + IPalette preview; [ObjectCreator.UseCtor] public ColorPreviewManagerWidget(WorldRenderer worldRenderer) @@ -34,17 +34,18 @@ namespace OpenRA.Mods.RA.Widgets public override void Initialize(WidgetArgs args) { base.Initialize(args); - preview = worldRenderer.Palette(Palette).Palette; + preview = worldRenderer.Palette(PaletteName).Palette; } public override void Tick() { if (cachedColor == Color) return; - - preview.ApplyRemap(new PlayerColorRemap(RemapIndices, Color, Ramp)); cachedColor = Color; + + var newPalette = new MutablePalette(preview); + newPalette.ApplyRemap(new PlayerColorRemap(RemapIndices, Color, Ramp)); + worldRenderer.ReplacePalette(PaletteName, newPalette); } } } - diff --git a/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs index 95b7af646b..c7bff743e5 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/AssetBrowserLogic.cs @@ -95,7 +95,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic var colorDropdown = panel.GetOrNull("COLOR"); if (colorDropdown != null) { - colorDropdown.IsDisabled = () => currentPalette != colorPreview.Palette; + colorDropdown.IsDisabled = () => currentPalette != colorPreview.PaletteName; colorDropdown.OnMouseDown = _ => ShowColorDropDown(colorDropdown, colorPreview, world); panel.Get("COLORBLOCK").GetColor = () => Game.Settings.Player.Color.RGB; } diff --git a/OpenRA.Mods.TS/ShroudPalette.cs b/OpenRA.Mods.TS/ShroudPalette.cs index 0a2a78b946..840669c298 100644 --- a/OpenRA.Mods.TS/ShroudPalette.cs +++ b/OpenRA.Mods.TS/ShroudPalette.cs @@ -9,8 +9,7 @@ #endregion using System; -using System.Drawing; -using OpenRA.FileFormats; +using System.Linq; using OpenRA.Graphics; using OpenRA.Traits; @@ -25,13 +24,13 @@ namespace OpenRA.Mods.TS public object Create(ActorInitializer init) { return new TSShroudPalette(this); } } - class TSShroudPalette : IPalette + class TSShroudPalette : ILoadsPalettes { readonly TSShroudPaletteInfo info; public TSShroudPalette(TSShroudPaletteInfo info) { this.info = info; } - public void InitPalette(WorldRenderer wr) + public void LoadPalettes(WorldRenderer wr) { Func makeColor = i => { @@ -40,7 +39,7 @@ namespace OpenRA.Mods.TS return 0; }; - wr.AddPalette(info.Name, new Palette(Exts.MakeArray(256, i => makeColor(i))), false); + wr.AddPalette(info.Name, new ImmutablePalette(Enumerable.Range(0, Palette.Size).Select(i => makeColor(i)))); } } } diff --git a/OpenRA.TilesetBuilder/FormBuilder.cs b/OpenRA.TilesetBuilder/FormBuilder.cs index 86ed83f1ac..b89d17eefe 100644 --- a/OpenRA.TilesetBuilder/FormBuilder.cs +++ b/OpenRA.TilesetBuilder/FormBuilder.cs @@ -25,7 +25,7 @@ namespace OpenRA.TilesetBuilder string srcfile; int size; public TerrainTypeInfo[] TerrainType; - public Palette TerrainPalette; + public ImmutablePalette TerrainPalette; public bool PaletteFromImage = true; public string PaletteFile = ""; public string ImageFile = ""; @@ -60,7 +60,7 @@ namespace OpenRA.TilesetBuilder if (!PaletteFromImage) { - TerrainPalette = Palette.Load(PaletteFile, shadowIndex); + TerrainPalette = new ImmutablePalette(PaletteFile, shadowIndex); rbitmap.Palette = TerrainPalette.AsSystemPalette(); } @@ -247,8 +247,8 @@ namespace OpenRA.TilesetBuilder static string ExportPalette(List p, string file) { - while (p.Count < 256) p.Add(Color.Black); // pad the palette out with extra blacks - var paletteData = p.Take(256).SelectMany( + while (p.Count < Palette.Size) p.Add(Color.Black); // pad the palette out with extra blacks + var paletteData = p.Take(Palette.Size).SelectMany( c => new byte[] { (byte)(c.R >> 2), (byte)(c.G >> 2), (byte)(c.B >> 2) }).ToArray(); File.WriteAllBytes(file, paletteData); return file; diff --git a/OpenRA.Utility/Command.cs b/OpenRA.Utility/Command.cs index eedf1c2f48..5994d7f3c9 100644 --- a/OpenRA.Utility/Command.cs +++ b/OpenRA.Utility/Command.cs @@ -96,7 +96,7 @@ namespace OpenRA.Utility shadowIndex[shadowIndex.Length - 3] = 4; } - var palette = Palette.Load(args[2], shadowIndex); + var palette = new ImmutablePalette(args[2], shadowIndex); ISpriteSource source; using (var stream = File.OpenRead(src)) @@ -209,16 +209,14 @@ namespace OpenRA.Utility = PlayerColorRemap.GetRemapIndex(destRemapIndex, i); // map everything else to the best match based on channel-wise distance - var srcPalette = Palette.Load(args[1].Split(':')[1], shadowIndex); - var destPalette = Palette.Load(args[2].Split(':')[1], shadowIndex); + var srcPalette = new ImmutablePalette(args[1].Split(':')[1], shadowIndex); + var destPalette = new ImmutablePalette(args[2].Split(':')[1], shadowIndex); - var fullIndexRange = Exts.MakeArray(256, x => x); - - for (var i = 0; i < 256; i++) + for (var i = 0; i < Palette.Size; i++) if (!remap.ContainsKey(i)) - remap[i] = fullIndexRange + remap[i] = Enumerable.Range(0, Palette.Size) .Where(a => !remap.ContainsValue(a)) - .MinBy(a => ColorDistance(destPalette.Values[a], srcPalette.Values[i])); + .MinBy(a => ColorDistance(destPalette[a], srcPalette[i])); var srcImage = ShpReader.Load(args[3]); diff --git a/glsl/shp.frag b/glsl/shp.frag index dbabad7184..bd4915121d 100644 --- a/glsl/shp.frag +++ b/glsl/shp.frag @@ -3,6 +3,6 @@ uniform sampler2D DiffuseTexture, Palette; void main() { vec4 x = texture2D(DiffuseTexture, gl_TexCoord[0].st); - vec2 p = vec2( dot(x, gl_TexCoord[1]), gl_TexCoord[0].p ); - gl_FragColor = texture2D(Palette,p); -} \ No newline at end of file + vec2 p = vec2(gl_TexCoord[0].p, dot(x, gl_TexCoord[1])); + gl_FragColor = texture2D(Palette, p); +} diff --git a/glsl/vxl.frag b/glsl/vxl.frag index d9d65ac2ba..c5baaeb919 100644 --- a/glsl/vxl.frag +++ b/glsl/vxl.frag @@ -7,11 +7,11 @@ uniform vec3 AmbientLight, DiffuseLight; void main() { vec4 x = texture2D(DiffuseTexture, gl_TexCoord[0].st); - vec4 color = texture2D(Palette, vec2(dot(x, gl_TexCoord[1]), PaletteRows.x)); + vec4 color = texture2D(Palette, vec2(PaletteRows.x, dot(x, gl_TexCoord[1]))); if (color.a < 0.01) discard; - vec4 normal = (2.0*texture2D(Palette, vec2(dot(x, gl_TexCoord[2]), PaletteRows.y)) - 1.0); - vec3 intensity = AmbientLight + DiffuseLight*max(dot(normal, LightDirection), 0.0); - gl_FragColor = vec4(intensity*color.rgb, color.a); + vec4 normal = (2.0 * texture2D(Palette, vec2(PaletteRows.y, dot(x, gl_TexCoord[2]))) - 1.0); + vec3 intensity = AmbientLight + DiffuseLight * max(dot(normal, LightDirection), 0.0); + gl_FragColor = vec4(intensity * color.rgb, color.a); }