Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

屬性檢查器外掛

屬性檢查器面板允許你透過外掛建立自訂小工具來編輯屬性。這在處理自訂資料型別與資源時特別有用,但你也可以利用這個功能修改內建型別的屬性檢查器小工具。你可以為特定屬性、整個物件,甚至特定資料型別設計專屬的自訂控制項。

本指南說明如何使用 EditorInspectorPluginEditorProperty 類別,為整數型別建立自訂介面,將預設的編輯行為替換為一個能產生 0 到 99 隨機值的按鈕。

../../../_images/inspector_plugin_example.png

左側為預設行為,右側為最終效果。

設定你的外掛

先建立一個全新的空白外掛。

也參考

請參閱 製作外掛程式 指南,來設定你的新外掛。

假設你的外掛資料夾命名為 my_inspector_plugin,你應該會有一個 addons/my_inspector_plugin 資料夾,裡面包含兩個檔案:plugin.cfgplugin.gd

和以往一樣,plugin.gd 是一個繼承自 EditorPlugin 的腳本,你需要在 _enter_tree_exit_tree 方法中新增程式碼。若要註冊你的屬性檢查器外掛,必須載入其腳本,然後使用 add_inspector_plugin() 來建立並新增實例。若外掛被停用時,應以 remove_inspector_plugin() 移除你新增的實例。

備註

這裡你載入的是腳本而非已封裝場景,因此應使用 new(),而不是 instantiate()

# plugin.gd
@tool
extends EditorPlugin

var plugin


func _enter_tree():
    plugin = preload("res://addons/my_inspector_plugin/my_inspector_plugin.gd").new()
    add_inspector_plugin(plugin)


func _exit_tree():
    remove_inspector_plugin(plugin)

與屬性檢查器互動

要與屬性檢查器面板互動,你的 my_inspector_plugin.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 的控制項。

# my_inspector_plugin.gd
extends EditorInspectorPlugin

var RandomIntEditor = preload("res://addons/my_inspector_plugin/random_int_editor.gd")


func _can_handle(object):
    # We support all objects in this example.
    return true


func _parse_property(object, type, name, hint_type, hint_string, usage_flags, wide):
    # 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(name, 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(),則會將它顯示在名稱下方。

# random_int_editor.gd
extends 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 = false


func _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.
    refresh_control_text()
    property_control.pressed.connect(_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
    refresh_control_text()
    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
    refresh_control_text()
    updating = false

func refresh_control_text():
    property_control.text = "Value: " + str(current_value)

使用上述範例程式碼,你應該可以製作一個自訂小工具,將整數屬性預設的 SpinBox 控制項替換為一個能產生隨機值的 Button