mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2025-04-01 01:39:44 -04:00
Rework Conductor to use instanced signals
This commit is contained in:
parent
a42524987e
commit
e64637ffdf
3 changed files with 132 additions and 41 deletions
source/funkin
|
@ -36,23 +36,43 @@ class Conductor
|
|||
* 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();
|
||||
public static var instance(get, set):Conductor;
|
||||
|
||||
static var _instance:Null<Conductor> = null;
|
||||
|
||||
/**
|
||||
* Signal fired when the current Conductor instance advances to a new measure.
|
||||
* Signal fired when the current static Conductor instance advances to a new measure.
|
||||
*/
|
||||
public static var measureHit(default, null):FlxSignal = new FlxSignal();
|
||||
|
||||
/**
|
||||
* Signal fired when THIS Conductor instance advances to a new measure.
|
||||
* TODO: This naming sucks but we can't make a static and instance field with the same name!
|
||||
*/
|
||||
public var onMeasureHit(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 THIS Conductor instance advances to a new beat.
|
||||
* TODO: This naming sucks but we can't make a static and instance field with the same name!
|
||||
*/
|
||||
public var onBeatHit(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();
|
||||
|
||||
/**
|
||||
* Signal fired when THIS Conductor instance advances to a new step.
|
||||
* TODO: This naming sucks but we can't make a static and instance field with the same name!
|
||||
*/
|
||||
public var onStepHit(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.
|
||||
|
@ -234,6 +254,81 @@ class Conductor
|
|||
return Std.int(timeSignatureNumerator / timeSignatureDenominator * Constants.STEPS_PER_BEAT * Constants.STEPS_PER_BEAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the Conductor, replacing the current instance with a fresh one.
|
||||
*/
|
||||
public static function reset():Void
|
||||
{
|
||||
set_instance(new Conductor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add values of the current main Conductor instance to the `FlxG.watch`.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
static function dispatchMeasureHit():Void
|
||||
{
|
||||
Conductor.measureHit.dispatch();
|
||||
}
|
||||
|
||||
static function dispatchBeatHit():Void
|
||||
{
|
||||
Conductor.beatHit.dispatch();
|
||||
}
|
||||
|
||||
static function dispatchStepHit():Void
|
||||
{
|
||||
Conductor.stepHit.dispatch();
|
||||
}
|
||||
|
||||
static function setupSingleton(input:Conductor):Void
|
||||
{
|
||||
input.onMeasureHit.add(dispatchMeasureHit);
|
||||
|
||||
input.onBeatHit.add(dispatchBeatHit);
|
||||
|
||||
input.onStepHit.add(dispatchStepHit);
|
||||
}
|
||||
|
||||
static function clearSingleton(input:Conductor):Void
|
||||
{
|
||||
input.onMeasureHit.remove(dispatchMeasureHit);
|
||||
|
||||
input.onBeatHit.remove(dispatchBeatHit);
|
||||
|
||||
input.onStepHit.remove(dispatchStepHit);
|
||||
}
|
||||
|
||||
static function get_instance():Conductor
|
||||
{
|
||||
if (Conductor._instance == null) set_instance(new Conductor());
|
||||
if (Conductor._instance == null) throw "Could not initialize singleton Conductor!";
|
||||
return Conductor._instance;
|
||||
}
|
||||
|
||||
static function set_instance(instance:Conductor):Conductor
|
||||
{
|
||||
// Use _instance in here to avoid recursion
|
||||
if (Conductor._instance != null) clearSingleton(Conductor._instance);
|
||||
|
||||
Conductor._instance = instance;
|
||||
|
||||
if (Conductor._instance != null) setupSingleton(Conductor._instance);
|
||||
|
||||
return Conductor._instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
*/
|
||||
public function new() {}
|
||||
|
||||
/**
|
||||
|
@ -244,6 +339,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.
|
||||
* We should probably deprecate this in the future.
|
||||
*/
|
||||
public function forceBPM(?bpm:Float = null)
|
||||
{
|
||||
|
@ -264,7 +360,7 @@ class Conductor
|
|||
* BPM, current step, etc. will be re-calculated based on the song position.
|
||||
*
|
||||
* @param songPosition The current position in the song in milliseconds.
|
||||
* Leave blank to use the FlxG.sound.music position.
|
||||
* Leave blank to use the `FlxG.sound.music` position.
|
||||
*/
|
||||
public function update(?songPos:Float)
|
||||
{
|
||||
|
@ -317,27 +413,27 @@ class Conductor
|
|||
this.currentMeasure = Math.floor(currentMeasureTime);
|
||||
}
|
||||
|
||||
// Only fire the signal if we are THE Conductor.
|
||||
if (this == Conductor.instance)
|
||||
// FlxSignals are really cool.
|
||||
if (currentStep != oldStep)
|
||||
{
|
||||
// FlxSignals are really cool.
|
||||
if (currentStep != oldStep)
|
||||
{
|
||||
Conductor.stepHit.dispatch();
|
||||
}
|
||||
this.onStepHit.dispatch();
|
||||
}
|
||||
|
||||
if (currentBeat != oldBeat)
|
||||
{
|
||||
Conductor.beatHit.dispatch();
|
||||
}
|
||||
if (currentBeat != oldBeat)
|
||||
{
|
||||
this.onBeatHit.dispatch();
|
||||
}
|
||||
|
||||
if (currentMeasure != oldMeasure)
|
||||
{
|
||||
Conductor.measureHit.dispatch();
|
||||
}
|
||||
if (currentMeasure != oldMeasure)
|
||||
{
|
||||
this.onMeasureHit.dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the time changes from a SongMetadata file.
|
||||
* @param songTimeChanges The time changes to apply.
|
||||
*/
|
||||
public function mapTimeChanges(songTimeChanges:Array<SongTimeChange>)
|
||||
{
|
||||
timeChanges = [];
|
||||
|
@ -383,7 +479,8 @@ class Conductor
|
|||
}
|
||||
|
||||
/**
|
||||
* Given a time in milliseconds, return a time in steps.
|
||||
* @param ms A timestamp in milliseconds.
|
||||
* @return The corresponding time in steps.
|
||||
*/
|
||||
public function getTimeInSteps(ms:Float):Float
|
||||
{
|
||||
|
@ -420,7 +517,8 @@ class Conductor
|
|||
}
|
||||
|
||||
/**
|
||||
* Given a time in steps and fractional steps, return a time in milliseconds.
|
||||
* @param stepTime A timestamp in steps.
|
||||
* @return The corresponding time in milliseconds.
|
||||
*/
|
||||
public function getStepTimeInMs(stepTime:Float):Float
|
||||
{
|
||||
|
@ -456,7 +554,8 @@ class Conductor
|
|||
}
|
||||
|
||||
/**
|
||||
* Given a time in beats and fractional beats, return a time in milliseconds.
|
||||
* @param beatTime A timestamp in fractional beats.
|
||||
* @return The corresponding time in milliseconds.
|
||||
*/
|
||||
public function getBeatTimeInMs(beatTime:Float):Float
|
||||
{
|
||||
|
@ -490,21 +589,4 @@ class Conductor
|
|||
return resultMs;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
Conductor.instance = new Conductor();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -374,12 +374,16 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
|
|||
|
||||
public function getFirstValidVariation(?diffId:String, ?possibleVariations:Array<String>):Null<String>
|
||||
{
|
||||
if (variations == null) possibleVariations = variations;
|
||||
if (possibleVariations == null)
|
||||
{
|
||||
possibleVariations = variations;
|
||||
possibleVariations.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST));
|
||||
}
|
||||
if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0];
|
||||
|
||||
for (variation in variations)
|
||||
for (variationId in possibleVariations)
|
||||
{
|
||||
if (difficulties.exists('$diffId-$variation')) return variation;
|
||||
if (difficulties.exists('$diffId-$variationId')) return variationId;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -157,6 +157,11 @@ class Constants
|
|||
*/
|
||||
public static final DEFAULT_VARIATION:String = 'default';
|
||||
|
||||
/**
|
||||
* Standardized variations for charts
|
||||
*/
|
||||
public static final DEFAULT_VARIATION_LIST:Array<String> = ['default', 'erect', 'pico'];
|
||||
|
||||
/**
|
||||
* The default intensity for camera zooms.
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue