Plugins de gizmos Spatial

Introducción

Los complementos de gizmos espaciales son utilizados por el editor y los complementos personalizados para definir los gizmos adjuntos a cualquier tipo de nodo espacial.

Este tutorial le mostrará los dos enfoques principales para definir sus propios gizmos personalizados. La primera opción funciona bien para gizmos simples y crea menos desorden en la estructura de su complemento, mientras que la segunda le permitirá almacenar algunos datos por gizmo.

Nota

Este tutorial asume que ya sabe cómo crear complementos genéricos. En caso de duda, consulte la página: ref: doc_making_plugins.

El EditorSpatialGizmoPlugin

Independientemente del enfoque que elijamos, necesitaremos crear un nuevo: ref: EditorSpatialGizmoPlugin <class_EditorSpatialGizmoPlugin>. Esto nos permitirá establecer un nombre para el nuevo tipo de gizmo y definir otros comportamientos, como si el gizmo se puede ocultar o no.

Esta sería una configuración básica:

# MyCustomGizmoPlugin.gd
extends EditorSpatialGizmoPlugin


func get_name():
    return "CustomNode"
# MyCustomEditorPlugin.gd
tool
extends EditorPlugin


const MyCustomGizmoPlugin = preload("res://addons/my-addon/MyCustomGizmoPlugin.gd")

var gizmo_plugin = MyCustomGizmoPlugin.new()


func _enter_tree():
    add_spatial_gizmo_plugin(gizmo_plugin)


func _exit_tree():
    remove_spatial_gizmo_plugin(gizmo_plugin)

Para gizmos simples, simplemente heredar: ref: EditorSpatialGizmoPlugin <class_EditorSpatialGizmoPlugin> es suficiente. Si desea almacenar algunos datos por gizmo o está transfiriendo un gizmo Godot 3.0 a 3.1+, debe optar por el segundo enfoque.

Enfoque simple

El primer paso es, en nuestro complemento de gizmo personalizado, anular el método: ref: has_gizmo () <class_EditorSpatialGizmoPlugin_method_has_gizmo> para que devuelva verdadero cuando el parámetro espacial es de nuestro tipo de destino.

# ...


func has_gizmo(spatial):
    return spatial is MyCustomSpatial


# ...

Entonces podemos anular métodos como: ref: redraw () <class_EditorSpatialGizmoPlugin_method_redraw> o todos los relacionados con el identificador.

# ...


func _init():
    create_material("main", Color(1, 0, 0))
    create_handle_material("handles")


func redraw(gizmo):
    gizmo.clear()

    var spatial = gizmo.get_spatial_node()

    var lines = PoolVector3Array()

    lines.push_back(Vector3(0, 1, 0))
    lines.push_back(Vector3(0, spatial.my_custom_value, 0))

    var handles = PoolVector3Array()

    handles.push_back(Vector3(0, 1, 0))
    handles.push_back(Vector3(0, spatial.my_custom_value, 0))

    gizmo.add_lines(lines, get_material("main", gizmo), false)
    gizmo.add_handles(handles, get_material("handles", gizmo))


# ...

Note que creamos un material en el método _init, y lo recuperamos en el método` redraw` usando: ref: get_material () <class_EditorSpatialGizmoPlugin_method_get_material>. Este método recupera una de las variantes del material dependiendo del estado del gizmo (seleccionado y / o editable).

La escena final del plugin debería verse similar a esta:

extends EditorSpatialGizmoPlugin


const MyCustomSpatial = preload("res://addons/my-addon/MyCustomSpatial.gd")


func _init():
    create_material("main", Color(1,0,0))
    create_handle_material("handles")


func has_gizmo(spatial):
    return spatial is MyCustomSpatial


func redraw(gizmo):
    gizmo.clear()

    var spatial = gizmo.get_spatial_node()

    var lines = PoolVector3Array()

    lines.push_back(Vector3(0, 1, 0))
    lines.push_back(Vector3(0, spatial.my_custom_value, 0))

    var handles = PoolVector3Array()

    handles.push_back(Vector3(0, 1, 0))
    handles.push_back(Vector3(0, spatial.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()...).

Tenga en cuenta que acabamos de agregar algunos identificadores en el método de redibujo, pero aún necesitamos implementar el resto de devoluciones de llamada relacionadas con identificadores en: ref: EditorSpatialGizmoPlugin <class_EditorSpatialGizmoPlugin> para que los identificadores funcionen correctamente.

Enfoque alternativo

En algunos casos, queremos proporcionar nuestra propia implementación de: ref: EditorSpatialGizmo <class_EditorSpatialGizmo>, tal vez porque queremos tener algún estado almacenado en cada gizmo o porque estamos portando un complemento de gizmo antiguo y no queremos ir a través del proceso de reescritura.

En estos casos, todo lo que tenemos que hacer es, en nuestro nuevo complemento de gizmo, anular: ref: create_gizmo () <class_EditorSpatialGizmoPlugin_method_create_gizmo>, por lo que devuelve nuestra implementación de gizmo personalizada para los nodos espaciales que queremos apuntar.

# MyCustomGizmoPlugin.gd
extends EditorSpatialGizmoPlugin


const MyCustomSpatial = preload("res://addons/my-addon/MyCustomSpatial.gd")
const MyCustomGizmo = preload("res://addons/my-addon/MyCustomGizmo.gd")


func _init():
    create_material("main", Color(1, 0, 0))
    create_handle_material("handles")


func create_gizmo(spatial):
    if spatial is MyCustomSpatial:
        return MyCustomGizmo.new()
    else:
        return null

De esta manera, toda la lógica del gizmo y los métodos de dibujo se pueden implementar en una nueva clase que se extiende: ref: EditorSpatialGizmo <class_EditorSpatialGizmo>, así:

# MyCustomGizmo.gd
extends EditorSpatialGizmo


# You can store data in the gizmo itself (more useful when working with handles).
var gizmo_size = 3.0


func redraw():
    clear()

    var spatial = get_spatial_node()

    var lines = PoolVector3Array()

    lines.push_back(Vector3(0, 1, 0))
    lines.push_back(Vector3(gizmo_size, spatial.my_custom_value, 0))

    var handles = PoolVector3Array()

    handles.push_back(Vector3(0, 1, 0))
    handles.push_back(Vector3(gizmo_size, spatial.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()...).

Tenga en cuenta que acabamos de agregar algunos identificadores en el método de redibujo, pero aún necesitamos implementar el resto de devoluciones de llamada relacionadas con identificadores en: ref: EditorSpatialGizmo <class_EditorSpatialGizmo> para que los identificadores funcionen correctamente.