fix: Windows spawn, prefab path, preview API, asset deps, error messages; add execute-context resource, tool descriptions, scene/script/asset tools

Bug fixes (verified against Cocos Creator 3.8.8):
- diagnostics: shell:true for .cmd/.bat on Windows (T125/T126)
- prefabs: duplicatePrefab target resolves under assets/ (T420)
- cocos-project: add preview.open candidate for 3.8.8 (T444)
- assets-advanced: detect directory assets in inspectAssetDependencies (T110)
- scene: improve component-not-found errors with compilation hint (T429)

Documentation improvements:
- tool-registry: add enum and injected vars to execute_javascript, path format examples, asset ref limitation note
- resources: add cocos://mcp/execute-context resource with variables, patterns, pitfalls

New tools (core 37->38, full 101->110):
- scene-management: create_scene, query_scene_state (core), copy_paste_node, rename_node, reparent_node
- scripts: create_script with component/plain templates
- prefabs: create_prefab
- assets-advanced: batch_asset_ops, find_unused_assets
This commit is contained in:
mingyuansi
2026-06-30 21:53:06 +08:00
parent a9b539ca9c
commit b65a4f22c3
21 changed files with 5273 additions and 53 deletions
+82 -6
View File
@@ -761,6 +761,82 @@ exports.methods = {
};
},
async renameNode(options = {}) {
const node = findNode(options);
if (!node) {
throw new Error('Target node was not found.');
}
const oldName = node.name;
const oldPath = getNodePath(node);
const newName = String(options.newName || '').trim();
if (!newName) {
throw new Error('newName is required.');
}
node.name = newName;
return {
renamed: true,
oldName,
newName,
oldPath,
newPath: getNodePath(node),
uuid: node.uuid,
};
},
async reparentNode(options = {}) {
const node = findNode(options);
if (!node) {
throw new Error('Target node was not found.');
}
const oldPath = getNodePath(node);
const oldParent = node.parent;
const keepWorldTransform = options.keepWorldTransform === true;
const oldWorldPos = keepWorldTransform ? node.worldPosition.clone() : null;
const oldWorldRot = keepWorldTransform ? node.worldRotation.clone() : null;
const oldWorldScale = keepWorldTransform ? node.worldScale.clone() : null;
let newParent = null;
if (options.targetUuid) {
newParent = findNodeByUuid(options.targetUuid);
} else if (options.targetPath) {
newParent = findNodeByPath(options.targetPath);
} else if (options.targetName) {
newParent = findNodeByName(options.targetName);
}
if (!newParent) {
throw new Error('Target parent node was not found.');
}
const siblingIndex = Number.isFinite(options.siblingIndex) ? options.siblingIndex : -1;
if (siblingIndex >= 0 && siblingIndex <= newParent.children.length) {
newParent.insertChild(node, siblingIndex);
} else {
node.parent = newParent;
}
if (keepWorldTransform) {
node.worldPosition = oldWorldPos;
node.worldRotation = oldWorldRot;
node.worldScale = oldWorldScale;
}
return {
reparented: true,
uuid: node.uuid,
oldPath,
newPath: getNodePath(node),
oldParent: oldParent ? oldParent.name : null,
newParent: newParent.name,
siblingIndex: node.getSiblingIndex(),
keepWorldTransform,
};
},
async setNodeTransform(options = {}) {
const node = findNode(options);
if (!node) {
@@ -847,7 +923,7 @@ exports.methods = {
const component = findComponent(node, options);
if (!component) {
throw new Error('Target component was not found.');
throw new Error(`Target component was not found${options.componentName ? ': ' + options.componentName : ''}. Ensure the script is compiled and the component is attached to the node.`);
}
const componentName = component.constructor ? component.constructor.name : 'UnknownComponent';
@@ -867,7 +943,7 @@ exports.methods = {
const component = findComponent(node, options);
if (!component) {
throw new Error('Target component was not found.');
throw new Error(`Target component was not found${options.componentName ? ': ' + options.componentName : ''}. Ensure the script is compiled and the component is attached to the node.`);
}
return {
@@ -892,7 +968,7 @@ exports.methods = {
const component = findComponent(node, options);
if (!component) {
throw new Error('Target component was not found.');
throw new Error(`Target component was not found${options.componentName ? ': ' + options.componentName : ''}. Ensure the script is compiled and the component is attached to the node.`);
}
setValueByPath(component, options.propertyPath, options.value);
@@ -913,7 +989,7 @@ exports.methods = {
const component = findComponent(node, options);
if (!component) {
throw new Error('Target component was not found.');
throw new Error(`Target component was not found${options.componentName ? ': ' + options.componentName : ''}. Ensure the script is compiled and the component is attached to the node.`);
}
resetValueByPath(component, options.propertyPath);
@@ -1410,7 +1486,7 @@ exports.methods = {
const component = findComponent(target, { componentName });
if (!component) {
throw new Error(`Target component was not found: ${componentName}`);
throw new Error(`Target component was not found: ${componentName}. Ensure the script is compiled and the component is attached to the target node.`);
}
if (typeof component[handlerName] !== 'function') {
throw new Error(`Target component method was not found: ${componentName}.${handlerName}`);
@@ -1465,7 +1541,7 @@ exports.methods = {
}
const component = findComponent(node, options);
if (!component) {
throw new Error('Target component was not found.');
throw new Error(`Target component was not found${options.componentName ? ': ' + options.componentName : ''}. Ensure the script is compiled and the component is attached to the node.`);
}
const methodName = String(options.methodName || '').trim();
if (!methodName || typeof component[methodName] !== 'function') {