package funkin.ui.debug.charting.commands; import funkin.data.song.SongData.SongNoteData; import funkin.data.song.SongData.SongEventData; import funkin.data.song.SongDataUtils; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; /** * Command that copies a given set of notes and song events to the clipboard, * without deleting them from the chart editor. */ @:nullSafety @:access(funkin.ui.debug.charting.ChartEditorState) class CopyItemsCommand implements ChartEditorCommand { var notes:Array; var events:Array; public function new(notes:Array, events:Array) { this.notes = notes; this.events = events; } public function execute(state:ChartEditorState):Void { // Calculate a single time offset for all the notes and events. var timeOffset:Null = state.currentNoteSelection.length > 0 ? Std.int(state.currentNoteSelection[0].time) : null; if (state.currentEventSelection.length > 0) { if (timeOffset == null || state.currentEventSelection[0].time < timeOffset) { timeOffset = Std.int(state.currentEventSelection[0].time); } } SongDataUtils.writeItemsToClipboard( { notes: SongDataUtils.buildNoteClipboard(state.currentNoteSelection, timeOffset), events: SongDataUtils.buildEventClipboard(state.currentEventSelection, timeOffset), }); performVisuals(state); } function performVisuals(state:ChartEditorState):Void { if (state.currentNoteSelection.length > 0) { // Display the "Copied Notes" text. if (state.txtCopyNotif != null) { state.txtCopyNotif.visible = true; state.txtCopyNotif.text = "Copied " + state.currentNoteSelection.length + " notes to clipboard"; state.txtCopyNotif.x = FlxG.mouse.x - (state.txtCopyNotif.width / 2); state.txtCopyNotif.y = FlxG.mouse.y - 16; FlxTween.tween(state.txtCopyNotif, {y: state.txtCopyNotif.y - 32}, 0.5, { type: FlxTween.ONESHOT, ease: FlxEase.quadOut, onComplete: function(_) { state.txtCopyNotif.visible = false; } }); } // Wiggle the notes. for (note in state.renderedNotes.members) { if (state.isNoteSelected(note.noteData)) { FlxTween.globalManager.cancelTweensOf(note); FlxTween.globalManager.cancelTweensOf(note.scale); note.playNoteAnimation(); var prevX:Float = note.scale.x; var prevY:Float = note.scale.y; note.scale.x *= 1.2; note.scale.y *= 1.2; note.angle = FlxG.random.bool() ? -10 : 10; FlxTween.tween(note, {"angle": 0}, 0.8, {ease: FlxEase.elasticOut}); FlxTween.tween(note.scale, {"y": prevX, "x": prevY}, 0.7, { ease: FlxEase.elasticOut, onComplete: function(_) { note.playNoteAnimation(); } }); } } // Wiggle the events. for (event in state.renderedEvents.members) { if (state.isEventSelected(event.eventData)) { FlxTween.globalManager.cancelTweensOf(event); FlxTween.globalManager.cancelTweensOf(event.scale); event.playAnimation(); var prevX:Float = event.scale.x; var prevY:Float = event.scale.y; event.scale.x *= 1.2; event.scale.y *= 1.2; event.angle = FlxG.random.bool() ? -10 : 10; FlxTween.tween(event, {"angle": 0}, 0.8, {ease: FlxEase.elasticOut}); FlxTween.tween(event.scale, {"y": prevX, "x": prevY}, 0.7, { ease: FlxEase.elasticOut, onComplete: function(_) { event.playAnimation(); } }); } } } } public function undo(state:ChartEditorState):Void { // This command is not undoable. Do nothing. } public function shouldAddToHistory(state:ChartEditorState):Bool { // This command is not undoable. Don't add it to the history. return false; } public function toString():String { var len:Int = notes.length + events.length; if (notes.length == 0) return 'Copy $len Events to Clipboard'; else if (events.length == 0) return 'Copy $len Notes to Clipboard'; else return 'Copy $len Items to Clipboard'; } }