Skip to content

Commit 7eebce4

Browse files
Kade-githubVioletSnowLeopardEliteMasterEric
authored andcommitted
[PUBLIC PR] Prevent softlock caused by removing all keybinds for a UI control (#988)
* prevent removing last keybind for UI controls * add popup to alert you cannot remove keybind * ensure controls list is unique * Use public submodule URLs (would be nice if this was automatic but oh well) --------- Co-authored-by: VioletSnowLeopard <ngzeretzke@gmail.com> Co-authored-by: EliteMasterEric <ericmyllyoja@gmail.com>
1 parent 750779a commit 7eebce4

File tree

1 file changed

+67
-3
lines changed

1 file changed

+67
-3
lines changed

source/funkin/ui/options/ControlsMenu.hx

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,15 @@ class ControlsMenu extends Page<OptionsState.OptionsMenuPageName>
4444
var deviceList:TextMenuList;
4545
var menuCamera:FlxCamera;
4646
var prompt:Prompt;
47+
var popup:Prompt;
4748
var camFollow:FlxObject;
4849
var labels:FlxTypedGroup<AtlasText>;
4950

5051
var currentDevice:Device = Keys;
5152
var deviceListSelected:Bool = false;
5253

54+
var actionPrevented:Bool = false;
55+
5356
static final CONTROL_BASE_X = 50;
5457
static final CONTROL_MARGIN_X = 700;
5558
static final CONTROL_SPACING_X = 300;
@@ -181,6 +184,13 @@ class ControlsMenu extends Page<OptionsState.OptionsMenuPageName>
181184
prompt.back.scrollFactor.set(0, 0);
182185
prompt.exists = false;
183186
add(prompt);
187+
188+
popup = new Prompt("\nYou cannot unbind\nthat key!\n\n\nEscape to exit", None);
189+
popup.create();
190+
popup.createBgFromMargin(100, 0xFFfafd6d);
191+
popup.back.scrollFactor.set(0, 0);
192+
popup.exists = false;
193+
add(popup);
184194
}
185195

186196
function createItem(x = 0.0, y = 0.0, control:Control, index:Int)
@@ -213,6 +223,12 @@ class ControlsMenu extends Page<OptionsState.OptionsMenuPageName>
213223
prompt.exists = true;
214224
}
215225

226+
function createPopup():Void
227+
{
228+
canExit = false;
229+
popup.exists = true;
230+
}
231+
216232
function goToDeviceList():Void
217233
{
218234
controlGrid.selectedItem.idle();
@@ -234,9 +250,16 @@ class ControlsMenu extends Page<OptionsState.OptionsMenuPageName>
234250
var inputName = device == Keys ? "key" : "button";
235251
var cancel = device == Keys ? "Escape" : "Back";
236252
// todo: alignment
237-
if (device == Keys) prompt.setText('\nPress any key to rebind\n\n\n\n $cancel to cancel');
253+
if (device == Keys)
254+
{
255+
prompt.setText('\nPress any key to rebind\n\n\n\n $cancel to cancel');
256+
popup.setText('\nYou cannot unbind\nthat key!\n\n\n$cancel to exit');
257+
}
238258
else
259+
{
239260
prompt.setText('\nPress any button\n to rebind\n\n\n $cancel to cancel');
261+
popup.setText('\nYou cannot unbind\nthat button!\n\n\n$cancel to exit');
262+
}
240263

241264
controlGrid.selectedItem.select();
242265
labels.members[Std.int(controlGrid.selectedIndex / COLUMNS)].alpha = 1.0;
@@ -313,6 +336,28 @@ class ControlsMenu extends Page<OptionsState.OptionsMenuPageName>
313336
}
314337
}
315338

339+
if (actionPrevented && !popup.exists) createPopup();
340+
341+
if (popup.exists)
342+
{
343+
switch (currentDevice)
344+
{
345+
case Keys:
346+
{
347+
var key = FlxG.keys.firstJustReleased();
348+
if (key == ESCAPE) closePopup();
349+
}
350+
case Gamepad(id):
351+
{
352+
var button = FlxG.gamepads.getByID(id).firstJustReleasedID();
353+
if (button == BACK) closePopup();
354+
355+
var key = FlxG.keys.firstJustReleased();
356+
if (key == ESCAPE) closePopup();
357+
}
358+
}
359+
}
360+
316361
switch (currentDevice)
317362
{
318363
case Keys:
@@ -339,6 +384,19 @@ class ControlsMenu extends Page<OptionsState.OptionsMenuPageName>
339384
function onInputSelect(input:Int):Void
340385
{
341386
var item = controlGrid.selectedItem;
387+
var leftItem = controlGrid.members[controlGrid.selectedIndex - 1];
388+
var rightItem = controlGrid.members[controlGrid.selectedIndex + 1];
389+
390+
// check if all keybinds are being removed and this is a UI control, prevent removing last keybind for this
391+
if (input == FlxKey.NONE && controlGrid.selectedIndex != 1 && rightItem.input == FlxKey.NONE)
392+
{
393+
for (group in itemGroups)
394+
{
395+
if (group.toString() == itemGroups[1].toString() && group.contains(item)) actionPrevented = true;
396+
}
397+
}
398+
399+
if (actionPrevented) return;
342400

343401
// check if that key is already set for this
344402
if (input != FlxKey.NONE)
@@ -379,7 +437,6 @@ class ControlsMenu extends Page<OptionsState.OptionsMenuPageName>
379437
if (controlGrid.selectedIndex % 2 == 1)
380438
{
381439
trace('Modified item on right side of grid');
382-
var leftItem = controlGrid.members[controlGrid.selectedIndex - 1];
383440
if (leftItem != null && input != FlxKey.NONE && leftItem.input == FlxKey.NONE)
384441
{
385442
trace('Left item is unbound and right item is not!');
@@ -395,7 +452,6 @@ class ControlsMenu extends Page<OptionsState.OptionsMenuPageName>
395452
else
396453
{
397454
trace('Modified item on left side of grid');
398-
var rightItem = controlGrid.members[controlGrid.selectedIndex + 1];
399455
if (rightItem != null && input == FlxKey.NONE && rightItem.input != FlxKey.NONE)
400456
{
401457
trace('Left item is unbound and right item is not!');
@@ -419,6 +475,13 @@ class ControlsMenu extends Page<OptionsState.OptionsMenuPageName>
419475
if (deviceList == null) canExit = true;
420476
}
421477

478+
function closePopup()
479+
{
480+
popup.exists = false;
481+
actionPrevented = false;
482+
if (deviceList == null) canExit = true;
483+
}
484+
422485
override function destroy()
423486
{
424487
super.destroy();
@@ -476,6 +539,7 @@ class InputItem extends TextMenuItem
476539
function getInput()
477540
{
478541
var list = PlayerSettings.player1.controls.getInputsFor(control, device);
542+
list = list.distinct();
479543
if (list.length > index)
480544
{
481545
if (list[index] != FlxKey.ESCAPE || list[index] != FlxGamepadInputID.BACK) return list[index];

0 commit comments

Comments
 (0)