mirror of
https://github.com/ppy/osu.git
synced 2025-01-31 05:32:57 +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;
|
||||||
using osu.Framework.Graphics.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
@ -23,6 +24,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.SelectV2
|
namespace osu.Game.Screens.SelectV2
|
||||||
{
|
{
|
||||||
|
[Cached]
|
||||||
public partial class BeatmapCarouselV2 : Carousel
|
public partial class BeatmapCarouselV2 : Carousel
|
||||||
{
|
{
|
||||||
private IBindableList<BeatmapSetInfo> detachedBeatmaps = null!;
|
private IBindableList<BeatmapSetInfo> detachedBeatmaps = null!;
|
||||||
@ -102,7 +104,48 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
|
|
||||||
public partial class BeatmapCarouselPanel : PoolableDrawable, ICarouselPanel
|
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()
|
protected override void PrepareForUse()
|
||||||
{
|
{
|
||||||
@ -111,6 +154,7 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
Debug.Assert(Item != null);
|
Debug.Assert(Item != null);
|
||||||
|
|
||||||
Size = new Vector2(500, Item.DrawHeight);
|
Size = new Vector2(500, Item.DrawHeight);
|
||||||
|
Masking = true;
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
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
|
public class BeatmapCarouselItem : CarouselItem
|
||||||
@ -165,7 +215,7 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
|
|
||||||
CarouselItem? lastItem = null;
|
CarouselItem? lastItem = null;
|
||||||
|
|
||||||
var newItems = new List<CarouselItem>();
|
var newItems = new List<CarouselItem>(items.Count());
|
||||||
|
|
||||||
foreach (var item in items)
|
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.
|
/// All items which are to be considered for display in this carousel.
|
||||||
/// Mutating this list will automatically queue a <see cref="QueueFilter"/>.
|
/// Mutating this list will automatically queue a <see cref="QueueFilter"/>.
|
||||||
/// </summary>
|
/// </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>();
|
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 List<CarouselItem>? displayedCarouselItems;
|
||||||
|
|
||||||
private readonly DoublePrecisionScroll scroll;
|
private readonly DoublePrecisionScroll scroll;
|
||||||
@ -169,6 +189,8 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
displayedCarouselItems = items.ToList();
|
displayedCarouselItems = items.ToList();
|
||||||
displayedRange = null;
|
displayedRange = null;
|
||||||
|
|
||||||
|
updateSelection();
|
||||||
|
|
||||||
void log(string text) => Logger.Log($"Carousel[op {cts.GetHashCode().ToString().Substring(0, 5)}] {stopwatch.ElapsedMilliseconds} ms: {text}");
|
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
|
#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
|
#region Display handling
|
||||||
|
|
||||||
private DisplayRange? displayedRange;
|
private DisplayRange? displayedRange;
|
||||||
|
@ -2,22 +2,25 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
|
||||||
namespace osu.Game.Screens.SelectV2
|
namespace osu.Game.Screens.SelectV2
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <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.
|
/// This is used to house information related to the attached model that helps with display and tracking.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class CarouselItem : IComparable<CarouselItem>
|
public abstract class CarouselItem : IComparable<CarouselItem>
|
||||||
{
|
{
|
||||||
|
public readonly BindableBool Selected = new BindableBool();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The model this item is representing.
|
/// The model this item is representing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly object Model;
|
public readonly object Model;
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public double CarouselYPosition { get; set; }
|
public double CarouselYPosition { get; set; }
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ using System.Threading.Tasks;
|
|||||||
namespace osu.Game.Screens.SelectV2
|
namespace osu.Game.Screens.SelectV2
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public interface ICarouselFilter
|
public interface ICarouselFilter
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@ using osu.Framework.Graphics;
|
|||||||
namespace osu.Game.Screens.SelectV2
|
namespace osu.Game.Screens.SelectV2
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public interface ICarouselPanel
|
public interface ICarouselPanel
|
||||||
{
|
{
|
||||||
@ -16,7 +16,7 @@ namespace osu.Game.Screens.SelectV2
|
|||||||
double YPosition => Item!.CarouselYPosition;
|
double YPosition => Item!.CarouselYPosition;
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
CarouselItem? Item { get; set; }
|
CarouselItem? Item { get; set; }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user