diff --git a/source/funkin/Conductor.hx b/source/funkin/Conductor.hx index 4cf245aaf..034477b60 100644 --- a/source/funkin/Conductor.hx +++ b/source/funkin/Conductor.hx @@ -316,7 +316,8 @@ class Conductor } } - resultStep += Math.floor((ms - lastTimeChange.timeStamp) / stepLengthMs); + var resultFractionalStep:Float = (ms - lastTimeChange.timeStamp) / stepLengthMs; + resultStep += resultFractionalStep; // Math.floor(); return resultStep; } diff --git a/source/funkin/ui/debug/charting/ChartEditorNoteSprite.hx b/source/funkin/ui/debug/charting/ChartEditorNoteSprite.hx index 501c28c3c..aa0b97270 100644 --- a/source/funkin/ui/debug/charting/ChartEditorNoteSprite.hx +++ b/source/funkin/ui/debug/charting/ChartEditorNoteSprite.hx @@ -34,16 +34,6 @@ class ChartEditorNoteSprite extends FlxSprite */ public var noteStyle(get, null):String; - /** - * This note is the previous sprite in a sustain chain. - */ - public var parentNoteSprite(default, set):ChartEditorNoteSprite = null; - - /** - * This note is the next sprite in a sustain chain. - */ - public var childNoteSprite(default, set):ChartEditorNoteSprite = null; - public function new(parent:ChartEditorState) { super(); @@ -124,14 +114,6 @@ class ChartEditorNoteSprite extends FlxSprite if (this.noteData == null) { - // Disown parent. - this.parentNoteSprite = null; - if (this.childNoteSprite != null) - { - // Kill all children and disown them. - this.childNoteSprite.noteData = null; - this.childNoteSprite = null; - } this.kill(); return this.noteData; } @@ -170,71 +152,22 @@ class ChartEditorNoteSprite extends FlxSprite } } - if (parentNoteSprite == null) + this.x = cursorColumn * ChartEditorState.GRID_SIZE; + + // Notes far in the song will start far down, but the group they belong to will have a high negative offset. + if (this.noteData.stepTime >= 0) { - this.x = cursorColumn * ChartEditorState.GRID_SIZE; - - // Notes far in the song will start far down, but the group they belong to will have a high negative offset. - if (this.noteData.stepTime >= 0) - { - // noteData.stepTime is a calculated value which accounts for BPM changes - this.y = this.noteData.stepTime * ChartEditorState.GRID_SIZE; - } - - if (origin != null) - { - this.x += origin.x; - this.y += origin.y; - } - } - else - { - // If this is a hold note, we need to adjust the position to be centered. - if (parentNoteSprite.parentNoteSprite == null) - { - this.x = parentNoteSprite.x; - this.x += (ChartEditorState.GRID_SIZE / 2); - this.x -= this.width / 2; - } - else - { - this.x = parentNoteSprite.x; - } - - this.y = parentNoteSprite.y; - if (parentNoteSprite.parentNoteSprite == null) - { - this.y += parentNoteSprite.height / 2; - } - else - { - this.y += parentNoteSprite.height - 1; - } - } - } - - function set_parentNoteSprite(value:ChartEditorNoteSprite):ChartEditorNoteSprite - { - this.parentNoteSprite = value; - - if (this.parentNoteSprite != null) - { - this.noteData = this.parentNoteSprite.noteData; + // noteData.stepTime is a calculated value which accounts for BPM changes + var stepTime:Float = this.noteData.stepTime; + var roundedStepTime:Float = Math.floor(stepTime + 0.01); // Add epsilon to fix rounding issues + this.y = roundedStepTime * ChartEditorState.GRID_SIZE; } - return this.parentNoteSprite; - } - - function set_childNoteSprite(value:ChartEditorNoteSprite):ChartEditorNoteSprite - { - this.childNoteSprite = value; - - if (this.parentNoteSprite != null) + if (origin != null) { - this.noteData = this.parentNoteSprite.noteData; + this.x += origin.x; + this.y += origin.y; } - - return this.childNoteSprite; } function get_noteStyle():String @@ -247,7 +180,6 @@ class ChartEditorNoteSprite extends FlxSprite { // Decide whether to display a note or a sustain. var baseAnimationName:String = 'tap'; - if (this.parentNoteSprite != null) baseAnimationName = (this.childNoteSprite != null) ? 'hold' : 'holdEnd'; // Play the appropriate animation for the type, direction, and skin. var animationName:String = '${baseAnimationName}${this.noteData.getDirectionName()}${this.noteStyle}'; @@ -260,17 +192,6 @@ class ChartEditorNoteSprite extends FlxSprite { case 'tap': this.setGraphicSize(0, ChartEditorState.GRID_SIZE); - case 'hold': - if (parentNoteSprite.parentNoteSprite == null) - { - this.setGraphicSize(Std.int(ChartEditorState.GRID_SIZE / 2), Std.int(ChartEditorState.GRID_SIZE / 2)); - } - else - { - this.setGraphicSize(Std.int(ChartEditorState.GRID_SIZE / 2), ChartEditorState.GRID_SIZE); - } - case 'holdEnd': - this.setGraphicSize(Std.int(ChartEditorState.GRID_SIZE / 2), Std.int(ChartEditorState.GRID_SIZE / 2)); } this.updateHitbox(); @@ -294,11 +215,4 @@ class ChartEditorNoteSprite extends FlxSprite return false; } - - public function getBaseNoteSprite() - { - if (this.parentNoteSprite == null) return this; - else - return this.parentNoteSprite; - } } diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 4a04c0bfb..c73e5fff4 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -1,5 +1,6 @@ package funkin.ui.debug.charting; +import funkin.graphics.rendering.SustainTrail; import funkin.util.SortUtil; import funkin.ui.debug.charting.ChartEditorCommand; import flixel.input.keyboard.FlxKey; @@ -944,6 +945,8 @@ class ChartEditorState extends HaxeUIState */ var renderedNotes:FlxTypedSpriteGroup<ChartEditorNoteSprite>; + var renderedHoldNotes:FlxTypedSpriteGroup<SustainTrail>; + /** * The sprite group containing the song events. * Only displays a subset of the data from `currentSongChartEventData`, @@ -1706,7 +1709,6 @@ class ChartEditorState extends HaxeUIState var cursorFractionalStep:Float = cursorY / GRID_SIZE / (16 / noteSnapQuant); var cursorStep:Int = Std.int(Math.floor(cursorFractionalStep)); var cursorMs:Float = Conductor.getStepTimeInMs(cursorStep); - trace('${cursorFractionalStep} ${cursorStep} ${cursorMs}'); // The direction value for the column at the cursor. var cursorColumn:Int = Math.floor(cursorX / GRID_SIZE); if (cursorColumn < 0) cursorColumn = 0; @@ -1858,8 +1860,7 @@ class ChartEditorState extends HaxeUIState { if (highlightedNote != null) { - // Handle the case of clicking on a sustain piece. - highlightedNote = highlightedNote.getBaseNoteSprite(); + // TODO: Handle the case of clicking on a sustain piece. // Control click to select/deselect an individual note. if (isNoteSelected(highlightedNote.noteData)) { @@ -2055,8 +2056,7 @@ class ChartEditorState extends HaxeUIState if (highlightedNote != null) { - // Handle the case of clicking on a sustain piece. - highlightedNote = highlightedNote.getBaseNoteSprite(); + // TODO: Handle the case of clicking on a sustain piece. // Remove the note. performCommand(new RemoveNotesCommand([highlightedNote.noteData])); } @@ -2167,18 +2167,18 @@ class ChartEditorState extends HaxeUIState // Kill the note sprite and recycle it. noteSprite.noteData = null; } - else if (noteSprite.noteData.length > 0 && (noteSprite.parentNoteSprite == null && noteSprite.childNoteSprite == null)) - { - // Note was extended. - // Kill the note sprite and recycle it. - noteSprite.noteData = null; - } - else if (noteSprite.noteData.length == 0 && (noteSprite.parentNoteSprite != null || noteSprite.childNoteSprite != null)) - { - // Note was shortened. - // Kill the note sprite and recycle it. - noteSprite.noteData = null; - } + // else if (noteSprite.noteData.length > 0 && (noteSprite.parentNoteSprite == null && noteSprite.childNoteSprite == null)) + // { + // // Note was extended. + // // Kill the note sprite and recycle it. + // noteSprite.noteData = null; + // } + // else if (noteSprite.noteData.length == 0 && (noteSprite.parentNoteSprite != null || noteSprite.childNoteSprite != null)) + // { + // // Note was shortened. + // // Kill the note sprite and recycle it. + // noteSprite.noteData = null; + // } else { // Note is already displayed and should remain displayed. @@ -2252,30 +2252,34 @@ class ChartEditorState extends HaxeUIState // TODO: Replace this with SustainTrail. if (noteSprite.noteData.length > 0) { + var holdNoteSprite:SustainTrail = renderedHoldNotes.recycle(() -> new SustainTrail(this)); + + var noteLengthPixels:Float = noteSprite.noteData.stepLength * GRID_SIZE; + // If the note is a hold, we need to make sure it's long enough. - var noteLengthSteps:Float = noteSprite.noteData.stepLength; - var lastNoteSprite:ChartEditorNoteSprite = noteSprite; - - while (noteLengthSteps > 0) - { - if (noteLengthSteps <= 1.0) - { - // Last note in the hold. - // TODO: We may need to make it shorter and clip it visually. - } - - var nextNoteSprite:ChartEditorNoteSprite = renderedNotes.recycle(ChartEditorNoteSprite); - nextNoteSprite.parentState = this; - nextNoteSprite.parentNoteSprite = lastNoteSprite; - lastNoteSprite.childNoteSprite = nextNoteSprite; - - lastNoteSprite = nextNoteSprite; - - noteLengthSteps -= 1; - } - - // Make sure the last note sprite shows the end cap properly. - lastNoteSprite.childNoteSprite = null; + // var noteLengthSteps:Float = ; + // var lastNoteSprite:ChartEditorNoteSprite = noteSprite; + // + // while (noteLengthSteps > 0) + // { + // if (noteLengthSteps <= 1.0) + // { + // // Last note in the hold. + // // TODO: We may need to make it shorter and clip it visually. + // } + // + // var nextNoteSprite:ChartEditorNoteSprite = renderedNotes.recycle(ChartEditorNoteSprite); + // nextNoteSprite.parentState = this; + // nextNoteSprite.parentNoteSprite = lastNoteSprite; + // lastNoteSprite.childNoteSprite = nextNoteSprite; + // + // lastNoteSprite = nextNoteSprite; + // + // noteLengthSteps -= 1; + // } + // + // // Make sure the last note sprite shows the end cap properly. + // lastNoteSprite.childNoteSprite = null; // var noteLengthPixels:Float = (noteLengthMs / Conductor.stepLengthMs + 1) * GRID_SIZE; // add(new FlxSprite(noteSprite.x, noteSprite.y - renderedNotes.y + noteLengthPixels).makeGraphic(40, 2, 0xFFFF0000)); @@ -2326,7 +2330,8 @@ class ChartEditorState extends HaxeUIState // Recycle selection squares if possible. for (noteSprite in renderedNotes.members) { - if (isNoteSelected(noteSprite.noteData) && noteSprite.parentNoteSprite == null) + // TODO: Handle selection of hold notes. + if (isNoteSelected(noteSprite.noteData)) { var selectionSquare:FlxSprite = renderedSelectionSquares.recycle(buildSelectionSquare); @@ -2833,11 +2838,13 @@ class ChartEditorState extends HaxeUIState // Assume notes are sorted by time. for (noteData in currentSongChartNoteData) { + // Check for notes between the old and new song positions. + if (noteData.time < oldSongPosition) // Note is in the past. continue; - if (noteData.time >= newSongPosition) // Note is in the future. - return; + if (noteData.time > newSongPosition) // Note is in the future. + return; // Assume all notes are also in the future. // Note was just hit. @@ -3122,6 +3129,8 @@ class ChartEditorState extends HaxeUIState Conductor.forceBPM(null); // Disable the forced BPM. Conductor.mapTimeChanges(currentSongMetadata.timeChanges); + sortChartData(); + loadInstrumentalFromAsset(Paths.inst(songId)); var voiceList:Array<String> = song.getDifficulty(selectedDifficulty).buildVoiceList();