1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-31 00:02:56 +08:00
osu-lazer/osu.Game/Screens/Select/Carousel/DrawableCarouselItem.cs

178 lines
5.0 KiB
C#
Raw Normal View History

// 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.
2018-04-13 17:19:50 +08:00
2020-10-12 14:36:03 +08:00
using System.Diagnostics;
using osu.Framework.Bindables;
2018-04-13 17:19:50 +08:00
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
2020-10-12 14:36:03 +08:00
using osu.Framework.Graphics.Pooling;
2018-10-02 11:02:47 +08:00
using osu.Framework.Input.Events;
using osuTK;
2018-04-13 17:19:50 +08:00
namespace osu.Game.Screens.Select.Carousel
{
2022-11-24 13:32:20 +08:00
public abstract partial class DrawableCarouselItem : PoolableDrawable
2018-04-13 17:19:50 +08:00
{
public const float MAX_HEIGHT = 80;
2020-10-12 14:36:03 +08:00
public override bool IsPresent => base.IsPresent || Item?.Visible == true;
2018-04-13 17:19:50 +08:00
public override bool HandlePositionalInput => Item?.Visible == true;
public override bool PropagatePositionalInputSubTree => Item?.Visible == true;
public readonly CarouselHeader Header;
2020-10-13 14:32:37 +08:00
/// <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);
2023-01-09 02:02:48 +08:00
private CarouselItem? item;
2023-01-09 02:02:48 +08:00
public CarouselItem? Item
2020-10-12 14:36:03 +08:00
{
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;
}
2020-10-12 14:36:03 +08:00
}
2018-04-13 17:19:50 +08:00
2020-10-12 14:36:03 +08:00
item = value;
2023-05-03 17:45:09 +08:00
if (IsLoaded && !IsDisposed)
2020-10-12 14:36:03 +08:00
UpdateItem();
}
}
2018-04-13 17:19:50 +08:00
protected DrawableCarouselItem()
2018-04-13 17:19:50 +08:00
{
RelativeSizeAxes = Axes.X;
Alpha = 0;
InternalChildren = new Drawable[]
2018-04-13 17:19:50 +08:00
{
MovementContainer = new Container
2018-04-13 17:19:50 +08:00
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
2018-04-13 17:19:50 +08:00
{
Header = new CarouselHeader(),
Content = new Container
{
RelativeSizeAxes = Axes.Both,
}
}
},
2018-04-13 17:19:50 +08:00
};
}
public void SetMultiplicativeAlpha(float alpha) => Header.BorderContainer.Alpha = alpha;
2018-04-13 17:19:50 +08:00
protected override void LoadComplete()
{
base.LoadComplete();
UpdateItem();
}
protected override void Update()
{
base.Update();
Content.Y = Header.Height;
}
2020-10-12 14:36:03 +08:00
protected virtual void UpdateItem()
{
if (Item == null)
2020-10-12 14:36:03 +08:00
return;
2020-10-12 17:13:25 +08:00
Scheduler.AddOnce(ApplyState);
2020-10-12 14:36:03 +08:00
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;
}
2018-04-13 17:19:50 +08:00
}
2020-10-12 17:13:25 +08:00
private void onStateChange(ValueChangedEvent<CarouselItemState> obj) => Scheduler.AddOnce(ApplyState);
2020-10-12 14:36:03 +08:00
2020-10-12 17:13:25 +08:00
private void onStateChange(ValueChangedEvent<bool> _) => Scheduler.AddOnce(ApplyState);
2020-10-12 14:36:03 +08:00
2018-04-13 17:19:50 +08:00
protected virtual void ApplyState()
{
2023-01-10 16:52:28 +08:00
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;
2018-04-13 17:19:50 +08:00
switch (Item.State.Value)
2018-04-13 17:19:50 +08:00
{
case CarouselItemState.NotSelected:
Deselected();
break;
case CarouselItemState.Selected:
Selected();
break;
2018-04-13 17:19:50 +08:00
}
if (!Item.Visible)
this.FadeOut(100, Easing.OutQuint);
2018-04-13 17:19:50 +08:00
else
this.FadeIn(400, Easing.OutQuint);
2018-04-13 17:19:50 +08:00
}
protected virtual void Selected()
{
2020-10-12 14:36:03 +08:00
Debug.Assert(Item != null);
2018-04-13 17:19:50 +08:00
}
protected virtual void Deselected()
{
}
2018-10-02 11:02:47 +08:00
protected override bool OnClick(ClickEvent e)
2018-04-13 17:19:50 +08:00
{
Debug.Assert(Item != null);
Item.State.Value = CarouselItemState.Selected;
2018-04-13 17:19:50 +08:00
return true;
}
2023-05-03 17:45:09 +08:00
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
// This is important to clean up event subscriptions.
Item = null;
}
2018-04-13 17:19:50 +08:00
}
}