mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-14 11:15:24 -05:00
Clipboard rework
This commit is contained in:
parent
175908f827
commit
7d21d80915
6 changed files with 233 additions and 137 deletions
|
@ -1246,7 +1246,7 @@
|
|||
"notes": [
|
||||
{"t":300, "d":4},
|
||||
{"t":600, "d":2},
|
||||
{"t":900, "d":1},
|
||||
{"t":900, "d":1},-
|
||||
{"t":1300, "d":3},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -439,37 +439,37 @@ abstract SongNoteData(RawSongNoteData)
|
|||
@:op(A == B)
|
||||
public function op_equals(other:SongNoteData):Bool
|
||||
{
|
||||
return this.t == other.t && this.d == other.d && this.l == other.l && this.k == other.k;
|
||||
return this.t == other.time && this.d == other.data && this.l == other.length && this.k == other.kind;
|
||||
}
|
||||
|
||||
@:op(A != B)
|
||||
public function op_notEquals(other:SongNoteData):Bool
|
||||
{
|
||||
return !this.op_equals(other);
|
||||
return this.t != other.time || this.d != other.data || this.l != other.length || this.k != other.kind;
|
||||
}
|
||||
|
||||
@:op(A > B)
|
||||
public function op_greaterThan(other:SongNoteData):Bool
|
||||
{
|
||||
return this.t > other.t;
|
||||
return this.t > other.time;
|
||||
}
|
||||
|
||||
@:op(A < B)
|
||||
public function op_lessThan(other:SongNoteData):Bool
|
||||
{
|
||||
return this.t < other.t;
|
||||
return this.t < other.time;
|
||||
}
|
||||
|
||||
@:op(A >= B)
|
||||
public function op_greaterThanOrEquals(other:SongNoteData):Bool
|
||||
{
|
||||
return this.t >= other.t;
|
||||
return this.t >= other.time;
|
||||
}
|
||||
|
||||
@:op(A <= B)
|
||||
public function op_lessThanOrEquals(other:SongNoteData):Bool
|
||||
{
|
||||
return this.t <= other.t;
|
||||
return this.t <= other.time;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -575,37 +575,37 @@ abstract SongEventData(RawSongEventData)
|
|||
@:op(A == B)
|
||||
public function op_equals(other:SongEventData):Bool
|
||||
{
|
||||
return this.t == other.t && this.e == other.e && this.v == other.v;
|
||||
return this.t == other.time && this.e == other.event && this.v == other.value;
|
||||
}
|
||||
|
||||
@:op(A != B)
|
||||
public function op_notEquals(other:SongEventData):Bool
|
||||
{
|
||||
return !this.op_equals(other);
|
||||
return this.t != other.time || this.e != other.event || this.v != other.value;
|
||||
}
|
||||
|
||||
@:op(A > B)
|
||||
public function op_greaterThan(other:SongEventData):Bool
|
||||
{
|
||||
return this.t > other.t;
|
||||
return this.t > other.time;
|
||||
}
|
||||
|
||||
@:op(A < B)
|
||||
public function op_lessThan(other:SongEventData):Bool
|
||||
{
|
||||
return this.t < other.t;
|
||||
return this.t < other.time;
|
||||
}
|
||||
|
||||
@:op(A >= B)
|
||||
public function op_greaterThanOrEquals(other:SongEventData):Bool
|
||||
{
|
||||
return this.t >= other.t;
|
||||
return this.t >= other.time;
|
||||
}
|
||||
|
||||
@:op(A <= B)
|
||||
public function op_lessThanOrEquals(other:SongEventData):Bool
|
||||
{
|
||||
return this.t <= other.t;
|
||||
return this.t <= other.time;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,65 +1,70 @@
|
|||
package funkin.play.song;
|
||||
|
||||
import funkin.play.song.SongData.SongEventData;
|
||||
import funkin.play.song.SongData.SongNoteData;
|
||||
|
||||
using Lambda;
|
||||
|
||||
class SongDataUtils {
|
||||
/**
|
||||
* Given an array of SongNoteData objects, return a new array of SongNoteData objects
|
||||
* whose timestamps are shifted by the given amount.
|
||||
*
|
||||
* @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> {
|
||||
return notes.map(function(note:SongNoteData):SongNoteData {
|
||||
return new SongNoteData(note.time + offset, note.data, note.length, note.kind);
|
||||
});
|
||||
}
|
||||
class SongDataUtils
|
||||
{
|
||||
/**
|
||||
* Given an array of SongNoteData objects, return a new array of SongNoteData objects
|
||||
* whose timestamps are shifted by the given amount.
|
||||
*
|
||||
* @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>
|
||||
{
|
||||
return notes.map(function(note:SongNoteData):SongNoteData
|
||||
{
|
||||
return new SongNoteData(note.time + offset, note.data, note.length, note.kind);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a certain subset of notes from an array of SongNoteData objects.
|
||||
*
|
||||
* @param notes The array of notes to be subtracted from.
|
||||
* @param subtrahend The notes to remove from the `notes` array. Yes, subtrahend is a real word.
|
||||
*/
|
||||
public static function subtractNotes(notes:Array<SongNoteData>, subtrahend:Array<SongNoteData>) {
|
||||
if (notes.length == 0 || subtrahend.length == 0)
|
||||
return notes;
|
||||
/**
|
||||
* Remove a certain subset of notes from an array of SongNoteData objects.
|
||||
*
|
||||
* @param notes The array of notes to be subtracted from.
|
||||
* @param subtrahend The notes to remove from the `notes` array. Yes, subtrahend is a real word.
|
||||
*/
|
||||
public static function subtractNotes(notes:Array<SongNoteData>, subtrahend:Array<SongNoteData>)
|
||||
{
|
||||
if (notes.length == 0 || subtrahend.length == 0)
|
||||
return notes;
|
||||
|
||||
if (subtrahend.length == 1)
|
||||
return notes.remove(subtrahend[0]);
|
||||
return notes.filter(function(note:SongNoteData):Bool
|
||||
{
|
||||
// SongNoteData's == operation has been overridden so that this will work.
|
||||
return !subtrahend.has(note);
|
||||
});
|
||||
}
|
||||
|
||||
return notes.filter(function(note:SongNoteData):Bool {
|
||||
// SongNoteData's == operation has been overridden so that this will work.
|
||||
return !subtrahend.has(note);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Remove a certain subset of events from an array of SongEventData objects.
|
||||
*
|
||||
* @param events The array of events to be subtracted from.
|
||||
* @param subtrahend The events to remove from the `events` array. Yes, subtrahend is a real word.
|
||||
*/
|
||||
public static function subtractEvents(events:Array<SongEventData>, subtrahend:Array<SongEventData>)
|
||||
{
|
||||
if (events.length == 0 || subtrahend.length == 0)
|
||||
return events;
|
||||
|
||||
/**
|
||||
* Remove a certain subset of events from an array of SongEventData objects.
|
||||
*
|
||||
* @param events The array of events to be subtracted from.
|
||||
* @param subtrahend The events to remove from the `events` array. Yes, subtrahend is a real word.
|
||||
*/
|
||||
public static function subtractEvents(events:Array<SongEventData>, subtrahend:Array<SongEventData>) {
|
||||
if (events.length == 0 || subtrahend.length == 0)
|
||||
return events;
|
||||
return events.filter(function(event:SongEventData):Bool
|
||||
{
|
||||
// SongEventData's == operation has been overridden so that this will work.
|
||||
return !subtrahend.has(event);
|
||||
});
|
||||
}
|
||||
|
||||
if (subtrahend.length == 1)
|
||||
return events.remove(subtrahend[0]);
|
||||
|
||||
return events.filter(function(event:SongEventData):Bool {
|
||||
// SongEventData's == operation has been overridden so that this will work.
|
||||
return !subtrahend.has(event);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an array of notes to be used as the clipboard data.
|
||||
*
|
||||
* Offset the provided array of notes such that the first note is at 0 milliseconds.
|
||||
*/
|
||||
public static function buildClipboard(notes:Array<SongNoteData>):Array<SongNoteData> {
|
||||
return offsetSongNoteData(notes, -notes[0].time);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Prepare an array of notes to be used as the clipboard data.
|
||||
*
|
||||
* Offset the provided array of notes such that the first note is at 0 milliseconds.
|
||||
*/
|
||||
public static function buildClipboard(notes:Array<SongNoteData>):Array<SongNoteData>
|
||||
{
|
||||
return offsetSongNoteData(notes, -notes[0].time);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package funkin.ui.debug.charting;
|
||||
|
||||
import funkin.play.song.SongDataUtils;
|
||||
import funkin.play.song.SongData.SongNoteData;
|
||||
import funkin.play.song.SongData.SongEventData;
|
||||
import funkin.play.song.SongData.SongNoteData;
|
||||
import funkin.play.song.SongDataUtils;
|
||||
|
||||
using Lambda;
|
||||
|
||||
|
@ -37,25 +37,26 @@ interface ChartEditorCommand
|
|||
|
||||
class AddNotesCommand implements ChartEditorCommand
|
||||
{
|
||||
private var notes:SongNoteData;
|
||||
private var notes:Array<SongNoteData>;
|
||||
|
||||
public function new(notes:SongNoteData)
|
||||
public function new(notes:Array<SongNoteData>)
|
||||
{
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
public function execute(state:ChartEditorState):Void
|
||||
{
|
||||
for (note in notes) {
|
||||
for (note in notes)
|
||||
{
|
||||
state.currentSongChartNoteData.push(note);
|
||||
}
|
||||
|
||||
state.currentSelection = notes;
|
||||
state.playSound(Paths.sound('funnyNoise/funnyNoise-08'));
|
||||
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
|
@ -67,48 +68,52 @@ class AddNotesCommand implements ChartEditorCommand
|
|||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
public function toString():String
|
||||
{
|
||||
if (notes.length == 1) {
|
||||
if (notes.length == 1)
|
||||
{
|
||||
var dir:String = notes[0].getDirectionName();
|
||||
return 'Add $dir Note';
|
||||
}
|
||||
|
||||
|
||||
return 'Add ${notes.length} Notes';
|
||||
}
|
||||
}
|
||||
|
||||
class RemoveNoteCommand implements ChartEditorCommand
|
||||
class RemoveNotesCommand implements ChartEditorCommand
|
||||
{
|
||||
private var note:SongNoteData;
|
||||
private var notes:Array<SongNoteData>;
|
||||
|
||||
public function new(note:SongNoteData)
|
||||
public function new(notes:Array<SongNoteData>)
|
||||
{
|
||||
this.note = note;
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
public function execute(state:ChartEditorState):Void
|
||||
{
|
||||
state.currentSongChartNoteData.remove(note);
|
||||
state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, notes);
|
||||
state.currentSelection = [];
|
||||
state.playSound(Paths.sound('funnyNoise/funnyNoise-01'));
|
||||
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
public function undo(state:ChartEditorState):Void
|
||||
{
|
||||
state.currentSongChartNoteData.push(note);
|
||||
state.currentSelection = [note];
|
||||
for (note in notes)
|
||||
{
|
||||
state.currentSongChartNoteData.push(note);
|
||||
}
|
||||
state.currentSelection = notes;
|
||||
state.playSound(Paths.sound('funnyNoise/funnyNoise-08'));
|
||||
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
|
@ -117,11 +122,12 @@ class RemoveNoteCommand implements ChartEditorCommand
|
|||
|
||||
public function toString():String
|
||||
{
|
||||
if (notes.length == 1) {
|
||||
if (notes.length == 1)
|
||||
{
|
||||
var dir:String = notes[0].getDirectionName();
|
||||
return 'Remove $dir Note';
|
||||
}
|
||||
|
||||
|
||||
return 'Remove ${notes.length} Notes';
|
||||
}
|
||||
}
|
||||
|
@ -176,7 +182,8 @@ class SelectNotesCommand implements ChartEditorCommand
|
|||
|
||||
public function execute(state:ChartEditorState):Void
|
||||
{
|
||||
for (note in this.notes) {
|
||||
for (note in this.notes)
|
||||
{
|
||||
state.currentSelection.push(note);
|
||||
}
|
||||
|
||||
|
@ -187,23 +194,24 @@ class SelectNotesCommand implements ChartEditorCommand
|
|||
public function undo(state:ChartEditorState):Void
|
||||
{
|
||||
state.currentSelection = SongDataUtils.subtractNotes(state.currentSelection, this.notes);
|
||||
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
}
|
||||
|
||||
public function toString():String
|
||||
{
|
||||
if (notes.length == 1) {
|
||||
if (notes.length == 1)
|
||||
{
|
||||
var dir:String = notes[0].getDirectionName();
|
||||
return 'Select $dir Note';
|
||||
}
|
||||
|
||||
|
||||
return 'Select ${notes.length} Notes';
|
||||
}
|
||||
}
|
||||
|
||||
class DeselectNoteCommand implements ChartEditorCommand
|
||||
class DeselectNotesCommand implements ChartEditorCommand
|
||||
{
|
||||
private var notes:Array<SongNoteData>;
|
||||
|
||||
|
@ -222,21 +230,23 @@ class DeselectNoteCommand implements ChartEditorCommand
|
|||
|
||||
public function undo(state:ChartEditorState):Void
|
||||
{
|
||||
for (note in this.notes) {
|
||||
for (note in this.notes)
|
||||
{
|
||||
state.currentSelection.push(note);
|
||||
}
|
||||
|
||||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
}
|
||||
|
||||
public function toString():String
|
||||
{
|
||||
if (notes.length == 1) {
|
||||
if (notes.length == 1)
|
||||
{
|
||||
var dir:String = notes[0].getDirectionName();
|
||||
return 'Deselect $dir Note';
|
||||
}
|
||||
|
||||
|
||||
return 'Deselect ${notes.length} Notes';
|
||||
}
|
||||
}
|
||||
|
@ -252,8 +262,7 @@ class SelectAllNotesCommand implements ChartEditorCommand
|
|||
|
||||
public function execute(state:ChartEditorState):Void
|
||||
{
|
||||
state.currentSelection = state.currentSongChartNoteData
|
||||
;
|
||||
state.currentSelection = state.currentSongChartNoteData;
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
}
|
||||
|
@ -336,7 +345,7 @@ class CutNotesCommand implements ChartEditorCommand
|
|||
private var notes:Array<SongNoteData>;
|
||||
private var previousSelection:Array<SongNoteData>;
|
||||
|
||||
public function new(notes:Array<SongNoteData>, ?previousSelection:Array<SongNoteData> = [])
|
||||
public function new(notes:Array<SongNoteData>, ?previousSelection:Array<SongNoteData>)
|
||||
{
|
||||
this.notes = notes;
|
||||
this.previousSelection = previousSelection == null ? [] : previousSelection;
|
||||
|
@ -346,7 +355,7 @@ class CutNotesCommand implements ChartEditorCommand
|
|||
{
|
||||
// Copy the notes.
|
||||
state.currentClipboard = SongDataUtils.buildClipboard(notes);
|
||||
|
||||
|
||||
// Delete the notes.
|
||||
state.currentSongChartNoteData = SongDataUtils.subtractNotes(state.currentSongChartNoteData, notes);
|
||||
state.currentSelection = [];
|
||||
|
@ -363,7 +372,7 @@ class CutNotesCommand implements ChartEditorCommand
|
|||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
|
@ -392,7 +401,7 @@ class PasteNotesCommand implements ChartEditorCommand
|
|||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
|
@ -405,13 +414,13 @@ class PasteNotesCommand implements ChartEditorCommand
|
|||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
public function toString():String
|
||||
{
|
||||
var len:Int = notes.length;
|
||||
var len:Int = state.currentClipboard.length;
|
||||
return 'Paste $len Notes from Clipboard';
|
||||
}
|
||||
}
|
||||
|
@ -419,6 +428,7 @@ class PasteNotesCommand implements ChartEditorCommand
|
|||
class AddEventsCommand implements ChartEditorCommand
|
||||
{
|
||||
private var events:Array<SongEventData>;
|
||||
|
||||
// private var previousSelection:Array<SongEventData>;
|
||||
|
||||
public function new(events:Array<SongEventData>, ?previousSelection:Array<SongEventData>)
|
||||
|
@ -435,7 +445,7 @@ class AddEventsCommand implements ChartEditorCommand
|
|||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
|
@ -447,7 +457,7 @@ class AddEventsCommand implements ChartEditorCommand
|
|||
|
||||
state.noteDisplayDirty = true;
|
||||
state.notePreviewDirty = true;
|
||||
|
||||
|
||||
state.sortChartData();
|
||||
}
|
||||
|
||||
|
@ -456,4 +466,4 @@ class AddEventsCommand implements ChartEditorCommand
|
|||
var len:Int = events.length;
|
||||
return 'Add $len Events';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package funkin.ui.debug.charting;
|
||||
|
||||
import haxe.ui.components.CheckBox;
|
||||
import haxe.ui.containers.TreeViewNode;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.addons.display.FlxGridOverlay;
|
||||
import flixel.addons.display.FlxTiledSprite;
|
||||
|
@ -16,9 +14,20 @@ import funkin.play.song.SongData.SongEventData;
|
|||
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;
|
||||
import funkin.ui.debug.charting.ChartEditorCommand.PasteNotesCommand;
|
||||
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.ui.haxeui.HaxeUIState;
|
||||
import haxe.ui.components.CheckBox;
|
||||
import haxe.ui.containers.TreeView;
|
||||
import haxe.ui.containers.TreeViewNode;
|
||||
import haxe.ui.containers.dialogs.Dialog;
|
||||
import haxe.ui.containers.menus.Menu.MenuEvent;
|
||||
import haxe.ui.containers.menus.MenuBar;
|
||||
|
@ -30,6 +39,8 @@ import haxe.ui.events.UIEvent;
|
|||
import openfl.display.BitmapData;
|
||||
import openfl.geom.Rectangle;
|
||||
|
||||
using Lambda;
|
||||
|
||||
// Since Haxe 3.1.0, if access is allowed to an interface, it extends to all classes implementing that interface.
|
||||
// Thus, any ChartEditorCommand has access to any private field.
|
||||
@:allow(funkin.ui.debug.charting.ChartEditorCommand)
|
||||
|
@ -68,7 +79,7 @@ class ChartEditorState extends HaxeUIState
|
|||
static final SPECTROGRAM_COLOR:FlxColor = 0xFFFF0000;
|
||||
static final SELECTION_SQUARE_BORDER_COLOR:FlxColor = 0xFF339933;
|
||||
static final SELECTION_SQUARE_FILL_COLOR:FlxColor = 0x4033FF33;
|
||||
|
||||
|
||||
/**
|
||||
* INSTANCE DATA
|
||||
*/
|
||||
|
@ -174,7 +185,8 @@ class ChartEditorState extends HaxeUIState
|
|||
*/
|
||||
var isViewDownscroll(default, set):Bool = false;
|
||||
|
||||
function set_isViewDownscroll(value:Bool):Bool {
|
||||
function set_isViewDownscroll(value:Bool):Bool
|
||||
{
|
||||
// Make sure view is updated.
|
||||
noteDisplayDirty = true;
|
||||
notePreviewDirty = true;
|
||||
|
@ -447,7 +459,7 @@ class ChartEditorState extends HaxeUIState
|
|||
* The IMAGE used for the grid.
|
||||
*/
|
||||
var gridBitmap:BitmapData;
|
||||
|
||||
|
||||
/**
|
||||
* The IMAGE used for the selection squares.
|
||||
*/
|
||||
|
@ -577,7 +589,8 @@ class ChartEditorState extends HaxeUIState
|
|||
dark ? GRID_COLOR_1_DARK : GRID_COLOR_1, dark ? GRID_COLOR_2_DARK : GRID_COLOR_2);
|
||||
}
|
||||
|
||||
function makeSelectionSquareBitmap() {
|
||||
function makeSelectionSquareBitmap()
|
||||
{
|
||||
selectionSquareBitmap = new BitmapData(GRID_SIZE, GRID_SIZE, true);
|
||||
|
||||
selectionSquareBitmap.fillRect(new Rectangle(0, 0, GRID_SIZE, GRID_SIZE), SELECTION_SQUARE_BORDER_COLOR);
|
||||
|
@ -710,7 +723,8 @@ class ChartEditorState extends HaxeUIState
|
|||
});
|
||||
setUISelected('menubarItemToggleSidebar', true);
|
||||
|
||||
addUIChangeListener('menubarItemDownscroll', (event:UIEvent) -> {
|
||||
addUIChangeListener('menubarItemDownscroll', (event:UIEvent) ->
|
||||
{
|
||||
isViewDownscroll = event.value;
|
||||
});
|
||||
setUISelected('menubarItemDownscroll', isViewDownscroll);
|
||||
|
@ -1024,46 +1038,56 @@ 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.find(function(note:ChartEditorNoteSprite):Bool
|
||||
{
|
||||
// return note.step == cursorStep && note.column == cursorColumn;
|
||||
return FlxG.mouse.overlaps(note);
|
||||
});
|
||||
|
||||
if (FlxG.keys.pressed.CONTROL) {
|
||||
if (highlightedNote != null) {
|
||||
if (isNoteSelected(highlightedNote.noteData)) {
|
||||
if (FlxG.keys.pressed.CONTROL)
|
||||
{
|
||||
if (highlightedNote != null)
|
||||
{
|
||||
if (isNoteSelected(highlightedNote.noteData))
|
||||
{
|
||||
performCommand(new SelectNotesCommand([highlightedNote.noteData]));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
performCommand(new DeselectNotesCommand([highlightedNote.noteData]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (highlightedNote != null) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (highlightedNote != null)
|
||||
{
|
||||
// Remove the note.
|
||||
performCommand(new RemoveNotesCommand([highlightedNote.noteData]));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Place a note.
|
||||
var eventColumn = (STRUMLINE_SIZE * 2 + 1) - 1;
|
||||
if (cursorColumn == eventColumn)
|
||||
{
|
||||
// Create an event and place it in the chart.
|
||||
var cursorMs = cursorStep * Conductor.stepCrochet;
|
||||
|
||||
|
||||
// TODO: Allow configuring the event to place from the sidebar.
|
||||
var newEventData:SongEventData = new SongEventData(cursorMs, "test", {});
|
||||
|
||||
|
||||
performCommand(new AddEventsCommand([newEventData]));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a note and place it in the chart.
|
||||
var cursorMs = cursorStep * Conductor.stepCrochet;
|
||||
|
||||
|
||||
var newNoteData:SongNoteData = new SongNoteData(cursorMs, cursorColumn, 0, selectedNoteKind);
|
||||
|
||||
|
||||
performCommand(new AddNotesCommand([newNoteData]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1149,14 +1173,17 @@ class ChartEditorState extends HaxeUIState
|
|||
}
|
||||
|
||||
// Handle selection squares.
|
||||
for (member in renderedNoteSelectionSquares.members) {
|
||||
for (member in renderedNoteSelectionSquares.members)
|
||||
{
|
||||
member.kill();
|
||||
}
|
||||
|
||||
for (noteSprite in renderedNotes.members) {
|
||||
if (isNoteSelected(noteSprite.noteData)) {
|
||||
for (noteSprite in renderedNotes.members)
|
||||
{
|
||||
if (isNoteSelected(noteSprite.noteData))
|
||||
{
|
||||
var selectionSquare:FlxSprite = renderedNoteSelectionSquares.recycle(FlxSprite).loadGraphic(selectionSquareBitmap);
|
||||
|
||||
|
||||
selectionSquare.x = noteSprite.x;
|
||||
selectionSquare.y = noteSprite.y;
|
||||
selectionSquare.width = noteSprite.width;
|
||||
|
@ -1474,9 +1501,12 @@ class ChartEditorState extends HaxeUIState
|
|||
this.scrollPosition = value;
|
||||
|
||||
// Move the grid sprite to the correct position.
|
||||
if (isViewDownscroll) {
|
||||
if (isViewDownscroll)
|
||||
{
|
||||
gridTiledSprite.y = -scrollPosition + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
gridTiledSprite.y = -scrollPosition + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
||||
}
|
||||
// Move the rendered notes to the correct position.
|
||||
|
|
51
source/funkin/util/ClipboardUtil.hx
Normal file
51
source/funkin/util/ClipboardUtil.hx
Normal file
|
@ -0,0 +1,51 @@
|
|||
package funkin.util;
|
||||
|
||||
/**
|
||||
* Utility functions for working with the system clipboard.
|
||||
* On platforms that don't support interacting with the clipboard,
|
||||
* an internal clipboard is used (neat!).
|
||||
*/
|
||||
class ClipboardUtil
|
||||
{
|
||||
/**
|
||||
* Add an event listener callback which executes next time the system clipboard is updated.
|
||||
*
|
||||
* @param callback The callback to execute when the clipboard is updated.
|
||||
* @param once If true, the callback will only execute once and then be deleted.
|
||||
* @param priority Set the priority at which the callback will be executed. Higher values execute first.
|
||||
*/
|
||||
public static function addListener(callback:Void->Void, ?once:Bool = false, ?priority:Int = 0):Void
|
||||
{
|
||||
lime.system.Clipboard.onUpdate.add(callback, once, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an event listener callback from the system clipboard.
|
||||
*
|
||||
* @param callback The callback to remove.
|
||||
*/
|
||||
public static function removeListener(callback:Void->Void):Void
|
||||
{
|
||||
lime.system.Clipboard.onUpdate.remove(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current contents of the system clipboard.
|
||||
*
|
||||
* @return The current contents of the system clipboard.
|
||||
*/
|
||||
public static function getClipboard():String
|
||||
{
|
||||
return lime.system.Clipboard.text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the contents of the system clipboard.
|
||||
*
|
||||
* @param text The text to set the system clipboard to.
|
||||
*/
|
||||
public static function setClipboard(text:String):String
|
||||
{
|
||||
return lime.system.Clipboard.text = text;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue