feat: 优化 UI 节点创建逻辑,修复 UUID 解析问题,并将所有文档和注释更新为简体中文
This commit is contained in:
20
README.md
20
README.md
@@ -123,15 +123,27 @@ Args: [你的项目所在盘符]:/[项目路径]/packages/mcp-bridge/mcp-proxy.j
|
|||||||
|
|
||||||
### 7. create_node
|
### 7. create_node
|
||||||
|
|
||||||
- **描述**: 在当前场景中创建一个新节点。对于 Canvas/Label 类型,会自动添加对应组件。
|
- **描述**: 在当前场景中创建一个新节点。
|
||||||
|
- **重要提示**:
|
||||||
|
1. 如果指定了 `parentId`,必须先通过 `get_scene_hierarchy` 确认该 UUID 对应的父节点仍然存在。
|
||||||
|
2. **预设类型差异**:
|
||||||
|
- `empty`: 纯空节点,无组件,不带贴图。
|
||||||
|
- `sprite`: 自动添加 Sprite 组件,默认尺寸 100x100,并带有引擎默认贴图占位。
|
||||||
|
- `button`: 自动添加 Sprite 和 Button 组件,默认尺寸 **150x50**,背景色设为深色以便看清文字,并带有默认贴图。
|
||||||
|
- `label`: 自动添加 Label 组件,默认尺寸 120x40。
|
||||||
- **参数**:
|
- **参数**:
|
||||||
- `name`: 节点名称
|
- `name`: 节点名称
|
||||||
- `parentId`: 父节点 UUID (可选,不传则挂在场景根部)
|
- `parentId`: 父节点 UUID (可选)
|
||||||
- `type`: 节点预设类型(`empty`, `sprite`, `label`, `canvas`)
|
- `type`: 节点预设类型(`empty`, `sprite`, `label`, `button`)
|
||||||
|
|
||||||
### 8. manage_components
|
### 8. manage_components
|
||||||
|
|
||||||
- **描述**: 管理节点组件。**重要最佳实践**:在执行 `add` 操作前,建议先通过 `get` 操作检查节点上是否已存在同类型的组件,以避免重复添加。
|
- **描述**: 管理节点组件。
|
||||||
|
- **重要最佳实践**:
|
||||||
|
1. **引用验证**:操作前必须调用 `get_scene_hierarchy` 确认 `nodeId` 对应的节点真实存在(防止由于场景重置或节点删除导致的引用失效)。
|
||||||
|
2. 在执行 `add` 操作前,建议先通过 `get` 操作检查是否已存在同类组件。
|
||||||
|
3. 添加 `cc.Sprite` 后请务必设置其 `spriteFrame` 属性,否则节点将不显示。
|
||||||
|
4. 创建按钮时,请确保目标节点有正数尺寸(`width`/`height`)作为点击区域。
|
||||||
- **参数**:
|
- **参数**:
|
||||||
- `nodeId`: 节点 UUID
|
- `nodeId`: 节点 UUID
|
||||||
- `action`: 操作类型(`add`, `remove`, `get`, `update`)
|
- `action`: 操作类型(`add`, `remove`, `get`, `update`)
|
||||||
|
|||||||
89
main.js
89
main.js
@@ -14,7 +14,11 @@ let serverConfig = {
|
|||||||
active: false,
|
active: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 封装日志函数,同时发送给面板和编辑器控制台
|
/**
|
||||||
|
* 封装日志函数,同时发送给面板、保存到内存并在编辑器控制台打印
|
||||||
|
* @param {'info' | 'success' | 'warn' | 'error'} type 日志类型
|
||||||
|
* @param {string} message 日志内容
|
||||||
|
*/
|
||||||
function addLog(type, message) {
|
function addLog(type, message) {
|
||||||
const logEntry = {
|
const logEntry = {
|
||||||
time: new Date().toLocaleTimeString(),
|
time: new Date().toLocaleTimeString(),
|
||||||
@@ -33,10 +37,18 @@ function addLog(type, message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取完整的日志内容(文本格式)
|
||||||
|
* @returns {string} 拼接后的日志字符串
|
||||||
|
*/
|
||||||
function getLogContent() {
|
function getLogContent() {
|
||||||
return logBuffer.map(entry => `[${entry.time}] [${entry.type}] ${entry.content}`).join('\n');
|
return logBuffer.map(entry => `[${entry.time}] [${entry.type}] ${entry.content}`).join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成新场景的 JSON 模板数据
|
||||||
|
* @returns {string} 场景数据的 JSON 字符串
|
||||||
|
*/
|
||||||
const getNewSceneTemplate = () => {
|
const getNewSceneTemplate = () => {
|
||||||
// 尝试获取 UUID 生成函数
|
// 尝试获取 UUID 生成函数
|
||||||
let newId = "";
|
let newId = "";
|
||||||
@@ -74,11 +86,15 @@ const getNewSceneTemplate = () => {
|
|||||||
return JSON.stringify(sceneData);
|
return JSON.stringify(sceneData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有支持的 MCP 工具列表定义
|
||||||
|
* @returns {Array<Object>} 工具定义数组
|
||||||
|
*/
|
||||||
const getToolsList = () => {
|
const getToolsList = () => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: "get_selected_node",
|
name: "get_selected_node",
|
||||||
description: "获取当前编辑器中选中的节点 ID",
|
description: "获取当前编辑器中选中的节点 ID。建议获取后立即调用 get_scene_hierarchy 确认该节点是否仍存在于当前场景中。",
|
||||||
inputSchema: { type: "object", properties: {} },
|
inputSchema: { type: "object", properties: {} },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -105,7 +121,7 @@ const getToolsList = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "update_node_transform",
|
name: "update_node_transform",
|
||||||
description: "修改节点的坐标、缩放或颜色",
|
description: "修改节点的坐标、缩放或颜色。执行前必须调用 get_scene_hierarchy 确保 node ID 有效。",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
@@ -158,7 +174,7 @@ const getToolsList = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "create_node",
|
name: "create_node",
|
||||||
description: "在当前场景中创建一个新节点",
|
description: "在当前场景中创建一个新节点。重要提示:1. 如果指定 parentId,必须先调用 get_scene_hierarchy 确保该父节点真实存在。2. 类型说明:'sprite' (100x100 尺寸 + 默认贴图), 'button' (150x50 尺寸 + 深色底图 + Button组件), 'label' (120x40 尺寸 + Label组件), 'empty' (纯空节点)。",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
@@ -169,7 +185,7 @@ const getToolsList = () => {
|
|||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: "string",
|
type: "string",
|
||||||
enum: ["empty", "sprite", "label"],
|
enum: ["empty", "sprite", "label", "button"],
|
||||||
description: "节点预设类型",
|
description: "节点预设类型",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -178,7 +194,7 @@ const getToolsList = () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "manage_components",
|
name: "manage_components",
|
||||||
description: "管理节点组件。重要提示:在执行 'add' 操作前,请务必先通过 'get' 操作检查节点上是否已存在同类型的组件,以避免重复添加导致逻辑异常。",
|
description: "管理节点组件。重要提示:1. 操作前必须调用 get_scene_hierarchy 确认 nodeId 对应的节点仍然存在。2. 添加前先用 'get' 检查是否已存在。3. 添加 cc.Sprite 后必须设置 spriteFrame 属性,否则节点不显示。4. 创建按钮时,请确保目标节点有足够的 width 和 height 作为点击区域。",
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
@@ -486,6 +502,9 @@ const getToolsList = () => {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"scene-script": "scene-script.js",
|
"scene-script": "scene-script.js",
|
||||||
|
/**
|
||||||
|
* 插件加载时的回调
|
||||||
|
*/
|
||||||
load() {
|
load() {
|
||||||
addLog("info", "MCP Bridge Plugin Loaded");
|
addLog("info", "MCP Bridge Plugin Loaded");
|
||||||
// 读取配置
|
// 读取配置
|
||||||
@@ -501,15 +520,25 @@ module.exports = {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 获取配置文件的辅助函数
|
/**
|
||||||
|
* 获取插件配置文件的辅助函数
|
||||||
|
* @returns {Object} Editor.Profile 实例
|
||||||
|
*/
|
||||||
getProfile() {
|
getProfile() {
|
||||||
// 'local' 表示存储在项目本地(local/mcp-bridge.json)
|
// 'local' 表示存储在项目本地(local/mcp-bridge.json)
|
||||||
return Editor.Profile.load("profile://local/mcp-bridge.json", "mcp-bridge");
|
return Editor.Profile.load("profile://local/mcp-bridge.json", "mcp-bridge");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件卸载时的回调
|
||||||
|
*/
|
||||||
unload() {
|
unload() {
|
||||||
this.stopServer();
|
this.stopServer();
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 启动 HTTP 服务器
|
||||||
|
* @param {number} port 监听端口
|
||||||
|
*/
|
||||||
startServer(port) {
|
startServer(port) {
|
||||||
if (mcpServer) this.stopServer();
|
if (mcpServer) this.stopServer();
|
||||||
|
|
||||||
@@ -711,6 +740,12 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理来自 HTTP 的 MCP 调用请求
|
||||||
|
* @param {string} name 工具名称
|
||||||
|
* @param {Object} args 工具参数
|
||||||
|
* @param {Function} callback 完成回调 (err, result)
|
||||||
|
*/
|
||||||
handleMcpCall(name, args, callback) {
|
handleMcpCall(name, args, callback) {
|
||||||
if (isSceneBusy && (name === "save_scene" || name === "create_node")) {
|
if (isSceneBusy && (name === "save_scene" || name === "create_node")) {
|
||||||
return callback("编辑器正忙(正在处理场景),请稍候。");
|
return callback("编辑器正忙(正在处理场景),请稍候。");
|
||||||
@@ -790,6 +825,10 @@ module.exports = {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "create_node":
|
case "create_node":
|
||||||
|
if (args.type === "sprite" || args.type === "button") {
|
||||||
|
const splashUuid = Editor.assetdb.urlToUuid("db://internal/image/default_sprite_splash.png/default_sprite_splash");
|
||||||
|
args.defaultSpriteUuid = splashUuid;
|
||||||
|
}
|
||||||
Editor.Scene.callSceneScript("mcp-bridge", "create-node", args, callback);
|
Editor.Scene.callSceneScript("mcp-bridge", "create-node", args, callback);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -905,7 +944,11 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 管理脚本文件
|
/**
|
||||||
|
* 管理项目中的脚本文件 (TS/JS)
|
||||||
|
* @param {Object} args 参数
|
||||||
|
* @param {Function} callback 完成回调
|
||||||
|
*/
|
||||||
manageScript(args, callback) {
|
manageScript(args, callback) {
|
||||||
const { action, path: scriptPath, content } = args;
|
const { action, path: scriptPath, content } = args;
|
||||||
|
|
||||||
@@ -1005,7 +1048,11 @@ export default class NewScript extends cc.Component {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 批处理执行
|
/**
|
||||||
|
* 批量执行多个 MCP 工具操作
|
||||||
|
* @param {Object} args 参数 (operations 数组)
|
||||||
|
* @param {Function} callback 完成回调
|
||||||
|
*/
|
||||||
batchExecute(args, callback) {
|
batchExecute(args, callback) {
|
||||||
const { operations } = args;
|
const { operations } = args;
|
||||||
const results = [];
|
const results = [];
|
||||||
@@ -1027,7 +1074,11 @@ export default class NewScript extends cc.Component {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 管理资源
|
/**
|
||||||
|
* 通用的资源管理函数 (创建、删除、移动等)
|
||||||
|
* @param {Object} args 参数
|
||||||
|
* @param {Function} callback 完成回调
|
||||||
|
*/
|
||||||
manageAsset(args, callback) {
|
manageAsset(args, callback) {
|
||||||
const { action, path, targetPath, content } = args;
|
const { action, path, targetPath, content } = args;
|
||||||
|
|
||||||
@@ -1095,7 +1146,11 @@ export default class NewScript extends cc.Component {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 场景管理
|
/**
|
||||||
|
* 场景相关的资源管理 (创建、克隆场景等)
|
||||||
|
* @param {Object} args 参数
|
||||||
|
* @param {Function} callback 完成回调
|
||||||
|
*/
|
||||||
sceneManagement(args, callback) {
|
sceneManagement(args, callback) {
|
||||||
const { action, path, targetPath, name } = args;
|
const { action, path, targetPath, name } = args;
|
||||||
|
|
||||||
@@ -1262,7 +1317,11 @@ export default class NewScript extends cc.Component {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 管理编辑器
|
/**
|
||||||
|
* 管理编辑器状态 (选中对象、刷新等)
|
||||||
|
* @param {Object} args 参数
|
||||||
|
* @param {Function} callback 完成回调
|
||||||
|
*/
|
||||||
manageEditor(args, callback) {
|
manageEditor(args, callback) {
|
||||||
const { action, target, properties } = args;
|
const { action, target, properties } = args;
|
||||||
|
|
||||||
@@ -1415,7 +1474,11 @@ export default class NewScript extends cc.Component {
|
|||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
// 应用文本编辑
|
/**
|
||||||
|
* 对文件应用一系列精确的文本编辑操作
|
||||||
|
* @param {Object} args 参数
|
||||||
|
* @param {Function} callback 完成回调
|
||||||
|
*/
|
||||||
applyTextEdits(args, callback) {
|
applyTextEdits(args, callback) {
|
||||||
const { filePath, edits } = args;
|
const { filePath, edits } = args;
|
||||||
|
|
||||||
|
|||||||
155
scene-script.js
155
scene-script.js
@@ -1,11 +1,38 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更加健壮的节点查找函数,支持解压后的 UUID
|
||||||
|
* @param {string} id 节点的 UUID (支持 22 位压缩格式)
|
||||||
|
* @returns {cc.Node | null} 找到的节点对象或 null
|
||||||
|
*/
|
||||||
|
const findNode = (id) => {
|
||||||
|
if (!id) return null;
|
||||||
|
let node = cc.engine.getInstanceById(id);
|
||||||
|
if (!node && typeof Editor !== 'undefined' && Editor.Utils && Editor.Utils.UuidUtils) {
|
||||||
|
// 如果直接查不到,尝试对可能是压缩格式的 ID 进行解压后再次查找
|
||||||
|
try {
|
||||||
|
const decompressed = Editor.Utils.UuidUtils.decompressUuid(id);
|
||||||
|
if (decompressed !== id) {
|
||||||
|
node = cc.engine.getInstanceById(decompressed);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// 忽略转换错误
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
/**
|
||||||
|
* 修改节点的基础属性
|
||||||
|
* @param {Object} event IPC 事件对象
|
||||||
|
* @param {Object} args 参数 (id, path, value)
|
||||||
|
*/
|
||||||
"set-property": function (event, args) {
|
"set-property": function (event, args) {
|
||||||
const { id, path, value } = args;
|
const { id, path, value } = args;
|
||||||
|
|
||||||
// 1. 获取节点
|
// 1. 获取节点
|
||||||
let node = cc.engine.getInstanceById(id);
|
let node = findNode(id);
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
// 2. 修改属性
|
// 2. 修改属性
|
||||||
@@ -34,6 +61,10 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 获取当前场景的完整层级树
|
||||||
|
* @param {Object} event IPC 事件对象
|
||||||
|
*/
|
||||||
"get-hierarchy": function (event) {
|
"get-hierarchy": function (event) {
|
||||||
const scene = cc.director.getScene();
|
const scene = cc.director.getScene();
|
||||||
|
|
||||||
@@ -66,11 +97,16 @@ module.exports = {
|
|||||||
if (event.reply) event.reply(null, hierarchy);
|
if (event.reply) event.reply(null, hierarchy);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新节点的变换信息 (坐标、缩放、颜色)
|
||||||
|
* @param {Object} event IPC 事件对象
|
||||||
|
* @param {Object} args 参数 (id, x, y, scaleX, scaleY, color)
|
||||||
|
*/
|
||||||
"update-node-transform": function (event, args) {
|
"update-node-transform": function (event, args) {
|
||||||
const { id, x, y, scaleX, scaleY, color } = args;
|
const { id, x, y, scaleX, scaleY, color } = args;
|
||||||
Editor.log(`[scene-script] update-node-transform called for ${id} with args: ${JSON.stringify(args)}`);
|
Editor.log(`[scene-script] update-node-transform called for ${id} with args: ${JSON.stringify(args)}`);
|
||||||
|
|
||||||
let node = cc.engine.getInstanceById(id);
|
let node = findNode(id);
|
||||||
|
|
||||||
if (node) {
|
if (node) {
|
||||||
Editor.log(`[scene-script] Node found: ${node.name}, Current Pos: (${node.x}, ${node.y})`);
|
Editor.log(`[scene-script] Node found: ${node.name}, Current Pos: (${node.x}, ${node.y})`);
|
||||||
@@ -107,6 +143,11 @@ module.exports = {
|
|||||||
if (event.reply) event.reply(new Error("找不到节点"));
|
if (event.reply) event.reply(new Error("找不到节点"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 在场景中创建新节点
|
||||||
|
* @param {Object} event IPC 事件对象
|
||||||
|
* @param {Object} args 参数 (name, parentId, type)
|
||||||
|
*/
|
||||||
"create-node": function (event, args) {
|
"create-node": function (event, args) {
|
||||||
const { name, parentId, type } = args;
|
const { name, parentId, type } = args;
|
||||||
const scene = cc.director.getScene();
|
const scene = cc.director.getScene();
|
||||||
@@ -130,18 +171,57 @@ module.exports = {
|
|||||||
camNode.addComponent(cc.Camera);
|
camNode.addComponent(cc.Camera);
|
||||||
camNode.parent = newNode;
|
camNode.parent = newNode;
|
||||||
} else if (type === "sprite") {
|
} else if (type === "sprite") {
|
||||||
newNode = new cc.Node(name || "New Sprite");
|
newNode = new cc.Node(name || "新建精灵节点");
|
||||||
newNode.addComponent(cc.Sprite);
|
let sprite = newNode.addComponent(cc.Sprite);
|
||||||
|
// 设置为 CUSTOM 模式
|
||||||
|
sprite.sizeMode = cc.Sprite.SizeMode.CUSTOM;
|
||||||
|
// 为精灵设置默认尺寸
|
||||||
|
newNode.width = 100;
|
||||||
|
newNode.height = 100;
|
||||||
|
|
||||||
|
// 加载引擎默认图做占位
|
||||||
|
if (args.defaultSpriteUuid) {
|
||||||
|
cc.assetManager.loadAny(args.defaultSpriteUuid, (err, asset) => {
|
||||||
|
if (!err && (asset instanceof cc.SpriteFrame || asset instanceof cc.Texture2D)) {
|
||||||
|
sprite.spriteFrame = asset instanceof cc.SpriteFrame ? asset : new cc.SpriteFrame(asset);
|
||||||
|
Editor.Ipc.sendToMain("scene:dirty");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (type === "button") {
|
||||||
|
newNode = new cc.Node(name || "新建按钮节点");
|
||||||
|
let sprite = newNode.addComponent(cc.Sprite);
|
||||||
|
newNode.addComponent(cc.Button);
|
||||||
|
|
||||||
|
// 设置为 CUSTOM 模式并应用按钮专用尺寸
|
||||||
|
sprite.sizeMode = cc.Sprite.SizeMode.CUSTOM;
|
||||||
|
newNode.width = 150;
|
||||||
|
newNode.height = 50;
|
||||||
|
|
||||||
|
// 设置稍暗的背景颜色 (#A0A0A0),以便于看清其上的文字
|
||||||
|
newNode.color = new cc.Color(160, 160, 160);
|
||||||
|
|
||||||
|
// 加载引擎默认图
|
||||||
|
if (args.defaultSpriteUuid) {
|
||||||
|
cc.assetManager.loadAny(args.defaultSpriteUuid, (err, asset) => {
|
||||||
|
if (!err && (asset instanceof cc.SpriteFrame || asset instanceof cc.Texture2D)) {
|
||||||
|
sprite.spriteFrame = asset instanceof cc.SpriteFrame ? asset : new cc.SpriteFrame(asset);
|
||||||
|
Editor.Ipc.sendToMain("scene:dirty");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (type === "label") {
|
} else if (type === "label") {
|
||||||
newNode = new cc.Node(name || "New Label");
|
newNode = new cc.Node(name || "新建文本节点");
|
||||||
let l = newNode.addComponent(cc.Label);
|
let l = newNode.addComponent(cc.Label);
|
||||||
l.string = "New Label";
|
l.string = "新文本";
|
||||||
|
newNode.width = 120;
|
||||||
|
newNode.height = 40;
|
||||||
} else {
|
} else {
|
||||||
newNode = new cc.Node(name || "New Node");
|
newNode = new cc.Node(name || "New Node");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置层级
|
// 设置层级
|
||||||
let parent = parentId ? cc.engine.getInstanceById(parentId) : scene;
|
let parent = parentId ? findNode(parentId) : scene;
|
||||||
if (parent) {
|
if (parent) {
|
||||||
newNode.parent = parent;
|
newNode.parent = parent;
|
||||||
|
|
||||||
@@ -157,12 +237,19 @@ module.exports = {
|
|||||||
}, 10);
|
}, 10);
|
||||||
|
|
||||||
if (event.reply) event.reply(null, newNode.uuid);
|
if (event.reply) event.reply(null, newNode.uuid);
|
||||||
|
} else {
|
||||||
|
if (event.reply) event.reply(new Error(`无法创建节点:找不到父节点 ${parentId}`));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理节点上的组件 (添加、移除、更新属性)
|
||||||
|
* @param {Object} event IPC 事件对象
|
||||||
|
* @param {Object} args 参数 (nodeId, action, componentType, componentId, properties)
|
||||||
|
*/
|
||||||
"manage-components": function (event, args) {
|
"manage-components": function (event, args) {
|
||||||
const { nodeId, action, componentType, componentId, properties } = args;
|
const { nodeId, action, componentType, componentId, properties } = args;
|
||||||
let node = cc.engine.getInstanceById(nodeId);
|
let node = findNode(nodeId);
|
||||||
|
|
||||||
// 辅助函数:应用属性并智能解析
|
// 辅助函数:应用属性并智能解析
|
||||||
const applyProperties = (component, props) => {
|
const applyProperties = (component, props) => {
|
||||||
@@ -182,16 +269,8 @@ module.exports = {
|
|||||||
|
|
||||||
// 解析 Target Node
|
// 解析 Target Node
|
||||||
if (item.target) {
|
if (item.target) {
|
||||||
let targetNode = null;
|
let targetNode = findNode(item.target);
|
||||||
if (typeof item.target === 'string') {
|
if (!targetNode && item.target instanceof cc.Node) {
|
||||||
targetNode = cc.engine.getInstanceById(item.target);
|
|
||||||
if (!targetNode && Editor.Utils && Editor.Utils.UuidUtils) {
|
|
||||||
try {
|
|
||||||
const decompressed = Editor.Utils.UuidUtils.decompressUuid(item.target);
|
|
||||||
targetNode = cc.engine.getInstanceById(decompressed);
|
|
||||||
} catch (e) { }
|
|
||||||
}
|
|
||||||
} else if (item.target instanceof cc.Node) {
|
|
||||||
targetNode = item.target;
|
targetNode = item.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,17 +304,7 @@ module.exports = {
|
|||||||
// 检查传入值是否是字符串 (可能是 UUID) 或 Node 对象
|
// 检查传入值是否是字符串 (可能是 UUID) 或 Node 对象
|
||||||
let targetNode = null;
|
let targetNode = null;
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
targetNode = cc.engine.getInstanceById(value);
|
targetNode = findNode(value);
|
||||||
|
|
||||||
// 针对压缩 UUID 的回退处理
|
|
||||||
if (!targetNode && Editor.Utils && Editor.Utils.UuidUtils) {
|
|
||||||
try {
|
|
||||||
const decompressed = Editor.Utils.UuidUtils.decompressUuid(value);
|
|
||||||
if (decompressed !== value) {
|
|
||||||
targetNode = cc.engine.getInstanceById(decompressed);
|
|
||||||
}
|
|
||||||
} catch (e) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetNode) {
|
if (targetNode) {
|
||||||
Editor.log(`[scene-script] Resolved node: ${value} -> ${targetNode.name}`);
|
Editor.log(`[scene-script] Resolved node: ${value} -> ${targetNode.name}`);
|
||||||
@@ -565,6 +634,11 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据特定条件在场景中搜索节点
|
||||||
|
* @param {Object} event IPC 事件对象
|
||||||
|
* @param {Object} args 参数 (conditions, recursive)
|
||||||
|
*/
|
||||||
"find-gameobjects": function (event, args) {
|
"find-gameobjects": function (event, args) {
|
||||||
const { conditions, recursive = true } = args;
|
const { conditions, recursive = true } = args;
|
||||||
const result = [];
|
const result = [];
|
||||||
@@ -634,9 +708,14 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定的场景节点
|
||||||
|
* @param {Object} event IPC 事件对象
|
||||||
|
* @param {Object} args 参数 (uuid)
|
||||||
|
*/
|
||||||
"delete-node": function (event, args) {
|
"delete-node": function (event, args) {
|
||||||
const { uuid } = args;
|
const { uuid } = args;
|
||||||
const node = cc.engine.getInstanceById(uuid);
|
const node = findNode(uuid);
|
||||||
if (node) {
|
if (node) {
|
||||||
const parent = node.parent;
|
const parent = node.parent;
|
||||||
node.destroy();
|
node.destroy();
|
||||||
@@ -656,6 +735,11 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理高效的全场景特效 (粒子系统)
|
||||||
|
* @param {Object} event IPC 事件对象
|
||||||
|
* @param {Object} args 参数 (action, nodeId, properties, name, parentId)
|
||||||
|
*/
|
||||||
"manage-vfx": function (event, args) {
|
"manage-vfx": function (event, args) {
|
||||||
const { action, nodeId, properties, name, parentId } = args;
|
const { action, nodeId, properties, name, parentId } = args;
|
||||||
const scene = cc.director.getScene();
|
const scene = cc.director.getScene();
|
||||||
@@ -743,7 +827,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if (action === "update") {
|
} else if (action === "update") {
|
||||||
let node = cc.engine.getInstanceById(nodeId);
|
let node = findNode(nodeId);
|
||||||
if (node) {
|
if (node) {
|
||||||
let particleSystem = node.getComponent(cc.ParticleSystem);
|
let particleSystem = node.getComponent(cc.ParticleSystem);
|
||||||
if (!particleSystem) {
|
if (!particleSystem) {
|
||||||
@@ -761,7 +845,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if (action === "get_info") {
|
} else if (action === "get_info") {
|
||||||
let node = cc.engine.getInstanceById(nodeId);
|
let node = findNode(nodeId);
|
||||||
if (node) {
|
if (node) {
|
||||||
let ps = node.getComponent(cc.ParticleSystem);
|
let ps = node.getComponent(cc.ParticleSystem);
|
||||||
if (ps) {
|
if (ps) {
|
||||||
@@ -791,9 +875,14 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 控制节点的动画组件 (播放、暂停、停止等)
|
||||||
|
* @param {Object} event IPC 事件对象
|
||||||
|
* @param {Object} args 参数 (action, nodeId, clipName)
|
||||||
|
*/
|
||||||
"manage-animation": function (event, args) {
|
"manage-animation": function (event, args) {
|
||||||
const { action, nodeId, clipName } = args;
|
const { action, nodeId, clipName } = args;
|
||||||
const node = cc.engine.getInstanceById(nodeId);
|
const node = findNode(nodeId);
|
||||||
|
|
||||||
if (!node) {
|
if (!node) {
|
||||||
if (event.reply) event.reply(new Error(`Node not found: ${nodeId}`));
|
if (event.reply) event.reply(new Error(`Node not found: ${nodeId}`));
|
||||||
|
|||||||
Reference in New Issue
Block a user