mirror of
https://github.com/ppy/osu.git
synced 2024-11-16 09:17:48 +08:00
f84ee3996f
I made these changes while working on https://github.com/ppy/osu/pull/30579. Basically, it's hard to fix the ranks not loading while underneath the footer, and the transparency both looks bad, and is going away in the redesign. I've chosen values here that are moving *in the direction* of the new design without overhauling everything. - I know that there's still some transparency. I did this because it helps keep all current elements / colours contrasting without too much effort. - I completely removed the transparency adjustments on the beatmap panels. This always looked bad due to being applied per-layer, and I don't think it added much.
178 lines
5.0 KiB
C#
178 lines
5.0 KiB
C#
// 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 System.Diagnostics;
|
|
using osu.Framework.Bindables;
|
|
using osu.Framework.Graphics;
|
|
using osu.Framework.Graphics.Containers;
|
|
using osu.Framework.Graphics.Pooling;
|
|
using osu.Framework.Input.Events;
|
|
using osuTK;
|
|
|
|
namespace osu.Game.Screens.Select.Carousel
|
|
{
|
|
public abstract partial class DrawableCarouselItem : PoolableDrawable
|
|
{
|
|
public const float MAX_HEIGHT = 80;
|
|
|
|
public override bool IsPresent => base.IsPresent || Item?.Visible == true;
|
|
|
|
public override bool HandlePositionalInput => Item?.Visible == true;
|
|
public override bool PropagatePositionalInputSubTree => Item?.Visible == true;
|
|
|
|
public readonly CarouselHeader Header;
|
|
|
|
/// <summary>
|
|
/// Optional content which sits below the header.
|
|
/// </summary>
|
|
protected readonly Container<Drawable> Content;
|
|
|
|
protected readonly Container MovementContainer;
|
|
|
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
|
|
Header.ReceivePositionalInputAt(screenSpacePos);
|
|
|
|
private CarouselItem? item;
|
|
|
|
public CarouselItem? Item
|
|
{
|
|
get => item;
|
|
set
|
|
{
|
|
if (item == value)
|
|
return;
|
|
|
|
if (item != null)
|
|
{
|
|
item.Filtered.ValueChanged -= onStateChange;
|
|
item.State.ValueChanged -= onStateChange;
|
|
|
|
Header.State.UnbindFrom(item.State);
|
|
|
|
if (item is CarouselGroup group)
|
|
{
|
|
foreach (var c in group.Items)
|
|
c.Filtered.ValueChanged -= onStateChange;
|
|
}
|
|
}
|
|
|
|
item = value;
|
|
|
|
if (IsLoaded && !IsDisposed)
|
|
UpdateItem();
|
|
}
|
|
}
|
|
|
|
protected DrawableCarouselItem()
|
|
{
|
|
RelativeSizeAxes = Axes.X;
|
|
|
|
Alpha = 0;
|
|
|
|
InternalChildren = new Drawable[]
|
|
{
|
|
MovementContainer = new Container
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
Children = new Drawable[]
|
|
{
|
|
Header = new CarouselHeader(),
|
|
Content = new Container
|
|
{
|
|
RelativeSizeAxes = Axes.Both,
|
|
}
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
protected override void LoadComplete()
|
|
{
|
|
base.LoadComplete();
|
|
|
|
UpdateItem();
|
|
}
|
|
|
|
protected override void Update()
|
|
{
|
|
base.Update();
|
|
Content.Y = Header.Height;
|
|
}
|
|
|
|
protected virtual void UpdateItem()
|
|
{
|
|
if (Item == null)
|
|
return;
|
|
|
|
Scheduler.AddOnce(ApplyState);
|
|
|
|
Item.Filtered.ValueChanged += onStateChange;
|
|
Item.State.ValueChanged += onStateChange;
|
|
|
|
Header.State.BindTo(Item.State);
|
|
|
|
if (Item is CarouselGroup group)
|
|
{
|
|
foreach (var c in group.Items)
|
|
c.Filtered.ValueChanged += onStateChange;
|
|
}
|
|
}
|
|
|
|
private void onStateChange(ValueChangedEvent<CarouselItemState> obj) => Scheduler.AddOnce(ApplyState);
|
|
|
|
private void onStateChange(ValueChangedEvent<bool> _) => Scheduler.AddOnce(ApplyState);
|
|
|
|
protected virtual void ApplyState()
|
|
{
|
|
Debug.Assert(Item != null);
|
|
|
|
// Use the fact that we know the precise height of the item from the model to avoid the need for AutoSize overhead.
|
|
// Additionally, AutoSize doesn't work well due to content starting off-screen and being masked away.
|
|
Height = Item.TotalHeight;
|
|
|
|
switch (Item.State.Value)
|
|
{
|
|
case CarouselItemState.NotSelected:
|
|
Deselected();
|
|
break;
|
|
|
|
case CarouselItemState.Selected:
|
|
Selected();
|
|
break;
|
|
}
|
|
|
|
if (!Item.Visible)
|
|
this.FadeOut(100, Easing.OutQuint);
|
|
else
|
|
this.FadeIn(400, Easing.OutQuint);
|
|
}
|
|
|
|
protected virtual void Selected()
|
|
{
|
|
Debug.Assert(Item != null);
|
|
}
|
|
|
|
protected virtual void Deselected()
|
|
{
|
|
}
|
|
|
|
protected override bool OnClick(ClickEvent e)
|
|
{
|
|
Debug.Assert(Item != null);
|
|
|
|
Item.State.Value = CarouselItemState.Selected;
|
|
return true;
|
|
}
|
|
|
|
protected override bool OnHover(HoverEvent e) => true;
|
|
|
|
protected override void Dispose(bool isDisposing)
|
|
{
|
|
base.Dispose(isDisposing);
|
|
|
|
// This is important to clean up event subscriptions.
|
|
Item = null;
|
|
}
|
|
}
|
|
}
|