mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2025-03-22 21:06:19 -04:00
Merge branch 'rewrite/master' into feature/chart-editor-haxeui-update
This commit is contained in:
commit
e4c248896a
26 changed files with 196 additions and 417 deletions
Project.xmlassets
source
Main.hx
funkin
Conductor.hx
data
import.hxinput
ui
util/tools
|
@ -162,7 +162,10 @@
|
|||
<icon path="art/iconOG.png" />
|
||||
<haxedef name="CAN_OPEN_LINKS" unless="switch" />
|
||||
<haxedef name="CAN_CHEAT" if="switch debug" />
|
||||
<!-- I don't -->
|
||||
<haxedef name="haxeui_no_mouse_reset" />
|
||||
<!-- Clicking outside a dialog should deselect the current focused component. -->
|
||||
<haxedef name="haxeui_focus_out_on_click" />
|
||||
<!-- Skip the Intro -->
|
||||
<section if="debug">
|
||||
<!-- Starts the game at the specified week, at the first song -->
|
||||
|
|
2
assets
2
assets
|
@ -1 +1 @@
|
|||
Subproject commit 69283c667d93e44da8d63f0588c7554f608575fb
|
||||
Subproject commit fb7120cf30d7accda049409b68d8daa0e1e7650f
|
|
@ -111,5 +111,6 @@ class Main extends Sprite
|
|||
Toolkit.init();
|
||||
Toolkit.theme = 'dark'; // don't be cringe
|
||||
Toolkit.autoScale = false;
|
||||
funkin.input.Cursor.registerHaxeUICursors();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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<String, Dynamic>,
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
|
|
@ -534,12 +534,22 @@ abstract SongEventData(SongEventDataRaw) from SongEventDataRaw to SongEventDataR
|
|||
|
||||
public inline function getInt(key:String):Null<Int>
|
||||
{
|
||||
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<Float>
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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<SongTimeChange>, desc:Bool = false):Array<SongTimeChange>
|
||||
{
|
||||
// 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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<BitmapData> = 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<BitmapData> = 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<BitmapData> = 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<BitmapData> = 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<BitmapData> = 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<BitmapData> = 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<BitmapData> = 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<BitmapData> = 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<BitmapData> = 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<BitmapData> = 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<BitmapData> = 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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -134,21 +134,25 @@ class ChartEditorEventSprite extends FlxSprite
|
|||
|
||||
function set_eventData(value:Null<SongEventData>):Null<SongEventData>
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -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<FunkinDropDown> = dialog.findComponent('inputNoteStyle', FunkinDropDown);
|
||||
var inputNoteStyle:Null<DropDown> = 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<FunkinDropDown> = dialog.findComponent('inputCharacterPlayer', FunkinDropDown);
|
||||
var inputCharacterPlayer:Null<DropDown> = 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<FunkinDropDown> = dialog.findComponent('inputCharacterOpponent', FunkinDropDown);
|
||||
var inputCharacterOpponent:Null<DropDown> = 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<FunkinDropDown> = dialog.findComponent('inputCharacterGirlfriend', FunkinDropDown);
|
||||
var inputCharacterGirlfriend:Null<DropDown> = 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;
|
||||
|
|
|
@ -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<String> = field.keys.get(optionName);
|
||||
var optionValue:Null<Dynamic> = 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<FunkinDropDown> = toolbox.findComponent('inputStage', FunkinDropDown);
|
||||
var inputStage:Null<DropDown> = 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<FunkinDropDown> = toolbox.findComponent('inputNoteStyle', FunkinDropDown);
|
||||
var inputNoteStyle:Null<DropDown> = 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<FunkinDropDown> = toolbox.findComponent('inputCharacterPlayer', FunkinDropDown);
|
||||
var inputCharacterPlayer:Null<DropDown> = 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<FunkinDropDown> = toolbox.findComponent('inputCharacterOpponent', FunkinDropDown);
|
||||
var inputCharacterOpponent:Null<DropDown> = 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<FunkinDropDown> = toolbox.findComponent('inputCharacterGirlfriend', FunkinDropDown);
|
||||
var inputCharacterGirlfriend:Null<DropDown> = 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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
14
source/funkin/util/tools/DynamicTools.hx
Normal file
14
source/funkin/util/tools/DynamicTools.hx
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue