Input System Refactor (#840)

* Fixes right click menu stopping input

Removed a flag change when the modal stack was showing, which preventing the click from getting passed to the next function.

* Added parsing for mod2 and mod3 from Keybind YAML

* Fixes a crash on context change when a keybind is not defined in keybinds.yml

* Implemented ShowDebugConsole Hotkey

* Refactored input system

Refactored input system to run Key and Mouse input through the InputManager before doing stuff.

* Upgraded LineEdit and classes that use it. Fixed input while KeyboardFocused.

Upgraded LineEdit to use Keybinds.
Upgraded DebugConsole to use Keybinds.
Replaced all references to MouseDown, MouseUp, KeyDown, and KeyUp with KeyBindUp and KeyBindDown.
Moved UserInterfaceManager call from GameController.Input to InputManager event.
Stopped input going to simulation while a control has focus in UserInterfaceManager.

* Some fixes for input system

Fixed keybinds getting stuck when selecting a LineEdit.
Changed MenuBar to not error.
Fixed a few cases where LineEdit would eat input if you hovered over it and where mouse input got eaten when clicking in the world while a LineEdit was selected.

* Removed extra dependencies

* Added GUIBoundKeyEventArgs to ButtonEventArgs

* Fixes for input with LineEdit selected

Fixed multiple keybinds mapped to the same key not triggering.
Fixed keybind input not getting to LineEdit when hovering over a control.

* Implemented Key Repeat for LineEdit

* Fix for input on Robust.Lite Launcher

* Renames NonFocusKeybinds to EnableAllKeybinds

Renamed NonFocusKeybinds to EnableAllKeybinds and added comment to clarify usage

* Adds repeating keybinds

Used for TextBackspace, TextCursorLeft, and TextCursorRight
Reverts a change to LineEdit that implemented repeating keys
Adds some documentation comments
This commit is contained in:
ShadowCommander
2019-08-21 08:13:48 -07:00
committed by Pieter-Jan Briers
parent fc67c5069c
commit a8d6c294ab
27 changed files with 544 additions and 435 deletions

View File

@@ -5,27 +5,18 @@ namespace Robust.Client
internal sealed partial class GameController
{
/// <summary>
/// Invoked when a key on the keyboard is pressed down.
/// Invoked when a key on the keyboard or a mouse button is pressed down.
/// </summary>
public void KeyDown(KeyEventArgs keyEvent)
{
_userInterfaceManager.KeyDown(keyEvent);
if (keyEvent.Handled)
{
return;
}
_inputManager.KeyDown(keyEvent);
}
/// <summary>
/// Invoked when a key on the keyboard is released.
/// Invoked when a key on the keyboard or a mouse button is released.
/// </summary>
public void KeyUp(KeyEventArgs keyEvent)
{
// Unlike KeyDown, InputManager still gets key ups.
// My logic is that it should be fine dealing with redundant key ups and this *might* prevent edge cases.
_userInterfaceManager.KeyUp(keyEvent);
_inputManager.KeyUp(keyEvent);
}
@@ -34,24 +25,6 @@ namespace Robust.Client
_userInterfaceManager.TextEntered(textEvent);
}
/// <summary>
/// Invoked when a button on the mouse is pressed down.
/// </summary>
public void MouseDown(MouseButtonEventArgs mouseEvent)
{
_userInterfaceManager.MouseDown(mouseEvent);
_stateManager.MouseDown(mouseEvent);
}
/// <summary>
/// Invoked when a button on the mouse is released.
/// </summary>
public void MouseUp(MouseButtonEventArgs mouseButtonEventArgs)
{
_userInterfaceManager.MouseUp(mouseButtonEventArgs);
_stateManager.MouseUp(mouseButtonEventArgs);
}
/// <summary>
/// Invoked when the mouse is moved inside the game window.
/// </summary>

View File

@@ -200,7 +200,6 @@ namespace Robust.Client.Graphics.Clyde
_mainThread = Thread.CurrentThread;
_window.KeyDown += (sender, eventArgs) => { _gameController.KeyDown((KeyEventArgs) eventArgs); };
_window.KeyUp += (sender, eventArgs) => { _gameController.KeyUp((KeyEventArgs) eventArgs); };
_window.Closed += _onWindowClosed;
_window.Resize += (sender, eventArgs) =>
@@ -211,24 +210,8 @@ namespace Robust.Client.Graphics.Clyde
_regenerateLightRenderTarget();
OnWindowResized?.Invoke(new WindowResizedEventArgs(oldSize, _windowSize));
};
_window.MouseDown += (sender, eventArgs) =>
{
var mouseButtonEventArgs = (MouseButtonEventArgs) eventArgs;
_gameController.MouseDown(mouseButtonEventArgs);
if (!mouseButtonEventArgs.Handled)
{
_gameController.KeyDown((KeyEventArgs) eventArgs);
}
};
_window.MouseUp += (sender, eventArgs) =>
{
var mouseButtonEventArgs = (MouseButtonEventArgs) eventArgs;
_gameController.MouseUp(mouseButtonEventArgs);
if (!mouseButtonEventArgs.Handled)
{
_gameController.KeyUp((KeyEventArgs) eventArgs);
}
};
_window.MouseDown += (sender, eventArgs) => { _gameController.KeyDown((KeyEventArgs) eventArgs); };
_window.MouseUp += (sender, eventArgs) => { _gameController.KeyUp((KeyEventArgs) eventArgs); };
_window.MouseMove += (sender, eventArgs) =>
{
MouseScreenPosition = new Vector2(eventArgs.X, eventArgs.Y);

View File

@@ -14,8 +14,11 @@ namespace Robust.Client.Input
public static void SetupContexts(IInputContextContainer contexts)
{
var common = contexts.GetContext(InputContextContainer.DefaultContextName);
common.AddFunction(EngineKeyFunctions.Use);
common.AddFunction(EngineKeyFunctions.EscapeMenu);
common.AddFunction(EngineKeyFunctions.HideUI);
common.AddFunction(EngineKeyFunctions.ShowDebugConsole);
common.AddFunction(EngineKeyFunctions.ShowDebugMonitors);
common.AddFunction(EngineKeyFunctions.MoveUp);
common.AddFunction(EngineKeyFunctions.MoveDown);
@@ -23,6 +26,16 @@ namespace Robust.Client.Input
common.AddFunction(EngineKeyFunctions.MoveRight);
common.AddFunction(EngineKeyFunctions.Run);
common.AddFunction(EngineKeyFunctions.TextCursorLeft);
common.AddFunction(EngineKeyFunctions.TextCursorRight);
common.AddFunction(EngineKeyFunctions.TextBackspace);
common.AddFunction(EngineKeyFunctions.TextSubmit);
common.AddFunction(EngineKeyFunctions.TextPaste);
common.AddFunction(EngineKeyFunctions.TextHistoryPrev);
common.AddFunction(EngineKeyFunctions.TextHistoryNext);
common.AddFunction(EngineKeyFunctions.TextReleaseFocus);
common.AddFunction(EngineKeyFunctions.TextScrollToBottom);
var editor = contexts.New("editor", common);
editor.AddFunction(EngineKeyFunctions.EditorLinePlace);
editor.AddFunction(EngineKeyFunctions.EditorGridPlace);

View File

@@ -2,11 +2,12 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Robust.Client.GameObjects.EntitySystems;
using Robust.Client.Interfaces.Input;
using Robust.Client.Interfaces.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Input;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Interfaces.Reflection;
using Robust.Shared.Interfaces.Resources;
using Robust.Shared.IoC;
@@ -24,13 +25,9 @@ namespace Robust.Client.Input
public virtual Vector2 MouseScreenPosition => Vector2.Zero;
[Dependency]
#pragma warning disable 649
private readonly IUserInterfaceManager _uiManager;
[Dependency]
private readonly IResourceManager _resourceMan;
[Dependency]
private readonly IReflectionManager _reflectionManager;
[Dependency] private readonly IResourceManager _resourceMan;
[Dependency] private readonly IReflectionManager _reflectionManager;
#pragma warning restore 649
private readonly Dictionary<BoundKeyFunction, InputCmdHandler> _commands = new Dictionary<BoundKeyFunction, InputCmdHandler>();
@@ -43,6 +40,9 @@ namespace Robust.Client.Input
/// <inheritdoc />
public IInputContextContainer Contexts { get; } = new InputContextContainer();
/// <inheritdoc />
public event Action<BoundKeyEventArgs> UIKeyBindStateChanged;
/// <inheritdoc />
public event Action<BoundKeyEventArgs> KeyBindStateChanged;
@@ -72,6 +72,10 @@ namespace Robust.Client.Input
foreach (var function in args.OldContext.Except(args.NewContext))
{
var bind = _bindings.Find(binding => binding.Function == function);
if (bind == null)
{
continue;
}
SetBindState(bind, BoundKeyState.Up);
}
}
@@ -79,7 +83,7 @@ namespace Robust.Client.Input
/// <inheritdoc />
public void KeyDown(KeyEventArgs args)
{
if (!Enabled || UIBlocked() || args.Key == Keyboard.Key.Unknown || args.IsRepeat)
if (!Enabled || args.Key == Keyboard.Key.Unknown)
{
return;
}
@@ -99,11 +103,14 @@ namespace Robust.Client.Input
if (PackedMatchesPressedState(binding.PackedKeyCombo))
{
// this statement *should* always be true first
if (matchedCombo == 0 && PackedContainsKey(binding.PackedKeyCombo, internalKey)) // first key match becomes pressed
// Keep triggering keybinds of the same PackedKeyCombo until Handled or no bindings left
if ((matchedCombo == 0 || binding.PackedKeyCombo == matchedCombo) &&
PackedContainsKey(binding.PackedKeyCombo, internalKey))
{
matchedCombo = binding.PackedKeyCombo;
DownBind(binding);
if (DownBind(binding))
break;
}
else if (PackedIsSubPattern(matchedCombo, binding.PackedKeyCombo))
{
@@ -137,19 +144,24 @@ namespace Robust.Client.Input
_keysPressed[internalKey] = false;
}
private void DownBind(KeyBinding binding)
private bool DownBind(KeyBinding binding)
{
if (binding.State == BoundKeyState.Down)
{
if (binding.BindingType == KeyBindingType.Toggle)
{
SetBindState(binding, BoundKeyState.Up);
return SetBindState(binding, BoundKeyState.Up);
}
else if (binding.CanRepeat)
{
return SetBindState(binding, BoundKeyState.Down);
}
}
else
{
SetBindState(binding, BoundKeyState.Down);
return SetBindState(binding, BoundKeyState.Down);
}
return false;
}
private void UpBind(KeyBinding binding)
@@ -162,11 +174,17 @@ namespace Robust.Client.Input
SetBindState(binding, BoundKeyState.Up);
}
private void SetBindState(KeyBinding binding, BoundKeyState state)
private bool SetBindState(KeyBinding binding, BoundKeyState state)
{
binding.State = state;
KeyBindStateChanged?.Invoke(new BoundKeyEventArgs(binding.Function, binding.State, new ScreenCoordinates(MouseScreenPosition)));
var eventArgs = new BoundKeyEventArgs(binding.Function, binding.State, new ScreenCoordinates(MouseScreenPosition), binding.CanFocus);
UIKeyBindStateChanged?.Invoke(eventArgs);
if (state == BoundKeyState.Up || !eventArgs.Handled)
{
KeyBindStateChanged?.Invoke(eventArgs);
}
var cmd = GetInputCommand(binding.Function);
if (state == BoundKeyState.Up)
@@ -177,6 +195,7 @@ namespace Robust.Client.Input
{
cmd?.Enabled(null);
}
return (eventArgs.Handled);
}
private bool PackedMatchesPressedState(int packedKeyCombo)
@@ -254,27 +273,46 @@ namespace Robust.Client.Input
}
var key = keyMapping.GetNode("key").AsEnum<Keyboard.Key>();
var canFocus = false;
if (keyMapping.TryGetNode("canFocus", out var canFocusName))
{
canFocus = canFocusName.AsBool();
}
var canRepeat = false;
if (keyMapping.TryGetNode("canRepeat", out var canRepeatName))
{
canRepeat = canRepeatName.AsBool();
}
var mod1 = Keyboard.Key.Unknown;
if (keyMapping.TryGetNode("mod1", out var mod1Name))
{
mod1 = mod1Name.AsEnum<Keyboard.Key>();
}
var mod2 = Keyboard.Key.Unknown;
if (keyMapping.TryGetNode("mod2", out var mod2Name))
{
mod2 = mod2Name.AsEnum<Keyboard.Key>();
}
var mod3 = Keyboard.Key.Unknown;
if (keyMapping.TryGetNode("mod3", out var mod3Name))
{
mod3 = mod3Name.AsEnum<Keyboard.Key>();
}
var type = keyMapping.GetNode("type").AsEnum<KeyBindingType>();
var binding = new KeyBinding(function, type, key, mod1);
var binding = new KeyBinding(function, type, key, canFocus, canRepeat, mod1, mod2, mod3);
RegisterBinding(binding);
}
}
// Don't take input if we're focused on a LineEdit.
// LineEdits don't intercept keydowns when typing properly.
// NOTE: macOS specific!
// https://github.com/godotengine/godot/issues/15071
// So if we didn't do this, the DebugConsole wouldn't block movement (for example).
private bool UIBlocked()
public void AddClickBind()
{
return _uiManager.KeyboardFocused is LineEdit;
RegisterBinding(new KeyBinding(EngineKeyFunctions.Use, KeyBindingType.State, Keyboard.Key.MouseLeft, true, false));
}
private void RegisterBinding(KeyBinding binding)
@@ -328,15 +366,28 @@ namespace Robust.Client.Input
public BoundKeyFunction Function { get; }
public KeyBindingType BindingType { get; }
/// <summary>
/// Whether the BoundKey can change the focused control.
/// </summary>
public bool CanFocus { get; internal set; }
/// <summary>
/// Whether the BoundKey still triggers while held down.
/// </summary>
public bool CanRepeat { get; internal set; }
public KeyBinding(BoundKeyFunction function,
KeyBindingType bindingType,
Keyboard.Key baseKey,
bool canFocus, bool canRepeat,
Keyboard.Key mod1 = Keyboard.Key.Unknown,
Keyboard.Key mod2 = Keyboard.Key.Unknown,
Keyboard.Key mod3 = Keyboard.Key.Unknown)
{
Function = function;
BindingType = bindingType;
CanFocus = canFocus;
CanRepeat = canRepeat;
PackedKeyCombo = PackKeyCombo(baseKey, mod1, mod2, mod3);
}

View File

@@ -1,4 +1,4 @@
using Robust.Client.Input;
using Robust.Client.Input;
using Robust.Shared.Timing;
namespace Robust.Client.Interfaces
@@ -17,8 +17,6 @@ namespace Robust.Client.Interfaces
void KeyDown(KeyEventArgs keyEvent);
void KeyUp(KeyEventArgs keyEvent);
void TextEntered(TextEventArgs textEvent);
void MouseDown(MouseButtonEventArgs mouseEvent);
void MouseUp(MouseButtonEventArgs mouseButtonEventArgs);
void MouseMove(MouseMoveEventArgs mouseMoveEventArgs);
void MouseWheel(MouseWheelEventArgs mouseWheelEventArgs);
void OverrideMainLoop(IGameLoop gameLoop);

View File

@@ -22,6 +22,11 @@ namespace Robust.Client.Interfaces.Input
void Initialize();
/// <summary>
/// Adds the Use keybind for Keyboard.Key.MouseLeft for Robust.Lite Launcher.
/// </summary>
void AddClickBind();
void KeyDown(KeyEventArgs e);
void KeyUp(KeyEventArgs e);
@@ -42,6 +47,14 @@ namespace Robust.Client.Interfaces.Input
void SetInputCommand(BoundKeyFunction function, InputCmdHandler cmdHandler);
/// <summary>
/// UIKeyBindStateChanged is called when a keybind is found.
/// </summary>
event Action<BoundKeyEventArgs> UIKeyBindStateChanged;
/// <summary>
/// If UIKeyBindStateChanged did not handle the BoundKeyEvent, KeyBindStateChanged is called.
/// </summary>
event Action<BoundKeyEventArgs> KeyBindStateChanged;
}
}

View File

@@ -1,7 +1,8 @@
using System;
using System;
using Robust.Client.Input;
using Robust.Client.Interfaces.Graphics;
using Robust.Client.UserInterface;
using Robust.Shared.Input;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
@@ -76,9 +77,9 @@ namespace Robust.Client.Interfaces.UserInterface
void FrameUpdate(FrameEventArgs args);
void MouseDown(MouseButtonEventArgs args);
void KeyBindDown(BoundKeyEventArgs args);
void MouseUp(MouseButtonEventArgs args);
void KeyBindUp(BoundKeyEventArgs args);
void MouseMove(MouseMoveEventArgs mouseMoveEventArgs);
@@ -86,10 +87,6 @@ namespace Robust.Client.Interfaces.UserInterface
void TextEntered(TextEventArgs textEvent);
void KeyDown(KeyEventArgs keyEvent);
void KeyUp(KeyEventArgs keyEvent);
void ControlHidden(Control control);
void ControlRemovedFromTree(Control control);

View File

@@ -7,6 +7,7 @@ using Robust.Client.Interfaces.GameObjects.Components;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Interfaces.Input;
using Robust.Client.Interfaces.Placement;
using Robust.Client.Interfaces.UserInterface;
using Robust.Client.Player;
using Robust.Shared.GameObjects;
using Robust.Shared.Input;

View File

@@ -16,6 +16,8 @@ using Robust.Shared.Interfaces.Network;
using Robust.Shared.Localization;
using Robust.Shared.Network;
using Robust.Shared.Utility;
using Robust.Shared.Input;
using Robust.Client.Interfaces.Input;
namespace Robust.Client.State.States
{

View File

@@ -1,5 +1,7 @@
using Robust.Client.Input;
using Robust.Client.Utility;
using Robust.Shared.Input;
using Robust.Shared.Map;
using Robust.Shared.Maths;
using System;
@@ -19,14 +21,14 @@ namespace Robust.Client.UserInterface
{
}
public event Action<GUIMouseButtonEventArgs> OnMouseDown;
public event Action<GUIBoundKeyEventArgs> OnKeyBindDown;
protected internal virtual void MouseDown(GUIMouseButtonEventArgs args)
protected internal virtual void KeyBindDown(GUIBoundKeyEventArgs args)
{
OnMouseDown?.Invoke(args);
OnKeyBindDown?.Invoke(args);
}
protected internal virtual void MouseUp(GUIMouseButtonEventArgs args)
protected internal virtual void KeyBindUp(GUIBoundKeyEventArgs args)
{
}
@@ -34,17 +36,6 @@ namespace Robust.Client.UserInterface
{
}
public event Action<GUIKeyEventArgs> OnKeyDown;
protected internal virtual void KeyDown(GUIKeyEventArgs args)
{
OnKeyDown?.Invoke(args);
}
protected internal virtual void KeyUp(GUIKeyEventArgs args)
{
}
protected internal virtual void KeyHeld(GUIKeyEventArgs args)
{
}
@@ -54,6 +45,24 @@ namespace Robust.Client.UserInterface
}
}
public class GUIBoundKeyEventArgs : BoundKeyEventArgs
{
/// <summary>
/// Position of the mouse, relative to the current control.
/// </summary>
public Vector2 RelativePosition { get; internal set; }
public Vector2 RelativePixelPosition { get; internal set; }
public GUIBoundKeyEventArgs(BoundKeyFunction function, BoundKeyState state, ScreenCoordinates pointerLocation,
bool canFocus, Vector2 relativePosition, Vector2 relativePixelPosition)
: base(function, state, pointerLocation, canFocus)
{
RelativePosition = relativePosition;
RelativePixelPosition = relativePixelPosition;
}
}
public class GUIKeyEventArgs : KeyEventArgs
{
/// <summary>
@@ -137,38 +146,6 @@ namespace Robust.Client.UserInterface
}
}
public class GUIMouseButtonEventArgs : GUIMouseEventArgs
{
/// <summary>
/// The mouse button that has been pressed or released.
/// </summary>
public Mouse.Button Button { get; }
/// <summary>
/// True if this action was a double click.
/// Can't be true if this was a release event.
/// </summary>
public bool DoubleClick { get; }
public GUIMouseButtonEventArgs(Mouse.Button button,
bool doubleClick,
Control sourceControl,
Mouse.ButtonMask buttonMask,
Vector2 globalPosition,
Vector2 globalPixelPosition,
Vector2 relativePosition,
Vector2 relativePixelPosition,
bool alt,
bool control,
bool shift,
bool system)
: base(sourceControl, buttonMask, globalPosition, globalPixelPosition, relativePosition, relativePixelPosition, alt, control, shift, system)
{
Button = button;
DoubleClick = doubleClick;
}
}
public class GUIMouseMoveEventArgs : GUIMouseEventArgs
{
/// <summary>

View File

@@ -416,7 +416,7 @@ namespace Robust.Client.UserInterface
DisposeAllChildren();
Parent?.RemoveChild(this);
OnKeyDown = null;
OnKeyBindDown = null;
}
~Control()

View File

@@ -1,4 +1,5 @@
using System;
using Robust.Shared.Input;
using Robust.Shared.ViewVariables;
namespace Robust.Client.UserInterface.Controls
@@ -15,6 +16,7 @@ namespace Robust.Client.UserInterface.Controls
private bool _beingHovered;
private bool _disabled;
private bool _pressed;
private bool _enableAllKeybinds;
/// <summary>
/// Controls mode of operation in relation to press/release events.
@@ -61,6 +63,15 @@ namespace Robust.Client.UserInterface.Controls
}
}
/// <summary>
/// Whether a button enables Keybinds without GUIBoundKeyEventArgs.CanFocus to trigger the button.
/// </summary>
public bool EnableAllKeybinds
{
get => _enableAllKeybinds;
set => _enableAllKeybinds = value;
}
/// <summary>
/// If <c>true</c>, this button functions as a toggle, not as a regular push button.
/// </summary>
@@ -124,16 +135,16 @@ namespace Robust.Client.UserInterface.Controls
{
}
protected internal override void MouseDown(GUIMouseButtonEventArgs args)
protected internal override void KeyBindDown(GUIBoundKeyEventArgs args)
{
base.MouseDown(args);
base.KeyBindDown(args);
if (Disabled)
if (Disabled || (!_enableAllKeybinds && !args.CanFocus))
{
return;
}
var buttonEventArgs = new ButtonEventArgs(this);
var buttonEventArgs = new ButtonEventArgs(this, args);
OnButtonDown?.Invoke(buttonEventArgs);
var drawMode = DrawMode;
@@ -147,7 +158,7 @@ namespace Robust.Client.UserInterface.Controls
{
_pressed = !_pressed;
OnPressed?.Invoke(buttonEventArgs);
OnToggled?.Invoke(new ButtonToggledEventArgs(Pressed, this));
OnToggled?.Invoke(new ButtonToggledEventArgs(Pressed, this, args));
}
else
{
@@ -162,16 +173,16 @@ namespace Robust.Client.UserInterface.Controls
}
}
protected internal override void MouseUp(GUIMouseButtonEventArgs args)
protected internal override void KeyBindUp(GUIBoundKeyEventArgs args)
{
base.MouseUp(args);
base.KeyBindUp(args);
if (Disabled)
{
return;
}
var buttonEventArgs = new ButtonEventArgs(this);
var buttonEventArgs = new ButtonEventArgs(this, args);
OnButtonUp?.Invoke(buttonEventArgs);
var drawMode = DrawMode;
@@ -183,9 +194,9 @@ namespace Robust.Client.UserInterface.Controls
}
OnPressed?.Invoke(buttonEventArgs);
if (ToggleMode)
if (ToggleMode && args.CanFocus)
{
OnToggled?.Invoke(new ButtonToggledEventArgs(Pressed, this));
OnToggled?.Invoke(new ButtonToggledEventArgs(Pressed, this, args));
}
}
@@ -235,9 +246,12 @@ namespace Robust.Client.UserInterface.Controls
/// </summary>
public BaseButton Button { get; }
public ButtonEventArgs(BaseButton button)
public GUIBoundKeyEventArgs Event { get; }
public ButtonEventArgs(BaseButton button, GUIBoundKeyEventArgs args)
{
Button = button;
Event = args;
}
}
@@ -251,7 +265,7 @@ namespace Robust.Client.UserInterface.Controls
/// </summary>
public bool Pressed { get; }
public ButtonToggledEventArgs(bool pressed, BaseButton button) : base(button)
public ButtonToggledEventArgs(bool pressed, BaseButton button, GUIBoundKeyEventArgs args) : base(button, args)
{
Pressed = pressed;
}

View File

@@ -4,6 +4,7 @@ using System.Diagnostics.Contracts;
using Robust.Client.Graphics;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Input;
using Robust.Shared.Input;
using Robust.Shared.Maths;
namespace Robust.Client.UserInterface.Controls
@@ -379,6 +380,30 @@ namespace Robust.Client.UserInterface.Controls
return size;
}
protected internal override void KeyBindDown(GUIBoundKeyEventArgs args)
{
base.KeyBindDown(args);
if (SelectMode == ItemListSelectMode.None || args.Function != EngineKeyFunctions.Use)
{
return;
}
foreach (var item in _itemList)
{
if (item.Region == null)
continue;
if (!item.Region.Value.Contains(args.RelativePosition))
continue;
if (item.Selectable && !item.Disabled)
if (item.Selected)
Unselect(item);
else
Select(item, SelectMode == ItemListSelectMode.Single);
break;
}
}
protected internal override void MouseMove(GUIMouseMoveEventArgs args)
{
base.MouseMove(args);
@@ -406,28 +431,6 @@ namespace Robust.Client.UserInterface.Controls
_isAtBottom = _scrollBar.IsAtEnd;
}
protected internal override void MouseDown(GUIMouseButtonEventArgs args)
{
base.MouseDown(args);
if (SelectMode == ItemListSelectMode.None || args.Button != Mouse.Button.Left)
{
return;
}
foreach (var item in _itemList)
{
if (item.Region == null) continue;
if (!item.Region.Value.Contains(args.RelativePosition)) continue;
if (item.Selectable && !item.Disabled)
if (item.Selected)
Unselect(item);
else
Select(item, SelectMode == ItemListSelectMode.Single);
break;
}
}
[Pure]
private int _getScrollSpeed()
{

View File

@@ -1,10 +1,14 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Robust.Client.GameObjects.EntitySystems;
using Robust.Client.Graphics;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Input;
using Robust.Client.Interfaces.Input;
using Robust.Client.Interfaces.UserInterface;
using Robust.Shared.Input;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
@@ -82,6 +86,22 @@ namespace Robust.Client.UserInterface.Controls
}
}
public int CursorPos
{
set
{
if (value < 0)
{
value = 0;
}
else if (value > _text.Length)
{
value = _text.Length;
}
_cursorPosition = value;
}
}
public bool IgnoreNext { get; set; }
// TODO:
@@ -236,16 +256,14 @@ namespace Robust.Client.UserInterface.Controls
_updatePseudoClass();
}
protected internal override void KeyDown(GUIKeyEventArgs args)
protected internal override void KeyBindDown(GUIBoundKeyEventArgs args)
{
base.KeyDown(args);
base.KeyBindDown(args);
// Just eat all keyboard input.
args.Handle();
switch (args.Key)
if (!args.CanFocus)
{
case Keyboard.Key.BackSpace:
if (args.Function == EngineKeyFunctions.TextBackspace)
{
if (_cursorPosition == 0 || !Editable)
{
return;
@@ -255,37 +273,35 @@ namespace Robust.Client.UserInterface.Controls
OnTextChanged?.Invoke(new LineEditEventArgs(this, _text));
_cursorPosition -= 1;
_updatePseudoClass();
break;
case Keyboard.Key.Left:
}
else if (args.Function == EngineKeyFunctions.TextCursorLeft)
{
if (_cursorPosition == 0)
{
return;
}
_cursorPosition -= 1;
break;
case Keyboard.Key.Right:
}
else if (args.Function == EngineKeyFunctions.TextCursorRight)
{
if (_cursorPosition == _text.Length)
{
return;
}
_cursorPosition += 1;
break;
case Keyboard.Key.NumpadEnter:
case Keyboard.Key.Return:
}
else if (args.Function == EngineKeyFunctions.TextSubmit)
{
if (Editable)
{
OnTextEntered?.Invoke(new LineEditEventArgs(this, _text));
}
break;
case Keyboard.Key.V:
if (Editable && args.Control)
}
else if (args.Function == EngineKeyFunctions.TextPaste)
{
if (Editable)
{
var clipboard = IoCManager.Resolve<IClipboardManager>();
if (!clipboard.Available)
@@ -296,63 +312,57 @@ namespace Robust.Client.UserInterface.Controls
InsertAtCursor(clipboard.GetText());
}
break;
}
}
}
protected internal override void MouseDown(GUIMouseButtonEventArgs args)
{
base.MouseDown(args);
// Find closest cursor position under mouse.
var style = _getStyleBox();
var contentBox = style.GetContentBox(PixelSizeBox);
var clickPosX = args.RelativePosition.X * UIScale;
var font = _getFont();
var index = 0;
var chrPosX = contentBox.Left;
var lastChrPostX = contentBox.Left;
foreach (var chr in _text)
else
{
if (!font.TryGetCharMetrics(chr, UIScale, out var metrics))
// Find closest cursor position under mouse.
var style = _getStyleBox();
var contentBox = style.GetContentBox(PixelSizeBox);
var clickPosX = args.RelativePosition.X * UIScale;
var font = _getFont();
var index = 0;
var chrPosX = contentBox.Left;
var lastChrPostX = contentBox.Left;
foreach (var chr in _text)
{
if (!font.TryGetCharMetrics(chr, UIScale, out var metrics))
{
index += 1;
continue;
}
if (chrPosX > clickPosX)
{
break;
}
lastChrPostX = chrPosX;
chrPosX += metrics.Advance;
index += 1;
continue;
if (chrPosX > contentBox.Right)
{
break;
}
}
if (chrPosX > clickPosX)
// Distance between the right side of the glyph overlapping the mouse and the mouse.
var distanceRight = chrPosX - clickPosX;
// Same but left side.
var distanceLeft = clickPosX - lastChrPostX;
// If the mouse is closer to the left of the glyph we lower the index one, so we select before that glyph.
if (distanceRight > distanceLeft)
{
break;
index -= 1;
}
lastChrPostX = chrPosX;
chrPosX += metrics.Advance;
index += 1;
if (chrPosX > contentBox.Right)
{
break;
}
_cursorPosition = index;
}
// Distance between the right side of the glyph overlapping the mouse and the mouse.
var distanceRight = chrPosX - clickPosX;
// Same but left side.
var distanceLeft = clickPosX - lastChrPostX;
// If the mouse is closer to the left of the glyph we lower the index one, so we select before that glyph.
if (distanceRight > distanceLeft)
{
index -= 1;
}
_cursorPosition = index;
// Reset this so the cursor is always visible immediately after a click.
_cursorCurrentlyLit = true;
_cursorBlinkTimer = BlinkTime;
// Reset this so the cursor is always visible immediately after a keybind is pressed.
_resetCursorBlink();
}
protected internal override void FocusEntered()
@@ -360,8 +370,7 @@ namespace Robust.Client.UserInterface.Controls
base.FocusEntered();
// Reset this so the cursor is always visible immediately after gaining focus..
_cursorCurrentlyLit = true;
_cursorBlinkTimer = BlinkTime;
_resetCursorBlink();
}
[Pure]
@@ -420,5 +429,11 @@ namespace Robust.Client.UserInterface.Controls
Text = text;
}
}
private void _resetCursorBlink()
{
_cursorCurrentlyLit = true;
_cursorBlinkTimer = BlinkTime;
}
}
}

View File

@@ -42,7 +42,7 @@ namespace Robust.Client.UserInterface.Controls
_buttons.Add(button);
_hBox.AddChild(button);
button.OnMouseDown += _ => OpenPopupFor(button);
button.OnKeyBindDown += _ => OpenPopupFor(button);
button.OnMouseEntered += () =>
{

View File

@@ -2,6 +2,7 @@
using JetBrains.Annotations;
using Robust.Client.Graphics.Drawing;
using Robust.Client.Input;
using Robust.Shared.Input;
using Robust.Shared.Maths;
namespace Robust.Client.UserInterface.Controls
@@ -53,6 +54,38 @@ namespace Robust.Client.UserInterface.Controls
_updatePseudoClass();
}
protected internal override void KeyBindDown(GUIBoundKeyEventArgs args)
{
base.KeyBindDown(args);
if (args.Function != EngineKeyFunctions.Use)
{
return;
}
var box = _getGrabberBox();
if (!box.Contains(args.RelativePosition))
{
return;
}
_grabData = (args.RelativePosition, Value);
_updatePseudoClass();
}
protected internal override void KeyBindUp(GUIBoundKeyEventArgs args)
{
base.KeyBindUp(args);
if (args.Function != EngineKeyFunctions.Use)
{
return;
}
_grabData = null;
_updatePseudoClass();
}
protected internal override void MouseMove(GUIMouseMoveEventArgs args)
{
if (_grabData == null)
@@ -82,34 +115,6 @@ namespace Robust.Client.UserInterface.Controls
Value = movedValue;
}
protected internal override void MouseDown(GUIMouseButtonEventArgs args)
{
if (args.Button != Mouse.Button.Left)
{
return;
}
var box = _getGrabberBox();
if (!box.Contains(args.RelativePosition))
{
return;
}
_grabData = (args.RelativePosition, Value);
_updatePseudoClass();
}
protected internal override void MouseUp(GUIMouseButtonEventArgs args)
{
if (args.Button != Mouse.Button.Left)
{
return;
}
_grabData = null;
_updatePseudoClass();
}
[System.Diagnostics.Contracts.Pure]
private UIBox2 _getGrabberBox()
{

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Robust.Client.Graphics;
@@ -234,11 +234,11 @@ namespace Robust.Client.UserInterface.Controls
_fixChildMargins(control);
}
protected internal override void MouseDown(GUIMouseButtonEventArgs args)
protected internal override void KeyBindDown(GUIBoundKeyEventArgs args)
{
base.MouseDown(args);
base.KeyBindDown(args);
if (!TabsVisible)
if (!TabsVisible || !args.CanFocus)
{
return;
}

View File

@@ -80,9 +80,14 @@ namespace Robust.Client.UserInterface.Controls
return item;
}
protected internal override void MouseDown(GUIMouseButtonEventArgs args)
protected internal override void KeyBindDown(GUIBoundKeyEventArgs args)
{
base.MouseDown(args);
base.KeyBindDown(args);
if (!args.CanFocus)
{
return;
}
var item = _tryFindItemAtPosition(args.RelativePosition);

View File

@@ -7,6 +7,7 @@ using Robust.Client.Graphics.Drawing;
using Robust.Client.Input;
using Robust.Client.Interfaces.Console;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Input;
using Robust.Shared.Interfaces.Resources;
using Robust.Shared.Maths;
using Robust.Shared.Timing;
@@ -71,7 +72,7 @@ namespace Robust.Client.UserInterface.CustomControls
CommandBar = new LineEdit {PlaceHolder = "Command Here"};
boxContainer.AddChild(CommandBar);
CommandBar.OnKeyDown += CommandBarOnOnKeyDown;
CommandBar.OnKeyBindDown += CommandBarOnOnKeyBindDown;
CommandBar.OnTextEntered += CommandEntered;
CommandBar.OnTextChanged += CommandBarOnOnTextChanged;
@@ -156,54 +157,55 @@ namespace Robust.Client.UserInterface.CustomControls
}
}
private void CommandBarOnOnKeyDown(GUIKeyEventArgs obj)
private void CommandBarOnOnKeyBindDown(GUIBoundKeyEventArgs args)
{
switch (obj.Key)
if (args.Function == EngineKeyFunctions.TextReleaseFocus)
{
case Keyboard.Key.Up:
CommandBar.ReleaseKeyboardFocus();
args.Handle();
Toggle();
return;
}
else if (args.Function == EngineKeyFunctions.TextHistoryPrev)
{
args.Handle();
var current = CommandBar.Text;
if (!string.IsNullOrWhiteSpace(current) && _currentCommandEdited)
{
obj.Handle();
var current = CommandBar.Text;
if (!string.IsNullOrWhiteSpace(current) && _currentCommandEdited)
{
// Block up/down if something is typed in.
return;
}
if (_historyPosition <= 0)
{
return;
}
CommandBar.Text = CommandHistory[--_historyPosition];
break;
// Block up/down if something is typed in.
return;
}
case Keyboard.Key.Down:
if (_historyPosition <= 0)
{
obj.Handle();
var current = CommandBar.Text;
if (!string.IsNullOrWhiteSpace(current) && _currentCommandEdited)
{
// Block up/down if something is typed in.
return;
}
if (++_historyPosition >= CommandHistory.Count)
{
CommandBar.Text = "";
_historyPosition = CommandHistory.Count;
return;
}
CommandBar.Text = CommandHistory[_historyPosition];
break;
return;
}
case Keyboard.Key.PageDown:
CommandBar.Text = CommandHistory[--_historyPosition];
}
else if (args.Function == EngineKeyFunctions.TextHistoryNext)
{
args.Handle();
var current = CommandBar.Text;
if (!string.IsNullOrWhiteSpace(current) && _currentCommandEdited)
{
obj.Handle();
Output.ScrollToBottom();
break;
// Block up/down if something is typed in.
return;
}
if (++_historyPosition >= CommandHistory.Count)
{
CommandBar.Text = "";
_historyPosition = CommandHistory.Count;
return;
}
CommandBar.Text = CommandHistory[_historyPosition];
}
else if (args.Function == EngineKeyFunctions.TextScrollToBottom)
{
args.Handle();
Output.ScrollToBottom();
}
}

View File

@@ -156,24 +156,34 @@ namespace Robust.Client.UserInterface.CustomControls
OnClose?.Invoke();
}
protected internal override void MouseDown(GUIMouseButtonEventArgs args)
protected internal override void KeyBindDown(GUIBoundKeyEventArgs args)
{
base.MouseDown(args);
base.KeyBindDown(args);
if (!args.CanFocus)
{
return;
}
CurrentDrag = GetDragModeFor(args.RelativePosition);
if (CurrentDrag != DragMode.None)
{
DragOffsetTopLeft = args.GlobalPosition - Position;
DragOffsetBottomRight = Position + Size - args.GlobalPosition;
DragOffsetTopLeft = args.PointerLocation.Position - Position;
DragOffsetBottomRight = Position + Size - args.PointerLocation.Position;
}
MoveToFront();
}
protected internal override void MouseUp(GUIMouseButtonEventArgs args)
protected internal override void KeyBindUp(GUIBoundKeyEventArgs args)
{
base.MouseUp(args);
base.KeyBindUp(args);
if (!args.CanFocus)
{
return;
}
DragOffsetTopLeft = DragOffsetBottomRight = Vector2.Zero;
CurrentDrag = DragMode.None;

View File

@@ -45,7 +45,7 @@ namespace Robust.Client.UserInterface
// When a control receives a mouse down it must also receive a mouse up and mouse moves, always.
// So we keep track of which control is "focused" by the mouse.
private Control _mouseFocused;
private Control _controlFocused;
public Control StateRoot { get; private set; }
public Control ModalRoot { get; private set; }
@@ -80,6 +80,9 @@ namespace Robust.Client.UserInterface
_debugMonitors = new DebugMonitors(_gameTiming, _playerManager, _eyeManager, _inputManager, _stateManager, _displayManager, _netManager, _mapManager);
RootControl.AddChild(_debugMonitors);
_inputManager.SetInputCommand(EngineKeyFunctions.ShowDebugConsole,
InputCmdHandler.FromDelegate(session => DebugConsole.Toggle()));
_inputManager.SetInputCommand(EngineKeyFunctions.ShowDebugMonitors,
InputCmdHandler.FromDelegate(enabled: session => { DebugMonitors.Visible = true; },
disabled: session => { DebugMonitors.Visible = false; }));
@@ -88,6 +91,8 @@ namespace Robust.Client.UserInterface
InputCmdHandler.FromDelegate(
enabled: session => _rendering = false,
disabled: session => _rendering = true));
_inputManager.UIKeyBindStateChanged += OnUIKeyBindStateChanged;
}
private void _initializeCommon()
@@ -177,63 +182,72 @@ namespace Robust.Client.UserInterface
}
}
public void MouseDown(MouseButtonEventArgs args)
public void KeyBindDown(BoundKeyEventArgs args)
{
// If we have a modal open and the mouse down was outside it, close said modal.
if (_modalStack.Count != 0)
var control = MouseGetControl(args.PointerLocation.Position);
if (args.CanFocus)
{
var top = _modalStack[_modalStack.Count - 1];
var offset = args.Position - top.GlobalPixelPosition;
if (!top.HasPoint(offset / UIScale))
// If we have a modal open and the mouse down was outside it, close said modal.
if (_modalStack.Count != 0)
{
RemoveModal(top);
args.Handle();
var top = _modalStack[_modalStack.Count - 1];
var offset = args.PointerLocation.Position - top.GlobalPixelPosition;
if (!top.HasPoint(offset / UIScale))
{
RemoveModal(top);
return;
}
}
if (control == null)
{
ReleaseKeyboardFocus();
return;
}
_controlFocused = control;
if (_controlFocused.CanKeyboardFocus && _controlFocused.KeyboardFocusOnClick)
{
_controlFocused.GrabKeyboardFocus();
}
}
else if (KeyboardFocused != null)
{
control = KeyboardFocused;
}
var control = MouseGetControl(args.Position);
if (control == null)
{
ReleaseKeyboardFocus();
return;
}
_mouseFocused = control;
var guiArgs = new GUIBoundKeyEventArgs(args.Function, args.State, args.PointerLocation, args.CanFocus,
args.PointerLocation.Position / UIScale - control.GlobalPosition,
args.PointerLocation.Position - control.GlobalPixelPosition);
if (_mouseFocused.CanKeyboardFocus && _mouseFocused.KeyboardFocusOnClick)
_doGuiInput(control, guiArgs, (c, ev) => c.KeyBindDown(ev));
if (args.CanFocus)
{
_mouseFocused.GrabKeyboardFocus();
args.Handle();
}
var guiArgs = new GUIMouseButtonEventArgs(args.Button, args.DoubleClick, control, Mouse.ButtonMask.None,
args.Position / UIScale, args.Position, args.Position / UIScale - control.GlobalPosition,
args.Position - control.GlobalPixelPosition, args.Alt, args.Control, args.Shift,
args.System);
_doMouseGuiInput(control, guiArgs, (c, ev) => c.MouseDown(ev));
// Always mark this as handled.
// The only case it should not be is if we do not have a control to click on,
// in which case we never reach this.
args.Handle();
}
public void MouseUp(MouseButtonEventArgs args)
public void KeyBindUp(BoundKeyEventArgs args)
{
if (_mouseFocused == null)
var control = _controlFocused ?? KeyboardFocused ?? MouseGetControl(args.PointerLocation.Position);
if (control == null)
{
return;
}
var guiArgs = new GUIMouseButtonEventArgs(args.Button, args.DoubleClick, _mouseFocused,
Mouse.ButtonMask.None,
args.Position / UIScale, args.Position, args.Position / UIScale - _mouseFocused.GlobalPosition,
args.Position - _mouseFocused.GlobalPixelPosition, args.Alt, args.Control, args.Shift,
args.System);
var guiArgs = new GUIBoundKeyEventArgs(args.Function, args.State, args.PointerLocation, args.CanFocus,
args.PointerLocation.Position / UIScale - control.GlobalPosition,
args.PointerLocation.Position - control.GlobalPixelPosition);
_doMouseGuiInput(_mouseFocused, guiArgs, (c, ev) => c.MouseUp(ev));
_mouseFocused = null;
_doGuiInput(control, guiArgs, (c, ev) => c.KeyBindUp(ev));
_controlFocused = null;
// Always mark this as handled.
// The only case it should not be is if we do not have a control to click on,
@@ -245,7 +259,7 @@ namespace Robust.Client.UserInterface
{
_resetTooltipTimer();
// Update which control is considered hovered.
var newHovered = _mouseFocused ?? MouseGetControl(mouseMoveEventArgs.Position);
var newHovered = _controlFocused ?? MouseGetControl(mouseMoveEventArgs.Position);
if (newHovered != CurrentlyHovered)
{
_clearTooltip();
@@ -254,7 +268,7 @@ namespace Robust.Client.UserInterface
CurrentlyHovered?.MouseEntered();
}
var target = _mouseFocused ?? newHovered;
var target = _controlFocused ?? newHovered;
if (target != null)
{
var guiArgs = new GUIMouseMoveEventArgs(mouseMoveEventArgs.Relative / UIScale,
@@ -298,43 +312,6 @@ namespace Robust.Client.UserInterface
KeyboardFocused.TextEntered(guiArgs);
}
public void KeyDown(KeyEventArgs keyEvent)
{
// TODO: This is ugly.
if (keyEvent.Key == Keyboard.Key.Tilde)
{
keyEvent.Handle();
DebugConsole.Toggle();
return;
}
if (KeyboardFocused == null)
{
return;
}
var guiArgs = new GUIKeyEventArgs(KeyboardFocused, keyEvent.Key, keyEvent.IsRepeat, keyEvent.Alt,
keyEvent.Control, keyEvent.Shift, keyEvent.System);
KeyboardFocused.KeyDown(guiArgs);
if (guiArgs.Handled)
{
keyEvent.Handle();
}
}
public void KeyUp(KeyEventArgs keyEvent)
{
if (KeyboardFocused == null)
{
return;
}
var guiArgs = new GUIKeyEventArgs(KeyboardFocused, keyEvent.Key, keyEvent.IsRepeat, keyEvent.Alt,
keyEvent.Control, keyEvent.Shift, keyEvent.System);
KeyboardFocused.KeyUp(guiArgs);
}
public void DisposeAllComponents()
{
RootControl.DisposeAllChildren();
@@ -356,6 +333,7 @@ namespace Robust.Client.UserInterface
return _mouseFindControlAtPos(RootControl, coordinates);
}
/// <inheritdoc />
public void GrabKeyboardFocus(Control control)
{
if (control == null)
@@ -416,9 +394,9 @@ namespace Robust.Client.UserInterface
CurrentlyHovered = null;
}
if (control == _mouseFocused)
if (control == _controlFocused)
{
_mouseFocused = null;
_controlFocused = null;
}
}
@@ -564,6 +542,28 @@ namespace Robust.Client.UserInterface
}
}
private static void _doGuiInput<T>(Control control, T guiEvent, Action<Control, T> action,
bool ignoreStop = false)
where T : GUIBoundKeyEventArgs
{
while (control != null)
{
if (control.MouseFilter != Control.MouseFilterMode.Ignore)
{
action(control, guiEvent);
if (guiEvent.Handled || (!ignoreStop && control.MouseFilter == Control.MouseFilterMode.Stop))
{
break;
}
}
guiEvent.RelativePosition += control.Position;
guiEvent.RelativePixelPosition += control.PixelPosition;
control = control.Parent;
}
}
private void _clearTooltip()
{
_tooltip.Visible = false;
@@ -633,5 +633,25 @@ namespace Robust.Client.UserInterface
{
RootControl.Size = _displayManager.ScreenSize / UIScale;
}
/// <summary>
/// Converts
/// </summary>
/// <param name="args">Event data values for a bound key state change.</param>
private void OnUIKeyBindStateChanged(BoundKeyEventArgs args)
{
if (!args.CanFocus && KeyboardFocused != null)
{
args.Handle();
}
if (args.State == BoundKeyState.Down)
{
KeyBindDown(args);
}
else
{
KeyBindUp(args);
}
}
}
}

View File

@@ -140,9 +140,14 @@ namespace Robust.Client.ViewVariables
return box;
}
protected internal override void MouseDown(GUIMouseButtonEventArgs args)
protected internal override void KeyBindDown(GUIBoundKeyEventArgs args)
{
base.MouseDown(args);
base.KeyBindDown(args);
if (!args.CanFocus)
{
return;
}
BottomContainer.Visible = !BottomContainer.Visible;
args.Handle();

View File

@@ -1,10 +1,11 @@
using System;
using System;
using System.Globalization;
using Robust.Client;
using Robust.Client.Input;
using Robust.Client.Interfaces;
using Robust.Client.Interfaces.Graphics;
using Robust.Client.Interfaces.Graphics.ClientEye;
using Robust.Client.Interfaces.Input;
using Robust.Client.Interfaces.ResourceManagement;
using Robust.Client.Interfaces.UserInterface;
using Robust.Shared;
@@ -38,6 +39,7 @@ namespace Robust.Lite
[Dependency] private readonly ITaskManager _taskManager;
[Dependency] private readonly ITimerManager _timerManager;
[Dependency] private readonly IUserInterfaceManagerInternal _userInterfaceManager;
[Dependency] private readonly IInputManager _inputManager;
#pragma warning restore 649
public bool LoadConfigAndUserData { get; set; }
@@ -96,6 +98,10 @@ namespace Robust.Lite
_userInterfaceManager.Initialize();
_inputManager.Initialize();
_inputManager.AddClickBind();
_clyde.Ready();
}
@@ -153,12 +159,12 @@ namespace Robust.Lite
public void KeyDown(KeyEventArgs keyEvent)
{
_userInterfaceManager.KeyDown(keyEvent);
_inputManager.KeyDown(keyEvent);
}
public void KeyUp(KeyEventArgs keyEvent)
{
_userInterfaceManager.KeyUp(keyEvent);
_inputManager.KeyUp(keyEvent);
}
public void TextEntered(TextEventArgs textEvent)
@@ -166,16 +172,6 @@ namespace Robust.Lite
_userInterfaceManager.TextEntered(textEvent);
}
public void MouseDown(MouseButtonEventArgs mouseEvent)
{
_userInterfaceManager.MouseDown(mouseEvent);
}
public void MouseUp(MouseButtonEventArgs mouseButtonEventArgs)
{
_userInterfaceManager.MouseUp(mouseButtonEventArgs);
}
public void MouseMove(MouseMoveEventArgs mouseMoveEventArgs)
{
_userInterfaceManager.MouseMove(mouseMoveEventArgs);

View File

@@ -23,17 +23,33 @@ namespace Robust.Shared.Input
/// </summary>
public ScreenCoordinates PointerLocation { get; }
/// <summary>
/// Whether the Bound key can change the focused control.
/// </summary>
public bool CanFocus { get; internal set; }
public bool Handled { get; private set; }
/// <summary>
/// Constructs a new instance of <see cref="BoundKeyEventArgs"/>.
/// </summary>
/// <param name="function">Bound key that that is changing.</param>
/// <param name="state">New state of the function.</param>
/// <param name="pointerLocation">Current Pointer location in screen coordinates.</param>
public BoundKeyEventArgs(BoundKeyFunction function, BoundKeyState state, ScreenCoordinates pointerLocation)
public BoundKeyEventArgs(BoundKeyFunction function, BoundKeyState state, ScreenCoordinates pointerLocation, bool canFocus)
{
Function = function;
State = state;
PointerLocation = pointerLocation;
CanFocus = canFocus;
}
/// <summary>
/// Mark this event as handled.
/// </summary>
public void Handle()
{
Handled = true;
}
}
}

View File

@@ -18,6 +18,9 @@ namespace Robust.Shared.Input
public static readonly BoundKeyFunction MoveRight = "MoveRight";
public static readonly BoundKeyFunction Run = "Run";
public static readonly BoundKeyFunction Use = "Use";
public static readonly BoundKeyFunction ShowDebugConsole = "ShowDebugConsole";
public static readonly BoundKeyFunction ShowDebugMonitors = "ShowDebugMonitors";
public static readonly BoundKeyFunction HideUI = "HideUI";
public static readonly BoundKeyFunction EscapeMenu = "ShowEscapeMenu";
@@ -27,6 +30,16 @@ namespace Robust.Shared.Input
public static readonly BoundKeyFunction EditorPlaceObject = "EditorPlaceObject";
public static readonly BoundKeyFunction EditorCancelPlace = "EditorCancelPlace";
public static readonly BoundKeyFunction EditorRotateObject = "EditorRotateObject";
public static readonly BoundKeyFunction TextCursorLeft = "TextCursorLeft";
public static readonly BoundKeyFunction TextCursorRight = "TextCursorRight";
public static readonly BoundKeyFunction TextBackspace = "TextBackspace";
public static readonly BoundKeyFunction TextSubmit = "TextSubmit";
public static readonly BoundKeyFunction TextPaste = "TextPaste";
public static readonly BoundKeyFunction TextHistoryPrev = "TextHistoryPrev";
public static readonly BoundKeyFunction TextHistoryNext = "TextHistoryNext";
public static readonly BoundKeyFunction TextReleaseFocus = "TextReleaseFocus";
public static readonly BoundKeyFunction TextScrollToBottom = "TextScrollToBottom";
}
[Serializable, NetSerializable]

View File

@@ -1,8 +1,9 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.CodeAnalysis;
using NUnit.Framework;
using Robust.Client.Input;
using Robust.Client.Interfaces.UserInterface;
using Robust.Client.UserInterface;
using Robust.Shared.Input;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
@@ -60,15 +61,15 @@ namespace Robust.UnitTesting.Client.UserInterface
control3.AddChild(control4);
control4.Position = new Vector2(5, 5);
var mouseEvent = new MouseButtonEventArgs(Mouse.Button.Left, false, Mouse.ButtonMask.None,
new Vector2(30, 30), false, false, false, false);
var mouseEvent = new BoundKeyEventArgs(EngineKeyFunctions.Use, BoundKeyState.Down,
new Robust.Shared.Map.ScreenCoordinates(30, 30), true);
var control2Fired = false;
var control3Fired = false;
control1.OnMouseDown += _ => Assert.Fail("Control 1 should not get a mouse event.");
control1.OnKeyBindDown += _ => Assert.Fail("Control 1 should not get a mouse event.");
void Control2MouseDown(GUIMouseButtonEventArgs ev)
void Control2MouseDown(GUIBoundKeyEventArgs ev)
{
Assert.That(control2Fired, Is.False);
Assert.That(control3Fired, Is.True);
@@ -78,9 +79,9 @@ namespace Robust.UnitTesting.Client.UserInterface
control2Fired = true;
}
control2.OnMouseDown += Control2MouseDown;
control2.OnKeyBindDown += Control2MouseDown;
control3.OnMouseDown += ev =>
control3.OnKeyBindDown += ev =>
{
Assert.That(control2Fired, Is.False);
Assert.That(control3Fired, Is.False);
@@ -90,9 +91,9 @@ namespace Robust.UnitTesting.Client.UserInterface
control3Fired = true;
};
control4.OnMouseDown += _ => Assert.Fail("Control 4 should not get a mouse event.");
control4.OnKeyBindDown += _ => Assert.Fail("Control 4 should not get a mouse event.");
_userInterfaceManager.MouseDown(mouseEvent);
_userInterfaceManager.KeyBindDown(mouseEvent);
Assert.Multiple(() =>
{
@@ -106,8 +107,8 @@ namespace Robust.UnitTesting.Client.UserInterface
control2Fired = false;
control3Fired = false;
control2.OnMouseDown -= Control2MouseDown;
control2.OnMouseDown += ev =>
control2.OnKeyBindDown -= Control2MouseDown;
control2.OnKeyBindDown += ev =>
{
Assert.That(control2Fired, Is.False);
Assert.That(control3Fired, Is.True);
@@ -119,7 +120,7 @@ namespace Robust.UnitTesting.Client.UserInterface
};
control2.MouseFilter = Control.MouseFilterMode.Pass;
_userInterfaceManager.MouseDown(mouseEvent);
_userInterfaceManager.KeyBindDown(mouseEvent);
Assert.Multiple(() =>
{
@@ -214,10 +215,12 @@ namespace Robust.UnitTesting.Client.UserInterface
_userInterfaceManager.RootControl.ForceRunLayoutUpdate();
var mouseEvent = new MouseButtonEventArgs(Mouse.Button.Left, false, Mouse.ButtonMask.None,
new Vector2(30, 30), false, false, false, false);
var pos = new Robust.Shared.Map.ScreenCoordinates(30, 30);
_userInterfaceManager.MouseDown(mouseEvent);
var mouseEvent = new GUIBoundKeyEventArgs(EngineKeyFunctions.Use, BoundKeyState.Down,
pos, true, pos.Position / 1 - control.GlobalPosition, pos.Position - control.GlobalPixelPosition);
_userInterfaceManager.KeyBindDown(mouseEvent);
Assert.That(_userInterfaceManager.KeyboardFocused, Is.EqualTo(control));
_userInterfaceManager.ReleaseKeyboardFocus();
@@ -240,10 +243,12 @@ namespace Robust.UnitTesting.Client.UserInterface
_userInterfaceManager.RootControl.AddChild(control);
var mouseEvent = new MouseButtonEventArgs(Mouse.Button.Left, false, Mouse.ButtonMask.None,
new Vector2(30, 30), false, false, false, false);
var pos = new Robust.Shared.Map.ScreenCoordinates(30, 30);
_userInterfaceManager.MouseDown(mouseEvent);
var mouseEvent = new GUIBoundKeyEventArgs(EngineKeyFunctions.Use, BoundKeyState.Down,
pos, true, pos.Position / 1 - control.GlobalPosition, pos.Position - control.GlobalPixelPosition);
_userInterfaceManager.KeyBindDown(mouseEvent);
Assert.That(_userInterfaceManager.KeyboardFocused, Is.Null);

View File

@@ -1,4 +1,4 @@
using Robust.Client;
using Robust.Client;
using Robust.Client.Input;
using Robust.Client.Interfaces;
using Robust.Shared.Timing;
@@ -37,14 +37,6 @@ namespace Robust.UnitTesting
{
}
public void MouseDown(MouseButtonEventArgs mouseEvent)
{
}
public void MouseUp(MouseButtonEventArgs mouseButtonEventArgs)
{
}
public void MouseMove(MouseMoveEventArgs mouseMoveEventArgs)
{
}