Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add disabled status to FlxButton #3087

Merged
merged 4 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified assets/images/ui/button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
86 changes: 59 additions & 27 deletions flixel/ui/FlxButton.hx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ import flixel.util.FlxDestroyUtil;
import flixel.input.touch.FlxTouch;
#end

enum abstract FlxButtonState(Int) to Int
{
/** The button is not highlighted or pressed */
var NORMAL = 0;

/** The button is selected, usually meaning the mouse is hovering over it */
var HIGHLIGHT = 1;

/** The button is being pressed usually by a mouse */
var PRESSED = 2;

/** The button is not interactible */
var DISABLED = 3;
}

/**
* A simple button class that calls a function when clicked by the mouse.
*/
Expand All @@ -26,17 +41,30 @@ class FlxButton extends FlxTypedButton<FlxText>
/**
* Used with public variable status, means not highlighted or pressed.
*/
public static inline var NORMAL:Int = 0;
@:dox(hide) @:noCompletion
@:deprecated("FlxButton.NORMAL is deprecated, use FlxButtonState.NORMAL")
public static inline var NORMAL = FlxButtonState.NORMAL;

/**
* Used with public variable status, means highlighted (usually from mouse over).
*/
public static inline var HIGHLIGHT:Int = 1;
@:dox(hide) @:noCompletion
@:deprecated("FlxButton.HIGHLIGHT is deprecated, use FlxButtonState.HIGHLIGHT")
public static inline var HIGHLIGHT = FlxButtonState.HIGHLIGHT;

/**
* Used with public variable status, means pressed (usually from mouse click).
*/
public static inline var PRESSED:Int = 2;
@:dox(hide) @:noCompletion
@:deprecated("FlxButton.PRESSED is deprecated, use FlxButtonState.PRESSED")
public static inline var PRESSED = FlxButtonState.PRESSED;

/**
* Used with public variable status, means non interactible.
*/
@:dox(hide) @:noCompletion
@:deprecated("FlxButton.DISABLED is deprecated, use FlxButtonState.DISABLED")
public static inline var DISABLED = FlxButtonState.DISABLED;

/**
* Shortcut to setting label.text
Expand Down Expand Up @@ -80,7 +108,7 @@ class FlxButton extends FlxTypedButton<FlxText>
{
if (Text != null)
{
label = new FlxText(x + labelOffsets[NORMAL].x, y + labelOffsets[NORMAL].y, 80, Text);
label = new FlxText(x + labelOffsets[FlxButtonState.NORMAL].x, y + labelOffsets[FlxButtonState.NORMAL].y, 80, Text);
label.setFormat(null, 8, 0x333333, "center");
label.alpha = labelAlphas[status];
label.drawFrame(true);
Expand Down Expand Up @@ -122,19 +150,19 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
/**
* What offsets the `label` should have for each status.
*/
public var labelOffsets:Array<FlxPoint> = [FlxPoint.get(), FlxPoint.get(), FlxPoint.get(0, 1)];
public var labelOffsets:Array<FlxPoint> = [FlxPoint.get(), FlxPoint.get(), FlxPoint.get(0, 1), FlxPoint.get()];

/**
* What alpha value the label should have for each status. Default is `[0.8, 1.0, 0.5]`.
* Multiplied with the button's `alpha`.
*/
public var labelAlphas:Array<Float> = [0.8, 1.0, 0.5];
public var labelAlphas:Array<Float> = [0.8, 1.0, 0.5, 0.3];

/**
* What animation should be played for each status.
* Default is ["normal", "highlight", "pressed"].
*/
public var statusAnimations:Array<String> = ["normal", "highlight", "pressed"];
public var statusAnimations:Array<String> = ["normal", "highlight", "pressed", "disabled"];

/**
* Whether you can press the button simply by releasing the touch / mouse button over it (default).
Expand All @@ -157,10 +185,10 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
public var maxInputMovement:Float = Math.POSITIVE_INFINITY;

/**
* Shows the current state of the button, either `FlxButton.NORMAL`,
* `FlxButton.HIGHLIGHT` or `FlxButton.PRESSED`.
* Shows the current state of the button, either `NORMAL`,
* `HIGHLIGHT` or `PRESSED`.
*/
public var status(default, set):Int;
public var status(default, set):FlxButtonState;

/**
* The properties of this button's `onUp` event (callback function, sound).
Expand Down Expand Up @@ -222,7 +250,7 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
onOver = new FlxButtonEvent();
onOut = new FlxButtonEvent();

status = FlxButton.NORMAL;
status = NORMAL;

// Since this is a UI element, the default scrollFactor is (0, 0)
scrollFactor.set();
Expand All @@ -232,8 +260,8 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
#end

#if FLX_NO_MOUSE // no need for highlight frame without mouse input
statusAnimations[FlxButton.HIGHLIGHT] = "normal";
labelAlphas[FlxButton.HIGHLIGHT] = 1;
statusAnimations[HIGHLIGHT] = "normal";
labelAlphas[HIGHLIGHT] = 1;
#end

input = new FlxInput(0);
Expand All @@ -243,9 +271,10 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
{
super.graphicLoaded();

setupAnimation("normal", FlxButton.NORMAL);
setupAnimation("highlight", FlxButton.HIGHLIGHT);
setupAnimation("pressed", FlxButton.PRESSED);
setupAnimation("normal", NORMAL);
setupAnimation("highlight", HIGHLIGHT);
setupAnimation("pressed", PRESSED);
setupAnimation("disabled", DISABLED);
}

function loadDefaultGraphic():Void
Expand Down Expand Up @@ -384,6 +413,9 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
*/
function updateButton():Void
{
// Prevent interactions with this input if it's currently disabled
if (status == DISABLED)
return;
// We're looking for any touch / mouse overlaps with this button
var overlapFound = checkMouseOverlap();
if (!overlapFound)
Expand All @@ -394,7 +426,7 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
onUpHandler();
}

if (status != FlxButton.NORMAL && (!overlapFound || (currentInput != null && currentInput.justReleased)))
if (status != NORMAL && (!overlapFound || (currentInput != null && currentInput.justReleased)))
{
onOutHandler();
}
Expand Down Expand Up @@ -464,7 +496,7 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
currentInput = input;
onDownHandler();
}
else if (status == FlxButton.NORMAL)
else if (status == NORMAL)
{
// Allow "swiping" to press a button (dragging it over the button while pressed)
if (allowSwiping && input.pressed)
Expand All @@ -489,7 +521,7 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput

function updateLabelAlpha()
{
if (_spriteLabel != null && labelAlphas.length > status)
if (_spriteLabel != null && labelAlphas.length > (status : Int))
{
_spriteLabel.alpha = alpha * labelAlphas[status];
}
Expand All @@ -502,7 +534,7 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
#if FLX_MOUSE
function onUpEventListener(_):Void
{
if (visible && exists && active && status == FlxButton.PRESSED)
if (visible && exists && active && status == PRESSED)
{
onUpHandler();
}
Expand All @@ -514,7 +546,7 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
*/
function onUpHandler():Void
{
status = FlxButton.HIGHLIGHT;
status = HIGHLIGHT;
input.release();
currentInput = null;
// Order matters here, because onUp.fire() could cause a state change and destroy this object.
Expand All @@ -526,7 +558,7 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
*/
function onDownHandler():Void
{
status = FlxButton.PRESSED;
status = PRESSED;
input.press();
// Order matters here, because onDown.fire() could cause a state change and destroy this object.
onDown.fire();
Expand All @@ -542,11 +574,11 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
// by remaining in the normal state (until mouse input is re-enabled).
if (!FlxG.mouse.enabled)
{
status = FlxButton.NORMAL;
status = NORMAL;
return;
}
#end
status = FlxButton.HIGHLIGHT;
status = HIGHLIGHT;
// Order matters here, because onOver.fire() could cause a state change and destroy this object.
onOver.fire();
}
Expand All @@ -556,7 +588,7 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
*/
function onOutHandler():Void
{
status = FlxButton.NORMAL;
status = NORMAL;
input.release();
// Order matters here, because onOut.fire() could cause a state change and destroy this object.
onOut.fire();
Expand All @@ -579,9 +611,9 @@ class FlxTypedButton<T:FlxSprite> extends FlxSprite implements IFlxInput
return Value;
}

function set_status(Value:Int):Int
function set_status(value:FlxButtonState):FlxButtonState
{
status = Value;
status = value;
updateLabelAlpha();
return status;
}
Expand Down
13 changes: 7 additions & 6 deletions tests/unit/src/flixel/ui/FlxButtonTest.hx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package flixel.ui;

import openfl.display.BitmapData;
import flixel.FlxSprite;
import flixel.ui.FlxButton;
import openfl.display.BitmapData;
import massive.munit.Assert;

class FlxButtonTest extends FlxTest
Expand Down Expand Up @@ -45,9 +46,9 @@ class FlxButtonTest extends FlxTest

function assertStatusAnimationsExist()
{
var normalName:String = button.statusAnimations[FlxButton.NORMAL];
var highlightName:String = button.statusAnimations[FlxButton.HIGHLIGHT];
var pressedName:String = button.statusAnimations[FlxButton.PRESSED];
var normalName:String = button.statusAnimations[NORMAL];
var highlightName:String = button.statusAnimations[HIGHLIGHT];
var pressedName:String = button.statusAnimations[PRESSED];

Assert.isNotNull(button.animation.getByName(normalName));
Assert.isNotNull(button.animation.getByName(highlightName));
Expand All @@ -74,7 +75,7 @@ class FlxButtonTest extends FlxTest

button.setPosition();
step(1);
Assert.areEqual(FlxButton.HIGHLIGHT, button.status);
Assert.areEqual(HIGHLIGHT, button.status);

FlxG.state.remove(button);
}
Expand All @@ -87,7 +88,7 @@ class FlxButtonTest extends FlxTest
FlxG.state.add(button);
step(2);

Assert.areEqual(FlxButton.NORMAL, button.status);
Assert.areEqual(NORMAL, button.status);
Assert.areEqual("normal", button.animation.curAnim.name);
Assert.areEqual(false, button.animation.finished);
step(10);
Expand Down
Loading