Tempo changes restored (#92)
* Prepwork for seeking + tempo change fixes TODO: make playing after seeking function (I'll need help with the offset stuff so if anyone can push to this branch please do) * functions to get the beat from a song position will need more testing but I think it works well enough to get into prod thanks @wooningcharithri#7419 for the psuedo-code
This commit is contained in:
parent
a4d6537f9c
commit
d3a528a43a
|
@ -85,6 +85,8 @@ namespace HeavenStudio
|
|||
bool negativeOffset = firstBeatOffset < 0f;
|
||||
bool negativeStartTime = false;
|
||||
|
||||
// Debug.Log("starting playback @ beat " + beat + ", offset is " + firstBeatOffset);
|
||||
|
||||
var startPos = GetSongPosFromBeat(beat);
|
||||
if (negativeOffset)
|
||||
{
|
||||
|
@ -99,8 +101,10 @@ namespace HeavenStudio
|
|||
else
|
||||
time = startPos;
|
||||
}
|
||||
|
||||
songPosBeat = time / secPerBeat;
|
||||
|
||||
//TODO: make this take into account past tempo changes
|
||||
songPosBeat = GetBeatFromSongPos(time - firstBeatOffset);
|
||||
// Debug.Log("corrected starting playback @ beat " + songPosBeat);
|
||||
|
||||
isPlaying = true;
|
||||
isPaused = false;
|
||||
|
@ -232,11 +236,93 @@ namespace HeavenStudio
|
|||
return GetBeatFromPosition(position, targetBeat - margin, margin);
|
||||
}
|
||||
|
||||
private List<Beatmap.TempoChange> GetSortedTempoChanges(Beatmap chart)
|
||||
{
|
||||
//iterate over all tempo changes, adding to counter
|
||||
List<Beatmap.TempoChange> tempoChanges = chart.tempoChanges;
|
||||
tempoChanges.Sort((x, y) => x.beat.CompareTo(y.beat)); //sorts all tempo changes by ascending time (GameManager already does this but juste en cas...)
|
||||
return tempoChanges;
|
||||
}
|
||||
|
||||
public float GetSongPosFromBeat(float beat)
|
||||
{
|
||||
return secPerBeat * beat;
|
||||
Beatmap chart = GameManager.instance.Beatmap;
|
||||
SetBpm(chart.bpm);
|
||||
|
||||
//initial counter
|
||||
float counter = 0f;
|
||||
|
||||
//time of last tempo change, to know how much to add to counter
|
||||
float lastTempoChangeBeat = 0f;
|
||||
|
||||
//iterate over all tempo changes, adding to counter
|
||||
List<Beatmap.TempoChange> tempoChanges = GetSortedTempoChanges(chart);
|
||||
foreach (var t in tempoChanges)
|
||||
{
|
||||
if (t.beat > beat)
|
||||
{
|
||||
// this tempo change is past our requested time, abort
|
||||
break;
|
||||
}
|
||||
// Debug.Log("tempo change at " + t.beat);
|
||||
|
||||
counter += (t.beat - lastTempoChangeBeat) * secPerBeat;
|
||||
// Debug.Log("counter is now " + counter);
|
||||
|
||||
// now update to new bpm
|
||||
SetBpm(t.tempo);
|
||||
lastTempoChangeBeat = t.beat;
|
||||
}
|
||||
|
||||
//passed all past tempo changes, now extrapolate from last tempo change until requested position
|
||||
counter += (beat - lastTempoChangeBeat) * secPerBeat;
|
||||
|
||||
// Debug.Log("GetSongPosFromBeat returning " + counter);
|
||||
return counter;
|
||||
}
|
||||
|
||||
//thank you @wooningcharithri#7419 for the psuedo-code
|
||||
private float BeatsToSecs(float beats, float bpm)
|
||||
{
|
||||
// Debug.Log("BeatsToSecs returning " + beats / bpm * 60);
|
||||
return beats / bpm * 60f;
|
||||
}
|
||||
private float SecsToBeats(float s, float bpm)
|
||||
{
|
||||
// Debug.Log("SecsToBeats returning " + s / 60f / bpm);
|
||||
return s / 60f * bpm;
|
||||
}
|
||||
|
||||
public float GetBeatFromSongPos(float seconds)
|
||||
{
|
||||
// Debug.Log("Getting beat of seconds " + seconds);
|
||||
Beatmap chart = GameManager.instance.Beatmap;
|
||||
float lastTempoChangeBeat = 0f;
|
||||
float lastBpm = chart.bpm;
|
||||
float counterSeconds = -firstBeatOffset;
|
||||
|
||||
List<Beatmap.TempoChange> tempoChanges = GetSortedTempoChanges(chart);
|
||||
foreach (var t in tempoChanges)
|
||||
{
|
||||
float beatToNext = t.beat - lastTempoChangeBeat;
|
||||
float secToNext = BeatsToSecs(beatToNext, lastBpm);
|
||||
float nextSecs = counterSeconds + secToNext;
|
||||
|
||||
// Debug.Log("nextSecs is " + nextSecs + ", seconds " + seconds);
|
||||
if (nextSecs >= seconds)
|
||||
break;
|
||||
|
||||
lastTempoChangeBeat = t.beat;
|
||||
lastBpm = t.tempo;
|
||||
counterSeconds = nextSecs;
|
||||
}
|
||||
|
||||
// Debug.Log("lastTempoChangeBeat is " + lastTempoChangeBeat + ", counterSeconds is " + counterSeconds);
|
||||
|
||||
return lastTempoChangeBeat + SecsToBeats(seconds - counterSeconds, lastBpm);
|
||||
}
|
||||
//
|
||||
|
||||
// convert real seconds to beats
|
||||
public float GetRestFromRealTime(float seconds)
|
||||
{
|
||||
|
@ -257,7 +343,7 @@ namespace HeavenStudio
|
|||
public float SongLengthInBeats()
|
||||
{
|
||||
if (!musicSource.clip) return 0;
|
||||
return musicSource.clip.length / secPerBeat;
|
||||
return GetBeatFromSongPos(musicSource.clip.length);
|
||||
}
|
||||
|
||||
public bool SongPosLessThanClipLength(float t)
|
||||
|
|
|
@ -151,7 +151,7 @@ namespace HeavenStudio
|
|||
// LateUpdate works a bit better(?) but causes some bugs (like issues with bop animations).
|
||||
private void Update()
|
||||
{
|
||||
if (Beatmap.entities.Count < 1)
|
||||
if (BeatmapEntities() < 1) //bruh really you forgot to ckeck tempo changes
|
||||
return;
|
||||
if (!Conductor.instance.isPlaying)
|
||||
return;
|
||||
|
@ -197,9 +197,11 @@ namespace HeavenStudio
|
|||
|
||||
if (currentTempoEvent < Beatmap.tempoChanges.Count && currentTempoEvent >= 0)
|
||||
{
|
||||
// Debug.Log("Checking Tempo Change at " + tempoChanges[currentTempoEvent] + ", current beat " + Conductor.instance.songPositionInBeats);
|
||||
if (Conductor.instance.songPositionInBeats >= tempoChanges[currentTempoEvent])
|
||||
{
|
||||
Conductor.instance.songBpm = Beatmap.tempoChanges[currentTempoEvent].tempo;
|
||||
// Debug.Log("Tempo Change at " + Conductor.instance.songPositionInBeats + " of bpm " + Beatmap.tempoChanges[currentTempoEvent].tempo);
|
||||
Conductor.instance.SetBpm(Beatmap.tempoChanges[currentTempoEvent].tempo);
|
||||
Conductor.instance.timeSinceLastTempoChange = Time.time;
|
||||
currentTempoEvent++;
|
||||
}
|
||||
|
@ -325,9 +327,20 @@ namespace HeavenStudio
|
|||
|
||||
if (Beatmap.tempoChanges.Count > 0)
|
||||
{
|
||||
currentTempoEvent = 0;
|
||||
List<float> tempoChanges = Beatmap.tempoChanges.Select(c => c.beat).ToList();
|
||||
|
||||
currentTempoEvent = tempoChanges.IndexOf(Mathp.GetClosestInList(tempoChanges, beat));
|
||||
//for tempo changes, just go over all of em until the last one we pass
|
||||
for (int t = 0; t < tempoChanges.Count; t++)
|
||||
{
|
||||
// Debug.Log("checking tempo event " + t + " against beat " + beat + "( tc beat " + tempoChanges[t] + ")");
|
||||
if (tempoChanges[t] > beat)
|
||||
{
|
||||
break;
|
||||
}
|
||||
currentTempoEvent = t;
|
||||
}
|
||||
// Debug.Log("currentTempoEvent is now " + currentTempoEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -129,11 +129,7 @@ namespace HeavenStudio.Editor.Track
|
|||
}
|
||||
|
||||
private void AddTempoChange(bool create, Beatmap.TempoChange tempoChange_ = null)
|
||||
{
|
||||
// TEMP: DISABLED UNTIL CRITICAL FIXES
|
||||
if (create)
|
||||
return;
|
||||
|
||||
{
|
||||
GameObject tempoChange = Instantiate(RefTempoChange.gameObject, this.transform);
|
||||
|
||||
tempoChange.transform.GetChild(0).GetComponent<Image>().color = EditorTheme.theme.properties.TempoLayerCol.Hex2RGB();
|
||||
|
|
|
@ -296,7 +296,7 @@ namespace HeavenStudio.Editor.Track
|
|||
if (movingPlayback)
|
||||
{
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(TimelineContent, Input.mousePosition, Editor.instance.EditorCamera, out lastMousePos);
|
||||
TimelineSlider.localPosition = new Vector3(Mathf.Clamp(Mathp.Round2Nearest(lastMousePos.x + 0.12f, Timeline.SnapInterval()), 0, Mathf.Infinity), TimelineSlider.transform.localPosition.y);
|
||||
TimelineSlider.localPosition = new Vector3(Mathf.Max(Mathp.Round2Nearest(lastMousePos.x + 0.12f, Timeline.SnapInterval()), 0), TimelineSlider.transform.localPosition.y);
|
||||
|
||||
if (TimelineSlider.localPosition.x != lastBeatPos)
|
||||
Conductor.instance.SetBeat(TimelineSlider.transform.localPosition.x);
|
||||
|
|
Loading…
Reference in a new issue