diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 775b4ad7b6..bcdbc53e26 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -841,7 +841,7 @@ namespace osu.Game.Screens.Select /// For nested items, the parent of the item to be updated. private void updateItem(DrawableCarouselItem item, DrawableCarouselItem parent = null) { - Vector2 posInScroll = scrollableContent.ToLocalSpace(item.ScreenSpaceDrawQuad.Centre); + Vector2 posInScroll = scrollableContent.ToLocalSpace(item.Header.ScreenSpaceDrawQuad.Centre); float itemDrawY = posInScroll.Y - visibleUpperBound; float dist = Math.Abs(1f - itemDrawY / visibleHalfHeight); diff --git a/osu.Game/Screens/Select/Carousel/CarouselHeader.cs b/osu.Game/Screens/Select/Carousel/CarouselHeader.cs new file mode 100644 index 0000000000..f59cccd8b6 --- /dev/null +++ b/osu.Game/Screens/Select/Carousel/CarouselHeader.cs @@ -0,0 +1,108 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Audio; +using osu.Framework.Audio.Sample; +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.Shapes; +using osu.Framework.Input.Events; +using osu.Framework.Utils; +using osu.Game.Graphics; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Screens.Select.Carousel +{ + public class CarouselHeader : Container + { + private SampleChannel sampleHover; + + private readonly Box hoverLayer; + + public Container BorderContainer; + + public readonly Bindable State = new Bindable(CarouselItemState.NotSelected); + + protected override Container Content { get; } = new Container { RelativeSizeAxes = Axes.Both }; + + public CarouselHeader() + { + RelativeSizeAxes = Axes.X; + Height = DrawableCarouselItem.MAX_HEIGHT; + + InternalChild = BorderContainer = new Container + { + RelativeSizeAxes = Axes.Both, + Masking = true, + CornerRadius = 10, + BorderColour = new Color4(221, 255, 255, 255), + Children = new Drawable[] + { + Content, + hoverLayer = new Box + { + RelativeSizeAxes = Axes.Both, + Alpha = 0, + Blending = BlendingParameters.Additive, + }, + } + }; + } + + [BackgroundDependencyLoader] + private void load(AudioManager audio, OsuColour colours) + { + sampleHover = audio.Samples.Get($@"SongSelect/song-ping-variation-{RNG.Next(1, 5)}"); + hoverLayer.Colour = colours.Blue.Opacity(0.1f); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + State.BindValueChanged(updateState, true); + } + + private void updateState(ValueChangedEvent state) + { + switch (state.NewValue) + { + case CarouselItemState.Collapsed: + case CarouselItemState.NotSelected: + BorderContainer.BorderThickness = 0; + BorderContainer.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Shadow, Offset = new Vector2(1), Radius = 10, Colour = Color4.Black.Opacity(100), + }; + break; + + case CarouselItemState.Selected: + BorderContainer.BorderThickness = 2.5f; + BorderContainer.EdgeEffect = new EdgeEffectParameters + { + Type = EdgeEffectType.Glow, Colour = new Color4(130, 204, 255, 150), Radius = 20, Roundness = 10, + }; + break; + } + } + + protected override bool OnHover(HoverEvent e) + { + sampleHover?.Play(); + + hoverLayer.FadeIn(100, Easing.OutQuint); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + hoverLayer.FadeOut(1000, Easing.OutQuint); + base.OnHoverLost(e); + } + } +} diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 23404a6c6e..b06b60e6c5 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -64,15 +64,14 @@ namespace osu.Game.Screens.Select.Carousel public DrawableCarouselBeatmap(CarouselBeatmap panel) { beatmap = panel.Beatmap; - Height = HEIGHT; - - // todo: temporary Item = panel; } [BackgroundDependencyLoader(true)] private void load(BeatmapManager manager, SongSelect songSelect) { + Header.Height = HEIGHT; + if (songSelect != null) { startRequested = b => songSelect.FinaliseSelection(b); @@ -83,7 +82,7 @@ namespace osu.Game.Screens.Select.Carousel if (manager != null) hideRequested = manager.Hide; - Content.Children = new Drawable[] + Header.Children = new Drawable[] { background = new Box { @@ -174,7 +173,7 @@ namespace osu.Game.Screens.Select.Carousel { base.Selected(); - BorderContainer.MoveToX(-50, 500, Easing.OutExpo); + Header.MoveToX(-50, 500, Easing.OutExpo); background.Colour = ColourInfo.GradientVertical( new Color4(20, 43, 51, 255), @@ -187,7 +186,7 @@ namespace osu.Game.Screens.Select.Carousel { base.Deselected(); - BorderContainer.MoveToX(0, 500, Easing.OutExpo); + Header.MoveToX(0, 500, Easing.OutExpo); background.Colour = new Color4(20, 43, 51, 255); triangles.Colour = OsuColour.Gray(0.5f); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 635eb6f375..e1a2ce3962 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -67,16 +67,12 @@ namespace osu.Game.Screens.Select.Carousel if (beatmapOverlay != null) viewDetails = beatmapOverlay.FetchAndShowBeatmapSet; - // TODO: temporary. we probably want to *not* inherit DrawableCarouselItem for this class, but only the above header portion. - AddRangeInternal(new Drawable[] + Content.Add(beatmapContainer = new Container { - beatmapContainer = new Container - { - X = 50, - Y = MAX_HEIGHT, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }, + X = 50, + Y = MAX_HEIGHT, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, }); } @@ -90,7 +86,7 @@ namespace osu.Game.Screens.Select.Carousel return; Logger.Log($"updating item {beatmapSet}"); - Content.Children = new Drawable[] + Header.Children = new Drawable[] { new DelayedLoadUnloadWrapper(() => { @@ -163,7 +159,7 @@ namespace osu.Game.Screens.Select.Carousel { base.Deselected(); - BorderContainer.MoveToX(0, 500, Easing.OutExpo); + MovementContainer.MoveToX(0, 500, Easing.OutExpo); foreach (var beatmap in beatmapContainer) { @@ -176,7 +172,7 @@ namespace osu.Game.Screens.Select.Carousel { base.Selected(); - BorderContainer.MoveToX(-100, 500, Easing.OutExpo); + MovementContainer.MoveToX(-100, 500, Easing.OutExpo); // on selection we show our child beatmaps. // for now this is a simple drawable construction each selection. diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs index 8cf63d184c..6a9b60fa57 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs @@ -4,21 +4,11 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using osu.Framework.Allocation; -using osu.Framework.Audio; -using osu.Framework.Audio.Sample; 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.Utils; -using osu.Game.Graphics; -using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Select.Carousel { @@ -28,6 +18,14 @@ namespace osu.Game.Screens.Select.Carousel public override bool IsPresent => base.IsPresent || Item?.Visible == true; + public readonly CarouselHeader Header; + + protected readonly Container Content; + + protected readonly Container MovementContainer; + + private CarouselItem item; + public CarouselItem Item { get => item; @@ -38,8 +36,10 @@ namespace osu.Game.Screens.Select.Carousel if (item != null) { - Item.Filtered.ValueChanged -= onStateChange; - Item.State.ValueChanged -= onStateChange; + item.Filtered.ValueChanged -= onStateChange; + item.State.ValueChanged -= onStateChange; + + Header.State.UnbindFrom(item.State); if (item is CarouselGroup group) { @@ -57,67 +57,33 @@ namespace osu.Game.Screens.Select.Carousel public virtual IEnumerable ChildItems => Enumerable.Empty(); - private readonly Container nestedContainer; - - protected readonly Container BorderContainer; - - private readonly Box hoverLayer; - - protected Container Content => nestedContainer; - protected DrawableCarouselItem() { - Height = MAX_HEIGHT; RelativeSizeAxes = Axes.X; + AutoSizeAxes = Axes.Y; + Alpha = 0; - InternalChild = BorderContainer = new Container + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.Both, - Masking = true, - CornerRadius = 10, - BorderColour = new Color4(221, 255, 255, 255), - Children = new Drawable[] + MovementContainer = new Container { - nestedContainer = new Container + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] { - RelativeSizeAxes = Axes.Both, - }, - hoverLayer = new Box - { - RelativeSizeAxes = Axes.Both, - Alpha = 0, - Blending = BlendingParameters.Additive, - }, - } + Header = new CarouselHeader(), + Content = new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + } + } + }, }; } - private SampleChannel sampleHover; - private CarouselItem item; - - [BackgroundDependencyLoader] - private void load(AudioManager audio, OsuColour colours) - { - sampleHover = audio.Samples.Get($@"SongSelect/song-ping-variation-{RNG.Next(1, 5)}"); - hoverLayer.Colour = colours.Blue.Opacity(0.1f); - } - - protected override bool OnHover(HoverEvent e) - { - sampleHover?.Play(); - - hoverLayer.FadeIn(100, Easing.OutQuint); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - hoverLayer.FadeOut(1000, Easing.OutQuint); - base.OnHoverLost(e); - } - - public void SetMultiplicativeAlpha(float alpha) => BorderContainer.Alpha = alpha; + public void SetMultiplicativeAlpha(float alpha) => Header.BorderContainer.Alpha = alpha; protected override void LoadComplete() { @@ -136,6 +102,8 @@ namespace osu.Game.Screens.Select.Carousel Item.Filtered.ValueChanged += onStateChange; Item.State.ValueChanged += onStateChange; + Header.State.BindTo(Item.State); + if (Item is CarouselGroup group) { foreach (var c in group.Children) @@ -171,31 +139,10 @@ namespace osu.Game.Screens.Select.Carousel protected virtual void Selected() { Debug.Assert(Item != null); - - Item.State.Value = CarouselItemState.Selected; - - BorderContainer.BorderThickness = 2.5f; - BorderContainer.EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Glow, - Colour = new Color4(130, 204, 255, 150), - Radius = 20, - Roundness = 10, - }; } protected virtual void Deselected() { - Item.State.Value = CarouselItemState.NotSelected; - - BorderContainer.BorderThickness = 0; - BorderContainer.EdgeEffect = new EdgeEffectParameters - { - Type = EdgeEffectType.Shadow, - Offset = new Vector2(1), - Radius = 10, - Colour = Color4.Black.Opacity(100), - }; } protected override bool OnClick(ClickEvent e)