Merge branch 'master' into beatmap-update-test

This commit is contained in:
Dean Herbert
2022-07-26 17:27:36 +09:00
committed by GitHub
54 changed files with 298 additions and 569 deletions

View File

@ -146,13 +146,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
waveform.Waveform = b.NewValue.Waveform;
track = b.NewValue.Track;
// todo: i don't think this is safe, the track may not be loaded yet.
if (track.Length > 0)
{
MaxZoom = getZoomLevelForVisibleMilliseconds(500);
MinZoom = getZoomLevelForVisibleMilliseconds(10000);
defaultTimelineZoom = getZoomLevelForVisibleMilliseconds(6000);
}
setupTimelineZoom();
}, true);
Zoom = (float)(defaultTimelineZoom * editorBeatmap.BeatmapInfo.TimelineZoom);
@ -205,6 +199,20 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
scrollToTrackTime();
}
private void setupTimelineZoom()
{
if (!track.IsLoaded)
{
Scheduler.AddOnce(setupTimelineZoom);
return;
}
defaultTimelineZoom = getZoomLevelForVisibleMilliseconds(6000);
float initialZoom = (float)(defaultTimelineZoom * editorBeatmap.BeatmapInfo.TimelineZoom);
SetupZoom(initialZoom, getZoomLevelForVisibleMilliseconds(10000), getZoomLevelForVisibleMilliseconds(500));
}
protected override bool OnScroll(ScrollEvent e)
{
// if this is not a precision scroll event, let the editor handle the seek itself (for snapping support)

View File

@ -32,20 +32,28 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
private readonly Container zoomedContent;
protected override Container<Drawable> Content => zoomedContent;
private float currentZoom = 1;
/// <summary>
/// The current zoom level of <see cref="ZoomableScrollContainer" />.
/// It may differ from <see cref="Zoom" /> during transitions.
/// The current zoom level of <see cref="ZoomableScrollContainer"/>.
/// It may differ from <see cref="Zoom"/> during transitions.
/// </summary>
public float CurrentZoom => currentZoom;
public float CurrentZoom { get; private set; } = 1;
private bool isZoomSetUp;
[Resolved(canBeNull: true)]
private IFrameBasedClock editorClock { get; set; }
private readonly LayoutValue zoomedContentWidthCache = new LayoutValue(Invalidation.DrawSize);
public ZoomableScrollContainer()
private float minZoom;
private float maxZoom;
/// <summary>
/// Creates a <see cref="ZoomableScrollContainer"/> with no zoom range.
/// Functionality will be disabled until zoom is set up via <see cref="SetupZoom"/>.
/// </summary>
protected ZoomableScrollContainer()
: base(Direction.Horizontal)
{
base.Content.Add(zoomedContent = new Container { RelativeSizeAxes = Axes.Y });
@ -53,46 +61,36 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
AddLayout(zoomedContentWidthCache);
}
private float minZoom = 1;
/// <summary>
/// The minimum zoom level allowed.
/// Creates a <see cref="ZoomableScrollContainer"/> with a defined zoom range.
/// </summary>
public float MinZoom
public ZoomableScrollContainer(float minimum, float maximum, float initial)
: this()
{
get => minZoom;
set
{
if (value < 1)
throw new ArgumentException($"{nameof(MinZoom)} must be >= 1.", nameof(value));
minZoom = value;
// ensure zoom range is in valid state before updating zoom.
if (MinZoom < MaxZoom)
updateZoom();
}
SetupZoom(initial, minimum, maximum);
}
private float maxZoom = 60;
/// <summary>
/// The maximum zoom level allowed.
/// Sets up the minimum and maximum range of this zoomable scroll container, along with the initial zoom value.
/// </summary>
public float MaxZoom
/// <param name="initial">The initial zoom value, applied immediately.</param>
/// <param name="minimum">The minimum zoom value.</param>
/// <param name="maximum">The maximum zoom value.</param>
protected void SetupZoom(float initial, float minimum, float maximum)
{
get => maxZoom;
set
{
if (value < 1)
throw new ArgumentException($"{nameof(MaxZoom)} must be >= 1.", nameof(value));
if (minimum < 1)
throw new ArgumentException($"{nameof(minimum)} ({minimum}) must be >= 1.", nameof(maximum));
maxZoom = value;
if (maximum < 1)
throw new ArgumentException($"{nameof(maximum)} ({maximum}) must be >= 1.", nameof(maximum));
// ensure zoom range is in valid state before updating zoom.
if (MaxZoom > MinZoom)
updateZoom();
}
if (minimum > maximum)
throw new ArgumentException($"{nameof(minimum)} ({minimum}) must be less than {nameof(maximum)} ({maximum})");
minZoom = minimum;
maxZoom = maximum;
CurrentZoom = zoomTarget = initial;
isZoomSetUp = true;
}
/// <summary>
@ -104,14 +102,17 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
set => updateZoom(value);
}
private void updateZoom(float? value = null)
private void updateZoom(float value)
{
float newZoom = Math.Clamp(value ?? Zoom, MinZoom, MaxZoom);
if (!isZoomSetUp)
return;
float newZoom = Math.Clamp(value, minZoom, maxZoom);
if (IsLoaded)
setZoomTarget(newZoom, ToSpaceOfOtherDrawable(new Vector2(DrawWidth / 2, 0), zoomedContent).X);
else
currentZoom = zoomTarget = newZoom;
CurrentZoom = zoomTarget = newZoom;
}
protected override void Update()
@ -141,22 +142,25 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
private void updateZoomedContentWidth()
{
zoomedContent.Width = DrawWidth * currentZoom;
zoomedContent.Width = DrawWidth * CurrentZoom;
zoomedContentWidthCache.Validate();
}
public void AdjustZoomRelatively(float change, float? focusPoint = null)
{
if (!isZoomSetUp)
return;
const float zoom_change_sensitivity = 0.02f;
setZoomTarget(zoomTarget + change * (MaxZoom - minZoom) * zoom_change_sensitivity, focusPoint);
setZoomTarget(zoomTarget + change * (maxZoom - minZoom) * zoom_change_sensitivity, focusPoint);
}
private float zoomTarget = 1;
private void setZoomTarget(float newZoom, float? focusPoint = null)
{
zoomTarget = Math.Clamp(newZoom, MinZoom, MaxZoom);
zoomTarget = Math.Clamp(newZoom, minZoom, maxZoom);
focusPoint ??= zoomedContent.ToLocalSpace(ToScreenSpace(new Vector2(DrawWidth / 2, 0))).X;
transformZoomTo(zoomTarget, focusPoint.Value, ZoomDuration, ZoomEasing);
@ -192,7 +196,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
private readonly float scrollOffset;
/// <summary>
/// Transforms <see cref="ZoomableScrollContainer.currentZoom"/> to a new value.
/// Transforms <see cref="ZoomableScrollContainer.CurrentZoom"/> to a new value.
/// </summary>
/// <param name="focusPoint">The focus point in absolute coordinates local to the content.</param>
/// <param name="contentSize">The size of the content.</param>
@ -204,7 +208,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
this.scrollOffset = scrollOffset;
}
public override string TargetMember => nameof(currentZoom);
public override string TargetMember => nameof(CurrentZoom);
private float valueAt(double time)
{
@ -222,7 +226,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
float expectedWidth = d.DrawWidth * newZoom;
float targetOffset = expectedWidth * (focusPoint / contentSize) - focusOffset;
d.currentZoom = newZoom;
d.CurrentZoom = newZoom;
d.updateZoomedContentWidth();
// Temporarily here to make sure ScrollTo gets the correct DrawSize for scrollable area.
@ -231,7 +235,7 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
d.ScrollTo(targetOffset, false);
}
protected override void ReadIntoStartValue(ZoomableScrollContainer d) => StartValue = d.currentZoom;
protected override void ReadIntoStartValue(ZoomableScrollContainer d) => StartValue = d.CurrentZoom;
}
}
}

View File

@ -11,6 +11,7 @@ using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input.Events;
@ -90,18 +91,16 @@ namespace osu.Game.Screens.Ranking.Statistics
spinner.Show();
var localCancellationSource = loadCancellation = new CancellationTokenSource();
IBeatmap playableBeatmap = null;
var workingBeatmap = beatmapManager.GetWorkingBeatmap(newScore.BeatmapInfo);
// Todo: The placement of this is temporary. Eventually we'll both generate the playable beatmap _and_ run through it in a background task to generate the hit events.
Task.Run(() =>
{
playableBeatmap = beatmapManager.GetWorkingBeatmap(newScore.BeatmapInfo).GetPlayableBeatmap(newScore.Ruleset, newScore.Mods);
}, loadCancellation.Token).ContinueWith(_ => Schedule(() =>
Task.Run(() => workingBeatmap.GetPlayableBeatmap(newScore.Ruleset, newScore.Mods), loadCancellation.Token).ContinueWith(task => Schedule(() =>
{
bool hitEventsAvailable = newScore.HitEvents.Count != 0;
Container<Drawable> container;
var statisticRows = newScore.Ruleset.CreateInstance().CreateStatisticsForScore(newScore, playableBeatmap);
var statisticRows = newScore.Ruleset.CreateInstance().CreateStatisticsForScore(newScore, task.GetResultSafely());
if (!hitEventsAvailable && statisticRows.SelectMany(r => r.Columns).All(c => c.RequiresHitEvents))
{

View File

@ -36,7 +36,7 @@ namespace osu.Game.Screens.Utility
public readonly Bindable<LatencyVisualMode> VisualMode = new Bindable<LatencyVisualMode>();
public CursorContainer? Cursor { get; private set; }
public CursorContainer? MenuCursor { get; private set; }
public bool ProvidingUserCursor => IsActiveArea.Value;
@ -91,7 +91,7 @@ namespace osu.Game.Screens.Utility
{
RelativeSizeAxes = Axes.Both,
},
Cursor = new LatencyCursorContainer
MenuCursor = new LatencyCursorContainer
{
RelativeSizeAxes = Axes.Both,
},
@ -105,7 +105,7 @@ namespace osu.Game.Screens.Utility
{
RelativeSizeAxes = Axes.Both,
},
Cursor = new LatencyCursorContainer
MenuCursor = new LatencyCursorContainer
{
RelativeSizeAxes = Axes.Both,
},
@ -119,7 +119,7 @@ namespace osu.Game.Screens.Utility
{
RelativeSizeAxes = Axes.Both,
},
Cursor = new LatencyCursorContainer
MenuCursor = new LatencyCursorContainer
{
RelativeSizeAxes = Axes.Both,
},