mirror of
https://github.com/ppy/osu.git
synced 2025-01-30 04:23:21 +08:00
Add basic selection support
This commit is contained in:
parent
5e9a7532d3
commit
288be46b17
@ -14,6 +14,7 @@ using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
@ -23,6 +24,7 @@ using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
[Cached]
|
||||
public partial class BeatmapCarouselV2 : Carousel
|
||||
{
|
||||
private IBindableList<BeatmapSetInfo> detachedBeatmaps = null!;
|
||||
@ -102,7 +104,48 @@ namespace osu.Game.Screens.SelectV2
|
||||
|
||||
public partial class BeatmapCarouselPanel : PoolableDrawable, ICarouselPanel
|
||||
{
|
||||
public CarouselItem? Item { get; set; }
|
||||
[Resolved]
|
||||
private BeatmapCarouselV2 carousel { get; set; } = null!;
|
||||
|
||||
public CarouselItem? Item
|
||||
{
|
||||
get => item;
|
||||
set
|
||||
{
|
||||
item = value;
|
||||
|
||||
selected.UnbindBindings();
|
||||
|
||||
if (item != null)
|
||||
selected.BindTo(item.Selected);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly BindableBool selected = new BindableBool();
|
||||
private CarouselItem? item;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
selected.BindValueChanged(value =>
|
||||
{
|
||||
if (value.NewValue)
|
||||
{
|
||||
BorderThickness = 5;
|
||||
BorderColour = Color4.Pink;
|
||||
}
|
||||
else
|
||||
{
|
||||
BorderThickness = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override void FreeAfterUse()
|
||||
{
|
||||
base.FreeAfterUse();
|
||||
Item = null;
|
||||
}
|
||||
|
||||
protected override void PrepareForUse()
|
||||
{
|
||||
@ -111,6 +154,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
Debug.Assert(Item != null);
|
||||
|
||||
Size = new Vector2(500, Item.DrawHeight);
|
||||
Masking = true;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
@ -128,6 +172,12 @@ namespace osu.Game.Screens.SelectV2
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected override bool OnClick(ClickEvent e)
|
||||
{
|
||||
carousel.CurrentSelection = Item!.Model;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class BeatmapCarouselItem : CarouselItem
|
||||
@ -165,7 +215,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
|
||||
CarouselItem? lastItem = null;
|
||||
|
||||
var newItems = new List<CarouselItem>();
|
||||
var newItems = new List<CarouselItem>(items.Count());
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
|
@ -77,8 +77,28 @@ namespace osu.Game.Screens.SelectV2
|
||||
/// All items which are to be considered for display in this carousel.
|
||||
/// Mutating this list will automatically queue a <see cref="QueueFilter"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that an <see cref="ICarouselFilter"/> may add new items which are displayed but not tracked in this list.
|
||||
/// </remarks>
|
||||
protected readonly BindableList<CarouselItem> Items = new BindableList<CarouselItem>();
|
||||
|
||||
/// <summary>
|
||||
/// The currently selected model.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Setting this will ensure <see cref="CarouselItem.Selected"/> is set to <c>true</c> only on the matching <see cref="CarouselItem"/>.
|
||||
/// Of note, if no matching item exists all items will be deselected while waiting for potential new item which matches.
|
||||
/// </remarks>
|
||||
public virtual object? CurrentSelection
|
||||
{
|
||||
get => currentSelection;
|
||||
set
|
||||
{
|
||||
currentSelection = value;
|
||||
updateSelection();
|
||||
}
|
||||
}
|
||||
|
||||
private List<CarouselItem>? displayedCarouselItems;
|
||||
|
||||
private readonly DoublePrecisionScroll scroll;
|
||||
@ -169,6 +189,8 @@ namespace osu.Game.Screens.SelectV2
|
||||
displayedCarouselItems = items.ToList();
|
||||
displayedRange = null;
|
||||
|
||||
updateSelection();
|
||||
|
||||
void log(string text) => Logger.Log($"Carousel[op {cts.GetHashCode().ToString().Substring(0, 5)}] {stopwatch.ElapsedMilliseconds} ms: {text}");
|
||||
}
|
||||
|
||||
@ -186,6 +208,24 @@ namespace osu.Game.Screens.SelectV2
|
||||
|
||||
#endregion
|
||||
|
||||
#region Selection handling
|
||||
|
||||
private object? currentSelection;
|
||||
|
||||
private void updateSelection()
|
||||
{
|
||||
if (displayedCarouselItems == null) return;
|
||||
|
||||
// TODO: this is ugly, we probably should stop exposing CarouselItem externally.
|
||||
foreach (var item in Items)
|
||||
item.Selected.Value = item.Model == currentSelection;
|
||||
|
||||
foreach (var item in displayedCarouselItems)
|
||||
item.Selected.Value = item.Model == currentSelection;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Display handling
|
||||
|
||||
private DisplayRange? displayedRange;
|
||||
|
@ -2,22 +2,25 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Bindables;
|
||||
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single display item for display in a <see cref="Carousel"/>.
|
||||
/// Represents a single display item for display in a <see cref="Carousel{T}"/>.
|
||||
/// This is used to house information related to the attached model that helps with display and tracking.
|
||||
/// </summary>
|
||||
public abstract class CarouselItem : IComparable<CarouselItem>
|
||||
{
|
||||
public readonly BindableBool Selected = new BindableBool();
|
||||
|
||||
/// <summary>
|
||||
/// The model this item is representing.
|
||||
/// </summary>
|
||||
public readonly object Model;
|
||||
|
||||
/// <summary>
|
||||
/// The current Y position in the carousel. This is managed by <see cref="Carousel"/> and should not be set manually.
|
||||
/// The current Y position in the carousel. This is managed by <see cref="Carousel{T}"/> and should not be set manually.
|
||||
/// </summary>
|
||||
public double CarouselYPosition { get; set; }
|
||||
|
||||
|
@ -8,7 +8,7 @@ using System.Threading.Tasks;
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface representing a filter operation which can be run on a <see cref="Carousel"/>.
|
||||
/// An interface representing a filter operation which can be run on a <see cref="Carousel{T}"/>.
|
||||
/// </summary>
|
||||
public interface ICarouselFilter
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ using osu.Framework.Graphics;
|
||||
namespace osu.Game.Screens.SelectV2
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface to be attached to any <see cref="Drawable"/>s which are used for display inside a <see cref="Carousel"/>.
|
||||
/// An interface to be attached to any <see cref="Drawable"/>s which are used for display inside a <see cref="Carousel{T}"/>.
|
||||
/// </summary>
|
||||
public interface ICarouselPanel
|
||||
{
|
||||
@ -16,7 +16,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
double YPosition => Item!.CarouselYPosition;
|
||||
|
||||
/// <summary>
|
||||
/// The carousel item this drawable is representing. This is managed by <see cref="Carousel"/> and should not be set manually.
|
||||
/// The carousel item this drawable is representing. This is managed by <see cref="Carousel{T}"/> and should not be set manually.
|
||||
/// </summary>
|
||||
CarouselItem? Item { get; set; }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user