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.
Checking the stable version of the documentation...
Плагіни 3D gizmo
Вступ
Плагіни 3D gizmo використовуються редактором і користувацькими плагінами для визначення гізмо, приєднаних до будь-якого типу вузла Node3D.
У цьому підручнику показано два основні підходи до визначення власних гізмо. Перший варіант добре працює для простих гізмо і створює менше безладу в структурі вашого плагіна, а другий дозволить вам зберігати деякі дані гізмо.
Примітка
Цей підручник передбачає, що ви вже знаєте, як створювати загальні плагіни. Якщо ви сумніваєтеся, зверніться до сторінки Створення додатків.
EditorNode3DGizmoPlugin
Незалежно від обраного підходу, нам потрібно буде створити новий EditorNode3DGizmoPlugin. Це дозволить нам встановити ім’я для нового типу гізмо та визначити іншу поведінку, наприклад, чи можна приховати гізмо чи ні.
Це буде базове налаштування:
# my_custom_gizmo_plugin.gd
extends EditorNode3DGizmoPlugin
func _get_gizmo_name():
return "CustomNode"
# MyCustomEditorPlugin.gd
@tool
extends EditorPlugin
const MyCustomGizmoPlugin = preload("res://addons/my-addon/my_custom_gizmo_plugin.gd")
var gizmo_plugin = MyCustomGizmoPlugin.new()
func _enter_tree():
add_node_3d_gizmo_plugin(gizmo_plugin)
func _exit_tree():
remove_node_3d_gizmo_plugin(gizmo_plugin)
Для простих гізм достатньо успадкування EditorNode3DGizmoPlugin. Якщо ви хочете зберігати деякі дані для кожного гізмо, вам слід скористатися другим підходом.
Простий підхід
Перший крок полягає в тому, щоб у нашому спеціальному плагіні gizmo перевизначити метод _has_gizmo(), щоб він повертав true, коли параметр вузла має наш цільовий тип.
# ...
func _has_gizmo(node):
return node is MyCustomNode3D
# ...
Тоді ми можемо перевизначити такі методи, як _redraw() або всі пов’язані з дескрипторами.
# ...
func _init():
create_material("main", Color(1, 0, 0))
create_handle_material("handles")
func _redraw(gizmo):
gizmo.clear()
var node3d = gizmo.get_node_3d()
var lines = PackedVector3Array()
lines.push_back(Vector3(0, 1, 0))
lines.push_back(Vector3(0, node3d.my_custom_value, 0))
var handles = PackedVector3Array()
handles.push_back(Vector3(0, 1, 0))
handles.push_back(Vector3(0, node3d.my_custom_value, 0))
gizmo.add_lines(lines, get_material("main", gizmo), false)
gizmo.add_handles(handles, get_material("handles", gizmo), [])
# ...
Зауважте, що ми створили матеріал у методі _init і отримали його в методі _redraw за допомогою get_material(). Цей метод отримує один із варіантів матеріалу залежно від стану гізмо (вибраного та/або редагованого).
Тож остаточний плагін виглядав би приблизно так:
extends EditorNode3DGizmoPlugin
const MyCustomNode3D = preload("res://addons/my-addon/my_custom_node_3d.gd")
func _init():
create_material("main", Color(1,0,0))
create_handle_material("handles")
func _has_gizmo(node):
return node is MyCustomNode3D
func _redraw(gizmo):
gizmo.clear()
var node3d = gizmo.get_node_3d()
var lines = PackedVector3Array()
lines.push_back(Vector3(0, 1, 0))
lines.push_back(Vector3(0, node3d.my_custom_value, 0))
var handles = PackedVector3Array()
handles.push_back(Vector3(0, 1, 0))
handles.push_back(Vector3(0, node3d.my_custom_value, 0))
gizmo.add_lines(lines, get_material("main", gizmo), false)
gizmo.add_handles(handles, get_material("handles", gizmo), [])
# You should implement the rest of handle-related callbacks
# (_get_handle_name(), _get_handle_value(), _commit_handle(), ...).
Зауважте, що ми щойно додали кілька дескрипторів у метод _redraw, але нам все ще потрібно реалізувати решту пов’язаних з дескрипторами зворотних викликів у EditorNode3DGizmoPlugin, щоб отримати належні робочі дескриптори.
Альтернативний підхід
У деяких випадках ми хочемо надати власну реалізацію EditorNode3DGizmo, можливо, тому, що ми хочемо, щоб певний стан зберігався в кожному gizmo, або тому, що ми переносимо старий плагін gizmo, і ми не хочемо переходити через процес переписування.
У цих випадках все, що нам потрібно зробити, це в нашому новому плагіні gizmo перевизначити _create_gizmo(), щоб він повернув нашу власну реалізацію gizmo для вузлів Node3D, на які ми хочемо націлити.
# my_custom_gizmo_plugin.gd
extends EditorNode3DGizmoPlugin
const MyCustomNode3D = preload("res://addons/my-addon/my_custom_node_3d.gd")
const MyCustomGizmo = preload("res://addons/my-addon/my_custom_gizmo.gd")
func _init():
create_material("main", Color(1, 0, 0))
create_handle_material("handles")
func _create_gizmo(node):
if node is MyCustomNode3D:
return MyCustomGizmo.new()
else:
return null
Таким чином уся логіка гізмо та методи малювання можуть бути реалізовані в новому класі, що розширює EditorNode3DGizmo, наприклад:
# my_custom_gizmo.gd
extends EditorNode3DGizmo
# You can store data in the gizmo itself (more useful when working with handles).
var gizmo_size = 3.0
func _redraw():
clear()
var node3d = get_node_3d()
var lines = PackedVector3Array()
lines.push_back(Vector3(0, 1, 0))
lines.push_back(Vector3(gizmo_size, node3d.my_custom_value, 0))
var handles = PackedVector3Array()
handles.push_back(Vector3(0, 1, 0))
handles.push_back(Vector3(gizmo_size, node3d.my_custom_value, 0))
var material = get_plugin().get_material("main", self)
add_lines(lines, material, false)
var handles_material = get_plugin().get_material("handles", self)
add_handles(handles, handles_material, [])
# You should implement the rest of handle-related callbacks
# (_get_handle_name(), _get_handle_value(), _commit_handle(), ...).
Зауважте, що ми щойно додали кілька дескрипторів у метод _redraw, але нам все одно потрібно реалізувати решту пов’язаних з дескрипторами зворотних викликів у EditorNode3DGizmo, щоб отримати належні робочі дескриптори.