Lock mouse position

This commit is contained in:
teinarss
2019-05-01 10:53:08 +02:00
committed by abcdefg30
parent 7bbfd823d0
commit ffd3834849
11 changed files with 101 additions and 73 deletions

View File

@@ -20,12 +20,26 @@ namespace OpenRA.Graphics
{ {
readonly Dictionary<string, IHardwareCursor[]> hardwareCursors = new Dictionary<string, IHardwareCursor[]>(); readonly Dictionary<string, IHardwareCursor[]> hardwareCursors = new Dictionary<string, IHardwareCursor[]>();
readonly CursorProvider cursorProvider; readonly CursorProvider cursorProvider;
readonly Dictionary<string, Sprite[]> sprites = new Dictionary<string, Sprite[]>();
readonly SheetBuilder sheetBuilder;
readonly HardwarePalette hardwarePalette = new HardwarePalette();
readonly Cache<string, PaletteReference> paletteReferences;
CursorSequence cursor; CursorSequence cursor;
bool isLocked = false;
int2 lockedPosition;
public HardwareCursor(CursorProvider cursorProvider) public HardwareCursor(CursorProvider cursorProvider)
{ {
this.cursorProvider = cursorProvider; this.cursorProvider = cursorProvider;
paletteReferences = new Cache<string, PaletteReference>(CreatePaletteReference);
foreach (var p in cursorProvider.Palettes)
hardwarePalette.AddPalette(p.Key, p.Value, false);
hardwarePalette.Initialize();
sheetBuilder = new SheetBuilder(SheetType.Indexed);
foreach (var kv in cursorProvider.Cursors) foreach (var kv in cursorProvider.Cursors)
{ {
var palette = cursorProvider.Palettes[kv.Value.Palette]; var palette = cursorProvider.Palettes[kv.Value.Palette];
@@ -34,11 +48,22 @@ namespace OpenRA.Graphics
.ToArray(); .ToArray();
hardwareCursors.Add(kv.Key, hc); hardwareCursors.Add(kv.Key, hc);
var s = kv.Value.Frames.Select(a => sheetBuilder.Add(a)).ToArray();
sprites.Add(kv.Key, s);
} }
sheetBuilder.Current.ReleaseBuffer();
Update(); Update();
} }
PaletteReference CreatePaletteReference(string name)
{
var pal = hardwarePalette.GetPalette(name);
return new PaletteReference(name, hardwarePalette.GetPaletteIndex(name), pal, hardwarePalette);
}
IHardwareCursor CreateCursor(ISpriteFrame f, ImmutablePalette palette, string name, CursorSequence sequence) IHardwareCursor CreateCursor(ISpriteFrame f, ImmutablePalette palette, string name, CursorSequence sequence)
{ {
var hotspot = sequence.Hotspot - f.Offset.ToInt2() + new int2(f.Size) / 2; var hotspot = sequence.Hotspot - f.Offset.ToInt2() + new int2(f.Size) / 2;
@@ -96,6 +121,7 @@ namespace OpenRA.Graphics
int frame; int frame;
int ticks; int ticks;
public void Tick() public void Tick()
{ {
if (cursor == null || cursor.Length == 1) if (cursor == null || cursor.Length == 1)
@@ -123,9 +149,35 @@ namespace OpenRA.Graphics
} }
} }
public void Render(Renderer renderer) { } public void Render(Renderer renderer)
{
if (cursor.Name == null || !isLocked)
return;
public int Frame { get { return frame; } } var cursorSequence = cursorProvider.GetCursorSequence(cursor.Name);
var cursorSprite = sprites[cursor.Name][frame];
var cursorOffset = cursorSequence.Hotspot + (0.5f * cursorSprite.Size.XY).ToInt2();
renderer.SetPalette(hardwarePalette);
renderer.SpriteRenderer.DrawSprite(cursorSprite,
lockedPosition - cursorOffset,
paletteReferences[cursorSequence.Palette],
cursorSprite.Size);
}
public void Lock()
{
lockedPosition = Viewport.LastMousePos;
Game.Renderer.Window.SetRelativeMouseMode(true);
isLocked = true;
}
public void Unlock()
{
Game.Renderer.Window.SetRelativeMouseMode(false);
isLocked = false;
}
public void Dispose() public void Dispose()
{ {
@@ -133,6 +185,7 @@ namespace OpenRA.Graphics
foreach (var cursor in cursors.Value) foreach (var cursor in cursors.Value)
cursor.Dispose(); cursor.Dispose();
sheetBuilder.Dispose();
hardwareCursors.Clear(); hardwareCursors.Clear();
} }
} }

View File

@@ -52,6 +52,7 @@ namespace OpenRA
IHardwareCursor CreateHardwareCursor(string name, Size size, byte[] data, int2 hotspot); IHardwareCursor CreateHardwareCursor(string name, Size size, byte[] data, int2 hotspot);
void SetHardwareCursor(IHardwareCursor cursor); void SetHardwareCursor(IHardwareCursor cursor);
void SetRelativeMouseMode(bool mode);
} }
public interface IGraphicsContext : IDisposable public interface IGraphicsContext : IDisposable

View File

@@ -21,7 +21,8 @@ namespace OpenRA.Graphics
void Render(Renderer renderer); void Render(Renderer renderer);
void SetCursor(string cursor); void SetCursor(string cursor);
void Tick(); void Tick();
int Frame { get; } void Lock();
void Unlock();
} }
public sealed class SoftwareCursor : ICursor public sealed class SoftwareCursor : ICursor
@@ -32,6 +33,9 @@ namespace OpenRA.Graphics
readonly CursorProvider cursorProvider; readonly CursorProvider cursorProvider;
readonly SheetBuilder sheetBuilder; readonly SheetBuilder sheetBuilder;
bool isLocked = false;
int2 lockedPosition;
public SoftwareCursor(CursorProvider cursorProvider) public SoftwareCursor(CursorProvider cursorProvider)
{ {
this.cursorProvider = cursorProvider; this.cursorProvider = cursorProvider;
@@ -78,7 +82,7 @@ namespace OpenRA.Graphics
return; return;
var cursorSequence = cursorProvider.GetCursorSequence(cursorName); var cursorSequence = cursorProvider.GetCursorSequence(cursorName);
var cursorSprite = sprites[cursorName][Frame]; var cursorSprite = sprites[cursorName][(int)cursorFrame % cursorSequence.Length];
var cursorSize = CursorProvider.CursorViewportZoomed ? 2.0f * cursorSprite.Size : cursorSprite.Size; var cursorSize = CursorProvider.CursorViewportZoomed ? 2.0f * cursorSprite.Size : cursorSprite.Size;
var cursorOffset = CursorProvider.CursorViewportZoomed ? var cursorOffset = CursorProvider.CursorViewportZoomed ?
@@ -86,19 +90,24 @@ namespace OpenRA.Graphics
cursorSequence.Hotspot + (0.5f * cursorSprite.Size.XY).ToInt2(); cursorSequence.Hotspot + (0.5f * cursorSprite.Size.XY).ToInt2();
renderer.SetPalette(palette); renderer.SetPalette(palette);
var mousePos = isLocked ? lockedPosition : Viewport.LastMousePos;
renderer.SpriteRenderer.DrawSprite(cursorSprite, renderer.SpriteRenderer.DrawSprite(cursorSprite,
Viewport.LastMousePos - cursorOffset, mousePos - cursorOffset,
paletteReferences[cursorSequence.Palette], paletteReferences[cursorSequence.Palette],
cursorSize); cursorSize);
} }
public int Frame public void Lock()
{ {
get Game.Renderer.Window.SetRelativeMouseMode(true);
{ lockedPosition = Viewport.LastMousePos;
var cursorSequence = cursorProvider.GetCursorSequence(cursorName); isLocked = true;
return (int)cursorFrame % cursorSequence.Length; }
}
public void Unlock()
{
Game.Renderer.Window.SetRelativeMouseMode(false);
isLocked = false;
} }
public void Dispose() public void Dispose()

View File

@@ -39,12 +39,6 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Enables the player directional targeting")] [Desc("Enables the player directional targeting")]
public readonly bool UseDirectionalTarget = false; public readonly bool UseDirectionalTarget = false;
[Desc("Placeholder cursor animation for the target cursor when using directional targeting.")]
public readonly string TargetPlaceholderCursorAnimation = null;
[Desc("Palette for placeholder cursor animation.")]
public readonly string TargetPlaceholderCursorPalette = "chrome";
[Desc("Animation used to render the direction arrows.")] [Desc("Animation used to render the direction arrows.")]
public readonly string DirectionArrowAnimation = null; public readonly string DirectionArrowAnimation = null;
@@ -75,8 +69,7 @@ namespace OpenRA.Mods.Common.Traits
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech",
Info.SelectTargetSpeechNotification, self.Owner.Faction.InternalName); Info.SelectTargetSpeechNotification, self.Owner.Faction.InternalName);
self.World.OrderGenerator = new SelectDirectionalTarget(self.World, order, manager, Info.Cursor, self.World.OrderGenerator = new SelectDirectionalTarget(self.World, order, manager, Info.Cursor, info.DirectionArrowAnimation, info.DirectionArrowPalette);
info.TargetPlaceholderCursorAnimation, info.DirectionArrowAnimation, info.TargetPlaceholderCursorPalette, info.DirectionArrowPalette);
} }
else else
base.SelectTarget(self, order, manager); base.SelectTarget(self, order, manager);

View File

@@ -53,12 +53,6 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Enables the player directional targeting")] [Desc("Enables the player directional targeting")]
public readonly bool UseDirectionalTarget = false; public readonly bool UseDirectionalTarget = false;
[Desc("Placeholder cursor animation for the target cursor when using directional targeting.")]
public readonly string TargetPlaceholderCursorAnimation = null;
[Desc("Palette for placeholder cursor animation.")]
public readonly string TargetPlaceholderCursorPalette = "chrome";
[Desc("Animation used to render the direction arrows.")] [Desc("Animation used to render the direction arrows.")]
public readonly string DirectionArrowAnimation = null; public readonly string DirectionArrowAnimation = null;
@@ -89,8 +83,7 @@ namespace OpenRA.Mods.Common.Traits
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech",
Info.SelectTargetSpeechNotification, self.Owner.Faction.InternalName); Info.SelectTargetSpeechNotification, self.Owner.Faction.InternalName);
self.World.OrderGenerator = new SelectDirectionalTarget(self.World, order, manager, Info.Cursor, self.World.OrderGenerator = new SelectDirectionalTarget(self.World, order, manager, Info.Cursor, info.DirectionArrowAnimation, info.DirectionArrowPalette);
info.TargetPlaceholderCursorAnimation, info.DirectionArrowAnimation, info.TargetPlaceholderCursorPalette, info.DirectionArrowPalette);
} }
else else
base.SelectTarget(self, order, manager); base.SelectTarget(self, order, manager);

View File

@@ -22,9 +22,7 @@ namespace OpenRA.Mods.Common.Traits
readonly string order; readonly string order;
readonly SupportPowerManager manager; readonly SupportPowerManager manager;
readonly string cursor; readonly string cursor;
readonly string targetPlaceholderCursorPalette;
readonly string directionArrowPalette; readonly string directionArrowPalette;
readonly Animation targetCursor;
readonly string[] arrows = { "arrow-t", "arrow-tl", "arrow-l", "arrow-bl", "arrow-b", "arrow-br", "arrow-r", "arrow-tr" }; readonly string[] arrows = { "arrow-t", "arrow-tl", "arrow-l", "arrow-bl", "arrow-b", "arrow-br", "arrow-r", "arrow-tr" };
readonly Arrow[] directionArrows; readonly Arrow[] directionArrows;
@@ -34,24 +32,17 @@ namespace OpenRA.Mods.Common.Traits
int2 dragLocation; int2 dragLocation;
bool activated; bool activated;
bool dragStarted; bool dragStarted;
bool hideMouse = true;
Arrow currentArrow; Arrow currentArrow;
public SelectDirectionalTarget(World world, string order, SupportPowerManager manager, string cursor, string targetPlaceholderCursorAnimation, public SelectDirectionalTarget(World world, string order, SupportPowerManager manager, string cursor,
string directionArrowAnimation, string targetPlaceholderCursorPalette, string directionArrowPalette) string directionArrowAnimation, string directionArrowPalette)
{ {
this.order = order; this.order = order;
this.manager = manager; this.manager = manager;
this.cursor = cursor; this.cursor = cursor;
this.targetPlaceholderCursorPalette = targetPlaceholderCursorPalette;
this.directionArrowPalette = directionArrowPalette; this.directionArrowPalette = directionArrowPalette;
targetCursor = new Animation(world, targetPlaceholderCursorAnimation);
targetCursor.PlayRepeating("cursor");
for (var i = 0; i < Game.Cursor.Frame; i++)
targetCursor.Tick();
directionArrows = LoadArrows(directionArrowAnimation, world, arrows.Length); directionArrows = LoadArrows(directionArrowAnimation, world, arrows.Length);
} }
@@ -70,6 +61,7 @@ namespace OpenRA.Mods.Common.Traits
targetCell = cell; targetCell = cell;
targetLocation = mi.Location; targetLocation = mi.Location;
activated = true; activated = true;
Game.Cursor.Lock();
} }
yield break; yield break;
@@ -101,8 +93,6 @@ namespace OpenRA.Mods.Common.Traits
void IOrderGenerator.Tick(World world) void IOrderGenerator.Tick(World world)
{ {
targetCursor.Tick();
// Cancel the OG if we can't use the power // Cancel the OG if we can't use the power
if (!manager.Powers.ContainsKey(order)) if (!manager.Powers.ContainsKey(order))
world.CancelInputMode(); world.CancelInputMode();
@@ -118,28 +108,16 @@ namespace OpenRA.Mods.Common.Traits
IEnumerable<IRenderable> IOrderGenerator.RenderAboveShroud(WorldRenderer wr, World world) IEnumerable<IRenderable> IOrderGenerator.RenderAboveShroud(WorldRenderer wr, World world)
{ {
if (!activated) if (!activated)
return Enumerable.Empty<IRenderable>(); yield break;
var targetPalette = wr.Palette(targetPlaceholderCursorPalette); var worldPx = wr.Viewport.ViewToWorldPx(targetLocation);
var location = activated ? targetLocation : Viewport.LastMousePos;
var worldPx = wr.Viewport.ViewToWorldPx(location);
var worldPos = wr.ProjectedPosition(worldPx); var worldPos = wr.ProjectedPosition(worldPx);
var renderables = new List<IRenderable>(targetCursor.Render(worldPos, WVec.Zero, -511, targetPalette, 1 / wr.Viewport.Zoom));
if (IsOutsideDragZone) if (IsOutsideDragZone)
{ {
var directionPalette = wr.Palette(directionArrowPalette); var directionPalette = wr.Palette(directionArrowPalette);
renderables.Add(new SpriteRenderable(currentArrow.Sprite, worldPos, WVec.Zero, -511, directionPalette, 1 / wr.Viewport.Zoom, true)); yield return new SpriteRenderable(currentArrow.Sprite, worldPos, WVec.Zero, -511, directionPalette, 1 / wr.Viewport.Zoom, true);
} }
if (hideMouse)
{
hideMouse = false;
Game.RunAfterTick(() => Game.HideCursor = true);
}
return renderables;
} }
string IOrderGenerator.GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi) { return cursor; } string IOrderGenerator.GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi) { return cursor; }
@@ -149,7 +127,7 @@ namespace OpenRA.Mods.Common.Traits
void IOrderGenerator.Deactivate() void IOrderGenerator.Deactivate()
{ {
if (activated) if (activated)
Game.HideCursor = false; Game.Cursor.Unlock();
} }
// Starting at (0, -1) and rotating in CCW // Starting at (0, -1) and rotating in CCW

View File

@@ -30,6 +30,7 @@ namespace OpenRA.Platforms.Default
Size windowSize; Size windowSize;
Size surfaceSize; Size surfaceSize;
float windowScale; float windowScale;
int2 mousePosition;
internal IntPtr Window internal IntPtr Window
{ {
@@ -276,6 +277,22 @@ namespace OpenRA.Platforms.Default
} }
} }
public void SetRelativeMouseMode(bool mode)
{
if (mode)
{
int x, y;
SDL.SDL_GetMouseState(out x, out y);
mousePosition = new int2(x, y);
SDL.SDL_SetRelativeMouseMode(SDL.SDL_bool.SDL_TRUE);
}
else
{
SDL.SDL_SetRelativeMouseMode(SDL.SDL_bool.SDL_FALSE);
SDL.SDL_WarpMouseInWindow(window, mousePosition.X, mousePosition.Y);
}
}
internal void WindowSizeChanged() internal void WindowSizeChanged()
{ {
// The ratio between pixels and points can change when moving between displays in OSX // The ratio between pixels and points can change when moving between displays in OSX

View File

@@ -655,7 +655,6 @@ HQ:
ClockSequence: clock ClockSequence: clock
CircleSequence: circles CircleSequence: circles
UseDirectionalTarget: True UseDirectionalTarget: True
TargetPlaceholderCursorAnimation: airstriketarget
DirectionArrowAnimation: airstrikedirection DirectionArrowAnimation: airstrikedirection
SupportPowerPaletteOrder: 10 SupportPowerPaletteOrder: 10
SupportPowerChargeBar: SupportPowerChargeBar:

View File

@@ -430,12 +430,6 @@ smokland:
Tick: 120 Tick: 120
ZOffset: 1023 ZOffset: 1023
airstriketarget:
cursor: mouse2
Start: 88
Length: 8
Tick: 80
airstrikedirection: airstrikedirection:
arrow-t: mouse2 arrow-t: mouse2
Start: 1 Start: 1

View File

@@ -1487,7 +1487,6 @@ AFLD:
ClockSequence: clock ClockSequence: clock
CircleSequence: circles CircleSequence: circles
UseDirectionalTarget: True UseDirectionalTarget: True
TargetPlaceholderCursorAnimation: paratarget
DirectionArrowAnimation: paradirection DirectionArrowAnimation: paradirection
SupportPowerPaletteOrder: 60 SupportPowerPaletteOrder: 60
ParatroopersPower@paratroopers: ParatroopersPower@paratroopers:
@@ -1509,7 +1508,6 @@ AFLD:
ClockSequence: clock ClockSequence: clock
CircleSequence: circles CircleSequence: circles
UseDirectionalTarget: True UseDirectionalTarget: True
TargetPlaceholderCursorAnimation: paratarget
DirectionArrowAnimation: paradirection DirectionArrowAnimation: paradirection
SupportPowerPaletteOrder: 50 SupportPowerPaletteOrder: 50
AirstrikePower@parabombs: AirstrikePower@parabombs:
@@ -1532,7 +1530,6 @@ AFLD:
ClockSequence: clock ClockSequence: clock
CircleSequence: circles CircleSequence: circles
UseDirectionalTarget: True UseDirectionalTarget: True
TargetPlaceholderCursorAnimation: paratarget
DirectionArrowAnimation: paradirection DirectionArrowAnimation: paradirection
SupportPowerPaletteOrder: 40 SupportPowerPaletteOrder: 40
ProductionBar: ProductionBar:

View File

@@ -623,12 +623,6 @@ ctflag:
Length: * Length: *
UseTilesetExtension: true UseTilesetExtension: true
paratarget:
cursor: mouse
Start: 82
Length: 8
Tick: 80
paradirection: paradirection:
arrow-t: mouse arrow-t: mouse
Start: 1 Start: 1