diff --git a/assets/images/editors/bgs/default.png b/assets/images/editors/bgs/default.png new file mode 100644 index 00000000..ba4754ed Binary files /dev/null and b/assets/images/editors/bgs/default.png differ diff --git a/assets/languages/en/Editors.xml b/assets/languages/en/Editors.xml index 86ca86ac..e62add53 100644 --- a/assets/languages/en/Editors.xml +++ b/assets/languages/en/Editors.xml @@ -46,7 +46,9 @@ Press ACCEPT to edit the chart for the selected difficulty. Select a difficulty to continue. New Difficulty + Press ACCEPT to create a new chart difficulty. New Song + Press ACCEPT to create a new song. @@ -435,6 +437,11 @@ Creating New Character Character Name $* Required$ Character Image File $* Required$ + + + Creating Character: Error! + The character you are trying to create already exists, if you would like to override it delete the character first! + @@ -442,6 +449,7 @@ Press ACCEPT to edit this typeface. New Typeface + Press ACCEPT to create a new typeface. Select a typeface to edit @@ -554,6 +562,11 @@ Stage Info Stage Name Stage Path + + + Creating Stage: Error! + The stage you are trying to create alreadly exists, if you would like to override it delete the stage first! + diff --git a/source/funkin/editors/DebugOptions.hx b/source/funkin/editors/DebugOptions.hx index 0f3dc9fd..e0293319 100644 --- a/source/funkin/editors/DebugOptions.hx +++ b/source/funkin/editors/DebugOptions.hx @@ -1,18 +1,57 @@ package funkin.editors; import funkin.backend.utils.NativeAPI; -import funkin.options.OptionsScreen; import funkin.options.TreeMenu; +import funkin.options.TreeMenuScreen; import funkin.options.type.*; class DebugOptions extends TreeMenu { - public override function create() { + var bg:FlxSprite; + + override function create() { super.create(); + UIState.setResolutionAware(); + + add(bg = new FlxSprite().loadAnimatedGraphic(Paths.image('menus/menuBGBlue'))); + bg.antialiasing = true; + bg.scrollFactor.set(); + updateBG(); + + addMenu(new TreeMenuScreen('DebugOptions.title', 'DebugOptions.desc')); FlxG.camera.fade(0xFF000000, 0.5, true); } + + public function updateBG() { + var scaleX:Float = FlxG.width / bg.width; + var scaleY:Float = FlxG.height / bg.height; + bg.scale.x = bg.scale.y = Math.max(scaleX, scaleY) * 1.15; + bg.screenCenter(); + } + + override function onResize(width:Int, height:Int) { + super.onResize(width, height); + if (!UIState.resolutionAware) return; + + updateBG(); + } } -class DebugOptionsScreen extends OptionsScreen { +class DebugOptionsScreen extends TreeMenuScreen { + public function new() { + super('DebugOptions.title', 'DebugOptions.desc', 'DebugOptions.'); + #if windows + add(new TextOption(getNameID("showConsole"), getDescID("showConsole"), () -> NativeAPI.allocConsole())); + #end + add(new Checkbox(getNameID("editorsResizable"), getDescID("editorsResizable"), "editorsResizable")); + add(new Checkbox(getNameID("bypassEditorsResize"), getDescID("bypassEditorsResize"), "bypassEditorsResize")); + add(new Checkbox(getNameID("editorSFX"), getDescID("editorSFX"), "editorSFX")); + add(new Checkbox(getNameID("editorPrettyPrint"), getDescID("editorPrettyPrint"), "editorPrettyPrint")); + add(new Checkbox(getNameID("intensiveBlur"), getDescID("intensiveBlur"), "intensiveBlur")); + add(new Checkbox(getNameID("charterAutoSaves"), getDescID("charterAutoSaves"), "charterAutoSaves")); + add(new NumOption(getNameID("charterAutoSaveTime"), getDescID("charterAutoSaveTime"), 60, 60*10, 1, "charterAutoSaveTime")); + add(new NumOption(getNameID("charterAutoSaveWarningTime"), getDescID("charterAutoSaveWarningTime"), 0, 15, 1, "charterAutoSaveWarningTime")); + add(new Checkbox(getNameID("charterAutoSavesSeparateFolder"), getDescID("charterAutoSavesSeparateFolder"), "charterAutoSavesSeparateFolder")); + } } \ No newline at end of file diff --git a/source/funkin/editors/EditorTreeMenu.hx b/source/funkin/editors/EditorTreeMenu.hx index b4904866..afe6dd18 100644 --- a/source/funkin/editors/EditorTreeMenu.hx +++ b/source/funkin/editors/EditorTreeMenu.hx @@ -1,28 +1,25 @@ package funkin.editors; import flixel.addons.display.FlxBackdrop; -import funkin.menus.MainMenuState; -import funkin.options.*; +import funkin.options.type.OptionType; -class EditorTreeMenu extends TreeMenu { +class EditorTreeMenu extends funkin.options.TreeMenu { public var bg:FlxBackdrop; public var bgType:String = "default"; public var bgMovement:FlxPoint = new FlxPoint(); - public var main:OptionsScreen; - - public override function create() { + override function create() { super.create(); - UIState.setResolutionAware(); - FlxG.camera.fade(0xFF000000, 0.5, true); + } - bg = new FlxBackdrop(); + override function createPost() { + super.createPost(); + add(bg = new FlxBackdrop()); bg.loadGraphic(Paths.image('editors/bgs/${bgType}')); bg.antialiasing = true; setBackgroundRotation(-5); - add(bg); } public inline function setBackgroundRotation(rotation:Float) { @@ -30,11 +27,47 @@ class EditorTreeMenu extends TreeMenu { bg.velocity.set(85, 0).degrees = bg.rotation; } - public override function exit() { - FlxG.switchState(new MainMenuState()); + override function exit() { + FlxG.switchState(new funkin.menus.MainMenuState()); } - public function onMenuChange() { - + override function update(elapsed:Float) { + super.update(elapsed); + + bg.colorTransform.redOffset = lerp(bg.colorTransform.redOffset, 0, 0.0625); + bg.colorTransform.greenOffset = lerp(bg.colorTransform.greenOffset, 0, 0.0625); + bg.colorTransform.blueOffset = lerp(bg.colorTransform.blueOffset, 0, 0.0625); + bg.colorTransform.redMultiplier = lerp(bg.colorTransform.redMultiplier, 1, 0.0625); + bg.colorTransform.greenMultiplier = lerp(bg.colorTransform.greenMultiplier, 1, 0.0625); + bg.colorTransform.blueMultiplier = lerp(bg.colorTransform.blueMultiplier, 1, 0.0625); + } + + override function menuChanged() @:privateAccess { + super.menuChanged(); + if (previousMenus.length > 0) return; // selected a sub-menu + + var prev = tree[tree.length - 2]; + if (prev == null || prev.curOption == null || !(prev.curOption is OptionType)) return; + + // small flashbang + var color = cast(prev.curOption, OptionType).editorFlashColor; + bg.colorTransform.redOffset = 0.25 * color.red; + bg.colorTransform.greenOffset = 0.25 * color.green; + bg.colorTransform.blueOffset = 0.25 * color.blue; + bg.colorTransform.redMultiplier = FlxMath.lerp(1, color.redFloat, 0.25); + bg.colorTransform.greenMultiplier = FlxMath.lerp(1, color.greenFloat, 0.25); + bg.colorTransform.blueMultiplier = FlxMath.lerp(1, color.blueFloat, 0.25); + } +} + +class EditorTreeMenuScreen extends funkin.options.TreeMenuScreen { + public function new(name:String, desc:String, ?prefix:String, ?objects:Array, + ?newButton:String, ?newButtonDesc:String, ?newCallback:Void->Void) + { + super(name, desc, prefix, objects); + if (newCallback != null) { + insert(0, new funkin.options.type.NewOption(getID(newButton), getID(newButtonDesc), newCallback)); + curSelected = 1; + } } } \ No newline at end of file diff --git a/source/funkin/editors/alphabet/AlphabetSelection.hx b/source/funkin/editors/alphabet/AlphabetSelection.hx index 1b8155ee..9d937a83 100644 --- a/source/funkin/editors/alphabet/AlphabetSelection.hx +++ b/source/funkin/editors/alphabet/AlphabetSelection.hx @@ -1,51 +1,35 @@ package funkin.editors.alphabet; +import haxe.io.Path; import haxe.xml.Access; import funkin.game.Character; -import funkin.options.OptionsScreen; -import funkin.options.type.IconOption; +import funkin.editors.EditorTreeMenu; import funkin.options.type.NewOption; import funkin.options.type.TextOption; import funkin.options.type.OptionType; -import haxe.io.Path; -class AlphabetSelection extends EditorTreeMenu -{ - inline function translate(id:String, ?args:Array) - return TU.translate("editor.alphabet.selection." + id, args); - - public override function create() - { - bgType = "charter"; +class AlphabetSelection extends EditorTreeMenu { + override function create() { super.create(); + DiscordUtil.call("onEditorTreeLoaded", ["Alphabet Editor"]); + addMenu(new AlphabetSelectionScreen()); + } +} + +class AlphabetSelectionScreen extends EditorTreeMenuScreen { + public function new() { + super('editor.alphabet.name', 'editor.alphabet.selection.desc', 'editor.alphabet.selection', 'newTypeface', 'newTypefaceDesc', () -> { + parent.openSubState(new UIWarningSubstate(translate('warnings.notImplemented-title'), translate('warnings.notImplemented-body'), [ + {label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}} + ])); + }); var modsList:Array = []; - for(file in Paths.getFolderContent('data/alphabet/', true, BOTH)) // mods ? MODS : BOTH + for (file in Paths.getFolderContent('data/alphabet/', true, BOTH)) // mods ? MODS : BOTH if (Path.extension(file) == "xml") modsList.push(CoolUtil.getFilename(file)); - var list:Array = [ - for (typeface in modsList) - new AlphabetIconOption(typeface, translate("acceptTypeface"), typeface, function() { - FlxG.switchState(new AlphabetEditor(typeface)); - }) - ]; - - var newChar = translate("newTypeface"); - list.insert(0, new NewOption(newChar, newChar, function() { - openSubState(new UIWarningSubstate(translate("warnings.notImplemented-title"), translate("warnings.notImplemented-body"), [ - {label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: function(t) {}} - ])); - })); - - main = new OptionsScreen(TU.translate("editor.alphabet.name"), translate("desc"), list); - - DiscordUtil.call("onEditorTreeLoaded", ["Alphabet Editor"]); - } - - override function createPost() { - super.createPost(); - - main.changeSelection(1); + for (typeface in modsList) + add(new AlphabetIconOption(typeface, getID('acceptTypeface'), typeface, () -> FlxG.switchState(new AlphabetEditor(typeface)))); } } @@ -57,7 +41,7 @@ class AlphabetIconOption extends TextOption { var xml = Xml.parse(Assets.getText(Paths.xml('alphabet/$typeface'))).firstElement(); var spritesheet = null; - for(node in xml.elements()) { + for (node in xml.elements()) { if (node.nodeName == "spritesheet") { spritesheet = node.firstChild().nodeValue; break; @@ -73,14 +57,14 @@ class AlphabetIconOption extends TextOption { iconSpr.frames = Paths.getFrames(spritesheet); iconSpr.antialiasing = true; var frameToUse = iconSpr.frames.frames[0]; - for(frame in iconSpr.frames.frames) { + for (frame in iconSpr.frames.frames) { if (frame.name.toUpperCase().startsWith("A")) { frameToUse = frame; break; } } iconSpr.frame = frameToUse; - if(useColorOffsets) { + if (useColorOffsets) { iconSpr.colorTransform.color = -1; } iconSpr.setPosition(90 - iconSpr.width - 20, (__text.height - iconSpr.height) / 2); diff --git a/source/funkin/editors/character/CharacterSelection.hx b/source/funkin/editors/character/CharacterSelection.hx index 9f009ccb..1b9d2d70 100644 --- a/source/funkin/editors/character/CharacterSelection.hx +++ b/source/funkin/editors/character/CharacterSelection.hx @@ -1,81 +1,69 @@ package funkin.editors.character; import haxe.xml.Printer; -import funkin.editors.ui.UIImageExplorer.ImageSaveData; import funkin.game.Character; -import funkin.options.OptionsScreen; +import funkin.editors.ui.UIImageExplorer.ImageSaveData; +import funkin.editors.EditorTreeMenu; import funkin.options.type.IconOption; import funkin.options.type.NewOption; import funkin.options.type.TextOption; import funkin.options.type.OptionType; -import funkin.backend.assets.ModsFolder; -class CharacterSelection extends EditorTreeMenu -{ - inline function translate(id:String, ?args:Array) - return TU.translate("characterSelection." + id, args); +class CharacterSelection extends EditorTreeMenu { + override function create() { + super.create(); + DiscordUtil.call("onEditorTreeLoaded", ["Character Editor"]); + addMenu(new CharacterSelectionScreen()); + } +} +class CharacterSelectionScreen extends EditorTreeMenuScreen { public var modsList:Array = []; - public override function create() - { - bgType = "charter"; - super.create(); + public function new() { + super('editor.character.name', 'characterSelection.desc', 'characterSelection.', 'newCharacter', 'newCharacterDesc', () -> { + parent.openSubState(new CharacterCreationScreen(createCharacter)); + }); var isMods:Bool = true; modsList = Character.getList(true, true); - if(modsList.length == 0) { + if (modsList.length == 0) { modsList = Character.getList(false, true); isMods = false; } - function generateList(modsList:Array, isMods:Bool, folderPath:String = ""):Array { - var list:Array = []; + function generateList(modsList:Array, isMods:Bool, folderPath:String = ""):Array { + var list:Array = []; - for(char in modsList) { - if(char.endsWith("/")) { + for (char in modsList) { + if (char.endsWith("/")) { var folderName = CoolUtil.getFilename(char.substr(0, char.length-1)); - list.push(new TextOption(folderName + " >", translate("acceptFolder"), function() { + list.push(new TextOption(folderName, getID('acceptFolder'), ' >', () -> { var newModsList = Character.getList(isMods, true, char); - var newList:Array = generateList(newModsList, isMods, folderPath + folderName + "/"); - optionsTree.add(new OptionsScreen(folderPath + folderName, translate("desc-folder", [folderPath + folderName + "/"]), newList)); + var newList:Array = generateList(newModsList, isMods, folderPath + folderName + "/"); + parent.addMenu(new EditorTreeMenuScreen(folderPath + folderName, translate('desc-folder', [folderPath + folderName + "/"]), newList)); + })); + } + else { + list.push(new IconOption(char, getID('acceptCharacter'), Character.getIconFromCharName(folderPath + char, char), () -> { + FlxG.switchState(new CharacterEditor(folderPath + char)); })); - } else { - list.push(new IconOption(char, translate("acceptCharacter"), Character.getIconFromCharName(folderPath + char, char), - function() { - FlxG.switchState(new CharacterEditor(folderPath + char)); - }) - ); } } - list.insert(0, new NewOption(translate("newCharacter"), translate("newCharacterDesc"), function() { - openSubState(new CharacterCreationScreen(createCharacter)); - })); - return list; } - var list = generateList(modsList, isMods); - - main = new OptionsScreen(TU.translate("editor.character.name"), translate("desc"), list); - - DiscordUtil.call("onEditorTreeLoaded", ["Character Editor"]); - } - - override function createPost() { - super.createPost(); - - main.changeSelection(1); + for (o in generateList(modsList, isMods)) add(o); } public function createCharacter(name:String, imageSaveData:ImageSaveData, xml:Xml) { var characterAlreadyExists:Bool = modsList.contains(name); if (characterAlreadyExists) { - openSubState(new UIWarningSubstate("Creating Character: Error!", "The character you are trying to create already exists, if you would like to override it delete the character first!", [ - {label: "Ok", color: 0xFFFF0000, onClick: function(t) {}} + parent.openSubState(new UIWarningSubstate(TU.translate('characterCreationScreen.warning.char-exists-title'), TU.translate('characterCreationScreen.warning.char-exists-body'), [ + {label: TU.translate('editor.ok'), color: 0xFFFF0000, onClick: (t) -> {}} ])); return; } @@ -88,11 +76,10 @@ class CharacterSelection extends EditorTreeMenu UIImageExplorer.saveFilesGlobal(imageSaveData, '${Paths.getAssetsRoot()}/images/characters'); // Add to Menu >:D - var option:IconOption = new IconOption(name, "Press ACCEPT to edit this character.", Character.getIconFromCharName(name), - function() { - FlxG.switchState(new CharacterEditor(name)); - } - ); - optionsTree.members[optionsTree.members.length-1].insert(1, option); + var option:IconOption = new IconOption(name, getID('acceptCharacter'), Character.getIconFromCharName(name), () -> { + FlxG.switchState(new CharacterEditor(name)); + }); + + insert(1, option); } } \ No newline at end of file diff --git a/source/funkin/editors/charter/CharterSelection.hx b/source/funkin/editors/charter/CharterSelection.hx index 467817d7..fda0f1c3 100644 --- a/source/funkin/editors/charter/CharterSelection.hx +++ b/source/funkin/editors/charter/CharterSelection.hx @@ -1,118 +1,83 @@ package funkin.editors.charter; +import flixel.util.FlxColor; import funkin.backend.chart.Chart; -import funkin.backend.chart.ChartData.ChartMetaData; import funkin.backend.chart.ChartData; -import funkin.backend.system.framerate.Framerate; -import funkin.editors.EditorTreeMenu; import funkin.editors.charter.SongCreationScreen.SongCreationData; +import funkin.editors.EditorTreeMenu; import funkin.menus.FreeplayState.FreeplaySonglist; -import funkin.options.*; import funkin.options.type.*; -import funkin.options.type.NewOption; import haxe.Json; using StringTools; class CharterSelection extends EditorTreeMenu { - public var freeplayList:FreeplaySonglist; - public var curSong:ChartMetaData; - public override function create() { - bgType = "charter"; - + override function create() { super.create(); + DiscordUtil.call("onEditorTreeLoaded", ["Chart Editor"]); + addMenu(new CharterSelectionScreen()); + bgType = 'charter'; + } +} - Framerate.offset.y = 60; +class CharterSelectionScreen extends EditorTreeMenuScreen { + public var freeplayList:FreeplaySonglist; + public var songList:Array = []; + public var curSong:ChartMetaData; + inline public function makeChartOption(d:String, name:String):TextOption { + return new TextOption(d, getID('acceptDifficulty'), () -> FlxG.switchState(new Charter(name, d))); + } + + public function makeSongOption(s:ChartMetaData):IconOption { + songList.push(s.name.toLowerCase()); + + var opt = new IconOption(s.name, getID('acceptSong'), s.icon, () -> { + curSong = s; + + var screen = new EditorTreeMenuScreen(s.name, getID('selectDifficulty'), [ + for (d in s.difficulties) if (d != '') makeChartOption(d, s.name) + ]); + + #if sys + screen.insert(0, new NewOption(getID('newDifficulty'), getID('newDifficultyDesc'), () -> { + parent.openSubState(new ChartCreationScreen(saveChart)); + })); + screen.curSelected = 1; + #end + + parent.addMenu(screen); + }); + opt.suffix = ' >'; + opt.color = s.color.getDefault(FlxColor.WHITE); + + return opt; + } + + public function new() { + super('editor.chart.name', 'charterSelection.desc', 'charterSelection.', 'newSong', 'newSongDesc', () -> { + parent.openSubState(new SongCreationScreen(saveSong)); + }); freeplayList = FreeplaySonglist.get(false); - var list:Array = [ - for(s in freeplayList.songs) new EditorIconOption(s.name, TU.translate("charterSelection.acceptSong"), s.icon, function() { - curSong = s; - var list:Array = [ - for(d in s.difficulties) if (d != "") - new TextOption(d, TU.translate("charterSelection.acceptDifficulty"), function() { - FlxG.switchState(new Charter(s.name, d)); - }) - ]; - #if sys - var newDiff = TU.translate("charterSelection.newDifficulty"); - list.push(new NewOption(newDiff, newDiff, function() { - FlxG.state.openSubState(new ChartCreationScreen(saveChart)); - })); - #end - optionsTree.add(new OptionsScreen(s.name, TU.translate("charterSelection.selectDifficulty"), list)); - }, s.color.getDefault(0xFFFFFFFF)) - ]; - - #if sys - var newSong = TU.translate("charterSelection.newSong"); - list.insert(0, new NewOption(newSong, newSong, function() { - FlxG.state.openSubState(new SongCreationScreen(saveSong)); - })); - #end - - main = new OptionsScreen(TU.translate("editor.chart.name"), TU.translate("charterSelection.desc"), list); - - DiscordUtil.call("onEditorTreeLoaded", ["Chart Editor"]); - } - - override function createPost() { - super.createPost(); - - main.changeSelection(1); - } - - public override function update(elapsed:Float) { - super.update(elapsed); - - bg.colorTransform.redOffset = lerp(bg.colorTransform.redOffset, 0, 0.0625); - bg.colorTransform.greenOffset = lerp(bg.colorTransform.greenOffset, 0, 0.0625); - bg.colorTransform.blueOffset = lerp(bg.colorTransform.blueOffset, 0, 0.0625); - bg.colorTransform.redMultiplier = lerp(bg.colorTransform.redMultiplier, 1, 0.0625); - bg.colorTransform.greenMultiplier = lerp(bg.colorTransform.greenMultiplier, 1, 0.0625); - bg.colorTransform.blueMultiplier = lerp(bg.colorTransform.blueMultiplier, 1, 0.0625); - } - - public override function onMenuChange() { - super.onMenuChange(); - if (optionsTree.members.length > 1) { // selected a song - if(main != null) { - var opt = main.members[main.curSelected]; - if(opt is EditorIconOption) { - var opt:EditorIconOption = cast opt; - - // small flashbang - var color = opt.flashColor; - bg.colorTransform.redOffset = 0.25 * color.red; - bg.colorTransform.greenOffset = 0.25 * color.green; - bg.colorTransform.blueOffset = 0.25 * color.blue; - bg.colorTransform.redMultiplier = FlxMath.lerp(1, color.redFloat, 0.25); - bg.colorTransform.greenMultiplier = FlxMath.lerp(1, color.greenFloat, 0.25); - bg.colorTransform.blueMultiplier = FlxMath.lerp(1, color.blueFloat, 0.25); - } - } - } + for (i => s in freeplayList.songs) add(makeSongOption(s)); } #if sys public function saveSong(creation:SongCreationData, ?callback:String -> SongCreationData -> Void) { - var songAlreadyExists:Bool = [for (s in freeplayList.songs) s.name.toLowerCase()].contains(creation.meta.name.toLowerCase()); - + var songAlreadyExists:Bool = songList.contains(creation.meta.name.toLowerCase()); if (songAlreadyExists) { - openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.song-exists-title"), TU.translate("chartCreation.warnings.song-exists-body"), [ - {label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: function(t) {}}, + parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.song-exists-title"), TU.translate("chartCreation.warnings.song-exists-body"), [ + {label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}}, ])); return; } - // Paths - var songsDir:String = '${Paths.getAssetsRoot()}/songs/'; - var songFolder:String = '$songsDir${creation.meta.name}'; + var songFolder:String = '${Paths.getAssetsRoot()}/songs/${creation.meta.name}'; #if sys // Make Directories - sys.FileSystem.createDirectory(songFolder); + CoolUtil.addMissingFolders(songFolder); sys.FileSystem.createDirectory('$songFolder/song'); sys.FileSystem.createDirectory('$songFolder/charts'); @@ -125,52 +90,30 @@ class CharterSelection extends EditorTreeMenu { if (creation.oppVocals != null) sys.io.File.saveBytes('$songFolder/song/Voices-Opponent.${Flags.SOUND_EXT}', creation.oppVocals); #end - if (callback != null) - callback(songFolder, creation); - - var option = new EditorIconOption(creation.meta.name, TU.translate("charterSelection.acceptSong"), creation.meta.icon, function() { - curSong = creation.meta; - var list:Array = [ - for(d in creation.meta.difficulties) - if (d != "") new TextOption(d, TU.translate("charterSelection.acceptDifficulty"), function() { - FlxG.switchState(new Charter(creation.meta.name, d)); - }) - ]; - var newDiff = TU.translate("charterSelection.newDifficulty"); - list.push(new NewOption(newDiff, newDiff, function() { - FlxG.state.openSubState(new ChartCreationScreen(saveChart)); - })); - optionsTree.insert(1, new OptionsScreen(creation.meta.name, TU.translate("charterSelection.selectDifficulty"), list)); - }, creation.meta.color.getDefault(0xFFFFFFFF)); + if (callback != null) callback(songFolder, creation); // Add to List freeplayList.songs.insert(0, creation.meta); - main.insert(1, option); + insert(1, makeSongOption(creation.meta)); } public function saveChart(name:String, data:ChartData) { var difficultyAlreadyExists:Bool = curSong.difficulties.contains(name); - if (difficultyAlreadyExists) { - openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.chart-exists-title"), TU.translate("chartCreation.warnings.chart-exists-body"), [ - {label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: function(t) {}}, + parent.openSubState(new UIWarningSubstate(TU.translate("chartCreation.warnings.chart-exists-title"), TU.translate("chartCreation.warnings.chart-exists-body"), [ + {label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}}, ])); return; } - // Paths var songFolder:String = '${Paths.getAssetsRoot()}/songs/${curSong.name}'; // Save Files CoolUtil.safeSaveFile('$songFolder/charts/${name}.json', Json.stringify(data, Flags.JSON_PRETTY_PRINT)); // Add to List - // duplicated code, todo: fix this curSong.difficulties.push(name); - var option = new TextOption(name, TU.translate("charterSelection.acceptDifficulty"), function() { - FlxG.switchState(new Charter(curSong.name, name)); - }); - optionsTree.members[optionsTree.members.length-1].insert(optionsTree.members[optionsTree.members.length-1].length-1, option); + parent.tree.last().insert(parent.tree.last().length - 1, makeChartOption(name, curSong.name)); // Add to Meta var meta = Json.parse(sys.io.File.getContent('$songFolder/meta.json')); diff --git a/source/funkin/editors/stage/StageSelection.hx b/source/funkin/editors/stage/StageSelection.hx index b78aebc3..418e0190 100644 --- a/source/funkin/editors/stage/StageSelection.hx +++ b/source/funkin/editors/stage/StageSelection.hx @@ -1,46 +1,47 @@ package funkin.editors.stage; import funkin.editors.stage.StageCreationScreen.StageCreationData; +import funkin.editors.EditorTreeMenu; import funkin.game.Stage; -import funkin.options.OptionsScreen; import funkin.options.type.NewOption; import funkin.options.type.OptionType; import funkin.options.type.TextOption; -class StageSelection extends EditorTreeMenu -{ +using StringTools; + +class StageSelection extends EditorTreeMenu { + override function create() { + super.create(); + DiscordUtil.call("onEditorTreeLoaded", ["Stage Editor"]); + addMenu(new StageSelectionScreen()); + } +} + +class StageSelectionScreen extends EditorTreeMenuScreen { public var stages:Array = []; - public override function create() - { - bgType = "charter"; - super.create(); + public function makeStageOption(stage:String):TextOption { + return new TextOption(stage, getID('acceptStage'), () -> { + FlxG.switchState(new StageEditor(stage)); + }); + } + + public function new() { + super('editor.stage.name', 'stageSelection.desc', 'stageSelection.', 'newStage', 'acceptNewStage', () -> { + parent.openSubState(new StageCreationScreen(saveStage)); + }); var modsList:Array = Stage.getList(true, true); - - var list:Array = [ - for (stage in (modsList.length == 0 ? Stage.getList(false, true) : modsList)) { - stages.push(stage); - new TextOption(stage, TU.translate("stageSelection.acceptStage"), - function() { - FlxG.switchState(new StageEditor(stage)); - }); - } - ]; - - list.insert(0, new NewOption(TU.translate("stageSelection.newStage"), TU.translate("stageSelection.acceptNewStage"), function() { - FlxG.state.openSubState(new StageCreationScreen(saveStage)); - })); - - main = new OptionsScreen(TU.translate("editor.stage.name"), TU.translate("stageSelection.desc"), list); - - DiscordUtil.call("onEditorTreeLoaded", ["Stage Editor"]); + for (stage in (modsList.length == 0 ? Stage.getList(false, true) : modsList)) { + stages.push(stage.toLowerCase()); + add(makeStageOption(stage)); + } } public function saveStage(creation:StageCreationData) { - if ([for (s in stages) s.toLowerCase()].contains(creation.name.toLowerCase())) { - openSubState(new UIWarningSubstate("Creating Stage: Error!", "The stage you are trying to create alreadly exists, if you would like to override it delete the stage first!", [ - {label: "Ok", color: 0xFFFF0000, onClick: function(t) {}} + if (stages.contains(creation.name.toLowerCase())) { + parent.openSubState(new UIWarningSubstate(TU.translate("stageCreationScreen.warnings.stage-exists-title"), TU.translate("stageCreationScreen.warnings.stage-exists-body"), [ + {label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: (t) -> {}}, ])); return; } @@ -51,15 +52,7 @@ class StageSelection extends EditorTreeMenu #end // Add to List - var option = new TextOption(creation.name, TU.translate("stageSelection.acceptStage"), function() { - FlxG.switchState(new StageEditor(creation.name)); - }); - optionsTree.members[optionsTree.members.length-1].insert(1, option); - } - - override function createPost() { - super.createPost(); - - main.changeSelection(1); + stages.push(creation.name.toLowerCase()); + parent.tree.last().insert(parent.tree.last().length - 1, makeStageOption(creation.name)); } } \ No newline at end of file diff --git a/source/funkin/menus/MainMenuState.hx b/source/funkin/menus/MainMenuState.hx index 1a931781..1a68f4a2 100644 --- a/source/funkin/menus/MainMenuState.hx +++ b/source/funkin/menus/MainMenuState.hx @@ -6,7 +6,7 @@ import flixel.tweens.FlxTween; import funkin.backend.FunkinText; import funkin.backend.scripting.events.menu.MenuChangeEvent; import funkin.backend.scripting.events.NameEvent; -//import funkin.menus.credits.CreditsMain; +import funkin.menus.credits.CreditsMain; import funkin.options.OptionsMenu; import lime.app.Application; @@ -168,7 +168,7 @@ class MainMenuState extends MusicBeatState { case 'story mode': FlxG.switchState(new StoryMenuState()); case 'freeplay': FlxG.switchState(new FreeplayState()); - //case 'donate', 'credits': FlxG.switchState(new CreditsMain()); // kept donate for not breaking scripts, if you don't want donate to bring you to the credits menu, thats easy softcodable - Nex + case 'donate', 'credits': FlxG.switchState(new CreditsMain()); // kept donate for not breaking scripts, if you don't want donate to bring you to the credits menu, thats easy softcodable - Nex case 'options': FlxG.switchState(new OptionsMenu()); } }); diff --git a/source/funkin/menus/credits/CreditsCodename.hx b/source/funkin/menus/credits/CreditsCodename.hx new file mode 100644 index 00000000..5448825c --- /dev/null +++ b/source/funkin/menus/credits/CreditsCodename.hx @@ -0,0 +1,135 @@ +package funkin.menus.credits; + +import flixel.text.FlxText; +import flixel.util.FlxColor; +import funkin.backend.system.github.GitHub; +import funkin.backend.system.github.GitHubContributor.CreditsGitHubContributor; +import funkin.options.PlayerSettings; +import funkin.options.type.GithubIconOption; + +using StringTools; + +class CreditsCodename extends funkin.options.TreeMenuScreen { + public var error:Bool = false; + public var totalContributions:Int = 0; + public var contribFormats:Array = []; + + public function new() { + super("Codename Engine", "credits.allContributors"); + tryUpdating(true); + } + + // blame the secondary threads if the code has to look this bad - Nex + private var _canReset:Bool = true; + private var _downloadingSteps:Int = 0; + override function update(elapsed:Float) { + super.update(elapsed); + + if (_downloadingSteps == 2) { + _downloadingSteps = 0; + _canReset = true; + displayList(); + } else if (_downloadingSteps == 1) { + _downloadingSteps = 0; + _canReset = true; + updateMenuDesc(); + } + else if (_canReset && PlayerSettings.solo.controls.RESET) tryUpdating(); + } + + public function tryUpdating(forceDisplaying:Bool = false) { + updateMenuDesc(TU.translate("credits.downloadingList")); + _canReset = false; + Main.execAsync(() -> { + if (checkUpdate() || forceDisplaying) _downloadingSteps = 2; + else _downloadingSteps = 1; + }); + } + + public override function updateMenuDesc(?txt:String) { + if (!_canReset) return; + super.updateMenuDesc(txt); + updateMarkup(); + } + + public function updateMarkup() { + if (parent == null) return; + var text:String = parent.descLabel.text; + parent.descLabel.text = ""; + parent.descLabel.applyMarkup(text, contribFormats = [ + new FlxTextFormatMarkerPair(new FlxTextFormat(Flags.MAIN_DEVS_COLOR), '*'), + new FlxTextFormatMarkerPair(new FlxTextFormat(FlxColor.interpolate(Flags.MIN_CONTRIBUTIONS_COLOR, Flags.MAIN_DEVS_COLOR, Options.contributors[curSelected].contributions / totalContributions)), '~') + ]); + } + + override function destroy() { + super.destroy(); + for (frmt in contribFormats) parent.descLabel.removeFormat(frmt.format); + } + + public function checkUpdate():Bool { + var curTime:Float = Date.now().getTime(); + if(Options.lastUpdated != null && curTime < Options.lastUpdated + 120000) return false; // Fuck you Github rate limits - Nex + Options.lastUpdated = curTime; + + error = false; + var idk = GitHub.getContributors(Flags.REPO_OWNER, Flags.REPO_NAME, function(e) { + error = true; + var errMsg:String = 'Error while trying to download contributors list:\n${CoolUtil.removeIP(e.message)}'; + Logs.error(errMsg.replace('\n', ' ')); + funkin.backend.utils.NativeAPI.showMessageBox("Codename Engine Warning", errMsg, MSG_WARNING); + }); + if(error) return false; + if((idk is Array)) { + var contributors:Array = []; + for(e in idk) contributors.push({ + login: e.login, + avatar_url: e.avatar_url, + html_url: e.html_url, + id: e.id, + contributions: e.contributions + }); + Options.contributors = contributors; + } + Logs.verbose('[CreditsCodename] Contributors list Updated!'); + + var errorOnMain:Bool = false; + var idk2 = GitHub.getOrganizationMembers(Flags.REPO_OWNER, function(e) { + errorOnMain = true; + var errMsg:String = 'Error while trying to download ${Flags.REPO_OWNER} members list:\n${CoolUtil.removeIP(e.message)}'; + Logs.error(errMsg.replace('\n', ' ')); + funkin.backend.utils.NativeAPI.showMessageBox("Codename Engine Warning", errMsg, MSG_WARNING); + }); + if(!errorOnMain) { + Options.mainDevs = [for(m in idk2) m.id]; + Logs.verbose('[CreditsCodename] Main Devs list Updated!'); + } + + return true; + } + + public function displayList() { + //if (curSelected > Options.contributors.length - 1) changeSelection(-(curSelected - (Options.contributors.length - 1))); + if (curSelected > Options.contributors.length - 1) curSelected = Options.contributors.length - 1; + changeSelection(0, true); + + while (members.length > 0) { + members[0].destroy(); + remove(members[0], true); + } + + totalContributions = 0; + for(c in Options.contributors) totalContributions += c.contributions; + for(c in Options.contributors) { + var text = TU.translate("credits.totalContributions", [c.contributions, totalContributions, FlxMath.roundDecimal(c.contributions / totalContributions * 100, 2)]); + var opt:GithubIconOption = new GithubIconOption(c, text); + if(Options.mainDevs.contains(c.id)) { + opt.desc += TU.translate("credits.mainDev"); + @:privateAccess opt.__text.color = Flags.MAIN_DEVS_COLOR; + } + add(opt); + } + + updateMenuDesc(); + } +} \ No newline at end of file diff --git a/source/funkin/menus/credits/CreditsMain.hx b/source/funkin/menus/credits/CreditsMain.hx new file mode 100644 index 00000000..79182bcc --- /dev/null +++ b/source/funkin/menus/credits/CreditsMain.hx @@ -0,0 +1,103 @@ +package funkin.menus.credits; + +import flixel.util.FlxColor; +import funkin.backend.assets.AssetSource; +import funkin.backend.system.github.GitHubContributor.CreditsGitHubContributor; +import funkin.options.TreeMenu; +import funkin.options.TreeMenuScreen; +import funkin.options.type.*; +import haxe.xml.Access; + +class CreditsMain extends TreeMenu { + var bg:FlxSprite; + var items:Array = []; + + override function create() { + super.create(); + + DiscordUtil.call("onMenuLoaded", ["Credits Menu"]); + + add(bg = new FlxSprite().loadAnimatedGraphic(Paths.image('menus/menuBGBlue'))); + bg.antialiasing = true; + bg.scrollFactor.set(); + updateBG(); + + var first = new TreeMenuScreen('credits.name', 'credits.madePossible'); + addMenu(first); + + for (i in funkin.backend.assets.ModsFolder.getLoadedMods()) { + var xmlPath = Paths.xml('config/credits/LIB_$i'); + + if (Paths.assetsTree.existsSpecific(xmlPath, "TEXT")) { + var access:Access = null; + try access = new Access(Xml.parse(Paths.assetsTree.getSpecificAsset(xmlPath, "TEXT"))) + catch(e) Logs.trace('[CreditsMain] Error while parsing credits.xml: ${Std.string(e)}', ERROR); + if (access != null) for (c in parseCreditsFromXML(access)) first.add(c); + } + } + + first.add(new TextOption('Codename Engine', 'credits.selectCodename', ' >', () -> addMenu(new CreditsCodename()))); + first.add(new TextOption('Friday Night Funkin\'', 'credits.selectBase', ' >', () -> CoolUtil.openURL(Flags.URL_FNF_ITCH))); + } + + public function updateBG() { + var scaleX:Float = FlxG.width / bg.width; + var scaleY:Float = FlxG.height / bg.height; + bg.scale.x = bg.scale.y = Math.max(scaleX, scaleY) * 1.15; + bg.screenCenter(); + } + + // XML STUFF + public function parseCreditsFromXML(xml:Access, source:AssetSource = BOTH):Array { + var credsMenus:Array = []; + + for(node in xml.elements) { + var desc = node.getAtt("desc").getDefault("No Description"); + + if (node.name == "github") { + if (!node.has.user) { + Logs.warn("A github node requires a user attribute.", "CreditsMain"); + continue; + } + + var username = node.getAtt("user"); + var user:CreditsGitHubContributor = { // Kind of forcing + login: username, + html_url: 'https://github.com/$username', + avatar_url: 'https://github.com/$username.png' + }; + var opt:GithubIconOption = new GithubIconOption(user, desc, null, + node.has.customName ? node.att.customName : null, + node.has.size ? Std.parseInt(node.att.size) : 96, + node.has.portrait ? node.att.portrait.toLowerCase() == "false" ? false : true : true + ); + if (node.has.color) + @:privateAccess opt.__text.color = FlxColor.fromString(node.att.color); + credsMenus.push(opt); + } else { + if (!node.has.name) { + Logs.warn("A credit node requires a name attribute.", "CreditsMain"); + continue; + } + var name = node.getAtt("name"); + + switch(node.name) { + case "credit": + var opt:PortraitOption = new PortraitOption(name, desc, function() if(node.has.url) CoolUtil.openURL(node.att.url), + node.has.icon && Paths.assetsTree.existsSpecific(Paths.image('credits/${node.att.icon}'), "IMAGE", source) ? + FlxG.bitmap.add(Paths.image('credits/${node.att.icon}')) : null, node.has.size ? Std.parseInt(node.att.size) : 96, + node.has.portrait ? node.att.portrait.toLowerCase() == "false" ? false : true : true + ); + if (node.has.color) + @:privateAccess opt.__text.color = FlxColor.fromString(node.att.color); + credsMenus.push(opt); + + case "menu": + credsMenus.push(new TextOption(name, desc, ' >', () -> addMenu(new TreeMenuScreen(name, desc, parseCreditsFromXML(node, source))))); + } + } + } + + return credsMenus; + } +} \ No newline at end of file diff --git a/source/funkin/options/OptionsMenu.hx b/source/funkin/options/OptionsMenu.hx index ae184e0c..7522b87c 100644 --- a/source/funkin/options/OptionsMenu.hx +++ b/source/funkin/options/OptionsMenu.hx @@ -94,7 +94,7 @@ class OptionsMenu extends TreeMenu { var access:Access = null; try access = new Access(Xml.parse(Paths.assetsTree.getSpecificAsset(xmlPath, "TEXT"))) catch(e) Logs.trace('Error while parsing options.xml: ${Std.string(e)}', ERROR); - //if (access != null) for (o in parseOptionsFromXML(access)) main.add(o); + if (access != null) for (o in parseOptionsFromXML(access)) tree.first().add(o); } } } @@ -120,9 +120,8 @@ class OptionsMenu extends TreeMenu { } // XML STUFF - /* - public function parseOptionsFromXML(xml:Access):Array { - var options:Array = []; + public function parseOptionsFromXML(xml:Access):Array { + var options:Array = []; for(node in xml.elements) { if (!node.has.name) { @@ -164,13 +163,10 @@ class OptionsMenu extends TreeMenu { options.push(new ArrayOption(name, desc, optionOptions, optionDisplayOptions, node.att.id, null, FlxG.save.data)); case "menu": - options.push(new TextOption(name + " >", desc, function() { - optionsTree.add(new TreeMenuScreen(name, desc, parseOptionsFromXML(node))); - })); + options.push(new TextOption(name, desc, ' >', () -> addMenu(new TreeMenuScreen(name, desc, parseOptionsFromXML(node))))); } } return options; } - */ } \ No newline at end of file diff --git a/source/funkin/options/OptionsScreen.hx b/source/funkin/options/OptionsScreen.hx deleted file mode 100644 index 672feb40..00000000 --- a/source/funkin/options/OptionsScreen.hx +++ /dev/null @@ -1,141 +0,0 @@ -// REMOVE THIS WHEN COMPLETE - -package funkin.options; - -import funkin.options.type.OptionType; - -class OptionsScreen extends FlxTypedSpriteGroup { - public static var optionHeight:Float = 120; - - public var parent:OptionsTree; - - public var curSelected:Int = 0; - public var id:Int = 0; - - private var __firstFrame:Bool = true; - - public var name:String; - public var desc:String; - /** - * The prefix to add to the translations ids. - **/ - public var prefix:String = ""; - - private var rawName(default, set):String; - private var rawDesc(default, set):String; - - public inline function getNameID(name):String { - return prefix + name + "-name"; - } - public inline function getDescID(name):String { - return prefix + name + "-desc"; - } - - public function getName(name:String, ?args:Array):String { - return TU.translate(getNameID(name), args); - } - public function getDesc(name:String, ?args:Array):String { - return TU.translate(getDescID(name), args); - } - public function translate(name:String, ?args:Array):String { - return TU.translate(prefix + name, args); - } - - public function new(name:String, desc:String, ?prefix:String, ?options:Array) { - super(); - rawName = name; - rawDesc = desc; - this.prefix = prefix != null ? prefix : ""; - if (options != null) for(o in options) add(o); - } - - function set_rawName(v:String) { - rawName = v; - this.name = TU.exists(rawName) ? TU.translate(rawName) : rawName; - return v; - } - - function set_rawDesc(v:String) { - rawDesc = v; - this.desc = TU.exists(rawDesc) ? TU.translate(rawDesc) : rawDesc; - return v; - } - - public function reloadStrings() { - this.rawName = rawName; - this.rawDesc = rawDesc; - - for(o in members) { - o.reloadStrings(); - } - } - - public override function update(elapsed:Float) { - super.update(elapsed); - - var controls = PlayerSettings.solo.controls; - - changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0) - FlxG.mouse.wheel); - x = id * FlxG.width; - for(k=>option in members) { - if(option == null) continue; - - var y:Float = ((FlxG.height - optionHeight) / 2) + ((k - curSelected) * optionHeight); - - option.selected = false; - option.y = __firstFrame ? y : CoolUtil.fpsLerp(option.y, y, 0.25); - option.x = x + (-50 + (Math.abs(Math.cos((option.y + (optionHeight / 2) - (FlxG.camera.scroll.y + (FlxG.camera.height / 2))) / (FlxG.camera.height * 1.25) * Math.PI)) * 150)); - } - if (__firstFrame) { - __firstFrame = false; - return; - } - - if (members.length > 0) { - members[curSelected].selected = true; - if (controls.ACCEPT || (FlxG.mouse.justReleased && Main.timeSinceFocus > 0.25)) { - members[curSelected].select(); - onSelect(members[curSelected]); - } - if (controls.LEFT_P) - members[curSelected].changeSelection(-1); - if (controls.RIGHT_P) - members[curSelected].changeSelection(1); - } - if (controls.BACK || FlxG.mouse.justReleasedRight) - close(); - } - - public function close() { - onClose(this); - } - - public function changeSelection(sel:Int, force:Bool = false) { - if (members.length <= 0 || (sel == 0 && !force)) return; - - CoolUtil.playMenuSFX(SCROLL); - curSelected = FlxMath.wrap(curSelected + sel, 0, members.length-1); - members[curSelected].selected = true; - updateMenuDesc(); - } - - public function updateMenuDesc(?customTxt:String) { - if (parent == null || parent.treeParent == null) return; - parent.treeParent.updateDesc(customTxt != null ? customTxt : members[curSelected].desc); - } - - public dynamic function onClose(o:OptionsScreen) {} - public dynamic function onSelect(o:OptionType) { - if(o is funkin.options.type.RadioButton) { - var orb:funkin.options.type.RadioButton = cast o; - for(e in members) { - if(e is funkin.options.type.RadioButton) { - var rb:funkin.options.type.RadioButton = cast e; - if(rb.forId == orb.forId && rb != o) { - rb.checked = false; - } - } - } - } - } -} \ No newline at end of file diff --git a/source/funkin/options/OptionsTree.hx b/source/funkin/options/OptionsTree.hx deleted file mode 100644 index 1f0bfcc7..00000000 --- a/source/funkin/options/OptionsTree.hx +++ /dev/null @@ -1,91 +0,0 @@ -// REMOVE THIS WHEN COMPLETE - -package funkin.options; - -class OptionsTree extends FlxTypedGroup { - public var lastMenu:OptionsScreen; - public var treeParent:TreeMenu; - public var wasClosing:Bool = false; - //public override function new() { - // super(); - //} - - public override function update(elapsed:Float) { - var last = members.last(); - if (last != null) - last.update(elapsed); - } - - public function updateAll(elapsed:Float) { - for (member in members) { - if(member == null) continue; - if(member.active && member.exists) { - member.update(elapsed); - } - } - } - - public override function draw() { - super.draw(); - if (lastMenu != null) { // manually draw lastMenu since it got removed from the members list - lastMenu.draw(); - } - } - - public function reloadStrings() { - for(o in members) { - o.reloadStrings(); - } - } - - public override function add(m:OptionsScreen) { - super.add(m); - setup(m); - clearLastMenu(); - wasClosing = false; - onMenuChange(); - return m; - } - public override function insert(pos:Int, m:OptionsScreen) { - var last = members.last(); - super.insert(pos, m); - setup(m); - if (last != members.last()) { - wasClosing = false; - onMenuChange(); - } - return m; - } - - public function setup(m:OptionsScreen) { - m.onClose = __subMenuClose; - m.id = members.indexOf(m); - m.parent = this; - m.update(0); - } - - function __subMenuClose(m:OptionsScreen) { - wasClosing = true; - clearLastMenu(); - lastMenu = m; - remove(m, true); - onMenuChange(); - onMenuClose(m); - } - - public function clearLastMenu() { - lastMenu = FlxDestroyUtil.destroy(lastMenu); - } - - public override function destroy() { - super.destroy(); - lastMenu = FlxDestroyUtil.destroy(lastMenu); - } - - public dynamic function onMenuChange() { - - } - - public dynamic function onMenuClose(m:OptionsScreen) { - } -} \ No newline at end of file diff --git a/source/funkin/options/TreeMenu.hx b/source/funkin/options/TreeMenu.hx index 9a8b933a..f5c0e177 100644 --- a/source/funkin/options/TreeMenu.hx +++ b/source/funkin/options/TreeMenu.hx @@ -32,8 +32,6 @@ class TreeMenu extends UIState { public var descLabel:FunkinText; public var bgLabel:FlxSprite; - public var optionsTree:OptionsTree; - var menuChangeTween:FlxTween; var __drawer:TreeMenuDrawer; var __treeCreated:Bool = false; @@ -74,7 +72,9 @@ class TreeMenu extends UIState { add(bgLabel); add(titleLabel); add(descLabel); - updateLabels(); + + FlxG.camera.scroll.x = -FlxG.width; + menuChanged(); __treeCreated = true; } diff --git a/source/funkin/options/type/EditorIconOption.hx b/source/funkin/options/type/EditorIconOption.hx deleted file mode 100644 index 5303fb01..00000000 --- a/source/funkin/options/type/EditorIconOption.hx +++ /dev/null @@ -1,13 +0,0 @@ -package funkin.options.type; - -import flixel.util.FlxColor; - -class EditorIconOption extends IconOption { - public var flashColor:FlxColor; - - public function new(name:String, desc:String, icon:String, callback:Void->Void, flashColor:FlxColor = 0) { - super(name, desc, icon, callback); - - this.flashColor = flashColor; - } -} \ No newline at end of file diff --git a/source/funkin/options/type/GithubIconOption.hx b/source/funkin/options/type/GithubIconOption.hx index be3567a8..16916b55 100644 --- a/source/funkin/options/type/GithubIconOption.hx +++ b/source/funkin/options/type/GithubIconOption.hx @@ -26,6 +26,7 @@ class GithubIconOption extends TextOption this.icon = new GithubUserIcon(user, size, waitUntilLoad); this.usePortrait = usePortrait; add(icon); + __text.x = 100; } } diff --git a/source/funkin/options/type/NewOption.hx b/source/funkin/options/type/NewOption.hx index 07f4fdf0..85181412 100644 --- a/source/funkin/options/type/NewOption.hx +++ b/source/funkin/options/type/NewOption.hx @@ -10,6 +10,7 @@ class NewOption extends TextOption { public function new(name:String, desc:String, callback:Void->Void) { super(name, desc, callback); + itemHeight = 160; __text.color = FlxColor.LIME; __text.x = 100; diff --git a/source/funkin/options/type/OptionType.hx b/source/funkin/options/type/OptionType.hx index 41f4302c..3d4d25f0 100644 --- a/source/funkin/options/type/OptionType.hx +++ b/source/funkin/options/type/OptionType.hx @@ -1,6 +1,7 @@ package funkin.options.type; import flixel.group.FlxSpriteGroup; +import flixel.util.FlxColor; import funkin.backend.system.Controls; import funkin.options.TreeMenu.ITreeOption; @@ -19,6 +20,8 @@ class OptionType extends FlxSpriteGroup implements ITreeOption { public var itemHeight:Float = 120; + public var editorFlashColor:FlxColor = FlxColor.WHITE; + public function new(text:String, desc:String) { super(); rawText = text; diff --git a/source/funkin/options/type/TextOption.hx b/source/funkin/options/type/TextOption.hx index 74ccfc2b..e859b668 100644 --- a/source/funkin/options/type/TextOption.hx +++ b/source/funkin/options/type/TextOption.hx @@ -6,7 +6,7 @@ import flixel.effects.FlxFlicker; * Option type that has text. **/ class TextOption extends OptionType { - public var suffix:String; + public var suffix(default, set):String; public var selectCallback:Void->Void; var __text:Alphabet; @@ -15,6 +15,12 @@ class TextOption extends OptionType { return text = v; } + function set_suffix(v:String) { + if (suffix == (suffix = v)) return v; + __text.text = text + suffix; + return v; + } + public function new(text:String, desc:String, ?suffix:String = "", ?selectCallback:Void->Void = null) { this.suffix = suffix; this.selectCallback = selectCallback;