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:
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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[] {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user