mirror of
https://github.com/osukey/osukey.git
synced 2025-05-25 23:47:30 +09:00
Refactor BeatSyncedContainer
to support GameplayClock
This commit is contained in:
parent
8cc2d2e79e
commit
a3129ad00e
@ -11,12 +11,12 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Timing;
|
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.UserInterface
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
@ -25,7 +25,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
public class TestSceneBeatSyncedContainer : OsuTestScene
|
public class TestSceneBeatSyncedContainer : OsuTestScene
|
||||||
{
|
{
|
||||||
private BeatContainer beatContainer;
|
private BeatContainer beatContainer;
|
||||||
private DecoupleableInterpolatingFramedClock decoupledClock;
|
|
||||||
|
private MasterGameplayClockContainer gameplayClockContainer;
|
||||||
|
|
||||||
[SetUpSteps]
|
[SetUpSteps]
|
||||||
public void SetUpSteps()
|
public void SetUpSteps()
|
||||||
@ -39,21 +40,18 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
beatContainer = new BeatContainer
|
gameplayClockContainer = new MasterGameplayClockContainer(Beatmap.Value, 0)
|
||||||
{
|
{
|
||||||
Clock = decoupledClock = new DecoupleableInterpolatingFramedClock
|
Child = beatContainer = new BeatContainer
|
||||||
{
|
{
|
||||||
IsCoupled = false,
|
|
||||||
},
|
|
||||||
Anchor = Anchor.BottomCentre,
|
Anchor = Anchor.BottomCentre,
|
||||||
Origin = Anchor.BottomCentre,
|
Origin = Anchor.BottomCentre,
|
||||||
},
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
decoupledClock.ChangeSource(Beatmap.Value.Track);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("Start playback", () => decoupledClock.Start());
|
AddStep("Start playback", () => gameplayClockContainer.Start());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -61,7 +59,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
{
|
{
|
||||||
AddStep("Set time before zero", () =>
|
AddStep("Set time before zero", () =>
|
||||||
{
|
{
|
||||||
decoupledClock.Seek(-1000);
|
gameplayClockContainer.Seek(-1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("bind event", () =>
|
AddStep("bind event", () =>
|
||||||
@ -150,8 +148,13 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Beatmap.ValueChanged += delegate
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
Beatmap.BindValueChanged(_ =>
|
||||||
{
|
{
|
||||||
timingPointCount.Value = 0;
|
timingPointCount.Value = 0;
|
||||||
currentTimingPoint.Value = 0;
|
currentTimingPoint.Value = 0;
|
||||||
@ -161,7 +164,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
adjustedBeatLength.Value = 0;
|
adjustedBeatLength.Value = 0;
|
||||||
timeUntilNextBeat.Value = 0;
|
timeUntilNextBeat.Value = 0;
|
||||||
timeSinceLastBeat.Value = 0;
|
timeSinceLastBeat.Value = 0;
|
||||||
};
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<TimingControlPoint> timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.ToList();
|
private List<TimingControlPoint> timingPoints => Beatmap.Value.Beatmap.ControlPointInfo.TimingPoints.ToList();
|
||||||
@ -181,7 +184,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
if (timingPoints.Count == 0) return 0;
|
if (timingPoints.Count == 0) return 0;
|
||||||
|
|
||||||
if (timingPoints[^1] == current)
|
if (timingPoints[^1] == current)
|
||||||
return (int)Math.Ceiling((Clock.CurrentTime - current.Time) / current.BeatLength);
|
return (int)Math.Ceiling((BeatSyncClock.CurrentTime - current.Time) / current.BeatLength);
|
||||||
|
|
||||||
return (int)Math.Ceiling((getNextTimingPoint(current).Time - current.Time) / current.BeatLength);
|
return (int)Math.Ceiling((getNextTimingPoint(current).Time - current.Time) / current.BeatLength);
|
||||||
}
|
}
|
||||||
@ -191,7 +194,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
base.Update();
|
base.Update();
|
||||||
timeUntilNextBeat.Value = TimeUntilNextBeat;
|
timeUntilNextBeat.Value = TimeUntilNextBeat;
|
||||||
timeSinceLastBeat.Value = TimeSinceLastBeat;
|
timeSinceLastBeat.Value = TimeSinceLastBeat;
|
||||||
currentTime.Value = Clock.CurrentTime;
|
currentTime.Value = BeatSyncClock.CurrentTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action<int, TimingControlPoint, EffectControlPoint, ChannelAmplitudes> NewBeat;
|
public Action<int, TimingControlPoint, EffectControlPoint, ChannelAmplitudes> NewBeat;
|
||||||
|
@ -1,19 +1,29 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio.Track;
|
using osu.Framework.Audio.Track;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Timing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Screens.Play;
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Containers
|
namespace osu.Game.Graphics.Containers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A container which fires a callback when a new beat is reached.
|
||||||
|
/// Consumes a parent <see cref="GameplayClock"/> or <see cref="Beatmap"/> (whichever is first available).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This container does not set its own clock to the source used for beat matching.
|
||||||
|
/// This means that if the beat source clock is playing faster or slower, animations may unexpectedly overlap.
|
||||||
|
/// Make sure this container's Clock is also set to the expected source (or within a parent element which provides this).
|
||||||
|
/// </remarks>
|
||||||
public class BeatSyncedContainer : Container
|
public class BeatSyncedContainer : Container
|
||||||
{
|
{
|
||||||
protected readonly IBindable<WorkingBeatmap> Beatmap = new Bindable<WorkingBeatmap>();
|
|
||||||
|
|
||||||
private int lastBeat;
|
private int lastBeat;
|
||||||
private TimingControlPoint lastTimingPoint;
|
private TimingControlPoint lastTimingPoint;
|
||||||
|
|
||||||
@ -45,15 +55,45 @@ namespace osu.Game.Graphics.Containers
|
|||||||
|
|
||||||
protected bool IsBeatSyncedWithTrack { get; private set; }
|
protected bool IsBeatSyncedWithTrack { get; private set; }
|
||||||
|
|
||||||
|
protected virtual void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
protected IBindable<WorkingBeatmap> Beatmap { get; private set; }
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
protected GameplayClock GameplayClock { get; private set; }
|
||||||
|
|
||||||
|
protected IClock BeatSyncClock
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (GameplayClock != null)
|
||||||
|
return GameplayClock;
|
||||||
|
|
||||||
|
if (Beatmap.Value.TrackLoaded)
|
||||||
|
return Beatmap.Value.Track;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
ITrack track = null;
|
ITrack track = null;
|
||||||
IBeatmap beatmap = null;
|
IBeatmap beatmap = null;
|
||||||
|
|
||||||
double currentTrackTime = 0;
|
double currentTrackTime = 0;
|
||||||
|
|
||||||
TimingControlPoint timingPoint = null;
|
TimingControlPoint timingPoint = null;
|
||||||
EffectControlPoint effectPoint = null;
|
EffectControlPoint effectPoint = null;
|
||||||
|
|
||||||
|
var clock = BeatSyncClock;
|
||||||
|
|
||||||
|
if (clock == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (Beatmap.Value.TrackLoaded && Beatmap.Value.BeatmapLoaded)
|
if (Beatmap.Value.TrackLoaded && Beatmap.Value.BeatmapLoaded)
|
||||||
{
|
{
|
||||||
track = Beatmap.Value.Track;
|
track = Beatmap.Value.Track;
|
||||||
@ -62,7 +102,7 @@ namespace osu.Game.Graphics.Containers
|
|||||||
|
|
||||||
if (track != null && beatmap != null && track.IsRunning && track.Length > 0)
|
if (track != null && beatmap != null && track.IsRunning && track.Length > 0)
|
||||||
{
|
{
|
||||||
currentTrackTime = track.CurrentTime + EarlyActivationMilliseconds;
|
currentTrackTime = clock.CurrentTime + EarlyActivationMilliseconds;
|
||||||
|
|
||||||
timingPoint = beatmap.ControlPointInfo.TimingPointAt(currentTrackTime);
|
timingPoint = beatmap.ControlPointInfo.TimingPointAt(currentTrackTime);
|
||||||
effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime);
|
effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime);
|
||||||
@ -70,13 +110,15 @@ namespace osu.Game.Graphics.Containers
|
|||||||
|
|
||||||
IsBeatSyncedWithTrack = timingPoint?.BeatLength > 0;
|
IsBeatSyncedWithTrack = timingPoint?.BeatLength > 0;
|
||||||
|
|
||||||
if (timingPoint == null || !IsBeatSyncedWithTrack)
|
if (!IsBeatSyncedWithTrack)
|
||||||
{
|
{
|
||||||
currentTrackTime = Clock.CurrentTime;
|
currentTrackTime = clock.CurrentTime;
|
||||||
timingPoint = TimingControlPoint.DEFAULT;
|
timingPoint = TimingControlPoint.DEFAULT;
|
||||||
effectPoint = EffectControlPoint.DEFAULT;
|
effectPoint = EffectControlPoint.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Debug.Assert(timingPoint != null);
|
||||||
|
|
||||||
double beatLength = timingPoint.BeatLength / Divisor;
|
double beatLength = timingPoint.BeatLength / Divisor;
|
||||||
|
|
||||||
while (beatLength < MinimumBeatLength)
|
while (beatLength < MinimumBeatLength)
|
||||||
@ -103,15 +145,5 @@ namespace osu.Game.Graphics.Containers
|
|||||||
lastBeat = beatIndex;
|
lastBeat = beatIndex;
|
||||||
lastTimingPoint = timingPoint;
|
lastTimingPoint = timingPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(IBindable<WorkingBeatmap> beatmap)
|
|
||||||
{
|
|
||||||
Beatmap.BindTo(beatmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user