《旧版插件兼容新版creator3.x指南》

简介

新版creator插件api修改了许多,但该有的api功能都还在
只是换了一种写法,做个api“翻译”即可
参考官方3d插件文档

以下是“翻译”代码编辑器插件为示例来讲解的流程:

  • 1.修改插件包的package.json配置格式
  • 2.修改插件包的main.js
  • 3.修改插件包的index.js文件
  • 4.替换对应的插件api
  • 5.将插件包packages目录重命名为extensions目录

具体流程

1.修改package.json配置格式;

官方参考文档: 第一个扩展包

下面备注标注出需要修改的位置与修改后的写法
旧版 2.xx格式:

{
	"name": "simple-code",
	"scene-script": "panel/scene-info.js", // 需要修改 1号
	"version": "2.1.1",
	"description": "内置代码编辑器",
	"author": "MCV",
	"main": "main.js",   // 需要修改 2号
	"main-menu": {       
		"扩展/代码编辑器/打开": { // 需要修改 3号
			"message": "simple-code:myOpenFunc",  // 需要修改 4号
			"accelerator": "CmdOrCtrl+o"      // 需要修改 5号
		},
    },

	"panel.vsEditor": {    // 需要修改 6号
		"main": "panel/index.js",
		"type": "dockable",
		"title": "代码编辑器",
		"width": 400,
		"height": 300
	}
}

对应的新版 3.xx格式:

{
	"name": "simple-code",
	"version": "3.0.0",
	"description": "内置代码编辑器",
	"author": "MCV",
	"main": "./main.js", // 2号 对应的修改 ,加前缀 ./
	"contributions": {
        "scene": {
            "script": "./panel/scene-info.js" // 1号 对应的修改 ,加前缀 ./
       },

        "menu":[
         {
          "path"    :"扩展/代码编辑器", // 3号 对应的修改 ,修改菜单路径
          "label"    :"打开",  // 3号 对应的修改 ,菜单路径下可点击的选项
          "message"  : "open"  // 4号 对应的修改 ,点击后发送的事件消息
        }],

        "shortcuts": [
         {
          "message"  : "open", // 5号 对应的修改 , 菜单快捷键发送的事件消息
          "win": "f1",
          "mac": "f1"
        }],

        "messages":{
          "open":{"methods":["myOpenFunc"]}, // 4号 对应的修改 ,接受到的消息 : 对应的处理函数名
         },

        "panels": {
             "vsEditor": {
               "main": "./panel/index.js",// 6号 对应的修改 , 插件面板
               "type": "dockable",
               "title": "代码编辑器",
               "width": 400,
               "height": 300
               },
         }
}

2.修改main.js

`
修改前2.x的 main.js文件

module.exports = {
  load () {},
  unload () {},
  messages: { // 需要修改的位置
	'myOpenFunc' () {},
  },

修改后3.x的 main.js文件

module.exports = {
  load () {},
  unload () {},
  methods: { // 对应修改的位置
	'myOpenFunc' () {},
  },

3.修改index.js

`
修改前2.x的 index.js文件

module.exports = {
  style:'',
  template:''
  $: {buttion:"#button"}
  load () {
     console.log(this.$button) // 需要修改位置 1号
  },
  unload () {},
  messages: { // 需要修改的位置 2号
	'scene:saved' () {},
  },

修改后3.x的 index.js文件

module.exports = {
  style:'',
  template:''
  $: {buttion:"#button"}
  load () {
     console.log(this.$.button)//  1号 对应修改位置
  },
  unload () {},
  'sceneSaved' () {},//  2号 对应修改的位置

注:3.x插件消息监听需要在package.json文件填写才能使用
官方参考文档:消息系统


{
	"name": "simple-code",
	...
	"messages":{
	    "open":{"methods":["myOpenFunc"]}, 
         // 2号 对应修改的位置,vsEditor.xxx代表消息对应的处理函数是vsEditor面板下xxxx函数
	    "scene:save":{"methods":["vsEditor.sceneSaved"]}, 
	},

4.替换对应的插件api

在3.x上 Editor模块内的API很多都被取消了如 Editor.assetdb、Editor.url …等
取而代之的API可参考以下代码:

'use strict';
/** 
 * 3d插件api映射,兼容2d插件
 * */ 

let fs = require("fs");
let path = require("path");
let baseDir = '';
const prsPath = (Editor.Project && Editor.Project.path ? Editor.Project.path : Editor.remote.projectPath).replace(/\\/g,'/');

// 2D 映射到 3D编辑器的命令
let MAP_CMD = {
	'scene:enter-prefab-edit-mode'	:'scene:open-scene',
	'scene:open-by-uuid'			:'scene:open-scene',
	'assets:hint' 					: "twinkle", // 3d里高亮资源命令是 ‘twinkle’
	'hint' 							: "hint" 		   // 高亮选中的节点,未找到映射关系
}

// 模拟creator2d插件的API实现
let Editor2D = 
{
	isWin32 : path.sep == '\\',
	appPath : Editor.App.path,
	
	error : console.error,
	log : console.log,
	warn : console.warn,
	info : console.info,
	
	_getUrlLast(url_path,head){
		let p_i = url_path.indexOf(head);
		if(p_i!=-1){
			return url_path.substr(head.length+2);
		}
	},

	url(url_path){
		let absPath = Editor._getUrlLast(url_path,'packages:');
		if(absPath){
			return path.join(baseDir,absPath)
		}

		absPath = Editor._getUrlLast(url_path,'db:');
		if(absPath ) {
			return path.join(prsPath,absPath)
		}
		return url_path;
	},

	require(url){
		url = Editor2D.url(url);
		return require(url);
	},

	Ipc : {

		sendToPanel: (head,cmd,...args)=>Editor2D.Ipc._send(head,cmd,...args),

		sendToAll:(cmd,...args)=>Editor2D.Ipc.sendToMain(cmd,...args),

		sendToMain:(cmd,...args)=>
		{
			cmd = MAP_CMD[cmd] || cmd;
			let temp = cmd.split(':')
			if(temp[1]){
				Editor2D.Ipc._send(temp[0],temp[1] || "",...args);
			}else{
				Editor.Message.send(cmd,...args);
			}
		},

		_send(head,cmd,...args)
		{
			let callback = arguments[arguments.length-1]
			Editor.Message.request(head,cmd,...args).then((v)=>{
				if(typeof callback == 'function'){
					callback(null,v);
					callback = null;
				}
			},()=>{
				if(typeof callback == 'function'){
					callback('run _send error');
					callback = null;
				}
			})
		}
	},

	Scene :{
		callSceneScript:(head,cmd,...args)=>{
			let info = {
				name: 'scene',
				method: cmd,
				args:args,
			}
			let callback = arguments[arguments.length-1]
			Editor2D.Ipc._send('scene','execute-scene-script',info,(callback instanceof Function) ? callback : null);
		},
	},
	
	assetdb:{
		assetBackupPath : path.join(prsPath,'temp','BackupAssets'),

		async urlToUuid(url){
			return await Editor.Message.request("asset-db",'query-uuid',url);
		},

		async uuidToUrl(uuid){
			return await Editor.Message.request("asset-db",'query-url',uuid);
		},

		async urlToFspath(uuidOrUrl){
			return await Editor.Message.request("asset-db",'query-path',uuidOrUrl);
		},

		async uuidToFspath(uuidOrUrl){
			return await Editor.Message.request("asset-db",'query-path',uuidOrUrl);
		},

		async fspathToUuid(fsPath){
			let url = "db://" + fsPath.replace(/\\/g,'/').replace(prsPath,'').substr(6);
			return await Editor.Message.request("asset-db",'query-uuid',url);
		},

		async existsByUuid(urlOrUUID){
			return await Editor.Message.request("asset-db",'query-asset-info',urlOrUUID);
		},
		
		async existsByUrl(urlOrUUID){
			return await Editor.Message.request("asset-db",'query-asset-info',urlOrUUID);
		},

		async assetInfoByUuid(urlOrUUID){
			return await Editor.Message.request("asset-db",'query-asset-info',urlOrUUID); // 注意3d返回字段与2d不太一样!
		},

		async assetInfoByUrl(urlOrUUID){
			return await Editor.Message.request("asset-db",'query-asset-info',urlOrUUID); // 注意3d返回字段与2d不太一样!
		},

		deepQuery(callback){
			if(!callback){
				return
			}
			Editor.Message.request("asset-db",'query-assets',{pattern:"db://**"}).then((list)=>{
				// 注意3d返回字段与2d不太一样!
				callback(null,list)
			},()=>{
				callback("run deepQuery error")
			});
		},

		queryInfoByUrl(...args){Editor2D.assetdb.queryInfoByUuid(...args)},
		queryInfoByUuid(urlOrUUID,callback){
			Editor.Message.request("asset-db",'query-asset-info',urlOrUUID).then((list)=>{
				// 注意3d返回字段与2d不太一样!
				callback(null,list)
			},()=>{
				callback("run queryInfoByUuid error")
			});
		},


		saveExists(url,text,callback){
			let promise = Editor.Message.request("asset-db",'save-asset',url,text).then(()=>{
				if(callback) callback()
			},()=>{
				if(callback) callback('save error')
			});
		},

		create(url,text,callback){
			let promise = Editor.Message.request("asset-db",'create-asset',url,text,{}).then((info)=>{
				if(callback) callback(null,info)
			},()=>{
				if(callback) callback('save error')
			});
		},

		delete(urls){
			for (let i = 0; i < urls.length; i++) {
				const url = urls[i];
				Editor.Message.request("asset-db",'delete-asset',url)
			}
		},
		
		move(source,target){
			Editor.Message.request("asset-db",'move-asset',source,target)
		},
	},

	
	Selection:{
		curGlobalActivate(){
			let type = Editor.Selection.getLastSelectedType();
			let ids = Editor.Selection.getSelected(type);
			return {type,id:ids[0]};
		},

		curSelection(type){
			return Editor.Selection.getSelected(type);
		},
	}
}

完整代码映射compatibleApi.js.zip (2.0 KB)

5.将插件包packages目录重命名为extensions目录

.CocosCreator/packages 目录改为 .CocosCreator/extensions
修改完成后就可以在插件管理那里调试bug了

*查找插件对应API技巧

1.最简单方法通过【菜单/开发者工具/消息列表 】查看对应消息命令:


2.当消息列表没有找到我们想要api时就要通过【菜单/开发者工具/消息调试工具 】搜索
比如我想要节点被点击后的消息事件
打开调试工具后,点击运行
再尝试点击下节点列表,然后可以看到打印一堆消息,再尝试找出你所要的消息即可

16赞

占楼…

官方文档自己都是错的 真的是

:ok_hand::ok_hand::ok_hand::ok_hand:

MARK.

thank you for share

请问editor:build-finished,这种消息监听又改成什么了呢?我试着package.json中写成这样,然后exports.methods里面并没有收到这个消息。
“messages”:{
“editor:build-finished”:{
“public”: true,
“methods”: [“buildFinished”]
}
}

https://docs.cocos.com/creator/3.0/manual/zh/editor/publish/custom-build-plugin.html?h=构建

3.0可以通过开发者调试工具查看消息

第一个创建插件包,image ,好像没有什么用?我是想在我自定义插件里面定义监听构建完成的消息,之前是使用editor:build-finished监听的,目前没有用了,我看了下插件包代码下hooks.ts里面有个onAfterBuild,但好像没有调用到。
第二个我是在开发者-》消息列表里面查看接口的,但是并没找到可参考的相关接口。
现在写个插件实在太难下手了,文档前前后后翻看都不明所以 :sweat:

6666666mark

c3d 编辑器插件API

留个脚印!

有这些工具,3.x的插件开发比2.x方便多了

1赞

刚好要用这个

請問第四點是要將js放到哪個文件中?

使用到 Editor 的文件里都要 require 这文件,位置随便
新版的文件editor2D.rar (2.4 KB)

1赞