Skip to content

Commit

Permalink
Merge pull request #48 from technologists-team/update-input
Browse files Browse the repository at this point in the history
Update input
  • Loading branch information
Tornado-Technology authored Aug 14, 2024
2 parents 16d3a24 + 7328a1f commit a8070ff
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 38 deletions.
1 change: 1 addition & 0 deletions Hypercube.Client/ClientConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
public static class ClientConstants
{
public static bool MultiThreadingWindow = false;

}
16 changes: 8 additions & 8 deletions Hypercube.Client/Graphics/Viewports/CameraManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,28 @@ public void UpdateInput(ICamera? camera, float delta)

var speed = 60f;

if (_inputHandler.IsKeyDown(Key.W))
if (_inputHandler.IsKeyHeld(Key.W))
position += Vector3.UnitY * speed * delta;

if (_inputHandler.IsKeyDown(Key.S))
if (_inputHandler.IsKeyHeld(Key.S))
position -= Vector3.UnitY * speed * delta;

if (_inputHandler.IsKeyDown(Key.A))
if (_inputHandler.IsKeyHeld(Key.A))
position -= Vector3.UnitX * speed * delta;

if (_inputHandler.IsKeyDown(Key.D))
if (_inputHandler.IsKeyHeld(Key.D))
position += Vector3.UnitX * speed * delta;

if (_inputHandler.IsKeyDown(Key.Q))
if (_inputHandler.IsKeyHeld(Key.Q))
rotation -= Vector3.UnitZ * delta;

if (_inputHandler.IsKeyDown(Key.E))
if (_inputHandler.IsKeyHeld(Key.E))
rotation += Vector3.UnitZ * delta;

if (_inputHandler.IsKeyDown(Key.T))
if (_inputHandler.IsKeyHeld(Key.T))
scale -= Vector3.One * delta;

if (_inputHandler.IsKeyDown(Key.Y))
if (_inputHandler.IsKeyHeld(Key.Y))
scale += Vector3.One * delta;

camera.SetPosition(position);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ private void OnErrorHandled(ErrorCode error, string description)

private void OnWindowKeyHandled(Window* window, Keys glfwKey, int scanCode, InputAction action, GlfwKeyModifiers mods)
{
RaiseInput(new WindowingKeyHandledEvent(new KeyStateChangedArgs(
RaiseInput(new WindowingKeyHandledEvent(
(Key)glfwKey,
Convert(action),
(KeyModifiers)mods,
scanCode
)));
));
}

private void OnWindowCharHandled(Window* window, uint codepoint)
Expand All @@ -75,11 +75,11 @@ private void OnWindowScrollHandled(Window* window, double offsetX, double offset

private void OnMouseButtonHandled(Window* window, GlfwMouseButton button, InputAction action, GlfwKeyModifiers mods)
{
RaiseInput(new WindowingMouseButtonHandledEvent(new MouseButtonChangedArgs(
RaiseInput(new WindowingMouseButtonHandledEvent(
(MouseButton)button,
Convert(action),
(KeyModifiers)mods
)));
));
}

private void RaiseInput<T>(T args) where T : IEventArgs
Expand Down Expand Up @@ -126,8 +126,8 @@ private static KeyState Convert(InputAction action)
return action switch
{
InputAction.Release => KeyState.Release,
InputAction.Press => KeyState.Press,
InputAction.Repeat => KeyState.Repeat,
InputAction.Press => KeyState.Pressed,
InputAction.Repeat => KeyState.Held,
_ => throw new ArgumentOutOfRangeException()
};
}
Expand Down
11 changes: 11 additions & 0 deletions Hypercube.Client/Input/Events/KeyHandledEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Hypercube.Input;
using Hypercube.Shared.EventBus.Events;

namespace Hypercube.Client.Input.Events;

public sealed class KeyHandledEvent : KeyStateChangedArgs, IEventArgs
{
public KeyHandledEvent(Key key, KeyState state, KeyModifiers modifiers, int scanCode) : base(key, state, modifiers, scanCode)
{
}
}
11 changes: 11 additions & 0 deletions Hypercube.Client/Input/Events/MouseButtonHandledEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Hypercube.Input;
using Hypercube.Shared.EventBus.Events;

namespace Hypercube.Client.Input.Events;

public class MouseButtonHandledEvent : MouseButtonChangedArgs, IEventArgs
{
public MouseButtonHandledEvent(MouseButton button, KeyState state, KeyModifiers modifiers) : base(button, state, modifiers)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@

namespace Hypercube.Client.Input.Events.Windowing;

public readonly record struct WindowingKeyHandledEvent(KeyStateChangedArgs State) : IEventArgs;
public sealed class WindowingKeyHandledEvent : KeyStateChangedArgs, IEventArgs
{
public WindowingKeyHandledEvent(Key key, KeyState state, KeyModifiers modifiers, int scanCode) : base(key, state, modifiers, scanCode)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@

namespace Hypercube.Client.Input.Events.Windowing;

public readonly record struct WindowingMouseButtonHandledEvent(MouseButtonChangedArgs State) : IEventArgs;
public class WindowingMouseButtonHandledEvent : MouseButtonChangedArgs, IEventArgs
{
public WindowingMouseButtonHandledEvent(MouseButton button, KeyState state, KeyModifiers modifiers) : base(button, state, modifiers)
{
}
}
12 changes: 11 additions & 1 deletion Hypercube.Client/Input/Handler/IInputHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,15 @@ namespace Hypercube.Client.Input.Handler;
/// </summary>
public interface IInputHandler : IEventSubscriber
{
bool IsKeyDown(Key key);
bool IsKeyState(Key key, KeyState state);
bool IsKeyHeld(Key key);
bool IsKeyPressed(Key key);
bool IsKeyReleased(Key key);
void KeyClear();

bool IsMouseButtonState(MouseButton button, KeyState state);
bool IsMouseButtonHeld(MouseButton button);
bool IsMouseButtonPressed(MouseButton button);
bool IsMouseButtonReleased(MouseButton button);
void MouseButtonClear();
}
162 changes: 147 additions & 15 deletions Hypercube.Client/Input/Handler/InputHandler.cs
Original file line number Diff line number Diff line change
@@ -1,65 +1,197 @@
using Hypercube.Client.Input.Events.Windowing;
using System.Collections.Frozen;
using Hypercube.Client.Input.Events;
using Hypercube.Client.Input.Events.Windowing;
using Hypercube.Input;
using Hypercube.Shared.Dependency;
using Hypercube.Shared.EventBus;
using Hypercube.Shared.Logging;
using Hypercube.Shared.Runtimes.Loop.Event;

namespace Hypercube.Client.Input.Handler;

public sealed class InputHandler : IInputHandler, IPostInject
{
[Dependency] private readonly IEventBus _eventBus = default!;

private readonly HashSet<Key> _keysRelease = [];
private readonly HashSet<Key> _keysPressed = [];
private readonly HashSet<Key> _keysDown = [];

private readonly FrozenDictionary<KeyState, HashSet<Key>> _keys = new Dictionary<KeyState, HashSet<Key>>
{
{ KeyState.Held, [] },
{ KeyState.Release, [] },
{ KeyState.Pressed, [] },
}.ToFrozenDictionary();

private readonly FrozenDictionary<KeyState, HashSet<MouseButton>> _mouseButtons = new Dictionary<KeyState, HashSet<MouseButton>>
{
{ KeyState.Held, [] },
{ KeyState.Release, [] },
{ KeyState.Pressed, [] },
}.ToFrozenDictionary();


private readonly Logger _logger = LoggingManager.GetLogger("input_handler");

public void PostInject()
{
_eventBus.Subscribe<InputFrameEvent>(this, OnInputFrameUpdate);

_eventBus.Subscribe<WindowingCharHandledEvent>(this, OnCharHandled);
_eventBus.Subscribe<WindowingKeyHandledEvent>(this, OnKeyHandled);
_eventBus.Subscribe<WindowingMouseButtonHandledEvent>(this, OnMouseButtonHandled);
_eventBus.Subscribe<WindowingScrollHandledEvent>(this, OnScrollHandled);
}

private void OnInputFrameUpdate(ref InputFrameEvent args)
{
_keys[KeyState.Pressed].Clear();
_keys[KeyState.Release].Clear();

foreach (var key in _keys[KeyState.Held])
{
// Held event don't support modifiers yet, also scanCode
_eventBus.Raise(new KeyHandledEvent(key, KeyState.Held, KeyModifiers.None, 0));
}

_mouseButtons[KeyState.Pressed].Clear();
_mouseButtons[KeyState.Release].Clear();

foreach (var mouseButton in _mouseButtons[KeyState.Held])
{
// Held event don't support modifiers yet
_eventBus.Raise(new MouseButtonHandledEvent(mouseButton, KeyState.Held, KeyModifiers.None));
}
}

private void OnCharHandled(ref WindowingCharHandledEvent args)
{
throw new NotImplementedException();
}

private void OnKeyHandled(ref WindowingKeyHandledEvent args)
{
#if DEBUG
// Use only in Debug build,
// as this check can take quite a lot of performance during input processing
if (!Enum.IsDefined(typeof(Key), args.State.Key))
if (!Enum.IsDefined(typeof(Key), args.Key))
{
_logger.Warning($"Unknown key {args.State.Key} handled");
_logger.Warning($"Unknown {args.Key} handled");
return;
}
#endif

if (args.State == KeyState.Press)
switch (args.State)
{
_keysDown.Add(args.State.Key);
return;
case KeyState.Held:
return;

// Legacy shit, maybe will eat many ram and cpu
// We made many shit because fucking Key rollover: https://en.wikipedia.org/wiki/Key_rollover
case KeyState.Pressed:
_keys[KeyState.Held].Add(args.Key);
_keys[KeyState.Pressed].Add(args.Key);
break;

case KeyState.Release:
_keys[KeyState.Held].Remove(args.Key);
_keys[KeyState.Pressed].Add(args.Key);
break;

default:
throw new ArgumentOutOfRangeException();
}
_keysDown.Remove(args.State.Key);

_eventBus.Raise(new KeyHandledEvent(args.Key, args.State, args.Modifiers, args.ScanCode));
}

private void OnMouseButtonHandled(ref WindowingMouseButtonHandledEvent args)
{
#if DEBUG
// Use only in Debug build,
// as this check can take quite a lot of performance during input processing
if (!Enum.IsDefined(typeof(MouseButton), args.Button))
{
_logger.Warning($"Unknown {args.Button} handled");
return;
}
#endif

switch (args.State)
{
case KeyState.Held:
return;

case KeyState.Pressed:
_mouseButtons[KeyState.Held].Add(args.Button);
_mouseButtons[KeyState.Pressed].Add(args.Button);
break;

case KeyState.Release:
_mouseButtons[KeyState.Held].Remove(args.Button);
_mouseButtons[KeyState.Pressed].Add(args.Button);
break;

default:
throw new ArgumentOutOfRangeException();
}

_eventBus.Raise(new MouseButtonHandledEvent(args.Button, args.State, args.Modifiers));
}

private void OnScrollHandled(ref WindowingScrollHandledEvent args)
{
}

public bool IsKeyDown(Key key)
public bool IsKeyState(Key key, KeyState state)
{
return _keysDown.Contains(key);
return _keys[state].Contains(key);
}

public bool IsKeyHeld(Key key)
{
return IsKeyState(key, KeyState.Held);
}

public bool IsKeyPressed(Key key)
{
return IsKeyState(key, KeyState.Pressed);
}

public bool IsKeyReleased(Key key)
{
return IsKeyState(key, KeyState.Pressed);
}

public void KeyClear()
{
foreach (var (_, key) in _keys)
{
key.Clear();
}
}

public bool IsMouseButtonState(MouseButton button, KeyState state)
{
return _mouseButtons[state].Contains(button);
}

public bool IsMouseButtonHeld(MouseButton button)
{
return IsMouseButtonState(button, KeyState.Held);
}

public bool IsMouseButtonPressed(MouseButton button)
{
return IsMouseButtonState(button, KeyState.Pressed);
}

public bool IsMouseButtonReleased(MouseButton button)
{
return IsMouseButtonState(button, KeyState.Release);
}

public void MouseButtonClear()
{
foreach (var (_, mouseButtons) in _mouseButtons)
{
mouseButtons.Clear();
}
}
}
4 changes: 2 additions & 2 deletions Hypercube.Example.Client/Controls/ControlsSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public override void FrameUpdate(UpdateFrameEvent args)
{
base.FrameUpdate(args);

var inputX = (_inputHandler.IsKeyDown(Key.D) ? 1 : 0) - (_inputHandler.IsKeyDown(Key.A) ? 1 : 0);
var inputY = (_inputHandler.IsKeyDown(Key.W) ? 1 : 0) - (_inputHandler.IsKeyDown(Key.S) ? 1 : 0);
var inputX = (_inputHandler.IsKeyHeld(Key.D) ? 1 : 0) - (_inputHandler.IsKeyHeld(Key.A) ? 1 : 0);
var inputY = (_inputHandler.IsKeyHeld(Key.W) ? 1 : 0) - (_inputHandler.IsKeyHeld(Key.S) ? 1 : 0);

foreach (var entity in GetEntities<ControlsComponent>())
{
Expand Down
4 changes: 2 additions & 2 deletions Hypercube.Input/KeyState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
public enum KeyState
{
Release,
Press,
Repeat
Pressed,
Held
}
2 changes: 1 addition & 1 deletion Hypercube.Input/KeyStateChangedArgs.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Hypercube.Input;

public readonly struct KeyStateChangedArgs
public class KeyStateChangedArgs
{
public bool Shift => Modifiers.HasFlag(KeyModifiers.Shift);
public bool Control => Modifiers.HasFlag(KeyModifiers.Control);
Expand Down
Loading

0 comments on commit a8070ff

Please sign in to comment.