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());