Add proper overlap and input check for circle buttons scheme

Co-Authored-By: Mihai Alexandru <77043862+majigsaw77@users.noreply.github.com>
This commit is contained in:
KarimAkra
2025-04-15 21:33:50 +03:00
co-authored by Mihai Alexandru
parent 381bc6521c
commit 9657b7eb72
3 changed files with 72 additions and 18 deletions
+61 -9
View File
@@ -12,6 +12,7 @@ import flixel.math.FlxPoint;
import flixel.util.FlxDestroyUtil;
import flixel.util.FlxSignal;
import funkin.mobile.util.SwipeUtil;
import haxe.ds.Map;
/**
* Enum representing the status of the button.
@@ -28,8 +29,15 @@ enum abstract FunkinButtonStatus(Int) from Int to Int
#if !display
@:generic
#end
@:allow(funkin.mobile.ui.FunkinHitbox)
@:allow(funkin.mobile.ui.FunkinButton)
class FunkinButton extends FunkinSprite implements IFlxInput
{
/**
* A map that's storing every active touch's ID that's pressing a button.
*/
public static var buttonsTouchID:Map<Int, FunkinButton> = new Map();
/**
* The current state of the button, either `FunkinButtonStatus.NORMAL` or `FunkinButtonStatus.PRESSED`.
*/
@@ -70,11 +78,21 @@ class FunkinButton extends FunkinSprite implements IFlxInput
*/
public var justPressed(get, never):Bool;
/**
* The touch instance that pressed this button.
*/
public var currentTouch(get, never):Null<FlxTouch>;
/**
* An array of objects that blocks your input.
*/
public var deadZones:Array<FunkinSprite> = [];
/**
* Wether the button should be released if you swiped over somwhere else.
*/
public var limitToBounds:Bool = true;
/**
* The input associated with the button, using `Int` as the type.
*/
@@ -86,6 +104,11 @@ class FunkinButton extends FunkinSprite implements IFlxInput
*/
var currentInput:IFlxInput;
/**
* The ID of the touch object that pressed this button.
*/
var touchID:Int = -1;
/**
* Creates a new `FunkinButton` object.
*
@@ -103,6 +126,7 @@ class FunkinButton extends FunkinSprite implements IFlxInput
ignoreDrawDebug = true;
#end
scrollFactor.set();
input = new FlxInput(0);
}
@@ -115,6 +139,10 @@ class FunkinButton extends FunkinSprite implements IFlxInput
currentInput = null;
input = null;
buttonsTouchID.remove(touchID);
touchID = -1;
super.destroy();
}
@@ -131,14 +159,14 @@ class FunkinButton extends FunkinSprite implements IFlxInput
{
final overlapFound:Bool = checkTouchOverlap();
if (currentInput != null && currentInput.justReleased)
if (currentInput != null && currentInput.justReleased && overlapFound)
{
onUpHandler();
}
if (status != FunkinButtonStatus.NORMAL && !SwipeUtil.swipeAny && (currentInput != null && !currentInput.pressed))
if (!isPressed(overlapFound))
{
onOutHandler();
if (limitToBounds || (!limitToBounds && (currentTouch != null && currentTouch.justReleased))) onOutHandler();
}
}
#end
@@ -146,24 +174,30 @@ class FunkinButton extends FunkinSprite implements IFlxInput
input.update();
}
private function checkTouchOverlap():Bool
private function checkTouchOverlap(?touch:FlxTouch):Bool
{
var touches = touch == null ? FlxG.touches.list : [touch];
for (camera in cameras)
{
for (touch in FlxG.touches.list)
for (touch in touches)
{
final worldPos:FlxPoint = touch.getWorldPosition(camera, _point);
for (zone in deadZones)
{
if (zone != null)
{
if (zone.overlapsPoint(worldPos, true, camera)) return false;
}
if (zone != null && zone.overlapsPoint(worldPos, true, camera)) return false;
}
if (overlapsPoint(worldPos, true, camera))
{
touchID = touch.touchPointID;
var prevButton = buttonsTouchID.get(touchID);
if (prevButton != null && prevButton != this && !prevButton.limitToBounds)
{
prevButton.onOutHandler();
}
buttonsTouchID.set(touchID, this);
updateStatus(touch);
return true;
@@ -174,6 +208,11 @@ class FunkinButton extends FunkinSprite implements IFlxInput
return false;
}
private function isPressed(check:Bool):Bool
{
return !(status != FunkinButtonStatus.NORMAL && (!check || (currentInput != null && currentInput.justReleased)));
}
private function updateStatus(input:IFlxInput):Void
{
if (input.justPressed)
@@ -197,6 +236,10 @@ class FunkinButton extends FunkinSprite implements IFlxInput
input.release();
buttonsTouchID.remove(touchID);
touchID = -1;
currentInput = null;
onUp.dispatch();
@@ -217,6 +260,10 @@ class FunkinButton extends FunkinSprite implements IFlxInput
input.release();
buttonsTouchID.remove(touchID);
touchID = -1;
onOut.dispatch();
}
@@ -239,4 +286,9 @@ class FunkinButton extends FunkinSprite implements IFlxInput
{
return input.justPressed;
}
private inline function get_currentTouch():Null<FlxTouch>
{
return FlxG.touches.getByID(touchID);
}
}
+3 -1
View File
@@ -368,7 +368,9 @@ class FunkinHitbox extends FlxTypedSpriteGroup<FunkinHint>
final x:Float = ((i == 1) ? FlxG.width - (hintSize * 4) : hintSize * 2) + Math.cos(hintsAngles[j]) * hintsZoneRadius;
final y:Float = (FlxG.height - (hintSize * 3.75)) + Math.sin(hintsAngles[j]) * hintsZoneRadius;
add(createHintCircle(x, y, hintsNoteDirections[j % hintsNoteDirections.length], hintSize, hintsColors[j % hintsColors.length]));
final hint:FunkinHint = createHintCircle(x, y, hintsNoteDirections[j % hintsNoteDirections.length], hintSize, hintsColors[j % hintsColors.length]);
hint.limitToBounds = false;
add(hint);
}
}
}
@@ -2,9 +2,9 @@ package funkin.mobile.ui;
import flixel.FlxCamera;
import flixel.FlxG;
import flixel.input.touch.FlxTouch;
import flixel.math.FlxPoint;
import flixel.ui.FlxButton;
import flixel.util.FlxDirectionFlags;
import flixel.input.touch.FlxTouch;
import openfl.display.Graphics;
/**
@@ -74,13 +74,14 @@ class FunkinPolygonButton extends FunkinButton
}
@:noCompletion
private override function checkTouchOverlap():Bool
private override function checkTouchOverlap(?touch:FlxTouch):Bool
{
if (polygon != null && polygon.length >= 6 && polygon.length % 2 == 0)
var touches = touch == null ? FlxG.touches.list : [touch];
for (touch in touches)
{
for (camera in cameras)
if (polygon != null && polygon.length >= 6 && polygon.length % 2 == 0)
{
for (touch in FlxG.touches.list)
for (camera in cameras)
{
final worldPos:FlxPoint = touch.getWorldPosition(camera, _point);
@@ -96,11 +97,10 @@ class FunkinPolygonButton extends FunkinButton
}
}
}
return false;
}
return super.checkTouchOverlap();
return super.checkTouchOverlap(touch);
}
#if FLX_DEBUG