More chart editor progress (selection)

This commit is contained in:
Eric Myllyoja 2022-10-12 21:42:40 -04:00
parent 7d21d80915
commit cedb224783
3 changed files with 71 additions and 45 deletions

View file

@ -2,6 +2,8 @@ package funkin.play.song;
import funkin.play.song.SongData.SongEventData; import funkin.play.song.SongData.SongEventData;
import funkin.play.song.SongData.SongNoteData; import funkin.play.song.SongData.SongNoteData;
import funkin.util.ClipboardUtil;
import funkin.util.SerializerUtil;
using Lambda; using Lambda;
@ -65,6 +67,34 @@ class SongDataUtils
*/ */
public static function buildClipboard(notes:Array<SongNoteData>):Array<SongNoteData> public static function buildClipboard(notes:Array<SongNoteData>):Array<SongNoteData>
{ {
return offsetSongNoteData(notes, -notes[0].time); return offsetSongNoteData(notes, -Std.int(notes[0].time));
} }
public static function writeNotesToClipboard(notes:Array<SongNoteData>):Void
{
var notesString = SerializerUtil.toJSON(notes);
ClipboardUtil.setClipboard(notesString);
trace('Wrote ' + notes.length + ' notes to clipboard.');
trace(notesString);
}
public static function readNotesFromClipboard():Array<SongNoteData>
{
var notesString = ClipboardUtil.getClipboard();
trace('Read ' + notesString.length + ' characters from clipboard.');
var notes:Array<SongNoteData> = SerializerUtil.fromJSON(notesString);
if (notes == null) {
trace('Failed to parse notes from clipboard.');
return [];
} else {
trace('Parsed ' + notes.length + ' notes from clipboard.');
return notes;
}
}
} }

View file

@ -312,34 +312,6 @@ class DeselectAllNotesCommand implements ChartEditorCommand
} }
} }
class CopyNotesCommand implements ChartEditorCommand
{
private var notes:Array<SongNoteData>;
private var previousSelection:Array<SongNoteData>;
public function new(notes:Array<SongNoteData>, ?previousSelection:Array<SongNoteData>)
{
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 class CutNotesCommand implements ChartEditorCommand
{ {
private var notes:Array<SongNoteData>; private var notes:Array<SongNoteData>;
@ -354,7 +326,7 @@ class CutNotesCommand implements ChartEditorCommand
public function execute(state:ChartEditorState):Void public function execute(state:ChartEditorState):Void
{ {
// Copy the notes. // Copy the notes.
state.currentClipboard = SongDataUtils.buildClipboard(notes); SongDataUtils.writeNotesToClipboard(SongDataUtils.buildClipboard(notes));
// Delete the notes. // Delete the notes.
state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, notes); state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, notes);
@ -366,7 +338,6 @@ class CutNotesCommand implements ChartEditorCommand
public function undo(state:ChartEditorState):Void public function undo(state:ChartEditorState):Void
{ {
state.currentClipboard = previousSelection;
state.currentSongChartNoteData = state.currentSongChartNoteData.concat(notes); state.currentSongChartNoteData = state.currentSongChartNoteData.concat(notes);
state.currentSelection = notes; state.currentSelection = notes;
@ -385,16 +356,18 @@ class CutNotesCommand implements ChartEditorCommand
class PasteNotesCommand 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; this.targetTimestamp = targetTimestamp;
} }
public function execute(state:ChartEditorState):Void public function execute(state:ChartEditorState):Void
{ {
var notesToAdd = SongDataUtils.offsetSongNoteData(state.currentClipboard, targetTimestamp); var currentClipboard:Array<SongNoteData> = SongDataUtils.readNotesFromClipboard();
var notesToAdd = SongDataUtils.offsetSongNoteData(currentClipboard, Std.int(targetTimestamp));
state.currentSongChartNoteData = state.currentSongChartNoteData.concat(notesToAdd); state.currentSongChartNoteData = state.currentSongChartNoteData.concat(notesToAdd);
state.currentSelection = notesToAdd; state.currentSelection = notesToAdd;
@ -409,7 +382,9 @@ class PasteNotesCommand implements ChartEditorCommand
{ {
// NOTE: We can assume that the previous action // NOTE: We can assume that the previous action
// defined the clipboard, so we don't need to redundantly it here... right? // 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<SongNoteData> = SongDataUtils.readNotesFromClipboard();
state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, currentClipboard);
state.currentSelection = []; state.currentSelection = [];
state.noteDisplayDirty = true; state.noteDisplayDirty = true;
@ -420,8 +395,8 @@ class PasteNotesCommand implements ChartEditorCommand
public function toString():String public function toString():String
{ {
var len:Int = state.currentClipboard.length; var currentClipboard:Array<SongNoteData> = SongDataUtils.readNotesFromClipboard();
return 'Paste $len Notes from Clipboard'; return 'Paste ${currentClipboard.length} Notes from Clipboard';
} }
} }

View file

@ -15,7 +15,6 @@ import funkin.play.song.SongData.SongMetadata;
import funkin.play.song.SongData.SongNoteData; import funkin.play.song.SongData.SongNoteData;
import funkin.play.song.SongSerializer; import funkin.play.song.SongSerializer;
import funkin.ui.debug.charting.ChartEditorCommand.AddNotesCommand; 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.CutNotesCommand;
import funkin.ui.debug.charting.ChartEditorCommand.DeselectAllNotesCommand; import funkin.ui.debug.charting.ChartEditorCommand.DeselectAllNotesCommand;
import funkin.ui.debug.charting.ChartEditorCommand.DeselectNotesCommand; 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.SelectAllNotesCommand;
import funkin.ui.debug.charting.ChartEditorCommand.SelectNotesCommand; import funkin.ui.debug.charting.ChartEditorCommand.SelectNotesCommand;
import funkin.ui.debug.charting.ChartEditorCommand; import funkin.ui.debug.charting.ChartEditorCommand;
import funkin.play.song.SongDataUtils;
import funkin.ui.haxeui.HaxeUIState; import funkin.ui.haxeui.HaxeUIState;
import haxe.ui.components.CheckBox; import haxe.ui.components.CheckBox;
import haxe.ui.containers.TreeView; import haxe.ui.containers.TreeView;
@ -243,12 +243,6 @@ class ChartEditorState extends HaxeUIState
*/ */
var currentSelection:Array<SongNoteData> = []; var currentSelection:Array<SongNoteData> = [];
/**
* 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<SongNoteData> = [];
/** /**
* AUDIO AND SOUND DATA * AUDIO AND SOUND DATA
*/ */
@ -676,6 +670,10 @@ class ChartEditorState extends HaxeUIState
renderedNotes.setPosition(gridTiledSprite.x, gridTiledSprite.y); renderedNotes.setPosition(gridTiledSprite.x, gridTiledSprite.y);
add(renderedNotes); add(renderedNotes);
renderedNoteSelectionSquares = new FlxTypedSpriteGroup<FlxSprite>();
renderedNoteSelectionSquares.setPosition(gridTiledSprite.x, gridTiledSprite.y);
add(renderedNoteSelectionSquares);
/* /*
var sustainSprite:SustainTrail = new SustainTrail(0, 600, Paths.image('NOTE_hold_assets'), 0.9, false); var sustainSprite:SustainTrail = new SustainTrail(0, 600, Paths.image('NOTE_hold_assets'), 0.9, false);
sustainSprite.scrollFactor.set(0, 0); sustainSprite.scrollFactor.set(0, 0);
@ -1038,7 +1036,7 @@ class ChartEditorState extends HaxeUIState
if (FlxG.mouse.justPressed) if (FlxG.mouse.justPressed)
{ {
// Find the first note that is at the cursor position. // 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 note.step == cursorStep && note.column == cursorColumn;
return FlxG.mouse.overlaps(note); return FlxG.mouse.overlaps(note);
@ -1221,6 +1219,28 @@ class ChartEditorState extends HaxeUIState
{ {
redoLastCommand(); 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. // Move the rendered notes to the correct position.
renderedNotes.setPosition(gridTiledSprite.x, gridTiledSprite.y); renderedNotes.setPosition(gridTiledSprite.x, gridTiledSprite.y);
renderedNoteSelectionSquares.setPosition(renderedNotes.x, renderedNotes.y);
return this.scrollPosition; return this.scrollPosition;
} }