Skip to content

Commit

Permalink
Even more Moonscraper refactors (YARC-Official#26)
Browse files Browse the repository at this point in the history
* Split out parser process lists into their own files

* Move .chart special phrase processing to process lists

* Remove specialized phrase parsing methods from .mid parser

* Add Solo special phrase type instead of using text events for them

* Add solo phrases to unit tests

* Use regex for text event handling
Nothing else has to check for brackets anymore, among other things

* Properly parse in lyric events on .mid vocal tracks

* Rewrite .chart global section parsing and use regex for detecting sections
  • Loading branch information
TheNathannator authored Jun 17, 2023
1 parent 1cd2097 commit c6e8119
Show file tree
Hide file tree
Showing 10 changed files with 1,120 additions and 907 deletions.
22 changes: 20 additions & 2 deletions YARG.Core.UnitTests/Parsing/ParseBehaviorTests.Chart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ public class ChartParseBehaviorTests
{ SpecialPhrase.Type.ProDrums_Activation, PHRASE_DRUM_FILL },
};

private static readonly List<SpecialPhrase.Type> DrumsOnlySpecialPhrases = new()
{
SpecialPhrase.Type.Starpower,
SpecialPhrase.Type.Versus_Player1,
SpecialPhrase.Type.Versus_Player2,
SpecialPhrase.Type.TremoloLane,
SpecialPhrase.Type.TrillLane,
SpecialPhrase.Type.ProDrums_Activation,
};

private static void GenerateSongSection(MoonSong sourceSong, StringBuilder builder)
{
builder.Append($"{SECTION_SONG}\n{{\n");
Expand Down Expand Up @@ -126,12 +136,20 @@ private static void GenerateInstrumentSection(MoonSong sourceSong, StringBuilder
break;
case SpecialPhrase phrase:
// Drums-only phrases
if (gameMode is not GameMode.Drums && phrase.type is SpecialPhrase.Type.TremoloLane or
SpecialPhrase.Type.TrillLane or SpecialPhrase.Type.ProDrums_Activation)
if (gameMode is not GameMode.Drums && DrumsOnlySpecialPhrases.Contains(phrase.type))
{
eventsToRemove.Add(chartObj);
continue;
}

// Solos are written as text events in .chart
if (phrase.type is SpecialPhrase.Type.Solo)
{
builder.Append($" {phrase.tick} = E {EVENT_SOLO_START}\n");
builder.Append($" {phrase.tick + phrase.length} = E {EVENT_SOLO_END}\n");
continue;
}

int phraseNumber = SpecialPhraseLookup[phrase.type];
builder.Append($" {phrase.tick} = S {phraseNumber} {phrase.length}\n");
break;
Expand Down
8 changes: 6 additions & 2 deletions YARG.Core.UnitTests/Parsing/ParseBehaviorTests.Midi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public class MidiParseBehaviorTests
private static readonly Dictionary<SpecialPhrase.Type, byte[]> GuitarSpecialPhraseLookup = new()
{
{ SpecialPhrase.Type.Starpower, new[] { STARPOWER_NOTE } },
{ SpecialPhrase.Type.Solo, new[] { SOLO_NOTE } },
{ SpecialPhrase.Type.Versus_Player1, new[] { VERSUS_PHRASE_PLAYER_1 } },
{ SpecialPhrase.Type.Versus_Player2, new[] { VERSUS_PHRASE_PLAYER_2 } },
{ SpecialPhrase.Type.TremoloLane, new[] { TREMOLO_LANE_NOTE } },
Expand All @@ -90,6 +91,7 @@ public class MidiParseBehaviorTests
private static readonly Dictionary<SpecialPhrase.Type, byte[]> GhlGuitarSpecialPhraseLookup = new()
{
{ SpecialPhrase.Type.Starpower, new[] { STARPOWER_NOTE } },
{ SpecialPhrase.Type.Solo, new[] { SOLO_NOTE } },
};

private static readonly Dictionary<int, int> ProGuitarNoteOffsetLookup = new()
Expand All @@ -113,6 +115,7 @@ public class MidiParseBehaviorTests
private static readonly Dictionary<SpecialPhrase.Type, byte[]> ProGuitarSpecialPhraseLookup = new()
{
{ SpecialPhrase.Type.Starpower, new[] { STARPOWER_NOTE } },
{ SpecialPhrase.Type.Solo, new[] { SOLO_NOTE_PRO_GUITAR } },
{ SpecialPhrase.Type.TremoloLane, new[] { TREMOLO_LANE_NOTE } },
{ SpecialPhrase.Type.TrillLane, new[] { TRILL_LANE_NOTE } },
};
Expand All @@ -130,6 +133,7 @@ public class MidiParseBehaviorTests
private static readonly Dictionary<SpecialPhrase.Type, byte[]> DrumsSpecialPhraseLookup = new()
{
{ SpecialPhrase.Type.Starpower, new[] { STARPOWER_NOTE } },
{ SpecialPhrase.Type.Solo, new[] { SOLO_NOTE } },
{ SpecialPhrase.Type.Versus_Player1, new[] { VERSUS_PHRASE_PLAYER_1 } },
{ SpecialPhrase.Type.Versus_Player2, new[] { VERSUS_PHRASE_PLAYER_2 } },
{ SpecialPhrase.Type.TremoloLane, new[] { TREMOLO_LANE_NOTE } },
Expand Down Expand Up @@ -262,9 +266,9 @@ private static TrackChunk GenerateTrackChunk(MoonSong sourceSong, MoonInstrument

// Text event flags to enable extended features
if (gameMode == GameMode.Drums)
timedEvents.Add((0, new TextEvent(CHART_DYNAMICS_TEXT_BRACKET)));
timedEvents.Add((0, new TextEvent($"[{CHART_DYNAMICS_TEXT}]")));
else if (gameMode == GameMode.Guitar)
timedEvents.Add((0, new TextEvent(ENHANCED_OPENS_TEXT_BRACKET)));
timedEvents.Add((0, new TextEvent($"[{ENHANCED_OPENS_TEXT}]")));

long lastNoteTick = 0;
foreach (var difficulty in EnumX<Difficulty>.Values)
Expand Down
35 changes: 35 additions & 0 deletions YARG.Core.UnitTests/Parsing/ParseBehaviorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ private static SpecialPhrase NewSpecial(int index, SpecialPhrase.Type type, uint
NewNote(32, GuitarFret.Red),
NewNote(33, GuitarFret.Green),
NewNote(34, GuitarFret.Red),

NewSpecial(35, SpecialPhrase.Type.Solo, RESOLUTION * 6),
NewNote(35, GuitarFret.Green, flags: Flags.Forced),
NewNote(36, GuitarFret.Red, flags: Flags.Forced),
NewNote(37, GuitarFret.Yellow, flags: Flags.Forced),
NewNote(38, GuitarFret.Blue, flags: Flags.Forced),
NewNote(39, GuitarFret.Orange, flags: Flags.Forced),
NewNote(40, GuitarFret.Open, flags: Flags.Forced),
};

public static readonly List<ChartObject> GhlGuitarTrack = new()
Expand Down Expand Up @@ -125,6 +133,15 @@ private static SpecialPhrase NewSpecial(int index, SpecialPhrase.Type type, uint
NewNote(24, GHLiveGuitarFret.White2),
NewNote(25, GHLiveGuitarFret.White3),
NewNote(26, GHLiveGuitarFret.Open),

NewSpecial(27, SpecialPhrase.Type.Solo, RESOLUTION * 7),
NewNote(27, GHLiveGuitarFret.Black1),
NewNote(28, GHLiveGuitarFret.Black2),
NewNote(29, GHLiveGuitarFret.Black3),
NewNote(30, GHLiveGuitarFret.White1),
NewNote(31, GHLiveGuitarFret.White2),
NewNote(32, GHLiveGuitarFret.White3),
NewNote(33, GHLiveGuitarFret.Open),
};

public static readonly List<ChartObject> ProGuitarTrack = new()
Expand Down Expand Up @@ -173,6 +190,14 @@ private static SpecialPhrase NewSpecial(int index, SpecialPhrase.Type type, uint
NewNote(33, ProGuitarString.Yellow, 6),
NewNote(34, ProGuitarString.Yellow, 5),
NewNote(35, ProGuitarString.Yellow, 6),

NewSpecial(36, SpecialPhrase.Type.Solo, RESOLUTION * 6),
NewNote(36, ProGuitarString.Red, 0),
NewNote(37, ProGuitarString.Green, 1),
NewNote(38, ProGuitarString.Orange, 2),
NewNote(39, ProGuitarString.Blue, 3),
NewNote(40, ProGuitarString.Yellow, 4),
NewNote(41, ProGuitarString.Purple, 5),
};

public static readonly List<ChartObject> DrumsTrack = new()
Expand Down Expand Up @@ -262,6 +287,16 @@ private static SpecialPhrase NewSpecial(int index, SpecialPhrase.Type type, uint
NewNote(67, DrumPad.Orange, flags: Flags.ProDrums_Cymbal),
NewNote(68, DrumPad.Yellow, flags: Flags.ProDrums_Cymbal),
NewNote(69, DrumPad.Orange, flags: Flags.ProDrums_Cymbal),

NewSpecial(70, SpecialPhrase.Type.Solo, RESOLUTION * 8),
NewNote(70, DrumPad.Red),
NewNote(71, DrumPad.Yellow),
NewNote(72, DrumPad.Blue),
NewNote(73, DrumPad.Orange),
NewNote(74, DrumPad.Green),
NewNote(75, DrumPad.Yellow, flags: Flags.ProDrums_Cymbal),
NewNote(76, DrumPad.Blue, flags: Flags.ProDrums_Cymbal),
NewNote(77, DrumPad.Orange, flags: Flags.ProDrums_Cymbal),
};

private const byte VOCALS_RANGE_START = MidIOHelper.VOCALS_RANGE_START;
Expand Down
1 change: 1 addition & 0 deletions YARG.Core/MoonscraperChartParser/Events/SpecialPhrase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class SpecialPhrase : ChartObject
public enum Type
{
Starpower,
Solo,

Versus_Player1,
Versus_Player2,
Expand Down
7 changes: 7 additions & 0 deletions YARG.Core/MoonscraperChartParser/IO/Chart/ChartIOHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See LICENSE in project root for license information.

using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace MoonscraperChartEditor.Song.IO
{
Expand All @@ -11,9 +12,15 @@ public static class ChartIOHelper
public const string SECTION_SYNC_TRACK = "[SyncTrack]";
public const string SECTION_EVENTS = "[Events]";

// See MidIOHelper for regex details
public static readonly Regex TextEventRegex = MidIOHelper.TextEventRegex;
public static readonly Regex SectionEventRegex = MidIOHelper.SectionEventRegex;

public const string LYRIC_EVENT_PREFIX = "lyric ";
public const string EVENT_PHRASE_START = "phrase_start";
public const string EVENT_PHRASE_END = "phrase_end";
public const string EVENT_SOLO_START = "solo";
public const string EVENT_SOLO_END = "soloend";

public const int NOTE_OFFSET_PRO_DRUMS = 64;
public const int NOTE_OFFSET_INSTRUMENT_PLUS = 32;
Expand Down
Loading

0 comments on commit c6e8119

Please sign in to comment.