diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index e0f52eb772..1d3b8b551f 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -29,6 +29,7 @@ namespace OpenRA { public static ModData modData; public static Settings Settings; + public static ICursor Cursor; static WorldRenderer worldRenderer; internal static OrderManager orderManager; @@ -129,6 +130,7 @@ namespace OpenRA public static event Action BeforeGameStart = () => { }; internal static void StartGame(string mapUID, bool isShellmap) { + Cursor.SetCursor(null); BeforeGameStart(); Map map; @@ -157,6 +159,7 @@ namespace OpenRA orderManager.LastTickTime = RunTime; orderManager.StartGame(); worldRenderer.RefreshPalette(); + Cursor.SetCursor("default"); GC.Collect(); } @@ -287,11 +290,33 @@ namespace OpenRA Sound.Initialize(); modData = new ModData(mod, true); + Renderer.InitializeFonts(modData.Manifest); modData.InitializeLoaders(); using (new PerfTimer("LoadMaps")) modData.MapCache.LoadMaps(); + if (Settings.Graphics.HardwareCursors) + { + try + { + Cursor = new HardwareCursor(modData.CursorProvider); + } + catch (Exception e) + { + Log.Write("debug", "Failed to initialize hardware cursors. Falling back to software cursors."); + Log.Write("debug", "Error was: " + e.Message); + + Console.WriteLine("Failed to initialize hardware cursors. Falling back to software cursors."); + Console.WriteLine("Error was: " + e.Message); + + Cursor = new SoftwareCursor(modData.CursorProvider); + Settings.Graphics.HardwareCursors = false; + } + } + else + Cursor = new SoftwareCursor(modData.CursorProvider); + PerfHistory.items["render"].hasNormalTick = false; PerfHistory.items["batches"].hasNormalTick = false; PerfHistory.items["render_widgets"].hasNormalTick = false; @@ -401,8 +426,6 @@ namespace OpenRA public static void RunAfterTick(Action a) { delayedActions.Add(a); } public static void RunAfterDelay(int delay, Action a) { delayedActions.Add(a, delay); } - static float cursorFrame = 0f; - static void InnerLogicTick(OrderManager orderManager) { var tick = RunTime; @@ -419,7 +442,7 @@ namespace OpenRA Viewport.TicksSinceLastMove += uiTickDelta / Timestep; Sync.CheckSyncUnchanged(world, Ui.Tick); - cursorFrame += 0.5f; + Cursor.Tick(); } var worldTimestep = world == null ? Timestep : world.Timestep; @@ -509,8 +532,8 @@ namespace OpenRA if (modData != null && modData.CursorProvider != null) { - var cursorName = Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default"; - modData.CursorProvider.DrawCursor(Renderer, cursorName, Viewport.LastMousePos, (int)cursorFrame); + Cursor.SetCursor(Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default"); + Cursor.Render(Renderer); } } diff --git a/OpenRA.Game/Graphics/CursorProvider.cs b/OpenRA.Game/Graphics/CursorProvider.cs index 1f1d8bdb79..f6e4143557 100644 --- a/OpenRA.Game/Graphics/CursorProvider.cs +++ b/OpenRA.Game/Graphics/CursorProvider.cs @@ -10,26 +10,21 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; using OpenRA.FileSystem; using OpenRA.Primitives; namespace OpenRA.Graphics { - public sealed class CursorProvider : IDisposable + public sealed class CursorProvider { - readonly HardwarePalette palette = new HardwarePalette(); - readonly Dictionary cursors = new Dictionary(); - readonly Cache palettes; - readonly SheetBuilder sheetBuilder; - - public static bool CursorViewportZoomed { get { return Game.Settings.Graphics.CursorDouble && Game.Settings.Graphics.PixelDouble; } } + public readonly IReadOnlyDictionary Cursors; + public readonly IReadOnlyDictionary Palettes; public CursorProvider(ModData modData) { var sequenceFiles = modData.Manifest.Cursors; - - palettes = new Cache(CreatePaletteReference); var sequences = new MiniYaml(null, sequenceFiles.Select(s => MiniYaml.FromFile(s)).Aggregate(MiniYaml.MergeLiberal)); var shadowIndex = new int[] { }; @@ -41,65 +36,35 @@ namespace OpenRA.Graphics out shadowIndex[shadowIndex.Length - 1]); } + var palettes = new Dictionary(); foreach (var p in nodesDict["Palettes"].Nodes) - palette.AddPalette(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false); + palettes.Add(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex)); - sheetBuilder = new SheetBuilder(SheetType.Indexed); - var spriteCache = new SpriteCache(modData.SpriteLoaders, new string[0], sheetBuilder); + Palettes = palettes.AsReadOnly(); + + var frameCache = new FrameCache(modData.SpriteLoaders, new string[0]); + var cursors = new Dictionary(); foreach (var s in nodesDict["Cursors"].Nodes) - LoadSequencesForCursor(spriteCache, s.Key, s.Value); - sheetBuilder.Current.ReleaseBuffer(); + foreach (var sequence in s.Value.Nodes) + cursors.Add(sequence.Key, new CursorSequence(frameCache, sequence.Key, s.Key, s.Value.Value, sequence.Value)); - palette.Initialize(); + Cursors = cursors.AsReadOnly(); } - PaletteReference CreatePaletteReference(string name) - { - var pal = palette.GetPalette(name); - return new PaletteReference(name, palette.GetPaletteIndex(name), pal); - } - - void LoadSequencesForCursor(SpriteCache cache, string cursorSrc, MiniYaml cursor) - { - foreach (var sequence in cursor.Nodes) - cursors.Add(sequence.Key, new CursorSequence(cache, cursorSrc, cursor.Value, sequence.Value)); - } + public static bool CursorViewportZoomed { get { return Game.Settings.Graphics.CursorDouble && Game.Settings.Graphics.PixelDouble; } } public bool HasCursorSequence(string cursor) { - return cursors.ContainsKey(cursor); - } - - public void DrawCursor(Renderer renderer, string cursorName, int2 lastMousePos, int cursorFrame) - { - var cursorSequence = GetCursorSequence(cursorName); - var cursorSprite = cursorSequence.GetSprite(cursorFrame); - var cursorSize = CursorViewportZoomed ? 2.0f * cursorSprite.size : cursorSprite.size; - - var cursorOffset = CursorViewportZoomed ? - (2 * cursorSequence.Hotspot) + cursorSprite.size.ToInt2() : - cursorSequence.Hotspot + (0.5f * cursorSprite.size).ToInt2(); - - renderer.SetPalette(palette); - renderer.SpriteRenderer.DrawSprite(cursorSprite, - lastMousePos - cursorOffset, - palettes[cursorSequence.Palette], - cursorSize); + return Cursors.ContainsKey(cursor); } public CursorSequence GetCursorSequence(string cursor) { - try { return cursors[cursor]; } + try { return Cursors[cursor]; } catch (KeyNotFoundException) { throw new InvalidOperationException("Cursor does not have a sequence `{0}`".F(cursor)); } } - - public void Dispose() - { - palette.Dispose(); - sheetBuilder.Dispose(); - } } } diff --git a/OpenRA.Game/Graphics/CursorSequence.cs b/OpenRA.Game/Graphics/CursorSequence.cs index 1db1f46b43..dececbdae9 100644 --- a/OpenRA.Game/Graphics/CursorSequence.cs +++ b/OpenRA.Game/Graphics/CursorSequence.cs @@ -8,47 +8,46 @@ */ #endregion +using System.Linq; + namespace OpenRA.Graphics { public class CursorSequence { - readonly int start, length; - readonly string palette; - - public int Start { get { return start; } } - public int End { get { return start + length; } } - public int Length { get { return length; } } - public string Palette { get { return palette; } } + public readonly string Name; + public readonly int Start; + public readonly int Length; + public readonly string Palette; public readonly int2 Hotspot; - Sprite[] sprites; + public readonly ISpriteFrame[] Frames; - public CursorSequence(SpriteCache cache, string cursorSrc, string palette, MiniYaml info) + public CursorSequence(FrameCache cache, string name, string cursorSrc, string palette, MiniYaml info) { - sprites = cache[cursorSrc]; var d = info.ToDictionary(); - start = Exts.ParseIntegerInvariant(d["start"].Value); - this.palette = palette; + Start = Exts.ParseIntegerInvariant(d["Start"].Value); + Palette = palette; + Name = name; - if ((d.ContainsKey("length") && d["length"].Value == "*") || (d.ContainsKey("end") && d["end"].Value == "*")) - length = sprites.Length - start; - else if (d.ContainsKey("length")) - length = Exts.ParseIntegerInvariant(d["length"].Value); - else if (d.ContainsKey("end")) - length = Exts.ParseIntegerInvariant(d["end"].Value) - start; + if ((d.ContainsKey("Length") && d["Length"].Value == "*") || (d.ContainsKey("End") && d["End"].Value == "*")) + Length = Frames.Length - Start; + else if (d.ContainsKey("Length")) + Length = Exts.ParseIntegerInvariant(d["Length"].Value); + else if (d.ContainsKey("End")) + Length = Exts.ParseIntegerInvariant(d["End"].Value) - Start; else - length = 1; + Length = 1; - if (d.ContainsKey("x")) - Exts.TryParseIntegerInvariant(d["x"].Value, out Hotspot.X); - if (d.ContainsKey("y")) - Exts.TryParseIntegerInvariant(d["y"].Value, out Hotspot.Y); - } + Frames = cache[cursorSrc] + .Skip(Start) + .Take(Length) + .ToArray(); - public Sprite GetSprite(int frame) - { - return sprites[(frame % length) + start]; + if (d.ContainsKey("X")) + Exts.TryParseIntegerInvariant(d["X"].Value, out Hotspot.X); + if (d.ContainsKey("Y")) + Exts.TryParseIntegerInvariant(d["Y"].Value, out Hotspot.Y); } } } diff --git a/OpenRA.Game/Graphics/HardwareCursor.cs b/OpenRA.Game/Graphics/HardwareCursor.cs new file mode 100644 index 0000000000..925c1c2a07 --- /dev/null +++ b/OpenRA.Game/Graphics/HardwareCursor.cs @@ -0,0 +1,138 @@ +#region Copyright & License Information +/* +* 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, +* see COPYING. +*/ +#endregion + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using OpenRA.Graphics; +using OpenRA.Primitives; + +namespace OpenRA.Graphics +{ + public class HardwareCursor : ICursor + { + readonly Dictionary hardwareCursors = new Dictionary(); + readonly CursorProvider cursorProvider; + CursorSequence cursor; + + public HardwareCursor(CursorProvider cursorProvider) + { + this.cursorProvider = cursorProvider; + + foreach (var kv in cursorProvider.Cursors) + { + var palette = cursorProvider.Palettes[kv.Value.Palette]; + var hc = kv.Value.Frames + .Select(f => CreateCursor(f, palette, kv.Key, kv.Value)) + .ToArray(); + + hardwareCursors.Add(kv.Key, hc); + } + + Update(); + } + + IHardwareCursor CreateCursor(ISpriteFrame f, ImmutablePalette palette, string name, CursorSequence sequence) + { + var hotspot = sequence.Hotspot - f.Offset.ToInt2() + new int2(f.Size) / 2; + + // Expand the frame if required to include the hotspot + var frameWidth = f.Size.Width; + var dataWidth = f.Size.Width; + var dataX = 0; + if (hotspot.X < 0) + { + dataX = -hotspot.X; + dataWidth += dataX; + hotspot.X = 0; + } + else if (hotspot.X >= frameWidth) + dataWidth = hotspot.X + 1; + + var frameHeight = f.Size.Height; + var dataHeight = f.Size.Height; + var dataY = 0; + if (hotspot.Y < 0) + { + dataY = -hotspot.Y; + dataHeight += dataY; + hotspot.Y = 0; + } + else if (hotspot.Y >= frameHeight) + dataHeight = hotspot.Y + 1; + + var data = new byte[4 * dataWidth * dataHeight]; + for (var j = 0; j < frameHeight; j++) + { + for (var i = 0; i < frameWidth; i++) + { + var bytes = BitConverter.GetBytes(palette[f.Data[j * frameWidth + i]]); + var start = 4 * ((j + dataY) * dataWidth + dataX + i); + for (var k = 0; k < 4; k++) + data[start + k] = bytes[k]; + } + } + + return Game.Renderer.Device.CreateHardwareCursor(name, new Size(dataWidth, dataHeight), data, hotspot); + } + + public void SetCursor(string cursorName) + { + if ((cursorName == null && cursor == null) || (cursor != null && cursorName == cursor.Name)) + return; + + if (cursorName == null || !cursorProvider.Cursors.TryGetValue(cursorName, out cursor)) + cursor = null; + + Update(); + } + + int frame; + int ticks; + public void Tick() + { + if (cursor == null || cursor.Length == 1) + return; + + if (++ticks > 2) + { + ticks -= 2; + frame++; + + Update(); + } + } + + void Update() + { + if (cursor == null) + Game.Renderer.Device.SetHardwareCursor(null); + else + { + if (frame >= cursor.Length) + frame = frame % cursor.Length; + + Game.Renderer.Device.SetHardwareCursor(hardwareCursors[cursor.Name][frame]); + } + } + + public void Render(Renderer renderer) { } + + public void Dispose() + { + foreach (var cursors in hardwareCursors) + foreach (var cursor in cursors.Value) + cursor.Dispose(); + + hardwareCursors.Clear(); + } + } +} \ No newline at end of file diff --git a/OpenRA.Game/Graphics/IGraphicsDevice.cs b/OpenRA.Game/Graphics/IGraphicsDevice.cs index c3ec766649..23c000bce6 100755 --- a/OpenRA.Game/Graphics/IGraphicsDevice.cs +++ b/OpenRA.Game/Graphics/IGraphicsDevice.cs @@ -32,6 +32,8 @@ namespace OpenRA IGraphicsDevice Create(Size size, WindowMode windowMode); } + public interface IHardwareCursor : IDisposable { } + public enum BlendMode : byte { None, Alpha, Additive, Subtractive, Multiply } public interface IGraphicsDevice : IDisposable @@ -61,6 +63,9 @@ namespace OpenRA void GrabWindowMouseFocus(); void ReleaseWindowMouseFocus(); + + IHardwareCursor CreateHardwareCursor(string name, Size size, byte[] data, int2 hotspot); + void SetHardwareCursor(IHardwareCursor cursor); } public interface IVertexBuffer : IDisposable diff --git a/OpenRA.Game/Graphics/SoftwareCursor.cs b/OpenRA.Game/Graphics/SoftwareCursor.cs new file mode 100644 index 0000000000..cbff0c227f --- /dev/null +++ b/OpenRA.Game/Graphics/SoftwareCursor.cs @@ -0,0 +1,102 @@ +#region Copyright & License Information +/* +* 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, +* see COPYING. +*/ +#endregion + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using OpenRA.Graphics; +using OpenRA.Primitives; + +namespace OpenRA.Graphics +{ + public interface ICursor : IDisposable + { + void Render(Renderer renderer); + void SetCursor(string cursor); + void Tick(); + } + + public class SoftwareCursor : ICursor + { + readonly HardwarePalette palette = new HardwarePalette(); + readonly Cache paletteReferences; + readonly Dictionary sprites = new Dictionary(); + readonly CursorProvider cursorProvider; + readonly SheetBuilder sheetBuilder; + + public SoftwareCursor(CursorProvider cursorProvider) + { + this.cursorProvider = cursorProvider; + + paletteReferences = new Cache(CreatePaletteReference); + foreach (var p in cursorProvider.Palettes) + palette.AddPalette(p.Key, p.Value, false); + + palette.Initialize(); + + sheetBuilder = new SheetBuilder(SheetType.Indexed); + foreach (var kv in cursorProvider.Cursors) + { + var s = kv.Value.Frames.Select(a => sheetBuilder.Add(a)).ToArray(); + sprites.Add(kv.Key, s); + } + + sheetBuilder.Current.ReleaseBuffer(); + + Game.Renderer.Device.SetHardwareCursor(null); + } + + PaletteReference CreatePaletteReference(string name) + { + var pal = palette.GetPalette(name); + return new PaletteReference(name, palette.GetPaletteIndex(name), pal); + } + + string cursorName; + public void SetCursor(string cursor) + { + cursorName = cursor; + } + + float cursorFrame; + public void Tick() + { + cursorFrame += 0.5f; + } + + public void Render(Renderer renderer) + { + if (cursorName == null) + return; + + var cursorSequence = cursorProvider.GetCursorSequence(cursorName); + var cursorSprite = sprites[cursorName][((int)cursorFrame % cursorSequence.Length)]; + var cursorSize = CursorProvider.CursorViewportZoomed ? 2.0f * cursorSprite.size : cursorSprite.size; + + var cursorOffset = CursorProvider.CursorViewportZoomed ? + (2 * cursorSequence.Hotspot) + cursorSprite.size.ToInt2() : + cursorSequence.Hotspot + (0.5f * cursorSprite.size).ToInt2(); + + renderer.SetPalette(palette); + renderer.SpriteRenderer.DrawSprite(cursorSprite, + Viewport.LastMousePos - cursorOffset, + paletteReferences[cursorSequence.Palette], + cursorSize); + } + + public void Dispose() + { + palette.Dispose(); + sheetBuilder.Dispose(); + } + } +} + diff --git a/OpenRA.Game/Graphics/SpriteLoader.cs b/OpenRA.Game/Graphics/SpriteLoader.cs index cc0ba8941d..ca0aecb36c 100644 --- a/OpenRA.Game/Graphics/SpriteLoader.cs +++ b/OpenRA.Game/Graphics/SpriteLoader.cs @@ -52,6 +52,8 @@ namespace OpenRA.Graphics public FrameCache(ISpriteLoader[] loaders, string[] exts) { + // Include extension-less version + exts = exts.Append("").ToArray(); frames = new Cache(filename => SpriteLoader.GetFrames(filename, exts, loaders)); } diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index 3715a3fbe6..d2e114f517 100644 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -90,8 +90,6 @@ namespace OpenRA VoxelLoader.Dispose(); VoxelLoader = new VoxelLoader(); - if (CursorProvider != null) - CursorProvider.Dispose(); CursorProvider = new CursorProvider(this); } @@ -175,8 +173,6 @@ namespace OpenRA MapCache.Dispose(); if (VoxelLoader != null) VoxelLoader.Dispose(); - if (CursorProvider != null) - CursorProvider.Dispose(); } } diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 3765eefdeb..6ab4068dc5 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -252,6 +252,8 @@ + + diff --git a/OpenRA.Game/Settings.cs b/OpenRA.Game/Settings.cs index cfc2fad897..78207f5c32 100644 --- a/OpenRA.Game/Settings.cs +++ b/OpenRA.Game/Settings.cs @@ -80,6 +80,7 @@ namespace OpenRA public WindowMode Mode = WindowMode.PseudoFullscreen; public int2 FullscreenSize = new int2(0, 0); public int2 WindowedSize = new int2(1024, 768); + public bool HardwareCursors = true; public bool PixelDouble = false; public bool CursorDouble = false; public bool CapFramerate = true; diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeModCommand.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeModCommand.cs index 4f2633b5d6..c1b6ff67cb 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeModCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeModCommand.cs @@ -62,6 +62,17 @@ namespace OpenRA.Mods.Common.UtilityCommands file.WriteLine(yaml.WriteToString()); } + Console.WriteLine("Processing Cursors:"); + foreach (var filename in Game.modData.Manifest.Cursors) + { + Console.WriteLine("\t" + filename); + var yaml = MiniYaml.FromFile(filename); + UpgradeRules.UpgradeCursors(engineDate, ref yaml, null, 0); + + using (var file = new StreamWriter(filename)) + file.WriteLine(yaml.WriteToString()); + } + Console.WriteLine("Processing Maps:"); var maps = Game.modData.MapCache .Where(m => m.Status == MapStatus.Available) diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index 7878201840..0d8cd75517 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -1041,5 +1041,27 @@ namespace OpenRA.Mods.Common.UtilityCommands nodes.AddRange(addNodes); } + + internal static void UpgradeCursors(int engineVersion, ref List nodes, MiniYamlNode parent, int depth) + { + foreach (var node in nodes) + { + if (engineVersion < 20141113 && depth == 3) + { + if (node.Key == "start") + node.Key = "Start"; + else if (node.Key == "length") + node.Key = "Length"; + else if (node.Key == "end") + node.Key = "End"; + else if (node.Key == "x") + node.Key = "X"; + else if (node.Key == "y") + node.Key = "Y"; + } + + UpgradeCursors(engineVersion, ref node.Value.Nodes, node, depth + 1); + } + } } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs index 315bcceef3..308f73b078 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs @@ -148,6 +148,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var ds = Game.Settings.Graphics; var gs = Game.Settings.Game; + BindCheckboxPref(panel, "HARDWARECURSORS_CHECKBOX", ds, "HardwareCursors"); BindCheckboxPref(panel, "PIXELDOUBLE_CHECKBOX", ds, "PixelDouble"); BindCheckboxPref(panel, "CURSORDOUBLE_CHECKBOX", ds, "CursorDouble"); BindCheckboxPref(panel, "FRAME_LIMIT_CHECKBOX", ds, "CapFramerate"); @@ -173,8 +174,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic worldRenderer.Viewport.Zoom = ds.PixelDouble ? 2 : 1; }; + // Cursor doubling is only supported with software cursors and when pixel doubling is enabled var cursorDoubleCheckbox = panel.Get("CURSORDOUBLE_CHECKBOX"); - cursorDoubleCheckbox.IsDisabled = () => !ds.PixelDouble; + cursorDoubleCheckbox.IsDisabled = () => !ds.PixelDouble || Game.Cursor is HardwareCursor; + + var cursorDoubleIsChecked = cursorDoubleCheckbox.IsChecked; + cursorDoubleCheckbox.IsChecked = () => !cursorDoubleCheckbox.IsDisabled() && cursorDoubleIsChecked(); panel.Get("WINDOW_RESOLUTION").IsVisible = () => ds.Mode == WindowMode.Windowed; var windowWidth = panel.Get("WINDOW_WIDTH"); diff --git a/OpenRA.Renderer.Null/NullGraphicsDevice.cs b/OpenRA.Renderer.Null/NullGraphicsDevice.cs index 299fa0ddea..265aafb19e 100644 --- a/OpenRA.Renderer.Null/NullGraphicsDevice.cs +++ b/OpenRA.Renderer.Null/NullGraphicsDevice.cs @@ -66,6 +66,9 @@ namespace OpenRA.Renderer.Null public ITexture CreateTexture(Bitmap bitmap) { return new NullTexture(); } public IFrameBuffer CreateFrameBuffer(Size s) { return new NullFrameBuffer(); } public IShader CreateShader(string name) { return new NullShader(); } + + public IHardwareCursor CreateHardwareCursor(string name, Size size, byte[] data, int2 hotspot) { return null; } + public void SetHardwareCursor(IHardwareCursor cursor) { } } public class NullShader : IShader diff --git a/OpenRA.Renderer.Sdl2/Sdl2GraphicsDevice.cs b/OpenRA.Renderer.Sdl2/Sdl2GraphicsDevice.cs index dce2c1bd73..084e10073c 100755 --- a/OpenRA.Renderer.Sdl2/Sdl2GraphicsDevice.cs +++ b/OpenRA.Renderer.Sdl2/Sdl2GraphicsDevice.cs @@ -10,6 +10,8 @@ using System; using System.Drawing; +using System.IO; +using System.Runtime.InteropServices; using OpenRA; using OpenRA.Graphics; using OpenTK.Graphics.OpenGL; @@ -80,7 +82,6 @@ namespace OpenRA.Renderer.Sdl2 SDL.SDL_SetHint(SDL.SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); } - SDL.SDL_ShowCursor(0); context = SDL.SDL_GL_CreateContext(window); SDL.SDL_GL_MakeCurrent(window, context); GL.LoadAll(); @@ -103,10 +104,53 @@ namespace OpenRA.Renderer.Sdl2 input = new Sdl2Input(); } + public IHardwareCursor CreateHardwareCursor(string name, Size size, byte[] data, int2 hotspot) + { + var c = new SDL2HardwareCursor(size, data, hotspot); + if (c.Cursor == IntPtr.Zero) + throw new InvalidDataException("Failed to create hardware cursor `{0}`: {1}".F(name, SDL.SDL_GetError())); + + return c; + } + + public void SetHardwareCursor(IHardwareCursor cursor) + { + var c = cursor as SDL2HardwareCursor; + if (c == null) + SDL.SDL_ShowCursor(0); + else + { + SDL.SDL_ShowCursor(1); + SDL.SDL_SetCursor(c.Cursor); + } + } + + class SDL2HardwareCursor : IHardwareCursor + { + public readonly IntPtr Cursor; + readonly IntPtr surface; + + public SDL2HardwareCursor(Size size, byte[] data, int2 hotspot) + { + surface = SDL.SDL_CreateRGBSurface(0, size.Width, size.Height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000); + + var sur = (SDL2.SDL.SDL_Surface)Marshal.PtrToStructure(surface, typeof(SDL2.SDL.SDL_Surface)); + Marshal.Copy(data, 0, sur.pixels, data.Length); + Cursor = SDL.SDL_CreateColorCursor(surface, hotspot.X, hotspot.Y); + } + + public void Dispose() + { + SDL.SDL_FreeCursor(Cursor); + SDL.SDL_FreeSurface(surface); + } + } + public void Dispose() { if (disposed) return; + disposed = true; if (context != IntPtr.Zero) { diff --git a/mods/cnc/chrome/settings.yaml b/mods/cnc/chrome/settings.yaml index 83549370a8..7760764ece 100644 --- a/mods/cnc/chrome/settings.yaml +++ b/mods/cnc/chrome/settings.yaml @@ -50,21 +50,21 @@ Container@SETTINGS_PANEL: Text: Display Align: Center Label@MODE_LABEL: - X: 120 + X: 110 Y: 39 Width: 45 Height: 25 Align: Right Text: Mode: DropDownButton@MODE_DROPDOWN: - X: 170 + X: 160 Y: 40 Width: 170 Height: 25 Font: Regular Text: Windowed Container@WINDOW_RESOLUTION: - X: 340 + X: 330 Y: 40 Children: Label@At: @@ -92,62 +92,69 @@ Container@SETTINGS_PANEL: Width: 45 Height: 25 MaxLength: 5 + Checkbox@HARDWARECURSORS_CHECKBOX: + X: 310 + Y: 75 + Width: 200 + Height: 20 + Font: Regular + Text: Use Hardware Cursors Label@VIDEO_DESC: - Y: 60 + Y: 93 Width: PARENT_RIGHT Height: 25 Font: Tiny Align: Center - Text: Mode/Resolution changes will be applied after the game is restarted + Text: Mode, resolution, and cursor changes will be applied after the game is restarted Checkbox@FRAME_LIMIT_CHECKBOX: X: 15 - Y: 100 + Y: 125 Width: 200 Height: 20 Font: Regular Text: Enable Frame Limiter Checkbox@PIXELDOUBLE_CHECKBOX: X: 310 - Y: 100 + Y: 125 Width: 200 Height: 20 Font: Regular Text: Enable Pixel Doubling Checkbox@CURSORDOUBLE_CHECKBOX: - X: 355 - Y: 135 + X: 340 + Y: 155 Width: 200 Height: 20 Font: Regular Text: Also Double Cursor Label@FRAME_LIMIT_DESC_A: X: 45 - Y: 132 + Y: 152 Width: 50 Height: 25 Text: Limit to Align: Right TextField@FRAME_LIMIT_TEXTFIELD: X: 100 - Y: 133 + Y: 153 Width: 45 Height: 25 MaxLength: 3 Label@FRAME_LIMIT_DESC_B: X: 150 - Y: 132 + Y: 152 Height: 25 Text: FPS Checkbox@TEAM_HEALTH_COLORS_CHECKBOX: X: 310 - Y: 170 + Y: 185 Width: 200 Height: 20 Font: Regular Text: Team Health Colors Checkbox@SHOW_SHELLMAP: X: 15 - Y: 170 + Y: 185 Width: 200 Height: 20 Font: Regular @@ -155,18 +162,18 @@ Container@SETTINGS_PANEL: Label@PLAYER: Text: Player: X: 15 - Y: 215 + Y: 225 TextField@PLAYERNAME: Text: Name X: 65 - Y: 205 + Y: 215 Width: 145 Height: 25 MaxLength: 16 ColorPreviewManager@COLOR_MANAGER: DropDownButton@PLAYERCOLOR: X: 215 - Y: 205 + Y: 215 Width: 70 Height: 25 IgnoreChildMouseOver: true @@ -178,13 +185,13 @@ Container@SETTINGS_PANEL: Height: PARENT_BOTTOM-12 Checkbox@ALWAYS_SHOW_STATUS_BARS_CHECKBOX: X: 310 - Y: 205 + Y: 215 Width: 200 Height: 20 Font: Regular Text: Always Show Status Bars Label@LOCALIZATION_TITLE: - Y: 225 + Y: 265 Width: PARENT_RIGHT Font: Bold Text: Localization @@ -192,7 +199,7 @@ Container@SETTINGS_PANEL: Visible: false Label@LANGUAGE_LABEL: X: 230 - WIDTH - 5 - Y: 244 + Y: 284 Width: 75 Height: 25 Align: Right @@ -200,13 +207,13 @@ Container@SETTINGS_PANEL: Visible: false DropDownButton@LANGUAGE_DROPDOWNBUTTON: X: 230 - Y: 245 + Y: 285 Width: 200 Height: 25 Font: Regular Visible: false Label@LANGUAGE_DESC_A: - Y: 265 + Y: 310 Width: PARENT_RIGHT Height: 25 Font: Tiny @@ -214,7 +221,7 @@ Container@SETTINGS_PANEL: Text: Language changes will be applied after the game is restarted Visible: false Label@LANGUAGE_DESC_B: - Y: 280 + Y: 325 Width: PARENT_RIGHT Height: 25 Font: Tiny diff --git a/mods/cnc/cursors.yaml b/mods/cnc/cursors.yaml index 9338dc0102..dcbbeb31c9 100644 --- a/mods/cnc/cursors.yaml +++ b/mods/cnc/cursors.yaml @@ -1,181 +1,180 @@ -Palettes: +Palettes: cursor: cursor.pal Cursors: mouse2.shp: cursor scroll-t: - start:1 + Start: 1 scroll-tr: - start:2 + Start: 2 scroll-r: - start:3 + Start: 3 scroll-br: - start:4 + Start: 4 scroll-b: - start:5 + Start: 5 scroll-bl: - start:6 + Start: 6 scroll-l: - start:7 + Start: 7 scroll-tl: - start:8 + Start: 8 scroll-t-blocked: - start:130 + Start: 130 scroll-tr-blocked: - start:131 + Start: 131 scroll-r-blocked: - start:132 + Start: 132 scroll-br-blocked: - start:133 + Start: 133 scroll-b-blocked: - start:134 + Start: 134 scroll-bl-blocked: - start:135 + Start: 135 scroll-l-blocked: - start:136 + Start: 136 scroll-tl-blocked: - start:137 + Start: 137 select: - start:12 - length:6 + Start: 12 + Length: 6 default-minimap: - start:86 - length:1 - x: -16 - y: -12 + Start: 86 + Length: 1 + X: -16 + Y: -12 generic-blocked: - start:9 + Start: 9 generic-blocked-minimap: - start:27 + Start: 27 attack: - start:18 - length:8 + Start: 18 + Length: 8 attack-minimap: - start:140 - length:8 + Start: 140 + Length: 8 harvest: - start:18 - length:8 + Start: 18 + Length: 8 harvest-minimap: - start:140 - length:8 + Start: 140 + Length: 8 enter: - start:119 - length:3 + Start: 119 + Length: 3 enter-minimap: - start:148 - length:3 + Start: 148 + Length: 3 c4: - start:122 - length:3 + Start: 122 + Length: 3 c4-minimap: - start:127 - length:3 + Start: 127 + Length: 3 # Cursors that need minimap variants deploy: - start:53 - length:9 + Start: 53 + Length: 9 repair: - start:29 - length:24 + Start: 29 + Length: 24 repair-blocked: - start:126 - length:1 + Start: 126 + Length: 1 sell: - start:62 - length:24 + Start: 62 + Length: 24 sell-blocked: - start:125 - length:1 + Start: 125 + Length: 1 ability: - start:88 - length:8 + Start: 88 + Length: 8 nuke: - start:96 - length:7 + Start: 96 + Length: 7 ioncannon: - start:103 - length:16 + Start: 103 + Length: 16 sell-vehicle: - start:154 - length:24 - + Start: 154 + Length: 24 mouse3.shp: cursor default: - start:0 - x: -16 - y: -12 + Start: 0 + X: -16 + Y: -12 deploy-blocked: - start:1 - length:1 - - mouse4.shp:cursor + Start: 1 + Length: 1 + mouse4.shp: cursor move: - start:0 - length:8 + Start: 0 + Length: 8 move-minimap: - start:8 - length:4 + Start: 8 + Length: 4 move-rough: - start:0 - length: 8 + Start: 0 + Length: 8 attackmove: - start:12 - length:8 + Start: 12 + Length: 8 attackmove-minimap: - start:20 - length:4 + Start: 20 + Length: 4 move-blocked: - start:24 - length:1 + Start: 24 + Length: 1 move-blocked-minimap: - start:25 - length:1 + Start: 25 + Length: 1 mouse5.shp: cursor guard: - start:0 - length:8 + Start: 0 + Length: 8 guard-minimap: - start:8 - length:8 + Start: 8 + Length: 8 mouse6.shp: cursor goldwrench: - start:0 - length:3 + Start: 0 + Length: 3 goldwrench-minimap: - start:3 - length:3 + Start: 3 + Length: 3 goldwrench-blocked: - start:6 - length:1 + Start: 6 + Length: 1 goldwrench-blocked-minimap: - start:7 - length:1 + Start: 7 + Length: 1 capture: - start:8 - length:3 + Start: 8 + Length: 3 capture-minimap: - start:11 - length:3 + Start: 11 + Length: 3 capture-blocked: - start:14 - length:1 + Start: 14 + Length: 1 capture-blocked-minimap: - start:15 - length:1 + Start: 15 + Length: 1 enter-blocked: - start:16 - length:1 + Start: 16 + Length: 1 enter-blocked-minimap: - start:17 - length:1 + Start: 17 + Length: 1 mouse7.shp: cursor attackoutsiderange: - start:0 - length:8 + Start: 0 + Length: 8 attackoutsiderange-minimap: - start:8 + Start: 8 + diff --git a/mods/d2k/cursors.yaml b/mods/d2k/cursors.yaml index 1240369d37..d27c9ffd1c 100644 --- a/mods/d2k/cursors.yaml +++ b/mods/d2k/cursors.yaml @@ -6,269 +6,268 @@ Palettes: Cursors: mouse.r8: mouse scroll-t: - start:112 - x: 24 - y: 24 + Start: 112 + X: 24 + Y: 24 scroll-tr: - start: 120 - x: 24 - y: 24 + Start: 120 + X: 24 + Y: 24 scroll-r: - start: 128 - x: 24 - y: 24 + Start: 128 + X: 24 + Y: 24 scroll-br: - start: 136 - x: 24 - y: 24 + Start: 136 + X: 24 + Y: 24 scroll-b: - start:148 - x: 24 - y: 24 + Start: 148 + X: 24 + Y: 24 scroll-bl: - start:156 - x: 24 - y: 24 + Start: 156 + X: 24 + Y: 24 scroll-l: - start:164 - x: 24 - y: 24 + Start: 164 + X: 24 + Y: 24 scroll-tl: - start:172 - x: 24 - y: 24 + Start: 172 + X: 24 + Y: 24 scroll-t-blocked: - start:180 - x: 24 - y: 24 + Start: 180 + X: 24 + Y: 24 scroll-tr-blocked: - start:188 - x: 24 - y: 24 + Start: 188 + X: 24 + Y: 24 scroll-r-blocked: - start:196 - x: 24 - y: 24 + Start: 196 + X: 24 + Y: 24 scroll-br-blocked: - start:204 - x: 24 - y: 24 + Start: 204 + X: 24 + Y: 24 scroll-b-blocked: - start:212 - x: 24 - y: 24 + Start: 212 + X: 24 + Y: 24 scroll-bl-blocked: - start:220 - x: 24 - y: 24 + Start: 220 + X: 24 + Y: 24 scroll-l-blocked: - start:228 - x: 24 - y: 24 + Start: 228 + X: 24 + Y: 24 scroll-tl-blocked: - start:236 - x: 24 - y: 24 + Start: 236 + X: 24 + Y: 24 select: - start:40 - length: 8 - x: 24 - y: 24 + Start: 40 + Length: 8 + X: 24 + Y: 24 default: - start:0 - x: 24 - y: 24 + Start: 0 + X: 24 + Y: 24 default-minimap: - start:0 - x: 24 - y: 24 + Start: 0 + X: 24 + Y: 24 generic-blocked: - start:24 - x: 24 - y: 24 + Start: 24 + X: 24 + Y: 24 generic-blocked-minimap: - start:24 - x: 24 - y: 24 + Start: 24 + X: 24 + Y: 24 move: - start:8 - length: 8 - x: 24 - y: 24 + Start: 8 + Length: 8 + X: 24 + Y: 24 move-minimap: - start:48 - length: 8 - x: 24 - y: 24 + Start: 48 + Length: 8 + X: 24 + Y: 24 move-blocked: - start:24 - x: 24 - y: 24 + Start: 24 + X: 24 + Y: 24 move-blocked-minimap: - start:24 - x: 24 - y: 24 + Start: 24 + X: 24 + Y: 24 attack: - start:16 - length: 8 - x: 24 - y: 24 + Start: 16 + Length: 8 + X: 24 + Y: 24 attack-minimap: - start:16 - length: 8 - x: 24 - y: 24 + Start: 16 + Length: 8 + X: 24 + Y: 24 attackoutsiderange: - start:16 - length: 8 - x: 24 - y: 24 + Start: 16 + Length: 8 + X: 24 + Y: 24 attackoutsiderange-minimap: - start:16 - length: 8 - x: 24 - y: 24 + Start: 16 + Length: 8 + X: 24 + Y: 24 attackmove: - start:16 - length: 8 - x: 24 - y: 24 + Start: 16 + Length: 8 + X: 24 + Y: 24 attackmove-minimap: - start:16 - length: 8 - x: 24 - y: 24 + Start: 16 + Length: 8 + X: 24 + Y: 24 harvest: - start:16 - length: 8 - x: 24 - y: 24 + Start: 16 + Length: 8 + X: 24 + Y: 24 harvest-minimap: - start:203 - length: 8 - x: 24 - y: 24 + Start: 203 + Length: 8 + X: 24 + Y: 24 enter: - start:32 - length: 8 - x: 24 - y: 24 + Start: 32 + Length: 8 + X: 24 + Y: 24 enter-minimap: - start:32 - length: 8 - x: 24 - y: 24 + Start: 32 + Length: 8 + X: 24 + Y: 24 enter-blocked: - start:104 - length: 1 - x: 24 - y: 24 + Start: 104 + Length: 1 + X: 24 + Y: 24 enter-blocked-minimap: - start:104 - x: 24 - y: 24 + Start: 104 + X: 24 + Y: 24 c4: - start:248 - length: 8 - x: 24 - y: 24 + Start: 248 + Length: 8 + X: 24 + Y: 24 c4-minimap: - start:248 - length: 8 - x: 24 - y: 24 + Start: 248 + Length: 8 + X: 24 + Y: 24 guard: - start:72 - length: 8 - x: 24 - y: 24 + Start: 72 + Length: 8 + X: 24 + Y: 24 guard-minimap: - start:72 - length: 8 - x: 24 - y: 24 + Start: 72 + Length: 8 + X: 24 + Y: 24 capture: - start:32 - length: 8 - x: 24 - y: 24 + Start: 32 + Length: 8 + X: 24 + Y: 24 capture-minimap: - start:32 - length: 8 - x: 24 - y: 24 + Start: 32 + Length: 8 + X: 24 + Y: 24 ability: - start:72 - length: 8 - x: 24 - y: 24 + Start: 72 + Length: 8 + X: 24 + Y: 24 ability-minimap: - start:72 - length: 8 - x: 24 - y: 24 + Start: 72 + Length: 8 + X: 24 + Y: 24 # Cursors that need minimap variants deploy: - start:96 - length: 8 - x: 24 - y: 24 + Start: 96 + Length: 8 + X: 24 + Y: 24 deploy-blocked: - start:104 - length: 1 - x: 24 - y: 24 + Start: 104 + Length: 1 + X: 24 + Y: 24 nuke: - start:240 - length: 8 - x: 24 - y: 24 - + Start: 240 + Length: 8 + X: 24 + Y: 24 sell: - start:80 - length: 8 - x: 24 - y: 24 + Start: 80 + Length: 8 + X: 24 + Y: 24 sell-blocked: - start:56 - length: 1 - x: 24 - y: 24 + Start: 56 + Length: 1 + X: 24 + Y: 24 repair: - start:88 - length: 8 - x: 24 - y: 24 + Start: 88 + Length: 8 + X: 24 + Y: 24 repair-blocked: - start:64 - length: 1 - x: 24 - y: 24 + Start: 64 + Length: 1 + X: 24 + Y: 24 goldwrench: - start:88 - length: 8 - x: 24 - y: 24 + Start: 88 + Length: 8 + X: 24 + Y: 24 goldwrench-blocked: - start:64 - length: 1 - x: 24 - y: 24 + Start: 64 + Length: 1 + X: 24 + Y: 24 move-rough: - start:256 - length: 8 - x: 24 - y: 24 - + Start: 256 + Length: 8 + X: 24 + Y: 24 nopower.shp: mouse powerdown-blocked: - start:0 - length: 1 - x: 12 - y: 12 + Start: 0 + Length: 1 + X: 12 + Y: 12 powerdown: - start:1 - length: 3 - x: 12 - y: 12 \ No newline at end of file + Start: 1 + Length: 3 + X: 12 + Y: 12 + diff --git a/mods/modchooser/cursors.yaml b/mods/modchooser/cursors.yaml index 37b7228e8d..40a86d6423 100644 --- a/mods/modchooser/cursors.yaml +++ b/mods/modchooser/cursors.yaml @@ -4,6 +4,6 @@ Cursors: cursor.shp: cursor default: - start:0 - x: -4 - y: -7 \ No newline at end of file + Start:0 + X: -4 + Y: -7 \ No newline at end of file diff --git a/mods/ra/chrome/settings.yaml b/mods/ra/chrome/settings.yaml index 7e544d3603..bc60296a97 100644 --- a/mods/ra/chrome/settings.yaml +++ b/mods/ra/chrome/settings.yaml @@ -63,21 +63,21 @@ Background@SETTINGS_PANEL: Height: PARENT_BOTTOM Children: Label@MODE_LABEL: - X: 120 + X: 110 Y: 39 Width: 45 Height: 25 Align: Right Text: Mode: DropDownButton@MODE_DROPDOWN: - X: 170 + X: 160 Y: 40 Width: 170 Height: 25 Font: Regular Text: Windowed Container@WINDOW_RESOLUTION: - X: 340 + X: 330 Y: 40 Children: Label@At: @@ -105,62 +105,69 @@ Background@SETTINGS_PANEL: Width: 45 Height: 25 MaxLength: 5 + Checkbox@HARDWARECURSORS_CHECKBOX: + X: 310 + Y: 75 + Width: 200 + Height: 20 + Font: Regular + Text: Use Hardware Cursors Label@VIDEO_DESC: - Y: 60 + Y: 93 Width: PARENT_RIGHT Height: 25 Font: Tiny Align: Center - Text: Mode/Resolution changes will be applied after the game is restarted + Text: Mode, resolution, and cursor changes will be applied after the game is restarted Checkbox@FRAME_LIMIT_CHECKBOX: X: 15 - Y: 100 + Y: 125 Width: 200 Height: 20 Font: Regular Text: Enable Frame Limiter Checkbox@PIXELDOUBLE_CHECKBOX: X: 310 - Y: 100 + Y: 125 Width: 200 Height: 20 Font: Regular Text: Enable Pixel Doubling Checkbox@CURSORDOUBLE_CHECKBOX: - X: 355 - Y: 135 + X: 340 + Y: 160 Width: 200 Height: 20 Font: Regular Text: Also Double Cursor Label@FRAME_LIMIT_DESC_A: X: 45 - Y: 132 + Y: 157 Width: 50 Height: 25 Text: Limit to Align: Right TextField@FRAME_LIMIT_TEXTFIELD: X: 100 - Y: 133 + Y: 158 Width: 45 Height: 25 MaxLength: 3 Label@FRAME_LIMIT_DESC_B: X: 150 - Y: 132 + Y: 157 Height: 25 Text: FPS Checkbox@TEAM_HEALTH_COLORS_CHECKBOX: X: 310 - Y: 170 + Y: 195 Width: 200 Height: 20 Font: Regular Text: Team Health Colors Checkbox@SHOW_SHELLMAP: X: 15 - Y: 170 + Y: 195 Width: 200 Height: 20 Font: Regular @@ -168,18 +175,18 @@ Background@SETTINGS_PANEL: Label@PLAYER: Text: Player: X: 15 - Y: 215 + Y: 240 TextField@PLAYERNAME: Text: Name X: 65 - Y: 205 + Y: 230 Width: 145 Height: 25 MaxLength: 16 ColorPreviewManager@COLOR_MANAGER: DropDownButton@PLAYERCOLOR: X: 215 - Y: 205 + Y: 230 Width: 70 Height: 25 IgnoreChildMouseOver: true @@ -191,13 +198,13 @@ Background@SETTINGS_PANEL: Height: PARENT_BOTTOM-12 Checkbox@ALWAYS_SHOW_STATUS_BARS_CHECKBOX: X: 310 - Y: 205 + Y: 230 Width: 200 Height: 20 Font: Regular Text: Always Show Status Bars Label@LOCALIZATION_TITLE: - Y: 225 + Y: 270 Width: PARENT_RIGHT Font: Bold Text: Localization @@ -205,7 +212,7 @@ Background@SETTINGS_PANEL: Visible: false Label@LANGUAGE_LABEL: X: 230 - WIDTH - 5 - Y: 244 + Y: 289 Width: 75 Height: 25 Align: Right @@ -213,12 +220,12 @@ Background@SETTINGS_PANEL: Visible: false DropDownButton@LANGUAGE_DROPDOWNBUTTON: X: 230 - Y: 245 + Y: 290 Width: 200 Height: 25 Visible: false Label@LANGUAGE_DESC_A: - Y: 265 + Y: 310 Width: PARENT_RIGHT Height: 25 Font: Tiny @@ -226,7 +233,7 @@ Background@SETTINGS_PANEL: Text: Language changes will be applied after the game is restarted Visible: false Label@LANGUAGE_DESC_B: - Y: 280 + Y: 325 Width: PARENT_RIGHT Height: 25 Font: Tiny diff --git a/mods/ra/cursors.yaml b/mods/ra/cursors.yaml index 3b874f6dc4..815e6a04f1 100644 --- a/mods/ra/cursors.yaml +++ b/mods/ra/cursors.yaml @@ -1,180 +1,179 @@ -Palettes: +Palettes: cursor: cursor.pal Cursors: mouse.shp: cursor scroll-t: - start:1 + Start: 1 scroll-tr: - start:2 + Start: 2 scroll-r: - start:3 + Start: 3 scroll-br: - start:4 + Start: 4 scroll-b: - start:5 + Start: 5 scroll-bl: - start:6 + Start: 6 scroll-l: - start:7 + Start: 7 scroll-tl: - start:8 + Start: 8 scroll-t-blocked: - start:124 + Start: 124 scroll-tr-blocked: - start:125 + Start: 125 scroll-r-blocked: - start:126 + Start: 126 scroll-br-blocked: - start:127 + Start: 127 scroll-b-blocked: - start:128 + Start: 128 scroll-bl-blocked: - start:129 + Start: 129 scroll-l-blocked: - start:130 + Start: 130 scroll-tl-blocked: - start:131 + Start: 131 select: - start:15 - length: 6 - + Start: 15 + Length: 6 default: - start:0 - x: -16 - y: -12 + Start: 0 + X: -16 + Y: -12 default-minimap: - start:80 - x: -16 - y: -12 + Start: 80 + X: -16 + Y: -12 generic-blocked: - start:9 + Start: 9 generic-blocked-minimap: - start:33 + Start: 33 move: - start:10 - length: 4 + Start: 10 + Length: 4 move-minimap: - start:29 - length: 4 + Start: 29 + Length: 4 move-rough: - start:10 - length: 4 + Start: 10 + Length: 4 move-blocked: - start:14 + Start: 14 move-blocked-minimap: - start:33 + Start: 33 attack: - start:195 - length: 8 + Start: 195 + Length: 8 attack-minimap: - start:203 - length: 8 + Start: 203 + Length: 8 attackoutsiderange: - start:21 - length: 8 + Start: 21 + Length: 8 attackoutsiderange-minimap: - start:134 - length: 8 + Start: 134 + Length: 8 harvest: - start:21 - length: 8 + Start: 21 + Length: 8 harvest-minimap: - start:134 - length: 8 + Start: 134 + Length: 8 enter: - start:113 - length: 3 + Start: 113 + Length: 3 enter-minimap: - start:139 - length: 3 + Start: 139 + Length: 3 enter-blocked: - start:212 - length: 1 + Start: 212 + Length: 1 enter-blocked-minimap: - start:33 + Start: 33 c4: - start:116 - length: 3 + Start: 116 + Length: 3 c4-minimap: - start:121 - length: 3 + Start: 121 + Length: 3 guard: - start:147 - length: 1 + Start: 147 + Length: 1 guard-minimap: - start:146 - length: 1 + Start: 146 + Length: 1 capture: - start:164 - length: 3 + Start: 164 + Length: 3 capture-minimap: - start:167 - length: 3 + Start: 167 + Length: 3 heal: - start:160 - length: 4 + Start: 160 + Length: 4 heal-minimap: - start:194 - length: 1 + Start: 194 + Length: 1 ability: - start:82 - length: 8 + Start: 82 + Length: 8 ability-minimap: - start:214 - length: 8 + Start: 214 + Length: 8 # Cursors that need minimap variants deploy: - start:59 - length: 9 + Start: 59 + Length: 9 deploy-blocked: - start:211 - length: 1 + Start: 211 + Length: 1 goldwrench: - start:170 - length: 24 + Start: 170 + Length: 24 goldwrench-blocked: - start:213 - length: 1 + Start: 213 + Length: 1 nuke: - start:90 - length: 7 + Start: 90 + Length: 7 chrono-select: - start:97 - length: 8 + Start: 97 + Length: 8 chrono-target: - start:105 - length: 8 - + Start: 105 + Length: 8 sell: - start:68 - length: 12 + Start: 68 + Length: 12 sell-blocked: - start:119 - length: 1 + Start: 119 + Length: 1 repair: - start:35 - length: 24 + Start: 35 + Length: 24 repair-blocked: - start:120 - length: 1 + Start: 120 + Length: 1 sell2: - start:148 - length: 12 + Start: 148 + Length: 12 nopower.shp: cursor powerdown-blocked: - start:0 - length: 1 + Start: 0 + Length: 1 powerdown: - start:1 - length: 3 + Start: 1 + Length: 3 attackmove.shp: cursor attackmove: - start:0 - length: 4 + Start: 0 + Length: 4 attackmove-minimap: - start:4 - length: 4 \ No newline at end of file + Start: 4 + Length: 4 + diff --git a/mods/ts/cursors.yaml b/mods/ts/cursors.yaml index aefebd9fb2..791f002be8 100644 --- a/mods/ts/cursors.yaml +++ b/mods/ts/cursors.yaml @@ -1,175 +1,176 @@ -Palettes: +Palettes: cursor: mousepal.pal Cursors: mouse.shp: cursor - scroll-t: #TODO - start: 2 - scroll-tr: #TODO - start: 3 - scroll-r: #TODO - start: 4 - scroll-br: #TODO - start: 5 - scroll-b: #TODO - start: 6 - scroll-bl: #TODO - start: 7 - scroll-l: #TODO - start: 8 - scroll-tl: #TODO - start: 9 - scroll-t-blocked: #TODO - start: 10 - scroll-tr-blocked: #TODO - start: 11 - scroll-r-blocked: #TODO - start: 12 - scroll-br-blocked: #TODO - start: 13 - scroll-b-blocked: #TODO - start: 14 - scroll-bl-blocked: #TODO - start: 15 - scroll-l-blocked: #TODO - start: 16 - scroll-tl-blocked: #TODO - start: 17 + scroll-t: + Start: 2 + scroll-tr: + Start: 3 + scroll-r: + Start: 4 + scroll-br: + Start: 5 + scroll-b: + Start: 6 + scroll-bl: + Start: 7 + scroll-l: + Start: 8 + scroll-tl: + Start: 9 + scroll-t-blocked: + Start: 10 + scroll-tr-blocked: + Start: 11 + scroll-r-blocked: + Start: 12 + scroll-br-blocked: + Start: 13 + scroll-b-blocked: + Start: 14 + scroll-bl-blocked: + Start: 15 + scroll-l-blocked: + Start: 16 + scroll-tl-blocked: + Start: 17 select: - start:18 - length: 12 + Start: 18 + Length: 12 default: - start:0 - x: -26 - y: -20 + Start: 0 + X: -26 + Y: -20 default-minimap: - start:1 - x: -26 - y: -20 + Start: 1 + X: -26 + Y: -20 generic-blocked: - start:9 + Start: 9 generic-blocked-minimap: - start:52 + Start: 52 move: - start:31 - length: 10 + Start: 31 + Length: 10 move-minimap: - start:42 - length: 10 + Start: 42 + Length: 10 move-rough: - start:31 - length: 10 + Start: 31 + Length: 10 move-blocked: - start:41 + Start: 41 move-blocked-minimap: - start:52 + Start: 52 attack: - start: 53 - length: 5 + Start: 53 + Length: 5 attack-blocked: # TODO: unused - start: 41 - length: 1 + Start: 41 + Length: 1 attack-minimap: - start: 63 - length: 5 + Start: 63 + Length: 5 attackoutsiderange: - start: 58 - length: 5 + Start: 58 + Length: 5 attackoutsiderange-minimap: - start: 63 - length: 5 - attackmove: #TODO - start: 58 - length: 5 - attackmove-minimap: #TODO - start:68 - length: 5 - harvest: #TODO - start:53 - length: 5 - harvest-minimap: #TODO - start:134 - length: 8 + Start: 63 + Length: 5 + attackmove: + Start: 58 + Length: 5 + attackmove-minimap: + Start: 68 + Length: 5 + harvest: + Start: 53 + Length: 5 + harvest-minimap: + Start: 134 + Length: 8 enter: - start: 89 - length: 10 + Start: 89 + Length: 10 enter-minimap: - start: 100 - length: 10 + Start: 100 + Length: 10 enter-blocked: - start: 99 - length: 1 - enter-blocked-minimap: #TODO - start:33 + Start: 99 + Length: 1 + enter-blocked-minimap: + Start: 33 c4: - start: 309 - length: 10 - c4-minimap: #TODO - start:121 - length: 3 + Start: 309 + Length: 10 + c4-minimap: + Start: 121 + Length: 3 guard: - start: 68 - length: 5 + Start: 68 + Length: 5 guard-minimap: - start: 73 - length: 5 + Start: 73 + Length: 5 capture: - start: 89 - length: 10 + Start: 89 + Length: 10 capture-minimap: - start: 100 - length: 10 + Start: 100 + Length: 10 heal: - start: 346 - length: 10 - heal-minimap: #TODO - start:194 - length: 1 + Start: 346 + Length: 10 + heal-minimap: + Start: 194 + Length: 1 ability: - start: 78 - length: 10 - ability-minimap: #TODO - start:214 - length: 8 + Start: 78 + Length: 10 + ability-minimap: + Start: 214 + Length: 8 deploy: - start: 110 - length: 9 + Start: 110 + Length: 9 deploy-blocked: - start: 119 - length: 1 + Start: 119 + Length: 1 undeploy: #TODO: unused - start:120 - length: 9 - goldwrench: #TODO - start:170 - length: 24 + Start: 120 + Length: 9 + goldwrench: + Start: 170 + Length: 24 goldwrench-blocked: #TODO - start:213 - length: 1 - nuke: #TODO - start:90 - length: 7 + Start: 213 + Length: 1 + nuke: + Start: 90 + Length: 7 sell: - start:129 - length: 10 + Start: 129 + Length: 10 sell-minimap: #TODO: unused - start:139 - length: 10 + Start: 139 + Length: 10 sell-blocked: - start:149 - length: 1 + Start: 149 + Length: 1 repair: - start:170 - length: 20 + Start: 170 + Length: 20 repair-blocked: - start:190 - length: 1 + Start: 190 + Length: 1 sell2: - start:139 - length: 10 + Start: 139 + Length: 10 powerdown-blocked: - start:345 - length: 1 + Start: 345 + Length: 1 powerdown: - start:329 - length: 15 + Start: 329 + Length: 15 +