Skip to content

Commit 633154d

Browse files
committed
add keyboard support
1 parent 38411a0 commit 633154d

18 files changed

Lines changed: 516 additions & 191 deletions

assets/img/config.png

5.57 KB
Loading

src/InputDisplay/Config/Settings.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ public record SelectedTheme(
2525
);
2626

2727
public SelectedTheme CurrentTheme { get; set; } = new();
28-
2928
public bool Borderless { get; set; }
3029
public bool ShadowHolding { get; set; } = true;
3130
public bool HideHolding { get; set; }
@@ -35,6 +34,7 @@ public record SelectedTheme(
3534
public bool InvertHistory { get; set; }
3635
public bool FramesAfter { get; set; }
3736
public bool HideButtonRelease { get; set; }
37+
public bool AutoSelectSinglePad { get; set; } = true;
3838
public SOCDMode SOCD { get; set; } = SOCDMode.Neutral;
3939
public bool ShortcutsEnabled { get; set; } = true;
4040
public int IconSize { get; set; } = 40;
@@ -48,8 +48,8 @@ public record SelectedTheme(
4848
public int Left { get; set; }
4949

5050
public InputMap InputMap { get; set; } = new();
51-
52-
public InputMacro Macros { get; set; } = new();
51+
public InputMacro Macros { get; set; } = [];
52+
public KeyboardToPadMap KeyboardMap { get; set; } = new();
5353

5454
public string BackgroundColor
5555
{
@@ -109,6 +109,8 @@ public void CopyFrom(Settings config)
109109
EnabledDirections = config.EnabledDirections;
110110
Borderless = config.Borderless;
111111
HideButtonRelease = config.HideButtonRelease;
112+
AutoSelectSinglePad = config.AutoSelectSinglePad;
113+
KeyboardMap = config.KeyboardMap;
112114
Width = config.Width;
113115
Height = config.Height;
114116
Top = config.Top;

src/InputDisplay/Config/Window/SettingsControls.cs

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ public sealed class SettingsControls(Desktop desktop, SettingsManager configMana
1515
{
1616
public ButtonName? MappingButton { get; private set; }
1717
public ButtonName? MappingMacro { get; private set; }
18+
public Direction? MappingDirection { get; private set; }
1819
public Button ResetMapButton { get; private set; }
1920
Label SelectedJoystick { get; set; }
20-
Image[] Directions { get; } = new Image[9];
21+
Button[] Directions { get; } = new Button[9];
2122
Dictionary<ButtonName, Button> Buttons { get; } = [];
2223
Dictionary<ButtonName, Button> Macros { get; } = [];
2324

@@ -26,6 +27,7 @@ public sealed class SettingsControls(Desktop desktop, SettingsManager configMana
2627
Theme defaultTheme;
2728

2829
static readonly Color darkGray = new(50, 50, 50);
30+
static readonly Color slateGray = Color.SlateGray;
2931

3032
Settings Config => configManager.CurrentConfig;
3133

@@ -75,15 +77,29 @@ public Widget BuildUI()
7577
ButtonName.KK,
7678
];
7779

78-
PlayerPad player;
80+
PlayerInputDevice player;
7981

80-
public void SetPlayer(PlayerPad pad)
82+
public void SetPlayer(PlayerInputDevice pad)
8183
{
8284
SelectedJoystick.Text = pad.Name;
8385

8486
var currentType = Config.InputMap.GetPadKind(pad);
8587
controllerTypeCombo.SelectedIndex = ThemeConfig.ControllerTypes.Keys.ToArray().IndexOf(currentType);
8688
player = pad;
89+
90+
foreach (var button in Directions)
91+
if (!player.IsKeyboard ||
92+
button.Tag is Direction
93+
and not (Direction.Up or Direction.Down or Direction.Backward or Direction.Forward))
94+
{
95+
button.Enabled = false;
96+
button.OverBackground = null;
97+
}
98+
else
99+
{
100+
button.Enabled = true;
101+
button.OverBackground = new SolidBrush(Color.DarkSlateGray);
102+
}
87103
}
88104

89105
void RebuildMacroButtons()
@@ -486,7 +502,9 @@ Grid BuildSettings()
486502
AddCheck(1, 1, "Frames after", Config.FramesAfter, check => Config.FramesAfter = check);
487503
AddCheck(1, 2, "Hide button release", Config.HideButtonRelease, check => Config.HideButtonRelease = check);
488504
AddCheck(1, 3, "Use Shortcuts", Config.ShortcutsEnabled, check => Config.ShortcutsEnabled = check);
489-
CreateDirectionsSourceBox(1, 4, "Dir.Sources");
505+
AddCheck(1, 4, "Auto select when single pad", Config.AutoSelectSinglePad,
506+
check => Config.AutoSelectSinglePad = check);
507+
CreateDirectionsSourceBox(1, 5, "Dir.Sources");
490508

491509
AddEnumCombo(2, 0, "SOCD", Config.SOCD, item => Config.SOCD = item);
492510
AddNumeric(2, 1, "Input space", Config.SpaceBetweenInputs, v => Config.SpaceBetweenInputs = v);
@@ -860,7 +878,7 @@ void InitButton(ButtonName buttonName, (int Row, int Collumn) pos, Grid grid)
860878
HorizontalAlignment = HorizontalAlignment.Center,
861879
TextColor = Color.White,
862880
Text = buttonName.ToString(),
863-
}
881+
},
864882
};
865883

866884
button.Click += OnButtonMapClick;
@@ -875,17 +893,27 @@ void InitButton(ButtonName buttonName, (int Row, int Collumn) pos, Grid grid)
875893
void OnButtonMapClick(object sender, EventArgs e)
876894
{
877895
var button = (Button)sender;
878-
var name = (ButtonName)button.Tag;
879896

880-
MappingButton = name;
881-
currentModal = BuildButtonMapModal($"Mapping {name}");
897+
if (button.Tag is ButtonName name)
898+
MappingButton = name;
899+
900+
if (button.Tag is Direction dir)
901+
{
902+
if (player?.IsKeyboard is not true)
903+
return;
904+
905+
MappingDirection = dir;
906+
}
907+
908+
currentModal = BuildButtonMapModal($"Mapping {button.Tag}");
882909
currentModal.ShowModal(desktop);
883910
}
884911

885912
public void ButtonMapped()
886913
{
887914
currentModal?.Close();
888915
MappingButton = null;
916+
MappingDirection = null;
889917
currentModal = null;
890918
}
891919

@@ -895,16 +923,29 @@ void InitNumpadDirection(int numpad, (int Row, int Collumn) pos, Grid grid)
895923
var texture = defaultTheme.GetTexture(dir);
896924
var index = numpad - 1;
897925

898-
Directions[index] = new()
926+
Image image = new()
899927
{
900928
Renderable = new TextureRegion(texture),
929+
Color = darkGray,
901930
Width = 30,
902931
Height = 30,
903932
VerticalAlignment = VerticalAlignment.Center,
904933
HorizontalAlignment = HorizontalAlignment.Center,
905-
Color = darkGray,
906934
};
907935

936+
Button button = new()
937+
{
938+
Tag = dir,
939+
Background = null,
940+
FocusedBackground = null,
941+
DisabledBackground = null,
942+
Content = image,
943+
};
944+
945+
button.Click += OnButtonMapClick;
946+
947+
Directions[index] = button;
948+
908949
Grid.SetColumn(Directions[index], pos.Collumn - 1);
909950
Grid.SetRow(Directions[index], pos.Row - 1);
910951
grid.Widgets.Add(Directions[index]);
@@ -950,7 +991,6 @@ Panel BuildSelectedController()
950991
left.Widgets.Add(labelJoyStick);
951992
left.Widgets.Add(SelectedJoystick);
952993

953-
954994
HorizontalStackPanel right = new()
955995
{
956996
VerticalAlignment = VerticalAlignment.Center,
@@ -987,7 +1027,7 @@ Panel BuildSelectedController()
9871027

9881028
void OnChangeControllerType(object sender, EventArgs e)
9891029
{
990-
if (sender is not ListView { SelectedItem: Label { Tag: PlayerPad.Kind kind } }
1030+
if (sender is not ListView { SelectedItem: Label { Tag: PlayerInputDevice.Kind kind } }
9911031
|| player is null || Config.InputMap.GetMapping(player) is not { } mapping)
9921032
return;
9931033

@@ -998,10 +1038,23 @@ void OnChangeControllerType(object sender, EventArgs e)
9981038
public void HighLightDirection(Direction dir)
9991039
{
10001040
var index = NumpadNotation.From(dir) - 1;
1041+
10011042
for (var i = 0; i < Directions.Length; i++)
1002-
Directions[i].Color = index == i && Config.EnabledDirections is not Settings.DirectionSources.None
1003-
? Color.White
1043+
{
1044+
ref var btn = ref Directions[i];
1045+
1046+
var backcolor = player?.IsKeyboard is true &&
1047+
btn.Tag is Direction.Up or Direction.Down or Direction.Backward or Direction.Forward
1048+
? slateGray
10041049
: darkGray;
1050+
1051+
var color = index == i && Config.EnabledDirections is not Settings.DirectionSources.None
1052+
? Color.White
1053+
: backcolor;
1054+
1055+
if (btn is { Content: Image img })
1056+
img.Color = color;
1057+
}
10051058
}
10061059

10071060
public void HighLightButtons(ButtonName buttons)

src/InputDisplay/Config/Window/SettingsGame.cs

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ public class SettingsGame : Game
2323
#pragma warning restore S1450
2424

2525
readonly SettingsManager configManager = new();
26-
PlayerPad? player;
26+
PlayerInputDevice? player;
2727

2828
Settings Config => configManager.CurrentConfig;
2929

3030
PlayerIndex? playerIndexArg;
31+
readonly bool fromPlayerUsingKeyboard;
3132

3233
static readonly Point windowSize = new(1080, 720);
3334

@@ -40,7 +41,12 @@ public SettingsGame(string? playerIndex = null)
4041
Window.AllowUserResizing = false;
4142
graphics.ApplyChanges();
4243

43-
if (playerIndex.IsNonEmpty() && Enum.TryParse(playerIndex, out PlayerIndex index))
44+
if (playerIndex is "keyboard")
45+
{
46+
fromPlayerUsingKeyboard = true;
47+
playerIndexArg = PlayerIndex.One;
48+
}
49+
else if (playerIndex.IsNonEmpty() && Enum.TryParse(playerIndex, out PlayerIndex index))
4450
playerIndexArg = index;
4551
}
4652

@@ -77,12 +83,21 @@ protected override void Update(GameTime gameTime)
7783
{
7884
KeyboardManager.Update();
7985

80-
if (controls.MappingButton is null && controls.MappingMacro is null &&
81-
KeyboardManager.IsKeyPressed(Keys.Escape))
82-
if (player is null || PlayerPad.GetConnected().Count() <= 1 || playerIndexArg is not null)
86+
if (KeyboardManager.IsKeyPressed(Keys.Escape))
87+
{
88+
if (controls.MappingButton is not null || controls.MappingMacro is not null)
89+
{
90+
controls.ButtonMapped();
91+
return;
92+
}
93+
94+
if (player is null
95+
|| (!PlayerInputDevice.HasMultiplePads() && Config.AutoSelectSinglePad)
96+
|| playerIndexArg is not null)
8397
Exit();
8498
else
8599
player = null;
100+
}
86101

87102
if (player is null)
88103
{
@@ -93,18 +108,43 @@ protected override void Update(GameTime gameTime)
93108
player.Update();
94109
gameInput.Update(player, Config);
95110

96-
if (controls.MappingButton is null)
111+
if (controls.MappingButton is null && controls.MappingDirection is null)
97112
{
98113
var input = gameInput.CurrentState;
99114
controls.HighLightDirection(input.Stick.Direction);
100115
controls.HighLightButtons(input.GetActiveButtons());
101116
}
102-
else if (player.GetAnyButton() is { } padButton && Config.InputMap.GetMapping(player.Identifier) is { } map)
117+
else if (controls.MappingButton is not null && Config.InputMap.GetMapping(player.Identifier) is { } map)
118+
{
119+
var found = false;
120+
if (!player.IsKeyboard && player.GetAnyButton() is { } padButton)
121+
{
122+
map.Set(controls.MappingButton.Value, padButton);
123+
found = true;
124+
}
125+
126+
if (player.IsKeyboard &&
127+
player.TryRemapKeyboardFor(InputMap.ButtonMap.Default.Get(controls.MappingButton.Value))
128+
)
129+
found = true;
130+
131+
if (found)
132+
{
133+
controls.ButtonMapped();
134+
configManager.SaveFile();
135+
}
136+
}
137+
else if (controls.MappingDirection is not null &&
138+
player.IsKeyboard &&
139+
player.TryRemapKeyboardFor(InputMap.DirectionToPadButton(controls.MappingDirection.Value)))
103140
{
104-
map.Set(controls.MappingButton.Value, padButton);
105141
controls.ButtonMapped();
106142
configManager.SaveFile();
107143
}
144+
else if (controls.MappingDirection is not null && !player.IsKeyboard)
145+
{
146+
controls.ButtonMapped();
147+
}
108148

109149
base.Update(gameTime);
110150
}
@@ -113,8 +153,14 @@ void DetectController()
113153
{
114154
if (playerIndexArg is not null && player is null)
115155
{
116-
PlayerPad argPlayer = new(playerIndexArg.Value);
117-
if (argPlayer.Capabilities.IsConnected)
156+
PlayerInputDevice argPlayer =
157+
fromPlayerUsingKeyboard
158+
? new(Config.KeyboardMap)
159+
: new(playerIndexArg.Value);
160+
161+
argPlayer.Update();
162+
163+
if (argPlayer.IsConnected)
118164
{
119165
SetPlayerPad(argPlayer);
120166
return;
@@ -124,20 +170,21 @@ void DetectController()
124170
playerIndexArg = null;
125171
}
126172

127-
if (PlayerPad.DetectPress() is not { } playerPad) return;
173+
if (PlayerInputDevice.DetectPress(Config.AutoSelectSinglePad, Config.KeyboardMap) is not { } playerPad) return;
128174
SetPlayerPad(playerPad);
129175
}
130176

131-
public void SetPlayerPad(PlayerPad playerPad)
177+
public void SetPlayerPad(PlayerInputDevice playerPad)
132178
{
133179
player = playerPad;
134180
controls.SetPlayer(playerPad);
135-
if (Config.InputMap.TryAddGamePad(player.Capabilities))
181+
if (Config.InputMap.TryAddGamePad(player))
136182
configManager.SaveFile();
137183
}
138184

139185
void OnResetMap(object? sender, EventArgs e)
140186
{
187+
Config.KeyboardMap.Reset();
141188
if (player is null || Config.InputMap.GetMapping(player.Identifier) is not { } map) return;
142189
map.Reset();
143190
configManager.SaveFile();

src/InputDisplay/Config/Window/SettingsWindow.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public enum WindowState { Closed, Starting, Started }
1212

1313
public bool IsOpen() => state is not WindowState.Closed && process is { Responding: true, HasExited: false };
1414

15-
public void Open(PlayerPad? player = null)
15+
public void Open(PlayerInputDevice? player = null)
1616
{
1717
if (state is WindowState.Starting) return;
1818

@@ -22,8 +22,15 @@ public void Open(PlayerPad? player = null)
2222
si.FileName = Process.GetCurrentProcess().MainModule?.FileName;
2323
si.Arguments = "config";
2424

25-
if (player is not null)
26-
si.Arguments += $" {player.Index}";
25+
switch (player)
26+
{
27+
case { IsKeyboard: true }:
28+
si.Arguments += " keyboard";
29+
break;
30+
case { Index: var index }:
31+
si.Arguments += $" {index}";
32+
break;
33+
}
2734

2835
if (IsOpen())
2936
{

0 commit comments

Comments
 (0)