Funkin/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx

443 lines
16 KiB
Haxe
Raw Normal View History

package funkin.ui.debug.charting.handlers;
import funkin.data.stage.StageData;
import funkin.play.character.CharacterData;
import funkin.play.character.CharacterData.CharacterDataParser;
2023-09-12 23:37:07 -04:00
import haxe.ui.components.HorizontalSlider;
import haxe.ui.containers.TreeView;
import haxe.ui.containers.TreeViewNode;
import funkin.play.character.BaseCharacter.CharacterType;
2023-01-22 19:55:30 -05:00
import funkin.play.event.SongEvent;
import funkin.data.event.SongEventSchema;
import funkin.data.song.SongData.SongTimeChange;
import funkin.play.character.BaseCharacter.CharacterType;
import funkin.play.character.CharacterData;
import funkin.play.character.CharacterData.CharacterDataParser;
2023-01-22 19:55:30 -05:00
import funkin.play.event.SongEvent;
import funkin.play.song.SongSerializer;
import funkin.data.stage.StageData;
import haxe.ui.RuntimeComponentBuilder;
import funkin.ui.debug.charting.util.ChartEditorDropdowns;
2023-01-22 19:55:30 -05:00
import funkin.ui.haxeui.components.CharacterPlayer;
import funkin.util.FileUtil;
import haxe.ui.components.Button;
import haxe.ui.data.ArrayDataSource;
2023-01-22 19:55:30 -05:00
import haxe.ui.components.CheckBox;
import haxe.ui.components.DropDown;
import haxe.ui.components.HorizontalSlider;
2023-01-22 19:55:30 -05:00
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;
2023-06-08 16:48:34 -04:00
import haxe.ui.containers.dialogs.CollapsibleDialog;
import haxe.ui.containers.dialogs.Dialog.DialogButton;
import haxe.ui.containers.dialogs.Dialog.DialogEvent;
import funkin.ui.debug.charting.toolboxes.ChartEditorBaseToolbox;
import funkin.ui.debug.charting.toolboxes.ChartEditorMetadataToolbox;
import funkin.ui.debug.charting.toolboxes.ChartEditorEventDataToolbox;
import funkin.ui.debug.charting.toolboxes.ChartEditorDifficultyToolbox;
import haxe.ui.containers.Frame;
import haxe.ui.containers.Grid;
import haxe.ui.containers.TreeView;
import haxe.ui.containers.TreeViewNode;
2023-01-22 19:55:30 -05:00
import haxe.ui.core.Component;
import haxe.ui.events.UIEvent;
2023-06-08 16:48:34 -04:00
/**
* Static functions which handle building themed UI elements for a provided ChartEditorState.
*/
2023-08-31 18:47:23 -04:00
@:nullSafety
@:access(funkin.ui.debug.charting.ChartEditorState)
class ChartEditorToolboxHandler
{
2023-01-22 19:55:30 -05:00
public static function setToolboxState(state:ChartEditorState, id:String, shown:Bool):Void
{
2023-06-08 16:48:34 -04:00
if (shown)
{
showToolbox(state, id);
}
2023-01-22 19:55:30 -05:00
else
2023-06-08 16:48:34 -04:00
{
2023-01-22 19:55:30 -05:00
hideToolbox(state, id);
2023-06-08 16:48:34 -04:00
}
2023-01-22 19:55:30 -05:00
}
2023-06-08 16:48:34 -04:00
public static function showToolbox(state:ChartEditorState, id:String):Void
2023-01-22 19:55:30 -05:00
{
2023-08-31 18:47:23 -04:00
var toolbox:Null<CollapsibleDialog> = state.activeToolboxes.get(id);
2023-01-22 19:55:30 -05:00
if (toolbox == null) toolbox = initToolbox(state, id);
2023-01-22 19:55:30 -05:00
if (toolbox != null)
{
toolbox.showDialog(false);
state.playSound(Paths.sound('chartingSounds/openWindow'));
2023-10-11 19:39:52 -04:00
switch (id)
{
case ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT:
onShowToolboxNoteData(state, toolbox);
case ChartEditorState.CHART_EDITOR_TOOLBOX_EVENT_DATA_LAYOUT:
// TODO: Fix this.
cast(toolbox, ChartEditorBaseToolbox).refresh();
2023-12-10 03:37:12 -05:00
case ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYTEST_PROPERTIES_LAYOUT:
onShowToolboxPlaytestProperties(state, toolbox);
case ChartEditorState.CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT:
cast(toolbox, ChartEditorBaseToolbox).refresh();
case ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT:
// TODO: Fix this.
cast(toolbox, ChartEditorBaseToolbox).refresh();
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');
}
2023-01-22 19:55:30 -05:00
}
else
{
trace('ChartEditorToolboxHandler.showToolbox() - Could not retrieve toolbox: $id');
}
}
public static function hideToolbox(state:ChartEditorState, id:String):Void
{
2023-08-31 18:47:23 -04:00
var toolbox:Null<CollapsibleDialog> = state.activeToolboxes.get(id);
2023-01-22 19:55:30 -05:00
if (toolbox == null) toolbox = initToolbox(state, id);
2023-01-22 19:55:30 -05:00
if (toolbox != null)
{
toolbox.hideDialog(DialogButton.CANCEL);
state.playSound(Paths.sound('chartingSounds/exitWindow'));
2023-10-11 19:39:52 -04:00
switch (id)
{
case ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT:
onHideToolboxNoteData(state, toolbox);
case ChartEditorState.CHART_EDITOR_TOOLBOX_EVENT_DATA_LAYOUT:
onHideToolboxEventData(state, toolbox);
2023-12-10 03:37:12 -05:00
case ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYTEST_PROPERTIES_LAYOUT:
onHideToolboxPlaytestProperties(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');
}
2023-01-22 19:55:30 -05:00
}
else
{
trace('ChartEditorToolboxHandler.hideToolbox() - Could not retrieve toolbox: $id');
}
}
public static function refreshToolbox(state:ChartEditorState, id:String):Void
{
var toolbox:Null<ChartEditorBaseToolbox> = cast state.activeToolboxes.get(id);
if (toolbox == null) return;
if (toolbox != null)
{
toolbox.refresh();
}
else
{
trace('ChartEditorToolboxHandler.refreshToolbox() - 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);
}
}
2023-06-08 16:48:34 -04:00
public static function minimizeToolbox(state:ChartEditorState, id:String):Void
{
2023-08-31 18:47:23 -04:00
var toolbox:Null<CollapsibleDialog> = state.activeToolboxes.get(id);
2023-06-08 16:48:34 -04:00
if (toolbox == null) return;
2023-01-22 19:55:30 -05:00
2023-06-08 16:48:34 -04:00
toolbox.minimized = true;
}
2023-01-22 19:55:30 -05:00
2023-06-08 16:48:34 -04:00
public static function maximizeToolbox(state:ChartEditorState, id:String):Void
2023-01-22 19:55:30 -05:00
{
2023-08-31 18:47:23 -04:00
var toolbox:Null<CollapsibleDialog> = state.activeToolboxes.get(id);
2023-06-08 16:48:34 -04:00
if (toolbox == null) return;
toolbox.minimized = false;
}
2023-08-31 18:47:23 -04:00
public static function initToolbox(state:ChartEditorState, id:String):Null<CollapsibleDialog>
2023-06-08 16:48:34 -04:00
{
2023-08-31 18:47:23 -04:00
var toolbox:Null<CollapsibleDialog> = null;
2023-01-22 19:55:30 -05:00
switch (id)
{
case ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT:
toolbox = buildToolboxNoteDataLayout(state);
case ChartEditorState.CHART_EDITOR_TOOLBOX_EVENT_DATA_LAYOUT:
2023-01-22 19:55:30 -05:00
toolbox = buildToolboxEventDataLayout(state);
2023-12-10 03:37:12 -05:00
case ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYTEST_PROPERTIES_LAYOUT:
toolbox = buildToolboxPlaytestPropertiesLayout(state);
2023-01-22 19:55:30 -05:00
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);
2023-01-22 19:55:30 -05:00
case ChartEditorState.CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT:
toolbox = buildToolboxOpponentPreviewLayout(state);
2023-01-22 19:55:30 -05:00
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;
2023-01-22 19:55:30 -05:00
// Make sure we can reuse the toolbox later.
toolbox.destroyOnClose = false;
state.activeToolboxes.set(id, toolbox);
return toolbox;
}
2023-06-08 16:48:34 -04:00
/**
* 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_OLD(state:ChartEditorState, id:String):Null<CollapsibleDialog>
2023-01-22 19:55:30 -05:00
{
2023-08-31 18:47:23 -04:00
var toolbox:Null<CollapsibleDialog> = state.activeToolboxes.get(id);
2023-01-22 19:55:30 -05:00
// Initialize the toolbox without showing it.
if (toolbox == null) toolbox = initToolbox(state, id);
2023-01-22 19:55:30 -05:00
if (toolbox == null) throw 'ChartEditorToolboxHandler.getToolbox_OLD() - Could not retrieve or build toolbox: $id';
2023-01-22 19:55:30 -05:00
return toolbox;
}
public static function getToolbox(state:ChartEditorState, id:String):Null<ChartEditorBaseToolbox>
{
var toolbox:Null<CollapsibleDialog> = 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 cast toolbox;
}
2023-08-31 18:47:23 -04:00
static function buildToolboxNoteDataLayout(state:ChartEditorState):Null<CollapsibleDialog>
2023-01-22 19:55:30 -05:00
{
var toolbox:CollapsibleDialog = cast RuntimeComponentBuilder.fromAsset(ChartEditorState.CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT);
2023-01-22 19:55:30 -05:00
if (toolbox == null) return null;
2023-01-22 19:55:30 -05:00
// Starting position.
toolbox.x = 75;
toolbox.y = 100;
2023-06-08 16:48:34 -04:00
toolbox.onDialogClosed = function(event:DialogEvent) {
state.menubarItemToggleToolboxNotes.selected = false;
2023-01-22 19:55:30 -05:00
}
2023-08-31 18:47:23 -04:00
var toolboxNotesNoteKind:Null<DropDown> = toolbox.findComponent('toolboxNotesNoteKind', DropDown);
if (toolboxNotesNoteKind == null) throw 'ChartEditorToolboxHandler.buildToolboxNoteDataLayout() - Could not find toolboxNotesNoteKind component.';
var toolboxNotesCustomKindLabel:Null<Label> = toolbox.findComponent('toolboxNotesCustomKindLabel', Label);
if (toolboxNotesCustomKindLabel == null)
throw 'ChartEditorToolboxHandler.buildToolboxNoteDataLayout() - Could not find toolboxNotesCustomKindLabel component.';
var toolboxNotesCustomKind:Null<TextField> = toolbox.findComponent('toolboxNotesCustomKind', TextField);
if (toolboxNotesCustomKind == null) throw 'ChartEditorToolboxHandler.buildToolboxNoteDataLayout() - Could not find toolboxNotesCustomKind component.';
2023-01-22 19:55:30 -05:00
2023-06-08 16:48:34 -04:00
toolboxNotesNoteKind.onChange = function(event:UIEvent) {
var isCustom:Bool = (event.data.id == '~CUSTOM~');
2023-01-22 19:55:30 -05:00
if (isCustom)
{
toolboxNotesCustomKindLabel.hidden = false;
toolboxNotesCustomKind.hidden = false;
state.noteKindToPlace = toolboxNotesCustomKind.text;
2023-01-22 19:55:30 -05:00
}
else
{
toolboxNotesCustomKindLabel.hidden = true;
toolboxNotesCustomKind.hidden = true;
state.noteKindToPlace = event.data.id;
2023-01-22 19:55:30 -05:00
}
}
2023-06-08 16:48:34 -04:00
toolboxNotesCustomKind.onChange = function(event:UIEvent) {
state.noteKindToPlace = toolboxNotesCustomKind.text;
2023-01-22 19:55:30 -05:00
}
return toolbox;
}
static function onShowToolboxNoteData(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
static function onHideToolboxNoteData(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
static function onHideToolboxMetadata(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
2023-01-22 19:55:30 -05:00
static function onHideToolboxEventData(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
2023-01-22 19:55:30 -05:00
2023-12-10 03:37:12 -05:00
static function onShowToolboxPlaytestProperties(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
static function onHideToolboxPlaytestProperties(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
static function buildToolboxPlaytestPropertiesLayout(state:ChartEditorState):Null<CollapsibleDialog>
{
// fill with playtest properties
var toolbox:CollapsibleDialog = cast RuntimeComponentBuilder.fromAsset(ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYTEST_PROPERTIES_LAYOUT);
if (toolbox == null) return null;
2023-12-10 03:49:24 -05:00
toolbox.onDialogClosed = function(_) {
state.menubarItemToggleToolboxPlaytestProperties.selected = false;
}
2023-12-10 03:37:12 -05:00
var checkboxPracticeMode:Null<CheckBox> = toolbox.findComponent('practiceModeCheckbox', CheckBox);
if (checkboxPracticeMode == null) throw 'ChartEditorToolboxHandler.buildToolboxPlaytestPropertiesLayout() - Could not find practiceModeCheckbox component.';
checkboxPracticeMode.selected = state.playtestPracticeMode;
2023-12-10 03:37:12 -05:00
checkboxPracticeMode.onClick = _ -> {
state.playtestPracticeMode = checkboxPracticeMode.selected;
};
var checkboxStartTime:Null<CheckBox> = toolbox.findComponent('playtestStartTimeCheckbox', CheckBox);
if (checkboxStartTime == null)
throw 'ChartEditorToolboxHandler.buildToolboxPlaytestPropertiesLayout() - Could not find playtestStartTimeCheckbox component.';
checkboxStartTime.selected = state.playtestStartTime;
checkboxStartTime.onClick = _ -> {
state.playtestStartTime = checkboxStartTime.selected;
};
2023-12-15 02:29:32 -05:00
var checkboxDebugger:Null<CheckBox> = toolbox.findComponent('playtestDebuggerCheckbox', CheckBox);
if (checkboxDebugger == null) throw 'ChartEditorToolboxHandler.buildToolboxPlaytestPropertiesLayout() - Could not find playtestDebuggerCheckbox component.';
state.enabledDebuggerPopup = checkboxDebugger.selected;
checkboxDebugger.onClick = _ -> {
state.enabledDebuggerPopup = checkboxDebugger.selected;
};
2023-12-10 03:37:12 -05:00
return toolbox;
}
static function buildToolboxDifficultyLayout(state:ChartEditorState):Null<ChartEditorBaseToolbox>
2023-01-22 19:55:30 -05:00
{
var toolbox:ChartEditorBaseToolbox = ChartEditorDifficultyToolbox.build(state);
2023-01-22 19:55:30 -05:00
if (toolbox == null) return null;
2023-01-22 19:55:30 -05:00
return toolbox;
}
static function buildToolboxMetadataLayout(state:ChartEditorState):Null<ChartEditorBaseToolbox>
2023-01-22 19:55:30 -05:00
{
var toolbox:ChartEditorBaseToolbox = ChartEditorMetadataToolbox.build(state);
2023-01-22 19:55:30 -05:00
if (toolbox == null) return null;
2023-01-22 19:55:30 -05:00
return toolbox;
}
static function buildToolboxEventDataLayout(state:ChartEditorState):Null<ChartEditorBaseToolbox>
{
var toolbox:ChartEditorBaseToolbox = ChartEditorEventDataToolbox.build(state);
if (toolbox == null) return null;
return toolbox;
}
2023-08-31 18:47:23 -04:00
static function buildToolboxPlayerPreviewLayout(state:ChartEditorState):Null<CollapsibleDialog>
2023-01-22 19:55:30 -05:00
{
var toolbox:CollapsibleDialog = cast RuntimeComponentBuilder.fromAsset(ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT);
2023-01-22 19:55:30 -05:00
if (toolbox == null) return null;
2023-01-22 19:55:30 -05:00
// Starting position.
toolbox.x = 200;
toolbox.y = 350;
2023-06-08 16:48:34 -04:00
toolbox.onDialogClosed = function(event:DialogEvent) {
state.menubarItemToggleToolboxPlayerPreview.selected = false;
2023-01-22 19:55:30 -05:00
}
2023-08-31 18:47:23 -04:00
var charPlayer:Null<CharacterPlayer> = toolbox.findComponent('charPlayer');
if (charPlayer == null) throw 'ChartEditorToolboxHandler.buildToolboxPlayerPreviewLayout() - Could not find charPlayer component.';
2023-01-22 19:55:30 -05:00
// TODO: We need to implement character swapping in ChartEditorState.
charPlayer.loadCharacter('bf');
2023-06-08 16:48:34 -04:00
charPlayer.characterType = CharacterType.BF;
2023-01-22 19:55:30 -05:00
charPlayer.flip = true;
2023-06-08 16:48:34 -04:00
charPlayer.targetScale = 0.5;
2023-01-22 19:55:30 -05:00
return toolbox;
}
static function onShowToolboxPlayerPreview(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
static function onHideToolboxPlayerPreview(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
2023-08-31 18:47:23 -04:00
static function buildToolboxOpponentPreviewLayout(state:ChartEditorState):Null<CollapsibleDialog>
2023-01-22 19:55:30 -05:00
{
var toolbox:CollapsibleDialog = cast RuntimeComponentBuilder.fromAsset(ChartEditorState.CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT);
2023-01-22 19:55:30 -05:00
if (toolbox == null) return null;
2023-01-22 19:55:30 -05:00
// Starting position.
toolbox.x = 200;
toolbox.y = 350;
2023-06-08 16:30:45 -04:00
toolbox.onDialogClosed = (event:DialogEvent) -> {
state.menubarItemToggleToolboxOpponentPreview.selected = false;
2023-01-22 19:55:30 -05:00
}
2023-08-31 18:47:23 -04:00
var charPlayer:Null<CharacterPlayer> = toolbox.findComponent('charPlayer');
if (charPlayer == null) throw 'ChartEditorToolboxHandler.buildToolboxOpponentPreviewLayout() - Could not find charPlayer component.';
2023-01-22 19:55:30 -05:00
// TODO: We need to implement character swapping in ChartEditorState.
charPlayer.loadCharacter('dad');
2023-06-08 16:48:34 -04:00
charPlayer.characterType = CharacterType.DAD;
2023-01-22 19:55:30 -05:00
charPlayer.flip = false;
2023-06-08 16:48:34 -04:00
charPlayer.targetScale = 0.5;
2023-01-22 19:55:30 -05:00
return toolbox;
}
static function onShowToolboxOpponentPreview(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
static function onHideToolboxOpponentPreview(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
}