mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 09:02:55 +08:00
Merge pull request #17049 from peppy/scaling-container-better-custom-override
Apply scaling container transforms at a single point to improve transitions
This commit is contained in:
commit
7be2d94b6a
@ -5,6 +5,7 @@ using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Screens;
|
||||
@ -38,24 +39,24 @@ namespace osu.Game.Graphics.Containers
|
||||
|
||||
private BackgroundScreenStack backgroundStack;
|
||||
|
||||
private bool allowScaling = true;
|
||||
private RectangleF? customRect;
|
||||
private bool customRectIsRelativePosition;
|
||||
|
||||
/// <summary>
|
||||
/// Whether user scaling preferences should be applied. Enabled by default.
|
||||
/// Set a custom position and scale which overrides any user specification.
|
||||
/// </summary>
|
||||
public bool AllowScaling
|
||||
/// <param name="rect">A rectangle with positional and sizing information for this container to conform to. <c>null</c> will clear the custom rect and revert to user settings.</param>
|
||||
/// <param name="relativePosition">Whether the position portion of the provided rect is in relative coordinate space or not.</param>
|
||||
public void SetCustomRect(RectangleF? rect, bool relativePosition = false)
|
||||
{
|
||||
get => allowScaling;
|
||||
set
|
||||
{
|
||||
if (value == allowScaling)
|
||||
return;
|
||||
customRect = rect;
|
||||
customRectIsRelativePosition = relativePosition;
|
||||
|
||||
allowScaling = value;
|
||||
if (IsLoaded) Scheduler.AddOnce(updateSize);
|
||||
}
|
||||
if (IsLoaded) Scheduler.AddOnce(updateSize);
|
||||
}
|
||||
|
||||
private const float corner_radius = 10;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance.
|
||||
/// </summary>
|
||||
@ -69,7 +70,7 @@ namespace osu.Game.Graphics.Containers
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
RelativePositionAxes = Axes.Both,
|
||||
CornerRadius = 10,
|
||||
CornerRadius = corner_radius,
|
||||
Child = content = new ScalingDrawSizePreservingFillContainer(targetMode != ScalingMode.Gameplay)
|
||||
};
|
||||
}
|
||||
@ -137,7 +138,7 @@ namespace osu.Game.Graphics.Containers
|
||||
|
||||
private void updateSize()
|
||||
{
|
||||
const float fade_time = 500;
|
||||
const float duration = 500;
|
||||
|
||||
if (targetMode == ScalingMode.Everything)
|
||||
{
|
||||
@ -156,17 +157,31 @@ namespace osu.Game.Graphics.Containers
|
||||
backgroundStack.Push(new ScalingBackgroundScreen());
|
||||
}
|
||||
|
||||
backgroundStack.FadeIn(fade_time);
|
||||
backgroundStack.FadeIn(duration);
|
||||
}
|
||||
else
|
||||
backgroundStack?.FadeOut(fade_time);
|
||||
backgroundStack?.FadeOut(duration);
|
||||
}
|
||||
|
||||
bool scaling = AllowScaling && (targetMode == null || scalingMode.Value == targetMode);
|
||||
RectangleF targetRect = new RectangleF(Vector2.Zero, Vector2.One);
|
||||
|
||||
var targetSize = scaling ? new Vector2(sizeX.Value, sizeY.Value) : Vector2.One;
|
||||
var targetPosition = scaling ? new Vector2(posX.Value, posY.Value) * (Vector2.One - targetSize) : Vector2.Zero;
|
||||
bool requiresMasking = (scaling && targetSize != Vector2.One)
|
||||
if (customRect != null)
|
||||
{
|
||||
sizableContainer.RelativePositionAxes = customRectIsRelativePosition ? Axes.Both : Axes.None;
|
||||
|
||||
targetRect = customRect.Value;
|
||||
}
|
||||
else if (targetMode == null || scalingMode.Value == targetMode)
|
||||
{
|
||||
sizableContainer.RelativePositionAxes = Axes.Both;
|
||||
|
||||
Vector2 scale = new Vector2(sizeX.Value, sizeY.Value);
|
||||
Vector2 pos = new Vector2(posX.Value, posY.Value) * (Vector2.One - scale);
|
||||
|
||||
targetRect = new RectangleF(pos, scale);
|
||||
}
|
||||
|
||||
bool requiresMasking = targetRect.Size != Vector2.One
|
||||
// For the top level scaling container, for now we apply masking if safe areas are in use.
|
||||
// In the future this can likely be removed as more of the actual UI supports overflowing into the safe areas.
|
||||
|| (targetMode == ScalingMode.Everything && safeAreaPadding.Value.Total != Vector2.Zero);
|
||||
@ -174,8 +189,14 @@ namespace osu.Game.Graphics.Containers
|
||||
if (requiresMasking)
|
||||
sizableContainer.Masking = true;
|
||||
|
||||
sizableContainer.MoveTo(targetPosition, 500, Easing.OutQuart);
|
||||
sizableContainer.ResizeTo(targetSize, 500, Easing.OutQuart).OnComplete(_ => { sizableContainer.Masking = requiresMasking; });
|
||||
sizableContainer.MoveTo(targetRect.Location, duration, Easing.OutQuart);
|
||||
sizableContainer.ResizeTo(targetRect.Size, duration, Easing.OutQuart);
|
||||
|
||||
// Of note, this will not work great in the case of nested ScalingContainers where multiple are applying corner radius.
|
||||
// Masking and corner radius should likely only be applied at one point in the full game stack to fix this.
|
||||
// An example of how this can occur is when the skin editor is visible and the game screen scaling is set to "Everything".
|
||||
sizableContainer.TransformTo(nameof(CornerRadius), requiresMasking ? corner_radius : 0, duration, requiresMasking ? Easing.OutQuart : Easing.None)
|
||||
.OnComplete(_ => { sizableContainer.Masking = requiresMasking; });
|
||||
}
|
||||
|
||||
private class ScalingBackgroundScreen : BackgroundScreenDefault
|
||||
|
@ -23,6 +23,8 @@ namespace osu.Game.Skinning.Editor
|
||||
{
|
||||
public class SkinComponentToolbox : ScrollingToolboxGroup
|
||||
{
|
||||
public const float WIDTH = 200;
|
||||
|
||||
public Action<Type> RequestPlacement;
|
||||
|
||||
private const float component_display_scale = 0.8f;
|
||||
@ -41,7 +43,7 @@ namespace osu.Game.Skinning.Editor
|
||||
: base("Components", height)
|
||||
{
|
||||
RelativeSizeAxes = Axes.None;
|
||||
Width = 200;
|
||||
Width = WIDTH;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
|
@ -5,6 +5,7 @@ using JetBrains.Annotations;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics.Containers;
|
||||
@ -100,30 +101,14 @@ namespace osu.Game.Skinning.Editor
|
||||
{
|
||||
if (visibility.NewValue == Visibility.Visible)
|
||||
{
|
||||
updateMasking();
|
||||
target.AllowScaling = false;
|
||||
target.RelativePositionAxes = Axes.Both;
|
||||
|
||||
target.ScaleTo(VISIBLE_TARGET_SCALE, SkinEditor.TRANSITION_DURATION, Easing.OutQuint);
|
||||
target.MoveToX(0.095f, SkinEditor.TRANSITION_DURATION, Easing.OutQuint);
|
||||
target.SetCustomRect(new RectangleF(0.18f, 0.1f, VISIBLE_TARGET_SCALE, VISIBLE_TARGET_SCALE), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
target.AllowScaling = true;
|
||||
|
||||
target.ScaleTo(1, SkinEditor.TRANSITION_DURATION, Easing.OutQuint).OnComplete(_ => updateMasking());
|
||||
target.MoveToX(0f, SkinEditor.TRANSITION_DURATION, Easing.OutQuint);
|
||||
target.SetCustomRect(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMasking()
|
||||
{
|
||||
if (skinEditor == null)
|
||||
return;
|
||||
|
||||
target.Masking = skinEditor.State.Value == Visibility.Visible;
|
||||
}
|
||||
|
||||
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
||||
{
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user