commit ae871335685149b52b53a729cd5f7d4d083b9bb4 Author: JianMiau Date: Thu Mar 31 08:59:17 2022 +0800 [add] first diff --git a/README.md b/README.md new file mode 100644 index 0000000..6846297 --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# Cocos Creater OutputComponent + +## 插件 安裝方式 + +1. 安裝在 **項目** 底下 +> 把插件資料夾放到項目的packages(跟assets同層) + +2. 安裝在 **全局** 底下 +> 把插件資料夾放到C:\Users\%USERNAME%\.CocosCreator\packages + +## 插件稍微說明(都是搬過來的資料 XD) + +剩下沒寫的可以到參考資料裡面看看😀 + +1. 定義你的包描述文件:**package.json** +> **name** String - 定義了包的名字,包的名字是全局唯一的,他關係到你今後在官網服務器上登錄時的名字。 +> +> **version** String - 版本號,我們推薦使用semver格式管理你的包版本。 +> +> **description** String(可选) - 一句話描述你的包是做什麼的。 +> +> **author** String(可选) - 擴展包的作者 +> +> **main** String (可选) - 入口程序 +> +> **scene-script** String (可选) - 調用引擎API 和項目腳本 +> +> **main-menu** Object (可选) - 主菜單定義 +> +> **有要使用介面的話:** +> +> **panel** Object (可选) - 定義的面板在package裡的描述 +> +> **注意panel的type有兩種:** +> +> dockable:可停靠面板,打開該面板後,可以通過拖拽面板標籤到編輯器裡,實現擴展面板嵌入到編輯器中。下面我們介紹的面板入口程序都是按照可停靠面板的要求聲明的。 +> +> simple:簡單Web面板,不可停靠到編輯器主窗口,相當於一份通用的HTML前端頁面。詳細情況請見定義簡單面板。 +> +> 在simple-package文件夾下面創建一個panel文件夾,然後在panel文件夾下創建一個index.js或者一個html文件都可以 + +2. 入口程序:**main.js** + +3. 定義介面以及按鈕綁定的方法,和主進程的通信:**index.js** + +3. 可以使用包括全部引擎API 和用戶組件腳本里聲明的方法和屬性:**scene-obtain..js** +> 可以在擴展包中獲取到場景裡的Canvas根節點有多少子節點,當然還可以用來對場景節點進行更多的查詢和操作。 + +## 參考資料 + +* 你的第一個擴展包 +> https://docs.cocos.com/creator/manual/zh/extension/your-first-extension.html + +* CocosCreator拓展编辑器 +> https://blog.csdn.net/qq_34772097/category_9577457.html + +* Cocos Creator Editor 編輯器擴展API記錄 +> https://blog.csdn.net/kingbook928/article/details/108659319 +> https://blog.csdn.net/qq_17209641/article/details/106822296 +> https://forum.cocos.org/t/creator-api/92605 \ No newline at end of file diff --git a/main.js b/main.js new file mode 100644 index 0000000..b9b6e2b --- /dev/null +++ b/main.js @@ -0,0 +1,46 @@ +"use strict"; +let fs = require("fs"); +let path = require("path"); + +module.exports = { + load() { + this.init(); + }, + unload() { + // Editor.log("卸載執行"); + }, + /** 初始化 */ + init() { + // this.createDirectory(); + }, + /** 創建Spine節點 */ + createSpine(...args) { + // Editor.log("文件0: " + JSON.stringify(args[0])); + // Editor.log("文件1: " + JSON.stringify(args[1])); + // Editor.log("文件2: " + JSON.stringify(args[2])); + Editor.Scene.callSceneScript("spineset", "get-asset-info", { args: args }, function (err, response) { + // Editor.log("callSceneScript: " + response); + // let info = JSON.parse(response); + // let path = info.path; + // let url = info.url; + }); + }, + messages: { + /** 打開面板 */ + "open-panel"() { + Editor.Panel.open("spineset"); + }, + /** 保存按鈕點擊 */ + "create-click"(event, ...args) { + this.createSpine(...args); + }, + /** 面板加載完成 */ + "panel-load-finish"(evnet, ...args) { + Editor.Scene.callSceneScript("spineset", "get-default-info", { args: args }, function (err, response) { + // Editor.log("callSceneScript: " + response); + Editor.Ipc.sendToPanel("spineset", "setDefault", response); + }); + }, + }, + +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..743d0cf --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "spineset", + "version": "0.0.1", + "description": "Sample-Package", + "author": "Sample", + "main": "main.js", + "scene-script": "scene-obtain.js", + "engineSupport": true, + "main-menu": { + "扩展/Create Spine": { + "message": "spineset:open-panel" + } + }, + "panel": { + "main": "panel/index.js", + "type": "dockable", + "title": "Create Spine", + "width": 400, + "height": 350 + } +} \ No newline at end of file diff --git a/panel/index.js b/panel/index.js new file mode 100644 index 0000000..f08c953 --- /dev/null +++ b/panel/index.js @@ -0,0 +1,101 @@ +let assetPath = ""; +let defaultPolygonPath = "assets/"; +let polygonNameHeader = "polygon_"; +let polygonName = ""; +Editor.Panel.extend({ + style: + `:host { margin: 5px; } + h2 { color: #f90; } + .bottom { height: 30px; }`, + + template: ` +

Auto Create Spine Prefab

+
+
+ 1. 把要輸出的節點拉進來
+ 2. 把要輸入的資料夾拉進來 +
+
+
+ 要輸出的Node + +
+
+
+ 要輸入的資料夾 + ui-asset> +
+
+ Spine大小(選填) + +
+
+
+ 要輸入的範例(選填) + +
+
+
+ 預設動畫名稱(選填) + +
+
+ 生成 +
+ `, + + $: { + /** Node */ + node: "#node", + /** 資料夾 */ + asset: "#asset", + /** Spine大小 */ + scale: "#scale", + /** 範例 */ + example: "#example", + /** 預設動畫名稱 */ + anim: "#anim", + /** 生成按鈕 */ + create: "#create", + }, + + ready() { + // Editor.Ipc.sendToMain("spineset:panel-load-finish"); + this.createBtnClick(); + + }, + /** 保存按鈕點擊事件 */ + createBtnClick() { + this.$create.addEventListener("confirm", () => { + if (!this.$node._value) { + Editor.error("請拖曳 Node 到視窗"); + return; + } else if (!this.$asset._value) { + Editor.error("請拖曳 資料夾 到視窗"); + return; + } + Editor.Ipc.sendToMain("spineset:create-click", this.$node, this.$asset, this.$example, this.$scale, this.$anim); + // Editor.Ipc.sendToMain("spineset:create-click", this.$asset); + }); + }, + messages: { + "setDefault": function (event, ...agrs) { + let Data = JSON.parse(agrs[0]); + let node_uuid = Data["node_uuid"]; + let example_uuid = Data["example_uuid"]; + // Editor.log(`agrs: ${agrs[0]}`); + // Editor.log(`node_uuid: ${node_uuid}`); + // Editor.log(`example_uuid: ${example_uuid}`); + if (node_uuid && node_uuid !== "") { + this.$node.value = node_uuid; + } + if (example_uuid && example_uuid !== "") { + this.$example.value = example_uuid; + } + if (event.reply) { + //if no error, the first argument should be null + event.reply(null, "Fine, thank you!"); + } + } + } +}); \ No newline at end of file diff --git a/scene-obtain.js b/scene-obtain.js new file mode 100644 index 0000000..6298d86 --- /dev/null +++ b/scene-obtain.js @@ -0,0 +1,223 @@ +"use strict"; +let fs = require("fs"); +let path = require("path"); + +module.exports = { + /** + * 獲取場景節點下的配置信息 + * @param event event + * @param data 這邊把panel的Node帶進來 + */ + "get-default-info": function (event, request) { + let self = this; + // Editor.log(`example: ${JSON.stringify(args[2])}`); + let Canvas = cc.find("Canvas"); + var response = null; + var args = request.args; + let node = cc.find("Canvas/Prefab"); + let node_uuid = ""; + if (node) { + node_uuid = node.uuid; + } + let example = cc.find("Canvas/example"); + let example_uuid = ""; + if (example) { + example_uuid = example.uuid; + } + response = JSON.stringify({ node_uuid: node_uuid, example_uuid: example_uuid }) + if (event.reply) { + event.reply(null, response); + } + }, + /** + * 獲取場景節點下的配置信息 + * @param event event + * @param data 這邊把panel的Node帶進來 + */ + "get-asset-info": function (event, request) { + let self = this; + // Editor.log(`example: ${JSON.stringify(args[2])}`); + let Canvas = cc.find("Canvas"); + var response = null; + var args = request.args; + let node = cc.find(args[0]._name); + if (!node) { + node = this.getAllChildByUuid(Canvas, args[0]._nodeID); + } + let asset = args[1]; + let example = cc.find(args[2]._name); + if (!example) { + example = this.getAllChildByUuid(Canvas, args[2]._nodeID); + } + if (!example) { + example = cc.instantiate(new cc.Node); + } + let scale = args[3]._value; + let anim = args[4]._value; + // Editor.log(`scale: ${scale}`); + // Editor.log(`node: ${node.name}`); + // Editor.log(`example: ${example.name}`); + Editor.assetdb.queryInfoByUuid(asset._value, function (err, info) { + // info.path// info.url // info.type + if (err) { + response = err; + } + + let FolderName = []; + // Editor.log("讀取資料夾中"); + fs.readdir(info.path, (err, files) => { + files.forEach(file => { + if (file.indexOf(".meta") === -1) { + FolderName.push(file); + // Editor.log(file); + } + }); + // Editor.log(`資料夾數量: ${FolderName.length}`); + Editor.log(`根據來源生成${FolderName.length}個節點`); + node.removeAllChildren(); + for (let i = 0; i < FolderName.length; i++) { + // for (let i = 0; i < 1; i++) { + // let i = 11; + self.CreateNode(node, example, info.path, FolderName[i], i + 1, scale, anim); + } + }); + + // response = JSON.stringify(info); + if (event.reply) { + event.reply(null, "response"); + } + }); + }, + + /** + * 把節點需要輸出的資料設置到每個json + * @param Parent 需要取得資料的節點 + * @param Node 需要取得資料的節點 + */ + async CreateNode(Parent, Node, path, FolderName, name, scale, anim) { + scale = scale ? scale : 1; + anim = anim ? anim : null; + let file_path = `${path}\\${FolderName}`; + let abs_path = `${path}\\${FolderName}\\${FolderName}.json`; + let url = Editor.remote.assetdb.fspathToUrl(abs_path); + let uuid = Editor.remote.assetdb.urlToUuid(url); + // Editor.log(`FolderName: ${FolderName}`); + // Editor.log(`abs_path: ${abs_path}`); + // Editor.log(`url: ${url}`); + // Editor.log(`uuid: ${uuid}`); + let NewNode = cc.instantiate(Node); + let Spine = NewNode.getChildByName("Spine"); + if (!Spine) { + NewNode.addChild(new cc.Node, 0, "Spine"); + Spine = NewNode.getChildByName("Spine"); + } + + let Skeleton = Spine.getComponent(sp.Skeleton); + if (!Skeleton) { + Skeleton = Spine.addComponent(sp.Skeleton); + } + NewNode.active = false; + Parent.addChild(NewNode, 0, name + ""); + + let _pngcount = function () { + return new Promise((resolve, reject) => { + fs.readdir(file_path, (err, files) => { + if (err) { + Editor.log(`err: ${err}`); + reject(err); + } + let pngcount = 0; + files.forEach(file => { + if (file.indexOf(".png") > -1 && file.indexOf(".meta") === -1) { + pngcount++; + } + }); + resolve(pngcount); + }); + }); + } + let pngcount = await _pngcount(); + + //TODO : 此处为你的远程资源路径 + var image = `${path}\\${FolderName}\\${FolderName}`; + var ske = `${path}\\${FolderName}\\${FolderName}.json`; + var atlas = `${path}\\${FolderName}\\${FolderName}.atlas`; + // Editor.log(`image: ${image}`); + // Editor.log(`image2: ${image2}`); + + // let texture = [await this.Load(image), await this.Load(image2)]; + // let textureName = [`${FolderName}.png`, `${FolderName}2.png`]; + let texture = []; + let textureName = []; + + + for (let i = 0; i < pngcount; i++) { + let num = i + 1; + texture.push(await this.Load(`${image}${(num > 1 ? num : "")}.png`)); + textureName.push(`${FolderName}${(num > 1 ? num : "")}.png`); + // Editor.log(`texture ${i}: ${texture[i]}`); + } + + let atlasJson = (await this.Load(atlas)).text; + // Editor.log(`atlasJson: ${atlasJson}`); + let spineJson = (await this.Load(ske)).json; + // Editor.log(`spineJson: ${spineJson}`); + var asset = new sp.SkeletonData(); + asset._uuid = uuid; + asset.skeletonJson = spineJson; + asset.atlasText = atlasJson; + asset.textures = texture; + asset.textureNames = textureName; + Skeleton.skeletonData = asset; + // Editor.log(scale); + Skeleton.node.scale = +scale; + if (anim) { + Skeleton.animation = anim; + } + Skeleton._updateSkeletonData(); + }, + + Load(abs_path) { + return new Promise((resolve, reject) => { + // cc.loader.load(abs_path, (error, response) => { + cc.assetManager.loadRemote(abs_path, (error, response) => { + if (error) { + Editor.log(`error: ${error}`); + reject(error); + } + // Editor.log(`abs_path: ${abs_path}`); + // Editor.log(`response: ${response}`); + resolve(response); + }); + }); + }, + + /** + * 根據Node去尋找底下每個子節點有沒有符合的UUID + * @param Node 需要搜尋的節點 + * @param UUID 目標的UUID + */ + getAllChildByUuid(Node, UUID) { + for (let i = 0; i < Node.childrenCount; i++) { + // Editor.log("Node: " + Node.name, "UUID: " + Node.uuid); + if (Node.uuid == UUID) { + // Editor.log("找到 Node: " + Node.name, "UUID: " + Node.uuid); + return Node; + } else { + // Editor.log("Node: " + Node.children[i].name, "UUID: " + Node.children[i].uuid); + if (Node.children[i].uuid == UUID) { + return Node.children[i]; + } + } + if (Node.children[i].childrenCount > 0) { + // Editor.log(Node.children[i].name + " childrenCount > 0"); + let getAllChildByUuid = this.getAllChildByUuid(Node.children[i], UUID); + if (getAllChildByUuid) { + return getAllChildByUuid; + } + } + } + // Editor.log("Node: " + Node.children[1].childrenCount); + return null; + }, +}; \ No newline at end of file