mirror of
https://github.com/HappyLifeOk/cc-3-8-x-mcp.git
synced 2026-08-20 13:37:13 +00:00
[cli] 新增: add-spine-socket op(绑定 Spine Socket 到节点)
This commit is contained in:
@@ -70,6 +70,7 @@ node extensions/cc-3-8-x-mcp/cli/bin/cocos-mcp-cli.js <command>
|
|||||||
|---|---|
|
|---|---|
|
||||||
| 加节点 | `add-node` |
|
| 加节点 | `add-node` |
|
||||||
| 加嵌套 prefab 实例(stub) | `add-nested-prefab`(parent + prefabUuid + name? + lpos?) |
|
| 加嵌套 prefab 实例(stub) | `add-nested-prefab`(parent + prefabUuid + name? + lpos?) |
|
||||||
|
| 给 Spine 增加/更新 socket 绑定 | `add-spine-socket`(node + path + target;同 path 幂等更新 target) |
|
||||||
| 替换嵌套 prefab 的 asset uuid(保留 stub 结构) | `replace-nested-prefab`(target + prefabUuid + clearOverrides?) |
|
| 替换嵌套 prefab 的 asset uuid(保留 stub 结构) | `replace-nested-prefab`(target + prefabUuid + clearOverrides?) |
|
||||||
| 删节点 | `remove-node` |
|
| 删节点 | `remove-node` |
|
||||||
| 清悬空嵌套实例根(删了一半的 prefab 残留:父引用没了但根 PrefabInfo 登记还在,残留 asset 仍被加载 → 404)| `sync-nested-roots`(无参,重建根 nestedPrefabInstanceRoots) |
|
| 清悬空嵌套实例根(删了一半的 prefab 残留:父引用没了但根 PrefabInfo 登记还在,残留 asset 仍被加载 → 404)| `sync-nested-roots`(无参,重建根 nestedPrefabInstanceRoots) |
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ Supported ops:
|
|||||||
reorder-children # 调子节点顺序(影响渲染层级)
|
reorder-children # 调子节点顺序(影响渲染层级)
|
||||||
bulk-set # 按 selector(byComponent/byNamePrefix/byNameRegex)一次改一批
|
bulk-set # 按 selector(byComponent/byNamePrefix/byNameRegex)一次改一批
|
||||||
add-node / remove-node / clone-node
|
add-node / remove-node / clone-node
|
||||||
|
add-spine-socket # 给 sp.Skeleton 增加/更新 socket 绑定
|
||||||
add-component / set-component-ref # componentType 支持 @ccclass 名或压缩 classId
|
add-component / set-component-ref # componentType 支持 @ccclass 名或压缩 classId
|
||||||
# set-component-ref 的 refSubNode 可用字符串数组走多层嵌套 stub
|
# set-component-ref 的 refSubNode 可用字符串数组走多层嵌套 stub
|
||||||
set-nested-component-field # 仅 stub 节点(嵌套 prefab)改组件字段
|
set-nested-component-field # 仅 stub 节点(嵌套 prefab)改组件字段
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ const { execSetSprite } = require('./ops/set-sprite.js');
|
|||||||
const { execSetNodeColor } = require('./ops/set-node-color.js');
|
const { execSetNodeColor } = require('./ops/set-node-color.js');
|
||||||
const { execReplaceNestedPrefab } = require('./ops/replace-nested-prefab.js');
|
const { execReplaceNestedPrefab } = require('./ops/replace-nested-prefab.js');
|
||||||
const { execAddNestedPrefab } = require('./ops/add-nested-prefab.js');
|
const { execAddNestedPrefab } = require('./ops/add-nested-prefab.js');
|
||||||
|
const { execAddSpineSocket } = require('./ops/add-spine-socket.js');
|
||||||
const { execResetOverrides } = require('./ops/reset-overrides.js');
|
const { execResetOverrides } = require('./ops/reset-overrides.js');
|
||||||
const { execEnsureMeta } = require('./ops/ensure-meta.js');
|
const { execEnsureMeta } = require('./ops/ensure-meta.js');
|
||||||
const { execSyncNestedRoots } = require('./ops/sync-nested-roots.js');
|
const { execSyncNestedRoots } = require('./ops/sync-nested-roots.js');
|
||||||
@@ -81,6 +82,7 @@ const OP_HANDLERS = {
|
|||||||
'set-node-color': execSetNodeColor,
|
'set-node-color': execSetNodeColor,
|
||||||
'replace-nested-prefab': execReplaceNestedPrefab,
|
'replace-nested-prefab': execReplaceNestedPrefab,
|
||||||
'add-nested-prefab': execAddNestedPrefab,
|
'add-nested-prefab': execAddNestedPrefab,
|
||||||
|
'add-spine-socket': execAddSpineSocket,
|
||||||
'reset-overrides': execResetOverrides,
|
'reset-overrides': execResetOverrides,
|
||||||
'ensure-meta': execEnsureMeta,
|
'ensure-meta': execEnsureMeta,
|
||||||
'sync-nested-roots': execSyncNestedRoots,
|
'sync-nested-roots': execSyncNestedRoots,
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ const T = {
|
|||||||
constraintNum: 'number',
|
constraintNum: 'number',
|
||||||
placeholder: 'string',
|
placeholder: 'string',
|
||||||
string: 'string',
|
string: 'string',
|
||||||
|
path: 'string',
|
||||||
labelNode: 'string',
|
labelNode: 'string',
|
||||||
spriteNode: 'string',
|
spriteNode: 'string',
|
||||||
subNode: 'any', // string | string[]
|
subNode: 'any', // string | string[]
|
||||||
@@ -129,6 +130,7 @@ const SCHEMAS = {
|
|||||||
'set-node-color': { required: ['node'], optional: ['r', 'g', 'b', 'a'] },
|
'set-node-color': { required: ['node'], optional: ['r', 'g', 'b', 'a'] },
|
||||||
'replace-nested-prefab': { required: ['target', 'prefabUuid'], optional: ['clearOverrides'] },
|
'replace-nested-prefab': { required: ['target', 'prefabUuid'], optional: ['clearOverrides'] },
|
||||||
'add-nested-prefab': { required: ['parent', 'prefabUuid'], optional: ['name', 'lpos'] },
|
'add-nested-prefab': { required: ['parent', 'prefabUuid'], optional: ['name', 'lpos'] },
|
||||||
|
'add-spine-socket': { required: ['node', 'path', 'target'], optional: [] },
|
||||||
'reset-overrides': { required: ['node'], optional: ['property', 'componentType', 'subNode', 'all'] },
|
'reset-overrides': { required: ['node'], optional: ['property', 'componentType', 'subNode', 'all'] },
|
||||||
// ensure-meta: 给 .ts/.json 文件创建 .meta(v4 uuid),让后续 className → classId 查表能命中
|
// ensure-meta: 给 .ts/.json 文件创建 .meta(v4 uuid),让后续 className → classId 查表能命中
|
||||||
'ensure-meta': { required: ['path'], optional: [], typeOverrides: { path: 'string' } },
|
'ensure-meta': { required: ['path'], optional: [], typeOverrides: { path: 'string' } },
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
// add-spine-socket: 给普通节点上的 sp.Skeleton 增加 / 更新 Spine socket 绑定
|
||||||
|
// op: { op:'add-spine-socket', node, path, target }
|
||||||
|
//
|
||||||
|
// - node: 挂 sp.Skeleton 的节点
|
||||||
|
// - path: Spine socket path,例如 "root/zk/tou2"
|
||||||
|
// - target: 要绑定到该 socket 的 cc.Node
|
||||||
|
// - 幂等:同 path 已存在时只更新 target,不新增重复 socket 对象
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const { makeSpineSocket } = require('../../primitives.js');
|
||||||
|
const { isStub, resolveNode, findComponent } = require('../helpers.js');
|
||||||
|
|
||||||
|
function execAddSpineSocket(prefabData, op) {
|
||||||
|
const { elements } = prefabData;
|
||||||
|
const { node: nodeSelector, path, target: targetSelector } = op;
|
||||||
|
|
||||||
|
if (typeof path !== 'string' || path.length === 0) {
|
||||||
|
throw new Error(`editPrefab [add-spine-socket]: path 必须是非空字符串`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { node, nodeId } = resolveNode(prefabData, nodeSelector, 'add-spine-socket');
|
||||||
|
if (isStub(elements, node)) {
|
||||||
|
throw new Error(`editPrefab [add-spine-socket]: 节点 "${node._name}" 是 stub 代理,不支持直接改子 prefab 的 sp.Skeleton`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const skeleton = findComponent(elements, node, 'sp.Skeleton');
|
||||||
|
if (!skeleton) {
|
||||||
|
throw new Error(`editPrefab [add-spine-socket]: 节点 "${node._name}" 上找不到 sp.Skeleton 组件`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { nodeId: targetId } = resolveNode(prefabData, targetSelector, 'add-spine-socket target');
|
||||||
|
|
||||||
|
if (!Array.isArray(skeleton._sockets)) skeleton._sockets = [];
|
||||||
|
for (const socketRef of skeleton._sockets) {
|
||||||
|
if (!socketRef || typeof socketRef.__id__ !== 'number') continue;
|
||||||
|
const socket = elements[socketRef.__id__];
|
||||||
|
if (socket && socket.__type__ === 'sp.Skeleton.SpineSocket' && socket.path === path) {
|
||||||
|
socket.target = { __id__: targetId };
|
||||||
|
return nodeId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const socketId = elements.length;
|
||||||
|
elements.push(makeSpineSocket({ path, targetId }));
|
||||||
|
skeleton._sockets.push({ __id__: socketId });
|
||||||
|
return nodeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { execAddSpineSocket };
|
||||||
@@ -391,6 +391,22 @@ function makeSpSkeleton(opts) {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造 sp.Skeleton.SpineSocket 裸对象。
|
||||||
|
* @param {object} opts
|
||||||
|
* @param {string} opts.path - Spine bone/slot path,例如 root/zk/tou2
|
||||||
|
* @param {number} opts.targetId - 绑定的 cc.Node __id__
|
||||||
|
* @returns {object}
|
||||||
|
*/
|
||||||
|
function makeSpineSocket(opts) {
|
||||||
|
const { path, targetId } = opts;
|
||||||
|
return {
|
||||||
|
__type__: 'sp.Skeleton.SpineSocket',
|
||||||
|
path,
|
||||||
|
target: ref(targetId),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
// cc.PrefabInfo / cc.CompPrefabInfo
|
// cc.PrefabInfo / cc.CompPrefabInfo
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
@@ -469,6 +485,7 @@ module.exports = {
|
|||||||
makeLabel,
|
makeLabel,
|
||||||
makeWidget,
|
makeWidget,
|
||||||
makeSpSkeleton,
|
makeSpSkeleton,
|
||||||
|
makeSpineSocket,
|
||||||
// Prefab 元信息
|
// Prefab 元信息
|
||||||
makePrefabInfo,
|
makePrefabInfo,
|
||||||
makeCompPrefabInfo,
|
makeCompPrefabInfo,
|
||||||
|
|||||||
@@ -360,6 +360,7 @@ stub 节点(嵌套 prefab 实例)在 prefab JSON 里 `_name = ""`(空字
|
|||||||
| op | 参数 | 说明 |
|
| op | 参数 | 说明 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `add-node` | `parent`, `node: {name, lpos?, active?, components?, width?, height?, anchor?}` | 新增 cc.Node;parent 是 stub 时走 mountedChildren。`components: ["UITransform"]` 自动建 UITransform |
|
| `add-node` | `parent`, `node: {name, lpos?, active?, components?, width?, height?, anchor?}` | 新增 cc.Node;parent 是 stub 时走 mountedChildren。`components: ["UITransform"]` 自动建 UITransform |
|
||||||
|
| `add-spine-socket` | `node`, `path`, `target` | 给普通节点上的 `sp.Skeleton` 新增 / 更新 `sp.Skeleton.SpineSocket`。`path` 是 Spine socket path(如 `root/zk/tou2`),`target` 是绑定节点;同 path 幂等更新 target,不重复追加 |
|
||||||
| `remove-node` | `target` | 从父节点移除引用;元素本身保留(orphan),保持其他 `__id__` 稳定 |
|
| `remove-node` | `target` | 从父节点移除引用;元素本身保留(orphan),保持其他 `__id__` 稳定 |
|
||||||
| `sync-nested-roots` | (无) | 重建根 `PrefabInfo.nestedPrefabInstanceRoots`,剔除「删了一半」残留的悬空嵌套实例根(节点 `_parent` 已移除但根登记残留 → 残留嵌套 prefab 的 asset 仍被当依赖加载,运行时 404)。只重写该数组,不删 elements、不动其他 `__id__`、不产生 null 槽;被孤立的残留对象成为不可达 orphan。复用 remove-node 内部同名逻辑 |
|
| `sync-nested-roots` | (无) | 重建根 `PrefabInfo.nestedPrefabInstanceRoots`,剔除「删了一半」残留的悬空嵌套实例根(节点 `_parent` 已移除但根登记残留 → 残留嵌套 prefab 的 asset 仍被当依赖加载,运行时 404)。只重写该数组,不删 elements、不动其他 `__id__`、不产生 null 槽;被孤立的残留对象成为不可达 orphan。复用 remove-node 内部同名逻辑 |
|
||||||
| `clone-node` | `source`, `parent`, `name` | 深拷贝整棵子树,分配新 `__id__` + 新 fileId |
|
| `clone-node` | `source`, `parent`, `name` | 深拷贝整棵子树,分配新 `__id__` + 新 fileId |
|
||||||
|
|||||||
Reference in New Issue
Block a user