Skip to content

Commit 08b3af9

Browse files
LasercarHundrec
authored andcommitted
Chart editor - select above/below playhead
1 parent cea54e3 commit 08b3af9

5 files changed

Lines changed: 358 additions & 9 deletions

File tree

source/funkin/ui/debug/charting/ChartEditorState.hx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import funkin.ui.debug.charting.commands.ChartEditorCommand;
5858
import funkin.ui.debug.charting.commands.CopyItemsCommand;
5959
import funkin.ui.debug.charting.commands.CutItemsCommand;
6060
import funkin.ui.debug.charting.commands.DeselectAllItemsCommand;
61+
import funkin.ui.debug.charting.commands.DeselectAllItemsBetweenTimeCommand;
6162
import funkin.ui.debug.charting.commands.DeselectItemsCommand;
6263
import funkin.ui.debug.charting.commands.ExtendNoteLengthCommand;
6364
import funkin.ui.debug.charting.commands.FlipNotesCommand;
@@ -72,6 +73,7 @@ import funkin.ui.debug.charting.commands.RemoveItemsCommand;
7273
import funkin.ui.debug.charting.commands.RemoveNotesCommand;
7374
import funkin.ui.debug.charting.commands.RemoveStackedNotesCommand;
7475
import funkin.ui.debug.charting.commands.SelectAllItemsCommand;
76+
import funkin.ui.debug.charting.commands.SelectAllItemsBetweenTimeCommand;
7577
import funkin.ui.debug.charting.commands.SelectItemsCommand;
7678
import funkin.ui.debug.charting.commands.SetItemSelectionCommand;
7779
import funkin.ui.debug.charting.commands.SwitchDifficultyCommand;
@@ -1966,14 +1968,14 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
19661968
var menubarItemSelectRegion:MenuItem;
19671969

19681970
/**
1969-
* The `Edit -> Select Before Cursor` menu item.
1971+
* The `Edit -> Select Before Playhead` menu item.
19701972
*/
1971-
var menubarItemSelectBeforeCursor:MenuItem;
1973+
var menubarItemSelectBeforePlayhead:MenuItem;
19721974

19731975
/**
1974-
* The `Edit -> Select After Cursor` menu item.
1976+
* The `Edit -> Select After Playhead` menu item.
19751977
*/
1976-
var menubarItemSelectAfterCursor:MenuItem;
1978+
var menubarItemSelectAfterPlayhead:MenuItem;
19771979

19781980
/**
19791981
* The `Edit -> Decrease Note Snap Precision` menu item.
@@ -3294,6 +3296,10 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
32943296

32953297
menubarItemSelectNone.onClick = _ -> performCommand(new DeselectAllItemsCommand());
32963298

3299+
menubarItemSelectBeforePlayhead.onClick = _ -> performCommand(new SelectAllItemsBetweenTimeCommand(scrollPositionInMs + playheadPositionInMs, true, true, true));
3300+
3301+
menubarItemSelectAfterPlayhead.onClick = _ -> performCommand(new SelectAllItemsBetweenTimeCommand(scrollPositionInMs + playheadPositionInMs, false, true, true));
3302+
32973303
menubarItemPlaytestFull.onClick = _ -> testSongInPlayState(false);
32983304
menubarItemPlaytestMinimal.onClick = _ -> testSongInPlayState(true);
32993305

@@ -4512,7 +4518,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
45124518
}
45134519

45144520
// HOME = Scroll to Top
4515-
if (FlxG.keys.justPressed.HOME)
4521+
if (!FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.HOME)
45164522
{
45174523
// Scroll amount is the difference between the current position and the top.
45184524
scrollAmount = 0 - this.scrollPositionInPixels;
@@ -4528,7 +4534,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
45284534
}
45294535

45304536
// END = Scroll to Bottom
4531-
if (FlxG.keys.justPressed.END)
4537+
if (!FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.END)
45324538
{
45334539
// Scroll amount is the difference between the current position and the bottom.
45344540
scrollAmount = this.songLengthInPixels - this.scrollPositionInPixels;
@@ -6218,6 +6224,26 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
62186224
// Deselect all items.
62196225
performCommand(new DeselectAllItemsCommand());
62206226
}
6227+
6228+
// SHIFT + Home = Select all above playhead
6229+
if (FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.HOME)
6230+
{
6231+
// CTRL + SHIFT + Home = Inverse - deselect all above playhead
6232+
if (FlxG.keys.pressed.CONTROL)
6233+
performCommand(new DeselectAllItemsBetweenTimeCommand(scrollPositionInMs + playheadPositionInMs, true, true, true));
6234+
else
6235+
performCommand(new SelectAllItemsBetweenTimeCommand(scrollPositionInMs + playheadPositionInMs, true, true, true));
6236+
}
6237+
6238+
// SHIFT + End = Select all below playhead
6239+
if (FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.END)
6240+
{
6241+
// CTRL + SHIFT + Home = Inverse - deselect all below playhead
6242+
if (FlxG.keys.pressed.CONTROL)
6243+
performCommand(new DeselectAllItemsBetweenTimeCommand(scrollPositionInMs + playheadPositionInMs, false, true, true));
6244+
else
6245+
performCommand(new SelectAllItemsBetweenTimeCommand(scrollPositionInMs + playheadPositionInMs, false, true, true));
6246+
}
62216247
}
62226248

62236249
/**
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package funkin.ui.debug.charting.commands;
2+
3+
import funkin.data.song.SongData.SongNoteData;
4+
import funkin.data.song.SongData.SongEventData;
5+
import funkin.data.song.SongDataUtils;
6+
7+
/**
8+
* Command that deselects all selected notes and/or events above or past the time given in the chart editor.
9+
*/
10+
@:nullSafety
11+
@:access(funkin.ui.debug.charting.ChartEditorState)
12+
class DeselectAllItemsBetweenTimeCommand implements ChartEditorCommand
13+
{
14+
var time:Float;
15+
var above:Bool;
16+
17+
var notes:Array<SongNoteData>;
18+
var events:Array<SongEventData>;
19+
20+
var shouldDeselectNotes:Bool;
21+
var shouldDeselectEvents:Bool;
22+
23+
public function new(time:Float, above:Bool, shouldDeselectNotes:Bool, shouldDeselectEvents:Bool)
24+
{
25+
this.time = time;
26+
this.above = above;
27+
28+
this.notes = [];
29+
this.events = [];
30+
31+
this.shouldDeselectNotes = shouldDeselectNotes;
32+
this.shouldDeselectEvents = shouldDeselectEvents;
33+
}
34+
35+
public function execute(state:ChartEditorState):Void
36+
{
37+
if (above)
38+
{
39+
if (shouldDeselectNotes)
40+
{
41+
for (i in 0...state.currentSongChartNoteData.length)
42+
{
43+
if (state.currentSongChartNoteData[i].time < time)
44+
notes.push(state.currentSongChartNoteData[i]);
45+
else
46+
// We've reached the end of the notes above this time,
47+
// there's no reason to waste our time running this loop to completion
48+
break;
49+
}
50+
}
51+
if (shouldDeselectEvents)
52+
{
53+
for (i in 0...state.currentSongChartEventData.length)
54+
{
55+
if (state.currentSongChartEventData[i].time < time)
56+
events.push(state.currentSongChartEventData[i]);
57+
else
58+
break;
59+
}
60+
}
61+
}
62+
else // Deselecting below the time given
63+
{
64+
if (shouldDeselectNotes)
65+
{
66+
for (i in 0...state.currentSongChartNoteData.length)
67+
{
68+
// Backwards for loop (kinda). Neat!
69+
if (state.currentSongChartNoteData[state.currentSongChartNoteData.length - i - 1].time > time)
70+
notes.push(state.currentSongChartNoteData[state.currentSongChartNoteData.length - i - 1]);
71+
else
72+
// We've reached the end of the notes below this time,
73+
// there's no reason to waste our time running this loop to completion
74+
break;
75+
}
76+
}
77+
if (shouldDeselectEvents)
78+
{
79+
for (i in 0...state.currentSongChartEventData.length)
80+
{
81+
if (state.currentSongChartEventData[state.currentSongChartEventData.length - i - 1].time > time)
82+
events.push(state.currentSongChartEventData[state.currentSongChartEventData.length- i - 1]);
83+
else
84+
break;
85+
}
86+
}
87+
}
88+
89+
state.currentNoteSelection = SongDataUtils.subtractNotes(state.currentNoteSelection, this.notes);
90+
state.currentEventSelection = SongDataUtils.subtractEvents(state.currentEventSelection, this.events);
91+
92+
state.noteDisplayDirty = true;
93+
state.notePreviewDirty = true;
94+
}
95+
96+
public function undo(state:ChartEditorState):Void
97+
{
98+
for (note in this.notes)
99+
{
100+
state.currentNoteSelection.push(note);
101+
}
102+
103+
for (event in this.events)
104+
{
105+
state.currentEventSelection.push(event);
106+
}
107+
108+
state.noteDisplayDirty = true;
109+
state.notePreviewDirty = true;
110+
}
111+
112+
public function shouldAddToHistory(state:ChartEditorState):Bool
113+
{
114+
// This command is undoable. Add to the history if we actually performed an action.
115+
return (notes.length > 0 || events.length > 0);
116+
}
117+
118+
public function toString():String
119+
{
120+
var isPlural = (notes.length + events.length) > 1;
121+
var notesOnly = (notes.length > 0 && events.length == 0);
122+
var eventsOnly = (notes.length == 0 && events.length > 0);
123+
124+
if (notesOnly)
125+
{
126+
return 'Deselect ${notes.length} ${isPlural ? 'Notes' : 'Note'}';
127+
}
128+
else if (eventsOnly)
129+
{
130+
return 'Deselect ${events.length} ${isPlural ? 'Events' : 'Event'}';
131+
}
132+
133+
return 'Deselect ${notes.length + events.length} Items';
134+
}
135+
}

0 commit comments

Comments
 (0)