Skip to content

Commit

Permalink
Merge pull request #18462 from frenzibyte/fix-timeline-zooming
Browse files Browse the repository at this point in the history
Fix timeline objects disappearing prematurely on wide-screens
  • Loading branch information
smoogipoo authored Jun 5, 2022
2 parents 47d2bd2 + 2138565 commit b897e14
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 8 deletions.
48 changes: 48 additions & 0 deletions osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
17 changes: 15 additions & 2 deletions osu.Game.Tests/Visual/Editing/TestSceneZoomableScrollContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ public void SetUpSteps()
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()
Expand All @@ -62,7 +67,15 @@ public void SetUpSteps()
[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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
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;
Expand Down Expand Up @@ -40,10 +41,14 @@ public class ZoomableScrollContainer : OsuScrollContainer
[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;
Expand Down Expand Up @@ -103,12 +108,12 @@ public float Zoom
}
}

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)
Expand All @@ -128,7 +133,11 @@ protected override bool OnScroll(ScrollEvent e)
return base.OnScroll(e);
}

private void updateZoomedContentWidth() => zoomedContent.Width = DrawWidth * currentZoom;
private void updateZoomedContentWidth()
{
zoomedContent.Width = DrawWidth * currentZoom;
zoomedContentWidthCache.Validate();
}

private float zoomTarget = 1;

Expand Down Expand Up @@ -199,8 +208,8 @@ protected override void Apply(ZoomableScrollContainer d, double time)
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);
Expand Down

0 comments on commit b897e14

Please sign in to comment.