Skip to content

fix(scene): route root path to editor root in create flow. - #878

Merged
star-e merged 1 commit into
cocos:mainfrom
qiuguohua:fix/prefab-default-parent-path
Aug 25, 2026
Merged

fix(scene): route root path to editor root in create flow.#878
star-e merged 1 commit into
cocos:mainfrom
qiuguohua:fix/prefab-default-parent-path

Conversation

@qiuguohua

Copy link
Copy Markdown
Contributor

Summary

In prefab edit mode, right-clicking with no selection (Pink sends path: '/' as parent) used to create the new node as a sibling of the prefab root, which the single-root constraint then discarded — the node "disappeared right after creation".

NodeMgr.getNodeByPath('/') returns cc.director.getScene(), which in prefab mode is the virtual scene hosting the prefab, not the prefab root. _getOrCreateNodeByPath and _getCreatePathPreflight accepted that as a truthy parent, bypassing the caller's parent = currentScene fallback (= Service.Editor.getRootNode() = the prefab root).

The component.ts add-component path already handles this with a resolveNodeByPath helper (#872). This aligns the node-create flow with the same convention.

Changes

  • _getOrCreateNodeByPath (node.ts): widen the early-return guard from !path to !path || isRootNodePath(path), so root-like inputs (/, //, ///) fall through to parent = currentScene.
  • _getCreatePathPreflight (node.ts): same guard on the NodeMgr.getNodeByPath short-circuit; the existing empty-pathParts fallback already produces parent: currentScene, now unmasked for /.

Tests

New file src/core/scene/test/service-core/node-create-root-path-prefab.test.ts (4 cases):

  1. path: '/' in prefab mode: new empty node's setParent is called with the prefab root, not the virtual scene.
  2. path: '//' normalizes to the same behaviour.
  3. preflightCreate({ path: '/' }) in prefab mode plans uiTransformPath: '/PrefabRoot' when the prefab root has a UITransform — i.e. preflight sees the prefab root as parent, not the virtual scene.
  4. Non-root paths (e.g. /ExistingChild) still resolve via NodeMgr.getNodeByPath unchanged.

Verified the tests catch the regression: reverting either isRootNodePath guard in node.ts makes cases 1 and 2 fail with capturedResultNode.parent equal to the virtual scene instead of the prefab root.

npx tsc --noEmit clean. jest src/core/scene/test/service-core/node-create-* — 18/18 pass (14 existing + 4 new).

QA notes

Reproduce on any prefab:

  1. Open a prefab in Pink.
  2. Deselect everything in the hierarchy.
  3. Right-click on empty hierarchy area → create an empty node (or drag a prefab in).

Before this PR: the newly created node flashes and is gone. After: it appears as a direct child of the prefab root.

_getOrCreateNodeByPath and _getCreatePathPreflight let NodeMgr.getNodeByPath('/')
short-circuit to cc.director.getScene(). In prefab mode that returns the
virtual scene hosting the prefab, not the prefab root, so a new node with
`path: '/'` landed as a sibling of the prefab root and got pruned by the
single-root constraint.

Detect root paths early with isRootNodePath so both helpers fall through to
`parent = currentScene` (= Service.Editor.getRootNode()), matching the
resolveNodeByPath helper already used by component.ts.
@qiuguohua

Copy link
Copy Markdown
Contributor Author

@qiuguohua qiuguohua changed the title fix(scene): route root path to editor root in create flow fix(scene): route root path to editor root in create flow. Aug 25, 2026
@qiuguohua
qiuguohua requested a review from star-e August 25, 2026 02:46
@star-e
star-e merged commit eff2b35 into cocos:main Aug 25, 2026
6 of 8 checks passed
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.

4 participants