Skip to content

Fix crash when clicking on another object mid-placement of spinner - #38513

Merged
peppy merged 2 commits into
ppy:masterfrom
bdach:spinners-crashing
Aug 4, 2026
Merged

Fix crash when clicking on another object mid-placement of spinner#38513
peppy merged 2 commits into
ppy:masterfrom
bdach:spinners-crashing

Conversation

@bdach

@bdach bdach commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Closes #38509.

You might be thinking: "@bdach is dumb and/or incompetent for not just directly reverting #38464 and instead just reverting half of it in #38506". That is certainly what I was thinking until I tried reverting and found that it actually doesn't help. This is actually a silent regression from #37485!

The chain of failure goes something like this:

  1. Start with editor seeked to a start time of one of the existing objects.

  2. Begin placing a spinner.

  3. Click the object that starts at the current time.

  4. On master, SpinnerPlacementBlueprint does not consume the left click input when spinner placement has already started. This means that the left click input is allowed to fall through to the blueprint container.

  5. When the left click input falls through to the blueprint container, it triggers selection logic to fire and the existing object to become selected.

  6. Object selection changing also changes the currently used tool to the "select" tool:

    private void selectionChanged(object sender, NotifyCollectionChangedEventArgs changedArgs)
    {
    if (EditorBeatmap.SelectedHitObjects.Any())
    {
    // ensure in selection mode if a selection is made.
    SetSelectTool();
    }
    }

  7. Changing the currently used tool causes any pending placement to be committed if valid:

    // As per stable editor, when changing tools, we should forcefully commit any pending placement.
    CommitIfPlacementActive();

  8. Committing the placement causes the object whose attempt at selection triggered this entire chain of events to begin with to be removed:

    EditorBeatmap.BeginChange();
    foreach (var h in EditorBeatmap.HitObjects.Where(ho => blueprintContainer.CurrentHitObjectPlacement?.ReplacesExistingObject(ho) == true).ToArray())
    EditorBeatmap.Remove(h);
    EditorBeatmap.Add(hitObject);
    EditorBeatmap.EndChange();

    And therefore the failure is understandable, because at that point the placement blueprint of the now-removed object really does not reside in the container.

    Prior to Replace hit objects when placing at same time in editor #37485 this would not cause an issue because the objects would both exist here.

To fix, prevent the issue at point (4) by making the placement blueprint consume left clicks and not allow fall-through to existing objects.

bdach added 2 commits August 4, 2026 09:01
You might be thinking: "@bdach is dumb and/or incompetent for not just
directly reverting ppy#38464 and instead
just reverting half of it in ppy#38506".
That is certainly what *I* was thinking until I tried reverting and
found that it actually doesn't help. This is actually a silent
regression from ppy#37485!

The chain of failure goes something like this:

1. Start with editor seeked to a start time of one of the existing
   objects.
2. Begin placing a spinner.
3. Click the object that starts at the current time.
4. On master, `SpinnerPlacementBlueprint` does not consume the left
   click input when spinner placement has already started.
   This means that the left click input is allowed to fall through to
   the blueprint container.
5. When the left click input falls through to the blueprint container,
   it triggers selection logic to fire and the existing object to become
   selected.
6. Object selection changing also changes the currently used tool to the
   "select" tool:

   https://github.com/ppy/osu/blob/cd27c935d6c15c3c6f2f5b561cc3340130f27407/osu.Game/Rulesets/Edit/HitObjectComposer.cs#L504-L511
7. Changing the currently used tool causes any pending placement to be
   committed if valid:

   https://github.com/ppy/osu/blob/abbf6e23492c471d722827c5b8baa935fad19419/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs#L437-L438
8. Committing the placement causes *the object whose attempt at
   selection triggered this entire chain of events to begin with* to be
   removed:

   https://github.com/ppy/osu/blob/cd27c935d6c15c3c6f2f5b561cc3340130f27407/osu.Game/Rulesets/Edit/HitObjectComposer.cs#L545-L550

   And therefore the failure is understandable, because at that point
   the placement blueprint of the now-removed object *really* does not
   reside in the container.

   Prior to ppy#37485 this would not cause
   an issue because the objects would both exist here.

To fix, prevent the issue at point (4) by making the placement blueprint
consume left clicks and not allow fall-through to existing objects.
@bdach bdach self-assigned this Aug 4, 2026
@bdach bdach added ruleset/osu! area:editor type/reliability Deals with game crashing or breaking in a serious way. labels Aug 4, 2026
@bdach bdach moved this from Inbox to Pending Review in osu! team task tracker Aug 4, 2026
@peppy
peppy self-requested a review August 4, 2026 09:22

@peppy peppy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirm crash and confirm fix. Editor interactions are... complex.

@peppy
peppy merged commit 426c160 into ppy:master Aug 4, 2026
7 of 10 checks passed
@github-project-automation github-project-automation Bot moved this from Pending Review to Done in osu! team task tracker Aug 4, 2026
@bdach
bdach deleted the spinners-crashing branch August 4, 2026 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:editor ruleset/osu! size/M type/reliability Deals with game crashing or breaking in a serious way.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Clicking through spinner on other elements crashes the game

2 participants