1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-17 12:22:55 +08:00

Integrate hotkey display into drawable menu items

This commit is contained in:
Bartłomiej Dach 2024-07-18 11:20:22 +02:00
parent 3c6c49187a
commit 3acc5fe5a0
No known key found for this signature in database
5 changed files with 82 additions and 47 deletions

View File

@ -3,6 +3,7 @@
#nullable disable
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
@ -20,12 +21,13 @@ namespace osu.Game.Graphics.UserInterface
{
public partial class DrawableOsuMenuItem : Menu.DrawableMenuItem
{
public const int MARGIN_HORIZONTAL = 17;
public const int MARGIN_HORIZONTAL = 10;
public const int MARGIN_VERTICAL = 4;
private const int text_size = 17;
private const int transition_length = 80;
private TextContainer text;
protected TextContainer Text { get; private set; }
private HotkeyDisplay hotkey;
private HoverClickSounds hoverClickSounds;
public DrawableOsuMenuItem(MenuItem item)
@ -39,32 +41,33 @@ namespace osu.Game.Graphics.UserInterface
BackgroundColour = Color4.Transparent;
BackgroundColourHover = Color4Extensions.FromHex(@"172023");
AddInternal(hotkey = new HotkeyDisplay
{
Alpha = 0,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
Margin = new MarginPadding { Right = 10, Top = 1 },
});
AddInternal(hoverClickSounds = new HoverClickSounds());
updateTextColour();
updateText();
bool hasSubmenu = Item.Items.Any();
// Only add right chevron if direction of menu items is vertical (i.e. width is relative size, see `DrawableMenuItem.SetFlowDirection()`).
if (hasSubmenu && RelativeSizeAxes == Axes.X)
if (showChevron)
{
AddInternal(new SpriteIcon
{
Margin = new MarginPadding(6),
Margin = new MarginPadding { Horizontal = 10, },
Size = new Vector2(8),
Icon = FontAwesome.Solid.ChevronRight,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
});
text.Padding = new MarginPadding
{
// Add some padding for the chevron above.
Right = 5,
};
}
}
// Only add right chevron if direction of menu items is vertical (i.e. width is relative size, see `DrawableMenuItem.SetFlowDirection()`).
private bool showChevron => Item.Items.Any() && RelativeSizeAxes == Axes.X;
protected override void LoadComplete()
{
base.LoadComplete();
@ -73,23 +76,39 @@ namespace osu.Game.Graphics.UserInterface
FinishTransforms();
}
private void updateTextColour()
private void updateText()
{
switch ((Item as OsuMenuItem)?.Type)
var osuMenuItem = Item as OsuMenuItem;
switch (osuMenuItem?.Type)
{
default:
case MenuItemType.Standard:
text.Colour = Color4.White;
Text.Colour = Color4.White;
break;
case MenuItemType.Destructive:
text.Colour = Color4.Red;
Text.Colour = Color4.Red;
break;
case MenuItemType.Highlighted:
text.Colour = Color4Extensions.FromHex(@"ffcc22");
Text.Colour = Color4Extensions.FromHex(@"ffcc22");
break;
}
hotkey.Hotkey = osuMenuItem?.Hotkey ?? default;
hotkey.Alpha = EqualityComparer<Hotkey>.Default.Equals(hotkey.Hotkey, default) ? 0 : 1;
}
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
// this hack ensures that the menu can auto-size while leaving enough space for the hotkey display.
// the gist of it is that while the hotkey display is not in the text / "content" that determines sizing
// (because it cannot be, because we want the hotkey display to align to the *right* and not the left),
// enough padding to fit the hotkey with _its_ spacing is added as padding of the text to compensate.
Text.Padding = new MarginPadding { Right = hotkey.Alpha > 0 || showChevron ? hotkey.DrawWidth + 15 : 0 };
}
protected override bool OnHover(HoverEvent e)
@ -111,20 +130,20 @@ namespace osu.Game.Graphics.UserInterface
if (IsHovered && IsActionable)
{
text.BoldText.FadeIn(transition_length, Easing.OutQuint);
text.NormalText.FadeOut(transition_length, Easing.OutQuint);
Text.BoldText.FadeIn(transition_length, Easing.OutQuint);
Text.NormalText.FadeOut(transition_length, Easing.OutQuint);
}
else
{
text.BoldText.FadeOut(transition_length, Easing.OutQuint);
text.NormalText.FadeIn(transition_length, Easing.OutQuint);
Text.BoldText.FadeOut(transition_length, Easing.OutQuint);
Text.NormalText.FadeIn(transition_length, Easing.OutQuint);
}
}
protected sealed override Drawable CreateContent() => text = CreateTextContainer();
protected sealed override Drawable CreateContent() => Text = CreateTextContainer();
protected virtual TextContainer CreateTextContainer() => new TextContainer();
protected partial class TextContainer : FillFlowContainer, IHasText
protected partial class TextContainer : Container, IHasText
{
public LocalisableString Text
{
@ -138,39 +157,53 @@ namespace osu.Game.Graphics.UserInterface
public readonly SpriteText NormalText;
public readonly SpriteText BoldText;
public readonly Container CheckboxContainer;
public TextContainer()
{
Anchor = Anchor.CentreLeft;
Origin = Anchor.CentreLeft;
AutoSizeAxes = Axes.Both;
Spacing = new Vector2(10);
Direction = FillDirection.Horizontal;
Child = new Container
Child = new FillFlowContainer
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
AutoSizeAxes = Axes.Both,
Margin = new MarginPadding { Horizontal = MARGIN_HORIZONTAL, Vertical = MARGIN_VERTICAL },
Spacing = new Vector2(10),
Direction = FillDirection.Horizontal,
Padding = new MarginPadding { Horizontal = MARGIN_HORIZONTAL, Vertical = MARGIN_VERTICAL, },
Children = new Drawable[]
{
NormalText = new OsuSpriteText
CheckboxContainer = new Container
{
AlwaysPresent = true, // ensures that the menu item does not change width when switching between normal and bold text.
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: text_size),
RelativeSizeAxes = Axes.Y,
Width = MARGIN_HORIZONTAL,
},
BoldText = new OsuSpriteText
new Container
{
AlwaysPresent = true, // ensures that the menu item does not change width when switching between normal and bold text.
Alpha = 0,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold),
}
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
NormalText = new OsuSpriteText
{
AlwaysPresent = true, // ensures that the menu item does not change width when switching between normal and bold text.
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: text_size),
},
BoldText = new OsuSpriteText
{
AlwaysPresent = true, // ensures that the menu item does not change width when switching between normal and bold text.
Alpha = 0,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold),
}
}
},
}
};
}

View File

@ -46,12 +46,11 @@ namespace osu.Game.Graphics.UserInterface
state = menuItem.State.GetBoundCopy();
Add(stateIcon = new SpriteIcon
CheckboxContainer.Add(stateIcon = new SpriteIcon
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Size = new Vector2(10),
Margin = new MarginPadding { Left = -MARGIN_HORIZONTAL, Right = MARGIN_HORIZONTAL },
AlwaysPresent = true,
});
}

View File

@ -109,7 +109,7 @@ namespace osu.Game.Graphics.UserInterface
Colour = BackgroundColourHover,
RelativeSizeAxes = Axes.X,
Height = 2f,
Width = 0.8f,
Width = 0.9f,
});
}

View File

@ -11,6 +11,8 @@ namespace osu.Game.Graphics.UserInterface
{
public readonly MenuItemType Type;
public Hotkey Hotkey { get; init; }
public OsuMenuItem(LocalisableString text, MenuItemType type = MenuItemType.Standard)
: this(text, type, null)
{

View File

@ -92,6 +92,7 @@ namespace osu.Game.Screens.Edit.Components.Menus
BackgroundColour = colourProvider.Background2;
ForegroundColourHover = colourProvider.Content1;
BackgroundColourHover = colourProvider.Background1;
Text.CheckboxContainer.Alpha = 0;
}
protected override void LoadComplete()