From afcf168416e6ced51e6680189b3f157dd2b75021 Mon Sep 17 00:00:00 2001 From: JordanSantiagoYT Date: Fri, 27 Oct 2023 15:41:29 -0400 Subject: [PATCH] android.. changes --- source/ClientPrefs.hx | 24 + source/Controls.hx | 10 +- source/MusicBeatState.hx | 3 +- source/PauseSubState.hx | 6 +- source/android/AndroidControls.hx | 271 ++-- .../AndroidControlsSettingsSubState.hx | 60 + source/android/AndroidControlsSubState.hx | 527 ++++---- .../android/backend/AndroidDialogsExtend.hx | 32 + source/android/flixel/FlxButton.hx | 1178 +++++++++-------- source/android/flixel/FlxHitbox.hx | 172 +-- source/android/flixel/FlxNewHitbox.hx | 124 ++ source/android/flixel/FlxVirtualPad.hx | 402 +++--- source/import.hx | 3 +- source/options/OptionsState.hx | 33 +- 14 files changed, 1585 insertions(+), 1260 deletions(-) create mode 100644 source/android/AndroidControlsSettingsSubState.hx create mode 100644 source/android/backend/AndroidDialogsExtend.hx create mode 100644 source/android/flixel/FlxNewHitbox.hx diff --git a/source/ClientPrefs.hx b/source/ClientPrefs.hx index 446f806812c..42861704c1e 100644 --- a/source/ClientPrefs.hx +++ b/source/ClientPrefs.hx @@ -14,6 +14,7 @@ class ClientPrefs { //default settings if it can't find a save file containing y public static var showFPS:Bool = true; public static var flashing:Bool = true; public static var globalAntialiasing:Bool = true; + public static var dynamicColors:Bool = true; public static var healthDisplay:Bool = true; public static var ghostTapAnim:Bool = true; public static var spaceVPose:Bool = true; @@ -79,6 +80,11 @@ class ClientPrefs { //default settings if it can't find a save file containing y public static var holdNoteHits:Bool = false; public static var comboScoreEffect:Bool = false; public static var noGunsRNG:Bool = false; + public static var hitboxSelection:String = 'Original'; + public static var hitboxAlpha:Float = 0.5; + public static var virtualPadAlpha:Float = 0.5; + public static var hitboxSpace:Bool = false; + public static var hitboxSpaceLocation:String = 'Bottom'; public static var comboMultiType:String = 'osu!'; public static var noteOffset:Int = 0; public static var arrowHSV:Array> = [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]; @@ -263,7 +269,13 @@ class ClientPrefs { //default settings if it can't find a save file containing y FlxG.save.data.pbRControls = pbRControls; FlxG.save.data.doubleGhost = doubleGhost; FlxG.save.data.bfIconStyle = bfIconStyle; + FlxG.save.data.hitboxSelection = hitboxSelection; + FlxG.save.data.hitboxAlpha = hitboxAlpha; + FlxG.save.data.virtualPadAlpha = virtualPadAlpha; + FlxG.save.data.hitboxSpace = hitboxSpace; + FlxG.save.data.hitboxSpaceLocation = hitboxSpaceLocation; FlxG.save.data.noteStyleThing = noteStyleThing; + FlxG.save.data.dynamicColors = dynamicColors; FlxG.save.data.antiCheatEnable = antiCheatEnable; FlxG.save.data.randomBotplayText = randomBotplayText; FlxG.save.data.showNPS = showNPS; @@ -422,6 +434,18 @@ class ClientPrefs { //default settings if it can't find a save file containing y if(FlxG.save.data.colorQuants != null) { colorQuants = FlxG.save.data.colorQuants; } + if (FlxG.save.data.hitboxSelection != null) { + hitboxSelection = FlxG.save.data.hitboxSelection; + } + if (FlxG.save.data.hitboxAlpha != null) { + hitboxAlpha = FlxG.save.data.hitboxAlpha; + } + if (FlxG.save.data.virtualPadAlpha != null) { + virtualPadAlpha = FlxG.save.data.virtualPadAlpha; + } + if (FlxG.save.data.dynamicColors != null) { + dynamicColors = FlxG.save.data.dynamicColors; + } if(FlxG.save.data.pbRControls != null) { pbRControls = FlxG.save.data.pbRControls; } diff --git a/source/Controls.hx b/source/Controls.hx index 0257d5a365a..78ceb4c8a8e 100644 --- a/source/Controls.hx +++ b/source/Controls.hx @@ -3,6 +3,7 @@ package; #if android import android.flixel.FlxButton; import android.flixel.FlxHitbox; +import android.flixel.FlxNewHitbox; import android.flixel.FlxVirtualPad; #end import flixel.FlxG; @@ -400,11 +401,18 @@ class Controls extends FlxActionSet action.add(input); } - public function setHitBox(Hitbox:FlxHitbox) { + public function setHitBox(Hitbox:FlxHitbox, NewHitbox:FlxNewHitbox) { + if (Hitbox != null) { inline forEachBound(Control.NOTE_UP, (action, state) -> addbuttonNOTES(action, Hitbox.buttonUp, state)); inline forEachBound(Control.NOTE_DOWN, (action, state) -> addbuttonNOTES(action, Hitbox.buttonDown, state)); inline forEachBound(Control.NOTE_LEFT, (action, state) -> addbuttonNOTES(action, Hitbox.buttonLeft, state)); inline forEachBound(Control.NOTE_RIGHT, (action, state) -> addbuttonNOTES(action, Hitbox.buttonRight, state)); + } else if (NewHitbox != null) { + inline forEachBound(Control.NOTE_UP, (action, state) -> addbuttonNOTES(action, NewHitbox.buttonUp, state)); + inline forEachBound(Control.NOTE_DOWN, (action, state) -> addbuttonNOTES(action, NewHitbox.buttonDown, state)); + inline forEachBound(Control.NOTE_LEFT, (action, state) -> addbuttonNOTES(action, NewHitbox.buttonLeft, state)); + inline forEachBound(Control.NOTE_RIGHT, (action, state) -> addbuttonNOTES(action, NewHitbox.buttonRight, state)); + } } public function setVirtualPadUI(VirtualPad:FlxVirtualPad, DPad:FlxDPadMode, Action:FlxActionMode) { diff --git a/source/MusicBeatState.hx b/source/MusicBeatState.hx index 1d20dcb613b..c81deed7c9d 100644 --- a/source/MusicBeatState.hx +++ b/source/MusicBeatState.hx @@ -75,7 +75,8 @@ class MusicBeatState extends FlxUIState case 3: // BOTH_FULL controls.setVirtualPadNOTES(androidControls.virtualPad, BOTH_FULL, NONE); case 4: // HITBOX - controls.setHitBox(androidControls.hitbox); + if (ClientPrefs.hitboxSelection != 'New') controls.setHitBox(androidControls.hitbox, null); + if (ClientPrefs.hitboxSelection == 'New') controls.setHitBox(null, androidControls.newHitbox); case 5: // KEYBOARD } diff --git a/source/PauseSubState.hx b/source/PauseSubState.hx index bc9927e6b16..81f00fc7f5b 100644 --- a/source/PauseSubState.hx +++ b/source/PauseSubState.hx @@ -22,7 +22,7 @@ class PauseSubState extends MusicBeatSubstate var grpMenuShit:FlxTypedGroup; var menuItems:Array = []; - var menuItemsOG:Array = ['Resume', 'Restart Song', 'Change Gameplay Settings', 'Change Difficulty', 'Options', 'Exit']; + var menuItemsOG:Array = ['Resume', 'Restart Song', 'Change Gameplay Settings', 'Change Difficulty', #if android 'Chart Editor', #end 'Options', 'Exit']; var menuItemsExit:Array = [(PlayState.isStoryMode ? 'Exit to Story Menu' : 'Exit to Freeplay'), 'Exit to Main Menu', 'Exit Game', 'Back']; var difficultyChoices = []; var curSelected:Int = 0; @@ -291,6 +291,10 @@ class PauseSubState extends MusicBeatSubstate case "End Song": close(); PlayState.instance.finishSong(true); + case 'Chart Editor': + MusicBeatState.switchState(new editors.ChartingState()); + MusicBeatState.windowNameSuffix = " - Chart Editor"; + PlayState.chartingMode = true; case "Change Gameplay Settings": persistentUpdate = false; openSubState(new GameplayChangersSubstate()); diff --git a/source/android/AndroidControls.hx b/source/android/AndroidControls.hx index d28f9b1bf2c..398e03c16ef 100644 --- a/source/android/AndroidControls.hx +++ b/source/android/AndroidControls.hx @@ -1,145 +1,126 @@ -package android; - -import android.flixel.FlxHitbox; -import android.flixel.FlxVirtualPad; -import flixel.FlxG; -import flixel.group.FlxSpriteGroup; -import flixel.math.FlxPoint; -import flixel.util.FlxDestroyUtil; - -class AndroidControls extends FlxSpriteGroup -{ - public var virtualPad:FlxVirtualPad; - public var hitbox:FlxHitbox; - - public function new() - { - super(); - - switch (AndroidControls.getMode()) - { - case 0: // RIGHT_FULL - initControler(0); - case 1: // LEFT_FULL - initControler(1); - case 2: // CUSTOM - initControler(2); - case 3: // BOTH_FULL - initControler(3); - case 4: // HITBOX - initControler(4); - case 5: // KEYBOARD - } - } - - private function initControler(virtualPadMode:Int = 0):Void - { - switch (virtualPadMode) - { - case 0: - virtualPad = new FlxVirtualPad(RIGHT_FULL, NONE); - add(virtualPad); - case 1: - virtualPad = new FlxVirtualPad(LEFT_FULL, NONE); - add(virtualPad); - case 2: - virtualPad = AndroidControls.getCustomMode(new FlxVirtualPad(RIGHT_FULL, NONE)); - add(virtualPad); - case 3: - virtualPad = new FlxVirtualPad(BOTH_FULL, NONE); - add(virtualPad); - case 4: - hitbox = new FlxHitbox(); - add(hitbox); - } - } - - override public function destroy():Void - { - super.destroy(); - - if (virtualPad != null) - { - virtualPad = FlxDestroyUtil.destroy(virtualPad); - virtualPad = null; - } - - if (hitbox != null) - { - hitbox = FlxDestroyUtil.destroy(hitbox); - hitbox = null; - } - } - - public static function setOpacity(opacity:Float = 0.6):Void - { - FlxG.save.data.androidControlsOpacity = opacity; - FlxG.save.flush(); - } - - public static function getOpacity():Float - { - if (FlxG.save.data.androidControlsOpacity == null) - { - FlxG.save.data.androidControlsOpacity = 0.6; - FlxG.save.flush(); - } - - return FlxG.save.data.androidControlsOpacity; - } - - public static function setMode(mode:Int = 0):Void - { - FlxG.save.data.androidControlsMode = mode; - FlxG.save.flush(); - } - - public static function getMode():Int - { - if (FlxG.save.data.androidControlsMode == null) - { - FlxG.save.data.androidControlsMode = 0; - FlxG.save.flush(); - } - - return FlxG.save.data.androidControlsMode; - } - - public static function setCustomMode(virtualPad:FlxVirtualPad):Void - { - if (FlxG.save.data.buttons == null) - { - FlxG.save.data.buttons = new Array(); - for (buttons in virtualPad) - FlxG.save.data.buttons.push(FlxPoint.get(buttons.x, buttons.y)); - } - else - { - var tempCount:Int = 0; - for (buttons in virtualPad) - { - FlxG.save.data.buttons[tempCount] = FlxPoint.get(buttons.x, buttons.y); - tempCount++; - } - } - - FlxG.save.flush(); - } - - public static function getCustomMode(virtualPad:FlxVirtualPad):FlxVirtualPad - { - var tempCount:Int = 0; - - if (FlxG.save.data.buttons == null) - return virtualPad; - - for (buttons in virtualPad) - { - buttons.x = FlxG.save.data.buttons[tempCount].x; - buttons.y = FlxG.save.data.buttons[tempCount].y; - tempCount++; - } - - return virtualPad; - } -} \ No newline at end of file +package android; + +import android.flixel.FlxNewHitbox; +import android.flixel.FlxHitbox; +import android.flixel.FlxVirtualPad; +import flixel.util.FlxDestroyUtil; +import flixel.FlxG; +import flixel.math.FlxPoint; + + + + +class AndroidControls extends FlxSpriteGroup { + public var virtualPad:FlxVirtualPad; + public var hitbox:FlxHitbox; + public var newHitbox:FlxNewHitbox; + + public function new() { + super(); + + switch (AndroidControls.getMode()) { + case 0: // RIGHT_FULL + initControler(0); + case 1: // LEFT_FULL + initControler(1); + case 2: // CUSTOM + initControler(2); + case 3: // BOTH_FULL + initControler(3); + case 4: // HITBOX + if (ClientPrefs.hitboxSelection != 'New') { + initControler(5); + } else { + initControler(4); + } + case 5: // KEYBOARD + } + } + + private function initControler(virtualPadMode:Int = 0):Void { + switch (virtualPadMode) { + case 0: + virtualPad = new FlxVirtualPad(RIGHT_FULL, NONE); + add(virtualPad); + case 1: + virtualPad = new FlxVirtualPad(LEFT_FULL, NONE); + add(virtualPad); + case 2: + virtualPad = AndroidControls.getCustomMode(new FlxVirtualPad(RIGHT_FULL, NONE)); + add(virtualPad); + case 3: + virtualPad = new FlxVirtualPad(BOTH_FULL, NONE); + add(virtualPad); + case 4: + newHitbox = new FlxNewHitbox(); + add(newHitbox); + case 5: + hitbox = new FlxHitbox(); + add(hitbox); + } + } + + override public function destroy():Void { + super.destroy(); + + if (virtualPad != null) { + virtualPad = FlxDestroyUtil.destroy(virtualPad); + virtualPad = null; + } + + if (newHitbox != null) { + newHitbox = FlxDestroyUtil.destroy(newHitbox); + newHitbox = null; + } + + if (hitbox != null) { + hitbox = FlxDestroyUtil.destroy(hitbox); + hitbox = null; + } + } + + public static function setMode(mode:Int = 0):Void { + FlxG.save.data.androidControlsMode = mode; + FlxG.save.flush(); + } + + public static function getMode():Int { + if (FlxG.save.data.androidControlsMode == null) { + FlxG.save.data.androidControlsMode = 0; + FlxG.save.flush(); + } + + return FlxG.save.data.androidControlsMode; + } + + public static function setCustomMode(virtualPad:FlxVirtualPad):Void { + if (FlxG.save.data.buttons == null) { + FlxG.save.data.buttons = new Array(); + for (buttons in virtualPad) + FlxG.save.data.buttons.push(FlxPoint.get(buttons.x, buttons.y)); + } else { + var tempCount:Int = 0; + for (buttons in virtualPad) { + FlxG.save.data.buttons[tempCount] = FlxPoint.get(buttons.x, buttons.y); + tempCount++; + } + } + + FlxG.save.flush(); + } + + public static function getCustomMode(virtualPad:FlxVirtualPad):FlxVirtualPad { + var tempCount:Int = 0; + + if (FlxG.save.data.buttons == null) + return virtualPad; + + for (buttons in virtualPad) { + buttons.x = FlxG.save.data.buttons[tempCount].x; + buttons.y = FlxG.save.data.buttons[tempCount].y; + tempCount++; + } + + return virtualPad; + } +} diff --git a/source/android/AndroidControlsSettingsSubState.hx b/source/android/AndroidControlsSettingsSubState.hx new file mode 100644 index 00000000000..b4d37de8d3f --- /dev/null +++ b/source/android/AndroidControlsSettingsSubState.hx @@ -0,0 +1,60 @@ +package android; + +import flixel.addons.transition.FlxTransitionableState; +import lime.utils.Assets; +import flixel.util.FlxSave; +import haxe.Json; +import options.BaseOptionsMenu; +import options.Option; +import openfl.Lib; + +using StringTools; + +class AndroidControlsSettingsSubState extends BaseOptionsMenu { + public function new() { + title = 'Android settings for virtual pads and hitbox'; + rpcTitle = 'Virtual pads and hitbox Menu'; + + var option:Option = new Option('Hitbox Opacity:', 'Change hitbox opacity\nNote: (Using to much opacity its gonna be so weird on gameplay!)', + 'hitboxAlpha', 'float', 0.2); // Credits: MarioMaster (Created hitbox opacity) + option.scrollSpeed = 1.6; + option.minValue = 0.0; + option.maxValue = 1; + option.changeValue = 0.1; + option.decimals = 1; + addOption(option); + + var option:Option = new Option('Virtual pad Opacity:', 'Changes virtual pad opacity', 'virtualPadAlpha', 'float', + 0.5); // Credits: MarioMaster (Created hitbox opacity) + option.scrollSpeed = 1.6; + option.minValue = 0.1; + option.maxValue = 1; + option.changeValue = 0.01; + option.decimals = 2; + addOption(option); + + var option:Option = new Option('Space Extend', + "Allow Extend Space Control. --Made by NF | Beihu", // Credits: NF | Beihu (Created hitbox space) + 'hitboxSpace', + 'bool', + false); + addOption(option); + + var option:Option = new Option('Space Location:', + "Choose Space Control Location. --Made by NF | Beihu", // Credits: NF | Beihu (Created hitbox space) + 'hitboxSpaceLocation', + 'string', + 'Bottom', + ['Bottom', 'Middle', 'Top']); + addOption(option); + + var option:Option = new Option('Dynamic Colors', + "If unchecked, disables colors from note. Made by mcgabe19", // Credits: mcgabe19 (Created dynamic colours for notes on Psych Engine 0.7.1h Android port) + 'dynamicColors', + 'bool', + true); + addOption(option); + + super(); + } +} diff --git a/source/android/AndroidControlsSubState.hx b/source/android/AndroidControlsSubState.hx index 06fc304b47b..23a8b4b92f6 100644 --- a/source/android/AndroidControlsSubState.hx +++ b/source/android/AndroidControlsSubState.hx @@ -1,247 +1,280 @@ -package android; - -import android.flixel.FlxButton; -import android.flixel.FlxHitbox; -import android.flixel.FlxVirtualPad; -import flixel.FlxG; -import flixel.FlxSprite; -import flixel.FlxSubState; -import flixel.addons.transition.FlxTransitionableState; -import flixel.graphics.frames.FlxAtlasFrames; -import flixel.group.FlxSpriteGroup; -import flixel.util.FlxSave; -import flixel.util.FlxColor; -import flixel.input.touch.FlxTouch; -import flixel.text.FlxText; -import flixel.tweens.FlxEase; -import flixel.tweens.FlxTween; -import openfl.utils.Assets; - -class AndroidControlsSubState extends FlxSubState { - final controlsItems:Array = ['Pad-Right', 'Pad-Left', 'Pad-Custom', 'Pad-Duo', 'Hitbox', 'Keyboard']; - var virtualPad:FlxVirtualPad; - var hitbox:FlxHitbox; - var upPosition:FlxText; - var downPosition:FlxText; - var leftPosition:FlxText; - var rightPosition:FlxText; - var inputText:FlxText; - var noAndroidControlsText:FlxText; - var tipText:FlxText; - var leftArrow:FlxSprite; - var rightArrow:FlxSprite; - var currentlySelected:Int = AndroidControls.getMode(); - var buttonBinded:Bool = false; - var bindButton:FlxButton; - var resetButton:FlxButton; - var background:FlxSprite; - - override function create() { - background = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.fromHSB(FlxG.random.int(0, 359), FlxG.random.float(0, 0.8), FlxG.random.float(0.3, 1))); - background.alpha = 0.00001; - background.scrollFactor.set(); - add(background); - - resetButton = new FlxButton(FlxG.width - 200, 50, 'Reset', function() { - if (resetButton.visible) { - virtualPad.buttonUp.x = FlxG.width - 258; - virtualPad.buttonUp.y = FlxG.height - 408; - virtualPad.buttonDown.x = FlxG.width - 258; - virtualPad.buttonDown.y = FlxG.height - 201; - virtualPad.buttonRight.x = FlxG.width - 132; - virtualPad.buttonRight.y = FlxG.height - 309; - virtualPad.buttonLeft.x = FlxG.width - 384; - virtualPad.buttonLeft.y = FlxG.height - 309; - } - }); - resetButton.setGraphicSize(Std.int(resetButton.width) * 3); - resetButton.label.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, CENTER); - resetButton.color = FlxColor.RED; - resetButton.visible = false; - add(resetButton); - - virtualPad = new FlxVirtualPad(NONE, NONE); - virtualPad.visible = false; - add(virtualPad); - - hitbox = new FlxHitbox(); - hitbox.visible = false; - add(hitbox); - - noAndroidControlsText = new FlxText(0, 50, 0, 'You dont have any Android Controls!', 32); - noAndroidControlsText.setFormat('VCR OSD Mono', 32, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); - noAndroidControlsText.borderSize = 2.4; - noAndroidControlsText.screenCenter(); - noAndroidControlsText.visible = false; - add(noAndroidControlsText); - - inputText = new FlxText(0, 100, 0, '', 32); - inputText.setFormat('VCR OSD Mono', 32, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); - inputText.borderSize = 2.4; - inputText.screenCenter(X); - add(inputText); - - leftArrow = new FlxSprite(inputText.x - 60, inputText.y - 25); - leftArrow.frames = FlxAtlasFrames.fromSparrow(Assets.getBitmapData('assets/android/menu/arrows.png'), - Assets.getText('assets/android/menu/arrows.xml')); - leftArrow.animation.addByPrefix('idle', 'arrow left'); - leftArrow.animation.play('idle'); - add(leftArrow); - - rightArrow = new FlxSprite(inputText.x + inputText.width + 10, inputText.y - 25); - rightArrow.frames = FlxAtlasFrames.fromSparrow(Assets.getBitmapData('assets/android/menu/arrows.png'), - Assets.getText('assets/android/menu/arrows.xml')); - rightArrow.animation.addByPrefix('idle', 'arrow right'); - rightArrow.animation.play('idle'); - add(rightArrow); - - tipText = new FlxText(10, FlxG.height - 24, 0, 'Press BACK on your phone to get back to the options menu', 16); - tipText.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); - tipText.borderSize = 1.25; - tipText.scrollFactor.set(); - add(tipText); - - rightPosition = new FlxText(10, FlxG.height - 44, 0, '', 16); - rightPosition.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); - rightPosition.borderSize = 2.4; - add(rightPosition); - - leftPosition = new FlxText(10, FlxG.height - 64, 0, '', 16); - leftPosition.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); - leftPosition.borderSize = 2.4; - add(leftPosition); - - downPosition = new FlxText(10, FlxG.height - 84, 0, '', 16); - downPosition.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); - downPosition.borderSize = 2.4; - add(downPosition); - - upPosition = new FlxText(10, FlxG.height - 104, 0, '', 16); - upPosition.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); - upPosition.borderSize = 2.4; - add(upPosition); - - changeSelection(); - - super.create(); - - FlxTween.tween(background, {alpha: 0.6}, 1, {ease: FlxEase.circInOut}); - } - - override function update(elapsed:Float) { - if (FlxG.android.justPressed.BACK || FlxG.android.justReleased.BACK) { - AndroidControls.setMode(currentlySelected); - - if (controlsItems[Math.floor(currentlySelected)] == 'Pad-Custom') - AndroidControls.setCustomMode(virtualPad); - - FlxTransitionableState.skipNextTransOut = true; - FlxG.resetState(); - } - - super.update(elapsed); - - inputText.screenCenter(X); - leftArrow.x = inputText.x - 60; - rightArrow.x = inputText.x + inputText.width + 10; - - for (touch in FlxG.touches.list) { - if (touch.overlaps(leftArrow) && touch.justPressed) - changeSelection(-1); - else if (touch.overlaps(rightArrow) && touch.justPressed) - changeSelection(1); - - if (controlsItems[Math.floor(currentlySelected)] == 'Pad-Custom') { - if (buttonBinded) { - if (touch.justReleased) { - bindButton = null; - buttonBinded = false; - } else - moveButton(touch, bindButton); - } else { - if (virtualPad.buttonUp.justPressed) - moveButton(touch, virtualPad.buttonUp); - - if (virtualPad.buttonDown.justPressed) - moveButton(touch, virtualPad.buttonDown); - - if (virtualPad.buttonRight.justPressed) - moveButton(touch, virtualPad.buttonRight); - - if (virtualPad.buttonLeft.justPressed) - moveButton(touch, virtualPad.buttonLeft); - } - } - } - - if (virtualPad != null) { - if (virtualPad.buttonUp != null) - upPosition.text = 'Button Up X:' + virtualPad.buttonUp.x + ' Y:' + virtualPad.buttonUp.y; - - if (virtualPad.buttonDown != null) - downPosition.text = 'Button Down X:' + virtualPad.buttonDown.x + ' Y:' + virtualPad.buttonDown.y; - - if (virtualPad.buttonLeft != null) - leftPosition.text = 'Button Left X:' + virtualPad.buttonLeft.x + ' Y:' + virtualPad.buttonLeft.y; - - if (virtualPad.buttonRight != null) - rightPosition.text = 'Button Right x:' + virtualPad.buttonRight.x + ' Y:' + virtualPad.buttonRight.y; - } - } - - function changeSelection(change:Int = 0):Void { - currentlySelected += change; - - if (currentlySelected < 0) - currentlySelected = controlsItems.length - 1; - if (currentlySelected >= controlsItems.length) - currentlySelected = 0; - - inputText.text = controlsItems[currentlySelected]; - - var daChoice:String = controlsItems[Math.floor(currentlySelected)]; - - switch (daChoice) { - case 'Pad-Right': - hitbox.visible = false; - virtualPad.destroy(); - virtualPad = new FlxVirtualPad(RIGHT_FULL, NONE); - add(virtualPad); - case 'Pad-Left': - hitbox.visible = false; - virtualPad.destroy(); - virtualPad = new FlxVirtualPad(LEFT_FULL, NONE); - add(virtualPad); - case 'Pad-Custom': - hitbox.visible = false; - virtualPad.destroy(); - virtualPad = AndroidControls.getCustomMode(new FlxVirtualPad(RIGHT_FULL, NONE)); - add(virtualPad); - case 'Pad-Duo': - hitbox.visible = false; - virtualPad.destroy(); - virtualPad = new FlxVirtualPad(BOTH_FULL, NONE); - add(virtualPad); - case 'Hitbox': - hitbox.visible = true; - virtualPad.visible = false; - case 'Keyboard': - hitbox.visible = false; - virtualPad.visible = false; - } - - noAndroidControlsText.visible = daChoice == 'Keyboard'; - resetButton.visible = daChoice == 'Pad-Custom'; - upPosition.visible = daChoice == 'Pad-Custom'; - downPosition.visible = daChoice == 'Pad-Custom'; - leftPosition.visible = daChoice == 'Pad-Custom'; - rightPosition.visible = daChoice == 'Pad-Custom'; - } - - function moveButton(touch:FlxTouch, button:FlxButton):Void { - bindButton = button; - bindButton.x = touch.x - Std.int(bindButton.width / 2); - bindButton.y = touch.y - Std.int(bindButton.height / 2); - buttonBinded = true; - } -} \ No newline at end of file +package android; + +import android.flixel.FlxButton; +import android.flixel.FlxHitbox; +import android.flixel.FlxNewHitbox; +import android.flixel.FlxVirtualPad; +import flixel.FlxSubState; +import flixel.math.FlxPoint; +import flixel.text.FlxText; +import flixel.FlxSprite; +import flixel.addons.display.FlxBackdrop; +import flixel.FlxG; +import flixel.util.FlxColor; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.tweens.FlxTween; +import flixel.addons.display.FlxGridOverlay; +import flixel.tweens.FlxEase; + + +import flixel.addons.transition.FlxTransitionableState; + + +import flixel.util.FlxSave; + +import flixel.input.touch.FlxTouch; + + + +import openfl.utils.Assets; + + +class AndroidControlsSubState extends FlxSubState { + final controlsItems:Array = ['Pad-Right', 'Pad-Left', 'Pad-Custom', 'Pad-Duo', 'Hitbox', 'Keyboard']; + var virtualPad:FlxVirtualPad; + var hitbox:FlxHitbox; + var newHitbox:FlxNewHitbox; + var upPosition:FlxText; + var downPosition:FlxText; + var leftPosition:FlxText; + var rightPosition:FlxText; + var inputText:FlxText; + var noAndroidControlsText:FlxText; + var tipText:FlxText; + var leftArrow:FlxSprite; + var rightArrow:FlxSprite; + var currentlySelected:Int = AndroidControls.getMode(); + var buttonBinded:Bool = false; + var bindButton:FlxButton; + var resetButton:FlxButton; + var background:FlxSprite; + var velocityBackground:FlxBackdrop; + + override function create() { + background = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.fromHSB(FlxG.random.int(0, 359), FlxG.random.float(0, 0.8), FlxG.random.float(0.3, 1))); + background.alpha = 0.00001; + background.scrollFactor.set(); + add(background); + + velocityBackground = new FlxBackdrop(FlxGridOverlay.createGrid(30, 30, 60, 60, true, 0x3B161932, 0x0), XY); + velocityBackground.velocity.set(FlxG.random.bool(50) ? 90 : -90, FlxG.random.bool(50) ? 90 : -90); + velocityBackground.visible = true; + velocityBackground.alpha = 0; + add(velocityBackground); + + resetButton = new FlxButton(FlxG.width - 200, 50, 'Reset', function() { + if (resetButton.visible) { + virtualPad.buttonUp.x = FlxG.width - 258; + virtualPad.buttonUp.y = FlxG.height - 408; + virtualPad.buttonDown.x = FlxG.width - 258; + virtualPad.buttonDown.y = FlxG.height - 201; + virtualPad.buttonRight.x = FlxG.width - 132; + virtualPad.buttonRight.y = FlxG.height - 309; + virtualPad.buttonLeft.x = FlxG.width - 384; + virtualPad.buttonLeft.y = FlxG.height - 309; + } + }); + resetButton.label.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, CENTER); + + resetButton.setGraphicSize(Std.int(resetButton.width) * 3); + resetButton.color = FlxColor.RED; + resetButton.visible = false; + add(resetButton); + + virtualPad = new FlxVirtualPad(NONE, NONE); + virtualPad.visible = false; + add(virtualPad); + + newHitbox = new FlxNewHitbox(); + newHitbox.visible = false; + add(newHitbox); + + hitbox = new FlxHitbox(); + hitbox.visible = false; + add(hitbox); + + noAndroidControlsText = new FlxText(0, 50, 0, 'You dont have any Android Controls!', 32); + inputText = new FlxText(0, 100, 0, '', 32); + noAndroidControlsText.setFormat('VCR OSD Mono', 32, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + inputText.setFormat('VCR OSD Mono', 32, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + + noAndroidControlsText.borderSize = 2.4; + noAndroidControlsText.screenCenter(); + noAndroidControlsText.visible = false; + inputText.borderSize = 2.4; + inputText.screenCenter(X); + add(noAndroidControlsText); + add(inputText); + + leftArrow = new FlxSprite(inputText.x - 60, inputText.y - 25); + leftArrow.frames = FlxAtlasFrames.fromSparrow(Assets.getBitmapData('assets/android/menu/arrows.png'), + Assets.getText('assets/android/menu/arrows.xml')); + leftArrow.animation.addByPrefix('idle', 'arrow left'); + leftArrow.animation.play('idle'); + add(leftArrow); + + rightArrow = new FlxSprite(inputText.x + inputText.width + 10, inputText.y - 25); + rightArrow.frames = FlxAtlasFrames.fromSparrow(Assets.getBitmapData('assets/android/menu/arrows.png'), + Assets.getText('assets/android/menu/arrows.xml')); + rightArrow.animation.addByPrefix('idle', 'arrow right'); + rightArrow.animation.play('idle'); + add(rightArrow); + + tipText = new FlxText(10, FlxG.height - 24, 0, 'Press BACK on your phone to get back to the options menu', 16); + leftPosition = new FlxText(10, FlxG.height - 64, 0, '', 16); + rightPosition = new FlxText(10, FlxG.height - 44, 0, '', 16); + downPosition = new FlxText(10, FlxG.height - 84, 0, '', 16); + upPosition = new FlxText(10, FlxG.height - 104, 0, '', 16); + tipText.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + rightPosition.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + leftPosition.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + downPosition.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + upPosition.setFormat('VCR OSD Mono', 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + + tipText.scrollFactor.set(); + rightPosition.borderSize = 2.4; + leftPosition.borderSize = 2.4; + downPosition.borderSize = 2.4; + upPosition.borderSize = 2.4; + + add(tipText); + add(rightPosition); + add(leftPosition); + add(downPosition); + add(upPosition); + + changeSelection(); + + super.create(); + + FlxTween.tween(background, {alpha: 0.6}, 1, {ease: FlxEase.circInOut}); + FlxTween.tween(velocityBackground, {alpha: 1}, 0.5, {ease: FlxEase.quadOut}); + } + + override function update(elapsed:Float) { + if (FlxG.android.justPressed.BACK || FlxG.android.justReleased.BACK) { + AndroidControls.setMode(currentlySelected); + + if (controlsItems[Math.floor(currentlySelected)] == 'Pad-Custom') + AndroidControls.setCustomMode(virtualPad); + + FlxTransitionableState.skipNextTransOut = true; + FlxG.resetState(); + } + + super.update(elapsed); + + inputText.screenCenter(X); + leftArrow.x = inputText.x - 60; + rightArrow.x = inputText.x + inputText.width + 10; + + for (touch in FlxG.touches.list) { + if (touch.overlaps(leftArrow) && touch.justPressed) + changeSelection(-1); + else if (touch.overlaps(rightArrow) && touch.justPressed) + changeSelection(1); + + if (controlsItems[Math.floor(currentlySelected)] == 'Pad-Custom') { + if (buttonBinded) { + if (touch.justReleased) { + bindButton = null; + buttonBinded = false; + } else + moveButton(touch, bindButton); + } else { + if (virtualPad.buttonUp.justPressed) + moveButton(touch, virtualPad.buttonUp); + + if (virtualPad.buttonDown.justPressed) + moveButton(touch, virtualPad.buttonDown); + + if (virtualPad.buttonRight.justPressed) + moveButton(touch, virtualPad.buttonRight); + + if (virtualPad.buttonLeft.justPressed) + moveButton(touch, virtualPad.buttonLeft); + } + } + } + + if (virtualPad != null) { + if (virtualPad.buttonUp != null) + upPosition.text = 'Button Up X:' + virtualPad.buttonUp.x + ' Y:' + virtualPad.buttonUp.y; + + if (virtualPad.buttonDown != null) + downPosition.text = 'Button Down X:' + virtualPad.buttonDown.x + ' Y:' + virtualPad.buttonDown.y; + + if (virtualPad.buttonLeft != null) + leftPosition.text = 'Button Left X:' + virtualPad.buttonLeft.x + ' Y:' + virtualPad.buttonLeft.y; + + if (virtualPad.buttonRight != null) + rightPosition.text = 'Button Right x:' + virtualPad.buttonRight.x + ' Y:' + virtualPad.buttonRight.y; + } + } + + function changeSelection(change:Int = 0):Void { + currentlySelected += change; + + if (currentlySelected < 0) + currentlySelected = controlsItems.length - 1; + if (currentlySelected >= controlsItems.length) + currentlySelected = 0; + + inputText.text = controlsItems[currentlySelected]; + + var daChoice:String = controlsItems[Math.floor(currentlySelected)]; + + switch (daChoice) { + case 'Pad-Right': + hitbox.visible = false; + virtualPad.destroy(); + virtualPad = new FlxVirtualPad(RIGHT_FULL, NONE); + add(virtualPad); + case 'Pad-Left': + hitbox.visible = false; + virtualPad.destroy(); + virtualPad = new FlxVirtualPad(LEFT_FULL, NONE); + add(virtualPad); + case 'Pad-Custom': + hitbox.visible = false; + virtualPad.destroy(); + virtualPad = AndroidControls.getCustomMode(new FlxVirtualPad(RIGHT_FULL, NONE)); + add(virtualPad); + case 'Pad-Duo': + hitbox.visible = false; + virtualPad.destroy(); + virtualPad = new FlxVirtualPad(BOTH_FULL, NONE); + add(virtualPad); + case 'Hitbox': + virtualPad.visible = false; + case 'Keyboard': + hitbox.visible = false; + virtualPad.visible = false; + } + + if (daChoice != "Hitbox") { + hitbox.visible = false; + newHitbox.visible = false; + } else { + if (ClientPrefs.hitboxSelection != 'New') { + hitbox.visible = true; + } else { + newHitbox.visible = true; + } + } + + noAndroidControlsText.visible = daChoice == 'Keyboard'; + resetButton.visible = daChoice == 'Pad-Custom'; + upPosition.visible = daChoice == 'Pad-Custom'; + downPosition.visible = daChoice == 'Pad-Custom'; + leftPosition.visible = daChoice == 'Pad-Custom'; + rightPosition.visible = daChoice == 'Pad-Custom'; + } + + function moveButton(touch:FlxTouch, button:FlxButton):Void { + bindButton = button; + bindButton.x = touch.x - Std.int(bindButton.width / 2); + bindButton.y = touch.y - Std.int(bindButton.height / 2); + buttonBinded = true; + } +} diff --git a/source/android/backend/AndroidDialogsExtend.hx b/source/android/backend/AndroidDialogsExtend.hx new file mode 100644 index 00000000000..4d5f4b5ffa5 --- /dev/null +++ b/source/android/backend/AndroidDialogsExtend.hx @@ -0,0 +1,32 @@ +package android.backend; + +//https://github.com/beihu235/AndroidDialogs + +import extension.androiddialogs.AndroidDialogs; + +class AndroidDialogsExtend { + + public static function OpenToast(showtext:String, time:Int) + { + if (time != 1 && time != 2) time = 1; + + AndroidDialogs.ShowToast(showtext, time); + } + + public static function OpenAlert(Title:String, Message:String, ConfirmName:String, CancelName:String) + { + AndroidDialogs.ShowAlertDialog(Title, Message, ConfirmName, CancelName); + } + + public static function OpenAlertSelect(Title:String, choose1:String, choose2:String, choose3:String, choose4:String, choose5:String) + { + var names_players:Array = new Array(); + names_players.push(choose1); + if (choose2 != null) names_players.push(choose2); + if (choose3 != null) names_players.push(choose3); + if (choose4 != null) names_players.push(choose4); + if (choose5 != null) names_players.push(choose5); + AndroidDialogs.ShowAlertSelectOption(Title, names_players); + } +} + diff --git a/source/android/flixel/FlxButton.hx b/source/android/flixel/FlxButton.hx index 30a60bb64db..e5ef7a32d97 100644 --- a/source/android/flixel/FlxButton.hx +++ b/source/android/flixel/FlxButton.hx @@ -1,587 +1,593 @@ -package android.flixel; - -import flixel.FlxG; -import flixel.FlxCamera; -import flixel.FlxSprite; -import flixel.graphics.atlas.FlxAtlas; -import flixel.graphics.atlas.FlxNode; -import flixel.graphics.frames.FlxTileFrames; -import flixel.input.FlxInput; -import flixel.input.FlxPointer; -import flixel.input.IFlxInput; -import flixel.math.FlxPoint; -import flixel.system.FlxSound; -import flixel.text.FlxText; -import flixel.util.FlxDestroyUtil; -import flixel.input.touch.FlxTouch; - -/** - * A simple button class that calls a function when clicked by the touch. - */ -class FlxButton extends FlxTypedButton -{ - /** - * Used with public variable status, means not highlighted or pressed. - */ - public static inline var NORMAL:Int = 0; - - /** - * Used with public variable status, means highlighted (usually from touch over). - */ - public static inline var HIGHLIGHT:Int = 1; - - /** - * Used with public variable status, means pressed (usually from touch click). - */ - public static inline var PRESSED:Int = 2; - - /** - * Shortcut to setting label.text - */ - public var text(get, set):String; - - /** - * Creates a new `FlxButton` object with a gray background - * and a callback function on the UI thread. - * - * @param X The x position of the button. - * @param Y The y position of the button. - * @param Text The text that you want to appear on the button. - * @param OnClick The function to call whenever the button is clicked. - */ - public function new(X:Float = 0, Y:Float = 0, ?Text:String, ?OnClick:Void->Void) - { - super(X, Y, OnClick); - - for (point in labelOffsets) - point.set(point.x - 1, point.y + 3); - - initLabel(Text); - } - - /** - * Updates the size of the text field to match the button. - */ - override function resetHelpers():Void - { - super.resetHelpers(); - - if (label != null) - { - label.fieldWidth = label.frameWidth = Std.int(width); - label.size = label.size; // Calls set_size(), don't remove! - } - } - - inline function initLabel(Text:String):Void - { - if (Text != null) - { - label = new FlxText(x + labelOffsets[NORMAL].x, y + labelOffsets[NORMAL].y, 80, Text); - label.setFormat(null, 8, 0x333333, 'center'); - label.alpha = labelAlphas[status]; - label.drawFrame(true); - } - } - - inline function get_text():String - { - return (label != null) ? label.text : null; - } - - inline function set_text(Text:String):String - { - if (label == null) - initLabel(Text); - else - label.text = Text; - return Text; - } -} - -/** - * A simple button class that calls a function when clicked by the touch. - */ -#if !display -@:generic -#end -class FlxTypedButton extends FlxSprite implements IFlxInput -{ - /** - * The label that appears on the button. Can be any `FlxSprite`. - */ - public var label(default, set):T; - - /** - * What offsets the `label` should have for each status. - */ - public var labelOffsets:Array = [FlxPoint.get(), FlxPoint.get(), FlxPoint.get(0, 1)]; - - /** - * 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 = [0.8, 1.0, 0.5]; - - /** - * What animation should be played for each status. - * Default is ['normal', 'highlight', 'pressed']. - */ - public var statusAnimations:Array = ['normal', 'highlight', 'pressed']; - - /** - * Whether you can press the button simply by releasing the touch button over it (default). - * If false, the input has to be pressed while hovering over the button. - */ - public var allowSwiping:Bool = true; - - /** - * Maximum distance a pointer can move to still trigger event handlers. - * If it moves beyond this limit, onOut is triggered. - * Defaults to `Math.POSITIVE_INFINITY` (i.e. no limit). - */ - public var maxInputMovement:Float = Math.POSITIVE_INFINITY; - - /** - * Shows the current state of the button, either `FlxButton.NORMAL`, - * `FlxButton.HIGHLIGHT` or `FlxButton.PRESSED`. - */ - public var status(default, set):Int; - - /** - * The properties of this button's `onUp` event (callback function, sound). - */ - public var onUp(default, null):FlxButtonEvent; - - /** - * The properties of this button's `onDown` event (callback function, sound). - */ - public var onDown(default, null):FlxButtonEvent; - - /** - * The properties of this button's `onOver` event (callback function, sound). - */ - public var onOver(default, null):FlxButtonEvent; - - /** - * The properties of this button's `onOut` event (callback function, sound). - */ - public var onOut(default, null):FlxButtonEvent; - - public var justReleased(get, never):Bool; - public var released(get, never):Bool; - public var pressed(get, never):Bool; - public var justPressed(get, never):Bool; - - /** - * We cast label to a `FlxSprite` for internal operations to avoid Dynamic casts in C++ - */ - var _spriteLabel:FlxSprite; - - /** - * We don't need an ID here, so let's just use `Int` as the type. - */ - var input:FlxInput; - - /** - * The input currently pressing this button, if none, it's `null`. Needed to check for its release. - */ - var currentInput:IFlxInput; - - var lastStatus = -1; - - /** - * Creates a new `FlxTypedButton` object with a gray background. - * - * @param X The x position of the button. - * @param Y The y position of the button. - * @param OnClick The function to call whenever the button is clicked. - */ - public function new(X:Float = 0, Y:Float = 0, ?OnClick:Void->Void) - { - super(X, Y); - - loadDefaultGraphic(); - - onUp = new FlxButtonEvent(OnClick); - onDown = new FlxButtonEvent(); - onOver = new FlxButtonEvent(); - onOut = new FlxButtonEvent(); - - status = FlxButton.NORMAL; - - // Since this is a UI element, the default scrollFactor is (0, 0) - scrollFactor.set(); - - statusAnimations[FlxButton.HIGHLIGHT] = 'normal'; - labelAlphas[FlxButton.HIGHLIGHT] = 1; - - input = new FlxInput(0); - } - - override public function graphicLoaded():Void - { - super.graphicLoaded(); - - setupAnimation('normal', FlxButton.NORMAL); - setupAnimation('highlight', FlxButton.HIGHLIGHT); - setupAnimation('pressed', FlxButton.PRESSED); - } - - function loadDefaultGraphic():Void - loadGraphic('flixel/images/ui/button.png', true, 80, 20); - - function setupAnimation(animationName:String, frameIndex:Int):Void - { - // make sure the animation doesn't contain an invalid frame - frameIndex = Std.int(Math.min(frameIndex, animation.frames - 1)); - animation.add(animationName, [frameIndex]); - } - - /** - * Called by the game state when state is changed (if this object belongs to the state) - */ - override public function destroy():Void - { - label = FlxDestroyUtil.destroy(label); - _spriteLabel = null; - - onUp = FlxDestroyUtil.destroy(onUp); - onDown = FlxDestroyUtil.destroy(onDown); - onOver = FlxDestroyUtil.destroy(onOver); - onOut = FlxDestroyUtil.destroy(onOut); - - labelOffsets = FlxDestroyUtil.putArray(labelOffsets); - - labelAlphas = null; - currentInput = null; - input = null; - - super.destroy(); - } - - /** - * Called by the game loop automatically, handles touch over and click detection. - */ - override public function update(elapsed:Float):Void - { - super.update(elapsed); - - if (visible) - { - // Update the button, but only if at least either touches are enabled - #if FLX_POINTER_INPUT - updateButton(); - #end - - // Trigger the animation only if the button's input status changes. - if (lastStatus != status) - { - updateStatusAnimation(); - lastStatus = status; - } - } - - input.update(); - } - - function updateStatusAnimation():Void - animation.play(statusAnimations[status]); - - /** - * Just draws the button graphic and text label to the screen. - */ - override public function draw():Void - { - super.draw(); - - if (_spriteLabel != null && _spriteLabel.visible) - { - _spriteLabel.cameras = cameras; - _spriteLabel.draw(); - } - } - - #if FLX_DEBUG - /** - * Helper function to draw the debug graphic for the label as well. - */ - override public function drawDebug():Void - { - super.drawDebug(); - - if (_spriteLabel != null) - _spriteLabel.drawDebug(); - } - #end - - /** - * Stamps button's graphic and label onto specified atlas object and loads graphic from this atlas. - * This method assumes that you're using whole image for button's graphic and image has no spaces between frames. - * And it assumes that label is a single frame sprite. - * - * @param atlas Atlas to stamp graphic to. - * @return Whether the button's graphic and label's graphic were stamped on the atlas successfully. - */ - public function stampOnAtlas(atlas:FlxAtlas):Bool - { - var buttonNode:FlxNode = atlas.addNode(graphic.bitmap, graphic.key); - var result:Bool = (buttonNode != null); - - if (buttonNode != null) - { - var buttonFrames:FlxTileFrames = cast frames; - var tileSize:FlxPoint = FlxPoint.get(buttonFrames.tileSize.x, buttonFrames.tileSize.y); - var tileFrames:FlxTileFrames = buttonNode.getTileFrames(tileSize); - this.frames = tileFrames; - } - - if (result && label != null) - { - var labelNode:FlxNode = atlas.addNode(label.graphic.bitmap, label.graphic.key); - result = result && (labelNode != null); - - if (labelNode != null) - label.frames = labelNode.getImageFrame(); - } - - return result; - } - - /** - * Basic button update logic - searches for overlaps with touches and - * the touch and calls `updateStatus()`. - */ - function updateButton():Void - { - var overlapFound = checkTouchOverlap(); - - if (currentInput != null && currentInput.justReleased && overlapFound) - onUpHandler(); - - if (status != FlxButton.NORMAL && (!overlapFound || (currentInput != null && currentInput.justReleased))) - onOutHandler(); - } - - function checkTouchOverlap():Bool - { - var overlap = false; - - for (camera in cameras) - for (touch in FlxG.touches.list) - if (checkInput(touch, touch, touch.justPressedPosition, camera)) - overlap = true; - - return overlap; - } - - function checkInput(pointer:FlxPointer, input:IFlxInput, justPressedPosition:FlxPoint, camera:FlxCamera):Bool - { - if (maxInputMovement != Math.POSITIVE_INFINITY - && justPressedPosition.distanceTo(pointer.getScreenPosition(FlxPoint.weak())) > maxInputMovement - && input == currentInput) - { - currentInput = null; - } - else if (overlapsPoint(pointer.getWorldPosition(camera, _point), true, camera)) - { - updateStatus(input); - return true; - } - - return false; - } - - /** - * Updates the button status by calling the respective event handler function. - */ - function updateStatus(input:IFlxInput):Void - { - if (input.justPressed) - { - currentInput = input; - onDownHandler(); - } - else if (status == FlxButton.NORMAL) - { - // Allow 'swiping' to press a button (dragging it over the button while pressed) - if (allowSwiping && input.pressed) - onDownHandler(); - else - onOverHandler(); - } - } - - function updateLabelPosition() - { - if (_spriteLabel != null) // Label positioning - { - _spriteLabel.x = (pixelPerfectPosition ? Math.floor(x) : x) + labelOffsets[status].x; - _spriteLabel.y = (pixelPerfectPosition ? Math.floor(y) : y) + labelOffsets[status].y; - } - } - - function updateLabelAlpha() - { - if (_spriteLabel != null && labelAlphas.length > status) - _spriteLabel.alpha = alpha * labelAlphas[status]; - } - - /** - * Internal function that handles the onUp event. - */ - function onUpHandler():Void - { - status = FlxButton.NORMAL; - input.release(); - currentInput = null; - // Order matters here, because onUp.fire() could cause a state change and destroy this object. - onUp.fire(); - } - - /** - * Internal function that handles the onDown event. - */ - function onDownHandler():Void - { - status = FlxButton.PRESSED; - input.press(); - // Order matters here, because onDown.fire() could cause a state change and destroy this object. - onDown.fire(); - } - - /** - * Internal function that handles the onOver event. - */ - function onOverHandler():Void - { - status = FlxButton.HIGHLIGHT; - // Order matters here, because onOver.fire() could cause a state change and destroy this object. - onOver.fire(); - } - - /** - * Internal function that handles the onOut event. - */ - function onOutHandler():Void - { - status = FlxButton.NORMAL; - input.release(); - // Order matters here, because onOut.fire() could cause a state change and destroy this object. - onOut.fire(); - } - - function set_label(Value:T):T - { - if (Value != null) - { - // use the same FlxPoint object for both - Value.scrollFactor.put(); - Value.scrollFactor = scrollFactor; - } - - label = Value; - _spriteLabel = label; - - updateLabelPosition(); - - return Value; - } - - function set_status(Value:Int):Int - { - status = Value; - updateLabelAlpha(); - return status; - } - - override function set_alpha(Value:Float):Float - { - super.set_alpha(Value); - updateLabelAlpha(); - return alpha; - } - - override function set_x(Value:Float):Float - { - super.set_x(Value); - updateLabelPosition(); - return x; - } - - override function set_y(Value:Float):Float - { - super.set_y(Value); - updateLabelPosition(); - return y; - } - - inline function get_justReleased():Bool - return input.justReleased; - - inline function get_released():Bool - return input.released; - - inline function get_pressed():Bool - return input.pressed; - - inline function get_justPressed():Bool - return input.justPressed; -} - -/** - * Helper function for `FlxButton` which handles its events. - */ -private class FlxButtonEvent implements IFlxDestroyable -{ - /** - * The callback function to call when this even fires. - */ - public var callback:Void->Void; - - #if FLX_SOUND_SYSTEM - /** - * The sound to play when this event fires. - */ - public var sound:FlxSound; - #end - - /** - * @param Callback The callback function to call when this even fires. - * @param sound The sound to play when this event fires. - */ - public function new(?Callback:Void->Void, ?sound:FlxSound) - { - callback = Callback; - - #if FLX_SOUND_SYSTEM - this.sound = sound; - #end - } - - /** - * Cleans up memory. - */ - public inline function destroy():Void - { - callback = null; - - #if FLX_SOUND_SYSTEM - sound = FlxDestroyUtil.destroy(sound); - #end - } - - /** - * Fires this event (calls the callback and plays the sound) - */ - public inline function fire():Void - { - if (callback != null) - callback(); - - #if FLX_SOUND_SYSTEM - if (sound != null) - sound.play(true); - #end - } +package android.flixel; + + +import flixel.math.FlxPoint; +import flixel.FlxCamera; +import flixel.FlxG; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.text.FlxText; +import flixel.FlxSprite; +import flixel.graphics.atlas.FlxAtlas; +import flixel.graphics.atlas.FlxNode; +import flixel.graphics.frames.FlxTileFrames; +import flixel.input.FlxInput; +import flixel.input.FlxPointer; +import flixel.input.IFlxInput; +import flixel.util.FlxDestroyUtil.IFlxDestroyable; +import flixel.util.FlxDestroyUtil; + +import flixel.system.FlxSound; + + +import flixel.input.touch.FlxTouch; + +/** + * A simple button class that calls a function when clicked by the touch. + */ +class FlxButton extends FlxTypedButton +{ + /** + * Used with public variable status, means not highlighted or pressed. + */ + public static inline var NORMAL:Int = 0; + + /** + * Used with public variable status, means highlighted (usually from touch over). + */ + public static inline var HIGHLIGHT:Int = 1; + + /** + * Used with public variable status, means pressed (usually from touch click). + */ + public static inline var PRESSED:Int = 2; + + /** + * Shortcut to setting label.text + */ + public var text(get, set):String; + + /** + * Creates a new `FlxButton` object with a gray background + * and a callback function on the UI thread. + * + * @param X The x position of the button. + * @param Y The y position of the button. + * @param Text The text that you want to appear on the button. + * @param OnClick The function to call whenever the button is clicked. + */ + public function new(X:Float = 0, Y:Float = 0, ?Text:String, ?OnClick:Void->Void) + { + super(X, Y, OnClick); + + for (point in labelOffsets) + point.set(point.x - 1, point.y + 3); + + initLabel(Text); + } + + /** + * Updates the size of the text field to match the button. + */ + override function resetHelpers():Void + { + super.resetHelpers(); + + if (label != null) + { + label.fieldWidth = label.frameWidth = Std.int(width); + label.size = label.size; // Calls set_size(), don't remove! + } + } + + inline function initLabel(Text:String):Void + { + if (Text != null) + { + label = new FlxText(x + labelOffsets[NORMAL].x, y + labelOffsets[NORMAL].y, 80, Text); + label.setFormat(null, 8, 0x333333, 'center'); + label.alpha = labelAlphas[status]; + label.drawFrame(true); + } + } + + inline function get_text():String + { + return (label != null) ? label.text : null; + } + + inline function set_text(Text:String):String + { + if (label == null) + initLabel(Text); + else + label.text = Text; + return Text; + } +} + +/** + * A simple button class that calls a function when clicked by the touch. + */ +#if !display +@:generic +#end +class FlxTypedButton extends FlxSprite implements IFlxInput +{ + /** + * The label that appears on the button. Can be any `FlxSprite`. + */ + public var label(default, set):T; + + /** + * What offsets the `label` should have for each status. + */ + public var labelOffsets:Array = [FlxPoint.get(), FlxPoint.get(), FlxPoint.get(0, 1)]; + + /** + * 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 = [0.8, 1.0, 0.5]; + + /** + * What animation should be played for each status. + * Default is ['normal', 'highlight', 'pressed']. + */ + public var statusAnimations:Array = ['normal', 'highlight', 'pressed']; + + /** + * Whether you can press the button simply by releasing the touch button over it (default). + * If false, the input has to be pressed while hovering over the button. + */ + public var allowSwiping:Bool = true; + + /** + * Maximum distance a pointer can move to still trigger event handlers. + * If it moves beyond this limit, onOut is triggered. + * Defaults to `Math.POSITIVE_INFINITY` (i.e. no limit). + */ + public var maxInputMovement:Float = Math.POSITIVE_INFINITY; + + /** + * Shows the current state of the button, either `FlxButton.NORMAL`, + * `FlxButton.HIGHLIGHT` or `FlxButton.PRESSED`. + */ + public var status(default, set):Int; + + /** + * The properties of this button's `onUp` event (callback function, sound). + */ + public var onUp(default, null):FlxButtonEvent; + + /** + * The properties of this button's `onDown` event (callback function, sound). + */ + public var onDown(default, null):FlxButtonEvent; + + /** + * The properties of this button's `onOver` event (callback function, sound). + */ + public var onOver(default, null):FlxButtonEvent; + + /** + * The properties of this button's `onOut` event (callback function, sound). + */ + public var onOut(default, null):FlxButtonEvent; + + public var justReleased(get, never):Bool; + public var released(get, never):Bool; + public var pressed(get, never):Bool; + public var justPressed(get, never):Bool; + + /** + * We cast label to a `FlxSprite` for internal operations to avoid Dynamic casts in C++ + */ + var _spriteLabel:FlxSprite; + + /** + * We don't need an ID here, so let's just use `Int` as the type. + */ + var input:FlxInput; + + /** + * The input currently pressing this button, if none, it's `null`. Needed to check for its release. + */ + var currentInput:IFlxInput; + + var lastStatus = -1; + + /** + * Creates a new `FlxTypedButton` object with a gray background. + * + * @param X The x position of the button. + * @param Y The y position of the button. + * @param OnClick The function to call whenever the button is clicked. + */ + public function new(X:Float = 0, Y:Float = 0, ?OnClick:Void->Void) + { + super(X, Y); + + loadDefaultGraphic(); + + onUp = new FlxButtonEvent(OnClick); + onDown = new FlxButtonEvent(); + onOver = new FlxButtonEvent(); + onOut = new FlxButtonEvent(); + + status = FlxButton.NORMAL; + + // Since this is a UI element, the default scrollFactor is (0, 0) + scrollFactor.set(); + + statusAnimations[FlxButton.HIGHLIGHT] = 'normal'; + labelAlphas[FlxButton.HIGHLIGHT] = 1; + + input = new FlxInput(0); + } + + override public function graphicLoaded():Void + { + super.graphicLoaded(); + + setupAnimation('normal', FlxButton.NORMAL); + setupAnimation('highlight', FlxButton.HIGHLIGHT); + setupAnimation('pressed', FlxButton.PRESSED); + } + + function loadDefaultGraphic():Void + loadGraphic('flixel/images/ui/button.png', true, 80, 20); + + function setupAnimation(animationName:String, frameIndex:Int):Void + { + // make sure the animation doesn't contain an invalid frame + frameIndex = Std.int(Math.min(frameIndex, animation.frames - 1)); + animation.add(animationName, [frameIndex]); + } + + /** + * Called by the game state when state is changed (if this object belongs to the state) + */ + override public function destroy():Void + { + label = FlxDestroyUtil.destroy(label); + _spriteLabel = null; + + onUp = FlxDestroyUtil.destroy(onUp); + onDown = FlxDestroyUtil.destroy(onDown); + onOver = FlxDestroyUtil.destroy(onOver); + onOut = FlxDestroyUtil.destroy(onOut); + + labelOffsets = FlxDestroyUtil.putArray(labelOffsets); + + labelAlphas = null; + currentInput = null; + input = null; + + super.destroy(); + } + + /** + * Called by the game loop automatically, handles touch over and click detection. + */ + override public function update(elapsed:Float):Void + { + super.update(elapsed); + + if (visible) + { + // Update the button, but only if at least either touches are enabled + #if FLX_POINTER_INPUT + updateButton(); + #end + + // Trigger the animation only if the button's input status changes. + if (lastStatus != status) + { + updateStatusAnimation(); + lastStatus = status; + } + } + + input.update(); + } + + function updateStatusAnimation():Void + animation.play(statusAnimations[status]); + + /** + * Just draws the button graphic and text label to the screen. + */ + override public function draw():Void + { + super.draw(); + + if (_spriteLabel != null && _spriteLabel.visible) + { + _spriteLabel.cameras = cameras; + _spriteLabel.draw(); + } + } + + #if FLX_DEBUG + /** + * Helper function to draw the debug graphic for the label as well. + */ + override public function drawDebug():Void + { + super.drawDebug(); + + if (_spriteLabel != null) + _spriteLabel.drawDebug(); + } + #end + + /** + * Stamps button's graphic and label onto specified atlas object and loads graphic from this atlas. + * This method assumes that you're using whole image for button's graphic and image has no spaces between frames. + * And it assumes that label is a single frame sprite. + * + * @param atlas Atlas to stamp graphic to. + * @return Whether the button's graphic and label's graphic were stamped on the atlas successfully. + */ + public function stampOnAtlas(atlas:FlxAtlas):Bool + { + var buttonNode:FlxNode = atlas.addNode(graphic.bitmap, graphic.key); + var result:Bool = (buttonNode != null); + + if (buttonNode != null) + { + var buttonFrames:FlxTileFrames = cast frames; + var tileSize:FlxPoint = FlxPoint.get(buttonFrames.tileSize.x, buttonFrames.tileSize.y); + var tileFrames:FlxTileFrames = buttonNode.getTileFrames(tileSize); + this.frames = tileFrames; + } + + if (result && label != null) + { + var labelNode:FlxNode = atlas.addNode(label.graphic.bitmap, label.graphic.key); + result = result && (labelNode != null); + + if (labelNode != null) + label.frames = labelNode.getImageFrame(); + } + + return result; + } + + /** + * Basic button update logic - searches for overlaps with touches and + * the touch and calls `updateStatus()`. + */ + function updateButton():Void + { + var overlapFound = checkTouchOverlap(); + + if (currentInput != null && currentInput.justReleased && overlapFound) + onUpHandler(); + + if (status != FlxButton.NORMAL && (!overlapFound || (currentInput != null && currentInput.justReleased))) + onOutHandler(); + } + + function checkTouchOverlap():Bool + { + var overlap = false; + + for (camera in cameras) + for (touch in FlxG.touches.list) + if (checkInput(touch, touch, touch.justPressedPosition, camera)) + overlap = true; + + return overlap; + } + + function checkInput(pointer:FlxPointer, input:IFlxInput, justPressedPosition:FlxPoint, camera:FlxCamera):Bool + { + if (maxInputMovement != Math.POSITIVE_INFINITY + && justPressedPosition.distanceTo(pointer.getScreenPosition(FlxPoint.weak())) > maxInputMovement + && input == currentInput) + { + currentInput = null; + } + else if (overlapsPoint(pointer.getWorldPosition(camera, _point), true, camera)) + { + updateStatus(input); + return true; + } + + return false; + } + + /** + * Updates the button status by calling the respective event handler function. + */ + function updateStatus(input:IFlxInput):Void + { + if (input.justPressed) + { + currentInput = input; + onDownHandler(); + } + else if (status == FlxButton.NORMAL) + { + // Allow 'swiping' to press a button (dragging it over the button while pressed) + if (allowSwiping && input.pressed) + onDownHandler(); + else + onOverHandler(); + } + } + + function updateLabelPosition() + { + if (_spriteLabel != null) // Label positioning + { + _spriteLabel.x = (pixelPerfectPosition ? Math.floor(x) : x) + labelOffsets[status].x; + _spriteLabel.y = (pixelPerfectPosition ? Math.floor(y) : y) + labelOffsets[status].y; + } + } + + function updateLabelAlpha() + { + if (_spriteLabel != null && labelAlphas.length > status) + _spriteLabel.alpha = alpha * labelAlphas[status]; + } + + /** + * Internal function that handles the onUp event. + */ + function onUpHandler():Void + { + status = FlxButton.NORMAL; + input.release(); + currentInput = null; + // Order matters here, because onUp.fire() could cause a state change and destroy this object. + onUp.fire(); + } + + /** + * Internal function that handles the onDown event. + */ + function onDownHandler():Void + { + status = FlxButton.PRESSED; + input.press(); + // Order matters here, because onDown.fire() could cause a state change and destroy this object. + onDown.fire(); + } + + /** + * Internal function that handles the onOver event. + */ + function onOverHandler():Void + { + status = FlxButton.HIGHLIGHT; + // Order matters here, because onOver.fire() could cause a state change and destroy this object. + onOver.fire(); + } + + /** + * Internal function that handles the onOut event. + */ + function onOutHandler():Void + { + status = FlxButton.NORMAL; + input.release(); + // Order matters here, because onOut.fire() could cause a state change and destroy this object. + onOut.fire(); + } + + function set_label(Value:T):T + { + if (Value != null) + { + // use the same FlxPoint object for both + Value.scrollFactor.put(); + Value.scrollFactor = scrollFactor; + } + + label = Value; + _spriteLabel = label; + + updateLabelPosition(); + + return Value; + } + + function set_status(Value:Int):Int + { + status = Value; + updateLabelAlpha(); + return status; + } + + override function set_alpha(Value:Float):Float + { + super.set_alpha(Value); + updateLabelAlpha(); + return alpha; + } + + override function set_x(Value:Float):Float + { + super.set_x(Value); + updateLabelPosition(); + return x; + } + + override function set_y(Value:Float):Float + { + super.set_y(Value); + updateLabelPosition(); + return y; + } + + inline function get_justReleased():Bool + return input.justReleased; + + inline function get_released():Bool + return input.released; + + inline function get_pressed():Bool + return input.pressed; + + inline function get_justPressed():Bool + return input.justPressed; +} + +/** + * Helper function for `FlxButton` which handles its events. + */ +private class FlxButtonEvent implements IFlxDestroyable +{ + /** + * The callback function to call when this even fires. + */ + public var callback:Void->Void; + + #if FLX_SOUND_SYSTEM + /** + * The sound to play when this event fires. + */ + public var sound:FlxSound; + #end + + /** + * @param Callback The callback function to call when this even fires. + * @param sound The sound to play when this event fires. + */ + public function new(?Callback:Void->Void, ?sound:FlxSound) + { + callback = Callback; + + #if FLX_SOUND_SYSTEM + this.sound = sound; + #end + } + + /** + * Cleans up memory. + */ + public inline function destroy():Void + { + callback = null; + + #if FLX_SOUND_SYSTEM + sound = FlxDestroyUtil.destroy(sound); + #end + } + + /** + * Fires this event (calls the callback and plays the sound) + */ + public inline function fire():Void + { + if (callback != null) + callback(); + + #if FLX_SOUND_SYSTEM + if (sound != null) + sound.play(true); + #end + } } \ No newline at end of file diff --git a/source/android/flixel/FlxHitbox.hx b/source/android/flixel/FlxHitbox.hx index c000c6ad3d7..74b54f18cbf 100644 --- a/source/android/flixel/FlxHitbox.hx +++ b/source/android/flixel/FlxHitbox.hx @@ -1,78 +1,94 @@ -package android.flixel; - -import android.flixel.FlxButton; -import flixel.FlxG; -import flixel.FlxSprite; -import flixel.util.FlxDestroyUtil; -import flixel.graphics.frames.FlxAtlasFrames; -import flixel.graphics.FlxGraphic; -import flixel.tweens.FlxTween; -import flixel.tweens.FlxEase; -import flixel.group.FlxSpriteGroup; -import openfl.utils.Assets; - -/** - * A zone with 4 buttons (A hitbox). - * It's easy to customize the layout. - * - * @author: Saw (M.A. Jigsaw) - */ -class FlxHitbox extends FlxSpriteGroup { - public var buttonLeft:FlxButton = new FlxButton(0, 0); - public var buttonDown:FlxButton = new FlxButton(0, 0); - public var buttonUp:FlxButton = new FlxButton(0, 0); - public var buttonRight:FlxButton = new FlxButton(0, 0); - - /** - * Create the zone. - */ - public function new() { - super(); - - scrollFactor.set(); - - add(buttonLeft = createHint(0, 0, 'left', 0xFF00FF)); - add(buttonDown = createHint(FlxG.width / 4, 0, 'down', 0x00FFFF)); - add(buttonUp = createHint(FlxG.width / 2, 0, 'up', 0x00FF00)); - add(buttonRight = createHint((FlxG.width / 2) + (FlxG.width / 4), 0, 'right', 0xFF0000)); - } - - /** - * Clean up memory. - */ - override function destroy() { - super.destroy(); - - buttonLeft = null; - buttonDown = null; - buttonUp = null; - buttonRight = null; - } - - private function createHint(X:Float, Y:Float, Graphic:String, Color:Int = 0xFFFFFF):FlxButton { - var hintTween:FlxTween = null; - var hint:FlxButton = new FlxButton(X, Y); - hint.loadGraphic(FlxGraphic.fromFrame(FlxAtlasFrames.fromSparrow(Assets.getBitmapData('assets/android/hitbox.png'), - Assets.getText('assets/android/hitbox.xml')) - .getByName(Graphic))); - hint.setGraphicSize(Std.int(FlxG.width / 4), FlxG.height); - hint.updateHitbox(); - hint.solid = false; - hint.immovable = true; - hint.scrollFactor.set(); - hint.color = Color; - hint.alpha = 0.00001; - hint.onDown.callback = hint.onOver.callback = function() { - } - hint.onUp.callback = hint.onOut.callback = function() { - if (hint.alpha != 0.00001) - hint.alpha = 0.00001; - } - hint.onOver.callback = hint.onDown.callback; - hint.onOut.callback = hint.onUp.callback; - #if FLX_DEBUG - hint.ignoreDrawDebug = true; - #end - return hint; - } -} +package android.flixel; + +import android.flixel.FlxButton; +import openfl.utils.Assets; +import flixel.util.FlxDestroyUtil; +import flixel.FlxG; +import flixel.util.FlxColor; +import flixel.tweens.FlxTween; +import flixel.graphics.FlxGraphic; +import flixel.graphics.frames.FlxAtlasFrames; + +/** + * A zone with 4 buttons (A hitbox). + * It's easy to customize the layout. + * + * @author: Saw (M.A. Jigsaw) + */ +class FlxHitbox extends FlxSpriteGroup { + public var buttonLeft:FlxButton = new FlxButton(0, 0); + public var buttonDown:FlxButton = new FlxButton(0, 0); + public var buttonUp:FlxButton = new FlxButton(0, 0); + public var buttonRight:FlxButton = new FlxButton(0, 0); + + /** + * Create the zone. + */ + public function new() { + super(); + + var buttonLeftColor:Array; + var buttonDownColor:Array; + var buttonUpColor:Array; + var buttonRightColor:Array; + if (ClientPrefs.dynamicColors) { //bri'ish type option + buttonLeftColor = ClientPrefs.arrowHSV[0]; + buttonDownColor = ClientPrefs.arrowHSV[1]; + buttonUpColor = ClientPrefs.arrowHSV[2]; + buttonRightColor = ClientPrefs.arrowHSV[3]; + } else { + buttonLeftColor = ClientPrefs.arrowHSV[0]; + buttonDownColor = ClientPrefs.arrowHSV[1]; + buttonUpColor = ClientPrefs.arrowHSV[2]; + buttonRightColor = ClientPrefs.arrowHSV[3]; + } + + scrollFactor.set(); + + add(buttonLeft = createHint(0, 0, 'left', buttonLeftColor[0])); + add(buttonDown = createHint(FlxG.width / 4, 0, 'down', buttonDownColor[0])); + add(buttonUp = createHint(FlxG.width / 2, 0, 'up', buttonUpColor[0])); + add(buttonRight = createHint((FlxG.width / 2) + (FlxG.width / 4), 0, 'right', buttonRightColor[0])); + } + + /** + * Clean up memory. + */ + override function destroy() { + super.destroy(); + + buttonLeft = null; + buttonDown = null; + buttonUp = null; + buttonRight = null; + } + + private function createHint(X:Float, Y:Float, Graphic:String, Color:Int = 0xFFFFFF):FlxButton { + var hintTween:FlxTween = null; + var hint:FlxButton = new FlxButton(X, Y); + hint.loadGraphic(FlxGraphic.fromFrame(FlxAtlasFrames.fromSparrow(Assets.getBitmapData('assets/android/hitbox.png'), + Assets.getText('assets/android/hitbox.xml')) + .getByName(Graphic))); + hint.setGraphicSize(Std.int(FlxG.width / 4), FlxG.height); + hint.updateHitbox(); + hint.solid = false; + hint.immovable = true; + hint.scrollFactor.set(); + hint.color = Color; + hint.alpha = 0.00001; + hint.onDown.callback = hint.onOver.callback = function() { + if (hint.alpha != ClientPrefs.hitboxAlpha) + hint.alpha = ClientPrefs.hitboxAlpha; + } + hint.onUp.callback = hint.onOut.callback = function() { + if (hint.alpha != 0.00001) + hint.alpha = 0.00001; + } + hint.onOver.callback = hint.onDown.callback; + hint.onOut.callback = hint.onUp.callback; + #if FLX_DEBUG + hint.ignoreDrawDebug = true; + #end + return hint; + } +} diff --git a/source/android/flixel/FlxNewHitbox.hx b/source/android/flixel/FlxNewHitbox.hx new file mode 100644 index 00000000000..7de52389533 --- /dev/null +++ b/source/android/flixel/FlxNewHitbox.hx @@ -0,0 +1,124 @@ +package android.flixel; + +import openfl.display.BitmapData; +import openfl.display.Shape; +import android.flixel.FlxButton; +import flixel.util.FlxColor; +import flixel.FlxG; + +/** + * A zone with 4 hint's (A hitbox). + * It's really easy to customize the layout. + * + * @author Mihai Alexandru (M.A. Jigsaw) + */ +class FlxNewHitbox extends FlxSpriteGroup { + public var buttonLeft:FlxButton = new FlxButton(0, 0); + public var buttonDown:FlxButton = new FlxButton(0, 0); + public var buttonUp:FlxButton = new FlxButton(0, 0); + public var buttonRight:FlxButton = new FlxButton(0, 0); + public var buttonSpace:FlxButton = new FlxButton(0, 0); + + /** + * Create the zone. + */ + public function new():Void { + super(); + + var buttonLeftColor:Array; + var buttonDownColor:Array; + var buttonUpColor:Array; + var buttonRightColor:Array; + if (ClientPrefs.dynamicColors) { //bri'ish type option + buttonLeftColor = ClientPrefs.arrowHSV[0]; + buttonDownColor = ClientPrefs.arrowHSV[1]; + buttonUpColor = ClientPrefs.arrowHSV[2]; + buttonRightColor = ClientPrefs.arrowHSV[3]; + } else { + buttonLeftColor = ClientPrefs.arrowHSV[0]; + buttonDownColor = ClientPrefs.arrowHSV[1]; + buttonUpColor = ClientPrefs.arrowHSV[2]; + buttonRightColor = ClientPrefs.arrowHSV[3]; + } + + if (!ClientPrefs.hitboxSpace) { + add(buttonLeft = createHint(0, 0, Std.int(FlxG.width / 4), Std.int(FlxG.height * 1), buttonLeftColor[0])); + add(buttonDown = createHint(FlxG.width / 4, 0, Std.int(FlxG.width / 4), Std.int(FlxG.height * 1), buttonDownColor[0])); + add(buttonUp = createHint(FlxG.width / 2, 0, Std.int(FlxG.width / 4), Std.int(FlxG.height * 1), buttonUpColor[0])); + add(buttonRight = createHint((FlxG.width / 2) + (FlxG.width / 4), 0, Std.int(FlxG.width / 4), Std.int(FlxG.height * 1), buttonRightColor[0])); + } + + else { + if (ClientPrefs.hitboxSpaceLocation == 'Bottom') { + add(buttonLeft = createHint(0, 0, Std.int(FlxG.width / 4), Std.int(FlxG.height * 0.8), buttonLeftColor[0])); + add(buttonDown = createHint(FlxG.width / 4, 0, Std.int(FlxG.width / 4), Std.int(FlxG.height * 0.8), buttonDownColor[0])); + add(buttonUp = createHint(FlxG.width / 2, 0, Std.int(FlxG.width / 4), Std.int(FlxG.height * 0.8), buttonUpColor[0])); + add(buttonRight = createHint((FlxG.width / 2) + (FlxG.width / 4), 0, Std.int(FlxG.width / 4), Std.int(FlxG.height * 0.8), buttonRightColor[0])); + add(buttonSpace = createHint(0, (FlxG.height / 5) * 4, FlxG.width, Std.int(FlxG.height / 5), 0xFFFF00)); + } + + else if (ClientPrefs.hitboxSpaceLocation == 'Top') { + add(buttonLeft = createHint(0, (FlxG.height / 5) * 1, Std.int(FlxG.width / 4), Std.int(FlxG.height * 0.8), buttonLeftColor[0])); + add(buttonDown = createHint(FlxG.width / 4, (FlxG.height / 5) * 1, Std.int(FlxG.width / 4), Std.int(FlxG.height * 0.8), buttonDownColor[0])); + add(buttonUp = createHint(FlxG.width / 2, (FlxG.height / 5) * 1, Std.int(FlxG.width / 4), Std.int(FlxG.height * 0.8), buttonUpColor[0])); + add(buttonRight = createHint((FlxG.width / 2) + (FlxG.width / 4), (FlxG.height / 5) * 1, Std.int(FlxG.width / 4), Std.int(FlxG.height * 0.8), buttonRightColor[0])); + add(buttonSpace = createHint(0, 0, FlxG.width, Std.int(FlxG.height / 5), 0xFFFF00)); + } + + else { + add(buttonLeft = createHint(0, 0, Std.int(FlxG.width / 5), Std.int(FlxG.height * 1), buttonLeftColor[0])); + add(buttonDown = createHint(FlxG.width / 5 * 1, 0, Std.int(FlxG.width / 5), Std.int(FlxG.height * 1), buttonDownColor[0])); + add(buttonUp = createHint(FlxG.width / 5 * 3, 0, Std.int(FlxG.width / 5), Std.int(FlxG.height * 1), buttonUpColor[0])); + add(buttonRight = createHint(FlxG.width / 5 * 4 , 0, Std.int(FlxG.width / 5), Std.int(FlxG.height * 1), buttonRightColor[0])); + add(buttonSpace = createHint(FlxG.width / 5 * 2, 0, Std.int(FlxG.width / 5), Std.int(FlxG.height * 1), 0xFFFF00)); + } + } + scrollFactor.set(); +} + + /** + * Clean up memory. + */ + override function destroy():Void { + super.destroy(); + + buttonLeft = null; + buttonDown = null; + buttonUp = null; + buttonRight = null; + buttonSpace = null; + } + + private function createHintGraphic(Width:Int, Height:Int, Color:Int = 0xFFFFFF):BitmapData { + var shape:Shape = new Shape(); + shape.graphics.beginFill(Color); + shape.graphics.lineStyle(10, Color, 1); + shape.graphics.drawRect(0, 0, Width, Height); + shape.graphics.endFill(); + + var bitmap:BitmapData = new BitmapData(Width, Height, true, 0); + bitmap.draw(shape); + return bitmap; + } + + private function createHint(X:Float, Y:Float, Width:Int, Height:Int, Color:Int = 0xFFFFFF):FlxButton { + var hint:FlxButton = new FlxButton(X, Y); + hint.loadGraphic(createHintGraphic(Width, Height, Color)); + hint.solid = false; + hint.immovable = true; + hint.scrollFactor.set(); + hint.alpha = 0.00001; + hint.onDown.callback = hint.onOver.callback = function() { + if (hint.alpha != ClientPrefs.hitboxAlpha) + hint.alpha = ClientPrefs.hitboxAlpha; + } + hint.onUp.callback = hint.onOut.callback = function() { + if (hint.alpha != 0.00001) + hint.alpha = 0.00001; + } + #if FLX_DEBUG + hint.ignoreDrawDebug = true; + #end + return hint; + } +} \ No newline at end of file diff --git a/source/android/flixel/FlxVirtualPad.hx b/source/android/flixel/FlxVirtualPad.hx index 5d6f09b81cc..f7a1ff6afb8 100644 --- a/source/android/flixel/FlxVirtualPad.hx +++ b/source/android/flixel/FlxVirtualPad.hx @@ -1,198 +1,204 @@ -package android.flixel; - -import android.flixel.FlxButton; -import flixel.FlxG; -import flixel.graphics.frames.FlxTileFrames; -import flixel.group.FlxSpriteGroup; -import flixel.math.FlxPoint; -import flixel.util.FlxDestroyUtil; -import flixel.graphics.frames.FlxAtlasFrames; -import flixel.graphics.FlxGraphic; -import openfl.utils.Assets; - -/** - * A gamepad. - * It's easy to customize the layout. - * - * @original author Ka Wing Chin - * @modification's author: Saw (M.A. Jigsaw) - */ -class FlxVirtualPad extends FlxSpriteGroup { - public var buttonLeft:FlxButton = new FlxButton(0, 0); - public var buttonUp:FlxButton = new FlxButton(0, 0); - public var buttonRight:FlxButton = new FlxButton(0, 0); - public var buttonDown:FlxButton = new FlxButton(0, 0); - - public var buttonLeft2:FlxButton = new FlxButton(0, 0); - public var buttonUp2:FlxButton = new FlxButton(0, 0); - public var buttonRight2:FlxButton = new FlxButton(0, 0); - public var buttonDown2:FlxButton = new FlxButton(0, 0); - - public var buttonA:FlxButton = new FlxButton(0, 0); - public var buttonB:FlxButton = new FlxButton(0, 0); - public var buttonC:FlxButton = new FlxButton(0, 0); - public var buttonD:FlxButton = new FlxButton(0, 0); - public var buttonE:FlxButton = new FlxButton(0, 0); - public var buttonV:FlxButton = new FlxButton(0, 0); - public var buttonX:FlxButton = new FlxButton(0, 0); - public var buttonY:FlxButton = new FlxButton(0, 0); - public var buttonZ:FlxButton = new FlxButton(0, 0); - - /** - * Create a gamepad. - * - * @param DPadMode The D-Pad mode. `LEFT_FULL` for example. - * @param ActionMode The action buttons mode. `A_B_C` for example. - */ - public function new(DPad:FlxDPadMode, Action:FlxActionMode) { - super(); - - scrollFactor.set(); - - switch (DPad) { - case UP_DOWN: - add(buttonUp = createButton(0, FlxG.height - 255, 132, 127, 'up', 0x00FF00)); - add(buttonDown = createButton(0, FlxG.height - 135, 132, 127, 'down', 0x00FFFF)); - case LEFT_RIGHT: - add(buttonLeft = createButton(0, FlxG.height - 135, 132, 127, 'left', 0xFF00FF)); - add(buttonRight = createButton(127, FlxG.height - 135, 132, 127, 'right', 0xFF0000)); - case UP_LEFT_RIGHT: - add(buttonUp = createButton(105, FlxG.height - 243, 132, 127, 'up', 0x00FF00)); - add(buttonLeft = createButton(0, FlxG.height - 135, 132, 127, 'left', 0xFF00FF)); - add(buttonRight = createButton(207, FlxG.height - 135, 132, 127, 'right', 0xFF0000)); - case LEFT_FULL: - add(buttonUp = createButton(105, FlxG.height - 345, 132, 127, 'up', 0x00FF00)); - add(buttonLeft = createButton(0, FlxG.height - 243, 132, 127, 'left', 0xFF00FF)); - add(buttonRight = createButton(207, FlxG.height - 243, 132, 127, 'right', 0xFF0000)); - add(buttonDown = createButton(105, FlxG.height - 135, 132, 127, 'down', 0x00FFFF)); - case RIGHT_FULL: - add(buttonUp = createButton(FlxG.width - 258, FlxG.height - 408, 132, 127, 'up', 0x00FF00)); - add(buttonLeft = createButton(FlxG.width - 384, FlxG.height - 309, 132, 127, 'left', 0xFF00FF)); - add(buttonRight = createButton(FlxG.width - 132, FlxG.height - 309, 132, 127, 'right', 0xFF0000)); - add(buttonDown = createButton(FlxG.width - 258, FlxG.height - 201, 132, 127, 'down', 0x00FFFF)); - case BOTH_FULL: - add(buttonUp = createButton(105, FlxG.height - 345, 132, 127, 'up', 0x00FF00)); - add(buttonLeft = createButton(0, FlxG.height - 243, 132, 127, 'left', 0xFF00FF)); - add(buttonRight = createButton(207, FlxG.height - 243, 132, 127, 'right', 0xFF0000)); - add(buttonDown = createButton(105, FlxG.height - 135, 132, 127, 'down', 0x00FFFF)); - add(buttonUp2 = createButton(FlxG.width - 258, FlxG.height - 408, 132, 127, 'up', 0x00FF00)); - add(buttonLeft2 = createButton(FlxG.width - 384, FlxG.height - 309, 132, 127, 'left', 0xFF00FF)); - add(buttonRight2 = createButton(FlxG.width - 132, FlxG.height - 309, 132, 127, 'right', 0xFF0000)); - add(buttonDown2 = createButton(FlxG.width - 258, FlxG.height - 201, 132, 127, 'down', 0x00FFFF)); - case NONE: // do nothing - } - - switch (Action) { - case A: - add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); - case B: - add(buttonB = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); - case A_B: - add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); - add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); - case A_B_C: - add(buttonC = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'c', 0x44FF00)); - add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); - add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); - case A_B_E: - add(buttonE = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'e', 0xFF7D00)); - add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); - add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); - case A_B_X_Y: - add(buttonX = createButton(FlxG.width - 510, FlxG.height - 135, 132, 127, 'x', 0x99062D)); - add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); - add(buttonY = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'y', 0x4A35B9)); - add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); - case A_B_C_X_Y: - add(buttonC = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'c', 0x44FF00)); - add(buttonX = createButton(FlxG.width - 258, FlxG.height - 255, 132, 127, 'x', 0x99062D)); - add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); - add(buttonY = createButton(FlxG.width - 132, FlxG.height - 255, 132, 127, 'y', 0x4A35B9)); - add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); - case A_B_C_X_Y_Z: - add(buttonX = createButton(FlxG.width - 384, FlxG.height - 255, 132, 127, 'x', 0x99062D)); - add(buttonC = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'c', 0x44FF00)); - add(buttonY = createButton(FlxG.width - 258, FlxG.height - 255, 132, 127, 'y', 0x4A35B9)); - add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); - add(buttonZ = createButton(FlxG.width - 132, FlxG.height - 255, 132, 127, 'z', 0xCCB98E)); - add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); - case A_B_C_D_V_X_Y_Z: - add(buttonV = createButton(FlxG.width - 510, FlxG.height - 255, 132, 127, 'v', 0x49A9B2)); - add(buttonD = createButton(FlxG.width - 510, FlxG.height - 135, 132, 127, 'd', 0x0078FF)); - add(buttonX = createButton(FlxG.width - 384, FlxG.height - 255, 132, 127, 'x', 0x99062D)); - add(buttonC = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'c', 0x44FF00)); - add(buttonY = createButton(FlxG.width - 258, FlxG.height - 255, 132, 127, 'y', 0x4A35B9)); - add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); - add(buttonZ = createButton(FlxG.width - 132, FlxG.height - 255, 132, 127, 'z', 0xCCB98E)); - add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); - case NONE: // do nothing - } - } - - /** - * Clean up memory. - */ - override public function destroy():Void { - super.destroy(); - - buttonLeft = null; - buttonUp = null; - buttonDown = null; - buttonRight = null; - - buttonLeft2 = null; - buttonUp2 = null; - buttonDown2 = null; - buttonRight2 = null; - - buttonA = null; - buttonB = null; - buttonC = null; - buttonD = null; - buttonE = null; - buttonV = null; - buttonX = null; - buttonY = null; - buttonZ = null; - } - - private function createButton(X:Float, Y:Float, Width:Int, Height:Int, Graphic:String, Color:Int = 0xFFFFFF):FlxButton { - var button:FlxButton = new FlxButton(X, Y); - button.frames = FlxTileFrames.fromFrame(FlxAtlasFrames.fromSparrow(Assets.getBitmapData('assets/android/virtualpad.png'), - Assets.getText('assets/android/virtualpad.xml')) - .getByName(Graphic), - FlxPoint.get(Width, Height)); - button.resetSizeFromFrame(); - button.solid = false; - button.immovable = true; - button.scrollFactor.set(); - button.color = Color; - #if FLX_DEBUG - button.ignoreDrawDebug = true; - #end - return button; - } -} - -enum FlxDPadMode { - UP_DOWN; - LEFT_RIGHT; - UP_LEFT_RIGHT; - LEFT_FULL; - RIGHT_FULL; - BOTH_FULL; - NONE; -} - -enum FlxActionMode { - A; - B; - A_B; - A_B_C; - A_B_E; - A_B_X_Y; - A_B_C_X_Y; - A_B_C_X_Y_Z; - A_B_C_D_V_X_Y_Z; - NONE; -} +package android.flixel; + +import android.flixel.FlxButton; + +import flixel.graphics.frames.FlxTileFrames; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.FlxG; +import flixel.math.FlxPoint; + + + + + +import openfl.utils.Assets; + + +/** + * A gamepad. + * It's easy to customize the layout. + * + * @original author Ka Wing Chin + * @modification's author: Saw (M.A. Jigsaw) + */ +class FlxVirtualPad extends FlxSpriteGroup { + public var buttonLeft:FlxButton = new FlxButton(0, 0); + public var buttonUp:FlxButton = new FlxButton(0, 0); + public var buttonRight:FlxButton = new FlxButton(0, 0); + public var buttonDown:FlxButton = new FlxButton(0, 0); + + public var buttonLeft2:FlxButton = new FlxButton(0, 0); + public var buttonUp2:FlxButton = new FlxButton(0, 0); + public var buttonRight2:FlxButton = new FlxButton(0, 0); + public var buttonDown2:FlxButton = new FlxButton(0, 0); + + public var buttonA:FlxButton = new FlxButton(0, 0); + public var buttonB:FlxButton = new FlxButton(0, 0); + public var buttonC:FlxButton = new FlxButton(0, 0); + public var buttonD:FlxButton = new FlxButton(0, 0); + public var buttonE:FlxButton = new FlxButton(0, 0); + public var buttonV:FlxButton = new FlxButton(0, 0); + public var buttonX:FlxButton = new FlxButton(0, 0); + public var buttonY:FlxButton = new FlxButton(0, 0); + public var buttonZ:FlxButton = new FlxButton(0, 0); + + /** + * Create a gamepad. + * + * @param DPadMode The D-Pad mode. `LEFT_FULL` for example. + * @param ActionMode The action buttons mode. `A_B_C` for example. + */ + public function new(DPad:FlxDPadMode, Action:FlxActionMode) { + super(); + + scrollFactor.set(); + + switch (DPad) { + case UP_DOWN: + add(buttonUp = createButton(0, FlxG.height - 255, 132, 127, 'up', 0x00FF00)); + add(buttonDown = createButton(0, FlxG.height - 135, 132, 127, 'down', 0x00FFFF)); + case LEFT_RIGHT: + add(buttonLeft = createButton(0, FlxG.height - 135, 132, 127, 'left', 0xFF00FF)); + add(buttonRight = createButton(127, FlxG.height - 135, 132, 127, 'right', 0xFF0000)); + case UP_LEFT_RIGHT: + add(buttonUp = createButton(105, FlxG.height - 243, 132, 127, 'up', 0x00FF00)); + add(buttonLeft = createButton(0, FlxG.height - 135, 132, 127, 'left', 0xFF00FF)); + add(buttonRight = createButton(207, FlxG.height - 135, 132, 127, 'right', 0xFF0000)); + case LEFT_FULL: + add(buttonUp = createButton(105, FlxG.height - 345, 132, 127, 'up', 0x00FF00)); + add(buttonLeft = createButton(0, FlxG.height - 243, 132, 127, 'left', 0xFF00FF)); + add(buttonRight = createButton(207, FlxG.height - 243, 132, 127, 'right', 0xFF0000)); + add(buttonDown = createButton(105, FlxG.height - 135, 132, 127, 'down', 0x00FFFF)); + case RIGHT_FULL: + add(buttonUp = createButton(FlxG.width - 258, FlxG.height - 408, 132, 127, 'up', 0x00FF00)); + add(buttonLeft = createButton(FlxG.width - 384, FlxG.height - 309, 132, 127, 'left', 0xFF00FF)); + add(buttonRight = createButton(FlxG.width - 132, FlxG.height - 309, 132, 127, 'right', 0xFF0000)); + add(buttonDown = createButton(FlxG.width - 258, FlxG.height - 201, 132, 127, 'down', 0x00FFFF)); + case BOTH_FULL: + add(buttonUp = createButton(105, FlxG.height - 345, 132, 127, 'up', 0x00FF00)); + add(buttonLeft = createButton(0, FlxG.height - 243, 132, 127, 'left', 0xFF00FF)); + add(buttonRight = createButton(207, FlxG.height - 243, 132, 127, 'right', 0xFF0000)); + add(buttonDown = createButton(105, FlxG.height - 135, 132, 127, 'down', 0x00FFFF)); + add(buttonUp2 = createButton(FlxG.width - 258, FlxG.height - 408, 132, 127, 'up', 0x00FF00)); + add(buttonLeft2 = createButton(FlxG.width - 384, FlxG.height - 309, 132, 127, 'left', 0xFF00FF)); + add(buttonRight2 = createButton(FlxG.width - 132, FlxG.height - 309, 132, 127, 'right', 0xFF0000)); + add(buttonDown2 = createButton(FlxG.width - 258, FlxG.height - 201, 132, 127, 'down', 0x00FFFF)); + case NONE: // do nothing + } + + switch (Action) { + case A: + add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); + case B: + add(buttonB = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); + case A_B: + add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); + add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); + case A_B_C: + add(buttonC = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'c', 0x44FF00)); + add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); + add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); + case A_B_E: + add(buttonE = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'e', 0xFF7D00)); + add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); + add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); + case A_B_X_Y: + add(buttonX = createButton(FlxG.width - 510, FlxG.height - 135, 132, 127, 'x', 0x99062D)); + add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); + add(buttonY = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'y', 0x4A35B9)); + add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); + case A_B_C_X_Y: + add(buttonC = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'c', 0x44FF00)); + add(buttonX = createButton(FlxG.width - 258, FlxG.height - 255, 132, 127, 'x', 0x99062D)); + add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); + add(buttonY = createButton(FlxG.width - 132, FlxG.height - 255, 132, 127, 'y', 0x4A35B9)); + add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); + case A_B_C_X_Y_Z: + add(buttonX = createButton(FlxG.width - 384, FlxG.height - 255, 132, 127, 'x', 0x99062D)); + add(buttonC = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'c', 0x44FF00)); + add(buttonY = createButton(FlxG.width - 258, FlxG.height - 255, 132, 127, 'y', 0x4A35B9)); + add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); + add(buttonZ = createButton(FlxG.width - 132, FlxG.height - 255, 132, 127, 'z', 0xCCB98E)); + add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); + case A_B_C_D_V_X_Y_Z: + add(buttonV = createButton(FlxG.width - 510, FlxG.height - 255, 132, 127, 'v', 0x49A9B2)); + add(buttonD = createButton(FlxG.width - 510, FlxG.height - 135, 132, 127, 'd', 0x0078FF)); + add(buttonX = createButton(FlxG.width - 384, FlxG.height - 255, 132, 127, 'x', 0x99062D)); + add(buttonC = createButton(FlxG.width - 384, FlxG.height - 135, 132, 127, 'c', 0x44FF00)); + add(buttonY = createButton(FlxG.width - 258, FlxG.height - 255, 132, 127, 'y', 0x4A35B9)); + add(buttonB = createButton(FlxG.width - 258, FlxG.height - 135, 132, 127, 'b', 0xFFCB00)); + add(buttonZ = createButton(FlxG.width - 132, FlxG.height - 255, 132, 127, 'z', 0xCCB98E)); + add(buttonA = createButton(FlxG.width - 132, FlxG.height - 135, 132, 127, 'a', 0xFF0000)); + case NONE: // do nothing + } + } + + /** + * Clean up memory. + */ + override public function destroy():Void { + super.destroy(); + + buttonLeft = null; + buttonUp = null; + buttonDown = null; + buttonRight = null; + + buttonLeft2 = null; + buttonUp2 = null; + buttonDown2 = null; + buttonRight2 = null; + + buttonA = null; + buttonB = null; + buttonC = null; + buttonD = null; + buttonE = null; + buttonV = null; + buttonX = null; + buttonY = null; + buttonZ = null; + } + + private function createButton(X:Float, Y:Float, Width:Int, Height:Int, Graphic:String, Color:Int = 0xFFFFFF):FlxButton { + var button:FlxButton = new FlxButton(X, Y); + button.frames = FlxTileFrames.fromFrame(FlxAtlasFrames.fromSparrow(Assets.getBitmapData('assets/android/virtualpad.png'), + Assets.getText('assets/android/virtualpad.xml')) + .getByName(Graphic), + FlxPoint.get(Width, Height)); + button.resetSizeFromFrame(); + button.moves = false; + button.solid = false; + button.immovable = true; + button.scrollFactor.set(); + button.color = Color; + button.alpha = ClientPrefs.virtualPadAlpha; + #if FLX_DEBUG + button.ignoreDrawDebug = true; + #end + return button; + } +} + +enum FlxDPadMode { + UP_DOWN; + LEFT_RIGHT; + UP_LEFT_RIGHT; + LEFT_FULL; + RIGHT_FULL; + BOTH_FULL; + NONE; +} + +enum FlxActionMode { + A; + B; + A_B; + A_B_C; + A_B_E; + A_B_X_Y; + A_B_C_X_Y; + A_B_C_X_Y_Z; + A_B_C_D_V_X_Y_Z; + NONE; +} diff --git a/source/import.hx b/source/import.hx index ba6ff0f0190..e6a07dcabda 100644 --- a/source/import.hx +++ b/source/import.hx @@ -1,2 +1,3 @@ import Paths; -import haxe.ds.Vector as HaxeVector; //apparently denpa uses vectors, which is required for camera panning i guess \ No newline at end of file +import haxe.ds.Vector as HaxeVector; //apparently denpa uses vectors, which is required for camera panning i guess +import flixel.group.FlxSpriteGroup; \ No newline at end of file diff --git a/source/options/OptionsState.hx b/source/options/OptionsState.hx index 39bd94fbfd7..631b62d20c3 100644 --- a/source/options/OptionsState.hx +++ b/source/options/OptionsState.hx @@ -81,6 +81,7 @@ class OptionsState extends MusicBeatState var selectorLeft:Alphabet; var selectorRight:Alphabet; var customizeAndroidControlsTipText:FlxText; + var androidControlsStyleTipText:FlxText; override function create() { Paths.clearStoredMemory(); @@ -118,8 +119,22 @@ class OptionsState extends MusicBeatState ClientPrefs.saveSettings(); #if android - addVirtualPad(UP_DOWN, A_B_C); - virtualPad.y = -42; + addVirtualPad(UP_DOWN, A_B_X_Y); + virtualPad.y = -44; + #end + + #if android + androidControlsStyleTipText = new FlxText(10, FlxG.height - 44, 0, 'Press Y to customize your opacity for hitbox, virtual pads and hitbox style!', 16); + customizeAndroidControlsTipText = new FlxText(10, FlxG.height - 24, 0, 'Press X to customize your android controls!', 16); + androidControlsStyleTipText.setFormat("VCR OSD Mono", 17, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + customizeAndroidControlsTipText.setFormat("VCR OSD Mono", 17, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); + + androidControlsStyleTipText.borderSize = 1.25; + androidControlsStyleTipText.scrollFactor.set(); + customizeAndroidControlsTipText.borderSize = 1.25; + customizeAndroidControlsTipText.scrollFactor.set(); + add(androidControlsStyleTipText); + add(customizeAndroidControlsTipText); #end super.create(); @@ -154,6 +169,20 @@ class OptionsState extends MusicBeatState if (controls.ACCEPT) { openSelectedSubstate(options[curSelected]); } + #if android + if (virtualPad.buttonX.justPressed) { + #if android + removeVirtualPad(); + #end + openSubState(new android.AndroidControlsSubState()); + } + if (virtualPad.buttonY.justPressed) { + #if android + removeVirtualPad(); + #end + openSubState(new android.AndroidControlsSettingsSubState()); + } + #end if (FlxG.keys.justPressed.ANY) { var k = keys[kId];