【Godot】Node2DのGizmoを描画する

はじめに

Node2DにGizmoを描画したくて色々ハマったので情報をまとめます。

動作環境

Godot Engine 3.2.1

メモ

SpatialGizmoは2Dでは動かない

SpatialGizmo https://docs.godotengine.org/ja/stable/tutorials/plugins/editor/spatial_gizmos.html

最初これかなと思って試したら、動かなくてウーンウーン悩んでました。 Spatialは3DのNodeなのでNode2Dで動かないのは当然でした。ちなみにGodot4からはSpatialはNode3Dに改名するみたいです。

2D版のGizmoは無かった

EditorPlugin https://docs.godotengine.org/en/stable/classes/class_editorplugin.html

EditorPluginにadd_spatial_gizmo_pluginは存在するが、add_node2d_gizmo_pluginは無さそうなので、2D版のGizmoは無いみたいです。

解決: _drawで描画する

他のCamera2Dといった2DノードはどうやってEditor画面に描画しているのか気になったのでGitHubのソースを眺めてみました。

https://github.com/godotengine/godot/blob/master/scene/2d/camera_2d.cpp

どうも_notificationのcase NOTIFICATION_DRAW で描画しているみたいです。 エンジンの真のお気持ちはソースコードに書いてあります。

GDScriptでは先頭にtoolを追加して_drawで描画すればよさそうです。

Node2Dの周りに四角形を描きたいときは以下のコードになります。

tool
extends Node2D

export var left   := -100
export var top    := -100
export var right  := 100
export var bottom := 100

func _process(delta):
    if Engine.editor_hint:
        update()

func _draw():
    if Engine.editor_hint:
        var color := Color(1.0, 0.0, 0.0)
        draw_line(Vector2(left, top), Vector2(right, top), color)
        draw_line(Vector2(right, top), Vector2(right, bottom), color)
        draw_line(Vector2(right, bottom), Vector2(left, bottom), color)
        draw_line(Vector2(left, bottom), Vector2(left, top), color)

EditorでGizmo描画できました。

f:id:ueshita:20200901110733p:plain

注意点

  • _processは実行時にも走るので、Engine.editor_hintでEditor上でのみ実行されるように制御する。
  • _processupdate()を呼び出す方式は、毎フレーム描画処理が行われてしまうので、Gizmo描画に影響あるパラメータをプロパティにしてその中でupdate()したほうがお行儀がよさそう。