1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-29 08:47:24 +08:00
osu-lazer/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/GroupVisualisation.cs
Dean Herbert c64a919a9d Reduce number of redundant control points displayed on summary timeline
As pointed out in https://github.com/ppy/osu/discussions/16435, beatmaps
with too many control points (usually added via external automation
apps) could cause the lazer editor to grind to a halt.

The overheads here are mostly from the GL side. An eventual goal would
be to render this in a smarter way, rather than using thousands of
drawables. Until that, this optimisation should help reduce the overhead
by omitting control points in close proximity that are redundant for
display purposes.

I've tried to contain this in the display logic directly, with the goal
that it can be ripped out as fast as it was added. Certainly required
more changes than I hoped for, but I don't think it's too ugly.
2022-01-14 17:13:26 +09:00

70 lines
2.5 KiB
C#

// 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.
using System.Linq;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps.ControlPoints;
namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
{
public class GroupVisualisation : CompositeDrawable
{
public readonly ControlPointGroup Group;
private readonly IBindableList<ControlPoint> controlPoints = new BindableList<ControlPoint>();
public GroupVisualisation(ControlPointGroup group)
{
RelativePositionAxes = Axes.X;
RelativeSizeAxes = Axes.Both;
Origin = Anchor.TopLeft;
Group = group;
X = (float)group.Time;
// Run in constructor so IsRedundant calls can work correctly.
controlPoints.BindTo(Group.ControlPoints);
controlPoints.BindCollectionChanged((_, __) =>
{
ClearInternal();
if (controlPoints.Count == 0)
return;
foreach (var point in Group.ControlPoints)
{
switch (point)
{
case TimingControlPoint _:
AddInternal(new ControlPointVisualisation(point) { Y = 0, });
break;
case DifficultyControlPoint _:
AddInternal(new ControlPointVisualisation(point) { Y = 0.25f, });
break;
case SampleControlPoint _:
AddInternal(new ControlPointVisualisation(point) { Y = 0.5f, });
break;
case EffectControlPoint effect:
AddInternal(new EffectPointVisualisation(effect) { Y = 0.75f });
break;
}
}
}, true);
}
/// <summary>
/// For display purposes, check whether the proposed group is made redundant by this visualisation group.
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public bool IsRedundant(ControlPointGroup other) =>
other.ControlPoints.Any(c => InternalChildren.OfType<IControlPointVisualisationRedundant>().Any(c2 => c2.IsRedundant(c)));
}
}