Godot4 プラグインで2Dワークスペースに円を描画するサンプルの実装と確認

無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、プラグインを新規作成して、公式ドキュメントに掲載されているサンプルコードを用いて、 2D ワークスペース上のマウスポインタの位置に円を EditorPlugin を継承したプラグインクラスで描画する処理を実装・確認します。

※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※スクリプトは自己責任でご使用ください。

前回の記事

前回は、独自のプラグインを新規作成して、有効・無効を切り替えた際にイベント関数が呼び出されることを確認しました。

 https://compota-soft.work/wp1/wp-admin/post.php?post=44662&action=edit

スクリプトの上書き

前回作成したプラグイン用のスクリプト sc_path_tool.gd に以下のスクリプトを上書きします。

内容とファイル名が一致しないので、別のファイル、例えば plugin_circle_at_mouse.gd などを作成しても良いでしょう。

プラグインでマウスの位置に円を描画するためのイベント関数については、呼び出される順番で後述します。
※詳細についてはスクリプト内のコメントを参照してください。

@tool
extends EditorPlugin

## ノードが SceneTree に入ったとき (インスタンス化時、シーン変更時、またはスクリプトで add_child を呼び出した後など) に呼び出されます。
func _enter_tree():
	# Initialization of the plugin goes here.
	print("ScPathTool plugin を初期化します")
	return

## ノードが SceneTree から出ようとしているときに呼び出されます(たとえば、解放時、シーンの変更時、またはスクリプトで Remove_child を呼び出した後)。
func _exit_tree():
	# Clean-up of the plugin goes here.
	print("ScPathTool plugin を終了します")
	return

## ユーザーがプロジェクト設定ウィンドウの [プラグイン] タブで EditorPlugin を有効にすると、エンジンによって呼び出されます。
func _enable_plugin():
	print("_enable_plugin called")
	return

## ユーザーがプロジェクト設定ウィンドウの [プラグイン] タブで EditorPlugin を無効にすると、エンジンによって呼び出されます。
func _disable_plugin():
	print("_disable_plugin called")
	return

## 2D エディタのビューポートが更新されるときにエンジンによって呼び出されます。
## 描画に [param overlay] コントロールを使用します。
## [method EditorPlugin.update_overlays] を呼び出すことで、ビューポートを手動で更新できます。
func _forward_canvas_draw_over_viewport(overlay: Control) -> void:
	print("_forward_canvas_force_draw_over_viewport called.", overlay)
	# 以下のコードは、公式のサンプルです。
	# https://docs.godotengine.org/ja/4.x/classes/class_editorplugin.html#class-editorplugin-private-method-forward-canvas-draw-over-viewport
	overlay.draw_circle(overlay.get_local_mouse_position(), 64, Color.WHITE)
	print("_forward_canvas_force_draw_over_viewport called.")
	return

## 現在の編集シーンにルートノードがあり、_handlesが実装され、2DビューポートでInputEventが発生したときに呼び出されます。
func _forward_canvas_gui_input(event: InputEvent) -> bool:
	print("_forward_canvas_gui_input called.", event)
	# 以下のコードは、公式のサンプルです。
	# https://docs.godotengine.org/ja/4.x/classes/class_editorplugin.html#class-editorplugin-private-method-forward-canvas-draw-over-viewport
	if event is InputEventMouseMotion:
		# Redraw viewport when cursor is moved.
		update_overlays()
		return true
	return false

## プラグインが特定のタイプのオブジェクト (リソースまたはノード) を編集する場合は、この関数を実装します。
## true を返すと、エディターが関数 _edit と _make_visible を要求したときに呼び出される関数を取得します。
## _forward_canvas_gui_input メソッドと _forward_3d_gui_input メソッドを宣言している場合、これらも呼び出されます。
func _handles(object: Object) -> bool:
	print("_handles called. object = ", object)
	return true

プラグインの 2D 描画処理でイベント関数の呼び出される順番

エディタ起動時に、プラグインの初期化のための _enter_tree イベント関数、その次に、最初に選択されているノードを引数にして _handles イベント関数が呼び出されます。

_handles で true を返すと、描画・入力処理のイベント関数が呼び出されます。

_handles イベント関数で描画・入力処理のイベント関数を呼び出すかを判定

_handles イベント関数は、_forward_canvas_gui_input などを定義すると、呼び出されます。
_handles イベント関数で true を返した場合は、そのときの引数のノードが選択されている間、後述の描画や入力処理のイベント関数が呼び出されるようになります。

具体的には、選択ノードが変化した際(エディタ起動時に初期に選択されたタイミングも同様)に そのノードを引数にして呼び出され、そのノードで描画・入力処理(今回はしませんが編集処理)を行うか戻り値で指定します。

今回のスクリプトでは、選択ノードに関わらず円を描画するので、無条件で true を返しています。

Implement this function if your plugin edits a specific type of object (Resource or Node). If you return true, then you will get the functions _edit and _make_visible called when the editor requests them. If you have declared the methods _forward_canvas_gui_input and _forward_3d_gui_input these will be called too.

Note: Each plugin should handle only one type of objects at a time. If a plugin handles more types of objects and they are edited at the same time, it will result in errors.

プラグインが特定のタイプのオブジェクト (リソースまたはノード) を編集する場合は、この関数を実装します。 true を返すと、エディターが関数 _edit と _make_visible を要求したときに呼び出される関数を取得します。 _forward_canvas_gui_input メソッドと _forward_3d_gui_input メソッドを宣言している場合、これらも呼び出されます。

注: 各プラグインは、一度に 1 種類のオブジェクトのみを処理する必要があります。プラグインがより多くの種類のオブジェクトを処理し、それらを同時に編集すると、エラーが発生します。
EditorPlugin — Godot Engine (4.x)の日本語のドキュメント method-handles

描画のイベント関数(円の描画)

プラグインで 2D ワークスペースを描画する場合は、 _forward_canvas_force_draw_over_viewport イベント関数を定義し、呼び出してもらったタイミングで描画処理を行います。
※描画結果を画面に反映するには後述する update_overlays 関数を呼び出します。

Called by the engine when the 2D editor’s viewport is updated. Use the overlay Control for drawing. You can update the viewport manually by calling update_overlays.

2D エディタのビューポートが更新されるときにエンジンによって呼び出されます。描画にはオーバーレイ コントロールを使用します。 update_overlays を呼び出すことで、ビューポートを手動で更新できます。
EditorPlugin — Godot Engine (4.x)の日本語のドキュメント #method-forward-canvas-draw-over-viewport と Google 翻訳

入力処理のイベント関数(マウスが動いたら表示を更新)

2D ワークスペースの入力処理を行う _forward_canvas_gui_input イベント関数を定義し、呼び出さいてもらったタイミングで入力処理を行います。

Called when there is a root node in the current edited scene, _handles is implemented and an InputEvent happens in the 2D viewport. Intercepts the InputEvent, if return true EditorPlugin consumes the event, otherwise forwards event to other Editor classes.

現在の編集シーンにルートノードがあり、_handlesが実装され、2DビューポートでInputEventが発生したときに呼び出される。InputEventをインターセプトし、もしreturn trueならEditorPluginがイベントを消費し、そうでなければ他のEditorクラスにイベントを転送します。
EditorPlugin — Godot Engine (4.x)の日本語のドキュメント #method-forward-canvas-gui-input と DeepL 翻訳

今回は、この _forward_canvas_gui_input イベント関数の入力処理で、マウスが移動した場合に、描画を画面に反映する update_overlays 関数を呼び出します。

Updates the overlays of the 2D and 3D editor viewport. Causes methods _forward_canvas_draw_over_viewport_forward_canvas_force_draw_over_viewport_forward_3d_draw_over_viewport and _forward_3d_force_draw_over_viewport to be called.

2D および 3D エディタのビューポートのオーバーレイを更新します。メソッド _forward_canvas_draw_over_viewport、_forward_canvas_force_draw_over_viewport、_forward_3d_draw_over_viewport、および _forward_3d_force_draw_over_viewport が呼び出されます。
EditorPlugin — Godot Engine (4.x)の日本語のドキュメント #update_overlays

描画・入力処理のイベント関数は繰り返し呼び出される

2D ワークスペースに切り替えて、 2D ワークスペース上をマウスオーバーすると、2D ワークスペースの描画処理、2D ワークスペースのイベント処理の関数が順に呼び出されます。

  • _handles
    エディタ起動時や、選択ノード変更時に呼び出されます。
    true を返すと、引数のノードが選択されている間、以下のイベント関数が繰り返し呼び出されます。
ScPathTool plugin を初期化します
_handles called. object = TilemapStage:<Node2D#1785079070652>
_handles called. object = TilemapStage:<Node2D#1785079070652>
_forward_canvas_force_draw_over_viewport called.@CanvasItemEditorViewport@9135:<CanvasItemEditorViewport#658556094878>
_forward_canvas_force_draw_over_viewport called.@CanvasItemEditorViewport@9135:<CanvasItemEditorViewport#658556094878>
_forward_canvas_gui_input called.InputEventMouseMotion: button_mask=0, position=((476, 4)), relative=((-2, 5)), velocity=((-214.8669, 595.7672)), pressure=0.00, tilt=((0, 0)), pen_inverted=(false)
_forward_canvas_force_draw_over_viewport called.@CanvasItemEditorViewport@9135:<CanvasItemEditorViewport#658556094878>
_forward_canvas_gui_input called.InputEventMouseMotion: button_mask=0, position=((473, 13)), relative=((-3, 9)), velocity=((-120.3287, 403.9605)), pressure=0.00, tilt=((0, 0)), pen_inverted=(false)
_forward_canvas_force_draw_over_viewport called.@CanvasItemEditorViewport@9135:<CanvasItemEditorViewport#658556094878>
_forward_canvas_gui_input called.InputEventMouseMotion: button_mask=0, position=((470, 19)), relative=((-3, 6)), velocity=((-120.3287, 403.9605)), pressure=0.00, tilt=((0, 0)), pen_inverted=(false)

テスト

2D ワークスペースに切り替えて、2D ワークスペース上をマウスで移動すると、それを追いかけるように描画されました。

Godot4 EditorPlugin 公式サンプルコードを用いた2Dワークスペースのマウスポインタの位置に円を描画するプラグイン例1SS1

解決していない軽微な問題点

通常、プラグインを利用する際は起こりにくいシチュエーションで、対処法もあるので、既知の軽微な問題点として紹介します。

「プロジェクト設定」ダイアログの「プラグイン」タブでプラグインの「有効」ON → OFF → ON にしたあと、すぐには、_handles が呼ばれず、描画用のイベント関数 _forward_canvas_draw_over_viewport が呼ばれないため、2D ワークスペースへのプラグインによる描画が行われません

しかし、選択しているノード切り替えるだけで、 _handles → _forward_canvas_draw_over_viewport イベント関数がそのタイミングで呼ばれ、 2D ワークスペースへのプラグインによる描画が行われるようになります

選択しているノードを、シーンドックで変更する他に、編集シーンを切り替えることでも間接的に選択ノードが変わるため、プラグインの描画が行われるようになります。

エディタ起動時には _handles が編集中のシーンのルートオブジェクトを引数にして呼び出されるため、通常の使用方法では、プラグインを有効にした直後にプラグインによる描画が行われない問題は発生しませんでした。

次回は、この軽微な問題に対して、スクリプトで選択ノードの再選択を行うことで対処する例を紹介します。

まとめ

今回は、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、プラグインを新規作成して、公式ドキュメントに掲載されているサンプルコードを用いて、 2D ワークスペース上のマウスポインタの位置に円を EditorPlugin を継承したプラグインクラスで描画する処理を実装・確認しました。

参照サイト Thank You!

記事一覧 → Compota-Soft-Press

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました