diff --git a/Project.xml b/Project.xml
index 85284f76c..3055cf457 100644
--- a/Project.xml
+++ b/Project.xml
@@ -180,6 +180,8 @@
+
+
diff --git a/source/Controls.hx b/source/Controls.hx
index 6e49c5387..95748946f 100644
--- a/source/Controls.hx
+++ b/source/Controls.hx
@@ -18,10 +18,11 @@ import flixel.input.keyboard.FlxKey;
*/
enum Control
{
- NOTE_UP;
+ // List notes in order from left to right on gameplay screen.
NOTE_LEFT;
- NOTE_RIGHT;
NOTE_DOWN;
+ NOTE_UP;
+ NOTE_RIGHT;
UI_UP;
UI_LEFT;
UI_RIGHT;
@@ -327,7 +328,7 @@ class Controls extends FlxActionSet
}
}
- public function replaceBinding(control:Control, device:Device, ?toAdd:Int, ?toRemove:Int)
+ public function replaceBinding(control:Control, device:Device, toAdd:Int, toRemove:Int)
{
if (toAdd == toRemove)
return;
@@ -335,16 +336,36 @@ class Controls extends FlxActionSet
switch (device)
{
case Keys:
- if (toRemove != null)
- unbindKeys(control, [toRemove]);
- if (toAdd != null)
- bindKeys(control, [toAdd]);
+ forEachBound(control, function(action, _) replaceKey(action, toAdd, toRemove));
case Gamepad(id):
- if (toRemove != null)
- unbindButtons(control, id, [toRemove]);
- if (toAdd != null)
- bindButtons(control, id, [toAdd]);
+ forEachBound(control, function(action, _) replaceButton(action, id, toAdd, toRemove));
+ }
+ }
+
+ function replaceKey(action:FlxActionDigital, toAdd:Int, toRemove:Int)
+ {
+ for (i in 0...action.inputs.length)
+ {
+ var input = action.inputs[i];
+ if (input.device == KEYBOARD && input.inputID == toRemove)
+ {
+ @:privateAccess
+ action.inputs[i].inputID = toAdd;
+ }
+ }
+ }
+
+ function replaceButton(action:FlxActionDigital, deviceID:Int, toAdd:Int, toRemove:Int)
+ {
+ for (i in 0...action.inputs.length)
+ {
+ var input = action.inputs[i];
+ if (isGamepad(input, deviceID) && input.inputID == toRemove)
+ {
+ @:privateAccess
+ action.inputs[i].inputID = toAdd;
+ }
}
}
@@ -498,12 +519,11 @@ class Controls extends FlxActionSet
}
}
- public function addGamepad(id:Int, ?buttonMap:Map>):Void
+ public function addGamepadWithSaveData(id:Int, ?padData:Dynamic):Void
{
gamepadsAdded.push(id);
- for (control in buttonMap.keys())
- bindButtons(control, id, buttonMap[control]);
+ fromSaveData(padData, Gamepad(id));
}
inline function addGamepadLiteral(id:Int, ?buttonMap:Map>):Void
@@ -522,7 +542,7 @@ class Controls extends FlxActionSet
while (i-- > 0)
{
var input = action.inputs[i];
- if (input.device == GAMEPAD && (deviceID == FlxInputDeviceID.ALL || input.deviceID == deviceID))
+ if (isGamepad(input, deviceID))
action.remove(input);
}
}
@@ -533,13 +553,9 @@ class Controls extends FlxActionSet
public function addDefaultGamepad(id):Void
{
addGamepadLiteral(id, [
- #if switch
- Control.ACCEPT => [B],
- Control.BACK => [A],
- #else
- Control.ACCEPT => [A],
- Control.BACK => [B],
- #end
+
+ Control.ACCEPT => [#if switch B #else A #end],
+ Control.BACK => [#if switch A #else B #end, BACK],
Control.UI_UP => [DPAD_UP, LEFT_STICK_DIGITAL_UP],
Control.UI_DOWN => [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN],
Control.UI_LEFT => [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT],
@@ -608,7 +624,7 @@ class Controls extends FlxActionSet
case Gamepad(id):
for (input in getActionFromControl(control).inputs)
{
- if (input.deviceID == id)
+ if (isGamepad(input, id))
list.push(input.inputID);
}
}
@@ -626,6 +642,37 @@ class Controls extends FlxActionSet
}
}
+ public function fromSaveData(data:Dynamic, device:Device)
+ {
+ for (control in Control.createAll())
+ {
+ var inputs:Array = Reflect.field(data, control.getName());
+ if (inputs != null)
+ {
+ switch(device)
+ {
+ case Keys: bindKeys(control, inputs.copy());
+ case Gamepad(id): bindButtons(control, id, inputs.copy());
+ }
+ }
+ }
+ }
+
+ public function createSaveData(device:Device):Dynamic
+ {
+ var isEmpty = true;
+ var data = {};
+ for (control in Control.createAll())
+ {
+ var inputs = getInputsFor(control, device);
+ isEmpty = isEmpty && inputs.length == 0;
+
+ Reflect.setField(data, control.getName(), inputs);
+ }
+
+ return isEmpty ? null : data;
+ }
+
static function isDevice(input:FlxActionInput, device:Device)
{
return switch device
@@ -640,3 +687,6 @@ class Controls extends FlxActionSet
return input.device == GAMEPAD && (deviceID == FlxInputDeviceID.ALL || input.deviceID == deviceID);
}
}
+
+
+typedef SaveInputLists = {?keys:Array, ?pad:Array};
\ No newline at end of file
diff --git a/source/OptionsMenu_old.hx b/source/OptionsMenu_old.hx
index 3acd212a3..4ec844323 100644
--- a/source/OptionsMenu_old.hx
+++ b/source/OptionsMenu_old.hx
@@ -82,7 +82,7 @@ class OptionsMenu_old extends MusicBeatState
{
if (FlxG.keys.getIsDown().length > 0)
{
- PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxG.keys.getIsDown()[0].ID, null);
+ // PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxG.keys.getIsDown()[0].ID, null);
}
// PlayerSettings.player1.controls.replaceBinding(Control)
}
diff --git a/source/PlayerSettings.hx b/source/PlayerSettings.hx
index df7586c44..a0ed2429a 100644
--- a/source/PlayerSettings.hx
+++ b/source/PlayerSettings.hx
@@ -1,8 +1,11 @@
package;
import Controls;
+
import flixel.FlxCamera;
import flixel.FlxG;
+import flixel.input.actions.FlxActionInput;
+import flixel.input.gamepad.FlxGamepad;
import flixel.util.FlxSignal;
// import ui.DeviceManager;
@@ -24,124 +27,223 @@ class PlayerSettings
// public var avatar:Player;
// public var camera(get, never):PlayCamera;
- function new(id, scheme)
+ function new(id)
{
this.id = id;
- this.controls = new Controls('player$id', scheme);
+ this.controls = new Controls('player$id', None);
+
+ #if CLEAR_INPUT_SAVE
+ FlxG.save.data.controls = null;
+ FlxG.save.flush();
+ #end
+
+ var useDefault = true;
+ var controlData = FlxG.save.data.controls;
+ if (controlData != null)
+ {
+ var keyData:Dynamic = null;
+ if (id == 0 && controlData.p1 != null && controlData.p1.keys != null)
+ keyData = controlData.p1.keys;
+ else if (id == 1 && controlData.p2 != null && controlData.p2.keys != null)
+ keyData = controlData.p2.keys;
+
+ if (keyData != null)
+ {
+ useDefault = false;
+ trace("loaded key data: " + haxe.Json.stringify(keyData));
+ controls.fromSaveData(keyData, Keys);
+ }
+ }
+
+ if (useDefault)
+ controls.setKeyboardScheme(Solo);
}
+
+ function addGamepad(gamepad:FlxGamepad)
+ {
+ var useDefault = true;
+ var controlData = FlxG.save.data.controls;
+ if (controlData != null)
+ {
+ var padData:Dynamic = null;
+ if (id == 0 && controlData.p1 != null && controlData.p1.pad != null)
+ padData = controlData.p1.pad;
+ else if (id == 1 && controlData.p2 != null && controlData.p2.pad != null)
+ padData = controlData.p2.pad;
+
+ if (padData != null)
+ {
+ useDefault = false;
+ trace("loaded pad data: " + haxe.Json.stringify(padData));
+ controls.addGamepadWithSaveData(gamepad.id, padData);
+ }
+ }
+
+ if (useDefault)
+ controls.addDefaultGamepad(gamepad.id);
+ }
+
+ public function saveControls()
+ {
+ if (FlxG.save.data.controls == null)
+ FlxG.save.data.controls = {};
+
+ var playerData:{ ?keys:Dynamic, ?pad:Dynamic }
+ if (id == 0)
+ {
+ if (FlxG.save.data.controls.p1 == null)
+ FlxG.save.data.controls.p1 = {};
+ playerData = FlxG.save.data.controls.p1;
+ }
+ else
+ {
+ if (FlxG.save.data.controls.p2 == null)
+ FlxG.save.data.controls.p2 = {};
+ playerData = FlxG.save.data.controls.p2;
+ }
+
+ var keyData = controls.createSaveData(Keys);
+ if (keyData != null)
+ {
+ playerData.keys = keyData;
+ trace("saving key data: " + haxe.Json.stringify(keyData));
+ }
+
+ if (controls.gamepadsAdded.length > 0)
+ {
+ var padData = controls.createSaveData(Gamepad(controls.gamepadsAdded[0]));
+ if (padData != null)
+ {
+ trace("saving pad data: " + haxe.Json.stringify(padData));
+ playerData.pad = padData;
+ }
+ }
+
+ FlxG.save.flush();
+ }
+
+ static public function init():Void
+ {
+ if (player1 == null)
+ {
+ player1 = new PlayerSettings(0);
+ ++numPlayers;
+ }
+
+ FlxG.gamepads.deviceConnected.add(onGamepadAdded);
+ var numGamepads = FlxG.gamepads.numActiveGamepads;
+ for (i in 0...numGamepads)
+ {
+ var gamepad = FlxG.gamepads.getByID(i);
+ if (gamepad != null)
+ onGamepadAdded(gamepad);
+ }
+
+ // player1.controls.addDefaultGamepad(0);
+ // }
+
+ // if (numGamepads > 1)
+ // {
+ // if (player2 == null)
+ // {
+ // player2 = new PlayerSettings(1, None);
+ // ++numPlayers;
+ // }
+
+ // var gamepad = FlxG.gamepads.getByID(1);
+ // if (gamepad == null)
+ // throw 'Unexpected null gamepad. id:0';
+
+ // player2.controls.addDefaultGamepad(1);
+ // }
+
+ // DeviceManager.init();
+ }
+
+ static function onGamepadAdded(gamepad:FlxGamepad)
+ {
+ player1.addGamepad(gamepad);
+ }
+
+
+ /*
public function setKeyboardScheme(scheme)
{
controls.setKeyboardScheme(scheme);
}
- /*
- static public function addAvatar(avatar:Player):PlayerSettings
- {
- var settings:PlayerSettings;
-
- if (player1 == null)
- {
- player1 = new PlayerSettings(0, Solo);
- ++numPlayers;
- }
-
- if (player1.avatar == null)
- settings = player1;
- else
- {
- if (player2 == null)
- {
- if (player1.controls.keyboardScheme.match(Duo(true)))
- player2 = new PlayerSettings(1, Duo(false));
- else
- player2 = new PlayerSettings(1, None);
- ++numPlayers;
- }
-
- if (player2.avatar == null)
- settings = player2;
- else
- throw throw 'Invalid number of players: ${numPlayers + 1}';
- }
- ++numAvatars;
- settings.avatar = avatar;
- avatar.settings = settings;
-
- splitCameras();
-
- onAvatarAdd.dispatch(settings);
-
- return settings;
- }
-
- static public function removeAvatar(avatar:Player):Void
- {
- var settings:PlayerSettings;
-
- if (player1 != null && player1.avatar == avatar)
- settings = player1;
- else if (player2 != null && player2.avatar == avatar)
- {
- settings = player2;
- if (player1.controls.keyboardScheme.match(Duo(_)))
- player1.setKeyboardScheme(Solo);
- }
- else
- throw "Cannot remove avatar that is not for a player";
-
- settings.avatar = null;
- while (settings.controls.gamepadsAdded.length > 0)
- {
- final id = settings.controls.gamepadsAdded.shift();
- settings.controls.removeGamepad(id);
- DeviceManager.releaseGamepad(FlxG.gamepads.getByID(id));
- }
-
- --numAvatars;
-
- splitCameras();
-
- onAvatarRemove.dispatch(avatar.settings);
- }
-
- */
- static public function init():Void
+ static public function addAvatar(avatar:Player):PlayerSettings
{
+ var settings:PlayerSettings;
+
if (player1 == null)
{
player1 = new PlayerSettings(0, Solo);
++numPlayers;
}
- var numGamepads = FlxG.gamepads.numActiveGamepads;
- if (numGamepads > 0)
- {
- var gamepad = FlxG.gamepads.getByID(0);
- if (gamepad == null)
- throw 'Unexpected null gamepad. id:0';
-
- player1.controls.addDefaultGamepad(0);
- }
-
- if (numGamepads > 1)
+ if (player1.avatar == null)
+ settings = player1;
+ else
{
if (player2 == null)
{
- player2 = new PlayerSettings(1, None);
+ if (player1.controls.keyboardScheme.match(Duo(true)))
+ player2 = new PlayerSettings(1, Duo(false));
+ else
+ player2 = new PlayerSettings(1, None);
++numPlayers;
}
- var gamepad = FlxG.gamepads.getByID(1);
- if (gamepad == null)
- throw 'Unexpected null gamepad. id:0';
+ if (player2.avatar == null)
+ settings = player2;
+ else
+ throw throw 'Invalid number of players: ${numPlayers + 1}';
+ }
+ ++numAvatars;
+ settings.avatar = avatar;
+ avatar.settings = settings;
- player2.controls.addDefaultGamepad(1);
+ splitCameras();
+
+ onAvatarAdd.dispatch(settings);
+
+ return settings;
+ }
+
+ static public function removeAvatar(avatar:Player):Void
+ {
+ var settings:PlayerSettings;
+
+ if (player1 != null && player1.avatar == avatar)
+ settings = player1;
+ else if (player2 != null && player2.avatar == avatar)
+ {
+ settings = player2;
+ if (player1.controls.keyboardScheme.match(Duo(_)))
+ player1.setKeyboardScheme(Solo);
+ }
+ else
+ throw "Cannot remove avatar that is not for a player";
+
+ settings.avatar = null;
+ while (settings.controls.gamepadsAdded.length > 0)
+ {
+ final id = settings.controls.gamepadsAdded.shift();
+ settings.controls.removeGamepad(id);
+ DeviceManager.releaseGamepad(FlxG.gamepads.getByID(id));
}
- // DeviceManager.init();
+ --numAvatars;
+
+ splitCameras();
+
+ onAvatarRemove.dispatch(avatar.settings);
}
+ */
+
static public function reset()
{
player1 = null;
diff --git a/source/TitleState.hx b/source/TitleState.hx
index 01668d72c..eff43f823 100644
--- a/source/TitleState.hx
+++ b/source/TitleState.hx
@@ -41,8 +41,6 @@ class TitleState extends MusicBeatState
FlxG.sound.muteKeys = [ZERO];
- PlayerSettings.init();
-
curWacky = FlxG.random.getObject(getIntroTextShit());
// DEBUG BULLSHIT
@@ -50,6 +48,7 @@ class TitleState extends MusicBeatState
super.create();
FlxG.save.bind('funkin', 'ninjamuffin99');
+ PlayerSettings.init();
Highscore.load();
#if newgrounds
diff --git a/source/ui/ControlsMenu.hx b/source/ui/ControlsMenu.hx
index ca923af29..629a89914 100644
--- a/source/ui/ControlsMenu.hx
+++ b/source/ui/ControlsMenu.hx
@@ -184,7 +184,12 @@ class ControlsMenu extends ui.OptionsState.Page
var inputName = device == Keys ? "key" : "button";
var cancel = device == Keys ? "Escape" : "Back";
- prompt.setText('\nPress any $inputName to rebind\n\n\n\n $cancel to cancel');
+ //todo: alignment
+ if (device == Keys)
+ prompt.setText('\nPress any key to rebind\n\n\n\n $cancel to cancel');
+ else
+ prompt.setText('\nPress any button\n to rebind\n\n\n $cancel to cancel');
+
controlGrid.selectedItem.select();
labels.members[Std.int(controlGrid.selectedIndex / COLUMNS)].alpha = 1.0;
@@ -265,13 +270,16 @@ class ControlsMenu extends ui.OptionsState.Page
// Don't use resetItem() since items share names/labels
item.input = input;
item.label.text = item.getLabel(input);
+
+ PlayerSettings.player1.saveControls();
}
function closePrompt()
{
- controlGrid.enabled = true;
- canExit = true;
prompt.exists = false;
+ controlGrid.enabled = true;
+ if (deviceList == null)
+ canExit = true;
}
override function destroy()