From 2a09f026daa616abc058d58193b33e6f4b3db18c Mon Sep 17 00:00:00 2001 From: TechnikTil Date: Sun, 24 May 2026 19:45:43 -0600 Subject: [PATCH] Completely rewrite Menu Core to be more `class` focused Signed-off-by: TechnikTil --- {shared/images => images}/mc_base.png | Bin {shared/images => images}/mc_bg.png | Bin scripts/MenuSwitchState.hxc | 207 +++++++++++++++ scripts/data/BaseMenu.hxc | 51 ++++ scripts/data/MenuRegistry.hxc | 106 ++++++++ scripts/menus/FunkinMenu.hxc | 26 ++ scripts/menus/LegacyMenu.hxc | 40 +++ scripts/menus/MenuCore.hxc | 55 ---- scripts/modules/MC_MainMenuStateHook.hxc | 53 ---- scripts/modules/MC_TitleStateHook.hxc | 34 --- scripts/modules/MenuCoreBackwardsCompat.hxc | 33 +++ scripts/modules/MenuCoreData.hxc | 54 ---- scripts/modules/MenuCoreHandler.hxc | 43 ++++ scripts/states/MenuSwitch.hxc | 271 -------------------- 14 files changed, 506 insertions(+), 467 deletions(-) rename {shared/images => images}/mc_base.png (100%) rename {shared/images => images}/mc_bg.png (100%) create mode 100644 scripts/MenuSwitchState.hxc create mode 100644 scripts/data/BaseMenu.hxc create mode 100644 scripts/data/MenuRegistry.hxc create mode 100644 scripts/menus/FunkinMenu.hxc create mode 100644 scripts/menus/LegacyMenu.hxc delete mode 100644 scripts/menus/MenuCore.hxc delete mode 100644 scripts/modules/MC_MainMenuStateHook.hxc delete mode 100644 scripts/modules/MC_TitleStateHook.hxc create mode 100644 scripts/modules/MenuCoreBackwardsCompat.hxc delete mode 100644 scripts/modules/MenuCoreData.hxc create mode 100644 scripts/modules/MenuCoreHandler.hxc delete mode 100644 scripts/states/MenuSwitch.hxc diff --git a/shared/images/mc_base.png b/images/mc_base.png similarity index 100% rename from shared/images/mc_base.png rename to images/mc_base.png diff --git a/shared/images/mc_bg.png b/images/mc_bg.png similarity index 100% rename from shared/images/mc_bg.png rename to images/mc_bg.png diff --git a/scripts/MenuSwitchState.hxc b/scripts/MenuSwitchState.hxc new file mode 100644 index 0000000..6c94fe3 --- /dev/null +++ b/scripts/MenuSwitchState.hxc @@ -0,0 +1,207 @@ +package kade.menucore; + +import funkin.ui.FullScreenScaleMode; +import funkin.graphics.FunkinSprite; +import funkin.ui.title.TitleState; +import funkin.group.FunkinGroup; +import funkin.audio.FunkinSound; +import funkin.ui.MusicBeatState; +import funkin.util.MathUtil; +import funkin.ui.AtlasText; + +#if FEATURE_TOUCH_CONTROLS +import funkin.util.TouchUtil; +import funkin.util.SwipeUtil; +#end + +import flixel.addons.transition.FlxTransitionableState; +import flixel.util.FlxColor; +import flixel.math.FlxMath; +import flixel.text.FlxText; + +class MenuSwitchState extends MusicBeatState +{ + var menuItems:Array; + var menuGroup:FunkinGroup; + var curSelected:Int = 0; + + var arrowLeft:FunkinSprite; + var arrowRight:FunkinSprite; + + var topRightText:FlxText; + var nameText:AtlasText; + + override public function create():Void + { + menuItems = MenuRegistry.instance.listEntryIds(); + curSelected = Math.max(menuItems.indexOf(BaseMenu.currentMenu), 0); + + FunkinSound.playMusic('menu-switch', { + startingVolume: 0.0, + overrideExisting: true, + restartTrack: false + }); + FlxG.sound.music.fadeIn(3); + + FlxTransitionableState.skipNextTransIn = true; + FlxTransitionableState.skipNextTransOut = true; + + var bg:FunkinSprite = FunkinSprite.create(0, 0, 'mc_bg'); + bg.setGraphicSize(Std.int(FlxG.width * 1.2)); + bg.updateHitbox(); + bg.screenCenter(); + bg.zIndex = 0; + add(bg); + + var chooseBlackBar:FunkinSprite = new FunkinSprite(0, 0); + chooseBlackBar.makeSolidColor(FlxG.width, 60, FlxColor.BLACK); + chooseBlackBar.zIndex = 10; + add(chooseBlackBar); + + var blackBar:FunkinSprite = new FunkinSprite(0, 0); + blackBar.makeSolidColor(FlxG.width, 185, FlxColor.BLACK); + blackBar.screenCenter(0x10); + blackBar.zIndex = 10; + add(blackBar); + + topRightText = new FlxText(0, 15, FlxG.width / 2, "WEED"); + topRightText.setFormat(Paths.font("vcr.ttf"), 35, FlxColor.WHITE, "right"); + topRightText.x = (FlxG.width - topRightText.width) - 6; + topRightText.zIndex = 20; + add(topRightText); + + final textX:Float = Math.max(6, FullScreenScaleMode.gameNotchSize.x); + var choose:FlxText = new FlxText(textX, 2, FlxG.width, "CHOOSE THE VERSION"); + choose.setFormat(Paths.font("vcr.ttf"), 55, FlxColor.WHITE); + choose.zIndex = 20; + add(choose); + + menuGroup = new FunkinGroup(0, 0, 0, false, false); + menuGroup.scale.set(0.8, 0.8); + menuGroup.zIndex = 30; + add(menuGroup); + + nameText = new AtlasText(0, 0, 'cock', 'bold'); + nameText.x = (FlxG.width - nameText.getWidth()) / 2; + nameText.y = FlxG.height - nameText.height - 25; + nameText.zIndex = 40; + add(nameText); + + arrowLeft = FunkinSprite.createSparrow(FlxG.width / 8, 0, 'freeplay/freeplaySelector/freeplaySelector'); + arrowLeft.animation.addByPrefix('shine', 'arrow pointer loop', 24); + arrowLeft.animation.play('shine'); + arrowLeft.x -= arrowLeft.width / 2; + arrowLeft.screenCenter(0x10); + arrowLeft.zIndex = 50; + add(arrowLeft); + + arrowRight = FunkinSprite.createSparrow(FlxG.width - (FlxG.width / 8), 0, 'freeplay/freeplaySelector/freeplaySelector'); + arrowRight.animation.addByPrefix('shine', 'arrow pointer loop', 24); + arrowRight.animation.play('shine'); + arrowRight.x -= arrowRight.width / 2; + arrowRight.screenCenter(0x10); + arrowRight.flipX = true; + arrowRight.zIndex = 50; + add(arrowRight); + + super.create(); + + #if FEATURE_TOUCH_CONTROLS + addBackButton(FlxG.width - 230, FlxG.height - 200, FlxColor.WHITE, () -> back(), 0.3); + #end + + populateMenuItems(); + + changeSelection(0); + menuGroup.x = menuGroup.localX; + } + + function populateMenuItems():Void + { + for (i in 0...menuItems.length) + { + var menu:BaseMenu = MenuRegistry.instance.fetchEntry(menuItems[i]); + + var sprite:FunkinSprite = new FunkinSprite(0, 0); + sprite.loadGraphic(menu.getImage()); + sprite.updateHitbox(); + + sprite.localX = (FlxG.width - sprite.width) / 2; + sprite.localY = (FlxG.height - sprite.height) / 2; + sprite.localX += FlxG.width * i; + + menuGroup.add(sprite); + } + } + + override public function update(elapsed:Float):Void + { + var leftP:Bool = controls.UI_LEFT_P; + var rightP:Bool = controls.UI_RIGHT_P; + var acceptP:Bool = controls.ACCEPT_P; + var backP:Bool = controls.BACK_P; + + #if FEATURE_TOUCH_CONTROLS + if (TouchUtil.pressAction(arrowLeft) || SwipeUtil.justSwipedLeft) + { + leftP = true; + } + else if (TouchUtil.pressAction(arrowRight) || SwipeUtil.justSwipedRight) + { + rightP = true; + } + else if (TouchUtil.pressAction(menuGroup.getChildAt(curSelected))) + { + acceptP = true; + } + #end + + if (leftP) + { + changeSelection(-1); + } + else if (rightP) + { + changeSelection(1); + } + else if (acceptP) + { + select(); + } + else if (backP) + { + back(); + } + + menuGroup.x = MathUtil.smoothLerpPrecision(menuGroup.x, menuGroup.localX, elapsed, 0.307); + super.update(elapsed); + } + + public function changeSelection(change:Int = 0):Void + { + curSelected = FlxMath.wrap(curSelected + change, 0, menuItems.length - 1); + menuGroup.localX = -FlxG.width * curSelected; + + if (change != 0) FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4); + + var menu:BaseMenu = MenuRegistry.instance.fetchEntry(menuItems[curSelected]); + + nameText.text = menu.getName(); + nameText.x = (FlxG.width - nameText.getWidth()) / 2; + + topRightText.text = menu.getDescription(); + } + + public function select():Void + { + var menu:BaseMenu = MenuRegistry.instance.fetchEntry(menuItems[curSelected]); + menu.onSelected(); + + BaseMenu.currentMenu = menu.id; + } + + public function back():Void + { + FlxG.switchState(() -> new TitleState()); + } +} \ No newline at end of file diff --git a/scripts/data/BaseMenu.hxc b/scripts/data/BaseMenu.hxc new file mode 100644 index 0000000..95181a7 --- /dev/null +++ b/scripts/data/BaseMenu.hxc @@ -0,0 +1,51 @@ +package kade.menucore.data; + +import funkin.ui.mainmenu.MainMenuState; +import funkin.modding.ModStore; + +class BaseMenu +{ + public static var currentMenu(get, set):String; + + static function get_currentMenu():String + { + return ModStore.get('MC_CurrentMenu'); + } + + static function set_currentMenu(value:String):String + { + ModStore.stores.set('MC_CurrentMenu', value); + return value; + } + + /** + * The internal ID for this menu. + */ + public final id:String; + + public function new(ID:String) + { + id = ID; + } + + public function getName():String + { + throw 'getName() must be overriden!'; + } + + public function getDescription():String + { + throw 'getDescription() must be overriden!'; + } + + public function getImage():FlxGraphicAsset + { + throw 'getImage() must be overriden!'; + } + + public function onSelected():Void + { + // By default, in case the custom menus come later! + FlxG.switchState(() -> new MainMenuState()); + } +} \ No newline at end of file diff --git a/scripts/data/MenuRegistry.hxc b/scripts/data/MenuRegistry.hxc new file mode 100644 index 0000000..bc6d976 --- /dev/null +++ b/scripts/data/MenuRegistry.hxc @@ -0,0 +1,106 @@ +package kade.menucore.data; + +import funkin.util.SortUtil; +import haxe.ds.StringMap; + +using funkin.util.AnsiUtil; + +class MenuRegistry +{ + public static var instance:MenuRegistry; + + var entries:StringMap; + + public function new() + { + entries = new StringMap(); + } + + public function loadEntries():Void + { + var scriptedClasses:Array = BaseMenu.listScriptClasses(); + scriptedClasses.remove('kade.menucore.menus.LegacyMenu'); + + log(' INFO '.info() + ' Parsing ${scriptedClasses.length} scripted entries...'); + + for (entryCls in scriptedClasses) + { + var menu:BaseMenu = null; + + try + { + menu = BaseMenu.scriptInit(entryCls, 'unknown'); + } + catch(e:Exception) {} + + if (menu != null) + { + registerEntry(menu); + } + else + { + log('Failed to create scripted entry (${entryCls})'); + } + } + } + + public function registerEntry(menu:BaseMenu):Void + { + entries.set(menu.id, menu); + log('Successfully registered entry (${menu.toString()} = ${menu.id})'); + } + + /** + * Retrieve a list of all entry IDs in this registry. + * @return The list of entry IDs. + */ + public function listEntryIds():Array + { + var toReturn:Array = [for (i in entries.keys()) i]; + toReturn.sort((a, b) -> SortUtil.defaultsThenAlphabetically(listBaseGameEntryIds(), a, b)); + return toReturn; + } + + /** + * Count the number of entries in this registry. + * @return The number of entries. + */ + public function countEntries():Int + { + return listEntryIds().length; + } + + /** + * Return whether the registry has successfully parsed an entry with the given ID. + * @param id The ID of the entry. + * @return `true` if the entry exists, `false` otherwise. + */ + public function hasEntry(id:String):Bool + { + return entries.exists(id); + } + + /** + * Fetch an entry by its ID. + * @param id The ID of the entry to fetch. + * @return The entry, or `null` if it does not exist. + */ + public function fetchEntry(id:String):BaseMenu + { + return entries.get(id); + } + + /** + * A list of all entries included in the base game. + * @return Array + */ + public function listBaseGameEntryIds():Array + { + return ['funkin']; + } + + static function log(message:String):Void + { + trace(' MENUCORE '.bold().bg_orange() + ' $message'); + } +} \ No newline at end of file diff --git a/scripts/menus/FunkinMenu.hxc b/scripts/menus/FunkinMenu.hxc new file mode 100644 index 0000000..382e7de --- /dev/null +++ b/scripts/menus/FunkinMenu.hxc @@ -0,0 +1,26 @@ +package kade.menucore.menus; + +import funkin.Paths; + +class FunkinMenu extends BaseMenu +{ + public function new() + { + super('funkin'); + } + + override public function getName():String + { + return 'Funkin'; + } + + override public function getDescription():String + { + return "Friday Night Funkin'"; + } + + override public function getImage():FlxGraphicAsset + { + return Paths.image('mc_base'); + } +} \ No newline at end of file diff --git a/scripts/menus/LegacyMenu.hxc b/scripts/menus/LegacyMenu.hxc new file mode 100644 index 0000000..f6f504b --- /dev/null +++ b/scripts/menus/LegacyMenu.hxc @@ -0,0 +1,40 @@ +package kade.menucore.menus; + +import funkin.Paths; + +class LegacyMenu extends BaseMenu +{ + final name:String; + final imageKey:String; + final description:String; + final state:FlxState; + + public function new(name:String, imageKey:String, description:String, state:FlxState) + { + super('legacy($name)'); + this.name = name; + this.imageKey = imageKey; + this.description = description; + this.state = state; + } + + override public function getName():String + { + return name; + } + + override public function getDescription():String + { + return description; + } + + override public function getImage():FlxGraphicAsset + { + return Paths.image(imageKey); + } + + override public function onSelected():Void + { + FlxG.switchState(state); + } +} \ No newline at end of file diff --git a/scripts/menus/MenuCore.hxc b/scripts/menus/MenuCore.hxc deleted file mode 100644 index 7e0070d..0000000 --- a/scripts/menus/MenuCore.hxc +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Base game icon script. - */ - -package kade.menucore; - -import funkin.ui.mainmenu.MainMenuState; - -import funkin.modding.module.Module; -import flixel.FlxState; - -import funkin.modding.module.ModuleHandler; - -class MenuCore extends Module { - var modName = "Funkin"; - var modDescription = "Friday Night Funkin'"; - var modAssetKey = "mc_base"; - - var modState = null; - - public function new() { - // Priority is set to 2 here. - super("MenuCore", 2); - } - - public function addVersion() - { - var mcHandle = ModuleHandler.getModule("MC_Data"); - if (mcHandle == null) { - trace("MenuCore: MC_Data not found!"); - return; - } - - if (mcHandle.versions.indexOf(modName) != -1) { - // Already added - return; - } - - modState = new MainMenuState(); - - mcHandle.addVersion(modName, modAssetKey, modDescription, modState); - } - - public override function onStateChangeBegin(event:StateChangeScriptEvent):Void { - super.onStateChangeBegin(event); - - addVersion(); - } - - public override function onCreate(event):Void { - super.onCreate(event); - - addVersion(); - } -} \ No newline at end of file diff --git a/scripts/modules/MC_MainMenuStateHook.hxc b/scripts/modules/MC_MainMenuStateHook.hxc deleted file mode 100644 index 7d1fb6c..0000000 --- a/scripts/modules/MC_MainMenuStateHook.hxc +++ /dev/null @@ -1,53 +0,0 @@ -/** - * MenuCore module for managing menu states and transitions. - */ - -package kade.menucore; - -import kade.menucore.states.MenuSwitch; - -import funkin.modding.module.ModuleHandler; -import funkin.modding.module.Module; -import funkin.ui.mainmenu.MainMenuState; - -class MC_MainMenuStateHook extends Module { - public var shouldAllowMainMenu:Bool = false; - public var isTransitioning:Bool = false; - public var once:Bool = true; - - public function new():Void { - super("MC_MainMenuStateHook", 1, { - state: MainMenuState - }); - } - - public override function onStateChangeEnd(event:StateChangeScriptEvent):Void { - super.onStateChangeEnd(event); - - if (shouldAllowMainMenu) - return; - - if (isTransitioning || FlxG.sound.music == null) - return; - - shouldAllowMainMenu = true; - - trace("MC_MainMenuStateHook: Intercepted MainMenuState creation, switching to MenuSwitch instead"); - - var mcHandle = ModuleHandler.getModule("MC_Data"); - if (mcHandle != null) { - mcHandle.dump(); - } - - // So basically the idea here is that TitleState only transitions into the MainMenu. - // Which means we can theoretically "hook" into it by overriding this method and canceling the change. - // Thus, we can have a custom menu and change into other custom menus! - - event.eventCanceled = true; - - isTransitioning = true; - - FlxG.switchState(new MenuSwitch()); - } - -} \ No newline at end of file diff --git a/scripts/modules/MC_TitleStateHook.hxc b/scripts/modules/MC_TitleStateHook.hxc deleted file mode 100644 index 9608943..0000000 --- a/scripts/modules/MC_TitleStateHook.hxc +++ /dev/null @@ -1,34 +0,0 @@ -/** - * MenuCore module for managing menu states and transitions. - */ - -package kade.menucore; - -import funkin.modding.module.ModuleHandler; -import funkin.modding.module.Module; -import funkin.ui.title.TitleState; - -class MC_TitleStateHook extends Module { - public var shouldAllowMainMenu:Bool = false; - public var isTransitioning:Bool = false; - public var once:Bool = true; - - public function new():Void { - super("MC_TitleStateHook", 1, { - state: TitleState - }); - } - - public override function onStateCreate(event):Void { - super.onStateCreate(event); - - var mainMenuStateHook = ModuleHandler.getModule("MC_MainMenuStateHook"); - if (mainMenuStateHook != null) { - trace("MC_TitleStateHook: Resetting MainMenuStateHook variables"); - mainMenuStateHook.shouldAllowMainMenu = false; - mainMenuStateHook.isTransitioning = false; - mainMenuStateHook.once = true; - } - } - -} \ No newline at end of file diff --git a/scripts/modules/MenuCoreBackwardsCompat.hxc b/scripts/modules/MenuCoreBackwardsCompat.hxc new file mode 100644 index 0000000..164ce00 --- /dev/null +++ b/scripts/modules/MenuCoreBackwardsCompat.hxc @@ -0,0 +1,33 @@ +package kade.menucore.modules; + +import funkin.modding.module.Module; + +class MenuCoreBackwardsCompat extends Module +{ + public function new() + { + super('MC_Data'); + } + + public var versions(get, never):Array; + function get_versions():Array + { + return [for (menu in getMenus()) menu.getName()]; + } + + function getMenus():Array + { + return [for (id in MenuRegistry.instance.listEntryIds()) MenuRegistry.instance.fetchEntry(id)]; + } + + /** + * Here for backwards compatibility. Does not do anything though. + */ + public function dump():Void {} + + public function addVersion(name:String, imageKey:String, description:String, state:FlxState):Void + { + var menu:LegacyMenu = new LegacyMenu(name, imageKey, description, state); + MenuRegistry.instance.registerEntry(menu); + } +} \ No newline at end of file diff --git a/scripts/modules/MenuCoreData.hxc b/scripts/modules/MenuCoreData.hxc deleted file mode 100644 index a57fe92..0000000 --- a/scripts/modules/MenuCoreData.hxc +++ /dev/null @@ -1,54 +0,0 @@ -/** - * MenuCore module for managing core data. - */ - -package kade.menucore; - -import funkin.modding.module.Module; -import funkin.ui.AtlasText; - -import flixel.FlxSprite; -import flixel.FlxState; - -class MC_Data extends Module { - public var versionImages:Array = []; - // Atlas texts are below the images - public var atlasTexts:Array = []; - // Version descriptions are the top right text - public var versionDescriptions:Array = []; - public var versions:Array = new Array(); - public var states:Array = new Array(); - - public function dump():Void { - versions = []; - states = []; - versionImages = []; - atlasTexts = []; - versionDescriptions = []; - trace("MC_Data: Dumped all versions"); - } - - public function addVersion(name:String, imageKey:String, description:String, state:FlxState):Void { - trace("MC_Data: Adding version " + name + " with image key " + imageKey + " and description " + description); - versions.push(name); - states.push(state); - versionImages.push(imageKey); - atlasTexts.push(new AtlasText(0,0,name, "bold")); - versionDescriptions.push(description); - } - - public override function onCreate(event):Void { - super.onCreate(event); - - versionImages = []; - atlasTexts = []; - versionDescriptions = []; - versions = new Array(); - states = new Array(); - } - - public function new():Void { - super("MC_Data", 1); - } - -} \ No newline at end of file diff --git a/scripts/modules/MenuCoreHandler.hxc b/scripts/modules/MenuCoreHandler.hxc new file mode 100644 index 0000000..ca7870e --- /dev/null +++ b/scripts/modules/MenuCoreHandler.hxc @@ -0,0 +1,43 @@ +package kade.menucore.modules; + +import funkin.modding.module.Module; +import funkin.ui.title.TitleState; +import flixel.math.FlxMath; + +using funkin.util.AnsiUtil; + +class MenuCoreHandler extends Module +{ + var transitioning:Bool = false; + + public function new() + { + super('MenuCore', FlxMath.MIN_VALUE_INT); + MenuRegistry.instance = new MenuRegistry(); + } + + override public function onCreate(event:ScriptEvent):Void + { + MenuRegistry.instance.loadEntries(); + + super.onCreate(event); + } + + override public function onStateChangeEnd(event:StateChangeScriptEvent):Void + { + super.onStateChangeEnd(event); + transitioning = false; + } + + override public function onStateChangeBegin(event:StateChangeScriptEvent):Void + { + super.onStateChangeBegin(event); + if (!Std.isOfType(FlxG.state, TitleState) || !FlxG.state.transitioning || transitioning) return; + + trace(' MENUCORE '.bold().bg_orange() + ' User is moving to the Main Menu!'); + event.cancel(); + transitioning = true; + + FlxG.switchState(() -> new MenuSwitchState()); + } +} \ No newline at end of file diff --git a/scripts/states/MenuSwitch.hxc b/scripts/states/MenuSwitch.hxc deleted file mode 100644 index d5d68ac..0000000 --- a/scripts/states/MenuSwitch.hxc +++ /dev/null @@ -1,271 +0,0 @@ -/** - * MenuCore Menu Switch State - * A state for switching between different menu versions. - */ - -package kade.menucore.states; - -import funkin.ui.title.TitleState; -import funkin.ui.mainmenu.MainMenuState; -import funkin.ui.FullScreenScaleMode; -import funkin.util.TouchUtil; -import funkin.util.SwipeUtil; -import funkin.ui.MusicBeatState; -import funkin.audio.FunkinSound; -import flixel.FlxG; -import flixel.text.FlxText; -import flixel.FlxSprite; -import funkin.graphics.FunkinSprite; -import funkin.Paths; -import flixel.FlxState; -import Array; -import Math; -import Std; - -import funkin.modding.module.ModuleHandler; - -import funkin.ui.AtlasText; - -class MenuSwitch extends MusicBeatState { - var mcHandle = null; - - var bg:FlxSprite; - var chooseBlackBar:FlxText; - var choose:FlxText; - - var topRightText:FlxText; - - var blackBar:FlxSprite; - - var leftSelect:FunkinSprite; - var rightSelect:FunkinSprite; - - var selected:Int = 0; - var visualSelect:Float = 0; - - public var versionImages:Array = []; - // Atlas texts are below the images - public var atlasTexts:Array = []; - // Version descriptions are the top right text - public var versionDescriptions:Array = []; - public var versions:Array = new Array(); - public var states:Array = new Array(); - - var backMobile:Bool = false; - - public function new():Void { - super(); - - mcHandle = ModuleHandler.getModule("MC_Data"); - - if (mcHandle == null) { - trace("MenuSwitch: MC_Data not found!"); - return; - } - - versions = mcHandle.versions; - states = mcHandle.states; - - atlasTexts = mcHandle.atlasTexts; - versionDescriptions = mcHandle.versionDescriptions; - - bg = new FlxSprite(); - bg.loadGraphic(Paths.image("mc_bg","shared")); - bg.setGraphicSize(Std.int(FlxG.width * 1.2)); - bg.updateHitbox(); - bg.screenCenter(); - bg.zIndex = 0; - add(bg); - - chooseBlackBar = new FlxSprite(0, 0); - chooseBlackBar.makeGraphic(FlxG.width, 60, 0xFF000000); - chooseBlackBar.zIndex = 10; - add(chooseBlackBar); - - choose = new FlxText(Math.max(FullScreenScaleMode.gameNotchSize.x, 6), 2, FlxG.width, "CHOOSE THE VERSION"); - choose.setFormat(Paths.font("vcr.ttf"), 55, 0xFFFFFFFF); - choose.zIndex = 20; - add(choose); - - topRightText = new FlxText(0, 15, FlxG.width / 2, ""); - topRightText.setFormat(Paths.font("vcr.ttf"), 35, 0xFFFFFFFF, "right"); - topRightText.x = (FlxG.width - topRightText.width - Math.max(FullScreenScaleMode.gameNotchSize.x, 10)); - topRightText.zIndex = 30; - add(topRightText); - - // Middle black bar of bg - blackBar = new FlxSprite(0, 0); - blackBar.makeGraphic(FlxG.width, 185, 0xFF000000); - blackBar.y = FlxG.height / 2 - blackBar.height / 2; - blackBar.zIndex = 40; - add(blackBar); - - leftSelect = FunkinSprite.createSparrow(0,0,"freeplay/freeplaySelector/freeplaySelector"); - leftSelect.animation.addByPrefix('shine', 'arrow pointer loop', 24); - leftSelect.animation.play("shine", true); - leftSelect.x = FlxG.width / 8 - leftSelect.width / 2; - leftSelect.y = FlxG.height / 2 - leftSelect.height / 2; - leftSelect.zIndex = 70; - add(leftSelect); - - rightSelect = FunkinSprite.createSparrow(0,0,"freeplay/freeplaySelector/freeplaySelector"); - rightSelect.animation.addByPrefix('shine', 'arrow pointer loop', 24); - rightSelect.animation.play("shine", true); - rightSelect.x = FlxG.width - FlxG.width / 8 - rightSelect.width / 2; - rightSelect.y = FlxG.height / 2 - rightSelect.height / 2; - rightSelect.flipX = true; - rightSelect.zIndex = 80; - add(rightSelect); - } - - var addedimages:Array = []; - var addedtexts:Array = []; - - public function populateVersions():Void { - // Remove all version images first - - for (image in addedimages) { - remove(image); - } - - for (text in addedtexts) { - remove(text); - } - - versionImages = new Array(); - - for (imageKey in mcHandle.versionImages) { - var sprite:FlxSprite = new FlxSprite().loadGraphic(Paths.image(imageKey, "shared")); - sprite.scale.set(0.8, 0.8); - versionImages.push(sprite); - } - - for (i in 0...versions.length) { - var versionName = versions[i]; - var versionImage = versionImages[i]; - var versionText = atlasTexts[i]; - - versionImage.y = (FlxG.height / 2 - versionImage.height / 2) + 20; - versionText.y = versionImage.y + versionImage.height - 25; - - versionImage.x = (FlxG.width / 2 - versionImage.width / 2) + (i - visualSelect) * versionImage.width * 1.2; - versionText.x = versionImage.x + (versionImage.width / 2 - versionText.width / 2); - - versionImage.zIndex = 50; - versionText.zIndex = 60; - - add(versionImage); - add(versionText); - - addedimages.push(versionImage); - addedtexts.push(versionText); - } - - topRightText.text = versionDescriptions[selected]; - topRightText.x = (FlxG.width - topRightText.width - Math.max(FullScreenScaleMode.gameNotchSize.x, 10)); - } - - public override function create():Void { - super.create(); - - var mainMenuHandle = ModuleHandler.getModule("MC_MainMenuStateHook"); - - if (mainMenuHandle == null) { - trace("MenuSwitch: MC_MainMenuStateHook not found!"); - return; - } - - mainMenuHandle.isTransitioning = false; - - populateVersions(); - - if (FlxG.onMobile) { - addBackButton(FlxG.width - 230, FlxG.height - 200, 0xFFFFFFFF, () -> { - backMobile = true; - }, 0.3); - } - - FunkinSound.playMusic("menu-switch", - { - startingVolume: 0, - overrideExisting: true, - restartTrack: true, - loop: true, - }); - - FlxG.sound.music.fadeIn(3); - - trace("MenuSwitch: Created Menu Switch State"); - } - - public override function update(elapsed:Float):Void { - super.update(elapsed); - - var back:Bool = controls.BACK || backMobile; - var accept:Bool = controls.ACCEPT; - var left:Bool = controls.UI_LEFT_P; - - var right:Bool = controls.UI_RIGHT_P; - - if (FlxG.onMobile) { - if (TouchUtil.pressAction(versionImages[selected])) - accept = true; - - if (TouchUtil.pressAction(leftSelect) || SwipeUtil.justSwipedLeft) - left = true; - - if (TouchUtil.pressAction(rightSelect) || SwipeUtil.justSwipedRight) - right = true; - } - - if (left || right) { - if (left) - selected--; - else - selected++; - - if (selected < 0) - selected = versions.length - 1; - else if (selected >= versions.length) - selected = 0; - - FunkinSound.playOnce(Paths.sound("scrollMenu"), 0.5); - - topRightText.text = versionDescriptions[selected]; - topRightText.x = (FlxG.width - topRightText.width - Math.max(FullScreenScaleMode.gameNotchSize.x, 10)); - } - else if (back) { - trace("MenuSwitch: ESCAPE pressed, going back to TitleState"); - var titleState = new TitleState(); - FlxG.switchState(titleState); - } - else if (accept) { - // TODO: Make this an animation or something - //FunkinSound.playOnce(Paths.sound("confirmMenu"), 0.5); - var toState = states[selected]; - trace("MenuSwitch: ENTER pressed, switching to " + toState); - FlxG.switchState(toState); - } - - visualSelect += (selected - visualSelect) * 0.2; - - for (i in 0...versionImages.length) { - var versionImage = versionImages[i]; - var versionText = atlasTexts[i]; - - // Start at half opacity, then go to full opacity when selected - // Also start at 0.9 scale, and go to 1.0 scale when selected - var targetAlpha = (i == Std.int(Math.round(visualSelect))) ? 1.0 : 0.5; - var targetScale = (i == Std.int(Math.round(visualSelect))) ? 0.9 : 0.7; - - versionText.alpha = versionImage.alpha; - versionText.scale.set(versionImage.scale.x, versionImage.scale.y); - - versionImage.x = (FlxG.width / 2 - versionImage.width / 2) + (i - visualSelect) * versionImage.width * 1.2; - versionText.x = versionImage.x + (versionImage.width / 2 - versionText.width / 2); - - versionImage.alpha += (targetAlpha - versionImage.alpha) * 0.2 * 60 * elapsed; - versionImage.scale.set(versionImage.scale.x + (targetScale - versionImage.scale.x) * 0.2 * 60 * elapsed, versionImage.scale.y + (targetScale - versionImage.scale.y) * 0.2 * 60 * elapsed); - } - } -} \ No newline at end of file