From d62042a99a66731d80e6a043bf85e66ae6198407 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 11 Dec 2023 17:38:16 -0500 Subject: [PATCH 01/37] skip transition into debug substate --- source/funkin/ui/debug/DebugMenuSubState.hx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index 404bf6f67..87977c85b 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -21,7 +21,9 @@ class DebugMenuSubState extends MusicBeatSubState override function create():Void { + FlxTransitionableState.skipNextTransIn = true; super.create(); + bgColor = 0x00000000; // Create an object for the camera to track. From 7058d9baa76c2b9a10dedb11a0c9ce419b976601 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 12 Dec 2023 23:28:16 -0500 Subject: [PATCH 02/37] stuf in progres --- source/funkin/ui/debug/DebugMenuSubState.hx | 7 ++++ .../funkin/ui/debug/latency/LatencyState.hx | 42 ++++++++++--------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index 87977c85b..11c2e3625 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -51,6 +51,7 @@ class DebugMenuSubState extends MusicBeatSubState // Create each menu item. // Call onMenuChange when the first item is created to move the camera . onMenuChange(createItem("CHART EDITOR", openChartEditor)); + createItem("Input Offset Testing", openInputOffsetTesting); createItem("ANIMATION EDITOR", openAnimationEditor); createItem("STAGE EDITOR", openStageEditor); createItem("TEST STICKERS", testStickers); @@ -92,6 +93,12 @@ class DebugMenuSubState extends MusicBeatSubState FlxG.switchState(new ChartEditorState()); } + function openInputOffsetTesting() + { + FlxG.switchState(new funkin.ui.debug.latency.LatencyState()); + trace('Input Offset Testing'); + } + function openAnimationEditor() { FlxG.switchState(new funkin.ui.debug.anim.DebugBoundingState()); diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 70ef97fd0..429884bb0 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -41,6 +41,10 @@ class LatencyState extends MusicBeatSubState override function create() { + super.create(); + + if (FlxG.sound.music != null) FlxG.sound.music.stop(); + swagSong = new HomemadeMusic(); swagSong.loadEmbedded(Paths.sound('soundTest'), true); @@ -66,8 +70,8 @@ class LatencyState extends MusicBeatSubState trace("\tFR FR PRESS: \t" + swagSong.getTimeWithDiff()); // trace("\tREDDIT: \t" + swagSong.frfrTime + " " + Timer.stamp()); - @:privateAccess - trace("\tREDDIT: \t" + FlxG.sound.music._channel.position + " " + Timer.stamp()); + // @:privateAccess + // trace("\tREDDIT: \t" + FlxG.sound.music._channel.position + " " + Timer.stamp()); // trace("EVENT LISTENER: " + key); }); @@ -91,14 +95,14 @@ class LatencyState extends MusicBeatSubState // // musSpec.visType = FREQUENCIES; // add(musSpec); - for (beat in 0...Math.floor(FlxG.sound.music.length / Conductor.instance.beatLengthMs)) + for (beat in 0...Math.floor(FlxG.sound.music.length / (Conductor.stepLengthMs * 2))) { - var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * Conductor.instance.beatLengthMs), FlxG.height - 15); + var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * (Conductor.stepLengthMs * 2)), FlxG.height - 15); beatTick.makeGraphic(2, 15); beatTick.alpha = 0.3; add(beatTick); - var offsetTxt:FlxText = new FlxText(songPosToX(beat * Conductor.instance.beatLengthMs), FlxG.height - 26, 0, "swag"); + var offsetTxt:FlxText = new FlxText(songPosToX(beat * (Conductor.stepLengthMs * 2)), FlxG.height - 26, 0, "swag"); offsetTxt.alpha = 0.5; diffGrp.add(offsetTxt); @@ -130,7 +134,7 @@ class LatencyState extends MusicBeatSubState for (i in 0...32) { - var note:NoteSprite = new NoteSprite(NoteStyleRegistry.instance.fetchDefault(), Conductor.instance.beatLengthMs * i); + var note:NoteSprite = new NoteSprite(NoteStyleRegistry.instance.fetchDefault(), (Conductor.stepLengthMs * 2) * i); noteGrp.add(note); } @@ -140,8 +144,6 @@ class LatencyState extends MusicBeatSubState strumLine = new FlxSprite(FlxG.width / 2, 100).makeGraphic(FlxG.width, 5); add(strumLine); - - super.create(); } override function stepHit():Bool @@ -183,12 +185,12 @@ class LatencyState extends MusicBeatSubState trace("\tUPDATE PRESS: \t" + FlxG.sound.music.time + " " + Timer.stamp()); } - if (FlxG.keys.justPressed.SPACE) - { - if (FlxG.sound.music.playing) FlxG.sound.music.pause(); - else - FlxG.sound.music.resume(); - } + // if (FlxG.keys.justPressed.SPACE) + // { + // if (FlxG.sound.music.playing) FlxG.sound.music.pause(); + // else + // FlxG.sound.music.resume(); + // } if (FlxG.keys.pressed.D) FlxG.sound.music.time += 1000 * FlxG.elapsed; @@ -217,7 +219,7 @@ class LatencyState extends MusicBeatSubState if (FlxG.keys.pressed.SHIFT) multiply = 1; - if (FlxG.keys.pressed.CONTROL) + if (FlxG.keys.pressed.CONTROL || FlxG.keys.pressed.SPACE) { if (FlxG.keys.justPressed.RIGHT) { @@ -250,7 +252,7 @@ class LatencyState extends MusicBeatSubState }*/ noteGrp.forEach(function(daNote:NoteSprite) { - daNote.y = (strumLine.y - ((Conductor.instance.songPosition - Conductor.instance.instrumentalOffset) - daNote.noteData.time) * 0.45); + daNote.y = (strumLine.y - ((Conductor.songPosition - Conductor.instrumentalOffset) - daNote.strumTime) * 0.45); daNote.x = strumLine.x + 30; if (daNote.y < strumLine.y) daNote.alpha = 0.5; @@ -269,12 +271,12 @@ class LatencyState extends MusicBeatSubState { Conductor.instance.update(swagSong.getTimeWithDiff()); - 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; + var closestBeat:Int = Math.round(Conductor.songPosition / (Conductor.stepLengthMs * 2)) % diffGrp.members.length; + var getDiff:Float = Conductor.songPosition - (closestBeat * (Conductor.stepLengthMs * 2)); + getDiff -= Conductor.inputOffset; // lil fix for end of song - if (closestBeat == 0 && getDiff >= Conductor.instance.beatLengthMs * 2) getDiff -= FlxG.sound.music.length; + if (closestBeat == 0 && getDiff >= Conductor.stepLengthMs * 2) getDiff -= FlxG.sound.music.length; trace("\tDISTANCE TO CLOSEST BEAT: " + getDiff + "ms"); trace("\tCLOSEST BEAT: " + closestBeat); From e323f46569798bac31d9973648208265aa99aa7e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 8 Jan 2024 15:46:16 -0500 Subject: [PATCH 03/37] conductor.instance fixes --- source/funkin/ui/debug/latency/LatencyState.hx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 429884bb0..c1321f19c 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -95,14 +95,14 @@ class LatencyState extends MusicBeatSubState // // musSpec.visType = FREQUENCIES; // add(musSpec); - for (beat in 0...Math.floor(FlxG.sound.music.length / (Conductor.stepLengthMs * 2))) + for (beat in 0...Math.floor(FlxG.sound.music.length / (Conductor.instance.stepLengthMs * 2))) { - var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * (Conductor.stepLengthMs * 2)), FlxG.height - 15); + var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * (Conductor.instance.stepLengthMs * 2)), FlxG.height - 15); beatTick.makeGraphic(2, 15); beatTick.alpha = 0.3; add(beatTick); - var offsetTxt:FlxText = new FlxText(songPosToX(beat * (Conductor.stepLengthMs * 2)), FlxG.height - 26, 0, "swag"); + var offsetTxt:FlxText = new FlxText(songPosToX(beat * (Conductor.instance.stepLengthMs * 2)), FlxG.height - 26, 0, "swag"); offsetTxt.alpha = 0.5; diffGrp.add(offsetTxt); @@ -134,7 +134,7 @@ class LatencyState extends MusicBeatSubState for (i in 0...32) { - var note:NoteSprite = new NoteSprite(NoteStyleRegistry.instance.fetchDefault(), (Conductor.stepLengthMs * 2) * i); + var note:NoteSprite = new NoteSprite(NoteStyleRegistry.instance.fetchDefault(), (Conductor.instance.stepLengthMs * 2) * i); noteGrp.add(note); } @@ -252,7 +252,7 @@ class LatencyState extends MusicBeatSubState }*/ noteGrp.forEach(function(daNote:NoteSprite) { - daNote.y = (strumLine.y - ((Conductor.songPosition - Conductor.instrumentalOffset) - daNote.strumTime) * 0.45); + daNote.y = (strumLine.y - ((Conductor.instance.songPosition - Conductor.instance.instrumentalOffset) - daNote.strumTime) * 0.45); daNote.x = strumLine.x + 30; if (daNote.y < strumLine.y) daNote.alpha = 0.5; @@ -271,12 +271,12 @@ class LatencyState extends MusicBeatSubState { Conductor.instance.update(swagSong.getTimeWithDiff()); - var closestBeat:Int = Math.round(Conductor.songPosition / (Conductor.stepLengthMs * 2)) % diffGrp.members.length; - var getDiff:Float = Conductor.songPosition - (closestBeat * (Conductor.stepLengthMs * 2)); - getDiff -= Conductor.inputOffset; + var closestBeat:Int = Math.round(Conductor.instance.songPosition / (Conductor.instance.stepLengthMs * 2)) % diffGrp.members.length; + var getDiff:Float = Conductor.instance.songPosition - (closestBeat * (Conductor.instance.stepLengthMs * 2)); + getDiff -= Conductor.instance.inputOffset; // lil fix for end of song - if (closestBeat == 0 && getDiff >= Conductor.stepLengthMs * 2) getDiff -= FlxG.sound.music.length; + if (closestBeat == 0 && getDiff >= Conductor.instance.stepLengthMs * 2) getDiff -= FlxG.sound.music.length; trace("\tDISTANCE TO CLOSEST BEAT: " + getDiff + "ms"); trace("\tCLOSEST BEAT: " + closestBeat); From 5d0c1521d58c4819b14847d620feb1064e556014 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 9 Jan 2024 13:16:00 -0500 Subject: [PATCH 04/37] strumline refactor stuffy --- source/funkin/play/PlayState.hx | 110 +----------------- source/funkin/play/notes/Strumline.hx | 81 +++++++++++++ source/funkin/ui/debug/DebugMenuSubState.hx | 4 +- .../funkin/ui/debug/latency/CoolStatsGraph.hx | 33 ++++-- .../funkin/ui/debug/latency/LatencyState.hx | 76 +++++------- 5 files changed, 142 insertions(+), 162 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 995797dd1..1eaad0b06 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -1791,63 +1791,7 @@ class PlayState extends MusicBeatSubState { if (playerStrumline?.notes?.members == null || opponentStrumline?.notes?.members == null) return; - // Process notes on the opponent's side. - for (note in opponentStrumline.notes.members) - { - if (note == null) continue; - - var hitWindowStart = note.strumTime - Constants.HIT_WINDOW_MS; - var hitWindowCenter = note.strumTime; - var hitWindowEnd = note.strumTime + Constants.HIT_WINDOW_MS; - - if (Conductor.instance.songPosition > hitWindowEnd) - { - if (note.hasMissed) continue; - - note.tooEarly = false; - note.mayHit = false; - note.hasMissed = true; - - if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = true; - } - else if (Conductor.instance.songPosition > hitWindowCenter) - { - if (note.hasBeenHit) continue; - - // Call an event to allow canceling the note hit. - // NOTE: This is what handles the character animations! - var event:NoteScriptEvent = new NoteScriptEvent(NOTE_HIT, note, 0, true); - dispatchEvent(event); - - // Calling event.cancelEvent() skips all the other logic! Neat! - if (event.eventCanceled) continue; - - // Command the opponent to hit the note on time. - // NOTE: This is what handles the strumline and cleaning up the note itself! - opponentStrumline.hitNote(note); - - if (note.holdNoteSprite != null) - { - opponentStrumline.playNoteHoldCover(note.holdNoteSprite); - } - } - else if (Conductor.instance.songPosition > hitWindowStart) - { - if (note.hasBeenHit || note.hasMissed) continue; - - note.tooEarly = false; - note.mayHit = true; - note.hasMissed = false; - if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false; - } - else - { - note.tooEarly = true; - note.mayHit = false; - note.hasMissed = false; - if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false; - } - } + opponentStrumline.processNotes(null, dispatchEvent); // Process hold notes on the opponent's side. for (holdNote in opponentStrumline.holdNotes.members) @@ -1868,57 +1812,7 @@ class PlayState extends MusicBeatSubState // if (holdNote.missedNote && !holdNote.handledMiss) { holdNote.handledMiss = true; } } - // Process notes on the player's side. - for (note in playerStrumline.notes.members) - { - if (note == null || note.hasBeenHit) continue; - - var hitWindowStart = note.strumTime - Constants.HIT_WINDOW_MS; - var hitWindowCenter = note.strumTime; - var hitWindowEnd = note.strumTime + Constants.HIT_WINDOW_MS; - - 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.instance.songPosition > hitWindowStart) - { - note.tooEarly = false; - note.mayHit = true; - note.hasMissed = false; - if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false; - } - else - { - note.tooEarly = true; - note.mayHit = false; - note.hasMissed = false; - if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false; - } - - // This becomes true when the note leaves the hit window. - // It might still be on screen. - if (note.hasMissed && !note.handledMiss) - { - // Call an event to allow canceling the note miss. - // NOTE: This is what handles the character animations! - var event:NoteScriptEvent = new NoteScriptEvent(NOTE_MISS, note, 0, true); - dispatchEvent(event); - - // Calling event.cancelEvent() skips all the other logic! Neat! - if (event.eventCanceled) continue; - - // Judge the miss. - // NOTE: This is what handles the scoring. - trace('Missed note! ${note.noteData}'); - onNoteMiss(note); - - note.handledMiss = true; - } - } + playerStrumline.processNotes(onNoteMiss, dispatchEvent); // Process hold notes on the player's side. // This handles scoring so we don't need it on the opponent's side. diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index b312494cf..b0ab1ba1c 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -14,6 +14,7 @@ import funkin.play.notes.SustainTrail; import funkin.data.song.SongData.SongNoteData; import funkin.ui.options.PreferencesMenu; import funkin.util.SortUtil; +import funkin.modding.events.ScriptEvent; /** * A group of sprites which handles the receptor, the note splashes, and the notes (with sustains) for a given player. @@ -142,6 +143,86 @@ class Strumline extends FlxSpriteGroup updateNotes(); } + /** + * Process the notes in this strumline. + * @param onNoteMiss + * @param dispatchEvent TODO: better way to do this? Maybe passing in current dispatchEvent function from current state? + */ + public function processNotes(?onNoteMiss:NoteSprite->Void, ?dispatchEvent:ScriptEvent->Void) + { + for (note in notes.members) + { + if (note == null || (isPlayer && note.hasBeenHit)) continue; + + var hitWindowStart = note.strumTime - Constants.HIT_WINDOW_MS; + var hitWindowCenter = note.strumTime; + var hitWindowEnd = note.strumTime + Constants.HIT_WINDOW_MS; + + if (Conductor.instance.songPosition > hitWindowEnd) + { + if (!isPlayer && note.hasMissed) continue; + + note.tooEarly = false; + note.mayHit = false; + note.hasMissed = true; + + if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = true; + } + else if (Conductor.instance.songPosition > hitWindowCenter) + { + // only run this on opponent strumlines! + if (!isPlayer) continue; + + // Call an event to allow canceling the note hit. + // NOTE: This is what handles the character animations! + var event:NoteScriptEvent = new NoteScriptEvent(NOTE_HIT, note, 0, true); + if (dispatchEvent != null) dispatchEvent(event); + + // Calling event.cancelEvent() skips all other logic! Neat! + if (event.eventCanceled) continue; + + // Command the opponent to hit the note on time. + // NOTE: This is what handles the strumline and cleaning up the note itself! + + hitNote(note); + + if (note.holdNoteSprite != null) + { + playNoteHoldCover(note.holdNoteSprite); + } + } + else if (Conductor.instance.songPosition > hitWindowStart) + { + if (!isPlayer && (note.hasBeenHit || note.hasMissed)) continue; + + note.tooEarly = false; + note.mayHit = true; + note.hasMissed = false; + if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false; + } + else + { + note.tooEarly = true; + note.mayHit = false; + note.hasMissed = false; + if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false; + } + + if (note.hasMissed && !note.handledMiss) + { + var event:NoteScriptEvent = new NoteScriptEvent(NOTE_MISS, note, 0, true); + + if (dispatchEvent != null) dispatchEvent(event); + + if (event.eventCanceled) continue; + + if (onNoteMiss != null) onNoteMiss(note); + + note.handledMiss = true; + } + } + } + var frameMax:Int; var animFinishedEver:Bool; diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index 11c2e3625..f797dfbad 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -48,6 +48,8 @@ class DebugMenuSubState extends MusicBeatSubState items.onChange.add(onMenuChange); add(items); + FlxTransitionableState.skipNextTransIn = true; + // Create each menu item. // Call onMenuChange when the first item is created to move the camera . onMenuChange(createItem("CHART EDITOR", openChartEditor)); @@ -88,8 +90,6 @@ class DebugMenuSubState extends MusicBeatSubState function openChartEditor() { - FlxTransitionableState.skipNextTransIn = true; - FlxG.switchState(new ChartEditorState()); } diff --git a/source/funkin/ui/debug/latency/CoolStatsGraph.hx b/source/funkin/ui/debug/latency/CoolStatsGraph.hx index 01689f494..fc733ec28 100644 --- a/source/funkin/ui/debug/latency/CoolStatsGraph.hx +++ b/source/funkin/ui/debug/latency/CoolStatsGraph.hx @@ -7,7 +7,6 @@ import flash.text.TextField; import flash.text.TextFormatAlign; import flixel.math.FlxMath; import flixel.system.debug.DebuggerUtil; -import flixel.system.debug.stats.Stats; import flixel.util.FlxColor; import flixel.util.FlxDestroyUtil; @@ -16,13 +15,31 @@ import flixel.util.FlxDestroyUtil; * SHAMELESSLY STOLEN FROM FLIXEL * https://github.com/HaxeFlixel/flixel/blob/master/flixel/system/debug/stats/StatsGraph.hx */ -#if FLX_DEBUG class CoolStatsGraph extends Sprite { static inline var AXIS_COLOR:FlxColor = 0xffffff; static inline var AXIS_ALPHA:Float = 0.5; static inline var HISTORY_MAX:Int = 500; + /** + * How often to update the stats, in ms. The lower, the more performance-intense! + */ + static inline var UPDATE_DELAY:Int = 250; + + /** + * The initial width of the stats window. + */ + static inline var INITIAL_WIDTH:Int = 160; + + static inline var FPS_COLOR:FlxColor = 0xff96ff00; + static inline var MEMORY_COLOR:FlxColor = 0xff009cff; + static inline var DRAW_TIME_COLOR:FlxColor = 0xffA60004; + static inline var UPDATE_TIME_COLOR:FlxColor = 0xffdcd400; + + public static inline var LABEL_COLOR:FlxColor = 0xaaffffff; + public static inline var TEXT_SIZE:Int = 11; + public static inline var DECIMALS:Int = 1; + public var minLabel:TextField; public var curLabel:TextField; public var maxLabel:TextField; @@ -45,6 +62,7 @@ class CoolStatsGraph extends Sprite public function new(X:Int, Y:Int, Width:Int, Height:Int, GraphColor:FlxColor, Unit:String, LabelWidth:Int = 45, ?Label:String) { super(); + x = X; y = Y; _width = Width - LabelWidth; @@ -57,11 +75,11 @@ class CoolStatsGraph extends Sprite _axis = new Shape(); _axis.x = _labelWidth + 10; - maxLabel = DebuggerUtil.createTextField(0, 0, Stats.LABEL_COLOR, Stats.TEXT_SIZE); - curLabel = DebuggerUtil.createTextField(0, (_height / 2) - (Stats.TEXT_SIZE / 2), graphColor, Stats.TEXT_SIZE); - minLabel = DebuggerUtil.createTextField(0, _height - Stats.TEXT_SIZE, Stats.LABEL_COLOR, Stats.TEXT_SIZE); + maxLabel = DebuggerUtil.createTextField(0, 0, LABEL_COLOR, TEXT_SIZE); + curLabel = DebuggerUtil.createTextField(0, (_height / 2) - (TEXT_SIZE / 2), graphColor, TEXT_SIZE); + minLabel = DebuggerUtil.createTextField(0, _height - TEXT_SIZE, LABEL_COLOR, TEXT_SIZE); - avgLabel = DebuggerUtil.createTextField(_labelWidth + 20, (_height / 2) - (Stats.TEXT_SIZE / 2) - 10, Stats.LABEL_COLOR, Stats.TEXT_SIZE); + avgLabel = DebuggerUtil.createTextField(_labelWidth + 20, (_height / 2) - (TEXT_SIZE / 2) - 10, LABEL_COLOR, TEXT_SIZE); avgLabel.width = _width; avgLabel.defaultTextFormat.align = TextFormatAlign.CENTER; avgLabel.alpha = 0.5; @@ -136,7 +154,7 @@ class CoolStatsGraph extends Sprite function formatValue(value:Float):String { - return FlxMath.roundDecimal(value, Stats.DECIMALS) + " " + _unit; + return FlxMath.roundDecimal(value, DECIMALS) + " " + _unit; } public function average():Float @@ -157,4 +175,3 @@ class CoolStatsGraph extends Sprite history = null; } } -#end diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index c1321f19c..ae922612b 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -8,7 +8,6 @@ import flixel.group.FlxGroup.FlxTypedGroup; import flixel.math.FlxMath; import funkin.ui.MusicBeatSubState; import flixel.sound.FlxSound; -import flixel.system.debug.stats.StatsGraph; import flixel.text.FlxText; import flixel.util.FlxColor; import funkin.audio.visualize.PolygonSpectogram; @@ -16,12 +15,17 @@ import funkin.play.notes.NoteSprite; import funkin.ui.debug.latency.CoolStatsGraph; import haxe.Timer; import openfl.events.KeyboardEvent; +import funkin.input.PreciseInputManager; +import funkin.play.notes.Strumline; +import funkin.play.notes.notestyle.NoteStyle; +import funkin.data.notestyle.NoteStyleData; +import funkin.data.notestyle.NoteStyleRegistry; class LatencyState extends MusicBeatSubState { var offsetText:FlxText; var noteGrp:FlxTypedGroup; - var strumLine:FlxSprite; + var strumLine:Strumline; var blocks:FlxTypedGroup; @@ -34,10 +38,8 @@ class LatencyState extends MusicBeatSubState var offsetsPerBeat:Array = []; var swagSong:HomemadeMusic; - #if FLX_DEBUG var funnyStatsGraph:CoolStatsGraph; var realStats:CoolStatsGraph; - #end override function create() { @@ -51,33 +53,24 @@ class LatencyState extends MusicBeatSubState FlxG.sound.music = swagSong; FlxG.sound.music.play(); - #if FLX_DEBUG - funnyStatsGraph = new CoolStatsGraph(0, Std.int(FlxG.height / 2), FlxG.width, Std.int(FlxG.height / 2), FlxColor.PINK, "time"); + funnyStatsGraph = new CoolStatsGraph(0, Std.int(FlxG.height / 3), Std.int(FlxG.width / 2), Std.int(FlxG.height / 3), FlxColor.PINK, "time"); + funnyStatsGraph.curLabel.y += 32; FlxG.addChildBelowMouse(funnyStatsGraph); - realStats = new CoolStatsGraph(0, Std.int(FlxG.height / 2), FlxG.width, Std.int(FlxG.height / 2), FlxColor.YELLOW, "REAL"); + realStats = new CoolStatsGraph(0, Std.int(FlxG.height / 3), Std.int(FlxG.width / 2), Std.int(FlxG.height / 3), FlxColor.YELLOW, "REAL"); + realStats.curLabel.y -= 32; FlxG.addChildBelowMouse(realStats); - #end - FlxG.stage.addEventListener(KeyboardEvent.KEY_DOWN, key -> { - trace(key.charCode); - - if (key.charCode == 120) generateBeatStuff(); - - trace("\tEVENT PRESS: \t" + FlxG.sound.music.time + " " + Timer.stamp()); - // trace(FlxG.sound.music.prevTimestamp); - trace(FlxG.sound.music.time); - trace("\tFR FR PRESS: \t" + swagSong.getTimeWithDiff()); - - // trace("\tREDDIT: \t" + swagSong.frfrTime + " " + Timer.stamp()); - // @:privateAccess - // trace("\tREDDIT: \t" + FlxG.sound.music._channel.position + " " + Timer.stamp()); - // trace("EVENT LISTENER: " + key); + PreciseInputManager.instance.onInputPressed.add(function(event:PreciseInputEvent) { + strumLine.pressKey(event.noteDirection); + strumLine.playPress(event.noteDirection); + generateBeatStuff(event); }); - // FlxG.sound.playMusic(Paths.sound('soundTest')); - - // funnyStatsGraph.hi + PreciseInputManager.instance.onInputReleased.add(function(event:PreciseInputEvent) { + strumLine.playStatic(event.noteDirection); + strumLine.releaseKey(event.noteDirection); + }); Conductor.instance.forceBPM(60); @@ -139,10 +132,11 @@ class LatencyState extends MusicBeatSubState } offsetText = new FlxText(); + offsetText.size = 20; offsetText.screenCenter(); add(offsetText); - strumLine = new FlxSprite(FlxG.width / 2, 100).makeGraphic(FlxG.width, 5); + strumLine = new Strumline(NoteStyleRegistry.instance.fetchDefault(), true); add(strumLine); } @@ -175,15 +169,8 @@ class LatencyState extends MusicBeatSubState trace(FlxG.sound.music._channel.position); */ - #if FLX_DEBUG - funnyStatsGraph.update(FlxG.sound.music.time % 500); + funnyStatsGraph.update(Conductor.instance.songPosition % 500); realStats.update(swagSong.getTimeWithDiff() % 500); - #end - - if (FlxG.keys.justPressed.S) - { - trace("\tUPDATE PRESS: \t" + FlxG.sound.music.time + " " + Timer.stamp()); - } // if (FlxG.keys.justPressed.SPACE) // { @@ -192,17 +179,15 @@ class LatencyState extends MusicBeatSubState // FlxG.sound.music.resume(); // } - if (FlxG.keys.pressed.D) FlxG.sound.music.time += 1000 * FlxG.elapsed; - - Conductor.instance.update(swagSong.getTimeWithDiff() - Conductor.instance.inputOffset); + Conductor.instance.update(); // Conductor.instance.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp; 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.instance.instrumentalOffset + "ms"; - offsetText.text += "\nINPUT Offset: " + Conductor.instance.inputOffset + "ms"; + offsetText.text = "INST Offset (CTRL+Left/Right to change): " + Conductor.instance.instrumentalOffset + "ms"; + offsetText.text += "\nINPUT Offset (Left/Right to change): " + Conductor.instance.inputOffset + "ms"; offsetText.text += "\ncurrentStep: " + Conductor.instance.currentStep; offsetText.text += "\ncurrentBeat: " + Conductor.instance.currentBeat; @@ -267,19 +252,23 @@ class LatencyState extends MusicBeatSubState super.update(elapsed); } - function generateBeatStuff() + function generateBeatStuff(event:PreciseInputEvent) { - Conductor.instance.update(swagSong.getTimeWithDiff()); + // Conductor.instance.update(swagSong.getTimeWithDiff()); + + var inputLatencyMs:Float = haxe.Int64.toInt(PreciseInputManager.getCurrentTimestamp() - event.timestamp) / 1000.0 / 1000.0; + trace("input latency: " + inputLatencyMs + "ms"); + trace("cur timestamp: " + PreciseInputManager.getCurrentTimestamp() + "ns"); + trace("event timestamp: " + event.timestamp + "ns"); var closestBeat:Int = Math.round(Conductor.instance.songPosition / (Conductor.instance.stepLengthMs * 2)) % diffGrp.members.length; var getDiff:Float = Conductor.instance.songPosition - (closestBeat * (Conductor.instance.stepLengthMs * 2)); getDiff -= Conductor.instance.inputOffset; + getDiff -= inputLatencyMs; // lil fix for end of song if (closestBeat == 0 && getDiff >= Conductor.instance.stepLengthMs * 2) getDiff -= FlxG.sound.music.length; - trace("\tDISTANCE TO CLOSEST BEAT: " + getDiff + "ms"); - trace("\tCLOSEST BEAT: " + closestBeat); beatTrail.x = songPosVis.x; diffGrp.members[closestBeat].text = getDiff + "ms"; @@ -295,7 +284,6 @@ class LatencyState extends MusicBeatSubState class HomemadeMusic extends FlxSound { public var prevTimestamp:Int = 0; - public var timeWithDiff:Float = 0; public function new() { From d9a6bead77d467a236913496ac244d8c091bf5b6 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 9 Jan 2024 19:41:25 -0500 Subject: [PATCH 05/37] inputOffset + audioVisualOffset in Save class --- Project.xml | 2 +- source/funkin/save/Save.hx | 16 +++++++++++++++- source/funkin/save/changelog.md | 12 ++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 source/funkin/save/changelog.md diff --git a/Project.xml b/Project.xml index e0677b026..fc6ebf085 100644 --- a/Project.xml +++ b/Project.xml @@ -127,7 +127,7 @@ - + diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 810d0fd93..6753419b7 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -15,7 +15,7 @@ import thx.semver.Version; abstract Save(RawSaveData) { // Version 2.0.1 adds attributes to `optionsChartEditor`, that should return default values if they are null. - public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.1"; + public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.2"; public static final SAVE_DATA_VERSION_RULE:thx.semver.VersionRule = "2.0.x"; // We load this version's saves from a new save path, to maintain SOME level of backwards compatibility. @@ -72,6 +72,8 @@ abstract Save(RawSaveData) zoomCamera: true, debugDisplay: false, autoPause: true, + inputOffset: 0, + audioVisualOffset: 0, controls: { @@ -828,6 +830,18 @@ typedef SaveDataOptions = */ var autoPause:Bool; + /** + * Offset the users inputs by this many ms. + * @default `0` + */ + var inputOffset:Int; + + /** + * Affects the delay between the audio and the visuals during gameplay + * @default `0` + */ + var audioVisualOffset:Int; + var controls: { var p1: diff --git a/source/funkin/save/changelog.md b/source/funkin/save/changelog.md new file mode 100644 index 000000000..3fa9839d1 --- /dev/null +++ b/source/funkin/save/changelog.md @@ -0,0 +1,12 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + +## [2.0.3] - 2024-01-09 +### Added +- `inputOffset:Float` to `SongDataOptions` +- `audioVisualOffset:Float` to `SongDataOptions` From 3544f2a804866ea248dceb95f3e13a30d1a84852 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 9 Jan 2024 19:48:01 -0500 Subject: [PATCH 06/37] input offset get/set functions in conductor --- source/funkin/Conductor.hx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 05c23108f..6113baf23 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -209,7 +209,17 @@ class Conductor /** * An offset set by the user to compensate for input lag. */ - public var inputOffset:Float = 0; + public var inputOffset(get, set):Float; + + function get_inputOffset():Float + { + return Save.get().options.inputOffset; + } + + function set_inputOffset(value:Float):Float + { + return Save.get().options.inputOffset = value; + } /** * The number of beats in a measure. May be fractional depending on the time signature. From b11bf096870cc1d4b54c7278f01f6c6b437d5d14 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 9 Jan 2024 19:57:33 -0500 Subject: [PATCH 07/37] save/load for inputOffsets --- source/funkin/Conductor.hx | 11 +++++++---- source/funkin/ui/debug/latency/LatencyState.hx | 10 +++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 6113baf23..2ca144a2d 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -6,6 +6,7 @@ import flixel.math.FlxMath; import funkin.play.song.Song.SongDifficulty; import funkin.data.song.SongData.SongTimeChange; import funkin.data.song.SongDataUtils; +import funkin.save.Save; /** * A core class which handles musical timing throughout the game, @@ -209,16 +210,18 @@ class Conductor /** * An offset set by the user to compensate for input lag. */ - public var inputOffset(get, set):Float; + public var inputOffset(get, set):Int; - function get_inputOffset():Float + function get_inputOffset():Int { return Save.get().options.inputOffset; } - function set_inputOffset(value:Float):Float + function set_inputOffset(value:Int):Int { - return Save.get().options.inputOffset = value; + Save.get().options.inputOffset = value; + Save.get().flush(); + return Save.get().options.inputOffset; } /** diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index ae922612b..84425d4a0 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -200,7 +200,7 @@ class LatencyState extends MusicBeatSubState offsetText.text += "\naverage input offset needed: " + avgOffsetInput; - var multiply:Float = 10; + var multiply:Int = 10; if (FlxG.keys.pressed.SHIFT) multiply = 1; @@ -208,24 +208,24 @@ class LatencyState extends MusicBeatSubState { if (FlxG.keys.justPressed.RIGHT) { - Conductor.instance.instrumentalOffset += 1.0 * multiply; + Conductor.instance.instrumentalOffset += 1 * multiply; } if (FlxG.keys.justPressed.LEFT) { - Conductor.instance.instrumentalOffset -= 1.0 * multiply; + Conductor.instance.instrumentalOffset -= 1 * multiply; } } else { if (FlxG.keys.justPressed.RIGHT) { - Conductor.instance.inputOffset += 1.0 * multiply; + Conductor.instance.inputOffset += 1 * multiply; } if (FlxG.keys.justPressed.LEFT) { - Conductor.instance.inputOffset -= 1.0 * multiply; + Conductor.instance.inputOffset -= 1 * multiply; } } From 53d3db200751dbad221771307268d8d6b06676c9 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 16 Jan 2024 04:06:56 -0500 Subject: [PATCH 08/37] assets subjod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index b282f3431..d094640f7 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b282f3431c15b719222196813da98ab70839d3e5 +Subproject commit d094640f727a670a348b3579d11af5ff6a2ada3a From 1dcd0debc728a6ab18c3a688a0336dcca37cfb0e Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 16 Jan 2024 05:37:06 -0500 Subject: [PATCH 09/37] conductor stuff --- source/funkin/Conductor.hx | 25 +++++++ .../funkin/ui/debug/latency/LatencyState.hx | 72 +++++++++---------- 2 files changed, 58 insertions(+), 39 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 2ca144a2d..7a4f76924 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -7,6 +7,7 @@ import funkin.play.song.Song.SongDifficulty; import funkin.data.song.SongData.SongTimeChange; import funkin.data.song.SongDataUtils; import funkin.save.Save; +import haxe.Timer; /** * A core class which handles musical timing throughout the game, @@ -71,6 +72,9 @@ class Conductor */ public var songPosition(default, null):Float = 0; + var prevTimestamp:Float = 0; + var prevTime:Float = 0; + /** * Beats per minute of the current song at the current time. */ @@ -349,6 +353,27 @@ class Conductor Conductor.measureHit.dispatch(); } } + + // only update the timestamp if songPosition actually changed + // which it doesn't do every frame! + if (prevTime != this.songPosition) + { + // Update the timestamp for use in-between frames + prevTime = this.songPosition; + prevTimestamp = Std.int(Timer.stamp() * 1000); + } + } + + /** + * Can be called in-between frames, usually for input related things + * that can potentially get processed on exact milliseconds/timestmaps. + * If you need song position, use `Conductor.instance.songPosition` instead + * for use in update() related functions. + * @return Float + */ + public function getTimeWithDiff():Float + { + return this.songPosition + (Std.int(Timer.stamp() * 1000) - prevTimestamp); } public function mapTimeChanges(songTimeChanges:Array) diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 84425d4a0..d3f7bb7b6 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -13,18 +13,19 @@ import flixel.util.FlxColor; import funkin.audio.visualize.PolygonSpectogram; import funkin.play.notes.NoteSprite; import funkin.ui.debug.latency.CoolStatsGraph; -import haxe.Timer; import openfl.events.KeyboardEvent; import funkin.input.PreciseInputManager; import funkin.play.notes.Strumline; import funkin.play.notes.notestyle.NoteStyle; import funkin.data.notestyle.NoteStyleData; import funkin.data.notestyle.NoteStyleRegistry; +import funkin.data.song.SongData.SongNoteData; +import haxe.Timer; class LatencyState extends MusicBeatSubState { var offsetText:FlxText; - var noteGrp:FlxTypedGroup; + var noteGrp:Array; var strumLine:Strumline; var blocks:FlxTypedGroup; @@ -74,8 +75,7 @@ class LatencyState extends MusicBeatSubState Conductor.instance.forceBPM(60); - noteGrp = new FlxTypedGroup(); - add(noteGrp); + noteGrp = []; diffGrp = new FlxTypedGroup(); add(diffGrp); @@ -125,12 +125,6 @@ class LatencyState extends MusicBeatSubState blocks.add(block); } - for (i in 0...32) - { - var note:NoteSprite = new NoteSprite(NoteStyleRegistry.instance.fetchDefault(), (Conductor.instance.stepLengthMs * 2) * i); - noteGrp.add(note); - } - offsetText = new FlxText(); offsetText.size = 20; offsetText.screenCenter(); @@ -138,6 +132,19 @@ class LatencyState extends MusicBeatSubState strumLine = new Strumline(NoteStyleRegistry.instance.fetchDefault(), true); add(strumLine); + + regenNoteData(); + } + + function regenNoteData() + { + for (i in 0...32) + { + var note:SongNoteData = new SongNoteData((Conductor.instance.stepLengthMs * 2) * i, 1); + noteGrp.push(note); + } + + strumLine.applyNoteData(noteGrp); } override function stepHit():Bool @@ -169,17 +176,11 @@ class LatencyState extends MusicBeatSubState trace(FlxG.sound.music._channel.position); */ - funnyStatsGraph.update(Conductor.instance.songPosition % 500); - realStats.update(swagSong.getTimeWithDiff() % 500); - - // if (FlxG.keys.justPressed.SPACE) - // { - // if (FlxG.sound.music.playing) FlxG.sound.music.pause(); - // else - // FlxG.sound.music.resume(); - // } - Conductor.instance.update(); + + funnyStatsGraph.update(Conductor.instance.songPosition % 500); + realStats.update(Conductor.instance.getTimeWithDiff() % 500); + // Conductor.instance.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp; songPosVis.x = songPosToX(Conductor.instance.songPosition); @@ -229,25 +230,18 @@ class LatencyState extends MusicBeatSubState } } - /* if (FlxG.keys.justPressed.SPACE) - { - FlxG.sound.music.stop(); + // noteGrp.forEach(function(daNote:NoteSprite) { + // daNote.y = (strumLine.y - ((Conductor.instance.songPosition - Conductor.instance.instrumentalOffset) - daNote.strumTime) * 0.45); + // daNote.x = strumLine.x + 30; - FlxG.resetState(); - }*/ + // if (daNote.y < strumLine.y) daNote.alpha = 0.5; - noteGrp.forEach(function(daNote:NoteSprite) { - daNote.y = (strumLine.y - ((Conductor.instance.songPosition - Conductor.instance.instrumentalOffset) - daNote.strumTime) * 0.45); - daNote.x = strumLine.x + 30; - - if (daNote.y < strumLine.y) daNote.alpha = 0.5; - - if (daNote.y < 0 - daNote.height) - { - daNote.alpha = 1; - // daNote.data.strumTime += Conductor.instance.beatLengthMs * 8; - } - }); + // if (daNote.y < 0 - daNote.height) + // { + // daNote.alpha = 1; + // // daNote.data.strumTime += Conductor.instance.beatLengthMs * 8; + // } + // }); super.update(elapsed); } @@ -261,8 +255,8 @@ class LatencyState extends MusicBeatSubState trace("cur timestamp: " + PreciseInputManager.getCurrentTimestamp() + "ns"); trace("event timestamp: " + event.timestamp + "ns"); - var closestBeat:Int = Math.round(Conductor.instance.songPosition / (Conductor.instance.stepLengthMs * 2)) % diffGrp.members.length; - var getDiff:Float = Conductor.instance.songPosition - (closestBeat * (Conductor.instance.stepLengthMs * 2)); + var closestBeat:Int = Math.round(Conductor.instance.getTimeWithDiff() / (Conductor.instance.stepLengthMs * 2)) % diffGrp.members.length; + var getDiff:Float = Conductor.instance.getTimeWithDiff() - (closestBeat * (Conductor.instance.stepLengthMs * 2)); getDiff -= Conductor.instance.inputOffset; getDiff -= inputLatencyMs; From df2c01b2ff8dc4b7b28c7b70d897cd078b5df7e1 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 27 Jan 2024 06:16:39 -0500 Subject: [PATCH 10/37] crackhead activity in progress --- .vscode/tasks.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 16a77646f..be4414ea0 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,13 +1,13 @@ { - "version": "2.0.0", - "tasks": [ - { - "type": "lime", - "command": "test", - "group": { - "kind": "build", - "isDefault": true - } - } - ] + "version": "2.0.0", + "tasks": [ + { + "type": "lime", + "command": "test", + "group": { + "kind": "build", + "isDefault": true + } + } + ] } From c44e33c5568fd27ebe633695f4879f4ab74f61d9 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 27 Jan 2024 06:16:46 -0500 Subject: [PATCH 11/37] derp --- .vscode/launch.json | 6 ++++++ assets | 2 +- source/funkin/Conductor.hx | 8 +++++++- source/funkin/ui/debug/latency/LatencyState.hx | 14 +++----------- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 74f72b826..afc0ab8db 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,6 +7,12 @@ "type": "lime", "request": "launch" }, + { + "name": "Debug", + "type": "lime", + "request": "launch", + "preLaunchTask": null + }, { // Launch in browser "name": "HTML5 Debug", diff --git a/assets b/assets index d094640f7..b2f8b6a78 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit d094640f727a670a348b3579d11af5ff6a2ada3a +Subproject commit b2f8b6a780316959d0a79adc6dbf61f9e4ca675f diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 7a4f76924..75031f6dd 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -373,7 +373,13 @@ class Conductor */ public function getTimeWithDiff():Float { - return this.songPosition + (Std.int(Timer.stamp() * 1000) - prevTimestamp); + // trace(this.songPosition); + + @:privateAccess + this.songPosition = FlxG.sound.music._channel.position; + // return this.songPosition + (Std.int(Timer.stamp() * 1000) - prevTimestamp); + // trace("\t--> " + this.songPosition); + return this.songPosition; } public function mapTimeChanges(songTimeChanges:Array) diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index d3f7bb7b6..f75ac16bc 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -63,9 +63,9 @@ class LatencyState extends MusicBeatSubState FlxG.addChildBelowMouse(realStats); PreciseInputManager.instance.onInputPressed.add(function(event:PreciseInputEvent) { + generateBeatStuff(event); strumLine.pressKey(event.noteDirection); strumLine.playPress(event.noteDirection); - generateBeatStuff(event); }); PreciseInputManager.instance.onInputReleased.add(function(event:PreciseInputEvent) { @@ -80,14 +80,6 @@ class LatencyState extends MusicBeatSubState diffGrp = new FlxTypedGroup(); add(diffGrp); - // var musSpec:PolygonSpectogram = new PolygonSpectogram(FlxG.sound.music, FlxColor.RED, FlxG.height, Math.floor(FlxG.height / 2)); - // musSpec.x += 170; - // musSpec.scrollFactor.set(); - // musSpec.waveAmplitude = 100; - // musSpec.realtimeVisLenght = 0.45; - // // musSpec.visType = FREQUENCIES; - // add(musSpec); - for (beat in 0...Math.floor(FlxG.sound.music.length / (Conductor.instance.stepLengthMs * 2))) { var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * (Conductor.instance.stepLengthMs * 2)), FlxG.height - 15); @@ -178,7 +170,7 @@ class LatencyState extends MusicBeatSubState Conductor.instance.update(); - funnyStatsGraph.update(Conductor.instance.songPosition % 500); + funnyStatsGraph.update(swagSong.getTimeWithDiff() % 500); realStats.update(Conductor.instance.getTimeWithDiff() % 500); // Conductor.instance.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp; @@ -266,7 +258,7 @@ class LatencyState extends MusicBeatSubState beatTrail.x = songPosVis.x; diffGrp.members[closestBeat].text = getDiff + "ms"; - offsetsPerBeat[closestBeat] = Std.int(getDiff); + offsetsPerBeat[closestBeat] = Math.round(getDiff); } function songPosToX(pos:Float):Float From cdb73f94ca6f93b96c988cb48f09def5196bf3dd Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 31 Jan 2024 01:10:57 -0500 Subject: [PATCH 12/37] lime fixy --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index 4b2885a87..54ddabb09 100644 --- a/hmm.json +++ b/hmm.json @@ -107,7 +107,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "fff39ba6fc64969cd51987ef7491d9345043dc5d", + "ref": "6bedb913b1429e81ac68996467e867501221e6c2", "url": "https://github.com/FunkinCrew/lime" }, { From 3621f17bd05d2170109fc3475d946395d90a4ceb Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 31 Jan 2024 03:24:00 -0500 Subject: [PATCH 13/37] maybe acurate? --- assets | 2 +- hmm.json | 2 +- source/funkin/input/PreciseInputManager.hx | 5 +++-- source/funkin/ui/debug/latency/LatencyState.hx | 3 ++- source/funkin/util/Constants.hx | 2 ++ 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/assets b/assets index b2f8b6a78..30ad76c15 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b2f8b6a780316959d0a79adc6dbf61f9e4ca675f +Subproject commit 30ad76c15d88bdff2b41ec017e3f3089ede52411 diff --git a/hmm.json b/hmm.json index 54ddabb09..80ae1023b 100644 --- a/hmm.json +++ b/hmm.json @@ -54,7 +54,7 @@ "name": "haxeui-core", "type": "git", "dir": null, - "ref": "5b2d5b8e7e470cf637953e1369c80a1f42016a75", + "ref": "a551159", "url": "https://github.com/haxeui/haxeui-core" }, { diff --git a/source/funkin/input/PreciseInputManager.hx b/source/funkin/input/PreciseInputManager.hx index 59e6610a5..1dfa7ac95 100644 --- a/source/funkin/input/PreciseInputManager.hx +++ b/source/funkin/input/PreciseInputManager.hx @@ -293,8 +293,9 @@ class PreciseInputManager extends FlxKeyManager // TODO: Remove this line with SDL3 when timestamps change meaning. // This is because SDL3's timestamps are measured in nanoseconds, not milliseconds. - timestamp *= Constants.NS_PER_MS; - + timestamp *= Constants.NS_PER_MS; // 18126000000 38367000000 + timestamp -= Conductor.instance.inputOffset * Constants.NS_PER_MS; + // trace(timestamp); updateKeyStates(key, true); if (getInputByKey(key)?.justPressed ?? false) diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index f75ac16bc..1a59167ef 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -246,10 +246,11 @@ class LatencyState extends MusicBeatSubState trace("input latency: " + inputLatencyMs + "ms"); trace("cur timestamp: " + PreciseInputManager.getCurrentTimestamp() + "ns"); trace("event timestamp: " + event.timestamp + "ns"); + trace("songtime: " + Conductor.instance.getTimeWithDiff() + "ms"); var closestBeat:Int = Math.round(Conductor.instance.getTimeWithDiff() / (Conductor.instance.stepLengthMs * 2)) % diffGrp.members.length; var getDiff:Float = Conductor.instance.getTimeWithDiff() - (closestBeat * (Conductor.instance.stepLengthMs * 2)); - getDiff -= Conductor.instance.inputOffset; + // getDiff -= Conductor.instance.inputOffset; getDiff -= inputLatencyMs; // lil fix for end of song diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx index 1005b312e..d18956a8a 100644 --- a/source/funkin/util/Constants.hx +++ b/source/funkin/util/Constants.hx @@ -224,6 +224,8 @@ class Constants /** * Constant for the number of seconds in a minute. + * + * sex per min */ public static final SECS_PER_MIN:Int = 60; From cd28f81c8c42925a963cc55a824d588e6102e478 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Fri, 9 Feb 2024 01:31:34 -0500 Subject: [PATCH 14/37] hmm commit update --- hmm.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hmm.json b/hmm.json index 80ae1023b..3845003c4 100644 --- a/hmm.json +++ b/hmm.json @@ -107,7 +107,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "6bedb913b1429e81ac68996467e867501221e6c2", + "ref": "develop2", "url": "https://github.com/FunkinCrew/lime" }, { @@ -163,4 +163,4 @@ "version": "0.11.0" } ] -} +} \ No newline at end of file From aeddcee9838b28695b57cc16558106b28f253581 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Sat, 10 Feb 2024 15:42:29 -0500 Subject: [PATCH 15/37] tweaks in progress --- hmm.json | 4 +- .../funkin/ui/debug/latency/LatencyState.hx | 69 ++++++++----------- 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/hmm.json b/hmm.json index 3845003c4..542feaf01 100644 --- a/hmm.json +++ b/hmm.json @@ -107,7 +107,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "develop2", + "ref": "6c92c7e", "url": "https://github.com/FunkinCrew/lime" }, { @@ -163,4 +163,4 @@ "version": "0.11.0" } ] -} \ No newline at end of file +} diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 1a59167ef..137ab77ee 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -24,6 +24,7 @@ import haxe.Timer; class LatencyState extends MusicBeatSubState { + var visualOffsetText:FlxText; var offsetText:FlxText; var noteGrp:Array; var strumLine:Strumline; @@ -39,9 +40,6 @@ class LatencyState extends MusicBeatSubState var offsetsPerBeat:Array = []; var swagSong:HomemadeMusic; - var funnyStatsGraph:CoolStatsGraph; - var realStats:CoolStatsGraph; - override function create() { super.create(); @@ -54,14 +52,6 @@ class LatencyState extends MusicBeatSubState FlxG.sound.music = swagSong; FlxG.sound.music.play(); - funnyStatsGraph = new CoolStatsGraph(0, Std.int(FlxG.height / 3), Std.int(FlxG.width / 2), Std.int(FlxG.height / 3), FlxColor.PINK, "time"); - funnyStatsGraph.curLabel.y += 32; - FlxG.addChildBelowMouse(funnyStatsGraph); - - realStats = new CoolStatsGraph(0, Std.int(FlxG.height / 3), Std.int(FlxG.width / 2), Std.int(FlxG.height / 3), FlxColor.YELLOW, "REAL"); - realStats.curLabel.y -= 32; - FlxG.addChildBelowMouse(realStats); - PreciseInputManager.instance.onInputPressed.add(function(event:PreciseInputEvent) { generateBeatStuff(event); strumLine.pressKey(event.noteDirection); @@ -112,19 +102,36 @@ class LatencyState extends MusicBeatSubState for (i in 0...8) { - var block = new FlxSprite(2, 50 * i).makeGraphic(48, 48); - block.alpha = 0; + var block = new FlxSprite(2, ((FlxG.height / 8) + 2) * i).makeGraphic(Std.int(FlxG.height / 8), Std.int((FlxG.height / 8) - 4)); + block.alpha = 0.1; blocks.add(block); } - offsetText = new FlxText(); - offsetText.size = 20; - offsetText.screenCenter(); - add(offsetText); + var strumlineBG:FlxSprite = new FlxSprite(); + add(strumlineBG); strumLine = new Strumline(NoteStyleRegistry.instance.fetchDefault(), true); + strumLine.screenCenter(); add(strumLine); + strumlineBG.x = strumLine.x; + strumlineBG.makeGraphic(Std.int(strumLine.width), FlxG.height, 0xFFFFFFFF); + strumlineBG.alpha = 0.1; + + visualOffsetText = new FlxText(); + visualOffsetText.setFormat(Paths.font("vcr.ttf"), 20); + visualOffsetText.x = (FlxG.height / 8) + 10; + visualOffsetText.y = 10; + visualOffsetText.fieldWidth = strumLine.x - visualOffsetText.x - 10; + add(visualOffsetText); + + offsetText = new FlxText(); + offsetText.setFormat(Paths.font("vcr.ttf"), 20); + offsetText.x = strumLine.x + strumLine.width + 10; + offsetText.y = 10; + offsetText.fieldWidth = FlxG.width - offsetText.x - 10; + add(offsetText); + regenNoteData(); } @@ -152,7 +159,7 @@ class LatencyState extends MusicBeatSubState override function beatHit():Bool { if (Conductor.instance.currentBeat % 8 == 0) blocks.forEach(blok -> { - blok.alpha = 0; + blok.alpha = 0.1; }); blocks.members[Conductor.instance.currentBeat % 8].alpha = 1; @@ -170,19 +177,16 @@ class LatencyState extends MusicBeatSubState Conductor.instance.update(); - funnyStatsGraph.update(swagSong.getTimeWithDiff() % 500); - realStats.update(Conductor.instance.getTimeWithDiff() % 500); - // Conductor.instance.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp; 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 (CTRL+Left/Right to change): " + Conductor.instance.instrumentalOffset + "ms"; - offsetText.text += "\nINPUT Offset (Left/Right to change): " + Conductor.instance.inputOffset + "ms"; - offsetText.text += "\ncurrentStep: " + Conductor.instance.currentStep; - offsetText.text += "\ncurrentBeat: " + Conductor.instance.currentBeat; + visualOffsetText.text = "Visual Offset: " + Conductor.instance.instrumentalOffset + "ms"; + visualOffsetText.text += "\nYou can press SPACE+Left/Right to change this value."; + + offsetText.text = "INPUT Offset (Left/Right to change): " + Conductor.instance.inputOffset + "ms"; var avgOffsetInput:Float = 0; @@ -191,7 +195,7 @@ class LatencyState extends MusicBeatSubState avgOffsetInput /= offsetsPerBeat.length; - offsetText.text += "\naverage input offset needed: " + avgOffsetInput; + offsetText.text += "\nEstimated average input offset needed: " + avgOffsetInput; var multiply:Int = 10; @@ -222,19 +226,6 @@ class LatencyState extends MusicBeatSubState } } - // noteGrp.forEach(function(daNote:NoteSprite) { - // daNote.y = (strumLine.y - ((Conductor.instance.songPosition - Conductor.instance.instrumentalOffset) - daNote.strumTime) * 0.45); - // daNote.x = strumLine.x + 30; - - // if (daNote.y < strumLine.y) daNote.alpha = 0.5; - - // if (daNote.y < 0 - daNote.height) - // { - // daNote.alpha = 1; - // // daNote.data.strumTime += Conductor.instance.beatLengthMs * 8; - // } - // }); - super.update(elapsed); } From 0145d7ed2d236dc759ba6ed7f214d7cbe6964766 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 12 Feb 2024 20:06:43 -0500 Subject: [PATCH 16/37] input offset edits in progress --- source/funkin/Conductor.hx | 9 +- source/funkin/play/PauseSubState.hx | 8 +- source/funkin/ui/debug/DebugMenuSubState.hx | 2 +- .../funkin/ui/debug/latency/LatencyState.hx | 93 ++++++++++++++----- 4 files changed, 85 insertions(+), 27 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 75031f6dd..8b2732a9a 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -8,6 +8,7 @@ import funkin.data.song.SongData.SongTimeChange; import funkin.data.song.SongDataUtils; import funkin.save.Save; import haxe.Timer; +import flixel.sound.FlxSound; /** * A core class which handles musical timing throughout the game, @@ -290,6 +291,8 @@ class Conductor // Take into account instrumental and file format song offsets. songPos = (FlxG.sound.music != null) ? (FlxG.sound.music.time + instrumentalOffset + formatOffset) : 0.0; } + else + songPos += instrumentalOffset + formatOffset; var oldMeasure = this.currentMeasure; var oldBeat = this.currentBeat; @@ -369,14 +372,16 @@ class Conductor * that can potentially get processed on exact milliseconds/timestmaps. * If you need song position, use `Conductor.instance.songPosition` instead * for use in update() related functions. + * @param soundToCheck Which FlxSound object to check, defaults to FlxG.sound.music if no input * @return Float */ - public function getTimeWithDiff():Float + public function getTimeWithDiff(?soundToCheck:FlxSound):Float { + if (soundToCheck == null) soundToCheck = FlxG.sound.music; // trace(this.songPosition); @:privateAccess - this.songPosition = FlxG.sound.music._channel.position; + this.songPosition = soundToCheck._channel.position; // return this.songPosition + (Std.int(Timer.stamp() * 1000) - prevTimestamp); // trace("\t--> " + this.songPosition); return this.songPosition; diff --git a/source/funkin/play/PauseSubState.hx b/source/funkin/play/PauseSubState.hx index c9039ce40..62a4e3f4d 100644 --- a/source/funkin/play/PauseSubState.hx +++ b/source/funkin/play/PauseSubState.hx @@ -5,6 +5,7 @@ import flixel.FlxSprite; import flixel.addons.transition.FlxTransitionableState; import flixel.group.FlxGroup.FlxTypedGroup; import funkin.ui.MusicBeatSubState; +import funkin.ui.debug.latency.LatencyState; import flixel.sound.FlxSound; import flixel.text.FlxText; import flixel.tweens.FlxEase; @@ -18,14 +19,16 @@ class PauseSubState extends MusicBeatSubState { var grpMenuShit:FlxTypedGroup; + // todo: maybe make these enums or somethin? final pauseOptionsBase:Array = [ 'Resume', 'Restart Song', 'Change Difficulty', 'Toggle Practice Mode', + 'Adjust Input Offsets', 'Exit to Menu' ]; - final pauseOptionsCharting:Array = ['Resume', 'Restart Song', 'Exit to Chart Editor']; + final pauseOptionsCharting:Array = ['Resume', 'Restart Song', 'Adjust Input Offsets', 'Exit to Chart Editor']; final pauseOptionsDifficultyBase:Array = ['BACK']; @@ -240,7 +243,8 @@ class PauseSubState extends MusicBeatSubState { openSubState(new funkin.ui.transition.StickerSubState(null, FREEPLAY)); } - + case 'Adjust Input Offsets': + openSubState(new LatencyState()); case 'Exit to Chart Editor': this.close(); if (FlxG.sound.music != null) FlxG.sound.music.pause(); // Don't reset song position! diff --git a/source/funkin/ui/debug/DebugMenuSubState.hx b/source/funkin/ui/debug/DebugMenuSubState.hx index f797dfbad..7e03b2d7a 100644 --- a/source/funkin/ui/debug/DebugMenuSubState.hx +++ b/source/funkin/ui/debug/DebugMenuSubState.hx @@ -95,7 +95,7 @@ class DebugMenuSubState extends MusicBeatSubState function openInputOffsetTesting() { - FlxG.switchState(new funkin.ui.debug.latency.LatencyState()); + openSubState(new funkin.ui.debug.latency.LatencyState()); trace('Input Offset Testing'); } diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 137ab77ee..6bba9200c 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -21,6 +21,7 @@ import funkin.data.notestyle.NoteStyleData; import funkin.data.notestyle.NoteStyleRegistry; import funkin.data.song.SongData.SongNoteData; import haxe.Timer; +import flixel.FlxCamera; class LatencyState extends MusicBeatSubState { @@ -38,30 +39,39 @@ class LatencyState extends MusicBeatSubState var beatTrail:FlxSprite; var diffGrp:FlxTypedGroup; var offsetsPerBeat:Array = []; - var swagSong:HomemadeMusic; + var swagSong:FlxSound; + + var previousVolume:Float; + + var stateCamera:FlxCamera; override function create() { super.create(); - if (FlxG.sound.music != null) FlxG.sound.music.stop(); + stateCamera = new FlxCamera(0, 0, FlxG.width, FlxG.height); + stateCamera.bgColor = FlxColor.BLACK; + FlxG.cameras.add(stateCamera); - swagSong = new HomemadeMusic(); + var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK); + add(bg); + + if (FlxG.sound.music != null) + { + previousVolume = FlxG.sound.music.volume; + FlxG.sound.music.volume = 0; // only want to mute the volume, incase we are coming from pause menu + } + else + previousVolume = 1; // defaults to 1 if no music is playing 🤔 also fuck it, emoji in code comment + + swagSong = new FlxSound(); swagSong.loadEmbedded(Paths.sound('soundTest'), true); + swagSong.looped = true; + swagSong.play(); - FlxG.sound.music = swagSong; - FlxG.sound.music.play(); + PreciseInputManager.instance.onInputPressed.add(preciseInputPressed); - PreciseInputManager.instance.onInputPressed.add(function(event:PreciseInputEvent) { - generateBeatStuff(event); - strumLine.pressKey(event.noteDirection); - strumLine.playPress(event.noteDirection); - }); - - PreciseInputManager.instance.onInputReleased.add(function(event:PreciseInputEvent) { - strumLine.playStatic(event.noteDirection); - strumLine.releaseKey(event.noteDirection); - }); + PreciseInputManager.instance.onInputReleased.add(preciseInputReleased); Conductor.instance.forceBPM(60); @@ -70,7 +80,7 @@ class LatencyState extends MusicBeatSubState diffGrp = new FlxTypedGroup(); add(diffGrp); - for (beat in 0...Math.floor(FlxG.sound.music.length / (Conductor.instance.stepLengthMs * 2))) + for (beat in 0...Math.floor(swagSong.length / (Conductor.instance.stepLengthMs * 2))) { var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * (Conductor.instance.stepLengthMs * 2)), FlxG.height - 15); beatTick.makeGraphic(2, 15); @@ -132,9 +142,43 @@ class LatencyState extends MusicBeatSubState offsetText.fieldWidth = FlxG.width - offsetText.x - 10; add(offsetText); + var helpText:FlxText = new FlxText(); + helpText.setFormat(Paths.font("vcr.ttf"), 20); + helpText.text = "Press ESC to return to main menu"; + helpText.x = FlxG.width - helpText.width; + helpText.y = FlxG.height - helpText.height - 2; + add(helpText); + regenNoteData(); } + function preciseInputPressed(event:PreciseInputEvent) + { + generateBeatStuff(event); + strumLine.pressKey(event.noteDirection); + strumLine.playPress(event.noteDirection); + } + + function preciseInputReleased(event:PreciseInputEvent) + { + strumLine.playStatic(event.noteDirection); + strumLine.releaseKey(event.noteDirection); + } + + override public function close():Void + { + PreciseInputManager.instance.onInputPressed.remove(preciseInputPressed); + + PreciseInputManager.instance.onInputReleased.remove(preciseInputReleased); + + FlxG.sound.music.volume = previousVolume; + swagSong.stop(); + + FlxG.cameras.remove(stateCamera); + + super.close(); + } + function regenNoteData() { for (i in 0...32) @@ -175,7 +219,7 @@ class LatencyState extends MusicBeatSubState trace(FlxG.sound.music._channel.position); */ - Conductor.instance.update(); + Conductor.instance.update(swagSong.position); // Conductor.instance.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp; @@ -226,6 +270,11 @@ class LatencyState extends MusicBeatSubState } } + if (FlxG.keys.justPressed.ESCAPE) + { + close(); + } + super.update(elapsed); } @@ -237,15 +286,15 @@ class LatencyState extends MusicBeatSubState trace("input latency: " + inputLatencyMs + "ms"); trace("cur timestamp: " + PreciseInputManager.getCurrentTimestamp() + "ns"); trace("event timestamp: " + event.timestamp + "ns"); - trace("songtime: " + Conductor.instance.getTimeWithDiff() + "ms"); + trace("songtime: " + Conductor.instance.getTimeWithDiff(swagSong) + "ms"); - var closestBeat:Int = Math.round(Conductor.instance.getTimeWithDiff() / (Conductor.instance.stepLengthMs * 2)) % diffGrp.members.length; - var getDiff:Float = Conductor.instance.getTimeWithDiff() - (closestBeat * (Conductor.instance.stepLengthMs * 2)); + var closestBeat:Int = Math.round(Conductor.instance.getTimeWithDiff(swagSong) / (Conductor.instance.stepLengthMs * 2)) % diffGrp.members.length; + var getDiff:Float = Conductor.instance.getTimeWithDiff(swagSong) - (closestBeat * (Conductor.instance.stepLengthMs * 2)); // getDiff -= Conductor.instance.inputOffset; getDiff -= inputLatencyMs; // lil fix for end of song - if (closestBeat == 0 && getDiff >= Conductor.instance.stepLengthMs * 2) getDiff -= FlxG.sound.music.length; + if (closestBeat == 0 && getDiff >= Conductor.instance.stepLengthMs * 2) getDiff -= swagSong.length; beatTrail.x = songPosVis.x; @@ -255,7 +304,7 @@ class LatencyState extends MusicBeatSubState function songPosToX(pos:Float):Float { - return FlxMath.remapToRange(pos, 0, FlxG.sound.music.length, 0, FlxG.width); + return FlxMath.remapToRange(pos, 0, swagSong.length, 0, FlxG.width); } } From 43ec35f5fd1c576226b965c99f5a3d00919408a3 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 12 Feb 2024 21:00:40 -0500 Subject: [PATCH 17/37] derp .position -> .time fix --- source/funkin/ui/debug/latency/LatencyState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 6bba9200c..aa186d6b3 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -219,7 +219,7 @@ class LatencyState extends MusicBeatSubState trace(FlxG.sound.music._channel.position); */ - Conductor.instance.update(swagSong.position); + Conductor.instance.update(swagSong.time); // Conductor.instance.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp; From 25766dbde9f939f2f6b2e5f5407ea019d6c5ccd7 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 12 Feb 2024 21:41:16 -0500 Subject: [PATCH 18/37] decoupling some stuff from Conductor.instance --- source/funkin/Conductor.hx | 4 +- source/funkin/play/notes/Strumline.hx | 28 +++++---- source/funkin/ui/MusicBeatState.hx | 5 +- source/funkin/ui/MusicBeatSubState.hx | 5 +- .../funkin/ui/debug/latency/LatencyState.hx | 63 +++++++++++-------- 5 files changed, 62 insertions(+), 43 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 8b2732a9a..dbfeb8621 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -284,7 +284,7 @@ class Conductor * @param songPosition The current position in the song in milliseconds. * Leave blank to use the FlxG.sound.music position. */ - public function update(?songPos:Float) + public function update(?songPos:Float, applyOffsets:Bool = true) { if (songPos == null) { @@ -292,7 +292,7 @@ class Conductor songPos = (FlxG.sound.music != null) ? (FlxG.sound.music.time + instrumentalOffset + formatOffset) : 0.0; } else - songPos += instrumentalOffset + formatOffset; + songPos += applyOffsets ? instrumentalOffset + formatOffset : 0; var oldMeasure = this.currentMeasure; var oldBeat = this.currentBeat; diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 057f05acb..4538696dc 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -41,6 +41,12 @@ class Strumline extends FlxSpriteGroup public var isPlayer:Bool; + /** + * Usually you want to keep this as is, but if you are using a Strumline and + * playing a sound that has it's own conductor, set this (LatencyState for example) + */ + public var conductorInUse:Conductor = Conductor.instance; + /** * The notes currently being rendered on the strumline. * This group iterates over this every frame to update note positions. @@ -158,7 +164,7 @@ class Strumline extends FlxSpriteGroup var hitWindowCenter = note.strumTime; var hitWindowEnd = note.strumTime + Constants.HIT_WINDOW_MS; - if (Conductor.instance.songPosition > hitWindowEnd) + if (conductorInUse.songPosition > hitWindowEnd) { if (!isPlayer && note.hasMissed) continue; @@ -168,7 +174,7 @@ class Strumline extends FlxSpriteGroup if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = true; } - else if (Conductor.instance.songPosition > hitWindowCenter) + else if (conductorInUse.songPosition > hitWindowCenter) { // only run this on opponent strumlines! if (!isPlayer) continue; @@ -191,7 +197,7 @@ class Strumline extends FlxSpriteGroup playNoteHoldCover(note.holdNoteSprite); } } - else if (Conductor.instance.songPosition > hitWindowStart) + else if (conductorInUse.songPosition > hitWindowStart) { if (!isPlayer && (note.hasBeenHit || note.hasMissed)) continue; @@ -352,7 +358,7 @@ class Strumline extends FlxSpriteGroup * @param strumTime * @return Float */ - static function calculateNoteYPos(strumTime:Float, vwoosh:Bool = true):Float + public 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; @@ -360,7 +366,7 @@ class Strumline extends FlxSpriteGroup var vwoosh:Float = 1.0; var scrollSpeed:Float = PlayState.instance?.currentChart?.scrollSpeed ?? 1.0; - return Constants.PIXELS_PER_MS * (Conductor.instance.songPosition - strumTime) * scrollSpeed * vwoosh * (Preferences.downscroll ? 1 : -1); + return Constants.PIXELS_PER_MS * (conductorInUse.songPosition - strumTime) * scrollSpeed * vwoosh * (Preferences.downscroll ? 1 : -1); } function updateNotes():Void @@ -368,8 +374,8 @@ class Strumline extends FlxSpriteGroup if (noteData.length == 0) return; var songStart:Float = PlayState.instance?.startTimestamp ?? 0.0; - var hitWindowStart:Float = Conductor.instance.songPosition - Constants.HIT_WINDOW_MS; - var renderWindowStart:Float = Conductor.instance.songPosition + RENDER_DISTANCE_MS; + var hitWindowStart:Float = conductorInUse.songPosition - Constants.HIT_WINDOW_MS; + var renderWindowStart:Float = conductorInUse.songPosition + RENDER_DISTANCE_MS; for (noteIndex in nextNoteIndex...noteData.length) { @@ -416,7 +422,7 @@ class Strumline extends FlxSpriteGroup { if (holdNote == null || !holdNote.alive) continue; - if (Conductor.instance.songPosition > holdNote.strumTime && holdNote.hitNote && !holdNote.missedNote) + if (conductorInUse.songPosition > holdNote.strumTime && holdNote.hitNote && !holdNote.missedNote) { if (isPlayer && !isKeyHeld(holdNote.noteDirection)) { @@ -430,7 +436,7 @@ class Strumline extends FlxSpriteGroup var renderWindowEnd = holdNote.strumTime + holdNote.fullSustainLength + Constants.HIT_WINDOW_MS + RENDER_DISTANCE_MS / 8; - if (holdNote.missedNote && Conductor.instance.songPosition >= renderWindowEnd) + if (holdNote.missedNote && conductorInUse.songPosition >= renderWindowEnd) { // Hold note is offscreen, kill it. holdNote.visible = false; @@ -476,13 +482,13 @@ class Strumline extends FlxSpriteGroup holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + yOffset + STRUMLINE_SIZE / 2; } } - else if (Conductor.instance.songPosition > holdNote.strumTime && holdNote.hitNote) + else if (conductorInUse.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.instance.songPosition; + holdNote.sustainLength = (holdNote.strumTime + holdNote.fullSustainLength) - conductorInUse.songPosition; if (holdNote.sustainLength <= 10) { diff --git a/source/funkin/ui/MusicBeatState.hx b/source/funkin/ui/MusicBeatState.hx index 33333565f..4013258af 100644 --- a/source/funkin/ui/MusicBeatState.hx +++ b/source/funkin/ui/MusicBeatState.hx @@ -27,6 +27,7 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler public var leftWatermarkText:FlxText = null; public var rightWatermarkText:FlxText = null; + public var conductorInUse:Conductor = Conductor.instance; public function new() { @@ -125,7 +126,7 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler public function stepHit():Bool { - var event = new SongTimeScriptEvent(SONG_STEP_HIT, Conductor.instance.currentBeat, Conductor.instance.currentStep); + var event = new SongTimeScriptEvent(SONG_STEP_HIT, conductorInUse.currentBeat, conductorInUse.currentStep); dispatchEvent(event); @@ -136,7 +137,7 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler public function beatHit():Bool { - var event = new SongTimeScriptEvent(SONG_BEAT_HIT, Conductor.instance.currentBeat, Conductor.instance.currentStep); + var event = new SongTimeScriptEvent(SONG_BEAT_HIT, conductorInUse.currentBeat, conductorInUse.currentStep); dispatchEvent(event); diff --git a/source/funkin/ui/MusicBeatSubState.hx b/source/funkin/ui/MusicBeatSubState.hx index 0fa55c234..dc2958b91 100644 --- a/source/funkin/ui/MusicBeatSubState.hx +++ b/source/funkin/ui/MusicBeatSubState.hx @@ -20,6 +20,7 @@ class MusicBeatSubState extends FlxTransitionableSubState implements IEventHandl { public var leftWatermarkText:FlxText = null; public var rightWatermarkText:FlxText = null; + public var conductorInUse:Conductor = Conductor.instance; public function new(bgColor:FlxColor = FlxColor.TRANSPARENT) { @@ -95,7 +96,7 @@ class MusicBeatSubState extends FlxTransitionableSubState implements IEventHandl */ public function stepHit():Bool { - var event:ScriptEvent = new SongTimeScriptEvent(SONG_STEP_HIT, Conductor.instance.currentBeat, Conductor.instance.currentStep); + var event:ScriptEvent = new SongTimeScriptEvent(SONG_STEP_HIT, conductorInUse.currentBeat, conductorInUse.currentStep); dispatchEvent(event); @@ -111,7 +112,7 @@ class MusicBeatSubState extends FlxTransitionableSubState implements IEventHandl */ public function beatHit():Bool { - var event:ScriptEvent = new SongTimeScriptEvent(SONG_BEAT_HIT, Conductor.instance.currentBeat, Conductor.instance.currentStep); + var event:ScriptEvent = new SongTimeScriptEvent(SONG_BEAT_HIT, conductorInUse.currentBeat, conductorInUse.currentStep); dispatchEvent(event); diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index aa186d6b3..0f396c972 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -45,10 +45,18 @@ class LatencyState extends MusicBeatSubState var stateCamera:FlxCamera; + /** + * A local conductor instance for this testing class, in-case we are in a PlayState + * because I'm too lazy to set the old variables for conductor stuff ! + */ + var localConductor:Conductor; + override function create() { super.create(); + localConductor = new Conductor(); + stateCamera = new FlxCamera(0, 0, FlxG.width, FlxG.height); stateCamera.bgColor = FlxColor.BLACK; FlxG.cameras.add(stateCamera); @@ -68,26 +76,27 @@ class LatencyState extends MusicBeatSubState swagSong.loadEmbedded(Paths.sound('soundTest'), true); swagSong.looped = true; swagSong.play(); + FlxG.sound.list.add(swagSong); PreciseInputManager.instance.onInputPressed.add(preciseInputPressed); PreciseInputManager.instance.onInputReleased.add(preciseInputReleased); - Conductor.instance.forceBPM(60); + localConductor.forceBPM(60); noteGrp = []; diffGrp = new FlxTypedGroup(); add(diffGrp); - for (beat in 0...Math.floor(swagSong.length / (Conductor.instance.stepLengthMs * 2))) + for (beat in 0...Math.floor(swagSong.length / (localConductor.stepLengthMs * 2))) { - var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * (Conductor.instance.stepLengthMs * 2)), FlxG.height - 15); + var beatTick:FlxSprite = new FlxSprite(songPosToX(beat * (localConductor.stepLengthMs * 2)), FlxG.height - 15); beatTick.makeGraphic(2, 15); beatTick.alpha = 0.3; add(beatTick); - var offsetTxt:FlxText = new FlxText(songPosToX(beat * (Conductor.instance.stepLengthMs * 2)), FlxG.height - 26, 0, "swag"); + var offsetTxt:FlxText = new FlxText(songPosToX(beat * (localConductor.stepLengthMs * 2)), FlxG.height - 26, 0, "swag"); offsetTxt.alpha = 0.5; diffGrp.add(offsetTxt); @@ -121,6 +130,7 @@ class LatencyState extends MusicBeatSubState add(strumlineBG); strumLine = new Strumline(NoteStyleRegistry.instance.fetchDefault(), true); + strumLine.conductorInUse = localConductor; strumLine.screenCenter(); add(strumLine); @@ -173,6 +183,7 @@ class LatencyState extends MusicBeatSubState FlxG.sound.music.volume = previousVolume; swagSong.stop(); + FlxG.sound.list.remove(swagSong); FlxG.cameras.remove(stateCamera); @@ -183,7 +194,7 @@ class LatencyState extends MusicBeatSubState { for (i in 0...32) { - var note:SongNoteData = new SongNoteData((Conductor.instance.stepLengthMs * 2) * i, 1); + var note:SongNoteData = new SongNoteData((localConductor.stepLengthMs * 2) * i, 1); noteGrp.push(note); } @@ -192,9 +203,9 @@ class LatencyState extends MusicBeatSubState override function stepHit():Bool { - if (Conductor.instance.currentStep % 4 == 2) + if (localConductor.currentStep % 4 == 2) { - blocks.members[((Conductor.instance.currentBeat % 8) + 1) % 8].alpha = 0.5; + blocks.members[((localConductor.currentBeat % 8) + 1) % 8].alpha = 0.5; } return super.stepHit(); @@ -202,11 +213,11 @@ class LatencyState extends MusicBeatSubState override function beatHit():Bool { - if (Conductor.instance.currentBeat % 8 == 0) blocks.forEach(blok -> { + if (localConductor.currentBeat % 8 == 0) blocks.forEach(blok -> { blok.alpha = 0.1; }); - blocks.members[Conductor.instance.currentBeat % 8].alpha = 1; + blocks.members[localConductor.currentBeat % 8].alpha = 1; // block.visible = !block.visible; return super.beatHit(); @@ -219,18 +230,18 @@ class LatencyState extends MusicBeatSubState trace(FlxG.sound.music._channel.position); */ - Conductor.instance.update(swagSong.time); + localConductor.update(swagSong.time, false); - // Conductor.instance.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp; + // localConductor.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp; - songPosVis.x = songPosToX(Conductor.instance.songPosition); - songVisFollowAudio.x = songPosToX(Conductor.instance.songPosition - Conductor.instance.instrumentalOffset); - songVisFollowVideo.x = songPosToX(Conductor.instance.songPosition - Conductor.instance.inputOffset); + songPosVis.x = songPosToX(localConductor.songPosition); + songVisFollowAudio.x = songPosToX(localConductor.songPosition - localConductor.instrumentalOffset); + songVisFollowVideo.x = songPosToX(localConductor.songPosition - localConductor.inputOffset); - visualOffsetText.text = "Visual Offset: " + Conductor.instance.instrumentalOffset + "ms"; + visualOffsetText.text = "Visual Offset: " + localConductor.instrumentalOffset + "ms"; visualOffsetText.text += "\nYou can press SPACE+Left/Right to change this value."; - offsetText.text = "INPUT Offset (Left/Right to change): " + Conductor.instance.inputOffset + "ms"; + offsetText.text = "INPUT Offset (Left/Right to change): " + localConductor.inputOffset + "ms"; var avgOffsetInput:Float = 0; @@ -249,24 +260,24 @@ class LatencyState extends MusicBeatSubState { if (FlxG.keys.justPressed.RIGHT) { - Conductor.instance.instrumentalOffset += 1 * multiply; + localConductor.instrumentalOffset += 1 * multiply; } if (FlxG.keys.justPressed.LEFT) { - Conductor.instance.instrumentalOffset -= 1 * multiply; + localConductor.instrumentalOffset -= 1 * multiply; } } else { if (FlxG.keys.justPressed.RIGHT) { - Conductor.instance.inputOffset += 1 * multiply; + localConductor.inputOffset += 1 * multiply; } if (FlxG.keys.justPressed.LEFT) { - Conductor.instance.inputOffset -= 1 * multiply; + localConductor.inputOffset -= 1 * multiply; } } @@ -280,21 +291,21 @@ class LatencyState extends MusicBeatSubState function generateBeatStuff(event:PreciseInputEvent) { - // Conductor.instance.update(swagSong.getTimeWithDiff()); + // localConductor.update(swagSong.getTimeWithDiff()); var inputLatencyMs:Float = haxe.Int64.toInt(PreciseInputManager.getCurrentTimestamp() - event.timestamp) / 1000.0 / 1000.0; trace("input latency: " + inputLatencyMs + "ms"); trace("cur timestamp: " + PreciseInputManager.getCurrentTimestamp() + "ns"); trace("event timestamp: " + event.timestamp + "ns"); - trace("songtime: " + Conductor.instance.getTimeWithDiff(swagSong) + "ms"); + trace("songtime: " + localConductor.getTimeWithDiff(swagSong) + "ms"); - var closestBeat:Int = Math.round(Conductor.instance.getTimeWithDiff(swagSong) / (Conductor.instance.stepLengthMs * 2)) % diffGrp.members.length; - var getDiff:Float = Conductor.instance.getTimeWithDiff(swagSong) - (closestBeat * (Conductor.instance.stepLengthMs * 2)); - // getDiff -= Conductor.instance.inputOffset; + var closestBeat:Int = Math.round(localConductor.getTimeWithDiff(swagSong) / (localConductor.stepLengthMs * 2)) % diffGrp.members.length; + var getDiff:Float = localConductor.getTimeWithDiff(swagSong) - (closestBeat * (localConductor.stepLengthMs * 2)); + // getDiff -= localConductor.inputOffset; getDiff -= inputLatencyMs; // lil fix for end of song - if (closestBeat == 0 && getDiff >= Conductor.instance.stepLengthMs * 2) getDiff -= swagSong.length; + if (closestBeat == 0 && getDiff >= localConductor.stepLengthMs * 2) getDiff -= swagSong.length; beatTrail.x = songPosVis.x; From e759f901478c982c6a90e7c5cceb10265e5546dd Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 12 Feb 2024 22:14:35 -0500 Subject: [PATCH 19/37] audioVisualOffset numbers --- source/funkin/Conductor.hx | 45 ++++++++++++++----- .../funkin/ui/debug/latency/LatencyState.hx | 18 ++++---- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index dbfeb8621..b30d405fa 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -217,6 +217,11 @@ class Conductor */ public var inputOffset(get, set):Int; + /** + * An offset set by the user to compensate for audio/visual lag + */ + public var audioVisualOffset(get, set):Int; + function get_inputOffset():Int { return Save.get().options.inputOffset; @@ -229,6 +234,18 @@ class Conductor return Save.get().options.inputOffset; } + function get_audioVisualOffset():Int + { + return Save.get().options.audioVisualOffset; + } + + function set_audioVisualOffset(value:Int):Int + { + Save.get().options.audioVisualOffset = value; + Save.get().flush(); + return Save.get().options.audioVisualOffset; + } + /** * The number of beats in a measure. May be fractional depending on the time signature. */ @@ -283,16 +300,17 @@ class Conductor * * @param songPosition The current position in the song in milliseconds. * Leave blank to use the FlxG.sound.music position. + * @param applyOffsets If it should apply the instrumentalOffset + formatOffset + audioVisualOffset */ - public function update(?songPos:Float, applyOffsets:Bool = true) + public function update(?songPos:Float, applyOffsets:Bool = true, forceDispatch:Bool = false) { if (songPos == null) { // Take into account instrumental and file format song offsets. - songPos = (FlxG.sound.music != null) ? (FlxG.sound.music.time + instrumentalOffset + formatOffset) : 0.0; + songPos = (FlxG.sound.music != null) ? (FlxG.sound.music.time + instrumentalOffset + formatOffset + audioVisualOffset) : 0.0; } else - songPos += applyOffsets ? instrumentalOffset + formatOffset : 0; + songPos += applyOffsets ? instrumentalOffset + formatOffset + audioVisualOffset : 0; var oldMeasure = this.currentMeasure; var oldBeat = this.currentBeat; @@ -338,7 +356,7 @@ class Conductor } // Only fire the signal if we are THE Conductor. - if (this == Conductor.instance) + if (this == Conductor.instance || forceDispatch) { // FlxSignals are really cool. if (currentStep != oldStep) @@ -428,7 +446,7 @@ class Conductor } // Update currentStepTime - this.update(Conductor.instance.songPosition); + this.update(this.songPosition, false); } /** @@ -540,13 +558,18 @@ class Conductor } } - public static function watchQuick():Void + /** + * @param conductorToUse defaults to Conductor.instance if null + */ + public static function watchQuick(?conductorToUse:Conductor):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); + if (conductorToUse == null) conductorToUse = Conductor.instance; + + FlxG.watch.addQuick("songPosition", conductorToUse.songPosition); + FlxG.watch.addQuick("bpm", conductorToUse.bpm); + FlxG.watch.addQuick("currentMeasureTime", conductorToUse.currentMeasureTime); + FlxG.watch.addQuick("currentBeatTime", conductorToUse.currentBeatTime); + FlxG.watch.addQuick("currentStepTime", conductorToUse.currentStepTime); } /** diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 0f396c972..4e9b83f2e 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -230,15 +230,15 @@ class LatencyState extends MusicBeatSubState trace(FlxG.sound.music._channel.position); */ - localConductor.update(swagSong.time, false); + localConductor.update(swagSong.time, false, true); // localConductor.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp; songPosVis.x = songPosToX(localConductor.songPosition); - songVisFollowAudio.x = songPosToX(localConductor.songPosition - localConductor.instrumentalOffset); + songVisFollowAudio.x = songPosToX(localConductor.songPosition - localConductor.audioVisualOffset); songVisFollowVideo.x = songPosToX(localConductor.songPosition - localConductor.inputOffset); - visualOffsetText.text = "Visual Offset: " + localConductor.instrumentalOffset + "ms"; + visualOffsetText.text = "Visual Offset: " + localConductor.audioVisualOffset + "ms"; visualOffsetText.text += "\nYou can press SPACE+Left/Right to change this value."; offsetText.text = "INPUT Offset (Left/Right to change): " + localConductor.inputOffset + "ms"; @@ -260,12 +260,12 @@ class LatencyState extends MusicBeatSubState { if (FlxG.keys.justPressed.RIGHT) { - localConductor.instrumentalOffset += 1 * multiply; + localConductor.audioVisualOffset += 1 * multiply; } if (FlxG.keys.justPressed.LEFT) { - localConductor.instrumentalOffset -= 1 * multiply; + localConductor.audioVisualOffset -= 1 * multiply; } } else @@ -294,10 +294,10 @@ class LatencyState extends MusicBeatSubState // localConductor.update(swagSong.getTimeWithDiff()); var inputLatencyMs:Float = haxe.Int64.toInt(PreciseInputManager.getCurrentTimestamp() - event.timestamp) / 1000.0 / 1000.0; - trace("input latency: " + inputLatencyMs + "ms"); - trace("cur timestamp: " + PreciseInputManager.getCurrentTimestamp() + "ns"); - trace("event timestamp: " + event.timestamp + "ns"); - trace("songtime: " + localConductor.getTimeWithDiff(swagSong) + "ms"); + // trace("input latency: " + inputLatencyMs + "ms"); + // trace("cur timestamp: " + PreciseInputManager.getCurrentTimestamp() + "ns"); + // trace("event timestamp: " + event.timestamp + "ns"); + // trace("songtime: " + localConductor.getTimeWithDiff(swagSong) + "ms"); var closestBeat:Int = Math.round(localConductor.getTimeWithDiff(swagSong) / (localConductor.stepLengthMs * 2)) % diffGrp.members.length; var getDiff:Float = localConductor.getTimeWithDiff(swagSong) - (closestBeat * (localConductor.stepLengthMs * 2)); From 58077b4505cae8b4575635d390f28b731f4b52eb Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 12 Feb 2024 22:44:59 -0500 Subject: [PATCH 20/37] more working audio offset in progress --- source/funkin/Conductor.hx | 4 ++++ source/funkin/ui/MusicBeatSubState.hx | 2 +- source/funkin/ui/debug/latency/LatencyState.hx | 8 ++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index b30d405fa..4b1b89dfa 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -214,11 +214,15 @@ class Conductor /** * An offset set by the user to compensate for input lag. + * No matter if you're using a local conductor or not, this always loads + * to/from the save file */ public var inputOffset(get, set):Int; /** * An offset set by the user to compensate for audio/visual lag + * No matter if you're using a local conductor or not, this always loads + * to/from the save file */ public var audioVisualOffset(get, set):Int; diff --git a/source/funkin/ui/MusicBeatSubState.hx b/source/funkin/ui/MusicBeatSubState.hx index dc2958b91..f93fbce0a 100644 --- a/source/funkin/ui/MusicBeatSubState.hx +++ b/source/funkin/ui/MusicBeatSubState.hx @@ -67,7 +67,7 @@ class MusicBeatSubState extends FlxTransitionableSubState implements IEventHandl // Display Conductor info in the watch window. FlxG.watch.addQuick("musicTime", FlxG.sound.music?.time ?? 0.0); - Conductor.watchQuick(); + Conductor.watchQuick(conductorInUse); dispatchEvent(new UpdateScriptEvent(elapsed)); } diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 4e9b83f2e..9cce4ca23 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -56,6 +56,7 @@ class LatencyState extends MusicBeatSubState super.create(); localConductor = new Conductor(); + conductorInUse = localConductor; stateCamera = new FlxCamera(0, 0, FlxG.width, FlxG.height); stateCamera.bgColor = FlxColor.BLACK; @@ -239,9 +240,11 @@ class LatencyState extends MusicBeatSubState songVisFollowVideo.x = songPosToX(localConductor.songPosition - localConductor.inputOffset); visualOffsetText.text = "Visual Offset: " + localConductor.audioVisualOffset + "ms"; - visualOffsetText.text += "\nYou can press SPACE+Left/Right to change this value."; + visualOffsetText.text += "\n\nYou can press SPACE+Left/Right to change this value."; + visualOffsetText.text += "\n\nYou can hold SHIFT to step 1ms at a time"; offsetText.text = "INPUT Offset (Left/Right to change): " + localConductor.inputOffset + "ms"; + offsetText.text += "\n\nYou can hold SHIFT to step 1ms at a time"; var avgOffsetInput:Float = 0; @@ -250,7 +253,7 @@ class LatencyState extends MusicBeatSubState avgOffsetInput /= offsetsPerBeat.length; - offsetText.text += "\nEstimated average input offset needed: " + avgOffsetInput; + offsetText.text += "\n\nEstimated average input offset needed: " + avgOffsetInput; var multiply:Int = 10; @@ -303,6 +306,7 @@ class LatencyState extends MusicBeatSubState var getDiff:Float = localConductor.getTimeWithDiff(swagSong) - (closestBeat * (localConductor.stepLengthMs * 2)); // getDiff -= localConductor.inputOffset; getDiff -= inputLatencyMs; + getDiff -= localConductor.audioVisualOffset; // lil fix for end of song if (closestBeat == 0 && getDiff >= localConductor.stepLengthMs * 2) getDiff -= swagSong.length; From 96d27c271ae2646bf1089beda4e7f9814b157000 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 14 Feb 2024 08:29:38 -0500 Subject: [PATCH 21/37] avg offset better calc --- source/funkin/ui/debug/latency/LatencyState.hx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 9cce4ca23..0d486fca1 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -38,7 +38,7 @@ class LatencyState extends MusicBeatSubState var beatTrail:FlxSprite; var diffGrp:FlxTypedGroup; - var offsetsPerBeat:Array = []; + var offsetsPerBeat:Array> = []; var swagSong:FlxSound; var previousVolume:Float; @@ -101,7 +101,7 @@ class LatencyState extends MusicBeatSubState offsetTxt.alpha = 0.5; diffGrp.add(offsetTxt); - offsetsPerBeat.push(0); + offsetsPerBeat.push(null); } songVisFollowAudio = new FlxSprite(0, FlxG.height - 20).makeGraphic(2, 20, FlxColor.YELLOW); @@ -248,10 +248,15 @@ class LatencyState extends MusicBeatSubState var avgOffsetInput:Float = 0; + var loopInd:Int = 0; for (offsetThing in offsetsPerBeat) + { + if (offsetThing == null) continue; avgOffsetInput += offsetThing; + loopInd++; + } - avgOffsetInput /= offsetsPerBeat.length; + avgOffsetInput /= loopInd; offsetText.text += "\n\nEstimated average input offset needed: " + avgOffsetInput; From 638c1666633cddd73398efbb2ccc6cb0bf59aa3d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Thu, 15 Feb 2024 04:10:48 -0500 Subject: [PATCH 22/37] optimization when opening from pause menu --- source/funkin/ui/debug/latency/LatencyState.hx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 0d486fca1..282f05651 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -51,10 +51,21 @@ class LatencyState extends MusicBeatSubState */ var localConductor:Conductor; + // stores values of what the previous persistent draw/update stuff was, example if opened + // from pause menu, we want to NOT draw persistently, but then resume drawing once closed + var prevPersistentDraw:Bool; + var prevPersistentUpdate:Bool; + override function create() { super.create(); + prevPersistentDraw = FlxG.state.persistentDraw; + prevPersistentUpdate = FlxG.state.persistentUpdate; + + FlxG.state.persistentDraw = false; + FlxG.state.persistentUpdate = false; + localConductor = new Conductor(); conductorInUse = localConductor; @@ -179,7 +190,6 @@ class LatencyState extends MusicBeatSubState override public function close():Void { PreciseInputManager.instance.onInputPressed.remove(preciseInputPressed); - PreciseInputManager.instance.onInputReleased.remove(preciseInputReleased); FlxG.sound.music.volume = previousVolume; @@ -188,6 +198,8 @@ class LatencyState extends MusicBeatSubState FlxG.cameras.remove(stateCamera); + FlxG.state.persistentDraw = prevPersistentDraw; + FlxG.state.persistentUpdate = prevPersistentUpdate; super.close(); } From 94732c1190c634a65ef7425669ad8f62f74a4e72 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 19 Feb 2024 20:33:48 -0500 Subject: [PATCH 23/37] assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 75ac8ec25..e76470d66 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 75ac8ec2564c9a56e8282b0853091ecd8b4f2dfd +Subproject commit e76470d66794bf3796f7ace84f2121b698e37a30 From 63a49010ba0d88d591b37b9513737b6b2f590056 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 19 Feb 2024 20:56:57 -0500 Subject: [PATCH 24/37] positioning and average reset --- .../funkin/ui/debug/latency/LatencyState.hx | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 282f05651..480338e46 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -108,7 +108,7 @@ class LatencyState extends MusicBeatSubState beatTick.alpha = 0.3; add(beatTick); - var offsetTxt:FlxText = new FlxText(songPosToX(beat * (localConductor.stepLengthMs * 2)), FlxG.height - 26, 0, "swag"); + var offsetTxt:FlxText = new FlxText(songPosToX(beat * (localConductor.stepLengthMs * 2)), FlxG.height - 26, 0, ""); offsetTxt.alpha = 0.5; diffGrp.add(offsetTxt); @@ -168,7 +168,7 @@ class LatencyState extends MusicBeatSubState helpText.setFormat(Paths.font("vcr.ttf"), 20); helpText.text = "Press ESC to return to main menu"; helpText.x = FlxG.width - helpText.width; - helpText.y = FlxG.height - helpText.height - 2; + helpText.y = FlxG.height - (helpText.height * 2) - 2; add(helpText); regenNoteData(); @@ -290,14 +290,22 @@ class LatencyState extends MusicBeatSubState } else { - if (FlxG.keys.justPressed.RIGHT) + if (FlxG.keys.anyJustPressed([LEFT, RIGHT])) { - localConductor.inputOffset += 1 * multiply; - } + if (FlxG.keys.justPressed.RIGHT) + { + localConductor.inputOffset += 1 * multiply; + } - if (FlxG.keys.justPressed.LEFT) - { - localConductor.inputOffset -= 1 * multiply; + if (FlxG.keys.justPressed.LEFT) + { + localConductor.inputOffset -= 1 * multiply; + } + + // reset the average, so you don't need to wait a full loop to start getting averages + // also reset each text member + offsetsPerBeat = []; + diffGrp.forEach(memb -> memb.text = ""); } } From e87a31368ac19c8cc1f1622b65266b6c19cf98c7 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 19 Feb 2024 21:03:50 -0500 Subject: [PATCH 25/37] update lime to version with ndll files --- hmm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hmm.json b/hmm.json index f45340855..dbb9d646e 100644 --- a/hmm.json +++ b/hmm.json @@ -104,7 +104,7 @@ "name": "lime", "type": "git", "dir": null, - "ref": "6c92c7e", + "ref": "90e6727a8127e016f1071ace045b5c6542ded099", "url": "https://github.com/FunkinCrew/lime" }, { From dc638a130371206407f7e4e0db4a69f599bb6ec3 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 23 Mar 2024 15:34:37 -0400 Subject: [PATCH 26/37] Fix a bunch of merge bugs. --- source/funkin/Conductor.hx | 16 +-- source/funkin/InitState.hx | 12 +- source/funkin/data/DataParse.hx | 4 +- source/funkin/data/conversation/TODO.md | 0 source/funkin/data/dialogue/TODO.md | 0 .../data/dialogue/conversation/CHANGELOG.md | 9 ++ .../{ => conversation}/ConversationData.hx | 2 +- .../ConversationRegistry.hx | 4 +- .../data/dialogue/dialoguebox/CHANGELOG.md | 13 ++ .../{ => dialoguebox}/DialogueBoxData.hx | 2 +- .../{ => dialoguebox}/DialogueBoxRegistry.hx | 4 +- .../funkin/data/dialogue/speaker/CHANGELOG.md | 9 ++ .../dialogue/{ => speaker}/SpeakerData.hx | 2 +- .../dialogue/{ => speaker}/SpeakerRegistry.hx | 4 +- .../data/freeplay/{ => album}/AlbumData.hx | 2 +- .../freeplay/{ => album}/AlbumRegistry.hx | 4 +- .../funkin/data/freeplay/album/CHANGELOG.md | 9 ++ source/funkin/data/song/CHANGELOG.md | 36 +++++ source/funkin/data/speaker/TODO.md | 0 source/funkin/data/stage/CHANGELOG.md | 14 ++ source/funkin/data/stage/StageRegistry.hx | 2 +- source/funkin/data/story/level/CHANGELOG.md | 9 ++ .../data/{ => story}/level/LevelData.hx | 4 +- .../data/{ => story}/level/LevelRegistry.hx | 4 +- source/funkin/modding/PolymodHandler.hx | 10 +- source/funkin/play/PlayState.hx | 10 +- .../play/cutscene/dialogue/Conversation.hx | 14 +- .../play/cutscene/dialogue/DialogueBox.hx | 4 +- .../funkin/play/cutscene/dialogue/Speaker.hx | 4 +- source/funkin/play/notes/Strumline.hx | 133 +++--------------- source/funkin/ui/MusicBeatState.hx | 16 ++- source/funkin/ui/MusicBeatSubState.hx | 7 +- .../debug/dialogue/ConversationDebugState.hx | 14 +- source/funkin/ui/freeplay/Album.hx | 4 +- source/funkin/ui/freeplay/AlbumRoll.hx | 2 +- source/funkin/ui/freeplay/FreeplayState.hx | 2 +- source/funkin/ui/options/OptionsState.hx | 4 + source/funkin/ui/story/Level.hx | 4 +- source/funkin/ui/story/LevelProp.hx | 2 +- source/funkin/ui/story/StoryMenuState.hx | 2 +- 40 files changed, 216 insertions(+), 181 deletions(-) delete mode 100644 source/funkin/data/conversation/TODO.md delete mode 100644 source/funkin/data/dialogue/TODO.md create mode 100644 source/funkin/data/dialogue/conversation/CHANGELOG.md rename source/funkin/data/dialogue/{ => conversation}/ConversationData.hx (98%) rename source/funkin/data/dialogue/{ => conversation}/ConversationRegistry.hx (95%) create mode 100644 source/funkin/data/dialogue/dialoguebox/CHANGELOG.md rename source/funkin/data/dialogue/{ => dialoguebox}/DialogueBoxData.hx (98%) rename source/funkin/data/dialogue/{ => dialoguebox}/DialogueBoxRegistry.hx (95%) create mode 100644 source/funkin/data/dialogue/speaker/CHANGELOG.md rename source/funkin/data/dialogue/{ => speaker}/SpeakerData.hx (97%) rename source/funkin/data/dialogue/{ => speaker}/SpeakerRegistry.hx (96%) rename source/funkin/data/freeplay/{ => album}/AlbumData.hx (95%) rename source/funkin/data/freeplay/{ => album}/AlbumRegistry.hx (96%) create mode 100644 source/funkin/data/freeplay/album/CHANGELOG.md create mode 100644 source/funkin/data/song/CHANGELOG.md delete mode 100644 source/funkin/data/speaker/TODO.md create mode 100644 source/funkin/data/stage/CHANGELOG.md create mode 100644 source/funkin/data/story/level/CHANGELOG.md rename source/funkin/data/{ => story}/level/LevelData.hx (95%) rename source/funkin/data/{ => story}/level/LevelRegistry.hx (97%) diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index aba154814..5b207c045 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -233,26 +233,26 @@ class Conductor function get_inputOffset():Int { - return Save.get().options.inputOffset; + return Save.instance.options.inputOffset; } function set_inputOffset(value:Int):Int { - Save.get().options.inputOffset = value; - Save.get().flush(); - return Save.get().options.inputOffset; + Save.instance.options.inputOffset = value; + Save.instance.flush(); + return Save.instance.options.inputOffset; } function get_audioVisualOffset():Int { - return Save.get().options.audioVisualOffset; + return Save.instance.options.audioVisualOffset; } function set_audioVisualOffset(value:Int):Int { - Save.get().options.audioVisualOffset = value; - Save.get().flush(); - return Save.get().options.audioVisualOffset; + Save.instance.options.audioVisualOffset = value; + Save.instance.flush(); + return Save.instance.options.audioVisualOffset; } /** diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx index 6ea77ec18..59c19d6ce 100644 --- a/source/funkin/InitState.hx +++ b/source/funkin/InitState.hx @@ -16,14 +16,14 @@ import funkin.util.macro.MacroUtil; import funkin.util.WindowUtil; import funkin.play.PlayStatePlaylist; import openfl.display.BitmapData; -import funkin.data.level.LevelRegistry; +import funkin.data.story.level.LevelRegistry; import funkin.data.notestyle.NoteStyleRegistry; import funkin.data.event.SongEventRegistry; import funkin.data.stage.StageRegistry; -import funkin.data.dialogue.ConversationRegistry; -import funkin.data.dialogue.DialogueBoxRegistry; -import funkin.data.dialogue.SpeakerRegistry; -import funkin.data.freeplay.AlbumRegistry; +import funkin.data.dialogue.conversation.ConversationRegistry; +import funkin.data.dialogue.dialoguebox.DialogueBoxRegistry; +import funkin.data.dialogue.speaker.SpeakerRegistry; +import funkin.data.freeplay.album.AlbumRegistry; import funkin.data.song.SongRegistry; import funkin.play.character.CharacterData.CharacterDataParser; import funkin.modding.module.ModuleHandler; @@ -275,7 +275,7 @@ class InitState extends FlxState */ function startLevel(levelId:String, difficultyId:String = 'normal'):Void { - var currentLevel:funkin.ui.story.Level = funkin.data.level.LevelRegistry.instance.fetchEntry(levelId); + var currentLevel:funkin.ui.story.Level = funkin.data.story.level.LevelRegistry.instance.fetchEntry(levelId); if (currentLevel == null) { diff --git a/source/funkin/data/DataParse.hx b/source/funkin/data/DataParse.hx index 244d41132..472ffd6e7 100644 --- a/source/funkin/data/DataParse.hx +++ b/source/funkin/data/DataParse.hx @@ -120,7 +120,7 @@ class DataParse } } - public static function backdropData(json:Json, name:String):funkin.data.dialogue.ConversationData.BackdropData + public static function backdropData(json:Json, name:String):funkin.data.dialogue.conversation.ConversationData.BackdropData { switch (json.value) { @@ -152,7 +152,7 @@ class DataParse } } - public static function outroData(json:Json, name:String):Null + public static function outroData(json:Json, name:String):Null { switch (json.value) { diff --git a/source/funkin/data/conversation/TODO.md b/source/funkin/data/conversation/TODO.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/source/funkin/data/dialogue/TODO.md b/source/funkin/data/dialogue/TODO.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/source/funkin/data/dialogue/conversation/CHANGELOG.md b/source/funkin/data/dialogue/conversation/CHANGELOG.md new file mode 100644 index 000000000..f9ab99fab --- /dev/null +++ b/source/funkin/data/dialogue/conversation/CHANGELOG.md @@ -0,0 +1,9 @@ +# Dialogue Conversation Data Schema Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.0] +Initial release. diff --git a/source/funkin/data/dialogue/ConversationData.hx b/source/funkin/data/dialogue/conversation/ConversationData.hx similarity index 98% rename from source/funkin/data/dialogue/ConversationData.hx rename to source/funkin/data/dialogue/conversation/ConversationData.hx index 795ddae9a..30e3f451b 100644 --- a/source/funkin/data/dialogue/ConversationData.hx +++ b/source/funkin/data/dialogue/conversation/ConversationData.hx @@ -1,4 +1,4 @@ -package funkin.data.dialogue; +package funkin.data.dialogue.conversation; import funkin.data.animation.AnimationData; diff --git a/source/funkin/data/dialogue/ConversationRegistry.hx b/source/funkin/data/dialogue/conversation/ConversationRegistry.hx similarity index 95% rename from source/funkin/data/dialogue/ConversationRegistry.hx rename to source/funkin/data/dialogue/conversation/ConversationRegistry.hx index 9186ef786..e64d62831 100644 --- a/source/funkin/data/dialogue/ConversationRegistry.hx +++ b/source/funkin/data/dialogue/conversation/ConversationRegistry.hx @@ -1,7 +1,7 @@ -package funkin.data.dialogue; +package funkin.data.dialogue.conversation; import funkin.play.cutscene.dialogue.Conversation; -import funkin.data.dialogue.ConversationData; +import funkin.data.dialogue.conversation.ConversationData; import funkin.play.cutscene.dialogue.ScriptedConversation; class ConversationRegistry extends BaseRegistry diff --git a/source/funkin/data/dialogue/dialoguebox/CHANGELOG.md b/source/funkin/data/dialogue/dialoguebox/CHANGELOG.md new file mode 100644 index 000000000..06604734a --- /dev/null +++ b/source/funkin/data/dialogue/dialoguebox/CHANGELOG.md @@ -0,0 +1,13 @@ +# Dialogue Box Data Schema Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.1.0] +### Added +- Added an option to specify the font used by the dialogue box. Defaults to `Arial` if unspecified. + +## [1.0.0] +Initial release. diff --git a/source/funkin/data/dialogue/DialogueBoxData.hx b/source/funkin/data/dialogue/dialoguebox/DialogueBoxData.hx similarity index 98% rename from source/funkin/data/dialogue/DialogueBoxData.hx rename to source/funkin/data/dialogue/dialoguebox/DialogueBoxData.hx index a75a5595a..228d391c8 100644 --- a/source/funkin/data/dialogue/DialogueBoxData.hx +++ b/source/funkin/data/dialogue/dialoguebox/DialogueBoxData.hx @@ -1,4 +1,4 @@ -package funkin.data.dialogue; +package funkin.data.dialogue.dialoguebox; import funkin.data.animation.AnimationData; diff --git a/source/funkin/data/dialogue/DialogueBoxRegistry.hx b/source/funkin/data/dialogue/dialoguebox/DialogueBoxRegistry.hx similarity index 95% rename from source/funkin/data/dialogue/DialogueBoxRegistry.hx rename to source/funkin/data/dialogue/dialoguebox/DialogueBoxRegistry.hx index 87205d96c..ec0feeaae 100644 --- a/source/funkin/data/dialogue/DialogueBoxRegistry.hx +++ b/source/funkin/data/dialogue/dialoguebox/DialogueBoxRegistry.hx @@ -1,7 +1,7 @@ -package funkin.data.dialogue; +package funkin.data.dialogue.dialoguebox; import funkin.play.cutscene.dialogue.DialogueBox; -import funkin.data.dialogue.DialogueBoxData; +import funkin.data.dialogue.dialoguebox.DialogueBoxData; import funkin.play.cutscene.dialogue.ScriptedDialogueBox; class DialogueBoxRegistry extends BaseRegistry diff --git a/source/funkin/data/dialogue/speaker/CHANGELOG.md b/source/funkin/data/dialogue/speaker/CHANGELOG.md new file mode 100644 index 000000000..284e690e1 --- /dev/null +++ b/source/funkin/data/dialogue/speaker/CHANGELOG.md @@ -0,0 +1,9 @@ +# Dialogue Speaker Data Schema Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.0] +Initial release. diff --git a/source/funkin/data/dialogue/SpeakerData.hx b/source/funkin/data/dialogue/speaker/SpeakerData.hx similarity index 97% rename from source/funkin/data/dialogue/SpeakerData.hx rename to source/funkin/data/dialogue/speaker/SpeakerData.hx index e8a2eacf0..458f91cab 100644 --- a/source/funkin/data/dialogue/SpeakerData.hx +++ b/source/funkin/data/dialogue/speaker/SpeakerData.hx @@ -1,4 +1,4 @@ -package funkin.data.dialogue; +package funkin.data.dialogue.speaker; import funkin.data.animation.AnimationData; diff --git a/source/funkin/data/dialogue/SpeakerRegistry.hx b/source/funkin/data/dialogue/speaker/SpeakerRegistry.hx similarity index 96% rename from source/funkin/data/dialogue/SpeakerRegistry.hx rename to source/funkin/data/dialogue/speaker/SpeakerRegistry.hx index 6bd301dd7..7db501d41 100644 --- a/source/funkin/data/dialogue/SpeakerRegistry.hx +++ b/source/funkin/data/dialogue/speaker/SpeakerRegistry.hx @@ -1,7 +1,7 @@ -package funkin.data.dialogue; +package funkin.data.dialogue.speaker; import funkin.play.cutscene.dialogue.Speaker; -import funkin.data.dialogue.SpeakerData; +import funkin.data.dialogue.speaker.SpeakerData; import funkin.play.cutscene.dialogue.ScriptedSpeaker; class SpeakerRegistry extends BaseRegistry diff --git a/source/funkin/data/freeplay/AlbumData.hx b/source/funkin/data/freeplay/album/AlbumData.hx similarity index 95% rename from source/funkin/data/freeplay/AlbumData.hx rename to source/funkin/data/freeplay/album/AlbumData.hx index 265a01fce..bb6ca4f00 100644 --- a/source/funkin/data/freeplay/AlbumData.hx +++ b/source/funkin/data/freeplay/album/AlbumData.hx @@ -1,4 +1,4 @@ -package funkin.data.freeplay; +package funkin.data.freeplay.album; /** * A type definition for the data for an album of songs. diff --git a/source/funkin/data/freeplay/AlbumRegistry.hx b/source/funkin/data/freeplay/album/AlbumRegistry.hx similarity index 96% rename from source/funkin/data/freeplay/AlbumRegistry.hx rename to source/funkin/data/freeplay/album/AlbumRegistry.hx index 78fba451b..c04464fd2 100644 --- a/source/funkin/data/freeplay/AlbumRegistry.hx +++ b/source/funkin/data/freeplay/album/AlbumRegistry.hx @@ -1,7 +1,7 @@ -package funkin.data.freeplay; +package funkin.data.freeplay.album; import funkin.ui.freeplay.Album; -import funkin.data.freeplay.AlbumData; +import funkin.data.freeplay.album.AlbumData; import funkin.ui.freeplay.ScriptedAlbum; class AlbumRegistry extends BaseRegistry diff --git a/source/funkin/data/freeplay/album/CHANGELOG.md b/source/funkin/data/freeplay/album/CHANGELOG.md new file mode 100644 index 000000000..ae307465e --- /dev/null +++ b/source/funkin/data/freeplay/album/CHANGELOG.md @@ -0,0 +1,9 @@ +# Freeplay Album Data Schema Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.0] +Initial release. diff --git a/source/funkin/data/song/CHANGELOG.md b/source/funkin/data/song/CHANGELOG.md new file mode 100644 index 000000000..3cd3af070 --- /dev/null +++ b/source/funkin/data/song/CHANGELOG.md @@ -0,0 +1,36 @@ +# Song Chart Data Schema Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [2.2.2] +### Added +- Added `playData.previewStart` and `playData.previewEnd` fields to specify when in the song should the song's audio should be played as a preview in Freeplay. + +## [2.2.1] +### Added +- Added `playData.offsets` field to specify instrumental and vocal offsets. + +## [2.2.0] +### Added +- Added `playData.album` to specify the album art to display in Freeplay. +- Added `playData.ratings` for difficulty ratings displayed in Freeplay. +### Changed +- Renamed `playData.noteSkin` to `playData.noteStyle`. + +## [2.1.0] +### Changed +- Rearranged the `playData` field. + - Refactored the `playableChars` +### Removed +- Removed the `variation` field. + +## [2.0.0] +Full refactor of the chart format for improved structure. +### Added +- Added a semantic version field for migration tracking. + +## [1.0.0] +Initial version from 2020. diff --git a/source/funkin/data/speaker/TODO.md b/source/funkin/data/speaker/TODO.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/source/funkin/data/stage/CHANGELOG.md b/source/funkin/data/stage/CHANGELOG.md new file mode 100644 index 000000000..879139db5 --- /dev/null +++ b/source/funkin/data/stage/CHANGELOG.md @@ -0,0 +1,14 @@ +# Story Mode Level Data Schema Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.1] +### Added +- Added the ability to specify a hexadecimal color in the `assetPath` field instead of a texture key. + - In this case, the `scale` property will be used to determine the size of the rectangle in pixels. + +## [1.0.0] +Initial release. diff --git a/source/funkin/data/stage/StageRegistry.hx b/source/funkin/data/stage/StageRegistry.hx index b78292e5b..f18a643d2 100644 --- a/source/funkin/data/stage/StageRegistry.hx +++ b/source/funkin/data/stage/StageRegistry.hx @@ -11,7 +11,7 @@ class StageRegistry extends BaseRegistry * Handle breaking changes by incrementing this value * and adding migration to the `migrateStageData()` function. */ - public static final STAGE_DATA_VERSION:thx.semver.Version = "1.0.1"; + public static final STAGE_DATA_VERSION:thx.semver.Version = "1.0.0"; public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; diff --git a/source/funkin/data/story/level/CHANGELOG.md b/source/funkin/data/story/level/CHANGELOG.md new file mode 100644 index 000000000..75d1fe4c0 --- /dev/null +++ b/source/funkin/data/story/level/CHANGELOG.md @@ -0,0 +1,9 @@ +# Story Mode Level Data Schema Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.0.0] +Initial release. diff --git a/source/funkin/data/level/LevelData.hx b/source/funkin/data/story/level/LevelData.hx similarity index 95% rename from source/funkin/data/level/LevelData.hx rename to source/funkin/data/story/level/LevelData.hx index f5e58ae16..957a9f66f 100644 --- a/source/funkin/data/level/LevelData.hx +++ b/source/funkin/data/story/level/LevelData.hx @@ -1,4 +1,4 @@ -package funkin.data.level; +package funkin.data.story.level; import funkin.data.animation.AnimationData; @@ -13,7 +13,7 @@ typedef LevelData = * When making changes to the level data format, this should be incremented, * and a migration function should be added to LevelDataParser to handle old versions. */ - @:default(funkin.data.level.LevelRegistry.LEVEL_DATA_VERSION) + @:default(funkin.data.story.level.LevelRegistry.LEVEL_DATA_VERSION) var version:String; /** diff --git a/source/funkin/data/level/LevelRegistry.hx b/source/funkin/data/story/level/LevelRegistry.hx similarity index 97% rename from source/funkin/data/level/LevelRegistry.hx rename to source/funkin/data/story/level/LevelRegistry.hx index 96712cba5..4f33207c8 100644 --- a/source/funkin/data/level/LevelRegistry.hx +++ b/source/funkin/data/story/level/LevelRegistry.hx @@ -1,7 +1,7 @@ -package funkin.data.level; +package funkin.data.story.level; import funkin.ui.story.Level; -import funkin.data.level.LevelData; +import funkin.data.story.level.LevelData; import funkin.ui.story.ScriptedLevel; class LevelRegistry extends BaseRegistry diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index a88476d4d..c53374454 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -1,14 +1,14 @@ package funkin.modding; -import funkin.data.dialogue.ConversationRegistry; -import funkin.data.dialogue.DialogueBoxRegistry; -import funkin.data.dialogue.SpeakerRegistry; +import funkin.data.dialogue.conversation.ConversationRegistry; +import funkin.data.dialogue.dialoguebox.DialogueBoxRegistry; +import funkin.data.dialogue.speaker.SpeakerRegistry; import funkin.data.event.SongEventRegistry; -import funkin.data.level.LevelRegistry; +import funkin.data.story.level.LevelRegistry; import funkin.data.notestyle.NoteStyleRegistry; import funkin.data.song.SongRegistry; import funkin.data.stage.StageRegistry; -import funkin.data.freeplay.AlbumRegistry; +import funkin.data.freeplay.album.AlbumRegistry; import funkin.modding.module.ModuleHandler; import funkin.play.character.CharacterData.CharacterDataParser; import funkin.save.Save; diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 12b290afd..a4f665329 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -24,7 +24,7 @@ import flixel.util.FlxTimer; import funkin.api.newgrounds.NGio; import funkin.audio.VoicesGroup; import funkin.audio.VoicesGroup; -import funkin.data.dialogue.ConversationRegistry; +import funkin.data.dialogue.conversation.ConversationRegistry; import funkin.data.event.SongEventRegistry; import funkin.data.notestyle.NoteStyleData; import funkin.data.notestyle.NoteStyleRegistry; @@ -2011,10 +2011,10 @@ class PlayState extends MusicBeatSubState { if (note == null) continue; - // TODO: Does this properly account for offsets? - var hitWindowStart = note.strumTime - Constants.HIT_WINDOW_MS; - var hitWindowCenter = note.strumTime; - var hitWindowEnd = note.strumTime + Constants.HIT_WINDOW_MS; + // TODO: Are offsets being accounted for in the correct direction? + var hitWindowStart = note.strumTime + Conductor.instance.inputOffset - Constants.HIT_WINDOW_MS; + var hitWindowCenter = note.strumTime + Conductor.instance.inputOffset; + var hitWindowEnd = note.strumTime + Conductor.instance.inputOffset + Constants.HIT_WINDOW_MS; if (Conductor.instance.songPosition > hitWindowEnd) { diff --git a/source/funkin/play/cutscene/dialogue/Conversation.hx b/source/funkin/play/cutscene/dialogue/Conversation.hx index f865f3b7b..1b899acf5 100644 --- a/source/funkin/play/cutscene/dialogue/Conversation.hx +++ b/source/funkin/play/cutscene/dialogue/Conversation.hx @@ -16,13 +16,13 @@ import funkin.play.cutscene.dialogue.DialogueBox; import funkin.modding.IScriptedClass.IDialogueScriptedClass; import funkin.modding.events.ScriptEventDispatcher; import flixel.addons.display.FlxPieDial; -import funkin.data.dialogue.ConversationData; -import funkin.data.dialogue.ConversationData.DialogueEntryData; -import funkin.data.dialogue.ConversationRegistry; -import funkin.data.dialogue.SpeakerData; -import funkin.data.dialogue.SpeakerRegistry; -import funkin.data.dialogue.DialogueBoxData; -import funkin.data.dialogue.DialogueBoxRegistry; +import funkin.data.dialogue.conversation.ConversationData; +import funkin.data.dialogue.conversation.ConversationData.DialogueEntryData; +import funkin.data.dialogue.conversation.ConversationRegistry; +import funkin.data.dialogue.speaker.SpeakerData; +import funkin.data.dialogue.speaker.SpeakerRegistry; +import funkin.data.dialogue.dialoguebox.DialogueBoxData; +import funkin.data.dialogue.dialoguebox.DialogueBoxRegistry; /** * A high-level handler for dialogue. diff --git a/source/funkin/play/cutscene/dialogue/DialogueBox.hx b/source/funkin/play/cutscene/dialogue/DialogueBox.hx index fe4f13be0..6d3c0b8bc 100644 --- a/source/funkin/play/cutscene/dialogue/DialogueBox.hx +++ b/source/funkin/play/cutscene/dialogue/DialogueBox.hx @@ -11,8 +11,8 @@ import funkin.modding.events.ScriptEvent; import funkin.audio.FunkinSound; import funkin.modding.IScriptedClass.IDialogueScriptedClass; import flixel.util.FlxColor; -import funkin.data.dialogue.DialogueBoxData; -import funkin.data.dialogue.DialogueBoxRegistry; +import funkin.data.dialogue.dialoguebox.DialogueBoxData; +import funkin.data.dialogue.dialoguebox.DialogueBoxRegistry; class DialogueBox extends FlxSpriteGroup implements IDialogueScriptedClass implements IRegistryEntry { diff --git a/source/funkin/play/cutscene/dialogue/Speaker.hx b/source/funkin/play/cutscene/dialogue/Speaker.hx index 0d29481c4..7203ddb28 100644 --- a/source/funkin/play/cutscene/dialogue/Speaker.hx +++ b/source/funkin/play/cutscene/dialogue/Speaker.hx @@ -6,8 +6,8 @@ import funkin.modding.events.ScriptEvent; import flixel.graphics.frames.FlxFramesCollection; import funkin.util.assets.FlxAnimationUtil; import funkin.modding.IScriptedClass.IDialogueScriptedClass; -import funkin.data.dialogue.SpeakerData; -import funkin.data.dialogue.SpeakerRegistry; +import funkin.data.dialogue.speaker.SpeakerData; +import funkin.data.dialogue.speaker.SpeakerRegistry; /** * The character sprite which displays during dialogue. diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index aa87fa2e4..f2db41428 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -50,7 +50,20 @@ class Strumline extends FlxSpriteGroup * Usually you want to keep this as is, but if you are using a Strumline and * playing a sound that has it's own conductor, set this (LatencyState for example) */ - public var conductorInUse:Conductor = Conductor.instance; + public var conductorInUse(get, set):Conductor; + + var _conductorInUse:Null; + + function get_conductorInUse():Conductor + { + if (_conductorInUse == null) return Conductor.instance; + return _conductorInUse; + } + + function set_conductorInUse(value:Conductor):Conductor + { + return _conductorInUse = value; + } /** * The notes currently being rendered on the strumline. @@ -159,103 +172,9 @@ class Strumline extends FlxSpriteGroup } /** - * Process the notes in this strumline. - * @param onNoteMiss - * @param dispatchEvent TODO: better way to do this? Maybe passing in current dispatchEvent function from current state? + * Return notes that are within `Constants.HIT_WINDOW` ms of the strumline. + * @return An array of `NoteSprite` objects. */ - public function processNotes(?onNoteMiss:NoteSprite->Void, ?dispatchEvent:ScriptEvent->Void) - { - for (note in notes.members) - { - if (note == null || (isPlayer && note.hasBeenHit)) continue; - - var hitWindowStart = note.strumTime - Constants.HIT_WINDOW_MS; - var hitWindowCenter = note.strumTime; - var hitWindowEnd = note.strumTime + Constants.HIT_WINDOW_MS; - - if (conductorInUse.songPosition > hitWindowEnd) - { - if (!isPlayer && note.hasMissed) continue; - - note.tooEarly = false; - note.mayHit = false; - note.hasMissed = true; - - if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = true; - } - else if (conductorInUse.songPosition > hitWindowCenter) - { - // only run this on opponent strumlines! - if (!isPlayer) continue; - - // Call an event to allow canceling the note hit. - // NOTE: This is what handles the character animations! - var event:NoteScriptEvent = new NoteScriptEvent(NOTE_HIT, note, 0, true); - if (dispatchEvent != null) dispatchEvent(event); - - // Calling event.cancelEvent() skips all other logic! Neat! - if (event.eventCanceled) continue; - - // Command the opponent to hit the note on time. - // NOTE: This is what handles the strumline and cleaning up the note itself! - - hitNote(note); - - if (note.holdNoteSprite != null) - { - playNoteHoldCover(note.holdNoteSprite); - } - } - else if (conductorInUse.songPosition > hitWindowStart) - { - if (!isPlayer && (note.hasBeenHit || note.hasMissed)) continue; - - note.tooEarly = false; - note.mayHit = true; - note.hasMissed = false; - if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false; - } - else - { - note.tooEarly = true; - note.mayHit = false; - note.hasMissed = false; - if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = false; - } - - if (note.hasMissed && !note.handledMiss) - { - var event:NoteScriptEvent = new NoteScriptEvent(NOTE_MISS, note, 0, true); - - if (dispatchEvent != null) dispatchEvent(event); - - if (event.eventCanceled) continue; - - if (onNoteMiss != null) onNoteMiss(note); - - note.handledMiss = true; - } - } - } - - var frameMax:Int; - var animFinishedEver:Bool; - - /** - * Get a list of notes within + or - the given strumtime. - * @param strumTime The current time. - * @param hitWindow The hit window to check. - */ - public function getNotesInRange(strumTime:Float, hitWindow:Float):Array - { - var hitWindowStart:Float = strumTime - hitWindow; - var hitWindowEnd:Float = strumTime + hitWindow; - - return notes.members.filter(function(note:NoteSprite) { - return note != null && note.alive && !note.hasBeenHit && note.strumTime >= hitWindowStart && note.strumTime <= hitWindowEnd; - }); - } - public function getNotesMayHit():Array { return notes.members.filter(function(note:NoteSprite) { @@ -263,6 +182,10 @@ class Strumline extends FlxSpriteGroup }); } + /** + * Return hold notes that are within `Constants.HIT_WINDOW` ms of the strumline. + * @return An array of `SustainTrail` objects. + */ public function getHoldNotesHitOrMissed():Array { return holdNotes.members.filter(function(holdNote:SustainTrail) { @@ -270,19 +193,6 @@ class Strumline extends FlxSpriteGroup }); } - public function getHoldNotesInRange(strumTime:Float, hitWindow:Float):Array - { - var hitWindowStart:Float = strumTime - hitWindow; - var hitWindowEnd:Float = strumTime + hitWindow; - - return holdNotes.members.filter(function(note:SustainTrail) { - return note != null - && note.alive - && note.strumTime >= hitWindowStart - && (note.strumTime + note.fullSustainLength) <= hitWindowEnd; - }); - } - public function getNoteSprite(noteData:SongNoteData):NoteSprite { if (noteData == null) return null; @@ -382,6 +292,9 @@ class Strumline extends FlxSpriteGroup { if (noteData.length == 0) return; + // Ensure note data gets reset if the song happens to loop. + if (conductorInUse.currentStep == 0) nextNoteIndex = 0; + var songStart:Float = PlayState.instance?.startTimestamp ?? 0.0; var hitWindowStart:Float = conductorInUse.songPosition - Constants.HIT_WINDOW_MS; var renderWindowStart:Float = conductorInUse.songPosition + RENDER_DISTANCE_MS; diff --git a/source/funkin/ui/MusicBeatState.hx b/source/funkin/ui/MusicBeatState.hx index d54fd5b8f..e76bf31a7 100644 --- a/source/funkin/ui/MusicBeatState.hx +++ b/source/funkin/ui/MusicBeatState.hx @@ -27,7 +27,21 @@ class MusicBeatState extends FlxTransitionableState implements IEventHandler public var leftWatermarkText:FlxText = null; public var rightWatermarkText:FlxText = null; - public var conductorInUse:Conductor = Conductor.instance; + + public var conductorInUse(get, set):Conductor; + + var _conductorInUse:Null; + + function get_conductorInUse():Conductor + { + if (_conductorInUse == null) return Conductor.instance; + return _conductorInUse; + } + + function set_conductorInUse(value:Conductor):Conductor + { + return _conductorInUse = value; + } public function new() { diff --git a/source/funkin/ui/MusicBeatSubState.hx b/source/funkin/ui/MusicBeatSubState.hx index ab62a082d..15c564db0 100644 --- a/source/funkin/ui/MusicBeatSubState.hx +++ b/source/funkin/ui/MusicBeatSubState.hx @@ -21,7 +21,7 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler public var leftWatermarkText:FlxText = null; public var rightWatermarkText:FlxText = null; - public var conductorInUse(get, default):Conductor; + public var conductorInUse(get, set):Conductor; var _conductorInUse:Null; @@ -31,6 +31,11 @@ class MusicBeatSubState extends FlxSubState implements IEventHandler return _conductorInUse; } + function set_conductorInUse(value:Conductor):Conductor + { + return _conductorInUse = value; + } + public function new(bgColor:FlxColor = FlxColor.TRANSPARENT) { super(); diff --git a/source/funkin/ui/debug/dialogue/ConversationDebugState.hx b/source/funkin/ui/debug/dialogue/ConversationDebugState.hx index c2edcca5a..db7b35d3e 100644 --- a/source/funkin/ui/debug/dialogue/ConversationDebugState.hx +++ b/source/funkin/ui/debug/dialogue/ConversationDebugState.hx @@ -5,13 +5,13 @@ import funkin.modding.events.ScriptEventDispatcher; import funkin.modding.events.ScriptEvent; import flixel.util.FlxColor; import funkin.ui.MusicBeatState; -import funkin.data.dialogue.ConversationData; -import funkin.data.dialogue.ConversationRegistry; -import funkin.data.dialogue.DialogueBoxData; -import funkin.data.dialogue.DialogueBoxRegistry; -import funkin.data.dialogue.SpeakerData; -import funkin.data.dialogue.SpeakerRegistry; -import funkin.data.freeplay.AlbumRegistry; +import funkin.data.dialogue.conversation.ConversationData; +import funkin.data.dialogue.conversation.ConversationRegistry; +import funkin.data.dialogue.dialoguebox.DialogueBoxData; +import funkin.data.dialogue.dialoguebox.DialogueBoxRegistry; +import funkin.data.dialogue.speaker.SpeakerData; +import funkin.data.dialogue.speaker.SpeakerRegistry; +import funkin.data.freeplay.album.AlbumRegistry; import funkin.play.cutscene.dialogue.Conversation; import funkin.play.cutscene.dialogue.DialogueBox; import funkin.play.cutscene.dialogue.Speaker; diff --git a/source/funkin/ui/freeplay/Album.hx b/source/funkin/ui/freeplay/Album.hx index 7291c7357..a686bff51 100644 --- a/source/funkin/ui/freeplay/Album.hx +++ b/source/funkin/ui/freeplay/Album.hx @@ -1,7 +1,7 @@ package funkin.ui.freeplay; -import funkin.data.freeplay.AlbumData; -import funkin.data.freeplay.AlbumRegistry; +import funkin.data.freeplay.album.AlbumData; +import funkin.data.freeplay.album.AlbumRegistry; import funkin.data.IRegistryEntry; import flixel.graphics.FlxGraphic; diff --git a/source/funkin/ui/freeplay/AlbumRoll.hx b/source/funkin/ui/freeplay/AlbumRoll.hx index a1e63c9a1..6e8ef8fe2 100644 --- a/source/funkin/ui/freeplay/AlbumRoll.hx +++ b/source/funkin/ui/freeplay/AlbumRoll.hx @@ -6,7 +6,7 @@ import flixel.util.FlxSort; import flixel.tweens.FlxTween; import flixel.util.FlxTimer; import flixel.tweens.FlxEase; -import funkin.data.freeplay.AlbumRegistry; +import funkin.data.freeplay.album.AlbumRegistry; import funkin.graphics.FunkinSprite; import funkin.util.SortUtil; import openfl.utils.Assets; diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index fc11eec28..858ff922f 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -18,7 +18,7 @@ import flixel.util.FlxColor; import flixel.util.FlxSpriteUtil; import flixel.util.FlxTimer; import funkin.audio.FunkinSound; -import funkin.data.level.LevelRegistry; +import funkin.data.story.level.LevelRegistry; import funkin.data.song.SongRegistry; import funkin.graphics.FunkinCamera; import funkin.graphics.FunkinSprite; diff --git a/source/funkin/ui/options/OptionsState.hx b/source/funkin/ui/options/OptionsState.hx index 7b233f03d..152d9b817 100644 --- a/source/funkin/ui/options/OptionsState.hx +++ b/source/funkin/ui/options/OptionsState.hx @@ -1,5 +1,6 @@ package funkin.ui.options; +import funkin.ui.debug.latency.LatencyState; import flixel.FlxSprite; import flixel.FlxSubState; import flixel.addons.transition.FlxTransitionableState; @@ -182,6 +183,9 @@ class OptionsMenu extends Page add(items = new TextMenuList()); createItem("PREFERENCES", function() switchPage(Preferences)); createItem("CONTROLS", function() switchPage(Controls)); + createItem("INPUT OFFSETS", function() { + FlxG.state.openSubState(new LatencyState()); + }); #if newgrounds if (NGio.isLoggedIn) createItem("LOGOUT", selectLogout); diff --git a/source/funkin/ui/story/Level.hx b/source/funkin/ui/story/Level.hx index 626fb8e52..22f10f096 100644 --- a/source/funkin/ui/story/Level.hx +++ b/source/funkin/ui/story/Level.hx @@ -6,8 +6,8 @@ import flixel.util.FlxColor; import funkin.play.song.Song; import funkin.data.IRegistryEntry; import funkin.data.song.SongRegistry; -import funkin.data.level.LevelRegistry; -import funkin.data.level.LevelData; +import funkin.data.story.level.LevelRegistry; +import funkin.data.story.level.LevelData; /** * An object used to retrieve data about a story mode level (also known as "weeks"). diff --git a/source/funkin/ui/story/LevelProp.hx b/source/funkin/ui/story/LevelProp.hx index d8eae9c77..ffc756e1c 100644 --- a/source/funkin/ui/story/LevelProp.hx +++ b/source/funkin/ui/story/LevelProp.hx @@ -2,7 +2,7 @@ package funkin.ui.story; import funkin.play.stage.Bopper; import funkin.util.assets.FlxAnimationUtil; -import funkin.data.level.LevelData; +import funkin.data.story.level.LevelData; class LevelProp extends Bopper { diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 9ce110c73..3719704c8 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -9,7 +9,7 @@ import flixel.tweens.FlxTween; import flixel.util.FlxColor; import flixel.util.FlxTimer; import funkin.audio.FunkinSound; -import funkin.data.level.LevelRegistry; +import funkin.data.story.level.LevelRegistry; import funkin.data.song.SongRegistry; import funkin.graphics.FunkinSprite; import funkin.modding.events.ScriptEvent; From 680ed3c2f3f85229326ff442eee833df7ee7b59a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 23 Mar 2024 15:34:48 -0400 Subject: [PATCH 27/37] Fix a syntax error. --- tests/unit/source/funkin/data/level/LevelRegistryTest.hx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/source/funkin/data/level/LevelRegistryTest.hx b/tests/unit/source/funkin/data/level/LevelRegistryTest.hx index 691d8bedc..44cfb909c 100644 --- a/tests/unit/source/funkin/data/level/LevelRegistryTest.hx +++ b/tests/unit/source/funkin/data/level/LevelRegistryTest.hx @@ -1,6 +1,6 @@ -package funkin.data.level; +package funkin.data.story.level; -import funkin.data.level.LevelRegistry; +import funkin.data.story.level.LevelRegistry; import funkin.ui.story.Level; import massive.munit.Assert; import massive.munit.async.AsyncFactory; @@ -8,7 +8,7 @@ import massive.munit.util.Timer; @:nullSafety @:access(funkin.ui.story.Level) -@:access(funkin.data.level.LevelRegistry) +@:access(funkin.data.story.level.LevelRegistry) class LevelRegistryTest extends FunkinTest { public function new() From 9a874d5293a17a93b7779c930a7b5d1583131f3c Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 4 Apr 2024 19:45:57 -0400 Subject: [PATCH 28/37] Fix for weird HSV colors --- assets | 2 +- source/funkin/graphics/shaders/HSVShader.hx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets b/assets index 5027bc656..ad6ed62bd 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 5027bc656c9df5ec208ab256f9494bd7da425111 +Subproject commit ad6ed62bd254456b9584b02ed0a5402118b033a8 diff --git a/source/funkin/graphics/shaders/HSVShader.hx b/source/funkin/graphics/shaders/HSVShader.hx index 733bbca7f..9b6ae4cdd 100644 --- a/source/funkin/graphics/shaders/HSVShader.hx +++ b/source/funkin/graphics/shaders/HSVShader.hx @@ -20,7 +20,7 @@ class HSVShader extends FlxRuntimeShader function set_hue(value:Float):Float { - this.setFloat('hue', value); + this.setFloat('_hue', value); this.hue = value; return this.hue; @@ -28,7 +28,7 @@ class HSVShader extends FlxRuntimeShader function set_saturation(value:Float):Float { - this.setFloat('sat', value); + this.setFloat('_sat', value); this.saturation = value; return this.saturation; @@ -36,7 +36,7 @@ class HSVShader extends FlxRuntimeShader function set_value(value:Float):Float { - this.setFloat('val', value); + this.setFloat('_val', value); this.value = value; return this.value; From 72a3742890c472cc40650a24b307ffacc1e4c19e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 4 Apr 2024 19:46:08 -0400 Subject: [PATCH 29/37] Fixes and improvements to LatencyState --- .../funkin/ui/debug/latency/LatencyState.hx | 25 ++++--------------- source/funkin/ui/freeplay/SongMenuItem.hx | 2 +- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 91cf2013b..9d1bcde71 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -27,7 +27,7 @@ class LatencyState extends MusicBeatSubState { var visualOffsetText:FlxText; var offsetText:FlxText; - var noteGrp:Array; + var noteGrp:Array = []; var strumLine:Strumline; var blocks:FlxTypedGroup; @@ -39,7 +39,7 @@ class LatencyState extends MusicBeatSubState var beatTrail:FlxSprite; var diffGrp:FlxTypedGroup; var offsetsPerBeat:Array> = []; - var swagSong:FlxSound; + var swagSong:HomemadeMusic; var previousVolume:Float; @@ -84,7 +84,7 @@ class LatencyState extends MusicBeatSubState else previousVolume = 1; // defaults to 1 if no music is playing 🤔 also fuck it, emoji in code comment - swagSong = new FlxSound(); + swagSong = new HomemadeMusic(); swagSong.loadEmbedded(Paths.sound('soundTest'), true); swagSong.looped = true; swagSong.play(); @@ -99,7 +99,7 @@ class LatencyState extends MusicBeatSubState FlxG.stage.addEventListener(KeyboardEvent.KEY_DOWN, key -> { trace(key.charCode); - if (key.charCode == 120) generateBeatStuff(); + // if (key.charCode == 120) generateBeatStuff(); trace("\tEVENT PRESS: \t" + FlxG.sound.music.time + " " + Timer.stamp()); // trace(FlxG.sound.music.prevTimestamp); @@ -116,9 +116,6 @@ class LatencyState extends MusicBeatSubState Conductor.instance.forceBPM(60); - noteGrp = new FlxTypedGroup(); - add(noteGrp); - diffGrp = new FlxTypedGroup(); add(diffGrp); @@ -264,7 +261,7 @@ class LatencyState extends MusicBeatSubState trace(FlxG.sound.music._channel.position); */ - localConductor.update(swagSong.time, false, true); + localConductor.update(swagSong.time, false); // localConductor.songPosition += (Timer.stamp() * 1000) - FlxG.sound.music.prevTimestamp; @@ -334,18 +331,6 @@ class LatencyState extends MusicBeatSubState { close(); } - noteGrp.forEach(function(daNote:NoteSprite) { - 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; - - if (daNote.y < 0 - daNote.height) - { - daNote.alpha = 1; - // daNote.data.strumTime += Conductor.instance.beatLengthMs * 8; - } - }); super.update(elapsed); } diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index f8b3d7ac3..bfb40c9ac 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -82,7 +82,7 @@ class SongMenuItem extends FlxSpriteGroup grayscaleShader = new Grayscale(1); diffRatingSprite = new FlxSprite(145, 90).loadGraphic(Paths.image('freeplay/diffRatings/diff00')); - diffRatingSprite.shader = grayscaleShader; + // diffRatingSprite.shader = grayscaleShader; diffRatingSprite.origin.set(capsule.origin.x - diffRatingSprite.x, capsule.origin.y - diffRatingSprite.y); // TODO: Readd once ratings are fully implemented // add(diffRatingSprite); From 17a15a3947cc03e6c4c2424a8a584bbd2bc33c56 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 10 Apr 2024 21:31:22 -0400 Subject: [PATCH 30/37] Reposition notes based on the configured input offset (so you still hit them when centered) --- source/funkin/play/notes/Strumline.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index 73c2a6fab..6a18f17d5 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -285,7 +285,8 @@ class Strumline extends FlxSpriteGroup var vwoosh:Float = 1.0; var scrollSpeed:Float = PlayState.instance?.currentChart?.scrollSpeed ?? 1.0; - return Constants.PIXELS_PER_MS * (conductorInUse.songPosition - strumTime) * scrollSpeed * vwoosh * (Preferences.downscroll ? 1 : -1); + return + Constants.PIXELS_PER_MS * (conductorInUse.songPosition - strumTime - Conductor.instance.inputOffset) * scrollSpeed * vwoosh * (Preferences.downscroll ? 1 : -1); } function updateNotes():Void From e0721b901ec7be33d55fa9293c745156da19503a Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 10 Apr 2024 21:31:49 -0400 Subject: [PATCH 31/37] Fix a bug where negative visual offsets would break the countdown. --- source/funkin/play/PlayState.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 787349952..8787f8175 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -890,7 +890,8 @@ class PlayState extends MusicBeatSubState { if (isInCountdown) { - Conductor.instance.update(Conductor.instance.songPosition + elapsed * 1000); + // Do NOT apply offsets at this point, because they already got applied the previous frame! + Conductor.instance.update(Conductor.instance.songPosition + elapsed * 1000, false); if (Conductor.instance.songPosition >= (startTimestamp)) startSong(); } } From c3ba4081f1b7231a8dda92da78390db95ad72705 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 10 Apr 2024 21:32:08 -0400 Subject: [PATCH 32/37] Fix a crash issue caused when pressing a key after leaving the input offsets state. --- source/funkin/ui/debug/latency/LatencyState.hx | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 9d1bcde71..94f179629 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -96,24 +96,6 @@ class LatencyState extends MusicBeatSubState localConductor.forceBPM(60); - FlxG.stage.addEventListener(KeyboardEvent.KEY_DOWN, key -> { - trace(key.charCode); - - // if (key.charCode == 120) generateBeatStuff(); - - trace("\tEVENT PRESS: \t" + FlxG.sound.music.time + " " + Timer.stamp()); - // trace(FlxG.sound.music.prevTimestamp); - trace(FlxG.sound.music.time); - trace("\tFR FR PRESS: \t" + swagSong.getTimeWithDiff()); - - // trace("\tREDDIT: \t" + swagSong.frfrTime + " " + Timer.stamp()); - @:privateAccess - trace("\tREDDIT: \t" + FlxG.sound.music._channel.position + " " + Timer.stamp()); - // trace("EVENT LISTENER: " + key); - }); - - // funnyStatsGraph.hi - Conductor.instance.forceBPM(60); diffGrp = new FlxTypedGroup(); From 85e06ef18fa2584fb1038e34c12fd696e3e2c264 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 24 Apr 2024 22:08:20 -0400 Subject: [PATCH 33/37] Make it possible to escape the input offsets menu on controller. --- source/funkin/ui/debug/latency/LatencyState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/debug/latency/LatencyState.hx b/source/funkin/ui/debug/latency/LatencyState.hx index 94f179629..962438154 100644 --- a/source/funkin/ui/debug/latency/LatencyState.hx +++ b/source/funkin/ui/debug/latency/LatencyState.hx @@ -166,7 +166,7 @@ class LatencyState extends MusicBeatSubState var helpText:FlxText = new FlxText(); helpText.setFormat(Paths.font("vcr.ttf"), 20); - helpText.text = "Press ESC to return to main menu"; + helpText.text = "Press BACK to return to main menu"; helpText.x = FlxG.width - helpText.width; helpText.y = FlxG.height - (helpText.height * 2) - 2; add(helpText); @@ -309,7 +309,7 @@ class LatencyState extends MusicBeatSubState } } - if (FlxG.keys.justPressed.ESCAPE) + if (controls.BACK) { close(); } From 3083305f51038051944db788e1b5ca0c49999617 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Mon, 29 Apr 2024 02:21:44 +0100 Subject: [PATCH 34/37] fix pixel combo numbers being huge --- source/funkin/play/components/PopUpStuff.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/play/components/PopUpStuff.hx b/source/funkin/play/components/PopUpStuff.hx index b062b22cf..b7e206e97 100644 --- a/source/funkin/play/components/PopUpStuff.hx +++ b/source/funkin/play/components/PopUpStuff.hx @@ -42,7 +42,7 @@ class PopUpStuff extends FlxTypedGroup if (PlayState.instance.currentStageId.startsWith('school')) { - rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.65)); + rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7)); rating.antialiasing = false; } else @@ -133,7 +133,7 @@ class PopUpStuff extends FlxTypedGroup if (PlayState.instance.currentStageId.startsWith('school')) { - numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE)); + numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 0.7)); numScore.antialiasing = false; } else From b35822f9a4935362655bc36f9d698366fc7f1f13 Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Mon, 29 Apr 2024 02:22:11 +0100 Subject: [PATCH 35/37] soundtray fade --- source/funkin/ui/options/FunkinSoundTray.hx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/options/FunkinSoundTray.hx b/source/funkin/ui/options/FunkinSoundTray.hx index 4af94569b..b8c408508 100644 --- a/source/funkin/ui/options/FunkinSoundTray.hx +++ b/source/funkin/ui/options/FunkinSoundTray.hx @@ -20,6 +20,7 @@ class FunkinSoundTray extends FlxSoundTray { var graphicScale:Float = 0.30; var lerpYPos:Float = 0; + var alphaTarget:Float = 0; var volumeMaxSound:String; @@ -40,7 +41,7 @@ class FunkinSoundTray extends FlxSoundTray // makes an alpha'd version of all the bars (bar_10.png) var backingBar:Bitmap = new Bitmap(Assets.getBitmapData(Paths.image("soundtray/bars_10"))); - backingBar.x = 10; + backingBar.x = 9; backingBar.y = 5; backingBar.scaleX = graphicScale; backingBar.scaleY = graphicScale; @@ -56,7 +57,7 @@ class FunkinSoundTray extends FlxSoundTray for (i in 1...11) { var bar:Bitmap = new Bitmap(Assets.getBitmapData(Paths.image("soundtray/bars_" + i))); - bar.x = 10; + bar.x = 9; bar.y = 5; bar.scaleX = graphicScale; bar.scaleY = graphicScale; @@ -77,15 +78,18 @@ class FunkinSoundTray extends FlxSoundTray override public function update(MS:Float):Void { y = MathUtil.coolLerp(y, lerpYPos, 0.1); + alpha = MathUtil.coolLerp(alpha, alphaTarget, 0.25); // Animate sound tray thing if (_timer > 0) { _timer -= (MS / 1000); + alphaTarget = 1; } else if (y > -height) { lerpYPos = -height - 10; + alphaTarget = 0; if (y <= -height) { From c609e3591bd8653194686457a09983aa85786fbb Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Mon, 29 Apr 2024 02:22:33 +0100 Subject: [PATCH 36/37] fixed classic camera reset --- source/funkin/play/event/FocusCameraSongEvent.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/event/FocusCameraSongEvent.hx b/source/funkin/play/event/FocusCameraSongEvent.hx index 569dcb87a..074fafccf 100644 --- a/source/funkin/play/event/FocusCameraSongEvent.hx +++ b/source/funkin/play/event/FocusCameraSongEvent.hx @@ -127,7 +127,7 @@ class FocusCameraSongEvent extends SongEvent switch (ease) { case 'CLASSIC': // Old-school. No ease. Just set follow point. - PlayState.instance.resetCamera(); + PlayState.instance.resetCamera(false, true); PlayState.instance.cameraFollowPoint.setPosition(targetX, targetY); case 'INSTANT': // Instant ease. Duration is automatically 0. PlayState.instance.tweenCameraToPosition(targetX, targetY, 0); From 333b177ffb1f90ab8c515b9abc2d8b1d55c4497b Mon Sep 17 00:00:00 2001 From: FabsTheFabs Date: Mon, 29 Apr 2024 02:22:49 +0100 Subject: [PATCH 37/37] update assets submod --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index ac8bf6e12..61eabfd45 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit ac8bf6e129113551e1c7971327b31096d703e433 +Subproject commit 61eabfd454436c18470af769610fe23b0af9a8e7