mirror of
https://github.com/ppy/osu.git
synced 2025-01-13 09:23:06 +08:00
Expose track from MusicController
This commit is contained in:
parent
6e42b8219c
commit
5c05fe3988
@ -343,7 +343,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
judgementResults = new List<JudgementResult>();
|
||||
});
|
||||
|
||||
AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrackTime == 0);
|
||||
AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack?.CurrentTime == 0);
|
||||
AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen());
|
||||
AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value);
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
judgementResults = new List<JudgementResult>();
|
||||
});
|
||||
|
||||
AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrackTime == 0);
|
||||
AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack?.CurrentTime == 0);
|
||||
AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen());
|
||||
AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value);
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
judgementResults = new List<JudgementResult>();
|
||||
});
|
||||
|
||||
AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrackTime == 0);
|
||||
AddUntilStep("Beatmap at 0", () => MusicController.CurrentTrack?.CurrentTime == 0);
|
||||
AddUntilStep("Wait until player is loaded", () => currentPlayer.IsCurrentScreen());
|
||||
AddUntilStep("Wait for completion", () => currentPlayer.ScoreProcessor.HasCompleted.Value);
|
||||
}
|
||||
|
@ -31,6 +31,6 @@ namespace osu.Game.Tests.Skins
|
||||
public void TestRetrieveOggSample() => AddAssert("sample is non-null", () => beatmap.Skin.GetSample(new SampleInfo("sample")) != null);
|
||||
|
||||
[Test]
|
||||
public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => !MusicController.IsDummyDevice);
|
||||
public void TestRetrieveOggTrack() => AddAssert("track is non-null", () => MusicController.CurrentTrack?.IsDummyDevice == false);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.
|
||||
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Graphics;
|
||||
@ -94,7 +95,10 @@ namespace osu.Game.Tests.Visual.Editing
|
||||
base.Update();
|
||||
|
||||
if (musicController.TrackLoaded)
|
||||
marker.X = (float)(editorClock.CurrentTime / musicController.TrackLength);
|
||||
{
|
||||
Debug.Assert(musicController.CurrentTrack != null);
|
||||
marker.X = (float)(editorClock.CurrentTime / musicController.CurrentTrack.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,7 +288,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
private void confirmNoTrackAdjustments()
|
||||
{
|
||||
AddAssert("track has no adjustments", () => MusicController.AggregateFrequency.Value == 1);
|
||||
AddAssert("track has no adjustments", () => MusicController.CurrentTrack?.AggregateFrequency.Value == 1);
|
||||
}
|
||||
|
||||
private void restart() => AddStep("restart", () => Player.Restart());
|
||||
|
@ -57,7 +57,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
Beatmap.Value = CreateWorkingBeatmap(new OsuRuleset().RulesetInfo);
|
||||
|
||||
foreach (var mod in SelectedMods.Value.OfType<IApplicableToTrack>())
|
||||
mod.ApplyToTrack(MusicController);
|
||||
mod.ApplyToTrack(MusicController.CurrentTrack);
|
||||
|
||||
InputManager.Child = container = new TestPlayerLoaderContainer(
|
||||
loader = new TestPlayerLoader(() =>
|
||||
@ -77,12 +77,12 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
{
|
||||
AddStep("load dummy beatmap", () => ResetPlayer(false, () => SelectedMods.Value = new[] { new OsuModNightcore() }));
|
||||
AddUntilStep("wait for current", () => loader.IsCurrentScreen());
|
||||
AddAssert("mod rate applied", () => MusicController.Rate != 1);
|
||||
AddAssert("mod rate applied", () => MusicController.CurrentTrack?.Rate != 1);
|
||||
AddStep("exit loader", () => loader.Exit());
|
||||
AddUntilStep("wait for not current", () => !loader.IsCurrentScreen());
|
||||
AddAssert("player did not load", () => !player.IsLoaded);
|
||||
AddUntilStep("player disposed", () => loader.DisposalTask?.IsCompleted == true);
|
||||
AddAssert("mod rate still applied", () => MusicController.Rate != 1);
|
||||
AddAssert("mod rate still applied", () => MusicController.CurrentTrack?.Rate != 1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -87,9 +87,9 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
|
||||
private void restart()
|
||||
{
|
||||
MusicController.Reset();
|
||||
MusicController.CurrentTrack?.Reset();
|
||||
loadStoryboard(Beatmap.Value);
|
||||
MusicController.Play(true);
|
||||
MusicController.CurrentTrack?.Start();
|
||||
}
|
||||
|
||||
private void loadStoryboard(WorkingBeatmap working)
|
||||
@ -104,7 +104,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
storyboard.Passing = false;
|
||||
|
||||
storyboardContainer.Add(storyboard);
|
||||
decoupledClock.ChangeSource(musicController.GetTrackClock());
|
||||
decoupledClock.ChangeSource(musicController.CurrentTrack);
|
||||
}
|
||||
|
||||
private void loadStoryboardNoVideo()
|
||||
@ -127,7 +127,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
||||
storyboard = sb.CreateDrawable(Beatmap.Value);
|
||||
|
||||
storyboardContainer.Add(storyboard);
|
||||
decoupledClock.ChangeSource(musicController.GetTrackClock());
|
||||
decoupledClock.ChangeSource(musicController.CurrentTrack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace osu.Game.Tests.Visual.Menus
|
||||
{
|
||||
AddUntilStep("wait for load", () => MusicController.TrackLoaded);
|
||||
|
||||
AddAssert("check if menu music loops", () => MusicController.Looping);
|
||||
AddAssert("check if menu music loops", () => MusicController.CurrentTrack?.Looping == true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -61,12 +62,12 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddUntilStep("wait for fail", () => player.HasFailed);
|
||||
|
||||
AddUntilStep("wait for track stop", () => !MusicController.IsPlaying);
|
||||
AddAssert("Ensure time before preview point", () => MusicController.CurrentTrackTime < beatmap().Metadata.PreviewTime);
|
||||
AddAssert("Ensure time before preview point", () => MusicController.CurrentTrack?.CurrentTime < beatmap().Metadata.PreviewTime);
|
||||
|
||||
pushEscape();
|
||||
|
||||
AddUntilStep("wait for track playing", () => MusicController.IsPlaying);
|
||||
AddAssert("Ensure time wasn't reset to preview point", () => MusicController.CurrentTrackTime < beatmap().Metadata.PreviewTime);
|
||||
AddAssert("Ensure time wasn't reset to preview point", () => MusicController.CurrentTrack?.CurrentTime < beatmap().Metadata.PreviewTime);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -76,11 +77,11 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
|
||||
PushAndConfirm(() => songSelect = new TestSongSelect());
|
||||
|
||||
AddUntilStep("wait for no track", () => MusicController.IsDummyDevice);
|
||||
AddUntilStep("wait for no track", () => MusicController.CurrentTrack?.IsDummyDevice == true);
|
||||
|
||||
AddStep("return to menu", () => songSelect.Exit());
|
||||
|
||||
AddUntilStep("wait for track", () => !MusicController.IsDummyDevice && MusicController.IsPlaying);
|
||||
AddUntilStep("wait for track", () => MusicController.CurrentTrack?.IsDummyDevice == false && MusicController.IsPlaying);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@ -135,8 +136,8 @@ namespace osu.Game.Tests.Visual.Navigation
|
||||
AddUntilStep("Wait for music controller", () => Game.MusicController.IsLoaded);
|
||||
AddStep("Seek close to end", () =>
|
||||
{
|
||||
Game.MusicController.SeekTo(MusicController.TrackLength - 1000);
|
||||
// MusicController.Completed += () => trackCompleted = true;
|
||||
Game.MusicController.SeekTo(MusicController.CurrentTrack.AsNonNull().Length - 1000);
|
||||
MusicController.CurrentTrack.AsNonNull().Completed += () => trackCompleted = true;
|
||||
});
|
||||
|
||||
AddUntilStep("Track was completed", () => trackCompleted);
|
||||
|
@ -8,6 +8,7 @@ using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -168,7 +169,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
if (timingPoints.Count == 0) return 0;
|
||||
|
||||
if (timingPoints[^1] == current)
|
||||
return (int)Math.Ceiling((musicController.TrackLength - current.Time) / current.BeatLength);
|
||||
return (int)Math.Ceiling((musicController.CurrentTrack.AsNonNull().Length - current.Time) / current.BeatLength);
|
||||
|
||||
return (int)Math.Ceiling((getNextTimingPoint(current).Time - current.Time) / current.BeatLength);
|
||||
}
|
||||
|
@ -80,12 +80,12 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
AddStep("Store track", () => currentBeatmap = Beatmap.Value);
|
||||
|
||||
AddStep(@"Seek track to 6 second", () => musicController.SeekTo(6000));
|
||||
AddUntilStep(@"Wait for current time to update", () => musicController.CurrentTrackTime > 5000);
|
||||
AddUntilStep(@"Wait for current time to update", () => musicController.CurrentTrack?.CurrentTime > 5000);
|
||||
|
||||
AddStep(@"Set previous", () => musicController.PreviousTrack());
|
||||
|
||||
AddAssert(@"Check beatmap didn't change", () => currentBeatmap == Beatmap.Value);
|
||||
AddUntilStep("Wait for current time to update", () => musicController.CurrentTrackTime < 5000);
|
||||
AddUntilStep("Wait for current time to update", () => musicController.CurrentTrack?.CurrentTime < 5000);
|
||||
|
||||
AddStep(@"Set previous", () => musicController.PreviousTrack());
|
||||
AddAssert(@"Check beatmap did change", () => currentBeatmap != Beatmap.Value);
|
||||
|
@ -51,6 +51,7 @@ namespace osu.Game.Graphics.Containers
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
ITrack track = null;
|
||||
IBeatmap beatmap = null;
|
||||
|
||||
double currentTrackTime = 0;
|
||||
@ -58,11 +59,14 @@ namespace osu.Game.Graphics.Containers
|
||||
EffectControlPoint effectPoint = null;
|
||||
|
||||
if (musicController.TrackLoaded && Beatmap.Value.BeatmapLoaded)
|
||||
beatmap = Beatmap.Value.Beatmap;
|
||||
|
||||
if (beatmap != null && musicController.IsPlaying && musicController.TrackLength > 0)
|
||||
{
|
||||
currentTrackTime = musicController.CurrentTrackTime + EarlyActivationMilliseconds;
|
||||
track = musicController.CurrentTrack;
|
||||
beatmap = Beatmap.Value.Beatmap;
|
||||
}
|
||||
|
||||
if (track != null && beatmap != null && musicController.IsPlaying && track.Length > 0)
|
||||
{
|
||||
currentTrackTime = track.CurrentTime + EarlyActivationMilliseconds;
|
||||
|
||||
timingPoint = beatmap.ControlPointInfo.TimingPointAt(currentTrackTime);
|
||||
effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime);
|
||||
@ -98,7 +102,7 @@ namespace osu.Game.Graphics.Containers
|
||||
return;
|
||||
|
||||
using (BeginDelayedSequence(-TimeSinceLastBeat, true))
|
||||
OnNewBeat(beatIndex, timingPoint, effectPoint, musicController.CurrentAmplitudes);
|
||||
OnNewBeat(beatIndex, timingPoint, effectPoint, track?.CurrentAmplitudes ?? ChannelAmplitudes.Empty);
|
||||
|
||||
lastBeat = beatIndex;
|
||||
lastTimingPoint = timingPoint;
|
||||
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
@ -15,7 +14,6 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Overlays.OSD;
|
||||
@ -26,7 +24,7 @@ namespace osu.Game.Overlays
|
||||
/// <summary>
|
||||
/// Handles playback of the global music track.
|
||||
/// </summary>
|
||||
public class MusicController : CompositeDrawable, IKeyBindingHandler<GlobalAction>, ITrack
|
||||
public class MusicController : CompositeDrawable, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
[Resolved]
|
||||
private BeatmapManager beatmaps { get; set; }
|
||||
@ -70,10 +68,7 @@ namespace osu.Game.Overlays
|
||||
private readonly TrackContainer trackContainer;
|
||||
|
||||
[CanBeNull]
|
||||
private DrawableTrack drawableTrack;
|
||||
|
||||
[CanBeNull]
|
||||
private Track track;
|
||||
public DrawableTrack CurrentTrack { get; private set; }
|
||||
|
||||
private IBindable<WeakReference<BeatmapSetInfo>> managerUpdated;
|
||||
private IBindable<WeakReference<BeatmapSetInfo>> managerRemoved;
|
||||
@ -116,33 +111,12 @@ namespace osu.Game.Overlays
|
||||
/// <summary>
|
||||
/// Returns whether the beatmap track is playing.
|
||||
/// </summary>
|
||||
public bool IsPlaying => drawableTrack?.IsRunning ?? false;
|
||||
public bool IsPlaying => CurrentTrack?.IsRunning ?? false;
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the beatmap track is loaded.
|
||||
/// </summary>
|
||||
public bool TrackLoaded => drawableTrack?.IsLoaded == true;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current time of the beatmap track.
|
||||
/// </summary>
|
||||
public double CurrentTrackTime => drawableTrack?.CurrentTime ?? 0;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the length of the beatmap track.
|
||||
/// </summary>
|
||||
public double TrackLength => drawableTrack?.Length ?? 0;
|
||||
|
||||
public void AddAdjustment(AdjustableProperty type, BindableNumber<double> adjustBindable)
|
||||
=> trackContainer.AddAdjustment(type, adjustBindable);
|
||||
|
||||
public void RemoveAdjustment(AdjustableProperty type, BindableNumber<double> adjustBindable)
|
||||
=> trackContainer.RemoveAdjustment(type, adjustBindable);
|
||||
|
||||
public void Reset() => drawableTrack?.Reset();
|
||||
|
||||
[CanBeNull]
|
||||
public IAdjustableClock GetTrackClock() => track;
|
||||
public bool TrackLoaded => CurrentTrack?.IsLoaded == true;
|
||||
|
||||
private void beatmapUpdated(ValueChangedEvent<WeakReference<BeatmapSetInfo>> weakSet)
|
||||
{
|
||||
@ -175,7 +149,7 @@ namespace osu.Game.Overlays
|
||||
seekDelegate = Schedule(() =>
|
||||
{
|
||||
if (!beatmap.Disabled)
|
||||
drawableTrack?.Seek(position);
|
||||
CurrentTrack?.Seek(position);
|
||||
});
|
||||
}
|
||||
|
||||
@ -187,7 +161,7 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
if (IsUserPaused) return;
|
||||
|
||||
if (drawableTrack == null || drawableTrack.IsDummyDevice)
|
||||
if (CurrentTrack == null || CurrentTrack.IsDummyDevice)
|
||||
{
|
||||
if (beatmap.Disabled)
|
||||
return;
|
||||
@ -208,13 +182,13 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
IsUserPaused = false;
|
||||
|
||||
if (drawableTrack == null)
|
||||
if (CurrentTrack == null)
|
||||
return false;
|
||||
|
||||
if (restart)
|
||||
drawableTrack.Restart();
|
||||
CurrentTrack.Restart();
|
||||
else if (!IsPlaying)
|
||||
drawableTrack.Start();
|
||||
CurrentTrack.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -225,8 +199,8 @@ namespace osu.Game.Overlays
|
||||
public void Stop()
|
||||
{
|
||||
IsUserPaused = true;
|
||||
if (drawableTrack?.IsRunning == true)
|
||||
drawableTrack.Stop();
|
||||
if (CurrentTrack?.IsRunning == true)
|
||||
CurrentTrack.Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -235,7 +209,7 @@ namespace osu.Game.Overlays
|
||||
/// <returns>Whether the operation was successful.</returns>
|
||||
public bool TogglePause()
|
||||
{
|
||||
if (drawableTrack?.IsRunning == true)
|
||||
if (CurrentTrack?.IsRunning == true)
|
||||
Stop();
|
||||
else
|
||||
Play();
|
||||
@ -257,7 +231,7 @@ namespace osu.Game.Overlays
|
||||
if (beatmap.Disabled)
|
||||
return PreviousTrackResult.None;
|
||||
|
||||
var currentTrackPosition = drawableTrack?.CurrentTime;
|
||||
var currentTrackPosition = CurrentTrack?.CurrentTime;
|
||||
|
||||
if (currentTrackPosition >= restart_cutoff_point)
|
||||
{
|
||||
@ -311,7 +285,7 @@ namespace osu.Game.Overlays
|
||||
{
|
||||
// if not scheduled, the previously track will be stopped one frame later (see ScheduleAfterChildren logic in GameBase).
|
||||
// we probably want to move this to a central method for switching to a new working beatmap in the future.
|
||||
Schedule(() => drawableTrack?.Restart());
|
||||
Schedule(() => CurrentTrack?.Restart());
|
||||
}
|
||||
|
||||
private WorkingBeatmap current;
|
||||
@ -345,12 +319,11 @@ namespace osu.Game.Overlays
|
||||
|
||||
current = beatmap.NewValue;
|
||||
|
||||
drawableTrack?.Expire();
|
||||
drawableTrack = null;
|
||||
track = null;
|
||||
CurrentTrack?.Expire();
|
||||
CurrentTrack = null;
|
||||
|
||||
if (current != null)
|
||||
trackContainer.Add(drawableTrack = new DrawableTrack(track = current.GetRealTrack()));
|
||||
trackContainer.Add(CurrentTrack = new DrawableTrack(current.GetRealTrack()));
|
||||
|
||||
TrackChanged?.Invoke(current, direction);
|
||||
|
||||
@ -379,15 +352,15 @@ namespace osu.Game.Overlays
|
||||
|
||||
public void ResetTrackAdjustments()
|
||||
{
|
||||
if (drawableTrack == null)
|
||||
if (CurrentTrack == null)
|
||||
return;
|
||||
|
||||
drawableTrack.ResetSpeedAdjustments();
|
||||
CurrentTrack.ResetSpeedAdjustments();
|
||||
|
||||
if (allowRateAdjustments)
|
||||
{
|
||||
foreach (var mod in mods.Value.OfType<IApplicableToTrack>())
|
||||
mod.ApplyToTrack(drawableTrack);
|
||||
mod.ApplyToTrack(CurrentTrack);
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,129 +415,6 @@ namespace osu.Game.Overlays
|
||||
private class TrackContainer : AudioContainer<DrawableTrack>
|
||||
{
|
||||
}
|
||||
|
||||
#region ITrack
|
||||
|
||||
/// <summary>
|
||||
/// The volume of this component.
|
||||
/// </summary>
|
||||
public BindableNumber<double> Volume => drawableTrack?.Volume; // Todo: Bad
|
||||
|
||||
/// <summary>
|
||||
/// The playback balance of this sample (-1 .. 1 where 0 is centered)
|
||||
/// </summary>
|
||||
public BindableNumber<double> Balance => drawableTrack?.Balance; // Todo: Bad
|
||||
|
||||
/// <summary>
|
||||
/// Rate at which the component is played back (affects pitch). 1 is 100% playback speed, or default frequency.
|
||||
/// </summary>
|
||||
public BindableNumber<double> Frequency => drawableTrack?.Frequency; // Todo: Bad
|
||||
|
||||
/// <summary>
|
||||
/// Rate at which the component is played back (does not affect pitch). 1 is 100% playback speed.
|
||||
/// </summary>
|
||||
public BindableNumber<double> Tempo => drawableTrack?.Tempo; // Todo: Bad
|
||||
|
||||
public IBindable<double> AggregateVolume => drawableTrack?.AggregateVolume; // Todo: Bad
|
||||
|
||||
public IBindable<double> AggregateBalance => drawableTrack?.AggregateBalance; // Todo: Bad
|
||||
|
||||
public IBindable<double> AggregateFrequency => drawableTrack?.AggregateFrequency; // Todo: Bad
|
||||
|
||||
public IBindable<double> AggregateTempo => drawableTrack?.AggregateTempo; // Todo: Bad
|
||||
|
||||
/// <summary>
|
||||
/// Overall playback rate (1 is 100%, -1 is reversed at 100%).
|
||||
/// </summary>
|
||||
public double Rate => AggregateFrequency.Value * AggregateTempo.Value;
|
||||
|
||||
event Action ITrack.Completed
|
||||
{
|
||||
add
|
||||
{
|
||||
if (drawableTrack != null)
|
||||
drawableTrack.Completed += value;
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (drawableTrack != null)
|
||||
drawableTrack.Completed -= value;
|
||||
}
|
||||
}
|
||||
|
||||
event Action ITrack.Failed
|
||||
{
|
||||
add
|
||||
{
|
||||
if (drawableTrack != null)
|
||||
drawableTrack.Failed += value;
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (drawableTrack != null)
|
||||
drawableTrack.Failed -= value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Looping
|
||||
{
|
||||
get => drawableTrack?.Looping ?? false;
|
||||
set
|
||||
{
|
||||
if (drawableTrack != null)
|
||||
drawableTrack.Looping = value;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDummyDevice => drawableTrack?.IsDummyDevice ?? true;
|
||||
|
||||
public double RestartPoint
|
||||
{
|
||||
get => drawableTrack?.RestartPoint ?? 0;
|
||||
set
|
||||
{
|
||||
if (drawableTrack != null)
|
||||
drawableTrack.RestartPoint = value;
|
||||
}
|
||||
}
|
||||
|
||||
double ITrack.CurrentTime => CurrentTrackTime;
|
||||
|
||||
double ITrack.Length
|
||||
{
|
||||
get => TrackLength;
|
||||
set
|
||||
{
|
||||
if (drawableTrack != null)
|
||||
drawableTrack.Length = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int? Bitrate => drawableTrack?.Bitrate;
|
||||
|
||||
bool ITrack.IsRunning => IsPlaying;
|
||||
|
||||
public bool IsReversed => drawableTrack?.IsReversed ?? false;
|
||||
|
||||
public bool HasCompleted => drawableTrack?.HasCompleted ?? false;
|
||||
|
||||
void ITrack.Reset() => drawableTrack?.Reset();
|
||||
|
||||
void ITrack.Restart() => Play(true);
|
||||
|
||||
void ITrack.ResetSpeedAdjustments() => ResetTrackAdjustments();
|
||||
|
||||
bool ITrack.Seek(double seek)
|
||||
{
|
||||
SeekTo(seek);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ITrack.Start() => Play();
|
||||
|
||||
public ChannelAmplitudes CurrentAmplitudes => drawableTrack?.CurrentAmplitudes ?? ChannelAmplitudes.Empty;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public enum TrackChangeDirection
|
||||
|
@ -234,12 +234,14 @@ namespace osu.Game.Overlays
|
||||
pendingBeatmapSwitch = null;
|
||||
}
|
||||
|
||||
if (musicController.IsDummyDevice == false)
|
||||
{
|
||||
progressBar.EndTime = musicController.TrackLength;
|
||||
progressBar.CurrentTime = musicController.CurrentTrackTime;
|
||||
var track = musicController.TrackLoaded ? musicController.CurrentTrack : null;
|
||||
|
||||
playButton.Icon = musicController.IsPlaying ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle;
|
||||
if (track?.IsDummyDevice == false)
|
||||
{
|
||||
progressBar.EndTime = track.Length;
|
||||
progressBar.CurrentTime = track.CurrentTime;
|
||||
|
||||
playButton.Icon = track.IsRunning ? FontAwesome.Regular.PauseCircle : FontAwesome.Regular.PlayCircle;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.
|
||||
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
|
||||
namespace osu.Game.Rulesets.Mods
|
||||
@ -10,6 +11,6 @@ namespace osu.Game.Rulesets.Mods
|
||||
/// </summary>
|
||||
public interface IApplicableToTrack : IApplicableMod
|
||||
{
|
||||
void ApplyToTrack(ITrack track);
|
||||
void ApplyToTrack<T>(T track) where T : ITrack, IAdjustableAudioComponent;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
|
||||
@ -27,11 +26,11 @@ namespace osu.Game.Rulesets.Mods
|
||||
}, true);
|
||||
}
|
||||
|
||||
public override void ApplyToTrack(ITrack track)
|
||||
public override void ApplyToTrack<T>(T track)
|
||||
{
|
||||
// base.ApplyToTrack() intentionally not called (different tempo adjustment is applied)
|
||||
(track as Track)?.AddAdjustment(AdjustableProperty.Frequency, freqAdjust);
|
||||
(track as Track)?.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust);
|
||||
track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust);
|
||||
track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,11 +38,11 @@ namespace osu.Game.Rulesets.Mods
|
||||
}, true);
|
||||
}
|
||||
|
||||
public override void ApplyToTrack(ITrack track)
|
||||
public override void ApplyToTrack<T>(T track)
|
||||
{
|
||||
// base.ApplyToTrack() intentionally not called (different tempo adjustment is applied)
|
||||
(track as Track)?.AddAdjustment(AdjustableProperty.Frequency, freqAdjust);
|
||||
(track as Track)?.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust);
|
||||
track.AddAdjustment(AdjustableProperty.Frequency, freqAdjust);
|
||||
track.AddAdjustment(AdjustableProperty.Tempo, tempoAdjust);
|
||||
}
|
||||
|
||||
public void ApplyToDrawableRuleset(DrawableRuleset<TObject> drawableRuleset)
|
||||
|
@ -12,9 +12,9 @@ namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
public abstract BindableNumber<double> SpeedChange { get; }
|
||||
|
||||
public virtual void ApplyToTrack(ITrack track)
|
||||
public virtual void ApplyToTrack<T>(T track) where T : ITrack, IAdjustableAudioComponent
|
||||
{
|
||||
(track as Track)?.AddAdjustment(AdjustableProperty.Tempo, SpeedChange);
|
||||
track.AddAdjustment(AdjustableProperty.Tempo, SpeedChange);
|
||||
}
|
||||
|
||||
public virtual void ApplyToSample(SampleChannel sample)
|
||||
|
@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
Precision = 0.01,
|
||||
};
|
||||
|
||||
private Track track;
|
||||
private ITrack track;
|
||||
|
||||
protected ModTimeRamp()
|
||||
{
|
||||
@ -51,9 +51,9 @@ namespace osu.Game.Rulesets.Mods
|
||||
AdjustPitch.BindValueChanged(applyPitchAdjustment);
|
||||
}
|
||||
|
||||
public void ApplyToTrack(ITrack track)
|
||||
public void ApplyToTrack<T>(T track) where T : ITrack, IAdjustableAudioComponent
|
||||
{
|
||||
this.track = track as Track;
|
||||
this.track = track;
|
||||
|
||||
FinalRate.TriggerChange();
|
||||
AdjustPitch.TriggerChange();
|
||||
@ -89,9 +89,9 @@ namespace osu.Game.Rulesets.Mods
|
||||
private void applyPitchAdjustment(ValueChangedEvent<bool> adjustPitchSetting)
|
||||
{
|
||||
// remove existing old adjustment
|
||||
track?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange);
|
||||
(track as IAdjustableAudioComponent)?.RemoveAdjustment(adjustmentForPitchSetting(adjustPitchSetting.OldValue), SpeedChange);
|
||||
|
||||
track?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange);
|
||||
(track as IAdjustableAudioComponent)?.AddAdjustment(adjustmentForPitchSetting(adjustPitchSetting.NewValue), SpeedChange);
|
||||
}
|
||||
|
||||
private AdjustableProperty adjustmentForPitchSetting(bool adjustPitchSettingValue)
|
||||
|
@ -66,12 +66,12 @@ namespace osu.Game.Screens.Edit.Components
|
||||
}
|
||||
};
|
||||
|
||||
musicController.AddAdjustment(AdjustableProperty.Tempo, tempo);
|
||||
musicController.CurrentTrack?.AddAdjustment(AdjustableProperty.Tempo, tempo);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
musicController?.RemoveAdjustment(AdjustableProperty.Tempo, tempo);
|
||||
musicController?.CurrentTrack?.RemoveAdjustment(AdjustableProperty.Tempo, tempo);
|
||||
|
||||
base.Dispose(isDisposing);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osuTK;
|
||||
@ -57,7 +58,8 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
|
||||
return;
|
||||
}
|
||||
|
||||
content.RelativeChildSize = new Vector2((float)Math.Max(1, musicController.TrackLength), 1);
|
||||
Debug.Assert(musicController.CurrentTrack != null);
|
||||
content.RelativeChildSize = new Vector2((float)Math.Max(1, musicController.CurrentTrack.Length), 1);
|
||||
}
|
||||
|
||||
protected virtual void LoadBeatmap(WorkingBeatmap beatmap)
|
||||
|
@ -2,7 +2,9 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
@ -60,21 +62,20 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
Beatmap.BindValueChanged(b =>
|
||||
{
|
||||
waveform.Waveform = b.NewValue.Waveform;
|
||||
track = musicController.CurrentTrack;
|
||||
|
||||
// Todo: Wrong.
|
||||
Schedule(() =>
|
||||
Debug.Assert(track != null);
|
||||
|
||||
if (track.Length > 0)
|
||||
{
|
||||
if (musicController.TrackLength > 0)
|
||||
{
|
||||
MaxZoom = getZoomLevelForVisibleMilliseconds(500);
|
||||
MinZoom = getZoomLevelForVisibleMilliseconds(10000);
|
||||
Zoom = getZoomLevelForVisibleMilliseconds(2000);
|
||||
}
|
||||
});
|
||||
MaxZoom = getZoomLevelForVisibleMilliseconds(500);
|
||||
MinZoom = getZoomLevelForVisibleMilliseconds(10000);
|
||||
Zoom = getZoomLevelForVisibleMilliseconds(2000);
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
private float getZoomLevelForVisibleMilliseconds(double milliseconds) => (float)(musicController.TrackLength / milliseconds);
|
||||
private float getZoomLevelForVisibleMilliseconds(double milliseconds) => (float)(track.Length / milliseconds);
|
||||
|
||||
/// <summary>
|
||||
/// The timeline's scroll position in the last frame.
|
||||
@ -96,6 +97,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
/// </summary>
|
||||
private bool trackWasPlaying;
|
||||
|
||||
private ITrack track;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
@ -136,15 +139,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
if (!musicController.TrackLoaded)
|
||||
return;
|
||||
|
||||
editorClock.Seek(Current / Content.DrawWidth * musicController.TrackLength);
|
||||
editorClock.Seek(Current / Content.DrawWidth * track.Length);
|
||||
}
|
||||
|
||||
private void scrollToTrackTime()
|
||||
{
|
||||
if (!musicController.TrackLoaded || musicController.TrackLength == 0)
|
||||
if (!musicController.TrackLoaded || track.Length == 0)
|
||||
return;
|
||||
|
||||
ScrollTo((float)(editorClock.CurrentTime / musicController.TrackLength) * Content.DrawWidth, false);
|
||||
ScrollTo((float)(editorClock.CurrentTime / track.Length) * Content.DrawWidth, false);
|
||||
}
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e)
|
||||
@ -188,7 +191,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
new SnapResult(screenSpacePosition, beatSnapProvider.SnapTime(getTimeFromPosition(Content.ToLocalSpace(screenSpacePosition))));
|
||||
|
||||
private double getTimeFromPosition(Vector2 localPosition) =>
|
||||
(localPosition.X / Content.DrawWidth) * musicController.TrackLength;
|
||||
(localPosition.X / Content.DrawWidth) * track.Length;
|
||||
|
||||
public float GetBeatSnapDistanceAt(double referenceTime) => throw new NotImplementedException();
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Overlays;
|
||||
@ -43,7 +44,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
|
||||
for (var i = 0; i < beatmap.ControlPointInfo.TimingPoints.Count; i++)
|
||||
{
|
||||
var point = beatmap.ControlPointInfo.TimingPoints[i];
|
||||
var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : musicController.TrackLength;
|
||||
var until = i + 1 < beatmap.ControlPointInfo.TimingPoints.Count ? beatmap.ControlPointInfo.TimingPoints[i + 1].Time : musicController.CurrentTrack.AsNonNull().Length;
|
||||
|
||||
int beat = 0;
|
||||
|
||||
|
@ -83,7 +83,7 @@ namespace osu.Game.Screens.Edit
|
||||
beatDivisor.BindValueChanged(divisor => Beatmap.Value.BeatmapInfo.BeatDivisor = divisor.NewValue);
|
||||
|
||||
// Todo: should probably be done at a DrawableRuleset level to share logic with Player.
|
||||
var sourceClock = musicController.GetTrackClock() ?? new StopwatchClock();
|
||||
var sourceClock = (IAdjustableClock)musicController.CurrentTrack ?? new StopwatchClock();
|
||||
clock = new EditorClock(Beatmap.Value, beatDivisor) { IsCoupled = false };
|
||||
clock.ChangeSource(sourceClock);
|
||||
|
||||
|
@ -55,7 +55,7 @@ namespace osu.Game.Screens.Edit
|
||||
private void load()
|
||||
{
|
||||
// Todo: What.
|
||||
TrackLength ??= musicController.TrackLength;
|
||||
TrackLength ??= musicController.CurrentTrack?.Length ?? 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -113,7 +113,9 @@ namespace osu.Game.Screens.Menu
|
||||
if (setInfo != null)
|
||||
{
|
||||
initialBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]);
|
||||
UsingThemedIntro = !MusicController.IsDummyDevice;
|
||||
|
||||
// Todo: Wrong.
|
||||
UsingThemedIntro = MusicController.CurrentTrack?.IsDummyDevice == false;
|
||||
}
|
||||
|
||||
return UsingThemedIntro;
|
||||
|
@ -59,7 +59,7 @@ namespace osu.Game.Screens.Menu
|
||||
LoadComponentAsync(new TrianglesIntroSequence(logo, background)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Clock = new FramedClock(UsingThemedIntro ? MusicController.GetTrackClock() : null),
|
||||
Clock = new FramedClock(UsingThemedIntro ? MusicController.CurrentTrack : null),
|
||||
LoadMenu = LoadMenu
|
||||
}, t =>
|
||||
{
|
||||
|
@ -44,7 +44,8 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
pianoReverb = audio.Samples.Get(@"Intro/Welcome/welcome_piano");
|
||||
|
||||
musicController.Looping = true;
|
||||
if (musicController.CurrentTrack != null)
|
||||
musicController.CurrentTrack.Looping = true;
|
||||
}
|
||||
|
||||
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||
|
@ -19,6 +19,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
@ -108,14 +109,14 @@ namespace osu.Game.Screens.Menu
|
||||
private void updateAmplitudes()
|
||||
{
|
||||
var effect = beatmap.Value.BeatmapLoaded && musicController.TrackLoaded
|
||||
? beatmap.Value.Beatmap?.ControlPointInfo.EffectPointAt(musicController.CurrentTrackTime)
|
||||
? beatmap.Value.Beatmap?.ControlPointInfo.EffectPointAt(musicController.CurrentTrack.AsNonNull().CurrentTime)
|
||||
: null;
|
||||
|
||||
for (int i = 0; i < temporalAmplitudes.Length; i++)
|
||||
temporalAmplitudes[i] = 0;
|
||||
|
||||
if (musicController.TrackLoaded)
|
||||
addAmplitudesFromSource(musicController);
|
||||
addAmplitudesFromSource(musicController.CurrentTrack.AsNonNull());
|
||||
|
||||
foreach (var source in amplitudeSources)
|
||||
addAmplitudesFromSource(source);
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -181,11 +182,12 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
if (last is IntroScreen && musicController.TrackLoaded)
|
||||
{
|
||||
// Todo: Wrong.
|
||||
if (!musicController.IsPlaying)
|
||||
Debug.Assert(musicController.CurrentTrack != null);
|
||||
|
||||
if (!musicController.CurrentTrack.IsRunning)
|
||||
{
|
||||
musicController.SeekTo(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * musicController.TrackLength);
|
||||
musicController.Play();
|
||||
musicController.CurrentTrack.Seek(metadata.PreviewTime != -1 ? metadata.PreviewTime : 0.4f * musicController.CurrentTrack.Length);
|
||||
musicController.CurrentTrack.Start();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,9 +330,9 @@ namespace osu.Game.Screens.Menu
|
||||
const float velocity_adjust_cutoff = 0.98f;
|
||||
const float paused_velocity = 0.5f;
|
||||
|
||||
if (musicController.IsPlaying)
|
||||
if (musicController.CurrentTrack?.IsRunning == true)
|
||||
{
|
||||
var maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentAmplitudes.Maximum : 0;
|
||||
var maxAmplitude = lastBeatIndex >= 0 ? musicController.CurrentTrack.CurrentAmplitudes.Maximum : 0;
|
||||
logoAmplitudeContainer.Scale = new Vector2((float)Interpolation.Damp(logoAmplitudeContainer.Scale.X, 1 - Math.Max(0, maxAmplitude - scale_adjust_cutoff) * 0.04f, 0.9f, Time.Elapsed));
|
||||
|
||||
if (maxAmplitude > velocity_adjust_cutoff)
|
||||
|
@ -104,7 +104,7 @@ namespace osu.Game.Screens.Multi.Match.Components
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasEnoughTime = DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(musicController.TrackLength) < endDate.Value;
|
||||
bool hasEnoughTime = musicController.CurrentTrack != null && DateTimeOffset.UtcNow.AddSeconds(30).AddMilliseconds(musicController.CurrentTrack.Length) < endDate.Value;
|
||||
|
||||
Enabled.Value = hasBeatmap && hasEnoughTime;
|
||||
}
|
||||
|
@ -343,9 +343,13 @@ namespace osu.Game.Screens.Multi
|
||||
{
|
||||
if (screenStack.CurrentScreen is MatchSubScreen)
|
||||
{
|
||||
musicController.RestartPoint = Beatmap.Value.Metadata.PreviewTime;
|
||||
musicController.Looping = true;
|
||||
musicController.EnsurePlayingSomething();
|
||||
if (musicController.CurrentTrack != null)
|
||||
{
|
||||
musicController.CurrentTrack.RestartPoint = Beatmap.Value.Metadata.PreviewTime;
|
||||
musicController.CurrentTrack.Looping = true;
|
||||
|
||||
musicController.EnsurePlayingSomething();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -355,8 +359,11 @@ namespace osu.Game.Screens.Multi
|
||||
|
||||
private void cancelLooping()
|
||||
{
|
||||
musicController.Looping = false;
|
||||
musicController.RestartPoint = 0;
|
||||
if (musicController.CurrentTrack != null)
|
||||
{
|
||||
musicController.CurrentTrack.Looping = false;
|
||||
musicController.CurrentTrack.RestartPoint = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
|
@ -9,6 +9,7 @@ using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Audio;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Overlays;
|
||||
@ -30,21 +31,21 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
private readonly BindableDouble trackFreq = new BindableDouble(1);
|
||||
|
||||
private DrawableTrack track;
|
||||
|
||||
private const float duration = 2500;
|
||||
|
||||
private SampleChannel failSample;
|
||||
|
||||
[Resolved]
|
||||
private MusicController musicController { get; set; }
|
||||
|
||||
public FailAnimation(DrawableRuleset drawableRuleset)
|
||||
{
|
||||
this.drawableRuleset = drawableRuleset;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(AudioManager audio, IBindable<WorkingBeatmap> beatmap)
|
||||
private void load(AudioManager audio, IBindable<WorkingBeatmap> beatmap, MusicController musicController)
|
||||
{
|
||||
track = musicController.CurrentTrack;
|
||||
failSample = audio.Samples.Get(@"Gameplay/failsound");
|
||||
}
|
||||
|
||||
@ -68,7 +69,7 @@ namespace osu.Game.Screens.Play
|
||||
Expire();
|
||||
});
|
||||
|
||||
musicController.AddAdjustment(AdjustableProperty.Frequency, trackFreq);
|
||||
track.AddAdjustment(AdjustableProperty.Frequency, trackFreq);
|
||||
|
||||
applyToPlayfield(drawableRuleset.Playfield);
|
||||
drawableRuleset.Playfield.HitObjectContainer.FlashColour(Color4.Red, 500);
|
||||
@ -107,7 +108,7 @@ namespace osu.Game.Screens.Play
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
musicController?.RemoveAdjustment(AdjustableProperty.Frequency, trackFreq);
|
||||
track?.RemoveAdjustment(AdjustableProperty.Frequency, trackFreq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,10 @@ using System.Threading.Tasks;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Audio;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -27,8 +29,7 @@ namespace osu.Game.Screens.Play
|
||||
private readonly WorkingBeatmap beatmap;
|
||||
private readonly IReadOnlyList<Mod> mods;
|
||||
|
||||
[Resolved]
|
||||
private MusicController musicController { get; set; }
|
||||
private DrawableTrack track;
|
||||
|
||||
public readonly BindableBool IsPaused = new BindableBool();
|
||||
|
||||
@ -95,8 +96,10 @@ namespace osu.Game.Screens.Play
|
||||
private readonly BindableDouble pauseFreqAdjust = new BindableDouble(1);
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuConfigManager config)
|
||||
private void load(OsuConfigManager config, MusicController musicController)
|
||||
{
|
||||
track = musicController.CurrentTrack;
|
||||
|
||||
userAudioOffset = config.GetBindable<double>(OsuSetting.AudioOffset);
|
||||
userAudioOffset.BindValueChanged(offset => userOffsetClock.Offset = offset.NewValue, true);
|
||||
|
||||
@ -121,15 +124,15 @@ namespace osu.Game.Screens.Play
|
||||
{
|
||||
// The Reset() call below causes speed adjustments to be reset in an async context, leading to deadlocks.
|
||||
// The deadlock can be prevented by resetting the track synchronously before entering the async context.
|
||||
musicController.Reset();
|
||||
track.ResetSpeedAdjustments();
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
musicController.Reset();
|
||||
track.Reset();
|
||||
|
||||
Schedule(() =>
|
||||
{
|
||||
adjustableClock.ChangeSource(musicController.GetTrackClock());
|
||||
adjustableClock.ChangeSource(track);
|
||||
updateRate();
|
||||
|
||||
if (!IsPaused.Value)
|
||||
@ -190,6 +193,20 @@ namespace osu.Game.Screens.Play
|
||||
IsPaused.Value = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the backing clock to avoid using the originally provided track.
|
||||
/// </summary>
|
||||
public void StopUsingBeatmapClock()
|
||||
{
|
||||
if (track == null)
|
||||
return;
|
||||
|
||||
removeSourceClockAdjustments();
|
||||
|
||||
track = new DrawableTrack(new TrackVirtual(track.Length));
|
||||
adjustableClock.ChangeSource(track);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
if (!IsPaused.Value)
|
||||
@ -202,23 +219,30 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
private void updateRate()
|
||||
{
|
||||
if (track == null) return;
|
||||
|
||||
speedAdjustmentsApplied = true;
|
||||
musicController.ResetTrackAdjustments();
|
||||
musicController.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);
|
||||
musicController.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate);
|
||||
track.ResetSpeedAdjustments();
|
||||
|
||||
track.AddAdjustment(AdjustableProperty.Frequency, pauseFreqAdjust);
|
||||
track.AddAdjustment(AdjustableProperty.Tempo, UserPlaybackRate);
|
||||
|
||||
foreach (var mod in mods.OfType<IApplicableToTrack>())
|
||||
mod.ApplyToTrack(track);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
removeSourceClockAdjustments();
|
||||
track = null;
|
||||
}
|
||||
|
||||
private void removeSourceClockAdjustments()
|
||||
{
|
||||
if (speedAdjustmentsApplied)
|
||||
{
|
||||
musicController.ResetTrackAdjustments();
|
||||
track.ResetSpeedAdjustments();
|
||||
speedAdjustmentsApplied = false;
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
@ -560,9 +561,9 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
BeatmapDetails.Refresh();
|
||||
|
||||
if (music != null)
|
||||
if (music?.CurrentTrack != null)
|
||||
{
|
||||
music.Looping = true;
|
||||
music.CurrentTrack.Looping = true;
|
||||
music.ResetTrackAdjustments();
|
||||
}
|
||||
|
||||
@ -588,8 +589,8 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
BeatmapOptions.Hide();
|
||||
|
||||
if (music != null)
|
||||
music.Looping = false;
|
||||
if (music?.CurrentTrack != null)
|
||||
music.CurrentTrack.Looping = false;
|
||||
|
||||
this.ScaleTo(1.1f, 250, Easing.InSine);
|
||||
|
||||
@ -610,8 +611,8 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
FilterControl.Deactivate();
|
||||
|
||||
if (music != null)
|
||||
music.Looping = false;
|
||||
if (music?.CurrentTrack != null)
|
||||
music.CurrentTrack.Looping = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -652,18 +653,30 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
BeatmapDetails.Beatmap = beatmap;
|
||||
|
||||
if (music != null)
|
||||
music.Looping = false;
|
||||
if (music?.CurrentTrack != null)
|
||||
music.CurrentTrack.Looping = false;
|
||||
}
|
||||
|
||||
private readonly WeakReference<ITrack> lastTrack = new WeakReference<ITrack>(null);
|
||||
|
||||
/// <summary>
|
||||
/// Ensures some music is playing for the current track.
|
||||
/// Will resume playback from a manual user pause if the track has changed.
|
||||
/// </summary>
|
||||
private void ensurePlayingSelected()
|
||||
{
|
||||
music.RestartPoint = Beatmap.Value.Metadata.PreviewTime;
|
||||
music.EnsurePlayingSomething();
|
||||
ITrack track = music?.CurrentTrack;
|
||||
if (track == null)
|
||||
return;
|
||||
|
||||
bool isNewTrack = !lastTrack.TryGetTarget(out var last) || last != track;
|
||||
|
||||
track.RestartPoint = Beatmap.Value.Metadata.PreviewTime;
|
||||
|
||||
if (!track.IsRunning && (music?.IsUserPaused != true || isNewTrack))
|
||||
music?.Play(true);
|
||||
|
||||
lastTrack.SetTarget(track);
|
||||
}
|
||||
|
||||
private void carouselBeatmapsLoaded()
|
||||
|
@ -44,7 +44,7 @@ namespace osu.Game.Tests.Visual
|
||||
private void beatmapChanged(ValueChangedEvent<WorkingBeatmap> e)
|
||||
{
|
||||
Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo;
|
||||
Clock.ChangeSource(MusicController.GetTrackClock() ?? new StopwatchClock());
|
||||
Clock.ChangeSource((IAdjustableClock)MusicController.CurrentTrack ?? new StopwatchClock());
|
||||
Clock.ProcessFrame();
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
// 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.
|
||||
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
/// <summary>
|
||||
@ -13,7 +15,7 @@ namespace osu.Game.Tests.Visual
|
||||
base.Update();
|
||||
|
||||
// note that this will override any mod rate application
|
||||
MusicController.Tempo.Value = Clock.Rate;
|
||||
MusicController.CurrentTrack.AsNonNull().Tempo.Value = Clock.Rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user