Files
mcp-bridge/scene-script.js
火焰库拉 f901bcc38f ```
feat(mcp-bridge): 添加场景和节点创建功能

- 新增 getNewSceneTemplate 函数用于生成标准场景模板
- 实现 create_scene 工具用于在 assets 目录下创建新场景文件
- 实现 create_prefab 工具用于将节点保存为预制体资源
- 实现 open_scene 工具用于在编辑器中打开指定场景
- 实现 create_node 工具用于在当前场景中创建新节点
- 在 scene-script.js 中添加 create-node 处理逻辑
- 支持创建不同类型的节点(空节点、精灵、标签等)
- 添加 UUID 生成的多种兼容方案
```
2026-01-29 14:26:28 +08:00

143 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";
module.exports = {
"set-property": function (event, args) {
const { id, path, value } = args;
// 1. 获取节点
let node = cc.engine.getInstanceById(id);
if (node) {
// 2. 修改属性
if (path === "name") {
node.name = value;
} else {
node[path] = value;
}
// 3. 【解决报错的关键】告诉编辑器场景变脏了(需要保存)
// 在场景进程中,我们发送 IPC 给主进程
Editor.Ipc.sendToMain("scene:dirty");
// 4. 【额外补丁】通知层级管理器Hierarchy同步更新节点名称
// 否则你修改了名字,层级管理器可能还是显示旧名字
Editor.Ipc.sendToAll("scene:node-changed", {
uuid: id,
});
if (event.reply) {
event.reply(null, `Node ${id} updated to ${value}`);
}
} else {
if (event.reply) {
event.reply(new Error("Scene Script: Node not found " + id));
}
}
},
"get-hierarchy": function (event) {
const scene = cc.director.getScene();
function dumpNodes(node) {
// 【优化】跳过编辑器内部的私有节点,减少数据量
if (node.name.startsWith("Editor Scene") || node.name === "gizmoRoot") {
return null;
}
let nodeData = {
name: node.name,
uuid: node.uuid,
active: node.active,
position: { x: Math.round(node.x), y: Math.round(node.y) },
scale: { x: node.scaleX, y: node.scaleY },
size: { width: node.width, height: node.height },
// 记录组件类型,让 AI 知道这是个什么节点
components: node._components.map((c) => c.__typename),
children: [],
};
for (let i = 0; i < node.childrenCount; i++) {
let childData = dumpNodes(node.children[i]);
if (childData) nodeData.children.push(childData);
}
return nodeData;
}
const hierarchy = dumpNodes(scene);
if (event.reply) event.reply(null, hierarchy);
},
"update-node-transform": function (event, args) {
const { id, x, y, scaleX, scaleY, color } = args;
let node = cc.engine.getInstanceById(id);
if (node) {
if (x !== undefined) node.x = x;
if (y !== undefined) node.y = y;
if (scaleX !== undefined) node.scaleX = scaleX;
if (scaleY !== undefined) node.scaleY = scaleY;
if (color) {
// color 格式如 "#FF0000"
node.color = new cc.Color().fromHEX(color);
}
Editor.Ipc.sendToMain("scene:dirty");
Editor.Ipc.sendToAll("scene:node-changed", { uuid: id });
if (event.reply) event.reply(null, "Transform updated");
} else {
if (event.reply) event.reply(new Error("Node not found"));
}
},
"create-node": function (event, args) {
const { name, parentId, type } = args;
const scene = cc.director.getScene();
let newNode = null;
// 特殊处理:如果是创建 Canvas自动设置好适配
if (type === "canvas" || name === "Canvas") {
newNode = new cc.Node("Canvas");
let canvas = newNode.addComponent(cc.Canvas);
newNode.addComponent(cc.Widget);
// 设置默认设计分辨率
canvas.designResolution = cc.size(960, 640);
canvas.fitHeight = true;
// 自动在 Canvas 下创建一个 Camera
let camNode = new cc.Node("Main Camera");
camNode.addComponent(cc.Camera);
camNode.parent = newNode;
} else if (type === "sprite") {
newNode = new cc.Node(name || "New Sprite");
newNode.addComponent(cc.Sprite);
} else if (type === "label") {
newNode = new cc.Node(name || "New Label");
let l = newNode.addComponent(cc.Label);
l.string = "New Label";
} else {
newNode = new cc.Node(name || "New Node");
}
// 设置层级
let parent = parentId ? cc.engine.getInstanceById(parentId) : scene;
if (newNode) {
newNode.parent = parent;
// 坐标居中处理(如果是 Canvas 子节点)
if (parent.name === "Canvas") {
newNode.setPosition(0, 0);
} else {
newNode.setPosition(cc.v2(cc.winSize.width / 2, cc.winSize.height / 2));
}
// 通知编辑器刷新
Editor.Ipc.sendToMain("scene:dirty");
Editor.Ipc.sendToAll("scene:node-created", {
uuid: newNode.uuid,
parentUuid: parent.uuid,
});
if (event.reply) event.reply(null, newNode.uuid);
}
},
};