main.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. 'use strict';
  2. // Anim Studio 导入器 —— Cocos Creator 3.8.x 编辑器扩展
  3. // 菜单:扩展 → Anim Studio → 1.导入 cocos-pack 资源 / 2.布置演示节点
  4. const fs = require('fs');
  5. const path = require('path');
  6. function projectAssets() {
  7. return path.join(Editor.Project.path, 'assets');
  8. }
  9. // 递归拷贝(Node 16+ 自带 fs.cpSync;做个兜底)
  10. function copyDir(src, dst) {
  11. if (fs.cpSync) { fs.cpSync(src, dst, { recursive: true }); return; }
  12. fs.mkdirSync(dst, { recursive: true });
  13. for (const name of fs.readdirSync(src)) {
  14. const s = path.join(src, name), d = path.join(dst, name);
  15. if (fs.statSync(s).isDirectory()) copyDir(s, d);
  16. else fs.copyFileSync(s, d);
  17. }
  18. }
  19. exports.methods = {
  20. // ---------- 1. 导入资源 ----------
  21. async importPack() {
  22. let picked;
  23. try {
  24. picked = await Editor.Dialog.select({
  25. title: '选择 Anim Studio 导出的 cocos-pack 文件夹',
  26. path: Editor.Project.path,
  27. type: 'directory',
  28. });
  29. } catch (e) {
  30. return Editor.Dialog.error('Anim Studio', { detail: '打开文件选择框失败:' + e });
  31. }
  32. if (!picked || picked.canceled || !picked.filePaths || !picked.filePaths.length) return;
  33. const pack = picked.filePaths[0];
  34. // 兼容:用户既可能选 cocos-pack 本身,也可能选到里面的 assets
  35. let srcAssets = path.join(pack, 'assets');
  36. if (!fs.existsSync(srcAssets) && fs.existsSync(path.join(pack, 'resources'))) {
  37. srcAssets = pack; // 选到了 assets 目录
  38. }
  39. if (!fs.existsSync(srcAssets)) {
  40. return Editor.Dialog.error('Anim Studio', {
  41. detail: '没找到 assets/(或 resources/)。请选 cocos-pack 文件夹,它里面应有 assets/resources 和 assets/scripts。',
  42. });
  43. }
  44. const dstAssets = projectAssets();
  45. const copied = [];
  46. try {
  47. for (const sub of ['resources', 'scripts']) {
  48. const s = path.join(srcAssets, sub);
  49. if (fs.existsSync(s)) { copyDir(s, path.join(dstAssets, sub)); copied.push(sub); }
  50. }
  51. } catch (e) {
  52. return Editor.Dialog.error('Anim Studio', { detail: '拷贝文件失败:' + e });
  53. }
  54. if (!copied.length) {
  55. return Editor.Dialog.error('Anim Studio', { detail: 'assets 里没有 resources / scripts 子目录。' });
  56. }
  57. // 让编辑器重新导入资源数据库
  58. try { await Editor.Message.request('asset-db', 'refresh-asset', 'db://assets'); } catch (e) {}
  59. Editor.Dialog.info('Anim Studio', {
  60. detail: '已导入:' + copied.join('、') +
  61. '。\n等右下角导入进度条走完后,新建或打开一个场景,再点菜单「2. 在当前场景布置演示节点」。',
  62. buttons: ['好的'],
  63. });
  64. },
  65. // ---------- 2. 布置演示节点 ----------
  66. async buildScene() {
  67. // 先确认有打开的场景
  68. let scene;
  69. try { scene = await Editor.Message.request('scene', 'query-is-ready'); } catch (e) {}
  70. try {
  71. // 找一个 Canvas 作父节点(新建 2D 场景默认就有,名为 Canvas)
  72. let parent = null;
  73. try {
  74. const tree = await Editor.Message.request('scene', 'query-node-tree');
  75. parent = findCanvasUuid(tree);
  76. } catch (e) {}
  77. const opt = { name: 'AnimStudioDemo' };
  78. if (parent) opt.parent = parent;
  79. const nodeUuid = await Editor.Message.request('scene', 'create-node', opt);
  80. const uuid = typeof nodeUuid === 'string' ? nodeUuid : (nodeUuid && nodeUuid.uuid);
  81. await Editor.Message.request('scene', 'create-component', { uuid, component: 'JellyDemo' });
  82. Editor.Dialog.info('Anim Studio', {
  83. detail: '已创建节点「AnimStudioDemo」并挂上 JellyDemo 组件。\n' +
  84. '按 Ctrl/Cmd+S 保存场景,再点上方 ▶ 播放即可。\n' +
  85. (parent ? '' : '(没检测到 Canvas,如果画面空白,请确认场景里有 Canvas,并把该节点拖到 Canvas 下。)'),
  86. buttons: ['完成'],
  87. });
  88. } catch (e) {
  89. Editor.Dialog.error('Anim Studio', {
  90. detail: '自动布置失败(多半是没有打开场景,或脚本还没导入完):' + e +
  91. '\n\n手动兜底:新建/打开一个场景 → 在 Canvas 下右键新建空节点 → 把 assets/scripts/JellyDemo.ts 拖到它的属性检查器上 → 保存并播放。',
  92. });
  93. }
  94. },
  95. };
  96. // 在节点树里找第一个名为 Canvas 的节点 uuid
  97. function findCanvasUuid(node) {
  98. if (!node) return null;
  99. if (Array.isArray(node)) {
  100. for (const n of node) { const r = findCanvasUuid(n); if (r) return r; }
  101. return null;
  102. }
  103. if (node.name === 'Canvas' && node.uuid) return node.uuid;
  104. if (node.children) return findCanvasUuid(node.children);
  105. return null;
  106. }
  107. exports.load = function () {};
  108. exports.unload = function () {};