1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2024-10-03 15:59:04 +00:00

Merge pull request #167 from FunkinCrew/rewrite/feature/snapped-paste

Chart Editor: Snapped Paste and Event Visiblity
This commit is contained in:
Cameron Taylor 2023-10-15 19:39:56 -04:00 committed by GitHub
commit 965363c062
4 changed files with 90 additions and 20 deletions

2
assets

@ -1 +1 @@
Subproject commit f2e37de1ff308eeaf65babad2a4089096c40cedb
Subproject commit 8104d43e584a1f25e574438d7b21a7e671358969

View file

@ -21,11 +21,21 @@ class SongDataUtils
* @param notes The notes to modify.
* @param offset The time difference to apply in milliseconds.
*/
public static function offsetSongNoteData(notes:Array<SongNoteData>, offset:Int):Array<SongNoteData>
public static function offsetSongNoteData(notes:Array<SongNoteData>, offset:Float):Array<SongNoteData>
{
return notes.map(function(note:SongNoteData):SongNoteData {
return new SongNoteData(note.time + offset, note.data, note.length, note.kind);
});
var offsetNote = function(note:SongNoteData):SongNoteData {
var time:Float = note.time + offset;
var data:Int = note.data;
var length:Float = note.length;
var kind:String = note.kind;
return new SongNoteData(time, data, length, kind);
};
trace(notes);
trace(notes[0]);
var result = [for (i in 0...notes.length) offsetNote(notes[i])];
trace(result);
return result;
}
/**
@ -36,7 +46,7 @@ class SongDataUtils
* @param events The events to modify.
* @param offset The time difference to apply in milliseconds.
*/
public static function offsetSongEventData(events:Array<SongEventData>, offset:Int):Array<SongEventData>
public static function offsetSongEventData(events:Array<SongEventData>, offset:Float):Array<SongEventData>
{
return events.map(function(event:SongEventData):SongEventData {
return new SongEventData(event.time + offset, event.event, event.value);
@ -152,7 +162,8 @@ class SongDataUtils
*/
public static function writeItemsToClipboard(data:SongClipboardItems):Void
{
var dataString = SerializerUtil.toJSON(data);
var writer = new json2object.JsonWriter<SongClipboardItems>();
var dataString:String = writer.write(data, ' ');
ClipboardUtil.setClipboard(dataString);
@ -170,19 +181,24 @@ class SongDataUtils
trace('Read ${notesString.length} characters from clipboard.');
var data:SongClipboardItems = notesString.parseJSON();
if (data == null)
var parser = new json2object.JsonParser<SongClipboardItems>();
parser.fromJson(notesString, 'clipboard');
if (parser.errors.length > 0)
{
trace('Failed to parse notes from clipboard.');
trace('[SongDataUtils] Error parsing note JSON data from clipboard.');
for (error in parser.errors)
DataError.printError(error);
return {
valid: false,
notes: [],
events: []
};
}
else
{
var data:SongClipboardItems = parser.value;
trace('Parsed ' + data.notes.length + ' notes and ' + data.events.length + ' from clipboard.');
data.valid = true;
return data;
}
}
@ -230,6 +246,7 @@ class SongDataUtils
typedef SongClipboardItems =
{
?valid:Bool,
notes:Array<SongNoteData>,
events:Array<SongEventData>
}

View file

@ -1,5 +1,7 @@
package funkin.ui.debug.charting;
import haxe.ui.notifications.NotificationType;
import haxe.ui.notifications.NotificationManager;
import funkin.data.song.SongData.SongEventData;
import funkin.data.song.SongData.SongNoteData;
import funkin.data.song.SongDataUtils;
@ -760,6 +762,22 @@ class PasteItemsCommand implements ChartEditorCommand
{
var currentClipboard:SongClipboardItems = SongDataUtils.readItemsFromClipboard();
if (currentClipboard.valid != true)
{
#if !mac
NotificationManager.instance.addNotification(
{
title: 'Failed to Paste',
body: 'Could not parse clipboard contents.',
type: NotificationType.Error,
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
});
#end
return;
}
trace(currentClipboard.notes);
addedNotes = SongDataUtils.offsetSongNoteData(currentClipboard.notes, Std.int(targetTimestamp));
addedEvents = SongDataUtils.offsetSongEventData(currentClipboard.events, Std.int(targetTimestamp));
@ -773,6 +791,16 @@ class PasteItemsCommand implements ChartEditorCommand
state.notePreviewDirty = true;
state.sortChartData();
#if !mac
NotificationManager.instance.addNotification(
{
title: 'Paste Successful',
body: 'Successfully pasted clipboard contents.',
type: NotificationType.Success,
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
});
#end
}
public function undo(state:ChartEditorState):Void

View file

@ -1547,11 +1547,11 @@ class ChartEditorState extends HaxeUIState
renderedEvents.setPosition(gridTiledSprite.x, gridTiledSprite.y);
add(renderedEvents);
renderedNotes.zIndex = 25;
renderedEvents.zIndex = 25;
renderedSelectionSquares.setPosition(gridTiledSprite.x, gridTiledSprite.y);
add(renderedSelectionSquares);
renderedNotes.zIndex = 26;
renderedSelectionSquares.zIndex = 26;
}
function buildAdditionalUI():Void
@ -1662,7 +1662,18 @@ class ChartEditorState extends HaxeUIState
addUIClickListener('menubarItemCut', _ -> performCommand(new CutItemsCommand(currentNoteSelection, currentEventSelection)));
addUIClickListener('menubarItemPaste', _ -> performCommand(new PasteItemsCommand(scrollPositionInMs + playheadPositionInMs)));
addUIClickListener('menubarItemPaste', _ -> {
var targetMs:Float = scrollPositionInMs + playheadPositionInMs;
var targetStep:Float = Conductor.getTimeInSteps(targetMs);
var targetSnappedStep:Float = Math.floor(targetStep / noteSnapRatio) * noteSnapRatio;
var targetSnappedMs:Float = Conductor.getStepTimeInMs(targetSnappedStep);
performCommand(new PasteItemsCommand(targetSnappedMs));
});
addUIClickListener('menubarItemPasteUnsnapped', _ -> {
var targetMs:Float = scrollPositionInMs + playheadPositionInMs;
performCommand(new PasteItemsCommand(targetMs));
});
addUIClickListener('menubarItemDelete', function(_) {
if (currentNoteSelection.length > 0 && currentEventSelection.length > 0)
@ -2335,7 +2346,6 @@ class ChartEditorState extends HaxeUIState
// Scroll up.
var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.screenY;
scrollPositionInPixels -= diff * 0.5; // Too fast!
trace('Scroll up: ' + diff);
moveSongToScrollPosition();
}
else if (FlxG.mouse.screenY > (playbarHeadLayout?.y ?? 0.0))
@ -2343,7 +2353,6 @@ class ChartEditorState extends HaxeUIState
// Scroll down.
var diff:Float = FlxG.mouse.screenY - (playbarHeadLayout?.y ?? 0.0);
scrollPositionInPixels += diff * 0.5; // Too fast!
trace('Scroll down: ' + diff);
moveSongToScrollPosition();
}
@ -2968,8 +2977,8 @@ class ChartEditorState extends HaxeUIState
// Set the position and size (because we might be recycling one with bad values).
selectionSquare.x = noteSprite.x;
selectionSquare.y = noteSprite.y;
selectionSquare.width = noteSprite.width;
selectionSquare.height = noteSprite.height;
selectionSquare.width = GRID_SIZE;
selectionSquare.height = GRID_SIZE;
}
}
@ -3000,6 +3009,8 @@ class ChartEditorState extends HaxeUIState
FlxG.watch.addQuick("tapNotesRendered", renderedNotes.members.length);
FlxG.watch.addQuick("holdNotesRendered", renderedHoldNotes.members.length);
FlxG.watch.addQuick("eventsRendered", renderedEvents.members.length);
FlxG.watch.addQuick("notesSelected", currentNoteSelection.length);
FlxG.watch.addQuick("eventsSelected", currentEventSelection.length);
}
/**
@ -3029,6 +3040,8 @@ class ChartEditorState extends HaxeUIState
if (selectionSquareBitmap == null)
throw "ERROR: Tried to build selection square, but selectionSquareBitmap is null! Check ChartEditorThemeHandler.updateSelectionSquare()";
FlxG.bitmapLog.add(selectionSquareBitmap, "selectionSquareBitmap");
return new FlxSprite().loadGraphic(selectionSquareBitmap);
}
@ -3148,8 +3161,20 @@ class ChartEditorState extends HaxeUIState
// CTRL + V = Paste
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.V)
{
// Paste notes from clipboard, at the playhead.
performCommand(new PasteItemsCommand(scrollPositionInMs + playheadPositionInMs));
// CTRL + SHIFT + V = Paste Unsnapped.
var targetMs:Float = if (FlxG.keys.pressed.SHIFT)
{
scrollPositionInMs + playheadPositionInMs;
}
else
{
var targetMs:Float = scrollPositionInMs + playheadPositionInMs;
var targetStep:Float = Conductor.getTimeInSteps(targetMs);
var targetSnappedStep:Float = Math.floor(targetStep / noteSnapRatio) * noteSnapRatio;
var targetSnappedMs:Float = Conductor.getStepTimeInMs(targetSnappedStep);
targetSnappedMs;
}
performCommand(new PasteItemsCommand(targetMs));
}
// DELETE = Delete