mirror of
https://github.com/osukey/osukey.git
synced 2025-07-01 16:29:58 +09:00
Apply reviews, add safety for multiple facades
This commit is contained in:
@ -21,13 +21,13 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Tests.Visual.UserInterface
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
{
|
{
|
||||||
public class TestCaseLogoFacadeContainer : OsuTestCase
|
public class TestCaseLogoTrackingContainer : OsuTestCase
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
typeof(PlayerLoader),
|
typeof(PlayerLoader),
|
||||||
typeof(Player),
|
typeof(Player),
|
||||||
typeof(LogoFacadeContainer),
|
typeof(LogoTrackingContainer),
|
||||||
typeof(ButtonSystem),
|
typeof(ButtonSystem),
|
||||||
typeof(ButtonSystemState),
|
typeof(ButtonSystemState),
|
||||||
typeof(Menu),
|
typeof(Menu),
|
||||||
@ -36,11 +36,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
private OsuLogo logo;
|
private OsuLogo logo;
|
||||||
private readonly Bindable<float> uiScale = new Bindable<float>();
|
private readonly Bindable<float> uiScale = new Bindable<float>();
|
||||||
private TestLogoFacadeContainer facadeContainer;
|
private TestLogoTrackingContainer trackingContainer;
|
||||||
private Container transferContainer;
|
private Container transferContainer;
|
||||||
private Box visualBox;
|
private Box visualBox;
|
||||||
private Box transferContainerBox;
|
private Box transferContainerBox;
|
||||||
private Container logoFacade;
|
private Drawable logoFacade;
|
||||||
private bool randomPositions;
|
private bool randomPositions;
|
||||||
|
|
||||||
private const float visual_box_size = 72;
|
private const float visual_box_size = 72;
|
||||||
@ -59,7 +59,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
Add(logo = new OsuLogo { Scale = new Vector2(0.15f), RelativePositionAxes = Axes.Both });
|
Add(logo = new OsuLogo { Scale = new Vector2(0.15f), RelativePositionAxes = Axes.Both });
|
||||||
facadeContainer = null;
|
trackingContainer = null;
|
||||||
transferContainer = null;
|
transferContainer = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -72,10 +72,10 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
public void MoveFacadeTest()
|
public void MoveFacadeTest()
|
||||||
{
|
{
|
||||||
AddToggleStep("Toggle move continuously", b => randomPositions = b);
|
AddToggleStep("Toggle move continuously", b => randomPositions = b);
|
||||||
AddStep("Add facade containers", addFacadeContainers);
|
AddStep("Add tracking containers", addFacadeContainers);
|
||||||
AddStep("Move facade to random position", startTrackingRandom);
|
AddStep("Move facade to random position", startTrackingRandom);
|
||||||
waitForMove();
|
waitForMove();
|
||||||
AddAssert("Logo is tracking", () => facadeContainer.IsLogoTracking);
|
AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -84,11 +84,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
[Test]
|
[Test]
|
||||||
public void RemoveFacadeTest()
|
public void RemoveFacadeTest()
|
||||||
{
|
{
|
||||||
AddStep("Add facade containers", addFacadeContainers);
|
AddStep("Add tracking containers", addFacadeContainers);
|
||||||
AddStep("Move facade to random position", startTrackingRandom);
|
AddStep("Move facade to random position", startTrackingRandom);
|
||||||
AddStep("Remove facade from FacadeContainer", removeFacade);
|
AddStep("Remove facade from FacadeContainer", removeFacade);
|
||||||
waitForMove();
|
waitForMove();
|
||||||
AddAssert("Logo is not tracking", () => !facadeContainer.IsLogoTracking);
|
AddAssert("Logo is not tracking", () => !trackingContainer.IsLogoTracking);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -97,17 +97,12 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
[Test]
|
[Test]
|
||||||
public void TransferFacadeTest()
|
public void TransferFacadeTest()
|
||||||
{
|
{
|
||||||
AddStep("Add facade containers", addFacadeContainers);
|
AddStep("Add tracking containers", addFacadeContainers);
|
||||||
AddStep("Move facade to random position", startTrackingRandom);
|
AddStep("Move facade to random position", startTrackingRandom);
|
||||||
AddStep("Remove facade from FacadeContainer", removeFacade);
|
AddStep("Remove facade from FacadeContainer", removeFacade);
|
||||||
AddStep("Transfer facade to a new container", () =>
|
AddStep("Transfer facade to a new container", addFacadeToNewContainer);
|
||||||
{
|
|
||||||
transferContainer.Add(logoFacade);
|
|
||||||
transferContainerBox.Colour = Color4.Tomato;
|
|
||||||
moveLogoFacade();
|
|
||||||
});
|
|
||||||
waitForMove();
|
waitForMove();
|
||||||
AddAssert("Logo is tracking", () => facadeContainer.IsLogoTracking);
|
AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -120,7 +115,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
AddStep("Create new flow container with facade", () =>
|
AddStep("Create new flow container with facade", () =>
|
||||||
{
|
{
|
||||||
Add(facadeContainer = new TestLogoFacadeContainer
|
Add(trackingContainer = new TestLogoTrackingContainer
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
@ -156,7 +151,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
Colour = Color4.White,
|
Colour = Color4.White,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
facadeContainer.LogoFacade,
|
trackingContainer.LogoFacade,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Box
|
new Box
|
||||||
@ -171,27 +166,34 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
AddStep("Perform logo movements", () =>
|
AddStep("Perform logo movements", () =>
|
||||||
{
|
{
|
||||||
facadeContainer.Tracking = false;
|
trackingContainer.Tracking = false;
|
||||||
logo.MoveTo(new Vector2(0.5f), 500, Easing.InOutExpo);
|
logo.MoveTo(new Vector2(0.5f), 500, Easing.InOutExpo);
|
||||||
facadeContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutExpo);
|
trackingContainer.SetLogo(logo, 1.0f, 1000, Easing.InOutExpo);
|
||||||
visualBox.Colour = Color4.White;
|
visualBox.Colour = Color4.White;
|
||||||
|
|
||||||
Scheduler.AddDelayed(() =>
|
Scheduler.AddDelayed(() =>
|
||||||
{
|
{
|
||||||
facadeContainer.Tracking = true;
|
trackingContainer.Tracking = true;
|
||||||
visualBox.Colour = Color4.Tomato;
|
visualBox.Colour = Color4.Tomato;
|
||||||
}, 700);
|
}, 700);
|
||||||
});
|
});
|
||||||
|
|
||||||
waitForMove(8);
|
waitForMove(8);
|
||||||
AddAssert("Logo is tracking", () => facadeContainer.IsLogoTracking);
|
AddAssert("Logo is tracking", () => trackingContainer.IsLogoTracking);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SetFacadeSizeTest()
|
||||||
|
{
|
||||||
|
AddStep("Add tracking containers", addFacadeContainers);
|
||||||
|
AddStep("Break shit", () => { logoFacade.Size = new Vector2(0, 0); });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFacadeContainers()
|
private void addFacadeContainers()
|
||||||
{
|
{
|
||||||
AddRange(new Drawable[]
|
AddRange(new Drawable[]
|
||||||
{
|
{
|
||||||
facadeContainer = new TestLogoFacadeContainer
|
trackingContainer = new TestLogoTrackingContainer
|
||||||
{
|
{
|
||||||
Alpha = 0.35f,
|
Alpha = 0.35f,
|
||||||
RelativeSizeAxes = Axes.None,
|
RelativeSizeAxes = Axes.None,
|
||||||
@ -215,22 +217,29 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
facadeContainer.Add(logoFacade = facadeContainer.LogoFacade);
|
trackingContainer.Add(logoFacade = trackingContainer.LogoFacade);
|
||||||
facadeContainer.SetLogo(logo, 1.0f, 1000);
|
trackingContainer.SetLogo(logo, 1.0f, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void waitForMove(int count = 5) => AddWaitStep("Wait for transforms to finish", count);
|
private void waitForMove(int count = 5) => AddWaitStep("Wait for transforms to finish", count);
|
||||||
|
|
||||||
private void removeFacade()
|
private void removeFacade()
|
||||||
{
|
{
|
||||||
facadeContainer.Remove(logoFacade);
|
trackingContainer.Remove(logoFacade);
|
||||||
visualBox.Colour = Color4.White;
|
visualBox.Colour = Color4.White;
|
||||||
moveLogoFacade();
|
moveLogoFacade();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startTrackingRandom()
|
private void startTrackingRandom()
|
||||||
{
|
{
|
||||||
facadeContainer.Tracking = true;
|
trackingContainer.Tracking = true;
|
||||||
|
moveLogoFacade();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addFacadeToNewContainer()
|
||||||
|
{
|
||||||
|
transferContainer.Add(logoFacade);
|
||||||
|
transferContainerBox.Colour = Color4.Tomato;
|
||||||
moveLogoFacade();
|
moveLogoFacade();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +248,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
if (logoFacade?.Transforms.Count == 0 && transferContainer?.Transforms.Count == 0)
|
if (logoFacade?.Transforms.Count == 0 && transferContainer?.Transforms.Count == 0)
|
||||||
{
|
{
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
facadeContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300);
|
trackingContainer.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);
|
transferContainer.Delay(500).MoveTo(new Vector2(random.Next(0, (int)logo.Parent.DrawWidth), random.Next(0, (int)logo.Parent.DrawHeight)), 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,12 +256,12 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
Schedule(moveLogoFacade);
|
Schedule(moveLogoFacade);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestLogoFacadeContainer : LogoFacadeContainer
|
private class TestLogoTrackingContainer : LogoTrackingContainer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check that the logo is tracking the position of the facade, with an acceptable precision lenience.
|
/// Check that the logo is tracking the position of the facade, with an acceptable precision lenience.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsLogoTracking => Precision.AlmostEquals(Logo.Position, LogoTrackingPosition());
|
public bool IsLogoTracking => Precision.AlmostEquals(Logo.Position, LogoTrackingPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,114 +0,0 @@
|
|||||||
// 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;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.MathUtils;
|
|
||||||
using osu.Game.Screens.Menu;
|
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Graphics.Containers
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A container that creates a <see cref="Facade"/> to be used to update and track the position of an <see cref="OsuLogo"/>.
|
|
||||||
/// </summary>
|
|
||||||
public class LogoFacadeContainer : Container
|
|
||||||
{
|
|
||||||
protected virtual Facade CreateFacade() => new Facade();
|
|
||||||
|
|
||||||
public Facade LogoFacade { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether or not the logo assigned to this FacadeContainer should be tracking the position its facade.
|
|
||||||
/// </summary>
|
|
||||||
public bool Tracking = false;
|
|
||||||
|
|
||||||
protected OsuLogo Logo;
|
|
||||||
|
|
||||||
private float facadeScale;
|
|
||||||
private Easing easing;
|
|
||||||
private Vector2? startPosition;
|
|
||||||
private double? startTime;
|
|
||||||
private double duration;
|
|
||||||
|
|
||||||
public LogoFacadeContainer()
|
|
||||||
{
|
|
||||||
LogoFacade = CreateFacade();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Assign the logo that should track the Facade's position, as well as how it should transform to its initial position.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="logo">The instance of the logo to be used for tracking.</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="easing">The easing type of the initial transform.</param>
|
|
||||||
public void SetLogo(OsuLogo logo, float facadeScale = 1.0f, double duration = 0, Easing easing = Easing.None)
|
|
||||||
{
|
|
||||||
Logo = logo ?? throw new ArgumentNullException(nameof(logo));
|
|
||||||
this.facadeScale = facadeScale;
|
|
||||||
this.duration = duration;
|
|
||||||
this.easing = easing;
|
|
||||||
|
|
||||||
startTime = null;
|
|
||||||
startPosition = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the position that the logo should move to with respect to the <see cref="LogoFacade"/>.
|
|
||||||
/// Manually performs a conversion of the Facade's position to the Logo's parent's relative space.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>Will only be correct if the logo's <see cref="Drawable.RelativePositionAxes"/> are set to Axes.Both</remarks>
|
|
||||||
/// <returns>The position that the logo should move to in its parent's relative space.</returns>
|
|
||||||
protected Vector2 LogoTrackingPosition()
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
|
||||||
{
|
|
||||||
base.Update();
|
|
||||||
|
|
||||||
if (Logo == null || !Tracking)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Account for the scale of the actual logo container, as SizeForFlow only accounts for the sprite scale.
|
|
||||||
LogoFacade.Size = new Vector2(Logo.SizeForFlow * Logo.Scale.X * facadeScale);
|
|
||||||
|
|
||||||
if (LogoFacade.Parent != null && Logo.Position != LogoTrackingPosition())
|
|
||||||
{
|
|
||||||
// If this is our first update since tracking has started, initialize our starting values for interpolation
|
|
||||||
if (startTime == null || startPosition == null)
|
|
||||||
{
|
|
||||||
startTime = Time.Current;
|
|
||||||
startPosition = Logo.Position;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (duration != 0)
|
|
||||||
{
|
|
||||||
double elapsedDuration = Time.Current - startTime ?? throw new ArgumentNullException(nameof(startTime));
|
|
||||||
|
|
||||||
var mount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1));
|
|
||||||
|
|
||||||
// Interpolate the position of the logo, where mount 0 is where the logo was when it first began interpolating, and mount 1 is the target location.
|
|
||||||
Logo.Position = Vector2.Lerp(startPosition ?? throw new ArgumentNullException(nameof(startPosition)), LogoTrackingPosition(), mount);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logo.Position = LogoTrackingPosition();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A placeholder container that serves as a dummy object to denote another object's location and size.
|
|
||||||
/// </summary>
|
|
||||||
public class Facade : Container
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
156
osu.Game/Graphics/Containers/LogoTrackingContainer.cs
Normal file
156
osu.Game/Graphics/Containers/LogoTrackingContainer.cs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
// 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;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.MathUtils;
|
||||||
|
using osu.Game.Screens.Menu;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.Containers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A container that handles tracking of an <see cref="OsuLogo"/> through different layout scenarios
|
||||||
|
/// </summary>
|
||||||
|
public class LogoTrackingContainer : Container
|
||||||
|
{
|
||||||
|
public Facade LogoFacade { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not the logo assigned to this FacadeContainer should be tracking the position of its facade.
|
||||||
|
/// </summary>
|
||||||
|
public bool Tracking { get; set; }
|
||||||
|
|
||||||
|
protected OsuLogo Logo;
|
||||||
|
|
||||||
|
private float facadeScale;
|
||||||
|
private Easing easing;
|
||||||
|
private Vector2? startPosition;
|
||||||
|
private double? startTime;
|
||||||
|
private double duration;
|
||||||
|
|
||||||
|
public LogoTrackingContainer()
|
||||||
|
{
|
||||||
|
LogoFacade = new ExposedFacade();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assign the logo that should track the Facade's position, as well as how it should transform to its initial position.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logo">The instance of the logo to be used for tracking.</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="easing">The easing type of the initial transform.</param>
|
||||||
|
public void SetLogo(OsuLogo logo, float facadeScale = 1.0f, double duration = 0, Easing easing = Easing.None)
|
||||||
|
{
|
||||||
|
if (Logo != logo)
|
||||||
|
{
|
||||||
|
if (logo?.HasTrackingContainer ?? throw new ArgumentNullException(nameof(logo)))
|
||||||
|
{
|
||||||
|
// Prevent the same logo from being added to multiple LogoTrackingContainers.
|
||||||
|
throw new InvalidOperationException($"Cannot add an instance of {typeof(OsuLogo)} to multiple {typeof(LogoTrackingContainer)}s");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Logo != null)
|
||||||
|
{
|
||||||
|
// If we're replacing the logo to be tracked, the old one no longer has a tracking container
|
||||||
|
Logo.HasTrackingContainer = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logo = logo;
|
||||||
|
Logo.HasTrackingContainer = true;
|
||||||
|
this.facadeScale = facadeScale;
|
||||||
|
this.duration = duration;
|
||||||
|
this.easing = easing;
|
||||||
|
|
||||||
|
startTime = null;
|
||||||
|
startPosition = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the position that the logo should move to with respect to the <see cref="LogoFacade"/>.
|
||||||
|
/// Manually performs a conversion of the Facade's position to the Logo's parent's relative space.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Will only be correct if the logo's <see cref="Drawable.RelativePositionAxes"/> are set to Axes.Both</remarks>
|
||||||
|
protected Vector2 LogoTrackingPosition => new Vector2(Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).X / Logo.Parent.RelativeToAbsoluteFactor.X,
|
||||||
|
Logo.Parent.ToLocalSpace(LogoFacade.ScreenSpaceDrawQuad.Centre).Y / Logo.Parent.RelativeToAbsoluteFactor.Y);
|
||||||
|
|
||||||
|
protected override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if (Logo == null || !Tracking)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Account for the scale of the actual OsuLogo, as SizeForFlow only accounts for the sprite scale.
|
||||||
|
((ExposedFacade)LogoFacade).SetSize(new Vector2(Logo.SizeForFlow * Logo.Scale.X * facadeScale));
|
||||||
|
|
||||||
|
if (LogoFacade.Parent != null && Logo.Position != LogoTrackingPosition && Logo.RelativePositionAxes == Axes.Both)
|
||||||
|
{
|
||||||
|
// If this is our first update since tracking has started, initialize our starting values for interpolation
|
||||||
|
if (startTime == null || startPosition == null)
|
||||||
|
{
|
||||||
|
startTime = Time.Current;
|
||||||
|
startPosition = Logo.Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (duration != 0)
|
||||||
|
{
|
||||||
|
double elapsedDuration = (double)(Time.Current - startTime);
|
||||||
|
|
||||||
|
var amount = (float)Interpolation.ApplyEasing(easing, Math.Min(elapsedDuration / duration, 1));
|
||||||
|
|
||||||
|
// Interpolate the position of the logo, where amount 0 is where the logo was when it first began interpolating, and amount 1 is the target location.
|
||||||
|
Logo.Position = Vector2.Lerp((Vector2)startPosition, LogoTrackingPosition, amount);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logo.Position = LogoTrackingPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
if (Logo != null)
|
||||||
|
Logo.HasTrackingContainer = false;
|
||||||
|
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 size;
|
||||||
|
|
||||||
|
private class ExposedFacade : Facade
|
||||||
|
{
|
||||||
|
public override Vector2 Size
|
||||||
|
{
|
||||||
|
get => base.Size;
|
||||||
|
set => throw new InvalidOperationException($"Cannot set the Size of a {typeof(Facade)} outside of a {typeof(LogoTrackingContainer)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSize(Vector2 size)
|
||||||
|
{
|
||||||
|
base.SetSize(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A dummy object used to denote another object's location.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class Facade : Drawable
|
||||||
|
{
|
||||||
|
public override Vector2 Size
|
||||||
|
{
|
||||||
|
get => base.Size;
|
||||||
|
set => throw new InvalidOperationException($"Cannot set the Size of a {typeof(Facade)} outside of a {typeof(LogoTrackingContainer)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetSize(Vector2 size)
|
||||||
|
{
|
||||||
|
base.Size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -60,7 +60,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
if (this.logo != null)
|
if (this.logo != null)
|
||||||
{
|
{
|
||||||
this.logo.Action = onOsuLogo;
|
this.logo.Action = onOsuLogo;
|
||||||
logoFacadeContainer.SetLogo(logo, 0.74f);
|
logoTrackingContainer.SetLogo(logo, 0.74f);
|
||||||
|
|
||||||
// osuLogo.SizeForFlow relies on loading to be complete.
|
// osuLogo.SizeForFlow relies on loading to be complete.
|
||||||
buttonArea.Flow.Position = new Vector2(WEDGE_WIDTH * 2 - (BUTTON_WIDTH + this.logo.SizeForFlow / 4), 0);
|
buttonArea.Flow.Position = new Vector2(WEDGE_WIDTH * 2 - (BUTTON_WIDTH + this.logo.SizeForFlow / 4), 0);
|
||||||
@ -70,7 +70,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We should stop tracking as the facade is now out of scope.
|
// We should stop tracking as the facade is now out of scope.
|
||||||
logoFacadeContainer.Tracking = false;
|
logoTrackingContainer.Tracking = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,29 +83,29 @@ namespace osu.Game.Screens.Menu
|
|||||||
|
|
||||||
private SampleChannel sampleBack;
|
private SampleChannel sampleBack;
|
||||||
|
|
||||||
private readonly LogoFacadeContainer logoFacadeContainer;
|
private readonly LogoTrackingContainer logoTrackingContainer;
|
||||||
|
|
||||||
public ButtonSystem()
|
public ButtonSystem()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
Child = logoFacadeContainer = new LogoFacadeContainer
|
Child = logoTrackingContainer = new LogoTrackingContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = buttonArea = new ButtonArea()
|
Child = buttonArea = new ButtonArea()
|
||||||
};
|
};
|
||||||
|
|
||||||
buttonArea.AddRange(new Container[]
|
buttonArea.AddRange(new Drawable[]
|
||||||
{
|
{
|
||||||
new Button(@"settings", string.Empty, FontAwesome.Gear, new Color4(85, 85, 85, 255), () => OnSettings?.Invoke(), -WEDGE_WIDTH, Key.O),
|
new Button(@"settings", string.Empty, FontAwesome.Gear, new Color4(85, 85, 85, 255), () => OnSettings?.Invoke(), -WEDGE_WIDTH, Key.O),
|
||||||
backButton = new Button(@"back", @"button-back-select", OsuIcon.LeftCircle, new Color4(51, 58, 94, 255), () => State = ButtonSystemState.TopLevel, -WEDGE_WIDTH)
|
backButton = new Button(@"back", @"button-back-select", OsuIcon.LeftCircle, new Color4(51, 58, 94, 255), () => State = ButtonSystemState.TopLevel, -WEDGE_WIDTH)
|
||||||
{
|
{
|
||||||
VisibleState = ButtonSystemState.Play,
|
VisibleState = ButtonSystemState.Play,
|
||||||
},
|
},
|
||||||
logoFacadeContainer.LogoFacade
|
logoTrackingContainer.LogoFacade
|
||||||
});
|
});
|
||||||
|
|
||||||
buttonArea.Flow.CentreTarget = logoFacadeContainer.LogoFacade;
|
buttonArea.Flow.CentreTarget = logoTrackingContainer.LogoFacade;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Resolved(CanBeNull = true)]
|
[Resolved(CanBeNull = true)]
|
||||||
@ -271,7 +271,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
logoDelayedAction?.Cancel();
|
logoDelayedAction?.Cancel();
|
||||||
logoDelayedAction = Scheduler.AddDelayed(() =>
|
logoDelayedAction = Scheduler.AddDelayed(() =>
|
||||||
{
|
{
|
||||||
logoFacadeContainer.Tracking = false;
|
logoTrackingContainer.Tracking = false;
|
||||||
|
|
||||||
game?.Toolbar.Hide();
|
game?.Toolbar.Hide();
|
||||||
|
|
||||||
@ -294,8 +294,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
if (lastState == ButtonSystemState.Initial)
|
if (lastState == ButtonSystemState.Initial)
|
||||||
logo.ScaleTo(0.5f, 200, Easing.In);
|
logo.ScaleTo(0.5f, 200, Easing.In);
|
||||||
|
|
||||||
logoFacadeContainer.SetLogo(logo, 0.74f, lastState == ButtonSystemState.EnteringMode ? 0 : 200, Easing.In);
|
logoTrackingContainer.SetLogo(logo, 0.74f, lastState == ButtonSystemState.EnteringMode ? 0 : 200, Easing.In);
|
||||||
logoFacadeContainer.Tracking = true;
|
logoTrackingContainer.Tracking = true;
|
||||||
|
|
||||||
logoDelayedAction?.Cancel();
|
logoDelayedAction?.Cancel();
|
||||||
logoDelayedAction = Scheduler.AddDelayed(() =>
|
logoDelayedAction = Scheduler.AddDelayed(() =>
|
||||||
@ -308,14 +308,14 @@ namespace osu.Game.Screens.Menu
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logo.ClearTransforms(targetMember: nameof(Position));
|
logo.ClearTransforms(targetMember: nameof(Position));
|
||||||
logoFacadeContainer.Tracking = true;
|
logoTrackingContainer.Tracking = true;
|
||||||
logo.ScaleTo(0.5f, 200, Easing.OutQuint);
|
logo.ScaleTo(0.5f, 200, Easing.OutQuint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ButtonSystemState.EnteringMode:
|
case ButtonSystemState.EnteringMode:
|
||||||
logoFacadeContainer.Tracking = true;
|
logoTrackingContainer.Tracking = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,8 +54,14 @@ namespace osu.Game.Screens.Menu
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<bool> Action;
|
public Func<bool> Action;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The size of the logo Sprite with respect to the scale of its hover and bounce containers.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Does not account for the scale of this <see cref="OsuLogo"/></remarks>
|
||||||
public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * logoHoverContainer.Scale.X;
|
public float SizeForFlow => logo == null ? 0 : logo.DrawSize.X * logo.Scale.X * logoBounceContainer.Scale.X * logoHoverContainer.Scale.X;
|
||||||
|
|
||||||
|
public bool HasTrackingContainer { get; set; }
|
||||||
|
|
||||||
private readonly Sprite ripple;
|
private readonly Sprite ripple;
|
||||||
|
|
||||||
private readonly Container rippleContainer;
|
private readonly Container rippleContainer;
|
||||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
private Player player;
|
private Player player;
|
||||||
|
|
||||||
private LogoFacadeContainer content;
|
private LogoTrackingContainer content;
|
||||||
|
|
||||||
private BeatmapMetadataDisplay info;
|
private BeatmapMetadataDisplay info;
|
||||||
|
|
||||||
@ -60,14 +60,12 @@ namespace osu.Game.Screens.Play
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
InternalChild = content = new LogoFacadeContainer
|
InternalChild = (content = new LogoTrackingContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
};
|
}).WithChildren(new Drawable[]
|
||||||
|
|
||||||
content.Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
info = new BeatmapMetadataDisplay(Beatmap.Value, content.LogoFacade)
|
info = new BeatmapMetadataDisplay(Beatmap.Value, content.LogoFacade)
|
||||||
{
|
{
|
||||||
@ -89,7 +87,7 @@ namespace osu.Game.Screens.Play
|
|||||||
new InputSettings()
|
new InputSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
loadNewPlayer();
|
loadNewPlayer();
|
||||||
}
|
}
|
||||||
@ -163,12 +161,9 @@ namespace osu.Game.Screens.Play
|
|||||||
logo.ScaleTo(new Vector2(0.15f), duration, Easing.In);
|
logo.ScaleTo(new Vector2(0.15f), duration, Easing.In);
|
||||||
logo.FadeIn(350);
|
logo.FadeIn(350);
|
||||||
|
|
||||||
content.SetLogo(logo, 1.0f, 500, Easing.InOutExpo);
|
content.SetLogo(logo, 1.0f, resuming ? 0 : 500, Easing.InOutExpo);
|
||||||
|
|
||||||
Scheduler.AddDelayed(() =>
|
Scheduler.AddDelayed(() => { content.Tracking = true; }, resuming ? 0 : 500);
|
||||||
{
|
|
||||||
content.Tracking = true;
|
|
||||||
}, resuming ? 0 : 500);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LogoExiting(OsuLogo logo)
|
protected override void LogoExiting(OsuLogo logo)
|
||||||
@ -321,7 +316,7 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly WorkingBeatmap beatmap;
|
private readonly WorkingBeatmap beatmap;
|
||||||
private readonly Container facade;
|
private readonly Drawable facade;
|
||||||
private LoadingAnimation loading;
|
private LoadingAnimation loading;
|
||||||
private Sprite backgroundSprite;
|
private Sprite backgroundSprite;
|
||||||
private ModDisplay modDisplay;
|
private ModDisplay modDisplay;
|
||||||
@ -343,7 +338,7 @@ namespace osu.Game.Screens.Play
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Container facade)
|
public BeatmapMetadataDisplay(WorkingBeatmap beatmap, Drawable facade)
|
||||||
{
|
{
|
||||||
this.beatmap = beatmap;
|
this.beatmap = beatmap;
|
||||||
this.facade = facade;
|
this.facade = facade;
|
||||||
@ -366,7 +361,7 @@ namespace osu.Game.Screens.Play
|
|||||||
Origin = Anchor.TopCentre,
|
Origin = Anchor.TopCentre,
|
||||||
Anchor = Anchor.TopCentre,
|
Anchor = Anchor.TopCentre,
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
Children = new Drawable[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
facade,
|
facade,
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
|
Reference in New Issue
Block a user