mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2025-02-17 04:11:23 -05:00
Work in progress on backup popup
This commit is contained in:
parent
95b43cce55
commit
27234ddd67
7 changed files with 169 additions and 24 deletions
|
@ -177,6 +177,23 @@ abstract Save(RawSaveData)
|
|||
return this.optionsChartEditor.previousFiles;
|
||||
}
|
||||
|
||||
public var chartEditorHasBackup(get, set):Bool;
|
||||
|
||||
function get_chartEditorHasBackup():Bool
|
||||
{
|
||||
if (this.optionsChartEditor.hasBackup == null) this.optionsChartEditor.hasBackup = [];
|
||||
|
||||
return this.optionsChartEditor.hasBackup;
|
||||
}
|
||||
|
||||
function set_chartEditorHasBackup(value:Array<String>):Bool
|
||||
{
|
||||
// Set and apply.
|
||||
this.optionsChartEditor.hasBackup = value;
|
||||
flush();
|
||||
return this.optionsChartEditor.hasBackup;
|
||||
}
|
||||
|
||||
public var chartEditorNoteQuant(get, set):Int;
|
||||
|
||||
function get_chartEditorNoteQuant():Int
|
||||
|
@ -926,6 +943,13 @@ typedef SaveControlsData =
|
|||
*/
|
||||
typedef SaveDataChartEditorOptions =
|
||||
{
|
||||
/**
|
||||
* Whether the Chart Editor created a backup the last time it closed.
|
||||
* Prompt the user to load it, then set this back to `false`.
|
||||
* @default `false`
|
||||
*/
|
||||
var ?hasBackup:Bool;
|
||||
|
||||
/**
|
||||
* Previous files opened in the Chart Editor.
|
||||
* @default `[]`
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package funkin.ui.debug.charting;
|
||||
|
||||
import funkin.util.logging.CrashHandler;
|
||||
import haxe.ui.containers.menus.MenuBar;
|
||||
import flixel.addons.display.FlxSliceSprite;
|
||||
import flixel.addons.display.FlxTiledSprite;
|
||||
|
@ -779,6 +780,18 @@ class ChartEditorState extends HaxeUIState
|
|||
return saveDataDirty;
|
||||
}
|
||||
|
||||
var shouldShowBackupAvailableDialog(get, set):Bool;
|
||||
|
||||
function get_shouldShowBackupAvailableDialog():Bool
|
||||
{
|
||||
return Save.get().chartEditorHasBackup;
|
||||
}
|
||||
|
||||
function set_shouldShowBackupAvailableDialog(value:Bool):Bool
|
||||
{
|
||||
return Save.get().chartEditorHasBackup = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the difficulty tree view in the toolbox has been modified and needs to be updated.
|
||||
* This happens when we add/remove difficulties.
|
||||
|
@ -1498,7 +1511,7 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
buildAdditionalUI();
|
||||
populateOpenRecentMenu();
|
||||
ChartEditorShortcutHandler.applyPlatformShortcutText(this);
|
||||
this.applyPlatformShortcutText();
|
||||
|
||||
// Setup the onClick listeners for the UI after it's been created.
|
||||
setupUIListeners();
|
||||
|
@ -1511,7 +1524,7 @@ class ChartEditorState extends HaxeUIState
|
|||
if (params != null && params.fnfcTargetPath != null)
|
||||
{
|
||||
// Chart editor was opened from the command line. Open the FNFC file now!
|
||||
var result:Null<Array<String>> = ChartEditorImportExportHandler.loadFromFNFCPath(this, params.fnfcTargetPath);
|
||||
var result:Null<Array<String>> = this.loadFromFNFCPath(params.fnfcTargetPath);
|
||||
if (result != null)
|
||||
{
|
||||
#if !mac
|
||||
|
@ -1537,8 +1550,8 @@ class ChartEditorState extends HaxeUIState
|
|||
#end
|
||||
|
||||
// Song failed to load, open the Welcome dialog so we aren't in a broken state.
|
||||
ChartEditorDialogHandler.openWelcomeDialog(this, false);
|
||||
}
|
||||
this.openWelcomeDialog(false);
|
||||
if (shouldShowBackupAvailableDialog)}
|
||||
}
|
||||
else if (params != null && params.targetSongId != null)
|
||||
{
|
||||
|
@ -1546,7 +1559,7 @@ class ChartEditorState extends HaxeUIState
|
|||
}
|
||||
else
|
||||
{
|
||||
ChartEditorDialogHandler.openWelcomeDialog(this, false);
|
||||
this.openWelcomeDialog(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1560,6 +1573,7 @@ class ChartEditorState extends HaxeUIState
|
|||
{
|
||||
var save:Save = Save.get();
|
||||
|
||||
showBackupAvailablePopup = save.chartEditorHasBackup;
|
||||
if (previousWorkingFilePaths[0] == null)
|
||||
{
|
||||
previousWorkingFilePaths = [null].concat(save.chartEditorPreviousFiles);
|
||||
|
@ -1583,7 +1597,7 @@ class ChartEditorState extends HaxeUIState
|
|||
// audioVocalTrackGroup.pitch = save.chartEditorPlaybackSpeed;
|
||||
}
|
||||
|
||||
public function writePreferences():Void
|
||||
public function writePreferences(hasBackup:Bool):Void
|
||||
{
|
||||
var save:Save = Save.get();
|
||||
|
||||
|
@ -1592,6 +1606,7 @@ class ChartEditorState extends HaxeUIState
|
|||
for (chartPath in previousWorkingFilePaths)
|
||||
if (chartPath != null) filteredWorkingFilePaths.push(chartPath);
|
||||
|
||||
save.chartEditorHasBackup = hasBackup;
|
||||
save.chartEditorPreviousFiles = filteredWorkingFilePaths;
|
||||
save.chartEditorNoteQuant = noteSnapQuantIndex;
|
||||
save.chartEditorLiveInputStyle = currentLiveInputStyle;
|
||||
|
@ -1624,7 +1639,7 @@ class ChartEditorState extends HaxeUIState
|
|||
stopWelcomeMusic();
|
||||
|
||||
// Load chart from file
|
||||
var result:Null<Array<String>> = ChartEditorImportExportHandler.loadFromFNFCPath(this, chartPath);
|
||||
var result:Null<Array<String>> = this.loadFromFNFCPath(chartPath);
|
||||
if (result != null)
|
||||
{
|
||||
#if !mac
|
||||
|
@ -2017,21 +2032,21 @@ class ChartEditorState extends HaxeUIState
|
|||
|
||||
// Add functionality to the menu items.
|
||||
|
||||
addUIClickListener('menubarItemNewChart', _ -> ChartEditorDialogHandler.openWelcomeDialog(this, true));
|
||||
addUIClickListener('menubarItemOpenChart', _ -> ChartEditorDialogHandler.openBrowseFNFC(this, true));
|
||||
addUIClickListener('menubarItemNewChart', _ -> this.openWelcomeDialog(true));
|
||||
addUIClickListener('menubarItemOpenChart', _ -> this.openBrowseFNFC(true));
|
||||
addUIClickListener('menubarItemSaveChart', _ -> {
|
||||
if (currentWorkingFilePath != null)
|
||||
{
|
||||
ChartEditorImportExportHandler.exportAllSongData(this, true, currentWorkingFilePath);
|
||||
this.exportAllSongData(true, currentWorkingFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
ChartEditorImportExportHandler.exportAllSongData(this, false);
|
||||
this.exportAllSongData(false);
|
||||
}
|
||||
});
|
||||
addUIClickListener('menubarItemSaveChartAs', _ -> ChartEditorImportExportHandler.exportAllSongData(this));
|
||||
addUIClickListener('menubarItemLoadInst', _ -> ChartEditorDialogHandler.openUploadInstDialog(this, true));
|
||||
addUIClickListener('menubarItemImportChart', _ -> ChartEditorDialogHandler.openImportChartDialog(this, 'legacy', true));
|
||||
addUIClickListener('menubarItemSaveChartAs', _ -> this.exportAllSongData());
|
||||
addUIClickListener('menubarItemLoadInst', _ -> this.openUploadInstDialog(true));
|
||||
addUIClickListener('menubarItemImportChart', _ -> this.openImportChartDialog('legacy', true));
|
||||
addUIClickListener('menubarItemExit', _ -> quitChartEditor());
|
||||
|
||||
addUIClickListener('menubarItemUndo', _ -> undoLastCommand());
|
||||
|
@ -2227,7 +2242,13 @@ class ChartEditorState extends HaxeUIState
|
|||
*/
|
||||
function setupAutoSave():Void
|
||||
{
|
||||
// Called when clicking the X button on the window.
|
||||
WindowUtil.windowExit.add(onWindowClose);
|
||||
|
||||
// Called when the game crashes.
|
||||
CrashHandler.errorSignal.add(onWindowCrash);
|
||||
CrashHandler.criticalErrorSignal.add(onWindowCrash);
|
||||
|
||||
saveDataDirty = false;
|
||||
}
|
||||
|
||||
|
@ -2239,7 +2260,7 @@ class ChartEditorState extends HaxeUIState
|
|||
saveDataDirty = false;
|
||||
|
||||
// Auto-save preferences.
|
||||
writePreferences();
|
||||
writePreferences(false);
|
||||
|
||||
// Auto-save the chart.
|
||||
#if html5
|
||||
|
@ -2247,24 +2268,51 @@ class ChartEditorState extends HaxeUIState
|
|||
// TODO: Implement this.
|
||||
#else
|
||||
// Auto-save to temp file.
|
||||
ChartEditorImportExportHandler.exportAllSongData(this, true);
|
||||
this.exportAllSongData(true);
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the window was closed, to save a backup of the chart.
|
||||
* @param exitCode The exit code of the window. We use `-1` when calling the function due to a game crash.
|
||||
*/
|
||||
function onWindowClose(exitCode:Int):Void
|
||||
{
|
||||
trace('Window exited with exit code: $exitCode');
|
||||
trace('Should save chart? $saveDataDirty');
|
||||
|
||||
if (saveDataDirty)
|
||||
var needsAutoSave:Bool = saveDataDirty;
|
||||
|
||||
writePreferences(needsAutoSave);
|
||||
|
||||
if (needsAutoSave)
|
||||
{
|
||||
ChartEditorImportExportHandler.exportAllSongData(this, true);
|
||||
this.exportAllSongData(true);
|
||||
}
|
||||
}
|
||||
|
||||
function onWindowCrash(message:String):Void
|
||||
{
|
||||
trace('Chart editor intercepted crash:');
|
||||
trace('${message}');
|
||||
|
||||
trace('Should save chart? $saveDataDirty');
|
||||
|
||||
var needsAutoSave:Bool = saveDataDirty;
|
||||
|
||||
writePreferences(needsAutoSave);
|
||||
|
||||
if (needsAutoSave)
|
||||
{
|
||||
this.exportAllSongData(true);
|
||||
}
|
||||
}
|
||||
|
||||
function cleanupAutoSave():Void
|
||||
{
|
||||
WindowUtil.windowExit.remove(onWindowClose);
|
||||
CrashHandler.errorSignal.remove(onWindowCrash);
|
||||
CrashHandler.criticalErrorSignal.remove(onWindowCrash);
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float):Void
|
||||
|
@ -3965,12 +4013,12 @@ class ChartEditorState extends HaxeUIState
|
|||
if (currentWorkingFilePath == null || FlxG.keys.pressed.SHIFT)
|
||||
{
|
||||
// CTRL + SHIFT + S = Save As
|
||||
ChartEditorImportExportHandler.exportAllSongData(this, false);
|
||||
this.exportAllSongData(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// CTRL + S = Save Chart
|
||||
ChartEditorImportExportHandler.exportAllSongData(this, true, currentWorkingFilePath);
|
||||
this.exportAllSongData(true, currentWorkingFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4138,6 +4186,14 @@ class ChartEditorState extends HaxeUIState
|
|||
{
|
||||
// F1 = Open Help
|
||||
if (FlxG.keys.justPressed.F1) this.openUserGuideDialog();
|
||||
|
||||
// DEBUG KEYBIND: Ctrl + Alt + Shift + L = Crash the game.
|
||||
#if debug
|
||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.L)
|
||||
{
|
||||
throw "DEBUG: Crashing the chart editor!";
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
override function handleQuickWatch():Void
|
||||
|
@ -4861,9 +4917,9 @@ class ChartEditorState extends HaxeUIState
|
|||
switch (noteData.getStrumlineIndex())
|
||||
{
|
||||
case 0: // Player
|
||||
if (hitsoundsEnabledPlayer) ChartEditorAudioHandler.playSound(this, Paths.sound('chartingSounds/hitNotePlayer'));
|
||||
if (hitsoundsEnabledPlayer) this.playSound(Paths.sound('chartingSounds/hitNotePlayer'));
|
||||
case 1: // Opponent
|
||||
if (hitsoundsEnabledOpponent) ChartEditorAudioHandler.playSound(this, Paths.sound('chartingSounds/hitNoteOpponent'));
|
||||
if (hitsoundsEnabledOpponent) this.playSound(Paths.sound('chartingSounds/hitNoteOpponent'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -250,6 +250,39 @@ class ChartEditorDialogHandler
|
|||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Description]
|
||||
* @param state
|
||||
* @return Null<Dialog>
|
||||
*/
|
||||
public static function openBackupAvailableDialog(state:ChartEditorState):Null<Dialog>
|
||||
{
|
||||
var dialog:Null<Dialog> = openDialog(state, CHART_EDITOR_DIALOG_BACKUP_AVAILABLE_LAYOUT, true, true);
|
||||
if (dialog == null) throw 'Could not locate Backup Available dialog';
|
||||
|
||||
state.isHaxeUIDialogOpen = true;
|
||||
|
||||
var buttonCancel:Null<Button> = dialog.findComponent('dialogCancel', Button);
|
||||
if (buttonCancel == null) throw 'Could not locate dialogCancel button in Backup Available dialog';
|
||||
buttonCancel.onClick = function(_event) {
|
||||
dialog.hideDialog(DialogButton.CANCEL);
|
||||
}
|
||||
|
||||
var buttonGoToFolder:Null<Button> = dialog.findComponent('buttonGoToFolder', Button);
|
||||
if (buttonGoToFolder == null) throw 'Could not locate buttonGoToFolder button in Backup Available dialog';
|
||||
buttonGoToFolder.onClick = function(_event) {
|
||||
dialog.hideDialog(DialogButton.CANCEL);
|
||||
state.openBackupFolder();
|
||||
}
|
||||
|
||||
var buttonOpenBackup:Null<Button> = dialog.findComponent('buttonOpenBackup', Button);
|
||||
if (buttonOpenBackup == null) throw 'Could not locate buttonOpenBackup button in Backup Available dialog';
|
||||
buttonOpenBackup.onClick = function(_event) {
|
||||
dialog.hideDialog(DialogButton.CANCEL);
|
||||
state.openBackup();
|
||||
}
|
||||
}
|
||||
|
||||
public static function openBrowseFNFC(state:ChartEditorState, closable:Bool):Null<Dialog>
|
||||
{
|
||||
var dialog:Null<Dialog> = openDialog(state, CHART_EDITOR_DIALOG_UPLOAD_CHART_LAYOUT, true, closable);
|
||||
|
|
|
@ -318,6 +318,16 @@ class ChartEditorImportExportHandler
|
|||
return warnings;
|
||||
}
|
||||
|
||||
public static function getLatestBackupPath()
|
||||
{
|
||||
throw 'Not implemented yet.';
|
||||
}
|
||||
|
||||
public static function getLatestBackupDate()
|
||||
{
|
||||
throw 'Not implemented yet.';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param force Whether to export without prompting. `false` will prompt the user for a location.
|
||||
* @param targetPath where to export if `force` is `true`. If `null`, will export to the `backups` folder.
|
||||
|
@ -375,7 +385,6 @@ class ChartEditorImportExportHandler
|
|||
// We have to force write because the program will die before the save dialog is closed.
|
||||
trace('Force exporting to $targetPath...');
|
||||
FileUtil.saveFilesAsZIPToPath(zipEntries, targetPath, targetMode);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -383,7 +392,6 @@ class ChartEditorImportExportHandler
|
|||
trace('Force exporting to $targetPath...');
|
||||
FileUtil.saveFilesAsZIPToPath(zipEntries, targetPath, targetMode);
|
||||
state.saveDataDirty = false;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -5,6 +5,7 @@ package funkin.ui.debug.charting;
|
|||
using funkin.ui.debug.charting.handlers.ChartEditorAudioHandler;
|
||||
using funkin.ui.debug.charting.handlers.ChartEditorDialogHandler;
|
||||
using funkin.ui.debug.charting.handlers.ChartEditorImportExportHandler;
|
||||
using funkin.ui.debug.charting.handlers.ChartEditorShortcutHandler;
|
||||
using funkin.ui.debug.charting.handlers.ChartEditorThemeHandler;
|
||||
using funkin.ui.debug.charting.handlers.ChartEditorToolboxHandler;
|
||||
#end
|
||||
|
|
|
@ -73,6 +73,11 @@ class FileUtil
|
|||
#end
|
||||
}
|
||||
|
||||
public static function openFolderInExplorer():Void
|
||||
{
|
||||
throw 'Not implemented yet.';
|
||||
}
|
||||
|
||||
/**
|
||||
* Browses for multiple file, then calls `onSelect(paths)` when a path chosen.
|
||||
* Note that on HTML5 this will immediately fail.
|
||||
|
|
|
@ -2,6 +2,7 @@ package funkin.util.logging;
|
|||
|
||||
import openfl.Lib;
|
||||
import openfl.events.UncaughtErrorEvent;
|
||||
import flixel.util.FlxSignal.FlxTypedSignal;
|
||||
|
||||
/**
|
||||
* A custom crash handler that writes to a log file and displays a message box.
|
||||
|
@ -11,6 +12,19 @@ class CrashHandler
|
|||
{
|
||||
static final LOG_FOLDER = 'logs';
|
||||
|
||||
/**
|
||||
* Called before exiting the game when a standard error occurs, like a thrown exception.
|
||||
* @param message The error message.
|
||||
*/
|
||||
public static var errorSignal(default, null):FlxTypedSignal<String->Void> = new FlxTypedSignal<String->Void>();
|
||||
|
||||
/**
|
||||
* Called before exiting the game when a critical error occurs, like a stack overflow or null object reference.
|
||||
* CAREFUL: The game may be in an unstable state when this is called.
|
||||
* @param message The error message.
|
||||
*/
|
||||
public static var criticalErrorSignal(default, null):FlxTypedSignal<String->Void> = new FlxTypedSignal<String->Void>();
|
||||
|
||||
/**
|
||||
* Initializes
|
||||
*/
|
||||
|
@ -34,6 +48,8 @@ class CrashHandler
|
|||
{
|
||||
try
|
||||
{
|
||||
errorSignal.dispatch(generateErrorMessage(error));
|
||||
|
||||
#if sys
|
||||
logError(error);
|
||||
#end
|
||||
|
@ -50,6 +66,8 @@ class CrashHandler
|
|||
{
|
||||
try
|
||||
{
|
||||
criticalErrorSignal.dispatch(message);
|
||||
|
||||
#if sys
|
||||
logErrorMessage(message, true);
|
||||
#end
|
||||
|
|
Loading…
Reference in a new issue