mirror of
https://github.com/ppy/osu.git
synced 2025-03-11 10:17:18 +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 System.Threading;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Colour;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Graphics.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.Drawables;
|
using osu.Game.Beatmaps.Drawables;
|
||||||
@ -25,7 +21,6 @@ using osu.Game.Resources.Localisation.Web;
|
|||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.SelectV2
|
namespace osu.Game.Screens.SelectV2
|
||||||
{
|
{
|
||||||
@ -33,36 +28,23 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
{
|
{
|
||||||
public const float HEIGHT = CarouselItem.DEFAULT_HEIGHT;
|
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
|
// 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).
|
// (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 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;
|
private const float duration = 500;
|
||||||
|
|
||||||
[Resolved]
|
private CarouselPanelPiece panel = null!;
|
||||||
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 StarCounter starCounter = null!;
|
private StarCounter starCounter = null!;
|
||||||
private ConstrainedIconContainer iconContainer = null!;
|
private ConstrainedIconContainer difficultyIcon = null!;
|
||||||
private Box hoverLayer = null!;
|
private OsuSpriteText keyCountText = null!;
|
||||||
private Box activationFlash = null!;
|
|
||||||
|
|
||||||
private Box backgroundBorder = null!;
|
|
||||||
|
|
||||||
private StarRatingDisplay starRatingDisplay = 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]
|
[Resolved]
|
||||||
private OverlayColourProvider colourProvider { get; set; } = null!;
|
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||||
@ -73,16 +55,24 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private BeatmapDifficultyCache difficultyCache { get; set; } = null!;
|
private BeatmapDifficultyCache difficultyCache { get; set; } = null!;
|
||||||
|
|
||||||
private OsuSpriteText keyCountText = null!;
|
[Resolved]
|
||||||
|
private BeatmapCarousel? carousel { get; set; }
|
||||||
|
|
||||||
private IBindable<StarDifficulty?>? starDifficultyBindable;
|
[Resolved]
|
||||||
private CancellationTokenSource? starDifficultyCancellationSource;
|
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
|
||||||
|
|
||||||
private Container rightContainer = null!;
|
[Resolved]
|
||||||
private Box starRatingGradient = null!;
|
private IBindable<IReadOnlyList<Mod>> mods { get; set; } = null!;
|
||||||
private TopLocalRankV2 difficultyRank = null!;
|
|
||||||
private OsuSpriteText difficultyText = null!;
|
protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos)
|
||||||
private OsuSpriteText authorText = null!;
|
{
|
||||||
|
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]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OverlayColourProvider colourProvider)
|
private void load(OverlayColourProvider colourProvider)
|
||||||
@ -94,67 +84,21 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
Width = 1f;
|
Width = 1f;
|
||||||
Height = HEIGHT;
|
Height = HEIGHT;
|
||||||
|
|
||||||
InternalChild = panel = new Container
|
InternalChild = panel = new CarouselPanelPiece(difficulty_x_offset)
|
||||||
{
|
{
|
||||||
Masking = true,
|
Icon = difficultyIcon = new ConstrainedIconContainer
|
||||||
CornerRadius = corner_radius,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
X = corner_radius,
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Size = new Vector2(20),
|
||||||
Offset = new Vector2(1f),
|
Margin = new MarginPadding { Horizontal = 5f },
|
||||||
Radius = 10,
|
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
|
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,
|
Direction = FillDirection.Vertical,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
Children = new Drawable[]
|
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()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
@ -260,8 +180,8 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
updateKeyCount();
|
updateKeyCount();
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
Selected.BindValueChanged(_ => updateSelectionDisplay(), true);
|
Selected.BindValueChanged(s => panel.Active.Value = s.NewValue, true);
|
||||||
KeyboardSelected.BindValueChanged(_ => updateKeyboardSelectedDisplay(), true);
|
KeyboardSelected.BindValueChanged(k => panel.KeyboardActive.Value = k.NewValue, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PrepareForUse()
|
protected override void PrepareForUse()
|
||||||
@ -271,63 +191,25 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
Debug.Assert(Item != null);
|
Debug.Assert(Item != null);
|
||||||
var beatmap = (BeatmapInfo)Item.Model;
|
var beatmap = (BeatmapInfo)Item.Model;
|
||||||
|
|
||||||
iconContainer.Icon = beatmap.Ruleset.CreateInstance().CreateIcon();
|
difficultyIcon.Icon = beatmap.Ruleset.CreateInstance().CreateIcon();
|
||||||
|
|
||||||
difficultyRank.Beatmap = beatmap;
|
difficultyRank.Beatmap = beatmap;
|
||||||
difficultyText.Text = beatmap.DifficultyName;
|
difficultyText.Text = beatmap.DifficultyName;
|
||||||
authorText.Text = BeatmapsetsStrings.ShowDetailsMappedBy(beatmap.Metadata.Author.Username);
|
authorText.Text = BeatmapsetsStrings.ShowDetailsMappedBy(beatmap.Metadata.Author.Username);
|
||||||
|
|
||||||
starDifficultyBindable = null;
|
|
||||||
|
|
||||||
computeStarRating();
|
computeStarRating();
|
||||||
updateKeyCount();
|
updateKeyCount();
|
||||||
|
|
||||||
updateSelectionDisplay();
|
|
||||||
FinishTransforms(true);
|
FinishTransforms(true);
|
||||||
|
|
||||||
this.FadeInFromZero(duration, Easing.OutQuint);
|
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);
|
difficultyRank.Beatmap = null;
|
||||||
|
starDifficultyBindable = null;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void computeStarRating()
|
private void computeStarRating()
|
||||||
@ -341,34 +223,7 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
var beatmap = (BeatmapInfo)Item.Model;
|
var beatmap = (BeatmapInfo)Item.Model;
|
||||||
|
|
||||||
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmap, starDifficultyCancellationSource.Token);
|
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmap, starDifficultyCancellationSource.Token);
|
||||||
starDifficultyBindable.BindValueChanged(d =>
|
starDifficultyBindable.BindValueChanged(_ => updateDisplay(), true);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateKeyCount()
|
private void updateKeyCount()
|
||||||
@ -392,16 +247,18 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
keyCountText.Alpha = 0;
|
keyCountText.Alpha = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
private void updateDisplay()
|
||||||
{
|
{
|
||||||
updateHover();
|
var starDifficulty = starDifficultyBindable?.Value ?? default;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
starRatingDisplay.Current.Value = starDifficulty;
|
||||||
{
|
starCounter.Current = (float)starDifficulty.Stars;
|
||||||
updateHover();
|
|
||||||
base.OnHoverLost(e);
|
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)
|
protected override bool OnClick(ClickEvent e)
|
||||||
@ -430,7 +287,7 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
|
|
||||||
public void Activated()
|
public void Activated()
|
||||||
{
|
{
|
||||||
activationFlash.FadeOutFromOne(500, Easing.OutQuint);
|
panel.Flash();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -6,12 +6,9 @@ using System.Diagnostics;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Graphics.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
@ -19,10 +16,8 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Beatmaps.Drawables;
|
using osu.Game.Beatmaps.Drawables;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.SelectV2
|
namespace osu.Game.Screens.SelectV2
|
||||||
{
|
{
|
||||||
@ -30,18 +25,22 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
{
|
{
|
||||||
public const float HEIGHT = CarouselItem.DEFAULT_HEIGHT * 1.6f;
|
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
|
// 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).
|
// (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 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 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]
|
[Resolved]
|
||||||
private BeatmapCarousel? carousel { get; set; }
|
private BeatmapCarousel? carousel { get; set; }
|
||||||
|
|
||||||
@ -51,22 +50,15 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private BeatmapManager beatmaps { get; set; } = null!;
|
private BeatmapManager beatmaps { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos)
|
||||||
private OsuColour colours { get; set; } = null!;
|
{
|
||||||
|
var inputRectangle = panel.TopLevelContent.DrawRectangle;
|
||||||
|
|
||||||
private Container panel = null!;
|
// Cover a gap introduced by the spacing between a BeatmapSetPanel and a BeatmapPanel either above it or below it.
|
||||||
private Box backgroundBorder = null!;
|
inputRectangle = inputRectangle.Inflate(new MarginPadding { Vertical = BeatmapCarousel.SPACING / 2f });
|
||||||
private BeatmapSetPanelBackground background = null!;
|
|
||||||
private Container backgroundContainer = null!;
|
|
||||||
private FillFlowContainer mainFlowContainer = null!;
|
|
||||||
private SpriteIcon chevronIcon = null!;
|
|
||||||
private Box hoverLayer = null!;
|
|
||||||
|
|
||||||
private OsuSpriteText titleText = null!;
|
return inputRectangle.Contains(panel.TopLevelContent.ToLocalSpace(screenSpacePos));
|
||||||
private OsuSpriteText artistText = null!;
|
}
|
||||||
private UpdateBeatmapSetButtonV2 updateButton = null!;
|
|
||||||
private BeatmapSetOnlineStatusPill statusPill = null!;
|
|
||||||
private DifficultySpectrumDisplay difficultiesDisplay = null!;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
@ -76,137 +68,89 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Height = HEIGHT;
|
Height = HEIGHT;
|
||||||
|
|
||||||
InternalChild = panel = new Container
|
InternalChild = panel = new CarouselPanelPiece(set_x_offset)
|
||||||
{
|
{
|
||||||
Masking = true,
|
Icon = chevronIcon = new Container
|
||||||
CornerRadius = corner_radius,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
X = corner_radius,
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Size = new Vector2(22),
|
||||||
Radius = 10,
|
Child = new SpriteIcon
|
||||||
},
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new BufferedContainer
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Anchor = Anchor.Centre,
|
||||||
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,
|
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Anchor = Anchor.CentreLeft,
|
|
||||||
Icon = FontAwesome.Solid.ChevronRight,
|
Icon = FontAwesome.Solid.ChevronRight,
|
||||||
Size = new Vector2(12),
|
Size = new Vector2(12),
|
||||||
|
X = 1f,
|
||||||
Colour = colourProvider.Background5,
|
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,
|
titleText = new OsuSpriteText
|
||||||
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),
|
||||||
|
},
|
||||||
|
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),
|
updateButton = new UpdateBeatmapSetButtonV2
|
||||||
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
|
Anchor = Anchor.CentreLeft,
|
||||||
{
|
Origin = Anchor.CentreLeft,
|
||||||
Anchor = Anchor.CentreLeft,
|
Margin = new MarginPadding { Right = 5f, Top = -2f },
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
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()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
Expanded.BindValueChanged(_ => updateExpandedDisplay(), true);
|
Expanded.BindValueChanged(_ => onExpanded(), true);
|
||||||
KeyboardSelected.BindValueChanged(_ => updateKeyboardSelectedDisplay(), 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()
|
protected override void PrepareForUse()
|
||||||
@ -226,9 +170,7 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
statusPill.Status = beatmapSet.Status;
|
statusPill.Status = beatmapSet.Status;
|
||||||
difficultiesDisplay.BeatmapSet = beatmapSet;
|
difficultiesDisplay.BeatmapSet = beatmapSet;
|
||||||
|
|
||||||
updateExpandedDisplay();
|
|
||||||
FinishTransforms(true);
|
FinishTransforms(true);
|
||||||
|
|
||||||
this.FadeInFromZero(duration, Easing.OutQuint);
|
this.FadeInFromZero(duration, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,70 +183,6 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
difficultiesDisplay.BeatmapSet = null;
|
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)
|
protected override bool OnClick(ClickEvent e)
|
||||||
{
|
{
|
||||||
if (carousel != null)
|
if (carousel != null)
|
||||||
|
@ -8,12 +8,9 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Graphics.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
@ -21,13 +18,11 @@ using osu.Game.Beatmaps.Drawables;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Resources.Localisation.Web;
|
using osu.Game.Resources.Localisation.Web;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.SelectV2
|
namespace osu.Game.Screens.SelectV2
|
||||||
{
|
{
|
||||||
@ -35,15 +30,9 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
{
|
{
|
||||||
public const float HEIGHT = CarouselItem.DEFAULT_HEIGHT * 1.6f;
|
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
|
// 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).
|
// (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 standalone_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 duration = 500;
|
private const float duration = 500;
|
||||||
|
|
||||||
@ -71,12 +60,8 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
private IBindable<StarDifficulty?>? starDifficultyBindable;
|
private IBindable<StarDifficulty?>? starDifficultyBindable;
|
||||||
private CancellationTokenSource? starDifficultyCancellationSource;
|
private CancellationTokenSource? starDifficultyCancellationSource;
|
||||||
|
|
||||||
private Container panel = null!;
|
private CarouselPanelPiece panel = null!;
|
||||||
private Box backgroundBorder = null!;
|
|
||||||
private BeatmapSetPanelBackground background = null!;
|
private BeatmapSetPanelBackground background = null!;
|
||||||
private Container backgroundContainer = null!;
|
|
||||||
private FillFlowContainer mainFlowContainer = null!;
|
|
||||||
private Box hoverLayer = null!;
|
|
||||||
|
|
||||||
private OsuSpriteText titleText = null!;
|
private OsuSpriteText titleText = null!;
|
||||||
private OsuSpriteText artistText = null!;
|
private OsuSpriteText artistText = null!;
|
||||||
@ -91,6 +76,16 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
private OsuSpriteText difficultyName = null!;
|
private OsuSpriteText difficultyName = null!;
|
||||||
private OsuSpriteText difficultyAuthor = 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]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
@ -100,167 +95,109 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
Width = 1f;
|
Width = 1f;
|
||||||
Height = HEIGHT;
|
Height = HEIGHT;
|
||||||
|
|
||||||
InternalChild = panel = new Container
|
InternalChild = panel = new CarouselPanelPiece(standalone_x_offset)
|
||||||
{
|
{
|
||||||
Masking = true,
|
Icon = difficultyIcon = new ConstrainedIconContainer
|
||||||
CornerRadius = corner_radius,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
X = corner_radius,
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
{
|
||||||
Type = EdgeEffectType.Shadow,
|
Size = new Vector2(20),
|
||||||
Radius = 10,
|
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,
|
titleText = new OsuSpriteText
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
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,
|
updateButton = new UpdateBeatmapSetButtonV2
|
||||||
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.CentreLeft,
|
||||||
{
|
Origin = Anchor.CentreLeft,
|
||||||
Anchor = Anchor.Centre,
|
Margin = new MarginPadding { Right = 5f, Top = -2f },
|
||||||
Origin = Anchor.Centre,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
statusPill = new BeatmapSetOnlineStatusPill
|
||||||
}
|
|
||||||
},
|
|
||||||
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[]
|
|
||||||
{
|
{
|
||||||
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,
|
difficultyStarRating = new StarRatingDisplay(default, StarRatingDisplaySize.Small)
|
||||||
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)
|
Origin = Anchor.CentreLeft,
|
||||||
{
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Scale = new Vector2(8f / 9f),
|
||||||
Anchor = Anchor.CentreLeft,
|
Margin = new MarginPadding { Right = 5f },
|
||||||
Scale = new Vector2(8f / 9f),
|
},
|
||||||
Margin = new MarginPadding { Right = 5f },
|
difficultyRank = new TopLocalRankV2
|
||||||
},
|
{
|
||||||
difficultyRank = new TopLocalRankV2
|
Scale = new Vector2(8f / 11),
|
||||||
{
|
Origin = Anchor.CentreLeft,
|
||||||
Scale = new Vector2(8f / 11),
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Margin = new MarginPadding { Right = 5f },
|
||||||
Anchor = Anchor.CentreLeft,
|
},
|
||||||
Margin = new MarginPadding { Right = 5f },
|
difficultyKeyCountText = new OsuSpriteText
|
||||||
},
|
{
|
||||||
difficultyKeyCountText = new OsuSpriteText
|
Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold),
|
||||||
{
|
Anchor = Anchor.BottomLeft,
|
||||||
Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold),
|
Origin = Anchor.BottomLeft,
|
||||||
Anchor = Anchor.BottomLeft,
|
Alpha = 0,
|
||||||
Origin = Anchor.BottomLeft,
|
Margin = new MarginPadding { Bottom = 2f },
|
||||||
Alpha = 0,
|
},
|
||||||
Margin = new MarginPadding { Bottom = 2f },
|
difficultyName = new OsuSpriteText
|
||||||
},
|
{
|
||||||
difficultyName = new OsuSpriteText
|
Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold),
|
||||||
{
|
Origin = Anchor.BottomLeft,
|
||||||
Font = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold),
|
Anchor = Anchor.BottomLeft,
|
||||||
Origin = Anchor.BottomLeft,
|
Margin = new MarginPadding { Right = 5f, Bottom = 2f },
|
||||||
Anchor = Anchor.BottomLeft,
|
},
|
||||||
Margin = new MarginPadding { Right = 5f, Bottom = 2f },
|
difficultyAuthor = new OsuSpriteText
|
||||||
},
|
{
|
||||||
difficultyAuthor = new OsuSpriteText
|
Colour = colourProvider.Content2,
|
||||||
{
|
Font = OsuFont.GetFont(weight: FontWeight.SemiBold),
|
||||||
Colour = colourProvider.Content2,
|
Origin = Anchor.BottomLeft,
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.SemiBold),
|
Anchor = Anchor.BottomLeft,
|
||||||
Origin = Anchor.BottomLeft,
|
Margin = new MarginPadding { Right = 5f, Bottom = 2f },
|
||||||
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()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
@ -277,8 +214,8 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
updateKeyCount();
|
updateKeyCount();
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
Selected.BindValueChanged(_ => updateSelectedDisplay(), true);
|
Selected.BindValueChanged(s => panel.Active.Value = s.NewValue, true);
|
||||||
KeyboardSelected.BindValueChanged(_ => updateKeyboardSelectedDisplay(), true);
|
KeyboardSelected.BindValueChanged(k => panel.KeyboardActive.Value = k.NewValue, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PrepareForUse()
|
protected override void PrepareForUse()
|
||||||
@ -308,7 +245,6 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
|
|
||||||
computeStarRating();
|
computeStarRating();
|
||||||
|
|
||||||
updateSelectedDisplay();
|
|
||||||
FinishTransforms(true);
|
FinishTransforms(true);
|
||||||
|
|
||||||
this.FadeInFromZero(duration, Easing.OutQuint);
|
this.FadeInFromZero(duration, Easing.OutQuint);
|
||||||
@ -324,55 +260,6 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
starDifficultyBindable = null;
|
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()
|
private void computeStarRating()
|
||||||
{
|
{
|
||||||
starDifficultyCancellationSource?.Cancel();
|
starDifficultyCancellationSource?.Cancel();
|
||||||
@ -384,23 +271,7 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
var beatmap = (BeatmapInfo)Item.Model;
|
var beatmap = (BeatmapInfo)Item.Model;
|
||||||
|
|
||||||
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmap, starDifficultyCancellationSource.Token);
|
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmap, starDifficultyCancellationSource.Token);
|
||||||
starDifficultyBindable.BindValueChanged(d =>
|
starDifficultyBindable.BindValueChanged(_ => updateDisplay(), true);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateKeyCount()
|
private void updateKeyCount()
|
||||||
@ -424,16 +295,13 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
difficultyKeyCountText.Alpha = 0;
|
difficultyKeyCountText.Alpha = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
private void updateDisplay()
|
||||||
{
|
{
|
||||||
updateHover();
|
var starDifficulty = starDifficultyBindable?.Value ?? default;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
panel.AccentColour = colours.ForStarDifficulty(starDifficulty.Stars);
|
||||||
{
|
difficultyIcon.FadeColour(starDifficulty.Stars > 6.5f ? colours.Orange1 : colourProvider.Background5, duration, Easing.OutQuint);
|
||||||
updateHover();
|
difficultyStarRating.Current.Value = starDifficulty;
|
||||||
base.OnHoverLost(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
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.Containers;
|
||||||
using osu.Framework.Graphics.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
@ -24,137 +24,83 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
{
|
{
|
||||||
public const float HEIGHT = CarouselItem.DEFAULT_HEIGHT;
|
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;
|
private const float duration = 500;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private BeatmapCarousel? carousel { get; set; }
|
private BeatmapCarousel? carousel { get; set; }
|
||||||
|
|
||||||
private Container panel = null!;
|
private CarouselPanelPiece panel = null!;
|
||||||
private Box activationFlash = null!;
|
private Drawable chevronIcon = null!;
|
||||||
private OsuSpriteText titleText = 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 });
|
inputRectangle = inputRectangle.Inflate(new MarginPadding { Vertical = BeatmapCarousel.SPACING / 2f });
|
||||||
|
|
||||||
return inputRectangle.Contains(panel.ToLocalSpace(screenSpacePos));
|
return inputRectangle.Contains(panel.TopLevelContent.ToLocalSpace(screenSpacePos));
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OverlayColourProvider colourProvider, OsuColour colours)
|
private void load(OverlayColourProvider colourProvider)
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopRight;
|
Anchor = Anchor.TopRight;
|
||||||
Origin = Anchor.TopRight;
|
Origin = Anchor.TopRight;
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Height = HEIGHT;
|
Height = HEIGHT;
|
||||||
|
|
||||||
InternalChild = panel = new Container
|
InternalChild = panel = new CarouselPanelPiece(0)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Icon = chevronIcon = new SpriteIcon
|
||||||
CornerRadius = corner_radius,
|
{
|
||||||
Masking = true,
|
AlwaysPresent = true,
|
||||||
X = corner_radius,
|
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[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Container
|
titleText = new OsuSpriteText
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Anchor = Anchor.CentreLeft,
|
||||||
Padding = new MarginPadding { Left = 10f },
|
Origin = Anchor.CentreLeft,
|
||||||
Child = new Container
|
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,
|
new Box
|
||||||
CornerRadius = corner_radius,
|
|
||||||
Masking = true,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
new Box
|
RelativeSizeAxes = Axes.Both,
|
||||||
{
|
Colour = Color4.Black.Opacity(0.7f),
|
||||||
RelativeSizeAxes = Axes.Both,
|
},
|
||||||
Colour = colourProvider.Background6,
|
new OsuSpriteText
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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[]
|
|
||||||
{
|
{
|
||||||
new Box
|
Anchor = Anchor.Centre,
|
||||||
{
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold),
|
||||||
Colour = colourProvider.Background5,
|
// TODO: requires Carousel/CarouselItem-side implementation
|
||||||
},
|
Text = "43",
|
||||||
titleText = new OsuSpriteText
|
UseFullGlyphHeight = false,
|
||||||
{
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
}
|
||||||
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();
|
base.LoadComplete();
|
||||||
|
|
||||||
Expanded.BindValueChanged(_ => updateExpandedDisplay(), true);
|
Expanded.BindValueChanged(_ => onExpanded(), true);
|
||||||
KeyboardSelected.BindValueChanged(_ => updateKeyboardSelectedDisplay(), 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.
|
chevronIcon.ResizeWidthTo(Expanded.Value ? 12f : 0f, duration, Easing.OutQuint);
|
||||||
|
chevronIcon.FadeTo(Expanded.Value ? 1f : 0f, duration, Easing.OutQuint);
|
||||||
activationFlash.FadeTo(0.2f).FadeTo(0f, 500, Easing.OutQuint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PrepareForUse()
|
protected override void PrepareForUse()
|
||||||
@ -186,6 +132,7 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
|
|
||||||
titleText.Text = group.Title;
|
titleText.Text = group.Title;
|
||||||
|
|
||||||
|
FinishTransforms(true);
|
||||||
this.FadeInFromZero(500, Easing.OutQuint);
|
this.FadeInFromZero(500, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,47 +144,6 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
return true;
|
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
|
#region ICarouselPanel
|
||||||
|
|
||||||
public CarouselItem? Item { get; set; }
|
public CarouselItem? Item { get; set; }
|
||||||
@ -249,7 +155,7 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
|
|
||||||
public void Activated()
|
public void Activated()
|
||||||
{
|
{
|
||||||
// sets should never be activated.
|
// groups should never be activated.
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Beatmaps.Drawables;
|
using osu.Game.Beatmaps.Drawables;
|
||||||
@ -26,10 +27,6 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
{
|
{
|
||||||
public const float HEIGHT = CarouselItem.DEFAULT_HEIGHT;
|
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;
|
private const float duration = 500;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
@ -41,20 +38,20 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private OverlayColourProvider colourProvider { get; set; } = null!;
|
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||||
|
|
||||||
private Box activationFlash = null!;
|
private CarouselPanelPiece panel = null!;
|
||||||
private Box outerLayer = null!;
|
private Drawable chevronIcon = null!;
|
||||||
|
private Box contentBackground = null!;
|
||||||
private StarRatingDisplay starRatingDisplay = null!;
|
private StarRatingDisplay starRatingDisplay = null!;
|
||||||
private StarCounter starCounter = 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 });
|
inputRectangle = inputRectangle.Inflate(new MarginPadding { Vertical = BeatmapCarousel.SPACING / 2f });
|
||||||
|
|
||||||
return inputRectangle.Contains(ToLocalSpace(screenSpacePos));
|
return inputRectangle.Contains(panel.TopLevelContent.ToLocalSpace(screenSpacePos));
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -65,118 +62,71 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
Height = HEIGHT;
|
Height = HEIGHT;
|
||||||
|
|
||||||
InternalChild = new Container
|
InternalChild = panel = new CarouselPanelPiece(0)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Icon = chevronIcon = new SpriteIcon
|
||||||
CornerRadius = 10f,
|
{
|
||||||
Masking = true,
|
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[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new Container
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Anchor = Anchor.CentreLeft,
|
||||||
Padding = new MarginPadding { Left = 10f },
|
Origin = Anchor.CentreLeft,
|
||||||
Child = new Container
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Spacing = new Vector2(10f, 0f),
|
||||||
|
Margin = new MarginPadding { Left = 10f },
|
||||||
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
starRatingDisplay = new StarRatingDisplay(default, StarRatingDisplaySize.Small)
|
||||||
CornerRadius = 10f,
|
|
||||||
Masking = true,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
new Box
|
Anchor = Anchor.CentreLeft,
|
||||||
{
|
Origin = Anchor.CentreLeft,
|
||||||
RelativeSizeAxes = Axes.Both,
|
},
|
||||||
Colour = colourProvider.Background6,
|
starCounter = new StarCounter
|
||||||
},
|
{
|
||||||
}
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Scale = new Vector2(8f / 20f),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
outerLayer = new Box
|
new CircularContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Anchor = Anchor.CentreRight,
|
||||||
Colour = colourProvider.Background3,
|
Origin = Anchor.CentreRight,
|
||||||
},
|
Size = new Vector2(50f, 14f),
|
||||||
new Container
|
Margin = new MarginPadding { Right = 20f },
|
||||||
{
|
Masking = true,
|
||||||
RelativeSizeAxes = Axes.Both,
|
Children = new Drawable[]
|
||||||
Padding = new MarginPadding { Left = 10f },
|
|
||||||
Child = new Container
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
new Box
|
||||||
CornerRadius = 10f,
|
|
||||||
Masking = true,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
new Box
|
RelativeSizeAxes = Axes.Both,
|
||||||
{
|
Colour = Color4.Black.Opacity(0.7f),
|
||||||
RelativeSizeAxes = Axes.Both,
|
},
|
||||||
Colour = Color4.Black.Opacity(0.2f),
|
new OsuSpriteText
|
||||||
},
|
{
|
||||||
new FillFlowContainer
|
Anchor = Anchor.Centre,
|
||||||
{
|
Origin = Anchor.Centre,
|
||||||
Anchor = Anchor.CentreLeft,
|
Font = OsuFont.Torus.With(size: 14.4f, weight: FontWeight.Bold),
|
||||||
Origin = Anchor.CentreLeft,
|
// TODO: requires Carousel/CarouselItem-side implementation
|
||||||
AutoSizeAxes = Axes.Both,
|
Text = "43",
|
||||||
Spacing = new Vector2(10f, 0f),
|
UseFullGlyphHeight = false,
|
||||||
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,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
}
|
||||||
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();
|
base.LoadComplete();
|
||||||
|
|
||||||
Expanded.BindValueChanged(_ => updateExpandedDisplay(), true);
|
Expanded.BindValueChanged(_ => onExpanded(), true);
|
||||||
KeyboardSelected.BindValueChanged(_ => updateKeyboardSelectedDisplay(), 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.
|
chevronIcon.ResizeWidthTo(Expanded.Value ? 12f : 0f, duration, Easing.OutQuint);
|
||||||
|
chevronIcon.FadeTo(Expanded.Value ? 1f : 0f, duration, Easing.OutQuint);
|
||||||
activationFlash.FadeTo(0.2f).FadeTo(0f, 500, Easing.OutQuint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PrepareForUse()
|
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 colour = group.StarNumber >= 9 ? OsuColour.Gray(0.2f) : colours.ForStarDifficulty(group.StarNumber);
|
||||||
Color4 contentColour = group.StarNumber >= 7 ? colours.Orange1 : colourProvider.Background5;
|
Color4 contentColour = group.StarNumber >= 7 ? colours.Orange1 : colourProvider.Background5;
|
||||||
|
|
||||||
outerLayer.Colour = colour;
|
panel.AccentColour = colour;
|
||||||
starCounter.Colour = contentColour;
|
contentBackground.Colour = colour.Darken(0.3f);
|
||||||
|
|
||||||
starRatingDisplay.Current.Value = new StarDifficulty(group.StarNumber, 0);
|
starRatingDisplay.Current.Value = new StarDifficulty(group.StarNumber, 0);
|
||||||
starCounter.Current = group.StarNumber;
|
starCounter.Current = group.StarNumber;
|
||||||
|
|
||||||
|
chevronIcon.Colour = contentColour;
|
||||||
|
starCounter.Colour = contentColour;
|
||||||
|
|
||||||
this.FadeInFromZero(500, Easing.OutQuint);
|
this.FadeInFromZero(500, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,47 +179,6 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
return true;
|
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
|
#region ICarouselPanel
|
||||||
|
|
||||||
public CarouselItem? Item { get; set; }
|
public CarouselItem? Item { get; set; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user