检查器插件

检查器面板支持以插件的形式来创建自定义小工具编辑属性。尽管可以用它来修改内置类型的检查器小工具,但它在需要处理自定义数据类型和资源时尤其有用。你不但可以为特定的属性或者整个对象设计自定义控件,还可以为特定数据类型设计单独的控件。 EditorInspectorPlugin 和 EditorProperty 类来为整数类型创建自定义的界面,将默认的行为替换为一个按了以后就会生成 0 到 99 之间随机数的按钮。 左图为默认行为,右图为最终结果。

创建你的插件

从创建新的空插件开始。 参见 制作插件。 my_inspector_plugin。那么此时你新建的 addons/my_inspector_plugin 文件夹中就有两个文件:plugin.cfgplugin.gdplugin.gd 是一个扩展了 EditorPlugin 的脚本,你需要在 _enter_tree_exit_tree 方法中加入新的代码。要创建自己的检查器插件,你必须加载对应的脚本,然后创建并调用 add_inspector_plugin() 来添加实例。禁用插件时,你应该调用 remove_inspector_plugin() 将该实例移除。 注解 new() 而不是 instance()。 GDScript

  1. # plugin.gdtoolextends EditorPluginvar pluginfunc _enter_tree(): plugin = preload("res://addons/my_inspector_plugin/MyInspectorPlugin.gd").new() add_inspector_plugin(plugin)func _exit_tree(): remove_inspector_plugin(plugin)

与检查器交互

MyInspectorPlugin.gd 脚本必须继承自 EditorInspectorPlugin 类。这个类提供了不少虚方法,可以用来控制检查器对属性的处理。 can_handle() 方法才能生效。编辑任何 Object 对象时都会调用这个函数,插件想要处理该对象或其属性的话,就必须返回 true。 注解 Resource 也同样如此。 parse_begin()parse_end() 方法顾名思义,只会在每个对象开始解析和结束解析的时候调用一次。在其中调用 add_custom_control() 就可以在检查器布局的顶部或底部添加控件。 parse_category()parse_property() 方法。在这两个函数中,除了 add_custom_control() 以外,你还可以调用 add_property_editor()add_property_editor_for_multiple_properties(),这两个函数是专门用来添加基于 EditorProperty 的控件的。 GDScript

  1. # MyInspectorPlugin.gdextends EditorInspectorPluginvar RandomIntEditor = preload("res://addons/my_inspector_plugin/RandomIntEditor.gd")func can_handle(object): # We support all objects in this example. return truefunc parse_property(object, type, path, hint, hint_text, usage): # We handle properties of type integer. if type == TYPE_INT: # Create an instance of the custom property editor and register # it to a specific property path. add_property_editor(path, RandomIntEditor.new()) # Inform the editor to remove the default property editor for # this property type. return true else: return false

添加编辑属性的界面

EditorProperty 是一种特殊的 Control,可以与检查器面板所编辑的对象进行交互。它本身不显示任何内容,但可以放入其他控件节点,甚至是复杂的场景。 EditorProperty 的脚本有三个必不可少的部分:

  1. _init() 方法,设置控件节点的结构。
  2. update_property(),处理外部对数据的更改。
  3. emit_changed 触发信号,告知检查器本控件对属性进行了修改。 add_child() 方法可以把它显示到属性名称的右边,在 add_child() 之后再调用 set_bottom_editor() 就可以把它显示到名称的下边。 GDScript
    1. # RandomIntEditor.gdextends EditorProperty# The main control for editing the property.var property_control = Button.new()# An internal value of the property.var current_value = 0# A guard against internal changes when the property is updated.var updating = falsefunc _init(): # Add the control as a direct child of EditorProperty node. add_child(property_control) # Make sure the control is able to retain the focus. add_focusable(property_control) # Setup the initial state and connect to the signal to track changes. property_control.text = "Value: " + str(current_value) property_control.connect("pressed", self, "_on_button_pressed")func _on_button_pressed(): # Ignore the signal if the property is currently being updated. if (updating): return # Generate a new random integer between 0 and 99. current_value = randi() % 100 property_control.text = "Value: " + str(current_value) emit_changed(get_edited_property(), current_value)func update_property(): # Read the current value from the property. var new_value = get_edited_object()[get_edited_property()] if (new_value == current_value): return # Update the control with the new value. updating = true current_value = new_value property_control.text = "Value: " + str(current_value) updating = false
    SpinBox 控件,点击 Button 后生成随机值。