2019-01-24 16:43:03 +08: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 17:19:50 +08:00
2022-01-15 14:24:30 +08:00
using System ;
2020-09-30 17:34:13 +08:00
using System.Collections.Specialized ;
2022-12-16 17:16:26 +08:00
using System.Diagnostics ;
2017-09-26 14:44:40 +08:00
using System.Linq ;
2020-09-30 17:34:13 +08:00
using osu.Framework.Bindables ;
2017-09-26 14:44:40 +08:00
using osu.Game.Beatmaps.ControlPoints ;
2018-04-13 17:19:50 +08:00
2017-09-26 14:44:40 +08:00
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
{
/// <summary>
/// The part of the timeline that displays the control points.
/// </summary>
2020-09-30 17:34:13 +08:00
public partial class ControlPointPart : TimelinePart < GroupVisualisation >
2017-09-26 14:44:40 +08:00
{
2020-11-04 14:29:14 +08:00
private readonly IBindableList < ControlPointGroup > controlPointGroups = new BindableList < ControlPointGroup > ( ) ;
2020-09-30 17:34:13 +08:00
2021-01-25 17:43:36 +08:00
protected override void LoadBeatmap ( EditorBeatmap beatmap )
2017-09-26 14:44:40 +08:00
{
2017-09-27 11:06:33 +08:00
base . LoadBeatmap ( beatmap ) ;
2018-04-13 17:19:50 +08:00
2020-11-08 03:59:41 +08:00
controlPointGroups . UnbindAll ( ) ;
2021-01-25 17:43:36 +08:00
controlPointGroups . BindTo ( beatmap . ControlPointInfo . Groups ) ;
2022-06-24 20:25:23 +08:00
controlPointGroups . BindCollectionChanged ( ( _ , args ) = >
2017-09-26 14:44:40 +08:00
{
2020-09-30 17:34:13 +08:00
switch ( args . Action )
{
case NotifyCollectionChangedAction . Reset :
Clear ( ) ;
break ;
case NotifyCollectionChangedAction . Add :
2022-12-16 17:16:26 +08:00
Debug . Assert ( args . NewItems ! = null ) ;
2020-09-30 17:34:13 +08:00
foreach ( var group in args . NewItems . OfType < ControlPointGroup > ( ) )
2022-01-14 15:29:26 +08:00
{
// as an optimisation, don't add a visualisation if there are already groups with the same types in close proximity.
// for newly added control points (ie. lazer editor first where group is added empty) we always skip for simplicity.
// that is fine, because cases where this is causing a performance issue are mostly where external tools were used to create an insane number of points.
2022-01-19 13:57:01 +08:00
if ( Children . Any ( g = > Math . Abs ( g . Group . Time - group . Time ) < 500 & & g . IsVisuallyRedundant ( group ) ) )
2022-01-15 14:24:30 +08:00
continue ;
2022-01-14 15:29:26 +08:00
2020-09-30 17:34:13 +08:00
Add ( new GroupVisualisation ( group ) ) ;
2022-01-14 15:29:26 +08:00
}
2020-09-30 17:34:13 +08:00
break ;
case NotifyCollectionChangedAction . Remove :
2022-12-16 17:16:26 +08:00
Debug . Assert ( args . OldItems ! = null ) ;
2020-09-30 17:34:13 +08:00
foreach ( var group in args . OldItems . OfType < ControlPointGroup > ( ) )
{
2022-06-20 15:53:03 +08:00
var matching = Children . SingleOrDefault ( gv = > ReferenceEquals ( gv . Group , group ) ) ;
2020-09-30 17:34:13 +08:00
2022-01-14 15:29:26 +08:00
if ( matching ! = null )
matching . Expire ( ) ;
else
{
// due to the add optimisation above, if a point is deleted which wasn't being displayed we need to recreate all points
// to guarantee an accurate representation.
//
// note that the case where control point (type) is added or removed from a non-displayed group is not handled correctly.
2022-01-15 22:57:20 +08:00
// this is an edge case which shouldn't affect the user too badly. we may flatten control point groups in the future
2022-01-14 15:29:26 +08:00
// which would allow this to be handled better.
Clear ( ) ;
foreach ( var g in controlPointGroups )
Add ( new GroupVisualisation ( g ) ) ;
}
2020-09-30 17:34:13 +08:00
}
break ;
}
} , true ) ;
2017-09-26 14:44:40 +08:00
}
}
}