-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix placing objects via touch in editor not working sometimes #30411
Conversation
…input More specifically, this fixes placement blueprints not beginning placement when using touch input while the cursor was previously outside compose area, due to the placement blueprint not existing (removed from the scene by `ComposeBlueprintContainer`).
@@ -127,6 +129,16 @@ protected override bool Handle(UIEvent e) | |||
} | |||
} | |||
|
|||
protected override void PopIn() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we want a fade.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought it may be a nice touch, no problem.
I think the direction seems okay. Will need some conflict resolution on tests (need to be moved to new class). |
osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs
Outdated
Show resolved
Hide resolved
In initial testing I can't find any edge cases that don't match previous behaviour. But reviewing this change is a bit arduous due to the amount of weird logic surrounding the placement object (and the change doesn't simplify but instead adds more new state). Will need some time to work through this. |
- Closes ppy#31423. - Regressed in ppy#30411. Admittedly, I don't completely understand all of the pieces here, because code quality of this placement blueprint code is ALL-CAPS ATROCIOUS, but I believe the failure mode to be something along the lines of: - User activates juice stream tool, blueprint gets created in initial state. It reads in a mouse position far outside of the playfield, and sets internal positioning appropriately. - When the user moves the mouse into the bounds of the playfield, some positions update (the ones inside `UpdateTimeAndPosition()`, but the fruit markers are for *nested* objects, and `updateHitObjectFromPath()` is responsible for updating those... however, it only fires if the `editablePath.PathId` changes, which it won't here, because there is only one path vertex until the user commits the starting point of the juice stream and it's always at (0,0). - Therefore the position of the starting fruit marker remains bogus until left click, at which point the path changes and everything returns to *relative* sanity. An alternative solution that shows this hypothesis to be true follows in the diff below: diff --cc osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs index 7b57dac36e,7b57dac36e..21cc260462 --- a/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Catch/Edit/Blueprints/JuiceStreamPlacementBlueprint.cs @@@ -88,10 -88,10 +88,9 @@@ namespace osu.Game.Rulesets.Catch.Edit. switch (PlacementActive) { case PlacementState.Waiting: -- if (!(result.Time is double snappedTime)) return; -- HitObject.OriginalX = ToLocalSpace(result.ScreenSpacePosition).X; -- HitObject.StartTime = snappedTime; ++ if (result.Time is double snappedTime) ++ HitObject.StartTime = snappedTime; break; case PlacementState.Active: @@@ -107,21 -107,21 +106,13 @@@ Vector2 startPosition = CatchHitObjectUtils.GetStartPosition(HitObjectContainer, HitObject); editablePath.Position = nestedOutlineContainer.Position = scrollingPath.Position = startPosition; -- updateHitObjectFromPath(); -- } -- -- private void updateHitObjectFromPath() -- { -- if (lastEditablePathId == editablePath.PathId) -- return; ++ if (lastEditablePathId != editablePath.PathId) ++ editablePath.UpdateHitObjectFromPath(HitObject); ++ lastEditablePathId = editablePath.PathId; -- editablePath.UpdateHitObjectFromPath(HitObject); ApplyDefaultsToHitObject(); -- scrollingPath.UpdatePathFrom(HitObjectContainer, HitObject); nestedOutlineContainer.UpdateNestedObjectsFrom(HitObjectContainer, HitObject); -- -- lastEditablePathId = editablePath.PathId; } private double positionToTime(float relativeYPosition) The patch essentially relies on inlining the broken method and only guarding the relevant part of processing behind the path version check (which is actually updating the path). Everything else that can touch positions of nesteds (like default application, and the drawable piece updates) is allowed to happen unconditionally. On one side, that patch looks more proper, but also does more processing, and is less safe, so I kinda just went with the easier option?
- Closes ppy#31423. - Regressed in ppy#30411. Admittedly, I don't completely understand all of the pieces here, because code quality of this placement blueprint code is ALL-CAPS ATROCIOUS, but I believe the failure mode to be something along the lines of: - User activates juice stream tool, blueprint gets created in initial state. It reads in a mouse position far outside of the playfield, and sets internal positioning appropriately. - When the user moves the mouse into the bounds of the playfield, some positions update (the ones inside `UpdateTimeAndPosition()`, but the fruit markers are for *nested* objects, and `updateHitObjectFromPath()` is responsible for updating those... however, it only fires if the `editablePath.PathId` changes, which it won't here, because there is only one path vertex until the user commits the starting point of the juice stream and it's always at (0,0). - Therefore the position of the starting fruit marker remains bogus until left click, at which point the path changes and everything returns to *relative* sanity. The solution essentially relies on inlining the broken method and only guarding the relevant part of processing behind the path version check (which is actually updating the path). Everything else that can touch positions of nesteds (like default application, and the drawable piece updates) is allowed to happen unconditionally.
- Closes ppy#31423. - Regressed in ppy#30411. Admittedly, I don't completely understand all of the pieces here, because code quality of this placement blueprint code is ALL-CAPS ATROCIOUS, but I believe the failure mode to be something along the lines of: - User activates juice stream tool, blueprint gets created in initial state. It reads in a mouse position far outside of the playfield, and sets internal positioning appropriately. - When the user moves the mouse into the bounds of the playfield, some positions update (the ones inside `UpdateTimeAndPosition()`, but the fruit markers are for *nested* objects, and `updateHitObjectFromPath()` is responsible for updating those... however, it only fires if the `editablePath.PathId` changes, which it won't here, because there is only one path vertex until the user commits the starting point of the juice stream and it's always at (0,0). - Therefore the position of the starting fruit marker remains bogus until left click, at which point the path changes and everything returns to *relative* sanity. The solution essentially relies on inlining the broken method and only guarding the relevant part of processing behind the path version check (which is actually updating the path). Everything else that can touch positions of nesteds (like default application, and the drawable piece updates) is allowed to happen unconditionally.
Placing objects in editor requires the presence of a
PlacementBlueprint
that responds to the input of the user placing the object. But placement blueprints are programmed to be removed when the user's cursor is outside the compose area.Similar to the symptoms in #30263, in the case of touch input, if the current position of the cursor (led by where the user has tapped the screen last time) is currently outside the compose area, then if the user tries to tap on the compose screen to place an object, nothing happens because there's no
PlacementBlueprint
present at the point of the user tapping the compose area.Unlike #30263, this cannot be resolved by responding to mouse movement events and create a
PlacementBlueprint
right before the subsequent mouse click event is raised, because adding a drawable in the scene requires waiting a full update frame cycle in order for the drawable to become alive (which is a prerequisite for the drawable to be considered in the input queue).Instead, this PR resolves the issue by making placement blueprints always exist, and change their visibility state instead. This required a minor refactor around the
IPlacementHandler
interface to better work with the new behaviour.ScreenRecording_10-23-2024.16-55-59_1.MP4