diff --git a/Engine b/Engine index d78c42a..efed24d 160000 --- a/Engine +++ b/Engine @@ -1 +1 @@ -Subproject commit d78c42a65327a5889636da1a8d99e57513e20098 +Subproject commit efed24de2011eb9aad6fbeac38697eb9a7c37e3f diff --git a/Platforms/Desktop/DesktopInputs.cs b/Platforms/Desktop/DesktopInputs.cs new file mode 100644 index 0000000..31c391e --- /dev/null +++ b/Platforms/Desktop/DesktopInputs.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; + +using Microsoft.Xna.Framework.Input; + +using Engine.Core; +using Engine.Integration.MonoGame; +using Engine.Systems.Input; + +using MyUniverse.Shared.Behaviours.Abstract; + +public class DesktopInputs : BehaviourBase, IEnterUniverse, IExitUniverse, IGameInputs +{ + public Event, IButtonInputs.ButtonCallbackArguments> OnAnyButtonPressed { get; } = new(); + public Event, IButtonInputs.ButtonCallbackArguments> OnAnyButtonReleased { get; } = new(); + + private readonly Dictionary, IButtonInputs.ButtonCallbackArguments>> OnPressed = new(256); + private readonly Dictionary, IButtonInputs.ButtonCallbackArguments>> OnReleased = new(256); + + private readonly Dictionary keyMappingReversed = []; + private readonly Dictionary keyMapping = new() { + { Keys.Space, IGameInputs.Button.Interact } + }; + + private KeyboardInputs keyboardInputs = null!; + + public void EnterUniverse(IUniverse universe) + { + keyboardInputs = BehaviourController.GetOrAddBehaviour(); + keyboardInputs.OnAnyButtonPressed.AddListener(AnyPressCallback); + keyboardInputs.OnAnyButtonReleased.AddListener(AnyReleaseCallback); + + foreach ((Keys key, IGameInputs.Button button) in keyMapping) + keyboardInputs.RegisterOnPress(key, PressCallback); + + foreach ((Keys key, IGameInputs.Button button) in keyMapping) + keyboardInputs.RegisterOnRelease(key, ReleaseCallback); + } + + public void ExitUniverse(IUniverse universe) + { + keyboardInputs.OnAnyButtonPressed.RemoveListener(AnyPressCallback); + keyboardInputs.OnAnyButtonReleased.RemoveListener(AnyReleaseCallback); + + foreach ((Keys key, IGameInputs.Button button) in keyMapping) + keyboardInputs.UnregisterOnPress(key, PressCallback); + + foreach ((Keys key, IGameInputs.Button button) in keyMapping) + keyboardInputs.UnregisterOnRelease(key, ReleaseCallback); + } + + private void PressCallback(IButtonInputs sender, IButtonInputs.ButtonCallbackArguments args) + { + if (!keyMapping.TryGetValue(args.Button, out IGameInputs.Button button)) + return; + + if (!OnPressed.TryGetValue(button, out Event, IButtonInputs.ButtonCallbackArguments>? @event)) + return; + + @event.Invoke(this, new(button)); + } + + private void ReleaseCallback(IButtonInputs sender, IButtonInputs.ButtonCallbackArguments args) + { + if (!keyMapping.TryGetValue(args.Button, out IGameInputs.Button button)) + return; + + if (!OnReleased.TryGetValue(button, out Event, IButtonInputs.ButtonCallbackArguments>? @event)) + return; + + @event.Invoke(this, new(button)); + } + + private void AnyReleaseCallback(IButtonInputs sender, IButtonInputs.ButtonCallbackArguments args) + { + if (keyMapping.TryGetValue(args.Button, out IGameInputs.Button button)) + OnAnyButtonPressed?.Invoke(this, new(button)); + } + + private void AnyPressCallback(IButtonInputs sender, IButtonInputs.ButtonCallbackArguments args) + { + if (keyMapping.TryGetValue(args.Button, out IGameInputs.Button button)) + OnAnyButtonPressed?.Invoke(this, new(button)); + } + + public void RegisterOnPress(IGameInputs.Button button, Event, IButtonInputs.ButtonCallbackArguments>.EventHandler callback) + { + if (!OnPressed.TryGetValue(button, out Event, IButtonInputs.ButtonCallbackArguments>? @event)) + { + @event = new(); + OnPressed.Add(button, @event); + } + + @event.AddListener(callback); + } + + public void UnregisterOnPress(IGameInputs.Button button, Event, IButtonInputs.ButtonCallbackArguments>.EventHandler callback) + { + if (OnPressed.TryGetValue(button, out Event, IButtonInputs.ButtonCallbackArguments>? @event)) + @event.RemoveListener(callback); + } + + public void RegisterOnRelease(IGameInputs.Button button, Event, IButtonInputs.ButtonCallbackArguments>.EventHandler callback) + { + if (!OnReleased.TryGetValue(button, out Event, IButtonInputs.ButtonCallbackArguments>? @event)) + { + @event = new(); + OnReleased.Add(button, @event); + } + + @event.AddListener(callback); + } + + public void UnregisterOnRelease(IGameInputs.Button button, Event, IButtonInputs.ButtonCallbackArguments>.EventHandler callback) + { + if (OnReleased.TryGetValue(button, out Event, IButtonInputs.ButtonCallbackArguments>? @event)) + @event.RemoveListener(callback); + } + + public bool IsPressed(IGameInputs.Button button) + { + if (!keyMappingReversed.TryGetValue(button, out Keys key)) + throw new($"{Enum.GetName(button)} is not mapped correctly"); + + return keyboardInputs.IsPressed(key); + } + + public DesktopInputs() + { + foreach ((Keys key, IGameInputs.Button button) in keyMapping) + keyMappingReversed.Add(button, key); + } +} diff --git a/Platforms/Desktop/Program.cs b/Platforms/Desktop/Program.cs index 235827f..4907937 100644 --- a/Platforms/Desktop/Program.cs +++ b/Platforms/Desktop/Program.cs @@ -23,7 +23,7 @@ universe.InstantiateUniverseObject().SetUniverseObject("Logger") .BehaviourController.AddBehaviour().Logger = ILogger.Shared = logger; universe.InstantiateUniverseObject().SetUniverseObject("Desktop Inputs") - .BehaviourController.AddBehaviour(); + .BehaviourController.AddBehaviour(); universe.InstantiateUniverseObject().SetUniverseObject("Visual Managers") .BehaviourController.AddBehaviour() diff --git a/Shared/Behaviours/Abstract/IGameInputs.cs b/Shared/Behaviours/Abstract/IGameInputs.cs new file mode 100644 index 0000000..d4b6990 --- /dev/null +++ b/Shared/Behaviours/Abstract/IGameInputs.cs @@ -0,0 +1,11 @@ +using Engine.Systems.Input; + +namespace MyUniverse.Shared.Behaviours.Abstract; + +public interface IGameInputs : IButtonInputs +{ + public enum Button + { + Interact + } +} diff --git a/Shared/Behaviours/IRotator.cs b/Shared/Behaviours/Abstract/IRotator.cs similarity index 100% rename from Shared/Behaviours/IRotator.cs rename to Shared/Behaviours/Abstract/IRotator.cs diff --git a/Shared/Behaviours/RotatorToggler.cs b/Shared/Behaviours/RotatorToggler.cs index 8084b81..9088603 100644 --- a/Shared/Behaviours/RotatorToggler.cs +++ b/Shared/Behaviours/RotatorToggler.cs @@ -1,31 +1,30 @@ -using System; using Engine.Core; -using Engine.Integration.MonoGame; using Engine.Systems.Input; -using Microsoft.Xna.Framework.Input; + +using MyUniverse.Shared.Behaviours.Abstract; namespace MyUniverse.Shared.Behaviours; public class RotatorToggler : Behaviour2D, IFirstFrameUpdate, ILastFrameUpdate { private IRotator rotator = null!; - private KeyboardInputs inputs = null!; + private IGameInputs inputs = null!; public void FirstActiveFrame() { rotator = BehaviourController.GetRequiredBehaviour(); - inputs = Universe.FindRequiredBehaviour(); + inputs = Universe.FindRequiredBehaviour(); - inputs.RegisterOnPress(Keys.Space, ToggleRotator); + inputs.RegisterOnPress(IGameInputs.Button.Interact, ToggleRotator); } - private void ToggleRotator(IButtonInputs sender, IButtonInputs.ButtonCallbackArguments args) + private void ToggleRotator(IButtonInputs sender, IButtonInputs.ButtonCallbackArguments args) { rotator.StateEnable.Enabled = !rotator.StateEnable.Enabled; } public void LastActiveFrame() { - inputs.UnregisterOnPress(Keys.Space, ToggleRotator); + inputs.UnregisterOnPress(IGameInputs.Button.Interact, ToggleRotator); } }