Add basic pooling setup

This commit is contained in:
Dean Herbert
2020-10-12 15:36:03 +09:00
parent f17d661c1a
commit 0a978c6131
5 changed files with 95 additions and 43 deletions

View File

@ -16,6 +16,7 @@ using osu.Framework.Bindables;
using osu.Framework.Caching; using osu.Framework.Caching;
using osu.Framework.Threading; using osu.Framework.Threading;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics.Pooling;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -136,6 +137,8 @@ namespace osu.Game.Screens.Select
private IBindable<WeakReference<BeatmapInfo>> itemHidden; private IBindable<WeakReference<BeatmapInfo>> itemHidden;
private IBindable<WeakReference<BeatmapInfo>> itemRestored; private IBindable<WeakReference<BeatmapInfo>> itemRestored;
private readonly DrawablePool<DrawableCarouselBeatmapSet> setPool = new DrawablePool<DrawableCarouselBeatmapSet>(100);
public BeatmapCarousel() public BeatmapCarousel()
{ {
root = new CarouselRoot(this); root = new CarouselRoot(this);
@ -146,11 +149,15 @@ namespace osu.Game.Screens.Select
{ {
Masking = false, Masking = false,
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Child = scrollableContent = new Container<DrawableCarouselItem> Children = new Drawable[]
{
setPool,
scrollableContent = new Container<DrawableCarouselItem>
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
} }
} }
}
}; };
} }
@ -580,11 +587,13 @@ namespace osu.Game.Screens.Select
// Add those items within the previously found index range that should be displayed. // Add those items within the previously found index range that should be displayed.
for (int i = firstIndex; i < lastIndex; ++i) for (int i = firstIndex; i < lastIndex; ++i)
{ {
var panel = scrollableContent.FirstOrDefault(c => c.Item == visibleItems[i]); var item = visibleItems[i];
var panel = scrollableContent.FirstOrDefault(c => c.Item == item);
if (panel == null) if (panel == null)
{ {
panel = visibleItems[i].CreateDrawableRepresentation(); panel = setPool.Get(p => p.Item = item);
scrollableContent.Add(panel); scrollableContent.Add(panel);
} }

View File

@ -43,8 +43,6 @@ namespace osu.Game.Screens.Select.Carousel
.ForEach(AddChild); .ForEach(AddChild);
} }
public override DrawableCarouselItem CreateDrawableRepresentation() => new DrawableCarouselBeatmapSet(this);
protected override CarouselItem GetNextToSelect() protected override CarouselItem GetNextToSelect()
{ {
if (LastSelected == null) if (LastSelected == null)

View File

@ -60,10 +60,12 @@ namespace osu.Game.Screens.Select.Carousel
private CancellationTokenSource starDifficultyCancellationSource; private CancellationTokenSource starDifficultyCancellationSource;
public DrawableCarouselBeatmap(CarouselBeatmap panel) public DrawableCarouselBeatmap(CarouselBeatmap panel)
: base(panel)
{ {
beatmap = panel.Beatmap; beatmap = panel.Beatmap;
Height = HEIGHT; Height = HEIGHT;
// todo: temporary
Item = panel;
} }
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
@ -79,7 +81,7 @@ namespace osu.Game.Screens.Select.Carousel
if (manager != null) if (manager != null)
hideRequested = manager.Hide; hideRequested = manager.Hide;
Children = new Drawable[] Content.Children = new Drawable[]
{ {
background = new Box background = new Box
{ {

View File

@ -45,26 +45,40 @@ namespace osu.Game.Screens.Select.Carousel
public override IEnumerable<DrawableCarouselItem> ChildItems => beatmapContainer?.Children ?? base.ChildItems; public override IEnumerable<DrawableCarouselItem> ChildItems => beatmapContainer?.Children ?? base.ChildItems;
private readonly BeatmapSetInfo beatmapSet; private BeatmapSetInfo beatmapSet => (Item as CarouselBeatmapSet)?.BeatmapSet;
private Container<DrawableCarouselBeatmap> beatmapContainer; private Container<DrawableCarouselBeatmap> beatmapContainer;
private Bindable<CarouselItemState> beatmapSetState; private Bindable<CarouselItemState> beatmapSetState;
public DrawableCarouselBeatmapSet(CarouselBeatmapSet set) [Resolved]
: base(set) private BeatmapManager manager { get; set; }
{
beatmapSet = set.BeatmapSet;
}
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(BeatmapManager manager, BeatmapSetOverlay beatmapOverlay) private void load(BeatmapSetOverlay beatmapOverlay)
{ {
restoreHiddenRequested = s => s.Beatmaps.ForEach(manager.Restore); restoreHiddenRequested = s => s.Beatmaps.ForEach(manager.Restore);
if (beatmapOverlay != null) if (beatmapOverlay != null)
viewDetails = beatmapOverlay.FetchAndShowBeatmapSet; viewDetails = beatmapOverlay.FetchAndShowBeatmapSet;
Children = new Drawable[] // TODO: temporary. we probably want to *not* inherit DrawableCarouselItem for this class, but only the above header portion.
AddRangeInternal(new Drawable[]
{
beatmapContainer = new Container<DrawableCarouselBeatmap>
{
X = 50,
Y = MAX_HEIGHT,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
},
});
}
protected override void UpdateItem()
{
base.UpdateItem();
Content.Children = new Drawable[]
{ {
new DelayedLoadUnloadWrapper(() => new DelayedLoadUnloadWrapper(() =>
{ {
@ -125,17 +139,7 @@ namespace osu.Game.Screens.Select.Carousel
} }
}; };
// TODO: temporary. we probably want to *not* inherit DrawableCarouselItem for this class, but only the above header portion. beatmapContainer.Clear();
AddRangeInternal(new Drawable[]
{
beatmapContainer = new Container<DrawableCarouselBeatmap>
{
X = 50,
Y = MAX_HEIGHT,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
},
});
beatmapSetState = Item.State.GetBoundCopy(); beatmapSetState = Item.State.GetBoundCopy();
beatmapSetState.BindValueChanged(setSelected, true); beatmapSetState.BindValueChanged(setSelected, true);
@ -153,11 +157,16 @@ namespace osu.Game.Screens.Select.Carousel
float yPos = 0; float yPos = 0;
foreach (var item in ((CarouselBeatmapSet)Item).Beatmaps.Select(b => b.CreateDrawableRepresentation()).OfType<DrawableCarouselBeatmap>()) var carouselBeatmapSet = (CarouselBeatmapSet)Item;
foreach (var item in carouselBeatmapSet.Children)
{ {
item.Y = yPos; var beatmapPanel = item.CreateDrawableRepresentation();
beatmapContainer.Add(item);
yPos += item.Item.TotalHeight; beatmapPanel.Y = yPos;
yPos += item.TotalHeight;
beatmapContainer.Add((DrawableCarouselBeatmap)beatmapPanel);
} }
break; break;

View File

@ -2,14 +2,17 @@
// 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.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Audio; using osu.Framework.Audio;
using osu.Framework.Audio.Sample; using osu.Framework.Audio.Sample;
using osu.Framework.Bindables;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Pooling;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Utils; using osu.Framework.Utils;
@ -19,15 +22,32 @@ using osuTK.Graphics;
namespace osu.Game.Screens.Select.Carousel namespace osu.Game.Screens.Select.Carousel
{ {
public abstract class DrawableCarouselItem : Container public abstract class DrawableCarouselItem : PoolableDrawable
{ {
public const float MAX_HEIGHT = 80; public const float MAX_HEIGHT = 80;
public override bool RemoveWhenNotAlive => false; public override bool IsPresent => base.IsPresent || Item?.Visible == true;
public override bool IsPresent => base.IsPresent || Item.Visible; public CarouselItem Item
{
get => item;
set
{
if (item == value)
return;
public readonly CarouselItem Item; if (item != null)
{
Item.Filtered.ValueChanged -= onStateChange;
Item.State.ValueChanged -= onStateChange;
}
item = value;
if (IsLoaded)
UpdateItem();
}
}
public virtual IEnumerable<DrawableCarouselItem> ChildItems => Enumerable.Empty<DrawableCarouselItem>(); public virtual IEnumerable<DrawableCarouselItem> ChildItems => Enumerable.Empty<DrawableCarouselItem>();
@ -37,12 +57,10 @@ namespace osu.Game.Screens.Select.Carousel
private readonly Box hoverLayer; private readonly Box hoverLayer;
protected override Container<Drawable> Content => nestedContainer; protected Container<Drawable> Content => nestedContainer;
protected DrawableCarouselItem(CarouselItem item) protected DrawableCarouselItem()
{ {
Item = item;
Height = MAX_HEIGHT; Height = MAX_HEIGHT;
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Alpha = 0; Alpha = 0;
@ -70,6 +88,7 @@ namespace osu.Game.Screens.Select.Carousel
} }
private SampleChannel sampleHover; private SampleChannel sampleHover;
private CarouselItem item;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(AudioManager audio, OsuColour colours) private void load(AudioManager audio, OsuColour colours)
@ -98,14 +117,27 @@ namespace osu.Game.Screens.Select.Carousel
{ {
base.LoadComplete(); base.LoadComplete();
ApplyState(); UpdateItem();
Item.Filtered.ValueChanged += _ => Schedule(ApplyState);
Item.State.ValueChanged += _ => Schedule(ApplyState);
} }
protected virtual void UpdateItem()
{
if (item == null)
return;
ApplyState();
Item.Filtered.ValueChanged += onStateChange;
Item.State.ValueChanged += onStateChange;
}
private void onStateChange(ValueChangedEvent<CarouselItemState> obj) => Schedule(ApplyState);
private void onStateChange(ValueChangedEvent<bool> _) => Schedule(ApplyState);
protected virtual void ApplyState() protected virtual void ApplyState()
{ {
if (!IsLoaded) return; Debug.Assert(Item != null);
switch (Item.State.Value) switch (Item.State.Value)
{ {
@ -126,6 +158,8 @@ namespace osu.Game.Screens.Select.Carousel
protected virtual void Selected() protected virtual void Selected()
{ {
Debug.Assert(Item != null);
Item.State.Value = CarouselItemState.Selected; Item.State.Value = CarouselItemState.Selected;
BorderContainer.BorderThickness = 2.5f; BorderContainer.BorderThickness = 2.5f;