1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 06:52:56 +08:00

Fix Axes.None requirement for FacadeContainer

This commit is contained in:
David Zhao 2019-04-03 19:57:22 +09:00
parent 020be50f03
commit 2ed945605e
5 changed files with 229 additions and 125 deletions

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Bindables; using osu.Framework.Bindables;
@ -10,10 +11,9 @@ 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.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Framework.Screens; using osu.Framework.Testing;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Screens;
using osu.Game.Screens.Menu; using osu.Game.Screens.Menu;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using osuTK; using osuTK;
@ -21,7 +21,7 @@ using osuTK.Graphics;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
public class TestCaseLogoFacadeContainer : ScreenTestCase public class TestCaseLogoFacadeContainer : OsuTestCase
{ {
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
@ -34,23 +34,38 @@ namespace osu.Game.Tests.Visual
typeof(MainMenu) typeof(MainMenu)
}; };
[Cached]
private OsuLogo logo; private OsuLogo logo;
private readonly Bindable<float> uiScale = new Bindable<float>(); private readonly Bindable<float> uiScale = new Bindable<float>();
private LogoFacadeContainer logoFacadeContainer;
private Container transferContainer;
private Box visualBox;
private Box transferContainerBox;
private Container logoFacade;
public TestCaseLogoFacadeContainer() private bool randomPositions = false;
{
Add(logo = new OsuLogo());
}
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuConfigManager config) private void load(OsuConfigManager config)
{ {
Add(logo = new OsuLogo { Scale = new Vector2(0.15f), RelativePositionAxes = Axes.None });
config.BindWith(OsuSetting.UIScale, uiScale); config.BindWith(OsuSetting.UIScale, uiScale);
AddSliderStep("Adjust scale", 0.8f, 1.5f, 1f, v => uiScale.Value = v); AddSliderStep("Adjust scale", 0.8f, 1.5f, 1f, v => uiScale.Value = v);
} }
[SetUpSteps]
public void SetUpSteps()
{
AddStep("Clear facades", () =>
{
Clear();
Add(logo = new OsuLogo { Scale = new Vector2(0.15f), RelativePositionAxes = Axes.None });
logoFacadeContainer = null;
transferContainer = null;
});
}
/// <summary> /// <summary>
/// Move the facade to 0,0, then move it to a random new location while the logo is still transforming to it. /// Move the facade to 0,0, then move it to a random new location while the logo is still transforming to it.
/// Check if the logo is still tracking the facade. /// Check if the logo is still tracking the facade.
@ -58,13 +73,11 @@ namespace osu.Game.Tests.Visual
[Test] [Test]
public void MoveFacadeTest() public void MoveFacadeTest()
{ {
TestScreen screen = null;
bool randomPositions = false;
AddToggleStep("Toggle move continuously", b => randomPositions = b); AddToggleStep("Toggle move continuously", b => randomPositions = b);
AddStep("Move facade to random position", () => LoadScreen(screen = new TestScreen(randomPositions))); AddStep("Add facade containers", addFacadeContainers);
AddUntilStep("Screen is current", () => screen.IsCurrentScreen()); AddStep("Move facade to random position", StartTrackingRandom);
waitForMove(); waitForMove();
AddAssert("Logo is tracking", () => screen.IsLogoTracking); AddAssert("Logo is tracking", () => IsLogoTracking);
} }
/// <summary> /// <summary>
@ -73,12 +86,11 @@ namespace osu.Game.Tests.Visual
[Test] [Test]
public void RemoveFacadeTest() public void RemoveFacadeTest()
{ {
TestScreen screen = null; AddStep("Add facade containers", addFacadeContainers);
AddStep("Move facade to random position", () => LoadScreen(screen = new TestScreen())); AddStep("Move facade to random position", StartTrackingRandom);
AddUntilStep("Screen is current", () => screen.IsCurrentScreen()); AddStep("Remove facade from FacadeContainer", RemoveFacade);
AddStep("Remove facade from FacadeContainer", () => screen.RemoveFacade());
waitForMove(); waitForMove();
AddAssert("Logo is not tracking", () => !screen.IsLogoTracking); AddAssert("Logo is not tracking", () => !IsLogoTracking);
} }
/// <summary> /// <summary>
@ -87,114 +99,162 @@ namespace osu.Game.Tests.Visual
[Test] [Test]
public void TransferFacadeTest() public void TransferFacadeTest()
{ {
TestScreen screen = null; AddStep("Add facade containers", addFacadeContainers);
AddStep("Move facade to random position", () => LoadScreen(screen = new TestScreen())); AddStep("Move facade to random position", StartTrackingRandom);
AddUntilStep("Screen is current", () => screen.IsCurrentScreen()); AddStep("Remove facade from FacadeContainer", RemoveFacade);
AddStep("Remove facade from FacadeContainer", () => screen.RemoveFacade()); AddStep("Transfer facade to a new container", TransferFacade);
AddStep("Transfer facade to a new container", () => screen.TransferFacade());
waitForMove(); waitForMove();
AddAssert("Logo is tracking", () => screen.IsLogoTracking); AddAssert("Logo is tracking", () => IsLogoTracking);
}
/// <summary>
/// Add a facade to a flow container then move logo to facade.
/// </summary>
[Test]
public void FlowContainerTest()
{
FillFlowContainer flowContainer;
AddStep("Create new Logo Facade Container", () =>
{
Add(logoFacadeContainer = new LogoFacadeContainer
{
AutoSizeAxes = Axes.Both,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Child = flowContainer = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Direction = FillDirection.Vertical,
}
});
flowContainer.Children = new Drawable[]
{
new Box
{
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Colour = Color4.Azure,
Size = new Vector2(70)
},
new Container
{
Alpha = 0.35f,
RelativeSizeAxes = Axes.None,
Size = new Vector2(72),
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Children = new Drawable[]
{
visualBox = new Box
{
Colour = Color4.White,
RelativeSizeAxes = Axes.Both,
},
logoFacadeContainer.LogoFacade,
}
},
new Box
{
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Colour = Color4.Azure,
Size = new Vector2(70)
},
};
});
AddStep("Perform logo movements", () =>
{
logoFacadeContainer.Tracking = false;
logo.RelativePositionAxes = Axes.Both;
logo.MoveTo(new Vector2(0.5f), 500, Easing.InOutExpo);
logoFacadeContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutExpo);
visualBox.Colour = Color4.White;
Scheduler.AddDelayed(() =>
{
logoFacadeContainer.Tracking = true;
//logo.RelativePositionAxes = Axes.None;
visualBox.Colour = Color4.Tomato;
}, 700);
});
}
private void addFacadeContainers()
{
AddRange(new Drawable[]
{
logoFacadeContainer = new LogoFacadeContainer
{
Alpha = 0.35f,
RelativeSizeAxes = Axes.None,
Size = new Vector2(72),
Child = visualBox = new Box
{
Colour = Color4.Tomato,
RelativeSizeAxes = Axes.Both,
}
},
transferContainer = new Container
{
Alpha = 0.35f,
RelativeSizeAxes = Axes.None,
Size = new Vector2(72),
Child = transferContainerBox = new Box
{
Colour = Color4.White,
RelativeSizeAxes = Axes.Both,
}
},
});
logoFacadeContainer.Add(logoFacade = logoFacadeContainer.LogoFacade);
logoFacadeContainer.SetLogo(logo, 1.0f, 1000);
} }
private void waitForMove() => AddWaitStep("Wait for transforms to finish", 5); private void waitForMove() => AddWaitStep("Wait for transforms to finish", 5);
private class TestScreen : OsuScreen private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(logoFacade.ScreenSpaceDrawQuad.Centre);
/// <summary>
/// Check that the logo is tracking the position of the facade, with an acceptable precision lenience.
/// </summary>
public bool IsLogoTracking => Math.Abs(logo.Position.X - logoTrackingPosition.X) < 0.001f && Math.Abs(logo.Position.Y - logoTrackingPosition.Y) < 0.001f;
public void RemoveFacade()
{ {
private LogoFacadeContainer logoFacadeContainer; logoFacadeContainer.Remove(logoFacade);
private Container transferContainer; visualBox.Colour = Color4.White;
private Container logoFacade; moveLogoFacade();
private readonly bool randomPositions; }
private OsuLogo logo;
private Box visualBox;
private Box transferContainerBox;
public TestScreen(bool randomPositions = false) public void TransferFacade()
{
transferContainer.Add(logoFacade);
transferContainerBox.Colour = Color4.Tomato;
moveLogoFacade();
}
public void StartTrackingRandom()
{
logoFacadeContainer.Tracking = true;
moveLogoFacade();
}
private void moveLogoFacade()
{
Random random = new Random();
if (logoFacade.Transforms.Count == 0 && transferContainer.Transforms.Count == 0)
{ {
this.randomPositions = randomPositions; logoFacadeContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300);
transferContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300);
} }
[BackgroundDependencyLoader] if (randomPositions)
private void load() Schedule(moveLogoFacade);
{
InternalChildren = new Drawable[]
{
logoFacadeContainer = new LogoFacadeContainer
{
Alpha = 0.35f,
RelativeSizeAxes = Axes.None,
Size = new Vector2(72),
Child = visualBox = new Box
{
Colour = Color4.Tomato,
RelativeSizeAxes = Axes.Both,
}
},
transferContainer = new Container
{
Alpha = 0.35f,
RelativeSizeAxes = Axes.None,
Size = new Vector2(72),
Child = transferContainerBox = new Box
{
Colour = Color4.White,
RelativeSizeAxes = Axes.Both,
}
},
};
logoFacadeContainer.Add(logoFacade = logoFacadeContainer.LogoFacade);
}
private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(logoFacade.ScreenSpaceDrawQuad.Centre);
/// <summary>
/// Check that the logo is tracking the position of the facade, with an acceptable precision lenience.
/// </summary>
public bool IsLogoTracking => Math.Abs(logo.Position.X - logoTrackingPosition.X) < 0.001f && Math.Abs(logo.Position.Y - logoTrackingPosition.Y) < 0.001f;
public void RemoveFacade()
{
logoFacadeContainer.Remove(logoFacade);
visualBox.Colour = Color4.White;
moveLogoFacade();
}
public void TransferFacade()
{
transferContainer.Add(logoFacade);
transferContainerBox.Colour = Color4.Tomato;
moveLogoFacade();
}
protected override void LogoArriving(OsuLogo logo, bool resuming)
{
base.LogoArriving(logo, resuming);
this.logo = logo;
logo.FadeIn(350);
logo.ScaleTo(new Vector2(0.15f), 350, Easing.In);
logoFacadeContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutQuint);
logoFacadeContainer.Tracking = true;
moveLogoFacade();
}
protected override void LogoExiting(OsuLogo logo)
{
base.LogoExiting(logo);
logoFacadeContainer.Tracking = false;
}
private void moveLogoFacade()
{
Random random = new Random();
if (logoFacade.Transforms.Count == 0 && transferContainer.Transforms.Count == 0)
{
logoFacadeContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)DrawWidth), random.Next(0, (int)DrawHeight)), 300);
transferContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)DrawWidth), random.Next(0, (int)DrawHeight)), 300);
}
if (randomPositions)
Schedule(moveLogoFacade);
}
} }
} }
} }

View File

@ -0,0 +1,33 @@
// 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.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Testing;
using osuTK;
namespace osu.Game.Tests.Visual
{
public class TestCasePositionAxes : OsuTestCase
{
private Box box;
public TestCasePositionAxes()
{
Add(new Container()
{
Size = new Vector2(1),
Child = box = new Box
{
Size = new Vector2(25),
RelativePositionAxes = Axes.None,
Position = new Vector2(250)
}
});
AddStep("blank", () => { });
AddStep("change axes", () => box.RelativePositionAxes = Axes.Both);
}
}
}

View File

@ -43,7 +43,7 @@ namespace osu.Game.Graphics.Containers
/// <param name="facadeScale">The scale of the facade. Does not actually affect the logo itself.</param> /// <param name="facadeScale">The scale of the facade. Does not actually affect the logo itself.</param>
/// <param name="duration">The duration of the initial transform. Default is instant.</param> /// <param name="duration">The duration of the initial transform. Default is instant.</param>
/// <param name="easing">The easing type of the initial transform.</param> /// <param name="easing">The easing type of the initial transform.</param>
public void SetLogo(OsuLogo logo, float facadeScale, double duration = 0, Easing easing = Easing.None) public void SetLogo(OsuLogo logo, float facadeScale = 1.0f, double duration = 0, Easing easing = Easing.None)
{ {
this.logo = logo ?? throw new ArgumentNullException(nameof(logo)); this.logo = logo ?? throw new ArgumentNullException(nameof(logo));
this.facadeScale = facadeScale; this.facadeScale = facadeScale;
@ -54,11 +54,19 @@ namespace osu.Game.Graphics.Containers
startPosition = null; startPosition = null;
} }
private Vector2 logoTrackingPosition => logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre); private Vector2 localSpaceConversion()
protected override void UpdateAfterChildren()
{ {
base.UpdateAfterChildren(); Vector2 local;
local.X = logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).X / logo.Parent.RelativeToAbsoluteFactor.X;
local.Y = logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).Y / logo.Parent.RelativeToAbsoluteFactor.Y;
return local;
}
private Vector2 logoTrackingPosition => logo.RelativePositionAxes == Axes.None ? logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre) : localSpaceConversion();
protected override void Update()
{
base.Update();
if (logo == null || !Tracking) if (logo == null || !Tracking)
return; return;
@ -68,9 +76,6 @@ namespace osu.Game.Graphics.Containers
if (LogoFacade.Parent != null && logo.Position != logoTrackingPosition) if (LogoFacade.Parent != null && logo.Position != logoTrackingPosition)
{ {
// Required for the correct position of the logo to be set with respect to logoTrackingPosition
logo.RelativePositionAxes = Axes.None;
// If this is our first update since tracking has started, initialize our starting values for interpolation // If this is our first update since tracking has started, initialize our starting values for interpolation
if (startTime == null || startPosition == null) if (startTime == null || startPosition == null)
{ {

View File

@ -290,6 +290,7 @@ namespace osu.Game.Screens.Menu
break; break;
case ButtonSystemState.Initial: case ButtonSystemState.Initial:
logo.ClearTransforms(targetMember: nameof(Position)); logo.ClearTransforms(targetMember: nameof(Position));
logo.RelativePositionAxes = Axes.None;
bool impact = logo.Scale.X > 0.6f; bool impact = logo.Scale.X > 0.6f;
@ -310,6 +311,7 @@ namespace osu.Game.Screens.Menu
break; break;
default: default:
logo.ClearTransforms(targetMember: nameof(Position)); logo.ClearTransforms(targetMember: nameof(Position));
logo.RelativePositionAxes = Axes.None;
logoFacadeContainer.Tracking = true; logoFacadeContainer.Tracking = true;
logo.ScaleTo(0.5f, 200, Easing.OutQuint); logo.ScaleTo(0.5f, 200, Easing.OutQuint);
break; break;

View File

@ -172,7 +172,11 @@ namespace osu.Game.Screens.Play
content.SetLogo(logo, 1.0f, 500, Easing.InOutExpo); content.SetLogo(logo, 1.0f, 500, Easing.InOutExpo);
Scheduler.AddDelayed(() => content.Tracking = true, resuming ? 0 : 500); Scheduler.AddDelayed(() =>
{
content.Tracking = true;
//logo.RelativePositionAxes = Axes.None;
}, resuming ? 0 : 500);
} }
protected override void LogoExiting(OsuLogo logo) protected override void LogoExiting(OsuLogo logo)