1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2025-04-10 22:34:17 +00:00

Fix for BPM changes, plus working on hold note rendering

This commit is contained in:
EliteMasterEric 2023-07-19 21:16:39 -04:00
parent c56517f94f
commit 16e3bfe85e
3 changed files with 65 additions and 141 deletions

View file

@ -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; return resultStep;
} }

View file

@ -34,16 +34,6 @@ class ChartEditorNoteSprite extends FlxSprite
*/ */
public var noteStyle(get, null):String; 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) public function new(parent:ChartEditorState)
{ {
super(); super();
@ -124,14 +114,6 @@ class ChartEditorNoteSprite extends FlxSprite
if (this.noteData == null) 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(); this.kill();
return this.noteData; 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; // noteData.stepTime is a calculated value which accounts for BPM changes
var stepTime:Float = this.noteData.stepTime;
// Notes far in the song will start far down, but the group they belong to will have a high negative offset. var roundedStepTime:Float = Math.floor(stepTime + 0.01); // Add epsilon to fix rounding issues
if (this.noteData.stepTime >= 0) this.y = roundedStepTime * ChartEditorState.GRID_SIZE;
{
// 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;
} }
return this.parentNoteSprite; if (origin != null)
}
function set_childNoteSprite(value:ChartEditorNoteSprite):ChartEditorNoteSprite
{
this.childNoteSprite = value;
if (this.parentNoteSprite != null)
{ {
this.noteData = this.parentNoteSprite.noteData; this.x += origin.x;
this.y += origin.y;
} }
return this.childNoteSprite;
} }
function get_noteStyle():String function get_noteStyle():String
@ -247,7 +180,6 @@ class ChartEditorNoteSprite extends FlxSprite
{ {
// Decide whether to display a note or a sustain. // Decide whether to display a note or a sustain.
var baseAnimationName:String = 'tap'; var baseAnimationName:String = 'tap';
if (this.parentNoteSprite != null) baseAnimationName = (this.childNoteSprite != null) ? 'hold' : 'holdEnd';
// Play the appropriate animation for the type, direction, and skin. // Play the appropriate animation for the type, direction, and skin.
var animationName:String = '${baseAnimationName}${this.noteData.getDirectionName()}${this.noteStyle}'; var animationName:String = '${baseAnimationName}${this.noteData.getDirectionName()}${this.noteStyle}';
@ -260,17 +192,6 @@ class ChartEditorNoteSprite extends FlxSprite
{ {
case 'tap': case 'tap':
this.setGraphicSize(0, ChartEditorState.GRID_SIZE); 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(); this.updateHitbox();
@ -294,11 +215,4 @@ class ChartEditorNoteSprite extends FlxSprite
return false; return false;
} }
public function getBaseNoteSprite()
{
if (this.parentNoteSprite == null) return this;
else
return this.parentNoteSprite;
}
} }

View file

@ -1,5 +1,6 @@
package funkin.ui.debug.charting; package funkin.ui.debug.charting;
import funkin.graphics.rendering.SustainTrail;
import funkin.util.SortUtil; import funkin.util.SortUtil;
import funkin.ui.debug.charting.ChartEditorCommand; import funkin.ui.debug.charting.ChartEditorCommand;
import flixel.input.keyboard.FlxKey; import flixel.input.keyboard.FlxKey;
@ -944,6 +945,8 @@ class ChartEditorState extends HaxeUIState
*/ */
var renderedNotes:FlxTypedSpriteGroup<ChartEditorNoteSprite>; var renderedNotes:FlxTypedSpriteGroup<ChartEditorNoteSprite>;
var renderedHoldNotes:FlxTypedSpriteGroup<SustainTrail>;
/** /**
* The sprite group containing the song events. * The sprite group containing the song events.
* Only displays a subset of the data from `currentSongChartEventData`, * 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 cursorFractionalStep:Float = cursorY / GRID_SIZE / (16 / noteSnapQuant);
var cursorStep:Int = Std.int(Math.floor(cursorFractionalStep)); var cursorStep:Int = Std.int(Math.floor(cursorFractionalStep));
var cursorMs:Float = Conductor.getStepTimeInMs(cursorStep); var cursorMs:Float = Conductor.getStepTimeInMs(cursorStep);
trace('${cursorFractionalStep} ${cursorStep} ${cursorMs}');
// The direction value for the column at the cursor. // The direction value for the column at the cursor.
var cursorColumn:Int = Math.floor(cursorX / GRID_SIZE); var cursorColumn:Int = Math.floor(cursorX / GRID_SIZE);
if (cursorColumn < 0) cursorColumn = 0; if (cursorColumn < 0) cursorColumn = 0;
@ -1858,8 +1860,7 @@ class ChartEditorState extends HaxeUIState
{ {
if (highlightedNote != null) if (highlightedNote != null)
{ {
// Handle the case of clicking on a sustain piece. // TODO: Handle the case of clicking on a sustain piece.
highlightedNote = highlightedNote.getBaseNoteSprite();
// Control click to select/deselect an individual note. // Control click to select/deselect an individual note.
if (isNoteSelected(highlightedNote.noteData)) if (isNoteSelected(highlightedNote.noteData))
{ {
@ -2055,8 +2056,7 @@ class ChartEditorState extends HaxeUIState
if (highlightedNote != null) if (highlightedNote != null)
{ {
// Handle the case of clicking on a sustain piece. // TODO: Handle the case of clicking on a sustain piece.
highlightedNote = highlightedNote.getBaseNoteSprite();
// Remove the note. // Remove the note.
performCommand(new RemoveNotesCommand([highlightedNote.noteData])); performCommand(new RemoveNotesCommand([highlightedNote.noteData]));
} }
@ -2167,18 +2167,18 @@ class ChartEditorState extends HaxeUIState
// Kill the note sprite and recycle it. // Kill the note sprite and recycle it.
noteSprite.noteData = null; noteSprite.noteData = null;
} }
else if (noteSprite.noteData.length > 0 && (noteSprite.parentNoteSprite == null && noteSprite.childNoteSprite == null)) // else if (noteSprite.noteData.length > 0 && (noteSprite.parentNoteSprite == null && noteSprite.childNoteSprite == null))
{ // {
// Note was extended. // // Note was extended.
// Kill the note sprite and recycle it. // // Kill the note sprite and recycle it.
noteSprite.noteData = null; // noteSprite.noteData = null;
} // }
else if (noteSprite.noteData.length == 0 && (noteSprite.parentNoteSprite != null || noteSprite.childNoteSprite != null)) // else if (noteSprite.noteData.length == 0 && (noteSprite.parentNoteSprite != null || noteSprite.childNoteSprite != null))
{ // {
// Note was shortened. // // Note was shortened.
// Kill the note sprite and recycle it. // // Kill the note sprite and recycle it.
noteSprite.noteData = null; // noteSprite.noteData = null;
} // }
else else
{ {
// Note is already displayed and should remain displayed. // Note is already displayed and should remain displayed.
@ -2252,30 +2252,34 @@ class ChartEditorState extends HaxeUIState
// TODO: Replace this with SustainTrail. // TODO: Replace this with SustainTrail.
if (noteSprite.noteData.length > 0) 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. // If the note is a hold, we need to make sure it's long enough.
var noteLengthSteps:Float = noteSprite.noteData.stepLength; // var noteLengthSteps:Float = ;
var lastNoteSprite:ChartEditorNoteSprite = noteSprite; // var lastNoteSprite:ChartEditorNoteSprite = noteSprite;
//
while (noteLengthSteps > 0) // while (noteLengthSteps > 0)
{ // {
if (noteLengthSteps <= 1.0) // if (noteLengthSteps <= 1.0)
{ // {
// Last note in the hold. // // Last note in the hold.
// TODO: We may need to make it shorter and clip it visually. // // TODO: We may need to make it shorter and clip it visually.
} // }
//
var nextNoteSprite:ChartEditorNoteSprite = renderedNotes.recycle(ChartEditorNoteSprite); // var nextNoteSprite:ChartEditorNoteSprite = renderedNotes.recycle(ChartEditorNoteSprite);
nextNoteSprite.parentState = this; // nextNoteSprite.parentState = this;
nextNoteSprite.parentNoteSprite = lastNoteSprite; // nextNoteSprite.parentNoteSprite = lastNoteSprite;
lastNoteSprite.childNoteSprite = nextNoteSprite; // lastNoteSprite.childNoteSprite = nextNoteSprite;
//
lastNoteSprite = nextNoteSprite; // lastNoteSprite = nextNoteSprite;
//
noteLengthSteps -= 1; // noteLengthSteps -= 1;
} // }
//
// Make sure the last note sprite shows the end cap properly. // // Make sure the last note sprite shows the end cap properly.
lastNoteSprite.childNoteSprite = null; // lastNoteSprite.childNoteSprite = null;
// var noteLengthPixels:Float = (noteLengthMs / Conductor.stepLengthMs + 1) * GRID_SIZE; // var noteLengthPixels:Float = (noteLengthMs / Conductor.stepLengthMs + 1) * GRID_SIZE;
// add(new FlxSprite(noteSprite.x, noteSprite.y - renderedNotes.y + noteLengthPixels).makeGraphic(40, 2, 0xFFFF0000)); // 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. // Recycle selection squares if possible.
for (noteSprite in renderedNotes.members) 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); var selectionSquare:FlxSprite = renderedSelectionSquares.recycle(buildSelectionSquare);
@ -2833,11 +2838,13 @@ class ChartEditorState extends HaxeUIState
// Assume notes are sorted by time. // Assume notes are sorted by time.
for (noteData in currentSongChartNoteData) for (noteData in currentSongChartNoteData)
{ {
// Check for notes between the old and new song positions.
if (noteData.time < oldSongPosition) // Note is in the past. if (noteData.time < oldSongPosition) // Note is in the past.
continue; continue;
if (noteData.time >= newSongPosition) // Note is in the future. if (noteData.time > newSongPosition) // Note is in the future.
return; return; // Assume all notes are also in the future.
// Note was just hit. // Note was just hit.
@ -3122,6 +3129,8 @@ class ChartEditorState extends HaxeUIState
Conductor.forceBPM(null); // Disable the forced BPM. Conductor.forceBPM(null); // Disable the forced BPM.
Conductor.mapTimeChanges(currentSongMetadata.timeChanges); Conductor.mapTimeChanges(currentSongMetadata.timeChanges);
sortChartData();
loadInstrumentalFromAsset(Paths.inst(songId)); loadInstrumentalFromAsset(Paths.inst(songId));
var voiceList:Array<String> = song.getDifficulty(selectedDifficulty).buildVoiceList(); var voiceList:Array<String> = song.getDifficulty(selectedDifficulty).buildVoiceList();