mirror of
https://github.com/HappyLifeOk/cc-3-8-x-mcp.git
synced 2026-06-10 17:56:47 +00:00
92 lines
3.4 KiB
JavaScript
92 lines
3.4 KiB
JavaScript
|
|
// reparent: 把节点从原父节点下移到新父节点下(不复制,原节点搬家)
|
|||
|
|
// op: { op:'reparent', node, parent, index? }
|
|||
|
|
//
|
|||
|
|
// 行为:
|
|||
|
|
// 1. 从原 parent._children 数组里移除 node 引用
|
|||
|
|
// 2. 把 node 引用 push 到新 parent._children(或按 index 插入指定位置)
|
|||
|
|
// 3. 改 node._parent 指向新 parent
|
|||
|
|
//
|
|||
|
|
// 限制:
|
|||
|
|
// - 不支持 stub 节点(嵌套 prefab 实例)作为 source 或 target
|
|||
|
|
// stub 的父子关系存在 PrefabInstance.mountedChildren / nestedPrefabInstanceRoots,
|
|||
|
|
// 需要独立的 nested-reparent op,本 op 仅处理普通 inline 节点
|
|||
|
|
// - node 不能是 prefab 根节点(rootId=1),根节点 _parent 必须为 null
|
|||
|
|
// - parent 不能是 node 的后代(避免循环)
|
|||
|
|
// - 不修改 PrefabInfo.fileId(节点身份不变,外部引用仍然有效)
|
|||
|
|
|
|||
|
|
'use strict';
|
|||
|
|
|
|||
|
|
const { isStub, resolveNode } = require('../helpers.js');
|
|||
|
|
|
|||
|
|
/** node 是否是 parent(或其后代)的祖先 → 循环检测 */
|
|||
|
|
function isAncestorOf(elements, ancestorId, candidateId) {
|
|||
|
|
let cur = candidateId;
|
|||
|
|
let safety = 0;
|
|||
|
|
while (cur != null && safety++ < 10000) {
|
|||
|
|
if (cur === ancestorId) return true;
|
|||
|
|
const node = elements[cur];
|
|||
|
|
if (!node || !node._parent) return false;
|
|||
|
|
cur = node._parent.__id__;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function execReparent(prefabData, op) {
|
|||
|
|
const { elements, rootId } = prefabData;
|
|||
|
|
const { node: nodeSelector, parent: parentSelector, index } = op;
|
|||
|
|
|
|||
|
|
const { node, nodeId } = resolveNode(prefabData, nodeSelector, 'reparent');
|
|||
|
|
const { node: newParent, nodeId: newParentId } = resolveNode(prefabData, parentSelector, 'reparent');
|
|||
|
|
|
|||
|
|
// 根节点不能搬家
|
|||
|
|
if (nodeId === rootId) {
|
|||
|
|
throw new Error(`editPrefab [reparent]: 根节点(id=${rootId})不能 reparent,其 _parent 必须为 null`);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// stub 检查
|
|||
|
|
if (isStub(elements, node)) {
|
|||
|
|
throw new Error(`editPrefab [reparent]: source 是 stub 节点(嵌套 prefab 实例),不支持,需独立 op`);
|
|||
|
|
}
|
|||
|
|
if (isStub(elements, newParent)) {
|
|||
|
|
throw new Error(`editPrefab [reparent]: target parent 是 stub 节点(嵌套 prefab 实例),不支持,需独立 op`);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 同一节点不动
|
|||
|
|
const oldParentId = node._parent ? node._parent.__id__ : null;
|
|||
|
|
if (oldParentId === newParentId) {
|
|||
|
|
// 仅 index 调整 → 走 reorder-children 更清晰;这里允许只换位(reorder 调整)
|
|||
|
|
if (index === undefined) return nodeId;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 循环检测:newParent 不能是 node 的后代
|
|||
|
|
if (isAncestorOf(elements, nodeId, newParentId)) {
|
|||
|
|
throw new Error(`editPrefab [reparent]: 循环引用——新父节点(id=${newParentId})是源节点(id=${nodeId})的后代`);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 1. 从原 parent._children 移除
|
|||
|
|
if (oldParentId != null) {
|
|||
|
|
const oldParent = elements[oldParentId];
|
|||
|
|
if (oldParent && Array.isArray(oldParent._children)) {
|
|||
|
|
oldParent._children = oldParent._children.filter(
|
|||
|
|
(c) => !c || c.__id__ !== nodeId
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 加到新 parent._children
|
|||
|
|
if (!Array.isArray(newParent._children)) newParent._children = [];
|
|||
|
|
const ref = { __id__: nodeId };
|
|||
|
|
if (typeof index === 'number' && index >= 0 && index < newParent._children.length) {
|
|||
|
|
newParent._children.splice(index, 0, ref);
|
|||
|
|
} else {
|
|||
|
|
newParent._children.push(ref);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. 改 node._parent
|
|||
|
|
node._parent = { __id__: newParentId };
|
|||
|
|
|
|||
|
|
return nodeId;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = { execReparent };
|