1.编辑器:自定义属性检查器(自定义组件渲染)
编辑器是由一个个面板组成的,除了场景编辑器,其他的面板都可以选择关闭或显示,如果关闭了其他面板:

所有的面板包括插件面板都可以通过菜单面板来管理。
属性检查器 作为 Cocos Creator 里显示当前选中状态的模块,为开发者提供了一些基础的扩展能力。
以一个空节点为例:属性检查器面板可以显示节点的一系列属性,除了基础的Node属性和UITransform属性,也可以自定义来扩展节点的能力。
下面将一一介绍扩展属性检查器的方法:
修饰器扩展
ccclass
ccclass是封装在_decorator中的一个装饰器,_decorator是引擎cc模块中的装饰器集合,比较常用的如ccclass、property等。
ccclass用于装饰类,使用ccclass修饰的类又称为cc类,ccclass封装了额外的信息用于控制 Cocos Creator 对该类对象的序列化、编辑器对该类对象的展示等。所以未声明 ccclass 的组件类,是不能作为组件添加到节点上的。
ccclass 装饰器的参数 name 指定 cc 类的名称,需要注意该参数是唯一的,如果修饰了同类名会冲突并警告,即使不同目录下的同名类也不行。
ccclass的应用语法如下:
import { _decorator } from 'cc';//引用引擎的cc模块
const { ccclass } = _decorator;//引用_decorator中的cclass对象并赋值给同名变量
@ccclass('NewClass')//修饰/传入类名
export class NewClass {
}
装饰器都是通过@装饰器变量(参数)来声明的。
概念:CocosCreator中的序列化和反序列化
简单的理解,CocosCreator中的序列化就是把对象状态保存(比如存到JSON、二进制、ProtocolBuffer等),或者叫存档;反序列化就是读取数据恢复对象状态,或者叫加载。
在CocosCreator中,序列化和反序列化是处理数据存储、传输和资源管理的核心机制,其本质是对象状态与可存储格式之间的双向转换,贯穿了整了使用过程。
- 序列化
将内存中的对象状态(如节点属性、组件数据)转换为可存储或传输的格式(如 JSON、二进制、Protocol Buffers 等),以便持久化到文件、数据库或网络传输。
比如:
游戏存档(角色位置、装备状态)
预制体资源
动画关键帧数据等等 - 反序列化
将存储的格式(如 JSON 字符串、二进制数据)恢复为内存中的对象,重现其状态
比如:
加载存档还原游戏进度
解析服务器传来的协议数据
等等
在CocosCreator的属性系统中,序列化通过装饰器来声明,这样在保存场景或预制时会自动序列化装饰器修饰的属性。
如上述cc类会在序列化时记录该对象的 cc 类名,反序列化时根据此名称找到相应的 cc 类。
而对于一些其他属性,如:
- 值类型属性(@property(args)来声明):数字、字符串、Bool值、颜色等会直接序列化为文本或二进制
- 引用类型属性(@property(args)来声明):节点、组件、纹理等会通过UUID(唯一标识符)关联引用,反序列化时通过该标识符确保资源正确加载
- 场景(.fire)和预制体(.prefab):本质是 JSON 格式的序列化数据,描述节点层级结构和组件属性
- 动画剪辑(.anim):序列化时间轴和关键帧数据
- 网络传输:结合 Protocol Buffers(protobuf),通过 protobuf.js 将对象序列化为二进制,传输后反序列化还原
- 用户数据存储:通过 cc.sys.localStorage 接口存储 JSON 序列化数据,反序列化通过JSON.parse来解析数据
组件类装饰器
CocosCreator工作流是以组件式开发为核心的架构,也称作 实体-组件架构。
在CocosCreator中,节点(Node) 是承载组件的实体,通过将具有各种功能的 组件(Component) 挂载到节点上,来让节点具有各式各样的表现和功能。组件是引擎创建的可以附加到节点的基类,继承自CCObject。所有继承自 Component 的类都称为组件类,其对象称为组件,也就是CocosCreator中的组件概念。
在 资源管理器 中创建的脚本,默认是一个 NewComponent 组件,也叫脚本组件。
上面有提到:未声明 ccclass 的组件类无法作为组件添加到节点上,反过来说,声明了ccclass的非组件类,也是无法附加到节点上的。
组件类装饰器,顾名思义,只能用来修饰组件类。
1. executeInEditMode
executeInEditMode修饰的组件类可以在编辑器环境下运行,默认参数是false。
在默认情况下,所有组件都只会在运行时执行,也就是说它们的生命周期回调在编辑器模式下并不会触发。
而如果通过@executeInEditMode(true)来修饰组件类,该组件就可以在编辑器模式下运行。
import { _decorator } from 'cc';//引用引擎的cc模块
const { ccclass, executeInEditMode } = _decorator;//引用_decorator中的cclass对象并赋值给同名变量
@ccclass('NewClass')//修饰/传入类名
@executeInEditMode(true)
export class NewClass extends Component {//组件类
update (dt: number) {
// 会在编辑器下每帧执行
}
}
2. requireComponent
装饰器requireComponent 参数用来指定当前组件的依赖组件,默认值为 null。
举个例子,在场景中创建一个节点,然后创建一个默认的脚本组件附加到该节点上。

假如说想要该节点有Sprite 组件功能,并在默认的组件脚本中操作。有两种方式,一种是手动在该节点上添加Sprite组件。还有一种就是在默认脚本中声明依赖组件。
如:
import { _decorator, Component, Node, Sprite } from 'cc';
const { ccclass, property, requireComponent } = _decorator;
@ccclass('NewComponent')
@requireComponent(Sprite)
export class NewComponent extends Component {
start() {
}
update(deltaTime: number) {
}
}
保存脚本后首先要把原来的脚本组件移除掉然后重新添加

会发现在添加脚本组件时自动添加了一个Sprite组件。
在运行时同样有效,在移除该脚本组件之前是不允许移除依赖组件的,这在一定程度上可以防止出错。
3. executionOrder
一个节点上可以添加多个脚本组件,默认情况下是脚本的生命周期回调执行顺序是自上而下的。
executionOrder可以自定义声明脚本生命周期回调的执行优先级。
对于同一节点上的不同组件,数值小的先执行,数值相同的按组件添加先后顺序执行。
对于不同节点上的同一组件,按节点树排列决定执行的先后顺序。
需要注意的是,该优先级设定只对 onLoad、onEnable、start、update 和 lateUpdate 有效,对 onDisable 和 onDestroy 无效。
4. disallowMultiple
同一节点上只允许添加一个同类型(含子类)的组件,防止逻辑发生冲突,默认值为 false。
5. menu
在节点的属性检查器面板中有一个添加组件的按钮,点击该按钮可以通过一系列的菜单选项来选择添加组件。

@menu(path) 就可以用来将当前组件添加到这个组件菜单中,方便查找添加。
如下:
import { _decorator, Component, Node, Sprite } from 'cc';
const { ccclass, property, requireComponent, menu } = _decorator;
@ccclass('NewComponent')
@menu('1/specialSprite')
@requireComponent(Sprite)
export class NewComponent extends Component {
start() {
}
update(deltaTime: number) {
}
}

6. help

如图,在节点的基础属性和内置的组件右上角都有一个“帮助”图标,点击后会跳转到对应组件的CocosCreator文档。
@help可以指定当前组件的帮助文档的 URL。设置完成后,在 属性检查器 中就会出现一个帮助图标,点击即可打开指定的网页。
这里随便指定一个url比如百度一下。
import { _decorator, Component, Node, Sprite } from 'cc';
const { ccclass, property, requireComponent, menu, help } = _decorator;
@ccclass('NewComponent')
@menu('1/specialSprite')
@requireComponent(Sprite)
@help('https://www.baidu.com')
export class NewComponent extends Component {
start() {
}
update(deltaTime: number) {
}
}

点击NewComponent脚本组件右上角的问号图标,就可以跳转到百度的首页。
以上就是Creator中所有的组件类装饰器。
属性装饰器
属性装饰器 property 可以被应用在 cc 类的属性或访问器上。用于控制 Cocos Creator 编辑器中对该属性的序列化、属性检查器 中对该属性的展示等。
具体的功能特性可以通过 @property() 的参数来指定。
语法参考如下:
@property({type:Node})
temp_node: Node = null;
1. type 参数
type 参数用于限定属性的数据类型
- 基础cc类型:
CCInteger(整数)、CCFloat(浮点数)、CCBoolean(布尔值)、CCString(字符串),基础类型一般仅用于数组属性的内部类型声明。非数组类型可以不用显式声明这些类型。
@property()
num:number = 0;
@property({type:[CCInteger]})
nums:number[] = [];
- 其他 cc 类型
其他的 cc 类型 都需要显式指定,否则编辑器无法正确识别类型,序列化也无法写入正确类型
比如:
import { _decorator, CCInteger, Component, Node, Sprite } from 'cc';
const { ccclass, property, requireComponent, menu, help } = _decorator;
@ccclass('CustomClass')
export class CustomClass {
@property()
num:number = 0;
@property({type:Node})
node:Node = null;
}
@ccclass('NewComponent')
@menu('1/specialSprite')
@requireComponent(Sprite)
@help('https://www.baidu.com')
export class NewComponent extends Component {
@property()
num:number = 0;
@property({type:CustomClass})
customClass:CustomClass = null;
start() {
}
update(deltaTime: number) {
}
}
- 数组类型
当使用基础属性类型或者 cc 类作为数组元素时,可以被通过数组类型声明被编辑器所识别。例如 [CCInteger]、[Node] 将分别以整数数组和节点数组的形式在 属性检查器 中展示
@property()
num:number = 0;
@property({type:[CCInteger]})
nums:number[] = [];
@property({type:[Node]})
nodes:Node[] = [];
@property({type:[CustomClass]})
customClasses:CustomClass[] = [];

需要注意的是:
在编辑器 属性检查器 中展示的属性,属性名开头不应该带 _,否则会识别为 private 属性,private 属性不会在编辑器组件属性面板上显示。
@property({type:[CustomClass]})
_customClasses:CustomClass[] = [];

- 一些常见的不同 cc 类型的属性声明
import { _decorator, CCInteger, Component, Enum, Node, Sprite } from 'cc';
const { ccclass, property, requireComponent, menu, help, integer,type,float } = _decorator;
enum A {
c,
d
}
Enum(A)
@ccclass('B')
export class B {
@property // JavaScript 原始类型,根据默认值自动识别为 Creator 的浮点数类型。
index = 0;
@property(Node) // 声明属性 cc 类型为 Node。当属性参数只有 type 时可这么写,等价于 @property({type: Node}),后续还会介绍除type外的其他参数
targetNode: Node | null = null; // 等价于 targetNode: Node = null!;
// 声明属性 children 的 cc 类型为 Node 数组
@property({
type: [Node]
})
children: Node[] = [];
@property({
type: String,
}) // 警告:不应该使用构造函数 String。等价于 CCString。也可以选择不声明类型
text = '';
@property
children2 = []; // 未声明 cc 类型,从初始化式的求值结果推断元素为未定义的数组
@property
_valueB = 'abc'; // 此处 '_' 开头的属性,只序列化,不会在编辑器属性面板显示
@property({ type: A })
accx : A = A.c;
//以下为之定义type参数的快捷声明cc类型的方式,等价于@property({type:xx})
@integer // 声明属性的 cc 类型为整数
index2 = 0;
@float // 声明属性的 cc 类型为浮点数
index3 = 0;
@type(A)
index4 = A.c;
@type([Node])// 声明属性 children 的 cc 类型为 Node 数组
childrens: Node[] = [];
}
@ccclass('NewComponent')
export class NewComponent extends Component {
@property(B)
b:B = null;
start() {
}
update(deltaTime: number) {
}
}

- 内置类型
引擎内部提供了一些常用的内置类型默认编辑界面
比如:
- Color
@property(Color)
self_color:Color;

- 曲线编辑:用于保存曲线类型、样式以及采样数据
@property(RealCurve)
self_realcurve:RealCurve = new RealCurve();

- 渐变色:记录渐变色的关键值和用于计算渐变色的结果
@property(Gradient)
gradient = new Gradient();

- 其他如:曲线范围、渐变色范围等可以根据自身需要声明
2. visible
一般情况下,属性是否显示在 属性检查器 中取决于属性名是否以 _ 开头。如果是以 _ 开头,则不显示。
如果要强制显示在 属性检查器 中,可以设置 visible 参数为 true:
@property({ visible: true })
private _num = 0;
如果要强制隐藏,可以设置 visible 参数为 false:
@property({ visible: false })
num = 0;
也可以用于属性条件判断
import { _decorator, CCInteger, Component, Enum, Node, Sprite } from 'cc';
const { ccclass, property, requireComponent, menu, help, integer,type,float } = _decorator;
enum A {
c,
d
}
Enum(A)
@ccclass('NewComponent')
export class NewComponent extends Component {
@property({type:A})
self_type:A = A.c;
@property({type:Sprite,visible(){
return this.self_type === A.c
}})
temp_sprite:Sprite = null;
start() {
}
update(deltaTime: number) {
}
}
3. serializable
属性默认情况下都会被序列化,序列化后就会将编辑器中设置好的属性值保存到场景等资源文件中,之后在加载场景时就会自动还原成设置好的属性值。如果不想序列化,可以设置 serializable: false
除非一些特殊情况,大多数情况下都用不到
@property({ serializable: false })
num = 0;
4. override
override参数可以指定是否会被子类覆盖继承。
默认情况下所有属性都会被子类继承,如果子类要覆盖父类同名属性,需要显式设置 override 参数,否则会有重名警告:
typescript
@property({override: true })
id = "";
5. displayName、tooltip
displayName指定属性在 属性检查器 面板中显示为另一个名字
tooltip可以在 属性检查器 面板中添加属性的 Tooltip
例如:
import { _decorator, CCInteger, Component, Enum, Node, Sprite } from 'cc';
const { ccclass, property, requireComponent, menu, help, integer,type,float } = _decorator;
enum A {
c,
d
}
Enum(A)
@ccclass('NewComponent')
export class NewComponent extends Component {
@property({type:A,displayName:'自定义枚举',tooltip:'c是大,d是小'})
self_type:A = A.c;
@property({type:Sprite,visible(){
return this.self_type === A.c
}})
temp_sprite:Sprite = null;
start() {
}
update(deltaTime: number) {
}
}

6. readonly
指定在 属性检查器 面板中只读
@property({type:Sprite,readonly:true,visible(){
return this.self_type === A.c
}})
temp_sprite:Sprite = null;
设置只读后无法在编辑器中添加引用

7. min、max、step
min限定数值在编辑器中输入的最小值
max限定数值在编辑器中输入的最大值
step指定数值在编辑器中调节的步长
@property({min:-10,max:10,step:0.1})
score:number = 0;

8. range
range参数可以一次性设置 min、max、step
@property({min:-10,max:10,step:0.1})
score:number = 0;
@property({range:[-10,10,0.1]})
score1:number = 0;

9. slide
slide是boolean类型,可以指定数值是否在编辑器中以滑动条的形式显示。
@property({min:-10,max:10,step:0.1})
score:number = 0;
@property({range:[-10,10,0.1]})
score1:number = 0;
@property({slide:true,range:[-10,10,0.1]})
score2:number = 0;

10. group
group可以指定属性在 属性检查器 面板中以分组的形式显示。
当脚本中定义的属性过多且杂时,可通过 group 对属性进行分组、排序,方便管理。同时还支持对组内属性进行分类。
group 写法包括以下两种:
@property({ group: { name } })@property({ group: { id, name, displayOrder, style } })
![image]()
- exp1:
@property({group:"分数1",min:-10,max:10,step:0.1})
score:number = 0;
@property({group:"分数1",range:[-10,10,0.1]})
score1:number = 0;
@property({group:"分数2",slide:true,range:[-10,10,0.1]})
score2:number = 0;

可点击切换查看:

- exp2:
import { _decorator, CCInteger, Component, Enum, Node, Sprite } from 'cc';
const { ccclass, property, requireComponent, menu, help, integer,type,float } = _decorator;
enum A {
c,
d
}
Enum(A)
@ccclass('NewComponent')
export class NewComponent extends Component {
@property({type:A,displayName:'自定义枚举',tooltip:'c是大,d是小'})
self_type:A = A.c;
@property({type:Sprite,readonly:true,visible(){
return this.self_type === A.c
}})
temp_sprite:Sprite = null;
@property({group:"分数1",min:-10,max:10,step:0.1})
score:number = 0;
@property({group:"分数1",range:[-10,10,0.1]})
score1:number = 0;
@property({group:"分数2",slide:true,range:[-10,10,0.1]})
score2:number = 0;
@property({group:{name:"分数3",id:'2',displayOrder:1},type:Sprite})
score3:Sprite = null;
@property({group:{name:"分数4",id:'2'},type:Node})
score4:Node = null;
start() {
}
update(deltaTime: number) {
}
}

分数3指定了 displayOrder 为 1,且分数3和分数4一组,所以在属性编辑器中分数3和分数4的分组会排前面。
- exp3
displayOrder也可以对分组内的属性排序
以分数1为例,有两个属性score和score1,上面score在score1的前面。
@property({group:"分数1",min:-10,max:10,step:0.1})
score:number = 0;
@property({group:"分数1",range:[-10,10,0.1],displayOrder:1})
score1:number = 0;

可以看到,score1排在了score的前面。
自定义渲染
如果以上方法不能满足需求,引擎还允许自定义渲染器。
在 属性检查器 里,定义了两个层级的数据:
- 1.选中的物体主类型
- 2.渲染主类型内容时,内容里包含的子数据类型
当在 层级管理器/资源管理器 中选中一个 节点/资源 时,Cocos Creator 会将物体被选中的消息进行广播。当 属性检查器 接收到消息后,会检查被选中的物体的类型,例如选中的是节点,那么类型便是 node;如果选择的是图片,那么类型则是图片格式。
针对两种类型,引擎允许注册两种渲染器:
- 主类型渲染器
- 主类型渲染器接收数据开始渲染的时候,允许附带子类型渲染器
比如选中的是 node,node 上携带了多个 component,所以主类型就是 node,而子类型则是 component。
在 属性检查器 收到选中物体的广播消息后,首先确定类型,而后 属性检查器 会将收到的数据(物体的 uuid),传递给 node 渲染器,将渲染权限完全移交。
在 node 渲染器里,会根据自身的实现,渲染到每个 组件 的时候,将该区域的渲染权限交给 子类型渲染器。
自定义 Component 渲染
如果内置的组件渲染器不能满足需求,就可以考虑自定义一个组件渲染器。
Cocos Creator 编辑器沿用了 Electron 的主进程和渲染进程的结构设计。进程间通信实际上就是在一个进程中发消息,然后在另外一个进程中监听消息的过程,在Creator编辑器内需要与其他功能进行交互的时候,需要通过 "消息机制" 进行交互。Creator封装了扩展进程间消息收发的方法,如果需要和其他功能交互,则需要对应功能开放对应的操作消息,在扩展内通过 消息系统 触发、查询和处理编辑器内的功能或者数据。
在自定义组件之前先明确一下需求,比如:在组件布局中显示一个按钮
-
首先创建一个自定义脚本组件
创建一个脚本组件CustomComponent.ts
然后创建一个空节点(用于测试),把脚本组件挂载到节点上。
![image]()
-
创建扩展,注册 contributions.inspector 信息
我们需要通过扩展来通信。
创建一个空白扩展,在contributions中注册inspector信息
![image]()
-
编写custom-component.ts脚本
在扩展目录下source下创建一个custom-component.ts文件,然后拷贝以下内容:
'use strict';
type Selector<$> = { $: Record<keyof $, any | null> }
export const template = `
<ui-prop type="dump" class="test"></ui-prop>
`;
export const $ = {
test: '.test',
};
export function update(this: Selector<typeof $>, dump: any) {
// 使用 ui-porp 自动渲染,设置 prop 的 type 为 dump
// render 传入一个 dump 数据,能够自动渲染出对应的界面
// 自动渲染的界面修改后,能够自动提交数据
this.$.test.render(dump.value.label);
}
export function ready(this: Selector<typeof $>) {}
其中,每一个 ui-prop 对应一条属性,若要显示多条属性需要定义多个 ui-prop
4. 编译、刷新扩展
上述创建扩展后忘记安装依赖了,需要打开扩展目录终端安装依赖:
npm install
然后编译
npm run build
刷新扩展后理论上CustomLabelComponent 组件的渲染被接管了。
以上自动渲染示例中使用了类型为 dump 的特殊的 ui-prop 进行渲染数据提交,它使我们可以快捷的接管组件的渲染,但若面临一些极端情况却很难处理一些细节问题,此时可以切换到手动渲染模式。
5. 尝试添加一个按钮,并添加点击事件
template 中的 html 布局是一个完全可以自由掌控的内容,理论上支持任何html样式,可根据需求制定出十分复杂的显示方式。
修改一下代码:
'use strict';
type Selector<$> = { $: Record<keyof $, any | null> }
export const template = `
<ui-button type="success" class="uiButton">success</ui-button>
`;
export const $ = {
uiButton:".uiButton",
};
exports.style = /* css */`
.uiButton{
width: 96%;
margin-left: 2%;
margin-top: 12px;
height:25px;
}
`;
type PanelThis = Selector<typeof $> & { dump: any };
export function update(this: PanelThis, dump: any) {
// 缓存 dump 数据,请挂在 this 上,否则多开的时候可能出现问题
this.dump = dump;
}
export function ready(this: PanelThis) {
// 监听点击事件并处理
this.$.uiButton.addEventListener('confirm', () => {
console.log(this)
Editor.Message.send("scene", "execute-component-method", { uuid: this.dump.value.uuid.value, name: "_uiButtonEvent", args: [] });
});
}
编译、刷新扩展

- 在自定义组件中注册按钮监听接口,注意事件名不要搞错了
import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('CustomComponent')
export class CustomComponent extends Component {
_uiButtonEvent():void{
console.log("点击success!!!>>>");
}
}
尝试点击自定义组件上的按钮

但是出现了一个问题,在自定义组件中声明其他的装饰器属性时不生效了。


test_node没有在属性检查器面板中显示。
- 装饰器兼容
上述问题出现的原因是:组件内置的渲染器和注册的自定义渲染器无法并存。当注册了自定义渲染器后,内置的渲染器将被覆盖。
参考:https://forum.cocos.org/t/topic/156927
在engine/editor/inspector/components目录下找到引擎内置的组件渲染器,会发现一个base.js的基础组件渲染器
// This is the basic template for component editing
const { updatePropByDump, disconnectGroup } = require('../utils/prop');
exports.template = `
<div class="component-container">
</div>
`;
exports.$ = {
componentContainer: '.component-container',
};
exports.update = function(dump) {
updatePropByDump(this, dump);
};
exports.close = function() {
disconnectGroup(this);
};
基础的组件渲染器有一个容器,并且会在update中去更新属性的显示
参考内置的基础组件渲染器来优化自定义的渲染器
- 将engine/editor/inspector/utils下的prop.js脚本拷贝到自己插件的dist目录下
- 修改自定义组件渲染器
'use strict';
const {updatePropByDump, disconnectGroup } = require('./prop');
type Selector<$> = { $: Record<keyof $, any | null> }
export const template = `
<div class="component-container">
<ui-button type="success" class="uiButton">success</ui-button>
`;
export const $ = {
componentContainer:".component-container",
uiButton:".uiButton",
};
exports.style = /* css */`
.uiButton{
width: 96%;
margin-left: 2%;
margin-top: 12px;
height:25px;
}
`;
type PanelThis = Selector<typeof $> & { dump: any };
export function update(this: PanelThis, dump: any) {
updatePropByDump(this, dump);
// 缓存 dump 数据,请挂在 this 上,否则多开的时候可能出现问题
this.dump = dump;
}
export function ready(this: PanelThis) {
disconnectGroup(this);
// 监听点击事件并处理
this.$.uiButton.addEventListener('confirm', () => {
//console.log(this)
Editor.Message.send("scene", "execute-component-method", { uuid: this.dump.value.uuid.value, name: "_uiButtonEvent", args: [] });
});
}
编译、刷新

自定义 Asset 渲染
当在资源管理窗口(Assets)中选中文件时,属性检查器窗口会显示当前选中文件的重要属性,如果默认显示的信息不满足要求,我们也可以自定义渲染内容。
在 package.json 中添加 contributions.section.asset 字段,并定义对应资源类型的自定义渲染脚本,如下所示:
{
"contributions": {
"inspector": {
"section": {
"asset": {
"effect": "./dist/contributions/inspector/asset-effect.js"
}
}
}
}
}
effect 表示我们要对 Cocos Shader(*.effect) 文件类型的资源属性面板自定义渲染。常见的资源文件类型如下:
scene - 场景文件
typescript - TypeScript 脚本文件
prefab - 预制体文件
fbx - FBX 文件
material - 材质文件
directory - 文件夹
image - 图片文件
可通过查看文件对应的 *.meta 中的 importer 字段获取该文件的类型定义。
接下来,在扩展目录下新建一个 src/contributions/inspector/asset-effect.ts 脚本文件,并编写如下代码:
'use strict';
interface Asset {
displayName: string;
file: string;
imported: boolean;
importer: string;
invalid: boolean;
isDirectory: boolean;
library: {
[extname: string]: string;
};
name: string;
url: string;
uuid: string;
visible: boolean;
subAssets: {
[id: string]: Asset;
};
}
interface Meta {
files: string[];
imported: boolean;
importer: string;
subMetas: {
[id: string]: Meta;
};
userData: {
[key: string]: any;
};
uuid: string;
ver: string;
}
type Selector<$> = { $: Record<keyof $, any | null> } & { dispatch(str: string): void, assetList: Asset[], metaList: Meta[] };
export const $ = {
'test': '.test',
};
export const template = `
<ui-prop>
<ui-label slot="label">Test</ui-label>
<ui-checkbox slot="content" class="test"></ui-checkbox>
</ui-prop>
`;
type PanelThis = Selector<typeof $>;
export function update(this: PanelThis, assetList: Asset[], metaList: Meta[]) {
this.assetList = assetList;
this.metaList = metaList;
this.$.test.value = metaList[0].userData.test || false;
};
export function ready(this: PanelThis) {
this.$.test.addEventListener('confirm', () => {
this.metaList.forEach((meta: any) => {
// 修改对应的 meta 里的数据
meta.userData.test = !!this.$.test.value;
});
// 修改后手动发送事件通知,资源面板是修改资源的 meta 文件,不是修改 dump 数据,所以发送的事件和组件属性修改不一样
this.dispatch('change');
});
};
export function close(his: PanelThis, ) {
// TODO something
};
编译、刷新扩展后,回到 Cocos Creator 编辑器界面,选中某个 Cocos Shader 文件,可以在属性检查器底部发现,多了一个 Test 复选框。
注意:
多个扩展注册的数据是并存的。如果一个 组件/资源 已经有了自定义渲染器,那么再次注册的自定义渲染器都会附加在后面。如果一个 组件/资源 没有内置自定义渲染器,使用的是默认的渲染器,那么当扩展注册自定义渲染器的时候,会完全接管渲染内容。



浙公网安备 33010602011771号