1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 10:52:53 +08:00

Merge pull request #18462 from frenzibyte/fix-timeline-zooming

Fix timeline objects disappearing prematurely on wide-screens
This commit is contained in:
Dan Balasescu 2022-06-05 11:49:44 +09:00 committed by GitHub
commit b897e1464f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 8 deletions

View File

@ -0,0 +1,48 @@
// 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 NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Utils;
namespace osu.Game.Tests.Visual.Editing
{
public class TestSceneTimelineZoom : TimelineTestScene
{
public override Drawable CreateTestComponent() => Empty();
[Test]
public void TestVisibleRangeUpdatesOnZoomChange()
{
double initialVisibleRange = 0;
AddStep("reset zoom", () => TimelineArea.Timeline.Zoom = 100);
AddStep("get initial range", () => initialVisibleRange = TimelineArea.Timeline.VisibleRange);
AddStep("scale zoom", () => TimelineArea.Timeline.Zoom = 200);
AddAssert("range halved", () => Precision.AlmostEquals(TimelineArea.Timeline.VisibleRange, initialVisibleRange / 2, 1));
AddStep("descale zoom", () => TimelineArea.Timeline.Zoom = 50);
AddAssert("range doubled", () => Precision.AlmostEquals(TimelineArea.Timeline.VisibleRange, initialVisibleRange * 2, 1));
AddStep("restore zoom", () => TimelineArea.Timeline.Zoom = 100);
AddAssert("range restored", () => Precision.AlmostEquals(TimelineArea.Timeline.VisibleRange, initialVisibleRange, 1));
}
[Test]
public void TestVisibleRangeConstantOnSizeChange()
{
double initialVisibleRange = 0;
AddStep("reset timeline size", () => TimelineArea.Timeline.Width = 1);
AddStep("get initial range", () => initialVisibleRange = TimelineArea.Timeline.VisibleRange);
AddStep("scale timeline size", () => TimelineArea.Timeline.Width = 2);
AddAssert("same range", () => TimelineArea.Timeline.VisibleRange == initialVisibleRange);
AddStep("descale timeline size", () => TimelineArea.Timeline.Width = 0.5f);
AddAssert("same range", () => TimelineArea.Timeline.VisibleRange == initialVisibleRange);
AddStep("restore timeline size", () => TimelineArea.Timeline.Width = 1);
AddAssert("same range", () => TimelineArea.Timeline.VisibleRange == initialVisibleRange);
}
}
}

View File

@ -44,7 +44,12 @@ namespace osu.Game.Tests.Visual.Editing
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.Gray(30)
},
scrollContainer = new ZoomableScrollContainer { RelativeSizeAxes = Axes.Both }
scrollContainer = new ZoomableScrollContainer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both,
}
}
},
new MenuCursor()
@ -62,7 +67,15 @@ namespace osu.Game.Tests.Visual.Editing
[Test]
public void TestWidthInitialization()
{
AddAssert("Inner container width was initialized", () => innerBox.DrawWidth > 0);
AddAssert("Inner container width was initialized", () => innerBox.DrawWidth == scrollContainer.DrawWidth);
}
[Test]
public void TestWidthUpdatesOnDrawSizeChanges()
{
AddStep("Shrink scroll container", () => scrollContainer.Width = 0.5f);
AddAssert("Scroll container width shrunk", () => scrollContainer.DrawWidth == scrollContainer.Parent.DrawWidth / 2);
AddAssert("Inner container width matches scroll container", () => innerBox.DrawWidth == scrollContainer.DrawWidth);
}
[Test]

View File

@ -7,6 +7,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Transforms;
using osu.Framework.Input.Events;
using osu.Framework.Layout;
using osu.Framework.Timing;
using osu.Framework.Utils;
using osu.Game.Graphics.Containers;
@ -40,10 +41,14 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
[Resolved(canBeNull: true)]
private IFrameBasedClock editorClock { get; set; }
private readonly LayoutValue zoomedContentWidthCache = new LayoutValue(Invalidation.DrawSize);
public ZoomableScrollContainer()
: base(Direction.Horizontal)
{
base.Content.Add(zoomedContent = new Container { RelativeSizeAxes = Axes.Y });
AddLayout(zoomedContentWidthCache);
}
private float minZoom = 1;
@ -103,12 +108,12 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
}
}
protected override void LoadComplete()
protected override void Update()
{
base.LoadComplete();
base.Update();
// This width only gets updated on the application of a transform, so this needs to be initialized here.
updateZoomedContentWidth();
if (!zoomedContentWidthCache.IsValid)
updateZoomedContentWidth();
}
protected override bool OnScroll(ScrollEvent e)
@ -128,7 +133,11 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
return base.OnScroll(e);
}
private void updateZoomedContentWidth() => zoomedContent.Width = DrawWidth * currentZoom;
private void updateZoomedContentWidth()
{
zoomedContent.Width = DrawWidth * currentZoom;
zoomedContentWidthCache.Validate();
}
private float zoomTarget = 1;
@ -199,8 +208,8 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline
float targetOffset = expectedWidth * (focusPoint / contentSize) - focusOffset;
d.currentZoom = newZoom;
d.updateZoomedContentWidth();
// Temporarily here to make sure ScrollTo gets the correct DrawSize for scrollable area.
// TODO: Make sure draw size gets invalidated properly on the framework side, and remove this once it is.
d.Invalidate(Invalidation.DrawSize);