無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、プラグインの初期化でサブメニューを含むツールメニューを追加する実装例を紹介します。
どのサブメニューが選択されたかを表すID の設定と引数での受け取り、不要になった際のツールメニューの除去などについても紹介します。

※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※スクリプトは自己責任でご利用ください。
プラグインの作成
サブメニューを含むツールメニューを追加するためのスクリプトを実行するためのプラグインをプロジェクト内に作成します。
メニュー「プロジェクト」→「プロジェクト設定」を選択します。

プロジェクト設定ダイアログのプラグインタブを開いて「新しいブラグインを作成」ボタンを押します。

プラグイン名、サブフォルダー(res://addons/ 以下のフォルダパス)などのプラグインの情報を入力して、作成ボタンを押します。

ファイルシステムドックを見ると、指定したサブフォルダ(res://addons 以下のフォルダ)に、プラグインの cfg ファイルと gd スクリプトファイルが作成されました。

スクリプト例
作成したプラグインの gd スクリプトファイルを開いて、以下のスクリプトで上書きして保存します。
@tool
extends EditorPlugin
## ProjectSettings の「ユーザ名/アドオン名/セクション名/キー」の読み書きを Dictionary 型を用いて行う関数とそのテストです。
## EditorInterface の機能はエディタ上で利用できます。
## ProjectSettings の機能を含む関数を実行するために、プラグインとしてこのスクリプトを追加して
## ツールメニュー(「プロジェクト」→「ツール」)から、これが追加したメニューを選択してください。
## 追加するメニューアイテムの表示名です。
const tool_menu_item_name: StringName = "Study ProjectSettings By Dictionary"
## メニューアイテムに追加するサブメニューアイテムの項目名と ID の配列です。
const tool_submenu_item_info_array = [
{"name": "Save", "id": 0},
{"name": "Set Initial Value", "id": 1},
{"name": "Load", "id": 2},
{"name": "Erase", "id": 3},
]
## サブメニューのリソースです。
var submenu: PopupMenu = null
## プラグインの初期化処理を定義します。
## プラグイン (プロジェクト設定ダイアログ>プラグイン>有効) を有効にした直後や、プラグインが有効な状態のプロジェクトを開いた際に呼び出されます。
func _enter_tree():
if submenu == null:
# サブメニュー用のポップアップメニューに項目名とその ID を追加します。
submenu = PopupMenu.new()
for info in tool_submenu_item_info_array:
submenu.add_item(info.name, info.id)
# 選択されたシグナル発生時に呼び出す関数を設定します。
submenu.id_pressed.connect(_on_submenu_id_pressed)
# ツールメニュー(「プロジェクト」→「ツール」)にメニューアイテムとそのサブメニューを追加します。
add_tool_submenu_item(tool_menu_item_name, submenu)
return
## プラグインの後片付けの処理を定義します。
## プラグインを無効 (プロジェクト設定ダイアログ>プラグイン>有効) にした直後や、プラグインが有効な状態でプロジェクトを閉じた際に呼び出されます。
func _exit_tree():
# ツールメニュー(「プロジェクト」→「ツール」)に追加したメニューアイテムを削除します。
remove_tool_menu_item(tool_menu_item_name)
# サブメニューのリソースを解放します。
if submenu != null:
submenu.queue_free()
submenu = null
return
## プラグインで追加したツールメニューのサブメニューを選択した際に呼び出される関数です。
## [param id] は、選択されたサブメニューの項目の ID です。
func _on_submenu_id_pressed(id):
print("_on_submenu_id_pressed called. id = ", id)
print(tool_submenu_item_info_array[id].name, " pressed.")
return
スクリプトの処理の流れ
サブメニューは、 PopupMenu として作成しておく必要があります。
_enter_tree イベント関数(23 行目)で、PopupMenu を作成して、そこに項目名と ID を設定した配列(12 行目)の内容を、add_item メンバ関数で追加して、サブメニューを作成します。
サブメニューが選択されたときに呼び出される関数は、 30 行目で id_pressed シグナルに、メンバ関数 _on_submenu_id_pressed (51 行目) を接続しています。
※ PopupMenu の index_pressed シグナルと接続した場合は id は渡されないので注意しましょう。
Adds a new item with text
label.テキスト ラベルが付いた新しいアイテムを追加します。
An
idcan optionally be provided, as well as an accelerator (accel). If noidis provided, one will be created from the index. If noaccelis provided, then the default value of 0 (corresponding to @GlobalScope.KEY_NONE) will be assigned to the item (which means it won’t have any accelerator). See get_item_accelerator for more info on accelerators.オプションで ID とアクセラレータ(accel)を指定できます。 ID が指定されていない場合は、インデックスから ID が作成されます。アクセルが指定されていない場合は、デフォルト値 0 (@GlobalScope.KEY_NONE に対応) が項目に割り当てられます (アクセラレータがないことを意味します)。アクセラレータの詳細については、「get_item_accelerator」を参照してください。
Note: The provided
idis used only in id_pressed and id_focused signals. It’s not related to theindexarguments in e.g. set_item_checked.注: 指定された ID は、id_pressed および id_focused シグナルでのみ使用されます。これは、例のインデックス引数とは関係ありません。 set_item_checked。
PopupMenu — Godot Engine (4.3) documentation in English #add_item と Google 翻訳
サブメニューは 32 行目の add_tool_submenu_item で、ツールメニュー名のあとの引数で渡しています。
Adds a custom PopupMenu submenu under Project > Tools >
name. Use remove_tool_menu_item on plugin clean up to remove the menu.[プロジェクト] > [ツール] > [名前] の下にカスタムの PopupMenu サブメニューを追加します。メニューを削除するには、プラグインのクリーンアップでremove_tool_menu_itemを使用します。
EditorPlugin — Godot Engine (4.3) documentation in English #add_tool_submenu_item と Google 翻訳
プラグインが無効にされた際に、追加したツールメニューを削除するために _exit_tree イベント関数(39 行目)で remove_tool_menu_item 関数を使用しています。
また、不要になったサブメニューのリソースも解放しています。
Removes a menu
namefrom Project > Tools.[プロジェクト] > [ツール] からメニュー名を削除します。
EditorPlugin — Godot Engine (4.3) documentation in English #remove_tool_menu_item と Google 翻訳
追加したサブメニューを選択する
スクリプトを貼り付けたら、そのスクリプトでツールメニューを追加している _enter_tree イベント関数を実行するために、一度プラグインをオフにして再びオンにします。
プロジェクト設定ダイアログのプラグインタブを開いて、追加したプラグインの有効チェックボックスを一度オフにしてからオンにします。
※プロジェクト設定ダイアログは、メニュー「プロジェクト」→「プロジェクト設定」から開けます。

メニュー「プロジェクト」→「ツール」に追加したツールメニュー(例:Study ProjectSettings By Dictionary)を選択すると、追加したサブメニューが表示されました。
サブメニューの各項目を選択すると、それぞれの項目に設定した ID が、指定した関数の引数に渡されていることが print 文の出力で確認できました。

_on_submenu_id_pressed called. id = 0
Save pressed.
_on_submenu_id_pressed called. id = 1
Set Initial Value pressed.
_on_submenu_id_pressed called. id = 2
Load pressed.
_on_submenu_id_pressed called. id = 3
Erase pressed.
_on_submenu_id_pressed called. id = 0
Save pressed.プラグインを無効にしてツールメニューを除去する
プロジェクト設定ダイアログのプラグインタブで、追加したプラグインの有効チェックボックスをオフにします。
プラグインを無効にすると、そのタイミングでプラグインのスクリプトの _exit_tree イベント関数が呼び出されます。
先ほどのスクリプトでは、 _exit_tree イベント関数で、メニューアイテムの除去・リソースの解放を行っているので、これにより追加したツールメニューが消えます。

プラグインをオフにした状態で、メニュー「プロジェクト」→「ツール」を開くと、追加したツールメニュー(例:Study ProjectSettings By Dictionary)が消えました。

まとめ
- サブメニューを含むツールメニューを追加するためのスクリプトを実行するためのプラグインをプロジェクト内に作成しました。
- サブメニューは、 PopupMenu として作成しておく必要があります。
- PopupMenu の項目は add_item メンバ関数などで追加します。
- PopupMenu のid_pressed シグナルに、メンバ関数を接続することで、選択時の処理を実装します。
- サブメニューは add_tool_submenu_item で、ツールメニュー名のあとの引数で渡して設定します。
- ツールメニューは remove_tool_menu_item 関数で除去できます。PopupMenu も不要になったら解放します。
参照サイト Thank You!
- Godot Engine – Free and open source 2D and 3D game engine
- Dictionary — Godot Engine (4.3) documentation in English
- EditorInterface — Godot Engine (4.x)の日本語のドキュメント
- EditorPlugin — Godot Engine (4.3) documentation in English #add_tool_submenu_item
- EditorPlugin — Godot Engine (4.3) documentation in English #remove_tool_menu_item
- PopupMenu — Godot Engine (4.3) documentation in English
記事一覧 → Compota-Soft-Press
コメント