From e36a51acf0deb94b30aec0b6da0b5a87de0938bd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 25 Nov 2016 18:14:56 +0900 Subject: [PATCH] Custom LifetimeList (experimental). --- osu.Game/Beatmaps/Drawables/BeatmapGroup.cs | 1 - osu.Game/Beatmaps/Drawables/Panel.cs | 6 +- osu.Game/Screens/Select/CarouselContainer.cs | 109 +++++++++++++------ 3 files changed, 79 insertions(+), 37 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs index 6721257393..3f5fe58ab5 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs @@ -60,7 +60,6 @@ namespace osu.Game.Beatmaps.Drawables Header = new BeatmapSetHeader(beatmap) { - Depth = 1, GainedSelection = headerGainedSelection, RelativeSizeAxes = Axes.X, }; diff --git a/osu.Game/Beatmaps/Drawables/Panel.cs b/osu.Game/Beatmaps/Drawables/Panel.cs index e271546cbe..cc8f5d4a55 100644 --- a/osu.Game/Beatmaps/Drawables/Panel.cs +++ b/osu.Game/Beatmaps/Drawables/Panel.cs @@ -15,7 +15,11 @@ namespace osu.Game.Beatmaps.Drawables { public const float MAX_HEIGHT = 80; - public bool Hidden => Alpha == 0 && Transforms.Count == 0; + public override bool RemoveWhenNotAlive => false; + + public bool OnScreen; + + public override bool IsAlive => OnScreen; private Container nestedContainer; diff --git a/osu.Game/Screens/Select/CarouselContainer.cs b/osu.Game/Screens/Select/CarouselContainer.cs index 26dc77d943..b7ffbefec0 100644 --- a/osu.Game/Screens/Select/CarouselContainer.cs +++ b/osu.Game/Screens/Select/CarouselContainer.cs @@ -10,39 +10,85 @@ using osu.Game.Database; using System; using System.Collections.Generic; using System.Linq; +using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Lists; using osu.Game.Beatmaps.Drawables; - +using osu.Framework.Timing; + namespace osu.Game.Screens.Select { class CarouselContainer : ScrollContainer { private Container scrollableContent; private List groups = new List(); - private List panels = new List(); public BeatmapGroup SelectedGroup { get; private set; } public BeatmapPanel SelectedPanel { get; private set; } - - private List yPositions = new List(); - - public CarouselContainer() - { - DistanceDecayJump = 0.01; - Add(scrollableContent = new Container + private List yPositions = new List(); + private CarouselLifetimeList Lifetime; + + public CarouselContainer() + { + DistanceDecayJump = 0.01; + + Add(scrollableContent = new Container(Lifetime = new CarouselLifetimeList(DepthComparer)) + { + RelativeSizeAxes = Axes.X, + }); + } + + internal class CarouselLifetimeList : LifetimeList + { + public CarouselLifetimeList(IComparer comparer) + : base(comparer) + { + } + + public int StartIndex; + public int EndIndex; + + public override bool Update(FrameTimeInfo time) { - RelativeSizeAxes = Axes.X, - }); - } + bool anyAliveChanged = false; + //check existing items to make sure they haven't died. + foreach (var item in AliveItems.ToArray()) + { + item.UpdateTime(time); + if (!item.IsAlive) + { + //todo: make this more efficient + int i = IndexOf(item); + anyAliveChanged |= CheckItem(item, ref i); + } + } + + //handle custom range + for (int i = StartIndex; i < EndIndex; i++) + { + var item = this[i]; + item.UpdateTime(time); + anyAliveChanged |= CheckItem(item, ref i); + } + + return anyAliveChanged; + } + } + public void AddGroup(BeatmapGroup group) { group.State = BeatmapGroupState.Collapsed; - groups.Add(group); - panels.Add(group.Header); + + group.Header.Depth = scrollableContent.Children.Count(); + scrollableContent.Add(group.Header); + foreach (BeatmapPanel panel in group.BeatmapPanels) - panels.Add(panel); + { + panel.Depth = scrollableContent.Children.Count(); + scrollableContent.Add(panel); + } computeYPositions(); } @@ -134,7 +180,7 @@ namespace osu.Game.Screens.Select ScrollTo(selectedY); } - private static float offsetX(Panel panel, float dist, float halfHeight) + private static float offsetX(float dist, float halfHeight) { // The radius of the circle the carousel moves on. const float CIRCLE_RADIUS = 4; @@ -144,28 +190,16 @@ namespace osu.Game.Screens.Select return 125 + x; } - private void addPanel(int index) - { - Panel panel = panels[index]; - if (panel.Hidden) - return; - - if (!scrollableContent.Contains(panel)) - { - panel.Depth = index + (panel is BeatmapSetHeader ? panels.Count : 0); - scrollableContent.Add(panel); - } - } - protected override void Update() { base.Update(); float drawHeight = DrawHeight; - scrollableContent.RemoveAll(delegate (Panel p) + + Lifetime.AliveItems.ForEach(delegate (Panel p) { float panelPosY = p.Position.Y; - return panelPosY < Current - p.DrawHeight || panelPosY > Current + drawHeight || !IsVisible; + p.OnScreen = panelPosY >= Current - p.DrawHeight && panelPosY <= Current + drawHeight; }); int firstIndex = yPositions.BinarySearch(Current - Panel.MAX_HEIGHT); @@ -173,19 +207,24 @@ namespace osu.Game.Screens.Select int lastIndex = yPositions.BinarySearch(Current + drawHeight); if (lastIndex < 0) lastIndex = ~lastIndex; - for (int i = firstIndex; i < lastIndex; ++i) - addPanel(i); + Lifetime.StartIndex = firstIndex; + Lifetime.EndIndex = lastIndex; float halfHeight = drawHeight / 2; - foreach (Panel panel in scrollableContent.Children) + + for (int i = firstIndex; i < lastIndex; ++i) { + var panel = Lifetime[i]; + + panel.OnScreen = true; + float panelDrawY = panel.Position.Y - Current + panel.DrawHeight / 2; float dist = Math.Abs(1f - panelDrawY / halfHeight); // Setting the origin position serves as an additive position on top of potential // local transformation we may want to apply (e.g. when a panel gets selected, we // may want to smoothly transform it leftwards.) - panel.OriginPosition = new Vector2(-offsetX(panel, dist, halfHeight), 0); + panel.OriginPosition = new Vector2(-offsetX(dist, halfHeight), 0); // We are applying a multiplicative alpha (which is internally done by nesting an // additional container and setting that container's alpha) such that we can