Skip to content

Commit

Permalink
checkpoint 2
Browse files Browse the repository at this point in the history
  • Loading branch information
peppy committed Jan 22, 2025
1 parent 6bcad44 commit ee7972b
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 26 deletions.
21 changes: 11 additions & 10 deletions osu.Game/Screens/SelectV2/BeatmapCarousel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ private void load(BeatmapStore beatmapStore, CancellationToken? cancellationToke

protected override CarouselItem CreateCarouselItemForModel(BeatmapInfo model) => new CarouselItem(model);

protected override void HandleItemDeselected(List<CarouselItem> allItems, CarouselItem item)
protected override void HandleItemDeselected(object? model)
{
base.HandleItemDeselected(allItems, item);
base.HandleItemDeselected(model);

var deselectedSet = item.Model as BeatmapSetInfo ?? (item.Model as BeatmapInfo)?.BeatmapSet;
var deselectedSet = model as BeatmapSetInfo ?? (model as BeatmapInfo)?.BeatmapSet;

if (grouping.SetGroups.TryGetValue(deselectedSet!, out var group))
{
Expand All @@ -70,26 +70,27 @@ protected override void HandleItemDeselected(List<CarouselItem> allItems, Carous
}
}

protected override void HandleItemSelected(List<CarouselItem> allItems, CarouselItem item)
protected override void HandleItemSelected(object? model)
{
base.HandleItemSelected(allItems, item);
base.HandleItemSelected(model);

// Selecting a set isn't valid – let's re-select the first difficulty.
if (item.Model is BeatmapSetInfo setInfo)
if (model is BeatmapSetInfo setInfo)
{
CurrentSelection = setInfo.Beatmaps.First();
return;
}

var currentSelectionSet = (item.Model as BeatmapInfo)?.BeatmapSet;
var currentSelectionSet = (model as BeatmapInfo)?.BeatmapSet;

if (grouping.SetGroups.TryGetValue(currentSelectionSet!, out var group))
if (currentSelectionSet == null)
return;

if (grouping.SetGroups.TryGetValue(currentSelectionSet, out var group))
{
foreach (var i in group)
i.IsVisible = true;
}

UpdateYPositions(allItems, VisibleHalfHeight, SpacingBetweenPanels);
}

protected override void HandleItemActivated(CarouselItem item)
Expand Down
63 changes: 47 additions & 16 deletions osu.Game/Screens/SelectV2/Carousel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public abstract partial class Carousel<T> : CompositeDrawable, IKeyBindingHandle
/// </remarks>
public virtual object? CurrentSelection
{
get => currentSelection;
get => currentSelection.Model;
set => setSelection(value);
}

Expand Down Expand Up @@ -170,14 +170,14 @@ public void ActivateSelection()
/// <summary>
/// Called when an item is "selected".
/// </summary>
protected virtual void HandleItemSelected(List<CarouselItem> allItems, CarouselItem item)
protected virtual void HandleItemSelected(object? model)
{
}

/// <summary>
/// Called when an item is "deselected".
/// </summary>
protected virtual void HandleItemDeselected(List<CarouselItem> allItems, CarouselItem item)
protected virtual void HandleItemDeselected(object? model)
{
}

Expand Down Expand Up @@ -254,7 +254,7 @@ await Task.Run(async () =>
}

log("Updating Y positions");
UpdateYPositions(items, VisibleHalfHeight, SpacingBetweenPanels);
updateYPositions(items, VisibleHalfHeight, SpacingBetweenPanels);
}
catch (OperationCanceledException)
{
Expand All @@ -269,12 +269,14 @@ await Task.Run(async () =>
displayedCarouselItems = items.ToList();
displayedRange = null;

HandleItemSelected(currentSelection.Model);

updateSelection();

void log(string text) => Logger.Log($"Carousel[op {cts.GetHashCode().ToString()}] {stopwatch.ElapsedMilliseconds} ms: {text}");
}

protected static void UpdateYPositions(IEnumerable<CarouselItem> carouselItems, float offset, float spacing)
private static void updateYPositions(IEnumerable<CarouselItem> carouselItems, float offset, float spacing)
{
float yPos = offset;

Expand Down Expand Up @@ -412,24 +414,39 @@ private void setSelection(object? model)
if (currentSelection.Model == model)
return;

if (displayedCarouselItems != null && currentSelection.CarouselItem != null)
HandleItemDeselected(displayedCarouselItems, currentSelection.CarouselItem);
var previousSelection = currentSelection;
currentSelection = currentKeyboardSelection = new Selection(model);

if (displayedCarouselItems != null && previousSelection.Model != null)
HandleItemDeselected(previousSelection.Model);

HandleItemSelected(model);
// ensure the selection hasn't changed in the handling of selection.
// if it's changed, avoid a second update of selection/scroll.
if (currentSelection.Model != model)
return;

currentKeyboardSelection = currentSelection = new Selection(model);
updateSelection();
scrollToSelection();
}

private void setKeyboardSelection(object? model)
{
currentKeyboardSelection = new Selection(model);

updateSelection();
scrollToSelection();
}

/// <summary>
/// Call after a selection of items change to re-attach <see cref="CarouselItem"/>s to current <see cref="Selection"/>s.
/// </summary>
private void updateSelection()
{
// TODO: hidden values may have changed. this isn't a great way of handling.
float yPos = VisibleHalfHeight;

// Invalidate display range as panel positions and visible status may have changed.
// Position transfer won't happen unless we invalidate this.
displayedRange = null;

if (displayedCarouselItems == null)
Expand All @@ -439,6 +456,19 @@ private void updateSelection()
return;
}

// let's make some early assertions in order to try and optimise this down
//
// when do we arrive here?
// - this method is called after a potential selection change
// (in this case, the selection will not have anything except a model)
// - this method is called after a potential CarouselItem refresh
// (in this case, the selection may have a CarouselItem but it may not be in the current list)
//
// what do we do here?
// - check whether the current selection has changed position (and adjust scroll)
// - update y positions if they have changed (but that can be some separately)

// TODO: we need to be able to avoid this iteration.
for (int i = 0; i < displayedCarouselItems.Count; i++)
{
var item = displayedCarouselItems[i];
Expand All @@ -450,7 +480,7 @@ private void updateSelection()
{
double? previousYPosition = currentKeyboardSelection?.YPosition;

currentKeyboardSelection = new Selection(item.Model, item, item.CarouselYPosition, i);
currentKeyboardSelection = new Selection(item.Model, item, item.CarouselYPosition);

if (previousYPosition != null && previousYPosition != item.CarouselYPosition)
{
Expand All @@ -460,11 +490,12 @@ private void updateSelection()
}

if (isSelected)
{
if (item != currentSelection?.CarouselItem)
HandleItemSelected(displayedCarouselItems, item);
currentSelection = new Selection(item.Model, item, item.CarouselYPosition, i);
}
currentSelection = new Selection(item.Model, item, item.CarouselYPosition);

item.CarouselYPosition = yPos;

if (item.IsVisible)
yPos += item.DrawHeight + SpacingBetweenPanels;
}
}

Expand Down Expand Up @@ -635,7 +666,7 @@ private static void expirePanelImmediately(Drawable panel)

#region Internal helper classes

private record Selection(object? Model = null, CarouselItem? CarouselItem = null, double? YPosition = null, int? Index = null);
private record Selection(object? Model = null, CarouselItem? CarouselItem = null, double? YPosition = null);

private record DisplayRange(int First, int Last);

Expand Down

0 comments on commit ee7972b

Please sign in to comment.