package funkin.ui.debug.charting; import funkin.ui.haxeui.components.FunkinDropDown; import flixel.util.FlxTimer; import funkin.data.song.importer.FNFLegacyData; import funkin.data.song.importer.FNFLegacyImporter; import funkin.data.song.SongData.SongCharacterData; import funkin.data.song.SongData.SongChartData; import funkin.data.song.SongData.SongMetadata; import funkin.data.song.SongData.SongTimeChange; import funkin.data.song.SongRegistry; import funkin.input.Cursor; import funkin.play.character.BaseCharacter; import funkin.play.character.CharacterData; import funkin.play.character.CharacterData.CharacterDataParser; import funkin.play.song.Song; import funkin.play.stage.StageData; import funkin.ui.haxeui.components.FunkinLink; import funkin.util.Constants; import funkin.util.FileUtil; import funkin.util.SerializerUtil; import funkin.util.SortUtil; import funkin.util.VersionUtil; import haxe.io.Path; import haxe.ui.components.Button; import haxe.ui.components.DropDown; import haxe.ui.components.Label; import haxe.ui.components.Link; import haxe.ui.components.NumberStepper; import haxe.ui.components.Slider; import haxe.ui.components.TextField; import haxe.ui.containers.Box; import haxe.ui.containers.dialogs.Dialog; import haxe.ui.containers.dialogs.Dialog.DialogButton; import haxe.ui.containers.dialogs.Dialogs; import haxe.ui.containers.Form; import haxe.ui.containers.VBox; import haxe.ui.core.Component; import haxe.ui.events.UIEvent; import haxe.ui.notifications.NotificationManager; import haxe.ui.notifications.NotificationType; import thx.semver.Version; using Lambda; /** * Handles dialogs for the new Chart Editor. */ @:nullSafety class ChartEditorDialogHandler { static final CHART_EDITOR_DIALOG_ABOUT_LAYOUT:String = Paths.ui('chart-editor/dialogs/about'); static final CHART_EDITOR_DIALOG_WELCOME_LAYOUT:String = Paths.ui('chart-editor/dialogs/welcome'); static final CHART_EDITOR_DIALOG_UPLOAD_CHART_LAYOUT:String = Paths.ui('chart-editor/dialogs/upload-chart'); static final CHART_EDITOR_DIALOG_UPLOAD_INST_LAYOUT:String = Paths.ui('chart-editor/dialogs/upload-inst'); static final CHART_EDITOR_DIALOG_SONG_METADATA_LAYOUT:String = Paths.ui('chart-editor/dialogs/song-metadata'); static final CHART_EDITOR_DIALOG_UPLOAD_VOCALS_LAYOUT:String = Paths.ui('chart-editor/dialogs/upload-vocals'); static final CHART_EDITOR_DIALOG_UPLOAD_VOCALS_ENTRY_LAYOUT:String = Paths.ui('chart-editor/dialogs/upload-vocals-entry'); static final CHART_EDITOR_DIALOG_OPEN_CHART_PARTS_LAYOUT:String = Paths.ui('chart-editor/dialogs/open-chart-parts'); static final CHART_EDITOR_DIALOG_OPEN_CHART_PARTS_ENTRY_LAYOUT:String = Paths.ui('chart-editor/dialogs/open-chart-parts-entry'); static final CHART_EDITOR_DIALOG_IMPORT_CHART_LAYOUT:String = Paths.ui('chart-editor/dialogs/import-chart'); static final CHART_EDITOR_DIALOG_USER_GUIDE_LAYOUT:String = Paths.ui('chart-editor/dialogs/user-guide'); static final CHART_EDITOR_DIALOG_ADD_VARIATION_LAYOUT:String = Paths.ui('chart-editor/dialogs/add-variation'); static final CHART_EDITOR_DIALOG_ADD_DIFFICULTY_LAYOUT:String = Paths.ui('chart-editor/dialogs/add-difficulty'); /** * Builds and opens a dialog giving brief credits for the chart editor. * @param state The current chart editor state. * @return The dialog that was opened. */ public static inline function openAboutDialog(state:ChartEditorState):Null { return openDialog(state, CHART_EDITOR_DIALOG_ABOUT_LAYOUT, true, true); } /** * Builds and opens a dialog letting the user create a new chart, open a recent chart, or load from a template. * @param state The current chart editor state. * @param closable Whether the dialog can be closed by the user. * @return The dialog that was opened. */ public static function openWelcomeDialog(state:ChartEditorState, closable:Bool = true):Null { var dialog:Null = openDialog(state, CHART_EDITOR_DIALOG_WELCOME_LAYOUT, true, closable); if (dialog == null) throw 'Could not locate Welcome dialog'; dialog.onDialogClosed = function(_event) { // Called when the Welcome dialog is closed while it is closable. state.stopWelcomeMusic(); } // Create New Song "Easy/Normal/Hard" var linkCreateBasic:Null = dialog.findComponent('splashCreateFromSongBasic', Link); if (linkCreateBasic == null) throw 'Could not locate splashCreateFromSongBasic link in Welcome dialog'; linkCreateBasic.onClick = function(_event) { // Hide the welcome dialog dialog.hideDialog(DialogButton.CANCEL); state.stopWelcomeMusic(); // // Create Song Wizard // openCreateSongWizardBasic(state, false); } // Create New Song "Erect/Nightmare" var linkCreateErect:Null = dialog.findComponent('splashCreateFromSongErect', Link); if (linkCreateErect == null) throw 'Could not locate splashCreateFromSongErect link in Welcome dialog'; linkCreateErect.onClick = function(_event) { // Hide the welcome dialog dialog.hideDialog(DialogButton.CANCEL); // // Create Song Wizard // openCreateSongWizardErect(state, false); } var linkImportChartLegacy:Null = dialog.findComponent('splashImportChartLegacy', Link); if (linkImportChartLegacy == null) throw 'Could not locate splashImportChartLegacy link in Welcome dialog'; linkImportChartLegacy.onClick = function(_event) { // Hide the welcome dialog dialog.hideDialog(DialogButton.CANCEL); state.stopWelcomeMusic(); // Open the "Import Chart" dialog openImportChartWizard(state, 'legacy', false); }; var buttonBrowse:Null