diff --git a/.vscode/settings.json b/.vscode/settings.json
index 92d49c3d4..cefbadcf6 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -4,8 +4,7 @@
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.codeActionsOnSave": {
- // Compilation server issues can cause auto-cleanup to remove valid imports.
- "source.organizeImports": false
+ "source.organizeImports": "never"
},
"editor.defaultFormatter": "nadako.vshaxe",
"editor.tabSize": 2
diff --git a/Project.xml b/Project.xml
index 4c0ffdce7..e0677b026 100644
--- a/Project.xml
+++ b/Project.xml
@@ -99,18 +99,20 @@
-
+
+
-
+
+
+
+
-
-
diff --git a/art b/art
index 1656bea53..03e7c2a23 160000
--- a/art
+++ b/art
@@ -1 +1 @@
-Subproject commit 1656bea5370c65879aaeb323e329f403c78071c5
+Subproject commit 03e7c2a2353b184e45955c96d763b7cdf1acbc34
diff --git a/assets b/assets
index dfaf23dfa..b551cb290 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit dfaf23dfa11ff67be2eea9113a80ff5dc0040f76
+Subproject commit b551cb29078e3599a5d608a22238450f9380a3fc
diff --git a/hmm.json b/hmm.json
index a10eed1a6..d461edd24 100644
--- a/hmm.json
+++ b/hmm.json
@@ -11,15 +11,20 @@
"name": "flixel",
"type": "git",
"dir": null,
- "ref": "da04cbda49a4c5eebe93fb61296dbaf4f0f1b556",
- "url": "https://github.com/EliteMasterEric/flixel"
+ "ref": "a83738673e7edbf8acba3a1426af284dfe6719fe",
+ "url": "https://github.com/FunkinCrew/flixel"
},
{
"name": "flixel-addons",
"type": "git",
"dir": null,
- "ref": "c8c41e26d463aaf2edc0582fb23b6e228235bd16",
- "url": "https://github.com/EliteMasterEric/flixel-addons"
+ "ref": "fd3aecdeb5635fa0428dffee204fc78fc26b5885",
+ "url": "https://github.com/FunkinCrew/flixel-addons"
+ },
+ {
+ "name": "flixel-text-input",
+ "type": "haxelib",
+ "version": "1.1.0"
},
{
"name": "flixel-ui",
@@ -32,8 +37,8 @@
"name": "flxanimate",
"type": "git",
"dir": null,
- "ref": "dd2903f7dc7024335b981edf2a770760cec912e1",
- "url": "https://github.com/ninjamuffin99/flxanimate"
+ "ref": "d7c5621be742e2c98d523dfe5af7528835eaff1e",
+ "url": "https://github.com/FunkinCrew/flxanimate"
},
{
"name": "format",
@@ -49,14 +54,14 @@
"name": "haxeui-core",
"type": "git",
"dir": null,
- "ref": "032192e849cdb7d1070c0a3241c58ee555ffaccc",
+ "ref": "5086e59e7551d775ed4d1fb0188e31de22d1312b",
"url": "https://github.com/haxeui/haxeui-core"
},
{
"name": "haxeui-flixel",
"type": "git",
"dir": null,
- "ref": "d90758b229d05206400df867d333c79d9fdbd478",
+ "ref": "2b9cff727999b53ed292b1675ac1c9089ac77600",
"url": "https://github.com/haxeui/haxeui-flixel"
},
{
@@ -95,15 +100,15 @@
"name": "json2object",
"type": "git",
"dir": null,
- "ref": "f4df19cfa196f85eece55c3367021fc965f1fa9a",
- "url": "https://github.com/EliteMasterEric/json2object"
+ "ref": "a8c26f18463c98da32f744c214fe02273e1823fa",
+ "url": "https://github.com/FunkinCrew/json2object"
},
{
"name": "lime",
"type": "git",
"dir": null,
"ref": "737b86f121cdc90358d59e2e527934f267c94a2c",
- "url": "https://github.com/EliteMasterEric/lime"
+ "url": "https://github.com/FunkinCrew/lime"
},
{
"name": "mconsole",
@@ -124,21 +129,21 @@
"type": "git",
"dir": "src",
"ref": "master",
- "url": "https://github.com/EliteMasterEric/mockatoo"
+ "url": "https://github.com/FunkinCrew/mockatoo"
},
{
"name": "munit",
"type": "git",
"dir": "src",
"ref": "master",
- "url": "https://github.com/EliteMasterEric/MassiveUnit"
+ "url": "https://github.com/FunkinCrew/MassiveUnit"
},
{
"name": "openfl",
"type": "git",
"dir": null,
"ref": "f229d76361c7e31025a048fe7909847f75bb5d5e",
- "url": "https://github.com/EliteMasterEric/openfl"
+ "url": "https://github.com/FunkinCrew/openfl"
},
{
"name": "polymod",
diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx
index c531678ad..05c23108f 100644
--- a/source/funkin/Conductor.hx
+++ b/source/funkin/Conductor.hx
@@ -11,6 +11,7 @@ import funkin.data.song.SongDataUtils;
* A core class which handles musical timing throughout the game,
* both in gameplay and in menus.
*/
+@:nullSafety
class Conductor
{
// onBeatHit is called every quarter note
@@ -28,29 +29,53 @@ class Conductor
// 60 BPM = 240 sixteenth notes per minute = 4 onStepHit per second
// 7/8 = 3.5 beats per measure = 14 steps per measure
+ /**
+ * The current instance of the Conductor.
+ * If one doesn't currently exist, a new one will be created.
+ *
+ * You can also do stuff like store a reference to the Conductor and pass it around or temporarily replace it,
+ * or have a second Conductor running at the same time, or other weird stuff like that if you need to.
+ */
+ public static var instance:Conductor = new Conductor();
+
+ /**
+ * Signal fired when the current Conductor instance advances to a new measure.
+ */
+ public static var measureHit(default, null):FlxSignal = new FlxSignal();
+
+ /**
+ * Signal fired when the current Conductor instance advances to a new beat.
+ */
+ public static var beatHit(default, null):FlxSignal = new FlxSignal();
+
+ /**
+ * Signal fired when the current Conductor instance advances to a new step.
+ */
+ public static var stepHit(default, null):FlxSignal = new FlxSignal();
+
/**
* The list of time changes in the song.
* There should be at least one time change (at the beginning of the song) to define the BPM.
*/
- static var timeChanges:Array = [];
+ var timeChanges:Array = [];
/**
* The most recent time change for the current song position.
*/
- public static var currentTimeChange(default, null):SongTimeChange;
+ public var currentTimeChange(default, null):Null;
/**
* The current position in the song in milliseconds.
- * Update this every frame based on the audio position using `Conductor.update()`.
+ * Update this every frame based on the audio position using `Conductor.instance.update()`.
*/
- public static var songPosition(default, null):Float = 0;
+ public var songPosition(default, null):Float = 0;
/**
* Beats per minute of the current song at the current time.
*/
- public static var bpm(get, never):Float;
+ public var bpm(get, never):Float;
- static function get_bpm():Float
+ function get_bpm():Float
{
if (bpmOverride != null) return bpmOverride;
@@ -62,9 +87,9 @@ class Conductor
/**
* Beats per minute of the current song at the start time.
*/
- public static var startingBPM(get, never):Float;
+ public var startingBPM(get, never):Float;
- static function get_startingBPM():Float
+ function get_startingBPM():Float
{
if (bpmOverride != null) return bpmOverride;
@@ -78,14 +103,14 @@ class Conductor
* The current value set by `forceBPM`.
* If false, BPM is determined by time changes.
*/
- static var bpmOverride:Null = null;
+ var bpmOverride:Null = null;
/**
* Duration of a measure in milliseconds. Calculated based on bpm.
*/
- public static var measureLengthMs(get, never):Float;
+ public var measureLengthMs(get, never):Float;
- static function get_measureLengthMs():Float
+ function get_measureLengthMs():Float
{
return beatLengthMs * timeSignatureNumerator;
}
@@ -93,9 +118,9 @@ class Conductor
/**
* Duration of a beat (quarter note) in milliseconds. Calculated based on bpm.
*/
- public static var beatLengthMs(get, never):Float;
+ public var beatLengthMs(get, never):Float;
- static function get_beatLengthMs():Float
+ function get_beatLengthMs():Float
{
// Tied directly to BPM.
return ((Constants.SECS_PER_MIN / bpm) * Constants.MS_PER_SEC);
@@ -104,25 +129,25 @@ class Conductor
/**
* Duration of a step (sixtennth note) in milliseconds. Calculated based on bpm.
*/
- public static var stepLengthMs(get, never):Float;
+ public var stepLengthMs(get, never):Float;
- static function get_stepLengthMs():Float
+ function get_stepLengthMs():Float
{
return beatLengthMs / timeSignatureNumerator;
}
- public static var timeSignatureNumerator(get, never):Int;
+ public var timeSignatureNumerator(get, never):Int;
- static function get_timeSignatureNumerator():Int
+ function get_timeSignatureNumerator():Int
{
if (currentTimeChange == null) return Constants.DEFAULT_TIME_SIGNATURE_NUM;
return currentTimeChange.timeSignatureNum;
}
- public static var timeSignatureDenominator(get, never):Int;
+ public var timeSignatureDenominator(get, never):Int;
- static function get_timeSignatureDenominator():Int
+ function get_timeSignatureDenominator():Int
{
if (currentTimeChange == null) return Constants.DEFAULT_TIME_SIGNATURE_DEN;
@@ -132,44 +157,44 @@ class Conductor
/**
* Current position in the song, in measures.
*/
- public static var currentMeasure(default, null):Int;
+ public var currentMeasure(default, null):Int = 0;
/**
* Current position in the song, in beats.
*/
- public static var currentBeat(default, null):Int;
+ public var currentBeat(default, null):Int = 0;
/**
* Current position in the song, in steps.
*/
- public static var currentStep(default, null):Int;
+ public var currentStep(default, null):Int = 0;
/**
* Current position in the song, in measures and fractions of a measure.
*/
- public static var currentMeasureTime(default, null):Float;
+ public var currentMeasureTime(default, null):Float = 0;
/**
* Current position in the song, in beats and fractions of a measure.
*/
- public static var currentBeatTime(default, null):Float;
+ public var currentBeatTime(default, null):Float = 0;
/**
* Current position in the song, in steps and fractions of a step.
*/
- public static var currentStepTime(default, null):Float;
+ public var currentStepTime(default, null):Float = 0;
/**
* An offset tied to the current chart file to compensate for a delay in the instrumental.
*/
- public static var instrumentalOffset:Float = 0;
+ public var instrumentalOffset:Float = 0;
/**
* The instrumental offset, in terms of steps.
*/
- public static var instrumentalOffsetSteps(get, never):Float;
+ public var instrumentalOffsetSteps(get, never):Float;
- static function get_instrumentalOffsetSteps():Float
+ function get_instrumentalOffsetSteps():Float
{
var startingStepLengthMs:Float = ((Constants.SECS_PER_MIN / startingBPM) * Constants.MS_PER_SEC) / timeSignatureNumerator;
@@ -179,19 +204,19 @@ class Conductor
/**
* An offset tied to the file format of the audio file being played.
*/
- public static var formatOffset:Float = 0;
+ public var formatOffset:Float = 0;
/**
* An offset set by the user to compensate for input lag.
*/
- public static var inputOffset:Float = 0;
+ public var inputOffset:Float = 0;
/**
* The number of beats in a measure. May be fractional depending on the time signature.
*/
- public static var beatsPerMeasure(get, never):Float;
+ public var beatsPerMeasure(get, never):Float;
- static function get_beatsPerMeasure():Float
+ function get_beatsPerMeasure():Float
{
// NOTE: Not always an integer, for example 7/8 is 3.5 beats per measure
return stepsPerMeasure / Constants.STEPS_PER_BEAT;
@@ -201,30 +226,15 @@ class Conductor
* The number of steps in a measure.
* TODO: I don't think this can be fractional?
*/
- public static var stepsPerMeasure(get, never):Int;
+ public var stepsPerMeasure(get, never):Int;
- static function get_stepsPerMeasure():Int
+ function get_stepsPerMeasure():Int
{
// TODO: Is this always an integer?
return Std.int(timeSignatureNumerator / timeSignatureDenominator * Constants.STEPS_PER_BEAT * Constants.STEPS_PER_BEAT);
}
- /**
- * Signal fired when the Conductor advances to a new measure.
- */
- public static var measureHit(default, null):FlxSignal = new FlxSignal();
-
- /**
- * Signal fired when the Conductor advances to a new beat.
- */
- public static var beatHit(default, null):FlxSignal = new FlxSignal();
-
- /**
- * Signal fired when the Conductor advances to a new step.
- */
- public static var stepHit(default, null):FlxSignal = new FlxSignal();
-
- function new() {}
+ public function new() {}
/**
* Forcibly defines the current BPM of the song.
@@ -235,7 +245,7 @@ class Conductor
* WARNING: Avoid this for things like setting the BPM of the title screen music,
* you should have a metadata file for it instead.
*/
- public static function forceBPM(?bpm:Float = null)
+ public function forceBPM(?bpm:Float = null)
{
if (bpm != null)
{
@@ -246,7 +256,7 @@ class Conductor
// trace('[CONDUCTOR] Resetting BPM to default');
}
- Conductor.bpmOverride = bpm;
+ this.bpmOverride = bpm;
}
/**
@@ -256,29 +266,29 @@ class Conductor
* @param songPosition The current position in the song in milliseconds.
* Leave blank to use the FlxG.sound.music position.
*/
- public static function update(?songPosition:Float)
+ public function update(?songPos:Float)
{
- if (songPosition == null)
+ if (songPos == null)
{
// Take into account instrumental and file format song offsets.
- songPosition = (FlxG.sound.music != null) ? (FlxG.sound.music.time + instrumentalOffset + formatOffset) : 0.0;
+ songPos = (FlxG.sound.music != null) ? (FlxG.sound.music.time + instrumentalOffset + formatOffset) : 0.0;
}
- var oldMeasure = currentMeasure;
- var oldBeat = currentBeat;
- var oldStep = currentStep;
+ var oldMeasure = this.currentMeasure;
+ var oldBeat = this.currentBeat;
+ var oldStep = this.currentStep;
// Set the song position we are at (for purposes of calculating note positions, etc).
- Conductor.songPosition = songPosition;
+ this.songPosition = songPos;
currentTimeChange = timeChanges[0];
- if (Conductor.songPosition > 0.0)
+ if (this.songPosition > 0.0)
{
for (i in 0...timeChanges.length)
{
- if (songPosition >= timeChanges[i].timeStamp) currentTimeChange = timeChanges[i];
+ if (this.songPosition >= timeChanges[i].timeStamp) currentTimeChange = timeChanges[i];
- if (songPosition < timeChanges[i].timeStamp) break;
+ if (this.songPosition < timeChanges[i].timeStamp) break;
}
}
@@ -286,45 +296,49 @@ class Conductor
{
trace('WARNING: Conductor is broken, timeChanges is empty.');
}
- else if (currentTimeChange != null && Conductor.songPosition > 0.0)
+ else if (currentTimeChange != null && this.songPosition > 0.0)
{
// roundDecimal prevents representing 8 as 7.9999999
- currentStepTime = FlxMath.roundDecimal((currentTimeChange.beatTime * 4) + (songPosition - currentTimeChange.timeStamp) / stepLengthMs, 6);
- currentBeatTime = currentStepTime / Constants.STEPS_PER_BEAT;
- currentMeasureTime = currentStepTime / stepsPerMeasure;
- currentStep = Math.floor(currentStepTime);
- currentBeat = Math.floor(currentBeatTime);
- currentMeasure = Math.floor(currentMeasureTime);
+ this.currentStepTime = FlxMath.roundDecimal((currentTimeChange.beatTime * 4) + (this.songPosition - currentTimeChange.timeStamp) / stepLengthMs, 6);
+ this.currentBeatTime = currentStepTime / Constants.STEPS_PER_BEAT;
+ this.currentMeasureTime = currentStepTime / stepsPerMeasure;
+ this.currentStep = Math.floor(currentStepTime);
+ this.currentBeat = Math.floor(currentBeatTime);
+ this.currentMeasure = Math.floor(currentMeasureTime);
}
else
{
// Assume a constant BPM equal to the forced value.
- currentStepTime = FlxMath.roundDecimal((songPosition / stepLengthMs), 4);
- currentBeatTime = currentStepTime / Constants.STEPS_PER_BEAT;
- currentMeasureTime = currentStepTime / stepsPerMeasure;
- currentStep = Math.floor(currentStepTime);
- currentBeat = Math.floor(currentBeatTime);
- currentMeasure = Math.floor(currentMeasureTime);
+ this.currentStepTime = FlxMath.roundDecimal((songPosition / stepLengthMs), 4);
+ this.currentBeatTime = currentStepTime / Constants.STEPS_PER_BEAT;
+ this.currentMeasureTime = currentStepTime / stepsPerMeasure;
+ this.currentStep = Math.floor(currentStepTime);
+ this.currentBeat = Math.floor(currentBeatTime);
+ this.currentMeasure = Math.floor(currentMeasureTime);
}
- // FlxSignals are really cool.
- if (currentStep != oldStep)
+ // Only fire the signal if we are THE Conductor.
+ if (this == Conductor.instance)
{
- stepHit.dispatch();
- }
+ // FlxSignals are really cool.
+ if (currentStep != oldStep)
+ {
+ Conductor.stepHit.dispatch();
+ }
- if (currentBeat != oldBeat)
- {
- beatHit.dispatch();
- }
+ if (currentBeat != oldBeat)
+ {
+ Conductor.beatHit.dispatch();
+ }
- if (currentMeasure != oldMeasure)
- {
- measureHit.dispatch();
+ if (currentMeasure != oldMeasure)
+ {
+ Conductor.measureHit.dispatch();
+ }
}
}
- public static function mapTimeChanges(songTimeChanges:Array)
+ public function mapTimeChanges(songTimeChanges:Array)
{
timeChanges = [];
@@ -338,24 +352,21 @@ class Conductor
// Without any custom handling, `currentStepTime` becomes non-zero at `songPosition = 0`.
if (currentTimeChange.timeStamp < 0.0) currentTimeChange.timeStamp = 0.0;
- if (currentTimeChange.beatTime == null)
+ if (currentTimeChange.timeStamp <= 0.0)
{
- if (currentTimeChange.timeStamp <= 0.0)
- {
- currentTimeChange.beatTime = 0.0;
- }
- else
- {
- // Calculate the beat time of this timestamp.
- currentTimeChange.beatTime = 0.0;
+ currentTimeChange.beatTime = 0.0;
+ }
+ else
+ {
+ // Calculate the beat time of this timestamp.
+ currentTimeChange.beatTime = 0.0;
- if (currentTimeChange.timeStamp > 0.0 && timeChanges.length > 0)
- {
- var prevTimeChange:SongTimeChange = timeChanges[timeChanges.length - 1];
- currentTimeChange.beatTime = FlxMath.roundDecimal(prevTimeChange.beatTime
- + ((currentTimeChange.timeStamp - prevTimeChange.timeStamp) * prevTimeChange.bpm / Constants.SECS_PER_MIN / Constants.MS_PER_SEC),
- 4);
- }
+ if (currentTimeChange.timeStamp > 0.0 && timeChanges.length > 0)
+ {
+ var prevTimeChange:SongTimeChange = timeChanges[timeChanges.length - 1];
+ currentTimeChange.beatTime = FlxMath.roundDecimal(prevTimeChange.beatTime
+ + ((currentTimeChange.timeStamp - prevTimeChange.timeStamp) * prevTimeChange.bpm / Constants.SECS_PER_MIN / Constants.MS_PER_SEC),
+ 4);
}
}
@@ -368,13 +379,13 @@ class Conductor
}
// Update currentStepTime
- Conductor.update(Conductor.songPosition);
+ this.update(Conductor.instance.songPosition);
}
/**
* Given a time in milliseconds, return a time in steps.
*/
- public static function getTimeInSteps(ms:Float):Float
+ public function getTimeInSteps(ms:Float):Float
{
if (timeChanges.length == 0)
{
@@ -411,7 +422,7 @@ class Conductor
/**
* Given a time in steps and fractional steps, return a time in milliseconds.
*/
- public static function getStepTimeInMs(stepTime:Float):Float
+ public function getStepTimeInMs(stepTime:Float):Float
{
if (timeChanges.length == 0)
{
@@ -447,7 +458,7 @@ class Conductor
/**
* Given a time in beats and fractional beats, return a time in milliseconds.
*/
- public static function getBeatTimeInMs(beatTime:Float):Float
+ public function getBeatTimeInMs(beatTime:Float):Float
{
if (timeChanges.length == 0)
{
@@ -480,13 +491,20 @@ class Conductor
}
}
+ public static function watchQuick():Void
+ {
+ FlxG.watch.addQuick("songPosition", Conductor.instance.songPosition);
+ FlxG.watch.addQuick("bpm", Conductor.instance.bpm);
+ FlxG.watch.addQuick("currentMeasureTime", Conductor.instance.currentMeasureTime);
+ FlxG.watch.addQuick("currentBeatTime", Conductor.instance.currentBeatTime);
+ FlxG.watch.addQuick("currentStepTime", Conductor.instance.currentStepTime);
+ }
+
+ /**
+ * Reset the Conductor, replacing the current instance with a fresh one.
+ */
public static function reset():Void
{
- beatHit.removeAll();
- stepHit.removeAll();
-
- mapTimeChanges([]);
- forceBPM(null);
- update(0);
+ Conductor.instance = new Conductor();
}
}
diff --git a/source/funkin/audio/visualize/ABotVis.hx b/source/funkin/audio/visualize/ABotVis.hx
index 681287808..89b004df4 100644
--- a/source/funkin/audio/visualize/ABotVis.hx
+++ b/source/funkin/audio/visualize/ABotVis.hx
@@ -64,7 +64,7 @@ class ABotVis extends FlxTypedSpriteGroup
if (vis.snd.playing) remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, vis.numSamples));
else
- remappedShit = Std.int(FlxMath.remapToRange(Conductor.songPosition, 0, vis.snd.length, 0, vis.numSamples));
+ remappedShit = Std.int(FlxMath.remapToRange(Conductor.instance.songPosition, 0, vis.snd.length, 0, vis.numSamples));
var fftSamples:Array = [];
diff --git a/source/funkin/audio/visualize/SpectogramSprite.hx b/source/funkin/audio/visualize/SpectogramSprite.hx
index 63d0fcd2e..b4e024a4c 100644
--- a/source/funkin/audio/visualize/SpectogramSprite.hx
+++ b/source/funkin/audio/visualize/SpectogramSprite.hx
@@ -164,7 +164,7 @@ class SpectogramSprite extends FlxTypedSpriteGroup
if (vis.snd.playing) remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, numSamples));
else
- remappedShit = Std.int(FlxMath.remapToRange(Conductor.songPosition, 0, vis.snd.length, 0, numSamples));
+ remappedShit = Std.int(FlxMath.remapToRange(Conductor.instance.songPosition, 0, vis.snd.length, 0, numSamples));
var fftSamples:Array = [];
var i = remappedShit;
@@ -235,15 +235,15 @@ class SpectogramSprite extends FlxTypedSpriteGroup
if (vis.snd.playing) remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, numSamples));
else
{
- if (curTime == Conductor.songPosition)
+ if (curTime == Conductor.instance.songPosition)
{
wavOptimiz = 3;
return; // already did shit, so finishes function early
}
- curTime = Conductor.songPosition;
+ curTime = Conductor.instance.songPosition;
- remappedShit = Std.int(FlxMath.remapToRange(Conductor.songPosition, 0, vis.snd.length, 0, numSamples));
+ remappedShit = Std.int(FlxMath.remapToRange(Conductor.instance.songPosition, 0, vis.snd.length, 0, numSamples));
}
wavOptimiz = 8;
diff --git a/source/funkin/data/DataParse.hx b/source/funkin/data/DataParse.hx
index cbd168a61..49dde0198 100644
--- a/source/funkin/data/DataParse.hx
+++ b/source/funkin/data/DataParse.hx
@@ -178,7 +178,31 @@ class DataParse
switch (json.value)
{
case JObject(fields):
- return cast Tools.getValue(json);
+ var result:LegacyNoteSection =
+ {
+ mustHitSection: false,
+ sectionNotes: [],
+ };
+ for (field in fields)
+ {
+ switch (field.name)
+ {
+ case 'sectionNotes':
+ result.sectionNotes = legacyNotes(field.value, field.name);
+
+ case 'mustHitSection':
+ result.mustHitSection = Tools.getValue(field.value);
+ case 'typeOfSection':
+ result.typeOfSection = Tools.getValue(field.value);
+ case 'lengthInSteps':
+ result.lengthInSteps = Tools.getValue(field.value);
+ case 'changeBPM':
+ result.changeBPM = Tools.getValue(field.value);
+ case 'bpm':
+ result.bpm = Tools.getValue(field.value);
+ }
+ }
+ return result;
default:
throw 'Expected property $name to be an object, but it was ${json.value}.';
}
@@ -189,7 +213,12 @@ class DataParse
switch (json.value)
{
case JObject(fields):
- return cast Tools.getValue(json);
+ var result = {};
+ for (field in fields)
+ {
+ Reflect.setField(result, field.name, legacyNoteSectionArray(field.value, field.name));
+ }
+ return result;
default:
throw 'Expected property $name to be an object, but it was ${json.value}.';
}
@@ -211,13 +240,13 @@ class DataParse
switch (json.value)
{
case JArray(values):
- // var time:Null = values[0] == null ? null : Tools.getValue(values[0]);
- // var data:Null = values[1] == null ? null : Tools.getValue(values[1]);
- // var length:Null = values[2] == null ? null : Tools.getValue(values[2]);
- // var alt:Null = values[3] == null ? null : Tools.getValue(values[3]);
+ var time:Null = values[0] == null ? null : Tools.getValue(values[0]);
+ var data:Null = values[1] == null ? null : Tools.getValue(values[1]);
+ var length:Null = values[2] == null ? null : Tools.getValue(values[2]);
+ var alt:Null = values[3] == null ? null : Tools.getValue(values[3]);
- // return new LegacyNote(time, data, length, alt);
- return null;
+ return new LegacyNote(time, data, length, alt);
+ // return null;
default:
throw 'Expected property $name to be a note, but it was ${json.value}.';
}
diff --git a/source/funkin/data/level/LevelRegistry.hx b/source/funkin/data/level/LevelRegistry.hx
index 75b0b11f6..b5c15de0f 100644
--- a/source/funkin/data/level/LevelRegistry.hx
+++ b/source/funkin/data/level/LevelRegistry.hx
@@ -30,6 +30,7 @@ class LevelRegistry extends BaseRegistry
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
@@ -57,6 +58,7 @@ class LevelRegistry extends BaseRegistry
public function parseEntryDataRaw(contents:String, ?fileName:String):Null
{
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
diff --git a/source/funkin/data/notestyle/NoteStyleRegistry.hx b/source/funkin/data/notestyle/NoteStyleRegistry.hx
index 4255a644b..ffb9bf490 100644
--- a/source/funkin/data/notestyle/NoteStyleRegistry.hx
+++ b/source/funkin/data/notestyle/NoteStyleRegistry.hx
@@ -35,6 +35,7 @@ class NoteStyleRegistry extends BaseRegistry
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
@@ -62,6 +63,7 @@ class NoteStyleRegistry extends BaseRegistry
public function parseEntryDataRaw(contents:String, ?fileName:String):Null
{
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
diff --git a/source/funkin/data/song/SongData.hx b/source/funkin/data/song/SongData.hx
index fe4e66032..78b3cd3fe 100644
--- a/source/funkin/data/song/SongData.hx
+++ b/source/funkin/data/song/SongData.hx
@@ -150,7 +150,7 @@ class SongTimeChange implements ICloneable
*/
@:optional
@:alias("b")
- public var beatTime:Null;
+ public var beatTime:Float;
/**
* Quarter notes per minute (float). Cannot be empty in the first element of the list,
@@ -657,7 +657,7 @@ class SongEventDataRaw implements ICloneable
{
if (_stepTime != null && !force) return _stepTime;
- return _stepTime = Conductor.getTimeInSteps(this.time);
+ return _stepTime = Conductor.instance.getTimeInSteps(this.time);
}
public function clone():SongEventDataRaw
@@ -802,7 +802,7 @@ class SongNoteDataRaw implements ICloneable
/**
* The kind of the note.
* This can allow the note to include information used for custom behavior.
- * Defaults to blank or `"normal"`.
+ * Defaults to blank or `Constants.DEFAULT_DIFFICULTY`.
*/
@:alias("k")
@:default("normal")
@@ -851,7 +851,7 @@ class SongNoteDataRaw implements ICloneable
{
if (_stepTime != null && !force) return _stepTime;
- return _stepTime = Conductor.getTimeInSteps(this.time);
+ return _stepTime = Conductor.instance.getTimeInSteps(this.time);
}
@:jignored
@@ -867,7 +867,7 @@ class SongNoteDataRaw implements ICloneable
if (_stepLength != null && !force) return _stepLength;
- return _stepLength = Conductor.getTimeInSteps(this.time + this.length) - getStepTime();
+ return _stepLength = Conductor.instance.getTimeInSteps(this.time + this.length) - getStepTime();
}
public function setStepLength(value:Float):Void
@@ -878,7 +878,7 @@ class SongNoteDataRaw implements ICloneable
}
else
{
- var lengthMs:Float = Conductor.getStepTimeInMs(value) - this.time;
+ var lengthMs:Float = Conductor.instance.getStepTimeInMs(value) - this.time;
this.length = lengthMs;
}
_stepLength = null;
diff --git a/source/funkin/data/song/SongDataUtils.hx b/source/funkin/data/song/SongDataUtils.hx
index 4ae4b1426..309676884 100644
--- a/source/funkin/data/song/SongDataUtils.hx
+++ b/source/funkin/data/song/SongDataUtils.hx
@@ -230,6 +230,7 @@ class SongDataUtils
trace('Read ${notesString.length} characters from clipboard.');
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
parser.fromJson(notesString, 'clipboard');
if (parser.errors.length > 0)
{
diff --git a/source/funkin/data/song/SongRegistry.hx b/source/funkin/data/song/SongRegistry.hx
index 850654eb7..5a0835f57 100644
--- a/source/funkin/data/song/SongRegistry.hx
+++ b/source/funkin/data/song/SongRegistry.hx
@@ -126,6 +126,8 @@ class SongRegistry extends BaseRegistry
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
+
switch (loadEntryMetadataFile(id, variation))
{
case {fileName: fileName, contents: contents}:
@@ -147,6 +149,7 @@ class SongRegistry extends BaseRegistry
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
@@ -206,6 +209,8 @@ class SongRegistry extends BaseRegistry
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
+
switch (loadEntryMetadataFile(id, variation))
{
case {fileName: fileName, contents: contents}:
@@ -226,6 +231,8 @@ class SongRegistry extends BaseRegistry
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
+
switch (loadEntryMetadataFile(id, variation))
{
case {fileName: fileName, contents: contents}:
@@ -244,6 +251,7 @@ class SongRegistry extends BaseRegistry
function parseEntryMetadataRaw_v2_1_0(contents:String, ?fileName:String = 'raw'):Null
{
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
@@ -257,6 +265,7 @@ class SongRegistry extends BaseRegistry
function parseEntryMetadataRaw_v2_0_0(contents:String, ?fileName:String = 'raw'):Null
{
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
@@ -272,6 +281,8 @@ class SongRegistry extends BaseRegistry
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
+
switch (loadMusicDataFile(id, variation))
{
case {fileName: fileName, contents: contents}:
@@ -291,6 +302,7 @@ class SongRegistry extends BaseRegistry
public function parseMusicDataRaw(contents:String, ?fileName:String = 'raw'):Null
{
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
@@ -334,6 +346,7 @@ class SongRegistry extends BaseRegistry
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
switch (loadEntryChartFile(id, variation))
{
@@ -356,6 +369,7 @@ class SongRegistry extends BaseRegistry
variation = variation == null ? Constants.DEFAULT_VARIATION : variation;
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
parser.fromJson(contents, fileName);
if (parser.errors.length > 0)
diff --git a/source/funkin/data/song/importer/ChartManifestData.hx b/source/funkin/data/song/importer/ChartManifestData.hx
index 0c7d2f0b0..dd0d28479 100644
--- a/source/funkin/data/song/importer/ChartManifestData.hx
+++ b/source/funkin/data/song/importer/ChartManifestData.hx
@@ -68,6 +68,7 @@ class ChartManifestData
public static function deserialize(contents:String):Null
{
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
parser.fromJson(contents, 'manifest.json');
if (parser.errors.length > 0)
diff --git a/source/funkin/data/song/importer/FNFLegacyData.hx b/source/funkin/data/song/importer/FNFLegacyData.hx
index 5b75368c9..52380d344 100644
--- a/source/funkin/data/song/importer/FNFLegacyData.hx
+++ b/source/funkin/data/song/importer/FNFLegacyData.hx
@@ -19,7 +19,8 @@ class LegacySongData
@:jcustomparse(funkin.data.DataParse.eitherLegacyScrollSpeeds)
public var speed:Either;
- public var stageDefault:String;
+ @:optional
+ public var stageDefault:Null;
public var bpm:Float;
@:jcustomparse(funkin.data.DataParse.eitherLegacyNoteData)
diff --git a/source/funkin/data/song/importer/FNFLegacyImporter.hx b/source/funkin/data/song/importer/FNFLegacyImporter.hx
index ee68513dc..ab2abda8e 100644
--- a/source/funkin/data/song/importer/FNFLegacyImporter.hx
+++ b/source/funkin/data/song/importer/FNFLegacyImporter.hx
@@ -14,6 +14,7 @@ class FNFLegacyImporter
public static function parseLegacyDataRaw(input:String, fileName:String = 'raw'):FNFLegacyData
{
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = true; // Set to true to ignore extra variables that might be included in the JSON.
parser.fromJson(input, fileName);
if (parser.errors.length > 0)
@@ -185,15 +186,34 @@ class FNFLegacyImporter
return result;
}
+ static final STRUMLINE_SIZE = 4;
+
static function migrateNoteSections(input:Array):Array
{
var result:Array = [];
for (section in input)
{
+ var mustHitSection = section.mustHitSection ?? false;
for (note in section.sectionNotes)
{
- result.push(new SongNoteData(note.time, note.data, note.length, note.getKind()));
+ // Handle the dumb logic for mustHitSection.
+ var noteData = note.data;
+
+ // Flip notes if mustHitSection is FALSE (not true lol).
+ if (!mustHitSection)
+ {
+ if (noteData >= STRUMLINE_SIZE)
+ {
+ noteData -= STRUMLINE_SIZE;
+ }
+ else
+ {
+ noteData += STRUMLINE_SIZE;
+ }
+ }
+
+ result.push(new SongNoteData(note.time, noteData, note.length, note.getKind()));
}
}
diff --git a/source/funkin/input/Cursor.hx b/source/funkin/input/Cursor.hx
index b4bf43808..39f399465 100644
--- a/source/funkin/input/Cursor.hx
+++ b/source/funkin/input/Cursor.hx
@@ -34,6 +34,18 @@ class Cursor
Cursor.cursorMode = null;
}
+ public static inline function toggle():Void
+ {
+ if (FlxG.mouse.visible)
+ {
+ hide();
+ }
+ else
+ {
+ show();
+ }
+ }
+
public static final CURSOR_DEFAULT_PARAMS:CursorParams =
{
graphic: "assets/images/cursor/cursor-default.png",
diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx
index d23574ce2..5b7ce9fc2 100644
--- a/source/funkin/play/Countdown.hx
+++ b/source/funkin/play/Countdown.hx
@@ -40,7 +40,7 @@ class Countdown
stopCountdown();
PlayState.instance.isInCountdown = true;
- Conductor.update(PlayState.instance.startTimestamp + Conductor.beatLengthMs * -5);
+ Conductor.instance.update(PlayState.instance.startTimestamp + Conductor.instance.beatLengthMs * -5);
// Handle onBeatHit events manually
// @:privateAccess
// PlayState.instance.dispatchEvent(new SongTimeScriptEvent(SONG_BEAT_HIT, 0, 0));
@@ -48,7 +48,7 @@ class Countdown
// The timer function gets called based on the beat of the song.
countdownTimer = new FlxTimer();
- countdownTimer.start(Conductor.beatLengthMs / 1000, function(tmr:FlxTimer) {
+ countdownTimer.start(Conductor.instance.beatLengthMs / 1000, function(tmr:FlxTimer) {
if (PlayState.instance == null)
{
tmr.cancel();
@@ -158,7 +158,7 @@ class Countdown
{
stopCountdown();
// This will trigger PlayState.startSong()
- Conductor.update(0);
+ Conductor.instance.update(0);
// PlayState.isInCountdown = false;
}
@@ -225,7 +225,7 @@ class Countdown
countdownSprite.screenCenter();
// Fade sprite in, then out, then destroy it.
- FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100, alpha: 0}, Conductor.beatLengthMs / 1000,
+ FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100, alpha: 0}, Conductor.instance.beatLengthMs / 1000,
{
ease: FlxEase.cubeInOut,
onComplete: function(twn:FlxTween) {
diff --git a/source/funkin/play/GameOverSubState.hx b/source/funkin/play/GameOverSubState.hx
index 6eb53e2d5..137bf3905 100644
--- a/source/funkin/play/GameOverSubState.hx
+++ b/source/funkin/play/GameOverSubState.hx
@@ -64,9 +64,16 @@ class GameOverSubState extends MusicBeatSubState
*/
var isEnding:Bool = false;
- public function new()
+ var isChartingMode:Bool = false;
+
+ var transparent:Bool;
+
+ public function new(params:GameOverParams)
{
super();
+
+ this.isChartingMode = params?.isChartingMode ?? false;
+ transparent = params.transparent;
}
/**
@@ -87,9 +94,10 @@ class GameOverSubState extends MusicBeatSubState
//
// Add a black background to the screen.
- // We make this transparent so that we can see the stage underneath during debugging.
var bg = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
- bg.alpha = 0.25;
+ // We make this transparent so that we can see the stage underneath during debugging,
+ // but it's normally opaque.
+ bg.alpha = transparent ? 0.25 : 1.0;
bg.scrollFactor.set();
add(bg);
@@ -121,7 +129,7 @@ class GameOverSubState extends MusicBeatSubState
gameOverMusic.stop();
// The conductor now represents the BPM of the game over music.
- Conductor.update(0);
+ Conductor.instance.update(0);
}
var hasStartedAnimation:Bool = false;
@@ -176,16 +184,27 @@ class GameOverSubState extends MusicBeatSubState
// PlayState.seenCutscene = false; // old thing...
gameOverMusic.stop();
- if (PlayStatePlaylist.isStoryMode) FlxG.switchState(new StoryMenuState());
+ if (isChartingMode)
+ {
+ this.close();
+ if (FlxG.sound.music != null) FlxG.sound.music.pause(); // Don't reset song position!
+ PlayState.instance.close(); // This only works because PlayState is a substate!
+ }
+ else if (PlayStatePlaylist.isStoryMode)
+ {
+ FlxG.switchState(new StoryMenuState());
+ }
else
+ {
FlxG.switchState(new FreeplayState());
+ }
}
if (gameOverMusic.playing)
{
// Match the conductor to the music.
// This enables the stepHit and beatHit events.
- Conductor.update(gameOverMusic.time);
+ Conductor.instance.update(gameOverMusic.time);
}
else
{
@@ -270,6 +289,7 @@ class GameOverSubState extends MusicBeatSubState
{
gameOverMusic.loadEmbedded(musicPath);
gameOverMusic.volume = startingVolume;
+ gameOverMusic.looped = !isEnding;
gameOverMusic.play();
}
}
@@ -307,3 +327,9 @@ class GameOverSubState extends MusicBeatSubState
});
}
}
+
+typedef GameOverParams =
+{
+ var isChartingMode:Bool;
+ var transparent:Bool;
+}
diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx
index 81757bcae..f15529a04 100644
--- a/source/funkin/play/PlayState.hx
+++ b/source/funkin/play/PlayState.hx
@@ -561,15 +561,15 @@ class PlayState extends MusicBeatSubState
}
// Prepare the Conductor.
- Conductor.forceBPM(null);
+ Conductor.instance.forceBPM(null);
if (currentChart.offsets != null)
{
- Conductor.instrumentalOffset = currentChart.offsets.getInstrumentalOffset();
+ Conductor.instance.instrumentalOffset = currentChart.offsets.getInstrumentalOffset();
}
- Conductor.mapTimeChanges(currentChart.timeChanges);
- Conductor.update((Conductor.beatLengthMs * -5) + startTimestamp);
+ Conductor.instance.mapTimeChanges(currentChart.timeChanges);
+ Conductor.instance.update((Conductor.instance.beatLengthMs * -5) + startTimestamp);
// The song is now loaded. We can continue to initialize the play state.
initCameras();
@@ -734,7 +734,7 @@ class PlayState extends MusicBeatSubState
// Reset music properly.
- FlxG.sound.music.time = Math.max(0, startTimestamp - Conductor.instrumentalOffset);
+ FlxG.sound.music.time = Math.max(0, startTimestamp - Conductor.instance.instrumentalOffset);
FlxG.sound.music.pause();
if (!overrideMusic)
@@ -785,22 +785,22 @@ class PlayState extends MusicBeatSubState
{
if (isInCountdown)
{
- Conductor.update(Conductor.songPosition + elapsed * 1000);
- if (Conductor.songPosition >= (startTimestamp)) startSong();
+ Conductor.instance.update(Conductor.instance.songPosition + elapsed * 1000);
+ if (Conductor.instance.songPosition >= (startTimestamp)) startSong();
}
}
else
{
if (Constants.EXT_SOUND == 'mp3')
{
- Conductor.formatOffset = Constants.MP3_DELAY_MS;
+ Conductor.instance.formatOffset = Constants.MP3_DELAY_MS;
}
else
{
- Conductor.formatOffset = 0.0;
+ Conductor.instance.formatOffset = 0.0;
}
- Conductor.update(); // Normal conductor update.
+ Conductor.instance.update(); // Normal conductor update.
}
var androidPause:Bool = false;
@@ -922,7 +922,11 @@ class PlayState extends MusicBeatSubState
}
#end
- var gameOverSubState = new GameOverSubState();
+ var gameOverSubState = new GameOverSubState(
+ {
+ isChartingMode: isChartingMode,
+ transparent: persistentDraw
+ });
FlxTransitionableSubState.skipNextTransIn = true;
FlxTransitionableSubState.skipNextTransOut = true;
openSubState(gameOverSubState);
@@ -938,7 +942,7 @@ class PlayState extends MusicBeatSubState
// TODO: Check that these work even when songPosition is less than 0.
if (songEvents != null && songEvents.length > 0)
{
- var songEventsToActivate:Array = SongEventParser.queryEvents(songEvents, Conductor.songPosition);
+ var songEventsToActivate:Array = SongEventParser.queryEvents(songEvents, Conductor.instance.songPosition);
if (songEventsToActivate.length > 0)
{
@@ -946,7 +950,7 @@ class PlayState extends MusicBeatSubState
for (event in songEventsToActivate)
{
// If an event is trying to play, but it's over 5 seconds old, skip it.
- if (event.time - Conductor.songPosition < -5000)
+ if (event.time - Conductor.instance.songPosition < -5000)
{
event.activated = true;
continue;
@@ -1048,7 +1052,7 @@ class PlayState extends MusicBeatSubState
if (startTimer.finished)
{
DiscordClient.changePresence(detailsText, '${currentChart.songName} ($storyDifficultyText)', iconRPC, true,
- currentSongLengthMs - Conductor.songPosition);
+ currentSongLengthMs - Conductor.instance.songPosition);
}
else
{
@@ -1072,12 +1076,12 @@ class PlayState extends MusicBeatSubState
{
if (health > Constants.HEALTH_MIN && !paused && FlxG.autoPause)
{
- if (Conductor.songPosition > 0.0) DiscordClient.changePresence(detailsText, currentSong.song
+ if (Conductor.instance.songPosition > 0.0) DiscordClient.changePresence(detailsText, currentSong.song
+ ' ('
+ storyDifficultyText
+ ')', iconRPC, true,
currentSongLengthMs
- - Conductor.songPosition);
+ - Conductor.instance.songPosition);
else
DiscordClient.changePresence(detailsText, currentSong.song + ' (' + storyDifficultyText + ')', iconRPC);
}
@@ -1097,23 +1101,6 @@ class PlayState extends MusicBeatSubState
}
#end
- /**
- * This function is called whenever Flixel switches switching to a new FlxState.
- * @return Whether to actually switch to the new state.
- */
- @:haxe.warning("-WDeprecated")
- override function switchTo(nextState:FlxState):Bool
- {
- var result:Bool = super.switchTo(nextState);
-
- if (result)
- {
- performCleanup();
- }
-
- return result;
- }
-
/**
* Removes any references to the current stage, then clears the stage cache,
* then reloads all the stages.
@@ -1167,17 +1154,17 @@ class PlayState extends MusicBeatSubState
if (!startingSong
&& FlxG.sound.music != null
- && (Math.abs(FlxG.sound.music.time - (Conductor.songPosition + Conductor.instrumentalOffset)) > 200
- || Math.abs(vocals.checkSyncError(Conductor.songPosition + Conductor.instrumentalOffset)) > 200))
+ && (Math.abs(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 200
+ || Math.abs(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset)) > 200))
{
trace("VOCALS NEED RESYNC");
- if (vocals != null) trace(vocals.checkSyncError(Conductor.songPosition + Conductor.instrumentalOffset));
- trace(FlxG.sound.music.time - (Conductor.songPosition + Conductor.instrumentalOffset));
+ if (vocals != null) trace(vocals.checkSyncError(Conductor.instance.songPosition + Conductor.instance.instrumentalOffset));
+ trace(FlxG.sound.music.time - (Conductor.instance.songPosition + Conductor.instance.instrumentalOffset));
resyncVocals();
}
- if (iconP1 != null) iconP1.onStepHit(Std.int(Conductor.currentStep));
- if (iconP2 != null) iconP2.onStepHit(Std.int(Conductor.currentStep));
+ if (iconP1 != null) iconP1.onStepHit(Std.int(Conductor.instance.currentStep));
+ if (iconP2 != null) iconP2.onStepHit(Std.int(Conductor.instance.currentStep));
return true;
}
@@ -1198,14 +1185,14 @@ class PlayState extends MusicBeatSubState
}
// Only zoom camera if we are zoomed by less than 35%.
- if (FlxG.camera.zoom < (1.35 * defaultCameraZoom) && cameraZoomRate > 0 && Conductor.currentBeat % cameraZoomRate == 0)
+ if (FlxG.camera.zoom < (1.35 * defaultCameraZoom) && cameraZoomRate > 0 && Conductor.instance.currentBeat % cameraZoomRate == 0)
{
// Zoom camera in (1.5%)
FlxG.camera.zoom += cameraZoomIntensity * defaultCameraZoom;
// Hud zooms double (3%)
camHUD.zoom += hudCameraZoomIntensity * defaultHUDCameraZoom;
}
- // trace('Not bopping camera: ${FlxG.camera.zoom} < ${(1.35 * defaultCameraZoom)} && ${cameraZoomRate} > 0 && ${Conductor.currentBeat} % ${cameraZoomRate} == ${Conductor.currentBeat % cameraZoomRate}}');
+ // trace('Not bopping camera: ${FlxG.camera.zoom} < ${(1.35 * defaultCameraZoom)} && ${cameraZoomRate} > 0 && ${Conductor.instance.currentBeat} % ${cameraZoomRate} == ${Conductor.instance.currentBeat % cameraZoomRate}}');
// That combo milestones that got spoiled that one time.
// Comes with NEAT visual and audio effects.
@@ -1218,13 +1205,13 @@ class PlayState extends MusicBeatSubState
// TODO: Re-enable combo text (how to do this without sections?).
// if (currentSong != null)
// {
- // shouldShowComboText = (Conductor.currentBeat % 8 == 7);
- // var daSection = .getSong()[Std.int(Conductor.currentBeat / 16)];
+ // shouldShowComboText = (Conductor.instance.currentBeat % 8 == 7);
+ // var daSection = .getSong()[Std.int(Conductor.instance.currentBeat / 16)];
// shouldShowComboText = shouldShowComboText && (daSection != null && daSection.mustHitSection);
// shouldShowComboText = shouldShowComboText && (Highscore.tallies.combo > 5);
//
- // var daNextSection = .getSong()[Std.int(Conductor.currentBeat / 16) + 1];
- // var isEndOfSong = .getSong().length < Std.int(Conductor.currentBeat / 16);
+ // var daNextSection = .getSong()[Std.int(Conductor.instance.currentBeat / 16) + 1];
+ // var isEndOfSong = .getSong().length < Std.int(Conductor.instance.currentBeat / 16);
// shouldShowComboText = shouldShowComboText && (isEndOfSong || (daNextSection != null && !daNextSection.mustHitSection));
// }
@@ -1237,7 +1224,7 @@ class PlayState extends MusicBeatSubState
var frameShit:Float = (1 / 24) * 2; // equals 2 frames in the animation
- new FlxTimer().start(((Conductor.beatLengthMs / 1000) * 1.25) - frameShit, function(tmr) {
+ new FlxTimer().start(((Conductor.instance.beatLengthMs / 1000) * 1.25) - frameShit, function(tmr) {
animShit.forceFinish();
});
}
@@ -1251,7 +1238,7 @@ class PlayState extends MusicBeatSubState
return true;
}
- override function destroy():Void
+ public override function destroy():Void
{
if (currentConversation != null)
{
@@ -1259,6 +1246,8 @@ class PlayState extends MusicBeatSubState
currentConversation.kill();
}
+ performCleanup();
+
super.destroy();
}
@@ -1272,10 +1261,10 @@ class PlayState extends MusicBeatSubState
if (currentStage == null) return;
// TODO: Add HEY! song events to Tutorial.
- if (Conductor.currentBeat % 16 == 15
+ if (Conductor.instance.currentBeat % 16 == 15
&& currentStage.getDad().characterId == 'gf'
- && Conductor.currentBeat > 16
- && Conductor.currentBeat < 48)
+ && Conductor.instance.currentBeat > 16
+ && Conductor.instance.currentBeat < 48)
{
currentStage.getBoyfriend().playAnimation('hey', true);
currentStage.getDad().playAnimation('cheer', true);
@@ -1586,7 +1575,7 @@ class PlayState extends MusicBeatSubState
trace('Song difficulty could not be loaded.');
}
- // Conductor.forceBPM(currentChart.getStartingBPM());
+ // Conductor.instance.forceBPM(currentChart.getStartingBPM());
if (!overrideMusic)
{
@@ -1717,7 +1706,7 @@ class PlayState extends MusicBeatSubState
FlxG.sound.music.onComplete = endSong;
// A negative instrumental offset means the song skips the first few milliseconds of the track.
// This just gets added into the startTimestamp behavior so we don't need to do anything extra.
- FlxG.sound.music.time = startTimestamp - Conductor.instrumentalOffset;
+ FlxG.sound.music.time = startTimestamp - Conductor.instance.instrumentalOffset;
trace('Playing vocals...');
add(vocals);
@@ -1733,7 +1722,7 @@ class PlayState extends MusicBeatSubState
if (startTimestamp > 0)
{
- // FlxG.sound.music.time = startTimestamp - Conductor.instrumentalOffset;
+ // FlxG.sound.music.time = startTimestamp - Conductor.instance.instrumentalOffset;
handleSkippedNotes();
}
}
@@ -1811,7 +1800,7 @@ class PlayState extends MusicBeatSubState
var hitWindowCenter = note.strumTime;
var hitWindowEnd = note.strumTime + Constants.HIT_WINDOW_MS;
- if (Conductor.songPosition > hitWindowEnd)
+ if (Conductor.instance.songPosition > hitWindowEnd)
{
if (note.hasMissed) continue;
@@ -1821,7 +1810,7 @@ class PlayState extends MusicBeatSubState
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = true;
}
- else if (Conductor.songPosition > hitWindowCenter)
+ else if (Conductor.instance.songPosition > hitWindowCenter)
{
if (note.hasBeenHit) continue;
@@ -1842,7 +1831,7 @@ class PlayState extends MusicBeatSubState
opponentStrumline.playNoteHoldCover(note.holdNoteSprite);
}
}
- else if (Conductor.songPosition > hitWindowStart)
+ else if (Conductor.instance.songPosition > hitWindowStart)
{
if (note.hasBeenHit || note.hasMissed) continue;
@@ -1888,14 +1877,14 @@ class PlayState extends MusicBeatSubState
var hitWindowCenter = note.strumTime;
var hitWindowEnd = note.strumTime + Constants.HIT_WINDOW_MS;
- if (Conductor.songPosition > hitWindowEnd)
+ if (Conductor.instance.songPosition > hitWindowEnd)
{
note.tooEarly = false;
note.mayHit = false;
note.hasMissed = true;
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = true;
}
- else if (Conductor.songPosition > hitWindowStart)
+ else if (Conductor.instance.songPosition > hitWindowStart)
{
note.tooEarly = false;
note.mayHit = true;
@@ -1962,7 +1951,7 @@ class PlayState extends MusicBeatSubState
if (note == null || note.hasBeenHit) continue;
var hitWindowEnd = note.strumTime + Constants.HIT_WINDOW_MS;
- if (Conductor.songPosition > hitWindowEnd)
+ if (Conductor.instance.songPosition > hitWindowEnd)
{
// We have passed this note.
// Flag the note for deletion without actually penalizing the player.
@@ -2126,7 +2115,7 @@ class PlayState extends MusicBeatSubState
{
inputSpitter.push(
{
- t: Std.int(Conductor.songPosition),
+ t: Std.int(Conductor.instance.songPosition),
d: indices[i],
l: 20
});
@@ -2136,7 +2125,7 @@ class PlayState extends MusicBeatSubState
{
inputSpitter.push(
{
- t: Std.int(Conductor.songPosition),
+ t: Std.int(Conductor.instance.songPosition),
d: -1,
l: 20
});
@@ -2197,7 +2186,7 @@ class PlayState extends MusicBeatSubState
{
inputSpitter.push(
{
- t: Std.int(Conductor.songPosition),
+ t: Std.int(Conductor.instance.songPosition),
d: indices[i],
l: 20
});
@@ -2286,7 +2275,7 @@ class PlayState extends MusicBeatSubState
// Get the offset and compensate for input latency.
// Round inward (trim remainder) for consistency.
- var noteDiff:Int = Std.int(Conductor.songPosition - daNote.noteData.time - inputLatencyMs);
+ var noteDiff:Int = Std.int(Conductor.instance.songPosition - daNote.noteData.time - inputLatencyMs);
var score = Scoring.scoreNote(noteDiff, PBOT1);
var daRating = Scoring.judgeNote(noteDiff, PBOT1);
@@ -2341,7 +2330,7 @@ class PlayState extends MusicBeatSubState
{
inputSpitter.push(
{
- t: Std.int(Conductor.songPosition),
+ t: Std.int(Conductor.instance.songPosition),
d: indices[i],
l: 20
});
@@ -2351,7 +2340,7 @@ class PlayState extends MusicBeatSubState
{
inputSpitter.push(
{
- t: Std.int(Conductor.songPosition),
+ t: Std.int(Conductor.instance.songPosition),
d: -1,
l: 20
});
@@ -2750,15 +2739,15 @@ class PlayState extends MusicBeatSubState
{
FlxG.sound.music.pause();
- var targetTimeSteps:Float = Conductor.currentStepTime + (Conductor.timeSignatureNumerator * Constants.STEPS_PER_BEAT * sections);
- var targetTimeMs:Float = Conductor.getStepTimeInMs(targetTimeSteps);
+ var targetTimeSteps:Float = Conductor.instance.currentStepTime + (Conductor.instance.timeSignatureNumerator * Constants.STEPS_PER_BEAT * sections);
+ var targetTimeMs:Float = Conductor.instance.getStepTimeInMs(targetTimeSteps);
FlxG.sound.music.time = targetTimeMs;
handleSkippedNotes();
// regenNoteData(FlxG.sound.music.time);
- Conductor.update(FlxG.sound.music.time);
+ Conductor.instance.update(FlxG.sound.music.time);
resyncVocals();
}
diff --git a/source/funkin/play/character/BaseCharacter.hx b/source/funkin/play/character/BaseCharacter.hx
index 7ad0892f6..390864148 100644
--- a/source/funkin/play/character/BaseCharacter.hx
+++ b/source/funkin/play/character/BaseCharacter.hx
@@ -367,7 +367,7 @@ class BaseCharacter extends Bopper
// This lets you add frames to the end of the sing animation to ease back into the idle!
holdTimer += event.elapsed;
- var singTimeSec:Float = singTimeSec * (Conductor.beatLengthMs * 0.001); // x beats, to ms.
+ var singTimeSec:Float = singTimeSec * (Conductor.instance.beatLengthMs * 0.001); // x beats, to ms.
if (getCurrentAnimation().endsWith('miss')) singTimeSec *= 2; // makes it feel more awkward when you miss
diff --git a/source/funkin/play/character/MultiSparrowCharacter.hx b/source/funkin/play/character/MultiSparrowCharacter.hx
index 968f613ff..0fc07399c 100644
--- a/source/funkin/play/character/MultiSparrowCharacter.hx
+++ b/source/funkin/play/character/MultiSparrowCharacter.hx
@@ -205,7 +205,7 @@ class MultiSparrowCharacter extends BaseCharacter
graphic = value.parent;
this.frames = value;
this.frame = value.getByIndex(0);
- this.numFrames = value.numFrames;
+ // this.numFrames = value.numFrames;
resetHelpers();
this.bakedRotationAngle = 0;
this.animation.frameIndex = 0;
diff --git a/source/funkin/play/components/ComboMilestone.hx b/source/funkin/play/components/ComboMilestone.hx
index 54d1438f1..4119e45c2 100644
--- a/source/funkin/play/components/ComboMilestone.hx
+++ b/source/funkin/play/components/ComboMilestone.hx
@@ -40,7 +40,7 @@ class ComboMilestone extends FlxTypedSpriteGroup
{
if (onScreenTime < 0.9)
{
- new FlxTimer().start((Conductor.beatLengthMs / 1000) * 0.25, function(tmr) {
+ new FlxTimer().start((Conductor.instance.beatLengthMs / 1000) * 0.25, function(tmr) {
forceFinish();
});
}
diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx
index 38a6ec15a..9553856a9 100644
--- a/source/funkin/play/components/PopUpStuff.hx
+++ b/source/funkin/play/components/PopUpStuff.hx
@@ -59,7 +59,7 @@ class PopUpStuff extends FlxTypedGroup
remove(rating, true);
rating.destroy();
},
- startDelay: Conductor.beatLengthMs * 0.001
+ startDelay: Conductor.instance.beatLengthMs * 0.001
});
}
@@ -110,7 +110,7 @@ class PopUpStuff extends FlxTypedGroup
remove(comboSpr, true);
comboSpr.destroy();
},
- startDelay: Conductor.beatLengthMs * 0.001
+ startDelay: Conductor.instance.beatLengthMs * 0.001
});
var seperatedScore:Array = [];
@@ -157,7 +157,7 @@ class PopUpStuff extends FlxTypedGroup
remove(numScore, true);
numScore.destroy();
},
- startDelay: Conductor.beatLengthMs * 0.002
+ startDelay: Conductor.instance.beatLengthMs * 0.002
});
daLoop++;
diff --git a/source/funkin/play/event/ZoomCameraSongEvent.hx b/source/funkin/play/event/ZoomCameraSongEvent.hx
index 1ae76039e..4ad2ed390 100644
--- a/source/funkin/play/event/ZoomCameraSongEvent.hx
+++ b/source/funkin/play/event/ZoomCameraSongEvent.hx
@@ -79,7 +79,8 @@ class ZoomCameraSongEvent extends SongEvent
return;
}
- FlxTween.tween(PlayState.instance, {defaultCameraZoom: zoom * FlxCamera.defaultZoom}, (Conductor.stepLengthMs * duration / 1000), {ease: easeFunction});
+ FlxTween.tween(PlayState.instance, {defaultCameraZoom: zoom * FlxCamera.defaultZoom}, (Conductor.instance.stepLengthMs * duration / 1000),
+ {ease: easeFunction});
}
}
diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx
index 0145dee3f..b312494cf 100644
--- a/source/funkin/play/notes/Strumline.hx
+++ b/source/funkin/play/notes/Strumline.hx
@@ -274,10 +274,12 @@ class Strumline extends FlxSpriteGroup
static function calculateNoteYPos(strumTime:Float, vwoosh:Bool = true):Float
{
// Make the note move faster visually as it moves offscreen.
- var vwoosh:Float = (strumTime < Conductor.songPosition) && vwoosh ? 2.0 : 1.0;
+ // var vwoosh:Float = (strumTime < Conductor.songPosition) && vwoosh ? 2.0 : 1.0;
+ // ^^^ commented this out... do NOT make it move faster as it moves offscreen!
+ var vwoosh:Float = 1.0;
var scrollSpeed:Float = PlayState.instance?.currentChart?.scrollSpeed ?? 1.0;
- return Constants.PIXELS_PER_MS * (Conductor.songPosition - strumTime) * scrollSpeed * vwoosh * (Preferences.downscroll ? 1 : -1);
+ return Constants.PIXELS_PER_MS * (Conductor.instance.songPosition - strumTime) * scrollSpeed * vwoosh * (Preferences.downscroll ? 1 : -1);
}
function updateNotes():Void
@@ -285,8 +287,8 @@ class Strumline extends FlxSpriteGroup
if (noteData.length == 0) return;
var songStart:Float = PlayState.instance?.startTimestamp ?? 0.0;
- var hitWindowStart:Float = Conductor.songPosition - Constants.HIT_WINDOW_MS;
- var renderWindowStart:Float = Conductor.songPosition + RENDER_DISTANCE_MS;
+ var hitWindowStart:Float = Conductor.instance.songPosition - Constants.HIT_WINDOW_MS;
+ var renderWindowStart:Float = Conductor.instance.songPosition + RENDER_DISTANCE_MS;
for (noteIndex in nextNoteIndex...noteData.length)
{
@@ -333,7 +335,7 @@ class Strumline extends FlxSpriteGroup
{
if (holdNote == null || !holdNote.alive) continue;
- if (Conductor.songPosition > holdNote.strumTime && holdNote.hitNote && !holdNote.missedNote)
+ if (Conductor.instance.songPosition > holdNote.strumTime && holdNote.hitNote && !holdNote.missedNote)
{
if (isPlayer && !isKeyHeld(holdNote.noteDirection))
{
@@ -347,7 +349,7 @@ class Strumline extends FlxSpriteGroup
var renderWindowEnd = holdNote.strumTime + holdNote.fullSustainLength + Constants.HIT_WINDOW_MS + RENDER_DISTANCE_MS / 8;
- if (holdNote.missedNote && Conductor.songPosition >= renderWindowEnd)
+ if (holdNote.missedNote && Conductor.instance.songPosition >= renderWindowEnd)
{
// Hold note is offscreen, kill it.
holdNote.visible = false;
@@ -397,13 +399,13 @@ class Strumline extends FlxSpriteGroup
holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + yOffset + STRUMLINE_SIZE / 2;
}
}
- else if (Conductor.songPosition > holdNote.strumTime && holdNote.hitNote)
+ else if (Conductor.instance.songPosition > holdNote.strumTime && holdNote.hitNote)
{
// Hold note is currently being hit, clip it off.
holdConfirm(holdNote.noteDirection);
holdNote.visible = true;
- holdNote.sustainLength = (holdNote.strumTime + holdNote.fullSustainLength) - Conductor.songPosition;
+ holdNote.sustainLength = (holdNote.strumTime + holdNote.fullSustainLength) - Conductor.instance.songPosition;
if (holdNote.sustainLength <= 10)
{
diff --git a/source/funkin/play/notes/SustainTrail.hx b/source/funkin/play/notes/SustainTrail.hx
index ab4bf5f16..7367b97af 100644
--- a/source/funkin/play/notes/SustainTrail.hx
+++ b/source/funkin/play/notes/SustainTrail.hx
@@ -149,9 +149,9 @@ class SustainTrail extends FlxSprite
if (sustainLength == s) return s;
height = sustainHeight(s, getScrollSpeed());
- // updateColorTransform();
+ this.sustainLength = s;
updateClipping();
- return sustainLength = s;
+ return this.sustainLength;
}
/**
@@ -162,13 +162,15 @@ class SustainTrail extends FlxSprite
public function updateClipping(songTime:Float = 0):Void
{
var clipHeight:Float = FlxMath.bound(sustainHeight(sustainLength - (songTime - strumTime), getScrollSpeed()), 0, height);
- if (clipHeight == 0)
+ if (clipHeight <= 0.1)
{
visible = false;
return;
}
else
+ {
visible = true;
+ }
var bottomHeight:Float = graphic.height * zoom * endOffset;
var partHeight:Float = clipHeight - bottomHeight;
diff --git a/source/funkin/play/stage/StageData.hx b/source/funkin/play/stage/StageData.hx
index d89995ef3..2d87dec31 100644
--- a/source/funkin/play/stage/StageData.hx
+++ b/source/funkin/play/stage/StageData.hx
@@ -164,6 +164,7 @@ class StageDataParser
try
{
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
parser.fromJson(rawJson, '$stageId.json');
if (parser.errors.length > 0)
diff --git a/source/funkin/ui/MusicBeatState.hx b/source/funkin/ui/MusicBeatState.hx
index 077e9e495..848985563 100644
--- a/source/funkin/ui/MusicBeatState.hx
+++ b/source/funkin/ui/MusicBeatState.hx
@@ -83,13 +83,13 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler
function handleQuickWatch():Void
{
// Display Conductor info in the watch window.
- FlxG.watch.addQuick("songPosition", Conductor.songPosition);
- FlxG.watch.addQuick("songPositionNoOffset", Conductor.songPosition + Conductor.instrumentalOffset);
+ FlxG.watch.addQuick("songPosition", Conductor.instance.songPosition);
+ FlxG.watch.addQuick("songPositionNoOffset", Conductor.instance.songPosition + Conductor.instance.instrumentalOffset);
FlxG.watch.addQuick("musicTime", FlxG.sound.music?.time ?? 0.0);
- FlxG.watch.addQuick("bpm", Conductor.bpm);
- FlxG.watch.addQuick("currentMeasureTime", Conductor.currentBeatTime);
- FlxG.watch.addQuick("currentBeatTime", Conductor.currentBeatTime);
- FlxG.watch.addQuick("currentStepTime", Conductor.currentStepTime);
+ FlxG.watch.addQuick("bpm", Conductor.instance.bpm);
+ FlxG.watch.addQuick("currentMeasureTime", Conductor.instance.currentBeatTime);
+ FlxG.watch.addQuick("currentBeatTime", Conductor.instance.currentBeatTime);
+ FlxG.watch.addQuick("currentStepTime", Conductor.instance.currentStepTime);
}
override function update(elapsed:Float)
@@ -139,7 +139,7 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler
public function stepHit():Bool
{
- var event = new SongTimeScriptEvent(SONG_STEP_HIT, Conductor.currentBeat, Conductor.currentStep);
+ var event = new SongTimeScriptEvent(SONG_STEP_HIT, Conductor.instance.currentBeat, Conductor.instance.currentStep);
dispatchEvent(event);
@@ -150,7 +150,7 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler
public function beatHit():Bool
{
- var event = new SongTimeScriptEvent(SONG_BEAT_HIT, Conductor.currentBeat, Conductor.currentStep);
+ var event = new SongTimeScriptEvent(SONG_BEAT_HIT, Conductor.instance.currentBeat, Conductor.instance.currentStep);
dispatchEvent(event);
diff --git a/source/funkin/ui/MusicBeatSubState.hx b/source/funkin/ui/MusicBeatSubState.hx
index 9dd755b62..0fa55c234 100644
--- a/source/funkin/ui/MusicBeatSubState.hx
+++ b/source/funkin/ui/MusicBeatSubState.hx
@@ -65,12 +65,8 @@ class MusicBeatSubState extends FlxTransitionableSubState implements IEventHandl
if (FlxG.keys.justPressed.F5) debug_refreshModules();
// Display Conductor info in the watch window.
- FlxG.watch.addQuick("songPosition", Conductor.songPosition);
FlxG.watch.addQuick("musicTime", FlxG.sound.music?.time ?? 0.0);
- FlxG.watch.addQuick("bpm", Conductor.bpm);
- FlxG.watch.addQuick("currentMeasureTime", Conductor.currentBeatTime);
- FlxG.watch.addQuick("currentBeatTime", Conductor.currentBeatTime);
- FlxG.watch.addQuick("currentStepTime", Conductor.currentStepTime);
+ Conductor.watchQuick();
dispatchEvent(new UpdateScriptEvent(elapsed));
}
@@ -99,7 +95,7 @@ class MusicBeatSubState extends FlxTransitionableSubState implements IEventHandl
*/
public function stepHit():Bool
{
- var event:ScriptEvent = new SongTimeScriptEvent(SONG_STEP_HIT, Conductor.currentBeat, Conductor.currentStep);
+ var event:ScriptEvent = new SongTimeScriptEvent(SONG_STEP_HIT, Conductor.instance.currentBeat, Conductor.instance.currentStep);
dispatchEvent(event);
@@ -115,7 +111,7 @@ class MusicBeatSubState extends FlxTransitionableSubState implements IEventHandl
*/
public function beatHit():Bool
{
- var event:ScriptEvent = new SongTimeScriptEvent(SONG_BEAT_HIT, Conductor.currentBeat, Conductor.currentStep);
+ var event:ScriptEvent = new SongTimeScriptEvent(SONG_BEAT_HIT, Conductor.instance.currentBeat, Conductor.instance.currentStep);
dispatchEvent(event);
diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index c120bb9e4..78b651734 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -21,6 +21,7 @@ import flixel.system.FlxAssets.FlxSoundAsset;
import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
import flixel.tweens.misc.VarTween;
+import haxe.ui.Toolkit;
import flixel.util.FlxColor;
import flixel.util.FlxSort;
import flixel.util.FlxTimer;
@@ -124,6 +125,7 @@ import flixel.group.FlxGroup.FlxTypedGroup;
import funkin.audio.visualize.PolygonVisGroup;
import flixel.input.mouse.FlxMouseEvent;
import flixel.text.FlxText;
+import flixel.system.debug.log.LogStyle;
using Lambda;
@@ -273,13 +275,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
function get_songLengthInSteps():Float
{
- return Conductor.getTimeInSteps(songLengthInMs);
+ return Conductor.instance.getTimeInSteps(songLengthInMs);
}
function set_songLengthInSteps(value:Float):Float
{
- // Getting a reasonable result from setting songLengthInSteps requires that Conductor.mapBPMChanges be called first.
- songLengthInMs = Conductor.getStepTimeInMs(value);
+ // Getting a reasonable result from setting songLengthInSteps requires that Conductor.instance.mapBPMChanges be called first.
+ songLengthInMs = Conductor.instance.getStepTimeInMs(value);
return value;
}
@@ -393,12 +395,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
function get_scrollPositionInMs():Float
{
- return Conductor.getStepTimeInMs(scrollPositionInSteps);
+ return Conductor.instance.getStepTimeInMs(scrollPositionInSteps);
}
function set_scrollPositionInMs(value:Float):Float
{
- scrollPositionInSteps = Conductor.getTimeInSteps(value);
+ scrollPositionInSteps = Conductor.instance.getTimeInSteps(value);
return value;
}
@@ -452,13 +454,13 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
function get_playheadPositionInMs():Float
{
if (audioVisGroup != null && audioVisGroup.playerVis != null)
- audioVisGroup.playerVis.realtimeStartOffset = -Conductor.getStepTimeInMs(playheadPositionInSteps);
- return Conductor.getStepTimeInMs(playheadPositionInSteps);
+ audioVisGroup.playerVis.realtimeStartOffset = -Conductor.instance.getStepTimeInMs(playheadPositionInSteps);
+ return Conductor.instance.getStepTimeInMs(playheadPositionInSteps);
}
function set_playheadPositionInMs(value:Float):Float
{
- playheadPositionInSteps = Conductor.getTimeInSteps(value);
+ playheadPositionInSteps = Conductor.instance.getTimeInSteps(value);
if (audioVisGroup != null && audioVisGroup.playerVis != null) audioVisGroup.playerVis.realtimeStartOffset = -value;
return value;
@@ -544,6 +546,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
*/
var playtestPracticeMode:Bool = false;
+ /**
+ * Enables or disables the "debugger" popup that appears when you run into a flixel error.
+ */
+ var enabledDebuggerPopup:Bool = true;
+
// Visuals
/**
@@ -753,15 +760,23 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
function set_currentNoteSelection(value:Array):Array
{
+ // This value is true if all elements of the current selection are also in the new selection.
+ var isSuperset:Bool = currentNoteSelection.isSubset(value);
+ var isEqual:Bool = currentNoteSelection.isEqualUnordered(value);
+
currentNoteSelection = value;
- if (currentNoteSelection.length > 0)
+ if (!isEqual)
{
- notePreview.addNotes(currentNoteSelection, Std.int(songLengthInMs), true);
- }
- else
- {
- notePreviewDirty = true;
+ if (currentNoteSelection.length > 0 && isSuperset)
+ {
+ notePreview.addSelectedNotes(currentNoteSelection, Std.int(songLengthInMs));
+ }
+ else
+ {
+ // The new selection removes elements from the old selection, so we have to redraw the note preview.
+ notePreviewDirty = true;
+ }
}
return currentNoteSelection;
@@ -1080,7 +1095,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
function get_availableDifficulties():Array
{
var m:Null = songMetadata.get(selectedVariation);
- return m?.playData?.difficulties ?? [];
+ return m?.playData?.difficulties ?? [Constants.DEFAULT_DIFFICULTY];
}
/**
@@ -1139,7 +1154,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
var result:Null = songChartData.get(selectedVariation);
if (result == null)
{
- result = new SongChartData(["normal" => 1.0], [], ["normal" => []]);
+ result = new SongChartData([Constants.DEFAULT_DIFFICULTY => 1.0], [], [Constants.DEFAULT_DIFFICULTY => []]);
songChartData.set(selectedVariation, result);
}
return result;
@@ -1363,6 +1378,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
function set_selectedDifficulty(value:String):String
{
+ if (value == null) value = availableDifficulties[0] ?? Constants.DEFAULT_DIFFICULTY;
+
selectedDifficulty = value;
// Make sure view is updated when the difficulty changes.
@@ -2408,16 +2425,33 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
}
else
{
- Conductor.currentTimeChange.bpm += 1;
+ Conductor.instance.currentTimeChange.bpm += 1;
this.refreshToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT);
}
}
playbarBPM.onRightClick = _ -> {
- Conductor.currentTimeChange.bpm -= 1;
+ Conductor.instance.currentTimeChange.bpm -= 1;
this.refreshToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT);
}
+ playbarDifficulty.onClick = _ -> {
+ if (FlxG.keys.pressed.CONTROL)
+ {
+ this.setToolboxState(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT, true);
+ }
+ else
+ {
+ incrementDifficulty(-1);
+ this.refreshToolbox(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT);
+ }
+ }
+
+ playbarDifficulty.onRightClick = _ -> {
+ incrementDifficulty(1);
+ this.refreshToolbox(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT);
+ }
+
// Add functionality to the menu items.
// File
@@ -2462,9 +2496,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
menubarItemPaste.onClick = _ -> {
var targetMs:Float = scrollPositionInMs + playheadPositionInMs;
- var targetStep:Float = Conductor.getTimeInSteps(targetMs);
+ var targetStep:Float = Conductor.instance.getTimeInSteps(targetMs);
var targetSnappedStep:Float = Math.floor(targetStep / noteSnapRatio) * noteSnapRatio;
- var targetSnappedMs:Float = Conductor.getStepTimeInMs(targetSnappedStep);
+ var targetSnappedMs:Float = Conductor.instance.getStepTimeInMs(targetSnappedStep);
performCommand(new PasteItemsCommand(targetSnappedMs));
};
@@ -2552,8 +2586,25 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
menubarItemPlayPause.onClick = _ -> toggleAudioPlayback();
- menubarItemLoadInstrumental.onClick = _ -> this.openUploadInstDialog(true);
- menubarItemLoadVocals.onClick = _ -> this.openUploadVocalsDialog(true);
+ menubarItemLoadInstrumental.onClick = _ -> {
+ var dialog = this.openUploadInstDialog(true);
+ // Ensure instrumental and vocals are reloaded properly.
+ dialog.onDialogClosed = function(_) {
+ this.isHaxeUIDialogOpen = false;
+ this.switchToCurrentInstrumental();
+ this.postLoadInstrumental();
+ }
+ };
+
+ menubarItemLoadVocals.onClick = _ -> {
+ var dialog = this.openUploadVocalsDialog(true);
+ // Ensure instrumental and vocals are reloaded properly.
+ dialog.onDialogClosed = function(_) {
+ this.isHaxeUIDialogOpen = false;
+ this.switchToCurrentInstrumental();
+ this.postLoadInstrumental();
+ }
+ };
menubarItemVolumeMetronome.onChange = event -> {
var volume:Float = event.value.toFloat() / 100.0;
@@ -2598,10 +2649,6 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
menubarLabelPlaybackSpeed.text = 'Playback Speed - ${pitchDisplay}x';
}
- playbarDifficulty.onClick = _ -> {
- this.setToolboxState(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT, true);
- }
-
menubarItemToggleToolboxDifficulty.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT, event.value);
menubarItemToggleToolboxMetadata.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT, event.value);
menubarItemToggleToolboxNotes.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT, event.value);
@@ -2645,10 +2692,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
saveDataDirty = false;
}
+ var displayAutosavePopup:Bool = false;
+
/**
* UPDATE FUNCTIONS
*/
- function autoSave():Void
+ function autoSave(?beforePlaytest:Bool = false):Void
{
var needsAutoSave:Bool = saveDataDirty;
@@ -2666,13 +2715,21 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
if (needsAutoSave)
{
this.exportAllSongData(true, null);
- var absoluteBackupsPath:String = Path.join([Sys.getCwd(), ChartEditorImportExportHandler.BACKUPS_PATH]);
- this.infoWithActions('Auto-Save', 'Chart auto-saved to ${absoluteBackupsPath}.', [
- {
- text: "Take Me There",
- callback: openBackupsFolder,
- }
- ]);
+ if (beforePlaytest)
+ {
+ displayAutosavePopup = true;
+ }
+ else
+ {
+ displayAutosavePopup = false;
+ var absoluteBackupsPath:String = Path.join([Sys.getCwd(), ChartEditorImportExportHandler.BACKUPS_PATH]);
+ this.infoWithActions('Auto-Save', 'Chart auto-saved to ${absoluteBackupsPath}.', [
+ {
+ text: "Take Me There",
+ callback: openBackupsFolder,
+ }
+ ]);
+ }
}
#end
}
@@ -2681,14 +2738,16 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
* Open the backups folder in the file explorer.
* Don't call this on HTML5.
*/
- function openBackupsFolder(?_):Void
+ function openBackupsFolder(?_):Bool
{
#if sys
// TODO: Is there a way to open a folder and highlight a file in it?
var absoluteBackupsPath:String = Path.join([Sys.getCwd(), ChartEditorImportExportHandler.BACKUPS_PATH]);
WindowUtil.openFolder(absoluteBackupsPath);
+ return true;
#else
trace('No file system access, cannot open backups folder.');
+ return false;
#end
}
@@ -2788,7 +2847,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
if (metronomeVolume > 0.0 && this.subState == null && (audioInstTrack != null && audioInstTrack.isPlaying))
{
- playMetronomeTick(Conductor.currentBeat % 4 == 0);
+ playMetronomeTick(Conductor.instance.currentBeat % 4 == 0);
}
return true;
@@ -2804,8 +2863,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
if (audioInstTrack != null && audioInstTrack.isPlaying)
{
- if (healthIconDad != null) healthIconDad.onStepHit(Conductor.currentStep);
- if (healthIconBF != null) healthIconBF.onStepHit(Conductor.currentStep);
+ if (healthIconDad != null) healthIconDad.onStepHit(Conductor.instance.currentStep);
+ if (healthIconBF != null) healthIconBF.onStepHit(Conductor.instance.currentStep);
}
// Updating these every step keeps it more accurate.
@@ -2833,12 +2892,12 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
audioInstTrack.update(elapsed);
// If the song starts 50ms in, make sure we start the song there.
- if (Conductor.instrumentalOffset < 0)
+ if (Conductor.instance.instrumentalOffset < 0)
{
- if (audioInstTrack.time < -Conductor.instrumentalOffset)
+ if (audioInstTrack.time < -Conductor.instance.instrumentalOffset)
{
- trace('Resetting instrumental time to ${- Conductor.instrumentalOffset}ms');
- audioInstTrack.time = -Conductor.instrumentalOffset;
+ trace('Resetting instrumental time to ${- Conductor.instance.instrumentalOffset}ms');
+ audioInstTrack.time = -Conductor.instance.instrumentalOffset;
}
}
}
@@ -2849,16 +2908,16 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
{
// If middle mouse panning during song playback, we move ONLY the playhead, without scrolling. Neat!
- var oldStepTime:Float = Conductor.currentStepTime;
- var oldSongPosition:Float = Conductor.songPosition + Conductor.instrumentalOffset;
- Conductor.update(audioInstTrack.time);
- handleHitsounds(oldSongPosition, Conductor.songPosition + Conductor.instrumentalOffset);
+ var oldStepTime:Float = Conductor.instance.currentStepTime;
+ var oldSongPosition:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
+ Conductor.instance.update(audioInstTrack.time);
+ handleHitsounds(oldSongPosition, Conductor.instance.songPosition + Conductor.instance.instrumentalOffset);
// Resync vocals.
if (audioVocalTrackGroup != null && Math.abs(audioInstTrack.time - audioVocalTrackGroup.time) > 100)
{
audioVocalTrackGroup.time = audioInstTrack.time;
}
- var diffStepTime:Float = Conductor.currentStepTime - oldStepTime;
+ var diffStepTime:Float = Conductor.instance.currentStepTime - oldStepTime;
// Move the playhead.
playheadPositionInPixels += diffStepTime * GRID_SIZE;
@@ -2868,9 +2927,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
else
{
// Else, move the entire view.
- var oldSongPosition:Float = Conductor.songPosition + Conductor.instrumentalOffset;
- Conductor.update(audioInstTrack.time);
- handleHitsounds(oldSongPosition, Conductor.songPosition + Conductor.instrumentalOffset);
+ var oldSongPosition:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
+ Conductor.instance.update(audioInstTrack.time);
+ handleHitsounds(oldSongPosition, Conductor.instance.songPosition + Conductor.instance.instrumentalOffset);
// Resync vocals.
if (audioVocalTrackGroup != null && Math.abs(audioInstTrack.time - audioVocalTrackGroup.time) > 100)
{
@@ -2879,7 +2938,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// We need time in fractional steps here to allow the song to actually play.
// Also account for a potentially offset playhead.
- scrollPositionInPixels = (Conductor.currentStepTime + Conductor.instrumentalOffsetSteps) * GRID_SIZE - playheadPositionInPixels;
+ scrollPositionInPixels = (Conductor.instance.currentStepTime + Conductor.instance.instrumentalOffsetSteps) * GRID_SIZE - playheadPositionInPixels;
// DO NOT move song to scroll position here specifically.
@@ -3008,8 +3067,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Let's try testing only notes within a certain range of the view area.
// TODO: I don't think this messes up really long sustains, does it?
- var viewAreaTopMs:Float = scrollPositionInMs - (Conductor.measureLengthMs * 2); // Is 2 measures enough?
- var viewAreaBottomMs:Float = scrollPositionInMs + (Conductor.measureLengthMs * 2); // Is 2 measures enough?
+ var viewAreaTopMs:Float = scrollPositionInMs - (Conductor.instance.measureLengthMs * 2); // Is 2 measures enough?
+ var viewAreaBottomMs:Float = scrollPositionInMs + (Conductor.instance.measureLengthMs * 2); // Is 2 measures enough?
// Add notes that are now visible.
for (noteData in currentSongChartNoteData)
@@ -3296,14 +3355,14 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// PAGE UP = Jump up to nearest measure
if (pageUpKeyHandler.activated)
{
- var measureHeight:Float = GRID_SIZE * 4 * Conductor.beatsPerMeasure;
+ var measureHeight:Float = GRID_SIZE * 4 * Conductor.instance.beatsPerMeasure;
var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels;
var targetScrollPosition:Float = Math.floor(playheadPos / measureHeight) * measureHeight;
// If we would move less than one grid, instead move to the top of the previous measure.
var targetScrollAmount = Math.abs(targetScrollPosition - playheadPos);
if (targetScrollAmount < GRID_SIZE)
{
- targetScrollPosition -= GRID_SIZE * Constants.STEPS_PER_BEAT * Conductor.beatsPerMeasure;
+ targetScrollPosition -= GRID_SIZE * Constants.STEPS_PER_BEAT * Conductor.instance.beatsPerMeasure;
}
scrollAmount = targetScrollPosition - playheadPos;
@@ -3312,21 +3371,21 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
if (playbarButtonPressed == 'playbarBack')
{
playbarButtonPressed = '';
- scrollAmount = -GRID_SIZE * 4 * Conductor.beatsPerMeasure;
+ scrollAmount = -GRID_SIZE * 4 * Conductor.instance.beatsPerMeasure;
shouldPause = true;
}
// PAGE DOWN = Jump down to nearest measure
if (pageDownKeyHandler.activated)
{
- var measureHeight:Float = GRID_SIZE * 4 * Conductor.beatsPerMeasure;
+ var measureHeight:Float = GRID_SIZE * 4 * Conductor.instance.beatsPerMeasure;
var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels;
var targetScrollPosition:Float = Math.ceil(playheadPos / measureHeight) * measureHeight;
// If we would move less than one grid, instead move to the top of the next measure.
var targetScrollAmount = Math.abs(targetScrollPosition - playheadPos);
if (targetScrollAmount < GRID_SIZE)
{
- targetScrollPosition += GRID_SIZE * Constants.STEPS_PER_BEAT * Conductor.beatsPerMeasure;
+ targetScrollPosition += GRID_SIZE * Constants.STEPS_PER_BEAT * Conductor.instance.beatsPerMeasure;
}
scrollAmount = targetScrollPosition - playheadPos;
@@ -3335,7 +3394,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
if (playbarButtonPressed == 'playbarForward')
{
playbarButtonPressed = '';
- scrollAmount = GRID_SIZE * 4 * Conductor.beatsPerMeasure;
+ scrollAmount = GRID_SIZE * 4 * Conductor.instance.beatsPerMeasure;
shouldPause = true;
}
@@ -3538,10 +3597,10 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// The song position of the cursor, in steps.
var cursorFractionalStep:Float = cursorY / GRID_SIZE;
- var cursorMs:Float = Conductor.getStepTimeInMs(cursorFractionalStep);
+ var cursorMs:Float = Conductor.instance.getStepTimeInMs(cursorFractionalStep);
// Round the cursor step to the nearest snap quant.
var cursorSnappedStep:Float = Math.floor(cursorFractionalStep / noteSnapRatio) * noteSnapRatio;
- var cursorSnappedMs:Float = Conductor.getStepTimeInMs(cursorSnappedStep);
+ var cursorSnappedMs:Float = Conductor.instance.getStepTimeInMs(cursorSnappedStep);
// The direction value for the column at the cursor.
var cursorGridPos:Int = Math.floor(cursorX / GRID_SIZE);
@@ -3563,7 +3622,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// We released the mouse. Select the notes in the box.
var cursorFractionalStepStart:Float = cursorYStart / GRID_SIZE;
var cursorStepStart:Int = Math.floor(cursorFractionalStepStart);
- var cursorMsStart:Float = Conductor.getStepTimeInMs(cursorStepStart);
+ var cursorMsStart:Float = Conductor.instance.getStepTimeInMs(cursorStepStart);
var cursorColumnBase:Int = Math.floor(cursorX / GRID_SIZE);
var cursorColumnBaseStart:Int = Math.floor(cursorXStart / GRID_SIZE);
@@ -3799,11 +3858,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
var dragDistanceMs:Float = 0;
if (dragTargetNote != null && dragTargetNote.noteData != null)
{
- dragDistanceMs = Conductor.getStepTimeInMs(dragTargetNote.noteData.getStepTime() + dragDistanceSteps) - dragTargetNote.noteData.time;
+ dragDistanceMs = Conductor.instance.getStepTimeInMs(dragTargetNote.noteData.getStepTime() + dragDistanceSteps) - dragTargetNote.noteData.time;
}
else if (dragTargetEvent != null && dragTargetEvent.eventData != null)
{
- dragDistanceMs = Conductor.getStepTimeInMs(dragTargetEvent.eventData.getStepTime() + dragDistanceSteps) - dragTargetEvent.eventData.time;
+ dragDistanceMs = Conductor.instance.getStepTimeInMs(dragTargetEvent.eventData.getStepTime() + dragDistanceSteps) - dragTargetEvent.eventData.time;
}
var dragDistanceColumns:Int = dragTargetCurrentColumn;
@@ -3863,7 +3922,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
{
stepTime = dragTargetEvent.eventData.getStepTime();
}
- var dragDistanceSteps:Float = Conductor.getTimeInSteps(cursorSnappedMs).clamp(0, songLengthInSteps - (1 * noteSnapRatio)) - stepTime;
+ var dragDistanceSteps:Float = Conductor.instance.getTimeInSteps(cursorSnappedMs).clamp(0, songLengthInSteps - (1 * noteSnapRatio)) - stepTime;
var data:Int = 0;
var noteGridPos:Int = 0;
if (dragTargetNote != null && dragTargetNote.noteData != null)
@@ -3895,8 +3954,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Handle extending the note as you drag.
var stepTime:Float = inline currentPlaceNoteData.getStepTime();
- var dragLengthSteps:Float = Conductor.getTimeInSteps(cursorSnappedMs) - stepTime;
- var dragLengthMs:Float = dragLengthSteps * Conductor.stepLengthMs;
+ var dragLengthSteps:Float = Conductor.instance.getTimeInSteps(cursorSnappedMs) - stepTime;
+ var dragLengthMs:Float = dragLengthSteps * Conductor.instance.stepLengthMs;
var dragLengthPixels:Float = dragLengthSteps * GRID_SIZE;
if (gridGhostNote != null && gridGhostNote.noteData != null && gridGhostHoldNote != null)
@@ -4051,7 +4110,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
}
else
{
- // If we clicked and released outside the grid, do nothing.
+ // If we clicked and released outside the grid (or on HaxeUI), do nothing.
}
}
@@ -4357,7 +4416,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
if (playbarHeadLayout.playbarHead.value != songPosPercent) playbarHeadLayout.playbarHead.value = songPosPercent;
}
- var songPos:Float = Conductor.songPosition + Conductor.instrumentalOffset;
+ var songPos:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
var songPosSeconds:String = Std.string(Math.floor((Math.abs(songPos) / 1000) % 60)).lpad('0', 2);
var songPosMinutes:String = Std.string(Math.floor((Math.abs(songPos) / 1000) / 60)).lpad('0', 2);
if (songPos < 0) songPosMinutes = '-' + songPosMinutes;
@@ -4373,8 +4432,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
if (playbarSongRemaining.value != songRemainingString) playbarSongRemaining.value = songRemainingString;
playbarNoteSnap.text = '1/${noteSnapQuant}';
- playbarDifficulty.text = "Difficulty: " + selectedDifficulty.toTitleCase();
- playbarBPM.text = "BPM: " + Conductor.currentTimeChange.bpm;
+ playbarDifficulty.text = '${selectedDifficulty.toTitleCase()}';
+ // playbarBPM.text = 'BPM: ${(Conductor.currentTimeChange?.bpm ?? 0.0)}';
}
function handlePlayhead():Void
@@ -4413,11 +4472,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels;
var playheadPosFractionalStep:Float = playheadPos / GRID_SIZE / noteSnapRatio;
var playheadPosStep:Int = Std.int(Math.floor(playheadPosFractionalStep));
- var playheadPosSnappedMs:Float = playheadPosStep * Conductor.stepLengthMs * noteSnapRatio;
+ var playheadPosSnappedMs:Float = playheadPosStep * Conductor.instance.stepLengthMs * noteSnapRatio;
// Look for notes within 1 step of the playhead.
var notesAtPos:Array = SongDataUtils.getNotesInTimeRange(currentSongChartNoteData, playheadPosSnappedMs,
- playheadPosSnappedMs + Conductor.stepLengthMs * noteSnapRatio);
+ playheadPosSnappedMs + Conductor.instance.stepLengthMs * noteSnapRatio);
notesAtPos = SongDataUtils.getNotesWithData(notesAtPos, [column]);
if (notesAtPos.length == 0)
@@ -4616,9 +4675,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
else
{
var targetMs:Float = scrollPositionInMs + playheadPositionInMs;
- var targetStep:Float = Conductor.getTimeInSteps(targetMs);
+ var targetStep:Float = Conductor.instance.getTimeInSteps(targetMs);
var targetSnappedStep:Float = Math.floor(targetStep / noteSnapRatio) * noteSnapRatio;
- var targetSnappedMs:Float = Conductor.getStepTimeInMs(targetSnappedStep);
+ var targetSnappedMs:Float = Conductor.instance.getStepTimeInMs(targetSnappedStep);
targetSnappedMs;
}
performCommand(new PasteItemsCommand(targetMs));
@@ -4731,16 +4790,16 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
{
super.handleQuickWatch();
- FlxG.watch.addQuick('musicTime', audioInstTrack?.time ?? 0.0);
+ FlxG.watch.addQuick('musicTime', audioInstTrack?.time);
FlxG.watch.addQuick('scrollPosInPixels', scrollPositionInPixels);
FlxG.watch.addQuick('playheadPosInPixels', playheadPositionInPixels);
- 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);
+ 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);
}
function handlePostUpdate():Void
@@ -4758,7 +4817,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
*/
function testSongInPlayState(minimal:Bool = false):Void
{
- autoSave();
+ autoSave(true);
stopWelcomeMusic();
@@ -4776,6 +4835,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
return;
}
+ LogStyle.WARNING.openConsole = enabledDebuggerPopup;
+ LogStyle.ERROR.openConsole = enabledDebuggerPopup;
+
// TODO: Rework asset system so we can remove this.
switch (currentSongStage)
{
@@ -4959,7 +5021,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Remove any notes past the end of the song.
var songCutoffPointSteps:Float = songLengthInSteps - 0.1;
- var songCutoffPointMs:Float = Conductor.getStepTimeInMs(songCutoffPointSteps);
+ var songCutoffPointMs:Float = Conductor.instance.getStepTimeInMs(songCutoffPointSteps);
currentSongChartNoteData = SongDataUtils.clampSongNoteData(currentSongChartNoteData, 0.0, songCutoffPointMs);
currentSongChartEventData = SongDataUtils.clampSongEventData(currentSongChartEventData, 0.0, songCutoffPointMs);
@@ -5061,7 +5123,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
var prevDifficulty = availableDifficulties[availableDifficulties.length - 1];
selectedDifficulty = prevDifficulty;
- Conductor.mapTimeChanges(this.currentSongMetadata.timeChanges);
+ Conductor.instance.mapTimeChanges(this.currentSongMetadata.timeChanges);
refreshDifficultyTreeSelection();
this.refreshToolbox(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT);
@@ -5105,7 +5167,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
}
}
- this.success('Switch Difficulty', 'Switched difficulty to ${selectedDifficulty.toTitleCase()}');
+ // Removed this notification because you can see your difficulty in the playbar now.
+ // this.success('Switch Difficulty', 'Switched difficulty to ${selectedDifficulty.toTitleCase()}');
}
/**
@@ -5122,9 +5185,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// Update the songPosition in the audio tracks.
if (audioInstTrack != null)
{
- audioInstTrack.time = scrollPositionInMs + playheadPositionInMs - Conductor.instrumentalOffset;
+ audioInstTrack.time = scrollPositionInMs + playheadPositionInMs - Conductor.instance.instrumentalOffset;
// Update the songPosition in the Conductor.
- Conductor.update(audioInstTrack.time);
+ Conductor.instance.update(audioInstTrack.time);
if (audioVocalTrackGroup != null) audioVocalTrackGroup.time = audioInstTrack.time;
}
@@ -5184,6 +5247,20 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
this.persistentUpdate = true;
this.persistentDraw = true;
+ if (displayAutosavePopup)
+ {
+ displayAutosavePopup = false;
+ Toolkit.callLater(() -> {
+ var absoluteBackupsPath:String = Path.join([Sys.getCwd(), ChartEditorImportExportHandler.BACKUPS_PATH]);
+ this.infoWithActions('Auto-Save', 'Chart auto-saved to ${absoluteBackupsPath}.', [
+ {
+ text: "Take Me There",
+ callback: openBackupsFolder,
+ }
+ ]);
+ });
+ }
+
moveSongToScrollPosition();
fadeInWelcomeMusic(7, 10);
@@ -5305,6 +5382,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
// TODO: Only update the notes that have changed.
notePreview.erase();
notePreview.addNotes(currentSongChartNoteData, Std.int(songLengthInMs));
+ notePreview.addSelectedNotes(currentNoteSelection, Std.int(songLengthInMs));
notePreview.addEvents(currentSongChartEventData, Std.int(songLengthInMs));
}
@@ -5442,7 +5520,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
trace('ERROR: Instrumental track is null!');
}
- this.songLengthInMs = (audioInstTrack?.length ?? 1000.0) + Conductor.instrumentalOffset;
+ this.songLengthInMs = (audioInstTrack?.length ?? 1000.0) + Conductor.instance.instrumentalOffset;
// Many things get reset when song length changes.
healthIconsDirty = true;
diff --git a/source/funkin/ui/debug/charting/commands/ChangeStartingBPMCommand.hx b/source/funkin/ui/debug/charting/commands/ChangeStartingBPMCommand.hx
index d80dd7c38..ea821afa9 100644
--- a/source/funkin/ui/debug/charting/commands/ChangeStartingBPMCommand.hx
+++ b/source/funkin/ui/debug/charting/commands/ChangeStartingBPMCommand.hx
@@ -39,7 +39,7 @@ class ChangeStartingBPMCommand implements ChartEditorCommand
state.notePreviewViewportBoundsDirty = true;
state.scrollPositionInPixels = 0;
- Conductor.mapTimeChanges(state.currentSongMetadata.timeChanges);
+ Conductor.instance.mapTimeChanges(state.currentSongMetadata.timeChanges);
}
public function undo(state:ChartEditorState):Void
@@ -61,7 +61,7 @@ class ChangeStartingBPMCommand implements ChartEditorCommand
state.notePreviewViewportBoundsDirty = true;
state.scrollPositionInPixels = 0;
- Conductor.mapTimeChanges(state.currentSongMetadata.timeChanges);
+ Conductor.instance.mapTimeChanges(state.currentSongMetadata.timeChanges);
}
public function toString():String
diff --git a/source/funkin/ui/debug/charting/commands/MoveEventsCommand.hx b/source/funkin/ui/debug/charting/commands/MoveEventsCommand.hx
index efe9c25d5..8331ed397 100644
--- a/source/funkin/ui/debug/charting/commands/MoveEventsCommand.hx
+++ b/source/funkin/ui/debug/charting/commands/MoveEventsCommand.hx
@@ -33,7 +33,7 @@ class MoveEventsCommand implements ChartEditorCommand
{
// Clone the notes to prevent editing from affecting the history.
var resultEvent = event.clone();
- resultEvent.time = (resultEvent.time + offset).clamp(0, Conductor.getStepTimeInMs(state.songLengthInSteps - (1 * state.noteSnapRatio)));
+ resultEvent.time = (resultEvent.time + offset).clamp(0, Conductor.instance.getStepTimeInMs(state.songLengthInSteps - (1 * state.noteSnapRatio)));
movedEvents.push(resultEvent);
}
diff --git a/source/funkin/ui/debug/charting/commands/MoveItemsCommand.hx b/source/funkin/ui/debug/charting/commands/MoveItemsCommand.hx
index 53090a6cc..9fac8a0c4 100644
--- a/source/funkin/ui/debug/charting/commands/MoveItemsCommand.hx
+++ b/source/funkin/ui/debug/charting/commands/MoveItemsCommand.hx
@@ -41,7 +41,7 @@ class MoveItemsCommand implements ChartEditorCommand
{
// Clone the notes to prevent editing from affecting the history.
var resultNote = note.clone();
- resultNote.time = (resultNote.time + offset).clamp(0, Conductor.getStepTimeInMs(state.songLengthInSteps - (1 * state.noteSnapRatio)));
+ resultNote.time = (resultNote.time + offset).clamp(0, Conductor.instance.getStepTimeInMs(state.songLengthInSteps - (1 * state.noteSnapRatio)));
resultNote.data = ChartEditorState.gridColumnToNoteData((ChartEditorState.noteDataToGridColumn(resultNote.data) + columns).clamp(0,
ChartEditorState.STRUMLINE_SIZE * 2 - 1));
@@ -52,7 +52,7 @@ class MoveItemsCommand implements ChartEditorCommand
{
// Clone the notes to prevent editing from affecting the history.
var resultEvent = event.clone();
- resultEvent.time = (resultEvent.time + offset).clamp(0, Conductor.getStepTimeInMs(state.songLengthInSteps - (1 * state.noteSnapRatio)));
+ resultEvent.time = (resultEvent.time + offset).clamp(0, Conductor.instance.getStepTimeInMs(state.songLengthInSteps - (1 * state.noteSnapRatio)));
movedEvents.push(resultEvent);
}
diff --git a/source/funkin/ui/debug/charting/commands/MoveNotesCommand.hx b/source/funkin/ui/debug/charting/commands/MoveNotesCommand.hx
index 8bce747a1..0308d8fc8 100644
--- a/source/funkin/ui/debug/charting/commands/MoveNotesCommand.hx
+++ b/source/funkin/ui/debug/charting/commands/MoveNotesCommand.hx
@@ -34,7 +34,7 @@ class MoveNotesCommand implements ChartEditorCommand
{
// Clone the notes to prevent editing from affecting the history.
var resultNote = note.clone();
- resultNote.time = (resultNote.time + offset).clamp(0, Conductor.getStepTimeInMs(state.songLengthInSteps - (1 * state.noteSnapRatio)));
+ resultNote.time = (resultNote.time + offset).clamp(0, Conductor.instance.getStepTimeInMs(state.songLengthInSteps - (1 * state.noteSnapRatio)));
resultNote.data = ChartEditorState.gridColumnToNoteData((ChartEditorState.noteDataToGridColumn(resultNote.data) + columns).clamp(0,
ChartEditorState.STRUMLINE_SIZE * 2 - 1));
diff --git a/source/funkin/ui/debug/charting/commands/PasteItemsCommand.hx b/source/funkin/ui/debug/charting/commands/PasteItemsCommand.hx
index 75382da41..7e40bc49b 100644
--- a/source/funkin/ui/debug/charting/commands/PasteItemsCommand.hx
+++ b/source/funkin/ui/debug/charting/commands/PasteItemsCommand.hx
@@ -32,9 +32,9 @@ class PasteItemsCommand implements ChartEditorCommand
return;
}
- var stepEndOfSong:Float = Conductor.getTimeInSteps(state.songLengthInMs);
+ var stepEndOfSong:Float = Conductor.instance.getTimeInSteps(state.songLengthInMs);
var stepCutoff:Float = stepEndOfSong - 1.0;
- var msCutoff:Float = Conductor.getStepTimeInMs(stepCutoff);
+ var msCutoff:Float = Conductor.instance.getStepTimeInMs(stepCutoff);
addedNotes = SongDataUtils.offsetSongNoteData(currentClipboard.notes, Std.int(targetTimestamp));
addedNotes = SongDataUtils.clampSongNoteData(addedNotes, 0.0, msCutoff);
diff --git a/source/funkin/ui/debug/charting/components/ChartEditorNotePreview.hx b/source/funkin/ui/debug/charting/components/ChartEditorNotePreview.hx
index 09c99531d..598cbb544 100644
--- a/source/funkin/ui/debug/charting/components/ChartEditorNotePreview.hx
+++ b/source/funkin/ui/debug/charting/components/ChartEditorNotePreview.hx
@@ -80,11 +80,24 @@ class ChartEditorNotePreview extends FlxSprite
* @param notes The data for the notes.
* @param songLengthInMs The total length of the song in milliseconds.
*/
- public function addNotes(notes:Array, songLengthInMs:Int, ?isSelection:Bool = false):Void
+ public function addNotes(notes:Array, songLengthInMs:Int):Void
{
for (note in notes)
{
- addNote(note, songLengthInMs, isSelection);
+ addNote(note, songLengthInMs, false);
+ }
+ }
+
+ /**
+ * Add an array of selected notes to the preview.
+ * @param notes The data for the notes.
+ * @param songLengthInMs The total length of the song in milliseconds.
+ */
+ public function addSelectedNotes(notes:Array, songLengthInMs:Int):Void
+ {
+ for (note in notes)
+ {
+ addNote(note, songLengthInMs, true);
}
}
diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorAboutDialog.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorAboutDialog.hx
index e6f57c49f..8b55be540 100644
--- a/source/funkin/ui/debug/charting/dialogs/ChartEditorAboutDialog.hx
+++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorAboutDialog.hx
@@ -5,14 +5,14 @@ import funkin.ui.debug.charting.dialogs.ChartEditorBaseDialog.DialogParams;
@:build(haxe.ui.ComponentBuilder.build("assets/exclude/data/ui/chart-editor/dialogs/about.xml"))
class ChartEditorAboutDialog extends ChartEditorBaseDialog
{
- public function new(state2:ChartEditorState, params2:DialogParams)
+ public function new(chartEditorState2:ChartEditorState, params2:DialogParams)
{
- super(state2, params2);
+ super(chartEditorState2, params2);
}
- public static function build(state:ChartEditorState, ?closable:Bool, ?modal:Bool):ChartEditorAboutDialog
+ public static function build(chartEditorState:ChartEditorState, ?closable:Bool, ?modal:Bool):ChartEditorAboutDialog
{
- var dialog = new ChartEditorAboutDialog(state,
+ var dialog = new ChartEditorAboutDialog(chartEditorState,
{
closable: closable ?? true,
modal: modal ?? true
diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx
index 6f76e543e..5b7cb15e1 100644
--- a/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx
+++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseDialog.hx
@@ -11,16 +11,16 @@ import haxe.ui.core.Component;
@:access(funkin.ui.debug.charting.ChartEditorState)
class ChartEditorBaseDialog extends Dialog
{
- var state:ChartEditorState;
+ var chartEditorState:ChartEditorState;
var params:DialogParams;
var locked:Bool = false;
- public function new(state:ChartEditorState, params:DialogParams)
+ public function new(chartEditorState:ChartEditorState, params:DialogParams)
{
super();
- this.state = state;
+ this.chartEditorState = chartEditorState;
this.params = params;
this.destroyOnClose = true;
@@ -47,7 +47,7 @@ class ChartEditorBaseDialog extends Dialog
*/
public function onClose(event:DialogEvent):Void
{
- state.isHaxeUIDialogOpen = false;
+ chartEditorState.isHaxeUIDialogOpen = false;
}
/**
diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseMenu.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseMenu.hx
index cb4cb447b..19ca2535c 100644
--- a/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseMenu.hx
+++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorBaseMenu.hx
@@ -11,13 +11,13 @@ import haxe.ui.containers.menus.Menu;
@:access(funkin.ui.debug.charting.ChartEditorState)
class ChartEditorBaseMenu extends Menu
{
- var state:ChartEditorState;
+ var chartEditorState:ChartEditorState;
- public function new(state:ChartEditorState)
+ public function new(chartEditorState:ChartEditorState)
{
super();
- this.state = state;
+ this.chartEditorState = chartEditorState;
// this.destroyOnClose = true;
}
diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx
index d7e9c259b..eb60cb6db 100644
--- a/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx
+++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorCharacterIconSelectorMenu.hx
@@ -24,9 +24,9 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
public var charSelectScroll:ScrollView;
public var charIconName:Label;
- public function new(state2:ChartEditorState, charType:CharacterType, lockPosition:Bool = false)
+ public function new(chartEditorState2:ChartEditorState, charType:CharacterType, lockPosition:Bool = false)
{
- super(state2);
+ super(chartEditorState2);
initialize(charType, lockPosition);
this.alpha = 0;
@@ -38,17 +38,17 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
{
var currentCharId:String = switch (charType)
{
- case BF: state.currentSongMetadata.playData.characters.player;
- case GF: state.currentSongMetadata.playData.characters.girlfriend;
- case DAD: state.currentSongMetadata.playData.characters.opponent;
+ case BF: chartEditorState.currentSongMetadata.playData.characters.player;
+ case GF: chartEditorState.currentSongMetadata.playData.characters.girlfriend;
+ case DAD: chartEditorState.currentSongMetadata.playData.characters.opponent;
default: throw 'Invalid charType: ' + charType;
};
// Position this menu.
var targetHealthIcon:Null = switch (charType)
{
- case BF: state.healthIconBF;
- case DAD: state.healthIconDad;
+ case BF: chartEditorState.healthIconBF;
+ case DAD: chartEditorState.healthIconDad;
default: null;
};
@@ -101,14 +101,14 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
charButton.onClick = _ -> {
switch (charType)
{
- case BF: state.currentSongMetadata.playData.characters.player = charId;
- case GF: state.currentSongMetadata.playData.characters.girlfriend = charId;
- case DAD: state.currentSongMetadata.playData.characters.opponent = charId;
+ case BF: chartEditorState.currentSongMetadata.playData.characters.player = charId;
+ case GF: chartEditorState.currentSongMetadata.playData.characters.girlfriend = charId;
+ case DAD: chartEditorState.currentSongMetadata.playData.characters.opponent = charId;
default: throw 'Invalid charType: ' + charType;
};
- state.healthIconsDirty = true;
- state.refreshToolbox(ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT);
+ chartEditorState.healthIconsDirty = true;
+ chartEditorState.refreshToolbox(ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT);
};
charButton.onMouseOver = _ -> {
@@ -123,9 +123,9 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
charIconName.text = defaultText;
}
- public static function build(state2:ChartEditorState, charType:CharacterType, lockPosition:Bool = false):ChartEditorCharacterIconSelectorMenu
+ public static function build(chartEditorState:ChartEditorState, charType:CharacterType, lockPosition:Bool = false):ChartEditorCharacterIconSelectorMenu
{
- var menu = new ChartEditorCharacterIconSelectorMenu(state2, charType, lockPosition);
+ var menu = new ChartEditorCharacterIconSelectorMenu(chartEditorState, charType, lockPosition);
Screen.instance.addComponent(menu);
diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx
index 4b7a950be..5b84148c6 100644
--- a/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx
+++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorUploadChartDialog.hx
@@ -64,12 +64,12 @@ class ChartEditorUploadChartDialog extends ChartEditorBaseDialog
if (event.button != DialogButton.APPLY && !this.closable)
{
// User cancelled the wizard! Back to the welcome dialog.
- state.openWelcomeDialog(this.closable);
+ chartEditorState.openWelcomeDialog(this.closable);
}
for (dropTarget in dropHandlers)
{
- state.removeDropHandler(dropTarget);
+ chartEditorState.removeDropHandler(dropTarget);
}
}
@@ -111,20 +111,21 @@ class ChartEditorUploadChartDialog extends ChartEditorBaseDialog
try
{
- var result:Null> = ChartEditorImportExportHandler.loadFromFNFCPath(state, path.toString());
+ var result:Null> = ChartEditorImportExportHandler.loadFromFNFCPath(chartEditorState, path.toString());
if (result != null)
{
- state.success('Loaded Chart', result.length == 0 ? 'Loaded chart (${path.toString()})' : 'Loaded chart (${path.toString()})\n${result.join("\n")}');
+ chartEditorState.success('Loaded Chart',
+ result.length == 0 ? 'Loaded chart (${path.toString()})' : 'Loaded chart (${path.toString()})\n${result.join("\n")}');
this.hideDialog(DialogButton.APPLY);
}
else
{
- state.failure('Failed to Load Chart', 'Failed to load chart (${path.toString()})');
+ chartEditorState.failure('Failed to Load Chart', 'Failed to load chart (${path.toString()})');
}
}
catch (err)
{
- state.failure('Failed to Load Chart', 'Failed to load chart (${path.toString()}): ${err}');
+ chartEditorState.failure('Failed to Load Chart', 'Failed to load chart (${path.toString()}): ${err}');
}
}
@@ -139,19 +140,19 @@ class ChartEditorUploadChartDialog extends ChartEditorBaseDialog
{
try
{
- var result:Null> = ChartEditorImportExportHandler.loadFromFNFC(state, selectedFile.bytes);
+ var result:Null> = ChartEditorImportExportHandler.loadFromFNFC(chartEditorState, selectedFile.bytes);
if (result != null)
{
- state.success('Loaded Chart',
+ chartEditorState.success('Loaded Chart',
result.length == 0 ? 'Loaded chart (${selectedFile.name})' : 'Loaded chart (${selectedFile.name})\n${result.join("\n")}');
- if (selectedFile.fullPath != null) state.currentWorkingFilePath = selectedFile.fullPath;
+ if (selectedFile.fullPath != null) chartEditorState.currentWorkingFilePath = selectedFile.fullPath;
this.hideDialog(DialogButton.APPLY);
}
}
catch (err)
{
- state.failure('Failed to Load Chart', 'Failed to load chart (${selectedFile.name}): ${err}');
+ chartEditorState.failure('Failed to Load Chart', 'Failed to load chart (${selectedFile.name}): ${err}');
}
}
}
diff --git a/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx b/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx
index 2a30c7d9e..7539b9725 100644
--- a/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx
+++ b/source/funkin/ui/debug/charting/dialogs/ChartEditorWelcomeDialog.hx
@@ -41,26 +41,26 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
// Add items to the Recent Charts list
#if sys
- for (chartPath in state.previousWorkingFilePaths)
+ for (chartPath in chartEditorState.previousWorkingFilePaths)
{
if (chartPath == null) continue;
- this.addRecentFilePath(state, chartPath);
+ this.addRecentFilePath(chartEditorState, chartPath);
}
#else
this.addHTML5RecentFileMessage();
#end
// Add items to the Load From Template list
- this.buildTemplateSongList(state);
+ this.buildTemplateSongList(chartEditorState);
}
/**
* @param state The current state of the chart editor.
* @return A newly created `ChartEditorWelcomeDialog`.
*/
- public static function build(state:ChartEditorState, ?closable:Bool, ?modal:Bool):ChartEditorWelcomeDialog
+ public static function build(chartEditorState:ChartEditorState, ?closable:Bool, ?modal:Bool):ChartEditorWelcomeDialog
{
- var dialog = new ChartEditorWelcomeDialog(state,
+ var dialog = new ChartEditorWelcomeDialog(chartEditorState,
{
closable: closable ?? false,
modal: modal ?? true
@@ -102,12 +102,12 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
var result:Null> = ChartEditorImportExportHandler.loadFromFNFCPath(state, chartPath);
if (result != null)
{
- state.success('Loaded Chart',
+ chartEditorState.success('Loaded Chart',
result.length == 0 ? 'Loaded chart (${chartPath.toString()})' : 'Loaded chart (${chartPath.toString()})\n${result.join("\n")}');
}
else
{
- state.error('Failed to Load Chart', 'Failed to load chart (${chartPath.toString()})');
+ chartEditorState.error('Failed to Load Chart', 'Failed to load chart (${chartPath.toString()})');
}
}
@@ -157,7 +157,7 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
this.hideDialog(DialogButton.CANCEL);
// Load song from template
- state.loadSongAsTemplate(targetSongId);
+ chartEditorState.loadSongAsTemplate(targetSongId);
});
}
}
@@ -184,7 +184,7 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
this.hideDialog(DialogButton.CANCEL);
// Open the "Open Chart" dialog
- state.openBrowseFNFC(false);
+ chartEditorState.openBrowseFNFC(false);
}
/**
@@ -199,7 +199,7 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
//
// Create Song Wizard
//
- state.openCreateSongWizardBasicOnly(false);
+ chartEditorState.openCreateSongWizardBasicOnly(false);
}
/**
@@ -214,7 +214,7 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
//
// Create Song Wizard
//
- state.openCreateSongWizardErectOnly(false);
+ chartEditorState.openCreateSongWizardErectOnly(false);
}
/**
@@ -229,7 +229,7 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
//
// Create Song Wizard
//
- state.openCreateSongWizardBasicErect(false);
+ chartEditorState.openCreateSongWizardBasicErect(false);
}
/**
@@ -242,6 +242,6 @@ class ChartEditorWelcomeDialog extends ChartEditorBaseDialog
this.hideDialog(DialogButton.CANCEL);
// Open the "Import Chart" dialog
- state.openImportChartWizard('legacy', false);
+ chartEditorState.openImportChartWizard('legacy', false);
}
}
diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx
index 272291a94..2ef3fd683 100644
--- a/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx
+++ b/source/funkin/ui/debug/charting/handlers/ChartEditorAudioHandler.hx
@@ -28,11 +28,11 @@ class ChartEditorAudioHandler
* @param instId The instrumental this vocal track will be for.
* @return Success or failure.
*/
- public static function loadVocalsFromPath(state:ChartEditorState, path:Path, charId:String, instId:String = ''):Bool
+ public static function loadVocalsFromPath(state:ChartEditorState, path:Path, charId:String, instId:String = '', wipeFirst:Bool = false):Bool
{
#if sys
var fileBytes:Bytes = sys.io.File.getBytes(path.toString());
- return loadVocalsFromBytes(state, fileBytes, charId, instId);
+ return loadVocalsFromBytes(state, fileBytes, charId, instId, wipeFirst);
#else
trace("[WARN] This platform can't load audio from a file path, you'll need to fetch the bytes some other way.");
return false;
@@ -47,12 +47,12 @@ class ChartEditorAudioHandler
* @param instId The instrumental this vocal track will be for.
* @return Success or failure.
*/
- public static function loadVocalsFromAsset(state:ChartEditorState, path:String, charId:String, instId:String = ''):Bool
+ public static function loadVocalsFromAsset(state:ChartEditorState, path:String, charId:String, instId:String = '', wipeFirst:Bool = false):Bool
{
var trackData:Null = Assets.getBytes(path);
if (trackData != null)
{
- return loadVocalsFromBytes(state, trackData, charId, instId);
+ return loadVocalsFromBytes(state, trackData, charId, instId, wipeFirst);
}
return false;
}
@@ -63,10 +63,12 @@ class ChartEditorAudioHandler
* @param bytes The audio byte data.
* @param charId The character this vocal track will be for.
* @param instId The instrumental this vocal track will be for.
+ * @param wipeFirst Whether to wipe the existing vocal data before loading.
*/
- public static function loadVocalsFromBytes(state:ChartEditorState, bytes:Bytes, charId:String, instId:String = ''):Bool
+ public static function loadVocalsFromBytes(state:ChartEditorState, bytes:Bytes, charId:String, instId:String = '', wipeFirst:Bool = false):Bool
{
var trackId:String = '${charId}${instId == '' ? '' : '-${instId}'}';
+ if (wipeFirst) wipeVocalData(state);
state.audioVocalTrackData.set(trackId, bytes);
return true;
}
@@ -78,11 +80,11 @@ class ChartEditorAudioHandler
* @param instId The instrumental this vocal track will be for.
* @return Success or failure.
*/
- public static function loadInstFromPath(state:ChartEditorState, path:Path, instId:String = ''):Bool
+ public static function loadInstFromPath(state:ChartEditorState, path:Path, instId:String = '', wipeFirst:Bool = false):Bool
{
#if sys
var fileBytes:Bytes = sys.io.File.getBytes(path.toString());
- return loadInstFromBytes(state, fileBytes, instId);
+ return loadInstFromBytes(state, fileBytes, instId, wipeFirst);
#else
trace("[WARN] This platform can't load audio from a file path, you'll need to fetch the bytes some other way.");
return false;
@@ -96,12 +98,12 @@ class ChartEditorAudioHandler
* @param instId The instrumental this vocal track will be for.
* @return Success or failure.
*/
- public static function loadInstFromAsset(state:ChartEditorState, path:String, instId:String = ''):Bool
+ public static function loadInstFromAsset(state:ChartEditorState, path:String, instId:String = '', wipeFirst:Bool = false):Bool
{
var trackData:Null = Assets.getBytes(path);
if (trackData != null)
{
- return loadInstFromBytes(state, trackData, instId);
+ return loadInstFromBytes(state, trackData, instId, wipeFirst);
}
return false;
}
@@ -113,9 +115,10 @@ class ChartEditorAudioHandler
* @param charId The character this vocal track will be for.
* @param instId The instrumental this vocal track will be for.
*/
- public static function loadInstFromBytes(state:ChartEditorState, bytes:Bytes, instId:String = ''):Bool
+ public static function loadInstFromBytes(state:ChartEditorState, bytes:Bytes, instId:String = '', wipeFirst:Bool = false):Bool
{
if (instId == '') instId = 'default';
+ if (wipeFirst) wipeInstrumentalData(state);
state.audioInstTrackData.set(instId, bytes);
return true;
}
@@ -127,9 +130,9 @@ class ChartEditorAudioHandler
stopExistingVocals(state);
result = playVocals(state, BF, playerId, instId);
- if (!result) return false;
+ // if (!result) return false;
result = playVocals(state, DAD, opponentId, instId);
- if (!result) return false;
+ // if (!result) return false;
return true;
}
@@ -182,7 +185,7 @@ class ChartEditorAudioHandler
state.audioVocalTrackGroup.addPlayerVoice(vocalTrack);
state.audioVisGroup.addPlayerVis(vocalTrack);
state.audioVisGroup.playerVis.x = 885;
- state.audioVisGroup.playerVis.realtimeVisLenght = Conductor.getStepTimeInMs(16) * 0.00195;
+ state.audioVisGroup.playerVis.realtimeVisLenght = Conductor.instance.getStepTimeInMs(16) * 0.00195;
state.audioVisGroup.playerVis.daHeight = (ChartEditorState.GRID_SIZE) * 16;
state.audioVisGroup.playerVis.detail = 1;
@@ -193,7 +196,7 @@ class ChartEditorAudioHandler
state.audioVisGroup.addOpponentVis(vocalTrack);
state.audioVisGroup.opponentVis.x = 435;
- state.audioVisGroup.opponentVis.realtimeVisLenght = Conductor.getStepTimeInMs(16) * 0.00195;
+ state.audioVisGroup.opponentVis.realtimeVisLenght = Conductor.instance.getStepTimeInMs(16) * 0.00195;
state.audioVisGroup.opponentVis.daHeight = (ChartEditorState.GRID_SIZE) * 16;
state.audioVisGroup.opponentVis.detail = 1;
diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx
index 666b3656c..1d53dfebd 100644
--- a/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx
+++ b/source/funkin/ui/debug/charting/handlers/ChartEditorDialogHandler.hx
@@ -684,8 +684,11 @@ class ChartEditorDialogHandler
state.songMetadata.set(targetVariation, newSongMetadata);
- Conductor.instrumentalOffset = state.currentInstrumentalOffset; // Loads from the metadata.
- Conductor.mapTimeChanges(state.currentSongMetadata.timeChanges);
+ Conductor.instance.instrumentalOffset = state.currentInstrumentalOffset; // Loads from the metadata.
+ Conductor.instance.mapTimeChanges(state.currentSongMetadata.timeChanges);
+
+ state.selectedVariation = Constants.DEFAULT_VARIATION;
+ state.selectedDifficulty = state.availableDifficulties[0];
state.difficultySelectDirty = true;
@@ -755,14 +758,9 @@ class ChartEditorDialogHandler
trace('Selected file: $pathStr');
var path:Path = new Path(pathStr);
- if (!hasClearedVocals)
+ if (state.loadVocalsFromPath(path, charKey, instId, !hasClearedVocals))
{
hasClearedVocals = true;
- state.stopExistingVocals();
- }
-
- if (state.loadVocalsFromPath(path, charKey, instId))
- {
// Tell the user the load was successful.
state.success('Loaded Vocals', 'Loaded vocals for $charName (${path.file}.${path.ext}), variation ${state.selectedVariation}');
#if FILE_DROP_SUPPORTED
@@ -796,13 +794,10 @@ class ChartEditorDialogHandler
if (selectedFile != null && selectedFile.bytes != null)
{
trace('Selected file: ' + selectedFile.name);
- if (!hasClearedVocals)
+
+ if (state.loadVocalsFromBytes(selectedFile.bytes, charKey, instId, !hasClearedVocals))
{
hasClearedVocals = true;
- state.stopExistingVocals();
- }
- if (state.loadVocalsFromBytes(selectedFile.bytes, charKey, instId))
- {
// Tell the user the load was successful.
state.success('Loaded Vocals', 'Loaded vocals for $charName (${selectedFile.name}), variation ${state.selectedVariation}');
diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx
index d8c893d4d..a38916c3b 100644
--- a/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx
+++ b/source/funkin/ui/debug/charting/handlers/ChartEditorImportExportHandler.hx
@@ -115,9 +115,9 @@ class ChartEditorImportExportHandler
state.songMetadata = newSongMetadata;
state.songChartData = newSongChartData;
- Conductor.forceBPM(null); // Disable the forced BPM.
- Conductor.instrumentalOffset = state.currentInstrumentalOffset; // Loads from the metadata.
- Conductor.mapTimeChanges(state.currentSongMetadata.timeChanges);
+ Conductor.instance.forceBPM(null); // Disable the forced BPM.
+ Conductor.instance.instrumentalOffset = state.currentInstrumentalOffset; // Loads from the metadata.
+ Conductor.instance.mapTimeChanges(state.currentSongMetadata.timeChanges);
state.notePreviewDirty = true;
state.notePreviewViewportBoundsDirty = true;
@@ -316,6 +316,8 @@ class ChartEditorImportExportHandler
public static function getLatestBackupPath():Null
{
#if sys
+ if (!sys.FileSystem.exists(BACKUPS_PATH)) sys.FileSystem.createDirectory(BACKUPS_PATH);
+
var entries:Array = sys.FileSystem.readDirectory(BACKUPS_PATH);
entries.sort(SortUtil.alphabetically);
@@ -414,16 +416,34 @@ class ChartEditorImportExportHandler
]);
// We have to force write because the program will die before the save dialog is closed.
trace('Force exporting to $targetPath...');
- FileUtil.saveFilesAsZIPToPath(zipEntries, targetPath, targetMode);
- if (onSaveCb != null) onSaveCb(targetPath);
+ try
+ {
+ FileUtil.saveFilesAsZIPToPath(zipEntries, targetPath, targetMode);
+ // On success.
+ if (onSaveCb != null) onSaveCb(targetPath);
+ }
+ catch (e)
+ {
+ // On failure.
+ if (onCancelCb != null) onCancelCb();
+ }
}
else
{
// Force write since we know what file the user wants to overwrite.
trace('Force exporting to $targetPath...');
- FileUtil.saveFilesAsZIPToPath(zipEntries, targetPath, targetMode);
- state.saveDataDirty = false;
- if (onSaveCb != null) onSaveCb(targetPath);
+ try
+ {
+ // On success.
+ FileUtil.saveFilesAsZIPToPath(zipEntries, targetPath, targetMode);
+ state.saveDataDirty = false;
+ if (onSaveCb != null) onSaveCb(targetPath);
+ }
+ catch (e)
+ {
+ // On failure.
+ if (onCancelCb != null) onCancelCb();
+ }
}
}
else
diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx
index 4197ebdd3..1625c53bc 100644
--- a/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx
+++ b/source/funkin/ui/debug/charting/handlers/ChartEditorThemeHandler.hx
@@ -125,7 +125,7 @@ class ChartEditorThemeHandler
// 2 * (Strumline Size) + 1 grid squares wide, by (4 * quarter notes per measure) grid squares tall.
// This gets reused to fill the screen.
var gridWidth:Int = Std.int(ChartEditorState.GRID_SIZE * TOTAL_COLUMN_COUNT);
- var gridHeight:Int = Std.int(ChartEditorState.GRID_SIZE * Conductor.stepsPerMeasure);
+ var gridHeight:Int = Std.int(ChartEditorState.GRID_SIZE * Conductor.instance.stepsPerMeasure);
state.gridBitmap = FlxGridOverlay.createGrid(ChartEditorState.GRID_SIZE, ChartEditorState.GRID_SIZE, gridWidth, gridHeight, true, gridColor1, gridColor2);
// Selection borders
@@ -142,7 +142,7 @@ class ChartEditorThemeHandler
selectionBorderColor);
// Selection borders horizontally along the middle.
- for (i in 1...(Conductor.stepsPerMeasure))
+ for (i in 1...(Conductor.instance.stepsPerMeasure))
{
state.gridBitmap.fillRect(new Rectangle(0, (ChartEditorState.GRID_SIZE * i) - (ChartEditorState.GRID_SELECTION_BORDER_WIDTH / 2),
state.gridBitmap.width, ChartEditorState.GRID_SELECTION_BORDER_WIDTH),
@@ -197,9 +197,9 @@ class ChartEditorThemeHandler
};
// Selection borders horizontally in the middle.
- for (i in 1...(Conductor.stepsPerMeasure))
+ for (i in 1...(Conductor.instance.stepsPerMeasure))
{
- if ((i % Conductor.beatsPerMeasure) == 0)
+ if ((i % Conductor.instance.beatsPerMeasure) == 0)
{
state.gridBitmap.fillRect(new Rectangle(0, (ChartEditorState.GRID_SIZE * i) - (GRID_BEAT_DIVIDER_WIDTH / 2), state.gridBitmap.width,
GRID_BEAT_DIVIDER_WIDTH),
diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx
index a9a9c375d..98d04887d 100644
--- a/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx
+++ b/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx
@@ -488,6 +488,16 @@ class ChartEditorToolboxHandler
state.playtestStartTime = checkboxStartTime.selected;
};
+ var checkboxDebugger:Null = toolbox.findComponent('playtestDebuggerCheckbox', CheckBox);
+
+ if (checkboxDebugger == null) throw 'ChartEditorToolboxHandler.buildToolboxPlaytestPropertiesLayout() - Could not find playtestDebuggerCheckbox component.';
+
+ state.enabledDebuggerPopup = checkboxDebugger.selected;
+
+ checkboxDebugger.onClick = _ -> {
+ state.enabledDebuggerPopup = checkboxDebugger.selected;
+ };
+
return toolbox;
}
diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorBaseToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorBaseToolbox.hx
index c4c532205..7df06c249 100644
--- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorBaseToolbox.hx
+++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorBaseToolbox.hx
@@ -12,13 +12,13 @@ import haxe.ui.core.Component;
@:access(funkin.ui.debug.charting.ChartEditorState)
class ChartEditorBaseToolbox extends CollapsibleDialog
{
- var state:ChartEditorState;
+ var chartEditorState:ChartEditorState;
- private function new(state:ChartEditorState)
+ private function new(chartEditorState:ChartEditorState)
{
super();
- this.state = state;
+ this.chartEditorState = chartEditorState;
}
/**
diff --git a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx
index e0ee4aca3..700e5ec6a 100644
--- a/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx
+++ b/source/funkin/ui/debug/charting/toolboxes/ChartEditorMetadataToolbox.hx
@@ -40,9 +40,9 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
var frameVariation:Frame;
var frameDifficulty:Frame;
- public function new(state2:ChartEditorState)
+ public function new(chartEditorState2:ChartEditorState)
{
- super(state2);
+ super(chartEditorState2);
initialize();
@@ -51,7 +51,7 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
function onClose(event:UIEvent)
{
- state.menubarItemToggleToolboxMetadata.selected = false;
+ chartEditorState.menubarItemToggleToolboxMetadata.selected = false;
}
function initialize():Void
@@ -67,11 +67,11 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
if (valid)
{
inputSongName.removeClass('invalid-value');
- state.currentSongMetadata.songName = event.target.text;
+ chartEditorState.currentSongMetadata.songName = event.target.text;
}
else
{
- state.currentSongMetadata.songName = '';
+ chartEditorState.currentSongMetadata.songName = '';
}
};
@@ -81,11 +81,11 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
if (valid)
{
inputSongArtist.removeClass('invalid-value');
- state.currentSongMetadata.artist = event.target.text;
+ chartEditorState.currentSongMetadata.artist = event.target.text;
}
else
{
- state.currentSongMetadata.artist = '';
+ chartEditorState.currentSongMetadata.artist = '';
}
};
@@ -94,41 +94,41 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
if (valid)
{
- state.currentSongMetadata.playData.stage = event.data.id;
+ chartEditorState.currentSongMetadata.playData.stage = event.data.id;
}
};
- var startingValueStage = ChartEditorDropdowns.populateDropdownWithStages(inputStage, state.currentSongMetadata.playData.stage);
+ var startingValueStage = ChartEditorDropdowns.populateDropdownWithStages(inputStage, chartEditorState.currentSongMetadata.playData.stage);
inputStage.value = startingValueStage;
inputNoteStyle.onChange = function(event:UIEvent) {
if (event.data?.id == null) return;
- state.currentSongNoteStyle = event.data.id;
+ chartEditorState.currentSongNoteStyle = event.data.id;
};
inputBPM.onChange = function(event:UIEvent) {
if (event.value == null || event.value <= 0) return;
// Use a command so we can undo/redo this action.
- var startingBPM = state.currentSongMetadata.timeChanges[0].bpm;
+ var startingBPM = chartEditorState.currentSongMetadata.timeChanges[0].bpm;
if (event.value != startingBPM)
{
- state.performCommand(new ChangeStartingBPMCommand(event.value));
+ chartEditorState.performCommand(new ChangeStartingBPMCommand(event.value));
}
};
inputOffsetInst.onChange = function(event:UIEvent) {
if (event.value == null) return;
- state.currentInstrumentalOffset = event.value;
- Conductor.instrumentalOffset = event.value;
+ chartEditorState.currentInstrumentalOffset = event.value;
+ Conductor.instance.instrumentalOffset = event.value;
// Update song length.
- state.songLengthInMs = (state.audioInstTrack?.length ?? 1000.0) + Conductor.instrumentalOffset;
+ chartEditorState.songLengthInMs = (chartEditorState.audioInstTrack?.length ?? 1000.0) + Conductor.instance.instrumentalOffset;
};
inputOffsetVocal.onChange = function(event:UIEvent) {
if (event.value == null) return;
- state.currentSongMetadata.offsets.setVocalOffset(state.currentSongMetadata.playData.characters.player, event.value);
+ chartEditorState.currentSongMetadata.offsets.setVocalOffset(chartEditorState.currentSongMetadata.playData.characters.player, event.value);
};
inputScrollSpeed.onChange = function(event:UIEvent) {
var valid:Bool = event.target.value != null && event.target.value > 0;
@@ -136,25 +136,25 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
if (valid)
{
inputScrollSpeed.removeClass('invalid-value');
- state.currentSongChartScrollSpeed = event.target.value;
+ chartEditorState.currentSongChartScrollSpeed = event.target.value;
}
else
{
- state.currentSongChartScrollSpeed = 1.0;
+ chartEditorState.currentSongChartScrollSpeed = 1.0;
}
- labelScrollSpeed.text = 'Scroll Speed: ${state.currentSongChartScrollSpeed}x';
+ labelScrollSpeed.text = 'Scroll Speed: ${chartEditorState.currentSongChartScrollSpeed}x';
};
buttonCharacterOpponent.onClick = function(_) {
- state.openCharacterDropdown(CharacterType.DAD, false);
+ chartEditorState.openCharacterDropdown(CharacterType.DAD, false);
};
buttonCharacterGirlfriend.onClick = function(_) {
- state.openCharacterDropdown(CharacterType.GF, false);
+ chartEditorState.openCharacterDropdown(CharacterType.GF, false);
};
buttonCharacterPlayer.onClick = function(_) {
- state.openCharacterDropdown(CharacterType.BF, false);
+ chartEditorState.openCharacterDropdown(CharacterType.BF, false);
};
refresh();
@@ -162,17 +162,17 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
public override function refresh():Void
{
- inputSongName.value = state.currentSongMetadata.songName;
- inputSongArtist.value = state.currentSongMetadata.artist;
- inputStage.value = state.currentSongMetadata.playData.stage;
- inputNoteStyle.value = state.currentSongMetadata.playData.noteStyle;
- inputBPM.value = state.currentSongMetadata.timeChanges[0].bpm;
- inputScrollSpeed.value = state.currentSongChartScrollSpeed;
- labelScrollSpeed.text = 'Scroll Speed: ${state.currentSongChartScrollSpeed}x';
- frameVariation.text = 'Variation: ${state.selectedVariation.toTitleCase()}';
- frameDifficulty.text = 'Difficulty: ${state.selectedDifficulty.toTitleCase()}';
+ inputSongName.value = chartEditorState.currentSongMetadata.songName;
+ inputSongArtist.value = chartEditorState.currentSongMetadata.artist;
+ inputStage.value = chartEditorState.currentSongMetadata.playData.stage;
+ inputNoteStyle.value = chartEditorState.currentSongMetadata.playData.noteStyle;
+ inputBPM.value = chartEditorState.currentSongMetadata.timeChanges[0].bpm;
+ inputScrollSpeed.value = chartEditorState.currentSongChartScrollSpeed;
+ labelScrollSpeed.text = 'Scroll Speed: ${chartEditorState.currentSongChartScrollSpeed}x';
+ frameVariation.text = 'Variation: ${chartEditorState.selectedVariation.toTitleCase()}';
+ frameDifficulty.text = 'Difficulty: ${chartEditorState.selectedDifficulty.toTitleCase()}';
- var stageId:String = state.currentSongMetadata.playData.stage;
+ var stageId:String = chartEditorState.currentSongMetadata.playData.stage;
var stageData:Null = StageDataParser.parseStageData(stageId);
if (inputStage != null)
{
@@ -183,21 +183,45 @@ class ChartEditorMetadataToolbox extends ChartEditorBaseToolbox
var LIMIT = 6;
- var charDataOpponent:CharacterData = CharacterDataParser.fetchCharacterData(state.currentSongMetadata.playData.characters.opponent);
- buttonCharacterOpponent.icon = CharacterDataParser.getCharPixelIconAsset(state.currentSongMetadata.playData.characters.opponent);
- buttonCharacterOpponent.text = charDataOpponent.name.length > LIMIT ? '${charDataOpponent.name.substr(0, LIMIT)}.' : '${charDataOpponent.name}';
+ var charDataOpponent:Null = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.opponent);
+ if (charDataOpponent != null)
+ {
+ buttonCharacterOpponent.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.opponent);
+ buttonCharacterOpponent.text = charDataOpponent.name.length > LIMIT ? '${charDataOpponent.name.substr(0, LIMIT)}.' : '${charDataOpponent.name}';
+ }
+ else
+ {
+ buttonCharacterOpponent.icon = null;
+ buttonCharacterOpponent.text = "None";
+ }
- var charDataGirlfriend:CharacterData = CharacterDataParser.fetchCharacterData(state.currentSongMetadata.playData.characters.girlfriend);
- buttonCharacterGirlfriend.icon = CharacterDataParser.getCharPixelIconAsset(state.currentSongMetadata.playData.characters.girlfriend);
- buttonCharacterGirlfriend.text = charDataGirlfriend.name.length > LIMIT ? '${charDataGirlfriend.name.substr(0, LIMIT)}.' : '${charDataGirlfriend.name}';
+ var charDataGirlfriend:Null = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.girlfriend);
+ if (charDataGirlfriend != null)
+ {
+ buttonCharacterGirlfriend.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.girlfriend);
+ buttonCharacterGirlfriend.text = charDataGirlfriend.name.length > LIMIT ? '${charDataGirlfriend.name.substr(0, LIMIT)}.' : '${charDataGirlfriend.name}';
+ }
+ else
+ {
+ buttonCharacterGirlfriend.icon = null;
+ buttonCharacterGirlfriend.text = "None";
+ }
- var charDataPlayer:CharacterData = CharacterDataParser.fetchCharacterData(state.currentSongMetadata.playData.characters.player);
- buttonCharacterPlayer.icon = CharacterDataParser.getCharPixelIconAsset(state.currentSongMetadata.playData.characters.player);
- buttonCharacterPlayer.text = charDataPlayer.name.length > LIMIT ? '${charDataPlayer.name.substr(0, LIMIT)}.' : '${charDataPlayer.name}';
+ var charDataPlayer:Null = CharacterDataParser.fetchCharacterData(chartEditorState.currentSongMetadata.playData.characters.player);
+ if (charDataPlayer != null)
+ {
+ buttonCharacterPlayer.icon = CharacterDataParser.getCharPixelIconAsset(chartEditorState.currentSongMetadata.playData.characters.player);
+ buttonCharacterPlayer.text = charDataPlayer.name.length > LIMIT ? '${charDataPlayer.name.substr(0, LIMIT)}.' : '${charDataPlayer.name}';
+ }
+ else
+ {
+ buttonCharacterPlayer.icon = null;
+ buttonCharacterPlayer.text = "None";
+ }
}
- public static function build(state:ChartEditorState):ChartEditorMetadataToolbox
+ public static function build(chartEditorState:ChartEditorState):ChartEditorMetadataToolbox
{
- return new ChartEditorMetadataToolbox(state);
+ return new ChartEditorMetadataToolbox(chartEditorState);
}
}
diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx
index 18b0010b2..70ef97fd0 100644
--- a/source/funkin/ui/debug/latency/LatencyState.hx
+++ b/source/funkin/ui/debug/latency/LatencyState.hx
@@ -75,7 +75,7 @@ class LatencyState extends MusicBeatSubState
// funnyStatsGraph.hi
- Conductor.forceBPM(60);
+ Conductor.instance.forceBPM(60);
noteGrp = new FlxTypedGroup();
add(noteGrp);
@@ -91,14 +91,14 @@ class LatencyState extends MusicBeatSubState
// // musSpec.visType = FREQUENCIES;
// add(musSpec);
- for (beat in 0...Math.floor(FlxG.sound.music.length / Conductor.beatLengthMs))
+ for (beat in 0...Math.floor(FlxG.sound.music.length / Conductor.instance.beatLengthMs))
{
- var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * Conductor.beatLengthMs), FlxG.height - 15);
+ var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * Conductor.instance.beatLengthMs), FlxG.height - 15);
beatTick.makeGraphic(2, 15);
beatTick.alpha = 0.3;
add(beatTick);
- var offsetTxt:FlxText = new FlxText(songPosToX(beat * Conductor.beatLengthMs), FlxG.height - 26, 0, "swag");
+ var offsetTxt:FlxText = new FlxText(songPosToX(beat * Conductor.instance.beatLengthMs), FlxG.height - 26, 0, "swag");
offsetTxt.alpha = 0.5;
diffGrp.add(offsetTxt);
@@ -130,7 +130,7 @@ class LatencyState extends MusicBeatSubState
for (i in 0...32)
{
- var note:NoteSprite = new NoteSprite(NoteStyleRegistry.instance.fetchDefault(), Conductor.beatLengthMs * i);
+ var note:NoteSprite = new NoteSprite(NoteStyleRegistry.instance.fetchDefault(), Conductor.instance.beatLengthMs * i);
noteGrp.add(note);
}
@@ -146,9 +146,9 @@ class LatencyState extends MusicBeatSubState
override function stepHit():Bool
{
- if (Conductor.currentStep % 4 == 2)
+ if (Conductor.instance.currentStep % 4 == 2)
{
- blocks.members[((Conductor.currentBeat % 8) + 1) % 8].alpha = 0.5;
+ blocks.members[((Conductor.instance.currentBeat % 8) + 1) % 8].alpha = 0.5;
}
return super.stepHit();
@@ -156,11 +156,11 @@ class LatencyState extends MusicBeatSubState
override function beatHit():Bool
{
- if (Conductor.currentBeat % 8 == 0) blocks.forEach(blok -> {
+ if (Conductor.instance.currentBeat % 8 == 0) blocks.forEach(blok -> {
blok.alpha = 0;
});
- blocks.members[Conductor.currentBeat % 8].alpha = 1;
+ blocks.members[Conductor.instance.currentBeat % 8].alpha = 1;
// block.visible = !block.visible;
return super.beatHit();
@@ -192,17 +192,17 @@ class LatencyState extends MusicBeatSubState
if (FlxG.keys.pressed.D) FlxG.sound.music.time += 1000 * FlxG.elapsed;
- Conductor.update(swagSong.getTimeWithDiff() - Conductor.inputOffset);
- // Conductor.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp;
+ Conductor.instance.update(swagSong.getTimeWithDiff() - Conductor.instance.inputOffset);
+ // Conductor.instance.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp;
- songPosVis.x = songPosToX(Conductor.songPosition);
- songVisFollowAudio.x = songPosToX(Conductor.songPosition - Conductor.instrumentalOffset);
- songVisFollowVideo.x = songPosToX(Conductor.songPosition - Conductor.inputOffset);
+ songPosVis.x = songPosToX(Conductor.instance.songPosition);
+ songVisFollowAudio.x = songPosToX(Conductor.instance.songPosition - Conductor.instance.instrumentalOffset);
+ songVisFollowVideo.x = songPosToX(Conductor.instance.songPosition - Conductor.instance.inputOffset);
- offsetText.text = "INST Offset: " + Conductor.instrumentalOffset + "ms";
- offsetText.text += "\nINPUT Offset: " + Conductor.inputOffset + "ms";
- offsetText.text += "\ncurrentStep: " + Conductor.currentStep;
- offsetText.text += "\ncurrentBeat: " + Conductor.currentBeat;
+ offsetText.text = "INST Offset: " + Conductor.instance.instrumentalOffset + "ms";
+ offsetText.text += "\nINPUT Offset: " + Conductor.instance.inputOffset + "ms";
+ offsetText.text += "\ncurrentStep: " + Conductor.instance.currentStep;
+ offsetText.text += "\ncurrentBeat: " + Conductor.instance.currentBeat;
var avgOffsetInput:Float = 0;
@@ -221,24 +221,24 @@ class LatencyState extends MusicBeatSubState
{
if (FlxG.keys.justPressed.RIGHT)
{
- Conductor.instrumentalOffset += 1.0 * multiply;
+ Conductor.instance.instrumentalOffset += 1.0 * multiply;
}
if (FlxG.keys.justPressed.LEFT)
{
- Conductor.instrumentalOffset -= 1.0 * multiply;
+ Conductor.instance.instrumentalOffset -= 1.0 * multiply;
}
}
else
{
if (FlxG.keys.justPressed.RIGHT)
{
- Conductor.inputOffset += 1.0 * multiply;
+ Conductor.instance.inputOffset += 1.0 * multiply;
}
if (FlxG.keys.justPressed.LEFT)
{
- Conductor.inputOffset -= 1.0 * multiply;
+ Conductor.instance.inputOffset -= 1.0 * multiply;
}
}
@@ -250,7 +250,7 @@ class LatencyState extends MusicBeatSubState
}*/
noteGrp.forEach(function(daNote:NoteSprite) {
- daNote.y = (strumLine.y - ((Conductor.songPosition - Conductor.instrumentalOffset) - daNote.noteData.time) * 0.45);
+ daNote.y = (strumLine.y - ((Conductor.instance.songPosition - Conductor.instance.instrumentalOffset) - daNote.noteData.time) * 0.45);
daNote.x = strumLine.x + 30;
if (daNote.y < strumLine.y) daNote.alpha = 0.5;
@@ -258,7 +258,7 @@ class LatencyState extends MusicBeatSubState
if (daNote.y < 0 - daNote.height)
{
daNote.alpha = 1;
- // daNote.data.strumTime += Conductor.beatLengthMs * 8;
+ // daNote.data.strumTime += Conductor.instance.beatLengthMs * 8;
}
});
@@ -267,14 +267,14 @@ class LatencyState extends MusicBeatSubState
function generateBeatStuff()
{
- Conductor.update(swagSong.getTimeWithDiff());
+ Conductor.instance.update(swagSong.getTimeWithDiff());
- var closestBeat:Int = Math.round(Conductor.songPosition / Conductor.beatLengthMs) % diffGrp.members.length;
- var getDiff:Float = Conductor.songPosition - (closestBeat * Conductor.beatLengthMs);
- getDiff -= Conductor.inputOffset;
+ var closestBeat:Int = Math.round(Conductor.instance.songPosition / Conductor.instance.beatLengthMs) % diffGrp.members.length;
+ var getDiff:Float = Conductor.instance.songPosition - (closestBeat * Conductor.instance.beatLengthMs);
+ getDiff -= Conductor.instance.inputOffset;
// lil fix for end of song
- if (closestBeat == 0 && getDiff >= Conductor.beatLengthMs * 2) getDiff -= FlxG.sound.music.length;
+ if (closestBeat == 0 && getDiff >= Conductor.instance.beatLengthMs * 2) getDiff -= FlxG.sound.music.length;
trace("\tDISTANCE TO CLOSEST BEAT: " + getDiff + "ms");
trace("\tCLOSEST BEAT: " + closestBeat);
diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx
index 371021114..f17c3d91e 100644
--- a/source/funkin/ui/freeplay/FreeplayState.hx
+++ b/source/funkin/ui/freeplay/FreeplayState.hx
@@ -97,7 +97,7 @@ class FreeplayState extends MusicBeatSubState
var stickerSubState:StickerSubState;
//
- static var rememberedDifficulty:Null = "normal";
+ static var rememberedDifficulty:Null = Constants.DEFAULT_DIFFICULTY;
static var rememberedSongId:Null = null;
public function new(?stickers:StickerSubState = null)
@@ -874,15 +874,14 @@ class FreeplayState extends MusicBeatSubState
}
}
- @:haxe.warning("-WDeprecated")
- override function switchTo(nextState:FlxState):Bool
+ public override function destroy():Void
{
+ super.destroy();
var daSong = songs[curSelected];
if (daSong != null)
{
clearDaCache(daSong.songName);
}
- return super.switchTo(nextState);
}
function changeDiff(change:Int = 0)
diff --git a/source/funkin/ui/haxeui/components/CharacterPlayer.hx b/source/funkin/ui/haxeui/components/CharacterPlayer.hx
index 66b94bfa2..c7171fac7 100644
--- a/source/funkin/ui/haxeui/components/CharacterPlayer.hx
+++ b/source/funkin/ui/haxeui/components/CharacterPlayer.hx
@@ -35,7 +35,7 @@ class CharacterPlayer extends Box
public function new(defaultToBf:Bool = true)
{
super();
- _overrideSkipTransformChildren = false;
+ // _overrideSkipTransformChildren = false;
if (defaultToBf)
{
diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx
index 456988873..d6dd536f7 100644
--- a/source/funkin/ui/story/StoryMenuState.hx
+++ b/source/funkin/ui/story/StoryMenuState.hx
@@ -106,7 +106,7 @@ class StoryMenuState extends MusicBeatState
var stickerSubState:StickerSubState;
static var rememberedLevelId:Null = null;
- static var rememberedDifficulty:Null = "normal";
+ static var rememberedDifficulty:Null = Constants.DEFAULT_DIFFICULTY;
public function new(?stickers:StickerSubState = null)
{
@@ -238,7 +238,7 @@ class StoryMenuState extends MusicBeatState
var freakyMenuMetadata:Null = SongRegistry.instance.parseMusicData('freakyMenu');
if (freakyMenuMetadata != null)
{
- Conductor.mapTimeChanges(freakyMenuMetadata.timeChanges);
+ Conductor.instance.mapTimeChanges(freakyMenuMetadata.timeChanges);
}
FlxG.sound.playMusic(Paths.music('freakyMenu/freakyMenu'), 0);
@@ -317,7 +317,7 @@ class StoryMenuState extends MusicBeatState
override function update(elapsed:Float)
{
- Conductor.update();
+ Conductor.instance.update();
highScoreLerp = Std.int(MathUtil.coolLerp(highScoreLerp, highScore, 0.5));
diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx
index 7671bb336..bc44af073 100644
--- a/source/funkin/ui/title/TitleState.hx
+++ b/source/funkin/ui/title/TitleState.hx
@@ -221,7 +221,7 @@ class TitleState extends MusicBeatState
var freakyMenuMetadata:Null = SongRegistry.instance.parseMusicData('freakyMenu');
if (freakyMenuMetadata != null)
{
- Conductor.mapTimeChanges(freakyMenuMetadata.timeChanges);
+ Conductor.instance.mapTimeChanges(freakyMenuMetadata.timeChanges);
}
FlxG.sound.playMusic(Paths.music('freakyMenu/freakyMenu'), 0);
FlxG.sound.music.fadeIn(4, 0, 0.7);
@@ -256,7 +256,7 @@ class TitleState extends MusicBeatState
if (FlxG.keys.pressed.DOWN) FlxG.sound.music.pitch -= 0.5 * elapsed;
#end
- Conductor.update();
+ Conductor.instance.update();
/* if (FlxG.onMobile)
{
@@ -280,7 +280,7 @@ class TitleState extends MusicBeatState
FlxTween.tween(FlxG.stage.window, {y: FlxG.stage.window.y + 100}, 0.7, {ease: FlxEase.quadInOut, type: PINGPONG});
}
- if (FlxG.sound.music != null) Conductor.update(FlxG.sound.music.time);
+ if (FlxG.sound.music != null) Conductor.instance.update(FlxG.sound.music.time);
if (FlxG.keys.justPressed.F) FlxG.fullscreen = !FlxG.fullscreen;
// do controls.PAUSE | controls.ACCEPT instead?
@@ -390,7 +390,7 @@ class TitleState extends MusicBeatState
var spec:SpectogramSprite = new SpectogramSprite(FlxG.sound.music);
add(spec);
- Conductor.forceBPM(190);
+ Conductor.instance.forceBPM(190);
FlxG.camera.flash(FlxColor.WHITE, 1);
FlxG.sound.play(Paths.sound('confirmMenu'), 0.7);
}
@@ -442,13 +442,13 @@ class TitleState extends MusicBeatState
if (!skippedIntro)
{
- // FlxG.log.add(Conductor.currentBeat);
+ // FlxG.log.add(Conductor.instance.currentBeat);
// if the user is draggin the window some beats will
// be missed so this is just to compensate
- if (Conductor.currentBeat > lastBeat)
+ if (Conductor.instance.currentBeat > lastBeat)
{
// TODO: Why does it perform ALL the previous steps each beat?
- for (i in lastBeat...Conductor.currentBeat)
+ for (i in lastBeat...Conductor.instance.currentBeat)
{
switch (i + 1)
{
@@ -483,11 +483,11 @@ class TitleState extends MusicBeatState
}
}
}
- lastBeat = Conductor.currentBeat;
+ lastBeat = Conductor.instance.currentBeat;
}
if (skippedIntro)
{
- if (cheatActive && Conductor.currentBeat % 2 == 0) swagShader.update(0.125);
+ if (cheatActive && Conductor.instance.currentBeat % 2 == 0) swagShader.update(0.125);
if (logoBl != null && logoBl.animation != null) logoBl.animation.play('bump', true);
diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx
index f8749567b..123267a49 100644
--- a/source/funkin/util/Constants.hx
+++ b/source/funkin/util/Constants.hx
@@ -123,6 +123,7 @@ class Constants
/**
* Default list of difficulties for charts.
+ * Assumes no Erect mode, etc.
*/
public static final DEFAULT_DIFFICULTY_LIST:Array = ['easy', 'normal', 'hard'];
diff --git a/tests/unit/source/funkin/ConductorTest.hx b/tests/unit/source/funkin/ConductorTest.hx
index c65f3f297..a0cfedbab 100644
--- a/tests/unit/source/funkin/ConductorTest.hx
+++ b/tests/unit/source/funkin/ConductorTest.hx
@@ -31,23 +31,23 @@ class ConductorTest extends FunkinTest
{
// NOTE: Expected value comes first.
- Assert.areEqual([], Conductor.timeChanges);
- Assert.areEqual(null, Conductor.currentTimeChange);
+ Assert.areEqual([], Conductor.instance.timeChanges);
+ Assert.areEqual(null, Conductor.instance.currentTimeChange);
- Assert.areEqual(0, Conductor.songPosition);
- Assert.areEqual(Constants.DEFAULT_BPM, Conductor.bpm);
- Assert.areEqual(null, Conductor.bpmOverride);
+ Assert.areEqual(0, Conductor.instance.songPosition);
+ Assert.areEqual(Constants.DEFAULT_BPM, Conductor.instance.bpm);
+ Assert.areEqual(null, Conductor.instance.bpmOverride);
- Assert.areEqual(600, Conductor.beatLengthMs);
+ Assert.areEqual(600, Conductor.instance.beatLengthMs);
- Assert.areEqual(4, Conductor.timeSignatureNumerator);
- Assert.areEqual(4, Conductor.timeSignatureDenominator);
+ Assert.areEqual(4, Conductor.instance.timeSignatureNumerator);
+ Assert.areEqual(4, Conductor.instance.timeSignatureDenominator);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(0, Conductor.currentStep);
- Assert.areEqual(0.0, Conductor.currentStepTime);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(0, Conductor.instance.currentStep);
+ Assert.areEqual(0.0, Conductor.instance.currentStepTime);
- Assert.areEqual(150, Conductor.stepLengthMs);
+ Assert.areEqual(150, Conductor.instance.stepLengthMs);
}
/**
@@ -60,23 +60,23 @@ class ConductorTest extends FunkinTest
var currentConductorState:Null = conductorState;
Assert.isNotNull(currentConductorState);
- Assert.areEqual(0, Conductor.songPosition);
+ Assert.areEqual(0, Conductor.instance.songPosition);
step(); // 1
var BPM_100_STEP_TIME = 1 / 9;
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(0, Conductor.currentStep);
- FunkinAssert.areNear(1 / 9, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(0, Conductor.instance.currentStep);
+ FunkinAssert.areNear(1 / 9, Conductor.instance.currentStepTime);
step(7); // 8
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 8, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(0, Conductor.currentStep);
- FunkinAssert.areNear(8 / 9, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 8, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(0, Conductor.instance.currentStep);
+ FunkinAssert.areNear(8 / 9, Conductor.instance.currentStepTime);
Assert.areEqual(0, currentConductorState.beatsHit);
Assert.areEqual(0, currentConductorState.stepsHit);
@@ -88,10 +88,10 @@ class ConductorTest extends FunkinTest
currentConductorState.beatsHit = 0;
currentConductorState.stepsHit = 0;
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 9, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(1, Conductor.currentStep);
- FunkinAssert.areNear(1.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 9, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(1, Conductor.instance.currentStep);
+ FunkinAssert.areNear(1.0, Conductor.instance.currentStepTime);
step(35 - 9); // 35
@@ -100,10 +100,10 @@ class ConductorTest extends FunkinTest
currentConductorState.beatsHit = 0;
currentConductorState.stepsHit = 0;
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 35, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(3, Conductor.currentStep);
- FunkinAssert.areNear(3.0 + 8 / 9, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 35, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(3, Conductor.instance.currentStep);
+ FunkinAssert.areNear(3.0 + 8 / 9, Conductor.instance.currentStepTime);
step(); // 36
@@ -112,83 +112,83 @@ class ConductorTest extends FunkinTest
currentConductorState.beatsHit = 0;
currentConductorState.stepsHit = 0;
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 36, Conductor.songPosition);
- Assert.areEqual(1, Conductor.currentBeat);
- Assert.areEqual(4, Conductor.currentStep);
- FunkinAssert.areNear(4.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 36, Conductor.instance.songPosition);
+ Assert.areEqual(1, Conductor.instance.currentBeat);
+ Assert.areEqual(4, Conductor.instance.currentStep);
+ FunkinAssert.areNear(4.0, Conductor.instance.currentStepTime);
step(50 - 36); // 50
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 50, Conductor.songPosition);
- Assert.areEqual(1, Conductor.currentBeat);
- Assert.areEqual(5, Conductor.currentStep);
- FunkinAssert.areNear(5.555555, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 50, Conductor.instance.songPosition);
+ Assert.areEqual(1, Conductor.instance.currentBeat);
+ Assert.areEqual(5, Conductor.instance.currentStep);
+ FunkinAssert.areNear(5.555555, Conductor.instance.currentStepTime);
step(49); // 99
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 99, Conductor.songPosition);
- Assert.areEqual(2, Conductor.currentBeat);
- Assert.areEqual(11, Conductor.currentStep);
- FunkinAssert.areNear(11.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 99, Conductor.instance.songPosition);
+ Assert.areEqual(2, Conductor.instance.currentBeat);
+ Assert.areEqual(11, Conductor.instance.currentStep);
+ FunkinAssert.areNear(11.0, Conductor.instance.currentStepTime);
step(1); // 100
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 100, Conductor.songPosition);
- Assert.areEqual(2, Conductor.currentBeat);
- Assert.areEqual(11, Conductor.currentStep);
- FunkinAssert.areNear(11.111111, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 100, Conductor.instance.songPosition);
+ Assert.areEqual(2, Conductor.instance.currentBeat);
+ Assert.areEqual(11, Conductor.instance.currentStep);
+ FunkinAssert.areNear(11.111111, Conductor.instance.currentStepTime);
}
@Test
function testUpdateForcedBPM():Void
{
- Conductor.forceBPM(60);
+ Conductor.instance.forceBPM(60);
- Assert.areEqual(0, Conductor.songPosition);
+ Assert.areEqual(0, Conductor.instance.songPosition);
// 60 beats per minute = 1 beat per second
// 1 beat per second = 1/60 beats per frame = 4/60 steps per frame
step(); // Advances time 1/60 of 1 second.
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(0, Conductor.currentStep);
- FunkinAssert.areNear(4 / 60, Conductor.currentStepTime); // 1/60 of 1 beat = 4/60 of 1 step
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(0, Conductor.instance.currentStep);
+ FunkinAssert.areNear(4 / 60, Conductor.instance.currentStepTime); // 1/60 of 1 beat = 4/60 of 1 step
step(14 - 1); // 14
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 14, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(0, Conductor.currentStep);
- FunkinAssert.areNear(1.0 - 4 / 60, Conductor.currentStepTime); // 1/60 of 1 beat = 4/60 of 1 step
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 14, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(0, Conductor.instance.currentStep);
+ FunkinAssert.areNear(1.0 - 4 / 60, Conductor.instance.currentStepTime); // 1/60 of 1 beat = 4/60 of 1 step
step(); // 15
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 15, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(1, Conductor.currentStep);
- FunkinAssert.areNear(1.0, Conductor.currentStepTime); // 1/60 of 1 beat = 4/60 of 1 step
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 15, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(1, Conductor.instance.currentStep);
+ FunkinAssert.areNear(1.0, Conductor.instance.currentStepTime); // 1/60 of 1 beat = 4/60 of 1 step
step(45 - 1); // 59
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(3, Conductor.currentStep);
- FunkinAssert.areNear(4.0 - 4 / 60, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(3, Conductor.instance.currentStep);
+ FunkinAssert.areNear(4.0 - 4 / 60, Conductor.instance.currentStepTime);
step(); // 60
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.songPosition);
- Assert.areEqual(1, Conductor.currentBeat);
- Assert.areEqual(4, Conductor.currentStep);
- FunkinAssert.areNear(4.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.instance.songPosition);
+ Assert.areEqual(1, Conductor.instance.currentBeat);
+ Assert.areEqual(4, Conductor.instance.currentStep);
+ FunkinAssert.areNear(4.0, Conductor.instance.currentStepTime);
step(); // 61
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.songPosition);
- Assert.areEqual(1, Conductor.currentBeat);
- Assert.areEqual(4, Conductor.currentStep);
- FunkinAssert.areNear(4.0 + 4 / 60, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.instance.songPosition);
+ Assert.areEqual(1, Conductor.instance.currentBeat);
+ Assert.areEqual(4, Conductor.instance.currentStep);
+ FunkinAssert.areNear(4.0 + 4 / 60, Conductor.instance.currentStepTime);
}
@Test
@@ -196,50 +196,50 @@ class ConductorTest extends FunkinTest
{
// Start the song with a BPM of 120.
var songTimeChanges:Array = [new SongTimeChange(0, 120)];
- Conductor.mapTimeChanges(songTimeChanges);
+ Conductor.instance.mapTimeChanges(songTimeChanges);
// All should be at 0.
- FunkinAssert.areNear(0, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(0, Conductor.currentStep);
- FunkinAssert.areNear(0.0, Conductor.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step
+ FunkinAssert.areNear(0, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(0, Conductor.instance.currentStep);
+ FunkinAssert.areNear(0.0, Conductor.instance.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step
// 120 beats per minute = 2 beat per second
// 2 beat per second = 2/60 beats per frame = 16/120 steps per frame
step(); // Advances time 1/60 of 1 second.
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(0, Conductor.currentStep);
- FunkinAssert.areNear(16 / 120, Conductor.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(0, Conductor.instance.currentStep);
+ FunkinAssert.areNear(16 / 120, Conductor.instance.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step
step(15 - 1); // 15
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 15, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(2, Conductor.currentStep);
- FunkinAssert.areNear(2.0, Conductor.currentStepTime); // 2/60 of 1 beat = 8/60 of 1 step
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 15, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(2, Conductor.instance.currentStep);
+ FunkinAssert.areNear(2.0, Conductor.instance.currentStepTime); // 2/60 of 1 beat = 8/60 of 1 step
step(45 - 1); // 59
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.songPosition);
- Assert.areEqual(1, Conductor.currentBeat);
- Assert.areEqual(7, Conductor.currentStep);
- FunkinAssert.areNear(7.0 + 104 / 120, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.instance.songPosition);
+ Assert.areEqual(1, Conductor.instance.currentBeat);
+ Assert.areEqual(7, Conductor.instance.currentStep);
+ FunkinAssert.areNear(7.0 + 104 / 120, Conductor.instance.currentStepTime);
step(); // 60
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.songPosition);
- Assert.areEqual(2, Conductor.currentBeat);
- Assert.areEqual(8, Conductor.currentStep);
- FunkinAssert.areNear(8.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.instance.songPosition);
+ Assert.areEqual(2, Conductor.instance.currentBeat);
+ Assert.areEqual(8, Conductor.instance.currentStep);
+ FunkinAssert.areNear(8.0, Conductor.instance.currentStepTime);
step(); // 61
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.songPosition);
- Assert.areEqual(2, Conductor.currentBeat);
- Assert.areEqual(8, Conductor.currentStep);
- FunkinAssert.areNear(8.0 + 8 / 60, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.instance.songPosition);
+ Assert.areEqual(2, Conductor.instance.currentBeat);
+ Assert.areEqual(8, Conductor.instance.currentStep);
+ FunkinAssert.areNear(8.0 + 8 / 60, Conductor.instance.currentStepTime);
}
@Test
@@ -247,57 +247,57 @@ class ConductorTest extends FunkinTest
{
// Start the song with a BPM of 120.
var songTimeChanges:Array = [new SongTimeChange(0, 120), new SongTimeChange(3000, 90)];
- Conductor.mapTimeChanges(songTimeChanges);
+ Conductor.instance.mapTimeChanges(songTimeChanges);
// All should be at 0.
- FunkinAssert.areNear(0, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(0, Conductor.currentStep);
- FunkinAssert.areNear(0.0, Conductor.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step
+ FunkinAssert.areNear(0, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(0, Conductor.instance.currentStep);
+ FunkinAssert.areNear(0.0, Conductor.instance.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step
// 120 beats per minute = 2 beat per second
// 2 beat per second = 2/60 beats per frame = 16/120 steps per frame
step(); // Advances time 1/60 of 1 second.
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(0, Conductor.currentStep);
- FunkinAssert.areNear(16 / 120, Conductor.currentStepTime); // 4/120 of 1 beat = 16/120 of 1 step
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(0, Conductor.instance.currentStep);
+ FunkinAssert.areNear(16 / 120, Conductor.instance.currentStepTime); // 4/120 of 1 beat = 16/120 of 1 step
step(60 - 1 - 1); // 59
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.songPosition);
- Assert.areEqual(1, Conductor.currentBeat);
- Assert.areEqual(7, Conductor.currentStep);
- FunkinAssert.areNear(7.0 + 104 / 120, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.instance.songPosition);
+ Assert.areEqual(1, Conductor.instance.currentBeat);
+ Assert.areEqual(7, Conductor.instance.currentStep);
+ FunkinAssert.areNear(7.0 + 104 / 120, Conductor.instance.currentStepTime);
step(); // 60
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.songPosition);
- Assert.areEqual(2, Conductor.currentBeat);
- Assert.areEqual(8, Conductor.currentStep);
- FunkinAssert.areNear(8.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.instance.songPosition);
+ Assert.areEqual(2, Conductor.instance.currentBeat);
+ Assert.areEqual(8, Conductor.instance.currentStep);
+ FunkinAssert.areNear(8.0, Conductor.instance.currentStepTime);
step(); // 61
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.songPosition);
- Assert.areEqual(2, Conductor.currentBeat);
- Assert.areEqual(8, Conductor.currentStep);
- FunkinAssert.areNear(8.0 + 8 / 60, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.instance.songPosition);
+ Assert.areEqual(2, Conductor.instance.currentBeat);
+ Assert.areEqual(8, Conductor.instance.currentStep);
+ FunkinAssert.areNear(8.0 + 8 / 60, Conductor.instance.currentStepTime);
step(179 - 61); // 179
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 179, Conductor.songPosition);
- Assert.areEqual(5, Conductor.currentBeat);
- Assert.areEqual(23, Conductor.currentStep);
- FunkinAssert.areNear(23.0 + 52 / 60, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 179, Conductor.instance.songPosition);
+ Assert.areEqual(5, Conductor.instance.currentBeat);
+ Assert.areEqual(23, Conductor.instance.currentStep);
+ FunkinAssert.areNear(23.0 + 52 / 60, Conductor.instance.currentStepTime);
step(); // 180 (3 seconds)
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 180, Conductor.songPosition);
- Assert.areEqual(6, Conductor.currentBeat);
- Assert.areEqual(24, Conductor.currentStep);
- FunkinAssert.areNear(24.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 180, Conductor.instance.songPosition);
+ Assert.areEqual(6, Conductor.instance.currentBeat);
+ Assert.areEqual(24, Conductor.instance.currentStep);
+ FunkinAssert.areNear(24.0, Conductor.instance.currentStepTime);
step(); // 181 (3 + 1/60 seconds)
// BPM has switched to 90!
@@ -305,24 +305,24 @@ class ConductorTest extends FunkinTest
// 1.5 beat per second = 1.5/60 beats per frame = 3/120 beats per frame
// = 12/120 steps per frame
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 181, Conductor.songPosition);
- Assert.areEqual(6, Conductor.currentBeat);
- Assert.areEqual(24, Conductor.currentStep);
- FunkinAssert.areNear(24.0 + 12 / 120, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 181, Conductor.instance.songPosition);
+ Assert.areEqual(6, Conductor.instance.currentBeat);
+ Assert.areEqual(24, Conductor.instance.currentStep);
+ FunkinAssert.areNear(24.0 + 12 / 120, Conductor.instance.currentStepTime);
step(59); // 240 (4 seconds)
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 240, Conductor.songPosition);
- Assert.areEqual(7, Conductor.currentBeat);
- Assert.areEqual(30, Conductor.currentStep);
- FunkinAssert.areNear(30.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 240, Conductor.instance.songPosition);
+ Assert.areEqual(7, Conductor.instance.currentBeat);
+ Assert.areEqual(30, Conductor.instance.currentStep);
+ FunkinAssert.areNear(30.0, Conductor.instance.currentStepTime);
step(); // 241 (4 + 1/60 seconds)
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 241, Conductor.songPosition);
- Assert.areEqual(7, Conductor.currentBeat);
- Assert.areEqual(30, Conductor.currentStep);
- FunkinAssert.areNear(30.0 + 12 / 120, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 241, Conductor.instance.songPosition);
+ Assert.areEqual(7, Conductor.instance.currentBeat);
+ Assert.areEqual(30, Conductor.instance.currentStep);
+ FunkinAssert.areNear(30.0 + 12 / 120, Conductor.instance.currentStepTime);
}
@Test
@@ -334,63 +334,63 @@ class ConductorTest extends FunkinTest
new SongTimeChange(3000, 90),
new SongTimeChange(6000, 180)
];
- Conductor.mapTimeChanges(songTimeChanges);
+ Conductor.instance.mapTimeChanges(songTimeChanges);
// Verify time changes.
- Assert.areEqual(3, Conductor.timeChanges.length);
- FunkinAssert.areNear(0, Conductor.timeChanges[0].beatTime);
- FunkinAssert.areNear(6, Conductor.timeChanges[1].beatTime);
- FunkinAssert.areNear(10.5, Conductor.timeChanges[2].beatTime);
+ Assert.areEqual(3, Conductor.instance.timeChanges.length);
+ FunkinAssert.areNear(0, Conductor.instance.timeChanges[0].beatTime);
+ FunkinAssert.areNear(6, Conductor.instance.timeChanges[1].beatTime);
+ FunkinAssert.areNear(10.5, Conductor.instance.timeChanges[2].beatTime);
// All should be at 0.
- FunkinAssert.areNear(0, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(0, Conductor.currentStep);
- FunkinAssert.areNear(0.0, Conductor.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step
+ FunkinAssert.areNear(0, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(0, Conductor.instance.currentStep);
+ FunkinAssert.areNear(0.0, Conductor.instance.currentStepTime); // 2/120 of 1 beat = 8/120 of 1 step
// 120 beats per minute = 2 beat per second
// 2 beat per second = 2/60 beats per frame = 16/120 steps per frame
step(); // Advances time 1/60 of 1 second.
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.songPosition);
- Assert.areEqual(0, Conductor.currentBeat);
- Assert.areEqual(0, Conductor.currentStep);
- FunkinAssert.areNear(16 / 120, Conductor.currentStepTime); // 4/120 of 1 beat = 16/120 of 1 step
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 1, Conductor.instance.songPosition);
+ Assert.areEqual(0, Conductor.instance.currentBeat);
+ Assert.areEqual(0, Conductor.instance.currentStep);
+ FunkinAssert.areNear(16 / 120, Conductor.instance.currentStepTime); // 4/120 of 1 beat = 16/120 of 1 step
step(60 - 1 - 1); // 59
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.songPosition);
- Assert.areEqual(1, Conductor.currentBeat);
- Assert.areEqual(7, Conductor.currentStep);
- FunkinAssert.areNear(7 + 104 / 120, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 59, Conductor.instance.songPosition);
+ Assert.areEqual(1, Conductor.instance.currentBeat);
+ Assert.areEqual(7, Conductor.instance.currentStep);
+ FunkinAssert.areNear(7 + 104 / 120, Conductor.instance.currentStepTime);
step(); // 60
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.songPosition);
- Assert.areEqual(2, Conductor.currentBeat);
- Assert.areEqual(8, Conductor.currentStep);
- FunkinAssert.areNear(8.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 60, Conductor.instance.songPosition);
+ Assert.areEqual(2, Conductor.instance.currentBeat);
+ Assert.areEqual(8, Conductor.instance.currentStep);
+ FunkinAssert.areNear(8.0, Conductor.instance.currentStepTime);
step(); // 61
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.songPosition);
- Assert.areEqual(2, Conductor.currentBeat);
- Assert.areEqual(8, Conductor.currentStep);
- FunkinAssert.areNear(8.0 + 8 / 60, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 61, Conductor.instance.songPosition);
+ Assert.areEqual(2, Conductor.instance.currentBeat);
+ Assert.areEqual(8, Conductor.instance.currentStep);
+ FunkinAssert.areNear(8.0 + 8 / 60, Conductor.instance.currentStepTime);
step(179 - 61); // 179
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 179, Conductor.songPosition);
- Assert.areEqual(5, Conductor.currentBeat);
- Assert.areEqual(23, Conductor.currentStep);
- FunkinAssert.areNear(23.0 + 52 / 60, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 179, Conductor.instance.songPosition);
+ Assert.areEqual(5, Conductor.instance.currentBeat);
+ Assert.areEqual(23, Conductor.instance.currentStep);
+ FunkinAssert.areNear(23.0 + 52 / 60, Conductor.instance.currentStepTime);
step(); // 180 (3 seconds)
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 180, Conductor.songPosition);
- Assert.areEqual(6, Conductor.currentBeat);
- Assert.areEqual(24, Conductor.currentStep); // 23.999 => 24
- FunkinAssert.areNear(24.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 180, Conductor.instance.songPosition);
+ Assert.areEqual(6, Conductor.instance.currentBeat);
+ Assert.areEqual(24, Conductor.instance.currentStep); // 23.999 => 24
+ FunkinAssert.areNear(24.0, Conductor.instance.currentStepTime);
step(); // 181 (3 + 1/60 seconds)
// BPM has switched to 90!
@@ -398,45 +398,45 @@ class ConductorTest extends FunkinTest
// 1.5 beat per second = 1.5/60 beats per frame = 3/120 beats per frame
// = 12/120 steps per frame
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 181, Conductor.songPosition);
- Assert.areEqual(6, Conductor.currentBeat);
- Assert.areEqual(24, Conductor.currentStep);
- FunkinAssert.areNear(24.0 + 12 / 120, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 181, Conductor.instance.songPosition);
+ Assert.areEqual(6, Conductor.instance.currentBeat);
+ Assert.areEqual(24, Conductor.instance.currentStep);
+ FunkinAssert.areNear(24.0 + 12 / 120, Conductor.instance.currentStepTime);
step(60 - 1 - 1); // 240 (4 seconds)
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 239, Conductor.songPosition);
- Assert.areEqual(7, Conductor.currentBeat);
- Assert.areEqual(29, Conductor.currentStep);
- FunkinAssert.areNear(29.0 + 108 / 120, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 239, Conductor.instance.songPosition);
+ Assert.areEqual(7, Conductor.instance.currentBeat);
+ Assert.areEqual(29, Conductor.instance.currentStep);
+ FunkinAssert.areNear(29.0 + 108 / 120, Conductor.instance.currentStepTime);
step(); // 240 (4 seconds)
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 240, Conductor.songPosition);
- Assert.areEqual(7, Conductor.currentBeat);
- Assert.areEqual(30, Conductor.currentStep);
- FunkinAssert.areNear(30.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 240, Conductor.instance.songPosition);
+ Assert.areEqual(7, Conductor.instance.currentBeat);
+ Assert.areEqual(30, Conductor.instance.currentStep);
+ FunkinAssert.areNear(30.0, Conductor.instance.currentStepTime);
step(); // 241 (4 + 1/60 seconds)
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 241, Conductor.songPosition);
- Assert.areEqual(7, Conductor.currentBeat);
- Assert.areEqual(30, Conductor.currentStep);
- FunkinAssert.areNear(30.0 + 12 / 120, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 241, Conductor.instance.songPosition);
+ Assert.areEqual(7, Conductor.instance.currentBeat);
+ Assert.areEqual(30, Conductor.instance.currentStep);
+ FunkinAssert.areNear(30.0 + 12 / 120, Conductor.instance.currentStepTime);
step(359 - 241); // 359 (5 + 59/60 seconds)
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 359, Conductor.songPosition);
- Assert.areEqual(10, Conductor.currentBeat);
- Assert.areEqual(41, Conductor.currentStep);
- FunkinAssert.areNear(41 + 108 / 120, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 359, Conductor.instance.songPosition);
+ Assert.areEqual(10, Conductor.instance.currentBeat);
+ Assert.areEqual(41, Conductor.instance.currentStep);
+ FunkinAssert.areNear(41 + 108 / 120, Conductor.instance.currentStepTime);
step(); // 360
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 360, Conductor.songPosition);
- Assert.areEqual(10, Conductor.currentBeat);
- Assert.areEqual(42, Conductor.currentStep); // 41.999
- FunkinAssert.areNear(42.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 360, Conductor.instance.songPosition);
+ Assert.areEqual(10, Conductor.instance.currentBeat);
+ Assert.areEqual(42, Conductor.instance.currentStep); // 41.999
+ FunkinAssert.areNear(42.0, Conductor.instance.currentStepTime);
step(); // 361
// BPM has switched to 180!
@@ -444,24 +444,24 @@ class ConductorTest extends FunkinTest
// 3 beat per second = 3/60 beats per frame
// = 12/60 steps per frame
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 361, Conductor.songPosition);
- Assert.areEqual(10, Conductor.currentBeat);
- Assert.areEqual(42, Conductor.currentStep);
- FunkinAssert.areNear(42.0 + 12 / 60, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 361, Conductor.instance.songPosition);
+ Assert.areEqual(10, Conductor.instance.currentBeat);
+ Assert.areEqual(42, Conductor.instance.currentStep);
+ FunkinAssert.areNear(42.0 + 12 / 60, Conductor.instance.currentStepTime);
step(); // 362
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 362, Conductor.songPosition);
- Assert.areEqual(10, Conductor.currentBeat);
- Assert.areEqual(42, Conductor.currentStep);
- FunkinAssert.areNear(42.0 + 24 / 60, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 362, Conductor.instance.songPosition);
+ Assert.areEqual(10, Conductor.instance.currentBeat);
+ Assert.areEqual(42, Conductor.instance.currentStep);
+ FunkinAssert.areNear(42.0 + 24 / 60, Conductor.instance.currentStepTime);
step(3); // 365
- FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 365, Conductor.songPosition);
- Assert.areEqual(10, Conductor.currentBeat);
- Assert.areEqual(43, Conductor.currentStep); // 42.999 => 42
- FunkinAssert.areNear(43.0, Conductor.currentStepTime);
+ FunkinAssert.areNear(FunkinTest.MS_PER_STEP * 365, Conductor.instance.songPosition);
+ Assert.areEqual(10, Conductor.instance.currentBeat);
+ Assert.areEqual(43, Conductor.instance.currentStep); // 42.999 => 42
+ FunkinAssert.areNear(43.0, Conductor.instance.currentStepTime);
}
}
@@ -504,6 +504,6 @@ class ConductorState extends FlxState
super.update(elapsed);
// On each step, increment the Conductor as though the song was playing.
- Conductor.update(Conductor.songPosition + elapsed * Constants.MS_PER_SEC);
+ Conductor.instance.update(Conductor.instance.songPosition + elapsed * Constants.MS_PER_SEC);
}
}
diff --git a/tests/unit/source/funkin/data/BaseRegistryTest.hx b/tests/unit/source/funkin/data/BaseRegistryTest.hx
index 0be932d35..5f837ba97 100644
--- a/tests/unit/source/funkin/data/BaseRegistryTest.hx
+++ b/tests/unit/source/funkin/data/BaseRegistryTest.hx
@@ -156,6 +156,7 @@ class MyTypeRegistry extends BaseRegistry
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{
@@ -181,6 +182,7 @@ class MyTypeRegistry extends BaseRegistry
// JsonParser does not take type parameters,
// otherwise this function would be in BaseRegistry.
var parser = new json2object.JsonParser();
+ parser.ignoreUnknownVariables = false;
switch (loadEntryFile(id))
{