Changed HardwarePalette.ApplyModifiers to be more efficient.

- Add separate ImmutablePalette and MutablePalette classes since the distinction is extremely important to HardwarePalette.
- Keep a cache of palettes in HardwarePalette to avoid reallocation them every time ApplyModifiers is called.
- Palettes that are not allowed to be modified are copied to the buffer once when added, rather than every time ApplyModifiers is called.
- The AdjustPalette method now takes a read-only dictionary to prevent the dictionary being messed with.
- Added a constant for the palette size to remove its usage as a magic number in several areas.
- The ColorPreviewManagerWidget is annoying in that it needs to actually permanently update a palette after it has been added. To allow this, HardwarePalette now allows a palette to be replaced after initialization. The WorldRenderer therefore now also updates the PaletteReference it created earlier with the new palette to prevent stale data being used elsewhere.
This commit is contained in:
RoosterDragon
2014-06-16 20:25:05 +01:00
parent 5c82fff0ef
commit 7030d8b2b6
36 changed files with 327 additions and 256 deletions

View File

@@ -33,16 +33,16 @@ namespace OpenRA.Mods.RA
remainingFrames--;
}
public void AdjustPalette(Dictionary<string,Palette> palettes)
public void AdjustPalette(IReadOnlyDictionary<string, MutablePalette> 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());

View File

@@ -15,7 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CloakPaletteEffectInfo : TraitInfo<CloakPaletteEffect> {}
public class CloakPaletteEffectInfo : TraitInfo<CloakPaletteEffect> { }
public class CloakPaletteEffect : IPaletteModifier, ITick
{
@@ -29,23 +29,22 @@ namespace OpenRA.Mods.RA
Color.FromArgb(178, 205, 250, 220),
};
public void AdjustPalette(Dictionary<string, Palette> b)
public void AdjustPalette(IReadOnlyDictionary<string, MutablePalette> 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;
}
}
}

View File

@@ -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<string,Palette> palettes)
public void AdjustPalette(IReadOnlyDictionary<string, MutablePalette> 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));
}
}
}

View File

@@ -66,24 +66,24 @@ namespace OpenRA.Mods.RA
}
}
public void AdjustPalette(Dictionary<string, Palette> palettes)
public void AdjustPalette(IReadOnlyDictionary<string, MutablePalette> 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));
}
}
}

View File

@@ -33,7 +33,7 @@ namespace OpenRA.Mods.RA
remainingFrames--;
}
public void AdjustPalette(Dictionary<string,Palette> palettes)
public void AdjustPalette(IReadOnlyDictionary<string, MutablePalette> 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));
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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[] {

View File

@@ -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

View File

@@ -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<string,Palette> palettes)
public void AdjustPalette(IReadOnlyDictionary<string, MutablePalette> 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];
}
}
}

View File

@@ -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<int[]>("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);
}
}
}

View File

@@ -95,7 +95,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var colorDropdown = panel.GetOrNull<DropDownButtonWidget>("COLOR");
if (colorDropdown != null)
{
colorDropdown.IsDisabled = () => currentPalette != colorPreview.Palette;
colorDropdown.IsDisabled = () => currentPalette != colorPreview.PaletteName;
colorDropdown.OnMouseDown = _ => ShowColorDropDown(colorDropdown, colorPreview, world);
panel.Get<ColorBlockWidget>("COLORBLOCK").GetColor = () => Game.Settings.Player.Color.RGB;
}