1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2025-03-23 18:39:33 +00:00

add rebind key prompt

This commit is contained in:
George FunBook 2021-03-16 09:56:08 -05:00
parent 9ffa28dd21
commit 9c1866dbdb
7 changed files with 200 additions and 49 deletions

View file

@ -11,6 +11,30 @@ import flixel.input.gamepad.FlxGamepadButton;
import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.gamepad.FlxGamepadInputID;
import flixel.input.keyboard.FlxKey; import flixel.input.keyboard.FlxKey;
/**
* Since, in many cases multiple actions should use similar keys, we don't want the
* rebinding UI to list every action. ActionBinders are what the user percieves as
* an input so, for instance, they can't set jump-press and jump-release to different keys.
*/
enum Control
{
NOTE_UP;
NOTE_LEFT;
NOTE_RIGHT;
NOTE_DOWN;
UI_UP;
UI_LEFT;
UI_RIGHT;
UI_DOWN;
RESET;
ACCEPT;
BACK;
PAUSE;
#if CAN_CHEAT
CHEAT;
#end
}
@:enum @:enum
abstract Action(String) to String from String abstract Action(String) to String from String
{ {
@ -53,30 +77,6 @@ enum Device
Gamepad(id:Int); Gamepad(id:Int);
} }
/**
* Since, in many cases multiple actions should use similar keys, we don't want the
* rebinding UI to list every action. ActionBinders are what the user percieves as
* an input so, for instance, they can't set jump-press and jump-release to different keys.
*/
enum Control
{
UI_UP;
UI_LEFT;
UI_RIGHT;
UI_DOWN;
NOTE_UP;
NOTE_LEFT;
NOTE_RIGHT;
NOTE_DOWN;
RESET;
ACCEPT;
BACK;
PAUSE;
#if CAN_CHEAT
CHEAT;
#end
}
enum KeyboardScheme enum KeyboardScheme
{ {
Solo; Solo;
@ -450,7 +450,7 @@ class Controls extends FlxActionSet
bindKeys(Control.NOTE_LEFT, [A, FlxKey.LEFT]); bindKeys(Control.NOTE_LEFT, [A, FlxKey.LEFT]);
bindKeys(Control.NOTE_RIGHT, [D, FlxKey.RIGHT]); bindKeys(Control.NOTE_RIGHT, [D, FlxKey.RIGHT]);
bindKeys(Control.ACCEPT, [Z, SPACE, ENTER]); bindKeys(Control.ACCEPT, [Z, SPACE, ENTER]);
bindKeys(Control.BACK, [BACKSPACE, ESCAPE]); bindKeys(Control.BACK, [X, BACKSPACE, ESCAPE]);
bindKeys(Control.PAUSE, [P, ENTER, ESCAPE]); bindKeys(Control.PAUSE, [P, ENTER, ESCAPE]);
bindKeys(Control.RESET, [R]); bindKeys(Control.RESET, [R]);
case Duo(true): case Duo(true):

View file

@ -148,6 +148,7 @@ class AtlasText extends FlxTypedSpriteGroup<AtlasChar>
} }
charSprite.x = xPos; charSprite.x = xPos;
charSprite.y = yPos + maxHeight - charSprite.height; charSprite.y = yPos + maxHeight - charSprite.height;
charSprite.alpha = 1;//gets multiplied when added
add(charSprite); add(charSprite);
xPos += charSprite.width; xPos += charSprite.width;

View file

@ -1,5 +1,6 @@
package ui; package ui;
import ui.MenuList;
import flixel.FlxG; import flixel.FlxG;
import flixel.FlxCamera; import flixel.FlxCamera;
import flixel.FlxObject; import flixel.FlxObject;
@ -13,9 +14,23 @@ import ui.TextMenuList;
class ControlsMenu extends ui.OptionsState.Page class ControlsMenu extends ui.OptionsState.Page
{ {
var controlGrid:TextMenuList; static var controlList = Control.createAll();
/*
* Defines groups of controls that cannot share inputs, like left and right. Say, if ACCEPT is Z, Back is X,
* if the player sets Back to Z it also set ACCEPT to X. This prevents the player from setting the controls in
* a way the prevents them from changing more controls or exiting the menu.
*/
static var controlGroups:Array<Array<Control>> =
[ [ NOTE_UP, NOTE_DOWN, NOTE_LEFT, NOTE_RIGHT ]
, [ UI_UP, UI_DOWN, UI_LEFT, UI_RIGHT, ACCEPT, BACK ]
];
var itemGroups:Array<Array<InputItem>> = [for (i in 0...controlGroups.length) []];
var controlGrid:MenuTypedList<InputItem>;
var labels:FlxTypedGroup<AtlasText>; var labels:FlxTypedGroup<AtlasText>;
var menuCamera:FlxCamera; var menuCamera:FlxCamera;
var prompt:Prompt;
public function new() public function new()
{ {
@ -29,54 +44,135 @@ class ControlsMenu extends ui.OptionsState.Page
FlxCamera.defaultCameras.remove(menuCamera); FlxCamera.defaultCameras.remove(menuCamera);
} }
menuCamera.bgColor = 0x0; menuCamera.bgColor = 0x0;
camera = menuCamera;
add(labels = new FlxTypedGroup<AtlasText>()); add(labels = new FlxTypedGroup<AtlasText>());
labels.camera = menuCamera; add(controlGrid = new MenuTypedList(Columns(2)));
add(controlGrid = new TextMenuList(Columns(2)));
controlGrid.camera = menuCamera;
// FlxG.debugger.drawDebug = true; // FlxG.debugger.drawDebug = true;
var controlList = Control.createAll(); var y = 30;
var spacer = 70;
var currentHeader:String = null;
// list order is determined by enum order
for (i in 0...controlList.length) for (i in 0...controlList.length)
{ {
var control = controlList[i]; var control = controlList[i];
var name = control.getName(); var name = control.getName();
var y = (70 * i) + 30; if (currentHeader != "UI_" && name.indexOf("UI_") == 0)
var label = labels.add(new BoldText(0, y, name)); {
label.x += 250; currentHeader = "UI_";
labels.add(new BoldText(0, y, "UI")).screenCenter(X);
y += spacer;
}
else if (currentHeader != "NOTE_" && name.indexOf("NOTE_") == 0)
{
currentHeader = "NOTE_";
labels.add(new BoldText(0, y, "NOTES")).screenCenter(X);
y += spacer;
}
if (currentHeader != null && name.indexOf(currentHeader) == 0)
name = name.substr(currentHeader.length);
var label = labels.add(new BoldText(250, y, name));
createItem(label.x + 400, y, control, 0); createItem(label.x + 400, y, control, 0);
createItem(label.x + 600, y, control, 1); createItem(label.x + 600, y, control, 1);
y += spacer;
} }
trace(itemGroups.map((group)->group.map((item)->item.label.text)));
var selected = controlGrid.members[0]; var selected = controlGrid.members[0];
var camFollow = new FlxObject(FlxG.width / 2, selected.y, 70, 70); var camFollow = new FlxObject(FlxG.width / 2, selected.y, 70, 70);
menuCamera.follow(camFollow, null, 0.06); menuCamera.follow(camFollow, null, 0.06);
var margin = 100; var margin = 100;
menuCamera.deadzone.set(0, margin, menuCamera.width, menuCamera.height - margin * 2); menuCamera.deadzone.set(0, margin, menuCamera.width, menuCamera.height - margin * 2);
controlGrid.onChange.add(function (selected) camFollow.y = selected.y); controlGrid.onChange.add(function (selected) camFollow.y = selected.y);
prompt = new Prompt("Press any key to rebind\n\n\n\n Escape to cancel", None);
prompt.create();
prompt.createBgFromMargin();
prompt.back.scrollFactor.set(0, 0);
prompt.exists = false;
add(prompt);
} }
function createItem(x = 0.0, y = 0.0, control:Control, index:Int) function createItem(x = 0.0, y = 0.0, control:Control, index:Int)
{ {
var list = PlayerSettings.player1.controls.getInputsFor(control, Keys); var item = new InputItem(x, y, control, index, onSelect);
var name = "---"; for (i in 0...controlGroups.length)
if (list.length > index)
{ {
if (list[index] == FlxKey.ESCAPE) if (controlGroups[i].contains(control))
return createItem(x, y, control, 2); itemGroups[i].push(item);
name = InputFormatter.format(list[index], Keys);
} }
trace(control.getName() + " " + index + ": " + name); return controlGrid.addItem(item.name, item);
return controlGrid.createItem(x, y, name, Default, onSelect.bind(name, control, index));
} }
function onSelect(name:String, control:Control, index:Int):Void function onSelect():Void
{ {
controlGrid.enabled = false; controlGrid.enabled = false;
// var prompt = new Prompt(); canExit = false;
prompt.exists = true;
}
override function update(elapsed:Float)
{
super.update(elapsed);
if (prompt.exists)
{
var key = FlxG.keys.firstJustPressed();
if (key != NONE)
{
if (key != ESCAPE)
onKeySelect(key);
closePrompt();
}
}
}
function onKeySelect(key:Int)
{
var item = controlGrid.selectedItem;
for (group in itemGroups)
{
if (group.contains(item))
{
for (otherItem in group)
{
// Check if items in the same group have the new input
if (otherItem != item && otherItem.input == key)
{
// replace that input with this items old input.
PlayerSettings.player1.controls.replaceBinding(otherItem.control, Keys, item.input, otherItem.input);
// Don't use resetItem() since items share names/labels
otherItem.input = item.input;
otherItem.label.text = item.label.text;
}
}
}
}
PlayerSettings.player1.controls.replaceBinding(item.control, Keys, key, item.input);
// Don't use resetItem() since items share names/labels
item.input = key;
item.label.text = item.getLabel(key);
}
function closePrompt()
{
controlGrid.enabled = true;
canExit = true;
prompt.exists = false;
}
override function destroy()
{
super.destroy();
if (FlxG.cameras.list.contains(menuCamera))
FlxG.cameras.remove(menuCamera);
} }
override function set_enabled(value:Bool) override function set_enabled(value:Bool)
@ -84,4 +180,33 @@ class ControlsMenu extends ui.OptionsState.Page
controlGrid.enabled = value; controlGrid.enabled = value;
return super.set_enabled(value); return super.set_enabled(value);
} }
}
class InputItem extends TextMenuItem
{
public var control:Control;
public var input:Int = -1;
public function new (x = 0.0, y = 0.0, control, index, ?callback)
{
this.control = control;
var list = PlayerSettings.player1.controls.getInputsFor(control, Keys);
if (list.length > index)
{
if (list[index] != FlxKey.ESCAPE)
input = list[index];
else if (list.length > 2)
// Escape isn't mappable, show a third option, instead.
input = list[2];
}
;
super(x, y, getLabel(input), Default, callback);
}
public function getLabel(input:Int)
{
return input == -1 ? "---" : InputFormatter.format(input, Keys);
}
} }

View file

@ -10,6 +10,7 @@ import flixel.util.FlxSignal;
class MenuTypedList<T:MenuItem> extends FlxTypedGroup<T> class MenuTypedList<T:MenuItem> extends FlxTypedGroup<T>
{ {
public var selectedIndex(default, null) = 0; public var selectedIndex(default, null) = 0;
public var selectedItem(get, never):T;
/** Called when a new item is highlighted */ /** Called when a new item is highlighted */
public var onChange(default, null) = new FlxTypedSignal<T->Void>(); public var onChange(default, null) = new FlxTypedSignal<T->Void>();
/** Called when an item is accepted */ /** Called when an item is accepted */
@ -189,6 +190,11 @@ class MenuTypedList<T:MenuItem> extends FlxTypedGroup<T>
onChange.removeAll(); onChange.removeAll();
onAcceptPress.removeAll(); onAcceptPress.removeAll();
} }
inline function get_selectedItem():T
{
return members[selectedIndex];
}
} }
class MenuItem extends FlxSprite class MenuItem extends FlxSprite
@ -221,8 +227,8 @@ class MenuItem extends FlxSprite
/** /**
* Calls setData and resets/redraws the state of the item * Calls setData and resets/redraws the state of the item
* @param name * @param name the label.
* @param callback * @param callback Unchanged if null.
*/ */
public function setItem(name:String, ?callback:Void->Void) public function setItem(name:String, ?callback:Void->Void)
{ {

View file

@ -25,6 +25,7 @@ class OptionsState extends MusicBeatState
menuBG.setGraphicSize(Std.int(menuBG.width * 1.1)); menuBG.setGraphicSize(Std.int(menuBG.width * 1.1));
menuBG.updateHitbox(); menuBG.updateHitbox();
menuBG.screenCenter(); menuBG.screenCenter();
menuBG.scrollFactor.set(0, 0);
add(menuBG); add(menuBG);
var options = addPage(Options, new OptionsMenu(false)); var options = addPage(Options, new OptionsMenu(false));
@ -94,6 +95,7 @@ class Page extends FlxGroup
public var onExit(default, null) = new FlxSignal(); public var onExit(default, null) = new FlxSignal();
public var enabled(default, set) = true; public var enabled(default, set) = true;
public var canExit = true;
var controls(get, never):Controls; var controls(get, never):Controls;
inline function get_controls() return PlayerSettings.player1.controls; inline function get_controls() return PlayerSettings.player1.controls;
@ -120,7 +122,7 @@ class Page extends FlxGroup
function updateEnabled(elapsed:Float) function updateEnabled(elapsed:Float)
{ {
if (controls.BACK) if (canExit && controls.BACK)
exit(); exit();
} }

View file

@ -17,13 +17,14 @@ class Prompt extends flixel.FlxSubState
public var onNo:Void->Void; public var onNo:Void->Void;
public var buttons:TextMenuList; public var buttons:TextMenuList;
public var field:AtlasText; public var field:AtlasText;
public var back:FlxSprite;
var style:ButtonStyle; var style:ButtonStyle;
public function new (text:String, style:ButtonStyle = Ok) public function new (text:String, style:ButtonStyle = Ok)
{ {
this.style = style; this.style = style;
super(0xA0000000); super(0x80000000);
buttons = new TextMenuList(Horizontal); buttons = new TextMenuList(Horizontal);
@ -43,6 +44,21 @@ class Prompt extends flixel.FlxSubState
add(buttons); add(buttons);
} }
public function createBg(width:Int, height:Int, color = 0xFF808080)
{
back = new FlxSprite();
back.makeGraphic(width, height, color, false, "prompt-bg");
back.screenCenter(XY);
add(back);
members.unshift(members.pop());// bring to front
}
public function createBgFromMargin(margin = MARGIN, color = 0xFF808080)
{
createBg(Std.int(FlxG.width - margin * 2), Std.int(FlxG.height - margin * 2), color);
}
public function setButtons(style:ButtonStyle) public function setButtons(style:ButtonStyle)
{ {
if (this.style != style) if (this.style != style)

View file

@ -39,6 +39,7 @@ class TextTypedMenuItem<T:AtlasText> extends MenuTypedItem<T>
if (label != null) if (label != null)
{ {
label.text = name; label.text = name;
label.alpha = alpha;
width = label.width; width = label.width;
height = label.height; height = label.height;
} }