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 e5b2d332c..5c3f6cc2c 100644 --- a/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx +++ b/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx @@ -367,6 +367,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 @@ -613,7 +622,11 @@ class ChartEditorDialogHandler var vocalsEntry:Component = state.buildComponent(CHART_EDITOR_DIALOG_UPLOAD_VOCALS_ENTRY_LAYOUT); var vocalsEntryLabel:Label = vocalsEntry.findComponent('vocalsEntryLabel', Label); + #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'); @@ -629,7 +642,12 @@ class ChartEditorDialogHandler type: NotificationType.Success, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #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); } @@ -653,7 +671,11 @@ class ChartEditorDialogHandler expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #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 } }; @@ -663,7 +685,11 @@ class ChartEditorDialogHandler if (selectedFile != 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); @@ -672,7 +698,9 @@ class ChartEditorDialogHandler } // onDropFile + #if FILE_DROP_SUPPORTED addDropHandler(vocalsEntry, onDropFile); + #end dialogContainer.addComponent(vocalsEntry); } @@ -729,7 +757,11 @@ class ChartEditorDialogHandler // Build an entry for -chart.json. var songDefaultChartDataEntry:Component = state.buildComponent(CHART_EDITOR_DIALOG_OPEN_CHART_ENTRY_LAYOUT); var songDefaultChartDataEntryLabel:Label = songDefaultChartDataEntry.findComponent('chartEntryLabel', Label); + #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)); @@ -740,19 +772,31 @@ class ChartEditorDialogHandler // Build entries for -metadata-.json. var songVariationMetadataEntry:Component = state.buildComponent(CHART_EDITOR_DIALOG_OPEN_CHART_ENTRY_LAYOUT); var songVariationMetadataEntryLabel:Label = songVariationMetadataEntry.findComponent('chartEntryLabel', Label); + #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:Label = songVariationChartDataEntry.findComponent('chartEntryLabel', Label); + #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); } } @@ -789,7 +833,11 @@ class ChartEditorDialogHandler expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #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); }; @@ -817,7 +865,11 @@ class ChartEditorDialogHandler expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #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); } @@ -846,7 +898,11 @@ class ChartEditorDialogHandler expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #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) { @@ -874,14 +930,28 @@ class ChartEditorDialogHandler expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #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 } }); } var metadataEntry:Component = state.buildComponent(CHART_EDITOR_DIALOG_OPEN_CHART_ENTRY_LAYOUT); var metadataEntryLabel:Label = metadataEntry.findComponent('chartEntryLabel', Label); + #if FILE_DROP_UNSUPPORTED + trace('File drop unsupported'); + #elseif FILE_DROP_SUPPORTED + trace('File drop supported'); + #end + + #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 f27fbb6c7..0fe6909e7 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -2555,8 +2555,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) { @@ -2717,12 +2716,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;