Skip to content

Commit

Permalink
Merge pull request ppy#28387 from bdach/taiko-selection-handler-is-slow
Browse files Browse the repository at this point in the history
Fix performance overhead from ternary state bindable callbacks when selection is changing
  • Loading branch information
peppy authored Jun 4, 2024
2 parents 7b14c77 + ecfcf7a commit 9f6ff48
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 0 deletions.
6 changes: 6 additions & 0 deletions osu.Game.Rulesets.Taiko/Edit/TaikoSelectionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ private void load()

public void SetStrongState(bool state)
{
if (SelectedItems.OfType<Hit>().All(h => h.IsStrong == state))
return;

EditorBeatmap.PerformOnSelection(h =>
{
if (!(h is Hit taikoHit)) return;
Expand All @@ -67,6 +70,9 @@ public void SetStrongState(bool state)

public void SetRimState(bool state)
{
if (SelectedItems.OfType<Hit>().All(h => h.Type == (state ? HitType.Rim : HitType.Centre)))
return;

EditorBeatmap.PerformOnSelection(h =>
{
if (h is Hit taikoHit)
Expand Down
12 changes: 12 additions & 0 deletions osu.Game/Screens/Edit/Compose/Components/EditorSelectionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ protected virtual void UpdateTernaryStates()
/// <param name="bankName">The name of the sample bank.</param>
public void AddSampleBank(string bankName)
{
if (SelectedItems.All(h => h.Samples.All(s => s.Bank == bankName)))
return;

EditorBeatmap.PerformOnSelection(h =>
{
if (h.Samples.All(s => s.Bank == bankName))
Expand All @@ -214,6 +217,9 @@ public void AddSampleBank(string bankName)
/// <param name="sampleName">The name of the hit sample.</param>
public void AddHitSample(string sampleName)
{
if (SelectedItems.All(h => h.Samples.Any(s => s.Name == sampleName)))
return;

EditorBeatmap.PerformOnSelection(h =>
{
// Make sure there isn't already an existing sample
Expand All @@ -231,6 +237,9 @@ public void AddHitSample(string sampleName)
/// <param name="sampleName">The name of the hit sample.</param>
public void RemoveHitSample(string sampleName)
{
if (SelectedItems.All(h => h.Samples.All(s => s.Name != sampleName)))
return;

EditorBeatmap.PerformOnSelection(h =>
{
h.SamplesBindable.RemoveAll(s => s.Name == sampleName);
Expand All @@ -245,6 +254,9 @@ public void RemoveHitSample(string sampleName)
/// <exception cref="InvalidOperationException">Throws if any selected object doesn't implement <see cref="IHasComboInformation"/></exception>
public void SetNewCombo(bool state)
{
if (SelectedItems.OfType<IHasComboInformation>().All(h => h.NewCombo == state))
return;

EditorBeatmap.PerformOnSelection(h =>
{
var comboInfo = h as IHasComboInformation;
Expand Down
5 changes: 5 additions & 0 deletions osu.Game/Screens/Edit/EditorBeatmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,11 @@ public ControlPointInfo ControlPointInfo
/// Perform the provided action on every selected hitobject.
/// Changes will be grouped as one history action.
/// </summary>
/// <remarks>
/// Note that this incurs a full state save, and as such requires the entire beatmap to be encoded, etc.
/// Very frequent use of this method (e.g. once a frame) is most discouraged.
/// If there is need to do so, use local precondition checks to eliminate changes that are known to be no-ops.
/// </remarks>
/// <param name="action">The action to perform.</param>
public void PerformOnSelection(Action<HitObject> action)
{
Expand Down

0 comments on commit 9f6ff48

Please sign in to comment.