package funkin.ui.debug.charting; import funkin.ui.haxeui.components.FunkinDropDown; import funkin.play.stage.StageData.StageDataParser; import funkin.play.stage.StageData; import funkin.play.character.CharacterData; import funkin.play.character.CharacterData.CharacterDataParser; import haxe.ui.components.HorizontalSlider; import haxe.ui.containers.TreeView; import haxe.ui.containers.TreeViewNode; import funkin.play.character.BaseCharacter.CharacterType; import funkin.play.event.SongEvent; import funkin.data.event.SongEventData; import funkin.data.song.SongData.SongTimeChange; import funkin.play.song.SongSerializer; import funkin.ui.haxeui.components.CharacterPlayer; import funkin.util.FileUtil; import haxe.ui.components.Button; import haxe.ui.components.CheckBox; import haxe.ui.components.DropDown; import haxe.ui.components.Label; import haxe.ui.components.NumberStepper; import haxe.ui.components.Slider; import haxe.ui.components.TextField; import haxe.ui.containers.Box; import haxe.ui.containers.Grid; import haxe.ui.containers.Group; import haxe.ui.containers.VBox; import haxe.ui.containers.Frame; import haxe.ui.containers.dialogs.CollapsibleDialog; import haxe.ui.containers.dialogs.Dialog.DialogButton; import haxe.ui.containers.dialogs.Dialog.DialogEvent; import haxe.ui.core.Component; import haxe.ui.data.ArrayDataSource; import haxe.ui.events.UIEvent; /** * Available tools for the chart editor state. */ enum ChartEditorToolMode { Select; Place; } /** * Static functions which handle building themed UI elements for a provided ChartEditorState. */ @:nullSafety @:allow(funkin.ui.debug.charting.ChartEditorState) class ChartEditorToolboxHandler { public static function setToolboxState(state:ChartEditorState, id:String, shown:Bool):Void { if (shown) { showToolbox(state, id); } else { hideToolbox(state, id); } } public static function showToolbox(state:ChartEditorState, id:String):Void { var toolbox:Null = state.activeToolboxes.get(id); if (toolbox == null) toolbox = initToolbox(state, id); if (toolbox != null) { toolbox.showDialog(false); ChartEditorAudioHandler.playSound(Paths.sound('chartingSounds/openWindow')); switch (id) { case ChartEditorState.CHART_EDITOR_TOOLBOX_TOOLS_LAYOUT: onShowToolboxTools(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT: onShowToolboxNoteData(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_EVENTDATA_LAYOUT: onShowToolboxEventData(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT: onShowToolboxDifficulty(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT: onShowToolboxMetadata(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT: onShowToolboxPlayerPreview(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT: onShowToolboxOpponentPreview(state, toolbox); default: // This happens if you try to load an unknown layout. trace('ChartEditorToolboxHandler.showToolbox() - Unknown toolbox ID: $id'); } } else { trace('ChartEditorToolboxHandler.showToolbox() - Could not retrieve toolbox: $id'); } } public static function hideToolbox(state:ChartEditorState, id:String):Void { var toolbox:Null = state.activeToolboxes.get(id); if (toolbox == null) toolbox = initToolbox(state, id); if (toolbox != null) { toolbox.hideDialog(DialogButton.CANCEL); ChartEditorAudioHandler.playSound(Paths.sound('chartingSounds/exitWindow')); switch (id) { case ChartEditorState.CHART_EDITOR_TOOLBOX_TOOLS_LAYOUT: onHideToolboxTools(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT: onHideToolboxNoteData(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_EVENTDATA_LAYOUT: onHideToolboxEventData(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT: onHideToolboxDifficulty(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT: onHideToolboxMetadata(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT: onHideToolboxPlayerPreview(state, toolbox); case ChartEditorState.CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT: onHideToolboxOpponentPreview(state, toolbox); default: // This happens if you try to load an unknown layout. trace('ChartEditorToolboxHandler.hideToolbox() - Unknown toolbox ID: $id'); } } else { trace('ChartEditorToolboxHandler.hideToolbox() - Could not retrieve toolbox: $id'); } } public static function rememberOpenToolboxes(state:ChartEditorState):Void {} public static function openRememberedToolboxes(state:ChartEditorState):Void {} public static function hideAllToolboxes(state:ChartEditorState):Void { for (toolbox in state.activeToolboxes.values()) { toolbox.hideDialog(DialogButton.CANCEL); } } public static function minimizeToolbox(state:ChartEditorState, id:String):Void { var toolbox:Null = state.activeToolboxes.get(id); if (toolbox == null) return; toolbox.minimized = true; } public static function maximizeToolbox(state:ChartEditorState, id:String):Void { var toolbox:Null = state.activeToolboxes.get(id); if (toolbox == null) return; toolbox.minimized = false; } public static function initToolbox(state:ChartEditorState, id:String):Null { var toolbox:Null = null; switch (id) { case ChartEditorState.CHART_EDITOR_TOOLBOX_TOOLS_LAYOUT: toolbox = buildToolboxToolsLayout(state); case ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT: toolbox = buildToolboxNoteDataLayout(state); case ChartEditorState.CHART_EDITOR_TOOLBOX_EVENTDATA_LAYOUT: toolbox = buildToolboxEventDataLayout(state); case ChartEditorState.CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT: toolbox = buildToolboxDifficultyLayout(state); case ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT: toolbox = buildToolboxMetadataLayout(state); case ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT: toolbox = buildToolboxPlayerPreviewLayout(state); case ChartEditorState.CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT: toolbox = buildToolboxOpponentPreviewLayout(state); default: // This happens if you try to load an unknown layout. trace('ChartEditorToolboxHandler.initToolbox() - Unknown toolbox ID: $id'); toolbox = null; } // This happens if the layout you try to load has a syntax error. if (toolbox == null) return null; // Make sure we can reuse the toolbox later. toolbox.destroyOnClose = false; state.activeToolboxes.set(id, toolbox); return toolbox; } /** * Retrieve a toolbox by its layout's asset ID. * @param state The ChartEditorState instance. * @param id The asset ID of the toolbox layout. * @return The toolbox. */ public static function getToolbox(state:ChartEditorState, id:String):Null { var toolbox:Null = state.activeToolboxes.get(id); // Initialize the toolbox without showing it. if (toolbox == null) toolbox = initToolbox(state, id); if (toolbox == null) throw 'ChartEditorToolboxHandler.getToolbox() - Could not retrieve or build toolbox: $id'; return toolbox; } static function buildToolboxToolsLayout(state:ChartEditorState):Null { var toolbox:CollapsibleDialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_TOOLS_LAYOUT); if (toolbox == null) return null; // Starting position. toolbox.x = 50; toolbox.y = 50; toolbox.onDialogClosed = function(event:DialogEvent) { state.setUICheckboxSelected('menubarItemToggleToolboxTools', false); } var toolsGroup:Null = toolbox.findComponent('toolboxToolsGroup', Group); if (toolsGroup == null) throw 'ChartEditorToolboxHandler.buildToolboxToolsLayout() - Could not find toolboxToolsGroup component.'; if (toolsGroup == null) return null; toolsGroup.onChange = function(event:UIEvent) { switch (event.target.id) { case 'toolboxToolsGroupSelect': state.currentToolMode = ChartEditorToolMode.Select; case 'toolboxToolsGroupPlace': state.currentToolMode = ChartEditorToolMode.Place; default: trace('ChartEditorToolboxHandler.buildToolboxToolsLayout() - Unknown toolbox tool selected: $event.target.id'); } } return toolbox; } static function onShowToolboxTools(state:ChartEditorState, toolbox:CollapsibleDialog):Void {} static function onHideToolboxTools(state:ChartEditorState, toolbox:CollapsibleDialog):Void {} static function buildToolboxNoteDataLayout(state:ChartEditorState):Null { var toolbox:CollapsibleDialog = cast state.buildComponent(ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT); if (toolbox == null) return null; // Starting position. toolbox.x = 75; toolbox.y = 100; toolbox.onDialogClosed = function(event:DialogEvent) { state.setUICheckboxSelected('menubarItemToggleToolboxNotes', false); } var toolboxNotesNoteKind:Null = toolbox.findComponent('toolboxNotesNoteKind', DropDown); if (toolboxNotesNoteKind == null) throw 'ChartEditorToolboxHandler.buildToolboxNoteDataLayout() - Could not find toolboxNotesNoteKind component.'; var toolboxNotesCustomKindLabel:Null