17.01.2021

+ WPF-Support
+ Game Controller System
+ GameKeybind System

+ SM_WPF_TEST
This commit is contained in:
Michel Fedde 2021-01-17 21:13:37 +01:00
parent af90d617d3
commit 6f23a80f7f
60 changed files with 1536 additions and 143 deletions

View file

@ -0,0 +1,39 @@
using SharpDX.XInput;
namespace SM.Game.Controls
{
public struct GameController
{
public static float GlobalDeadband = 2500;
private Controller _controller;
public float Deadband { get; set; }
public bool IsConnected => _controller.IsConnected;
public UserIndex Index { get; private set; }
public GameController(int id) : this((UserIndex)id)
{}
public GameController(UserIndex index = UserIndex.Any)
{
_controller = new Controller(index);
Index = index;
Deadband = GlobalDeadband;
}
public GameControllerState GetState()
{
if (!IsConnected)
{
return new GameControllerState(true);
}
Gamepad state = _controller.GetState().Gamepad;
return new GameControllerState(state, ref this);
}
}
}

View file

@ -0,0 +1,57 @@
using System;
using OpenTK;
using SharpDX.XInput;
namespace SM.Game.Controls
{
public struct GameControllerState
{
public GameControllerStateThumbs Thumbs;
public GameControllerStateTriggers Triggers;
public GameControllerStateDPad DPad;
public GameControllerStateButtons Buttons;
public bool FromConnected { get; }
internal GameControllerState(bool empty)
{
FromConnected = false;
Thumbs = GameControllerStateThumbs.Default;
Triggers = GameControllerStateTriggers.Default;
DPad = GameControllerStateDPad.Default;
Buttons = GameControllerStateButtons.Default;
}
internal GameControllerState(Gamepad state, ref GameController controller)
{
FromConnected = true;
Thumbs = new GameControllerStateThumbs
{
Left = new Vector2(
Math.Abs((float)state.LeftThumbX) < controller.Deadband ? 0 : (float)state.LeftThumbX / short.MaxValue,
Math.Abs((float)state.LeftThumbY) < controller.Deadband ? 0 : (float)state.LeftThumbY / short.MaxValue),
Right = new Vector2(
Math.Abs((float)state.RightThumbX) < controller.Deadband ? 0 : (float)state.RightThumbX / short.MaxValue,
Math.Abs((float)state.RightThumbY) < controller.Deadband ? 0 : (float)state.RightThumbY / short.MaxValue),
PressedLeft = state.Buttons.HasFlag(GamepadButtonFlags.LeftThumb),
PressedRight = state.Buttons.HasFlag(GamepadButtonFlags.RightThumb)
};
Triggers = new GameControllerStateTriggers()
{
Left = (float)state.LeftTrigger / byte.MaxValue,
Right = (float)state.RightTrigger / byte.MaxValue
};
DPad = new GameControllerStateDPad(state.Buttons);
Buttons = new GameControllerStateButtons(state.Buttons);
}
public override string ToString()
{
return !FromConnected ? "[From a disconnected controller]" : $"Thumbs: [{Thumbs}]; Trigger: [{Triggers}]; DPad: [{DPad}]; Buttons: [{Buttons}]";
}
}
}

View file

@ -0,0 +1,45 @@
using SharpDX.XInput;
namespace SM.Game.Controls
{
public struct GameControllerStateButtons
{
public static GameControllerStateButtons Default = new GameControllerStateButtons(GamepadButtonFlags.None);
private GamepadButtonFlags _buttonFlags;
public bool X;
public bool Y;
public bool A;
public bool B;
public bool LB;
public bool RB;
public bool LeftThumb;
public bool RightThumb;
public bool this[GamepadButtonFlags flags] => _buttonFlags.HasFlag(flags);
internal GameControllerStateButtons(GamepadButtonFlags flags)
{
_buttonFlags = flags;
X = flags.HasFlag(GamepadButtonFlags.X);
Y = flags.HasFlag(GamepadButtonFlags.Y);
A = flags.HasFlag(GamepadButtonFlags.A);
B = flags.HasFlag(GamepadButtonFlags.B);
LB = flags.HasFlag(GamepadButtonFlags.LeftShoulder);
RB = flags.HasFlag(GamepadButtonFlags.RightShoulder);
LeftThumb = flags.HasFlag(GamepadButtonFlags.LeftThumb);
RightThumb = flags.HasFlag(GamepadButtonFlags.RightThumb);
}
public override string ToString()
{
return $"X: {(X ? "1" : "0")}; Y: {(Y ? "1" : "0")}; A: {(A ? "1" : "0")}; B: {(B ? "1" : "0")}; LB: {(LB ? "1" : "0")}; RB: {(RB ? "1" : "0")}; LT: {(LeftThumb ? "1" : "0")}; RT: {(RightThumb ? "1" : "0")}";
}
}
}

View file

@ -0,0 +1,28 @@
using SharpDX.XInput;
namespace SM.Game.Controls
{
public struct GameControllerStateDPad
{
public static GameControllerStateDPad Default = new GameControllerStateDPad(GamepadButtonFlags.None);
public bool Up;
public bool Down;
public bool Left;
public bool Right;
internal GameControllerStateDPad(GamepadButtonFlags flags)
{
Up = flags.HasFlag(GamepadButtonFlags.DPadUp);
Down = flags.HasFlag(GamepadButtonFlags.DPadDown);
Left = flags.HasFlag(GamepadButtonFlags.DPadLeft);
Right = flags.HasFlag(GamepadButtonFlags.DPadRight);
}
public override string ToString()
{
return
$"Up: {(Up ? "1" : "0")}; Down: {(Down ? "1" : "0")}; Left: {(Left ? "1" : "0")}; Right: {(Right ? "1" : "0")};";
}
}
}

View file

@ -0,0 +1,21 @@
using OpenTK;
namespace SM.Game.Controls
{
public struct GameControllerStateThumbs
{
public static GameControllerStateThumbs Default = new GameControllerStateThumbs()
{Left = Vector2.Zero, Right = Vector2.Zero};
public Vector2 Left;
public Vector2 Right;
public bool PressedLeft;
public bool PressedRight;
public override string ToString()
{
return $"Left: ({Left.X}; {Left.Y}){(PressedLeft ? " Pressed" : "")}; Right: ({Right.X}; {Right.Y}){(PressedRight ? " Pressed" : "")}";
}
}
}

View file

@ -0,0 +1,14 @@
namespace SM.Game.Controls
{
public struct GameControllerStateTriggers
{
public static GameControllerStateTriggers Default = new GameControllerStateTriggers {Left = 0f, Right = 0f};
public float Left;
public float Right;
public override string ToString()
{
return $"Left: {Left}; Right: {Right}";
}
}
}

View file

@ -0,0 +1,32 @@
using System;
using OpenTK.Input;
namespace SM.Game.Controls
{
public class GameKeybind
{
public Func<GameKeybindContext, object> Keyboard;
public Func<GameKeybindContext, object> Controller;
public Func<GameKeybindContext, object> AI;
public Func<GameKeybindContext, object> this[GameKeybindActorType type]
{
get
{
switch (type)
{
case GameKeybindActorType.AI:
return AI;
case GameKeybindActorType.Keyboard:
return Keyboard;
break;
case GameKeybindActorType.Controller:
return Controller;
break;
default:
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
}
}
}
}

View file

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using OpenTK.Input;
namespace SM.Game.Controls
{
public enum GameKeybindActorType
{
AI,
Keyboard,
Controller
}
public struct GameKeybindActor
{
private GameKeybindActorType _type;
private GameController? _controller;
private GameKeybindHost _keybindHost;
public GameKeybindActorType Type => _type;
public GameController? Controller => _controller;
public object[] Parameter;
private GameKeybindActor(GameKeybindActorType type, GameController? controller)
{
_type = type;
_controller = controller;
_keybindHost = null;
Parameter = new object[0];
}
public void ConnectHost(GameKeybindHost host)
{
_keybindHost = host;
}
public ReturnType Get<ReturnType>(string name, params object[] param)
{
return (ReturnType) Get(name, param);
}
public object Get(string name, params object[] objects)
{
if (_keybindHost == null) return null;
if (!_keybindHost._actions.ContainsKey(name)) return null;
GameKeybind keybind = _keybindHost._actions[name];
GameKeybindContext context = new GameKeybindContext()
{
Actor = this,
Host = _keybindHost,
ActorParameter = Parameter,
InstanceParameter = objects,
KeyboardState = Keyboard.GetState(),
MouseState = Mouse.GetState(),
ControllerState = Controller?.GetState(),
};
return keybind[Type].Invoke(context);
}
public static GameKeybindActor CreateAIActor()
{
return new GameKeybindActor(GameKeybindActorType.AI, null);
}
public static GameKeybindActor CreateKeyboardActor()
{
return new GameKeybindActor(GameKeybindActorType.Keyboard, null);
}
public static GameKeybindActor CreateControllerActor(int id)
{
return CreateControllerActor(new GameController(id));
}
public static GameKeybindActor CreateControllerActor(GameController controller)
{
return new GameKeybindActor(GameKeybindActorType.Controller, controller);
}
}
}

View file

@ -0,0 +1,17 @@
using OpenTK.Input;
namespace SM.Game.Controls
{
public struct GameKeybindContext
{
public KeyboardState KeyboardState;
public MouseState MouseState;
public GameControllerState? ControllerState;
public GameKeybindActor Actor;
public GameKeybindHost Host;
public object[] InstanceParameter;
public object[] ActorParameter;
}
}

View file

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using OpenTK.Input;
namespace SM.Game.Controls
{
public class GameKeybindHost
{
internal Dictionary<string, GameKeybind> _actions = new Dictionary<string, GameKeybind>();
public GameKeybindHost()
{ }
public GameKeybindHost(GameKeybindList setup)
{
for (int i = 0; i < setup.Count; i++)
{
_actions[setup[i].Key] = setup[i].Value;
}
}
public void Setup(string name, Func<GameKeybindContext, object> keyboard = null, Func<GameKeybindContext, object> gameController = null, Func<GameKeybindContext, object> ai = null)
{
GameKeybind bind;
if (_actions.ContainsKey(name))
{
bind = _actions[name];
}
else
{
bind = new GameKeybind();
_actions.Add(name, bind);
}
bind.Keyboard = keyboard;
bind.Controller = gameController;
bind.AI = ai;
}
}
}

View file

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using OpenTK.Input;
namespace SM.Game.Controls
{
public class GameKeybindList : List<KeyValuePair<string, GameKeybind>>
{
public void Add(string name, GameKeybind keybind)
{
Add(new KeyValuePair<string, GameKeybind>(name, keybind));
}
public void Add(string name, Func<GameKeybindContext, object> keyboard = null,
Func<GameKeybindContext, object> controller = null)
{
Add(new KeyValuePair<string, GameKeybind>(name, new GameKeybind()
{
AI = null,
Controller = controller,
Keyboard = keyboard
}));
}
}
}