Skip to content

Commit

Permalink
allow multiple inputs of the same type (HaxeFlixel#3134)
Browse files Browse the repository at this point in the history
* allow multiple inputs of the same type

* fix error

* use addInput

* add InputFrontEnd tests
  • Loading branch information
Geokureli committed May 9, 2024
1 parent ac6cc5e commit fd3eff9
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 62 deletions.
27 changes: 15 additions & 12 deletions flixel/FlxG.hx
Original file line number Diff line number Diff line change
Expand Up @@ -630,23 +630,23 @@ class FlxG

// Instantiate inputs
#if FLX_KEYBOARD
keys = inputs.add(new FlxKeyboard());
keys = inputs.addInput(new FlxKeyboard());
#end

#if FLX_MOUSE
mouse = inputs.add(new FlxMouse(game._inputContainer));
mouse = inputs.addInput(new FlxMouse(game._inputContainer));
#end

#if FLX_TOUCH
touches = inputs.add(new FlxTouchManager());
touches = inputs.addInput(new FlxTouchManager());
#end

#if FLX_GAMEPAD
gamepads = inputs.add(new FlxGamepadManager());
gamepads = inputs.addInput(new FlxGamepadManager());
#end

#if android
android = inputs.add(new FlxAndroidKeys());
android = inputs.addInput(new FlxAndroidKeys());
#end

#if FLX_ACCELEROMETER
Expand Down Expand Up @@ -756,21 +756,24 @@ class FlxG
}

#if FLX_MOUSE
static function set_mouse(NewMouse:FlxMouse):FlxMouse
static function set_mouse(newMouse:FlxMouse):FlxMouse
{
if (mouse == null) // if no mouse, just add it
// if there's no mouse, add it
if (mouse == null)
{
mouse = inputs.add(NewMouse); // safe to do b/c it won't add repeats!
mouse = inputs.addUniqueType(newMouse);
return mouse;
}
var oldMouse:FlxMouse = mouse;
var result:FlxMouse = inputs.replace(oldMouse, NewMouse); // replace existing mouse

// replace existing mouse
final oldMouse:FlxMouse = mouse;
final result:FlxMouse = inputs.replace(oldMouse, newMouse, true);
if (result != null)
{
mouse = result;
oldMouse.destroy();
return NewMouse;
return newMouse;
}

return oldMouse;
}
#end
Expand Down
95 changes: 45 additions & 50 deletions flixel/system/frontEnds/InputFrontEnd.hx
Original file line number Diff line number Diff line change
Expand Up @@ -22,76 +22,71 @@ class InputFrontEnd

/**
* Add an input to the system
*
* @param Input The input to add
* @return The input
*/
@:generic
public function add<T:IFlxInputManager>(Input:T):T
@:deprecated("add is deprecated, use addUniqueType")
public inline function add<T:IFlxInputManager>(input:T):T
{
// Don't add repeats
for (input in list)
{
if (FlxStringUtil.sameClassName(Input, input))
{
return Input;
}
}
return addUniqueType(input);
}

/**
* Add an input to the system, unless the same instance was already added
*/
@:generic
public function addInput<T:IFlxInputManager>(input:T):T
{
if (!list.contains(input))
list.push(input);

return input;
}

list.push(Input);
return Input;
/**
* Add an input to the system, unless the same type was already added
*/
@:generic
public function addUniqueType<T:IFlxInputManager>(input:T):T
{
// Don't add repeat types
if (!Lambda.exists(list, FlxStringUtil.sameClassName.bind(_, input)))
list.push(input);

return input;
}

/**
* Removes an input from the system
*
* @param Input The input to remove
* @return Bool indicating whether it was removed or not
* @param Input The input to remove
* @return Bool indicating whether it was removed or not
*/
@:generic
public function remove<T:IFlxInputManager>(Input:T):Bool
public inline function remove<T:IFlxInputManager>(input:T):Bool
{
var i:Int = 0;
for (input in list)
{
if (input == Input)
{
list.splice(i, 1);
return true;
}
i++;
}
return false;
return list.remove(input);
}

/**
* Replace an existing input in the system with a new one
*
* @param Old The old input to replace
* @param New The new input to put in its place
* @return If successful returns New. Otherwise returns null.
* @param oldInput The old input to replace
* @param newInput The new input to put in its place
* @param destroyOld Whether to destroy the old input
* @return If successful returns `newInput`. Otherwise returns `null`.
*/
@:generic
public function replace<T:IFlxInputManager>(Old:T, New:T):T
public function replace<T:IFlxInputManager>(oldInput:T, newInput:T, destroyOld = false):Null<T>
{
var i:Int = 0;
var success:Bool = false;
for (input in list)
{
if (input == Old)
{
list[i] = New; // Replace Old with New
success = true;
break;
}
i++;
}

if (success)
{
return New;
}
return null;
final index = list.indexOf(oldInput);
if (index == -1)
return null;

if (destroyOld)
oldInput.destroy();

list[index] = newInput;
return newInput;
}

public function reset():Void
Expand Down
20 changes: 20 additions & 0 deletions tests/unit/src/FlxAssert.hx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,26 @@ class FlxAssert
Assert.fail('\nValue\n ${actual}\nwas equal to\n ${expected}\n', info);
}

public static function arrayContains<T>(array:Array<T>, item:T, ?msg:String, ?info:PosInfos):Void
{
if (array.contains(item))
Assert.assertionCount++;
else if (msg != null)
Assert.fail(msg, info);
else
Assert.fail('\nValue\n ${item}\nwas not found in array\n ${array}\n', info);
}

public static function arrayNotContains<T>(array:Array<T>, item:T, ?msg:String, ?info:PosInfos):Void
{
if (!array.contains(item))
Assert.assertionCount++;
else if (msg != null)
Assert.fail(msg, info);
else
Assert.fail('\nValue\n ${item}\nwas found in array\n ${array}\n', info);
}

public static function pointsEqual(expected:FlxPoint, actual:FlxPoint, ?msg:String, ?info:PosInfos)
{
if (expected.equals(actual))
Expand Down
70 changes: 70 additions & 0 deletions tests/unit/src/flixel/system/frontEnds/InputFrontEndTest.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package flixel.system.frontEnds;

import flixel.system.frontEnds.InputFrontEnd;
import flixel.FlxG;
import flixel.input.IFlxInputManager;
import massive.munit.Assert;

class InputFrontEndTest
{
var inputs:InputFrontEnd;

@Before
function before():Void
{
@:privateAccess
inputs = new InputFrontEnd();
}

@Test
@:haxe.warning("-WDeprecated")
function testAdd()
{
final input1 = new CustomInputManager();
inputs.add(input1);
FlxAssert.arrayContains(inputs.list, input1);

final input2 = new CustomInputManager();
inputs.add(input2);
FlxAssert.arrayNotContains(inputs.list, input2);
}

@Test
function testAddUniqueType()
{
final input1 = new CustomInputManager();
inputs.addUniqueType(input1);
FlxAssert.arrayContains(inputs.list, input1);

final input2 = new CustomInputManager();
inputs.addUniqueType(input2);
FlxAssert.arrayNotContains(inputs.list, input2);
}

@Test
function testAddInput()
{
final input1 = new CustomInputManager();
inputs.addInput(input1);
FlxAssert.arrayContains(inputs.list, input1);

final oldLength = inputs.list.length;
// add again
inputs.addInput(input1);
Assert.areEqual(inputs.list.length, oldLength);

final input2 = new CustomInputManager();
inputs.addInput(input2);
FlxAssert.arrayContains(inputs.list, input2);
}
}

class CustomInputManager implements IFlxInputManager
{
public function new () {}
public function destroy() {}
public function reset():Void {}
function update():Void {}
function onFocus():Void {}
function onFocusLost():Void {}
}

0 comments on commit fd3eff9

Please sign in to comment.