空间变换轴插件

简介

编辑器和自定义插件,使用空间变换轴插件,来定义附加到任何类型的空间节点的变换轴。

本教程向您展示自定义变换轴的两种主要定义方法。第一种方法适用于简单变换轴,可以减少插件结构的混乱,而第二种方法将允许您存储每个变换轴的数据。

注解

本教程假设您已经知道如何制作通用插件。 如有疑问,请参阅 :参考:`文档_制作插件` 页面。

编辑器空间变换轴插件

不管我们选择什么方式,我们需要创建一个新的:参考:编辑器空间变换轴插件<类_编辑器空间变换轴插件>。我们可以为新建的变换轴类型设置名称,并定义其他行为,比如是否可以隐藏变换轴。

这是一个基本设置:

# 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)

对于简单变换轴来说,只继承自:参考:`编辑器空间变换轴插件<类_编辑器空间变换轴插件>`就足够了。如果你想为每个变换轴存储一些数据,或者你想将Godot 3.0版本的变换轴,移植到3.1以上版本中,你应该采用第二种方法。

简单方法

第一步,在我们的自定义变换轴插件中,重写:参考:已有变换轴()<类_编辑器空间变换轴插件_方法_已有变换轴> 方法,以便在空间参数为目标类型时返回“真”值。

# ...

func has_gizmo(spatial):
    return spatial is MyCustomSpatial
# ...

我们可以重写以下方法:参考:重绘()<类_编辑器空间变换轴插件_方法_重绘> 或所有与句柄相关的方法。

# ...

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 that we created a material in the _init method, and retrieved it in the redraw method using get_material(). This method retrieves one of the material’s variants depending on the state of the gizmo (selected and/or editable).

So the final plugin would look somewhat like this:

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()...)

注意,我们只是在重绘方法中添加了一些句柄,但是我们仍然需要在:参考:`编辑器空间变换轴插件<类_编辑器空间变换轴插件>`中实现其他与句柄相关的回调,以获得正确的工作句柄。

替代方法

在某些情况下,我们希望提供自己的:参考:`编辑器空间变换轴<类_编辑器空间变换轴>`实现,也许是因为我们想要在每个变换轴中存储一些状态,或者正在移植一个旧的变换轴插件,而不想经历重写过程。

在这些情况下,我们需要做的就是在我们的新变换轴插件中覆盖:参考:创建变换轴()<类_编辑器空间变换轴插件_方法_创建变换轴>,因此它返回我们想要实现的目标空间节点的自定义变换轴。

# 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

This way all the gizmo logic and drawing methods can be implemented in a new class extending EditorSpatialGizmo, like so:

# 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()...)

请注意,我们刚刚在重绘方法中添加了一些句柄,但我们仍然需要在:参考:`编辑器空间变换轴<类_编辑器空间变换轴>`中实现其余的与句柄相关的回调,以获得正确工作的句柄。