algorithm to make the charter faster
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
package funkin.backend.utils;
|
||||
|
||||
/**
|
||||
* All types of utils only usable in a sorted array.
|
||||
*/
|
||||
class SortedArrayUtil {
|
||||
/**
|
||||
* Gets the index of a possible new element of an Array of T using an efficient algorithm.
|
||||
* @param array Array of T to check in
|
||||
* @param getVal Function that returns the position value of T
|
||||
* @return Index
|
||||
*/
|
||||
public static inline function binarySearch<T>(array:Array<T>, val:Float, getVal:T->Float):Int {
|
||||
if (array.length <= 0) return 0; // if the array is empty, it should be equal to zero (the beginning)
|
||||
if (getVal(array[0]) > val) return 0; // in case its the minimum
|
||||
if (getVal(array[array.length-1]) < val) return array.length; // in case its the maximum
|
||||
|
||||
// binary search
|
||||
var iMin:Int = 0;
|
||||
var iMax:Int = array.length-1;
|
||||
|
||||
var i:Int = 0;
|
||||
var mid:Float;
|
||||
while(iMin <= iMax) {
|
||||
i = Math.floor((iMin + iMax) / 2);
|
||||
mid = getVal(array[i]);
|
||||
if (mid < val)
|
||||
iMin = i+1
|
||||
else if (mid > val)
|
||||
iMax = i-1;
|
||||
else {
|
||||
iMin = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return iMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to a sorted array, using binary search.
|
||||
* @param array Array to add to
|
||||
* @param val Value to add
|
||||
* @param getVal Function that returns the value that needs to be sorted
|
||||
*/
|
||||
public static inline function addSorted<T>(array:Array<T>, val:T, getVal:T->Float) {
|
||||
if (val != null)
|
||||
array.insert(binarySearch(array, getVal(val), getVal), val);
|
||||
}
|
||||
}
|
||||
@@ -399,6 +399,7 @@ class Charter extends UIState {
|
||||
vocals = FlxG.sound.load(Paths.voices(__song, __diff));
|
||||
vocals.group = FlxG.sound.defaultMusicGroup;
|
||||
|
||||
trace("generating notes...");
|
||||
for(strID=>strL in PlayState.SONG.strumLines) {
|
||||
for(note in strL.notes) {
|
||||
var n = new CharterNote();
|
||||
@@ -409,6 +410,12 @@ class Charter extends UIState {
|
||||
|
||||
strumLines.add(new CharterStrumline(strL));
|
||||
}
|
||||
trace("sorting notes...");
|
||||
notesGroup.sort(function(i, n1, n2) {
|
||||
if (n1.step == n2.step)
|
||||
return FlxSort.byValues(FlxSort.ASCENDING, n1.id, n2.id);
|
||||
return FlxSort.byValues(FlxSort.ASCENDING, n1.step, n2.step);
|
||||
});
|
||||
|
||||
refreshBPMSensitive();
|
||||
}
|
||||
@@ -522,6 +529,8 @@ class Charter extends UIState {
|
||||
deletes.push(s);
|
||||
} else {
|
||||
s.updatePos(newStep, newID, s.susLength, s.type);
|
||||
notesGroup.remove(s);
|
||||
notesGroup.add(s);
|
||||
|
||||
drags.push({
|
||||
note: s,
|
||||
@@ -785,8 +794,11 @@ class Charter extends UIState {
|
||||
for(n in changes)
|
||||
n.note.updatePos(n.note.step, n.note.id, n.before, n.note.type);
|
||||
case CNoteDrag(notes, deletes):
|
||||
for(n in notes)
|
||||
for(n in notes) {
|
||||
n.note.updatePos(n.oldStep, n.oldID, n.note.susLength, n.note.type);
|
||||
notesGroup.remove(n.note);
|
||||
notesGroup.add(n.note);
|
||||
}
|
||||
for(d in deletes) {
|
||||
notesGroup.add(d);
|
||||
d.revive();
|
||||
@@ -832,8 +844,11 @@ class Charter extends UIState {
|
||||
for(n in changes)
|
||||
n.note.updatePos(n.note.step, n.note.id, n.after, n.note.type);
|
||||
case CNoteDrag(notes, deletes):
|
||||
for(n in notes)
|
||||
for(n in notes) {
|
||||
n.note.updatePos(n.newStep, n.newID, n.note.susLength, n.note.type);
|
||||
notesGroup.remove(n.note);
|
||||
notesGroup.add(n.note);
|
||||
}
|
||||
deleteNotes(deletes, false);
|
||||
selection = [for(n in notes) n.note];
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ class CharterNoteGroup extends FlxTypedGroup<CharterNote> {
|
||||
var __currentlyLooping:Bool = false;
|
||||
|
||||
public override function forEach(noteFunc:CharterNote->Void, recursive:Bool = false) {
|
||||
i = 0;
|
||||
__loopSprite = null;
|
||||
|
||||
max = FlxG.height / 70 / camera.zoom;
|
||||
@@ -21,19 +20,34 @@ class CharterNoteGroup extends FlxTypedGroup<CharterNote> {
|
||||
if (FlxG.state is Charter && !FlxG.sound.music.playing)
|
||||
curStep = cast(FlxG.state, Charter).conductorFollowerSpr.y / 40;
|
||||
|
||||
while(i < length) {
|
||||
var begin = SortedArrayUtil.binarySearch(members, curStep - max, getVarForEach);
|
||||
var end = SortedArrayUtil.binarySearch(members, curStep + max, getVarForEach);
|
||||
|
||||
for(i in begin...end) {
|
||||
__loopSprite = members[i];
|
||||
if (__loopSprite == null || !__loopSprite.exists) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (Math.abs(__loopSprite.step - curStep) - __loopSprite.susLength < max)
|
||||
if (!cast(FlxG.state, Charter).selection.contains(__loopSprite))
|
||||
noteFunc(__loopSprite);
|
||||
i++;
|
||||
}
|
||||
for(c in cast(FlxG.state, Charter).selection)
|
||||
noteFunc(c);
|
||||
|
||||
__currentlyLooping = oldCur;
|
||||
}
|
||||
|
||||
public override function add(v:CharterNote):CharterNote {
|
||||
SortedArrayUtil.addSorted(members, v, getVar);
|
||||
return v;
|
||||
}
|
||||
|
||||
public override function remove(v:CharterNote, force:Bool = true):CharterNote
|
||||
return super.remove(v, true);
|
||||
|
||||
private static function getVar(n:CharterNote)
|
||||
return n.step;
|
||||
|
||||
private static function getVarForEach(n:CharterNote)
|
||||
return n.step + n.susLength;
|
||||
|
||||
public override function draw() {
|
||||
@:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras;
|
||||
@:privateAccess if (cameras != null) FlxCamera._defaultCameras = cameras;
|
||||
|
||||
Reference in New Issue
Block a user