diff --git a/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx b/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx index 7391c3d16..bce5443be 100644 --- a/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx +++ b/source/funkin/ui/debug/charting/ChartEditorDialogHandler.hx @@ -306,6 +306,7 @@ class ChartEditorDialogHandler if (state.loadInstrumentalFromBytes(selectedFile.bytes)) { trace('Selected file: ' + selectedFile.fullPath); + #if !mac NotificationManager.instance.addNotification( { title: 'Success', @@ -313,6 +314,7 @@ class ChartEditorDialogHandler type: NotificationType.Success, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end dialog.hideDialog(DialogButton.APPLY); removeDropHandler(onDropFile); @@ -321,6 +323,7 @@ class ChartEditorDialogHandler { trace('Failed to load instrumental (${selectedFile.fullPath})'); + #if !mac NotificationManager.instance.addNotification( { title: 'Failure', @@ -328,6 +331,7 @@ class ChartEditorDialogHandler type: NotificationType.Error, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end } } }); @@ -339,6 +343,7 @@ class ChartEditorDialogHandler if (state.loadInstrumentalFromPath(path)) { // Tell the user the load was successful. + #if !mac NotificationManager.instance.addNotification( { title: 'Success', @@ -346,6 +351,7 @@ class ChartEditorDialogHandler type: NotificationType.Success, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end dialog.hideDialog(DialogButton.APPLY); removeDropHandler(onDropFile); @@ -362,6 +368,7 @@ class ChartEditorDialogHandler } // Tell the user the load was successful. + #if !mac NotificationManager.instance.addNotification( { title: 'Failure', @@ -369,6 +376,7 @@ class ChartEditorDialogHandler type: NotificationType.Error, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end } }; @@ -656,6 +664,7 @@ class ChartEditorDialogHandler if (state.loadVocalsFromPath(path, charKey)) { // Tell the user the load was successful. + #if !mac NotificationManager.instance.addNotification( { title: 'Success', @@ -663,6 +672,7 @@ class ChartEditorDialogHandler type: NotificationType.Success, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end vocalsEntryLabel.text = 'Vocals for $charName (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}'; dialogNoVocals.hidden = true; removeDropHandler(onDropFile); @@ -679,6 +689,7 @@ class ChartEditorDialogHandler } // Vocals failed to load. + #if !mac NotificationManager.instance.addNotification( { title: 'Failure', @@ -686,6 +697,7 @@ class ChartEditorDialogHandler type: NotificationType.Error, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end vocalsEntryLabel.text = 'Drag and drop vocals for $charName here, or click to browse.'; } @@ -811,6 +823,7 @@ class ChartEditorDialogHandler if (songMetadataVariation == null) { // Tell the user the load was not successful. + #if !mac NotificationManager.instance.addNotification( { title: 'Failure', @@ -818,12 +831,14 @@ class ChartEditorDialogHandler type: NotificationType.Error, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end return; } songMetadata.set(variation, songMetadataVariation); // Tell the user the load was successful. + #if !mac NotificationManager.instance.addNotification( { title: 'Success', @@ -831,6 +846,7 @@ class ChartEditorDialogHandler type: NotificationType.Success, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}'; @@ -852,6 +868,7 @@ class ChartEditorDialogHandler songMetadata.set(variation, songMetadataVariation); // Tell the user the load was successful. + #if !mac NotificationManager.instance.addNotification( { title: 'Success', @@ -859,6 +876,7 @@ class ChartEditorDialogHandler type: NotificationType.Success, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}'; @@ -881,6 +899,7 @@ class ChartEditorDialogHandler state.noteDisplayDirty = true; // Tell the user the load was successful. + #if !mac NotificationManager.instance.addNotification( { title: 'Success', @@ -888,6 +907,7 @@ class ChartEditorDialogHandler type: NotificationType.Success, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}'; }; @@ -909,6 +929,7 @@ class ChartEditorDialogHandler state.noteDisplayDirty = true; // Tell the user the load was successful. + #if !mac NotificationManager.instance.addNotification( { title: 'Success', @@ -916,6 +937,7 @@ class ChartEditorDialogHandler type: NotificationType.Success, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}'; } @@ -995,6 +1017,7 @@ class ChartEditorDialogHandler state.loadSong([Constants.DEFAULT_VARIATION => songMetadata], [Constants.DEFAULT_VARIATION => songChartData]); dialog.hideDialog(DialogButton.APPLY); + #if !mac NotificationManager.instance.addNotification( { title: 'Success', @@ -1002,6 +1025,7 @@ class ChartEditorDialogHandler type: NotificationType.Success, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end } }); } @@ -1015,6 +1039,7 @@ class ChartEditorDialogHandler state.loadSong([Constants.DEFAULT_VARIATION => songMetadata], [Constants.DEFAULT_VARIATION => songChartData]); dialog.hideDialog(DialogButton.APPLY); + #if !mac NotificationManager.instance.addNotification( { title: 'Success', @@ -1022,6 +1047,7 @@ class ChartEditorDialogHandler type: NotificationType.Success, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end }; addDropHandler(importBox, onDropFile); diff --git a/source/funkin/ui/debug/charting/ChartEditorNoteSprite.hx b/source/funkin/ui/debug/charting/ChartEditorNoteSprite.hx index c0f65db40..10e0f9045 100644 --- a/source/funkin/ui/debug/charting/ChartEditorNoteSprite.hx +++ b/source/funkin/ui/debug/charting/ChartEditorNoteSprite.hx @@ -143,7 +143,7 @@ class ChartEditorNoteSprite extends FlxSprite return this.noteData; } - public function updateNotePosition(?origin:FlxObject) + public function updateNotePosition(?origin:FlxObject):Void { if (this.noteData == null) return; @@ -173,9 +173,7 @@ class ChartEditorNoteSprite extends FlxSprite if (this.noteData.stepTime >= 0) { // noteData.stepTime is a calculated value which accounts for BPM changes - var stepTime:Float = this.noteData.stepTime; - var roundedStepTime:Float = Math.floor(stepTime + 0.01); // Add epsilon to fix rounding issues - this.y = roundedStepTime * ChartEditorState.GRID_SIZE; + this.y = this.noteData.stepTime * ChartEditorState.GRID_SIZE; } if (origin != null) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 83b8d7b38..a33fd77c6 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -179,14 +179,24 @@ class ChartEditorState extends HaxeUIState */ static final SNAP_QUANTS:Array = [4, 8, 12, 16, 20, 24, 32, 48, 64, 96, 192]; + static final BASE_QUANT:Int = 16; + /** * INSTANCE DATA */ // ============================== public var currentZoomLevel:Float = 1.0; - var noteSnapQuantIndex:Int = 3; + /** + * The internal index of what note snapping value is in use. + * Increment to make placement more preceise and decrement to make placement less precise. + */ + var noteSnapQuantIndex:Int = 3; // default is 16 + /** + * The current note snapping value. + * For example, `32` when snapping to 32nd notes. + */ public var noteSnapQuant(get, never):Int; function get_noteSnapQuant():Int @@ -194,6 +204,17 @@ class ChartEditorState extends HaxeUIState return SNAP_QUANTS[noteSnapQuantIndex]; } + /** + * The ratio of the current note snapping value to the default. + * For example, `32` becomes `0.5` when snapping to 16th notes. + */ + public var noteSnapRatio(get, never):Float; + + function get_noteSnapRatio():Float + { + return BASE_QUANT / noteSnapQuant; + } + /** * scrollPosition is the current position in the song, in pixels. * One pixel is 1/40 of 1 step, and 1/160 of 1 beat. @@ -1769,7 +1790,7 @@ class ChartEditorState extends HaxeUIState // These ones only happen if the modal dialog is not open. handleScrollKeybinds(); // handleZoom(); - // handleSnap(); + handleSnap(); handleCursor(); handleMenubar(); @@ -2027,11 +2048,29 @@ class ChartEditorState extends HaxeUIState if (FlxG.keys.justPressed.LEFT) { noteSnapQuantIndex--; + #if !mac + NotificationManager.instance.addNotification( + { + title: 'Note Snapping', + body: 'Updated note snapping to 1/${noteSnapQuant}', + type: NotificationType.Success, + expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME + }); + #end } if (FlxG.keys.justPressed.RIGHT) { noteSnapQuantIndex++; + #if !mac + NotificationManager.instance.addNotification( + { + title: 'Note Snapping', + body: 'Updated note snapping to 1/${noteSnapQuant}', + type: NotificationType.Success, + expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME + }); + #end } } @@ -2119,8 +2158,12 @@ class ChartEditorState extends HaxeUIState } // The song position of the cursor, in steps. - var cursorFractionalStep:Float = cursorY / GRID_SIZE / (16 / noteSnapQuant); + var cursorFractionalStep:Float = cursorY / GRID_SIZE; var cursorMs:Float = Conductor.getStepTimeInMs(cursorFractionalStep); + // Round the cursor step to the nearest snap quant. + var cursorSnappedStep:Float = Math.floor(cursorFractionalStep / noteSnapRatio) * noteSnapRatio; + var cursorSnappedMs:Float = Conductor.getStepTimeInMs(cursorSnappedStep); + // The direction value for the column at the cursor. var cursorColumn:Int = Math.floor(cursorX / GRID_SIZE); if (cursorColumn < 0) cursorColumn = 0; @@ -2543,7 +2586,7 @@ class ChartEditorState extends HaxeUIState { eventData.event = selectedEventKind; } - eventData.time = cursorMs; + eventData.time = cursorSnappedMs; gridGhostEvent.visible = true; gridGhostEvent.eventData = eventData; @@ -2564,7 +2607,7 @@ class ChartEditorState extends HaxeUIState noteData.data = cursorColumn; gridGhostNote.playNoteAnimation(); } - noteData.time = cursorMs; + noteData.time = cursorSnappedMs; gridGhostNote.visible = true; gridGhostNote.noteData = noteData; @@ -4005,6 +4048,7 @@ class ChartEditorState extends HaxeUIState } } + #if !mac NotificationManager.instance.addNotification( { title: 'Success', @@ -4012,6 +4056,7 @@ class ChartEditorState extends HaxeUIState type: NotificationType.Success, expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME }); + #end } /**