mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2025-12-10 05:59:15 +00:00
Move migration porcces into ChartEditor itself, when we load events data
This commit is contained in:
parent
fdaab2b229
commit
204dae213c
|
|
@ -39,6 +39,7 @@ import funkin.input.Cursor;
|
|||
import funkin.input.TurboButtonHandler;
|
||||
import funkin.input.TurboKeyHandler;
|
||||
import funkin.modding.events.ScriptEvent;
|
||||
import funkin.play.event.SongEvent;
|
||||
import funkin.play.notes.notekind.NoteKindManager;
|
||||
import funkin.play.character.BaseCharacter.CharacterType;
|
||||
import funkin.data.character.CharacterData.CharacterDataParser;
|
||||
|
|
@ -3830,10 +3831,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
for (eventData in currentSongChartEventData)
|
||||
{
|
||||
// Remember if we are already displaying this event.
|
||||
if (displayedEventData.indexOf(eventData) != -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (displayedEventData.indexOf(eventData) != -1) continue;
|
||||
|
||||
if (!ChartEditorEventSprite.wouldEventBeVisible(viewAreaBottomPixels, viewAreaTopPixels, eventData, renderedNotes)) continue;
|
||||
|
||||
|
|
@ -3846,6 +3844,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
eventSprite.parentState = this;
|
||||
trace('Creating new Event... (${renderedEvents.members.length})');
|
||||
|
||||
if (eventData?.value != null && (eventData?.value?.ease != null && eventData?.value?.easeDir == null))
|
||||
{
|
||||
eventData.value = migrateEventEaseDirectionFields(eventData.value);
|
||||
}
|
||||
|
||||
// The event sprite handles animation playback and positioning.
|
||||
eventSprite.eventData = eventData;
|
||||
eventSprite.overrideStepTime = null;
|
||||
|
|
@ -4077,6 +4080,19 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates old event data with ease and without easeDir fields, so we split them into ease and easeDir here.
|
||||
*/
|
||||
function migrateEventEaseDirectionFields(eventValues:Dynamic):Dynamic
|
||||
{
|
||||
if (eventValues.ease != null && SongEvent.EASE_TYPE_DIR_REGEX.match(eventValues.ease))
|
||||
{
|
||||
eventValues.ease = SongEvent.EASE_TYPE_DIR_REGEX.matchedLeft();
|
||||
eventValues.easeDir = SongEvent.EASE_TYPE_DIR_REGEX.matched(0);
|
||||
}
|
||||
return eventValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle keybinds for scrolling the chart editor grid.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import haxe.ui.containers.Frame;
|
|||
import haxe.ui.events.UIEvent;
|
||||
import haxe.ui.data.ArrayDataSource;
|
||||
import haxe.ui.containers.Grid;
|
||||
import funkin.play.event.SongEvent;
|
||||
|
||||
/**
|
||||
* The toolbox which allows modifying information like Song Title, Scroll Speed, Characters/Stages, and starting BPM.
|
||||
|
|
@ -171,51 +170,13 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox
|
|||
function buildEventDataFormFromSchema(target:Box, schema:SongEventSchema, eventKind:String):Void
|
||||
{
|
||||
trace('Building event data form from schema for event kind: ${eventKind}');
|
||||
// trace(schema);
|
||||
|
||||
lastEventKind = eventKind ?? 'unknown';
|
||||
|
||||
// Clear the frame.
|
||||
target.removeAllComponents();
|
||||
|
||||
// Check if we have both ease and easeDir fields in the schema
|
||||
var hasEaseField = false;
|
||||
var hasEaseDirField = false;
|
||||
for (field in schema)
|
||||
{
|
||||
if (field != null)
|
||||
{
|
||||
if (field.name == 'ease') hasEaseField = true;
|
||||
if (field.name == 'easeDir') hasEaseDirField = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert ease data for ALL events (both new and existing)
|
||||
if (hasEaseField && hasEaseDirField)
|
||||
{
|
||||
final originalData:Map<String, Dynamic> = new Map<String, Dynamic>();
|
||||
for (key in chartEditorState.eventDataToPlace.keys())
|
||||
originalData.set(key, chartEditorState.eventDataToPlace.get(key));
|
||||
|
||||
final converted:Bool = convertEaseData(chartEditorState.eventDataToPlace);
|
||||
|
||||
for (key => value in originalData)
|
||||
{
|
||||
if (key != 'ease' && key != 'easeDir') chartEditorState.eventDataToPlace.set(key, value);
|
||||
}
|
||||
|
||||
if (converted && !_initializing && chartEditorState.currentEventSelection.length > 0)
|
||||
{
|
||||
for (songEvent in chartEditorState.currentEventSelection)
|
||||
{
|
||||
songEvent.eventKind = chartEditorState.eventKindToPlace;
|
||||
songEvent.value = Reflect.copy(chartEditorState.eventDataToPlace);
|
||||
}
|
||||
chartEditorState.saveDataDirty = true;
|
||||
chartEditorState.noteDisplayDirty = true;
|
||||
chartEditorState.notePreviewDirty = true;
|
||||
chartEditorState.noteTooltipsDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (field in schema)
|
||||
{
|
||||
if (field == null) continue;
|
||||
|
|
@ -228,7 +189,6 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox
|
|||
|
||||
// Add an input field for the data field.
|
||||
var input:Component;
|
||||
final fieldValue = chartEditorState.eventDataToPlace.get(field.name);
|
||||
switch (field.type)
|
||||
{
|
||||
case INTEGER:
|
||||
|
|
@ -237,8 +197,7 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox
|
|||
numberStepper.step = field.step ?? 1.0;
|
||||
if (field.min != null) numberStepper.min = field.min;
|
||||
if (field.max != null) numberStepper.max = field.max;
|
||||
if (fieldValue != null) numberStepper.value = fieldValue;
|
||||
else if (field.defaultValue != null) numberStepper.value = field.defaultValue;
|
||||
if (field.defaultValue != null) numberStepper.value = field.defaultValue;
|
||||
input = numberStepper;
|
||||
case FLOAT:
|
||||
var numberStepper:NumberStepper = new NumberStepper();
|
||||
|
|
@ -246,14 +205,12 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox
|
|||
numberStepper.step = field.step ?? 0.1;
|
||||
if (field.min != null) numberStepper.min = field.min;
|
||||
if (field.max != null) numberStepper.max = field.max;
|
||||
if (fieldValue != null) numberStepper.value = fieldValue;
|
||||
else if (field.defaultValue != null) numberStepper.value = field.defaultValue;
|
||||
if (field.defaultValue != null) numberStepper.value = field.defaultValue;
|
||||
input = numberStepper;
|
||||
case BOOL:
|
||||
var checkBox:CheckBox = new CheckBox();
|
||||
checkBox.id = field.name;
|
||||
if (fieldValue != null) checkBox.selected = fieldValue;
|
||||
else if (field.defaultValue != null) checkBox.selected = field.defaultValue;
|
||||
if (field.defaultValue != null) checkBox.selected = field.defaultValue;
|
||||
input = checkBox;
|
||||
case ENUM:
|
||||
var dropDown:DropDown = new DropDown();
|
||||
|
|
@ -267,13 +224,15 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox
|
|||
if (field.keys == null) throw 'Field "${field.name}" is of Enum type but has no keys.';
|
||||
|
||||
// Add entries to the dropdown.
|
||||
|
||||
for (optionName in field.keys.keys())
|
||||
{
|
||||
var optionValue:Null<Dynamic> = field.keys.get(optionName);
|
||||
// trace('$optionName : $optionValue');
|
||||
dropDown.dataSource.add({value: optionValue, text: optionName});
|
||||
}
|
||||
|
||||
dropDown.value = fieldValue ?? field.defaultValue;
|
||||
dropDown.value = field.defaultValue;
|
||||
|
||||
// TODO: Add an option to customize sort.
|
||||
dropDown.dataSource.sort('text', ASCENDING);
|
||||
|
|
@ -282,8 +241,7 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox
|
|||
case STRING:
|
||||
input = new TextField();
|
||||
input.id = field.name;
|
||||
if (fieldValue != null) input.text = fieldValue;
|
||||
else if (field.defaultValue != null) input.text = field.defaultValue;
|
||||
if (field.defaultValue != null) input.text = field.defaultValue;
|
||||
default:
|
||||
// Unknown type. Display a label that proclaims the type so we can debug it.
|
||||
input = new Label();
|
||||
|
|
@ -306,202 +264,47 @@ class ChartEditorEventDataToolbox extends ChartEditorBaseToolbox
|
|||
|
||||
target.addComponent(inputBox);
|
||||
|
||||
// Special handling for ease field to automatically detect and separate direction
|
||||
// No, im not gonna kill myself
|
||||
if (field.name == 'ease' && hasEaseDirField)
|
||||
{
|
||||
input.onChange = function(event:UIEvent) {
|
||||
var value = event.target.value;
|
||||
if (field.type == ENUM)
|
||||
{
|
||||
var drp:DropDown = cast event.target;
|
||||
value = drp.selectedItem?.value ?? field.defaultValue;
|
||||
}
|
||||
|
||||
trace('ChartEditorToolboxHandler.buildEventDataFormFromSchema() - ${event.target.id} = ${value}');
|
||||
|
||||
final currentData = new Map<String, Dynamic>();
|
||||
for (key in chartEditorState.eventDataToPlace.keys())
|
||||
currentData.set(key, chartEditorState.eventDataToPlace.get(key));
|
||||
|
||||
// Check if ease value contains direction and split it
|
||||
if (value != null && Std.isOfType(value, String))
|
||||
{
|
||||
var converted = convertEaseDataForField(value, target);
|
||||
if (converted.converted)
|
||||
{
|
||||
// Update the display to show base value
|
||||
input.pauseEvent(UIEvent.CHANGE, true);
|
||||
switch (input)
|
||||
{
|
||||
case Std.isOfType(_, DropDown) => true:
|
||||
var dropDown:DropDown = cast input;
|
||||
dropDown.value = converted.baseEase;
|
||||
case Std.isOfType(_, TextField) => true:
|
||||
var textField:TextField = cast input;
|
||||
textField.text = converted.baseEase;
|
||||
default:
|
||||
}
|
||||
input.resumeEvent(UIEvent.CHANGE, true, true);
|
||||
|
||||
for (key => val in currentData)
|
||||
{
|
||||
if (key != 'ease' && key != 'easeDir') chartEditorState.eventDataToPlace.set(key, val);
|
||||
}
|
||||
chartEditorState.eventDataToPlace.set('ease', converted.baseEase);
|
||||
chartEditorState.eventDataToPlace.set('easeDir', converted.easeDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (key => val in currentData)
|
||||
{
|
||||
if (key != 'ease') chartEditorState.eventDataToPlace.set(key, val);
|
||||
}
|
||||
chartEditorState.eventDataToPlace.set(event.target.id, value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (key => val in currentData)
|
||||
{
|
||||
if (key != 'ease') chartEditorState.eventDataToPlace.set(key, val);
|
||||
}
|
||||
chartEditorState.eventDataToPlace.set(event.target.id, value);
|
||||
}
|
||||
|
||||
// Edit the event data of any existing events.
|
||||
if (!_initializing && chartEditorState.currentEventSelection.length > 0)
|
||||
{
|
||||
for (songEvent in chartEditorState.currentEventSelection)
|
||||
{
|
||||
songEvent.eventKind = chartEditorState.eventKindToPlace;
|
||||
songEvent.value = Reflect.copy(chartEditorState.eventDataToPlace);
|
||||
}
|
||||
chartEditorState.saveDataDirty = true;
|
||||
chartEditorState.noteDisplayDirty = true;
|
||||
chartEditorState.notePreviewDirty = true;
|
||||
chartEditorState.noteTooltipsDirty = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// Standard onChange handler for non-ease fields
|
||||
input.onChange = function(event:UIEvent) {
|
||||
var value = event.target.value;
|
||||
if (field.type == ENUM)
|
||||
{
|
||||
var drp:DropDown = cast event.target;
|
||||
value = drp.selectedItem?.value ?? field.defaultValue;
|
||||
}
|
||||
else if (field.type == BOOL)
|
||||
{
|
||||
var chk:CheckBox = cast event.target;
|
||||
value = cast(chk.selected, Null<Bool>);
|
||||
}
|
||||
|
||||
trace('ChartEditorToolboxHandler.buildEventDataFormFromSchema() - ${event.target.id} = ${value}');
|
||||
|
||||
// Update the event data to place.
|
||||
if (value == null)
|
||||
{
|
||||
chartEditorState.eventDataToPlace.remove(event.target.id);
|
||||
}
|
||||
else
|
||||
{
|
||||
chartEditorState.eventDataToPlace.set(event.target.id, value);
|
||||
}
|
||||
|
||||
// Edit the event data of any existing events.
|
||||
if (!_initializing && chartEditorState.currentEventSelection.length > 0)
|
||||
{
|
||||
for (songEvent in chartEditorState.currentEventSelection)
|
||||
{
|
||||
songEvent.eventKind = chartEditorState.eventKindToPlace;
|
||||
songEvent.value = Reflect.copy(chartEditorState.eventDataToPlace);
|
||||
}
|
||||
chartEditorState.saveDataDirty = true;
|
||||
chartEditorState.noteDisplayDirty = true;
|
||||
chartEditorState.notePreviewDirty = true;
|
||||
chartEditorState.noteTooltipsDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts ease data in the event data map by splitting combined ease values
|
||||
* @return Whether conversion occurred
|
||||
*/
|
||||
function convertEaseData(data:haxe.DynamicAccess<Dynamic>):Bool
|
||||
{
|
||||
if (data == null) return false;
|
||||
|
||||
var easeValue = data.get('ease');
|
||||
if (easeValue != null && Std.isOfType(easeValue, String))
|
||||
{
|
||||
var easeString:String = easeValue;
|
||||
trace('convertEaseData: Processing ease string "${easeString}"');
|
||||
|
||||
if (SongEvent.EASE_TYPE_DIR_REGEX.match(easeString))
|
||||
{
|
||||
var baseEase = SongEvent.EASE_TYPE_DIR_REGEX.matchedLeft();
|
||||
var easeDir = SongEvent.EASE_TYPE_DIR_REGEX.matched(0);
|
||||
|
||||
// Update the event data with separated values
|
||||
data.set('ease', baseEase);
|
||||
data.set('easeDir', easeDir);
|
||||
|
||||
trace('Auto-split ease on load: ${easeString} -> ${baseEase} + ${easeDir}');
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('convertEaseData: No direction suffix found in "${easeString}"');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('convertEaseData: easeValue is null or not a string: ${easeValue}');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts ease data for a specific field value and updates the UI
|
||||
* @return Object with conversion result
|
||||
*/
|
||||
function convertEaseDataForField(easeValue:String, target:Box):{converted:Bool, baseEase:String, easeDir:String}
|
||||
{
|
||||
if (easeValue != null && SongEvent.EASE_TYPE_DIR_REGEX.match(easeValue))
|
||||
{
|
||||
var baseEase = SongEvent.EASE_TYPE_DIR_REGEX.matchedLeft();
|
||||
var easeDir = SongEvent.EASE_TYPE_DIR_REGEX.matched(0);
|
||||
|
||||
// Find and update the easeDir field if it exists
|
||||
var easeDirField:Component = target.findComponent('easeDir', Component);
|
||||
if (easeDirField != null)
|
||||
{
|
||||
easeDirField.pauseEvent(UIEvent.CHANGE, true);
|
||||
switch (easeDirField)
|
||||
// Update the value of the event data.
|
||||
input.onChange = function(event:UIEvent) {
|
||||
var value = event.target.value;
|
||||
if (field.type == ENUM)
|
||||
{
|
||||
case Std.isOfType(_, DropDown) => true:
|
||||
var easeDirDropDown:DropDown = cast easeDirField;
|
||||
easeDirDropDown.value = easeDir;
|
||||
case Std.isOfType(_, TextField) => true:
|
||||
var easeDirTextField:TextField = cast easeDirField;
|
||||
easeDirTextField.text = easeDir;
|
||||
default:
|
||||
var drp:DropDown = cast event.target;
|
||||
value = drp.selectedItem?.value ?? field.defaultValue;
|
||||
}
|
||||
else if (field.type == BOOL)
|
||||
{
|
||||
var chk:CheckBox = cast event.target;
|
||||
value = cast(chk.selected, Null<Bool>); // Need to cast to nullable bool or the compiler will get mad.
|
||||
}
|
||||
easeDirField.resumeEvent(UIEvent.CHANGE, true, true);
|
||||
|
||||
trace('ChartEditorToolboxHandler - Auto-split ease: ${easeValue} -> ${baseEase} + ${easeDir}');
|
||||
return {converted: true, baseEase: baseEase, easeDir: easeDir};
|
||||
trace('ChartEditorToolboxHandler.buildEventDataFormFromSchema() - ${event.target.id} = ${value}');
|
||||
|
||||
// Edit the event data to place.
|
||||
if (value == null)
|
||||
{
|
||||
chartEditorState.eventDataToPlace.remove(event.target.id);
|
||||
}
|
||||
else
|
||||
{
|
||||
chartEditorState.eventDataToPlace.set(event.target.id, value);
|
||||
}
|
||||
|
||||
// Edit the event data of any existing events.
|
||||
if (!_initializing && chartEditorState.currentEventSelection.length > 0)
|
||||
{
|
||||
for (songEvent in chartEditorState.currentEventSelection)
|
||||
{
|
||||
songEvent.eventKind = chartEditorState.eventKindToPlace;
|
||||
songEvent.value = Reflect.copy(chartEditorState.eventDataToPlace);
|
||||
}
|
||||
chartEditorState.saveDataDirty = true;
|
||||
chartEditorState.noteDisplayDirty = true;
|
||||
chartEditorState.notePreviewDirty = true;
|
||||
chartEditorState.noteTooltipsDirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {converted: false, baseEase: easeValue, easeDir: ''};
|
||||
}
|
||||
|
||||
public static function build(chartEditorState:ChartEditorState):ChartEditorEventDataToolbox
|
||||
|
|
|
|||
Loading…
Reference in a new issue