diff --git a/Project.xml b/Project.xml
index a83db1677..ccf6c83a3 100644
--- a/Project.xml
+++ b/Project.xml
@@ -200,6 +200,12 @@
-->
-->
+
+
+
+
diff --git a/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx b/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx
index bce5443be..b7a51600a 100644
--- a/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx
@@ -391,6 +391,15 @@ class ChartEditorDialogHandler
handler:(String->Void)
}> = [];
+ /**
+ * Add a callback for when a file is dropped on a component.
+ *
+ * On OS X you can’t drop on the application window, but rather only the app icon
+ * (either in the dock while running or the icon on the hard drive) so this must be disabled
+ * and UI updated appropriately.
+ * @param component
+ * @param handler
+ */
static function addDropHandler(component:Component, handler:String->Void):Void
{
#if desktop
@@ -655,7 +664,11 @@ class ChartEditorDialogHandler
var vocalsEntryLabel:Null = vocalsEntry.findComponent('vocalsEntryLabel', Label);
if (vocalsEntryLabel == null) throw 'Could not locate vocalsEntryLabel in Upload Vocals dialog';
+ #if FILE_DROP_SUPPORTED
vocalsEntryLabel.text = 'Drag and drop vocals for $charName here, or click to browse.';
+ #else
+ vocalsEntryLabel.text = 'Click to browse for vocals for $charName.';
+ #end
var onDropFile:String->Void = function(pathStr:String) {
trace('Selected file: $pathStr');
@@ -673,7 +686,12 @@ class ChartEditorDialogHandler
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
});
#end
+ #if FILE_DROP_SUPPORTED
vocalsEntryLabel.text = 'Vocals for $charName (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
+ #else
+ vocalsEntryLabel.text = 'Vocals for $charName (click to browse)\n${path.file}.${path.ext}';
+ #end
+
dialogNoVocals.hidden = true;
removeDropHandler(onDropFile);
}
@@ -699,7 +717,11 @@ class ChartEditorDialogHandler
});
#end
+ #if FILE_DROP_SUPPORTED
vocalsEntryLabel.text = 'Drag and drop vocals for $charName here, or click to browse.';
+ #else
+ vocalsEntryLabel.text = 'Click to browse for vocals for $charName.';
+ #end
}
};
@@ -709,7 +731,11 @@ class ChartEditorDialogHandler
if (selectedFile != null && selectedFile.bytes != null)
{
trace('Selected file: ' + selectedFile.name);
+ #if FILE_DROP_SUPPORTED
+ vocalsEntryLabel.text = 'Vocals for $charName (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
+ #else
vocalsEntryLabel.text = 'Vocals for $charName (click to browse)\n${selectedFile.name}';
+ #end
state.loadVocalsFromBytes(selectedFile.bytes, charKey);
dialogNoVocals.hidden = true;
removeDropHandler(onDropFile);
@@ -718,7 +744,9 @@ class ChartEditorDialogHandler
}
// onDropFile
+ #if FILE_DROP_SUPPORTED
addDropHandler(vocalsEntry, onDropFile);
+ #end
dialogContainer.addComponent(vocalsEntry);
}
@@ -782,7 +810,11 @@ class ChartEditorDialogHandler
var songDefaultChartDataEntry:Component = state.buildComponent(CHART_EDITOR_DIALOG_OPEN_CHART_ENTRY_LAYOUT);
var songDefaultChartDataEntryLabel:Null = songDefaultChartDataEntry.findComponent('chartEntryLabel', Label);
if (songDefaultChartDataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
+ #if FILE_DROP_SUPPORTED
songDefaultChartDataEntryLabel.text = 'Drag and drop -chart.json file, or click to browse.';
+ #else
+ songDefaultChartDataEntryLabel.text = 'Click to browse for -chart.json file.';
+ #end
songDefaultChartDataEntry.onClick = onClickChartDataVariation.bind(Constants.DEFAULT_VARIATION).bind(songDefaultChartDataEntryLabel);
addDropHandler(songDefaultChartDataEntry, onDropFileChartDataVariation.bind(Constants.DEFAULT_VARIATION).bind(songDefaultChartDataEntryLabel));
@@ -794,20 +826,32 @@ class ChartEditorDialogHandler
var songVariationMetadataEntry:Component = state.buildComponent(CHART_EDITOR_DIALOG_OPEN_CHART_ENTRY_LAYOUT);
var songVariationMetadataEntryLabel:Null = songVariationMetadataEntry.findComponent('chartEntryLabel', Label);
if (songVariationMetadataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
+ #if FILE_DROP_SUPPORTED
songVariationMetadataEntryLabel.text = 'Drag and drop -metadata-${variation}.json file, or click to browse.';
+ #else
+ songVariationMetadataEntryLabel.text = 'Click to browse for -metadata-${variation}.json file.';
+ #end
songVariationMetadataEntry.onClick = onClickMetadataVariation.bind(variation).bind(songVariationMetadataEntryLabel);
+ #if FILE_DROP_SUPPORTED
addDropHandler(songVariationMetadataEntry, onDropFileMetadataVariation.bind(variation).bind(songVariationMetadataEntryLabel));
+ #end
chartContainerB.addComponent(songVariationMetadataEntry);
// Build entries for -chart-.json.
var songVariationChartDataEntry:Component = state.buildComponent(CHART_EDITOR_DIALOG_OPEN_CHART_ENTRY_LAYOUT);
var songVariationChartDataEntryLabel:Null = songVariationChartDataEntry.findComponent('chartEntryLabel', Label);
if (songVariationChartDataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
+ #if FILE_DROP_SUPPORTED
songVariationChartDataEntryLabel.text = 'Drag and drop -chart-${variation}.json file, or click to browse.';
+ #else
+ songVariationChartDataEntryLabel.text = 'Click to browse for -chart-${variation}.json file.';
+ #end
songVariationChartDataEntry.onClick = onClickChartDataVariation.bind(variation).bind(songVariationChartDataEntryLabel);
+ #if FILE_DROP_SUPPORTED
addDropHandler(songVariationChartDataEntry, onDropFileChartDataVariation.bind(variation).bind(songVariationChartDataEntryLabel));
+ #end
chartContainerB.addComponent(songVariationChartDataEntry);
}
}
@@ -848,7 +892,11 @@ class ChartEditorDialogHandler
});
#end
+ #if FILE_DROP_SUPPORTED
label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
+ #else
+ label.text = 'Metadata file (click to browse)\n${path.file}.${path.ext}';
+ #end
if (variation == Constants.DEFAULT_VARIATION) constructVariationEntries(songMetadataVariation.playData.songVariations);
};
@@ -878,7 +926,11 @@ class ChartEditorDialogHandler
});
#end
+ #if FILE_DROP_SUPPORTED
label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
+ #else
+ label.text = 'Metadata file (click to browse)\n${selectedFile.name}';
+ #end
if (variation == Constants.DEFAULT_VARIATION) constructVariationEntries(songMetadataVariation.playData.songVariations);
}
@@ -909,7 +961,11 @@ class ChartEditorDialogHandler
});
#end
+ #if FILE_DROP_SUPPORTED
label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
+ #else
+ label.text = 'Chart data file (click to browse)\n${path.file}.${path.ext}';
+ #end
};
onClickChartDataVariation = function(variation:String, label:Label, _event:UIEvent) {
@@ -939,7 +995,11 @@ class ChartEditorDialogHandler
});
#end
+ #if FILE_DROP_SUPPORTED
label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
+ #else
+ label.text = 'Chart data file (click to browse)\n${selectedFile.name}';
+ #end
}
});
}
@@ -947,7 +1007,12 @@ class ChartEditorDialogHandler
var metadataEntry:Component = state.buildComponent(CHART_EDITOR_DIALOG_OPEN_CHART_ENTRY_LAYOUT);
var metadataEntryLabel:Null = metadataEntry.findComponent('chartEntryLabel', Label);
if (metadataEntryLabel == null) throw 'Could not locate chartEntryLabel in Open Chart dialog';
+
+ #if FILE_DROP_SUPPORTED
metadataEntryLabel.text = 'Drag and drop -metadata.json file, or click to browse.';
+ #else
+ metadataEntryLabel.text = 'Click to browse for -metadata.json file.';
+ #end
metadataEntry.onClick = onClickMetadataVariation.bind(Constants.DEFAULT_VARIATION).bind(metadataEntryLabel);
addDropHandler(metadataEntry, onDropFileMetadataVariation.bind(Constants.DEFAULT_VARIATION).bind(metadataEntryLabel));
diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index 15c433d18..3fbe1297d 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -2598,8 +2598,7 @@ class ChartEditorState extends HaxeUIState
if (gridGhostNote == null) throw "ERROR: Tried to handle cursor, but gridGhostNote is null! Check ChartEditorState.buildGrid()";
- var noteData:SongNoteData = gridGhostNote.noteData != null ? gridGhostNote.noteData : new SongNoteData(cursorMs, cursorColumn, 0,
- selectedNoteKind);
+ var noteData:SongNoteData = gridGhostNote.noteData != null ? gridGhostNote.noteData : new SongNoteData(cursorMs, cursorColumn, 0, selectedNoteKind);
if (cursorColumn != noteData.data || selectedNoteKind != noteData.kind)
{
@@ -2760,12 +2759,12 @@ class ChartEditorState extends HaxeUIState
trace('Creating new Note... (${renderedNotes.members.length})');
noteSprite.parentState = this;
- // The note sprite handles animation playback and positioning.
- noteSprite.noteData = noteData;
-
// Setting note data resets position relative to the grid so we fix that.
noteSprite.updateNotePosition(renderedNotes);
+ // The note sprite handles animation playback and positioning.
+ noteSprite.noteData = noteData;
+
// Add hold notes that are now visible (and not already displayed).
if (noteSprite.noteData != null && noteSprite.noteData.length > 0 && displayedHoldNoteData.indexOf(noteSprite.noteData) == -1)
{
diff --git a/source/funkin/util/FileUtil.hx b/source/funkin/util/FileUtil.hx
index 21c2920d9..3a6f4e330 100644
--- a/source/funkin/util/FileUtil.hx
+++ b/source/funkin/util/FileUtil.hx
@@ -240,6 +240,10 @@ class FileUtil
onSaveAll(paths);
}
+ trace('Browsing for directory to save individual files to...');
+ #if mac
+ defaultPath = null;
+ #end
browseForDirectory(null, onSelectDir, onCancel, defaultPath, 'Choose directory to save all files to...');
return true;