136 lines
5.0 KiB
C#

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;
namespace MyUniverse.Platforms.Desktop;
public class DesktopInputs : BehaviourBase, IEnterUniverse, IExitUniverse, IGameInputs
{
public IButtonInputs<IGameInputs.Button>.InputEvent OnAnyButtonPressed { get; } = new();
public IButtonInputs<IGameInputs.Button>.InputEvent OnAnyButtonReleased { get; } = new();
private readonly Dictionary<IGameInputs.Button, IButtonInputs<IGameInputs.Button>.InputEvent> OnPressed = new(256);
private readonly Dictionary<IGameInputs.Button, IButtonInputs<IGameInputs.Button>.InputEvent> OnReleased = new(256);
private readonly Dictionary<IGameInputs.Button, Keys> keyMappingReversed = [];
private readonly Dictionary<Keys, IGameInputs.Button> keyMapping = new() {
{ Keys.Space, IGameInputs.Button.Interact }
};
private KeyboardInputs keyboardInputs = null!;
public void EnterUniverse(IUniverse universe)
{
keyboardInputs = BehaviourController.GetOrAddBehaviour<KeyboardInputs>();
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<Keys> sender, IButtonInputs<Keys>.ButtonCallbackArguments args)
{
if (!keyMapping.TryGetValue(args.Button, out IGameInputs.Button button))
return;
if (!OnPressed.TryGetValue(button, out IButtonInputs<IGameInputs.Button>.InputEvent? @event))
return;
@event.Invoke(this, new(button));
}
private void ReleaseCallback(IButtonInputs<Keys> sender, IButtonInputs<Keys>.ButtonCallbackArguments args)
{
if (!keyMapping.TryGetValue(args.Button, out IGameInputs.Button button))
return;
if (!OnReleased.TryGetValue(button, out IButtonInputs<IGameInputs.Button>.InputEvent? @event))
return;
@event.Invoke(this, new(button));
}
private void AnyReleaseCallback(IButtonInputs<Keys> sender, IButtonInputs<Keys>.ButtonCallbackArguments args)
{
if (keyMapping.TryGetValue(args.Button, out IGameInputs.Button button))
OnAnyButtonPressed?.Invoke(this, new(button));
}
private void AnyPressCallback(IButtonInputs<Keys> sender, IButtonInputs<Keys>.ButtonCallbackArguments args)
{
if (keyMapping.TryGetValue(args.Button, out IGameInputs.Button button))
OnAnyButtonPressed?.Invoke(this, new(button));
}
public void RegisterOnPress(IGameInputs.Button button, IButtonInputs<IGameInputs.Button>.InputEvent.EventHandler callback)
{
if (!OnPressed.TryGetValue(button, out IButtonInputs<IGameInputs.Button>.InputEvent? @event))
{
@event = new();
OnPressed.Add(button, @event);
}
@event.AddListener(callback);
}
public void UnregisterOnPress(IGameInputs.Button button, IButtonInputs<IGameInputs.Button>.InputEvent.EventHandler callback)
{
if (OnPressed.TryGetValue(button, out IButtonInputs<IGameInputs.Button>.InputEvent? @event))
@event.RemoveListener(callback);
}
public void RegisterOnRelease(IGameInputs.Button button, IButtonInputs<IGameInputs.Button>.InputEvent.EventHandler callback)
{
if (!OnReleased.TryGetValue(button, out IButtonInputs<IGameInputs.Button>.InputEvent? @event))
{
@event = new();
OnReleased.Add(button, @event);
}
@event.AddListener(callback);
}
public void UnregisterOnRelease(IGameInputs.Button button, IButtonInputs<IGameInputs.Button>.InputEvent.EventHandler callback)
{
if (OnReleased.TryGetValue(button, out IButtonInputs<IGameInputs.Button>.InputEvent? @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);
}
}