1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-24 10:07:28 +08:00
osu-lazer/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs

113 lines
5.1 KiB
C#
Raw Normal View History

// 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.
2018-04-13 17:19:50 +08:00
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Extensions;
2018-04-13 17:19:50 +08:00
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
2018-04-13 17:19:50 +08:00
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
{
2019-11-05 22:20:46 +08:00
/// <summary>
2019-11-06 15:33:42 +08:00
/// Visualises connections between <see cref="DrawableOsuHitObject"/>s.
2019-11-05 22:20:46 +08:00
/// </summary>
public class FollowPointRenderer : CompositeDrawable
2018-04-13 17:19:50 +08:00
{
2019-11-05 22:20:46 +08:00
/// <summary>
2019-11-06 15:33:42 +08:00
/// All the <see cref="FollowPointConnection"/>s contained by this <see cref="FollowPointRenderer"/>.
2019-11-05 22:20:46 +08:00
/// </summary>
2019-11-06 15:33:42 +08:00
internal IReadOnlyList<FollowPointConnection> Connections => connections;
2019-11-05 18:31:58 +08:00
2019-11-06 15:33:42 +08:00
private readonly List<FollowPointConnection> connections = new List<FollowPointConnection>();
public override bool RemoveCompletedTransforms => false;
2018-04-13 17:19:50 +08:00
/// <summary>
/// Adds the <see cref="FollowPoint"/>s around a <see cref="DrawableOsuHitObject"/>.
/// This includes <see cref="FollowPoint"/>s leading into <paramref name="hitObject"/>, and <see cref="FollowPoint"/>s exiting <paramref name="hitObject"/>.
2018-04-13 17:19:50 +08:00
/// </summary>
/// <param name="hitObject">The <see cref="DrawableOsuHitObject"/> to add <see cref="FollowPoint"/>s for.</param>
public void AddFollowPoints(DrawableOsuHitObject hitObject)
2019-11-06 15:33:42 +08:00
=> addConnection(new FollowPointConnection(hitObject).With(g => g.StartTime.BindValueChanged(_ => onStartTimeChanged(g))));
/// <summary>
/// Removes the <see cref="FollowPoint"/>s around a <see cref="DrawableOsuHitObject"/>.
/// This includes <see cref="FollowPoint"/>s leading into <paramref name="hitObject"/>, and <see cref="FollowPoint"/>s exiting <paramref name="hitObject"/>.
/// </summary>
/// <param name="hitObject">The <see cref="DrawableOsuHitObject"/> to remove <see cref="FollowPoint"/>s for.</param>
2019-11-06 15:33:42 +08:00
public void RemoveFollowPoints(DrawableOsuHitObject hitObject) => removeGroup(connections.Single(g => g.Start == hitObject));
/// <summary>
2019-11-06 15:33:42 +08:00
/// Adds a <see cref="FollowPointConnection"/> to this <see cref="FollowPointRenderer"/>.
/// </summary>
2019-11-06 15:33:42 +08:00
/// <param name="connection">The <see cref="FollowPointConnection"/> to add.</param>
/// <returns>The index of <paramref name="connection"/> in <see cref="connections"/>.</returns>
private int addConnection(FollowPointConnection connection)
2018-04-13 17:19:50 +08:00
{
2019-11-06 15:33:42 +08:00
AddInternal(connection);
2019-11-06 15:33:42 +08:00
// Groups are sorted by their start time when added such that the index can be used to post-process other surrounding connections
int index = connections.AddInPlace(connection, Comparer<FollowPointConnection>.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value)));
2019-11-06 15:33:42 +08:00
if (index < connections.Count - 1)
2018-04-13 17:19:50 +08:00
{
2019-11-06 15:33:42 +08:00
// Update the connection's end point to the next connection's start point
// h1 -> -> -> h2
2019-11-06 15:33:42 +08:00
// connection nextGroup
2019-11-06 15:33:42 +08:00
FollowPointConnection nextConnection = connections[index + 1];
connection.End = nextConnection.Start;
2018-04-13 17:19:50 +08:00
}
else
2019-11-05 22:20:46 +08:00
{
// The end point may be non-null during re-ordering
2019-11-06 15:33:42 +08:00
connection.End = null;
2019-11-05 22:20:46 +08:00
}
if (index > 0)
2018-04-13 17:19:50 +08:00
{
2019-11-06 15:33:42 +08:00
// Update the previous connection's end point to the current connection's start point
// h1 -> -> -> h2
2019-11-06 15:33:42 +08:00
// prevGroup connection
2019-11-06 15:33:42 +08:00
FollowPointConnection previousConnection = connections[index - 1];
previousConnection.End = connection.Start;
2018-04-13 17:19:50 +08:00
}
return index;
2018-04-13 17:19:50 +08:00
}
/// <summary>
2019-11-06 15:33:42 +08:00
/// Removes a <see cref="FollowPointConnection"/> from this <see cref="FollowPointRenderer"/>.
/// </summary>
2019-11-06 15:33:42 +08:00
/// <param name="connection">The <see cref="FollowPointConnection"/> to remove.</param>
/// <returns>Whether <paramref name="connection"/> was removed.</returns>
private bool removeGroup(FollowPointConnection connection)
2018-04-13 17:19:50 +08:00
{
2019-11-06 15:33:42 +08:00
RemoveInternal(connection);
2018-04-13 17:19:50 +08:00
2019-11-06 15:33:42 +08:00
int index = connections.IndexOf(connection);
2019-04-01 11:16:05 +08:00
if (index > 0)
2018-04-13 17:19:50 +08:00
{
2019-11-06 15:33:42 +08:00
// Update the previous connection's end point to the next connection's start point
// h1 -> -> -> h2 -> -> -> h3
2019-11-06 15:33:42 +08:00
// prevGroup connection nextGroup
// The current connection's end point is used since there may not be a next connection
FollowPointConnection previousConnection = connections[index - 1];
previousConnection.End = connection.End;
2018-04-13 17:19:50 +08:00
}
2019-11-06 15:33:42 +08:00
return connections.Remove(connection);
}
2019-11-06 15:33:42 +08:00
private void onStartTimeChanged(FollowPointConnection connection)
{
2019-11-05 22:20:46 +08:00
// Naive but can be improved if performance becomes an issue
2019-11-06 15:33:42 +08:00
removeGroup(connection);
addConnection(connection);
2018-04-13 17:19:50 +08:00
}
}
}