Skip to content

[Editor] Change TransformationGizmo Update to be synchronous and change entity duplication behavior#3186

Open
Basewq wants to merge 1 commit into
stride3d:masterfrom
Basewq:gizmo_sync_update
Open

[Editor] Change TransformationGizmo Update to be synchronous and change entity duplication behavior#3186
Basewq wants to merge 1 commit into
stride3d:masterfrom
Basewq:gizmo_sync_update

Conversation

@Basewq
Copy link
Copy Markdown
Contributor

@Basewq Basewq commented May 23, 2026

PR Details

This serves as a bit of prep work leading to #3183.

The purpose of this PR is to remove the async part of TransformationGizmo.Update.
The only two places where async is used is:

  1. Keyboard shortcut to change the transform gizmo mode (translate/rotate/scale via W/E/R keys)
  2. Hold Ctrl -> Drag gizmo to duplicate entities (note: an existing quirk is you must focus in the scene before Ctrl key down is detected, which is not fixed in this PR).

My changes and reasoning:

  1. No longer await UI invoke. This is an example of game -> editor -> game, which relies on the editor -> game return to set update the transform gizmo mode (refer to Related Issue section for a bit more context).
    It now just treats it as a fire-and-forget request to the editor, which will 'eventually' update the mode back to the game thread.
    I'm not really sure if there is a cleaner solution, other than either 'predicting' the mode change (ie. update directly as well), or block the gizmo until the editor 'confirms' the request.

  2. Moved the entity duplication logic out of the transform gizmo and into EditorGameEntityTransformService.
    This makes the transform gizmo reusable for other things which may or may not have 'duplication' logic (eg. spline tool).
    Another change, which might be more debatable, is now the initial duplication is only done on the game side (temp cloned entities), then at the end of the transform the request is sent to the editor.
    Doing it this way also means there is only one undo/redo transaction, whereas the previous behavior had two transactions (1st transaction on the drag start to generate entities in place, then a 2nd transaction for the position update), ie. you had to undo twice to actually remove the duplicated objects.
    One other quirk is when duplicating a large number of entities (eg. use 3rd Person Platformer template and duplicate the entire 'Platform' folder via Ctrl + drag), the original behavior has a large initial freeze since it clones at the start.
    This change makes the large freeze occur at the end of the transform (along with a progress bar popup if longer than 500ms), however this does introduce a different quirk where the preview entities disappear then the real objects are added afterwards.

  3. (New functionality) There is also now the ability to hit Escape key to cancel the transform when you're in the middle of transforming (no transaction goes the editor).

Related Issue

Prep work for #3183

Regarding further context for change 1:
There is a bit of concern with the current architecture of the 'game services', which may need additional thoughts on.
The issue is the back and forth marshaling between 'WPF UI thread' (ie. where the asset/quantum data live) and the 'game thread' (ie. live scene editor).

There are some 'game services' that contain both the game scene data and the 'view model'/UI thread data (ie. implement IEditorGameService and IEditorGameViewModelService as a single class), and can end up doing things like 'game thread' -> await InvokeAsync to 'UI thread' -> InvokeAsync to 'game thread', which is exactly what the gizmo code was doing.

Regarding further context for change 2:
The future goal is to change classes that inherit EditorGameMouseServiceBase to only have sync update methods, so they can ultimately be bundled through some 'edit mode' class and updated in some specified order (and optionally enabled/disabled depending on the mode), rather than the free-for-all approach that's happening now (they will still have the option to register an independent task via ScriptSystem if they need it).

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Not sure if doc change is required or not, TranslationGizmo/ScaleGizmo/RotationGizmo are public, however these gizmos are part of Stride.Assets.Presentation, which the general user cannot accidentally stumble into due to the lack of proper plugin integration.

Checklist

  • My change requires a change to the documentation.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have built and run the editor to try this change out.

…tity duplication from gizmo to EditorGameEntityTransformService.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant