2022-01-06 12:05:00 +00:00
|
|
|
// 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.Allocation;
|
2022-01-21 14:43:05 +00:00
|
|
|
using osu.Framework.Bindables;
|
2022-01-06 16:24:30 +00:00
|
|
|
using osu.Framework.Caching;
|
2022-01-06 14:08:50 +00:00
|
|
|
using osu.Framework.Extensions.EnumExtensions;
|
2022-01-06 12:05:00 +00:00
|
|
|
using osu.Framework.Graphics;
|
|
|
|
using osu.Framework.Graphics.Containers;
|
|
|
|
using osu.Framework.Graphics.Shapes;
|
|
|
|
using osu.Framework.Graphics.Sprites;
|
|
|
|
using osu.Framework.Input.Events;
|
2022-01-06 14:08:50 +00:00
|
|
|
using osu.Framework.Layout;
|
2022-01-06 12:05:00 +00:00
|
|
|
using osu.Game.Graphics;
|
2022-02-14 08:51:39 +00:00
|
|
|
using osu.Game.Graphics.Containers;
|
2022-01-06 12:05:00 +00:00
|
|
|
using osu.Game.Graphics.Sprites;
|
|
|
|
using osu.Game.Graphics.UserInterface;
|
|
|
|
using osuTK;
|
|
|
|
using osuTK.Graphics;
|
|
|
|
|
|
|
|
namespace osu.Game.Overlays
|
|
|
|
{
|
2022-01-21 14:43:05 +00:00
|
|
|
public class SettingsToolboxGroup : Container, IExpandable
|
2022-01-06 12:05:00 +00:00
|
|
|
{
|
2022-03-03 07:23:30 +00:00
|
|
|
public const int CONTAINER_WIDTH = 270;
|
|
|
|
|
2022-01-06 12:05:00 +00:00
|
|
|
private const float transition_duration = 250;
|
|
|
|
private const int border_thickness = 2;
|
|
|
|
private const int header_height = 30;
|
|
|
|
private const int corner_radius = 5;
|
|
|
|
|
2022-01-06 16:24:30 +00:00
|
|
|
private const float fade_duration = 800;
|
|
|
|
private const float inactive_alpha = 0.5f;
|
|
|
|
|
|
|
|
private readonly Cached headerTextVisibilityCache = new Cached();
|
|
|
|
|
2022-01-06 12:05:00 +00:00
|
|
|
private readonly FillFlowContainer content;
|
|
|
|
private readonly IconButton button;
|
|
|
|
|
2022-01-21 14:43:05 +00:00
|
|
|
public BindableBool Expanded { get; } = new BindableBool(true);
|
2022-01-06 12:05:00 +00:00
|
|
|
|
|
|
|
private Color4 expandedColour;
|
|
|
|
|
2022-01-06 14:08:50 +00:00
|
|
|
private readonly OsuSpriteText headerText;
|
|
|
|
|
2022-01-06 12:05:00 +00:00
|
|
|
/// <summary>
|
|
|
|
/// Create a new instance.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="title">The title to be displayed in the header of this group.</param>
|
2022-01-21 14:43:05 +00:00
|
|
|
public SettingsToolboxGroup(string title)
|
2022-01-06 12:05:00 +00:00
|
|
|
{
|
|
|
|
AutoSizeAxes = Axes.Y;
|
2022-03-03 07:23:30 +00:00
|
|
|
Width = CONTAINER_WIDTH;
|
2022-01-06 12:05:00 +00:00
|
|
|
Masking = true;
|
|
|
|
CornerRadius = corner_radius;
|
|
|
|
BorderColour = Color4.Black;
|
|
|
|
BorderThickness = border_thickness;
|
|
|
|
|
|
|
|
InternalChildren = new Drawable[]
|
|
|
|
{
|
|
|
|
new Box
|
|
|
|
{
|
|
|
|
RelativeSizeAxes = Axes.Both,
|
|
|
|
Colour = Color4.Black,
|
|
|
|
Alpha = 0.5f,
|
|
|
|
},
|
|
|
|
new FillFlowContainer
|
|
|
|
{
|
|
|
|
Direction = FillDirection.Vertical,
|
|
|
|
RelativeSizeAxes = Axes.X,
|
|
|
|
AutoSizeAxes = Axes.Y,
|
|
|
|
Children = new Drawable[]
|
|
|
|
{
|
|
|
|
new Container
|
|
|
|
{
|
|
|
|
Name = @"Header",
|
|
|
|
Origin = Anchor.TopCentre,
|
|
|
|
Anchor = Anchor.TopCentre,
|
|
|
|
RelativeSizeAxes = Axes.X,
|
|
|
|
Height = header_height,
|
|
|
|
Children = new Drawable[]
|
|
|
|
{
|
2022-01-06 14:08:50 +00:00
|
|
|
headerText = new OsuSpriteText
|
2022-01-06 12:05:00 +00:00
|
|
|
{
|
|
|
|
Origin = Anchor.CentreLeft,
|
|
|
|
Anchor = Anchor.CentreLeft,
|
|
|
|
Text = title.ToUpperInvariant(),
|
|
|
|
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 17),
|
2022-01-06 12:10:45 +00:00
|
|
|
Padding = new MarginPadding { Left = 10, Right = 30 },
|
2022-01-06 12:05:00 +00:00
|
|
|
},
|
|
|
|
button = new IconButton
|
|
|
|
{
|
|
|
|
Origin = Anchor.Centre,
|
|
|
|
Anchor = Anchor.CentreRight,
|
|
|
|
Position = new Vector2(-15, 0),
|
|
|
|
Icon = FontAwesome.Solid.Bars,
|
|
|
|
Scale = new Vector2(0.75f),
|
2022-01-21 14:43:05 +00:00
|
|
|
Action = () => Expanded.Toggle(),
|
2022-01-06 12:05:00 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
content = new FillFlowContainer
|
|
|
|
{
|
|
|
|
Name = @"Content",
|
|
|
|
Origin = Anchor.TopCentre,
|
|
|
|
Anchor = Anchor.TopCentre,
|
|
|
|
Direction = FillDirection.Vertical,
|
|
|
|
RelativeSizeAxes = Axes.X,
|
|
|
|
AutoSizeDuration = transition_duration,
|
|
|
|
AutoSizeEasing = Easing.OutQuint,
|
|
|
|
AutoSizeAxes = Axes.Y,
|
|
|
|
Padding = new MarginPadding(15),
|
|
|
|
Spacing = new Vector2(0, 15),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-05-06 10:39:09 +00:00
|
|
|
[BackgroundDependencyLoader]
|
|
|
|
private void load(OsuColour colours)
|
2022-01-06 16:24:30 +00:00
|
|
|
{
|
2022-05-06 10:39:09 +00:00
|
|
|
expandedColour = colours.Yellow;
|
2022-01-06 16:24:30 +00:00
|
|
|
}
|
|
|
|
|
2022-01-06 12:05:00 +00:00
|
|
|
protected override void LoadComplete()
|
|
|
|
{
|
|
|
|
base.LoadComplete();
|
Fix settings toolbox toggle button starting in incorrect state
While displaying replays, the colour of the toolbox toggle button would
not match the actual state of the rest of the toolbox, i.e. both buttons
would be white, even though the "playback settings" section was expanded
and as such should have a yellow toggle button.
In the case of the replay player, the failure scenario was as follows:
1. `SettingsToolboxGroup` calls `updateExpanded()` in its BDL to update
the initial state of the toolbox, including the toggle button
colour, by adding a colour fade transform.
2. An ancestor of both the toolbox groups - `PlayerSettingsOverlay`,
which is a `VisibilityContainer` - calls `FinishTransforms(true)` in
its `LoadCompleteAsync()`, therefore instantly applying the colour
from point (1) to the toggle button instantly.
3. However, `IconButton` inherits from `OsuAnimatedButton`. And
`OsuAnimatedButton` changes its colour in `LoadComplete()`, therefore
undoing the instant application from point (2).
This conjunction of circumstances is instrumental to reproducing the
bug, because if the `FinishTransforms(true)` call wasn't there, point
(3) wouldn't matter - the transform would get applied at some
indeterminate point in the future, ignoring the write from
`OsuAnimatedButton`.
As for the fix, move the `updateExpanded()` call in
`SettingsToolboxGroup` to `LoadComplete()` to avoid the above
unfortunate order. Applying initial visual state in `LoadComplete()` is
the idiomatic style of doing things these days anyhow.
2022-01-06 19:25:03 +00:00
|
|
|
|
2022-05-06 10:39:09 +00:00
|
|
|
Expanded.BindValueChanged(updateExpandedState, true);
|
2022-01-21 14:43:05 +00:00
|
|
|
|
2022-05-06 10:36:41 +00:00
|
|
|
this.Delay(600).Schedule(updateFadeState);
|
2022-01-06 12:05:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override bool OnHover(HoverEvent e)
|
|
|
|
{
|
2022-05-06 10:36:41 +00:00
|
|
|
updateFadeState();
|
2022-01-06 12:05:00 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override void OnHoverLost(HoverLostEvent e)
|
|
|
|
{
|
2022-05-06 10:36:41 +00:00
|
|
|
updateFadeState();
|
2022-01-06 12:05:00 +00:00
|
|
|
base.OnHoverLost(e);
|
|
|
|
}
|
|
|
|
|
2022-05-06 10:39:09 +00:00
|
|
|
protected override void Update()
|
2022-01-06 12:05:00 +00:00
|
|
|
{
|
2022-05-06 10:39:09 +00:00
|
|
|
base.Update();
|
|
|
|
|
|
|
|
if (!headerTextVisibilityCache.IsValid)
|
|
|
|
// These toolbox grouped may be contracted to only show icons.
|
|
|
|
// For now, let's hide the header to avoid text truncation weirdness in such cases.
|
|
|
|
headerText.FadeTo(headerText.DrawWidth < DrawWidth ? 1 : 0, 150, Easing.OutQuint);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source)
|
|
|
|
{
|
|
|
|
if (invalidation.HasFlagFast(Invalidation.DrawSize))
|
|
|
|
headerTextVisibilityCache.Invalidate();
|
|
|
|
|
|
|
|
return base.OnInvalidate(invalidation, source);
|
2022-01-06 12:05:00 +00:00
|
|
|
}
|
|
|
|
|
2022-05-06 10:39:09 +00:00
|
|
|
private void updateExpandedState(ValueChangedEvent<bool> expanded)
|
2022-05-06 10:36:41 +00:00
|
|
|
{
|
2022-05-06 10:39:09 +00:00
|
|
|
if (expanded.NewValue)
|
2022-05-06 10:36:41 +00:00
|
|
|
content.AutoSizeAxes = Axes.Y;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
content.AutoSizeAxes = Axes.None;
|
|
|
|
content.ResizeHeightTo(0, transition_duration, Easing.OutQuint);
|
|
|
|
}
|
|
|
|
|
2022-05-06 10:39:09 +00:00
|
|
|
button.FadeColour(expanded.NewValue ? expandedColour : Color4.White, 200, Easing.InOutQuint);
|
2022-05-06 10:36:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void updateFadeState()
|
2022-01-21 14:43:05 +00:00
|
|
|
{
|
2022-05-06 10:36:41 +00:00
|
|
|
this.FadeTo(IsHovered ? 1 : inactive_alpha, fade_duration, Easing.OutQuint);
|
2022-01-21 14:43:05 +00:00
|
|
|
}
|
2022-01-06 12:05:00 +00:00
|
|
|
|
|
|
|
protected override Container<Drawable> Content => content;
|
|
|
|
}
|
|
|
|
}
|