mirror of
https://github.com/osukey/osukey.git
synced 2025-08-07 16:43:52 +09:00
Merge pull request #13331 from ekrctb/pdwl-follow-point
Use general lifetime container for follow point container
This commit is contained in:
@ -5,6 +5,7 @@ using System;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Pooling;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||||
@ -12,34 +13,29 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visualises the <see cref="FollowPoint"/>s between two <see cref="DrawableOsuHitObject"/>s.
|
/// Visualises the <see cref="FollowPoint"/>s between two <see cref="DrawableOsuHitObject"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FollowPointConnection : PoolableDrawable
|
public class FollowPointConnection : PoolableDrawableWithLifetime<FollowPointLifetimeEntry>
|
||||||
{
|
{
|
||||||
// Todo: These shouldn't be constants
|
// Todo: These shouldn't be constants
|
||||||
public const int SPACING = 32;
|
public const int SPACING = 32;
|
||||||
public const double PREEMPT = 800;
|
public const double PREEMPT = 800;
|
||||||
|
|
||||||
public FollowPointLifetimeEntry Entry;
|
|
||||||
public DrawablePool<FollowPoint> Pool;
|
public DrawablePool<FollowPoint> Pool;
|
||||||
|
|
||||||
protected override void PrepareForUse()
|
protected override void OnApply(FollowPointLifetimeEntry entry)
|
||||||
{
|
{
|
||||||
base.PrepareForUse();
|
base.OnApply(entry);
|
||||||
|
|
||||||
Entry.Invalidated += onEntryInvalidated;
|
|
||||||
|
|
||||||
|
entry.Invalidated += onEntryInvalidated;
|
||||||
refreshPoints();
|
refreshPoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void FreeAfterUse()
|
protected override void OnFree(FollowPointLifetimeEntry entry)
|
||||||
{
|
{
|
||||||
base.FreeAfterUse();
|
base.OnFree(entry);
|
||||||
|
|
||||||
Entry.Invalidated -= onEntryInvalidated;
|
|
||||||
|
|
||||||
|
entry.Invalidated -= onEntryInvalidated;
|
||||||
// Return points to the pool.
|
// Return points to the pool.
|
||||||
ClearInternal(false);
|
ClearInternal(false);
|
||||||
|
|
||||||
Entry = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onEntryInvalidated() => Scheduler.AddOnce(refreshPoints);
|
private void onEntryInvalidated() => Scheduler.AddOnce(refreshPoints);
|
||||||
@ -48,8 +44,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
{
|
{
|
||||||
ClearInternal(false);
|
ClearInternal(false);
|
||||||
|
|
||||||
OsuHitObject start = Entry.Start;
|
var entry = Entry;
|
||||||
OsuHitObject end = Entry.End;
|
if (entry?.End == null) return;
|
||||||
|
|
||||||
|
OsuHitObject start = entry.Start;
|
||||||
|
OsuHitObject end = entry.End;
|
||||||
|
|
||||||
double startTime = start.GetEndTime();
|
double startTime = start.GetEndTime();
|
||||||
|
|
||||||
@ -87,14 +86,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
fp.FadeIn(end.TimeFadeIn);
|
fp.FadeIn(end.TimeFadeIn);
|
||||||
fp.ScaleTo(end.Scale, end.TimeFadeIn, Easing.Out);
|
fp.ScaleTo(end.Scale, end.TimeFadeIn, Easing.Out);
|
||||||
fp.MoveTo(pointEndPosition, end.TimeFadeIn, Easing.Out);
|
fp.MoveTo(pointEndPosition, end.TimeFadeIn, Easing.Out);
|
||||||
fp.Delay(fadeOutTime - fadeInTime).FadeOut(end.TimeFadeIn);
|
fp.Delay(fadeOutTime - fadeInTime).FadeOut(end.TimeFadeIn).Expire();
|
||||||
|
|
||||||
finalTransformEndTime = fadeOutTime + end.TimeFadeIn;
|
finalTransformEndTime = fp.LifetimeEnd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: use Expire() on FollowPoints and take lifetime from them when https://github.com/ppy/osu-framework/issues/3300 is fixed.
|
entry.LifetimeEnd = finalTransformEndTime;
|
||||||
Entry.LifetimeEnd = finalTransformEndTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics.Performance;
|
using osu.Framework.Graphics.Performance;
|
||||||
@ -11,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
{
|
{
|
||||||
public class FollowPointLifetimeEntry : LifetimeEntry
|
public class FollowPointLifetimeEntry : LifetimeEntry
|
||||||
{
|
{
|
||||||
public event Action Invalidated;
|
public event Action? Invalidated;
|
||||||
public readonly OsuHitObject Start;
|
public readonly OsuHitObject Start;
|
||||||
|
|
||||||
public FollowPointLifetimeEntry(OsuHitObject start)
|
public FollowPointLifetimeEntry(OsuHitObject start)
|
||||||
@ -22,9 +24,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
bindEvents();
|
bindEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
private OsuHitObject end;
|
private OsuHitObject? end;
|
||||||
|
|
||||||
public OsuHitObject End
|
public OsuHitObject? End
|
||||||
{
|
{
|
||||||
get => end;
|
get => end;
|
||||||
set
|
set
|
||||||
@ -56,11 +58,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
|
|
||||||
public void UnbindEvents()
|
public void UnbindEvents()
|
||||||
{
|
{
|
||||||
if (Start != null)
|
Start.DefaultsApplied -= onDefaultsApplied;
|
||||||
{
|
Start.PositionBindable.ValueChanged -= onPositionChanged;
|
||||||
Start.DefaultsApplied -= onDefaultsApplied;
|
|
||||||
Start.PositionBindable.ValueChanged -= onPositionChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (End != null)
|
if (End != null)
|
||||||
{
|
{
|
||||||
|
@ -6,43 +6,32 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Performance;
|
|
||||||
using osu.Framework.Graphics.Pooling;
|
using osu.Framework.Graphics.Pooling;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osu.Game.Rulesets.Objects.Pooling;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Visualises connections between <see cref="DrawableOsuHitObject"/>s.
|
/// Visualises connections between <see cref="DrawableOsuHitObject"/>s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FollowPointRenderer : CompositeDrawable
|
public class FollowPointRenderer : PooledDrawableWithLifetimeContainer<FollowPointLifetimeEntry, FollowPointConnection>
|
||||||
{
|
{
|
||||||
public override bool RemoveCompletedTransforms => false;
|
public new IReadOnlyList<FollowPointLifetimeEntry> Entries => lifetimeEntries;
|
||||||
|
|
||||||
public IReadOnlyList<FollowPointLifetimeEntry> Entries => lifetimeEntries;
|
|
||||||
|
|
||||||
private DrawablePool<FollowPointConnection> connectionPool;
|
private DrawablePool<FollowPointConnection> connectionPool;
|
||||||
private DrawablePool<FollowPoint> pointPool;
|
private DrawablePool<FollowPoint> pointPool;
|
||||||
|
|
||||||
private readonly List<FollowPointLifetimeEntry> lifetimeEntries = new List<FollowPointLifetimeEntry>();
|
private readonly List<FollowPointLifetimeEntry> lifetimeEntries = new List<FollowPointLifetimeEntry>();
|
||||||
private readonly Dictionary<LifetimeEntry, FollowPointConnection> connectionsInUse = new Dictionary<LifetimeEntry, FollowPointConnection>();
|
|
||||||
private readonly Dictionary<HitObject, IBindable> startTimeMap = new Dictionary<HitObject, IBindable>();
|
private readonly Dictionary<HitObject, IBindable> startTimeMap = new Dictionary<HitObject, IBindable>();
|
||||||
private readonly LifetimeEntryManager lifetimeManager = new LifetimeEntryManager();
|
|
||||||
|
|
||||||
public FollowPointRenderer()
|
|
||||||
{
|
|
||||||
lifetimeManager.EntryBecameAlive += onEntryBecameAlive;
|
|
||||||
lifetimeManager.EntryBecameDead += onEntryBecameDead;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
InternalChildren = new Drawable[]
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
connectionPool = new DrawablePoolNoLifetime<FollowPointConnection>(1, 200),
|
connectionPool = new DrawablePool<FollowPointConnection>(1, 200),
|
||||||
pointPool = new DrawablePoolNoLifetime<FollowPoint>(50, 1000)
|
pointPool = new DrawablePool<FollowPoint>(50, 1000)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +96,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
previousEntry.End = newEntry.Start;
|
previousEntry.End = newEntry.Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
lifetimeManager.AddEntry(newEntry);
|
Add(newEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeEntry(OsuHitObject hitObject)
|
private void removeEntry(OsuHitObject hitObject)
|
||||||
@ -118,7 +107,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
entry.UnbindEvents();
|
entry.UnbindEvents();
|
||||||
|
|
||||||
lifetimeEntries.RemoveAt(index);
|
lifetimeEntries.RemoveAt(index);
|
||||||
lifetimeManager.RemoveEntry(entry);
|
Remove(entry);
|
||||||
|
|
||||||
if (index > 0)
|
if (index > 0)
|
||||||
{
|
{
|
||||||
@ -131,30 +120,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool CheckChildrenLife()
|
protected override FollowPointConnection GetDrawable(FollowPointLifetimeEntry entry)
|
||||||
{
|
{
|
||||||
bool anyAliveChanged = base.CheckChildrenLife();
|
var connection = connectionPool.Get();
|
||||||
anyAliveChanged |= lifetimeManager.Update(Time.Current);
|
connection.Pool = pointPool;
|
||||||
return anyAliveChanged;
|
connection.Apply(entry);
|
||||||
}
|
return connection;
|
||||||
|
|
||||||
private void onEntryBecameAlive(LifetimeEntry entry)
|
|
||||||
{
|
|
||||||
var connection = connectionPool.Get(c =>
|
|
||||||
{
|
|
||||||
c.Entry = (FollowPointLifetimeEntry)entry;
|
|
||||||
c.Pool = pointPool;
|
|
||||||
});
|
|
||||||
|
|
||||||
connectionsInUse[entry] = connection;
|
|
||||||
|
|
||||||
AddInternal(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onEntryBecameDead(LifetimeEntry entry)
|
|
||||||
{
|
|
||||||
RemoveInternal(connectionsInUse[entry]);
|
|
||||||
connectionsInUse.Remove(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onStartTimeChanged(OsuHitObject hitObject)
|
private void onStartTimeChanged(OsuHitObject hitObject)
|
||||||
@ -171,16 +142,5 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
entry.UnbindEvents();
|
entry.UnbindEvents();
|
||||||
lifetimeEntries.Clear();
|
lifetimeEntries.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DrawablePoolNoLifetime<T> : DrawablePool<T>
|
|
||||||
where T : PoolableDrawable, new()
|
|
||||||
{
|
|
||||||
public override bool RemoveWhenNotAlive => false;
|
|
||||||
|
|
||||||
public DrawablePoolNoLifetime(int initialSize, int? maximumSize = null)
|
|
||||||
: base(initialSize, maximumSize)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user