diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 4b1261d4b..4cf245aaf 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -322,6 +322,76 @@ class Conductor } } + /** + * Given a time in steps and fractional steps, return a time in milliseconds. + */ + public static function getStepTimeInMs(stepTime:Float):Float + { + if (timeChanges.length == 0) + { + // Assume a constant BPM equal to the forced value. + return stepTime * stepLengthMs; + } + else + { + var resultMs:Float = 0; + + var lastTimeChange:SongTimeChange = timeChanges[0]; + for (timeChange in timeChanges) + { + if (stepTime >= timeChange.beatTime * 4) + { + lastTimeChange = timeChange; + resultMs = lastTimeChange.timeStamp; + } + else + { + // This time change is after the requested time. + break; + } + } + + resultMs += (stepTime - lastTimeChange.beatTime * 4) * stepLengthMs; + + return resultMs; + } + } + + /** + * Given a time in beats and fractional beats, return a time in milliseconds. + */ + public static function getBeatTimeInMs(beatTime:Float):Float + { + if (timeChanges.length == 0) + { + // Assume a constant BPM equal to the forced value. + return beatTime * stepLengthMs * Constants.STEPS_PER_BEAT; + } + else + { + var resultMs:Float = 0; + + var lastTimeChange:SongTimeChange = timeChanges[0]; + for (timeChange in timeChanges) + { + if (beatTime >= timeChange.beatTime) + { + lastTimeChange = timeChange; + resultMs = lastTimeChange.timeStamp; + } + else + { + // This time change is after the requested time. + break; + } + } + + resultMs += (beatTime - lastTimeChange.beatTime) * stepLengthMs * Constants.STEPS_PER_BEAT; + + return resultMs; + } + } + public static function reset():Void { beatHit.removeAll(); diff --git a/source/funkin/play/event/SongEvent.hx b/source/funkin/play/event/SongEvent.hx index 098a84e12..6acc745ff 100644 --- a/source/funkin/play/event/SongEvent.hx +++ b/source/funkin/play/event/SongEvent.hx @@ -37,6 +37,15 @@ class SongEvent return null; } + /** + * Retrieves the asset path to the icon this event type should use in the chart editor. + * To customize this, override getIconPath(). + */ + public function getIconPath():String + { + return 'ui/chart-editor/events/default'; + } + /** * Retrieves the human readable title of this song event type. * Used for the chart editor. diff --git a/source/funkin/play/song/SongData.hx b/source/funkin/play/song/SongData.hx index 5015f1f93..176604bcc 100644 --- a/source/funkin/play/song/SongData.hx +++ b/source/funkin/play/song/SongData.hx @@ -402,7 +402,7 @@ abstract SongNoteData(RawSongNoteData) public function get_stepTime():Float { - return Conductor.getTimeInSteps(this.t); + return Conductor.getTimeInSteps(abstract.time); } /** @@ -428,12 +428,12 @@ abstract SongNoteData(RawSongNoteData) */ public inline function getDirection(strumlineSize:Int = 4):Int { - return this.d % strumlineSize; + return abstract.data % strumlineSize; } public function getDirectionName(strumlineSize:Int = 4):String { - switch (this.d % strumlineSize) + switch (abstract.data % strumlineSize) { case 0: return 'Left'; @@ -456,7 +456,7 @@ abstract SongNoteData(RawSongNoteData) */ public inline function getStrumlineIndex(strumlineSize:Int = 4):Int { - return Math.floor(this.d / strumlineSize); + return Math.floor(abstract.data / strumlineSize); } public inline function getMustHitNote(strumlineSize:Int = 4):Bool @@ -466,19 +466,31 @@ abstract SongNoteData(RawSongNoteData) public var length(get, set):Float; - public function get_length():Float + function get_length():Float { return this.l; } - public function set_length(value:Float):Float + function set_length(value:Float):Float { return this.l = value; } + public var stepLength(get, set):Float; + + function get_stepLength():Float + { + return Conductor.getTimeInSteps(abstract.time + abstract.length) - abstract.stepTime; + } + + function set_stepLength(value:Float):Float + { + return abstract.length = Conductor.getStepTimeInMs(value) - abstract.time; + } + public var kind(get, set):String; - public function get_kind():String + function get_kind():String { if (this.k == null || this.k == '') return 'normal'; @@ -494,21 +506,37 @@ abstract SongNoteData(RawSongNoteData) @:op(A == B) public function op_equals(other:SongNoteData):Bool { - if (this.k == '') if (other.kind != '' && other.kind != 'normal') return false; + if (abstract.kind == '') + { + if (other.kind != '' && other.kind != 'normal') return false; + } + else + { + if (other.kind == '' || other.kind != abstract.kind) return false; + } - return this.t == other.time && this.d == other.data && this.l == other.length; + return abstract.time == other.time && abstract.data == other.data && abstract.length == other.length; } @:op(A != B) public function op_notEquals(other:SongNoteData):Bool { - return this.t != other.time || this.d != other.data || this.l != other.length || this.k != other.kind; + if (abstract.kind == '') + { + if (other.kind != '' && other.kind != 'normal') return true; + } + else + { + if (other.kind == '' || other.kind != abstract.kind) return true; + } + + return abstract.time != other.time || abstract.data != other.data || abstract.length != other.length; } @:op(A > B) public function op_greaterThan(other:SongNoteData):Bool { - return this.t > other.time; + return abstract.time > other.time; } @:op(A < B) @@ -587,7 +615,7 @@ abstract SongEventData(RawSongEventData) public function get_stepTime():Float { - return Conductor.getTimeInSteps(this.t); + return Conductor.getTimeInSteps(abstract.time); } public var event(get, set):String;