From bb0de4eddadc2e8fc75134142dc4066ad42e5210 Mon Sep 17 00:00:00 2001 From: lunarcleint <88809950+lunarcleint@users.noreply.github.com> Date: Mon, 5 Feb 2024 19:30:42 -0700 Subject: [PATCH] UNSAVED IN PLAYTESTING :D --- source/funkin/editors/SaveWarning.hx | 4 + source/funkin/editors/charter/Charter.hx | 7 +- source/funkin/game/GameOverSubstate.hx | 26 ++-- source/funkin/game/PlayState.hx | 65 ++++++++++ source/funkin/menus/GitarooPause.hx | 23 ++-- source/funkin/menus/PauseSubState.hx | 14 ++- .../menus/PlaytestingWarningSubstate.hx | 113 ++++++++++++++++++ 7 files changed, 230 insertions(+), 22 deletions(-) create mode 100644 source/funkin/menus/PlaytestingWarningSubstate.hx diff --git a/source/funkin/editors/SaveWarning.hx b/source/funkin/editors/SaveWarning.hx index fad155b48..86dedecbb 100644 --- a/source/funkin/editors/SaveWarning.hx +++ b/source/funkin/editors/SaveWarning.hx @@ -16,7 +16,10 @@ class SaveWarning { } } + public static var warningFunc:Bool->Void = null; public static function triggerWarning(?closingWindow:Bool = false) { + if (warningFunc != null) warningFunc(closingWindow); + if (FlxG.state != null && FlxG.state is UIState) { FlxG.state.openSubState(new UIWarningSubstate("Unsaved Changes!", "Your changes will be lost if you don't save them. (Can't be recovered)\n\n\nWould you like to Cancel?", [ @@ -60,5 +63,6 @@ class SaveWarning { SaveWarning.showWarning = false; SaveWarning.selectionClass = null; SaveWarning.saveFunc = null; + SaveWarning.warningFunc = null; } } \ No newline at end of file diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 64869b451..d08937e55 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -1094,7 +1094,7 @@ class Charter extends UIState { #if REGION function _file_exit(_) { if (undos.unsaved) SaveWarning.triggerWarning(); - else {undos = null; FlxG.switchState(new CharterSelection());} + else {undos = null; FlxG.switchState(new CharterSelection()); PlayState.resetSongInfos(); Charter.instance.__clearStatics();} } function _file_save(_) { @@ -1197,7 +1197,6 @@ class Charter extends UIState { selection = []; var undo = undos.undo(); - trace(undo); switch(undo) { case null: // do nothing case CDeleteStrumLine(strumLineID, strumLine): @@ -1644,6 +1643,10 @@ class Charter extends UIState { clipboard = []; playtestInfo = null; } + @:noCompletion public function __clearStatics() { + selection = null; undos = null; clipboard = null; playtestInfo = null; + } + @:noCompletion public function __updatePlaytestInfo() { playtestInfo = { songPosition: Conductor.songPosition, diff --git a/source/funkin/game/GameOverSubstate.hx b/source/funkin/game/GameOverSubstate.hx index 6566f5d3d..f7bd5cff2 100644 --- a/source/funkin/game/GameOverSubstate.hx +++ b/source/funkin/game/GameOverSubstate.hx @@ -1,5 +1,6 @@ package funkin.game; +import funkin.editors.charter.Charter; import funkin.backend.scripting.events.GameOverCreationEvent; import funkin.backend.scripting.events.CancellableEvent; import funkin.backend.scripting.Script; @@ -110,15 +111,22 @@ class GameOverSubstate extends MusicBeatSubstate if (controls.BACK) { - PlayState.resetSongInfos(); - if (FlxG.sound.music != null) - FlxG.sound.music.stop(); - FlxG.sound.music = null; - - if (PlayState.isStoryMode) - FlxG.switchState(new StoryMenuState()); - else - FlxG.switchState(new FreeplayState()); + if (PlayState.chartingMode && Charter.undos.unsaved) + PlayState.instance.saveWarn(false); + else { + PlayState.resetSongInfos(); + Charter.instance.__clearStatics(); + + if (FlxG.sound.music != null) + FlxG.sound.music.stop(); + FlxG.sound.music = null; + + if (PlayState.isStoryMode) + FlxG.switchState(new StoryMenuState()); + else + FlxG.switchState(new FreeplayState()); + } + } if (!isEnding && ((!lossSFX.playing) || (character.getAnimName() == "firstDeath" && character.isAnimFinished())) && (FlxG.sound.music == null || !FlxG.sound.music.playing)) diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx index 92f1e4df2..99d4608ca 100644 --- a/source/funkin/game/PlayState.hx +++ b/source/funkin/game/PlayState.hx @@ -1,5 +1,9 @@ package funkin.game; +import funkin.editors.charter.CharterSelection; +import flixel.FlxState; +import funkin.editors.EditorTreeMenu; +import funkin.editors.SaveWarning; import funkin.backend.chart.EventsData; import funkin.backend.system.RotatingSpriteGroup; import funkin.editors.charter.Charter; @@ -751,6 +755,19 @@ class PlayState extends MusicBeatState for(s in introSounds) if (s != null) FlxG.sound.load(Paths.sound(s)); + + if (chartingMode) { + WindowUtils.endfix = " (Chart Playtesting)"; + WindowUtils.prefix = Charter.undos.unsaved ? "* " : ""; + + SaveWarning.showWarning = Charter.undos.unsaved; + SaveWarning.selectionClass = CharterSelection; + SaveWarning.warningFunc = saveWarn; + SaveWarning.saveFunc = () -> { + @:privateAccess Chart.save('${Paths.getAssetsRoot()}/songs/${Charter.__song.toLowerCase()}', + PlayState.SONG, Charter.__diff.toLowerCase(), {saveMetaInChart: false}); + } + } } @:dox(hide) public override function createPost() { @@ -941,6 +958,10 @@ class PlayState extends MusicBeatState FlxG.sound.destroySound(inst); FlxG.sound.destroySound(vocals); } + + WindowUtils.resetTitle(); + SaveWarning.reset(); + instance = null; Note.__customNoteTypeExists = []; @@ -1120,6 +1141,50 @@ class PlayState extends MusicBeatState updateDiscordPresence(); } + public function saveWarn(closingWindow:Bool = true) { + persistentUpdate = false; + paused = true; + + var state:FlxState = FlxG.state; + if (FlxG.state.subState != null) + state = FlxG.state.subState; + + state.openSubState(new PlaytestingWarningSubstate(closingWindow, [ + { + label: closingWindow ? "Exit Game" : "Exit To Menu", + color: 0xFF0000, + onClick: function(_) { + if (!closingWindow) { + if (SaveWarning.selectionClass != null) FlxG.switchState(Type.createInstance(SaveWarning.selectionClass, [])); + } else { + WindowUtils.preventClosing = false; WindowUtils.resetClosing(); + Sys.exit(0); + } + } + }, + { + label: closingWindow ? "Save & Exit Game" : "Save & Exit To Menu", + color: 0xFFFF00, + onClick: function(_) { + if (SaveWarning.saveFunc != null) SaveWarning.saveFunc(); + if (!closingWindow) { + if (SaveWarning.selectionClass != null) FlxG.switchState(Type.createInstance(SaveWarning.selectionClass, [])); + } else { + WindowUtils.preventClosing = false; WindowUtils.resetClosing(); + Sys.exit(0); + } + } + }, + { + label: "Cancel", + color: 0xFFFFFF, + onClick: function (_) { + if (closingWindow) WindowUtils.resetClosing(); + } + } + ])); + } + function updateIconPositions() { var iconOffset:Int = 26; diff --git a/source/funkin/menus/GitarooPause.hx b/source/funkin/menus/GitarooPause.hx index fc569c85a..296f51344 100644 --- a/source/funkin/menus/GitarooPause.hx +++ b/source/funkin/menus/GitarooPause.hx @@ -1,5 +1,6 @@ package funkin.menus; +import funkin.editors.charter.Charter; import flixel.graphics.frames.FlxAtlasFrames; class GitarooPause extends MusicBeatState @@ -55,14 +56,20 @@ class GitarooPause extends MusicBeatState if (controls.ACCEPT) { - if (replaySelect) - { - FlxG.switchState(new PlayState()); - } - else - { - PlayState.resetSongInfos(); - FlxG.switchState(new MainMenuState()); + if (PlayState.chartingMode && Charter.undos.unsaved) + PlayState.instance.saveWarn(false); + else { + if (replaySelect) + { + FlxG.switchState(new PlayState()); + } + else + { + PlayState.resetSongInfos(); + Charter.instance.__clearStatics(); + + FlxG.switchState(new MainMenuState()); + } } } diff --git a/source/funkin/menus/PauseSubState.hx b/source/funkin/menus/PauseSubState.hx index 64b31a483..a7d8f9eee 100644 --- a/source/funkin/menus/PauseSubState.hx +++ b/source/funkin/menus/PauseSubState.hx @@ -1,5 +1,6 @@ package funkin.menus; +import funkin.editors.charter.Charter; import funkin.backend.scripting.events.MenuChangeEvent; import funkin.options.OptionsMenu; import funkin.backend.scripting.events.PauseCreationEvent; @@ -158,9 +159,16 @@ class PauseSubState extends MusicBeatSubstate case "Exit to charter": FlxG.switchState(new funkin.editors.charter.Charter(PlayState.SONG.meta.name, PlayState.difficulty, false)); case "Exit to menu": - PlayState.resetSongInfos(); - CoolUtil.playMenuSong(); - FlxG.switchState(PlayState.isStoryMode ? new StoryMenuState() : new FreeplayState()); + if (PlayState.chartingMode && Charter.undos.unsaved) + PlayState.instance.saveWarn(false); + else { + PlayState.resetSongInfos(); + Charter.instance.__clearStatics(); + + CoolUtil.playMenuSong(); + FlxG.switchState(PlayState.isStoryMode ? new StoryMenuState() : new FreeplayState()); + } + } } override function destroy() diff --git a/source/funkin/menus/PlaytestingWarningSubstate.hx b/source/funkin/menus/PlaytestingWarningSubstate.hx new file mode 100644 index 000000000..047d42ced --- /dev/null +++ b/source/funkin/menus/PlaytestingWarningSubstate.hx @@ -0,0 +1,113 @@ +package funkin.menus; + +import flixel.tweens.FlxTween; +import funkin.editors.ui.UIWarningSubstate.WarningButton; +import flixel.util.FlxColor; +import flixel.text.FlxText.FlxTextFormat; +import flixel.text.FlxText.FlxTextFormatMarkerPair; +import funkin.backend.FunkinText; + +class PlaytestingWarningSubstate extends MusicBeatSubstate +{ + var titleAlphabet:Alphabet; + var disclaimer:FunkinText; + + var windowClosing:Bool = false; + + var curSelected:Int = 0; + var options:Array = []; + var buttonsData:Array = []; + + var indicator:FunkinText; + + public function new(closingWindow:Bool, buttons:Array) { + super(); + windowClosing = closingWindow; + buttonsData = buttons; + } + + override function create() { + super.create(); + + camera = new FlxCamera(); + camera.bgColor = 0; + FlxG.cameras.add(camera, false); + + var bg:FlxSprite = new FlxSprite().makeSolid(FlxG.width + 100, FlxG.height + 100, FlxColor.BLACK); + bg.updateHitbox(); + bg.alpha = .8; + bg.screenCenter(); + bg.scrollFactor.set(); + add(bg); + + titleAlphabet = new Alphabet(0, 140, "UNSAVED CHANGES!", true); + titleAlphabet.screenCenter(X); + add(titleAlphabet); + + disclaimer = new FunkinText(16, titleAlphabet.y + titleAlphabet.height + 70, FlxG.width - 32, "", 32); + disclaimer.alignment = CENTER; + disclaimer.applyMarkup("Your changes will be *lost* if you don't save them. (Can't be recovered)\n\n\nWould you like to Cancel?", + [ + new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFF4444), "*") + ] + ); + disclaimer.borderSize = 4; + add(disclaimer); + + for (buttonData in buttonsData) { + var textOption:FunkinText = new FunkinText(0, disclaimer.y + disclaimer.height + 140, 0, buttonData.label, 24); + textOption.borderSize = 4; if (buttonData.color != null) textOption.color = buttonData.color; + options.push(cast add(textOption)); + } + + indicator = new FunkinText(0, disclaimer.y + disclaimer.height + 86, 0, "V", 22); + indicator.borderSize = 4; + add(indicator); + + FlxTween.tween(indicator.offset, {y: -7.5}, {ease: FlxEase.quadInOut, type: PINGPONG}); + + curSelected = options.length-1; + changeSelection(0); + } + + var sinner:Float = 0; + var __firstFrame:Bool = true; + override function update(elapsed:Float) { + super.update(elapsed); sinner += elapsed; + + titleAlphabet.offset.y = FlxMath.fastSin(sinner) * 12; + disclaimer.offset.y = FlxMath.fastSin(sinner+.8) * 8; + + if (controls.RIGHT_P) changeSelection(1); + if (controls.LEFT_P) changeSelection(-1); + + for (i => option in options) { + option.x = FlxG.width * ((1+i)/4) - (option.fieldWidth/2); + switch(i) { + case 1: option.x -= 20; + } + if (i == curSelected) indicator.x = option.x + (option.fieldWidth/2) - (indicator.fieldWidth/2); + option.alpha = i == curSelected ? 1 : 0.4; + option.y = disclaimer.y + disclaimer.height + 140 + (FlxMath.fastSin((sinner*2)+1.2+(.3*i)) * 4); + option.offset.y = CoolUtil.fpsLerp(option.offset.y, i == curSelected ? 10 : -10, 1/6); + } + + if (controls.ACCEPT && !__firstFrame) { + buttonsData[curSelected].onClick(null); + close(); + } + + __firstFrame = false; + } + + function changeSelection(change:Int) { + CoolUtil.playMenuSFX(SCROLL, 0.7); + curSelected = FlxMath.wrap(curSelected+change, 0, options.length-1); + } + + override function destroy() { + if(FlxG.cameras.list.contains(camera)) + FlxG.cameras.remove(camera, true); + super.destroy(); + } +} \ No newline at end of file