2019-01-24 17:43:03 +09:00
// 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 18:19:50 +09:00
2019-11-01 19:22:07 +09:00
using System.Collections.Generic ;
using System.Linq ;
using osu.Framework.Extensions ;
2018-04-13 18:19:50 +09:00
using osu.Framework.Graphics ;
2019-11-01 15:34:24 +09:00
using osu.Framework.Graphics.Containers ;
2018-04-13 18:19:50 +09:00
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
{
2019-11-05 23:20:46 +09:00
/// <summary>
2019-11-06 16:33:42 +09:00
/// Visualises connections between <see cref="DrawableOsuHitObject"/>s.
2019-11-05 23:20:46 +09:00
/// </summary>
2020-02-23 04:37:04 +09:00
public class FollowPointRenderer : LifetimeManagementContainer
2018-04-13 18:19:50 +09:00
{
2019-11-05 23:20:46 +09:00
/// <summary>
2019-11-06 16:33:42 +09:00
/// All the <see cref="FollowPointConnection"/>s contained by this <see cref="FollowPointRenderer"/>.
2019-11-05 23:20:46 +09:00
/// </summary>
2019-11-06 16:33:42 +09:00
internal IReadOnlyList < FollowPointConnection > Connections = > connections ;
2019-11-05 19:31:58 +09:00
2019-11-06 16:33:42 +09:00
private readonly List < FollowPointConnection > connections = new List < FollowPointConnection > ( ) ;
2019-11-01 19:22:07 +09:00
2019-11-05 23:02:39 +09:00
public override bool RemoveCompletedTransforms = > false ;
2018-04-13 18:19:50 +09:00
/// <summary>
2019-11-01 15:39:23 +09:00
/// 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 18:19:50 +09:00
/// </summary>
2019-11-01 15:39:23 +09:00
/// <param name="hitObject">The <see cref="DrawableOsuHitObject"/> to add <see cref="FollowPoint"/>s for.</param>
public void AddFollowPoints ( DrawableOsuHitObject hitObject )
2019-11-06 16:33:42 +09:00
= > addConnection ( new FollowPointConnection ( hitObject ) . With ( g = > g . StartTime . BindValueChanged ( _ = > onStartTimeChanged ( g ) ) ) ) ;
2019-11-01 19:22:07 +09:00
/// <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 16:33:42 +09:00
public void RemoveFollowPoints ( DrawableOsuHitObject hitObject ) = > removeGroup ( connections . Single ( g = > g . Start = = hitObject ) ) ;
2019-11-01 19:22:07 +09:00
/// <summary>
2019-11-06 16:33:42 +09:00
/// Adds a <see cref="FollowPointConnection"/> to this <see cref="FollowPointRenderer"/>.
2019-11-01 19:22:07 +09:00
/// </summary>
2019-11-06 16:33:42 +09:00
/// <param name="connection">The <see cref="FollowPointConnection"/> to add.</param>
/// <returns>The index of <paramref name="connection"/> in <see cref="connections"/>.</returns>
2019-11-06 16:36:12 +09:00
private void addConnection ( FollowPointConnection connection )
2018-04-13 18:19:50 +09:00
{
2019-11-06 16:33:42 +09: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-01 15:39:23 +09:00
2019-11-06 16:33:42 +09:00
if ( index < connections . Count - 1 )
2018-04-13 18:19:50 +09:00
{
2019-11-06 16:33:42 +09:00
// Update the connection's end point to the next connection's start point
2019-11-01 15:39:23 +09:00
// h1 -> -> -> h2
2019-11-06 16:33:42 +09:00
// connection nextGroup
2019-02-27 21:07:17 +09:00
2019-11-06 16:33:42 +09:00
FollowPointConnection nextConnection = connections [ index + 1 ] ;
connection . End = nextConnection . Start ;
2018-04-13 18:19:50 +09:00
}
2019-11-05 19:31:48 +09:00
else
2019-11-05 23:20:46 +09:00
{
// The end point may be non-null during re-ordering
2019-11-06 16:33:42 +09:00
connection . End = null ;
2019-11-05 23:20:46 +09:00
}
2019-02-27 21:07:17 +09:00
2019-11-01 19:22:07 +09:00
if ( index > 0 )
2018-04-13 18:19:50 +09:00
{
2019-11-06 16:33:42 +09:00
// Update the previous connection's end point to the current connection's start point
2019-11-01 15:39:23 +09:00
// h1 -> -> -> h2
2019-11-06 16:33:42 +09:00
// prevGroup connection
2019-02-27 21:07:17 +09:00
2019-11-06 16:33:42 +09:00
FollowPointConnection previousConnection = connections [ index - 1 ] ;
previousConnection . End = connection . Start ;
2018-04-13 18:19:50 +09:00
}
2020-02-23 04:37:04 +09:00
AddInternal ( connection ) ;
2018-04-13 18:19:50 +09:00
}
2019-11-01 15:39:23 +09:00
/// <summary>
2019-11-06 16:33:42 +09:00
/// Removes a <see cref="FollowPointConnection"/> from this <see cref="FollowPointRenderer"/>.
2019-11-01 15:39:23 +09:00
/// </summary>
2019-11-06 16:33:42 +09:00
/// <param name="connection">The <see cref="FollowPointConnection"/> to remove.</param>
/// <returns>Whether <paramref name="connection"/> was removed.</returns>
2019-11-06 16:36:12 +09:00
private void removeGroup ( FollowPointConnection connection )
2018-04-13 18:19:50 +09:00
{
2019-11-06 16:33:42 +09:00
RemoveInternal ( connection ) ;
2018-04-13 18:19:50 +09:00
2019-11-06 16:33:42 +09:00
int index = connections . IndexOf ( connection ) ;
2019-04-01 12:16:05 +09:00
2019-11-01 19:22:07 +09:00
if ( index > 0 )
2018-04-13 18:19:50 +09:00
{
2019-11-06 16:33:42 +09:00
// Update the previous connection's end point to the next connection's start point
2019-11-01 19:22:07 +09:00
// h1 -> -> -> h2 -> -> -> h3
2019-11-06 16:33:42 +09: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 18:19:50 +09:00
}
2019-11-01 15:39:23 +09:00
2019-11-06 16:36:12 +09:00
connections . Remove ( connection ) ;
2019-11-01 15:39:23 +09:00
}
2019-11-06 16:33:42 +09:00
private void onStartTimeChanged ( FollowPointConnection connection )
2019-11-01 15:39:23 +09:00
{
2019-11-05 23:20:46 +09:00
// Naive but can be improved if performance becomes an issue
2019-11-06 16:33:42 +09:00
removeGroup ( connection ) ;
addConnection ( connection ) ;
2018-04-13 18:19:50 +09:00
}
}
}