無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、@tool アノテーションをつけたエディタ拡張でも動作する GD スクリプトが、エディタのデバッグ実行や、エクスポートした WebGL 版を「フリーゲーム投稿サイト GodotPlayer」して動作するかどうかを確認した手順と結果を紹介します。

※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※スクリプトは自己責任でご使用ください。
前回の記事
前回は、数値を設定する2ノード(例では SpinBox )の値が変更されたら大小関係を維持するスクリプト例と、それをエディタ拡張のダイアログで使用する例を紹介しました。
https://compota-soft.work/wp1/wp-admin/post.php?post=47615&action=edit
この2ノードの値の大小関係を維持するスクリプトは @tool アノテーションがつけられているので、このダイアログをエディタ実行と WebGL 環境で表示して値の変更時に大小関係が維持されることで、動作を確認します。
調べる対象のスクリプト
今回の動作確認の対象となる、@tool アノテーションをつけたスクリプトについては、以下の記事を参照してください。
https://compota-soft.work/wp1/wp-admin/post.php?post=47615&action=edit
後述するテストシーンで表示するダイアログの2つの SpinBox は、このスクリプトのイベント処理によって値の大小関係を維持する調整が行われます。
テストシーンの作成
テストシーンは、前回作成した最大最小の2つの値を入力するダイアログを表示するボタンを1つ置いた、 Control ルートノードのシーンです。
メニュー「シーン」→「新規シーン」を選択してシーンドックで「インターフェース」を選択して Control ルートノードを作成します。
そのルートノードを StudyPopupScFitFonSizeDialog に F2 キーでリネームして、その子ノードに Button ノードを追加します。
ルートノードを選択してから右上の+のアイコンの「スクリプトをアタッチする」ボタンを押して、 study_popup_sc_fit_font_size_dialog.gd スクリプトを作成して割り当てます。

Button ノードを選択した状態で、インスペクタードックタブの隣などにあるノードドックを選択して、 ボタンが離されたときに関数を呼び出す button_up() シグナルをダブルクリックします。
表示されたダイアログで、先ほど gd スクリプトを割り当てたルートノードを選択した状態で「接続」ボタンを押して、受信側メソッドの関数をそのスクリプトに追加します。

シーンは Ctrl + S キーなどで study_popup_sc_fit_font_size_dialog.tscn として保存します。
テストシーンのスクリプト
先ほどルートノードに作成して割り当てた gd スクリプトを以下のスクリプトで上書きします。
ボタンが押された際に呼び出される受信側メソッドの関数内で、前回作成した最大最小の2つの値を入力するダイアログを表示します。
※詳細は、スクリプト内のコメントを参照してください。
extends Control
## パラメータを入力するダイアログのシーンです。
const sc_fit_font_size_dialog_scene: PackedScene = preload("res://addons/sc_fit_font_size/sc_fit_font_size_dialog.tscn")
## sc_fit_font_size_dialog_scene シーンを実体化したダイアログです。
var sc_fit_font_size_dialog: AcceptDialog = null
# Called when the node enters the scene tree for the first time.
func _ready():
# ダイアログはボタンが押されるまで無効です。
sc_fit_font_size_dialog = null
print("sc_fit_font_size.gd: _enter_tree called")
return
## プラグインの後片付けの処理を定義します。
## プラグインを無効 (プロジェクト設定ダイアログ>プラグイン>有効) にした直後や、プラグインが有効な状態のプロジェクトを閉じた際に呼び出されます。
func _exit_tree():
# Clean-up of the plugin goes here.
_free_dialog() # もしも解放されていなければ、ダイアログを解放します。
print("sc_fit_font_size.gd: _exit_tree called")
## $Button の button_up シグナルの受信側メソッドです。
## 動作確認のため最大最小を設定するダイアログを表示します。
func _on_button_button_up():
_free_dialog() # もしも解放されていなければ、ダイアログを解放します。
# ダイアログのシーンを実体化します。
sc_fit_font_size_dialog = sc_fit_font_size_dialog_scene.instantiate()
# ダイアログに Cancel ボタンを追加します。
sc_fit_font_size_dialog.add_cancel_button("Cancel")
# ダイアログに配置されているコントロール群にフィットするようにサイズを調整するために 0 を設定します。
# これにより、最小限の Window のサイズが自動的に設定されます。インスペクターでも同様の方法を実行できます。
sc_fit_font_size_dialog.size = Vector2(0, 0)
# ダイアログの OK ボタン、 Cancel ボタンと関数を関連付けます。
sc_fit_font_size_dialog.connect("confirmed", Callable(self, "_on_dialog_confirmed"))
sc_fit_font_size_dialog.connect("canceled", Callable(self, "_on_dialog_canceled"))
get_tree().root.add_child(sc_fit_font_size_dialog)
## パラメータを入力するダイアログを表示します。
sc_fit_font_size_dialog.popup_centered()
return
## ダイアログで OK ボタンが押された際に呼び出される関数です。
func _on_dialog_confirmed():
print("_on_dialog_confirmed called.")
print_dialog_parameter() # ダイアログの SpinBoxMin, SpinBoxMax の値を出力します。
_free_dialog() # ダイアログを解放します。
return
## ダイアログで Cancel ボタンが押された際に呼び出される関数です。
func _on_dialog_canceled():
print("_on_dialog_canceled called.")
print_dialog_parameter() # ダイアログの SpinBoxMin, SpinBoxMax の値を出力します。
_free_dialog() # ダイアログを解放します。
return
## ダイアログを解放して [member sc_fit_font_size_dialog] を null に設定します。
## [member sc_fit_font_size_dialog] の使用が完了した際に呼び出します。
func _free_dialog():
# ダイアログがもしも消されていない場合は解放します。
if sc_fit_font_size_dialog != null:
sc_fit_font_size_dialog.queue_free()
sc_fit_font_size_dialog = null
return
## デバッグ用。 [member sc_fit_font_size_dialog] の2個 SpinBox の値を print 関数で出力します。
func print_dialog_parameter() -> void:
# ダイアログがない場合はエラーメッセージを出力して戻ります。
if sc_fit_font_size_dialog == null:
push_error("sc_fit_font_size.gd: sc_fit_font_size_dialog == null")
return
# ダイアログに配置されている SpinBox コントロールを取得します。
var spin_box_min: SpinBox = sc_fit_font_size_dialog.find_child("SpinBoxMin")
var spin_box_max: SpinBox = sc_fit_font_size_dialog.find_child("SpinBoxMax")
# SpinBox が見つからない場合はエラーメッセージを出力して戻ります。
if spin_box_min == null or spin_box_max == null:
push_error("sc_fit_font_size.gd: spin_box_min == null or spin_box_max == null")
return
# SpinBox の値を出力ボトムパネルに表示します。
print("SpinBoxMin.value = " + str(spin_box_min.value) + ", SpinBoxMax.value = " + str(spin_box_max.value))
return
ハイライトしている 4 行目で、ダイアログのシーンを読み込み、 24 行目の受信側メソッドでそのダイアログを実体化して表示します。
テスト
テストは、エディタ上で行うデバッグ実行と、 WebGL 版を「フリーゲーム投稿サイト GodotPlayer」にアップロードして行います。
エディタ上でのデバッグ実行
エディタ上での実行では、先ほど作成したシーンを選択した状態で、 F6 キーを押して、選択しているそのシーンを実行します。
表示されたボタンを押すとダイアログが表示されるので、中央の 2 個の SpinBox を操作して、値を変更します。
常に左側が右側の値以下に、右側が左側の値以上になるようにして、@tool アノテーションのついたスクリプトによって調整されます。

モーダルダイアログの動作確認
本編とは違いますが、モーダルダイアログが表示されていると、その呼び出し元のウィンドウの操作はできないことを確認します。
モーダルダイアログを表示した状態でウィンドウの閉じるボタンを押しても反応しません。
モーダルダイアログを閉じてから押すと反応してウィンドウが閉じます。

以下は上述のエディタ上でのデバッグ実行の結果の動画です。
GodotPlayer にアップロードして WebGL 版の実行
先ほどのシーンをメインシーンに設定して WebGL 版をエクスポートして、「フリーゲーム投稿サイト GodotPlayer」にアップロードして Web 環境で実行を確認します。
先ほど作成したシーンをメインシーンとして最初に表示するため、ファイルシステムドックの study_popup_sc_fit_font_size_dialog.tscn シーンファイルを右クリックして表示されるメニュー「メインシーンとして設定」を選択します。

プリセットで Web を選択して右上のエクスポート先のパスを設定して「プロジェクトのエクスポート」ボタンを押します。
※プリセットが空の場合は、上部の「追加」ボタンを押して表示されるドロップダウンリストから Web を選択してください。

「ファイルを保存」ダイアログで、 WebGL 版の複数ファイルを出力するフォルダと html のファイル名を指定して、デバッグ付きエクスポートのチェックを OFF にしてから、「保存」ボタンを押します。
※複数ファイルが出力されるので、空のフォルダに出力すると良いでしょう。

WebGL 版のエクスポートについては以下の記事を参照してください。
https://compota-soft.work/wp1/wp-admin/post.php?post=44032&action=edit
「フリーゲーム投稿サイト GodotPlayer」にログインして、右上のアカウントメニューから「ゲームを登録」を選択して、ゲームの情報を登録します。
すでに作ってあるゲームを変更する場合は、アカウントメニューから「投稿したゲーム」を選択します。
投稿したゲームの一覧から、対象のゲームの設定画面のリンクをクリックして移動します。
左側の「HTML5 アップロード」を選択してから、右側の HTML5 ゲームファイルの「ファイル選択」ボタンを押して作成したファイル群を全て選択して「アップロード」ボタンを押します。
アップロードが完了したら、右上のゲームのタイトルのリンクからゲームの実行ページに移動します。

WebGL 版を起動してボタンを押すとダイアログが表示され、2つの SpinBox が、 @tool アノテーションをいれたスクリプトの機能により、大小関係を維持しながら動作しました。
これにより、 @tool アノテーションをいれたスクリプトも、エディタ以外の環境で動作することが確認できました。
Chrome の場合 F12 キーを押すと表示されるデベロッパーツールで、 Console タブを見ると赤色のエラーメッセージは表示されず、エラーが起きなかったことも確認できました。

以下は、上述の WebGL 版を「フリーゲーム投稿サイト GodotPlayer」でテストした結果の動画です。
関連記事
エディタ拡張で用いる EditorPlugin クラスは実行時に含まれないため、実行時の処理が記述された gd スクリプトに EditorPlugin が含まれていると、読み込みエラーになり、他の関数も実行できません。
その例として、Tweet 用のリンクを開く機能が、エディタ上のデバッグ実行では動作したのに、WebGL 環境で動作しなかった際の対策例については以下の記事を参照してください。
https://compota-soft.work/wp1/wp-admin/post.php?post=46795&action=edit
まとめ
今回は、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、@tool アノテーションをつけたエディタ拡張でも動作する GD スクリプトが、エディタのデバッグ実行や、エクスポートした WebGL 版を「フリーゲーム投稿サイト GodotPlayer」して動作するかどうかを確認した手順と結果を紹介しました。
参照サイト Thank You!
- Godot Engine – Free and open source 2D and 3D game engine
- エディタでコードを実行する — Godot Engine (4.x)の日本語のドキュメント
- フリーゲーム投稿サイト GodotPlayer
記事一覧 → Compota-Soft-Press
コメント