Import fixup of old code into new Unity project
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25140b91ea8636ea5acb3ff90421f11a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,332 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
using WacK.Data.Mer;
|
||||
|
||||
namespace WacK.Data.Chart
|
||||
{
|
||||
/// <summary>
|
||||
/// Chart data.
|
||||
/// </summary>
|
||||
public class Chart
|
||||
{
|
||||
public static bool doneLoading { get; private set; } = false;
|
||||
// [ms] = List<Note> (list for chord marking creation)
|
||||
public SortedList<float, List<NotePlay>> playNotes { get; private set; }
|
||||
public SortedList<float, NoteEvent<(int, int)>> timeSigChgs { get; private set; }
|
||||
public SortedList<float, NoteEvent<float>> tempoChgs { get; private set; }
|
||||
public SortedList<float, NoteEvent<int>> events { get; private set; }
|
||||
|
||||
public Chart()
|
||||
{
|
||||
doneLoading = false;
|
||||
}
|
||||
|
||||
// place notes and events relative to the previous
|
||||
public void Load(Mer.Mer chart)
|
||||
{
|
||||
playNotes = new SortedList<float, List<NotePlay>>();
|
||||
|
||||
List<float> tempo = new List<float>();
|
||||
List<int> tempoChangeMeasures = new List<int>();
|
||||
List<int> tempoChangeBeats = new List<int>();
|
||||
|
||||
// TODO: switch to MeasureBeat
|
||||
List<int> beatsPerMeasure = new List<int>();
|
||||
List<int> bpmChangeMeasures = new List<int>();
|
||||
|
||||
tempo.Add(0);
|
||||
tempoChangeMeasures.Add(0);
|
||||
tempoChangeBeats.Add(0);
|
||||
|
||||
beatsPerMeasure.Add(0);
|
||||
bpmChangeMeasures.Add(0);
|
||||
|
||||
float queuedTempo = -1;
|
||||
int queuedBPM = -1;
|
||||
|
||||
// timing info of the previous beat
|
||||
float prevTime = 0;
|
||||
int prevMeasure = 0;
|
||||
int prevBeat = 0; // (/1920 beats per measure)
|
||||
|
||||
Note prevNote = null;
|
||||
Note curNote = null;
|
||||
var prevHoldPoint = new System.Collections.Generic.Dictionary<int, NotePlay>(); // <note idx, previous point of hold>
|
||||
var curHoldNote = new System.Collections.Generic.Dictionary<int, NoteHold>(); // <next hold idx, HoldStart>
|
||||
|
||||
// Notes and Events //
|
||||
foreach (var measure in chart.notes) // `measure` = measure: List
|
||||
{
|
||||
foreach (var chartNote in measure.Value) // `chartNote` = beat, ChartNote
|
||||
{
|
||||
var curTime = prevTime + Util.NoteTime(measure.Key - prevMeasure, chartNote.Item1 - prevBeat, tempo.Last<float>(), beatsPerMeasure.Last<int>());
|
||||
var mb = new MeasureBeat(measure.Key, chartNote.Item1);
|
||||
|
||||
if (prevMeasure != measure.Key && prevBeat != chartNote.Item1)
|
||||
{
|
||||
if (queuedTempo != -1)
|
||||
{
|
||||
tempo.Add(queuedTempo);
|
||||
tempoChangeMeasures.Add(measure.Key);
|
||||
tempoChangeBeats.Add(chartNote.Item1);
|
||||
queuedTempo = -1;
|
||||
}
|
||||
|
||||
if (queuedBPM != -1)
|
||||
{
|
||||
beatsPerMeasure.Add(queuedBPM);
|
||||
bpmChangeMeasures.Add(measure.Key);
|
||||
queuedBPM = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// notetype-dependent operations
|
||||
switch (chartNote.Item2.noteType)
|
||||
{
|
||||
// Beat map data
|
||||
case MerType.Tempo:
|
||||
if (tempo.Count == 1)
|
||||
{
|
||||
tempo.Add(float.Parse(chartNote.Item2.value));
|
||||
tempoChangeMeasures.Add(measure.Key);
|
||||
tempoChangeBeats.Add(chartNote.Item1);
|
||||
}
|
||||
else
|
||||
queuedTempo = float.Parse(chartNote.Item2.value);
|
||||
this.tempoChgs.Add(
|
||||
curTime,
|
||||
new NoteEvent<float> (
|
||||
curTime, mb,
|
||||
NoteEventType.Tempo,
|
||||
value: float.Parse(chartNote.Item2.value)
|
||||
));
|
||||
break;
|
||||
case MerType.TimeSignature:
|
||||
var words = chartNote.Item2.value.Split();
|
||||
var nu = int.Parse(words[0]);
|
||||
var de = int.Parse(words[1]);
|
||||
if (beatsPerMeasure.Count == 1)
|
||||
{
|
||||
beatsPerMeasure.Add(int.Parse(chartNote.Item2.value));
|
||||
bpmChangeMeasures.Add(measure.Key);
|
||||
}
|
||||
else
|
||||
queuedBPM = int.Parse(chartNote.Item2.value);
|
||||
this.timeSigChgs.Add(
|
||||
curTime,
|
||||
new NoteEvent<(int, int)> (
|
||||
curTime, mb,
|
||||
NoteEventType.TimeSignature,
|
||||
value: (nu, de)
|
||||
));
|
||||
break;
|
||||
// Playable notes
|
||||
case MerType.Touch:
|
||||
curNote = new NotePlay(
|
||||
curTime, mb,
|
||||
chartNote.Item2.position, chartNote.Item2.size
|
||||
);
|
||||
break;
|
||||
case MerType.HoldStart:
|
||||
curNote = new NoteHold(
|
||||
curTime, mb,
|
||||
chartNote.Item2.position, chartNote.Item2.size,
|
||||
holdIndex: chartNote.Item2.holdIdx,
|
||||
holdNext: chartNote.Item2.holdNextIdx
|
||||
);
|
||||
var nh = curNote as NoteHold;
|
||||
prevHoldPoint[chartNote.Item2.holdNextIdx] = (NotePlay) curNote;
|
||||
curHoldNote[chartNote.Item2.holdNextIdx] = nh;
|
||||
break;
|
||||
case MerType.HoldMid:
|
||||
curNote = new NotePlay(
|
||||
curTime, mb,
|
||||
chartNote.Item2.position, chartNote.Item2.size,
|
||||
type: NotePlayType.HoldMid,
|
||||
holdIndex: chartNote.Item2.holdIdx,
|
||||
holdNext: chartNote.Item2.holdNextIdx
|
||||
);
|
||||
prevHoldPoint[chartNote.Item2.holdNextIdx] = (NotePlay) curNote;
|
||||
curHoldNote[chartNote.Item2.holdNextIdx] = curHoldNote[chartNote.Item2.holdIdx];
|
||||
break;
|
||||
case MerType.HoldEnd: // TODO: draw end note on cone texture
|
||||
curNote = new NotePlay(
|
||||
curTime, mb,
|
||||
chartNote.Item2.position, chartNote.Item2.size,
|
||||
type: NotePlayType.HoldEnd,
|
||||
holdIndex: chartNote.Item2.holdIdx
|
||||
);
|
||||
break;
|
||||
case MerType.Untimed:
|
||||
curNote = new NotePlay(
|
||||
curTime, mb,
|
||||
chartNote.Item2.position, chartNote.Item2.size,
|
||||
type: NotePlayType.Untimed
|
||||
);
|
||||
break;
|
||||
case MerType.SwipeIn:
|
||||
curNote = new NotePlay(
|
||||
curTime, mb,
|
||||
chartNote.Item2.position, chartNote.Item2.size,
|
||||
type: NotePlayType.SwipeIn
|
||||
);
|
||||
break;
|
||||
case MerType.SwipeOut:
|
||||
curNote = new NotePlay(
|
||||
curTime, mb,
|
||||
chartNote.Item2.position, chartNote.Item2.size,
|
||||
type: NotePlayType.SwipeOut
|
||||
);
|
||||
break;
|
||||
case MerType.SwipeCW:
|
||||
curNote = new NotePlay(
|
||||
curTime, mb,
|
||||
chartNote.Item2.position, chartNote.Item2.size,
|
||||
type: NotePlayType.SwipeCW
|
||||
);
|
||||
break;
|
||||
case MerType.SwipeCCW:
|
||||
curNote = new NotePlay(
|
||||
curTime, mb,
|
||||
chartNote.Item2.position, chartNote.Item2.size,
|
||||
type: NotePlayType.SwipeCCW
|
||||
);
|
||||
break;
|
||||
// Events (invisible modifier notes)
|
||||
case MerType.BGAdd:
|
||||
curNote = new NoteEvent<int>(
|
||||
curTime, mb,
|
||||
NoteEventType.BGAdd,
|
||||
chartNote.Item2.position, chartNote.Item2.size,
|
||||
value: int.Parse(chartNote.Item2.value)
|
||||
);
|
||||
break;
|
||||
case MerType.BGRem:
|
||||
curNote = new NoteEvent<int>(
|
||||
curTime, mb,
|
||||
NoteEventType.BGRem,
|
||||
chartNote.Item2.position, chartNote.Item2.size,
|
||||
value: int.Parse(chartNote.Item2.value)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
if (curNote == null || curNote == prevNote) continue;
|
||||
|
||||
/* Handle our crafted curNote, storing it somewhere in this Chart */
|
||||
// NotePlay
|
||||
var np = curNote as NotePlay;
|
||||
if (np != null)
|
||||
{
|
||||
// hold point handling
|
||||
if (np.type == NotePlayType.HoldMid || np.type == NotePlayType.HoldEnd)
|
||||
{
|
||||
curHoldNote[np.holdIdx].points[curTime] = np;
|
||||
}
|
||||
|
||||
// add note
|
||||
if (!playNotes.ContainsKey(curTime))
|
||||
{
|
||||
playNotes[curTime] = new List<NotePlay>();
|
||||
}
|
||||
playNotes[curTime].Add(np);
|
||||
}
|
||||
|
||||
// NoteEvent<float> -- tempo changes
|
||||
var nef = curNote as NoteEvent<float>;
|
||||
if (nef != null)
|
||||
{
|
||||
if (nef.type == NoteEventType.Tempo)
|
||||
this.tempoChgs[curTime] = nef;
|
||||
else
|
||||
Debug.LogWarning($"Didn't add NoteEvent<float> of type {nef.type}");
|
||||
}
|
||||
|
||||
// NoteEvent<(int, int)> -- time signature changes
|
||||
var neii = curNote as NoteEvent<(int, int)>;
|
||||
if (neii != null)
|
||||
{
|
||||
this.timeSigChgs[curTime] = neii;
|
||||
}
|
||||
|
||||
// NoteEvent<int>
|
||||
var nei = curNote as NoteEvent<int>;
|
||||
if (nei != null)
|
||||
{
|
||||
this.events[curTime] = nei;
|
||||
}
|
||||
|
||||
// update previous states
|
||||
prevNote = curNote;
|
||||
prevTime = curTime;
|
||||
prevBeat = chartNote.Item1;
|
||||
prevMeasure = measure.Key;
|
||||
}
|
||||
}
|
||||
|
||||
// chords
|
||||
foreach (KeyValuePair<float, List<NotePlay>> pair in playNotes)
|
||||
{
|
||||
List<Note> chordableNotes = new List<Note>();
|
||||
foreach (NotePlay n in pair.Value)
|
||||
{
|
||||
if (n.type != NotePlayType.HoldEnd && n.type != NotePlayType.Untimed)
|
||||
if (!(new NotePlayType[] { NotePlayType.HoldEnd, NotePlayType.Untimed, NotePlayType.HoldMid }).Contains(n.type))
|
||||
chordableNotes.Add(n);
|
||||
}
|
||||
if (chordableNotes.Count >= 2)
|
||||
{
|
||||
Debug.Log($"Found chord: {string.Join(", ", chordableNotes)}");
|
||||
// TODO: draw chord indicators "Chordify"
|
||||
}
|
||||
}
|
||||
|
||||
// Measure Lines //
|
||||
// TODO: adapt to tempo changes in the middle of a measure
|
||||
// int tempoIdx = 1;
|
||||
// int bpmIdx = 1;
|
||||
// for (int curMeasure = 0; curMeasure < chart.notes.Count; curMeasure++)
|
||||
// {
|
||||
// while (curMeasure >= bpmChangeMeasures[bpmIdx] && bpmIdx < bpmChangeMeasures.Count - 1)
|
||||
// ++bpmIdx;
|
||||
// GD.Print($"{curMeasure}: {bpmIdx}");
|
||||
|
||||
// // last tempo change / only one tempo change exists
|
||||
// if (tempoIdx == tempoChangeMeasures.Count - 1)
|
||||
// {
|
||||
// float pos = tempoChangePositions[tempoIdx] + Util.NotePosition(curMeasure - tempoChangeMeasures[tempoIdx], 0, tempo.Last(), beatsPerMeasure[bpmIdx]);
|
||||
// var ml = measureLine.Instance<MeasureLine>();
|
||||
// measureScroll.AddChild(ml);
|
||||
// ml.Translation = new Vector3(0, 0, pos);
|
||||
// ml.Text = $"{curMeasure}";
|
||||
// }
|
||||
// else if (tempoIdx < tempoChangeMeasures.Count)
|
||||
// {
|
||||
// // TODO: adapt to key signature changes
|
||||
// while (curMeasure == tempoChangeMeasures[tempoIdx])
|
||||
// {
|
||||
// int measuresToCreate = tempoChangeMeasures[tempoIdx] - tempoChangeMeasures[tempoIdx - 1];
|
||||
// for (int i = 0; i < measuresToCreate; ++i)
|
||||
// {
|
||||
// int measureNum = tempoChangeMeasures[tempoIdx - 1] + i;
|
||||
// // GD.Print($"{tempoIdx} / {tempoChangePositions.Count}, {tempo.Count}");
|
||||
// float pos = Util.InterpFloat(tempoChangePositions[tempoIdx - 1], tempoChangePositions[tempoIdx], (float)i/measuresToCreate);
|
||||
|
||||
// var ml = measureLine.Instance<MeasureLine>();
|
||||
// measureScroll.AddChild(ml);
|
||||
// ml.Translation = new Vector3(0, 0, pos);
|
||||
// ml.Text = $"{curMeasure}";
|
||||
// }
|
||||
// tempoIdx = Mathf.Clamp(tempoIdx + 1, 0, tempo.Count - 1);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
doneLoading = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 562cc671f5a30839c8769855d8d0483f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace WacK.Data.Chart
|
||||
{
|
||||
public enum DifficultyLevel
|
||||
{
|
||||
Normal, Hard, Expert, Inferno
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02342af085b6384489297bdfaaff13f1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
|
||||
namespace WacK.Data.Chart
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a non-timed chart position in measure and beat as a fraction of the measure.
|
||||
/// </summary>
|
||||
public class MeasureBeat
|
||||
{
|
||||
public const int DENOMINATOR = 1920;
|
||||
|
||||
public int measure { get; private set; }
|
||||
/// <summary>
|
||||
/// Beat in the measure, represented as beat/1920 of a measure.
|
||||
/// </summary>
|
||||
public int beat { get; private set; }
|
||||
|
||||
public MeasureBeat(int measure, int beat)
|
||||
{
|
||||
this.measure = measure;
|
||||
this.beat = beat;
|
||||
Normalize();
|
||||
}
|
||||
|
||||
public void Normalize()
|
||||
{
|
||||
// beats larger than denominator
|
||||
if (Math.Abs(beat) >= DENOMINATOR)
|
||||
{
|
||||
measure += beat / DENOMINATOR;
|
||||
beat %= DENOMINATOR;
|
||||
}
|
||||
// positive measure, negative beats
|
||||
if (beat < 0 && measure > 0)
|
||||
{
|
||||
measure--;
|
||||
beat += DENOMINATOR;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"MeasureBeat({this.measure}, {this.beat}/{DENOMINATOR})";
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return measure*DENOMINATOR + beat;
|
||||
}
|
||||
|
||||
public override bool Equals(object tgt)
|
||||
{
|
||||
if (tgt == null) return false;
|
||||
|
||||
return this == (MeasureBeat)tgt;
|
||||
}
|
||||
|
||||
/* STATIC CONSTANTS */
|
||||
public readonly static MeasureBeat ZERO = new MeasureBeat(0, 0);
|
||||
|
||||
/* STATIC OPERATORS */
|
||||
public static MeasureBeat operator +(MeasureBeat a) => a;
|
||||
public static MeasureBeat operator -(MeasureBeat a)
|
||||
=> new MeasureBeat(-a.measure, -a.beat);
|
||||
|
||||
public static MeasureBeat operator +(MeasureBeat a, MeasureBeat b)
|
||||
{
|
||||
var meas = a.measure + b.measure;
|
||||
var beat = a.beat + b.beat;
|
||||
return new MeasureBeat(meas, beat);
|
||||
}
|
||||
|
||||
public static MeasureBeat operator -(MeasureBeat a, MeasureBeat b)
|
||||
{
|
||||
return a + -b;
|
||||
}
|
||||
|
||||
public static bool operator ==(MeasureBeat a, MeasureBeat b)
|
||||
{
|
||||
return a.measure == b.measure && a.beat == b.beat;
|
||||
}
|
||||
|
||||
public static bool operator !=(MeasureBeat a, MeasureBeat b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
public static bool operator <(MeasureBeat a, MeasureBeat b)
|
||||
{
|
||||
if (a.measure < b.measure) return true;
|
||||
|
||||
if (a.measure == b.measure)
|
||||
{
|
||||
return a.beat < b.beat;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool operator >(MeasureBeat a, MeasureBeat b)
|
||||
{
|
||||
if (a != b)
|
||||
{
|
||||
return !(a < b);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool operator <=(MeasureBeat a, MeasureBeat b)
|
||||
{
|
||||
if (a == b) return true;
|
||||
return a < b;
|
||||
}
|
||||
|
||||
public static bool operator >=(MeasureBeat a, MeasureBeat b)
|
||||
{
|
||||
if (a == b) return true;
|
||||
return a > b;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f19917e007c0523e9a5ccccea23e9524
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WacK.Data.Chart
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for various in-play note types.
|
||||
/// </summary>
|
||||
public abstract class Note
|
||||
{
|
||||
/// <summary>
|
||||
/// Time in milliseconds which the note occurs.
|
||||
/// </summary>
|
||||
public double time = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Time of the note in MeasureBeat.
|
||||
/// </summary>
|
||||
public MeasureBeat measureBeat;
|
||||
|
||||
/// <summary>
|
||||
/// The note's radial position out of 60.
|
||||
/// </summary>
|
||||
public int? position;
|
||||
|
||||
/// <summary>
|
||||
/// The radial size of the note.
|
||||
/// 1 <= size <= 60
|
||||
/// </summary>
|
||||
public int? size;
|
||||
|
||||
public Note(double time, MeasureBeat measureBeat, int? position = null, int? size = null)
|
||||
{
|
||||
this.time = time;
|
||||
this.measureBeat = measureBeat;
|
||||
this.position = position;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public Note()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ed8bb3e1326d18f9927b087b6e8fe7c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WacK.Data.Chart
|
||||
{
|
||||
public enum NoteEventType
|
||||
{
|
||||
Tempo,
|
||||
TimeSignature,
|
||||
ScrollSpeedMultiplier,
|
||||
BGAdd,
|
||||
BGRem,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an unplayable event with some associated data value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The value's type.</typeparam>
|
||||
public class NoteEvent<T> : Note
|
||||
{
|
||||
public NoteEventType type;
|
||||
|
||||
/// <summary>
|
||||
/// A value whose function will vary depending on the type of note.
|
||||
/// </summary>
|
||||
public T value;
|
||||
|
||||
public NoteEvent(double time, MeasureBeat measureBeat, NoteEventType type, int? position = null, int? size = null, T value = default(T)) :
|
||||
base(time, measureBeat, position, size)
|
||||
{
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f133260cfe1efeb06bc84818f1f694c0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace WacK.Data.Chart
|
||||
{
|
||||
/// <summary>
|
||||
/// A hold note. Notably contains data about hold points.
|
||||
/// </summary>
|
||||
public class NoteHold : NotePlay
|
||||
{
|
||||
public SortedList<float, NotePlay> points;
|
||||
|
||||
public NoteHold(double time, MeasureBeat measureBeat, int position, int size, int holdIndex, int holdNext, bool bonus = false)
|
||||
: base(time, measureBeat, position, size,holdIndex, holdNext, type: NotePlayType.HoldStart, bonus: false)
|
||||
{
|
||||
// points = (SortedList<float, Note>)holdPoints.Skip(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 74c839480bb719c9b96e11709817d2e6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WacK.Data.Chart
|
||||
{
|
||||
public enum NotePlayType
|
||||
{
|
||||
Touch,
|
||||
HoldStart,
|
||||
HoldMid,
|
||||
HoldEnd,
|
||||
Untimed,
|
||||
SwipeIn,
|
||||
SwipeOut,
|
||||
SwipeCW,
|
||||
SwipeCCW,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents playable notes.
|
||||
/// </summary>
|
||||
public class NotePlay : Note
|
||||
{
|
||||
public NotePlayType type { get; private set; }
|
||||
public bool isBonus { get; private set; }
|
||||
public int holdIdx { get; private set; }
|
||||
public int holdNextIdx { get; private set; }
|
||||
|
||||
public NotePlay(double time, MeasureBeat measureBeat, int position, int size, int holdIndex = -1, int holdNext = -1,
|
||||
NotePlayType type = NotePlayType.Touch, bool bonus = false)
|
||||
: base(time, measureBeat, position, size)
|
||||
{
|
||||
this.type = type;
|
||||
this.isBonus = bonus;
|
||||
this.holdIdx = holdIndex;
|
||||
this.holdNextIdx = holdNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ccfc6a251580ee67a83e2269870a227c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ed6e3a31145daf8597c9bd80394d64d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* Chart.cs
|
||||
* Representation of a chart, constructed from a .mer file.
|
||||
*
|
||||
* by muskit
|
||||
* July 1, 2022
|
||||
**/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WacK.Data.Mer
|
||||
{
|
||||
/// <summary>
|
||||
/// Structurized representation of a .mer file.
|
||||
/// </summary>
|
||||
public class Mer
|
||||
{
|
||||
/// <summary>
|
||||
/// HIERARCHY:
|
||||
/// Key is measure.
|
||||
/// Value is List of (beat/1920, Notes) tuples.
|
||||
/// </summary>
|
||||
public SortedList<int, List<(int, MerNote)>> notes = new SortedList<int, List<(int, MerNote)>>();
|
||||
|
||||
public int playableNoteCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct Chart from contents of .mer file.
|
||||
/// </summary>
|
||||
/// <param name="str">Contents of a .mer file.</param>
|
||||
public Mer(string str)
|
||||
{
|
||||
if (str == String.Empty) return;
|
||||
|
||||
playableNoteCount = 0;
|
||||
|
||||
List<string> lines = new List<string>(str.Split('\n'));
|
||||
foreach (var line in lines)
|
||||
{
|
||||
List<string> tokens = new List<string>(line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries));
|
||||
if (tokens.Count == 0) continue;
|
||||
if (tokens[0][0] == '#') continue;
|
||||
|
||||
int currentMeasure = int.Parse(tokens[0]);
|
||||
int currentBeat = int.Parse(tokens[1]);
|
||||
|
||||
if (!notes.ContainsKey(currentMeasure))
|
||||
{
|
||||
notes[currentMeasure] = new List<(int, MerNote)>();
|
||||
}
|
||||
|
||||
switch (tokens[2])
|
||||
{
|
||||
case "1": // common note types
|
||||
switch(tokens[3])
|
||||
{
|
||||
case "1": // touch
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.Touch)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "2": // touch w/ bonus
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.Touch, bonus: true)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "20": // touch w/ bonus (+ "big effect")
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.Touch, bonus: true)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "16": // untimed
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.Untimed)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "26": // untimed w/ bonus
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.Untimed, bonus: true)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "3": // swipe in (red)
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeIn)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "21": // swipe in w/ bonus
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeIn, bonus: true)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "4": // swipe out (blue)
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeOut)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "22": // swipe out w/ bonus
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeOut, bonus: true)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "7": // swipe CCW
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeCCW)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "8": // swipe CCW w/ bonus
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeCCW, bonus: true)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "5": // swipe CW
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeCW)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "6": // swipe CW w/ bonus
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), type: MerType.SwipeCW, bonus: true)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "9": // hold start
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), holdIndex: int.Parse(tokens[4]), holdNext: int.Parse(tokens[8]), type: MerType.HoldStart)));
|
||||
break;
|
||||
case "25": // hold start (w/ bonus)
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), holdIndex: int.Parse(tokens[4]), holdNext: int.Parse(tokens[8]), type: MerType.HoldStart, bonus: true)));
|
||||
++playableNoteCount;
|
||||
break;
|
||||
case "10": // hold middle
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), holdIndex: int.Parse(tokens[4]), holdNext: int.Parse(tokens[8]), type: MerType.HoldMid)));
|
||||
break;
|
||||
case "11": // hold end
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), holdIndex: int.Parse(tokens[4]), type: MerType.HoldEnd)));
|
||||
break;
|
||||
case "12": // BG add
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), value: tokens[8], type: MerType.BGAdd)));
|
||||
break;
|
||||
case "13": // BG rem
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(int.Parse(tokens[5]), int.Parse(tokens[6]), value: tokens[8], type: MerType.BGRem)));
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
case "2": // tempo
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(value: tokens[3], type: MerType.Tempo)));
|
||||
break;
|
||||
case "3": // beats per measure
|
||||
notes[currentMeasure].Add((currentBeat, new MerNote(value: $"{tokens[3]} {tokens[4]}", type: MerType.TimeSignature)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach (var measure in notes)
|
||||
{
|
||||
measure.Value.Sort((x, y) => x.Item1.CompareTo(y.Item1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03f65fd134dbd18faba49dbb870b3450
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Note.cs
|
||||
* A struct representing a note.
|
||||
*
|
||||
* by muskit
|
||||
* July 1, 2022
|
||||
**/
|
||||
|
||||
namespace WacK.Data.Mer
|
||||
{
|
||||
public enum MerType
|
||||
{
|
||||
Touch, HoldStart, HoldMid, HoldEnd, Untimed, SwipeIn, SwipeOut, SwipeCW, SwipeCCW, Tempo, TimeSignature, BGAdd, BGRem
|
||||
}
|
||||
public struct MerNote
|
||||
{
|
||||
public MerType noteType { get; private set; }
|
||||
public bool isBonus { get; private set; }
|
||||
|
||||
// Radial values in minutes
|
||||
public int position { get; private set; }
|
||||
public int size { get; private set; } // 1 <= size <= 60
|
||||
public string value { get; private set; }
|
||||
public int holdIdx { get; private set; }
|
||||
public int holdNextIdx { get; private set; }
|
||||
|
||||
public MerNote(int position = 0, int size = 1, string value = "", int holdIndex = -1, int holdNext = -1, MerType type = MerType.Touch, bool bonus = false)
|
||||
{
|
||||
this.position = position;
|
||||
this.size = size;
|
||||
this.value = value;
|
||||
this.holdIdx = holdIndex;
|
||||
this.holdNextIdx = holdNext;
|
||||
this.noteType = type;
|
||||
this.isBonus = bonus;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f03d973b6879b96a5b79467d1dd3cbfc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user