From 99f6ad9d500715d0415d4ef7801b3c450147ae05 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Mon, 15 Feb 2021 11:43:51 -0600 Subject: [PATCH 01/37] wtf am i doing --- README.md | 7 +- source/MainMenuState.hx | 207 ++++++++++++++------------------------ source/NGio.hx | 26 +++-- source/ui/MenuItemList.hx | 154 ++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+), 139 deletions(-) create mode 100644 source/ui/MenuItemList.hx diff --git a/README.md b/README.md index 8b70997e2..b7cc56c49 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ haxelib git polymod https://github.com/larsiusprime/polymod.git ### Ignored files I gitignore the API keys for the game, so that no one can nab them and post fake highscores on the leaderboards. But because of that the game -doesn't compile without it. +doesn't compile without it. Below is a version of APIStuff that points at a debug NG project for the game. Just make a file in `/source` and call it `APIStuff.hx`, and copy paste this into it @@ -57,8 +57,9 @@ package; class APIStuff { - public static var API:String = ""; - public static var EncKey:String = ""; + inline public static var API:String = "51348:TtzK0rZ8"; + inline public static var EncKey:String = "5NqKsSVSNKHbF9fPgZPqPg=="; + inline public static var SESSION:String = null; } ``` diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index 4b6a0464d..b25db84b1 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -1,5 +1,8 @@ package; +import flixel.util.FlxTimer; +import flixel.FlxState; +import cpp.abi.Abi; import flixel.FlxG; import flixel.FlxObject; import flixel.FlxSprite; @@ -14,19 +17,13 @@ import flixel.util.FlxColor; import io.newgrounds.NG; import lime.app.Application; +import ui.MenuItemList; + using StringTools; class MainMenuState extends MusicBeatState { - var curSelected:Int = 0; - - var menuItems:FlxTypedGroup; - - #if !switch - var optionShit:Array = ['story mode', 'freeplay', 'donate']; - #else - var optionShit:Array = ['story mode', 'freeplay']; - #end + var menuItems:MenuItemList; var magenta:FlxSprite; var camFollow:FlxObject; @@ -67,23 +64,38 @@ class MainMenuState extends MusicBeatState add(magenta); // magenta.scrollFactor.set(); - menuItems = new FlxTypedGroup(); + menuItems = new MenuItemList('FNF_main_menu_assets'); add(menuItems); - - var tex = Paths.getSparrowAtlas('FNF_main_menu_assets'); - - for (i in 0...optionShit.length) + menuItems.onChange.add(onMenuItemChange); + menuItems.onAcceptPress.add(function(_) { - var menuItem:FlxSprite = new FlxSprite(0, 60 + (i * 160)); - menuItem.frames = tex; - menuItem.animation.addByPrefix('idle', optionShit[i] + " basic", 24); - menuItem.animation.addByPrefix('selected', optionShit[i] + " white", 24); - menuItem.animation.play('idle'); - menuItem.ID = i; - menuItem.screenCenter(X); - menuItems.add(menuItem); - menuItem.scrollFactor.set(); - menuItem.antialiasing = true; + FlxFlicker.flicker(magenta, 1.1, 0.15, false, true); + }); + + + var hasPopupBlocker = #if web true #else false #end; + + menuItems.addItem('story mode', function () startExitState(new StoryMenuState())); + menuItems.addItem('freeplay', function () startExitState(new FreeplayState())); + // addMenuItem('options', function () startExitState(new OptionMenu())); + #if (!switch) + menuItems.addItem('donate', selectDonate, hasPopupBlocker); + #end + #if newgrounds + if (NG.core.loggedIn) + menuItems.addItem("logout", selectLogout); + else + menuItems.addItem("login", selectLogin, hasPopupBlocker); + #end + + // center vertically + var spacing = 160; + var top = (FlxG.height - (spacing * (menuItems.length - 1))) / 2; + for (i in 0...menuItems.length) + { + var menuItem = menuItems.members[i]; + menuItem.x = FlxG.width / 2; + menuItem.y = top + spacing * i; } FlxG.camera.follow(camFollow, null, 0.06); @@ -95,12 +107,48 @@ class MainMenuState extends MusicBeatState // NG.core.calls.event.logEvent('swag').send(); - changeItem(); - super.create(); } - - var selectedSomethin:Bool = false; + + function onMenuItemChange(selected:MenuItem) + { + camFollow.setPosition(selected.getGraphicMidpoint().x, selected.getGraphicMidpoint().y); + } + + function selectDonate() + { + #if linux + Sys.command('/usr/bin/xdg-open', ["https://ninja-muffin24.itch.io/funkin", "&"]); + #else + FlxG.openURL('https://ninja-muffin24.itch.io/funkin'); + #end + } + + function selectLogin() + { + } + + function selectLogout() + { + } + + function startExitState(state:FlxState) + { + var duration = 0.4; + menuItems.forEach(function(item) + { + if (menuItems.selectedIndex != item.ID) + { + FlxTween.tween(item, {alpha: 0}, duration, { ease: FlxEase.quadOut }); + } + else + { + item.visible = false; + } + }); + + new FlxTimer().start(duration, function(_) FlxG.switchState(state)); + } override function update(elapsed:Float) { @@ -109,108 +157,9 @@ class MainMenuState extends MusicBeatState FlxG.sound.music.volume += 0.5 * FlxG.elapsed; } - if (!selectedSomethin) - { - if (controls.UP_P) - { - FlxG.sound.play(Paths.sound('scrollMenu')); - changeItem(-1); - } - - if (controls.DOWN_P) - { - FlxG.sound.play(Paths.sound('scrollMenu')); - changeItem(1); - } - - if (controls.BACK) - { - FlxG.switchState(new TitleState()); - } - - if (controls.ACCEPT) - { - if (optionShit[curSelected] == 'donate') - { - #if linux - Sys.command('/usr/bin/xdg-open', ["https://ninja-muffin24.itch.io/funkin", "&"]); - #else - FlxG.openURL('https://ninja-muffin24.itch.io/funkin'); - #end - } - else - { - selectedSomethin = true; - FlxG.sound.play(Paths.sound('confirmMenu')); - - FlxFlicker.flicker(magenta, 1.1, 0.15, false); - - menuItems.forEach(function(spr:FlxSprite) - { - if (curSelected != spr.ID) - { - FlxTween.tween(spr, {alpha: 0}, 0.4, { - ease: FlxEase.quadOut, - onComplete: function(twn:FlxTween) - { - spr.kill(); - } - }); - } - else - { - FlxFlicker.flicker(spr, 1, 0.06, false, false, function(flick:FlxFlicker) - { - var daChoice:String = optionShit[curSelected]; - - switch (daChoice) - { - case 'story mode': - FlxG.switchState(new StoryMenuState()); - trace("Story Menu Selected"); - case 'freeplay': - FlxG.switchState(new FreeplayState()); - - trace("Freeplay Menu Selected"); - - case 'options': - FlxG.switchState(new OptionsMenu()); - } - }); - } - }); - } - } - } + if (menuItems.active && controls.BACK) + FlxG.switchState(new TitleState()); super.update(elapsed); - - menuItems.forEach(function(spr:FlxSprite) - { - spr.screenCenter(X); - }); - } - - function changeItem(huh:Int = 0) - { - curSelected += huh; - - if (curSelected >= menuItems.length) - curSelected = 0; - if (curSelected < 0) - curSelected = menuItems.length - 1; - - menuItems.forEach(function(spr:FlxSprite) - { - spr.animation.play('idle'); - - if (spr.ID == curSelected) - { - spr.animation.play('selected'); - camFollow.setPosition(spr.getGraphicMidpoint().x, spr.getGraphicMidpoint().y); - } - - spr.updateHitbox(); - }); } } diff --git a/source/NGio.hx b/source/NGio.hx index 0c2631b86..82188925d 100644 --- a/source/NGio.hx +++ b/source/NGio.hx @@ -4,6 +4,7 @@ import flixel.FlxG; import flixel.util.FlxSignal; import flixel.util.FlxTimer; import io.newgrounds.NG; +import io.newgrounds.NGLite; import io.newgrounds.components.ScoreBoardComponent.Period; import io.newgrounds.objects.Medal; import io.newgrounds.objects.Score; @@ -43,7 +44,7 @@ class NGio { var call = NG.core.calls.app.getCurrentVersion(GAME_VER).addDataHandler(function(response:Response) { - GAME_VER = response.result.data.current_version; + GAME_VER = response.result.data.currentVersion; trace('CURRENT NG VERSION: ' + GAME_VER); gotOnlineVer = true; }); @@ -53,18 +54,28 @@ class NGio } } - public function new(api:String, encKey:String, ?sessionId:String) + public function new(api:String, encKey:String) { trace("connecting to newgrounds"); - - NG.createAndCheckSession(api, sessionId); - + + var sessionId:String = NGLite.getSessionId(); + if (sessionId != null) + trace("found web session id"); + + #if (debug) + if (sessionId == null && APIStuff.SESSION != null) + { + sessionId = APIStuff.SESSION; + trace("using debug session id"); + } + #end + + + NG.create(api, sessionId); NG.core.verbose = true; // Set the encryption cipher/format to RC4/Base64. AES128 and Hex are not implemented yet NG.core.initEncryption(encKey); // Found in you NG project view - trace(NG.core.attemptingLogin); - if (NG.core.attemptingLogin) { /* a session_id was found in the loadervars, this means the user is playing on newgrounds.com @@ -73,6 +84,7 @@ class NGio trace("attempting login"); NG.core.onLogin.add(onNGLogin); } + //GK: taking out auto login, adding a login button to the main menu else { /* They are NOT playing on newgrounds.com, no session id was found. We must start one manually, if we want to. diff --git a/source/ui/MenuItemList.hx b/source/ui/MenuItemList.hx new file mode 100644 index 000000000..491a39b02 --- /dev/null +++ b/source/ui/MenuItemList.hx @@ -0,0 +1,154 @@ +package ui; + +import flixel.util.typeLimit.OneOfTwo; +import flixel.math.FlxPoint; +import flixel.FlxG; +import flixel.effects.FlxFlicker; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.group.FlxGroup; +import flixel.tweens.FlxEase; +import flixel.tweens.FlxTween; +import flixel.util.FlxSignal; + +typedef ItemAsset = OneOfTwo + +class MenuItemList extends MenuTypedItemList +{ + public function addItem(x = 0.0, y = 0.0, name, callback, fireInstantly = false) + { + var i = length; + var menuItem = new MenuItem(name, tex, callback, x, y); + menuItem.fireInstantly = fireInstantly; + menuItem.ID = i; + add(menuItem); + + if (i == selectedIndex) + menuItem.select(); + + return menuItem; + } +} + +class MenuTypedItemList extends FlxTypedGroup +{ + public var tex:FlxAtlasFrames; + public var selectedIndex = 0; + public var onChange(default, null) = new FlxTypedSignalVoid>(); + public var onAcceptPress(default, null) = new FlxTypedSignalVoid>(); + + public function new (asset:ItemAsset) + { + super(); + + if (Std.is(asset, String)) + tex = Paths.getSparrowAtlas(cast asset); + else + tex = cast asset; + } + + override function update(elapsed:Float) + { + super.update(elapsed); + + var controls = PlayerSettings.player1.controls; + + if (controls.UP_P) + prev(); + + if (controls.DOWN_P) + next(); + + if (controls.ACCEPT) + accept(); + } + + public function accept() + { + var selected = members[selectedIndex]; + if (selected.fireInstantly) + selected.callback(); + else + { + active = false; + FlxG.sound.play(Paths.sound('confirmMenu')); + FlxFlicker.flicker(selected, 1, 0.06, true, false, function(_) + { + selected.callback(); + active = true; + }); + } + } + + inline function prev() changeItem(-1); + inline function next() changeItem(1); + + function changeItem(amount:Int) + { + FlxG.sound.play(Paths.sound('scrollMenu')); + members[selectedIndex].idle(); + + selectedIndex += amount; + + if (selectedIndex >= length) + selectedIndex = 0; + else if (selectedIndex < 0) + selectedIndex = length - 1; + + var selected = members[selectedIndex]; + selected.select(); + onChange.dispatch(selected); + } + + override function destroy() + { + super.destroy(); + tex = null; + } +} + +class MenuItem extends flixel.FlxSprite +{ + public var callback:Void->Void; + /** + * Set to true for things like opening URLs otherwise, it may it get blocked. + */ + public var fireInstantly = false; + + public function new (name, tex, callback, x = 0.0, y = 0.0) + { + super(x, y); + + frames = tex; + setItem(name, callback); + } + + public function setItem(name:String, callback:Void->Void) + { + this.callback = callback; + + animation.addByPrefix('idle', '$name basic', 24); + animation.addByPrefix('selected', '$name white', 24); + idle(); + scrollFactor.set(); + antialiasing = true; + } + + function updateSize() + { + updateHitbox(); + centerOrigin(); + offset.copyFrom(origin); + } + + public function idle() + { + animation.play('idle'); + updateSize(); + } + + public function select() + { + animation.play('selected'); + updateSize(); + } +} \ No newline at end of file From d3a873037d2375929a35dae6c16b420d95d40270 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Mon, 15 Feb 2021 16:04:08 -0600 Subject: [PATCH 02/37] flicker on accept --- source/MainMenuState.hx | 5 ++--- source/ui/MenuItemList.hx | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index b25db84b1..a2d484650 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -1,11 +1,9 @@ package; -import flixel.util.FlxTimer; -import flixel.FlxState; -import cpp.abi.Abi; import flixel.FlxG; import flixel.FlxObject; import flixel.FlxSprite; +import flixel.FlxState; import flixel.addons.transition.FlxTransitionableState; import flixel.effects.FlxFlicker; import flixel.graphics.frames.FlxAtlasFrames; @@ -14,6 +12,7 @@ import flixel.text.FlxText; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.util.FlxColor; +import flixel.util.FlxTimer; import io.newgrounds.NG; import lime.app.Application; diff --git a/source/ui/MenuItemList.hx b/source/ui/MenuItemList.hx index 491a39b02..241aac43d 100644 --- a/source/ui/MenuItemList.hx +++ b/source/ui/MenuItemList.hx @@ -65,6 +65,8 @@ class MenuTypedItemList extends FlxTypedGroup public function accept() { var selected = members[selectedIndex]; + onAcceptPress.dispatch(selected); + if (selected.fireInstantly) selected.callback(); else From 80e7539debc3abd9d117822e961f2abd56e84a8d Mon Sep 17 00:00:00 2001 From: George FunBook Date: Thu, 18 Feb 2021 13:58:16 -0600 Subject: [PATCH 03/37] add prompt, finalize login UI --- Project.xml | 8 +- source/MainMenuState.hx | 166 ++++++++++++++++++++++++++++++++++++-- source/NGio.hx | 156 +++++++++++++++++++++++++---------- source/TitleState.hx | 42 +++++----- source/ui/MenuItemList.hx | 164 +++++++++++++++++++++++++++---------- source/ui/Prompt.hx | 120 +++++++++++++++++++++++++++ 6 files changed, 538 insertions(+), 118 deletions(-) create mode 100644 source/ui/Prompt.hx diff --git a/Project.xml b/Project.xml index f943faede..bb9ef84de 100644 --- a/Project.xml +++ b/Project.xml @@ -166,6 +166,12 @@ - + + + + + + + diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index a2d484650..db00ce94d 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -1,5 +1,7 @@ package; +import NGio; +import flixel.ui.FlxButton; import flixel.FlxG; import flixel.FlxObject; import flixel.FlxSprite; @@ -17,12 +19,13 @@ import io.newgrounds.NG; import lime.app.Application; import ui.MenuItemList; +import ui.Prompt; using StringTools; class MainMenuState extends MusicBeatState { - var menuItems:MenuItemList; + var menuItems:MainMenuItemList; var magenta:FlxSprite; var camFollow:FlxObject; @@ -63,7 +66,7 @@ class MainMenuState extends MusicBeatState add(magenta); // magenta.scrollFactor.set(); - menuItems = new MenuItemList('FNF_main_menu_assets'); + menuItems = new MainMenuItemList('FNF_main_menu_assets'); add(menuItems); menuItems.onChange.add(onMenuItemChange); menuItems.onAcceptPress.add(function(_) @@ -74,17 +77,18 @@ class MainMenuState extends MusicBeatState var hasPopupBlocker = #if web true #else false #end; - menuItems.addItem('story mode', function () startExitState(new StoryMenuState())); - menuItems.addItem('freeplay', function () startExitState(new FreeplayState())); + menuItems.enabled = false;// disable for intro + menuItems.createItem('story mode', function () startExitState(new StoryMenuState())); + menuItems.createItem('freeplay', function () startExitState(new FreeplayState())); // addMenuItem('options', function () startExitState(new OptionMenu())); #if (!switch) - menuItems.addItem('donate', selectDonate, hasPopupBlocker); + menuItems.createItem('donate', selectDonate, hasPopupBlocker); #end #if newgrounds if (NG.core.loggedIn) - menuItems.addItem("logout", selectLogout); + menuItems.createItem("logout", selectLogout); else - menuItems.addItem("login", selectLogin, hasPopupBlocker); + menuItems.createItem("login", selectLogin); #end // center vertically @@ -109,6 +113,16 @@ class MainMenuState extends MusicBeatState super.create(); } + override function finishTransIn() + { + super.finishTransIn(); + + menuItems.enabled = true; + + if (NGio.savedSessionFailed) + showSavedSessionFailed(); + } + function onMenuItemChange(selected:MenuItem) { camFollow.setPosition(selected.getGraphicMidpoint().x, selected.getGraphicMidpoint().y); @@ -123,13 +137,101 @@ class MainMenuState extends MusicBeatState #end } + #if newgrounds function selectLogin() { + showNgPrompt(true); + } + + function showSavedSessionFailed() + { + showNgPrompt(false); + } + + function showNgPrompt(fromUi:Bool) + { + menuItems.enabled = false; + + var prompt = new Prompt("prompt-ng_login", "Talking to server...", None); + prompt.closeCallback = function() menuItems.enabled = true; + openSubState(prompt); + function onLoginComplete(result:ConnectionResult) + { + switch (result) + { + case Success: + menuItems.resetItem("login", "logout", selectLogout); + prompt.setText("Login Successful"); + prompt.setButtons(Ok); + prompt.onYes = prompt.close; + case Fail(msg): + trace("Login Error:" + msg); + prompt.setText("Login failed"); + prompt.setButtons(Ok); + prompt.onYes = prompt.close; + case Cancelled: + if (prompt != null) + { + prompt.setText("Login cancelled by user"); + prompt.setButtons(Ok); + prompt.onYes = prompt.close; + } + } + } + + NGio.login + ( + function popupLauncher(openPassportUrl) + { + var choiceMsg = fromUi + ? #if web "Log in to Newgrounds?" #else null #end // User-input needed to allow popups + : "Your session has expired.\n Please login again."; + + if (choiceMsg != null) + { + prompt.setText(choiceMsg); + prompt.setButtons(Yes_No); + #if web + prompt.buttons.getItem("yes").fireInstantly = true; + #end + prompt.onYes = function() + { + prompt.setText("Connecting..."); + prompt.setButtons(None); + openPassportUrl(); + }; + prompt.onNo = function() + { + prompt.close(); + prompt = null; + NG.core.cancelLoginRequest(); + }; + } + else + { + prompt.setText("Connecting..."); + openPassportUrl(); + } + }, + onLoginComplete + ); } function selectLogout() { + menuItems.enabled = false; + var prompt = new Prompt("prompt-ng_login", "Log out of " + NG.core.user.name + "?", Yes_No); + prompt.closeCallback = function () menuItems.enabled = true; + prompt.onYes = function() + { + NGio.logout(); + prompt.close(); + menuItems.resetItem("logout", "login", selectLogin); + }; + prompt.onNo = prompt.close; + openSubState(prompt); } + #end function startExitState(state:FlxState) { @@ -156,9 +258,57 @@ class MainMenuState extends MusicBeatState FlxG.sound.music.volume += 0.5 * FlxG.elapsed; } - if (menuItems.active && controls.BACK) + if (menuItems.enabled && controls.BACK) FlxG.switchState(new TitleState()); super.update(elapsed); } } + + +private class MainMenuItemList extends MenuTypedItemList +{ + public var atlas:FlxAtlasFrames; + + public function new (atlas) + { + super(Vertical); + + if (Std.is(atlas, String)) + this.atlas = Paths.getSparrowAtlas(cast atlas); + else + this.atlas = cast atlas; + } + + public function createItem(x = 0.0, y = 0.0, name:String, callback, fireInstantly = false) + { + var i = length; + var item = new MainMenuItem(x, y, name, atlas, callback); + item.fireInstantly = fireInstantly; + item.ID = i; + + return addItem(name, item); + } + + override function destroy() + { + super.destroy(); + atlas = null; + } +} +private class MainMenuItem extends MenuItem +{ + public function new(x = 0.0, y = 0.0, name, atlas, callback) + { + super(x, y, name, atlas, callback); + scrollFactor.set(); + } + + override function changeAnim(anim:String) + { + super.changeAnim(anim); + // position by center + centerOrigin(); + offset.copyFrom(origin); + } +} \ No newline at end of file diff --git a/source/NGio.hx b/source/NGio.hx index ec48ca613..b05b7e8aa 100644 --- a/source/NGio.hx +++ b/source/NGio.hx @@ -6,6 +6,7 @@ import flixel.util.FlxTimer; import io.newgrounds.NG; import io.newgrounds.NGLite; import io.newgrounds.components.ScoreBoardComponent.Period; +import io.newgrounds.objects.Error; import io.newgrounds.objects.Medal; import io.newgrounds.objects.Score; import io.newgrounds.objects.ScoreBoard; @@ -22,6 +23,11 @@ using StringTools; */ class NGio { + /** + * True, if the saved sessionId was used in the initial login, and failed to connect. + * Used in MainMenuState to show a popup to establish a new connection + */ + public static var savedSessionFailed(default, null):Bool = false; public static var isLoggedIn:Bool = false; public static var scoreboardsLoaded:Bool = false; @@ -31,54 +37,68 @@ class NGio public static var ngScoresLoaded(default, null):FlxSignal = new FlxSignal(); public static var GAME_VER:String = ""; - public static var GAME_VER_NUMS:String = ''; - public static var gotOnlineVer:Bool = false; + - public static function noLogin(api:String) + static public function checkVersion(callback:String->Void) { - trace('INIT NOLOGIN'); + trace('checking NG.io version'); GAME_VER = "v" + Application.current.meta.get('version'); - if (api.length != 0) - { - NG.create(api); - - new FlxTimer().start(2, function(tmr:FlxTimer) + NG.core.calls.app.getCurrentVersion(GAME_VER) + .addDataHandler(function(response) { - var call = NG.core.calls.app.getCurrentVersion(GAME_VER).addDataHandler(function(response:Response) - { - GAME_VER = response.result.data.currentVersion; - GAME_VER_NUMS = GAME_VER.split(" ")[0].trim(); - trace('CURRENT NG VERSION: ' + GAME_VER); - gotOnlineVer = true; - }); - - call.send(); - }); - } + GAME_VER = response.result.data.currentVersion; + trace('CURRENT NG VERSION: ' + GAME_VER); + callback(GAME_VER); + }) + .send(); } - public function new(api:String, encKey:String) + static public function init(api:String, encKey:String) { + var api = APIStuff.API; + if (api == null || api.length == 0) + { + trace("Missing Newgrounds API key, aborting connection"); + return; + } trace("connecting to newgrounds"); - var sessionId:String = NGLite.getSessionId(); - if (sessionId != null) - trace("found web session id"); + #if NG_FORCE_EXPIRED_SESSION + var sessionId:String = "fake_session_id"; + function onSessionFail(error:Error) + { + trace("Forcing an expired saved session. " + + "To disable, comment out NG_FORCE_EXPIRED_SESSION in Project.xml"); + savedSessionFailed = true; + } + #else + var sessionId:String = NGLite.getSessionId(); + if (sessionId != null) + trace("found web session id"); + + #if (debug) + if (sessionId == null && APIStuff.SESSION != null) + { + trace("using debug session id"); + sessionId = APIStuff.SESSION; + } + #end - #if (debug) - if (sessionId == null && APIStuff.SESSION != null) - { - sessionId = APIStuff.SESSION; - trace("using debug session id"); - } + var onSessionFail:Error->Void = null; + if (sessionId == null && FlxG.save.data.sessionId != null) + { + trace("using stored session id"); + sessionId = FlxG.save.data.sessionId; + onSessionFail = function (error) savedSessionFailed = true; + } #end + NG.create(api, sessionId, #if NG_DEBUG true #else false #end, onSessionFail); - NG.create(api, sessionId); - NG.core.verbose = true; + #if NG_VERBOSE NG.core.verbose = true; #end // Set the encryption cipher/format to RC4/Base64. AES128 and Hex are not implemented yet - NG.core.initEncryption(encKey); // Found in you NG project view + NG.core.initEncryption(APIStuff.EncKey); // Found in you NG project view if (NG.core.attemptingLogin) { @@ -89,21 +109,53 @@ class NGio NG.core.onLogin.add(onNGLogin); } //GK: taking out auto login, adding a login button to the main menu - else + // else + // { + // /* They are NOT playing on newgrounds.com, no session id was found. We must start one manually, if we want to. + // * Note: This will cause a new browser window to pop up where they can log in to newgrounds + // */ + // NG.core.requestLogin(onNGLogin); + // } + } + + /** + * Attempts to log in to newgrounds by requesting a new session ID, only call if no session ID was found automatically + * @param popupLauncher The function to call to open the login url, must be inside + * a user input event or the popup blocker will block it. + * @param onComplete A callback with the result of the connection. + */ + static public function login(?popupLauncher:(Void->Void)->Void, onComplete:ConnectionResult->Void) + { + trace("Logging in manually"); + var onPending:Void->Void = null; + if (popupLauncher != null) { - /* They are NOT playing on newgrounds.com, no session id was found. We must start one manually, if we want to. - * Note: This will cause a new browser window to pop up where they can log in to newgrounds - */ - NG.core.requestLogin(onNGLogin); + onPending = function () popupLauncher(NG.core.openPassportUrl); } + + var onSuccess:Void->Void = onNGLogin; + var onFail:Error->Void = null; + var onCancel:Void->Void = null; + if (onComplete != null) + { + onSuccess = function () + { + onNGLogin(); + onComplete(Success); + } + onFail = function (e) onComplete(Fail(e.message)); + onCancel = function() onComplete(Cancelled); + } + + NG.core.requestLogin(onSuccess, onPending, onFail, onCancel); } - function onNGLogin():Void + static function onNGLogin():Void { trace('logged in! user:${NG.core.user.name}'); isLoggedIn = true; FlxG.save.data.sessionId = NG.core.sessionId; - // FlxG.save.flush(); + FlxG.save.flush(); // Load medals then call onNGMedalFetch() NG.core.requestMedals(onNGMedalFetch); @@ -112,9 +164,17 @@ class NGio ngDataLoaded.dispatch(); } + + static public function logout() + { + NG.core.logOut(); + + FlxG.save.data.sessionId = null; + FlxG.save.flush(); + } // --- MEDALS - function onNGMedalFetch():Void + static function onNGMedalFetch():Void { /* // Reading medal info @@ -132,7 +192,7 @@ class NGio } // --- SCOREBOARDS - function onNGBoardsFetch():Void + static function onNGBoardsFetch():Void { /* // Reading medal info @@ -174,7 +234,7 @@ class NGio } } - function onNGScoresFetch():Void + static function onNGScoresFetch():Void { scoreboardsLoaded = true; @@ -209,3 +269,13 @@ class NGio } } } + +enum ConnectionResult +{ + /** Log in successful */ + Success; + /** Could not login */ + Fail(msg:String); + /** User cancelled the login */ + Cancelled; +} diff --git a/source/TitleState.hx b/source/TitleState.hx index 8a8aeb42b..ffc691947 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -54,17 +54,11 @@ class TitleState extends MusicBeatState super.create(); - NGio.noLogin(APIStuff.API); - - #if ng - var ng:NGio = new NGio(APIStuff.API, APIStuff.EncKey); - trace('NEWGROUNDS LOL'); - #end - FlxG.save.bind('funkin', 'ninjamuffin99'); - Highscore.load(); + NGio.init(APIStuff.API, APIStuff.EncKey); + if (FlxG.save.data.weekUnlocked != null) { // FIX LATER!!! @@ -264,22 +258,26 @@ class TitleState extends MusicBeatState transitioning = true; // FlxG.sound.music.stop(); - new FlxTimer().start(2, function(tmr:FlxTimer) + if (!OutdatedSubState.leftState) { - // Check if version is outdated - - var version:String = "v" + Application.current.meta.get('version'); - - if (version.trim() != NGio.GAME_VER_NUMS && !OutdatedSubState.leftState) + NGio.checkVersion(function(version) { - trace('OLD VERSION!'); - FlxG.switchState(new OutdatedSubState()); - } - else - { - FlxG.switchState(new MainMenuState()); - } - }); + // Check if version is outdated + + var localVersion:String = "v" + Application.current.meta.get('version'); + var onlineVersion = version.split(" ")[0].trim(); + + if (version.trim() != onlineVersion) + { + trace('OLD VERSION!'); + FlxG.switchState(new OutdatedSubState()); + } + else + { + FlxG.switchState(new MainMenuState()); + } + }); + } // FlxG.sound.play(Paths.music('titleShoot'), 0.7); } diff --git a/source/ui/MenuItemList.hx b/source/ui/MenuItemList.hx index 241aac43d..a79ca1f2b 100644 --- a/source/ui/MenuItemList.hx +++ b/source/ui/MenuItemList.hx @@ -10,53 +10,110 @@ import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.util.FlxSignal; -typedef ItemAsset = OneOfTwo +typedef AtlasAsset = OneOfTwo; class MenuItemList extends MenuTypedItemList { - public function addItem(x = 0.0, y = 0.0, name, callback, fireInstantly = false) + public var atlas:FlxAtlasFrames; + + public function new (atlas, navControls:NavControls = Vertical) { - var i = length; - var menuItem = new MenuItem(name, tex, callback, x, y); - menuItem.fireInstantly = fireInstantly; - menuItem.ID = i; - add(menuItem); + super(navControls); - if (i == selectedIndex) - menuItem.select(); - - return menuItem; + if (Std.is(atlas, String)) + this.atlas = Paths.getSparrowAtlas(cast atlas); + else + this.atlas = cast atlas; + } + + public function createItem(x = 0.0, y = 0.0, name, callback, fireInstantly = false) + { + var item = new MenuItem(x, y, name, atlas, callback); + item.fireInstantly = fireInstantly; + return addItem(name, item); + } + + override function destroy() + { + super.destroy(); + atlas = null; } } class MenuTypedItemList extends FlxTypedGroup { - public var tex:FlxAtlasFrames; - public var selectedIndex = 0; + public var selectedIndex(default, null) = 0; + /** Called when a new item is highlighted */ public var onChange(default, null) = new FlxTypedSignalVoid>(); + /** Called when an item is accepted */ public var onAcceptPress(default, null) = new FlxTypedSignalVoid>(); + /** The navigation control scheme to use */ + public var navControls:NavControls; + /** Set to false to disable nav control */ + public var enabled:Bool = true; - public function new (asset:ItemAsset) + var byName = new Map(); + /** Set to true, internally to disable controls, without affecting vars like `enabled` */ + var busy:Bool = false; + + public function new (navControls:NavControls = Vertical) { + this.navControls = navControls; super(); + } + + function addItem(name:String, item:T):T + { + if (length == selectedIndex) + item.select(); - if (Std.is(asset, String)) - tex = Paths.getSparrowAtlas(cast asset); - else - tex = cast asset; + byName[name] = item; + return add(item); + } + + public function resetItem(oldName:String, newName:String, ?callback:Void->Void):T + { + if (!byName.exists(oldName)) + throw "No item named:" + oldName; + + var item = byName[oldName]; + byName.remove(oldName); + byName[newName] = item; + item.setItem(newName, callback); + + return item; } override function update(elapsed:Float) { super.update(elapsed); + if (enabled && !busy) + updateControls(); + } + + inline function updateControls() + { var controls = PlayerSettings.player1.controls; - if (controls.UP_P) - prev(); - - if (controls.DOWN_P) - next(); + switch(navControls) + { + case Vertical: + { + if (controls.UP_P ) prev(); + if (controls.DOWN_P) next(); + } + case Horizontal: + { + if (controls.LEFT_P ) prev(); + if (controls.RIGHT_P) next(); + } + case Both: + { + if (controls.LEFT_P || controls.UP_P ) prev(); + if (controls.RIGHT_P || controls.DOWN_P) next(); + } + } if (controls.ACCEPT) accept(); @@ -71,12 +128,12 @@ class MenuTypedItemList extends FlxTypedGroup selected.callback(); else { - active = false; + busy = true; FlxG.sound.play(Paths.sound('confirmMenu')); FlxFlicker.flicker(selected, 1, 0.06, true, false, function(_) { + busy = false; selected.callback(); - active = true; }); } } @@ -87,24 +144,35 @@ class MenuTypedItemList extends FlxTypedGroup function changeItem(amount:Int) { FlxG.sound.play(Paths.sound('scrollMenu')); + var index = selectedIndex + amount; + if (index >= length) + index = 0; + else if (index < 0) + index = length - 1; + + selectItem(index); + } + + public function selectItem(index:Int) + { members[selectedIndex].idle(); - selectedIndex += amount; - - if (selectedIndex >= length) - selectedIndex = 0; - else if (selectedIndex < 0) - selectedIndex = length - 1; + selectedIndex = index; var selected = members[selectedIndex]; selected.select(); onChange.dispatch(selected); } + public function getItem(name:String) + { + return byName[name]; + } + override function destroy() { super.destroy(); - tex = null; + byName.clear(); } } @@ -116,41 +184,49 @@ class MenuItem extends flixel.FlxSprite */ public var fireInstantly = false; - public function new (name, tex, callback, x = 0.0, y = 0.0) + public function new (x = 0.0, y = 0.0, name, tex, callback) { super(x, y); frames = tex; setItem(name, callback); + antialiasing = true; } - public function setItem(name:String, callback:Void->Void) + public function setItem(name:String, ?callback:Void->Void) { - this.callback = callback; + if (callback != null) + this.callback = callback; + + var selected = animation.curAnim != null && animation.curAnim.name == "selected"; animation.addByPrefix('idle', '$name basic', 24); animation.addByPrefix('selected', '$name white', 24); idle(); - scrollFactor.set(); - antialiasing = true; + if (selected) + select(); } - function updateSize() + function changeAnim(anim:String) { + animation.play(anim); updateHitbox(); - centerOrigin(); - offset.copyFrom(origin); } public function idle() { - animation.play('idle'); - updateSize(); + changeAnim('idle'); } public function select() { - animation.play('selected'); - updateSize(); + changeAnim('selected'); } +} + +enum NavControls +{ + Horizontal; + Vertical; + Both; } \ No newline at end of file diff --git a/source/ui/Prompt.hx b/source/ui/Prompt.hx new file mode 100644 index 000000000..dea595252 --- /dev/null +++ b/source/ui/Prompt.hx @@ -0,0 +1,120 @@ +package ui; + +import flixel.FlxSprite; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.text.FlxText; +import flixel.util.FlxColor; + +class Prompt extends flixel.FlxSubState +{ + inline static var MARGIN = 100; + + public var onYes:Void->Void; + public var onNo:Void->Void; + public var buttons:MenuItemList; + public var field:FlxText; + public var back:FlxSprite; + + var style:ButtonStyle; + + public function new (atlas, text:String, style:ButtonStyle = Ok) + { + this.style = style; + super(); + + var texture:FlxAtlasFrames; + if (Std.is(atlas, String)) + texture = Paths.getSparrowAtlas(cast atlas); + else + texture = cast atlas; + + back = new FlxSprite(); + back.frames = texture; + back.animation.addByPrefix("idle", "back"); + back.scrollFactor.set(0, 0); + + buttons = new MenuItemList(texture, Horizontal); + + field = new FlxText(); + field.setFormat(Paths.font("vcr.ttf"), 64, FlxColor.BLACK, CENTER); + field.text = text; + field.scrollFactor.set(0, 0); + } + + override function create() + { + super.create(); + + back.animation.play("idle"); + back.updateHitbox(); + back.screenCenter(XY); + add(back); + + field.y = back.y + MARGIN; + field.screenCenter(X); + add(field); + + createButtons(); + add(buttons); + } + + public function setButtons(style:ButtonStyle) + { + if (this.style != style) + { + this.style = style; + createButtons(); + } + } + + function createButtons() + { + // destroy previous buttons + while(buttons.members.length > 0) + { + buttons.remove(buttons.members[0], true).destroy(); + } + + switch(style) + { + case Yes_No : createButtonsHelper("yes", "no"); + case Ok : createButtonsHelper("ok"); + case Custom(yes, no): createButtonsHelper(yes, no); + case None : buttons.exists = false; + }; + } + + function createButtonsHelper(yes:String, ?no:String) + { + buttons.exists = true; + // pass anonymous functions rather than the current callbacks, in case they change later + var yesButton = buttons.createItem(yes, function() onYes()); + yesButton.screenCenter(X); + yesButton.y = back.y + back.height - yesButton.height - MARGIN; + yesButton.scrollFactor.set(0, 0); + if (no != null) + { + // place right + yesButton.x = back.x + back.width - yesButton.width - MARGIN; + + var noButton = buttons.createItem(no, function() onNo()); + noButton.x = back.x + MARGIN; + noButton.y = back.y + back.height - noButton.height - MARGIN; + noButton.scrollFactor.set(0, 0); + } + } + + public function setText(text:String) + { + field.text = text; + field.screenCenter(X); + } +} + +enum ButtonStyle +{ + Ok; + Yes_No; + Custom(yes:String, no:Null);//Todo: more than 2 + None; +} \ No newline at end of file From e6b9ec21008c2586081cc4d5158b66af3dd0068c Mon Sep 17 00:00:00 2001 From: George FunBook Date: Fri, 19 Feb 2021 20:11:33 -0600 Subject: [PATCH 04/37] finalize prompts and uix --- Project.xml | 20 +++++++---- source/FreeplayState.hx | 6 ---- source/Highscore.hx | 40 ++++++++++++---------- source/MainMenuState.hx | 45 +++++++++++++++++------- source/NGio.hx | 72 +++++++++++++++++++++++++-------------- source/OptionsMenu.hx | 2 -- source/PlayState.hx | 2 -- source/StoryMenuState.hx | 6 ---- source/TitleState.hx | 15 ++++---- source/ui/MenuItemList.hx | 3 +- 10 files changed, 126 insertions(+), 85 deletions(-) diff --git a/Project.xml b/Project.xml index bb9ef84de..174fbf25b 100644 --- a/Project.xml +++ b/Project.xml @@ -113,7 +113,7 @@ - + @@ -167,11 +167,17 @@ - - - - - - + + +
+ + + + + + + + +
diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx index b39ebc973..872e44d27 100644 --- a/source/FreeplayState.hx +++ b/source/FreeplayState.hx @@ -211,9 +211,7 @@ class FreeplayState extends MusicBeatState if (curDifficulty > 2) curDifficulty = 0; - #if !switch intendedScore = Highscore.getScore(songs[curSelected], curDifficulty); - #end switch (curDifficulty) { @@ -228,9 +226,7 @@ class FreeplayState extends MusicBeatState function changeSelection(change:Int = 0) { - #if !switch NGio.logEvent('Fresh'); - #end // NGio.logEvent('Fresh'); FlxG.sound.play(Paths.sound('scrollMenu'), 0.4); @@ -244,10 +240,8 @@ class FreeplayState extends MusicBeatState // selector.y = (70 * curSelected) + 30; - #if !switch intendedScore = Highscore.getScore(songs[curSelected], curDifficulty); // lerpScore = 0; - #end #if PRELOAD_ALL FlxG.sound.playMusic(Paths.inst(songs[curSelected]), 0); diff --git a/source/Highscore.hx b/source/Highscore.hx index 5fbc73298..2fee324fd 100644 --- a/source/Highscore.hx +++ b/source/Highscore.hx @@ -13,51 +13,55 @@ class Highscore public static function saveScore(song:String, score:Int = 0, ?diff:Int = 0):Void { - var daSong:String = formatSong(song, diff); + var formattedSong:String = formatSong(song, diff); - - #if !switch + #if newgrounds NGio.postScore(score, song); #end - - if (songScores.exists(daSong)) + if (songScores.exists(formattedSong)) { - if (songScores.get(daSong) < score) - setScore(daSong, score); + if (songScores.get(formattedSong) < score) + setScore(formattedSong, score); } else - setScore(daSong, score); + setScore(formattedSong, score); } public static function saveWeekScore(week:Int = 1, score:Int = 0, ?diff:Int = 0):Void { - - #if !switch + #if newgrounds NGio.postScore(score, "Week " + week); #end + var formattedSong:String = formatSong('week' + week, diff); - var daWeek:String = formatSong('week' + week, diff); - - if (songScores.exists(daWeek)) + if (songScores.exists(formattedSong)) { - if (songScores.get(daWeek) < score) - setScore(daWeek, score); + if (songScores.get(formattedSong) < score) + setScore(formattedSong, score); } else - setScore(daWeek, score); + setScore(formattedSong, score); } /** * YOU SHOULD FORMAT SONG WITH formatSong() BEFORE TOSSING IN SONG VARIABLE */ - static function setScore(song:String, score:Int):Void + static function setScore(formattedSong:String, score:Int):Void { + /** GeoKureli + * References to Highscore were wrapped in `#if !switch` blocks. I wasn't sure if this + * is because switch doesn't use NGio, or because switch has a different saving method. + * I moved the compiler flag here, rather than using it everywhere else. + */ + #if !switch + // Reminder that I don't need to format this song, it should come formatted! - songScores.set(song, score); + songScores.set(formattedSong, score); FlxG.save.data.songScores = songScores; FlxG.save.flush(); + #end } public static function formatSong(song:String, diff:Int):String diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index db00ce94d..b207f97e5 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -15,7 +15,6 @@ import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.util.FlxColor; import flixel.util.FlxTimer; -import io.newgrounds.NG; import lime.app.Application; import ui.MenuItemList; @@ -81,11 +80,11 @@ class MainMenuState extends MusicBeatState menuItems.createItem('story mode', function () startExitState(new StoryMenuState())); menuItems.createItem('freeplay', function () startExitState(new FreeplayState())); // addMenuItem('options', function () startExitState(new OptionMenu())); - #if (!switch) + #if CAN_OPEN_LINKS menuItems.createItem('donate', selectDonate, hasPopupBlocker); #end #if newgrounds - if (NG.core.loggedIn) + if (NGio.isLoggedIn) menuItems.createItem("logout", selectLogout); else menuItems.createItem("login", selectLogin); @@ -119,8 +118,10 @@ class MainMenuState extends MusicBeatState menuItems.enabled = true; + #if newgrounds if (NGio.savedSessionFailed) showSavedSessionFailed(); + #end } function onMenuItemChange(selected:MenuItem) @@ -150,32 +151,37 @@ class MainMenuState extends MusicBeatState function showNgPrompt(fromUi:Bool) { - menuItems.enabled = false; - - var prompt = new Prompt("prompt-ng_login", "Talking to server...", None); - prompt.closeCallback = function() menuItems.enabled = true; + var prompt = createNGPrompt("Talking to server...", None); openSubState(prompt); function onLoginComplete(result:ConnectionResult) { switch (result) { case Success: + { menuItems.resetItem("login", "logout", selectLogout); prompt.setText("Login Successful"); prompt.setButtons(Ok); prompt.onYes = prompt.close; + } case Fail(msg): + { trace("Login Error:" + msg); prompt.setText("Login failed"); prompt.setButtons(Ok); prompt.onYes = prompt.close; + } case Cancelled: + { if (prompt != null) { prompt.setText("Login cancelled by user"); prompt.setButtons(Ok); prompt.onYes = prompt.close; } + else + trace("Login cancelled via prompt"); + } } } @@ -196,7 +202,7 @@ class MainMenuState extends MusicBeatState #end prompt.onYes = function() { - prompt.setText("Connecting..."); + prompt.setText("Connecting..." #if web + "\n(check your popup blocker)" #end); prompt.setButtons(None); openPassportUrl(); }; @@ -204,7 +210,7 @@ class MainMenuState extends MusicBeatState { prompt.close(); prompt = null; - NG.core.cancelLoginRequest(); + NGio.cancelLogin(); }; } else @@ -219,9 +225,8 @@ class MainMenuState extends MusicBeatState function selectLogout() { - menuItems.enabled = false; - var prompt = new Prompt("prompt-ng_login", "Log out of " + NG.core.user.name + "?", Yes_No); - prompt.closeCallback = function () menuItems.enabled = true; + var user = io.newgrounds.NG.core.user.name; + var prompt = createNGPrompt('Log out of $user?', Yes_No); prompt.onYes = function() { NGio.logout(); @@ -231,6 +236,22 @@ class MainMenuState extends MusicBeatState prompt.onNo = prompt.close; openSubState(prompt); } + + public function createNGPrompt(text:String, style:ButtonStyle = Yes_No) + { + var oldAutoPause = FlxG.autoPause; + FlxG.autoPause = false; + menuItems.enabled = false; + + var prompt = new Prompt("prompt-ng_login", text, style); + prompt.closeCallback = function () + { + menuItems.enabled = true; + FlxG.autoPause = oldAutoPause; + } + + return prompt; + } #end function startExitState(state:FlxState) diff --git a/source/NGio.hx b/source/NGio.hx index b05b7e8aa..f82323e4b 100644 --- a/source/NGio.hx +++ b/source/NGio.hx @@ -1,4 +1,5 @@ package; +#if newgrounds import flixel.FlxG; import flixel.util.FlxSignal; @@ -17,19 +18,24 @@ import lime.app.Application; import openfl.display.Stage; using StringTools; - +#end /** * MADE BY GEOKURELI THE LEGENED GOD HERO MVP */ class NGio { + #if newgrounds /** * True, if the saved sessionId was used in the initial login, and failed to connect. * Used in MainMenuState to show a popup to establish a new connection */ public static var savedSessionFailed(default, null):Bool = false; - public static var isLoggedIn:Bool = false; public static var scoreboardsLoaded:Bool = false; + public static var isLoggedIn(get, never):Bool; + inline static function get_isLoggedIn() + { + return NG.core != null && NG.core.loggedIn; + } public static var scoreboardArray:Array = []; @@ -38,7 +44,6 @@ class NGio public static var GAME_VER:String = ""; - static public function checkVersion(callback:String->Void) { trace('checking NG.io version'); @@ -54,7 +59,7 @@ class NGio .send(); } - static public function init(api:String, encKey:String) + static public function init() { var api = APIStuff.API; if (api == null || api.length == 0) @@ -149,11 +154,15 @@ class NGio NG.core.requestLogin(onSuccess, onPending, onFail, onCancel); } + + inline static public function cancelLogin():Void + { + NG.core.cancelLoginRequest(); + } static function onNGLogin():Void { trace('logged in! user:${NG.core.user.name}'); - isLoggedIn = true; FlxG.save.data.sessionId = NG.core.sessionId; FlxG.save.flush(); // Load medals then call onNGMedalFetch() @@ -216,24 +225,6 @@ class NGio // more info on scores --- http://www.newgrounds.io/help/components/#scoreboard-getscores } - inline static public function postScore(score:Int = 0, song:String) - { - if (isLoggedIn) - { - for (id in NG.core.scoreBoards.keys()) - { - var board = NG.core.scoreBoards.get(id); - - if (song == board.name) - { - board.postScore(score, "Uhh meow?"); - } - - // trace('loaded scoreboard id:$id, name:${board.name}'); - } - } - } - static function onNGScoresFetch():Void { scoreboardsLoaded = true; @@ -252,21 +243,52 @@ class NGio // NGio.scoreboardArray = NG.core.scoreBoards.get(8004).scores; } + #end - inline static public function logEvent(event:String) + static public function logEvent(event:String) { + #if newgrounds NG.core.calls.event.logEvent(event).send(); trace('should have logged: ' + event); + #else + #if debug trace('event:$event - not logged, missing NG.io lib'); #end + #end } - inline static public function unlockMedal(id:Int) + static public function unlockMedal(id:Int) { + #if newgrounds if (isLoggedIn) { var medal = NG.core.medals.get(id); if (!medal.unlocked) medal.sendUnlock(); } + #else + #if debug trace('medal:$id - not unlocked, missing NG.io lib'); #end + #end + } + + static public function postScore(score:Int = 0, song:String) + { + #if newgrounds + if (isLoggedIn) + { + for (id in NG.core.scoreBoards.keys()) + { + var board = NG.core.scoreBoards.get(id); + + if (song == board.name) + { + board.postScore(score, "Uhh meow?"); + } + + // trace('loaded scoreboard id:$id, name:${board.name}'); + } + } + #else + #if debug trace('Song:$song, Score:$score - not posted, missing NG.io lib'); #end + #end } } diff --git a/source/OptionsMenu.hx b/source/OptionsMenu.hx index bf36c83d5..a938495db 100644 --- a/source/OptionsMenu.hx +++ b/source/OptionsMenu.hx @@ -93,9 +93,7 @@ class OptionsMenu extends MusicBeatState function changeSelection(change:Int = 0) { - #if !switch NGio.logEvent('Fresh'); - #end FlxG.sound.play(Paths.sound('scrollMenu'), 0.4); diff --git a/source/PlayState.hx b/source/PlayState.hx index 647357157..3366edf0a 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1604,9 +1604,7 @@ class PlayState extends MusicBeatState vocals.volume = 0; if (SONG.validScore) { - #if !switch Highscore.saveScore(SONG.song, songScore, storyDifficulty); - #end } if (isStoryMode) diff --git a/source/StoryMenuState.hx b/source/StoryMenuState.hx index adb9d6cb3..b985369b8 100644 --- a/source/StoryMenuState.hx +++ b/source/StoryMenuState.hx @@ -352,10 +352,6 @@ class StoryMenuState extends MusicBeatState sprDifficulty.y = leftArrow.y - 15; intendedScore = Highscore.getWeekScore(curWeek, curDifficulty); - #if !switch - intendedScore = Highscore.getWeekScore(curWeek, curDifficulty); - #end - FlxTween.tween(sprDifficulty, {y: leftArrow.y + 15, alpha: 1}, 0.07); } @@ -431,8 +427,6 @@ class StoryMenuState extends MusicBeatState txtTracklist.screenCenter(X); txtTracklist.x -= FlxG.width * 0.35; - #if !switch intendedScore = Highscore.getWeekScore(curWeek, curDifficulty); - #end } } diff --git a/source/TitleState.hx b/source/TitleState.hx index ffc691947..2c3e2a43d 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -20,7 +20,6 @@ import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.util.FlxColor; import flixel.util.FlxTimer; -import io.newgrounds.NG; import lime.app.Application; import openfl.Assets; @@ -56,9 +55,11 @@ class TitleState extends MusicBeatState FlxG.save.bind('funkin', 'ninjamuffin99'); Highscore.load(); - - NGio.init(APIStuff.API, APIStuff.EncKey); - + + #if newgrounds + NGio.init(); + #end + if (FlxG.save.data.weekUnlocked != null) { // FIX LATER!!! @@ -242,13 +243,11 @@ class TitleState extends MusicBeatState if (pressedEnter && !transitioning && skippedIntro) { - #if !switch NGio.unlockMedal(60960); // If it's Friday according to da clock if (Date.now().getDay() == 5) NGio.unlockMedal(61034); - #end titleText.animation.play('press'); @@ -258,6 +257,7 @@ class TitleState extends MusicBeatState transitioning = true; // FlxG.sound.music.stop(); + #if newgrounds if (!OutdatedSubState.leftState) { NGio.checkVersion(function(version) @@ -278,6 +278,9 @@ class TitleState extends MusicBeatState } }); } + #else + FlxG.switchState(new MainMenuState()); + #end // FlxG.sound.play(Paths.music('titleShoot'), 0.7); } diff --git a/source/ui/MenuItemList.hx b/source/ui/MenuItemList.hx index a79ca1f2b..4991c9b2a 100644 --- a/source/ui/MenuItemList.hx +++ b/source/ui/MenuItemList.hx @@ -114,7 +114,8 @@ class MenuTypedItemList extends FlxTypedGroup if (controls.RIGHT_P || controls.DOWN_P) next(); } } - + + //Todo: bypass popup blocker on firefox if (controls.ACCEPT) accept(); } From 3936f739b258bac027a16c7a54d1028143552b6e Mon Sep 17 00:00:00 2001 From: George FunBook Date: Fri, 19 Feb 2021 22:10:16 -0600 Subject: [PATCH 05/37] move ngPrompt to new file --- source/MainMenuState.hx | 120 ++++++++-------------------------------- source/ui/NgPrompt.hx | 107 +++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 98 deletions(-) create mode 100644 source/ui/NgPrompt.hx diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index b207f97e5..8d600ab45 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -17,8 +17,13 @@ import flixel.util.FlxColor; import flixel.util.FlxTimer; import lime.app.Application; +#if newgrounds +import io.newgrounds.NG; +#end + import ui.MenuItemList; import ui.Prompt; +import ui.NgPrompt; using StringTools; @@ -141,118 +146,38 @@ class MainMenuState extends MusicBeatState #if newgrounds function selectLogin() { - showNgPrompt(true); - } - - function showSavedSessionFailed() - { - showNgPrompt(false); - } - - function showNgPrompt(fromUi:Bool) - { - var prompt = createNGPrompt("Talking to server...", None); - openSubState(prompt); - function onLoginComplete(result:ConnectionResult) - { - switch (result) - { - case Success: - { - menuItems.resetItem("login", "logout", selectLogout); - prompt.setText("Login Successful"); - prompt.setButtons(Ok); - prompt.onYes = prompt.close; - } - case Fail(msg): - { - trace("Login Error:" + msg); - prompt.setText("Login failed"); - prompt.setButtons(Ok); - prompt.onYes = prompt.close; - } - case Cancelled: - { - if (prompt != null) - { - prompt.setText("Login cancelled by user"); - prompt.setButtons(Ok); - prompt.onYes = prompt.close; - } - else - trace("Login cancelled via prompt"); - } - } - } - - NGio.login - ( - function popupLauncher(openPassportUrl) - { - var choiceMsg = fromUi - ? #if web "Log in to Newgrounds?" #else null #end // User-input needed to allow popups - : "Your session has expired.\n Please login again."; - - if (choiceMsg != null) - { - prompt.setText(choiceMsg); - prompt.setButtons(Yes_No); - #if web - prompt.buttons.getItem("yes").fireInstantly = true; - #end - prompt.onYes = function() - { - prompt.setText("Connecting..." #if web + "\n(check your popup blocker)" #end); - prompt.setButtons(None); - openPassportUrl(); - }; - prompt.onNo = function() - { - prompt.close(); - prompt = null; - NGio.cancelLogin(); - }; - } - else - { - prompt.setText("Connecting..."); - openPassportUrl(); - } - }, - onLoginComplete + openPrompt(NgPrompt.showLogin(), + function onPromptClose() menuItems.resetItem("login", "logout", selectLogout) ); } function selectLogout() { - var user = io.newgrounds.NG.core.user.name; - var prompt = createNGPrompt('Log out of $user?', Yes_No); - prompt.onYes = function() - { - NGio.logout(); - prompt.close(); - menuItems.resetItem("logout", "login", selectLogin); - }; - prompt.onNo = prompt.close; - openSubState(prompt); + openPrompt(NgPrompt.showLogout(), + function onPromptClose() menuItems.resetItem("logout", "login", selectLogin) + ); } - public function createNGPrompt(text:String, style:ButtonStyle = Yes_No) + function showSavedSessionFailed() + { + openPrompt(NgPrompt.showSavedSessionFailed(), + function onPromptClose() menuItems.resetItem("login", "logout", selectLogout) + ); + } + #end + + public function openPrompt(prompt:Prompt, onClose:Void->Void) { - var oldAutoPause = FlxG.autoPause; - FlxG.autoPause = false; menuItems.enabled = false; - - var prompt = new Prompt("prompt-ng_login", text, style); prompt.closeCallback = function () { menuItems.enabled = true; - FlxG.autoPause = oldAutoPause; + if (onClose != null) + onClose(); } - return prompt; + openSubState(prompt); } - #end function startExitState(state:FlxState) { @@ -286,7 +211,6 @@ class MainMenuState extends MusicBeatState } } - private class MainMenuItemList extends MenuTypedItemList { public var atlas:FlxAtlasFrames; diff --git a/source/ui/NgPrompt.hx b/source/ui/NgPrompt.hx new file mode 100644 index 000000000..2a2688553 --- /dev/null +++ b/source/ui/NgPrompt.hx @@ -0,0 +1,107 @@ +package ui; + +import NGio; +import ui.Prompt; + +class NgPrompt extends Prompt +{ + public function new (text:String, style:ButtonStyle = Yes_No) + { + super("prompt-ng_login", text, style); + } + + static public function showLogin() + { + return showLoginPrompt(true); + } + + static public function showSavedSessionFailed() + { + return showLoginPrompt(false); + } + + static function showLoginPrompt(fromUi:Bool) + { + var prompt = new NgPrompt("Talking to server...", None); + prompt.openCallback = NGio.login.bind + ( + function popupLauncher(openPassportUrl) + { + var choiceMsg = fromUi + ? #if web "Log in to Newgrounds?" #else null #end // User-input needed to allow popups + : "Your session has expired.\n Please login again."; + + if (choiceMsg != null) + { + prompt.setText(choiceMsg); + prompt.setButtons(Yes_No); + #if web + prompt.buttons.getItem("yes").fireInstantly = true; + #end + prompt.onYes = function() + { + prompt.setText("Connecting..." #if web + "\n(check your popup blocker)" #end); + prompt.setButtons(None); + openPassportUrl(); + }; + prompt.onNo = function() + { + prompt.close(); + prompt = null; + NGio.cancelLogin(); + }; + } + else + { + prompt.setText("Connecting..."); + openPassportUrl(); + } + }, + function onLoginComplete(result:ConnectionResult) + { + switch (result) + { + case Success: + { + prompt.setText("Login Successful"); + prompt.setButtons(Ok); + prompt.onYes = prompt.close; + } + case Fail(msg): + { + trace("Login Error:" + msg); + prompt.setText("Login failed"); + prompt.setButtons(Ok); + prompt.onYes = prompt.close; + } + case Cancelled: + { + if (prompt != null) + { + prompt.setText("Login cancelled by user"); + prompt.setButtons(Ok); + prompt.onYes = prompt.close; + } + else + trace("Login cancelled via prompt"); + } + } + } + ); + + return prompt; + } + + static public function showLogout() + { + var user = io.newgrounds.NG.core.user.name; + var prompt = new NgPrompt('Log out of $user?', Yes_No); + prompt.onYes = function() + { + NGio.logout(); + prompt.close(); + }; + prompt.onNo = prompt.close; + return prompt; + } +} \ No newline at end of file From aef55f90c6af57d52211733e1f547f5f438fe0c2 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Sun, 21 Feb 2021 12:08:30 -0600 Subject: [PATCH 06/37] alphabet menu items + separate ngPrompt --- Project.xml | 38 ++--- source/Alphabet.hx | 2 +- source/MainMenuState.hx | 71 ++++++--- source/ui/AlphabetMenuList.hx | 53 +++++++ source/ui/AtlasMenuList.hx | 81 ++++++++++ source/ui/{MenuItemList.hx => MenuList.hx} | 169 ++++++++++++++------- source/ui/NgPrompt.hx | 2 +- source/ui/Prompt.hx | 44 ++---- 8 files changed, 330 insertions(+), 130 deletions(-) create mode 100644 source/ui/AlphabetMenuList.hx create mode 100644 source/ui/AtlasMenuList.hx rename source/ui/{MenuItemList.hx => MenuList.hx} (64%) diff --git a/Project.xml b/Project.xml index 174fbf25b..0c784a3cc 100644 --- a/Project.xml +++ b/Project.xml @@ -71,24 +71,24 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -171,7 +171,7 @@
- + diff --git a/source/Alphabet.hx b/source/Alphabet.hx index 77ac5dc8e..6fca9d0a5 100644 --- a/source/Alphabet.hx +++ b/source/Alphabet.hx @@ -40,7 +40,7 @@ class Alphabet extends FlxSpriteGroup var isBold:Bool = false; - public function new(x:Float, y:Float, text:String = "", ?bold:Bool = false, typed:Bool = false) + public function new(x:Float = 0.0, y:Float = 0.0, text:String = "", ?bold:Bool = false, typed:Bool = false) { super(x, y); diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index 8d600ab45..a716f1c06 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -21,7 +21,8 @@ import lime.app.Application; import io.newgrounds.NG; #end -import ui.MenuItemList; +import ui.MenuList; +import ui.AtlasMenuList; import ui.Prompt; import ui.NgPrompt; @@ -29,7 +30,7 @@ using StringTools; class MainMenuState extends MusicBeatState { - var menuItems:MainMenuItemList; + var menuItems:MainMenuList; var magenta:FlxSprite; var camFollow:FlxObject; @@ -70,7 +71,7 @@ class MainMenuState extends MusicBeatState add(magenta); // magenta.scrollFactor.set(); - menuItems = new MainMenuItemList('FNF_main_menu_assets'); + menuItems = new MainMenuList(); add(menuItems); menuItems.onChange.add(onMenuItemChange); menuItems.onAcceptPress.add(function(_) @@ -88,6 +89,7 @@ class MainMenuState extends MusicBeatState #if CAN_OPEN_LINKS menuItems.createItem('donate', selectDonate, hasPopupBlocker); #end + // menuItems.createItem('options', function () startExitState(new OptionsMenu())); #if newgrounds if (NGio.isLoggedIn) menuItems.createItem("logout", selectLogout); @@ -123,10 +125,10 @@ class MainMenuState extends MusicBeatState menuItems.enabled = true; - #if newgrounds - if (NGio.savedSessionFailed) - showSavedSessionFailed(); - #end + // #if newgrounds + // if (NGio.savedSessionFailed) + // showSavedSessionFailed(); + // #end } function onMenuItemChange(selected:MenuItem) @@ -146,23 +148,46 @@ class MainMenuState extends MusicBeatState #if newgrounds function selectLogin() { - openPrompt(NgPrompt.showLogin(), - function onPromptClose() menuItems.resetItem("login", "logout", selectLogout) - ); + openNgPrompt(NgPrompt.showLogin()); } function selectLogout() { - openPrompt(NgPrompt.showLogout(), - function onPromptClose() menuItems.resetItem("logout", "login", selectLogin) - ); + openNgPrompt(NgPrompt.showLogout()); } function showSavedSessionFailed() { - openPrompt(NgPrompt.showSavedSessionFailed(), - function onPromptClose() menuItems.resetItem("login", "logout", selectLogout) - ); + openNgPrompt(NgPrompt.showSavedSessionFailed()); + } + + /** + * Calls openPrompt and redraws the login/logout button + * @param prompt + * @param onClose + */ + public function openNgPrompt(prompt:Prompt, ?onClose:Void->Void) + { + var onPromptClose = checkLoginStatus; + if (onClose != null) + { + onPromptClose = function () + { + checkLoginStatus(); + onClose(); + } + } + + openPrompt(prompt, onPromptClose); + } + + function checkLoginStatus() + { + var prevLoggedIn = menuItems.has("logout"); + if (prevLoggedIn && !NGio.isLoggedIn) + menuItems.resetItem("login", "logout", selectLogout); + else if (!prevLoggedIn && NGio.isLoggedIn) + menuItems.resetItem("logout", "login", selectLogin); } #end @@ -211,26 +236,22 @@ class MainMenuState extends MusicBeatState } } -private class MainMenuItemList extends MenuTypedItemList +private class MainMenuList extends MenuTypedList { public var atlas:FlxAtlasFrames; - public function new (atlas) + public function new () { + atlas = Paths.getSparrowAtlas('main_menu'); super(Vertical); - if (Std.is(atlas, String)) - this.atlas = Paths.getSparrowAtlas(cast atlas); - else - this.atlas = cast atlas; } public function createItem(x = 0.0, y = 0.0, name:String, callback, fireInstantly = false) { - var i = length; var item = new MainMenuItem(x, y, name, atlas, callback); item.fireInstantly = fireInstantly; - item.ID = i; + item.ID = length; return addItem(name, item); } @@ -241,7 +262,7 @@ private class MainMenuItemList extends MenuTypedItemList atlas = null; } } -private class MainMenuItem extends MenuItem +private class MainMenuItem extends AtlasMenuItem { public function new(x = 0.0, y = 0.0, name, atlas, callback) { diff --git a/source/ui/AlphabetMenuList.hx b/source/ui/AlphabetMenuList.hx new file mode 100644 index 000000000..47832e582 --- /dev/null +++ b/source/ui/AlphabetMenuList.hx @@ -0,0 +1,53 @@ +package ui; + +import ui.MenuList; + +class AlphabetMenuList extends MenuTypedList +{ + public function new (navControls:NavControls = Vertical) + { + super(navControls); + } + + public function createItem(x = 0.0, y = 0.0, name:String, bold = true, callback, fireInstantly = false) + { + var item = new AlphabetMenuItem(x, y, name, bold, callback); + item.fireInstantly = fireInstantly; + return addItem(name, item); + } +} + +class AlphabetMenuItem extends AlphabetTypedMenuItem +{ + public function new (x = 0.0, y = 0.0, name:String, bold = true, callback) + { + super(x, y, new Alphabet(x, y, name, bold), name, callback); + } +} + +class AlphabetTypedMenuItem extends MenuTypedItem +{ + public function new (x = 0.0, y = 0.0, label:T, name:String, callback) + { + super(x, y, label, name, callback); + } + + override function setItem(name:String, ?callback:() -> Void) + { + if (label != null) + { + label.text = name; + width = label.width; + height = label.height; + } + + super.setItem(name, callback); + } + + override function set_label(value:T):T + { + super.set_label(value); + setItem(name, callback); + return value; + } +} \ No newline at end of file diff --git a/source/ui/AtlasMenuList.hx b/source/ui/AtlasMenuList.hx new file mode 100644 index 000000000..e9572d07c --- /dev/null +++ b/source/ui/AtlasMenuList.hx @@ -0,0 +1,81 @@ +package ui; + +import ui.MenuList; + +import flixel.graphics.frames.FlxAtlasFrames; + +typedef AtlasAsset = flixel.util.typeLimit.OneOfTwo; + +class AtlasMenuList extends MenuTypedList +{ + public var atlas:FlxAtlasFrames; + + public function new (atlas, navControls:NavControls = Vertical) + { + super(navControls); + + if (Std.is(atlas, String)) + this.atlas = Paths.getSparrowAtlas(cast atlas); + else + this.atlas = cast atlas; + } + + public function createItem(x = 0.0, y = 0.0, name, callback, fireInstantly = false) + { + var item = new AtlasMenuItem(x, y, name, atlas, callback); + item.fireInstantly = fireInstantly; + return addItem(name, item); + } + + override function destroy() + { + super.destroy(); + atlas = null; + } +} + +class AtlasMenuItem extends MenuItem +{ + var atlas:FlxAtlasFrames; + public function new (x = 0.0, y = 0.0, name:String, atlas:FlxAtlasFrames, callback) + { + this.atlas = atlas; + super(x, y, name, callback); + } + + override function setData(name:String, ?callback:Void->Void) + { + frames = atlas; + animation.addByPrefix('idle', '$name idle', 24); + animation.addByPrefix('selected', '$name selected', 24); + + super.setData(name, callback); + } + + function changeAnim(animName:String) + { + animation.play(animName); + updateHitbox(); + } + + override function idle() + { + changeAnim('idle'); + } + + override function select() + { + changeAnim('selected'); + } + + override function get_selected() + { + return animation.curAnim != null && animation.curAnim.name == "selected"; + } + + override function destroy() + { + super.destroy(); + atlas = null; + } +} \ No newline at end of file diff --git a/source/ui/MenuItemList.hx b/source/ui/MenuList.hx similarity index 64% rename from source/ui/MenuItemList.hx rename to source/ui/MenuList.hx index 4991c9b2a..8fdb373a5 100644 --- a/source/ui/MenuItemList.hx +++ b/source/ui/MenuList.hx @@ -1,46 +1,13 @@ package ui; -import flixel.util.typeLimit.OneOfTwo; import flixel.math.FlxPoint; import flixel.FlxG; +import flixel.FlxSprite; import flixel.effects.FlxFlicker; -import flixel.graphics.frames.FlxAtlasFrames; import flixel.group.FlxGroup; -import flixel.tweens.FlxEase; -import flixel.tweens.FlxTween; import flixel.util.FlxSignal; -typedef AtlasAsset = OneOfTwo; - -class MenuItemList extends MenuTypedItemList -{ - public var atlas:FlxAtlasFrames; - - public function new (atlas, navControls:NavControls = Vertical) - { - super(navControls); - - if (Std.is(atlas, String)) - this.atlas = Paths.getSparrowAtlas(cast atlas); - else - this.atlas = cast atlas; - } - - public function createItem(x = 0.0, y = 0.0, name, callback, fireInstantly = false) - { - var item = new MenuItem(x, y, name, atlas, callback); - item.fireInstantly = fireInstantly; - return addItem(name, item); - } - - override function destroy() - { - super.destroy(); - atlas = null; - } -} - -class MenuTypedItemList extends FlxTypedGroup +class MenuTypedList extends FlxTypedGroup { public var selectedIndex(default, null) = 0; /** Called when a new item is highlighted */ @@ -165,6 +132,11 @@ class MenuTypedItemList extends FlxTypedGroup onChange.dispatch(selected); } + public function has(name:String) + { + return byName.exists(name); + } + public function getItem(name:String) { return byName[name]; @@ -177,51 +149,140 @@ class MenuTypedItemList extends FlxTypedGroup } } -class MenuItem extends flixel.FlxSprite -{ +class MenuItem extends FlxSprite +{ public var callback:Void->Void; + public var name:String; /** * Set to true for things like opening URLs otherwise, it may it get blocked. */ public var fireInstantly = false; + public var selected(get, never):Bool; + function get_selected() return alpha == 1.0; - public function new (x = 0.0, y = 0.0, name, tex, callback) + public function new (x = 0.0, y = 0.0, name:String, callback) { super(x, y); - frames = tex; - setItem(name, callback); antialiasing = true; + setData(name, callback); + idle(); } - public function setItem(name:String, ?callback:Void->Void) + function setData(name:String, ?callback:Void->Void) { + this.name = name; + if (callback != null) this.callback = callback; - - var selected = animation.curAnim != null && animation.curAnim.name == "selected"; - - animation.addByPrefix('idle', '$name basic', 24); - animation.addByPrefix('selected', '$name white', 24); - idle(); - if (selected) - select(); } - function changeAnim(anim:String) + /** + * Calls setData and resets/redraws the state of the item + * @param name + * @param callback + */ + public function setItem(name:String, ?callback:Void->Void) { - animation.play(anim); - updateHitbox(); + setData(name, callback); + + if (selected) + select(); + else + idle(); } public function idle() { - changeAnim('idle'); + alpha = 0.6; } public function select() { - changeAnim('selected'); + alpha = 1.0; + } +} + +class MenuTypedItem extends MenuItem +{ + public var label(default, set):T; + + public function new (x = 0.0, y = 0.0, label:T, name:String, callback) + { + super(x, y, name, callback); + // set label after super otherwise setters fuck up + this.label = label; + } + + /** + * Use this when you only want to show the label + */ + function setEmptyBackground() + { + var oldWidth = width; + var oldHeight = height; + makeGraphic(1, 1, 0x0); + width = oldWidth; + height = oldHeight; + } + + function set_label(value:T) + { + if (value != null) + { + value.x = x; + value.y = y; + value.alpha = alpha; + } + return this.label = value; + } + + override function update(elapsed:Float) + { + super.update(elapsed); + if (label != null) + label.update(elapsed); + } + + override function draw() + { + super.draw(); + if (label != null) + { + label.cameras = cameras; + label.scrollFactor.copyFrom(scrollFactor); + label.draw(); + } + } + + override function set_alpha(value:Float):Float + { + super.set_alpha(value); + + if (label != null) + label.alpha = alpha; + + return alpha; + } + + override function set_x(value:Float):Float + { + super.set_x(value); + + if (label != null) + label.x = x; + + return x; + } + + override function set_y(Value:Float):Float + { + super.set_y(Value); + + if (label != null) + label.y = y; + + return y; } } diff --git a/source/ui/NgPrompt.hx b/source/ui/NgPrompt.hx index 2a2688553..4bf75997f 100644 --- a/source/ui/NgPrompt.hx +++ b/source/ui/NgPrompt.hx @@ -7,7 +7,7 @@ class NgPrompt extends Prompt { public function new (text:String, style:ButtonStyle = Yes_No) { - super("prompt-ng_login", text, style); + super(text, style); } static public function showLogin() diff --git a/source/ui/Prompt.hx b/source/ui/Prompt.hx index dea595252..6cbf450c0 100644 --- a/source/ui/Prompt.hx +++ b/source/ui/Prompt.hx @@ -1,5 +1,8 @@ package ui; +import ui.MenuList; + +import flixel.FlxG; import flixel.FlxSprite; import flixel.graphics.frames.FlxAtlasFrames; import flixel.text.FlxText; @@ -11,33 +14,19 @@ class Prompt extends flixel.FlxSubState public var onYes:Void->Void; public var onNo:Void->Void; - public var buttons:MenuItemList; - public var field:FlxText; - public var back:FlxSprite; + public var buttons:AlphabetMenuList; + public var field:Alphabet; var style:ButtonStyle; - public function new (atlas, text:String, style:ButtonStyle = Ok) + public function new (text:String, style:ButtonStyle = Ok) { this.style = style; - super(); + super(0xA0000000); - var texture:FlxAtlasFrames; - if (Std.is(atlas, String)) - texture = Paths.getSparrowAtlas(cast atlas); - else - texture = cast atlas; + buttons = new AlphabetMenuList(Horizontal); - back = new FlxSprite(); - back.frames = texture; - back.animation.addByPrefix("idle", "back"); - back.scrollFactor.set(0, 0); - - buttons = new MenuItemList(texture, Horizontal); - - field = new FlxText(); - field.setFormat(Paths.font("vcr.ttf"), 64, FlxColor.BLACK, CENTER); - field.text = text; + field = new Alphabet(text, true); field.scrollFactor.set(0, 0); } @@ -45,12 +34,7 @@ class Prompt extends flixel.FlxSubState { super.create(); - back.animation.play("idle"); - back.updateHitbox(); - back.screenCenter(XY); - add(back); - - field.y = back.y + MARGIN; + field.y = MARGIN; field.screenCenter(X); add(field); @@ -90,16 +74,16 @@ class Prompt extends flixel.FlxSubState // pass anonymous functions rather than the current callbacks, in case they change later var yesButton = buttons.createItem(yes, function() onYes()); yesButton.screenCenter(X); - yesButton.y = back.y + back.height - yesButton.height - MARGIN; + yesButton.y = FlxG.height - yesButton.height - MARGIN; yesButton.scrollFactor.set(0, 0); if (no != null) { // place right - yesButton.x = back.x + back.width - yesButton.width - MARGIN; + yesButton.x = FlxG.width - yesButton.width - MARGIN; var noButton = buttons.createItem(no, function() onNo()); - noButton.x = back.x + MARGIN; - noButton.y = back.y + back.height - noButton.height - MARGIN; + noButton.x = MARGIN; + noButton.y = FlxG.height - noButton.height - MARGIN; noButton.scrollFactor.set(0, 0); } } From d9371cc8eba97203bda1be4d454f17dfedb86b8c Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 23 Feb 2021 18:55:24 -0600 Subject: [PATCH 07/37] add AtlasText cuz Alpabet sux --- source/ui/AtlasText.hx | 140 ++++++++++++++++++ source/ui/Prompt.hx | 9 +- .../{AlphabetMenuList.hx => TextMenuList.hx} | 16 +- 3 files changed, 154 insertions(+), 11 deletions(-) create mode 100644 source/ui/AtlasText.hx rename source/ui/{AlphabetMenuList.hx => TextMenuList.hx} (54%) diff --git a/source/ui/AtlasText.hx b/source/ui/AtlasText.hx new file mode 100644 index 000000000..579c35729 --- /dev/null +++ b/source/ui/AtlasText.hx @@ -0,0 +1,140 @@ +package ui; + +import flixel.FlxSprite; +import flixel.group.FlxSpriteGroup; +import flixel.graphics.frames.FlxAtlasFrames; + +@:forward +abstract BoldText(AtlasText) from AtlasText to AtlasText +{ + inline public function new (x = 0.0, y = 0.0, text:String) + { + this = new AtlasText(x, y, text, Bold); + } +} + +/** + * Alphabet.hx has a ton of bugs and does a bunch of stuff I don't need, fuck that class + */ +class AtlasText extends FlxTypedSpriteGroup +{ + static var maxHeights = new Map(); + public var text(default, set):String; + + var atlas:FlxAtlasFrames; + var maxHeight = 0.0; + + public function new (x = 0.0, y = 0.0, text:String, font:AtlasFont = Default) + { + atlas = Paths.getSparrowAtlas("fonts/" + font.getName().toLowerCase()); + if (maxHeights.exists(font)) + { + maxHeight = 0; + for (frame in atlas.frames) + maxHeight = Math.max(maxHeight, frame.frame.height); + maxHeights[font] = maxHeight; + } + maxHeight = maxHeights[font]; + + super(x, y); + + this.text = text; + } + + function set_text(value:String) + { + if (this.text == value) + return this.text; + + group.kill(); + + var xPos:Float = 0; + var yPos:Float = 0; + + var charCount = 0; + for (char in value.split("")) + { + switch(char) + { + case " ": + { + xPos += 40; + } + case "\n": + { + xPos = 0; + yPos += 55; + } + default: + { + var charSprite:AtlasChar; + if (group.members.length <= charCount) + charSprite = new AtlasChar(atlas, char); + else + { + charSprite = group.members[charCount]; + charSprite.revive(); + charSprite.char = char; + } + charSprite.x = xPos; + charSprite.y = yPos + maxHeight - charSprite.height; + add(charSprite); + + xPos += charSprite.width; + charCount++; + } + } + } + // updateHitbox(); + return this.text = value; + } +} + +class AtlasChar extends FlxSprite +{ + public var char(default, set):String; + public function new(x = 0.0, y = 0.0, atlas:FlxAtlasFrames, char:String) + { + super(x, y); + frames = atlas; + this.char = char; + antialiasing = true; + } + + function set_char(value:String) + { + if (this.char != value) + { + animation.addByPrefix("anim", getAnimPrefix(value), 24); + animation.play("anim"); + updateHitbox(); + } + + return this.char = value; + } + + function getAnimPrefix(char:String) + { + return switch (char) + { + case '-': '-dash-'; + case '.': '-period-'; + case ",": '-comma-'; + case "'": '-apostraphie-'; + case "?": '-question mark-'; + case "!": '-exclamation point-'; + case "\\": '-back slash-'; + case "/": '-forward slash-'; + case "*": '-multiply x-'; + case "“": '-start quote-'; + case "”": '-end quote-'; + default: char; + } + } +} + +enum AtlasFont +{ + Default; + Bold; +} \ No newline at end of file diff --git a/source/ui/Prompt.hx b/source/ui/Prompt.hx index 6cbf450c0..ccac5d576 100644 --- a/source/ui/Prompt.hx +++ b/source/ui/Prompt.hx @@ -1,5 +1,6 @@ package ui; +import ui.AtlasText; import ui.MenuList; import flixel.FlxG; @@ -14,8 +15,8 @@ class Prompt extends flixel.FlxSubState public var onYes:Void->Void; public var onNo:Void->Void; - public var buttons:AlphabetMenuList; - public var field:Alphabet; + public var buttons:TextMenuList; + public var field:AtlasText; var style:ButtonStyle; @@ -24,9 +25,9 @@ class Prompt extends flixel.FlxSubState this.style = style; super(0xA0000000); - buttons = new AlphabetMenuList(Horizontal); + buttons = new TextMenuList(Horizontal); - field = new Alphabet(text, true); + field = new BoldText(text); field.scrollFactor.set(0, 0); } diff --git a/source/ui/AlphabetMenuList.hx b/source/ui/TextMenuList.hx similarity index 54% rename from source/ui/AlphabetMenuList.hx rename to source/ui/TextMenuList.hx index 47832e582..bfc356c26 100644 --- a/source/ui/AlphabetMenuList.hx +++ b/source/ui/TextMenuList.hx @@ -1,31 +1,33 @@ package ui; +import ui.AtlasText; import ui.MenuList; -class AlphabetMenuList extends MenuTypedList +class TextMenuList extends MenuTypedList { public function new (navControls:NavControls = Vertical) { super(navControls); } - public function createItem(x = 0.0, y = 0.0, name:String, bold = true, callback, fireInstantly = false) + public function createItem(x = 0.0, y = 0.0, name:String, font:AtlasFont = Bold, callback, fireInstantly = false) { - var item = new AlphabetMenuItem(x, y, name, bold, callback); + var item = new TextMenuItem(x, y, name, font, callback); item.fireInstantly = fireInstantly; return addItem(name, item); } } -class AlphabetMenuItem extends AlphabetTypedMenuItem +class TextMenuItem extends TextTypedMenuItem { - public function new (x = 0.0, y = 0.0, name:String, bold = true, callback) + public function new (x = 0.0, y = 0.0, name:String, font:AtlasFont = Bold, callback) { - super(x, y, new Alphabet(x, y, name, bold), name, callback); + super(x, y, new AtlasText(0, 0, name, font), name, callback); + setEmptyBackground(); } } -class AlphabetTypedMenuItem extends MenuTypedItem +class TextTypedMenuItem extends MenuTypedItem { public function new (x = 0.0, y = 0.0, label:T, name:String, callback) { From 38496ea74d23c7b186780f9e567872ff2db57a84 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 23 Feb 2021 18:57:49 -0600 Subject: [PATCH 08/37] cheats on debug only --- Project.xml | 3 ++- source/Controls.hx | 24 ++++++++++++++++++++++-- source/PlayState.hx | 3 ++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Project.xml b/Project.xml index 0c784a3cc..d85bd91e0 100644 --- a/Project.xml +++ b/Project.xml @@ -116,7 +116,7 @@ - + @@ -168,6 +168,7 @@ +
diff --git a/source/Controls.hx b/source/Controls.hx index 7d1e2c40e..bb24d7883 100644 --- a/source/Controls.hx +++ b/source/Controls.hx @@ -30,7 +30,9 @@ enum abstract Action(String) to String from String var BACK = "back"; var PAUSE = "pause"; var RESET = "reset"; + #if CAN_CHEAT var CHEAT = "cheat"; + #end } #else @:enum @@ -52,7 +54,9 @@ abstract Action(String) to String from String var BACK = "back"; var PAUSE = "pause"; var RESET = "reset"; + #if CAN_CHEAT var CHEAT = "cheat"; + #end } #end @@ -77,7 +81,9 @@ enum Control ACCEPT; BACK; PAUSE; + #if CAN_CHEAT CHEAT; + #end } enum KeyboardScheme @@ -110,8 +116,10 @@ class Controls extends FlxActionSet var _back = new FlxActionDigital(Action.BACK); var _pause = new FlxActionDigital(Action.PAUSE); var _reset = new FlxActionDigital(Action.RESET); + #if CAN_CHEAT var _cheat = new FlxActionDigital(Action.CHEAT); - + #end + #if (haxe >= "4.0.0") var byName:Map = []; #else @@ -201,11 +209,13 @@ class Controls extends FlxActionSet inline function get_RESET() return _reset.check(); + #if CAN_CHEAT public var CHEAT(get, never):Bool; inline function get_CHEAT() return _cheat.check(); - + #end + #if (haxe >= "4.0.0") public function new(name, scheme = None) { @@ -227,7 +237,9 @@ class Controls extends FlxActionSet add(_back); add(_pause); add(_reset); + #if CAN_CHEAT add(_cheat); + #end for (action in digitalActions) byName[action.name] = action; @@ -255,7 +267,9 @@ class Controls extends FlxActionSet add(_back); add(_pause); add(_reset); + #if CAN_CHEAT add(_cheat); + #end for (action in digitalActions) byName[action.name] = action; @@ -309,7 +323,9 @@ class Controls extends FlxActionSet case BACK: _back; case PAUSE: _pause; case RESET: _reset; + #if CAN_CHEAT case CHEAT: _cheat; + #end } } @@ -353,8 +369,10 @@ class Controls extends FlxActionSet func(_pause, JUST_PRESSED); case RESET: func(_reset, JUST_PRESSED); + #if CAN_CHEAT case CHEAT: func(_cheat, JUST_PRESSED); + #end } } @@ -644,7 +662,9 @@ class Controls extends FlxActionSet Control.PAUSE => [START], //Swap Y and X for switch Control.RESET => [Y], + #if CAN_CHEAT Control.CHEAT => [X] + #end ]); #end } diff --git a/source/PlayState.hx b/source/PlayState.hx index 3366edf0a..2f699ea45 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1452,12 +1452,13 @@ class PlayState extends MusicBeatState trace("RESET = True"); } - // CHEAT = brandon's a pussy + #if CAN_CHEAT // brandon's a pussy if (controls.CHEAT) { health += 1; trace("User is cheating!"); } + #end if (health <= 0) { From d3e17274a8bd19085f36bd0c5194c06b9557094c Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 23 Feb 2021 18:59:09 -0600 Subject: [PATCH 09/37] add grid nav controls --- source/ui/MenuList.hx | 108 +++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 32 deletions(-) diff --git a/source/ui/MenuList.hx b/source/ui/MenuList.hx index 8fdb373a5..050cbe666 100644 --- a/source/ui/MenuList.hx +++ b/source/ui/MenuList.hx @@ -29,7 +29,7 @@ class MenuTypedList extends FlxTypedGroup super(); } - function addItem(name:String, item:T):T + public function addItem(name:String, item:T):T { if (length == selectedIndex) item.select(); @@ -63,23 +63,20 @@ class MenuTypedList extends FlxTypedGroup { var controls = PlayerSettings.player1.controls; - switch(navControls) + var newIndex = switch(navControls) { - case Vertical: - { - if (controls.UP_P ) prev(); - if (controls.DOWN_P) next(); - } - case Horizontal: - { - if (controls.LEFT_P ) prev(); - if (controls.RIGHT_P) next(); - } - case Both: - { - if (controls.LEFT_P || controls.UP_P ) prev(); - if (controls.RIGHT_P || controls.DOWN_P) next(); - } + case Vertical : navList(controls.UP_P , controls.DOWN_P); + case Horizontal : navList(controls.LEFT_P, controls.RIGHT_P); + case Both : navList(controls.LEFT_P || controls.UP_P, controls.RIGHT_P || controls.DOWN_P); + + case Columns(num): navGrid(num, controls.LEFT_P, controls.RIGHT_P, controls.UP_P, controls.DOWN_P); + case Rows (num): navGrid(num, controls.UP_P, controls.DOWN_P, controls.LEFT_P, controls.RIGHT_P); + } + + if (newIndex != selectedIndex) + { + FlxG.sound.play(Paths.sound('scrollMenu')); + selectItem(newIndex); } //Todo: bypass popup blocker on firefox @@ -87,6 +84,64 @@ class MenuTypedList extends FlxTypedGroup accept(); } + function navAxis(index:Int, size:Int, prev:Bool, next:Bool, allowWrap:Bool):Int + { + if (prev == next) + return index; + + if (prev) + { + if (index > 0) + index--; + else if (allowWrap) + index = size - 1; + } + else + { + if (index < size - 1) + index++; + else if (allowWrap) + index = 0; + } + + return index; + } + + /** + * Controls navigation on a linear list of items such as Vertical. + * @param prev + * @param next + * @param allowWrap + */ + inline function navList(prev:Bool, next:Bool, allowWrap:Bool = true) + { + return navAxis(selectedIndex, length, prev, next, allowWrap); + } + + /** + * Controls navigation on a grid + * @param latSize The size of the fixed axis of the grid, or the "lateral axis" + * @param latPrev Whether the 'prev' key is pressed along the fixed-lengthed axis. eg: "left" in Column mode + * @param latNext Whether the 'next' key is pressed along the fixed-lengthed axis. eg: "right" in Column mode + * @param prev Whether the 'prev' key is pressed along the variable-lengthed axis. eg: "up" in Column mode + * @param next Whether the 'next' key is pressed along the variable-lengthed axis. eg: "down" in Column mode + * @param allowWrap unused + */ + function navGrid(latSize:Int, latPrev:Bool, latNext:Bool, prev:Bool, next:Bool, allowWrap:Bool = true):Int + { + // The grid lenth along the variable-length axis + var size = Math.ceil(length / latSize); + // The selected position along the variable-length axis + var index = Math.floor(selectedIndex / latSize); + // The selected position along the fixed axis + var latIndex = selectedIndex % latSize; + + latIndex = navAxis(latIndex, latSize, latPrev, latNext, allowWrap); + index = navAxis(index, size, prev, next, allowWrap); + + return Std.int(Math.min(length - 1, index * latSize + latIndex)); + } + public function accept() { var selected = members[selectedIndex]; @@ -106,21 +161,6 @@ class MenuTypedList extends FlxTypedGroup } } - inline function prev() changeItem(-1); - inline function next() changeItem(1); - - function changeItem(amount:Int) - { - FlxG.sound.play(Paths.sound('scrollMenu')); - var index = selectedIndex + amount; - if (index >= length) - index = 0; - else if (index < 0) - index = length - 1; - - selectItem(index); - } - public function selectItem(index:Int) { members[selectedIndex].idle(); @@ -146,6 +186,8 @@ class MenuTypedList extends FlxTypedGroup { super.destroy(); byName.clear(); + onChange.removeAll(); + onAcceptPress.removeAll(); } } @@ -291,4 +333,6 @@ enum NavControls Horizontal; Vertical; Both; + Columns(num:Int); + Rows(num:Int); } \ No newline at end of file From 5b6862d6cf63e6fac1e8e53ee15586490330f9e2 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 23 Feb 2021 18:59:36 -0600 Subject: [PATCH 10/37] start new Controls menu --- source/InputFormatter.hx | 223 ++++++++++++++++++++++++++++++++++++++ source/MainMenuState.hx | 18 +-- source/OptionsMenu.hx | 8 ++ source/ui/ControlsMenu.hx | 81 ++++++++++++++ 4 files changed, 321 insertions(+), 9 deletions(-) create mode 100644 source/InputFormatter.hx create mode 100644 source/ui/ControlsMenu.hx diff --git a/source/InputFormatter.hx b/source/InputFormatter.hx new file mode 100644 index 000000000..c80c67384 --- /dev/null +++ b/source/InputFormatter.hx @@ -0,0 +1,223 @@ +package ; + +import Controls; + +import flixel.FlxG; +import flixel.input.gamepad.FlxGamepad; +import flixel.input.gamepad.FlxGamepadInputID; +import flixel.input.keyboard.FlxKey; + +using flixel.util.FlxStringUtil; + +class InputFormatter +{ + static public function format(id:Int, device:Device):String + { + return switch (device) + { + case Keys: getKeyName(id); + case Gamepad(gamepadID): getButtonName(id, FlxG.gamepads.getByID(gamepadID)); + } + } + + static public function getKeyName(id:Int):String + { + return switch(id) + { + case ZERO : "0"; + case ONE : "1"; + case TWO : "2"; + case THREE : "3"; + case FOUR : "4"; + case FIVE : "5"; + case SIX : "6"; + case SEVEN : "7"; + case EIGHT : "8"; + case NINE : "9"; + case PAGEUP : "PgU"; + case PAGEDOWN : "PgD"; + case HOME : "Hm"; + case END : "End"; + case INSERT : "Ins"; + case ESCAPE : "Esc"; + case MINUS : "-"; + case PLUS : "+"; + case DELETE : "Del"; + case BACKSPACE : "Bck"; + case LBRACKET : "["; + case RBRACKET : "]"; + case BACKSLASH : "\\"; + case CAPSLOCK : "Cap"; + case SEMICOLON : ";"; + case QUOTE : "'"; + case ENTER : "Ent"; + case SHIFT : "Shf"; + case COMMA : ","; + case PERIOD : "."; + case SLASH : "/"; + case GRAVEACCENT : "`"; + case CONTROL : "Ctl"; + case ALT : "Alt"; + case SPACE : "Spc"; + case UP : "Up"; + case DOWN : "Dn"; + case LEFT : "Lf"; + case RIGHT : "Rt"; + case TAB : "Tab"; + case PRINTSCREEN : "Prt"; + case NUMPADZERO : "#0"; + case NUMPADONE : "#1"; + case NUMPADTWO : "#2"; + case NUMPADTHREE : "#3"; + case NUMPADFOUR : "#4"; + case NUMPADFIVE : "#5"; + case NUMPADSIX : "#6"; + case NUMPADSEVEN : "#7"; + case NUMPADEIGHT : "#8"; + case NUMPADNINE : "#9"; + case NUMPADMINUS : "#-"; + case NUMPADPLUS : "#+"; + case NUMPADPERIOD : "#."; + case NUMPADMULTIPLY: "#*"; + default: titleCaseTrim(FlxKey.toStringMap[id]); + } + } + + static var dirReg = ~/^(l|r).?-(left|right|down|up)$/; + inline static public function getButtonName(id:Int, gamepad:FlxGamepad):String + { + return switch(gamepad.getInputLabel(id)) + { + // case null | "": shortenButtonName(FlxGamepadInputID.toStringMap[id]); + case label: shortenButtonName(label); + } + } + + static function shortenButtonName(name:String) + { + return switch (name == null ? "" : name.toLowerCase()) + { + case "": "[?]"; + case "square" : "[]"; + case "circle" : "()"; + case "triangle": "/\\"; + case "plus" : "+"; + case "minus" : "-"; + case "home" : "Hm"; + case "guide" : "Gd"; + case "back" : "Bk"; + case "select" : "Bk"; + case "start" : "St"; + case "left" : "Lf"; + case "right" : "Rt"; + case "down" : "Dn"; + case "up" : "Up"; + case dir if (dirReg.match(dir)): + dirReg.matched(1).toUpperCase() + "-" + + switch (dirReg.matched(2)) + { + case "left" : "L"; + case "right": "R"; + case "down" : "D"; + case "up" : "U"; + default: throw "Unreachable exaustiveness case"; + }; + case label: titleCaseTrim(label); + } + } + + inline static function titleCaseTrim(str:String, length = 3) + { + return str.charAt(0).toUpperCase() + str.substr(1, length - 1).toLowerCase(); + } + + inline static public function parsePadName(name:String):ControllerName + { + return ControllerName.parseName(name); + } + + inline static public function getPadName(gamepad:FlxGamepad):ControllerName + { + return ControllerName.getName(gamepad); + } + + inline static public function getPadNameById(id:Int):ControllerName + { + return ControllerName.getNameById(id); + } +} + +@:forward +enum abstract ControllerName(String) from String to String +{ + var OUYA = "Ouya" ; + var PS4 = "PS4" ; + var LOGI = "Logi" ; + var XBOX = "XBox" ; + var XINPUT = "XInput" ; + var WII = "Wii" ; + var PRO_CON = "Pro_Con" ; + var JOYCONS = "Joycons" ; + var JOYCON_L = "Joycon_L"; + var JOYCON_R = "Joycon_R"; + var MFI = "MFI" ; + var PAD = "Pad" ; + + static public function getAssetByDevice(device:Device):String + { + return switch (device) + { + case Keys: getAsset(null); + case Gamepad(id): getAsset(FlxG.gamepads.getByID(id)); + } + } + + static public function getAsset(gamepad:FlxGamepad):String + { + if (gamepad == null) + return 'assets/images/ui/devices/Keys.png'; + + final name = parseName(gamepad.name); + var path = 'assets/images/ui/devices/$name.png'; + if (openfl.utils.Assets.exists(path)) + return path; + + return 'assets/images/ui/devices/Pad.png'; + } + + + + inline static public function getNameById(id:Int):ControllerName return getName(FlxG.gamepads.getByID(id)); + inline static public function getName(gamepad:FlxGamepad):ControllerName return parseName(gamepad.name); + static public function parseName(name:String):ControllerName + { + name = name.toLowerCase().remove("-").remove("_"); + return + if (name.contains("ouya")) + OUYA; + else if (name.contains("wireless controller") || name.contains("ps4")) + PS4; + else if (name.contains("logitech")) + LOGI; + else if (name.contains("xbox")) + XBOX + else if (name.contains("xinput")) + XINPUT; + else if (name.contains("nintendo rvlcnt01tr") || name.contains("nintendo rvlcnt01")) + WII; + else if (name.contains("mayflash wiimote pc adapter")) + WII; + else if (name.contains("pro controller")) + PRO_CON; + else if (name.contains("joycon l+r")) + JOYCONS; + else if (name.contains("joycon (l)")) + JOYCON_L; + else if (name.contains("joycon (r)")) + JOYCON_R; + else if (name.contains("mfi")) + MFI; + else + PAD; + } +} \ No newline at end of file diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index a716f1c06..26d893b30 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -19,12 +19,12 @@ import lime.app.Application; #if newgrounds import io.newgrounds.NG; +import ui.NgPrompt; #end -import ui.MenuList; import ui.AtlasMenuList; +import ui.MenuList; import ui.Prompt; -import ui.NgPrompt; using StringTools; @@ -89,13 +89,13 @@ class MainMenuState extends MusicBeatState #if CAN_OPEN_LINKS menuItems.createItem('donate', selectDonate, hasPopupBlocker); #end - // menuItems.createItem('options', function () startExitState(new OptionsMenu())); - #if newgrounds - if (NGio.isLoggedIn) - menuItems.createItem("logout", selectLogout); - else - menuItems.createItem("login", selectLogin); - #end + menuItems.createItem('options', function () startExitState(new OptionsMenu())); + // #if newgrounds + // if (NGio.isLoggedIn) + // menuItems.createItem("logout", selectLogout); + // else + // menuItems.createItem("login", selectLogin); + // #end // center vertically var spacing = 160; diff --git a/source/OptionsMenu.hx b/source/OptionsMenu.hx index a938495db..c3dc35a09 100644 --- a/source/OptionsMenu.hx +++ b/source/OptionsMenu.hx @@ -13,6 +13,14 @@ import flixel.util.FlxColor; import lime.utils.Assets; class OptionsMenu extends MusicBeatState +{ + override function create() + { + add(new ui.ControlsMenu()); + } +} + +class OptionsMenu_old extends MusicBeatState { var selector:FlxText; var curSelected:Int = 0; diff --git a/source/ui/ControlsMenu.hx b/source/ui/ControlsMenu.hx new file mode 100644 index 000000000..7dbc20983 --- /dev/null +++ b/source/ui/ControlsMenu.hx @@ -0,0 +1,81 @@ +package ui; + +import flixel.FlxG; +import flixel.FlxCamera; +import flixel.FlxObject; +import flixel.FlxSprite; +import flixel.group.FlxGroup; +import flixel.input.keyboard.FlxKey; + +import Controls; +import ui.AtlasText; +import ui.TextMenuList; + +class ControlsMenu extends flixel.group.FlxGroup +{ + var controlGrid:TextMenuList; + var labels:FlxTypedGroup; + var menuCamera:FlxCamera; + + public function new() + { + super(); + + var menuBG = new FlxSprite().loadGraphic(Paths.image('menuDesat')); + menuBG.color = 0xFFea71fd; + menuBG.setGraphicSize(Std.int(menuBG.width * 1.1)); + menuBG.updateHitbox(); + menuBG.screenCenter(); + add(menuBG); + + camera = FlxG.camera; + FlxG.cameras.add(menuCamera = new FlxCamera()); + menuCamera.bgColor = 0x0; + + add(labels = new FlxTypedGroup()); + labels.camera = menuCamera; + + add(controlGrid = new TextMenuList(Columns(2))); + controlGrid.camera = menuCamera; + + // FlxG.debugger.drawDebug = true; + var controlList = Control.createAll(); + for (i in 0...controlList.length) + { + var control = controlList[i]; + var name = control.getName(); + var y = (70 * i) + 30; + var label = labels.add(new BoldText(0, y, name)); + label.x += 100; + createItem(500, y, control, 0); + createItem(700, y, control, 1); + } + + var selected = controlGrid.members[0]; + var camFollow = new FlxObject(FlxG.width / 2, selected.y); + menuCamera.follow(camFollow, LOCKON, 0.06); + controlGrid.onChange.add(function (selected) camFollow.y = selected.y); + } + + function createItem(x = 0.0, y = 0.0, control:Control, index:Int) + { + var list = PlayerSettings.player1.controls.getInputsFor(control, Keys); + var name = "---"; + if (list.length > index) + { + if (list[index] == FlxKey.ESCAPE) + return createItem(x, y, control, 2); + + name = InputFormatter.format(list[index], Keys); + } + + trace(control.getName() + " " + index + ": " + name); + return controlGrid.createItem(x, y, name, Default, onSelect.bind(name, control, index)); + } + + function onSelect(name:String, control:Control, index:Int):Void + { + controlGrid.enabled = false; + // var prompt = new Prompt(); + } +} \ No newline at end of file From 43b0d5ac78b78a46e06fb5539d8895342331d17a Mon Sep 17 00:00:00 2001 From: George FunBook Date: Sat, 13 Mar 2021 20:11:56 -0600 Subject: [PATCH 11/37] add options menu --- source/Controls.hx | 504 +++++++----------- source/FreeplayState.hx | 8 +- source/GitarooPause.hx | 2 +- source/InputFormatter.hx | 2 +- source/LoadingState.hx | 2 +- source/MainMenuState.hx | 7 +- source/{OptionsMenu.hx => OptionsMenu_old.hx} | 8 - source/PauseSubState.hx | 6 +- source/PlayState.hx | 34 +- source/StoryMenuState.hx | 12 +- source/ui/AtlasText.hx | 158 +++++- source/ui/ControlsMenu.hx | 138 ++--- source/ui/MenuList.hx | 10 +- source/ui/OptionsState.hx | 258 +++++++++ source/ui/TextMenuList.hx | 2 +- 15 files changed, 701 insertions(+), 450 deletions(-) rename source/{OptionsMenu.hx => OptionsMenu_old.hx} (96%) create mode 100644 source/ui/OptionsState.hx diff --git a/source/Controls.hx b/source/Controls.hx index bb24d7883..c864cc918 100644 --- a/source/Controls.hx +++ b/source/Controls.hx @@ -11,45 +11,33 @@ import flixel.input.gamepad.FlxGamepadButton; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.keyboard.FlxKey; -#if (haxe >= "4.0.0") -enum abstract Action(String) to String from String -{ - var UP = "up"; - var LEFT = "left"; - var RIGHT = "right"; - var DOWN = "down"; - var UP_P = "up-press"; - var LEFT_P = "left-press"; - var RIGHT_P = "right-press"; - var DOWN_P = "down-press"; - var UP_R = "up-release"; - var LEFT_R = "left-release"; - var RIGHT_R = "right-release"; - var DOWN_R = "down-release"; - var ACCEPT = "accept"; - var BACK = "back"; - var PAUSE = "pause"; - var RESET = "reset"; - #if CAN_CHEAT - var CHEAT = "cheat"; - #end -} -#else @:enum abstract Action(String) to String from String { - var UP = "up"; - var LEFT = "left"; - var RIGHT = "right"; - var DOWN = "down"; - var UP_P = "up-press"; - var LEFT_P = "left-press"; - var RIGHT_P = "right-press"; - var DOWN_P = "down-press"; - var UP_R = "up-release"; - var LEFT_R = "left-release"; - var RIGHT_R = "right-release"; - var DOWN_R = "down-release"; + var UI_UP = "ui_up"; + var UI_LEFT = "ui_left"; + var UI_RIGHT = "ui_right"; + var UI_DOWN = "ui_down"; + var UI_UP_P = "ui_up-press"; + var UI_LEFT_P = "ui_left-press"; + var UI_RIGHT_P = "ui_right-press"; + var UI_DOWN_P = "ui_down-press"; + var UI_UP_R = "ui_up-release"; + var UI_LEFT_R = "ui_left-release"; + var UI_RIGHT_R = "ui_right-release"; + var UI_DOWN_R = "ui_down-release"; + var NOTE_UP = "note_up"; + var NOTE_LEFT = "note_left"; + var NOTE_RIGHT = "note_right"; + var NOTE_DOWN = "note_down"; + var NOTE_UP_P = "note_up-press"; + var NOTE_LEFT_P = "note_left-press"; + var NOTE_RIGHT_P = "note_right-press"; + var NOTE_DOWN_P = "note_down-press"; + var NOTE_UP_R = "note_up-release"; + var NOTE_LEFT_R = "note_left-release"; + var NOTE_RIGHT_R = "note_right-release"; + var NOTE_DOWN_R = "note_down-release"; var ACCEPT = "accept"; var BACK = "back"; var PAUSE = "pause"; @@ -58,7 +46,6 @@ abstract Action(String) to String from String var CHEAT = "cheat"; #end } -#end enum Device { @@ -73,10 +60,14 @@ enum Device */ enum Control { - UP; - LEFT; - RIGHT; - DOWN; + UI_UP; + UI_LEFT; + UI_RIGHT; + UI_DOWN; + NOTE_UP; + NOTE_LEFT; + NOTE_RIGHT; + NOTE_DOWN; RESET; ACCEPT; BACK; @@ -100,18 +91,30 @@ enum KeyboardScheme */ class Controls extends FlxActionSet { - var _up = new FlxActionDigital(Action.UP); - var _left = new FlxActionDigital(Action.LEFT); - var _right = new FlxActionDigital(Action.RIGHT); - var _down = new FlxActionDigital(Action.DOWN); - var _upP = new FlxActionDigital(Action.UP_P); - var _leftP = new FlxActionDigital(Action.LEFT_P); - var _rightP = new FlxActionDigital(Action.RIGHT_P); - var _downP = new FlxActionDigital(Action.DOWN_P); - var _upR = new FlxActionDigital(Action.UP_R); - var _leftR = new FlxActionDigital(Action.LEFT_R); - var _rightR = new FlxActionDigital(Action.RIGHT_R); - var _downR = new FlxActionDigital(Action.DOWN_R); + var _ui_up = new FlxActionDigital(Action.UI_UP); + var _ui_left = new FlxActionDigital(Action.UI_LEFT); + var _ui_right = new FlxActionDigital(Action.UI_RIGHT); + var _ui_down = new FlxActionDigital(Action.UI_DOWN); + var _ui_upP = new FlxActionDigital(Action.UI_UP_P); + var _ui_leftP = new FlxActionDigital(Action.UI_LEFT_P); + var _ui_rightP = new FlxActionDigital(Action.UI_RIGHT_P); + var _ui_downP = new FlxActionDigital(Action.UI_DOWN_P); + var _ui_upR = new FlxActionDigital(Action.UI_UP_R); + var _ui_leftR = new FlxActionDigital(Action.UI_LEFT_R); + var _ui_rightR = new FlxActionDigital(Action.UI_RIGHT_R); + var _ui_downR = new FlxActionDigital(Action.UI_DOWN_R); + var _note_up = new FlxActionDigital(Action.NOTE_UP); + var _note_left = new FlxActionDigital(Action.NOTE_LEFT); + var _note_right = new FlxActionDigital(Action.NOTE_RIGHT); + var _note_down = new FlxActionDigital(Action.NOTE_DOWN); + var _note_upP = new FlxActionDigital(Action.NOTE_UP_P); + var _note_leftP = new FlxActionDigital(Action.NOTE_LEFT_P); + var _note_rightP = new FlxActionDigital(Action.NOTE_RIGHT_P); + var _note_downP = new FlxActionDigital(Action.NOTE_DOWN_P); + var _note_upR = new FlxActionDigital(Action.NOTE_UP_R); + var _note_leftR = new FlxActionDigital(Action.NOTE_LEFT_R); + var _note_rightR = new FlxActionDigital(Action.NOTE_RIGHT_R); + var _note_downR = new FlxActionDigital(Action.NOTE_DOWN_R); var _accept = new FlxActionDigital(Action.ACCEPT); var _back = new FlxActionDigital(Action.BACK); var _pause = new FlxActionDigital(Action.PAUSE); @@ -120,149 +123,77 @@ class Controls extends FlxActionSet var _cheat = new FlxActionDigital(Action.CHEAT); #end - #if (haxe >= "4.0.0") - var byName:Map = []; - #else var byName:Map = new Map(); - #end public var gamepadsAdded:Array = []; public var keyboardScheme = KeyboardScheme.None; - public var UP(get, never):Bool; + public var UI_UP (get, never):Bool; inline function get_UI_UP () return _ui_up .check(); + public var UI_LEFT (get, never):Bool; inline function get_UI_LEFT () return _ui_left .check(); + public var UI_RIGHT(get, never):Bool; inline function get_UI_RIGHT() return _ui_right.check(); + public var UI_DOWN (get, never):Bool; inline function get_UI_DOWN () return _ui_down .check(); - inline function get_UP() - return _up.check(); + public var UI_UP_P (get, never):Bool; inline function get_UI_UP_P () return _ui_upP .check(); + public var UI_LEFT_P (get, never):Bool; inline function get_UI_LEFT_P () return _ui_leftP .check(); + public var UI_RIGHT_P(get, never):Bool; inline function get_UI_RIGHT_P() return _ui_rightP.check(); + public var UI_DOWN_P (get, never):Bool; inline function get_UI_DOWN_P () return _ui_downP .check(); - public var LEFT(get, never):Bool; + public var UI_UP_R (get, never):Bool; inline function get_UI_UP_R () return _ui_upR .check(); + public var UI_LEFT_R (get, never):Bool; inline function get_UI_LEFT_R () return _ui_leftR .check(); + public var UI_RIGHT_R(get, never):Bool; inline function get_UI_RIGHT_R() return _ui_rightR.check(); + public var UI_DOWN_R (get, never):Bool; inline function get_UI_DOWN_R () return _ui_downR .check(); + + public var NOTE_UP (get, never):Bool; inline function get_NOTE_UP () return _note_up .check(); + public var NOTE_LEFT (get, never):Bool; inline function get_NOTE_LEFT () return _note_left .check(); + public var NOTE_RIGHT(get, never):Bool; inline function get_NOTE_RIGHT() return _note_right.check(); + public var NOTE_DOWN (get, never):Bool; inline function get_NOTE_DOWN () return _note_down .check(); - inline function get_LEFT() - return _left.check(); + public var NOTE_UP_P (get, never):Bool; inline function get_NOTE_UP_P () return _note_upP .check(); + public var NOTE_LEFT_P (get, never):Bool; inline function get_NOTE_LEFT_P () return _note_leftP .check(); + public var NOTE_RIGHT_P(get, never):Bool; inline function get_NOTE_RIGHT_P() return _note_rightP.check(); + public var NOTE_DOWN_P (get, never):Bool; inline function get_NOTE_DOWN_P () return _note_downP .check(); - public var RIGHT(get, never):Bool; - - inline function get_RIGHT() - return _right.check(); - - public var DOWN(get, never):Bool; - - inline function get_DOWN() - return _down.check(); - - public var UP_P(get, never):Bool; - - inline function get_UP_P() - return _upP.check(); - - public var LEFT_P(get, never):Bool; - - inline function get_LEFT_P() - return _leftP.check(); - - public var RIGHT_P(get, never):Bool; - - inline function get_RIGHT_P() - return _rightP.check(); - - public var DOWN_P(get, never):Bool; - - inline function get_DOWN_P() - return _downP.check(); - - public var UP_R(get, never):Bool; - - inline function get_UP_R() - return _upR.check(); - - public var LEFT_R(get, never):Bool; - - inline function get_LEFT_R() - return _leftR.check(); - - public var RIGHT_R(get, never):Bool; - - inline function get_RIGHT_R() - return _rightR.check(); - - public var DOWN_R(get, never):Bool; - - inline function get_DOWN_R() - return _downR.check(); - - public var ACCEPT(get, never):Bool; - - inline function get_ACCEPT() - return _accept.check(); - - public var BACK(get, never):Bool; - - inline function get_BACK() - return _back.check(); - - public var PAUSE(get, never):Bool; - - inline function get_PAUSE() - return _pause.check(); - - public var RESET(get, never):Bool; - - inline function get_RESET() - return _reset.check(); + public var NOTE_UP_R (get, never):Bool; inline function get_NOTE_UP_R () return _note_upR .check(); + public var NOTE_LEFT_R (get, never):Bool; inline function get_NOTE_LEFT_R () return _note_leftR .check(); + public var NOTE_RIGHT_R(get, never):Bool; inline function get_NOTE_RIGHT_R() return _note_rightR.check(); + public var NOTE_DOWN_R (get, never):Bool; inline function get_NOTE_DOWN_R () return _note_downR .check(); + public var ACCEPT(get, never):Bool; inline function get_ACCEPT() return _accept.check(); + public var BACK (get, never):Bool; inline function get_BACK () return _back .check(); + public var PAUSE (get, never):Bool; inline function get_PAUSE () return _pause .check(); + public var RESET (get, never):Bool; inline function get_RESET () return _reset .check(); #if CAN_CHEAT - public var CHEAT(get, never):Bool; - - inline function get_CHEAT() - return _cheat.check(); + public var CHEAT (get, never):Bool; inline function get_CHEAT () return _cheat.check (); #end - #if (haxe >= "4.0.0") - public function new(name, scheme = None) - { - super(name); - - add(_up); - add(_left); - add(_right); - add(_down); - add(_upP); - add(_leftP); - add(_rightP); - add(_downP); - add(_upR); - add(_leftR); - add(_rightR); - add(_downR); - add(_accept); - add(_back); - add(_pause); - add(_reset); - #if CAN_CHEAT - add(_cheat); - #end - - for (action in digitalActions) - byName[action.name] = action; - - setKeyboardScheme(scheme, false); - } - #else public function new(name, scheme:KeyboardScheme = null) { super(name); - add(_up); - add(_left); - add(_right); - add(_down); - add(_upP); - add(_leftP); - add(_rightP); - add(_downP); - add(_upR); - add(_leftR); - add(_rightR); - add(_downR); + add(_ui_up); + add(_ui_left); + add(_ui_right); + add(_ui_down); + add(_ui_upP); + add(_ui_leftP); + add(_ui_rightP); + add(_ui_downP); + add(_ui_upR); + add(_ui_leftR); + add(_ui_rightR); + add(_ui_downR); + add(_note_up); + add(_note_left); + add(_note_right); + add(_note_down); + add(_note_upP); + add(_note_leftP); + add(_note_rightP); + add(_note_downP); + add(_note_upR); + add(_note_leftR); + add(_note_rightR); + add(_note_downR); add(_accept); add(_back); add(_pause); @@ -273,12 +204,12 @@ class Controls extends FlxActionSet for (action in digitalActions) byName[action.name] = action; - + if (scheme == null) scheme = None; + setKeyboardScheme(scheme, false); } - #end override function update() { @@ -315,10 +246,14 @@ class Controls extends FlxActionSet { return switch (control) { - case UP: _up; - case DOWN: _down; - case LEFT: _left; - case RIGHT: _right; + case UI_UP: _ui_up; + case UI_DOWN: _ui_down; + case UI_LEFT: _ui_left; + case UI_RIGHT: _ui_right; + case NOTE_UP: _note_up; + case NOTE_DOWN: _note_down; + case NOTE_LEFT: _note_left; + case NOTE_RIGHT: _note_right; case ACCEPT: _accept; case BACK: _back; case PAUSE: _pause; @@ -345,22 +280,38 @@ class Controls extends FlxActionSet { switch (control) { - case UP: - func(_up, PRESSED); - func(_upP, JUST_PRESSED); - func(_upR, JUST_RELEASED); - case LEFT: - func(_left, PRESSED); - func(_leftP, JUST_PRESSED); - func(_leftR, JUST_RELEASED); - case RIGHT: - func(_right, PRESSED); - func(_rightP, JUST_PRESSED); - func(_rightR, JUST_RELEASED); - case DOWN: - func(_down, PRESSED); - func(_downP, JUST_PRESSED); - func(_downR, JUST_RELEASED); + case UI_UP: + func(_ui_up, PRESSED); + func(_ui_upP, JUST_PRESSED); + func(_ui_upR, JUST_RELEASED); + case UI_LEFT: + func(_ui_left, PRESSED); + func(_ui_leftP, JUST_PRESSED); + func(_ui_leftR, JUST_RELEASED); + case UI_RIGHT: + func(_ui_right, PRESSED); + func(_ui_rightP, JUST_PRESSED); + func(_ui_rightR, JUST_RELEASED); + case UI_DOWN: + func(_ui_down, PRESSED); + func(_ui_downP, JUST_PRESSED); + func(_ui_downR, JUST_RELEASED); + case NOTE_UP: + func(_note_up, PRESSED); + func(_note_upP, JUST_PRESSED); + func(_note_upR, JUST_RELEASED); + case NOTE_LEFT: + func(_note_left, PRESSED); + func(_note_leftP, JUST_PRESSED); + func(_note_leftR, JUST_RELEASED); + case NOTE_RIGHT: + func(_note_right, PRESSED); + func(_note_rightP, JUST_PRESSED); + func(_note_rightR, JUST_RELEASED); + case NOTE_DOWN: + func(_note_down, PRESSED); + func(_note_downP, JUST_PRESSED); + func(_note_downR, JUST_RELEASED); case ACCEPT: func(_accept, JUST_PRESSED); case BACK: @@ -399,16 +350,6 @@ class Controls extends FlxActionSet public function copyFrom(controls:Controls, ?device:Device) { - #if (haxe >= "4.0.0") - for (name => action in controls.byName) - { - for (input in action.inputs) - { - if (device == null || isDevice(input, device)) - byName[name].add(cast input); - } - } - #else for (name in controls.byName.keys()) { var action = controls.byName[name]; @@ -418,21 +359,14 @@ class Controls extends FlxActionSet byName[name].add(cast input); } } - #end switch (device) { case null: // add all - #if (haxe >= "4.0.0") - for (gamepad in controls.gamepadsAdded) - if (!gamepadsAdded.contains(gamepad)) - gamepadsAdded.push(gamepad); - #else for (gamepad in controls.gamepadsAdded) if (gamepadsAdded.indexOf(gamepad) == -1) gamepadsAdded.push(gamepad); - #end mergeKeyboardScheme(controls.keyboardScheme); @@ -468,11 +402,7 @@ class Controls extends FlxActionSet */ public function bindKeys(control:Control, keys:Array) { - #if (haxe >= "4.0.0") - inline forEachBound(control, (action, state) -> addKeys(action, keys, state)); - #else forEachBound(control, function(action, state) addKeys(action, keys, state)); - #end } /** @@ -481,11 +411,7 @@ class Controls extends FlxActionSet */ public function unbindKeys(control:Control, keys:Array) { - #if (haxe >= "4.0.0") - inline forEachBound(control, (action, _) -> removeKeys(action, keys)); - #else forEachBound(control, function(action, _) removeKeys(action, keys)); - #end } inline static function addKeys(action:FlxActionDigital, keys:Array, state:FlxInputState) @@ -512,65 +438,43 @@ class Controls extends FlxActionSet keyboardScheme = scheme; - #if (haxe >= "4.0.0") switch (scheme) { case Solo: - inline bindKeys(Control.UP, [W, FlxKey.UP]); - inline bindKeys(Control.DOWN, [S, FlxKey.DOWN]); - inline bindKeys(Control.LEFT, [A, FlxKey.LEFT]); - inline bindKeys(Control.RIGHT, [D, FlxKey.RIGHT]); - inline bindKeys(Control.ACCEPT, [Z, SPACE, ENTER]); - inline bindKeys(Control.BACK, [BACKSPACE, ESCAPE]); - inline bindKeys(Control.PAUSE, [P, ENTER, ESCAPE]); - inline bindKeys(Control.RESET, [R]); - case Duo(true): - inline bindKeys(Control.UP, [W]); - inline bindKeys(Control.DOWN, [S]); - inline bindKeys(Control.LEFT, [A]); - inline bindKeys(Control.RIGHT, [D]); - inline bindKeys(Control.ACCEPT, [G, Z]); - inline bindKeys(Control.BACK, [H, X]); - inline bindKeys(Control.PAUSE, [ONE]); - inline bindKeys(Control.RESET, [R]); - case Duo(false): - inline bindKeys(Control.UP, [FlxKey.UP]); - inline bindKeys(Control.DOWN, [FlxKey.DOWN]); - inline bindKeys(Control.LEFT, [FlxKey.LEFT]); - inline bindKeys(Control.RIGHT, [FlxKey.RIGHT]); - inline bindKeys(Control.ACCEPT, [O]); - inline bindKeys(Control.BACK, [P]); - inline bindKeys(Control.PAUSE, [ENTER]); - inline bindKeys(Control.RESET, [BACKSPACE]); - case None: // nothing - case Custom: // nothing - } - #else - switch (scheme) - { - case Solo: - bindKeys(Control.UP, [W, FlxKey.UP]); - bindKeys(Control.DOWN, [S, FlxKey.DOWN]); - bindKeys(Control.LEFT, [A, FlxKey.LEFT]); - bindKeys(Control.RIGHT, [D, FlxKey.RIGHT]); + bindKeys(Control.UI_UP, [W, FlxKey.UP]); + bindKeys(Control.UI_DOWN, [S, FlxKey.DOWN]); + bindKeys(Control.UI_LEFT, [A, FlxKey.LEFT]); + bindKeys(Control.UI_RIGHT, [D, FlxKey.RIGHT]); + bindKeys(Control.NOTE_UP, [W, FlxKey.UP]); + bindKeys(Control.NOTE_DOWN, [S, FlxKey.DOWN]); + bindKeys(Control.NOTE_LEFT, [A, FlxKey.LEFT]); + bindKeys(Control.NOTE_RIGHT, [D, FlxKey.RIGHT]); bindKeys(Control.ACCEPT, [Z, SPACE, ENTER]); bindKeys(Control.BACK, [BACKSPACE, ESCAPE]); bindKeys(Control.PAUSE, [P, ENTER, ESCAPE]); bindKeys(Control.RESET, [R]); case Duo(true): - bindKeys(Control.UP, [W]); - bindKeys(Control.DOWN, [S]); - bindKeys(Control.LEFT, [A]); - bindKeys(Control.RIGHT, [D]); + bindKeys(Control.UI_UP, [W]); + bindKeys(Control.UI_DOWN, [S]); + bindKeys(Control.UI_LEFT, [A]); + bindKeys(Control.UI_RIGHT, [D]); + bindKeys(Control.NOTE_UP, [W]); + bindKeys(Control.NOTE_DOWN, [S]); + bindKeys(Control.NOTE_LEFT, [A]); + bindKeys(Control.NOTE_RIGHT, [D]); bindKeys(Control.ACCEPT, [G, Z]); bindKeys(Control.BACK, [H, X]); bindKeys(Control.PAUSE, [ONE]); bindKeys(Control.RESET, [R]); case Duo(false): - bindKeys(Control.UP, [FlxKey.UP]); - bindKeys(Control.DOWN, [FlxKey.DOWN]); - bindKeys(Control.LEFT, [FlxKey.LEFT]); - bindKeys(Control.RIGHT, [FlxKey.RIGHT]); + bindKeys(Control.UI_UP, [FlxKey.UP]); + bindKeys(Control.UI_DOWN, [FlxKey.DOWN]); + bindKeys(Control.UI_LEFT, [FlxKey.LEFT]); + bindKeys(Control.UI_RIGHT, [FlxKey.RIGHT]); + bindKeys(Control.NOTE_UP, [FlxKey.UP]); + bindKeys(Control.NOTE_DOWN, [FlxKey.DOWN]); + bindKeys(Control.NOTE_LEFT, [FlxKey.LEFT]); + bindKeys(Control.NOTE_RIGHT, [FlxKey.RIGHT]); bindKeys(Control.ACCEPT, [O]); bindKeys(Control.BACK, [P]); bindKeys(Control.PAUSE, [ENTER]); @@ -578,7 +482,6 @@ class Controls extends FlxActionSet case None: // nothing case Custom: // nothing } - #end } function removeKeyboard() @@ -599,26 +502,16 @@ class Controls extends FlxActionSet { gamepadsAdded.push(id); - #if (haxe >= "4.0.0") - for (control => buttons in buttonMap) - inline bindButtons(control, id, buttons); - #else for (control in buttonMap.keys()) bindButtons(control, id, buttonMap[control]); - #end } inline function addGamepadLiteral(id:Int, ?buttonMap:Map>):Void { gamepadsAdded.push(id); - #if (haxe >= "4.0.0") - for (control => buttons in buttonMap) - inline bindButtons(control, id, buttons); - #else for (control in buttonMap.keys()) bindButtons(control, id, buttonMap[control]); - #end } public function removeGamepad(deviceID:Int = FlxInputDeviceID.ALL):Void @@ -639,34 +532,29 @@ class Controls extends FlxActionSet public function addDefaultGamepad(id):Void { - #if !switch addGamepadLiteral(id, [ - Control.ACCEPT => [A], - Control.BACK => [B], - Control.UP => [DPAD_UP, LEFT_STICK_DIGITAL_UP], - Control.DOWN => [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN], - Control.LEFT => [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT], - Control.RIGHT => [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT], - Control.PAUSE => [START], - Control.RESET => [Y] - ]); - #else - addGamepadLiteral(id, [ - //Swap A and B for switch + #if switch Control.ACCEPT => [B], Control.BACK => [A], - Control.UP => [DPAD_UP, LEFT_STICK_DIGITAL_UP, RIGHT_STICK_DIGITAL_UP], - Control.DOWN => [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN, RIGHT_STICK_DIGITAL_DOWN], - Control.LEFT => [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT], - Control.RIGHT => [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT], + #else + Control.ACCEPT => [A], + Control.BACK => [B], + #end + Control.UI_UP => [DPAD_UP, LEFT_STICK_DIGITAL_UP], + Control.UI_DOWN => [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN], + Control.UI_LEFT => [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT], + Control.UI_RIGHT => [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT], + // don't swap A/B or X/Y for switch on these. A is always the bottom face button + Control.NOTE_UP => [DPAD_UP, Y, LEFT_STICK_DIGITAL_UP, RIGHT_STICK_DIGITAL_UP], + Control.NOTE_DOWN => [DPAD_DOWN, A, LEFT_STICK_DIGITAL_DOWN, RIGHT_STICK_DIGITAL_DOWN], + Control.NOTE_LEFT => [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT], + Control.NOTE_RIGHT => [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT], Control.PAUSE => [START], - //Swap Y and X for switch - Control.RESET => [Y], + Control.RESET => [Y] #if CAN_CHEAT - Control.CHEAT => [X] + ,Control.CHEAT => [X] #end ]); - #end } /** @@ -675,11 +563,7 @@ class Controls extends FlxActionSet */ public function bindButtons(control:Control, id, buttons) { - #if (haxe >= "4.0.0") - inline forEachBound(control, (action, state) -> addButtons(action, buttons, state, id)); - #else forEachBound(control, function(action, state) addButtons(action, buttons, state, id)); - #end } /** @@ -688,11 +572,7 @@ class Controls extends FlxActionSet */ public function unbindButtons(control:Control, gamepadID:Int, buttons) { - #if (haxe >= "4.0.0") - inline forEachBound(control, (action, _) -> removeButtons(action, gamepadID, buttons)); - #else forEachBound(control, function(action, _) removeButtons(action, gamepadID, buttons)); - #end } inline static function addButtons(action:FlxActionDigital, buttons:Array, state, id) diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx index 872e44d27..9bf241128 100644 --- a/source/FreeplayState.hx +++ b/source/FreeplayState.hx @@ -166,8 +166,8 @@ class FreeplayState extends MusicBeatState scoreText.text = "PERSONAL BEST:" + lerpScore; - var upP = controls.UP_P; - var downP = controls.DOWN_P; + var upP = controls.UI_UP_P; + var downP = controls.UI_DOWN_P; var accepted = controls.ACCEPT; if (upP) @@ -179,9 +179,9 @@ class FreeplayState extends MusicBeatState changeSelection(1); } - if (controls.LEFT_P) + if (controls.UI_LEFT_P) changeDiff(-1); - if (controls.RIGHT_P) + if (controls.UI_RIGHT_P) changeDiff(1); if (controls.BACK) diff --git a/source/GitarooPause.hx b/source/GitarooPause.hx index cb9705c55..1e9a1c8cd 100644 --- a/source/GitarooPause.hx +++ b/source/GitarooPause.hx @@ -52,7 +52,7 @@ class GitarooPause extends MusicBeatState override function update(elapsed:Float) { - if (controls.LEFT_P || controls.RIGHT_P) + if (controls.UI_LEFT_P || controls.UI_RIGHT_P) changeThing(); if (controls.ACCEPT) diff --git a/source/InputFormatter.hx b/source/InputFormatter.hx index c80c67384..2ace8b0ac 100644 --- a/source/InputFormatter.hx +++ b/source/InputFormatter.hx @@ -148,7 +148,7 @@ class InputFormatter } @:forward -enum abstract ControllerName(String) from String to String +@:enum abstract ControllerName(String) from String to String { var OUYA = "Ouya" ; var PS4 = "PS4" ; diff --git a/source/LoadingState.hx b/source/LoadingState.hx index 23bce2e68..b479250d7 100644 --- a/source/LoadingState.hx +++ b/source/LoadingState.hx @@ -80,7 +80,7 @@ class LoadingState extends MusicBeatState if (!Assets.cache.hasSound(path)) { var library = Assets.getLibrary("songs"); - final symbolPath = path.split(":").pop(); + var symbolPath = path.split(":").pop(); // @:privateAccess // library.types.set(symbolPath, SOUND); // @:privateAccess diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index 26d893b30..0513d82a7 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -24,6 +24,7 @@ import ui.NgPrompt; import ui.AtlasMenuList; import ui.MenuList; +import ui.OptionsState; import ui.Prompt; using StringTools; @@ -80,16 +81,16 @@ class MainMenuState extends MusicBeatState }); - var hasPopupBlocker = #if web true #else false #end; menuItems.enabled = false;// disable for intro menuItems.createItem('story mode', function () startExitState(new StoryMenuState())); menuItems.createItem('freeplay', function () startExitState(new FreeplayState())); // addMenuItem('options', function () startExitState(new OptionMenu())); #if CAN_OPEN_LINKS + var hasPopupBlocker = #if web true #else false #end; menuItems.createItem('donate', selectDonate, hasPopupBlocker); #end - menuItems.createItem('options', function () startExitState(new OptionsMenu())); + menuItems.createItem('options', function () startExitState(new OptionsState())); // #if newgrounds // if (NGio.isLoggedIn) // menuItems.createItem("logout", selectLogout); @@ -136,6 +137,7 @@ class MainMenuState extends MusicBeatState camFollow.setPosition(selected.getGraphicMidpoint().x, selected.getGraphicMidpoint().y); } + #if CAN_OPEN_LINKS function selectDonate() { #if linux @@ -144,6 +146,7 @@ class MainMenuState extends MusicBeatState FlxG.openURL('https://ninja-muffin24.itch.io/funkin'); #end } + #end #if newgrounds function selectLogin() diff --git a/source/OptionsMenu.hx b/source/OptionsMenu_old.hx similarity index 96% rename from source/OptionsMenu.hx rename to source/OptionsMenu_old.hx index c3dc35a09..36cd79d7f 100644 --- a/source/OptionsMenu.hx +++ b/source/OptionsMenu_old.hx @@ -12,14 +12,6 @@ import flixel.text.FlxText; import flixel.util.FlxColor; import lime.utils.Assets; -class OptionsMenu extends MusicBeatState -{ - override function create() - { - add(new ui.ControlsMenu()); - } -} - class OptionsMenu_old extends MusicBeatState { var selector:FlxText; diff --git a/source/PauseSubState.hx b/source/PauseSubState.hx index 69bdf6007..7a5d56a38 100644 --- a/source/PauseSubState.hx +++ b/source/PauseSubState.hx @@ -47,7 +47,7 @@ class PauseSubState extends MusicBeatSubstate changeSelection(); - cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; + // cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]]; } override function update(elapsed:Float) @@ -57,8 +57,8 @@ class PauseSubState extends MusicBeatSubstate super.update(elapsed); - var upP = controls.UP_P; - var downP = controls.DOWN_P; + var upP = controls.UI_UP_P; + var downP = controls.UI_DOWN_P; var accepted = controls.ACCEPT; if (upP) diff --git a/source/PlayState.hx b/source/PlayState.hx index 2f699ea45..cf9006af9 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1188,6 +1188,7 @@ class PlayState extends MusicBeatState { if (paused) { + camHUD.exists = false; if (FlxG.sound.music != null) { FlxG.sound.music.pause(); @@ -1213,6 +1214,7 @@ class PlayState extends MusicBeatState if (!startTimer.finished) startTimer.active = true; paused = false; + camHUD.exists = true; } super.closeSubState(); @@ -1835,20 +1837,20 @@ class PlayState extends MusicBeatState private function keyShit():Void { // HOLDING - var up = controls.UP; - var right = controls.RIGHT; - var down = controls.DOWN; - var left = controls.LEFT; + var up = controls.NOTE_UP; + var right = controls.NOTE_RIGHT; + var down = controls.NOTE_DOWN; + var left = controls.NOTE_LEFT; - var upP = controls.UP_P; - var rightP = controls.RIGHT_P; - var downP = controls.DOWN_P; - var leftP = controls.LEFT_P; + var upP = controls.NOTE_UP_P; + var rightP = controls.NOTE_RIGHT_P; + var downP = controls.NOTE_DOWN_P; + var leftP = controls.NOTE_LEFT_P; - var upR = controls.UP_R; - var rightR = controls.RIGHT_R; - var downR = controls.DOWN_R; - var leftR = controls.LEFT_R; + var upR = controls.NOTE_UP_R; + var rightR = controls.NOTE_RIGHT_R; + var downR = controls.NOTE_DOWN_R; + var leftR = controls.NOTE_LEFT_R; var controlArray:Array = [leftP, downP, upP, rightP]; @@ -2067,10 +2069,10 @@ class PlayState extends MusicBeatState { // just double pasting this shit cuz fuk u // REDO THIS SYSTEM! - var upP = controls.UP_P; - var rightP = controls.RIGHT_P; - var downP = controls.DOWN_P; - var leftP = controls.LEFT_P; + var upP = controls.NOTE_UP_P; + var rightP = controls.NOTE_RIGHT_P; + var downP = controls.NOTE_DOWN_P; + var leftP = controls.NOTE_LEFT_P; if (leftP) noteMiss(0); diff --git a/source/StoryMenuState.hx b/source/StoryMenuState.hx index b985369b8..22ba229ca 100644 --- a/source/StoryMenuState.hx +++ b/source/StoryMenuState.hx @@ -237,29 +237,29 @@ class StoryMenuState extends MusicBeatState { if (!selectedWeek) { - if (controls.UP_P) + if (controls.UI_UP_P) { changeWeek(-1); } - if (controls.DOWN_P) + if (controls.UI_DOWN_P) { changeWeek(1); } - if (controls.RIGHT) + if (controls.UI_RIGHT) rightArrow.animation.play('press') else rightArrow.animation.play('idle'); - if (controls.LEFT) + if (controls.UI_LEFT) leftArrow.animation.play('press'); else leftArrow.animation.play('idle'); - if (controls.RIGHT_P) + if (controls.UI_RIGHT_P) changeDifficulty(1); - if (controls.LEFT_P) + if (controls.UI_LEFT_P) changeDifficulty(-1); } diff --git a/source/ui/AtlasText.hx b/source/ui/AtlasText.hx index 579c35729..4c5f653b2 100644 --- a/source/ui/AtlasText.hx +++ b/source/ui/AtlasText.hx @@ -18,23 +18,24 @@ abstract BoldText(AtlasText) from AtlasText to AtlasText */ class AtlasText extends FlxTypedSpriteGroup { - static var maxHeights = new Map(); - public var text(default, set):String; + static var fonts = new Map(); + static var casesAllowed = new Map(); + public var text(default, set):String = ""; - var atlas:FlxAtlasFrames; - var maxHeight = 0.0; + var font:AtlasFontData; - public function new (x = 0.0, y = 0.0, text:String, font:AtlasFont = Default) + public var atlas(get, never):FlxAtlasFrames; + inline function get_atlas() return font.atlas; + public var caseAllowed(get, never):Case; + inline function get_caseAllowed() return font.caseAllowed; + public var maxHeight(get, never):Float; + inline function get_maxHeight() return font.maxHeight; + + public function new (x = 0.0, y = 0.0, text:String, fontName:AtlasFont = Default) { - atlas = Paths.getSparrowAtlas("fonts/" + font.getName().toLowerCase()); - if (maxHeights.exists(font)) - { - maxHeight = 0; - for (frame in atlas.frames) - maxHeight = Math.max(maxHeight, frame.frame.height); - maxHeights[font] = maxHeight; - } - maxHeight = maxHeights[font]; + if (!fonts.exists(fontName)) + fonts[fontName] = new AtlasFontData(fontName); + font = fonts[fontName]; super(x, y); @@ -43,18 +44,87 @@ class AtlasText extends FlxTypedSpriteGroup function set_text(value:String) { - if (this.text == value) + if (value == null) + value = ""; + + var caseValue = restrictCase(value); + var caseText = restrictCase(this.text); + + this.text = value; + if (caseText == caseValue) + return value; // cancel redraw + + if (caseValue.indexOf(caseText) == 0) + { + // new text is just old text with additions at the end, append the difference + appendTextCased(caseValue.substr(caseText.length)); return this.text; + } + + value = caseValue; group.kill(); + if (value == "") + return this.text; + + appendTextCased(this.text); + return this.text; + } + + /** + * Adds new characters, without needing to redraw the previous characters + * @param text The text to add. + * @throws String if `text` is null. + */ + public function appendText(text:String) + { + if (text == null) + throw "cannot append null"; + + if (text == "") + return; + + this.text = this.text + text; + } + + /** + * Converts all characters to fit the font's `allowedCase`. + * @param text + */ + function restrictCase(text:String) + { + return switch(caseAllowed) + { + case Both: text; + case Upper: text.toUpperCase(); + case Lower: text.toLowerCase(); + } + } + + /** + * Adds new text on top of the existing text. Helper for other methods; DOESN'T CHANGE `this.text`. + * @param text The text to add, assumed to match the font's `caseAllowed`. + */ + function appendTextCased(text:String) + { + var charCount = group.countLiving(); var xPos:Float = 0; var yPos:Float = 0; - - var charCount = 0; - for (char in value.split("")) + // `countLiving` returns -1 if group is empty + if (charCount == -1) + charCount = 0; + else if (charCount > 0) { - switch(char) + var lastChar = group.members[charCount - 1]; + xPos = lastChar.x + lastChar.width; + yPos = lastChar.y + lastChar.height - maxHeight; + } + + var splitValues = text.split(""); + for (i in 0...splitValues.length) + { + switch(splitValues[i]) { case " ": { @@ -63,9 +133,9 @@ class AtlasText extends FlxTypedSpriteGroup case "\n": { xPos = 0; - yPos += 55; + yPos += maxHeight; } - default: + case char: { var charSprite:AtlasChar; if (group.members.length <= charCount) @@ -85,8 +155,6 @@ class AtlasText extends FlxTypedSpriteGroup } } } - // updateHitbox(); - return this.text = value; } } @@ -105,7 +173,8 @@ class AtlasChar extends FlxSprite { if (this.char != value) { - animation.addByPrefix("anim", getAnimPrefix(value), 24); + var prefix = getAnimPrefix(value); + animation.addByPrefix("anim", prefix, 24); animation.play("anim"); updateHitbox(); } @@ -133,6 +202,47 @@ class AtlasChar extends FlxSprite } } +private class AtlasFontData +{ + static public var upperChar = ~/^[A-Z]\d+$/; + static public var lowerChar = ~/^[a-z]\d+$/; + + public var atlas:FlxAtlasFrames; + public var maxHeight:Float = 0.0; + public var caseAllowed:Case = Both; + + public function new (name:AtlasFont) + { + atlas = Paths.getSparrowAtlas("fonts/" + name.getName().toLowerCase()); + atlas.parent.destroyOnNoUse = false; + atlas.parent.persist = true; + + var containsUpper = false; + var containsLower = false; + + for (frame in atlas.frames) + { + maxHeight = Math.max(maxHeight, frame.frame.height); + + if (!containsUpper) + containsUpper = upperChar.match(frame.name); + + if (!containsLower) + containsLower = lowerChar.match(frame.name); + } + + if (containsUpper != containsLower) + caseAllowed = containsUpper ? Upper : Lower; + } +} + +enum Case +{ + Both; + Upper; + Lower; +} + enum AtlasFont { Default; diff --git a/source/ui/ControlsMenu.hx b/source/ui/ControlsMenu.hx index 7dbc20983..90d3909bc 100644 --- a/source/ui/ControlsMenu.hx +++ b/source/ui/ControlsMenu.hx @@ -11,71 +11,77 @@ import Controls; import ui.AtlasText; import ui.TextMenuList; -class ControlsMenu extends flixel.group.FlxGroup +class ControlsMenu extends ui.OptionsState.Page { - var controlGrid:TextMenuList; - var labels:FlxTypedGroup; - var menuCamera:FlxCamera; - - public function new() - { - super(); - - var menuBG = new FlxSprite().loadGraphic(Paths.image('menuDesat')); - menuBG.color = 0xFFea71fd; - menuBG.setGraphicSize(Std.int(menuBG.width * 1.1)); - menuBG.updateHitbox(); - menuBG.screenCenter(); - add(menuBG); - - camera = FlxG.camera; - FlxG.cameras.add(menuCamera = new FlxCamera()); - menuCamera.bgColor = 0x0; - - add(labels = new FlxTypedGroup()); - labels.camera = menuCamera; - - add(controlGrid = new TextMenuList(Columns(2))); - controlGrid.camera = menuCamera; - - // FlxG.debugger.drawDebug = true; - var controlList = Control.createAll(); - for (i in 0...controlList.length) - { - var control = controlList[i]; - var name = control.getName(); - var y = (70 * i) + 30; - var label = labels.add(new BoldText(0, y, name)); - label.x += 100; - createItem(500, y, control, 0); - createItem(700, y, control, 1); - } - - var selected = controlGrid.members[0]; - var camFollow = new FlxObject(FlxG.width / 2, selected.y); - menuCamera.follow(camFollow, LOCKON, 0.06); - controlGrid.onChange.add(function (selected) camFollow.y = selected.y); - } - - function createItem(x = 0.0, y = 0.0, control:Control, index:Int) - { - var list = PlayerSettings.player1.controls.getInputsFor(control, Keys); - var name = "---"; - if (list.length > index) - { - if (list[index] == FlxKey.ESCAPE) - return createItem(x, y, control, 2); - - name = InputFormatter.format(list[index], Keys); - } - - trace(control.getName() + " " + index + ": " + name); - return controlGrid.createItem(x, y, name, Default, onSelect.bind(name, control, index)); - } - - function onSelect(name:String, control:Control, index:Int):Void - { - controlGrid.enabled = false; - // var prompt = new Prompt(); - } + var controlGrid:TextMenuList; + var labels:FlxTypedGroup; + var menuCamera:FlxCamera; + + public function new() + { + super(); + + menuCamera = new FlxCamera(); + FlxG.cameras.add(menuCamera);// false); + if (FlxCamera.defaultCameras.indexOf(menuCamera) != -1) + { + FlxCamera.defaultCameras = FlxCamera.defaultCameras.copy(); + FlxCamera.defaultCameras.remove(menuCamera); + } + menuCamera.bgColor = 0x0; + + add(labels = new FlxTypedGroup()); + labels.camera = menuCamera; + + add(controlGrid = new TextMenuList(Columns(2))); + controlGrid.camera = menuCamera; + + // FlxG.debugger.drawDebug = true; + var controlList = Control.createAll(); + for (i in 0...controlList.length) + { + var control = controlList[i]; + var name = control.getName(); + var y = (70 * i) + 30; + var label = labels.add(new BoldText(0, y, name)); + label.x += 250; + createItem(label.x + 400, y, control, 0); + createItem(label.x + 600, y, control, 1); + } + + var selected = controlGrid.members[0]; + var camFollow = new FlxObject(FlxG.width / 2, selected.y, 70, 70); + menuCamera.follow(camFollow, null, 0.06); + var margin = 100; + menuCamera.deadzone.set(0, margin, menuCamera.width, menuCamera.height - margin * 2); + controlGrid.onChange.add(function (selected) camFollow.y = selected.y); + } + + function createItem(x = 0.0, y = 0.0, control:Control, index:Int) + { + var list = PlayerSettings.player1.controls.getInputsFor(control, Keys); + var name = "---"; + if (list.length > index) + { + if (list[index] == FlxKey.ESCAPE) + return createItem(x, y, control, 2); + + name = InputFormatter.format(list[index], Keys); + } + + trace(control.getName() + " " + index + ": " + name); + return controlGrid.createItem(x, y, name, Default, onSelect.bind(name, control, index)); + } + + function onSelect(name:String, control:Control, index:Int):Void + { + controlGrid.enabled = false; + // var prompt = new Prompt(); + } + + override function set_enabled(value:Bool) + { + controlGrid.enabled = value; + return super.set_enabled(value); + } } \ No newline at end of file diff --git a/source/ui/MenuList.hx b/source/ui/MenuList.hx index 050cbe666..f4df6066f 100644 --- a/source/ui/MenuList.hx +++ b/source/ui/MenuList.hx @@ -65,12 +65,12 @@ class MenuTypedList extends FlxTypedGroup var newIndex = switch(navControls) { - case Vertical : navList(controls.UP_P , controls.DOWN_P); - case Horizontal : navList(controls.LEFT_P, controls.RIGHT_P); - case Both : navList(controls.LEFT_P || controls.UP_P, controls.RIGHT_P || controls.DOWN_P); + case Vertical : navList(controls.UI_UP_P , controls.UI_DOWN_P); + case Horizontal : navList(controls.UI_LEFT_P, controls.UI_RIGHT_P); + case Both : navList(controls.UI_LEFT_P || controls.UI_UP_P, controls.UI_RIGHT_P || controls.UI_DOWN_P); - case Columns(num): navGrid(num, controls.LEFT_P, controls.RIGHT_P, controls.UP_P, controls.DOWN_P); - case Rows (num): navGrid(num, controls.UP_P, controls.DOWN_P, controls.LEFT_P, controls.RIGHT_P); + case Columns(num): navGrid(num, controls.UI_LEFT_P, controls.UI_RIGHT_P, controls.UI_UP_P , controls.UI_DOWN_P ); + case Rows (num): navGrid(num, controls.UI_UP_P , controls.UI_DOWN_P , controls.UI_LEFT_P, controls.UI_RIGHT_P); } if (newIndex != selectedIndex) diff --git a/source/ui/OptionsState.hx b/source/ui/OptionsState.hx new file mode 100644 index 000000000..6801b4270 --- /dev/null +++ b/source/ui/OptionsState.hx @@ -0,0 +1,258 @@ +package ui; + +import flixel.FlxSubState; +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.group.FlxGroup; +import flixel.util.FlxSignal; + +import flixel.addons.transition.FlxTransitionableState; + +// typedef OptionsState = OptionsMenu_old; + +// class OptionsState_new extends MusicBeatState +class OptionsState extends MusicBeatState +{ + var pages = new Map(); + var currentName:PageName = #if newgrounds Options #else Controls #end; + var currentPage(get, never):Page; + inline function get_currentPage() return pages[currentName]; + + override function create() + { + var menuBG = new FlxSprite().loadGraphic(Paths.image('menuDesat')); + menuBG.color = 0xFFea71fd; + menuBG.setGraphicSize(Std.int(menuBG.width * 1.1)); + menuBG.updateHitbox(); + menuBG.screenCenter(); + add(menuBG); + + var options = addPage(Options, new OptionsMenu(false)); + var controls = addPage(Controls, new ControlsMenu()); + + if (options.hasMultipleOptions()) + { + options.onExit.add(exitToMainMenu); + controls.onExit.add(switchPage.bind(Options)); + } + else + { + // No need to show Options page + controls.onExit.add(exitToMainMenu); + setPage(Controls); + } + + // disable for intro transition + currentPage.enabled = false; + super.create(); + } + + function addPage(name:PageName, page:T) + { + page.onSwitch.add(switchPage); + pages[name] = page; + add(page); + page.exists = currentName == name; + return page; + } + + function setPage(name:PageName) + { + if (pages.exists(currentName)) + currentPage.exists = false; + + currentName = name; + + if (pages.exists(currentName)) + currentPage.exists = true; + } + + override function finishTransIn() + { + super.finishTransIn(); + + currentPage.enabled = true; + } + + function switchPage(name:PageName) + { + //Todo animate? + setPage(name); + } + + function exitToMainMenu() + { + currentPage.enabled = false; + //Todo animate? + FlxG.switchState(new MainMenuState()); + } +} + +class Page extends FlxGroup +{ + public var onSwitch(default, null) = new FlxTypedSignalVoid>(); + public var onExit(default, null) = new FlxSignal(); + + public var enabled(default, set) = true; + + var controls(get, never):Controls; + inline function get_controls() return PlayerSettings.player1.controls; + + var subState:FlxSubState; + + inline function switchPage(name:PageName) + { + onSwitch.dispatch(name); + } + + inline function exit() + { + onExit.dispatch(); + } + + override function update(elapsed:Float) + { + super.update(elapsed); + + if (enabled) + updateEnabled(elapsed); + } + + function updateEnabled(elapsed:Float) + { + if (controls.BACK) + exit(); + } + + function set_enabled(value:Bool) + { + return this.enabled = value; + } + + function openPrompt(prompt:Prompt, onClose:Void->Void) + { + enabled = false; + prompt.closeCallback = function () + { + enabled = true; + if (onClose != null) + onClose(); + } + + FlxG.state.openSubState(prompt); + } + + override function destroy() + { + super.destroy(); + onSwitch.removeAll(); + } +} + +class OptionsMenu extends Page +{ + var items:TextMenuList; + + public function new (showDonate:Bool) + { + super(); + + add(items = new TextMenuList()); + createItem("controls", function() switchPage(Controls)); + #if CAN_OPEN_LINKS + if (showDonate) + { + var hasPopupBlocker = #if web true #else false #end; + createItem('donate', selectDonate, hasPopupBlocker); + } + #end + #if newgrounds + if (NGio.isLoggedIn) + createItem("logout", selectLogout); + else + createItem("login", selectLogin); + #end + createItem("exit", exit); + } + + function createItem(name:String, callback:Void->Void, fireInstantly = false) + { + var item = items.createItem(0, 100 + items.length * 100, name, Bold, callback); + item.fireInstantly = fireInstantly; + item.screenCenter(X); + return item; + } + + override function set_enabled(value:Bool) + { + items.enabled = value; + return super.set_enabled(value); + } + + /** + * True if this page has multiple options, ecluding the exit option. + * If false, there's no reason to ever show this page. + */ + public function hasMultipleOptions():Bool + { + return items.length > 2; + } + + #if CAN_OPEN_LINKS + function selectDonate() + { + #if linux + Sys.command('/usr/bin/xdg-open', ["https://ninja-muffin24.itch.io/funkin", "&"]); + #else + FlxG.openURL('https://ninja-muffin24.itch.io/funkin'); + #end + } + #end + + #if newgrounds + function selectLogin() + { + openNgPrompt(NgPrompt.showLogin()); + } + + function selectLogout() + { + openNgPrompt(NgPrompt.showLogout()); + } + + /** + * Calls openPrompt and redraws the login/logout button + * @param prompt + * @param onClose + */ + public function openNgPrompt(prompt:Prompt, ?onClose:Void->Void) + { + var onPromptClose = checkLoginStatus; + if (onClose != null) + { + onPromptClose = function () + { + checkLoginStatus(); + onClose(); + } + } + + openPrompt(prompt, onPromptClose); + } + + function checkLoginStatus() + { + var prevLoggedIn = items.has("logout"); + if (prevLoggedIn && !NGio.isLoggedIn) + items.resetItem("login", "logout", selectLogout); + else if (!prevLoggedIn && NGio.isLoggedIn) + items.resetItem("logout", "login", selectLogin); + } + #end +} + +enum PageName +{ + Options; + Controls; +} diff --git a/source/ui/TextMenuList.hx b/source/ui/TextMenuList.hx index bfc356c26..d3134a5c7 100644 --- a/source/ui/TextMenuList.hx +++ b/source/ui/TextMenuList.hx @@ -34,7 +34,7 @@ class TextTypedMenuItem extends MenuTypedItem super(x, y, label, name, callback); } - override function setItem(name:String, ?callback:() -> Void) + override function setItem(name:String, ?callback:Void -> Void) { if (label != null) { From 307150d3e23b2ac728ccc96566b8a4c365979dbd Mon Sep 17 00:00:00 2001 From: George FunBook Date: Sat, 13 Mar 2021 21:41:12 -0600 Subject: [PATCH 12/37] fix camera --- source/PlayState.hx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/PlayState.hx b/source/PlayState.hx index 35bb88f51..a8f5d0015 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1192,7 +1192,6 @@ class PlayState extends MusicBeatState { if (paused) { - camHUD.exists = false; if (FlxG.sound.music != null) { FlxG.sound.music.pause(); @@ -1218,7 +1217,6 @@ class PlayState extends MusicBeatState if (!startTimer.finished) startTimer.active = true; paused = false; - camHUD.exists = true; } super.closeSubState(); @@ -1285,7 +1283,13 @@ class PlayState extends MusicBeatState FlxG.switchState(new GitarooPause()); } else - openSubState(new PauseSubState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y)); + { + var boyfriendPos = boyfriend.getScreenPosition(); + var pauseSubState = new PauseSubState(boyfriendPos.x, boyfriendPos.y); + openSubState(pauseSubState); + pauseSubState.camera = camHUD; + boyfriendPos.put(); + } } if (FlxG.keys.justPressed.SEVEN) From 9c1866dbdb95da1c887a29eac1124f6cce53c7ef Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 16 Mar 2021 09:56:08 -0500 Subject: [PATCH 13/37] add rebind key prompt --- source/Controls.hx | 50 ++++++------ source/ui/AtlasText.hx | 1 + source/ui/ControlsMenu.hx | 165 +++++++++++++++++++++++++++++++++----- source/ui/MenuList.hx | 10 ++- source/ui/OptionsState.hx | 4 +- source/ui/Prompt.hx | 18 ++++- source/ui/TextMenuList.hx | 1 + 7 files changed, 200 insertions(+), 49 deletions(-) diff --git a/source/Controls.hx b/source/Controls.hx index c864cc918..6e49c5387 100644 --- a/source/Controls.hx +++ b/source/Controls.hx @@ -11,6 +11,30 @@ import flixel.input.gamepad.FlxGamepadButton; import flixel.input.gamepad.FlxGamepadInputID; import flixel.input.keyboard.FlxKey; +/** + * Since, in many cases multiple actions should use similar keys, we don't want the + * rebinding UI to list every action. ActionBinders are what the user percieves as + * an input so, for instance, they can't set jump-press and jump-release to different keys. + */ +enum Control +{ + NOTE_UP; + NOTE_LEFT; + NOTE_RIGHT; + NOTE_DOWN; + UI_UP; + UI_LEFT; + UI_RIGHT; + UI_DOWN; + RESET; + ACCEPT; + BACK; + PAUSE; + #if CAN_CHEAT + CHEAT; + #end +} + @:enum abstract Action(String) to String from String { @@ -53,30 +77,6 @@ enum Device Gamepad(id:Int); } -/** - * Since, in many cases multiple actions should use similar keys, we don't want the - * rebinding UI to list every action. ActionBinders are what the user percieves as - * an input so, for instance, they can't set jump-press and jump-release to different keys. - */ -enum Control -{ - UI_UP; - UI_LEFT; - UI_RIGHT; - UI_DOWN; - NOTE_UP; - NOTE_LEFT; - NOTE_RIGHT; - NOTE_DOWN; - RESET; - ACCEPT; - BACK; - PAUSE; - #if CAN_CHEAT - CHEAT; - #end -} - enum KeyboardScheme { Solo; @@ -450,7 +450,7 @@ class Controls extends FlxActionSet bindKeys(Control.NOTE_LEFT, [A, FlxKey.LEFT]); bindKeys(Control.NOTE_RIGHT, [D, FlxKey.RIGHT]); bindKeys(Control.ACCEPT, [Z, SPACE, ENTER]); - bindKeys(Control.BACK, [BACKSPACE, ESCAPE]); + bindKeys(Control.BACK, [X, BACKSPACE, ESCAPE]); bindKeys(Control.PAUSE, [P, ENTER, ESCAPE]); bindKeys(Control.RESET, [R]); case Duo(true): diff --git a/source/ui/AtlasText.hx b/source/ui/AtlasText.hx index 4c5f653b2..6e3f8fa48 100644 --- a/source/ui/AtlasText.hx +++ b/source/ui/AtlasText.hx @@ -148,6 +148,7 @@ class AtlasText extends FlxTypedSpriteGroup } charSprite.x = xPos; charSprite.y = yPos + maxHeight - charSprite.height; + charSprite.alpha = 1;//gets multiplied when added add(charSprite); xPos += charSprite.width; diff --git a/source/ui/ControlsMenu.hx b/source/ui/ControlsMenu.hx index 90d3909bc..04d7fee4f 100644 --- a/source/ui/ControlsMenu.hx +++ b/source/ui/ControlsMenu.hx @@ -1,5 +1,6 @@ package ui; +import ui.MenuList; import flixel.FlxG; import flixel.FlxCamera; import flixel.FlxObject; @@ -13,9 +14,23 @@ import ui.TextMenuList; class ControlsMenu extends ui.OptionsState.Page { - var controlGrid:TextMenuList; + static var controlList = Control.createAll(); + /* + * Defines groups of controls that cannot share inputs, like left and right. Say, if ACCEPT is Z, Back is X, + * if the player sets Back to Z it also set ACCEPT to X. This prevents the player from setting the controls in + * a way the prevents them from changing more controls or exiting the menu. + */ + static var controlGroups:Array> = + [ [ NOTE_UP, NOTE_DOWN, NOTE_LEFT, NOTE_RIGHT ] + , [ UI_UP, UI_DOWN, UI_LEFT, UI_RIGHT, ACCEPT, BACK ] + ]; + + var itemGroups:Array> = [for (i in 0...controlGroups.length) []]; + + var controlGrid:MenuTypedList; var labels:FlxTypedGroup; var menuCamera:FlxCamera; + var prompt:Prompt; public function new() { @@ -29,54 +44,135 @@ class ControlsMenu extends ui.OptionsState.Page FlxCamera.defaultCameras.remove(menuCamera); } menuCamera.bgColor = 0x0; + camera = menuCamera; add(labels = new FlxTypedGroup()); - labels.camera = menuCamera; - - add(controlGrid = new TextMenuList(Columns(2))); - controlGrid.camera = menuCamera; + add(controlGrid = new MenuTypedList(Columns(2))); // FlxG.debugger.drawDebug = true; - var controlList = Control.createAll(); + var y = 30; + var spacer = 70; + var currentHeader:String = null; + // list order is determined by enum order for (i in 0...controlList.length) { var control = controlList[i]; var name = control.getName(); - var y = (70 * i) + 30; - var label = labels.add(new BoldText(0, y, name)); - label.x += 250; + if (currentHeader != "UI_" && name.indexOf("UI_") == 0) + { + currentHeader = "UI_"; + labels.add(new BoldText(0, y, "UI")).screenCenter(X); + y += spacer; + } + else if (currentHeader != "NOTE_" && name.indexOf("NOTE_") == 0) + { + currentHeader = "NOTE_"; + labels.add(new BoldText(0, y, "NOTES")).screenCenter(X); + y += spacer; + } + + if (currentHeader != null && name.indexOf(currentHeader) == 0) + name = name.substr(currentHeader.length); + + var label = labels.add(new BoldText(250, y, name)); createItem(label.x + 400, y, control, 0); createItem(label.x + 600, y, control, 1); + y += spacer; } + trace(itemGroups.map((group)->group.map((item)->item.label.text))); + var selected = controlGrid.members[0]; var camFollow = new FlxObject(FlxG.width / 2, selected.y, 70, 70); menuCamera.follow(camFollow, null, 0.06); var margin = 100; menuCamera.deadzone.set(0, margin, menuCamera.width, menuCamera.height - margin * 2); controlGrid.onChange.add(function (selected) camFollow.y = selected.y); + + prompt = new Prompt("Press any key to rebind\n\n\n\n Escape to cancel", None); + prompt.create(); + prompt.createBgFromMargin(); + prompt.back.scrollFactor.set(0, 0); + prompt.exists = false; + add(prompt); } function createItem(x = 0.0, y = 0.0, control:Control, index:Int) { - var list = PlayerSettings.player1.controls.getInputsFor(control, Keys); - var name = "---"; - if (list.length > index) + var item = new InputItem(x, y, control, index, onSelect); + for (i in 0...controlGroups.length) { - if (list[index] == FlxKey.ESCAPE) - return createItem(x, y, control, 2); - - name = InputFormatter.format(list[index], Keys); + if (controlGroups[i].contains(control)) + itemGroups[i].push(item); } - trace(control.getName() + " " + index + ": " + name); - return controlGrid.createItem(x, y, name, Default, onSelect.bind(name, control, index)); + return controlGrid.addItem(item.name, item); } - function onSelect(name:String, control:Control, index:Int):Void + function onSelect():Void { controlGrid.enabled = false; - // var prompt = new Prompt(); + canExit = false; + prompt.exists = true; + } + + override function update(elapsed:Float) + { + super.update(elapsed); + + if (prompt.exists) + { + var key = FlxG.keys.firstJustPressed(); + if (key != NONE) + { + if (key != ESCAPE) + onKeySelect(key); + closePrompt(); + } + } + } + + function onKeySelect(key:Int) + { + var item = controlGrid.selectedItem; + for (group in itemGroups) + { + if (group.contains(item)) + { + for (otherItem in group) + { + // Check if items in the same group have the new input + if (otherItem != item && otherItem.input == key) + { + // replace that input with this items old input. + PlayerSettings.player1.controls.replaceBinding(otherItem.control, Keys, item.input, otherItem.input); + // Don't use resetItem() since items share names/labels + otherItem.input = item.input; + otherItem.label.text = item.label.text; + } + } + } + } + + PlayerSettings.player1.controls.replaceBinding(item.control, Keys, key, item.input); + // Don't use resetItem() since items share names/labels + item.input = key; + item.label.text = item.getLabel(key); + } + + function closePrompt() + { + controlGrid.enabled = true; + canExit = true; + prompt.exists = false; + } + + override function destroy() + { + super.destroy(); + + if (FlxG.cameras.list.contains(menuCamera)) + FlxG.cameras.remove(menuCamera); } override function set_enabled(value:Bool) @@ -84,4 +180,33 @@ class ControlsMenu extends ui.OptionsState.Page controlGrid.enabled = value; return super.set_enabled(value); } +} + +class InputItem extends TextMenuItem +{ + public var control:Control; + public var input:Int = -1; + + public function new (x = 0.0, y = 0.0, control, index, ?callback) + { + this.control = control; + + var list = PlayerSettings.player1.controls.getInputsFor(control, Keys); + if (list.length > index) + { + if (list[index] != FlxKey.ESCAPE) + input = list[index]; + else if (list.length > 2) + // Escape isn't mappable, show a third option, instead. + input = list[2]; + } + + ; + super(x, y, getLabel(input), Default, callback); + } + + public function getLabel(input:Int) + { + return input == -1 ? "---" : InputFormatter.format(input, Keys); + } } \ No newline at end of file diff --git a/source/ui/MenuList.hx b/source/ui/MenuList.hx index f4df6066f..2dfb84144 100644 --- a/source/ui/MenuList.hx +++ b/source/ui/MenuList.hx @@ -10,6 +10,7 @@ import flixel.util.FlxSignal; class MenuTypedList extends FlxTypedGroup { public var selectedIndex(default, null) = 0; + public var selectedItem(get, never):T; /** Called when a new item is highlighted */ public var onChange(default, null) = new FlxTypedSignalVoid>(); /** Called when an item is accepted */ @@ -189,6 +190,11 @@ class MenuTypedList extends FlxTypedGroup onChange.removeAll(); onAcceptPress.removeAll(); } + + inline function get_selectedItem():T + { + return members[selectedIndex]; + } } class MenuItem extends FlxSprite @@ -221,8 +227,8 @@ class MenuItem extends FlxSprite /** * Calls setData and resets/redraws the state of the item - * @param name - * @param callback + * @param name the label. + * @param callback Unchanged if null. */ public function setItem(name:String, ?callback:Void->Void) { diff --git a/source/ui/OptionsState.hx b/source/ui/OptionsState.hx index 6801b4270..0e4fae95c 100644 --- a/source/ui/OptionsState.hx +++ b/source/ui/OptionsState.hx @@ -25,6 +25,7 @@ class OptionsState extends MusicBeatState menuBG.setGraphicSize(Std.int(menuBG.width * 1.1)); menuBG.updateHitbox(); menuBG.screenCenter(); + menuBG.scrollFactor.set(0, 0); add(menuBG); var options = addPage(Options, new OptionsMenu(false)); @@ -94,6 +95,7 @@ class Page extends FlxGroup public var onExit(default, null) = new FlxSignal(); public var enabled(default, set) = true; + public var canExit = true; var controls(get, never):Controls; inline function get_controls() return PlayerSettings.player1.controls; @@ -120,7 +122,7 @@ class Page extends FlxGroup function updateEnabled(elapsed:Float) { - if (controls.BACK) + if (canExit && controls.BACK) exit(); } diff --git a/source/ui/Prompt.hx b/source/ui/Prompt.hx index ccac5d576..0ef80007d 100644 --- a/source/ui/Prompt.hx +++ b/source/ui/Prompt.hx @@ -17,13 +17,14 @@ class Prompt extends flixel.FlxSubState public var onNo:Void->Void; public var buttons:TextMenuList; public var field:AtlasText; + public var back:FlxSprite; var style:ButtonStyle; public function new (text:String, style:ButtonStyle = Ok) { this.style = style; - super(0xA0000000); + super(0x80000000); buttons = new TextMenuList(Horizontal); @@ -43,6 +44,21 @@ class Prompt extends flixel.FlxSubState add(buttons); } + public function createBg(width:Int, height:Int, color = 0xFF808080) + { + back = new FlxSprite(); + back.makeGraphic(width, height, color, false, "prompt-bg"); + back.screenCenter(XY); + add(back); + members.unshift(members.pop());// bring to front + } + + + public function createBgFromMargin(margin = MARGIN, color = 0xFF808080) + { + createBg(Std.int(FlxG.width - margin * 2), Std.int(FlxG.height - margin * 2), color); + } + public function setButtons(style:ButtonStyle) { if (this.style != style) diff --git a/source/ui/TextMenuList.hx b/source/ui/TextMenuList.hx index d3134a5c7..b7a90afa5 100644 --- a/source/ui/TextMenuList.hx +++ b/source/ui/TextMenuList.hx @@ -39,6 +39,7 @@ class TextTypedMenuItem extends MenuTypedItem if (label != null) { label.text = name; + label.alpha = alpha; width = label.width; height = label.height; } From a75e6ecb387c13a7a6cfa88f1f2a3d7b3936cad1 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 16 Mar 2021 10:20:40 -0500 Subject: [PATCH 14/37] add input groups --- source/ui/ControlsMenu.hx | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/source/ui/ControlsMenu.hx b/source/ui/ControlsMenu.hx index 04d7fee4f..034c18d35 100644 --- a/source/ui/ControlsMenu.hx +++ b/source/ui/ControlsMenu.hx @@ -28,7 +28,6 @@ class ControlsMenu extends ui.OptionsState.Page var itemGroups:Array> = [for (i in 0...controlGroups.length) []]; var controlGrid:MenuTypedList; - var labels:FlxTypedGroup; var menuCamera:FlxCamera; var prompt:Prompt; @@ -46,9 +45,14 @@ class ControlsMenu extends ui.OptionsState.Page menuCamera.bgColor = 0x0; camera = menuCamera; - add(labels = new FlxTypedGroup()); + var labels = new FlxTypedGroup(); + var headers = new FlxTypedGroup(); add(controlGrid = new MenuTypedList(Columns(2))); + add(labels); + add(headers); + add(controlGrid); + // FlxG.debugger.drawDebug = true; var y = 30; var spacer = 70; @@ -61,13 +65,13 @@ class ControlsMenu extends ui.OptionsState.Page if (currentHeader != "UI_" && name.indexOf("UI_") == 0) { currentHeader = "UI_"; - labels.add(new BoldText(0, y, "UI")).screenCenter(X); + headers.add(new BoldText(0, y, "UI")).screenCenter(X); y += spacer; } else if (currentHeader != "NOTE_" && name.indexOf("NOTE_") == 0) { currentHeader = "NOTE_"; - labels.add(new BoldText(0, y, "NOTES")).screenCenter(X); + headers.add(new BoldText(0, y, "NOTES")).screenCenter(X); y += spacer; } @@ -75,21 +79,27 @@ class ControlsMenu extends ui.OptionsState.Page name = name.substr(currentHeader.length); var label = labels.add(new BoldText(250, y, name)); + label.alpha = 0.6; createItem(label.x + 400, y, control, 0); createItem(label.x + 600, y, control, 1); y += spacer; } - trace(itemGroups.map((group)->group.map((item)->item.label.text))); - + labels.members[0].alpha = 1.0; var selected = controlGrid.members[0]; var camFollow = new FlxObject(FlxG.width / 2, selected.y, 70, 70); menuCamera.follow(camFollow, null, 0.06); var margin = 100; menuCamera.deadzone.set(0, margin, menuCamera.width, menuCamera.height - margin * 2); - controlGrid.onChange.add(function (selected) camFollow.y = selected.y); + controlGrid.onChange.add(function (selected) + { + camFollow.y = selected.y; + + labels.forEach((label)->label.alpha = 0.6); + labels.members[Std.int(controlGrid.selectedIndex / 2)].alpha = 1.0; + }); - prompt = new Prompt("Press any key to rebind\n\n\n\n Escape to cancel", None); + prompt = new Prompt("\nPress any key to rebind\n\n\n\n Escape to cancel", None); prompt.create(); prompt.createBgFromMargin(); prompt.back.scrollFactor.set(0, 0); From 0ed0093fdded19b1661fb0c6a58f7462b11ea3ea Mon Sep 17 00:00:00 2001 From: George FunBook Date: Mon, 22 Mar 2021 07:48:52 -0500 Subject: [PATCH 15/37] more work on controls menu --- source/InputFormatter.hx | 91 +++++++++-------- source/ui/AtlasMenuList.hx | 4 +- source/ui/AtlasText.hx | 13 ++- source/ui/ControlsMenu.hx | 197 ++++++++++++++++++++++++++++++------- source/ui/MenuList.hx | 40 ++++++-- source/ui/TextMenuList.hx | 4 +- 6 files changed, 254 insertions(+), 95 deletions(-) diff --git a/source/InputFormatter.hx b/source/InputFormatter.hx index 2ace8b0ac..413910543 100644 --- a/source/InputFormatter.hx +++ b/source/InputFormatter.hx @@ -34,37 +34,37 @@ class InputFormatter case SEVEN : "7"; case EIGHT : "8"; case NINE : "9"; - case PAGEUP : "PgU"; - case PAGEDOWN : "PgD"; - case HOME : "Hm"; - case END : "End"; - case INSERT : "Ins"; - case ESCAPE : "Esc"; - case MINUS : "-"; - case PLUS : "+"; - case DELETE : "Del"; - case BACKSPACE : "Bck"; + case PAGEUP : "PgUp"; + case PAGEDOWN : "PgDown"; + // case HOME : "Hm"; + // case END : "End"; + // case INSERT : "Ins"; + // case ESCAPE : "Esc"; + // case MINUS : "-"; + // case PLUS : "+"; + // case DELETE : "Del"; + case BACKSPACE : "BckSpc"; case LBRACKET : "["; case RBRACKET : "]"; case BACKSLASH : "\\"; - case CAPSLOCK : "Cap"; + case CAPSLOCK : "Caps"; case SEMICOLON : ";"; case QUOTE : "'"; - case ENTER : "Ent"; - case SHIFT : "Shf"; + // case ENTER : "Ent"; + // case SHIFT : "Shf"; case COMMA : ","; case PERIOD : "."; case SLASH : "/"; case GRAVEACCENT : "`"; - case CONTROL : "Ctl"; + case CONTROL : "Ctrl"; case ALT : "Alt"; - case SPACE : "Spc"; - case UP : "Up"; - case DOWN : "Dn"; - case LEFT : "Lf"; - case RIGHT : "Rt"; - case TAB : "Tab"; - case PRINTSCREEN : "Prt"; + // case SPACE : "Spc"; + // case UP : "Up"; + // case DOWN : "Dn"; + // case LEFT : "Lf"; + // case RIGHT : "Rt"; + // case TAB : "Tab"; + case PRINTSCREEN : "PrtScrn"; case NUMPADZERO : "#0"; case NUMPADONE : "#1"; case NUMPADTWO : "#2"; @@ -79,7 +79,7 @@ class InputFormatter case NUMPADPLUS : "#+"; case NUMPADPERIOD : "#."; case NUMPADMULTIPLY: "#*"; - default: titleCaseTrim(FlxKey.toStringMap[id]); + default: titleCase(FlxKey.toStringMap[id]); } } @@ -98,39 +98,36 @@ class InputFormatter return switch (name == null ? "" : name.toLowerCase()) { case "": "[?]"; - case "square" : "[]"; - case "circle" : "()"; - case "triangle": "/\\"; - case "plus" : "+"; - case "minus" : "-"; - case "home" : "Hm"; - case "guide" : "Gd"; - case "back" : "Bk"; - case "select" : "Bk"; - case "start" : "St"; - case "left" : "Lf"; - case "right" : "Rt"; - case "down" : "Dn"; - case "up" : "Up"; + // case "square" : "[]"; + // case "circle" : "()"; + // case "triangle": "/\\"; + // case "plus" : "+"; + // case "minus" : "-"; + // case "home" : "Hm"; + // case "guide" : "Gd"; + // case "back" : "Bk"; + // case "select" : "Bk"; + // case "start" : "St"; + // case "left" : "Lf"; + // case "right" : "Rt"; + // case "down" : "Dn"; + // case "up" : "Up"; case dir if (dirReg.match(dir)): - dirReg.matched(1).toUpperCase() + "-" - + switch (dirReg.matched(2)) - { - case "left" : "L"; - case "right": "R"; - case "down" : "D"; - case "up" : "U"; - default: throw "Unreachable exaustiveness case"; - }; - case label: titleCaseTrim(label); + dirReg.matched(1).toUpperCase() + " " + titleCase(dirReg.matched(2)); + case label: titleCase(label); } } - inline static function titleCaseTrim(str:String, length = 3) + inline static function titleCaseTrim(str:String, length = 8) { return str.charAt(0).toUpperCase() + str.substr(1, length - 1).toLowerCase(); } + inline static function titleCase(str:String) + { + return str.charAt(0).toUpperCase() + str.substr(1).toLowerCase(); + } + inline static public function parsePadName(name:String):ControllerName { return ControllerName.parseName(name); diff --git a/source/ui/AtlasMenuList.hx b/source/ui/AtlasMenuList.hx index e9572d07c..68232da5c 100644 --- a/source/ui/AtlasMenuList.hx +++ b/source/ui/AtlasMenuList.hx @@ -10,9 +10,9 @@ class AtlasMenuList extends MenuTypedList { public var atlas:FlxAtlasFrames; - public function new (atlas, navControls:NavControls = Vertical) + public function new (atlas, navControls:NavControls = Vertical, ?wrapMode) { - super(navControls); + super(navControls, wrapMode); if (Std.is(atlas, String)) this.atlas = Paths.getSparrowAtlas(cast atlas); diff --git a/source/ui/AtlasText.hx b/source/ui/AtlasText.hx index 6e3f8fa48..3ba3a746a 100644 --- a/source/ui/AtlasText.hx +++ b/source/ui/AtlasText.hx @@ -3,6 +3,7 @@ package ui; import flixel.FlxSprite; import flixel.group.FlxSpriteGroup; import flixel.graphics.frames.FlxAtlasFrames; +import flixel.util.FlxStringUtil; @:forward abstract BoldText(AtlasText) from AtlasText to AtlasText @@ -68,7 +69,7 @@ class AtlasText extends FlxTypedSpriteGroup if (value == "") return this.text; - appendTextCased(this.text); + appendTextCased(caseValue); return this.text; } @@ -157,6 +158,16 @@ class AtlasText extends FlxTypedSpriteGroup } } } + + override function toString() + { + return "InputItem, " + FlxStringUtil.getDebugString( + [ LabelValuePair.weak("x", x) + , LabelValuePair.weak("y", y) + , LabelValuePair.weak("text", text) + ] + ); + } } class AtlasChar extends FlxSprite diff --git a/source/ui/ControlsMenu.hx b/source/ui/ControlsMenu.hx index 034c18d35..cb471c2cf 100644 --- a/source/ui/ControlsMenu.hx +++ b/source/ui/ControlsMenu.hx @@ -1,6 +1,7 @@ package ui; -import ui.MenuList; +import flixel.input.actions.FlxActionInput; +import flixel.input.gamepad.FlxGamepadInputID; import flixel.FlxG; import flixel.FlxCamera; import flixel.FlxObject; @@ -10,10 +11,12 @@ import flixel.input.keyboard.FlxKey; import Controls; import ui.AtlasText; +import ui.MenuList; import ui.TextMenuList; class ControlsMenu extends ui.OptionsState.Page { + inline static public var COLUMNS = 2; static var controlList = Control.createAll(); /* * Defines groups of controls that cannot share inputs, like left and right. Say, if ACCEPT is Z, Back is X, @@ -28,8 +31,14 @@ class ControlsMenu extends ui.OptionsState.Page var itemGroups:Array> = [for (i in 0...controlGroups.length) []]; var controlGrid:MenuTypedList; + var deviceList:TextMenuList; var menuCamera:FlxCamera; var prompt:Prompt; + var camFollow:FlxObject; + var labels:FlxTypedGroup; + + var currentDevice:Device = Keys; + var deviceListSelected = false; public function new() { @@ -45,16 +54,36 @@ class ControlsMenu extends ui.OptionsState.Page menuCamera.bgColor = 0x0; camera = menuCamera; - var labels = new FlxTypedGroup(); + labels = new FlxTypedGroup(); var headers = new FlxTypedGroup(); - add(controlGrid = new MenuTypedList(Columns(2))); + controlGrid = new MenuTypedList(Columns(COLUMNS), Vertical); add(labels); add(headers); add(controlGrid); + if (FlxG.gamepads.numActiveGamepads > 0) + { + var devicesBg = new FlxSprite(); + devicesBg.makeGraphic(FlxG.width, 100, 0xFF808080); + add(devicesBg); + deviceList = new TextMenuList(Horizontal, None); + add(deviceList); + deviceListSelected = true; + + var item; + + item = deviceList.createItem("Keyboard", Bold, selectDevice.bind(Keys)); + item.x = FlxG.width / 2 - item.width - 30; + item.y = (devicesBg.height - item.height) / 2; + + item = deviceList.createItem("Gamepad", Bold, selectDevice.bind(Gamepad(FlxG.gamepads.firstActive.id))); + item.x = FlxG.width / 2 + 30; + item.y = (devicesBg.height - item.height) / 2; + } + // FlxG.debugger.drawDebug = true; - var y = 30; + var y = deviceList == null ? 30 : 120; var spacer = 70; var currentHeader:String = null; // list order is determined by enum order @@ -78,25 +107,33 @@ class ControlsMenu extends ui.OptionsState.Page if (currentHeader != null && name.indexOf(currentHeader) == 0) name = name.substr(currentHeader.length); - var label = labels.add(new BoldText(250, y, name)); + var label = labels.add(new BoldText(150, y, name)); label.alpha = 0.6; - createItem(label.x + 400, y, control, 0); - createItem(label.x + 600, y, control, 1); + for (i in 0...COLUMNS) + createItem(label.x + 400 + i * 300, y, control, i); + y += spacer; } - labels.members[0].alpha = 1.0; - var selected = controlGrid.members[0]; - var camFollow = new FlxObject(FlxG.width / 2, selected.y, 70, 70); + camFollow = new FlxObject(FlxG.width / 2, 0, 70, 70); + if (deviceList != null) + { + camFollow.y = deviceList.selectedItem.y; + controlGrid.selectedItem.idle(); + } + else + camFollow.y = controlGrid.selectedItem.y; + menuCamera.follow(camFollow, null, 0.06); var margin = 100; menuCamera.deadzone.set(0, margin, menuCamera.width, menuCamera.height - margin * 2); + menuCamera.minScrollY = 0; controlGrid.onChange.add(function (selected) { camFollow.y = selected.y; labels.forEach((label)->label.alpha = 0.6); - labels.members[Std.int(controlGrid.selectedIndex / 2)].alpha = 1.0; + labels.members[Std.int(controlGrid.selectedIndex / COLUMNS)].alpha = 1.0; }); prompt = new Prompt("\nPress any key to rebind\n\n\n\n Escape to cancel", None); @@ -109,7 +146,7 @@ class ControlsMenu extends ui.OptionsState.Page function createItem(x = 0.0, y = 0.0, control:Control, index:Int) { - var item = new InputItem(x, y, control, index, onSelect); + var item = new InputItem(x, y, currentDevice, control, index, onSelect); for (i in 0...controlGroups.length) { if (controlGroups[i].contains(control)) @@ -126,36 +163,95 @@ class ControlsMenu extends ui.OptionsState.Page prompt.exists = true; } + function goToDeviceList() + { + controlGrid.selectedItem.idle(); + labels.members[Std.int(controlGrid.selectedIndex / COLUMNS)].alpha = 0.6; + controlGrid.enabled = false; + deviceList.enabled = true; + canExit = true; + camFollow.y = deviceList.selectedItem.y; + deviceListSelected = true; + } + + function selectDevice(device:Device) + { + currentDevice = device; + + for (item in controlGrid.members) + item.updateDevice(currentDevice); + + var inputName = device == Keys ? "key" : "button"; + var cancel = device == Keys ? "Escape" : "Back"; + prompt.setText('\nPress any $inputName to rebind\n\n\n\n $cancel to cancel'); + + controlGrid.selectedItem.select(); + labels.members[Std.int(controlGrid.selectedIndex / COLUMNS)].alpha = 1.0; + controlGrid.enabled = true; + deviceList.enabled = false; + deviceListSelected = false; + canExit = false; + } + override function update(elapsed:Float) { super.update(elapsed); + var controls = PlayerSettings.player1.controls; + if (enabled && deviceList != null && deviceListSelected == false && controls.BACK) + goToDeviceList(); + if (prompt.exists) { - var key = FlxG.keys.firstJustPressed(); - if (key != NONE) + switch (currentDevice) { - if (key != ESCAPE) - onKeySelect(key); - closePrompt(); + case Keys: + { + var key = FlxG.keys.firstJustPressed(); + if (key != NONE) + { + if (key != ESCAPE) + onInputSelect(key); + closePrompt(); + } + } + case Gamepad(id): + { + var button = FlxG.gamepads.getByID(id).firstJustPressedID(); + if (button != NONE) + { + if (button != BACK) + onInputSelect(button); + closePrompt(); + } + } } } } - function onKeySelect(key:Int) + function onInputSelect(input:Int) { var item = controlGrid.selectedItem; + + // check if that key is already set for this + var column0 = Math.floor(controlGrid.selectedIndex / 2) * 2; + for (i in 0...COLUMNS) + { + if (controlGrid.members[column0 + i].input == input) + return; + } + + // Check if items in the same group already have the new input for (group in itemGroups) { if (group.contains(item)) { for (otherItem in group) { - // Check if items in the same group have the new input - if (otherItem != item && otherItem.input == key) + if (otherItem != item && otherItem.input == input) { // replace that input with this items old input. - PlayerSettings.player1.controls.replaceBinding(otherItem.control, Keys, item.input, otherItem.input); + PlayerSettings.player1.controls.replaceBinding(otherItem.control, currentDevice, item.input, otherItem.input); // Don't use resetItem() since items share names/labels otherItem.input = item.input; otherItem.label.text = item.label.text; @@ -164,10 +260,10 @@ class ControlsMenu extends ui.OptionsState.Page } } - PlayerSettings.player1.controls.replaceBinding(item.control, Keys, key, item.input); + PlayerSettings.player1.controls.replaceBinding(item.control, currentDevice, input, item.input); // Don't use resetItem() since items share names/labels - item.input = key; - item.label.text = item.getLabel(key); + item.input = input; + item.label.text = item.getLabel(input); } function closePrompt() @@ -181,42 +277,75 @@ class ControlsMenu extends ui.OptionsState.Page { super.destroy(); + itemGroups = null; + if (FlxG.cameras.list.contains(menuCamera)) FlxG.cameras.remove(menuCamera); } override function set_enabled(value:Bool) { - controlGrid.enabled = value; + if (value == false) + { + controlGrid.enabled = false; + if (deviceList != null) + deviceList.enabled = false; + } + else + { + controlGrid.enabled = !deviceListSelected; + if (deviceList != null) + deviceList.enabled = deviceListSelected; + } return super.set_enabled(value); } } class InputItem extends TextMenuItem { + public var device(default, null):Device = Keys; public var control:Control; public var input:Int = -1; + public var index:Int = -1; - public function new (x = 0.0, y = 0.0, control, index, ?callback) + public function new (x = 0.0, y = 0.0, device, control, index, ?callback) { + this.device = device; this.control = control; + this.index = index; + this.input = getInput(); - var list = PlayerSettings.player1.controls.getInputsFor(control, Keys); + super(x, y, getLabel(input), Default, callback); + } + + public function updateDevice(device:Device) + { + if (this.device != device) + { + this.device = device; + input = getInput(); + label.text = getLabel(input); + } + } + + function getInput() + { + var list = PlayerSettings.player1.controls.getInputsFor(control, device); if (list.length > index) { - if (list[index] != FlxKey.ESCAPE) - input = list[index]; - else if (list.length > 2) + if (list[index] != FlxKey.ESCAPE || list[index] != FlxGamepadInputID.BACK) + return list[index]; + + if (list.length > ControlsMenu.COLUMNS) // Escape isn't mappable, show a third option, instead. - input = list[2]; + return list[ControlsMenu.COLUMNS]; } - ; - super(x, y, getLabel(input), Default, callback); + return -1; } public function getLabel(input:Int) { - return input == -1 ? "---" : InputFormatter.format(input, Keys); + return input == -1 ? "---" : InputFormatter.format(input, device); } } \ No newline at end of file diff --git a/source/ui/MenuList.hx b/source/ui/MenuList.hx index 2dfb84144..6d20d7d82 100644 --- a/source/ui/MenuList.hx +++ b/source/ui/MenuList.hx @@ -19,14 +19,26 @@ class MenuTypedList extends FlxTypedGroup public var navControls:NavControls; /** Set to false to disable nav control */ public var enabled:Bool = true; + /** */ + public var wrapMode:WrapMode = Both; var byName = new Map(); /** Set to true, internally to disable controls, without affecting vars like `enabled` */ var busy:Bool = false; - public function new (navControls:NavControls = Vertical) + public function new (navControls:NavControls = Vertical, ?wrapMode:WrapMode) { this.navControls = navControls; + + if (wrapMode != null) + this.wrapMode = wrapMode; + else + this.wrapMode = switch (navControls) + { + case Horizontal: Horizontal; + case Vertical: Vertical; + default: Both; + } super(); } @@ -64,14 +76,16 @@ class MenuTypedList extends FlxTypedGroup { var controls = PlayerSettings.player1.controls; + var wrapX = wrapMode.match(Horizontal | Both); + var wrapY = wrapMode.match(Vertical | Both); var newIndex = switch(navControls) { - case Vertical : navList(controls.UI_UP_P , controls.UI_DOWN_P); - case Horizontal : navList(controls.UI_LEFT_P, controls.UI_RIGHT_P); - case Both : navList(controls.UI_LEFT_P || controls.UI_UP_P, controls.UI_RIGHT_P || controls.UI_DOWN_P); + case Vertical : navList(controls.UI_UP_P , controls.UI_DOWN_P, wrapY); + case Horizontal : navList(controls.UI_LEFT_P, controls.UI_RIGHT_P, wrapX); + case Both : navList(controls.UI_LEFT_P || controls.UI_UP_P, controls.UI_RIGHT_P || controls.UI_DOWN_P, !wrapMode.match(None)); - case Columns(num): navGrid(num, controls.UI_LEFT_P, controls.UI_RIGHT_P, controls.UI_UP_P , controls.UI_DOWN_P ); - case Rows (num): navGrid(num, controls.UI_UP_P , controls.UI_DOWN_P , controls.UI_LEFT_P, controls.UI_RIGHT_P); + case Columns(num): navGrid(num, controls.UI_LEFT_P, controls.UI_RIGHT_P, wrapX, controls.UI_UP_P , controls.UI_DOWN_P , wrapY); + case Rows (num): navGrid(num, controls.UI_UP_P , controls.UI_DOWN_P , wrapY, controls.UI_LEFT_P, controls.UI_RIGHT_P, wrapX); } if (newIndex != selectedIndex) @@ -114,7 +128,7 @@ class MenuTypedList extends FlxTypedGroup * @param next * @param allowWrap */ - inline function navList(prev:Bool, next:Bool, allowWrap:Bool = true) + inline function navList(prev:Bool, next:Bool, allowWrap:Bool) { return navAxis(selectedIndex, length, prev, next, allowWrap); } @@ -128,7 +142,7 @@ class MenuTypedList extends FlxTypedGroup * @param next Whether the 'next' key is pressed along the variable-lengthed axis. eg: "down" in Column mode * @param allowWrap unused */ - function navGrid(latSize:Int, latPrev:Bool, latNext:Bool, prev:Bool, next:Bool, allowWrap:Bool = true):Int + function navGrid(latSize:Int, latPrev:Bool, latNext:Bool, latAllowWrap:Bool, prev:Bool, next:Bool, allowWrap:Bool):Int { // The grid lenth along the variable-length axis var size = Math.ceil(length / latSize); @@ -137,7 +151,7 @@ class MenuTypedList extends FlxTypedGroup // The selected position along the fixed axis var latIndex = selectedIndex % latSize; - latIndex = navAxis(latIndex, latSize, latPrev, latNext, allowWrap); + latIndex = navAxis(latIndex, latSize, latPrev, latNext, latAllowWrap); index = navAxis(index, size, prev, next, allowWrap); return Std.int(Math.min(length - 1, index * latSize + latIndex)); @@ -341,4 +355,12 @@ enum NavControls Both; Columns(num:Int); Rows(num:Int); +} + +enum WrapMode +{ + Horizontal; + Vertical; + Both; + None; } \ No newline at end of file diff --git a/source/ui/TextMenuList.hx b/source/ui/TextMenuList.hx index b7a90afa5..d1c617b17 100644 --- a/source/ui/TextMenuList.hx +++ b/source/ui/TextMenuList.hx @@ -5,9 +5,9 @@ import ui.MenuList; class TextMenuList extends MenuTypedList { - public function new (navControls:NavControls = Vertical) + public function new (navControls:NavControls = Vertical, ?wrapMode) { - super(navControls); + super(navControls, wrapMode); } public function createItem(x = 0.0, y = 0.0, name:String, font:AtlasFont = Bold, callback, fireInstantly = false) From 34cb7f9982ab6b26127dd439a8167ee2ecabccad Mon Sep 17 00:00:00 2001 From: George FunBook Date: Mon, 22 Mar 2021 08:40:32 -0500 Subject: [PATCH 16/37] more ui work --- source/MainMenuState.hx | 16 +++++++++------- source/PlayerSettings.hx | 15 +++------------ source/ui/ControlsMenu.hx | 5 +++-- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index 0513d82a7..f2bc0f426 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -48,10 +48,10 @@ class MainMenuState extends MusicBeatState persistentUpdate = persistentDraw = true; - var bg:FlxSprite = new FlxSprite(-80).loadGraphic(Paths.image('menuBG')); + var bg:FlxSprite = new FlxSprite(Paths.image('menuBG')); bg.scrollFactor.x = 0; bg.scrollFactor.y = 0.18; - bg.setGraphicSize(Std.int(bg.width * 1.1)); + bg.setGraphicSize(Std.int(bg.width * 1.3)); bg.updateHitbox(); bg.screenCenter(); bg.antialiasing = true; @@ -60,12 +60,13 @@ class MainMenuState extends MusicBeatState camFollow = new FlxObject(0, 0, 1, 1); add(camFollow); - magenta = new FlxSprite(-80).loadGraphic(Paths.image('menuDesat')); - magenta.scrollFactor.x = 0; - magenta.scrollFactor.y = 0.18; - magenta.setGraphicSize(Std.int(magenta.width * 1.1)); + magenta = new FlxSprite(Paths.image('menuDesat')); + magenta.scrollFactor.x = bg.scrollFactor.x; + magenta.scrollFactor.y = bg.scrollFactor.y; + magenta.setGraphicSize(Std.int(bg.width)); magenta.updateHitbox(); - magenta.screenCenter(); + magenta.x = bg.x; + magenta.y = bg.y; magenta.visible = false; magenta.antialiasing = true; magenta.color = 0xFFfd719b; @@ -109,6 +110,7 @@ class MainMenuState extends MusicBeatState } FlxG.camera.follow(camFollow, null, 0.06); + FlxG.camera.setScrollBounds(bg.x, bg.x + bg.width, bg.y, bg.y + bg.height * 1.2); var versionShit:FlxText = new FlxText(5, FlxG.height - 18, 0, "v" + Application.current.meta.get('version'), 12); versionShit.scrollFactor.set(); diff --git a/source/PlayerSettings.hx b/source/PlayerSettings.hx index b275b9b51..df7586c44 100644 --- a/source/PlayerSettings.hx +++ b/source/PlayerSettings.hx @@ -14,21 +14,12 @@ class PlayerSettings static public var player1(default, null):PlayerSettings; static public var player2(default, null):PlayerSettings; - #if (haxe >= "4.0.0") - static public final onAvatarAdd = new FlxTypedSignalVoid>(); - static public final onAvatarRemove = new FlxTypedSignalVoid>(); - #else - static public var onAvatarAdd = new FlxTypedSignalVoid>(); - static public var onAvatarRemove = new FlxTypedSignalVoid>(); - #end + static public var onAvatarAdd(default, null) = new FlxTypedSignalVoid>(); + static public var onAvatarRemove(default, null) = new FlxTypedSignalVoid>(); public var id(default, null):Int; - #if (haxe >= "4.0.0") - public final controls:Controls; - #else - public var controls:Controls; - #end + public var controls(default, null):Controls; // public var avatar:Player; // public var camera(get, never):PlayCamera; diff --git a/source/ui/ControlsMenu.hx b/source/ui/ControlsMenu.hx index cb471c2cf..ca923af29 100644 --- a/source/ui/ControlsMenu.hx +++ b/source/ui/ControlsMenu.hx @@ -65,7 +65,7 @@ class ControlsMenu extends ui.OptionsState.Page if (FlxG.gamepads.numActiveGamepads > 0) { var devicesBg = new FlxSprite(); - devicesBg.makeGraphic(FlxG.width, 100, 0xFF808080); + devicesBg.makeGraphic(FlxG.width, 100, 0xFFfafd6d); add(devicesBg); deviceList = new TextMenuList(Horizontal, None); add(deviceList); @@ -120,6 +120,7 @@ class ControlsMenu extends ui.OptionsState.Page { camFollow.y = deviceList.selectedItem.y; controlGrid.selectedItem.idle(); + controlGrid.enabled = false; } else camFollow.y = controlGrid.selectedItem.y; @@ -138,7 +139,7 @@ class ControlsMenu extends ui.OptionsState.Page prompt = new Prompt("\nPress any key to rebind\n\n\n\n Escape to cancel", None); prompt.create(); - prompt.createBgFromMargin(); + prompt.createBgFromMargin(100, 0xFFfafd6d); prompt.back.scrollFactor.set(0, 0); prompt.exists = false; add(prompt); From 9c6b3bf51d3c51219c79ab37daba2d8305ed607a Mon Sep 17 00:00:00 2001 From: George FunBook Date: Mon, 22 Mar 2021 21:39:35 -0500 Subject: [PATCH 17/37] finalize options menu --- Project.xml | 2 + source/Controls.hx | 96 ++++++++++--- source/OptionsMenu_old.hx | 2 +- source/PlayerSettings.hx | 284 ++++++++++++++++++++++++++------------ source/TitleState.hx | 3 +- source/ui/ControlsMenu.hx | 14 +- 6 files changed, 281 insertions(+), 120 deletions(-) diff --git a/Project.xml b/Project.xml index 85284f76c..3055cf457 100644 --- a/Project.xml +++ b/Project.xml @@ -180,6 +180,8 @@ + +
diff --git a/source/Controls.hx b/source/Controls.hx index 6e49c5387..95748946f 100644 --- a/source/Controls.hx +++ b/source/Controls.hx @@ -18,10 +18,11 @@ import flixel.input.keyboard.FlxKey; */ enum Control { - NOTE_UP; + // List notes in order from left to right on gameplay screen. NOTE_LEFT; - NOTE_RIGHT; NOTE_DOWN; + NOTE_UP; + NOTE_RIGHT; UI_UP; UI_LEFT; UI_RIGHT; @@ -327,7 +328,7 @@ class Controls extends FlxActionSet } } - public function replaceBinding(control:Control, device:Device, ?toAdd:Int, ?toRemove:Int) + public function replaceBinding(control:Control, device:Device, toAdd:Int, toRemove:Int) { if (toAdd == toRemove) return; @@ -335,16 +336,36 @@ class Controls extends FlxActionSet switch (device) { case Keys: - if (toRemove != null) - unbindKeys(control, [toRemove]); - if (toAdd != null) - bindKeys(control, [toAdd]); + forEachBound(control, function(action, _) replaceKey(action, toAdd, toRemove)); case Gamepad(id): - if (toRemove != null) - unbindButtons(control, id, [toRemove]); - if (toAdd != null) - bindButtons(control, id, [toAdd]); + forEachBound(control, function(action, _) replaceButton(action, id, toAdd, toRemove)); + } + } + + function replaceKey(action:FlxActionDigital, toAdd:Int, toRemove:Int) + { + for (i in 0...action.inputs.length) + { + var input = action.inputs[i]; + if (input.device == KEYBOARD && input.inputID == toRemove) + { + @:privateAccess + action.inputs[i].inputID = toAdd; + } + } + } + + function replaceButton(action:FlxActionDigital, deviceID:Int, toAdd:Int, toRemove:Int) + { + for (i in 0...action.inputs.length) + { + var input = action.inputs[i]; + if (isGamepad(input, deviceID) && input.inputID == toRemove) + { + @:privateAccess + action.inputs[i].inputID = toAdd; + } } } @@ -498,12 +519,11 @@ class Controls extends FlxActionSet } } - public function addGamepad(id:Int, ?buttonMap:Map>):Void + public function addGamepadWithSaveData(id:Int, ?padData:Dynamic):Void { gamepadsAdded.push(id); - for (control in buttonMap.keys()) - bindButtons(control, id, buttonMap[control]); + fromSaveData(padData, Gamepad(id)); } inline function addGamepadLiteral(id:Int, ?buttonMap:Map>):Void @@ -522,7 +542,7 @@ class Controls extends FlxActionSet while (i-- > 0) { var input = action.inputs[i]; - if (input.device == GAMEPAD && (deviceID == FlxInputDeviceID.ALL || input.deviceID == deviceID)) + if (isGamepad(input, deviceID)) action.remove(input); } } @@ -533,13 +553,9 @@ class Controls extends FlxActionSet public function addDefaultGamepad(id):Void { addGamepadLiteral(id, [ - #if switch - Control.ACCEPT => [B], - Control.BACK => [A], - #else - Control.ACCEPT => [A], - Control.BACK => [B], - #end + + Control.ACCEPT => [#if switch B #else A #end], + Control.BACK => [#if switch A #else B #end, BACK], Control.UI_UP => [DPAD_UP, LEFT_STICK_DIGITAL_UP], Control.UI_DOWN => [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN], Control.UI_LEFT => [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT], @@ -608,7 +624,7 @@ class Controls extends FlxActionSet case Gamepad(id): for (input in getActionFromControl(control).inputs) { - if (input.deviceID == id) + if (isGamepad(input, id)) list.push(input.inputID); } } @@ -626,6 +642,37 @@ class Controls extends FlxActionSet } } + public function fromSaveData(data:Dynamic, device:Device) + { + for (control in Control.createAll()) + { + var inputs:Array = Reflect.field(data, control.getName()); + if (inputs != null) + { + switch(device) + { + case Keys: bindKeys(control, inputs.copy()); + case Gamepad(id): bindButtons(control, id, inputs.copy()); + } + } + } + } + + public function createSaveData(device:Device):Dynamic + { + var isEmpty = true; + var data = {}; + for (control in Control.createAll()) + { + var inputs = getInputsFor(control, device); + isEmpty = isEmpty && inputs.length == 0; + + Reflect.setField(data, control.getName(), inputs); + } + + return isEmpty ? null : data; + } + static function isDevice(input:FlxActionInput, device:Device) { return switch device @@ -640,3 +687,6 @@ class Controls extends FlxActionSet return input.device == GAMEPAD && (deviceID == FlxInputDeviceID.ALL || input.deviceID == deviceID); } } + + +typedef SaveInputLists = {?keys:Array, ?pad:Array}; \ No newline at end of file diff --git a/source/OptionsMenu_old.hx b/source/OptionsMenu_old.hx index 3acd212a3..4ec844323 100644 --- a/source/OptionsMenu_old.hx +++ b/source/OptionsMenu_old.hx @@ -82,7 +82,7 @@ class OptionsMenu_old extends MusicBeatState { if (FlxG.keys.getIsDown().length > 0) { - PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxG.keys.getIsDown()[0].ID, null); + // PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxG.keys.getIsDown()[0].ID, null); } // PlayerSettings.player1.controls.replaceBinding(Control) } diff --git a/source/PlayerSettings.hx b/source/PlayerSettings.hx index df7586c44..a0ed2429a 100644 --- a/source/PlayerSettings.hx +++ b/source/PlayerSettings.hx @@ -1,8 +1,11 @@ package; import Controls; + import flixel.FlxCamera; import flixel.FlxG; +import flixel.input.actions.FlxActionInput; +import flixel.input.gamepad.FlxGamepad; import flixel.util.FlxSignal; // import ui.DeviceManager; @@ -24,124 +27,223 @@ class PlayerSettings // public var avatar:Player; // public var camera(get, never):PlayCamera; - function new(id, scheme) + function new(id) { this.id = id; - this.controls = new Controls('player$id', scheme); + this.controls = new Controls('player$id', None); + + #if CLEAR_INPUT_SAVE + FlxG.save.data.controls = null; + FlxG.save.flush(); + #end + + var useDefault = true; + var controlData = FlxG.save.data.controls; + if (controlData != null) + { + var keyData:Dynamic = null; + if (id == 0 && controlData.p1 != null && controlData.p1.keys != null) + keyData = controlData.p1.keys; + else if (id == 1 && controlData.p2 != null && controlData.p2.keys != null) + keyData = controlData.p2.keys; + + if (keyData != null) + { + useDefault = false; + trace("loaded key data: " + haxe.Json.stringify(keyData)); + controls.fromSaveData(keyData, Keys); + } + } + + if (useDefault) + controls.setKeyboardScheme(Solo); } + + function addGamepad(gamepad:FlxGamepad) + { + var useDefault = true; + var controlData = FlxG.save.data.controls; + if (controlData != null) + { + var padData:Dynamic = null; + if (id == 0 && controlData.p1 != null && controlData.p1.pad != null) + padData = controlData.p1.pad; + else if (id == 1 && controlData.p2 != null && controlData.p2.pad != null) + padData = controlData.p2.pad; + + if (padData != null) + { + useDefault = false; + trace("loaded pad data: " + haxe.Json.stringify(padData)); + controls.addGamepadWithSaveData(gamepad.id, padData); + } + } + + if (useDefault) + controls.addDefaultGamepad(gamepad.id); + } + + public function saveControls() + { + if (FlxG.save.data.controls == null) + FlxG.save.data.controls = {}; + + var playerData:{ ?keys:Dynamic, ?pad:Dynamic } + if (id == 0) + { + if (FlxG.save.data.controls.p1 == null) + FlxG.save.data.controls.p1 = {}; + playerData = FlxG.save.data.controls.p1; + } + else + { + if (FlxG.save.data.controls.p2 == null) + FlxG.save.data.controls.p2 = {}; + playerData = FlxG.save.data.controls.p2; + } + + var keyData = controls.createSaveData(Keys); + if (keyData != null) + { + playerData.keys = keyData; + trace("saving key data: " + haxe.Json.stringify(keyData)); + } + + if (controls.gamepadsAdded.length > 0) + { + var padData = controls.createSaveData(Gamepad(controls.gamepadsAdded[0])); + if (padData != null) + { + trace("saving pad data: " + haxe.Json.stringify(padData)); + playerData.pad = padData; + } + } + + FlxG.save.flush(); + } + + static public function init():Void + { + if (player1 == null) + { + player1 = new PlayerSettings(0); + ++numPlayers; + } + + FlxG.gamepads.deviceConnected.add(onGamepadAdded); + var numGamepads = FlxG.gamepads.numActiveGamepads; + for (i in 0...numGamepads) + { + var gamepad = FlxG.gamepads.getByID(i); + if (gamepad != null) + onGamepadAdded(gamepad); + } + + // player1.controls.addDefaultGamepad(0); + // } + + // if (numGamepads > 1) + // { + // if (player2 == null) + // { + // player2 = new PlayerSettings(1, None); + // ++numPlayers; + // } + + // var gamepad = FlxG.gamepads.getByID(1); + // if (gamepad == null) + // throw 'Unexpected null gamepad. id:0'; + + // player2.controls.addDefaultGamepad(1); + // } + + // DeviceManager.init(); + } + + static function onGamepadAdded(gamepad:FlxGamepad) + { + player1.addGamepad(gamepad); + } + + + /* public function setKeyboardScheme(scheme) { controls.setKeyboardScheme(scheme); } - /* - static public function addAvatar(avatar:Player):PlayerSettings - { - var settings:PlayerSettings; - - if (player1 == null) - { - player1 = new PlayerSettings(0, Solo); - ++numPlayers; - } - - if (player1.avatar == null) - settings = player1; - else - { - if (player2 == null) - { - if (player1.controls.keyboardScheme.match(Duo(true))) - player2 = new PlayerSettings(1, Duo(false)); - else - player2 = new PlayerSettings(1, None); - ++numPlayers; - } - - if (player2.avatar == null) - settings = player2; - else - throw throw 'Invalid number of players: ${numPlayers + 1}'; - } - ++numAvatars; - settings.avatar = avatar; - avatar.settings = settings; - - splitCameras(); - - onAvatarAdd.dispatch(settings); - - return settings; - } - - static public function removeAvatar(avatar:Player):Void - { - var settings:PlayerSettings; - - if (player1 != null && player1.avatar == avatar) - settings = player1; - else if (player2 != null && player2.avatar == avatar) - { - settings = player2; - if (player1.controls.keyboardScheme.match(Duo(_))) - player1.setKeyboardScheme(Solo); - } - else - throw "Cannot remove avatar that is not for a player"; - - settings.avatar = null; - while (settings.controls.gamepadsAdded.length > 0) - { - final id = settings.controls.gamepadsAdded.shift(); - settings.controls.removeGamepad(id); - DeviceManager.releaseGamepad(FlxG.gamepads.getByID(id)); - } - - --numAvatars; - - splitCameras(); - - onAvatarRemove.dispatch(avatar.settings); - } - - */ - static public function init():Void + static public function addAvatar(avatar:Player):PlayerSettings { + var settings:PlayerSettings; + if (player1 == null) { player1 = new PlayerSettings(0, Solo); ++numPlayers; } - var numGamepads = FlxG.gamepads.numActiveGamepads; - if (numGamepads > 0) - { - var gamepad = FlxG.gamepads.getByID(0); - if (gamepad == null) - throw 'Unexpected null gamepad. id:0'; - - player1.controls.addDefaultGamepad(0); - } - - if (numGamepads > 1) + if (player1.avatar == null) + settings = player1; + else { if (player2 == null) { - player2 = new PlayerSettings(1, None); + if (player1.controls.keyboardScheme.match(Duo(true))) + player2 = new PlayerSettings(1, Duo(false)); + else + player2 = new PlayerSettings(1, None); ++numPlayers; } - var gamepad = FlxG.gamepads.getByID(1); - if (gamepad == null) - throw 'Unexpected null gamepad. id:0'; + if (player2.avatar == null) + settings = player2; + else + throw throw 'Invalid number of players: ${numPlayers + 1}'; + } + ++numAvatars; + settings.avatar = avatar; + avatar.settings = settings; - player2.controls.addDefaultGamepad(1); + splitCameras(); + + onAvatarAdd.dispatch(settings); + + return settings; + } + + static public function removeAvatar(avatar:Player):Void + { + var settings:PlayerSettings; + + if (player1 != null && player1.avatar == avatar) + settings = player1; + else if (player2 != null && player2.avatar == avatar) + { + settings = player2; + if (player1.controls.keyboardScheme.match(Duo(_))) + player1.setKeyboardScheme(Solo); + } + else + throw "Cannot remove avatar that is not for a player"; + + settings.avatar = null; + while (settings.controls.gamepadsAdded.length > 0) + { + final id = settings.controls.gamepadsAdded.shift(); + settings.controls.removeGamepad(id); + DeviceManager.releaseGamepad(FlxG.gamepads.getByID(id)); } - // DeviceManager.init(); + --numAvatars; + + splitCameras(); + + onAvatarRemove.dispatch(avatar.settings); } + */ + static public function reset() { player1 = null; diff --git a/source/TitleState.hx b/source/TitleState.hx index 01668d72c..eff43f823 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -41,8 +41,6 @@ class TitleState extends MusicBeatState FlxG.sound.muteKeys = [ZERO]; - PlayerSettings.init(); - curWacky = FlxG.random.getObject(getIntroTextShit()); // DEBUG BULLSHIT @@ -50,6 +48,7 @@ class TitleState extends MusicBeatState super.create(); FlxG.save.bind('funkin', 'ninjamuffin99'); + PlayerSettings.init(); Highscore.load(); #if newgrounds diff --git a/source/ui/ControlsMenu.hx b/source/ui/ControlsMenu.hx index ca923af29..629a89914 100644 --- a/source/ui/ControlsMenu.hx +++ b/source/ui/ControlsMenu.hx @@ -184,7 +184,12 @@ class ControlsMenu extends ui.OptionsState.Page var inputName = device == Keys ? "key" : "button"; var cancel = device == Keys ? "Escape" : "Back"; - prompt.setText('\nPress any $inputName to rebind\n\n\n\n $cancel to cancel'); + //todo: alignment + if (device == Keys) + prompt.setText('\nPress any key to rebind\n\n\n\n $cancel to cancel'); + else + prompt.setText('\nPress any button\n to rebind\n\n\n $cancel to cancel'); + controlGrid.selectedItem.select(); labels.members[Std.int(controlGrid.selectedIndex / COLUMNS)].alpha = 1.0; @@ -265,13 +270,16 @@ class ControlsMenu extends ui.OptionsState.Page // Don't use resetItem() since items share names/labels item.input = input; item.label.text = item.getLabel(input); + + PlayerSettings.player1.saveControls(); } function closePrompt() { - controlGrid.enabled = true; - canExit = true; prompt.exists = false; + controlGrid.enabled = true; + if (deviceList == null) + canExit = true; } override function destroy() From c545a6e090e0777668b2d706c5fb737ca68163a7 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Mon, 22 Mar 2021 21:39:50 -0500 Subject: [PATCH 18/37] fix AtlasText bug --- source/ui/AtlasText.hx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/ui/AtlasText.hx b/source/ui/AtlasText.hx index 3ba3a746a..e9d06e711 100644 --- a/source/ui/AtlasText.hx +++ b/source/ui/AtlasText.hx @@ -118,8 +118,8 @@ class AtlasText extends FlxTypedSpriteGroup else if (charCount > 0) { var lastChar = group.members[charCount - 1]; - xPos = lastChar.x + lastChar.width; - yPos = lastChar.y + lastChar.height - maxHeight; + xPos = lastChar.x + lastChar.width - x; + yPos = lastChar.y + lastChar.height - maxHeight - y; } var splitValues = text.split(""); @@ -146,10 +146,10 @@ class AtlasText extends FlxTypedSpriteGroup charSprite = group.members[charCount]; charSprite.revive(); charSprite.char = char; + charSprite.alpha = 1;//gets multiplied when added } charSprite.x = xPos; charSprite.y = yPos + maxHeight - charSprite.height; - charSprite.alpha = 1;//gets multiplied when added add(charSprite); xPos += charSprite.width; From b8ef4952cd9d02b69ec9f7b18ef94497724b6a73 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Mon, 22 Mar 2021 22:41:27 -0500 Subject: [PATCH 19/37] fix type --- source/Controls.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Controls.hx b/source/Controls.hx index 95748946f..760fc0af0 100644 --- a/source/Controls.hx +++ b/source/Controls.hx @@ -555,7 +555,7 @@ class Controls extends FlxActionSet addGamepadLiteral(id, [ Control.ACCEPT => [#if switch B #else A #end], - Control.BACK => [#if switch A #else B #end, BACK], + Control.BACK => [#if switch A #else B #end, FlxGamepadInputID.BACK], Control.UI_UP => [DPAD_UP, LEFT_STICK_DIGITAL_UP], Control.UI_DOWN => [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN], Control.UI_LEFT => [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT], From e6a50648455a9957de369362e2133b5bd6af874d Mon Sep 17 00:00:00 2001 From: George FunBook Date: Mon, 22 Mar 2021 22:41:37 -0500 Subject: [PATCH 20/37] fix camera --- source/MainMenuState.hx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index f2bc0f426..6c04e758d 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -50,8 +50,8 @@ class MainMenuState extends MusicBeatState var bg:FlxSprite = new FlxSprite(Paths.image('menuBG')); bg.scrollFactor.x = 0; - bg.scrollFactor.y = 0.18; - bg.setGraphicSize(Std.int(bg.width * 1.3)); + bg.scrollFactor.y = 0.17; + bg.setGraphicSize(Std.int(bg.width * 1.2)); bg.updateHitbox(); bg.screenCenter(); bg.antialiasing = true; @@ -110,7 +110,7 @@ class MainMenuState extends MusicBeatState } FlxG.camera.follow(camFollow, null, 0.06); - FlxG.camera.setScrollBounds(bg.x, bg.x + bg.width, bg.y, bg.y + bg.height * 1.2); + // FlxG.camera.setScrollBounds(bg.x, bg.x + bg.width, bg.y, bg.y + bg.height * 1.2); var versionShit:FlxText = new FlxText(5, FlxG.height - 18, 0, "v" + Application.current.meta.get('version'), 12); versionShit.scrollFactor.set(); From e6c48ed56fadbfe316087a3cfbf4845fa8f92c04 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 23 Mar 2021 17:28:05 -0500 Subject: [PATCH 21/37] fix back bug --- source/ui/ControlsMenu.hx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/ui/ControlsMenu.hx b/source/ui/ControlsMenu.hx index 629a89914..5f977659a 100644 --- a/source/ui/ControlsMenu.hx +++ b/source/ui/ControlsMenu.hx @@ -204,7 +204,7 @@ class ControlsMenu extends ui.OptionsState.Page super.update(elapsed); var controls = PlayerSettings.player1.controls; - if (enabled && deviceList != null && deviceListSelected == false && controls.BACK) + if (controlGrid.enabled && deviceList != null && deviceListSelected == false && controls.BACK) goToDeviceList(); if (prompt.exists) @@ -213,7 +213,8 @@ class ControlsMenu extends ui.OptionsState.Page { case Keys: { - var key = FlxG.keys.firstJustPressed(); + // check released otherwise bugs can happen when you change the BACK key + var key = FlxG.keys.firstJustReleased(); if (key != NONE) { if (key != ESCAPE) @@ -223,7 +224,7 @@ class ControlsMenu extends ui.OptionsState.Page } case Gamepad(id): { - var button = FlxG.gamepads.getByID(id).firstJustPressedID(); + var button = FlxG.gamepads.getByID(id).firstJustReleasedID(); if (button != NONE) { if (button != BACK) From d5d484bfb23c4f4a671b53e9720ec54990308350 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Tue, 23 Mar 2021 17:30:58 -0500 Subject: [PATCH 22/37] fix remove defaultCamera refs --- source/PlayState.hx | 4 +--- source/ui/ControlsMenu.hx | 7 +------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/source/PlayState.hx b/source/PlayState.hx index 610d50987..2d6afdda2 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -153,9 +153,7 @@ class PlayState extends MusicBeatState camHUD.bgColor.alpha = 0; FlxG.cameras.reset(camGame); - FlxG.cameras.add(camHUD); - - FlxCamera.defaultCameras = [camGame]; + FlxG.cameras.add(camHUD, false); persistentUpdate = true; persistentDraw = true; diff --git a/source/ui/ControlsMenu.hx b/source/ui/ControlsMenu.hx index 5f977659a..cd1e8b9f8 100644 --- a/source/ui/ControlsMenu.hx +++ b/source/ui/ControlsMenu.hx @@ -45,12 +45,7 @@ class ControlsMenu extends ui.OptionsState.Page super(); menuCamera = new FlxCamera(); - FlxG.cameras.add(menuCamera);// false); - if (FlxCamera.defaultCameras.indexOf(menuCamera) != -1) - { - FlxCamera.defaultCameras = FlxCamera.defaultCameras.copy(); - FlxCamera.defaultCameras.remove(menuCamera); - } + FlxG.cameras.add(menuCamera, false); menuCamera.bgColor = 0x0; camera = menuCamera; From 9397334792c108b91a02eba83f661b47b8491489 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 23 Mar 2021 18:43:08 -0400 Subject: [PATCH 23/37] outline shader in progress --- source/ColorpickSubstate.hx | 11 +++++++++++ source/shaderslmfao/ColorSwap.hx | 21 +++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/source/ColorpickSubstate.hx b/source/ColorpickSubstate.hx index 6123acc9b..b988acce4 100644 --- a/source/ColorpickSubstate.hx +++ b/source/ColorpickSubstate.hx @@ -1,7 +1,10 @@ package; import flixel.FlxG; +import flixel.addons.effects.chainable.FlxEffectSprite; +import flixel.addons.effects.chainable.FlxOutlineEffect; import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.util.FlxColor; import shaderslmfao.ColorSwap; class ColorpickSubstate extends MusicBeatSubstate @@ -24,6 +27,14 @@ class ColorpickSubstate extends MusicBeatSubstate note.x = (100 * i) + i; note.screenCenter(Y); + var _effectSpr:FlxEffectSprite = new FlxEffectSprite(note, [new FlxOutlineEffect(FlxOutlineMode.FAST, FlxColor.WHITE, 4, 1)]); + add(_effectSpr); + _effectSpr.y = 0; + _effectSpr.x = i * 80; + _effectSpr.antialiasing = true; + _effectSpr.setGraphicSize(Std.int(_effectSpr.width * 0.7)); + _effectSpr.updateHitbox(); + grpNotes.add(note); } } diff --git a/source/shaderslmfao/ColorSwap.hx b/source/shaderslmfao/ColorSwap.hx index 1f57dc7a0..33272e476 100644 --- a/source/shaderslmfao/ColorSwap.hx +++ b/source/shaderslmfao/ColorSwap.hx @@ -53,6 +53,9 @@ class ColorSwapShader extends FlxShader uniform float uTime; uniform float money; + const float offset = 1.0 / 128.0; + + vec3 normalizeColor(vec3 color) { return vec3( @@ -93,8 +96,22 @@ class ColorSwapShader extends FlxShader // money += swagColor[0]; color = vec4(hsv2rgb(vec3(swagColor[0], swagColor[1], swagColor[2])), swagColor[3]); - - gl_FragColor = color; +/* + if (color.a > 0.5) + gl_FragColor = color; + else + { + float a = flixel_texture2D(bitmap, vec2(openfl_TextureCoordv + offset, openfl_TextureCoordv.y)).a + + flixel_texture2D(bitmap, vec2(openfl_TextureCoordv, openfl_TextureCoordv.y - offset)).a + + flixel_texture2D(bitmap, vec2(openfl_TextureCoordv - offset, openfl_TextureCoordv.y)).a + + flixel_texture2D(bitmap, vec2(openfl_TextureCoordv, openfl_TextureCoordv.y + offset)).a; + if (color.a < 1.0 && a > 0.0) + gl_FragColor = vec4(0.0, 0.0, 0.0, 0.8); + else + gl_FragColor = color; + } + */ + } ') From 6def44b83ca8d3c148489fb8b74ad8904300bfec Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 23 Mar 2021 21:33:17 -0400 Subject: [PATCH 24/37] lol fixed dumbass shader thinge oops --- source/shaderslmfao/ColorSwap.hx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/shaderslmfao/ColorSwap.hx b/source/shaderslmfao/ColorSwap.hx index 33272e476..2ce958385 100644 --- a/source/shaderslmfao/ColorSwap.hx +++ b/source/shaderslmfao/ColorSwap.hx @@ -96,7 +96,10 @@ class ColorSwapShader extends FlxShader // money += swagColor[0]; color = vec4(hsv2rgb(vec3(swagColor[0], swagColor[1], swagColor[2])), swagColor[3]); -/* + gl_FragColor = color; + + + /* if (color.a > 0.5) gl_FragColor = color; else @@ -110,7 +113,7 @@ class ColorSwapShader extends FlxShader else gl_FragColor = color; } - */ + */ } From 985bd5374bdf55ffc8ba501c688e6fc54ad5cb09 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 24 Mar 2021 16:44:58 -0400 Subject: [PATCH 25/37] converting shit to new options menu --- source/ColorpickSubstate.hx | 8 +-- source/ModdingSubstate.hx | 4 +- source/OptionsSubState.hx | 4 +- source/ui/ColorsMenu.hx | 73 +++++++++++++++++++++++++++ source/ui/OptionsState.hx | 98 ++++++++++++++++++++----------------- 5 files changed, 133 insertions(+), 54 deletions(-) create mode 100644 source/ui/ColorsMenu.hx diff --git a/source/ColorpickSubstate.hx b/source/ColorpickSubstate.hx index b988acce4..8a5b486b3 100644 --- a/source/ColorpickSubstate.hx +++ b/source/ColorpickSubstate.hx @@ -47,9 +47,9 @@ class ColorpickSubstate extends MusicBeatSubstate FlxG.state.openSubState(new OptionsSubState()); } - if (controls.RIGHT_P) + if (controls.UI_RIGHT_P) curSelected += 1; - if (controls.LEFT_P) + if (controls.UI_LEFT_P) curSelected -= 1; if (curSelected < 0) @@ -57,13 +57,13 @@ class ColorpickSubstate extends MusicBeatSubstate if (curSelected >= grpNotes.members.length) curSelected = 0; - if (controls.UP) + if (controls.UI_UP) { grpNotes.members[curSelected].colorSwap.update(elapsed * 0.3); Note.arrowColors[curSelected] += elapsed * 0.3; } - if (controls.DOWN) + if (controls.UI_DOWN) { grpNotes.members[curSelected].colorSwap.update(-elapsed * 0.3); Note.arrowColors[curSelected] += -elapsed * 0.3; diff --git a/source/ModdingSubstate.hx b/source/ModdingSubstate.hx index 8dfc46016..530fc5cb2 100644 --- a/source/ModdingSubstate.hx +++ b/source/ModdingSubstate.hx @@ -35,9 +35,9 @@ class ModdingSubstate extends MusicBeatSubstate selections(); - if (controls.UP_P) + if (controls.UI_UP_P) selections(-1); - if (controls.DOWN_P) + if (controls.UI_DOWN_P) selections(1); if (FlxG.keys.justPressed.SPACE) diff --git a/source/OptionsSubState.hx b/source/OptionsSubState.hx index ee27bdfc1..b1fd705f0 100644 --- a/source/OptionsSubState.hx +++ b/source/OptionsSubState.hx @@ -43,10 +43,10 @@ class OptionsSubState extends MusicBeatSubstate { super.update(elapsed); - if (controls.UP_P) + if (controls.UI_UP_P) curSelected -= 1; - if (controls.DOWN_P) + if (controls.UI_DOWN_P) curSelected += 1; if (curSelected < 0) diff --git a/source/ui/ColorsMenu.hx b/source/ui/ColorsMenu.hx new file mode 100644 index 000000000..bd5071f59 --- /dev/null +++ b/source/ui/ColorsMenu.hx @@ -0,0 +1,73 @@ +package ui; + +import flixel.FlxG; +import flixel.addons.effects.chainable.FlxEffectSprite; +import flixel.addons.effects.chainable.FlxOutlineEffect; +import flixel.group.FlxGroup.FlxTypedGroup; +import flixel.util.FlxColor; + +class ColorsMenu extends ui.OptionsState.Page +{ + var curSelected:Int = 0; + + var grpNotes:FlxTypedGroup; + + public function new() + { + super(); + + grpNotes = new FlxTypedGroup(); + add(grpNotes); + + for (i in 0...4) + { + var note:Note = new Note(0, i); + + note.x = (100 * i) + i; + note.screenCenter(Y); + + var _effectSpr:FlxEffectSprite = new FlxEffectSprite(note, [new FlxOutlineEffect(FlxOutlineMode.FAST, FlxColor.WHITE, 4, 1)]); + add(_effectSpr); + _effectSpr.y = 0; + _effectSpr.x = i * 80; + _effectSpr.antialiasing = true; + _effectSpr.setGraphicSize(Std.int(_effectSpr.width * 0.7)); + _effectSpr.updateHitbox(); + + grpNotes.add(note); + } + } + + override function update(elapsed:Float) + { + if (controls.BACK) + { + FlxG.state.closeSubState(); + FlxG.state.openSubState(new OptionsSubState()); + } + + if (controls.UI_RIGHT_P) + curSelected += 1; + if (controls.UI_LEFT_P) + curSelected -= 1; + + if (curSelected < 0) + curSelected = grpNotes.members.length - 1; + if (curSelected >= grpNotes.members.length) + curSelected = 0; + + if (controls.UI_UP) + { + grpNotes.members[curSelected].colorSwap.update(elapsed * 0.3); + Note.arrowColors[curSelected] += elapsed * 0.3; + } + + if (controls.UI_DOWN) + { + grpNotes.members[curSelected].colorSwap.update(-elapsed * 0.3); + Note.arrowColors[curSelected] += -elapsed * 0.3; + } + + super.update(elapsed); + } +} diff --git a/source/ui/OptionsState.hx b/source/ui/OptionsState.hx index 0e4fae95c..f4daa3c86 100644 --- a/source/ui/OptionsState.hx +++ b/source/ui/OptionsState.hx @@ -1,23 +1,23 @@ package ui; -import flixel.FlxSubState; import flixel.FlxG; import flixel.FlxSprite; +import flixel.FlxSubState; +import flixel.addons.transition.FlxTransitionableState; import flixel.group.FlxGroup; import flixel.util.FlxSignal; -import flixel.addons.transition.FlxTransitionableState; - // typedef OptionsState = OptionsMenu_old; - // class OptionsState_new extends MusicBeatState class OptionsState extends MusicBeatState { var pages = new Map(); var currentName:PageName = #if newgrounds Options #else Controls #end; var currentPage(get, never):Page; - inline function get_currentPage() return pages[currentName]; - + + inline function get_currentPage() + return pages[currentName]; + override function create() { var menuBG = new FlxSprite().loadGraphic(Paths.image('menuDesat')); @@ -27,14 +27,16 @@ class OptionsState extends MusicBeatState menuBG.screenCenter(); menuBG.scrollFactor.set(0, 0); add(menuBG); - + var options = addPage(Options, new OptionsMenu(false)); var controls = addPage(Controls, new ControlsMenu()); - + var colors = addPage(Colors, new ColorsMenu()); + if (options.hasMultipleOptions()) { options.onExit.add(exitToMainMenu); controls.onExit.add(switchPage.bind(Options)); + colors.onExit.add(switchPage.bind(Options)); } else { @@ -42,12 +44,12 @@ class OptionsState extends MusicBeatState controls.onExit.add(exitToMainMenu); setPage(Controls); } - + // disable for intro transition currentPage.enabled = false; super.create(); } - + function addPage(name:PageName, page:T) { page.onSwitch.add(switchPage); @@ -56,35 +58,35 @@ class OptionsState extends MusicBeatState page.exists = currentName == name; return page; } - + function setPage(name:PageName) { if (pages.exists(currentName)) currentPage.exists = false; - + currentName = name; - + if (pages.exists(currentName)) currentPage.exists = true; } - + override function finishTransIn() { super.finishTransIn(); - + currentPage.enabled = true; } - + function switchPage(name:PageName) { - //Todo animate? + // Todo animate? setPage(name); } - + function exitToMainMenu() { currentPage.enabled = false; - //Todo animate? + // Todo animate? FlxG.switchState(new MainMenuState()); } } @@ -93,57 +95,59 @@ class Page extends FlxGroup { public var onSwitch(default, null) = new FlxTypedSignalVoid>(); public var onExit(default, null) = new FlxSignal(); - + public var enabled(default, set) = true; public var canExit = true; - + var controls(get, never):Controls; - inline function get_controls() return PlayerSettings.player1.controls; - + + inline function get_controls() + return PlayerSettings.player1.controls; + var subState:FlxSubState; - + inline function switchPage(name:PageName) { onSwitch.dispatch(name); } - + inline function exit() { onExit.dispatch(); } - + override function update(elapsed:Float) { super.update(elapsed); - + if (enabled) updateEnabled(elapsed); } - + function updateEnabled(elapsed:Float) { if (canExit && controls.BACK) exit(); } - + function set_enabled(value:Bool) { return this.enabled = value; } - + function openPrompt(prompt:Prompt, onClose:Void->Void) { enabled = false; - prompt.closeCallback = function () + prompt.closeCallback = function() { enabled = true; if (onClose != null) onClose(); } - + FlxG.state.openSubState(prompt); } - + override function destroy() { super.destroy(); @@ -154,13 +158,14 @@ class Page extends FlxGroup class OptionsMenu extends Page { var items:TextMenuList; - - public function new (showDonate:Bool) + + public function new(showDonate:Bool) { super(); - + add(items = new TextMenuList()); createItem("controls", function() switchPage(Controls)); + createItem('colors', function() switchPage(Colors)); #if CAN_OPEN_LINKS if (showDonate) { @@ -176,7 +181,7 @@ class OptionsMenu extends Page #end createItem("exit", exit); } - + function createItem(name:String, callback:Void->Void, fireInstantly = false) { var item = items.createItem(0, 100 + items.length * 100, name, Bold, callback); @@ -184,13 +189,13 @@ class OptionsMenu extends Page item.screenCenter(X); return item; } - + override function set_enabled(value:Bool) { items.enabled = value; return super.set_enabled(value); } - + /** * True if this page has multiple options, ecluding the exit option. * If false, there's no reason to ever show this page. @@ -199,7 +204,7 @@ class OptionsMenu extends Page { return items.length > 2; } - + #if CAN_OPEN_LINKS function selectDonate() { @@ -210,18 +215,18 @@ class OptionsMenu extends Page #end } #end - + #if newgrounds function selectLogin() { openNgPrompt(NgPrompt.showLogin()); } - + function selectLogout() { openNgPrompt(NgPrompt.showLogout()); } - + /** * Calls openPrompt and redraws the login/logout button * @param prompt @@ -232,16 +237,16 @@ class OptionsMenu extends Page var onPromptClose = checkLoginStatus; if (onClose != null) { - onPromptClose = function () + onPromptClose = function() { checkLoginStatus(); onClose(); } } - + openPrompt(prompt, onPromptClose); } - + function checkLoginStatus() { var prevLoggedIn = items.has("logout"); @@ -257,4 +262,5 @@ enum PageName { Options; Controls; + Colors; } From 180c3db3c4da7b744b3b9d86f1fcc5e8bcc24962 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 24 Mar 2021 18:41:54 -0400 Subject: [PATCH 26/37] outline bullshit in progress --- source/ColorpickSubstate.hx | 74 -------------------- source/OptionsSubState.hx | 9 ++- source/TitleState.hx | 7 +- source/shaderslmfao/ColorSwap.hx | 40 ++++++++++- source/ui/ColorsMenu.hx | 16 ++--- source/{ModdingSubstate.hx => ui/ModMenu.hx} | 7 +- source/ui/OptionsState.hx | 5 ++ 7 files changed, 64 insertions(+), 94 deletions(-) delete mode 100644 source/ColorpickSubstate.hx rename source/{ModdingSubstate.hx => ui/ModMenu.hx} (96%) diff --git a/source/ColorpickSubstate.hx b/source/ColorpickSubstate.hx deleted file mode 100644 index 8a5b486b3..000000000 --- a/source/ColorpickSubstate.hx +++ /dev/null @@ -1,74 +0,0 @@ -package; - -import flixel.FlxG; -import flixel.addons.effects.chainable.FlxEffectSprite; -import flixel.addons.effects.chainable.FlxOutlineEffect; -import flixel.group.FlxGroup.FlxTypedGroup; -import flixel.util.FlxColor; -import shaderslmfao.ColorSwap; - -class ColorpickSubstate extends MusicBeatSubstate -{ - var curSelected:Int = 0; - - var grpNotes:FlxTypedGroup; - - public function new() - { - super(); - - grpNotes = new FlxTypedGroup(); - add(grpNotes); - - for (i in 0...4) - { - var note:Note = new Note(0, i); - - note.x = (100 * i) + i; - note.screenCenter(Y); - - var _effectSpr:FlxEffectSprite = new FlxEffectSprite(note, [new FlxOutlineEffect(FlxOutlineMode.FAST, FlxColor.WHITE, 4, 1)]); - add(_effectSpr); - _effectSpr.y = 0; - _effectSpr.x = i * 80; - _effectSpr.antialiasing = true; - _effectSpr.setGraphicSize(Std.int(_effectSpr.width * 0.7)); - _effectSpr.updateHitbox(); - - grpNotes.add(note); - } - } - - override function update(elapsed:Float) - { - if (controls.BACK) - { - FlxG.state.closeSubState(); - FlxG.state.openSubState(new OptionsSubState()); - } - - if (controls.UI_RIGHT_P) - curSelected += 1; - if (controls.UI_LEFT_P) - curSelected -= 1; - - if (curSelected < 0) - curSelected = grpNotes.members.length - 1; - if (curSelected >= grpNotes.members.length) - curSelected = 0; - - if (controls.UI_UP) - { - grpNotes.members[curSelected].colorSwap.update(elapsed * 0.3); - Note.arrowColors[curSelected] += elapsed * 0.3; - } - - if (controls.UI_DOWN) - { - grpNotes.members[curSelected].colorSwap.update(-elapsed * 0.3); - Note.arrowColors[curSelected] += -elapsed * 0.3; - } - - super.update(elapsed); - } -} diff --git a/source/OptionsSubState.hx b/source/OptionsSubState.hx index b1fd705f0..1b5071c74 100644 --- a/source/OptionsSubState.hx +++ b/source/OptionsSubState.hx @@ -1,10 +1,15 @@ package; +import Controls.Control; import flixel.FlxG; import flixel.FlxSprite; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.text.FlxText; import flixel.util.FlxColor; +import polymod.Polymod; +#if desktop +import sys.FileSystem; +#end class OptionsSubState extends MusicBeatSubstate { @@ -72,13 +77,13 @@ class OptionsSubState extends MusicBeatSubstate { case "Colors": FlxG.state.closeSubState(); - FlxG.state.openSubState(new ColorpickSubstate()); + case "Controls": FlxG.state.closeSubState(); FlxG.state.openSubState(new ControlsSubState()); case "Mods": FlxG.state.closeSubState(); - FlxG.state.openSubState(new ModdingSubstate()); + // FlxG.state.openSubState(new ModdingSubstate()); case "Back": FlxG.switchState(new MainMenuState()); } diff --git a/source/TitleState.hx b/source/TitleState.hx index 98c681e7d..3e531bac7 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -62,11 +62,11 @@ class TitleState extends MusicBeatState FlxG.save.bind('funkin', 'ninjamuffin99'); PlayerSettings.init(); Highscore.load(); - + #if newgrounds NGio.init(); #end - + if (FlxG.save.data.weekUnlocked != null) { // FIX LATER!!! @@ -329,6 +329,9 @@ class TitleState extends MusicBeatState skipIntro(); } + if (FlxG.keys.justPressed.SPACE) + swagShader.hasOutline = !swagShader.hasOutline; + if (controls.UI_LEFT) { swagShader.update(-elapsed * 0.1); diff --git a/source/shaderslmfao/ColorSwap.hx b/source/shaderslmfao/ColorSwap.hx index 2ce958385..e24ac1095 100644 --- a/source/shaderslmfao/ColorSwap.hx +++ b/source/shaderslmfao/ColorSwap.hx @@ -9,6 +9,9 @@ class ColorSwap public var colorToReplace(default, set):FlxColor; public var newColor(default, set):FlxColor; public var daTime(default, set):Float; + + public var hasOutline(default, set):Bool = false; + public var hueShit:Float = 0; public function new():Void @@ -16,6 +19,7 @@ class ColorSwap shader = new ColorSwapShader(); shader.uTime.value = [0]; shader.money.value = [0]; + shader.awesomeOutline.value = [hasOutline]; } public function update(elapsed:Float):Void @@ -32,6 +36,12 @@ class ColorSwap return color; } + function set_hasOutline(lol:Bool):Bool + { + shader.awesomeOutline.value = [lol]; + return lol; + } + function set_daTime(daTime:Float):Float { return daTime; @@ -52,9 +62,12 @@ class ColorSwapShader extends FlxShader uniform float uTime; uniform float money; + uniform bool awesomeOutline; + const float offset = 1.0 / 128.0; + vec3 normalizeColor(vec3 color) { @@ -96,6 +109,29 @@ class ColorSwapShader extends FlxShader // money += swagColor[0]; color = vec4(hsv2rgb(vec3(swagColor[0], swagColor[1], swagColor[2])), swagColor[3]); + + + if (awesomeOutline) + { + // Outline bullshit? + vec2 size = vec2(3, 3); + + if (color.a <= 0.5) { + float w = size.x / openfl_TextureSize.x; + float h = size.y / openfl_TextureSize.y; + + if (flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x + w, openfl_TextureCoordv.y)).a != 0. + || flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x - w, openfl_TextureCoordv.y)).a != 0. + || flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x, openfl_TextureCoordv.y + h)).a != 0. + || flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x, openfl_TextureCoordv.y - h)).a != 0.) + color = vec4(1.0, 1.0, 1.0, 1.0); + } + + + } + + + gl_FragColor = color; @@ -112,9 +148,7 @@ class ColorSwapShader extends FlxShader gl_FragColor = vec4(0.0, 0.0, 0.0, 0.8); else gl_FragColor = color; - } - */ - + } */ } ') diff --git a/source/ui/ColorsMenu.hx b/source/ui/ColorsMenu.hx index bd5071f59..849451a59 100644 --- a/source/ui/ColorsMenu.hx +++ b/source/ui/ColorsMenu.hx @@ -29,10 +29,14 @@ class ColorsMenu extends ui.OptionsState.Page var _effectSpr:FlxEffectSprite = new FlxEffectSprite(note, [new FlxOutlineEffect(FlxOutlineMode.FAST, FlxColor.WHITE, 4, 1)]); add(_effectSpr); _effectSpr.y = 0; - _effectSpr.x = i * 80; + _effectSpr.x = i * 130; _effectSpr.antialiasing = true; - _effectSpr.setGraphicSize(Std.int(_effectSpr.width * 0.7)); - _effectSpr.updateHitbox(); + _effectSpr.scale.x = _effectSpr.scale.y = 0.7; + // _effectSpr.setGraphicSize(); + _effectSpr.height = note.height; + _effectSpr.width = note.width; + + // _effectSpr.updateHitbox(); grpNotes.add(note); } @@ -40,12 +44,6 @@ class ColorsMenu extends ui.OptionsState.Page override function update(elapsed:Float) { - if (controls.BACK) - { - FlxG.state.closeSubState(); - FlxG.state.openSubState(new OptionsSubState()); - } - if (controls.UI_RIGHT_P) curSelected += 1; if (controls.UI_LEFT_P) diff --git a/source/ModdingSubstate.hx b/source/ui/ModMenu.hx similarity index 96% rename from source/ModdingSubstate.hx rename to source/ui/ModMenu.hx index 530fc5cb2..7fed9b4bb 100644 --- a/source/ModdingSubstate.hx +++ b/source/ui/ModMenu.hx @@ -1,16 +1,15 @@ -package; +package ui; -import Controls.Control; import flixel.FlxG; import flixel.group.FlxGroup.FlxTypedGroup; import flixel.text.FlxText; import flixel.util.FlxColor; +#if cpp import polymod.Polymod; -#if desktop import sys.FileSystem; #end -class ModdingSubstate extends MusicBeatSubstate +class ModMenu extends ui.OptionsState.Page { var grpMods:FlxTypedGroup; var enabledMods:Array = []; diff --git a/source/ui/OptionsState.hx b/source/ui/OptionsState.hx index f4daa3c86..283cbc85f 100644 --- a/source/ui/OptionsState.hx +++ b/source/ui/OptionsState.hx @@ -166,6 +166,10 @@ class OptionsMenu extends Page add(items = new TextMenuList()); createItem("controls", function() switchPage(Controls)); createItem('colors', function() switchPage(Colors)); + #if cpp + createItem('mods', function() switchPage(Mods)); + #end + #if CAN_OPEN_LINKS if (showDonate) { @@ -263,4 +267,5 @@ enum PageName Options; Controls; Colors; + Mods; } From 2fdea58951033992137997e59eddd427d149be47 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 24 Mar 2021 19:19:08 -0400 Subject: [PATCH 27/37] mod menu thingie --- source/ui/OptionsState.hx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/ui/OptionsState.hx b/source/ui/OptionsState.hx index 283cbc85f..3459c9b1b 100644 --- a/source/ui/OptionsState.hx +++ b/source/ui/OptionsState.hx @@ -32,11 +32,19 @@ class OptionsState extends MusicBeatState var controls = addPage(Controls, new ControlsMenu()); var colors = addPage(Colors, new ColorsMenu()); + #if cpp + var mods = addPage(Mods, new ModMenu()); + #end + if (options.hasMultipleOptions()) { options.onExit.add(exitToMainMenu); controls.onExit.add(switchPage.bind(Options)); colors.onExit.add(switchPage.bind(Options)); + + #if cpp + mods.onExit.add(switchPage.bind(Options)); + #end } else { From 7766ddf9bd6752955184839e690a37021de515ae Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 24 Mar 2021 22:41:41 -0400 Subject: [PATCH 28/37] camera movement lerp fix for high framerates --- source/PlayState.hx | 111 +++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 54 deletions(-) diff --git a/source/PlayState.hx b/source/PlayState.hx index 2d6afdda2..9790aceff 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1387,6 +1387,9 @@ class PlayState extends MusicBeatState override public function update(elapsed:Float) { + // makes the lerp non-dependant on the framerate + FlxG.camera.followLerp = 0.04 * (elapsed / (1 / 60)); + #if !debug perfectMode = false; #end @@ -1519,60 +1522,7 @@ class PlayState extends MusicBeatState if (generatedMusic && PlayState.SONG.notes[Std.int(curStep / 16)] != null) { - if (curBeat % 4 == 0) - { - // trace(PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection); - } - - if (camFollow.x != dad.getMidpoint().x + 150 && !PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection) - { - camFollow.setPosition(dad.getMidpoint().x + 150, dad.getMidpoint().y - 100); - // camFollow.setPosition(lucky.getMidpoint().x - 120, lucky.getMidpoint().y + 210); - - switch (dad.curCharacter) - { - case 'mom': - camFollow.y = dad.getMidpoint().y; - case 'senpai': - camFollow.y = dad.getMidpoint().y - 430; - camFollow.x = dad.getMidpoint().x - 100; - case 'senpai-angry': - camFollow.y = dad.getMidpoint().y - 430; - camFollow.x = dad.getMidpoint().x - 100; - } - - if (dad.curCharacter == 'mom') - vocals.volume = 1; - - if (SONG.song.toLowerCase() == 'tutorial') - { - tweenCamIn(); - } - } - - if (PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection && camFollow.x != boyfriend.getMidpoint().x - 100) - { - camFollow.setPosition(boyfriend.getMidpoint().x - 100, boyfriend.getMidpoint().y - 100); - - switch (curStage) - { - case 'limo': - camFollow.x = boyfriend.getMidpoint().x - 300; - case 'mall': - camFollow.y = boyfriend.getMidpoint().y - 200; - case 'school': - camFollow.x = boyfriend.getMidpoint().x - 200; - camFollow.y = boyfriend.getMidpoint().y - 200; - case 'schoolEvil': - camFollow.x = boyfriend.getMidpoint().x - 200; - camFollow.y = boyfriend.getMidpoint().y - 200; - } - - if (SONG.song.toLowerCase() == 'tutorial') - { - FlxTween.tween(FlxG.camera, {zoom: 1}, (Conductor.stepCrochet * 4 / 1000), {ease: FlxEase.elasticInOut}); - } - } + cameraMovement(); } if (camZooming) @@ -1994,6 +1944,59 @@ class PlayState extends MusicBeatState curSection += 1; } + function cameraMovement() + { + if (camFollow.x != dad.getMidpoint().x + 150 && !PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection) + { + camFollow.setPosition(dad.getMidpoint().x + 150, dad.getMidpoint().y - 100); + // camFollow.setPosition(lucky.getMidpoint().x - 120, lucky.getMidpoint().y + 210); + + switch (dad.curCharacter) + { + case 'mom': + camFollow.y = dad.getMidpoint().y; + case 'senpai': + camFollow.y = dad.getMidpoint().y - 430; + camFollow.x = dad.getMidpoint().x - 100; + case 'senpai-angry': + camFollow.y = dad.getMidpoint().y - 430; + camFollow.x = dad.getMidpoint().x - 100; + } + + if (dad.curCharacter == 'mom') + vocals.volume = 1; + + if (SONG.song.toLowerCase() == 'tutorial') + { + tweenCamIn(); + } + } + + if (PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection && camFollow.x != boyfriend.getMidpoint().x - 100) + { + camFollow.setPosition(boyfriend.getMidpoint().x - 100, boyfriend.getMidpoint().y - 100); + + switch (curStage) + { + case 'limo': + camFollow.x = boyfriend.getMidpoint().x - 300; + case 'mall': + camFollow.y = boyfriend.getMidpoint().y - 200; + case 'school': + camFollow.x = boyfriend.getMidpoint().x - 200; + camFollow.y = boyfriend.getMidpoint().y - 200; + case 'schoolEvil': + camFollow.x = boyfriend.getMidpoint().x - 200; + camFollow.y = boyfriend.getMidpoint().y - 200; + } + + if (SONG.song.toLowerCase() == 'tutorial') + { + FlxTween.tween(FlxG.camera, {zoom: 1}, (Conductor.stepCrochet * 4 / 1000), {ease: FlxEase.elasticInOut}); + } + } + } + private function keyShit():Void { // HOLDING From 85e181bc809eac246212cf7f8eb99e8989abb482 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 24 Mar 2021 23:39:19 -0400 Subject: [PATCH 29/37] lerp tweaks and shit more --- source/PlayState.hx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/source/PlayState.hx b/source/PlayState.hx index 9790aceff..0c95bbf53 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1488,8 +1488,8 @@ class PlayState extends MusicBeatState // FlxG.watch.addQuick('VOL', vocals.amplitudeLeft); // FlxG.watch.addQuick('VOLRight', vocals.amplitudeRight); - iconP1.setGraphicSize(Std.int(FlxMath.lerp(150, iconP1.width, 0.50))); - iconP2.setGraphicSize(Std.int(FlxMath.lerp(150, iconP2.width, 0.50))); + iconP1.setGraphicSize(Std.int(FlxMath.lerp(150, iconP1.width, 0.85))); + iconP2.setGraphicSize(Std.int(FlxMath.lerp(150, iconP2.width, 0.85))); iconP1.updateHitbox(); iconP2.updateHitbox(); @@ -1522,6 +1522,8 @@ class PlayState extends MusicBeatState if (generatedMusic && PlayState.SONG.notes[Std.int(curStep / 16)] != null) { + cameraRightSide = PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection; + cameraMovement(); } @@ -1944,9 +1946,11 @@ class PlayState extends MusicBeatState curSection += 1; } + var cameraRightSide:Bool = false; + function cameraMovement() { - if (camFollow.x != dad.getMidpoint().x + 150 && !PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection) + if (camFollow.x != dad.getMidpoint().x + 150 && !cameraRightSide) { camFollow.setPosition(dad.getMidpoint().x + 150, dad.getMidpoint().y - 100); // camFollow.setPosition(lucky.getMidpoint().x - 120, lucky.getMidpoint().y + 210); @@ -1972,7 +1976,7 @@ class PlayState extends MusicBeatState } } - if (PlayState.SONG.notes[Std.int(curStep / 16)].mustHitSection && camFollow.x != boyfriend.getMidpoint().x - 100) + if (cameraRightSide && camFollow.x != boyfriend.getMidpoint().x - 100) { camFollow.setPosition(boyfriend.getMidpoint().x - 100, boyfriend.getMidpoint().y - 100); @@ -2123,7 +2127,7 @@ class PlayState extends MusicBeatState } } - if ((up || right || down || left) && !boyfriend.stunned && generatedMusic) + if ((up || right || down || left) && /*!boyfriend.stunned && */ generatedMusic) { notes.forEachAlive(function(daNote:Note) { From 45652399c35fe13e1b0eb9110c8c11bc01754e86 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 26 Mar 2021 03:51:39 -0400 Subject: [PATCH 30/37] cool note thingies --- source/NoteSplash.hx | 38 ++++++++++++++++++++++++++++++++++++++ source/PlayState.hx | 17 +++++++++++++++-- source/ui/SettingsMenu.hx | 9 +++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 source/NoteSplash.hx create mode 100644 source/ui/SettingsMenu.hx diff --git a/source/NoteSplash.hx b/source/NoteSplash.hx new file mode 100644 index 000000000..a06bd024c --- /dev/null +++ b/source/NoteSplash.hx @@ -0,0 +1,38 @@ +package; + +import flixel.FlxG; +import flixel.FlxSprite; +import haxe.io.Path; + +class NoteSplash extends FlxSprite +{ + public function new(x:Float, y:Float, noteData:Int = 0):Void + { + super(x, y); + + frames = Paths.getSparrowAtlas('noteSplashes'); + + animation.addByPrefix('note1-0', 'note impact 1 blue', 24, false); + animation.addByPrefix('note2-0', 'note impact 1 green', 24, false); + animation.addByPrefix('note0-0', 'note impact 1 purple', 24, false); + animation.addByPrefix('note3-0', 'note impact 1 red', 24, false); + animation.addByPrefix('note1-1', 'note impact 2 blue', 24, false); + animation.addByPrefix('note2-1', 'note impact 2 green', 24, false); + animation.addByPrefix('note0-1', 'note impact 2 purple', 24, false); + animation.addByPrefix('note3-1', 'note impact 2 red', 24, false); + + animation.play('note' + noteData + '-' + FlxG.random.int(0, 1)); + animation.curAnim.frameRate += FlxG.random.int(-2, 2); + updateHitbox(); + + offset.set(width * 0.3, height * 0.3); + } + + override function update(elapsed:Float) + { + if (animation.curAnim.finished) + kill(); + + super.update(elapsed); + } +} diff --git a/source/PlayState.hx b/source/PlayState.hx index 0c95bbf53..cc08460ce 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1792,7 +1792,7 @@ class PlayState extends MusicBeatState var endingSong:Bool = false; - private function popUpScore(strumtime:Float):Void + private function popUpScore(strumtime:Float, daNote:Note):Void { var noteDiff:Float = Math.abs(strumtime - Conductor.songPosition); // boyfriend.playAnim('hey'); @@ -1810,20 +1810,33 @@ class PlayState extends MusicBeatState var daRating:String = "sick"; + var isSick:Bool = true; + if (noteDiff > Conductor.safeZoneOffset * 0.9) { daRating = 'shit'; score = 50; + isSick = false; // shitty copypaste on this literally just because im lazy and tired lol! } else if (noteDiff > Conductor.safeZoneOffset * 0.75) { daRating = 'bad'; score = 100; + isSick = false; } else if (noteDiff > Conductor.safeZoneOffset * 0.2) { daRating = 'good'; score = 200; + isSick = false; + } + + if (isSick) + { + var noteSplash:NoteSplash = new NoteSplash(daNote.x, daNote.y, daNote.noteData); + add(noteSplash); + + noteSplash.cameras = [camHUD]; } songScore += score; @@ -2272,7 +2285,7 @@ class PlayState extends MusicBeatState { if (!note.isSustainNote) { - popUpScore(note.strumTime); + popUpScore(note.strumTime, note); combo += 1; } diff --git a/source/ui/SettingsMenu.hx b/source/ui/SettingsMenu.hx new file mode 100644 index 000000000..179ff4100 --- /dev/null +++ b/source/ui/SettingsMenu.hx @@ -0,0 +1,9 @@ +package ui; + +class SettingsMenu extends ui.OptionsState.Page +{ + public function new() + { + super(); + } +} From 27c410cb9dd64bcddeb380c491e9880aeb5ad81d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 26 Mar 2021 05:09:42 -0400 Subject: [PATCH 31/37] cutscene bullshit --- source/NoteSplash.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/NoteSplash.hx b/source/NoteSplash.hx index a06bd024c..0b6295bba 100644 --- a/source/NoteSplash.hx +++ b/source/NoteSplash.hx @@ -26,6 +26,8 @@ class NoteSplash extends FlxSprite updateHitbox(); offset.set(width * 0.3, height * 0.3); + + alpha = 0.75; } override function update(elapsed:Float) From b470cfc83ad146e4a0c4e28977e8dae826b1d2c7 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 26 Mar 2021 20:09:04 -0400 Subject: [PATCH 32/37] preference toggling --- .gitignore | 3 +- hxformat.json | 31 ++++---- source/OptionsMenu_old.hx | 132 ----------------------------------- source/OptionsSubState.hx | 92 ------------------------ source/PlayState.hx | 4 +- source/TitleState.hx | 4 +- source/ui/OptionsState.hx | 6 +- source/ui/PreferencesMenu.hx | 68 ++++++++++++++++++ source/ui/SettingsMenu.hx | 9 --- 9 files changed, 93 insertions(+), 256 deletions(-) delete mode 100644 source/OptionsMenu_old.hx delete mode 100644 source/OptionsSubState.hx create mode 100644 source/ui/PreferencesMenu.hx delete mode 100644 source/ui/SettingsMenu.hx diff --git a/.gitignore b/.gitignore index 7dbb7d607..b15789ba4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ export/ .vscode/ -APIStuff.hx \ No newline at end of file +APIStuff.hx +.DS_STORE diff --git a/hxformat.json b/hxformat.json index 4d31f1457..5f15f3835 100644 --- a/hxformat.json +++ b/hxformat.json @@ -1,16 +1,15 @@ -{ - "lineEnds": { - "leftCurly": "both", - "rightCurly": "both", - "emptyCurly": "break", - "objectLiteralCurly": { - "leftCurly": "after" - } - }, - "sameLine": { - "ifElse": "next", - "doWhile": "next", - "tryBody": "next", - "tryCatch": "next" - } -} +{ + "lineEnds": { + "leftCurly": "both", + "rightCurly": "both", + "objectLiteralCurly": { + "leftCurly": "after" + } + }, + "sameLine": { + "ifElse": "next", + "doWhile": "next", + "tryBody": "next", + "tryCatch": "next" + } +} diff --git a/source/OptionsMenu_old.hx b/source/OptionsMenu_old.hx deleted file mode 100644 index 4ec844323..000000000 --- a/source/OptionsMenu_old.hx +++ /dev/null @@ -1,132 +0,0 @@ -package; - -import Controls.Control; -import flash.text.TextField; -import flixel.FlxG; -import flixel.FlxSprite; -import flixel.addons.display.FlxGridOverlay; -import flixel.group.FlxGroup.FlxTypedGroup; -import flixel.input.keyboard.FlxKey; -import flixel.math.FlxMath; -import flixel.text.FlxText; -import flixel.util.FlxColor; -import lime.utils.Assets; - -class OptionsMenu_old extends MusicBeatState -{ - var selector:FlxText; - var curSelected:Int = 0; - - var controlsStrings:Array = []; - - private var grpControls:FlxTypedGroup; - - override function create() - { - var menuBG:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuDesat')); - controlsStrings = CoolUtil.coolTextFile(Paths.txt('controls')); - menuBG.color = 0xFFea71fd; - menuBG.setGraphicSize(Std.int(menuBG.width * 1.1)); - menuBG.updateHitbox(); - menuBG.screenCenter(); - menuBG.antialiasing = true; - add(menuBG); - - /* - grpControls = new FlxTypedGroup(); - add(grpControls); - - for (i in 0...controlsStrings.length) - { - if (controlsStrings[i].indexOf('set') != -1) - { - var controlLabel:Alphabet = new Alphabet(0, (70 * i) + 30, controlsStrings[i].substring(3) + ': ' + controlsStrings[i + 1], true, false); - controlLabel.isMenuItem = true; - controlLabel.targetY = i; - grpControls.add(controlLabel); - } - // DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !! - } - */ - - super.create(); - - openSubState(new OptionsSubState()); - } - - override function update(elapsed:Float) - { - super.update(elapsed); - - /* - if (controls.ACCEPT) - { - changeBinding(); - } - - if (isSettingControl) - waitingInput(); - else - { - if (controls.BACK) - FlxG.switchState(new MainMenuState()); - if (controls.UP_P) - changeSelection(-1); - if (controls.DOWN_P) - changeSelection(1); - } - */ - } - - function waitingInput():Void - { - if (FlxG.keys.getIsDown().length > 0) - { - // PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxG.keys.getIsDown()[0].ID, null); - } - // PlayerSettings.player1.controls.replaceBinding(Control) - } - - var isSettingControl:Bool = false; - - function changeBinding():Void - { - if (!isSettingControl) - { - isSettingControl = true; - } - } - - function changeSelection(change:Int = 0) - { - NGio.logEvent('Fresh'); - - FlxG.sound.play(Paths.sound('scrollMenu'), 0.4); - - curSelected += change; - - if (curSelected < 0) - curSelected = grpControls.length - 1; - if (curSelected >= grpControls.length) - curSelected = 0; - - // selector.y = (70 * curSelected) + 30; - - var bullShit:Int = 0; - - for (item in grpControls.members) - { - item.targetY = bullShit - curSelected; - bullShit++; - - item.alpha = 0.6; - // item.setGraphicSize(Std.int(item.width * 0.8)); - - if (item.targetY == 0) - { - item.alpha = 1; - // item.setGraphicSize(Std.int(item.width)); - } - } - } -} diff --git a/source/OptionsSubState.hx b/source/OptionsSubState.hx deleted file mode 100644 index 1b5071c74..000000000 --- a/source/OptionsSubState.hx +++ /dev/null @@ -1,92 +0,0 @@ -package; - -import Controls.Control; -import flixel.FlxG; -import flixel.FlxSprite; -import flixel.group.FlxGroup.FlxTypedGroup; -import flixel.text.FlxText; -import flixel.util.FlxColor; -import polymod.Polymod; -#if desktop -import sys.FileSystem; -#end - -class OptionsSubState extends MusicBeatSubstate -{ - var textMenuItems:Array = ['Master Volume', 'Sound Volume', 'Controls', 'Colors', 'Back']; - - var selector:FlxSprite; - var curSelected:Int = 0; - - var grpOptionsTexts:FlxTypedGroup; - - // public static var isDownscroll:Bool = false; - - public function new() - { - super(); - - #if desktop - textMenuItems.push('Mods'); - #end - - grpOptionsTexts = new FlxTypedGroup(); - add(grpOptionsTexts); - - selector = new FlxSprite().makeGraphic(5, 5, FlxColor.RED); - add(selector); - - for (i in 0...textMenuItems.length) - { - var optionText:FlxText = new FlxText(20, 20 + (i * 50), 0, textMenuItems[i], 32); - optionText.ID = i; - grpOptionsTexts.add(optionText); - } - } - - override function update(elapsed:Float) - { - super.update(elapsed); - - if (controls.UI_UP_P) - curSelected -= 1; - - if (controls.UI_DOWN_P) - curSelected += 1; - - if (curSelected < 0) - curSelected = textMenuItems.length - 1; - - if (curSelected >= textMenuItems.length) - curSelected = 0; - - grpOptionsTexts.forEach(function(txt:FlxText) - { - txt.color = FlxColor.WHITE; - - if (txt.ID == curSelected) - txt.color = FlxColor.YELLOW; - }); - - if (controls.BACK) - FlxG.switchState(new MainMenuState()); - - if (controls.ACCEPT) - { - switch (textMenuItems[curSelected]) - { - case "Colors": - FlxG.state.closeSubState(); - - case "Controls": - FlxG.state.closeSubState(); - FlxG.state.openSubState(new ControlsSubState()); - case "Mods": - FlxG.state.closeSubState(); - // FlxG.state.openSubState(new ModdingSubstate()); - case "Back": - FlxG.switchState(new MainMenuState()); - } - } - } -} diff --git a/source/PlayState.hx b/source/PlayState.hx index cc08460ce..c6a9e2fa8 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -1163,9 +1163,7 @@ class PlayState extends MusicBeatState { swagNote.x += FlxG.width / 2; // general offset } - else - { - } + else {} } daBeats += 1; } diff --git a/source/TitleState.hx b/source/TitleState.hx index 3e531bac7..114753464 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -63,7 +63,7 @@ class TitleState extends MusicBeatState PlayerSettings.init(); Highscore.load(); - #if newgrounds + #if ng NGio.init(); #end @@ -297,7 +297,7 @@ class TitleState extends MusicBeatState transitioning = true; // FlxG.sound.music.stop(); - #if newgrounds + #if ng if (!OutdatedSubState.leftState) { NGio.checkVersion(function(version) diff --git a/source/ui/OptionsState.hx b/source/ui/OptionsState.hx index 3459c9b1b..da51df269 100644 --- a/source/ui/OptionsState.hx +++ b/source/ui/OptionsState.hx @@ -12,7 +12,7 @@ import flixel.util.FlxSignal; class OptionsState extends MusicBeatState { var pages = new Map(); - var currentName:PageName = #if newgrounds Options #else Controls #end; + var currentName:PageName = Options; var currentPage(get, never):Page; inline function get_currentPage() @@ -29,6 +29,7 @@ class OptionsState extends MusicBeatState add(menuBG); var options = addPage(Options, new OptionsMenu(false)); + var preferences = addPage(Preferences, new PreferencesMenu()); var controls = addPage(Controls, new ControlsMenu()); var colors = addPage(Colors, new ColorsMenu()); @@ -41,6 +42,7 @@ class OptionsState extends MusicBeatState options.onExit.add(exitToMainMenu); controls.onExit.add(switchPage.bind(Options)); colors.onExit.add(switchPage.bind(Options)); + preferences.onExit.add(switchPage.bind(Options)); #if cpp mods.onExit.add(switchPage.bind(Options)); @@ -172,6 +174,7 @@ class OptionsMenu extends Page super(); add(items = new TextMenuList()); + createItem('preferences', function() switchPage(Preferences)); createItem("controls", function() switchPage(Controls)); createItem('colors', function() switchPage(Colors)); #if cpp @@ -276,4 +279,5 @@ enum PageName Controls; Colors; Mods; + Preferences; } diff --git a/source/ui/PreferencesMenu.hx b/source/ui/PreferencesMenu.hx new file mode 100644 index 000000000..e5afbf9fd --- /dev/null +++ b/source/ui/PreferencesMenu.hx @@ -0,0 +1,68 @@ +package ui; + +import flixel.FlxG; +import ui.AtlasText.AtlasFont; + +class PreferencesMenu extends ui.OptionsState.Page +{ + public static var preferences:Map = new Map(); + + var items:TextMenuList; + + public function new() + { + super(); + add(items = new TextMenuList()); + + createPrefItem('naughtyness', 'censor-naughty', false); + createPrefItem('downscroll', 'downscroll', false); + } + + private function createPrefItem(prefName:String, prefString:String, prefValue:Dynamic):Void + { + items.createItem(100, 100 * items.length, prefName, AtlasFont.Bold, function() + { + preferenceCheck(prefString, prefValue); + + switch (Type.typeof(prefValue).getName()) + { + case 'TBool': + prefToggle(prefString); + + default: + trace('swag'); + } + }); + + trace(Type.typeof(prefValue).getName()); + } + + /** + * Assumes that the preference has already been checked/set? + */ + private function prefToggle(prefName:String) + { + var daSwap:Bool = preferences.get(prefName); + daSwap = !daSwap; + preferences.set(prefName, daSwap); + trace('toggled? ' + preferences.get(prefName)); + } + + override function update(elapsed:Float) + { + super.update(elapsed); + } + + private function preferenceCheck(prefString:String, prefValue:Dynamic):Void + { + if (preferences.get(prefString) == null) + { + preferences.set(prefString, prefValue); + trace('set preference!'); + } + else + { + trace('found preference: ' + preferences.get(prefString)); + } + } +} diff --git a/source/ui/SettingsMenu.hx b/source/ui/SettingsMenu.hx deleted file mode 100644 index 179ff4100..000000000 --- a/source/ui/SettingsMenu.hx +++ /dev/null @@ -1,9 +0,0 @@ -package ui; - -class SettingsMenu extends ui.OptionsState.Page -{ - public function new() - { - super(); - } -} From 105c05f2e26bcba5a085672bfcad26921647b9e7 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 26 Mar 2021 21:22:07 -0400 Subject: [PATCH 33/37] no flashing menu --- source/MainMenuState.hx | 91 +++++++++++++++++------------------- source/TitleState.hx | 3 ++ source/ui/PreferencesMenu.hx | 54 ++++++++++++++++++++- source/ui/TextMenuList.hx | 18 +++---- 4 files changed, 109 insertions(+), 57 deletions(-) diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index 58494cc47..75fab2853 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -1,8 +1,6 @@ package; import NGio; - -import flixel.ui.FlxButton; import flixel.FlxG; import flixel.FlxObject; import flixel.FlxSprite; @@ -14,26 +12,26 @@ import flixel.group.FlxGroup.FlxTypedGroup; import flixel.text.FlxText; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; +import flixel.ui.FlxButton; import flixel.util.FlxColor; import flixel.util.FlxTimer; import lime.app.Application; +import ui.AtlasMenuList; +import ui.MenuList; +import ui.OptionsState; +import ui.PreferencesMenu; +import ui.Prompt; + +using StringTools; #if desktop import Discord.DiscordClient; #end - #if newgrounds import io.newgrounds.NG; import ui.NgPrompt; #end -import ui.AtlasMenuList; -import ui.MenuList; -import ui.OptionsState; -import ui.Prompt; - -using StringTools; - class MainMenuState extends MusicBeatState { var menuItems:MainMenuList; @@ -80,7 +78,8 @@ class MainMenuState extends MusicBeatState magenta.visible = false; magenta.antialiasing = true; magenta.color = 0xFFfd719b; - add(magenta); + if (PreferencesMenu.preferences.get('flashing-menu')) + add(magenta); // magenta.scrollFactor.set(); menuItems = new MainMenuList(); @@ -90,25 +89,23 @@ class MainMenuState extends MusicBeatState { FlxFlicker.flicker(magenta, 1.1, 0.15, false, true); }); - - - - menuItems.enabled = false;// disable for intro - menuItems.createItem('story mode', function () startExitState(new StoryMenuState())); - menuItems.createItem('freeplay', function () startExitState(new FreeplayState())); + + menuItems.enabled = false; // disable for intro + menuItems.createItem('story mode', function() startExitState(new StoryMenuState())); + menuItems.createItem('freeplay', function() startExitState(new FreeplayState())); // addMenuItem('options', function () startExitState(new OptionMenu())); #if CAN_OPEN_LINKS - var hasPopupBlocker = #if web true #else false #end; - menuItems.createItem('donate', selectDonate, hasPopupBlocker); + var hasPopupBlocker = #if web true #else false #end; + menuItems.createItem('donate', selectDonate, hasPopupBlocker); #end - menuItems.createItem('options', function () startExitState(new OptionsState())); + menuItems.createItem('options', function() startExitState(new OptionsState())); // #if newgrounds // if (NGio.isLoggedIn) // menuItems.createItem("logout", selectLogout); // else // menuItems.createItem("login", selectLogin); // #end - + // center vertically var spacing = 160; var top = (FlxG.height - (spacing * (menuItems.length - 1))) / 2; @@ -131,24 +128,24 @@ class MainMenuState extends MusicBeatState super.create(); } - + override function finishTransIn() { super.finishTransIn(); - + menuItems.enabled = true; - + // #if newgrounds // if (NGio.savedSessionFailed) // showSavedSessionFailed(); // #end } - + function onMenuItemChange(selected:MenuItem) { camFollow.setPosition(selected.getGraphicMidpoint().x, selected.getGraphicMidpoint().y); } - + #if CAN_OPEN_LINKS function selectDonate() { @@ -159,23 +156,23 @@ class MainMenuState extends MusicBeatState #end } #end - + #if newgrounds function selectLogin() { openNgPrompt(NgPrompt.showLogin()); } - + function selectLogout() { openNgPrompt(NgPrompt.showLogout()); } - + function showSavedSessionFailed() { openNgPrompt(NgPrompt.showSavedSessionFailed()); } - + /** * Calls openPrompt and redraws the login/logout button * @param prompt @@ -186,16 +183,16 @@ class MainMenuState extends MusicBeatState var onPromptClose = checkLoginStatus; if (onClose != null) { - onPromptClose = function () + onPromptClose = function() { checkLoginStatus(); onClose(); } } - + openPrompt(prompt, onPromptClose); } - + function checkLoginStatus() { var prevLoggedIn = menuItems.has("logout"); @@ -205,20 +202,20 @@ class MainMenuState extends MusicBeatState menuItems.resetItem("logout", "login", selectLogin); } #end - + public function openPrompt(prompt:Prompt, onClose:Void->Void) { menuItems.enabled = false; - prompt.closeCallback = function () + prompt.closeCallback = function() { menuItems.enabled = true; if (onClose != null) onClose(); } - + openSubState(prompt); } - + function startExitState(state:FlxState) { var duration = 0.4; @@ -226,14 +223,14 @@ class MainMenuState extends MusicBeatState { if (menuItems.selectedIndex != item.ID) { - FlxTween.tween(item, {alpha: 0}, duration, { ease: FlxEase.quadOut }); + FlxTween.tween(item, {alpha: 0}, duration, {ease: FlxEase.quadOut}); } else { item.visible = false; } }); - + new FlxTimer().start(duration, function(_) FlxG.switchState(state)); } @@ -254,29 +251,29 @@ class MainMenuState extends MusicBeatState private class MainMenuList extends MenuTypedList { public var atlas:FlxAtlasFrames; - - public function new () + + public function new() { atlas = Paths.getSparrowAtlas('main_menu'); super(Vertical); - } - + public function createItem(x = 0.0, y = 0.0, name:String, callback, fireInstantly = false) { var item = new MainMenuItem(x, y, name, atlas, callback); item.fireInstantly = fireInstantly; item.ID = length; - + return addItem(name, item); } - + override function destroy() { super.destroy(); atlas = null; } } + private class MainMenuItem extends AtlasMenuItem { public function new(x = 0.0, y = 0.0, name, atlas, callback) @@ -284,7 +281,7 @@ private class MainMenuItem extends AtlasMenuItem super(x, y, name, atlas, callback); scrollFactor.set(); } - + override function changeAnim(anim:String) { super.changeAnim(anim); @@ -292,4 +289,4 @@ private class MainMenuItem extends AtlasMenuItem centerOrigin(); offset.copyFrom(origin); } -} \ No newline at end of file +} diff --git a/source/TitleState.hx b/source/TitleState.hx index 114753464..8d31350f8 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -17,6 +17,7 @@ import flixel.util.FlxTimer; import lime.app.Application; import openfl.Assets; import shaderslmfao.ColorSwap; +import ui.PreferencesMenu; using StringTools; @@ -59,6 +60,8 @@ class TitleState extends MusicBeatState super.create(); + PreferencesMenu.initPrefs(); + FlxG.save.bind('funkin', 'ninjamuffin99'); PlayerSettings.init(); Highscore.load(); diff --git a/source/ui/PreferencesMenu.hx b/source/ui/PreferencesMenu.hx index e5afbf9fd..b82300519 100644 --- a/source/ui/PreferencesMenu.hx +++ b/source/ui/PreferencesMenu.hx @@ -1,7 +1,11 @@ package ui; import flixel.FlxG; +import flixel.FlxSprite; +import flixel.group.FlxGroup; +import flixel.util.FlxColor; import ui.AtlasText.AtlasFont; +import ui.TextMenuList.TextMenuItem; class PreferencesMenu extends ui.OptionsState.Page { @@ -9,6 +13,8 @@ class PreferencesMenu extends ui.OptionsState.Page var items:TextMenuList; + var checkboxes:Array = []; + public function new() { super(); @@ -16,6 +22,14 @@ class PreferencesMenu extends ui.OptionsState.Page createPrefItem('naughtyness', 'censor-naughty', false); createPrefItem('downscroll', 'downscroll', false); + createPrefItem('flashing menu', 'flashing-menu', true); + } + + public static function initPrefs():Void + { + preferenceCheck('censor-naughty', false); + preferenceCheck('downscroll', false); + preferenceCheck('flashing-menu', true); } private function createPrefItem(prefName:String, prefString:String, prefValue:Dynamic):Void @@ -34,9 +48,24 @@ class PreferencesMenu extends ui.OptionsState.Page } }); + switch (Type.typeof(prefValue).getName()) + { + case 'TBool': + createCheckbox(prefString); + + default: + trace('swag'); + } + trace(Type.typeof(prefValue).getName()); } + function createCheckbox(prefString:String) + { + var checkbox:CheckboxThingie = new CheckboxThingie(0, 100 * items.length, preferences.get(prefString)); + add(checkbox); + } + /** * Assumes that the preference has already been checked/set? */ @@ -53,7 +82,7 @@ class PreferencesMenu extends ui.OptionsState.Page super.update(elapsed); } - private function preferenceCheck(prefString:String, prefValue:Dynamic):Void + private static function preferenceCheck(prefString:String, prefValue:Dynamic):Void { if (preferences.get(prefString) == null) { @@ -66,3 +95,26 @@ class PreferencesMenu extends ui.OptionsState.Page } } } + +class CheckboxThingie extends FlxSprite +{ + public var daValue(default, set):Bool = false; + + public function new(x:Float, y:Float, daValue:Bool = false) + { + super(x, y); + + this.daValue = daValue; + makeGraphic(50, 50, FlxColor.WHITE); + } + + function set_daValue(value:Bool):Bool + { + if (value) + color = FlxColor.GREEN; + else + color = FlxColor.RED; + + return value; + } +} diff --git a/source/ui/TextMenuList.hx b/source/ui/TextMenuList.hx index d1c617b17..c507ae864 100644 --- a/source/ui/TextMenuList.hx +++ b/source/ui/TextMenuList.hx @@ -5,11 +5,11 @@ import ui.MenuList; class TextMenuList extends MenuTypedList { - public function new (navControls:NavControls = Vertical, ?wrapMode) + public function new(navControls:NavControls = Vertical, ?wrapMode) { super(navControls, wrapMode); } - + public function createItem(x = 0.0, y = 0.0, name:String, font:AtlasFont = Bold, callback, fireInstantly = false) { var item = new TextMenuItem(x, y, name, font, callback); @@ -20,7 +20,7 @@ class TextMenuList extends MenuTypedList class TextMenuItem extends TextTypedMenuItem { - public function new (x = 0.0, y = 0.0, name:String, font:AtlasFont = Bold, callback) + public function new(x = 0.0, y = 0.0, name:String, font:AtlasFont = Bold, callback) { super(x, y, new AtlasText(0, 0, name, font), name, callback); setEmptyBackground(); @@ -29,12 +29,12 @@ class TextMenuItem extends TextTypedMenuItem class TextTypedMenuItem extends MenuTypedItem { - public function new (x = 0.0, y = 0.0, label:T, name:String, callback) + public function new(x = 0.0, y = 0.0, label:T, name:String, callback) { super(x, y, label, name, callback); } - - override function setItem(name:String, ?callback:Void -> Void) + + override function setItem(name:String, ?callback:Void->Void) { if (label != null) { @@ -43,14 +43,14 @@ class TextTypedMenuItem extends MenuTypedItem width = label.width; height = label.height; } - + super.setItem(name, callback); } - + override function set_label(value:T):T { super.set_label(value); setItem(name, callback); return value; } -} \ No newline at end of file +} From c7097eae6222c701d8d8ac3b5ca438028fce6563 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 26 Mar 2021 21:28:04 -0400 Subject: [PATCH 34/37] no camera zoom shit --- source/PlayState.hx | 21 +++++++++++++-------- source/ui/PreferencesMenu.hx | 7 +++++++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/source/PlayState.hx b/source/PlayState.hx index c6a9e2fa8..86d2e87f1 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -39,6 +39,7 @@ import openfl.display.BlendMode; import openfl.display.StageQuality; import openfl.filters.ShaderFilter; import shaderslmfao.ColorSwap; +import ui.PreferencesMenu; using StringTools; @@ -2451,16 +2452,20 @@ class PlayState extends MusicBeatState wiggleShit.update(Conductor.crochet); // HARDCODING FOR MILF ZOOMS! - if (curSong.toLowerCase() == 'milf' && curBeat >= 168 && curBeat < 200 && camZooming && FlxG.camera.zoom < 1.35) - { - FlxG.camera.zoom += 0.015; - camHUD.zoom += 0.03; - } - if (camZooming && FlxG.camera.zoom < 1.35 && curBeat % 4 == 0) + if (PreferencesMenu.getPref('camera-zoom')) { - FlxG.camera.zoom += 0.015; - camHUD.zoom += 0.03; + if (curSong.toLowerCase() == 'milf' && curBeat >= 168 && curBeat < 200 && camZooming && FlxG.camera.zoom < 1.35) + { + FlxG.camera.zoom += 0.015; + camHUD.zoom += 0.03; + } + + if (camZooming && FlxG.camera.zoom < 1.35 && curBeat % 4 == 0) + { + FlxG.camera.zoom += 0.015; + camHUD.zoom += 0.03; + } } iconP1.setGraphicSize(Std.int(iconP1.width + 30)); diff --git a/source/ui/PreferencesMenu.hx b/source/ui/PreferencesMenu.hx index b82300519..fd72eed47 100644 --- a/source/ui/PreferencesMenu.hx +++ b/source/ui/PreferencesMenu.hx @@ -23,6 +23,12 @@ class PreferencesMenu extends ui.OptionsState.Page createPrefItem('naughtyness', 'censor-naughty', false); createPrefItem('downscroll', 'downscroll', false); createPrefItem('flashing menu', 'flashing-menu', true); + createPrefItem('Camera Zooming on Beat', 'camera-zoom', true); + } + + public static function getPref(pref:String):Dynamic + { + return preferences.get(pref); } public static function initPrefs():Void @@ -30,6 +36,7 @@ class PreferencesMenu extends ui.OptionsState.Page preferenceCheck('censor-naughty', false); preferenceCheck('downscroll', false); preferenceCheck('flashing-menu', true); + preferenceCheck('camera-zoom', true); } private function createPrefItem(prefName:String, prefString:String, prefValue:Dynamic):Void From 32a73e7d7035dbf30864519b0de513f4e2560452 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 26 Mar 2021 21:33:16 -0400 Subject: [PATCH 35/37] checkbox fix in progress --- source/ui/PreferencesMenu.hx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/ui/PreferencesMenu.hx b/source/ui/PreferencesMenu.hx index fd72eed47..2fa44f478 100644 --- a/source/ui/PreferencesMenu.hx +++ b/source/ui/PreferencesMenu.hx @@ -13,7 +13,7 @@ class PreferencesMenu extends ui.OptionsState.Page var items:TextMenuList; - var checkboxes:Array = []; + var checkboxes:Array = []; public function new() { @@ -69,7 +69,8 @@ class PreferencesMenu extends ui.OptionsState.Page function createCheckbox(prefString:String) { - var checkbox:CheckboxThingie = new CheckboxThingie(0, 100 * items.length, preferences.get(prefString)); + var checkbox:CheckboxThingie = new CheckboxThingie(0, 100 * (items.length - 1), preferences.get(prefString)); + checkboxes.push(checkbox); add(checkbox); } @@ -81,6 +82,7 @@ class PreferencesMenu extends ui.OptionsState.Page var daSwap:Bool = preferences.get(prefName); daSwap = !daSwap; preferences.set(prefName, daSwap); + checkboxes[items.selectedIndex].daValue = daSwap; trace('toggled? ' + preferences.get(prefName)); } @@ -115,6 +117,11 @@ class CheckboxThingie extends FlxSprite makeGraphic(50, 50, FlxColor.WHITE); } + override function update(elapsed:Float) + { + super.update(elapsed); + } + function set_daValue(value:Bool):Bool { if (value) From 17545fbc86f9f4f90c8b735abece4eba70e34507 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 27 Mar 2021 16:11:14 -0700 Subject: [PATCH 36/37] reverted the ng thingies --- source/TitleState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/TitleState.hx b/source/TitleState.hx index 8d31350f8..2f9c3a7f1 100644 --- a/source/TitleState.hx +++ b/source/TitleState.hx @@ -66,7 +66,7 @@ class TitleState extends MusicBeatState PlayerSettings.init(); Highscore.load(); - #if ng + #if newgrounds NGio.init(); #end @@ -300,7 +300,7 @@ class TitleState extends MusicBeatState transitioning = true; // FlxG.sound.music.stop(); - #if ng + #if newgrounds if (!OutdatedSubState.leftState) { NGio.checkVersion(function(version) From 00bfd2670394a95af4b5375cff0d7f8d2d678531 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 27 Mar 2021 20:01:53 -0700 Subject: [PATCH 37/37] checkbox thingie hehe --- source/ui/PreferencesMenu.hx | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/source/ui/PreferencesMenu.hx b/source/ui/PreferencesMenu.hx index 2fa44f478..eadd31ec0 100644 --- a/source/ui/PreferencesMenu.hx +++ b/source/ui/PreferencesMenu.hx @@ -107,27 +107,43 @@ class PreferencesMenu extends ui.OptionsState.Page class CheckboxThingie extends FlxSprite { - public var daValue(default, set):Bool = false; + public var daValue(default, set):Bool; public function new(x:Float, y:Float, daValue:Bool = false) { super(x, y); + frames = Paths.getSparrowAtlas('checkboxThingie'); + animation.addByPrefix('static', 'Check Box unselected', 24, false); + animation.addByPrefix('checked', 'Check Box selecting animation', 24, false); + + antialiasing = true; + + setGraphicSize(Std.int(width * 0.7)); + updateHitbox(); + this.daValue = daValue; - makeGraphic(50, 50, FlxColor.WHITE); } override function update(elapsed:Float) { super.update(elapsed); + + switch (animation.curAnim.name) + { + case 'static': + offset.set(); + case 'checked': + offset.set(17, 70); + } } function set_daValue(value:Bool):Bool { if (value) - color = FlxColor.GREEN; + animation.play('checked', true); else - color = FlxColor.RED; + animation.play('static'); return value; }