Reorganize cursor plumbing in preparation for hardware cursors.
This commit is contained in:
@@ -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,14 @@ namespace OpenRA
|
||||
Sound.Initialize();
|
||||
|
||||
modData = new ModData(mod, true);
|
||||
|
||||
Renderer.InitializeFonts(modData.Manifest);
|
||||
modData.InitializeLoaders();
|
||||
using (new PerfTimer("LoadMaps"))
|
||||
modData.MapCache.LoadMaps();
|
||||
|
||||
Cursor = new SoftwareCursor(modData.CursorProvider);
|
||||
|
||||
PerfHistory.items["render"].hasNormalTick = false;
|
||||
PerfHistory.items["batches"].hasNormalTick = false;
|
||||
PerfHistory.items["render_widgets"].hasNormalTick = false;
|
||||
@@ -401,8 +407,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 +423,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 +513,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<string, CursorSequence> cursors = new Dictionary<string, CursorSequence>();
|
||||
readonly Cache<string, PaletteReference> palettes;
|
||||
readonly SheetBuilder sheetBuilder;
|
||||
|
||||
public static bool CursorViewportZoomed { get { return Game.Settings.Graphics.CursorDouble && Game.Settings.Graphics.PixelDouble; } }
|
||||
public readonly IReadOnlyDictionary<string, CursorSequence> Cursors;
|
||||
public readonly IReadOnlyDictionary<string, ImmutablePalette> Palettes;
|
||||
|
||||
public CursorProvider(ModData modData)
|
||||
{
|
||||
var sequenceFiles = modData.Manifest.Cursors;
|
||||
|
||||
palettes = new Cache<string, PaletteReference>(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<string, ImmutablePalette>();
|
||||
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<string, CursorSequence>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
Length = Frames.Length - Start;
|
||||
else if (d.ContainsKey("Length"))
|
||||
length = Exts.ParseIntegerInvariant(d["Length"].Value);
|
||||
Length = Exts.ParseIntegerInvariant(d["Length"].Value);
|
||||
else if (d.ContainsKey("End"))
|
||||
length = Exts.ParseIntegerInvariant(d["End"].Value) - start;
|
||||
Length = Exts.ParseIntegerInvariant(d["End"].Value) - Start;
|
||||
else
|
||||
length = 1;
|
||||
Length = 1;
|
||||
|
||||
Frames = cache[cursorSrc]
|
||||
.Skip(Start)
|
||||
.Take(Length)
|
||||
.ToArray();
|
||||
|
||||
if (d.ContainsKey("X"))
|
||||
Exts.TryParseIntegerInvariant(d["X"].Value, out Hotspot.X);
|
||||
if (d.ContainsKey("Y"))
|
||||
Exts.TryParseIntegerInvariant(d["Y"].Value, out Hotspot.Y);
|
||||
}
|
||||
|
||||
public Sprite GetSprite(int frame)
|
||||
{
|
||||
return sprites[(frame % length) + start];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
100
OpenRA.Game/Graphics/SoftwareCursor.cs
Normal file
100
OpenRA.Game/Graphics/SoftwareCursor.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
#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<string, PaletteReference> paletteReferences;
|
||||
readonly Dictionary<string, Sprite[]> sprites = new Dictionary<string, Sprite[]>();
|
||||
readonly CursorProvider cursorProvider;
|
||||
readonly SheetBuilder sheetBuilder;
|
||||
|
||||
public SoftwareCursor(CursorProvider cursorProvider)
|
||||
{
|
||||
this.cursorProvider = cursorProvider;
|
||||
|
||||
paletteReferences = new Cache<string, PaletteReference>(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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
<Compile Include="Graphics\TargetLineRenderable.cs" />
|
||||
<Compile Include="Graphics\UISpriteRenderable.cs" />
|
||||
<Compile Include="GameRules\DamageWarhead.cs" />
|
||||
<Compile Include="Graphics\SoftwareCursor.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="FileSystem\D2kSoundResources.cs" />
|
||||
|
||||
Reference in New Issue
Block a user