mirror of
https://github.com/ppy/osu.git
synced 2025-03-11 06:37:19 +08:00
Abstractify beatmap panel piece and update all panel implementations
This commit is contained in:
parent
ecc3aeadf2
commit
134e62c39a
@ -6,13 +6,9 @@ using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
@ -25,7 +21,6 @@ using osu.Game.Resources.Localisation.Web;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
@ -33,36 +28,23 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
public const float HEIGHT = CarouselItem.DEFAULT_HEIGHT;
|
||||
|
||||
private const float colour_box_width = 30;
|
||||
private const float corner_radius = 10;
|
||||
|
||||
// todo: this should be replaced with information from CarouselItem about how deep is BeatmapPanel in the carousel
|
||||
// (i.e. whether it's under a beatmap set that's under a group, or just under a top-level beatmap set).
|
||||
private const float difficulty_x_offset = 100f; // constant X offset for beatmap difficulty panels specifically.
|
||||
|
||||
private const float preselected_x_offset = 25f;
|
||||
private const float selected_x_offset = 50f;
|
||||
|
||||
private const float duration = 500;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapCarousel? carousel { get; set; }
|
||||
|
||||
[Resolved]
|
||||
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private IBindable<IReadOnlyList<Mod>> mods { get; set; } = null!;
|
||||
|
||||
private Container panel = null!;
|
||||
private CarouselPanelPiece panel = null!;
|
||||
private StarCounter starCounter = null!;
|
||||
private ConstrainedIconContainer iconContainer = null!;
|
||||
private Box hoverLayer = null!;
|
||||
private Box activationFlash = null!;
|
||||
|
||||
private Box backgroundBorder = null!;
|
||||
|
||||
private ConstrainedIconContainer difficultyIcon = null!;
|
||||
private OsuSpriteText keyCountText = null!;
|
||||
private StarRatingDisplay starRatingDisplay = null!;
|
||||
private TopLocalRankV2 difficultyRank = null!;
|
||||
private OsuSpriteText difficultyText = null!;
|
||||
private OsuSpriteText authorText = null!;
|
||||
|
||||
private IBindable<StarDifficulty?>? starDifficultyBindable;
|
||||
private CancellationTokenSource? starDifficultyCancellationSource;
|
||||
|
||||
[Resolved]
|
||||
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||
@ -73,16 +55,24 @@ namespace osu.Game.Screens.SelectV2
|
||||
[Resolved]
|
||||
private BeatmapDifficultyCache difficultyCache { get; set; } = null!;
|
||||
|
||||
private OsuSpriteText keyCountText = null!;
|
||||
[Resolved]
|
||||
private BeatmapCarousel? carousel { get; set; }
|
||||
|
||||
private IBindable<StarDifficulty?>? starDifficultyBindable;
|
||||
private CancellationTokenSource? starDifficultyCancellationSource;
|
||||
[Resolved]
|
||||
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
|
||||
|
||||
private Container rightContainer = null!;
|
||||
private Box starRatingGradient = null!;
|
||||
private TopLocalRankV2 difficultyRank = null!;
|
||||
private OsuSpriteText difficultyText = null!;
|
||||
private OsuSpriteText authorText = null!;
|
||||
[Resolved]
|
||||
private IBindable<IReadOnlyList<Mod>> mods { get; set; } = null!;
|
||||
|
||||
protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos)
|
||||
{
|
||||
var inputRectangle = panel.TopLevelContent.DrawRectangle;
|
||||
|
||||
// Cover the gaps introduced by the spacing between BeatmapPanels.
|
||||
inputRectangle = inputRectangle.Inflate(new MarginPadding { Vertical = BeatmapCarousel.SPACING / 2f });
|
||||
|
||||
return inputRectangle.Contains(panel.TopLevelContent.ToLocalSpace(screenSpacePos));
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colourProvider)
|
||||
@ -94,67 +84,21 @@ namespace osu.Game.Screens.SelectV2
|
||||
Width = 1f;
|
||||
Height = HEIGHT;
|
||||
|
||||
InternalChild = panel = new Container
|
||||
InternalChild = panel = new CarouselPanelPiece(difficulty_x_offset)
|
||||
{
|
||||
Masking = true,
|
||||
CornerRadius = corner_radius,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
X = corner_radius,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
Icon = difficultyIcon = new ConstrainedIconContainer
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Offset = new Vector2(1f),
|
||||
Radius = 10,
|
||||
Size = new Vector2(20),
|
||||
Margin = new MarginPadding { Horizontal = 5f },
|
||||
Colour = colourProvider.Background5,
|
||||
},
|
||||
Children = new Drawable[]
|
||||
Children = new[]
|
||||
{
|
||||
new BufferedContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
backgroundBorder = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colours.ForStarDifficulty(0),
|
||||
EdgeSmoothness = new Vector2(2, 0),
|
||||
},
|
||||
rightContainer = new Container
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Masking = true,
|
||||
CornerRadius = corner_radius,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = HEIGHT,
|
||||
X = colour_box_width,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = ColourInfo.GradientHorizontal(colourProvider.Background3, colourProvider.Background4),
|
||||
},
|
||||
starRatingGradient = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Alpha = 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
iconContainer = new ConstrainedIconContainer
|
||||
{
|
||||
X = colour_box_width / 2,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Size = new Vector2(20),
|
||||
Colour = colourProvider.Background5,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Padding = new MarginPadding { Top = 8, Left = colour_box_width + corner_radius },
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Padding = new MarginPadding { Left = 10f },
|
||||
Direction = FillDirection.Vertical,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
@ -216,34 +160,10 @@ namespace osu.Game.Screens.SelectV2
|
||||
}
|
||||
}
|
||||
},
|
||||
hoverLayer = new Box
|
||||
{
|
||||
Colour = colours.Blue.Opacity(0.1f),
|
||||
Alpha = 0,
|
||||
Blending = BlendingParameters.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
activationFlash = new Box
|
||||
{
|
||||
Blending = BlendingParameters.Additive,
|
||||
Alpha = 0f,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new HoverSounds(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos)
|
||||
{
|
||||
var inputRectangle = panel.DrawRectangle;
|
||||
|
||||
// Cover the gaps introduced by the spacing between BeatmapPanels.
|
||||
inputRectangle = inputRectangle.Inflate(new MarginPadding { Vertical = BeatmapCarousel.SPACING / 2f });
|
||||
|
||||
return inputRectangle.Contains(panel.ToLocalSpace(screenSpacePos));
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
@ -260,8 +180,8 @@ namespace osu.Game.Screens.SelectV2
|
||||
updateKeyCount();
|
||||
}, true);
|
||||
|
||||
Selected.BindValueChanged(_ => updateSelectionDisplay(), true);
|
||||
KeyboardSelected.BindValueChanged(_ => updateKeyboardSelectedDisplay(), true);
|
||||
Selected.BindValueChanged(s => panel.Active.Value = s.NewValue, true);
|
||||
KeyboardSelected.BindValueChanged(k => panel.KeyboardActive.Value = k.NewValue, true);
|
||||
}
|
||||
|
||||
protected override void PrepareForUse()
|
||||
@ -271,63 +191,25 @@ namespace osu.Game.Screens.SelectV2
|
||||
Debug.Assert(Item != null);
|
||||
var beatmap = (BeatmapInfo)Item.Model;
|
||||
|
||||
iconContainer.Icon = beatmap.Ruleset.CreateInstance().CreateIcon();
|
||||
difficultyIcon.Icon = beatmap.Ruleset.CreateInstance().CreateIcon();
|
||||
|
||||
difficultyRank.Beatmap = beatmap;
|
||||
difficultyText.Text = beatmap.DifficultyName;
|
||||
authorText.Text = BeatmapsetsStrings.ShowDetailsMappedBy(beatmap.Metadata.Author.Username);
|
||||
|
||||
starDifficultyBindable = null;
|
||||
|
||||
computeStarRating();
|
||||
updateKeyCount();
|
||||
|
||||
updateSelectionDisplay();
|
||||
FinishTransforms(true);
|
||||
|
||||
this.FadeInFromZero(duration, Easing.OutQuint);
|
||||
|
||||
// todo: only do this when visible.
|
||||
// starCounter.ReplayAnimation();
|
||||
}
|
||||
|
||||
private void updateSelectionDisplay()
|
||||
protected override void FreeAfterUse()
|
||||
{
|
||||
bool selected = Selected.Value;
|
||||
base.FreeAfterUse();
|
||||
|
||||
rightContainer.ResizeHeightTo(selected ? HEIGHT - 4 : HEIGHT, duration, Easing.OutQuint);
|
||||
|
||||
updatePanelPosition();
|
||||
updateEdgeEffectColour();
|
||||
}
|
||||
|
||||
private void updateKeyboardSelectedDisplay()
|
||||
{
|
||||
updatePanelPosition();
|
||||
updateHover();
|
||||
}
|
||||
|
||||
private void updatePanelPosition()
|
||||
{
|
||||
float x = difficulty_x_offset + selected_x_offset + preselected_x_offset;
|
||||
|
||||
if (Selected.Value)
|
||||
x -= selected_x_offset;
|
||||
|
||||
if (KeyboardSelected.Value)
|
||||
x -= preselected_x_offset;
|
||||
|
||||
this.TransformTo(nameof(Padding), new MarginPadding { Left = x }, duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void updateHover()
|
||||
{
|
||||
bool hovered = IsHovered || KeyboardSelected.Value;
|
||||
|
||||
if (hovered)
|
||||
hoverLayer.FadeIn(100, Easing.OutQuint);
|
||||
else
|
||||
hoverLayer.FadeOut(1000, Easing.OutQuint);
|
||||
difficultyRank.Beatmap = null;
|
||||
starDifficultyBindable = null;
|
||||
}
|
||||
|
||||
private void computeStarRating()
|
||||
@ -341,34 +223,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
var beatmap = (BeatmapInfo)Item.Model;
|
||||
|
||||
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmap, starDifficultyCancellationSource.Token);
|
||||
starDifficultyBindable.BindValueChanged(d =>
|
||||
{
|
||||
var value = d.NewValue ?? default;
|
||||
|
||||
starRatingDisplay.Current.Value = value;
|
||||
starCounter.Current = (float)value.Stars;
|
||||
|
||||
iconContainer.FadeColour(value.Stars > 6.5f ? colours.Orange1 : colourProvider.Background5, duration, Easing.OutQuint);
|
||||
|
||||
var starRatingColour = colours.ForStarDifficulty(value.Stars);
|
||||
|
||||
backgroundBorder.FadeColour(starRatingColour, duration, Easing.OutQuint);
|
||||
starCounter.FadeColour(starRatingColour, duration, Easing.OutQuint);
|
||||
starRatingGradient.FadeColour(ColourInfo.GradientHorizontal(starRatingColour.Opacity(0.25f), starRatingColour.Opacity(0)), duration, Easing.OutQuint);
|
||||
starRatingGradient.FadeIn(duration, Easing.OutQuint);
|
||||
|
||||
// todo: this doesn't work for dark star rating colours, still not sure how to fix.
|
||||
activationFlash.FadeColour(starRatingColour, duration, Easing.OutQuint);
|
||||
|
||||
updateEdgeEffectColour();
|
||||
}, true);
|
||||
}
|
||||
|
||||
private void updateEdgeEffectColour()
|
||||
{
|
||||
panel.FadeEdgeEffectTo(Selected.Value
|
||||
? colours.ForStarDifficulty(starDifficultyBindable?.Value?.Stars ?? 0f).Opacity(0.5f)
|
||||
: Color4.Black.Opacity(0.4f), duration, Easing.OutQuint);
|
||||
starDifficultyBindable.BindValueChanged(_ => updateDisplay(), true);
|
||||
}
|
||||
|
||||
private void updateKeyCount()
|
||||
@ -392,16 +247,18 @@ namespace osu.Game.Screens.SelectV2
|
||||
keyCountText.Alpha = 0;
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
private void updateDisplay()
|
||||
{
|
||||
updateHover();
|
||||
return true;
|
||||
}
|
||||
var starDifficulty = starDifficultyBindable?.Value ?? default;
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
updateHover();
|
||||
base.OnHoverLost(e);
|
||||
starRatingDisplay.Current.Value = starDifficulty;
|
||||
starCounter.Current = (float)starDifficulty.Stars;
|
||||
|
||||
difficultyIcon.FadeColour(starDifficulty.Stars > 6.5f ? colours.Orange1 : colourProvider.Background5, duration, Easing.OutQuint);
|
||||
|
||||
var starRatingColour = colours.ForStarDifficulty(starDifficulty.Stars);
|
||||
starCounter.FadeColour(starRatingColour, duration, Easing.OutQuint);
|
||||
panel.AccentColour = starRatingColour;
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
@ -430,7 +287,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
|
||||
public void Activated()
|
||||
{
|
||||
activationFlash.FadeOutFromOne(500, Easing.OutQuint);
|
||||
panel.Flash();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -6,12 +6,9 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
@ -19,10 +16,8 @@ using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
@ -30,18 +25,22 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
public const float HEIGHT = CarouselItem.DEFAULT_HEIGHT * 1.6f;
|
||||
|
||||
private const float arrow_container_width = 20;
|
||||
private const float corner_radius = 10;
|
||||
|
||||
// todo: this should be replaced with information from CarouselItem about how deep is BeatmapPanel in the carousel
|
||||
// (i.e. whether it's under a beatmap set that's under a group, or just under a top-level beatmap set).
|
||||
private const float set_x_offset = 20f; // constant X offset for beatmap set/standalone panels specifically.
|
||||
|
||||
private const float preselected_x_offset = 25f;
|
||||
private const float expanded_x_offset = 50f;
|
||||
|
||||
private const float duration = 500;
|
||||
|
||||
private CarouselPanelPiece panel = null!;
|
||||
private BeatmapSetPanelBackground background = null!;
|
||||
|
||||
private OsuSpriteText titleText = null!;
|
||||
private OsuSpriteText artistText = null!;
|
||||
private Drawable chevronIcon = null!;
|
||||
private UpdateBeatmapSetButtonV2 updateButton = null!;
|
||||
private BeatmapSetOnlineStatusPill statusPill = null!;
|
||||
private DifficultySpectrumDisplay difficultiesDisplay = null!;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapCarousel? carousel { get; set; }
|
||||
|
||||
@ -51,22 +50,15 @@ namespace osu.Game.Screens.SelectV2
|
||||
[Resolved]
|
||||
private BeatmapManager beatmaps { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private OsuColour colours { get; set; } = null!;
|
||||
protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos)
|
||||
{
|
||||
var inputRectangle = panel.TopLevelContent.DrawRectangle;
|
||||
|
||||
private Container panel = null!;
|
||||
private Box backgroundBorder = null!;
|
||||
private BeatmapSetPanelBackground background = null!;
|
||||
private Container backgroundContainer = null!;
|
||||
private FillFlowContainer mainFlowContainer = null!;
|
||||
private SpriteIcon chevronIcon = null!;
|
||||
private Box hoverLayer = null!;
|
||||
// Cover a gap introduced by the spacing between a BeatmapSetPanel and a BeatmapPanel either above it or below it.
|
||||
inputRectangle = inputRectangle.Inflate(new MarginPadding { Vertical = BeatmapCarousel.SPACING / 2f });
|
||||
|
||||
private OsuSpriteText titleText = null!;
|
||||
private OsuSpriteText artistText = null!;
|
||||
private UpdateBeatmapSetButtonV2 updateButton = null!;
|
||||
private BeatmapSetOnlineStatusPill statusPill = null!;
|
||||
private DifficultySpectrumDisplay difficultiesDisplay = null!;
|
||||
return inputRectangle.Contains(panel.TopLevelContent.ToLocalSpace(screenSpacePos));
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
@ -76,137 +68,89 @@ namespace osu.Game.Screens.SelectV2
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = HEIGHT;
|
||||
|
||||
InternalChild = panel = new Container
|
||||
InternalChild = panel = new CarouselPanelPiece(set_x_offset)
|
||||
{
|
||||
Masking = true,
|
||||
CornerRadius = corner_radius,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
X = corner_radius,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
Icon = chevronIcon = new Container
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Radius = 10,
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new BufferedContainer
|
||||
Size = new Vector2(22),
|
||||
Child = new SpriteIcon
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
backgroundBorder = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Alpha = 0,
|
||||
EdgeSmoothness = new Vector2(2, 0),
|
||||
},
|
||||
backgroundContainer = new Container
|
||||
{
|
||||
Masking = true,
|
||||
CornerRadius = corner_radius,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
MaskingSmoothness = 2,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
background = new BeatmapSetPanelBackground
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
chevronIcon = new SpriteIcon
|
||||
{
|
||||
X = arrow_container_width / 2,
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Icon = FontAwesome.Solid.ChevronRight,
|
||||
Size = new Vector2(12),
|
||||
X = 1f,
|
||||
Colour = colourProvider.Background5,
|
||||
},
|
||||
mainFlowContainer = new FillFlowContainer
|
||||
},
|
||||
Background = background = new BeatmapSetPanelBackground
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Padding = new MarginPadding { Top = 7.5f, Left = 15, Bottom = 5 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Padding = new MarginPadding { Top = 7.5f, Left = 15, Bottom = 5 },
|
||||
Children = new Drawable[]
|
||||
titleText = new OsuSpriteText
|
||||
{
|
||||
titleText = new OsuSpriteText
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22, italics: true),
|
||||
},
|
||||
artistText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 17, italics: true),
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Horizontal,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding { Top = 5f },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22, italics: true),
|
||||
Shadow = true,
|
||||
},
|
||||
artistText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 17, italics: true),
|
||||
Shadow = true,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Horizontal,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding { Top = 5f },
|
||||
Children = new Drawable[]
|
||||
updateButton = new UpdateBeatmapSetButtonV2
|
||||
{
|
||||
updateButton = new UpdateBeatmapSetButtonV2
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding { Right = 5f, Top = -2f },
|
||||
},
|
||||
statusPill = new BeatmapSetOnlineStatusPill
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
TextSize = 11,
|
||||
TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 },
|
||||
Margin = new MarginPadding { Right = 5f },
|
||||
},
|
||||
difficultiesDisplay = new DifficultySpectrumDisplay
|
||||
{
|
||||
DotSize = new Vector2(5, 10),
|
||||
DotSpacing = 2,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
},
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding { Right = 5f, Top = -2f },
|
||||
},
|
||||
}
|
||||
statusPill = new BeatmapSetOnlineStatusPill
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
TextSize = 11,
|
||||
TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 },
|
||||
Margin = new MarginPadding { Right = 5f },
|
||||
},
|
||||
difficultiesDisplay = new DifficultySpectrumDisplay
|
||||
{
|
||||
DotSize = new Vector2(5, 10),
|
||||
DotSpacing = 2,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
hoverLayer = new Box
|
||||
{
|
||||
Colour = colours.Blue.Opacity(0.1f),
|
||||
Alpha = 0,
|
||||
Blending = BlendingParameters.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new HoverSounds(),
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos)
|
||||
{
|
||||
var inputRectangle = panel.DrawRectangle;
|
||||
|
||||
// Cover a gap introduced by the spacing between a BeatmapSetPanel and a BeatmapPanel either above it or below it.
|
||||
inputRectangle = inputRectangle.Inflate(new MarginPadding { Vertical = BeatmapCarousel.SPACING / 2f });
|
||||
|
||||
return inputRectangle.Contains(panel.ToLocalSpace(screenSpacePos));
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Expanded.BindValueChanged(_ => updateExpandedDisplay(), true);
|
||||
KeyboardSelected.BindValueChanged(_ => updateKeyboardSelectedDisplay(), true);
|
||||
Expanded.BindValueChanged(_ => onExpanded(), true);
|
||||
KeyboardSelected.BindValueChanged(k => panel.KeyboardActive.Value = k.NewValue, true);
|
||||
}
|
||||
|
||||
private void onExpanded()
|
||||
{
|
||||
panel.Active.Value = Expanded.Value;
|
||||
chevronIcon.ResizeWidthTo(Expanded.Value ? 22 : 0f, duration, Easing.OutQuint);
|
||||
chevronIcon.FadeTo(Expanded.Value ? 1f : 0f, duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PrepareForUse()
|
||||
@ -226,9 +170,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
statusPill.Status = beatmapSet.Status;
|
||||
difficultiesDisplay.BeatmapSet = beatmapSet;
|
||||
|
||||
updateExpandedDisplay();
|
||||
FinishTransforms(true);
|
||||
|
||||
this.FadeInFromZero(duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
@ -241,70 +183,6 @@ namespace osu.Game.Screens.SelectV2
|
||||
difficultiesDisplay.BeatmapSet = null;
|
||||
}
|
||||
|
||||
private void updateExpandedDisplay()
|
||||
{
|
||||
if (Item == null)
|
||||
return;
|
||||
|
||||
updatePanelPosition();
|
||||
|
||||
backgroundBorder.RelativeSizeAxes = Expanded.Value ? Axes.Both : Axes.Y;
|
||||
backgroundBorder.Width = Expanded.Value ? 1 : arrow_container_width + corner_radius;
|
||||
backgroundBorder.FadeTo(Expanded.Value ? 1 : 0, duration, Easing.OutQuint);
|
||||
chevronIcon.FadeTo(Expanded.Value ? 1 : 0, duration, Easing.OutQuint);
|
||||
|
||||
backgroundContainer.ResizeHeightTo(Expanded.Value ? HEIGHT - 4 : HEIGHT, duration, Easing.OutQuint);
|
||||
backgroundContainer.MoveToX(Expanded.Value ? arrow_container_width : 0, duration, Easing.OutQuint);
|
||||
mainFlowContainer.MoveToX(Expanded.Value ? arrow_container_width : 0, duration, Easing.OutQuint);
|
||||
|
||||
panel.EdgeEffect = panel.EdgeEffect with { Radius = Expanded.Value ? 15 : 10 };
|
||||
|
||||
panel.FadeEdgeEffectTo(Expanded.Value
|
||||
? Color4Extensions.FromHex(@"4EBFFF").Opacity(0.5f)
|
||||
: Color4.Black.Opacity(0.4f), duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void updateKeyboardSelectedDisplay()
|
||||
{
|
||||
updatePanelPosition();
|
||||
updateHover();
|
||||
}
|
||||
|
||||
private void updatePanelPosition()
|
||||
{
|
||||
float x = set_x_offset + expanded_x_offset + preselected_x_offset;
|
||||
|
||||
if (Expanded.Value)
|
||||
x -= expanded_x_offset;
|
||||
|
||||
if (KeyboardSelected.Value)
|
||||
x -= preselected_x_offset;
|
||||
|
||||
this.TransformTo(nameof(Padding), new MarginPadding { Left = x }, duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void updateHover()
|
||||
{
|
||||
bool hovered = IsHovered || KeyboardSelected.Value;
|
||||
|
||||
if (hovered)
|
||||
hoverLayer.FadeIn(100, Easing.OutQuint);
|
||||
else
|
||||
hoverLayer.FadeOut(1000, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
updateHover();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
updateHover();
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
if (carousel != null)
|
||||
|
@ -8,12 +8,9 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Beatmaps;
|
||||
@ -21,13 +18,11 @@ using osu.Game.Beatmaps.Drawables;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
@ -35,15 +30,9 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
public const float HEIGHT = CarouselItem.DEFAULT_HEIGHT * 1.6f;
|
||||
|
||||
private const float difficulty_icon_container_width = 30;
|
||||
private const float corner_radius = 10;
|
||||
|
||||
// todo: this should be replaced with information from CarouselItem about how deep is BeatmapPanel in the carousel
|
||||
// (i.e. whether it's under a beatmap set that's under a group, or just under a top-level beatmap set).
|
||||
private const float set_x_offset = 20f; // constant X offset for beatmap set/standalone panels specifically.
|
||||
|
||||
private const float preselected_x_offset = 25f;
|
||||
private const float selected_x_offset = 50f;
|
||||
private const float standalone_x_offset = 20f; // constant X offset for beatmap set/standalone panels specifically.
|
||||
|
||||
private const float duration = 500;
|
||||
|
||||
@ -71,12 +60,8 @@ namespace osu.Game.Screens.SelectV2
|
||||
private IBindable<StarDifficulty?>? starDifficultyBindable;
|
||||
private CancellationTokenSource? starDifficultyCancellationSource;
|
||||
|
||||
private Container panel = null!;
|
||||
private Box backgroundBorder = null!;
|
||||
private CarouselPanelPiece panel = null!;
|
||||
private BeatmapSetPanelBackground background = null!;
|
||||
private Container backgroundContainer = null!;
|
||||
private FillFlowContainer mainFlowContainer = null!;
|
||||
private Box hoverLayer = null!;
|
||||
|
||||
private OsuSpriteText titleText = null!;
|
||||
private OsuSpriteText artistText = null!;
|
||||
@ -91,6 +76,16 @@ namespace osu.Game.Screens.SelectV2
|
||||
private OsuSpriteText difficultyName = null!;
|
||||
private OsuSpriteText difficultyAuthor = null!;
|
||||
|
||||
protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos)
|
||||
{
|
||||
var inputRectangle = panel.TopLevelContent.DrawRectangle;
|
||||
|
||||
// Cover a gap introduced by the spacing between a BeatmapSetPanel and a BeatmapPanel either above it or below it.
|
||||
inputRectangle = inputRectangle.Inflate(new MarginPadding { Vertical = BeatmapCarousel.SPACING / 2f });
|
||||
|
||||
return inputRectangle.Contains(panel.TopLevelContent.ToLocalSpace(screenSpacePos));
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@ -100,167 +95,109 @@ namespace osu.Game.Screens.SelectV2
|
||||
Width = 1f;
|
||||
Height = HEIGHT;
|
||||
|
||||
InternalChild = panel = new Container
|
||||
InternalChild = panel = new CarouselPanelPiece(standalone_x_offset)
|
||||
{
|
||||
Masking = true,
|
||||
CornerRadius = corner_radius,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
X = corner_radius,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
Icon = difficultyIcon = new ConstrainedIconContainer
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Radius = 10,
|
||||
Size = new Vector2(20),
|
||||
Margin = new MarginPadding { Horizontal = 5f },
|
||||
Colour = colourProvider.Background5,
|
||||
},
|
||||
Children = new Drawable[]
|
||||
Background = background = new BeatmapSetPanelBackground
|
||||
{
|
||||
new BufferedContainer
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
Child = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Padding = new MarginPadding { Top = 7.5f, Left = 15, Bottom = 5 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
titleText = new OsuSpriteText
|
||||
{
|
||||
backgroundBorder = new Box
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22, italics: true),
|
||||
Shadow = true,
|
||||
},
|
||||
artistText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 17, italics: true),
|
||||
Shadow = true,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Horizontal,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding { Top = 5f },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Alpha = 0,
|
||||
EdgeSmoothness = new Vector2(2, 0),
|
||||
},
|
||||
backgroundContainer = new Container
|
||||
{
|
||||
Masking = true,
|
||||
CornerRadius = corner_radius,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
MaskingSmoothness = 2,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Children = new Drawable[]
|
||||
updateButton = new UpdateBeatmapSetButtonV2
|
||||
{
|
||||
background = new BeatmapSetPanelBackground
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding { Right = 5f, Top = -2f },
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
difficultyIcon = new ConstrainedIconContainer
|
||||
{
|
||||
X = difficulty_icon_container_width / 2,
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Size = new Vector2(20),
|
||||
},
|
||||
mainFlowContainer = new FillFlowContainer
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Vertical,
|
||||
Padding = new MarginPadding { Top = 7.5f, Left = 15, Bottom = 5 },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
titleText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 22, italics: true),
|
||||
Shadow = true,
|
||||
},
|
||||
artistText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 17, italics: true),
|
||||
Shadow = true,
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Horizontal,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Margin = new MarginPadding { Top = 5f },
|
||||
Children = new Drawable[]
|
||||
statusPill = new BeatmapSetOnlineStatusPill
|
||||
{
|
||||
updateButton = new UpdateBeatmapSetButtonV2
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
TextSize = 11,
|
||||
TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 },
|
||||
Margin = new MarginPadding { Right = 5f },
|
||||
},
|
||||
difficultyLine = new FillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Horizontal,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding { Right = 5f, Top = -2f },
|
||||
},
|
||||
statusPill = new BeatmapSetOnlineStatusPill
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
TextSize = 11,
|
||||
TextPadding = new MarginPadding { Horizontal = 8, Vertical = 2 },
|
||||
Margin = new MarginPadding { Right = 5f },
|
||||
},
|
||||
difficultyLine = new FillFlowContainer
|
||||
{
|
||||
Direction = FillDirection.Horizontal,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
difficultyStarRating = new StarRatingDisplay(default, StarRatingDisplaySize.Small)
|
||||
{
|
||||
difficultyStarRating = new StarRatingDisplay(default, StarRatingDisplaySize.Small)
|
||||
{
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Scale = new Vector2(8f / 9f),
|
||||
Margin = new MarginPadding { Right = 5f },
|
||||
},
|
||||
difficultyRank = new TopLocalRankV2
|
||||
{
|
||||
Scale = new Vector2(8f / 11),
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding { Right = 5f },
|
||||
},
|
||||
difficultyKeyCountText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold),
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Alpha = 0,
|
||||
Margin = new MarginPadding { Bottom = 2f },
|
||||
},
|
||||
difficultyName = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold),
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Margin = new MarginPadding { Right = 5f, Bottom = 2f },
|
||||
},
|
||||
difficultyAuthor = new OsuSpriteText
|
||||
{
|
||||
Colour = colourProvider.Content2,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.SemiBold),
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Margin = new MarginPadding { Right = 5f, Bottom = 2f },
|
||||
}
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Scale = new Vector2(8f / 9f),
|
||||
Margin = new MarginPadding { Right = 5f },
|
||||
},
|
||||
difficultyRank = new TopLocalRankV2
|
||||
{
|
||||
Scale = new Vector2(8f / 11),
|
||||
Origin = Anchor.CentreLeft,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Margin = new MarginPadding { Right = 5f },
|
||||
},
|
||||
difficultyKeyCountText = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold),
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Origin = Anchor.BottomLeft,
|
||||
Alpha = 0,
|
||||
Margin = new MarginPadding { Bottom = 2f },
|
||||
},
|
||||
difficultyName = new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold),
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Margin = new MarginPadding { Right = 5f, Bottom = 2f },
|
||||
},
|
||||
difficultyAuthor = new OsuSpriteText
|
||||
{
|
||||
Colour = colourProvider.Content2,
|
||||
Font = OsuFont.GetFont(weight: FontWeight.SemiBold),
|
||||
Origin = Anchor.BottomLeft,
|
||||
Anchor = Anchor.BottomLeft,
|
||||
Margin = new MarginPadding { Right = 5f, Bottom = 2f },
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
hoverLayer = new Box
|
||||
{
|
||||
Colour = colours.Blue.Opacity(0.1f),
|
||||
Alpha = 0,
|
||||
Blending = BlendingParameters.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new HoverSounds(),
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos)
|
||||
{
|
||||
var inputRectangle = panel.DrawRectangle;
|
||||
|
||||
// Cover a gap introduced by the spacing between a BeatmapSetPanel and a BeatmapPanel either above it or below it.
|
||||
inputRectangle = inputRectangle.Inflate(new MarginPadding { Vertical = BeatmapCarousel.SPACING / 2f });
|
||||
|
||||
return inputRectangle.Contains(panel.ToLocalSpace(screenSpacePos));
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
@ -277,8 +214,8 @@ namespace osu.Game.Screens.SelectV2
|
||||
updateKeyCount();
|
||||
}, true);
|
||||
|
||||
Selected.BindValueChanged(_ => updateSelectedDisplay(), true);
|
||||
KeyboardSelected.BindValueChanged(_ => updateKeyboardSelectedDisplay(), true);
|
||||
Selected.BindValueChanged(s => panel.Active.Value = s.NewValue, true);
|
||||
KeyboardSelected.BindValueChanged(k => panel.KeyboardActive.Value = k.NewValue, true);
|
||||
}
|
||||
|
||||
protected override void PrepareForUse()
|
||||
@ -308,7 +245,6 @@ namespace osu.Game.Screens.SelectV2
|
||||
|
||||
computeStarRating();
|
||||
|
||||
updateSelectedDisplay();
|
||||
FinishTransforms(true);
|
||||
|
||||
this.FadeInFromZero(duration, Easing.OutQuint);
|
||||
@ -324,55 +260,6 @@ namespace osu.Game.Screens.SelectV2
|
||||
starDifficultyBindable = null;
|
||||
}
|
||||
|
||||
private void updateSelectedDisplay()
|
||||
{
|
||||
if (Item == null)
|
||||
return;
|
||||
|
||||
updatePanelPosition();
|
||||
|
||||
backgroundBorder.RelativeSizeAxes = Selected.Value ? Axes.Both : Axes.Y;
|
||||
backgroundBorder.Width = Selected.Value ? 1 : difficulty_icon_container_width + corner_radius;
|
||||
backgroundBorder.FadeTo(Selected.Value ? 1 : 0, duration, Easing.OutQuint);
|
||||
difficultyIcon.FadeTo(Selected.Value ? 1 : 0, duration, Easing.OutQuint);
|
||||
|
||||
backgroundContainer.ResizeHeightTo(Selected.Value ? HEIGHT - 4 : HEIGHT, duration, Easing.OutQuint);
|
||||
backgroundContainer.MoveToX(Selected.Value ? difficulty_icon_container_width : 0, duration, Easing.OutQuint);
|
||||
mainFlowContainer.MoveToX(Selected.Value ? difficulty_icon_container_width : 0, duration, Easing.OutQuint);
|
||||
|
||||
panel.EdgeEffect = panel.EdgeEffect with { Radius = Selected.Value ? 15 : 10 };
|
||||
updateEdgeEffectColour();
|
||||
}
|
||||
|
||||
private void updateKeyboardSelectedDisplay()
|
||||
{
|
||||
updatePanelPosition();
|
||||
updateHover();
|
||||
}
|
||||
|
||||
private void updatePanelPosition()
|
||||
{
|
||||
float x = set_x_offset + selected_x_offset + preselected_x_offset;
|
||||
|
||||
if (Selected.Value)
|
||||
x -= selected_x_offset;
|
||||
|
||||
if (KeyboardSelected.Value)
|
||||
x -= preselected_x_offset;
|
||||
|
||||
this.TransformTo(nameof(Padding), new MarginPadding { Left = x }, duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void updateHover()
|
||||
{
|
||||
bool hovered = IsHovered || KeyboardSelected.Value;
|
||||
|
||||
if (hovered)
|
||||
hoverLayer.FadeIn(100, Easing.OutQuint);
|
||||
else
|
||||
hoverLayer.FadeOut(1000, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void computeStarRating()
|
||||
{
|
||||
starDifficultyCancellationSource?.Cancel();
|
||||
@ -384,23 +271,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
var beatmap = (BeatmapInfo)Item.Model;
|
||||
|
||||
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmap, starDifficultyCancellationSource.Token);
|
||||
starDifficultyBindable.BindValueChanged(d =>
|
||||
{
|
||||
var value = d.NewValue ?? default;
|
||||
|
||||
backgroundBorder.FadeColour(colours.ForStarDifficulty(value.Stars), duration, Easing.OutQuint);
|
||||
difficultyIcon.FadeColour(value.Stars > 6.5f ? colours.Orange1 : colourProvider.Background5, duration, Easing.OutQuint);
|
||||
difficultyStarRating.Current.Value = value;
|
||||
|
||||
updateEdgeEffectColour();
|
||||
}, true);
|
||||
}
|
||||
|
||||
private void updateEdgeEffectColour()
|
||||
{
|
||||
panel.FadeEdgeEffectTo(Selected.Value
|
||||
? colours.ForStarDifficulty(starDifficultyBindable?.Value?.Stars ?? 0f).Opacity(0.5f)
|
||||
: Color4.Black.Opacity(0.4f), duration, Easing.OutQuint);
|
||||
starDifficultyBindable.BindValueChanged(_ => updateDisplay(), true);
|
||||
}
|
||||
|
||||
private void updateKeyCount()
|
||||
@ -424,16 +295,13 @@ namespace osu.Game.Screens.SelectV2
|
||||
difficultyKeyCountText.Alpha = 0;
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
private void updateDisplay()
|
||||
{
|
||||
updateHover();
|
||||
return true;
|
||||
}
|
||||
var starDifficulty = starDifficultyBindable?.Value ?? default;
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
updateHover();
|
||||
base.OnHoverLost(e);
|
||||
panel.AccentColour = colours.ForStarDifficulty(starDifficulty.Stars);
|
||||
difficultyIcon.FadeColour(starDifficulty.Stars > 6.5f ? colours.Orange1 : colourProvider.Background5, duration, Easing.OutQuint);
|
||||
difficultyStarRating.Current.Value = starDifficulty;
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
|
240
osu.Game/Screens/SelectV2/CarouselPanelPiece.cs
Normal file
240
osu.Game/Screens/SelectV2/CarouselPanelPiece.cs
Normal file
@ -0,0 +1,240 @@
|
||||
// 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;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Effects;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
public partial class CarouselPanelPiece : Container
|
||||
{
|
||||
private const float corner_radius = 10;
|
||||
|
||||
private const float left_edge_x_offset = 20f;
|
||||
private const float keyboard_active_x_offset = 25f;
|
||||
private const float active_x_offset = 50f;
|
||||
|
||||
private const float duration = 500;
|
||||
|
||||
private readonly float panelXOffset;
|
||||
|
||||
private readonly Box backgroundBorder;
|
||||
private readonly Box backgroundGradient;
|
||||
private readonly Box backgroundAccentGradient;
|
||||
private readonly Container backgroundLayer;
|
||||
private readonly Container backgroundLayerHorizontalPadding;
|
||||
private readonly Container backgroundContainer;
|
||||
private readonly Container iconContainer;
|
||||
private readonly Box activationFlash;
|
||||
private readonly Box hoverLayer;
|
||||
|
||||
public Container TopLevelContent { get; }
|
||||
|
||||
protected override Container Content { get; }
|
||||
|
||||
public Drawable Background
|
||||
{
|
||||
set => backgroundContainer.Child = value;
|
||||
}
|
||||
|
||||
public Drawable Icon
|
||||
{
|
||||
set => iconContainer.Child = value;
|
||||
}
|
||||
|
||||
private Color4? accentColour;
|
||||
|
||||
public Color4? AccentColour
|
||||
{
|
||||
get => accentColour;
|
||||
set
|
||||
{
|
||||
accentColour = value;
|
||||
updateDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
public readonly BindableBool Active = new BindableBool();
|
||||
public readonly BindableBool KeyboardActive = new BindableBool();
|
||||
|
||||
public CarouselPanelPiece(float panelXOffset)
|
||||
{
|
||||
this.panelXOffset = panelXOffset;
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
|
||||
InternalChild = TopLevelContent = new Container
|
||||
{
|
||||
Masking = true,
|
||||
CornerRadius = corner_radius,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
X = corner_radius,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Offset = new Vector2(1f),
|
||||
Radius = 10,
|
||||
},
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new BufferedContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
backgroundBorder = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.White,
|
||||
},
|
||||
backgroundLayerHorizontalPadding = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = backgroundLayer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = new Container
|
||||
{
|
||||
Masking = true,
|
||||
CornerRadius = corner_radius,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
backgroundGradient = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
backgroundAccentGradient = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
backgroundContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
iconContainer = new Container
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
},
|
||||
Content = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Right = panelXOffset + corner_radius },
|
||||
},
|
||||
hoverLayer = new Box
|
||||
{
|
||||
Alpha = 0,
|
||||
Blending = BlendingParameters.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
activationFlash = new Box
|
||||
{
|
||||
Colour = Color4.White.Opacity(0.4f),
|
||||
Blending = BlendingParameters.Additive,
|
||||
Alpha = 0f,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new HoverSounds(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colourProvider, OsuColour colours)
|
||||
{
|
||||
hoverLayer.Colour = colours.Blue.Opacity(0.1f);
|
||||
backgroundGradient.Colour = ColourInfo.GradientHorizontal(colourProvider.Background3, colourProvider.Background4);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Active.BindValueChanged(_ => updateDisplay());
|
||||
KeyboardActive.BindValueChanged(_ => updateDisplay(), true);
|
||||
}
|
||||
|
||||
public void Flash()
|
||||
{
|
||||
activationFlash.FadeOutFromOne(500, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void updateDisplay()
|
||||
{
|
||||
backgroundLayer.TransformTo(nameof(Padding), backgroundLayer.Padding with { Vertical = Active.Value ? 2f : 0f }, duration, Easing.OutQuint);
|
||||
|
||||
var backgroundColour = accentColour ?? Color4.White;
|
||||
var edgeEffectColour = accentColour ?? Color4Extensions.FromHex(@"4EBFFF");
|
||||
|
||||
backgroundAccentGradient.FadeColour(ColourInfo.GradientHorizontal(backgroundColour.Opacity(0.25f), backgroundColour.Opacity(0f)), duration, Easing.OutQuint);
|
||||
backgroundBorder.FadeColour(backgroundColour, duration, Easing.OutQuint);
|
||||
|
||||
TopLevelContent.FadeEdgeEffectTo(Active.Value ? edgeEffectColour.Opacity(0.5f) : Color4.Black.Opacity(0.4f), duration, Easing.OutQuint);
|
||||
|
||||
updateXOffset();
|
||||
updateHover();
|
||||
}
|
||||
|
||||
private void updateXOffset()
|
||||
{
|
||||
float x = panelXOffset + active_x_offset + keyboard_active_x_offset + left_edge_x_offset;
|
||||
|
||||
if (Active.Value)
|
||||
x -= active_x_offset;
|
||||
|
||||
if (KeyboardActive.Value)
|
||||
x -= keyboard_active_x_offset;
|
||||
|
||||
this.TransformTo(nameof(Padding), new MarginPadding { Left = x }, duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void updateHover()
|
||||
{
|
||||
bool hovered = IsHovered || KeyboardActive.Value;
|
||||
|
||||
if (hovered)
|
||||
hoverLayer.FadeIn(100, Easing.OutQuint);
|
||||
else
|
||||
hoverLayer.FadeOut(1000, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
updateDisplay();
|
||||
return base.OnHover(e);
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
updateDisplay();
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
Content.Padding = Content.Padding with { Left = iconContainer.DrawWidth };
|
||||
backgroundLayerHorizontalPadding.Padding = new MarginPadding { Left = iconContainer.DrawWidth };
|
||||
}
|
||||
}
|
||||
}
|
@ -10,10 +10,10 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Overlays;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
@ -24,137 +24,83 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
public const float HEIGHT = CarouselItem.DEFAULT_HEIGHT;
|
||||
|
||||
private const float corner_radius = 10;
|
||||
|
||||
private const float glow_offset = 10f; // extra space for any edge effect to not be cutoff by the right edge of the carousel.
|
||||
private const float preselected_x_offset = 25f;
|
||||
private const float selected_x_offset = 50f;
|
||||
|
||||
private const float duration = 500;
|
||||
|
||||
[Resolved]
|
||||
private BeatmapCarousel? carousel { get; set; }
|
||||
|
||||
private Container panel = null!;
|
||||
private Box activationFlash = null!;
|
||||
private CarouselPanelPiece panel = null!;
|
||||
private Drawable chevronIcon = null!;
|
||||
private OsuSpriteText titleText = null!;
|
||||
private Box hoverLayer = null!;
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos)
|
||||
protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos)
|
||||
{
|
||||
var inputRectangle = panel.DrawRectangle;
|
||||
var inputRectangle = panel.TopLevelContent.DrawRectangle;
|
||||
|
||||
// Cover a gap introduced by the spacing between a GroupPanel and a BeatmapPanel either below/above it.
|
||||
// Cover a gap introduced by the spacing between a GroupPanel and other panel types either below/above it.
|
||||
inputRectangle = inputRectangle.Inflate(new MarginPadding { Vertical = BeatmapCarousel.SPACING / 2f });
|
||||
|
||||
return inputRectangle.Contains(panel.ToLocalSpace(screenSpacePos));
|
||||
return inputRectangle.Contains(panel.TopLevelContent.ToLocalSpace(screenSpacePos));
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider colourProvider, OsuColour colours)
|
||||
private void load(OverlayColourProvider colourProvider)
|
||||
{
|
||||
Anchor = Anchor.TopRight;
|
||||
Origin = Anchor.TopRight;
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = HEIGHT;
|
||||
|
||||
InternalChild = panel = new Container
|
||||
InternalChild = panel = new CarouselPanelPiece(0)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CornerRadius = corner_radius,
|
||||
Masking = true,
|
||||
X = corner_radius,
|
||||
Icon = chevronIcon = new SpriteIcon
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Icon = FontAwesome.Solid.ChevronDown,
|
||||
Size = new Vector2(12),
|
||||
Margin = new MarginPadding { Horizontal = 5f },
|
||||
X = 2f,
|
||||
Colour = colourProvider.Background3,
|
||||
},
|
||||
Background = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Dark1,
|
||||
},
|
||||
AccentColour = colourProvider.Highlight1,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
titleText = new OsuSpriteText
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Left = 10f },
|
||||
Child = new Container
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
X = 10f,
|
||||
},
|
||||
new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Size = new Vector2(50f, 14f),
|
||||
Margin = new MarginPadding { Right = 20f },
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CornerRadius = corner_radius,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
new Box
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Background6,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Background3,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Left = 10f },
|
||||
Child = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CornerRadius = corner_radius,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black.Opacity(0.7f),
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Background5,
|
||||
},
|
||||
titleText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
X = 10f,
|
||||
},
|
||||
new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Size = new Vector2(50f, 14f),
|
||||
Margin = new MarginPadding { Right = 30f },
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black.Opacity(0.7f),
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold),
|
||||
// TODO: requires Carousel/CarouselItem-side implementation
|
||||
Text = "43",
|
||||
UseFullGlyphHeight = false,
|
||||
}
|
||||
},
|
||||
},
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold),
|
||||
// TODO: requires Carousel/CarouselItem-side implementation
|
||||
Text = "43",
|
||||
UseFullGlyphHeight = false,
|
||||
}
|
||||
}
|
||||
},
|
||||
activationFlash = new Box
|
||||
{
|
||||
Colour = Color4.White,
|
||||
Blending = BlendingParameters.Additive,
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
hoverLayer = new Box
|
||||
{
|
||||
Colour = colours.Blue.Opacity(0.1f),
|
||||
Alpha = 0,
|
||||
Blending = BlendingParameters.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new HoverSounds(),
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -163,17 +109,17 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Expanded.BindValueChanged(_ => updateExpandedDisplay(), true);
|
||||
KeyboardSelected.BindValueChanged(_ => updateKeyboardSelectedDisplay(), true);
|
||||
Expanded.BindValueChanged(_ => onExpanded(), true);
|
||||
KeyboardSelected.BindValueChanged(k => panel.KeyboardActive.Value = k.NewValue, true);
|
||||
}
|
||||
|
||||
private void updateExpandedDisplay()
|
||||
private void onExpanded()
|
||||
{
|
||||
updatePanelPosition();
|
||||
panel.Active.Value = Expanded.Value;
|
||||
panel.Flash();
|
||||
|
||||
// todo: figma shares no extra visual feedback on this.
|
||||
|
||||
activationFlash.FadeTo(0.2f).FadeTo(0f, 500, Easing.OutQuint);
|
||||
chevronIcon.ResizeWidthTo(Expanded.Value ? 12f : 0f, duration, Easing.OutQuint);
|
||||
chevronIcon.FadeTo(Expanded.Value ? 1f : 0f, duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PrepareForUse()
|
||||
@ -186,6 +132,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
|
||||
titleText.Text = group.Title;
|
||||
|
||||
FinishTransforms(true);
|
||||
this.FadeInFromZero(500, Easing.OutQuint);
|
||||
}
|
||||
|
||||
@ -197,47 +144,6 @@ namespace osu.Game.Screens.SelectV2
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateKeyboardSelectedDisplay()
|
||||
{
|
||||
updatePanelPosition();
|
||||
updateHover();
|
||||
}
|
||||
|
||||
private void updatePanelPosition()
|
||||
{
|
||||
float x = glow_offset + selected_x_offset + preselected_x_offset;
|
||||
|
||||
if (Expanded.Value)
|
||||
x -= selected_x_offset;
|
||||
|
||||
if (KeyboardSelected.Value)
|
||||
x -= preselected_x_offset;
|
||||
|
||||
this.TransformTo(nameof(Padding), new MarginPadding { Left = x }, duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void updateHover()
|
||||
{
|
||||
bool hovered = IsHovered || KeyboardSelected.Value;
|
||||
|
||||
if (hovered)
|
||||
hoverLayer.FadeIn(100, Easing.OutQuint);
|
||||
else
|
||||
hoverLayer.FadeOut(1000, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
updateHover();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
updateHover();
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
#region ICarouselPanel
|
||||
|
||||
public CarouselItem? Item { get; set; }
|
||||
@ -249,7 +155,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
|
||||
public void Activated()
|
||||
{
|
||||
// sets should never be activated.
|
||||
// groups should never be activated.
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Drawables;
|
||||
@ -26,10 +27,6 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
public const float HEIGHT = CarouselItem.DEFAULT_HEIGHT;
|
||||
|
||||
private const float glow_offset = 10f; // extra space for the edge effect to not be cutoff by the right edge of the carousel.
|
||||
private const float preselected_x_offset = 25f;
|
||||
private const float expanded_x_offset = 50f;
|
||||
|
||||
private const float duration = 500;
|
||||
|
||||
[Resolved]
|
||||
@ -41,20 +38,20 @@ namespace osu.Game.Screens.SelectV2
|
||||
[Resolved]
|
||||
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||
|
||||
private Box activationFlash = null!;
|
||||
private Box outerLayer = null!;
|
||||
private CarouselPanelPiece panel = null!;
|
||||
private Drawable chevronIcon = null!;
|
||||
private Box contentBackground = null!;
|
||||
private StarRatingDisplay starRatingDisplay = null!;
|
||||
private StarCounter starCounter = null!;
|
||||
private Box hoverLayer = null!;
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos)
|
||||
protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos)
|
||||
{
|
||||
var inputRectangle = DrawRectangle;
|
||||
var inputRectangle = panel.TopLevelContent.DrawRectangle;
|
||||
|
||||
// Cover a gap introduced by the spacing between a GroupPanel and a BeatmapPanel either below/above it.
|
||||
// Cover a gap introduced by the spacing between a GroupPanel and other panel types either below/above it.
|
||||
inputRectangle = inputRectangle.Inflate(new MarginPadding { Vertical = BeatmapCarousel.SPACING / 2f });
|
||||
|
||||
return inputRectangle.Contains(ToLocalSpace(screenSpacePos));
|
||||
return inputRectangle.Contains(panel.TopLevelContent.ToLocalSpace(screenSpacePos));
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@ -65,118 +62,71 @@ namespace osu.Game.Screens.SelectV2
|
||||
RelativeSizeAxes = Axes.X;
|
||||
Height = HEIGHT;
|
||||
|
||||
InternalChild = new Container
|
||||
InternalChild = panel = new CarouselPanelPiece(0)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CornerRadius = 10f,
|
||||
Masking = true,
|
||||
Icon = chevronIcon = new SpriteIcon
|
||||
{
|
||||
AlwaysPresent = true,
|
||||
Icon = FontAwesome.Solid.ChevronDown,
|
||||
Size = new Vector2(12),
|
||||
Margin = new MarginPadding { Horizontal = 5f },
|
||||
X = 2f,
|
||||
},
|
||||
Background = contentBackground = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Dark1,
|
||||
},
|
||||
AccentColour = colourProvider.Highlight1,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Left = 10f },
|
||||
Child = new Container
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Spacing = new Vector2(10f, 0f),
|
||||
Margin = new MarginPadding { Left = 10f },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CornerRadius = 10f,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
starRatingDisplay = new StarRatingDisplay(default, StarRatingDisplaySize.Small)
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Background6,
|
||||
},
|
||||
}
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
},
|
||||
starCounter = new StarCounter
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Scale = new Vector2(8f / 20f),
|
||||
},
|
||||
}
|
||||
},
|
||||
outerLayer = new Box
|
||||
new CircularContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Background3,
|
||||
},
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Padding = new MarginPadding { Left = 10f },
|
||||
Child = new Container
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Size = new Vector2(50f, 14f),
|
||||
Margin = new MarginPadding { Right = 20f },
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CornerRadius = 10f,
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
new Box
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black.Opacity(0.2f),
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Spacing = new Vector2(10f, 0f),
|
||||
Margin = new MarginPadding { Left = 10f },
|
||||
Children = new Drawable[]
|
||||
{
|
||||
starRatingDisplay = new StarRatingDisplay(default, StarRatingDisplaySize.Small)
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
},
|
||||
starCounter = new StarCounter
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Scale = new Vector2(8f / 20f),
|
||||
},
|
||||
}
|
||||
},
|
||||
new CircularContainer
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Size = new Vector2(50f, 14f),
|
||||
Margin = new MarginPadding { Right = 30f },
|
||||
Masking = true,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black.Opacity(0.7f),
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold),
|
||||
// TODO: requires Carousel/CarouselItem-side implementation
|
||||
Text = "43",
|
||||
UseFullGlyphHeight = false,
|
||||
}
|
||||
},
|
||||
},
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = Color4.Black.Opacity(0.7f),
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold),
|
||||
// TODO: requires Carousel/CarouselItem-side implementation
|
||||
Text = "43",
|
||||
UseFullGlyphHeight = false,
|
||||
}
|
||||
}
|
||||
},
|
||||
activationFlash = new Box
|
||||
{
|
||||
Colour = Color4.White,
|
||||
Blending = BlendingParameters.Additive,
|
||||
Alpha = 0,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
hoverLayer = new Box
|
||||
{
|
||||
Colour = colours.Blue.Opacity(0.1f),
|
||||
Alpha = 0,
|
||||
Blending = BlendingParameters.Additive,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new HoverSounds(),
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -185,17 +135,17 @@ namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Expanded.BindValueChanged(_ => updateExpandedDisplay(), true);
|
||||
KeyboardSelected.BindValueChanged(_ => updateKeyboardSelectedDisplay(), true);
|
||||
Expanded.BindValueChanged(_ => onExpanded(), true);
|
||||
KeyboardSelected.BindValueChanged(k => panel.KeyboardActive.Value = k.NewValue, true);
|
||||
}
|
||||
|
||||
private void updateExpandedDisplay()
|
||||
private void onExpanded()
|
||||
{
|
||||
updatePanelPosition();
|
||||
panel.Active.Value = Expanded.Value;
|
||||
panel.Flash();
|
||||
|
||||
// todo: figma shares no extra visual feedback on this.
|
||||
|
||||
activationFlash.FadeTo(0.2f).FadeTo(0f, 500, Easing.OutQuint);
|
||||
chevronIcon.ResizeWidthTo(Expanded.Value ? 12f : 0f, duration, Easing.OutQuint);
|
||||
chevronIcon.FadeTo(Expanded.Value ? 1f : 0f, duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override void PrepareForUse()
|
||||
@ -209,12 +159,15 @@ namespace osu.Game.Screens.SelectV2
|
||||
Color4 colour = group.StarNumber >= 9 ? OsuColour.Gray(0.2f) : colours.ForStarDifficulty(group.StarNumber);
|
||||
Color4 contentColour = group.StarNumber >= 7 ? colours.Orange1 : colourProvider.Background5;
|
||||
|
||||
outerLayer.Colour = colour;
|
||||
starCounter.Colour = contentColour;
|
||||
panel.AccentColour = colour;
|
||||
contentBackground.Colour = colour.Darken(0.3f);
|
||||
|
||||
starRatingDisplay.Current.Value = new StarDifficulty(group.StarNumber, 0);
|
||||
starCounter.Current = group.StarNumber;
|
||||
|
||||
chevronIcon.Colour = contentColour;
|
||||
starCounter.Colour = contentColour;
|
||||
|
||||
this.FadeInFromZero(500, Easing.OutQuint);
|
||||
}
|
||||
|
||||
@ -226,47 +179,6 @@ namespace osu.Game.Screens.SelectV2
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateKeyboardSelectedDisplay()
|
||||
{
|
||||
updatePanelPosition();
|
||||
updateHover();
|
||||
}
|
||||
|
||||
private void updatePanelPosition()
|
||||
{
|
||||
float x = glow_offset + expanded_x_offset + preselected_x_offset;
|
||||
|
||||
if (Expanded.Value)
|
||||
x -= expanded_x_offset;
|
||||
|
||||
if (KeyboardSelected.Value)
|
||||
x -= preselected_x_offset;
|
||||
|
||||
this.TransformTo(nameof(Padding), new MarginPadding { Left = x }, duration, Easing.OutQuint);
|
||||
}
|
||||
|
||||
private void updateHover()
|
||||
{
|
||||
bool hovered = IsHovered || KeyboardSelected.Value;
|
||||
|
||||
if (hovered)
|
||||
hoverLayer.FadeIn(100, Easing.OutQuint);
|
||||
else
|
||||
hoverLayer.FadeOut(1000, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
updateHover();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
updateHover();
|
||||
base.OnHoverLost(e);
|
||||
}
|
||||
|
||||
#region ICarouselPanel
|
||||
|
||||
public CarouselItem? Item { get; set; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user