diff --git a/source/funkin/play/song/SongDataUtils.hx b/source/funkin/play/song/SongDataUtils.hx index bba93dbd8..bb7f5af38 100644 --- a/source/funkin/play/song/SongDataUtils.hx +++ b/source/funkin/play/song/SongDataUtils.hx @@ -2,6 +2,8 @@ package funkin.play.song; import funkin.play.song.SongData.SongEventData; import funkin.play.song.SongData.SongNoteData; +import funkin.util.ClipboardUtil; +import funkin.util.SerializerUtil; using Lambda; @@ -65,6 +67,34 @@ class SongDataUtils */ public static function buildClipboard(notes:Array):Array { - return offsetSongNoteData(notes, -notes[0].time); + return offsetSongNoteData(notes, -Std.int(notes[0].time)); } + + public static function writeNotesToClipboard(notes:Array):Void + { + var notesString = SerializerUtil.toJSON(notes); + + ClipboardUtil.setClipboard(notesString); + + trace('Wrote ' + notes.length + ' notes to clipboard.'); + + trace(notesString); + } + + public static function readNotesFromClipboard():Array + { + var notesString = ClipboardUtil.getClipboard(); + + trace('Read ' + notesString.length + ' characters from clipboard.'); + + var notes:Array = SerializerUtil.fromJSON(notesString); + + if (notes == null) { + trace('Failed to parse notes from clipboard.'); + return []; + } else { + trace('Parsed ' + notes.length + ' notes from clipboard.'); + return notes; + } + } } diff --git a/source/funkin/ui/debug/charting/ChartEditorCommand.hx b/source/funkin/ui/debug/charting/ChartEditorCommand.hx index ed357cea8..6892c19d6 100644 --- a/source/funkin/ui/debug/charting/ChartEditorCommand.hx +++ b/source/funkin/ui/debug/charting/ChartEditorCommand.hx @@ -312,34 +312,6 @@ class DeselectAllNotesCommand implements ChartEditorCommand } } -class CopyNotesCommand implements ChartEditorCommand -{ - private var notes:Array; - private var previousSelection:Array; - - public function new(notes:Array, ?previousSelection:Array) - { - this.notes = notes; - this.previousSelection = previousSelection == null ? [] : previousSelection; - } - - public function execute(state:ChartEditorState):Void - { - state.currentClipboard = SongDataUtils.buildClipboard(notes); - } - - public function undo(state:ChartEditorState):Void - { - state.currentClipboard = previousSelection; - } - - public function toString():String - { - var len:Int = notes.length; - return 'Copy $len Notes to Clipboard'; - } -} - class CutNotesCommand implements ChartEditorCommand { private var notes:Array; @@ -354,7 +326,7 @@ class CutNotesCommand implements ChartEditorCommand public function execute(state:ChartEditorState):Void { // Copy the notes. - state.currentClipboard = SongDataUtils.buildClipboard(notes); + SongDataUtils.writeNotesToClipboard(SongDataUtils.buildClipboard(notes)); // Delete the notes. state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, notes); @@ -366,7 +338,6 @@ class CutNotesCommand implements ChartEditorCommand public function undo(state:ChartEditorState):Void { - state.currentClipboard = previousSelection; state.currentSongChartNoteData = state.currentSongChartNoteData.concat(notes); state.currentSelection = notes; @@ -385,16 +356,18 @@ class CutNotesCommand implements ChartEditorCommand class PasteNotesCommand implements ChartEditorCommand { - private var targetTimestamp:Int; + private var targetTimestamp:Float; - public function new(targetTimestamp:Int) + public function new(targetTimestamp:Float) { this.targetTimestamp = targetTimestamp; } public function execute(state:ChartEditorState):Void { - var notesToAdd = SongDataUtils.offsetSongNoteData(state.currentClipboard, targetTimestamp); + var currentClipboard:Array = SongDataUtils.readNotesFromClipboard(); + + var notesToAdd = SongDataUtils.offsetSongNoteData(currentClipboard, Std.int(targetTimestamp)); state.currentSongChartNoteData = state.currentSongChartNoteData.concat(notesToAdd); state.currentSelection = notesToAdd; @@ -409,7 +382,9 @@ class PasteNotesCommand implements ChartEditorCommand { // NOTE: We can assume that the previous action // defined the clipboard, so we don't need to redundantly it here... right? - state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, state.currentClipboard); + // TODO: Test that this works as expected. + var currentClipboard:Array = SongDataUtils.readNotesFromClipboard(); + state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, currentClipboard); state.currentSelection = []; state.noteDisplayDirty = true; @@ -420,8 +395,8 @@ class PasteNotesCommand implements ChartEditorCommand public function toString():String { - var len:Int = state.currentClipboard.length; - return 'Paste $len Notes from Clipboard'; + var currentClipboard:Array = SongDataUtils.readNotesFromClipboard(); + return 'Paste ${currentClipboard.length} Notes from Clipboard'; } } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 05c810b1f..732c47fe2 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -15,7 +15,6 @@ import funkin.play.song.SongData.SongMetadata; import funkin.play.song.SongData.SongNoteData; import funkin.play.song.SongSerializer; import funkin.ui.debug.charting.ChartEditorCommand.AddNotesCommand; -import funkin.ui.debug.charting.ChartEditorCommand.CopyNotesCommand; import funkin.ui.debug.charting.ChartEditorCommand.CutNotesCommand; import funkin.ui.debug.charting.ChartEditorCommand.DeselectAllNotesCommand; import funkin.ui.debug.charting.ChartEditorCommand.DeselectNotesCommand; @@ -24,6 +23,7 @@ import funkin.ui.debug.charting.ChartEditorCommand.RemoveNotesCommand; import funkin.ui.debug.charting.ChartEditorCommand.SelectAllNotesCommand; import funkin.ui.debug.charting.ChartEditorCommand.SelectNotesCommand; import funkin.ui.debug.charting.ChartEditorCommand; +import funkin.play.song.SongDataUtils; import funkin.ui.haxeui.HaxeUIState; import haxe.ui.components.CheckBox; import haxe.ui.containers.TreeView; @@ -243,12 +243,6 @@ class ChartEditorState extends HaxeUIState */ var currentSelection:Array = []; - /** - * The user's current clipboard. Contains a full list of the notes they have copied or cut. - * TODO: Replace this with serialization in the real clipboard. - */ - var currentClipboard:Array = []; - /** * AUDIO AND SOUND DATA */ @@ -676,6 +670,10 @@ class ChartEditorState extends HaxeUIState renderedNotes.setPosition(gridTiledSprite.x, gridTiledSprite.y); add(renderedNotes); + renderedNoteSelectionSquares = new FlxTypedSpriteGroup(); + renderedNoteSelectionSquares.setPosition(gridTiledSprite.x, gridTiledSprite.y); + add(renderedNoteSelectionSquares); + /* var sustainSprite:SustainTrail = new SustainTrail(0, 600, Paths.image('NOTE_hold_assets'), 0.9, false); sustainSprite.scrollFactor.set(0, 0); @@ -1038,7 +1036,7 @@ class ChartEditorState extends HaxeUIState if (FlxG.mouse.justPressed) { // Find the first note that is at the cursor position. - var highlightedNote:ChartEditorNoteSprite = renderedNotes.find(function(note:ChartEditorNoteSprite):Bool + var highlightedNote:ChartEditorNoteSprite = renderedNotes.members.find(function(note:ChartEditorNoteSprite):Bool { // return note.step == cursorStep && note.column == cursorColumn; return FlxG.mouse.overlaps(note); @@ -1221,6 +1219,28 @@ class ChartEditorState extends HaxeUIState { redoLastCommand(); } + + // CTRL + C = Copy + if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.C) + { + // Copy selected notes. + // We don't need a command for this since we can't undo it. + SongDataUtils.writeNotesToClipboard(SongDataUtils.buildClipboard(currentSelection)); + } + + // CTRL + X = Cut + if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.X) + { + // Cut selected notes. + performCommand(new CutNotesCommand(currentSelection)); + } + + // CTRL + V = Paste + if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.V) + { + // Paste notes from clipboard, at the playhead. + performCommand(new PasteNotesCommand(scrollPositionInMs + playheadPositionInMs)); + } } /** @@ -1511,6 +1531,7 @@ class ChartEditorState extends HaxeUIState } // Move the rendered notes to the correct position. renderedNotes.setPosition(gridTiledSprite.x, gridTiledSprite.y); + renderedNoteSelectionSquares.setPosition(renderedNotes.x, renderedNotes.y); return this.scrollPosition; }