diff --git a/Project.xml b/Project.xml index 9fad26fd7..46ba7f155 100644 --- a/Project.xml +++ b/Project.xml @@ -162,7 +162,10 @@ + + +
diff --git a/assets b/assets index 69283c667..fb7120cf3 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 69283c667d93e44da8d63f0588c7554f608575fb +Subproject commit fb7120cf30d7accda049409b68d8daa0e1e7650f diff --git a/source/Main.hx b/source/Main.hx index 3a7d36178..5fbb6747b 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -111,5 +111,6 @@ class Main extends Sprite Toolkit.init(); Toolkit.theme = 'dark'; // don't be cringe Toolkit.autoScale = false; + funkin.input.Cursor.registerHaxeUICursors(); } } diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index b79ae0fc4..10bf505f0 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -5,6 +5,7 @@ import flixel.util.FlxSignal; import flixel.math.FlxMath; import funkin.play.song.Song.SongDifficulty; import funkin.data.song.SongData.SongTimeChange; +import funkin.data.song.SongDataUtils; /** * A core class which handles musical timing throughout the game, @@ -257,6 +258,9 @@ class Conductor { timeChanges = []; + // Sort in place just in case it's out of order. + SongDataUtils.sortTimeChanges(songTimeChanges); + for (currentTimeChange in songTimeChanges) { // TODO: Maybe handle this different? diff --git a/source/funkin/data/event/SongEventData.hx b/source/funkin/data/event/SongEventData.hx index 831a53fbd..7a167b031 100644 --- a/source/funkin/data/event/SongEventData.hx +++ b/source/funkin/data/event/SongEventData.hx @@ -208,25 +208,32 @@ typedef SongEventSchemaField = type:SongEventFieldType, /** - * Used for ENUM values. + * Used only for ENUM values. * The key is the display name and the value is the actual value. */ ?keys:Map, + /** * Used for INTEGER and FLOAT values. * The minimum value that can be entered. + * @default No minimum */ ?min:Float, + /** * Used for INTEGER and FLOAT values. * The maximum value that can be entered. + * @default No maximum */ ?max:Float, + /** * Used for INTEGER and FLOAT values. * The step value that will be used when incrementing/decrementing the value. + * @default `0.1` */ ?step:Float, + /** * An optional default value for the field. */ diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx index e8da2518c..e79e1a3f4 100644 --- a/source/funkin/data/song/SongData.hx +++ b/source/funkin/data/song/SongData.hx @@ -534,12 +534,22 @@ abstract SongEventData(SongEventDataRaw) from SongEventDataRaw to SongEventDataR public inline function getInt(key:String):Null { - return this.value == null ? null : cast Reflect.field(this.value, key); + if (this.value == null) return null; + var result = Reflect.field(this.value, key); + if (result == null) return null; + if (Std.isOfType(result, Int)) return result; + if (Std.isOfType(result, String)) return Std.parseInt(cast result); + return cast result; } public inline function getFloat(key:String):Null { - return this.value == null ? null : cast Reflect.field(this.value, key); + if (this.value == null) return null; + var result = Reflect.field(this.value, key); + if (result == null) return null; + if (Std.isOfType(result, Float)) return result; + if (Std.isOfType(result, String)) return Std.parseFloat(cast result); + return cast result; } public inline function getString(key:String):String diff --git a/source/funkin/data/song/SongDataUtils.hx b/source/funkin/data/song/SongDataUtils.hx index 984af18fa..b149a8855 100644 --- a/source/funkin/data/song/SongDataUtils.hx +++ b/source/funkin/data/song/SongDataUtils.hx @@ -3,6 +3,7 @@ package funkin.data.song; import flixel.util.FlxSort; import funkin.data.song.SongData.SongEventData; import funkin.data.song.SongData.SongNoteData; +import funkin.data.song.SongData.SongTimeChange; import funkin.util.ClipboardUtil; import funkin.util.SerializerUtil; @@ -163,6 +164,18 @@ class SongDataUtils return events; } + /** + * Sort an array of notes by strum time. + */ + public static function sortTimeChanges(timeChanges:Array, desc:Bool = false):Array + { + // TODO: Modifies the array in place. Is this okay? + timeChanges.sort(function(a:SongTimeChange, b:SongTimeChange):Int { + return FlxSort.byValues(desc ? FlxSort.DESCENDING : FlxSort.ASCENDING, a.timeStamp, b.timeStamp); + }); + return timeChanges; + } + /** * Serialize note and event data and write it to the clipboard. */ diff --git a/source/funkin/import.hx b/source/funkin/import.hx index 8c7124da0..5ca6b03db 100644 --- a/source/funkin/import.hx +++ b/source/funkin/import.hx @@ -12,6 +12,7 @@ using Lambda; using StringTools; using funkin.util.tools.ArraySortTools; using funkin.util.tools.ArrayTools; +using funkin.util.tools.DynamicTools; using funkin.util.tools.FloatTools; using funkin.util.tools.Int64Tools; using funkin.util.tools.IntTools; diff --git a/source/funkin/input/Cursor.hx b/source/funkin/input/Cursor.hx index edd9e70f3..c609c9e30 100644 --- a/source/funkin/input/Cursor.hx +++ b/source/funkin/input/Cursor.hx @@ -1,5 +1,6 @@ package funkin.input; +import haxe.ui.backend.flixel.CursorHelper; import openfl.utils.Assets; import lime.app.Future; import openfl.display.BitmapData; @@ -33,7 +34,7 @@ class Cursor Cursor.cursorMode = null; } - static final CURSOR_DEFAULT_PARAMS:CursorParams = + public static final CURSOR_DEFAULT_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-default.png", scale: 1.0, @@ -42,7 +43,7 @@ class Cursor }; static var assetCursorDefault:Null = null; - static final CURSOR_CROSS_PARAMS:CursorParams = + public static final CURSOR_CROSS_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-cross.png", scale: 1.0, @@ -51,7 +52,7 @@ class Cursor }; static var assetCursorCross:Null = null; - static final CURSOR_ERASER_PARAMS:CursorParams = + public static final CURSOR_ERASER_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-eraser.png", scale: 1.0, @@ -60,7 +61,7 @@ class Cursor }; static var assetCursorEraser:Null = null; - static final CURSOR_GRABBING_PARAMS:CursorParams = + public static final CURSOR_GRABBING_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-grabbing.png", scale: 1.0, @@ -69,7 +70,7 @@ class Cursor }; static var assetCursorGrabbing:Null = null; - static final CURSOR_HOURGLASS_PARAMS:CursorParams = + public static final CURSOR_HOURGLASS_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-hourglass.png", scale: 1.0, @@ -78,7 +79,7 @@ class Cursor }; static var assetCursorHourglass:Null = null; - static final CURSOR_POINTER_PARAMS:CursorParams = + public static final CURSOR_POINTER_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-pointer.png", scale: 1.0, @@ -87,7 +88,7 @@ class Cursor }; static var assetCursorPointer:Null = null; - static final CURSOR_TEXT_PARAMS:CursorParams = + public static final CURSOR_TEXT_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-text.png", scale: 0.2, @@ -96,7 +97,7 @@ class Cursor }; static var assetCursorText:Null = null; - static final CURSOR_TEXT_VERTICAL_PARAMS:CursorParams = + public static final CURSOR_TEXT_VERTICAL_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-text-vertical.png", scale: 0.2, @@ -105,7 +106,7 @@ class Cursor }; static var assetCursorTextVertical:Null = null; - static final CURSOR_ZOOM_IN_PARAMS:CursorParams = + public static final CURSOR_ZOOM_IN_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-zoom-in.png", scale: 1.0, @@ -114,7 +115,7 @@ class Cursor }; static var assetCursorZoomIn:Null = null; - static final CURSOR_ZOOM_OUT_PARAMS:CursorParams = + public static final CURSOR_ZOOM_OUT_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-zoom-out.png", scale: 1.0, @@ -123,7 +124,7 @@ class Cursor }; static var assetCursorZoomOut:Null = null; - static final CURSOR_CROSSHAIR_PARAMS:CursorParams = + public static final CURSOR_CROSSHAIR_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-crosshair.png", scale: 1.0, @@ -132,7 +133,7 @@ class Cursor }; static var assetCursorCrosshair:Null = null; - static final CURSOR_CELL_PARAMS:CursorParams = + public static final CURSOR_CELL_PARAMS:CursorParams = { graphic: "assets/images/cursor/cursor-cell.png", scale: 1.0, @@ -500,6 +501,28 @@ class Cursor { trace("Failed to load cursor graphic for cursor mode " + cursorMode + ": " + error); } + + public static function registerHaxeUICursors():Void + { + CursorHelper.useCustomCursors = true; + registerHaxeUICursor('default', CURSOR_DEFAULT_PARAMS); + registerHaxeUICursor('cross', CURSOR_CROSS_PARAMS); + registerHaxeUICursor('eraser', CURSOR_ERASER_PARAMS); + registerHaxeUICursor('grabbing', CURSOR_GRABBING_PARAMS); + registerHaxeUICursor('hourglass', CURSOR_HOURGLASS_PARAMS); + registerHaxeUICursor('pointer', CURSOR_POINTER_PARAMS); + registerHaxeUICursor('text', CURSOR_TEXT_PARAMS); + registerHaxeUICursor('text-vertical', CURSOR_TEXT_VERTICAL_PARAMS); + registerHaxeUICursor('zoom-in', CURSOR_ZOOM_IN_PARAMS); + registerHaxeUICursor('zoom-out', CURSOR_ZOOM_OUT_PARAMS); + registerHaxeUICursor('crosshair', CURSOR_CROSSHAIR_PARAMS); + registerHaxeUICursor('cell', CURSOR_CELL_PARAMS); + } + + public static function registerHaxeUICursor(id:String, params:CursorParams):Void + { + CursorHelper.registerCursor(id, params.graphic, params.scale, params.offsetX, params.offsetY); + } } // https://developer.mozilla.org/en-US/docs/Web/CSS/cursor diff --git a/source/funkin/ui/MusicBeatState.hx b/source/funkin/ui/MusicBeatState.hx index 6d592f438..328a26428 100644 --- a/source/funkin/ui/MusicBeatState.hx +++ b/source/funkin/ui/MusicBeatState.hx @@ -57,27 +57,45 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler Conductor.stepHit.remove(this.stepHit); } - override function update(elapsed:Float) + function handleControls():Void { - super.update(elapsed); + var isHaxeUIFocused:Bool = haxe.ui.focus.FocusManager.instance?.focus != null; - // Rebindable volume keys. - if (controls.VOLUME_MUTE) FlxG.sound.toggleMuted(); - else if (controls.VOLUME_UP) FlxG.sound.changeVolume(0.1); - else if (controls.VOLUME_DOWN) FlxG.sound.changeVolume(-0.1); + if (!isHaxeUIFocused) + { + // Rebindable volume keys. + if (controls.VOLUME_MUTE) FlxG.sound.toggleMuted(); + else if (controls.VOLUME_UP) FlxG.sound.changeVolume(0.1); + else if (controls.VOLUME_DOWN) FlxG.sound.changeVolume(-0.1); + } + } + function handleFunctionControls():Void + { // Emergency exit button. if (FlxG.keys.justPressed.F4) FlxG.switchState(new MainMenuState()); // This can now be used in EVERY STATE YAY! if (FlxG.keys.justPressed.F5) debug_refreshModules(); + } + function handleQuickWatch():Void + { // Display Conductor info in the watch window. FlxG.watch.addQuick("songPosition", Conductor.songPosition); FlxG.watch.addQuick("bpm", Conductor.bpm); FlxG.watch.addQuick("currentMeasureTime", Conductor.currentBeatTime); FlxG.watch.addQuick("currentBeatTime", Conductor.currentBeatTime); FlxG.watch.addQuick("currentStepTime", Conductor.currentStepTime); + } + + override function update(elapsed:Float) + { + super.update(elapsed); + + handleControls(); + handleFunctionControls(); + handleQuickWatch(); dispatchEvent(new UpdateScriptEvent(elapsed)); } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index aedabc956..382bab592 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -91,6 +91,7 @@ import haxe.ui.core.Component; import haxe.ui.core.Screen; import haxe.ui.events.DragEvent; import haxe.ui.events.UIEvent; +import haxe.ui.focus.FocusManager; import haxe.ui.notifications.NotificationManager; import haxe.ui.notifications.NotificationType; import openfl.display.BitmapData; @@ -548,22 +549,14 @@ class ChartEditorState extends HaxeUIState // HaxeUI /** - * Whether the user's mouse cursor is hovering over a SOLID component of the HaxeUI. - * If so, ignore mouse events underneath as well as certain key events. + * Whether the user is focused on an input in the Haxe UI, and inputs are being fed into it. + * If the user clicks off the input, focus will leave. */ - var isCursorOverHaxeUI(get, never):Bool; + var isHaxeUIFocused(get, never):Bool; - function get_isCursorOverHaxeUI():Bool + function get_isHaxeUIFocused():Bool { - return Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.screenX, FlxG.mouse.screenY); - } - - var isCursorOverHaxeUIButton(get, never):Bool; - - function get_isCursorOverHaxeUIButton():Bool - { - return Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.screenX, FlxG.mouse.screenY, haxe.ui.components.Button) - || Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.screenX, FlxG.mouse.screenY, haxe.ui.components.Link); + return FocusManager.instance.focus != null; } /** @@ -2058,21 +2051,6 @@ class ChartEditorState extends HaxeUIState #end } - function handleQuickWatch():Void - { - FlxG.watch.addQuick('scrollPosInPixels', scrollPositionInPixels); - FlxG.watch.addQuick('playheadPosInPixels', playheadPositionInPixels); - - // Add a debug value which displays the current size of the note pool. - // The pool will grow as more notes need to be rendered at once. - // If this gets too big, something needs to be optimized somewhere! -Eric - if (renderedNotes != null && renderedNotes.members != null) FlxG.watch.addQuick("tapNotesRendered", renderedNotes.members.length); - if (renderedHoldNotes != null && renderedHoldNotes.members != null) FlxG.watch.addQuick("holdNotesRendered", renderedHoldNotes.members.length); - if (renderedEvents != null && renderedEvents.members != null) FlxG.watch.addQuick("eventsRendered", renderedEvents.members.length); - if (currentNoteSelection != null) FlxG.watch.addQuick("notesSelected", currentNoteSelection.length); - if (currentEventSelection != null) FlxG.watch.addQuick("eventsSelected", currentEventSelection.length); - } - /** * Beat hit while the song is playing. */ @@ -2557,8 +2535,8 @@ class ChartEditorState extends HaxeUIState */ function handleScrollKeybinds():Void { - // Don't scroll when the cursor is over the UI, unless a playbar button (the << >> ones) is pressed. - if (isCursorOverHaxeUI && playbarButtonPressed == null) return; + // Don't scroll when the user is interacting with the UI, unless a playbar button (the << >> ones) is pressed. + if (isHaxeUIFocused && playbarButtonPressed == null) return; var scrollAmount:Float = 0; // Amount to scroll the grid. var playheadAmount:Float = 0; // Amount to scroll the playhead relative to the grid. @@ -2757,7 +2735,7 @@ class ChartEditorState extends HaxeUIState if (FlxG.mouse.justReleased) FlxG.sound.play(Paths.sound("chartingSounds/ClickUp")); // Note: If a menu is open in HaxeUI, don't handle cursor behavior. - var shouldHandleCursor:Bool = !isCursorOverHaxeUI + var shouldHandleCursor:Bool = !isHaxeUIFocused || (selectionBoxStartPos != null) || (dragTargetNote != null || dragTargetEvent != null); var eventColumn:Int = (STRUMLINE_SIZE * 2 + 1) - 1; @@ -3317,14 +3295,14 @@ class ChartEditorState extends HaxeUIState { // Create an event and place it in the chart. // TODO: Figure out configuring event data. - var newEventData:SongEventData = new SongEventData(cursorSnappedMs, selectedEventKind, selectedEventData); + var newEventData:SongEventData = new SongEventData(cursorSnappedMs, selectedEventKind, selectedEventData.clone()); performCommand(new AddEventsCommand([newEventData], FlxG.keys.pressed.CONTROL)); } else { // Create a note and place it in the chart. - var newNoteData:SongNoteData = new SongNoteData(cursorSnappedMs, cursorColumn, 0, selectedNoteKind); + var newNoteData:SongNoteData = new SongNoteData(cursorSnappedMs, cursorColumn, 0, selectedNoteKind.clone()); performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL)); @@ -3989,7 +3967,7 @@ class ChartEditorState extends HaxeUIState */ function handleTestKeybinds():Void { - if (!isHaxeUIDialogOpen && !isCursorOverHaxeUI && FlxG.keys.justPressed.ENTER) + if (!isHaxeUIDialogOpen && !isHaxeUIFocused && FlxG.keys.justPressed.ENTER) { var minimal = FlxG.keys.pressed.SHIFT; this.hideAllToolboxes(); @@ -4006,6 +3984,20 @@ class ChartEditorState extends HaxeUIState if (FlxG.keys.justPressed.F1) this.openUserGuideDialog(); } + override function handleQuickWatch():Void + { + super.handleQuickWatch(); + + FlxG.watch.addQuick('scrollPosInPixels', scrollPositionInPixels); + FlxG.watch.addQuick('playheadPosInPixels', playheadPositionInPixels); + + FlxG.watch.addQuick("tapNotesRendered", renderedNotes.members.length); + FlxG.watch.addQuick("holdNotesRendered", renderedHoldNotes.members.length); + FlxG.watch.addQuick("eventsRendered", renderedEvents.members.length); + FlxG.watch.addQuick("notesSelected", currentNoteSelection.length); + FlxG.watch.addQuick("eventsSelected", currentEventSelection.length); + } + /** * PLAYTEST FUNCTIONS */ diff --git a/source/funkin/ui/debug/charting/components/ChartEditorEventSprite.hx b/source/funkin/ui/debug/charting/components/ChartEditorEventSprite.hx index 2bd719df2..4c9d91407 100644 --- a/source/funkin/ui/debug/charting/components/ChartEditorEventSprite.hx +++ b/source/funkin/ui/debug/charting/components/ChartEditorEventSprite.hx @@ -134,21 +134,25 @@ class ChartEditorEventSprite extends FlxSprite function set_eventData(value:Null):Null { - this.eventData = value; - - if (this.eventData == null) + if (value == null) { + this.eventData = null; // Disown parent. MAKE SURE TO REVIVE BEFORE REUSING this.kill(); + this.visible = false; + return null; + } + else + { + this.visible = true; + // Only play the animation if the event type has changed. + // if (this.eventData == null || this.eventData.event != value.event) + playAnimation(value.event); + this.eventData = value; + // Update the position to match the note data. + updateEventPosition(); return this.eventData; } - - this.visible = true; - playAnimation(this.eventData.event); - // Update the position to match the note data. - updateEventPosition(); - - return this.eventData; } public function updateEventPosition(?origin:FlxObject) diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx index dba513c32..f5cbccff6 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx @@ -15,8 +15,6 @@ import funkin.play.character.CharacterData.CharacterDataParser; import funkin.play.song.Song; import funkin.play.stage.StageData; import funkin.ui.debug.charting.util.ChartEditorDropdowns; -import funkin.ui.haxeui.components.FunkinDropDown; -import funkin.ui.haxeui.components.FunkinLink; import funkin.util.Constants; import funkin.util.FileUtil; import funkin.util.SerializerUtil; @@ -160,7 +158,7 @@ class ChartEditorDialogHandler continue; } - var linkTemplateSong:Link = new FunkinLink(); + var linkTemplateSong:Link = new Link(); linkTemplateSong.text = songName; linkTemplateSong.onClick = function(_event) { dialog.hideDialog(DialogButton.CANCEL); @@ -687,7 +685,7 @@ class ChartEditorDialogHandler var startingValueStage = ChartEditorDropdowns.populateDropdownWithStages(inputStage, newSongMetadata.playData.stage); inputStage.value = startingValueStage; - var inputNoteStyle:Null = dialog.findComponent('inputNoteStyle', FunkinDropDown); + var inputNoteStyle:Null = dialog.findComponent('inputNoteStyle', DropDown); if (inputNoteStyle == null) throw 'Could not locate inputNoteStyle DropDown in Song Metadata dialog'; inputNoteStyle.onChange = function(event:UIEvent) { if (event.data.id == null) return; @@ -696,7 +694,7 @@ class ChartEditorDialogHandler var startingValueNoteStyle = ChartEditorDropdowns.populateDropdownWithNoteStyles(inputNoteStyle, newSongMetadata.playData.noteStyle); inputNoteStyle.value = startingValueNoteStyle; - var inputCharacterPlayer:Null = dialog.findComponent('inputCharacterPlayer', FunkinDropDown); + var inputCharacterPlayer:Null = dialog.findComponent('inputCharacterPlayer', DropDown); if (inputCharacterPlayer == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputCharacterPlayer component.'; inputCharacterPlayer.onChange = function(event:UIEvent) { if (event.data?.id == null) return; @@ -706,7 +704,7 @@ class ChartEditorDialogHandler newSongMetadata.playData.characters.player); inputCharacterPlayer.value = startingValuePlayer; - var inputCharacterOpponent:Null = dialog.findComponent('inputCharacterOpponent', FunkinDropDown); + var inputCharacterOpponent:Null = dialog.findComponent('inputCharacterOpponent', DropDown); if (inputCharacterOpponent == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputCharacterOpponent component.'; inputCharacterOpponent.onChange = function(event:UIEvent) { if (event.data?.id == null) return; @@ -716,7 +714,7 @@ class ChartEditorDialogHandler newSongMetadata.playData.characters.opponent); inputCharacterOpponent.value = startingValueOpponent; - var inputCharacterGirlfriend:Null = dialog.findComponent('inputCharacterGirlfriend', FunkinDropDown); + var inputCharacterGirlfriend:Null = dialog.findComponent('inputCharacterGirlfriend', DropDown); if (inputCharacterGirlfriend == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputCharacterGirlfriend component.'; inputCharacterGirlfriend.onChange = function(event:UIEvent) { if (event.data?.id == null) return; diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx index f0c634666..a43dd2989 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx @@ -1,5 +1,14 @@ package funkin.ui.debug.charting.handlers; +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.character.BaseCharacter.CharacterType; @@ -11,7 +20,6 @@ import funkin.play.stage.StageData; import funkin.play.stage.StageData.StageDataParser; import funkin.ui.debug.charting.util.ChartEditorDropdowns; import funkin.ui.haxeui.components.CharacterPlayer; -import funkin.ui.haxeui.components.FunkinDropDown; import funkin.util.FileUtil; import haxe.ui.components.Button; import haxe.ui.components.CheckBox; @@ -292,6 +300,8 @@ class ChartEditorToolboxHandler trace('ChartEditorToolboxHandler.buildToolboxEventDataLayout() - Event type changed: $eventType'); + state.selectedEventKind = eventType; + var schema:SongEventSchema = SongEventParser.getEventSchema(eventType); if (schema == null) @@ -302,6 +312,7 @@ class ChartEditorToolboxHandler buildEventDataFormFromSchema(state, toolboxEventsDataGrid, schema); } + toolboxEventsEventKind.value = state.selectedEventKind; return toolbox; } @@ -325,6 +336,7 @@ class ChartEditorToolboxHandler // Add a label. var label:Label = new Label(); label.text = field.title; + label.verticalAlign = "center"; target.addComponent(label); var input:Component; @@ -342,8 +354,8 @@ class ChartEditorToolboxHandler var numberStepper:NumberStepper = new NumberStepper(); numberStepper.id = field.name; numberStepper.step = field.step ?? 0.1; - numberStepper.min = field.min ?? 0.0; - numberStepper.max = field.max ?? 1.0; + if (field.min != null) numberStepper.min = field.min; + if (field.max != null) numberStepper.max = field.max; if (field.defaultValue != null) numberStepper.value = field.defaultValue; input = numberStepper; case BOOL: @@ -354,6 +366,7 @@ class ChartEditorToolboxHandler case ENUM: var dropDown:DropDown = new DropDown(); dropDown.id = field.name; + dropDown.width = 200.0; dropDown.dataSource = new ArrayDataSource(); if (field.keys == null) throw 'Field "${field.name}" is of Enum type but has no keys.'; @@ -362,7 +375,7 @@ class ChartEditorToolboxHandler for (optionName in field.keys.keys()) { - var optionValue:Null = field.keys.get(optionName); + var optionValue:Null = field.keys.get(optionName); trace('$optionName : $optionValue'); dropDown.dataSource.add({value: optionValue, text: optionName}); } @@ -384,11 +397,21 @@ class ChartEditorToolboxHandler target.addComponent(input); input.onChange = function(event:UIEvent) { - trace('ChartEditorToolboxHandler.buildEventDataFormFromSchema() - ${event.target.id} = ${event.target.value}'); + var value = event.target.value; + if (field.type == ENUM) + { + value = event.target.value.value; + } + trace('ChartEditorToolboxHandler.buildEventDataFormFromSchema() - ${event.target.id} = ${value}'); - if (event.target.value == null) state.selectedEventData.remove(event.target.id); + if (value == null) + { + state.selectedEventData.remove(event.target.id); + } else - state.selectedEventData.set(event.target.id, event.target.value); + { + state.selectedEventData.set(event.target.id, value); + } } } } @@ -528,7 +551,7 @@ class ChartEditorToolboxHandler }; inputSongArtist.value = state.currentSongMetadata.artist; - var inputStage:Null = toolbox.findComponent('inputStage', FunkinDropDown); + var inputStage:Null = toolbox.findComponent('inputStage', DropDown); if (inputStage == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputStage component.'; inputStage.onChange = function(event:UIEvent) { var valid:Bool = event.data != null && event.data.id != null; @@ -541,7 +564,7 @@ class ChartEditorToolboxHandler var startingValueStage = ChartEditorDropdowns.populateDropdownWithStages(inputStage, state.currentSongMetadata.playData.stage); inputStage.value = startingValueStage; - var inputNoteStyle:Null = toolbox.findComponent('inputNoteStyle', FunkinDropDown); + var inputNoteStyle:Null = toolbox.findComponent('inputNoteStyle', DropDown); if (inputNoteStyle == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputNoteStyle component.'; inputNoteStyle.onChange = function(event:UIEvent) { if (event.data?.id == null) return; @@ -551,7 +574,7 @@ class ChartEditorToolboxHandler // By using this flag, we prevent the dropdown value from changing while it is being populated. - var inputCharacterPlayer:Null = toolbox.findComponent('inputCharacterPlayer', FunkinDropDown); + var inputCharacterPlayer:Null = toolbox.findComponent('inputCharacterPlayer', DropDown); if (inputCharacterPlayer == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputCharacterPlayer component.'; inputCharacterPlayer.onChange = function(event:UIEvent) { if (event.data?.id == null) return; @@ -561,7 +584,7 @@ class ChartEditorToolboxHandler state.currentSongMetadata.playData.characters.player); inputCharacterPlayer.value = startingValuePlayer; - var inputCharacterOpponent:Null = toolbox.findComponent('inputCharacterOpponent', FunkinDropDown); + var inputCharacterOpponent:Null = toolbox.findComponent('inputCharacterOpponent', DropDown); if (inputCharacterOpponent == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputCharacterOpponent component.'; inputCharacterOpponent.onChange = function(event:UIEvent) { if (event.data?.id == null) return; @@ -571,7 +594,7 @@ class ChartEditorToolboxHandler state.currentSongMetadata.playData.characters.opponent); inputCharacterOpponent.value = startingValueOpponent; - var inputCharacterGirlfriend:Null = toolbox.findComponent('inputCharacterGirlfriend', FunkinDropDown); + var inputCharacterGirlfriend:Null = toolbox.findComponent('inputCharacterGirlfriend', DropDown); if (inputCharacterGirlfriend == null) throw 'ChartEditorToolboxHandler.buildToolboxMetadataLayout() - Could not find inputCharacterGirlfriend component.'; inputCharacterGirlfriend.onChange = function(event:UIEvent) { if (event.data?.id == null) return; diff --git a/source/funkin/ui/haxeui/components/FunkinButton.hx b/source/funkin/ui/haxeui/components/FunkinButton.hx deleted file mode 100644 index 45987b9ec..000000000 --- a/source/funkin/ui/haxeui/components/FunkinButton.hx +++ /dev/null @@ -1,30 +0,0 @@ -package funkin.ui.haxeui.components; - -import funkin.input.Cursor; -import haxe.ui.events.MouseEvent; -import haxe.ui.components.Button; - -/** - * A HaxeUI button which: - * - Changes the current cursor when hovered over. - */ -class FunkinButton extends Button -{ - public function new() - { - super(); - - this.onMouseOver = handleMouseOver; - this.onMouseOut = handleMouseOut; - } - - private function handleMouseOver(event:MouseEvent) - { - Cursor.cursorMode = Pointer; - } - - private function handleMouseOut(event:MouseEvent) - { - Cursor.cursorMode = Default; - } -} diff --git a/source/funkin/ui/haxeui/components/FunkinClickLabel.hx b/source/funkin/ui/haxeui/components/FunkinClickLabel.hx deleted file mode 100644 index 77c9dbc0f..000000000 --- a/source/funkin/ui/haxeui/components/FunkinClickLabel.hx +++ /dev/null @@ -1,30 +0,0 @@ -package funkin.ui.haxeui.components; - -import haxe.ui.components.Label; -import funkin.input.Cursor; -import haxe.ui.events.MouseEvent; - -/** - * A HaxeUI label which: - * - Changes the current cursor when hovered over (assume an onClick handler will be added!). - */ -class FunkinClickLabel extends Label -{ - public function new() - { - super(); - - this.onMouseOver = handleMouseOver; - this.onMouseOut = handleMouseOut; - } - - private function handleMouseOver(event:MouseEvent) - { - Cursor.cursorMode = Pointer; - } - - private function handleMouseOut(event:MouseEvent) - { - Cursor.cursorMode = Default; - } -} diff --git a/source/funkin/ui/haxeui/components/FunkinDropDown.hx b/source/funkin/ui/haxeui/components/FunkinDropDown.hx deleted file mode 100644 index ad396856c..000000000 --- a/source/funkin/ui/haxeui/components/FunkinDropDown.hx +++ /dev/null @@ -1,30 +0,0 @@ -package funkin.ui.haxeui.components; - -import haxe.ui.components.DropDown; -import funkin.input.Cursor; -import haxe.ui.events.MouseEvent; - -/** - * A HaxeUI dropdown which: - * - Changes the current cursor when hovered over. - */ -class FunkinDropDown extends DropDown -{ - public function new() - { - super(); - - this.onMouseOver = handleMouseOver; - this.onMouseOut = handleMouseOut; - } - - private function handleMouseOver(event:MouseEvent) - { - Cursor.cursorMode = Pointer; - } - - private function handleMouseOut(event:MouseEvent) - { - Cursor.cursorMode = Default; - } -} diff --git a/source/funkin/ui/haxeui/components/FunkinHorizontalSlider.hx b/source/funkin/ui/haxeui/components/FunkinHorizontalSlider.hx deleted file mode 100644 index baf42aada..000000000 --- a/source/funkin/ui/haxeui/components/FunkinHorizontalSlider.hx +++ /dev/null @@ -1,30 +0,0 @@ -package funkin.ui.haxeui.components; - -import haxe.ui.components.HorizontalSlider; -import funkin.input.Cursor; -import haxe.ui.events.MouseEvent; - -/** - * A HaxeUI horizontal slider which: - * - Changes the current cursor when hovered over. - */ -class FunkinHorizontalSlider extends HorizontalSlider -{ - public function new() - { - super(); - - this.onMouseOver = handleMouseOver; - this.onMouseOut = handleMouseOut; - } - - private function handleMouseOver(event:MouseEvent) - { - Cursor.cursorMode = Pointer; - } - - private function handleMouseOut(event:MouseEvent) - { - Cursor.cursorMode = Default; - } -} diff --git a/source/funkin/ui/haxeui/components/FunkinLink.hx b/source/funkin/ui/haxeui/components/FunkinLink.hx deleted file mode 100644 index 74eb6e7c4..000000000 --- a/source/funkin/ui/haxeui/components/FunkinLink.hx +++ /dev/null @@ -1,30 +0,0 @@ -package funkin.ui.haxeui.components; - -import funkin.input.Cursor; -import haxe.ui.events.MouseEvent; -import haxe.ui.components.Link; - -/** - * A HaxeUI link which: - * - Changes the current cursor when hovered over. - */ -class FunkinLink extends Link -{ - public function new() - { - super(); - - this.onMouseOver = handleMouseOver; - this.onMouseOut = handleMouseOut; - } - - private function handleMouseOver(event:MouseEvent) - { - Cursor.cursorMode = Pointer; - } - - private function handleMouseOut(event:MouseEvent) - { - Cursor.cursorMode = Default; - } -} diff --git a/source/funkin/ui/haxeui/components/FunkinMenuBar.hx b/source/funkin/ui/haxeui/components/FunkinMenuBar.hx deleted file mode 100644 index 393372d74..000000000 --- a/source/funkin/ui/haxeui/components/FunkinMenuBar.hx +++ /dev/null @@ -1,32 +0,0 @@ -package funkin.ui.haxeui.components; - -import funkin.input.Cursor; -import haxe.ui.events.MouseEvent; -import haxe.ui.containers.menus.MenuBar; -import haxe.ui.core.CompositeBuilder; - -/** - * A HaxeUI menu bar which: - * - Changes the current cursor when each button is hovered over. - */ -class FunkinMenuBar extends MenuBar -{ - public function new() - { - super(); - - registerListeners(); - } - - private function registerListeners():Void {} - - private function handleMouseOver(event:MouseEvent) - { - Cursor.cursorMode = Pointer; - } - - private function handleMouseOut(event:MouseEvent) - { - Cursor.cursorMode = Default; - } -} diff --git a/source/funkin/ui/haxeui/components/FunkinMenuCheckBox.hx b/source/funkin/ui/haxeui/components/FunkinMenuCheckBox.hx deleted file mode 100644 index 263277c6f..000000000 --- a/source/funkin/ui/haxeui/components/FunkinMenuCheckBox.hx +++ /dev/null @@ -1,30 +0,0 @@ -package funkin.ui.haxeui.components; - -import funkin.input.Cursor; -import haxe.ui.events.MouseEvent; -import haxe.ui.containers.menus.MenuCheckBox; - -/** - * A HaxeUI menu checkbox which: - * - Changes the current cursor when hovered over. - */ -class FunkinMenuCheckBox extends MenuCheckBox -{ - public function new() - { - super(); - - this.onMouseOver = handleMouseOver; - this.onMouseOut = handleMouseOut; - } - - private function handleMouseOver(event:MouseEvent) - { - Cursor.cursorMode = Pointer; - } - - private function handleMouseOut(event:MouseEvent) - { - Cursor.cursorMode = Default; - } -} diff --git a/source/funkin/ui/haxeui/components/FunkinMenuItem.hx b/source/funkin/ui/haxeui/components/FunkinMenuItem.hx deleted file mode 100644 index 2eb7db729..000000000 --- a/source/funkin/ui/haxeui/components/FunkinMenuItem.hx +++ /dev/null @@ -1,30 +0,0 @@ -package funkin.ui.haxeui.components; - -import funkin.input.Cursor; -import haxe.ui.events.MouseEvent; -import haxe.ui.containers.menus.MenuItem; - -/** - * A HaxeUI menu item which: - * - Changes the current cursor when hovered over. - */ -class FunkinMenuItem extends MenuItem -{ - public function new() - { - super(); - - this.onMouseOver = handleMouseOver; - this.onMouseOut = handleMouseOut; - } - - private function handleMouseOver(event:MouseEvent) - { - Cursor.cursorMode = Pointer; - } - - private function handleMouseOut(event:MouseEvent) - { - Cursor.cursorMode = Default; - } -} diff --git a/source/funkin/ui/haxeui/components/FunkinMenuOptionBox.hx b/source/funkin/ui/haxeui/components/FunkinMenuOptionBox.hx deleted file mode 100644 index d9985eede..000000000 --- a/source/funkin/ui/haxeui/components/FunkinMenuOptionBox.hx +++ /dev/null @@ -1,30 +0,0 @@ -package funkin.ui.haxeui.components; - -import haxe.ui.containers.menus.MenuOptionBox; -import funkin.input.Cursor; -import haxe.ui.events.MouseEvent; - -/** - * A HaxeUI menu option box which: - * - Changes the current cursor when hovered over. - */ -class FunkinMenuOptionBox extends MenuOptionBox -{ - public function new() - { - super(); - - this.onMouseOver = handleMouseOver; - this.onMouseOut = handleMouseOut; - } - - private function handleMouseOver(event:MouseEvent) - { - Cursor.cursorMode = Pointer; - } - - private function handleMouseOut(event:MouseEvent) - { - Cursor.cursorMode = Default; - } -} diff --git a/source/funkin/ui/haxeui/components/FunkinNumberStepper.hx b/source/funkin/ui/haxeui/components/FunkinNumberStepper.hx deleted file mode 100644 index db8d4fb7f..000000000 --- a/source/funkin/ui/haxeui/components/FunkinNumberStepper.hx +++ /dev/null @@ -1,30 +0,0 @@ -package funkin.ui.haxeui.components; - -import haxe.ui.components.NumberStepper; -import funkin.input.Cursor; -import haxe.ui.events.MouseEvent; - -/** - * A HaxeUI number stepper which: - * - Changes the current cursor when hovered over. - */ -class FunkinNumberStepper extends NumberStepper -{ - public function new() - { - super(); - - this.onMouseOver = handleMouseOver; - this.onMouseOut = handleMouseOut; - } - - private function handleMouseOver(event:MouseEvent) - { - Cursor.cursorMode = Pointer; - } - - private function handleMouseOut(event:MouseEvent) - { - Cursor.cursorMode = Default; - } -} diff --git a/source/funkin/ui/haxeui/components/FunkinTextField.hx b/source/funkin/ui/haxeui/components/FunkinTextField.hx deleted file mode 100644 index 3ecab0684..000000000 --- a/source/funkin/ui/haxeui/components/FunkinTextField.hx +++ /dev/null @@ -1,30 +0,0 @@ -package funkin.ui.haxeui.components; - -import haxe.ui.components.TextField; -import funkin.input.Cursor; -import haxe.ui.events.MouseEvent; - -/** - * A HaxeUI text field which: - * - Changes the current cursor when hovered over. - */ -class FunkinTextField extends TextField -{ - public function new() - { - super(); - - this.onMouseOver = handleMouseOver; - this.onMouseOut = handleMouseOut; - } - - private function handleMouseOver(event:MouseEvent) - { - Cursor.cursorMode = Text; - } - - private function handleMouseOut(event:MouseEvent) - { - Cursor.cursorMode = Default; - } -} diff --git a/source/funkin/util/tools/DynamicTools.hx b/source/funkin/util/tools/DynamicTools.hx new file mode 100644 index 000000000..47501ea22 --- /dev/null +++ b/source/funkin/util/tools/DynamicTools.hx @@ -0,0 +1,14 @@ +package funkin.util.tools; + +class DynamicTools +{ + /** + * Creates a full clone of the input `Dynamic`. Only guaranteed to work on anonymous structures. + * @param input The `Dynamic` to clone. + * @return A clone of the input `Dynamic`. + */ + public static function clone(input:Dynamic):Dynamic + { + return Reflect.copy(input); + } +}