diff --git a/assets/images/editors/ui/grayscale-popup.png b/assets/images/editors/ui/grayscale-popup.png new file mode 100644 index 00000000..b0113603 Binary files /dev/null and b/assets/images/editors/ui/grayscale-popup.png differ diff --git a/assets/images/editors/ui/grayscale-popup.xml b/assets/images/editors/ui/grayscale-popup.xml new file mode 100644 index 00000000..021dd81a --- /dev/null +++ b/assets/images/editors/ui/grayscale-popup.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/images/editors/warning.aseprite b/assets/images/editors/warning.aseprite deleted file mode 100644 index 74aa0e65..00000000 Binary files a/assets/images/editors/warning.aseprite and /dev/null differ diff --git a/assets/images/editors/warning.png b/assets/images/editors/warning.png deleted file mode 100644 index 71c84154..00000000 Binary files a/assets/images/editors/warning.png and /dev/null differ diff --git a/assets/images/editors/warnings/warning.png b/assets/images/editors/warnings/warning.png new file mode 100644 index 00000000..6c864eaf Binary files /dev/null and b/assets/images/editors/warnings/warning.png differ diff --git a/source/funkin/backend/system/Main.hx b/source/funkin/backend/system/Main.hx index fbe59ac1..088c8619 100644 --- a/source/funkin/backend/system/Main.hx +++ b/source/funkin/backend/system/Main.hx @@ -1,5 +1,6 @@ package funkin.backend.system; +import funkin.editors.SaveWarning; import funkin.backend.assets.AssetsLibraryList; import funkin.backend.system.framerate.SystemInfo; import openfl.utils.AssetLibrary; @@ -107,7 +108,8 @@ class Main extends Sprite } public static function loadGameSettings() { - WindowTitle.init(); + WindowUtils.init(); + SaveWarning.init(); MemoryUtil.init(); @:privateAccess FlxG.game.getTimer = getTimer; diff --git a/source/funkin/backend/utils/WindowTitle.hx b/source/funkin/backend/utils/WindowUtils.hx similarity index 63% rename from source/funkin/backend/utils/WindowTitle.hx rename to source/funkin/backend/utils/WindowUtils.hx index 239efa4f..d1ddec7c 100644 --- a/source/funkin/backend/utils/WindowTitle.hx +++ b/source/funkin/backend/utils/WindowUtils.hx @@ -2,7 +2,7 @@ package funkin.backend.utils; import openfl.Lib; -class WindowTitle { +class WindowUtils { public static var winTitle(default, set):String; public static function set_winTitle(newWinTitle:String):String { winTitle = newWinTitle; @@ -22,9 +22,25 @@ class WindowTitle { return endPrefix; } - public static inline function init() + public static var preventClosing:Bool = true; + public static var onClosing:Void->Void; + + static var __triedClosing:Bool = false; + public static inline function resetClosing() __triedClosing = false; + + public static inline function init() { reset(); + Lib.application.window.onClose.add(function () { + if (preventClosing && !__triedClosing) { + Lib.application.window.onClose.cancel(); + __triedClosing = true; + } + if (onClosing != null) onClosing(); + }); + } + + public static inline function reset() { winTitle = Lib.application.meta["name"]; prefix = endfix = ""; diff --git a/source/funkin/editors/SaveWarning.hx b/source/funkin/editors/SaveWarning.hx new file mode 100644 index 00000000..fc30ea32 --- /dev/null +++ b/source/funkin/editors/SaveWarning.hx @@ -0,0 +1,39 @@ +package funkin.editors; + +class SaveWarning { + public static var showWarning(default, set):Bool; + public static function set_showWarning(warning:Bool):Bool + return WindowUtils.preventClosing = showWarning = warning; + + public static var selectionClass:Class = null; + + public static function init() { + showWarning = false; + + WindowUtils.onClosing = function () { + if (SaveWarning.showWarning) triggerWarning(true); + } + } + + public static function triggerWarning(?resetClosing:Bool = false) { + 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?", + [{ + label: "Exit To Menu", + onClick: function(_) { + if (selectionClass != null) FlxG.switchState(Type.createInstance(SaveWarning.selectionClass, [])); + if (resetClosing) WindowUtils.resetClosing(); + } + }, + { + label: "Cancel", + onClick: function (_) {if (resetClosing) WindowUtils.resetClosing();} + }], false)); + } + } + + public static inline function reset() { + SaveWarning.showWarning = false; + SaveWarning.selectionClass = null; + } +} \ No newline at end of file diff --git a/source/funkin/editors/character/CharacterEditor.hx b/source/funkin/editors/character/CharacterEditor.hx index b41a89cc..cf0434d4 100644 --- a/source/funkin/editors/character/CharacterEditor.hx +++ b/source/funkin/editors/character/CharacterEditor.hx @@ -51,7 +51,8 @@ class CharacterEditor extends UIState { public override function create() { super.create(); - WindowTitle.endfix = " (Character Editor)"; + WindowUtils.endfix = " (Character Editor)"; + SaveWarning.selectionClass = CharacterSelection; topMenu = [ { label: "File", @@ -310,12 +311,16 @@ class CharacterEditor extends UIState { characterBG.scale.set(FlxG.width/characterBG.width, FlxG.height/characterBG.height); characterBG.scale.set(characterBG.scale.x / charCamera.zoom, characterBG.scale.y / charCamera.zoom); + + WindowUtils.prefix = undos.unsaved ? "* " : ""; + SaveWarning.showWarning = undos.unsaved; } // TOP MENU OPTIONS #if REGION function _file_exit(_) { - FlxG.switchState(new CharacterSelection()); + if (undos.unsaved) SaveWarning.triggerWarning(); + else FlxG.switchState(new CharacterSelection()); } function _file_new(_) { @@ -327,6 +332,7 @@ class CharacterEditor extends UIState { '${Paths.getAssetsRoot()}/data/characters/${character.curCharacter}.xml', buildCharacter() ); + undos.save(); return; #end _file_saveas(_); @@ -336,6 +342,7 @@ class CharacterEditor extends UIState { openSubState(new SaveSubstate(buildCharacter(), { defaultSaveFile: '${character.curCharacter}.xml' })); + undos.save(); } function buildCharacter():String { diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 4e4d9d98..a5207063 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -93,7 +93,8 @@ class Charter extends UIState { public override function create() { super.create(); - WindowTitle.endfix = " (Chart Editor)"; + WindowUtils.endfix = " (Chart Editor)"; + SaveWarning.selectionClass = CharterSelection; topMenu = [ { label: "File", @@ -591,7 +592,7 @@ class Charter extends UIState { // Some maths, so cool bro -lunar (i dont know why i quopte my self here) if (s.step + changePoint.x < 0) boundedChange.x += Math.abs(s.step + changePoint.x); - if (s.step + changePoint.x > Charter.instance.__endStep-1) boundedChange.x -= (s.step + changePoint.x) - (Charter.instance.__endStep-1); + if (s.step + changePoint.x > __endStep-1) boundedChange.x -= (s.step + changePoint.x) - (__endStep-1); if (s is CharterNote) { var note:CharterNote = cast (s, CharterNote); @@ -896,7 +897,8 @@ class Charter extends UIState { if (charterCamera.zoom != (charterCamera.zoom = lerp(charterCamera.zoom, __camZoom, 0.125))) updateDisplaySprites(); - WindowTitle.prefix = undos.unsaved ? "* " : ""; + WindowUtils.prefix = undos.unsaved ? "* " : ""; + SaveWarning.showWarning = undos.unsaved; } public static var startTime:Float = 0; @@ -931,19 +933,8 @@ class Charter extends UIState { // TOP MENU OPTIONS #if REGION function _file_exit(_) { - if (undos.unsaved) { - 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?", [ - { - label: "Exit To Menu", - onClick: function(_) FlxG.switchState(new CharterSelection()) - }, - { - label: "Cancel", - onClick: function (_) {} - } - ], false)); - } else - FlxG.switchState(new CharterSelection()); + if (undos.unsaved) SaveWarning.triggerWarning(); + else FlxG.switchState(new CharterSelection()); } function _file_save(_) { diff --git a/source/funkin/editors/ui/UIState.hx b/source/funkin/editors/ui/UIState.hx index 4987d8fb..1120c614 100644 --- a/source/funkin/editors/ui/UIState.hx +++ b/source/funkin/editors/ui/UIState.hx @@ -127,8 +127,11 @@ class UIState extends MusicBeatState { public override function destroy() { super.destroy(); - WindowTitle.reset(); __mousePos.put(); + + WindowUtils.reset(); + SaveWarning.reset(); + FlxG.stage.window.onKeyDown.remove(onKeyDown); FlxG.stage.window.onKeyUp.remove(onKeyUp); FlxG.stage.window.onTextInput.remove(onTextInput); diff --git a/source/funkin/editors/ui/UIWarningSubstate.hx b/source/funkin/editors/ui/UIWarningSubstate.hx index 9fee13e2..43633410 100644 --- a/source/funkin/editors/ui/UIWarningSubstate.hx +++ b/source/funkin/editors/ui/UIWarningSubstate.hx @@ -56,16 +56,16 @@ class UIWarningSubstate extends MusicBeatSubstate { warnCam.zoom = 0.1; FlxG.cameras.add(warnCam, false); - var spr = new UISliceSprite(0, 0, CoolUtil.maxInt(560, 30 + (170 * buttons.length)), 232, "editors/ui/normal-popup"); + var spr = new UISliceSprite(0, 0, CoolUtil.maxInt(560, 30 + (170 * buttons.length)), 232, 'editors/ui/${isError ? "normal" : "grayscale"}-popup'); spr.x = (FlxG.width - spr.bWidth) / 2; spr.y = (FlxG.height - spr.bHeight) / 2; - spr.color = 0xFFFF0000; + spr.color = isError ? 0xFFFF0000 : 0xFFFFFF00; add(spr); add(titleSpr = new UIText(spr.x + 25, spr.y, spr.bWidth - 50, title, 15, -1)); titleSpr.y = spr.y + ((30 - titleSpr.height) / 2); - var sprIcon:FlxSprite = new FlxSprite(spr.x + 26, spr.y + 28 + 26).makeSolid(100, 100, -1); + var sprIcon:FlxSprite = new FlxSprite(spr.x + 26, spr.y + 28 + 26).loadGraphic(Paths.image('editors/warnings/${isError ? "error" : "warning"}')); add(sprIcon); add(messageSpr = new UIText(sprIcon.x + 100 + 16, sprIcon.y + 12, spr.bWidth - 100 - (26 * 2), message)); diff --git a/source/funkin/menus/PauseSubState.hx b/source/funkin/menus/PauseSubState.hx index 7568c27a..3464f3ce 100644 --- a/source/funkin/menus/PauseSubState.hx +++ b/source/funkin/menus/PauseSubState.hx @@ -22,7 +22,7 @@ class PauseSubState extends MusicBeatSubstate var grpMenuShit:FlxTypedGroup; - var menuItems:Array = ['Resume', 'Restart Song', 'Change Controls', 'Options','Exit to menu']; + var menuItems:Array = ['Resume', 'Restart Song', 'Change Controls', 'Change Options', 'Exit to menu', "Exit to charter"]; var curSelected:Int = 0; var pauseMusic:FlxSound; @@ -42,6 +42,9 @@ class PauseSubState extends MusicBeatSubstate { super.create(); + if (menuItems.contains("Exit to charter") && !PlayState.chartingMode) + menuItems.remove("Exit to charter"); + add(parentDisabler = new FunkinParentDisabler()); pauseScript = Script.create(Paths.script(script)); @@ -147,8 +150,10 @@ class PauseSubState extends MusicBeatSubstate case "Change Controls": persistentDraw = false; openSubState(new KeybindsOptions()); - case "Options": + case "Change Options": FlxG.switchState(new OptionsMenu()); + case "Exit to charter": + FlxG.switchState(new funkin.editors.charter.Charter(PlayState.SONG.meta.name, PlayState.difficulty, false)); case "Exit to menu": CoolUtil.playMenuSong(); FlxG.switchState(PlayState.isStoryMode ? new StoryMenuState() : new FreeplayState());