diff --git a/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx b/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx index dd874577a..bfb860c92 100644 --- a/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx +++ b/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx @@ -97,6 +97,8 @@ class ChartEditorDialogHandler for (chartPath in state.previousWorkingFilePaths) { + if (chartPath == null) continue; + var linkRecentChart:Link = new FunkinLink(); linkRecentChart.text = chartPath; linkRecentChart.onClick = function(_event) { @@ -270,10 +272,6 @@ class ChartEditorDialogHandler }); #end - trace(selectedFile.name); - trace(selectedFile.text); - trace(selectedFile.isBinary); - trace(selectedFile.fullPath); if (selectedFile.fullPath != null) state.currentWorkingFilePath = selectedFile.fullPath; dialog.hideDialog(DialogButton.APPLY); removeDropHandler(onDropFile); @@ -437,6 +435,7 @@ class ChartEditorDialogHandler var uploadVocalsDialog:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog uploadVocalsDialog.onDialogClosed = function(_event) { state.isHaxeUIDialogOpen = false; + state.currentWorkingFilePath = null; // New file, so no path. state.switchToCurrentInstrumental(); state.postLoadInstrumental(); } @@ -495,6 +494,7 @@ class ChartEditorDialogHandler var uploadVocalsDialogErect:Dialog = openUploadVocalsDialog(state, closable); // var uploadVocalsDialog:Dialog uploadVocalsDialogErect.onDialogClosed = function(_event) { state.isHaxeUIDialogOpen = false; + state.currentWorkingFilePath = null; // New file, so no path. state.switchToCurrentInstrumental(); state.postLoadInstrumental(); } diff --git a/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx b/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx index c5cbdd5de..6e9022457 100644 --- a/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx +++ b/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx @@ -361,7 +361,15 @@ class ChartEditorImportExportHandler { // Prompt and save. var onSave:Array->Void = function(paths:Array) { - trace('Successfully exported files.'); + if (paths.length != 1) + { + trace('[WARN] Could not get save path.'); + } + else + { + state.currentWorkingFilePath = paths[0]; + state.applyWindowTitle(); + } }; var onCancel:Void->Void = function() { diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 831afe738..fb91e763d 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -1167,6 +1167,11 @@ class ChartEditorState extends HaxeUIState */ var menubarOpenRecent:Null = null; + /** + * The item in the menubar to save the currently opened chart. + */ + var menubarItemSave:Null = null; + /** * The playbar head slider. */ @@ -1225,10 +1230,21 @@ class ChartEditorState extends HaxeUIState * A list of previous working file paths. * Also known as the "recent files" list. */ - public var previousWorkingFilePaths:Array = []; + public var previousWorkingFilePaths(default, set):Array = []; + + function set_previousWorkingFilePaths(value:Array):Array + { + // Called only when the WHOLE LIST is overridden. + previousWorkingFilePaths = value; + applyWindowTitle(); + populateOpenRecentMenu(); + applyCanQuickSave(); + return value; + } /** * The current file path which the chart editor is working with. + * If `null`, the current chart has not been saved yet. */ public var currentWorkingFilePath(get, set):Null; @@ -1239,10 +1255,14 @@ class ChartEditorState extends HaxeUIState function set_currentWorkingFilePath(value:Null):Null { - if (value == null) return null; - if (value == previousWorkingFilePaths[0]) return value; + if (previousWorkingFilePaths.contains(null)) + { + // Filter all instances of `null` from the array. + previousWorkingFilePaths = previousWorkingFilePaths.filter((x) -> x != null); + } + if (previousWorkingFilePaths.contains(value)) { // Move the path to the front of the list. @@ -1257,11 +1277,12 @@ class ChartEditorState extends HaxeUIState while (previousWorkingFilePaths.length > Constants.MAX_PREVIOUS_WORKING_FILES) { - // Remove the oldest path. + // Remove the last path in the list. previousWorkingFilePaths.pop(); } populateOpenRecentMenu(); + applyWindowTitle(); return value; } @@ -1395,10 +1416,12 @@ class ChartEditorState extends HaxeUIState if (menubarOpenRecent == null) return; #if sys - menubarOpenRecent.clear(); + menubarOpenRecent.removeAllComponents(); for (chartPath in previousWorkingFilePaths) { + if (chartPath == null) continue; + var menuItemRecentChart:FunkinMenuItem = new FunkinMenuItem(); menuItemRecentChart.text = chartPath; menuItemRecentChart.onClick = function(_event) { @@ -1751,6 +1774,9 @@ class ChartEditorState extends HaxeUIState menubarOpenRecent = findComponent('menubarOpenRecent', Menu); if (menubarOpenRecent == null) throw "Could not find menubarOpenRecent!"; + menubarItemSave = findComponent('menubarItemSave', FunkinMenuItem); + if (menubarItemSave == null) throw "Could not find menubarItemSave!"; + // Setup notifications. @:privateAccess NotificationManager.GUTTER_SIZE = 20; @@ -1783,6 +1809,16 @@ class ChartEditorState extends HaxeUIState addUIClickListener('menubarItemNewChart', _ -> ChartEditorDialogHandler.openWelcomeDialog(this, true)); addUIClickListener('menubarItemOpenChart', _ -> ChartEditorDialogHandler.openBrowseFNFC(this, true)); + addUIClickListener('menubarItemSaveChart', _ -> { + if (currentWorkingFilePath != null) + { + ChartEditorImportExportHandler.exportAllSongData(this, true, currentWorkingFilePath); + } + else + { + ChartEditorImportExportHandler.exportAllSongData(this, false); + } + }); addUIClickListener('menubarItemSaveChartAs', _ -> ChartEditorImportExportHandler.exportAllSongData(this)); addUIClickListener('menubarItemLoadInst', _ -> ChartEditorDialogHandler.openUploadInstDialog(this, true)); addUIClickListener('menubarItemImportChart', _ -> ChartEditorDialogHandler.openImportChartDialog(this, 'legacy', true)); @@ -4495,6 +4531,26 @@ class ChartEditorState extends HaxeUIState { NotificationManager.instance.clearNotifications(); } + + function applyCanQuickSave():Void + { + if (currentWorkingFilePath == null) {} + else {} + } + + function applyWindowTitle():Void + { + var inner:String = (currentSongMetadata.songName != null) ? currentSongMetadata.songName : 'Untitled'; + if (currentWorkingFilePath == null) + { + inner += '*'; + } + else + { + inner += ' (${currentWorkingFilePath})'; + } + WindowUtil.setWindowTitle('FNF Chart Editor - ${inner}'); + } } enum LiveInputStyle