Remove CursorProvider.

This commit is contained in:
Paul Chote
2025-12-09 15:39:50 +00:00
committed by Gustas Kažukauskas
parent 9e548fd0f0
commit 94177848a8
7 changed files with 65 additions and 117 deletions

View File

@@ -513,7 +513,7 @@ namespace OpenRA
ModData.MapCache.LoadMaps();
Cursor?.Dispose();
Cursor = new CursorManager(ModData.CursorProvider, ModData.Manifest.CursorSheetSize);
Cursor = new CursorManager(ModData);
var metadata = ModData.Manifest.Metadata;
if (!string.IsNullOrEmpty(metadata.WindowTitleTranslated))
@@ -740,15 +740,12 @@ namespace OpenRA
Ui.Draw();
if (ModData != null && ModData.CursorProvider != null)
if (HideCursor)
Cursor?.SetCursor(null);
else
{
if (HideCursor)
Cursor.SetCursor(null);
else
{
Cursor.SetCursor(Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default");
Cursor.Render(Renderer);
}
Cursor?.SetCursor(Ui.Root.GetCursorOuter(Viewport.LastMousePos) ?? "default");
Cursor?.Render(Renderer);
}
}

View File

@@ -13,6 +13,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Graphics
{
@@ -39,19 +40,36 @@ namespace OpenRA.Graphics
readonly bool hardwareCursorsDisabled = false;
bool hardwareCursorsDoubled = false;
public CursorManager(CursorProvider cursorProvider, int cursorSheetSize)
public CursorManager(ModData modData)
{
hardwareCursorsDisabled = Game.Settings.Graphics.DisableHardwareCursors;
graphicSettings = Game.Settings.Graphics;
SheetBuilder = new SheetBuilder(SheetType.BGRA, cursorSheetSize);
SheetBuilder = new SheetBuilder(SheetType.BGRA, modData.Manifest.CursorSheetSize);
// Overwrite previous definitions if there are duplicates
var pals = new Dictionary<string, IProvidesCursorPaletteInfo>();
foreach (var p in modData.DefaultRules.Actors[SystemActors.World].TraitInfos<IProvidesCursorPaletteInfo>())
if (p.Palette != null)
pals[p.Palette] = p;
var paletteCache = new Cache<string, ImmutablePalette>(p => pals[p].ReadPalette(modData.DefaultFileSystem));
var frameCache = new FrameCache(modData.DefaultFileSystem, modData.SpriteLoaders);
// Sort the cursors for better packing onto the sheet.
foreach (var kv in cursorProvider.Cursors
.OrderBy(kvp => kvp.Value.Frames.Max(f => f.Size.Height)))
foreach (var kv in modData.Cursors)
{
var frames = kv.Value.Frames;
var palette = !string.IsNullOrEmpty(kv.Value.Palette) ? cursorProvider.Palettes[kv.Value.Palette] : null;
var cursorSprites = frameCache[kv.Value.Src];
var length = kv.Value.Length ?? cursorSprites.Length - kv.Value.Start;
if (kv.Value.Start > cursorSprites.Length)
throw new YamlException($"Cursor {kv.Value.Name}: {nameof(kv.Value.Start)} is greater than the length of the sprite sequence.");
if (kv.Value.Length > cursorSprites.Length)
throw new YamlException($"Cursor {kv.Value.Name}: {nameof(kv.Value.Length)} is greater than the length of the sprite sequence.");
var frames = cursorSprites.Skip(kv.Value.Start).Take(length).ToArray();
var palette = !string.IsNullOrEmpty(kv.Value.Palette) ? paletteCache[kv.Value.Palette] : null;
var c = new Cursor
{

View File

@@ -1,67 +0,0 @@
#region Copyright & License Information
/*
* Copyright (c) The OpenRA Developers and Contributors
* 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, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Graphics
{
public sealed class CursorProvider
{
public readonly IReadOnlyDictionary<string, CursorSequence> Cursors;
public readonly IReadOnlyDictionary<string, ImmutablePalette> Palettes;
public CursorProvider(ModData modData)
{
var fileSystem = modData.DefaultFileSystem;
var stringPool = new HashSet<string>(); // Reuse common strings in YAML
var sequenceYaml = MiniYaml.Merge(modData.Manifest.Cursors.Select(
s => MiniYaml.FromStream(fileSystem.Open(s), s, stringPool: stringPool)));
var cursorsYaml = new MiniYaml(null, sequenceYaml).NodeWithKey("Cursors").Value;
// Overwrite previous definitions if there are duplicates
var pals = new Dictionary<string, IProvidesCursorPaletteInfo>();
foreach (var p in modData.DefaultRules.Actors[SystemActors.World].TraitInfos<IProvidesCursorPaletteInfo>())
if (p.Palette != null)
pals[p.Palette] = p;
Palettes = cursorsYaml.Nodes.Select(n => n.Value.Value)
.Where(p => p != null)
.Distinct()
.ToDictionary(p => p, p => pals[p].ReadPalette(modData.DefaultFileSystem));
var frameCache = new FrameCache(fileSystem, modData.SpriteLoaders);
var cursors = new Dictionary<string, CursorSequence>();
foreach (var s in cursorsYaml.Nodes)
foreach (var sequence in s.Value.Nodes)
cursors.Add(sequence.Key, new CursorSequence(frameCache, sequence.Key, s.Key, s.Value.Value, sequence.Value));
Cursors = cursors;
}
public bool HasCursorSequence(string cursor)
{
return Cursors.ContainsKey(cursor);
}
public CursorSequence GetCursorSequence(string cursor)
{
try { return Cursors[cursor]; }
catch (KeyNotFoundException)
{
throw new InvalidOperationException($"Cursor does not have a sequence `{cursor}`");
}
}
}
}

View File

@@ -9,50 +9,26 @@
*/
#endregion
using System.Linq;
namespace OpenRA.Graphics
{
public class CursorSequence
{
public readonly string Name;
public readonly string Src;
public readonly int Start;
public readonly int Length;
public readonly int? Length;
public readonly string Palette;
public readonly int2 Hotspot;
public readonly ISpriteFrame[] Frames;
public CursorSequence(FrameCache cache, string name, string cursorSrc, string palette, MiniYaml info)
public CursorSequence(string name, string cursorSrc, string palette, MiniYaml info)
{
var d = info.ToDictionary();
Start = Exts.ParseInt32Invariant(d["Start"].Value);
Palette = palette;
Name = name;
Src = cursorSrc;
var cursorSprites = cache[cursorSrc];
Frames = cursorSprites.Skip(Start).ToArray();
if ((d.TryGetValue("Length", out var yaml) && yaml.Value == "*") ||
(d.TryGetValue("End", out yaml) && yaml.Value == "*"))
Length = Frames.Length;
else if (d.TryGetValue("Length", out yaml))
Length = Exts.ParseInt32Invariant(yaml.Value);
else if (d.TryGetValue("End", out yaml))
Length = Exts.ParseInt32Invariant(yaml.Value) - Start;
else
Length = 1;
Frames = Frames.Take(Length).ToArray();
if (Start > cursorSprites.Length)
throw new YamlException($"Cursor {name}: {nameof(Start)} is greater than the length of the sprite sequence.");
if (Length > cursorSprites.Length)
throw new YamlException($"Cursor {name}: {nameof(Length)} is greater than the length of the sprite sequence.");
if (d.TryGetValue("X", out yaml))
if (d.TryGetValue("X", out var yaml))
{
Exts.TryParseInt32Invariant(yaml.Value, out var x);
Hotspot = Hotspot.WithX(x);
@@ -63,6 +39,14 @@ namespace OpenRA.Graphics
Exts.TryParseInt32Invariant(yaml.Value, out var y);
Hotspot = Hotspot.WithY(y);
}
Start = Exts.ParseInt32Invariant(d["Start"].Value);
if (d.TryGetValue("Length", out yaml))
Length = yaml.Value != "*" ? Exts.ParseInt32Invariant(yaml.Value) : null;
else if (d.TryGetValue("End", out yaml) && yaml.Value == "*")
Length = yaml.Value != "*" ? Exts.ParseInt32Invariant(yaml.Value) - Start : null;
else
Length = 1;
}
}
}

View File

@@ -10,6 +10,7 @@
#endregion
using System;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
@@ -35,9 +36,9 @@ namespace OpenRA
public readonly IVideoLoader[] VideoLoaders;
public readonly HotkeyManager Hotkeys;
public readonly IFileSystemLoader FileSystemLoader;
public readonly FrozenDictionary<string, CursorSequence> Cursors;
public ILoadScreen LoadScreen { get; }
public CursorProvider CursorProvider { get; private set; }
public FS ModFiles;
public IReadOnlyFileSystem DefaultFileSystem => ModFiles;
@@ -97,6 +98,7 @@ namespace OpenRA
SpriteSequenceLoader = (ISpriteSequenceLoader)sequenceCtor.Invoke([this]);
Hotkeys = new HotkeyManager(ModFiles, Game.Settings.Keys, Manifest);
Cursors = ParseCursors(Manifest, DefaultFileSystem);
defaultRules = Exts.Lazy(() => Ruleset.LoadDefaults(this));
defaultTerrainInfo = Exts.Lazy(() =>
@@ -115,6 +117,23 @@ namespace OpenRA
initialThreadId = Environment.CurrentManagedThreadId;
}
static FrozenDictionary<string, CursorSequence> ParseCursors(Manifest manifest, IReadOnlyFileSystem fileSystem)
{
var stringPool = new HashSet<string>(); // Reuse common strings in YAML
var sequenceYaml = MiniYaml.Merge(manifest.Cursors.Select(
s => MiniYaml.FromStream(fileSystem.Open(s), s, stringPool: stringPool)));
var cursors = new Dictionary<string, CursorSequence>();
foreach (var node in sequenceYaml)
if (node.Key == "Cursors")
foreach (var fileNode in node.Value.Nodes)
foreach (var sequenceNode in fileNode.Value.Nodes)
cursors.Add(sequenceNode.Key, new CursorSequence(
sequenceNode.Key, fileNode.Key, fileNode.Value.Value, sequenceNode.Value));
return cursors.ToFrozenDictionary();
}
// HACK: Only update the loading screen if we're in the main thread.
readonly int initialThreadId;
internal void HandleLoadingProgress()
@@ -134,8 +153,6 @@ namespace OpenRA
FluentProvider.Initialize(this, fileSystem);
Game.Sound.Initialize(SoundLoaders, fileSystem);
CursorProvider = new CursorProvider(this);
}
public IEnumerable<string> Languages { get; }

View File

@@ -65,8 +65,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
}
var sheetCount = 1;
var cursorProvider = new CursorProvider(modData);
using (var cursor = new CursorManager(cursorProvider, modData.Manifest.CursorSheetSize))
using (var cursor = new CursorManager(modData))
foreach (var sheet in cursor.SheetBuilder.AllSheets)
CommitSheet(null, sheet, "cursors", palette, ref sheetCount);

View File

@@ -302,7 +302,7 @@ namespace OpenRA.Mods.Common.Widgets
if (cursor == null)
return worldDefaultCursor;
return Game.ModData.CursorProvider.HasCursorSequence(cursor + "-minimap") ? cursor + "-minimap" : cursor;
return Game.ModData.Cursors.ContainsKey(cursor + "-minimap") ? cursor + "-minimap" : cursor;
}
public override bool HandleMouseInput(MouseInput mi)