無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、エディターに独自機能を追加できるプラグインを実装する EditorPlugin クラスを用いて追加したツールメニューアイテムを実行した際に、その時点で選択しているノード群と子ノード群から、特定クラス派生のノードだけを配列に集めるスクリプト例と実行結果を紹介します。

※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※スクリプトは自己責任でご使用ください。
関数を呼び出すツールメニューを追加
任意の関数を呼び出すツールメニューを追加する手順は以下の記事を参照してください。
特定クラスだけを配列に追加する関数
以下の関数は、指定されたクラスまたはその派生クラスであるノードだけを引数の配列に追加する関数です。
12行目では、さらに子ノードを持っているノードだった場合、そのノードを引数に、再帰的に関数を呼び出して、さらに下のノード群を繰り返し確認します。
※詳しくはコメントを参照してください。
## 指定したクラスのノードを探します。指定された [param node] が下位のノードを持つ場合は、それも再帰的に探します。
## [param name_of_class] はクラス名の文字列を指定します。
## [param found_nodes] は、条件に合ったノードを追加する配列です。
## 指定したノードまたはその下位のノード群の中に1つでも指定したクラス(またはその派生)のノードがあれば true を、他は false を返します。
static func find_nodes_of_specified_class(node: Node, name_of_class: String, found_nodes: Array[Node]) -> bool:
var is_one_or_more_matches: bool = false # 戻り値
if node.is_class(name_of_class):
#print(name_of_class, " Node found. node = ", node)
found_nodes.append(node)
is_one_or_more_matches = true
for lower_node in node.get_children():
if find_nodes_of_specified_class(lower_node, name_of_class, found_nodes) == true:
is_one_or_more_matches = true
return is_one_or_more_matches
追加したツールメニューから呼び出される関数
以下の関数は、ツールメニューを追加して、そのツールメニューが呼ばれた際に、前述の関数を呼び出して、特定のクラス(例では Control クラス)とその派生クラスのノードだけを、選択中のノード群とその子ノード群から、集めて、その結果を print 出力するスクリプトです。
最後に定義してある _on_menu_item_sc_fit_font_size関数以外は、関数を呼び出すツールメニューの追加方法を紹介した以前の記事を参照してください。
@tool
extends EditorPlugin
## 選択されているノード群にテキストを持ったコントロールがある場合に、
## コントロールのサイズからはみ出ない最大のサイズにフィットしたフォントサイズに自動調節するエディタ拡張です。
## メニュー「プロジェクト」→「ツール」に追加されたメニューアイテムを選択することで実行されます。
## メニューアイテムの表示名です。
var tool_menu_item_name: StringName = "Sc Fit Font Size"
## プラグインの初期化処理を定義します。
## プラグイン (プロジェクト設定ダイアログ>プラグイン>有効) を有効にした直後や、プラグインが有効な状態のプロジェクトを開いた際に呼び出されます。
func _enter_tree():
# Initialization of the plugin goes here.
add_tool_menu_item(tool_menu_item_name, Callable(self, "_on_menu_item_sc_fit_font_size"))
print("sc_fit_font_size.gd: _enter_tree called")
## プラグインの後片付けの処理を定義します。
## プラグインを無効 (プロジェクト設定ダイアログ>プラグイン>有効) にした直後や、プラグインが有効な状態のプロジェクトを閉じた際に呼び出されます。
func _exit_tree():
# Clean-up of the plugin goes here.
remove_tool_menu_item(tool_menu_item_name)
print("sc_fit_font_size.gd: _exit_tree called")
## メニュー「プロジェクト」→「ツール」→「Sc Fit Font Size」メニューが選択された際に呼び出される関数です。
## 選択中のノード群またはその下位のノード群の Control 派生クラスの
## 表示テキストがコントロールのサイズに合わさるようにフォントサイズを調整します。
func _on_menu_item_sc_fit_font_size():
# 引数と同等と思われる配列を取得します。詳細は呼び出している関数の説明を参照してください。
var selected_nodes: Array[Node] = ScUtilEditor.get_editor_plugin_handles_argumnt(self)
# 選択されているノード群とその下位ノード群の Control 派生ノードを探します。
var found_nodes: Array[Node] = []
for selected_node in selected_nodes:
ScUtil.find_nodes_of_specified_class(selected_node, "Control", found_nodes)
# 配列の要素を重複しないように変換します。
var found_unique_nodes: Array = ScUtil.to_unique_array(found_nodes)
print("found_nodes = ", found_nodes)
# 探した Control 派生クラスのテキストのフォントサイズを調整します。
var index: int = 0
for node in found_unique_nodes:
print("found_node[", str(index), "] = ", node)
index += 1
# 指定したクラスまたはその派生であることを確認します。
if not node is Control:
push_error("_on_menu_item_sc_fit_font_size: Control 派生を探した結果に Control を派生していない Node がありました。")
return
33 行目で、選択中のノード1つ1つを引数にして、 Control または Control 派生のクラスを得るためにクラス名に Control を指定して先述の自作関数を呼び出しています。
35 行目では、配列に同じ要素が重複しないように配列から重複を取り除いています。
43 行目では配列の要素が条件を満たしているかチェックしています。
配列の要素を重複しないように変換する ScUtil.to_unique_array 関数については以下の記事を参照してください。
テスト結果
テストでは、先述の find_nodes_of_specified_class 自作関数の呼び出しで指定したクラス(例では Control 派生のノード(緑色))とそうではないノード(青色)を混ぜたシーンを作り、ノードを複数選択した状態で、追加したツールメニューを実行して、出力結果に Control 派生のノードだけが出力されることを確認します。
ノードを print した場合、StudyFitFontSize:<Control#1780867989443> のように、ノード名<クラス名#数字の番号>が出力ボトムパネルに表示されます。
配列を print した場合、[] の中に先ほどのノードの print した結果がカンマ( , )区切りで列挙されます。

指定したクラスまたはクラス派生ではないノードを選択した状態では、空の配列が得られました。

found_nodes = []
複数ノードを選択した場合、 指定したクラスまたは派生クラスのノードだけが入った配列が得られました。
※例では Node2D が Control 派生ではないクラスのノードです。

found_nodes = [ColorRect:<ColorRect#1782411493417>, TextEdit:<TextEdit#1782042394647>]
found_node[0] = ColorRect:<ColorRect#1782411493417>
found_node[1] = TextEdit:<TextEdit#1782042394647>
子ノードを持っているノードを選択した場合、選択されていない子ノード群も含めて、指定したクラスまたは派生クラスのノードだけの配列が得られました。

found_nodes = [ColorRect:<ColorRect#1782411493417>, TextEdit:<TextEdit#1782042394647>, Panel:<Panel#1782344384548>, LabelOnPanel:<Label#1782377938983>]
found_node[0] = ColorRect:<ColorRect#1782411493417>
found_node[1] = TextEdit:<TextEdit#1782042394647>
found_node[2] = Panel:<Panel#1782344384548>
found_node[3] = LabelOnPanel:<Label#1782377938983>
ルートノードを選択した場合、ルートノードとそのすべての下位のノード、シーンすべてのノードを対象にして、指定したクラスまたはクラス派生のノードだけの配列が得られました。

found_nodes = [StudyFitFontSize:<Control#1780867989443>, ColorRectBG:<ColorRect#1780901543888>, Button:<Button#1780935098327>, Button2:<Button#1780985429978>, CheckButton:<CheckButton#1781035761629>, ColorPickerButton:<ColorPickerButton#1781086093280>, MenuButton:<MenuButton#1781136424931>, OptionButton:<OptionButton#1781421637620>, LinkButton:<LinkButton#1781773959177>, Label:<Label#1781824290828>, LineEdit:<LineEdit#1781857845262>, RichTextLabel:<RichTextLabel#1781891399696>, TextEdit:<TextEdit#1782042394647>, Panel:<Panel#1782344384548>, LabelOnPanel:<Label#1782377938983>, ColorRect:<ColorRect#1782411493417>]
found_node[0] = StudyFitFontSize:<Control#1780867989443>
found_node[1] = ColorRectBG:<ColorRect#1780901543888>
found_node[2] = Button:<Button#1780935098327>
found_node[3] = Button2:<Button#1780985429978>
found_node[4] = CheckButton:<CheckButton#1781035761629>
found_node[5] = ColorPickerButton:<ColorPickerButton#1781086093280>
found_node[6] = MenuButton:<MenuButton#1781136424931>
found_node[7] = OptionButton:<OptionButton#1781421637620>
found_node[8] = LinkButton:<LinkButton#1781773959177>
found_node[9] = Label:<Label#1781824290828>
found_node[10] = LineEdit:<LineEdit#1781857845262>
found_node[11] = RichTextLabel:<RichTextLabel#1781891399696>
found_node[12] = TextEdit:<TextEdit#1782042394647>
found_node[13] = Panel:<Panel#1782344384548>
found_node[14] = LabelOnPanel:<Label#1782377938983>
found_node[15] = ColorRect:<ColorRect#1782411493417>
以下は、上述した一連のテストの動画です。
まとめ
今回は、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、エディターに独自機能を追加できるプラグインを実装する EditorPlugin クラスを用いて追加したツールメニューアイテムを実行した際に、その時点で選択しているノード群と子ノード群から、特定クラス派生のノードだけを配列に集めるスクリプト例と実行結果を紹介しました。
参照サイト Thank You!
- Godot Engine – Free and open source 2D and 3D game engine
- プラグインの作成 — Godot Engine (4.x)の日本語のドキュメント
- EditorPlugin — Godot Engine (4.3)の日本語のドキュメント
- EditorPlugin — Godot Engine (4.3)の日本語のドキュメント #add_tool_menu_item
- EditorPlugin — Godot Engine (4.3)の日本語のドキュメント #remove_tool_menu_item
- Callable — Godot Engine (4.3)の日本語のドキュメント
- EditorContextMenuPlugin — Godot Engine (4.x)の日本語のドキュメント
記事一覧 → Compota-Soft-Press
コメント