1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-15 14:03:01 +08:00

Store y positions inside items rather than in a separate array

This commit is contained in:
Dean Herbert 2020-10-13 13:21:21 +09:00
parent b92c22ad42
commit f6aa448523
2 changed files with 46 additions and 18 deletions

View File

@ -116,7 +116,6 @@ namespace osu.Game.Screens.Select
});
}
private readonly List<float> yPositions = new List<float>();
private readonly List<CarouselItem> visibleItems = new List<CarouselItem>();
private readonly Cached itemsCache = new Cached();
@ -570,23 +569,15 @@ namespace osu.Game.Screens.Select
if (revalidateItems)
updateYPositions();
// Find index range of all items that should be on-screen
int firstIndex = yPositions.BinarySearch(visibleUpperBound);
if (firstIndex < 0) firstIndex = ~firstIndex;
int lastIndex = yPositions.BinarySearch(visibleBottomBound);
if (lastIndex < 0) lastIndex = ~lastIndex;
// as we can't be 100% sure on the size of individual carousel drawables,
// always play it safe and extend bounds by one.
firstIndex = Math.Max(0, firstIndex - 1);
lastIndex = Math.Min(yPositions.Count, lastIndex + 1);
var (firstIndex, lastIndex) = getDisplayRange();
if (revalidateItems || firstIndex != displayedRange.first || lastIndex != displayedRange.last)
{
Logger.Log("revalidation requested");
// Remove all items that should no longer be on-screen
scrollableContent.RemoveAll(p => p.Y + p.Item.TotalHeight < visibleUpperBound || p.Y > visibleBottomBound);
// TODO: figure out a more resilient way of doing this removal.
// scrollableContent.RemoveAll(p => p.Y + p.Item.TotalHeight < visibleUpperBound || p.Y > visibleBottomBound);
displayedRange = (firstIndex, lastIndex);
@ -601,7 +592,7 @@ namespace osu.Game.Screens.Select
{
Logger.Log($"getting panel for {item} from pool");
panel = setPool.Get(p => p.Item = item);
panel.Y = yPositions[i];
panel.Y = item.CarouselYPosition;
panel.Depth = i;
panel.ClearTransforms();
@ -611,9 +602,9 @@ namespace osu.Game.Screens.Select
else
{
if (panel.IsPresent)
panel.MoveToY(yPositions[i], 800, Easing.OutQuint);
panel.MoveToY(item.CarouselYPosition, 800, Easing.OutQuint);
else
panel.Y = yPositions[i];
panel.Y = item.CarouselYPosition;
scrollableContent.ChangeChildDepth(panel, i);
}
@ -626,6 +617,22 @@ namespace osu.Game.Screens.Select
updateItem(p);
}
private (int firstIndex, int lastIndex) getDisplayRange()
{
// Find index range of all items that should be on-screen
// TODO: reduce allocs of CarouselBoundsItem.
int firstIndex = visibleItems.BinarySearch(new CarouselBoundsItem(visibleUpperBound));
if (firstIndex < 0) firstIndex = ~firstIndex;
int lastIndex = visibleItems.BinarySearch(new CarouselBoundsItem(visibleBottomBound));
if (lastIndex < 0) lastIndex = ~lastIndex;
// as we can't be 100% sure on the size of individual carousel drawables,
// always play it safe and extend bounds by one.
firstIndex = Math.Max(0, firstIndex - 1);
lastIndex = Math.Min(visibleItems.Count, lastIndex + 1);
return (firstIndex, lastIndex);
}
protected override void UpdateAfterChildren()
{
base.UpdateAfterChildren();
@ -698,7 +705,6 @@ namespace osu.Game.Screens.Select
/// <returns>The Y position of the currently selected item.</returns>
private void updateYPositions()
{
yPositions.Clear();
visibleItems.Clear();
float currentY = visibleHalfHeight;
@ -715,7 +721,7 @@ namespace osu.Game.Screens.Select
case CarouselBeatmapSet set:
{
visibleItems.Add(set);
yPositions.Add(currentY);
set.CarouselYPosition = currentY;
if (item.State.Value == CarouselItemState.Selected)
{
@ -815,6 +821,20 @@ namespace osu.Game.Screens.Select
p.SetMultiplicativeAlpha(Math.Clamp(1.75f - 1.5f * dist, 0, 1));
}
/// <summary>
/// A carousel item strictly used for binary search purposes.
/// </summary>
private class CarouselBoundsItem : CarouselItem
{
public CarouselBoundsItem(in float pos)
{
CarouselYPosition = pos;
}
public override DrawableCarouselItem CreateDrawableRepresentation() =>
throw new NotImplementedException();
}
private class CarouselRoot : CarouselGroupEagerSelect
{
private readonly BeatmapCarousel carousel;

View File

@ -1,14 +1,20 @@
// 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;
using osu.Framework.Bindables;
namespace osu.Game.Screens.Select.Carousel
{
public abstract class CarouselItem
public abstract class CarouselItem : IComparable<CarouselItem>
{
public virtual float TotalHeight => 0;
/// <summary>
/// An externally defined value used to determine this item's vertical display offset relative to the carousel.
/// </summary>
public float CarouselYPosition;
public readonly BindableBool Filtered = new BindableBool();
public readonly Bindable<CarouselItemState> State = new Bindable<CarouselItemState>(CarouselItemState.NotSelected);
@ -42,6 +48,8 @@ namespace osu.Game.Screens.Select.Carousel
}
public virtual int CompareTo(FilterCriteria criteria, CarouselItem other) => ChildID.CompareTo(other.ChildID);
public int CompareTo(CarouselItem other) => CarouselYPosition.CompareTo(other.CarouselYPosition);
}
public enum CarouselItemState