# 画面設計書 39-実行インスタンスダイアログ

## 概要

本ドキュメントは、Godot Engineエディタにおける実行インスタンスダイアログ（RunInstancesDialog）の画面設計を記述する。このダイアログはプロジェクト実行時に複数のゲームインスタンスを同時起動し、それぞれに異なる起動引数やフィーチャータグを設定するために使用される。

### 本画面の処理概要

このダイアログ画面では、マルチプレイヤーゲームのテストなど、複数のインスタンスを同時実行する際の設定を管理する。各インスタンスに個別の起動引数とフィーチャータグを設定可能で、メイン設定を上書きするオプションも提供される。

**業務上の目的・背景**：マルチプレイヤーゲーム開発では、クライアント・サーバーやP2P接続のテストのため、複数のゲームインスタンスを同時に起動する必要がある。このダイアログにより、各インスタンスにhost/client等の異なる引数を渡し、効率的なテストが可能となる。

**画面へのアクセス方法**：エディタツールバーの実行ボタン右にあるドロップダウンメニューから「Run Instances」を選択してアクセスする。

**主要な操作・処理内容**：
1. メイン起動引数の設定（全インスタンス共通）
2. メインフィーチャータグの設定（全インスタンス共通）
3. インスタンス数の指定（1-20）
4. 各インスタンスの個別引数/フィーチャータグ設定
5. メイン設定の上書きオプション

**画面遷移**：
- 遷移元：エディタツールバー > 実行ドロップダウン
- 遷移先：設定は自動保存され、OKボタンでダイアログが閉じる

**権限による表示制御**：enable_multiple_instances_checkboxの状態により、インスタンス数SpinBoxの編集可否が制御される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| F-080 | マルチインスタンス実行 | 主機能 | 複数インスタンスの同時起動 |
| F-081 | 起動引数管理 | 補助機能 | 引数の設定と保存 |
| F-082 | フィーチャータグ管理 | 補助機能 | カスタムフィーチャータグの設定 |

## 画面種別

設定（モーダルダイアログ）

## URL/ルーティング

該当なし（デスクトップアプリケーションのモーダルダイアログ）

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|---------|------|------|
| Main Run Args | 入力 | String | オプション | 全インスタンス共通の起動引数 |
| Main Feature Tags | 入力 | String | オプション | 全インスタンス共通のフィーチャータグ |
| Enable Multiple Instances | 入力 | bool | - | マルチインスタンス有効化 |
| インスタンス数 | 入力 | int | - | 1-20の範囲 |
| Override Main Run Args | 入力 | bool[] | - | 各インスタンスでメイン引数を上書き |
| Launch Arguments | 入力 | String[] | - | 各インスタンスの追加/上書き引数 |
| Override Main Tags | 入力 | bool[] | - | 各インスタンスでメインタグを上書き |
| Feature Tags | 入力 | String[] | - | 各インスタンスの追加/上書きタグ |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| Main Run Args | テキスト入力 | プレースホルダー「Space-separated arguments, example: host player1 blue」 |
| Main Feature Tags | テキスト入力 | プレースホルダー「Comma-separated tags, example: demo, steam, event」 |
| Enable Multiple Instances | チェックボックス | マルチインスタンスモードの有効化 |
| インスタンス数 | SpinBox | 1-20の数値入力 |
| インスタンスツリー | Tree | 4列構成の設定テーブル |
| Override Main Run Args | チェックボックス列 | 引数上書きフラグ |
| Launch Arguments | テキスト列 | 引数入力 |
| Override Main Tags | チェックボックス列 | タグ上書きフラグ |
| Feature Tags | テキスト列 | タグ入力 |

## イベント仕様

### 1-ダイアログ表示

popup_dialog()が呼び出され、Size2(1200, 600) * EDSCALEでダイアログが表示される。

### 2-メイン引数入力

main_args_editのtext_changedにより_start_main_timer()が呼び出され、0.5秒後に_save_main_args()が実行される。ProjectSettingsに「editor/run/main_run_args」として保存される。

### 3-メインフィーチャータグ入力

main_features_editのtext_changedにより_start_main_timer()が呼び出され、0.5秒後に_save_main_args()が実行される。EditorSettingsのproject_metadataに保存される。

### 4-マルチインスタンス有効化

enable_multiple_instances_checkboxのpressedにより：
1. _start_main_timer()でproject_metadataに保存
2. instance_count SpinBoxのset_editable()が呼び出される

### 5-インスタンス数変更

instance_countのvalue_changedにより：
1. _start_instance_timer()で保存タイマー開始
2. _refresh_argument_count()でツリー再構築
3. stored_dataに足りない分のDictionaryを追加
4. 各インスタンスの_create_instance()呼び出し

### 6-インスタンス設定変更

instance_treeのitem_editedにより_start_instance_timer()が呼び出され、0.5秒後に_save_arguments()が実行される。各インスタンスのデータがEditorSettingsのproject_metadataに保存される。

### 7-右クリックメニュー

instance_treeでの右クリック（item_mouse_selected/empty_clicked）により_instance_tree_rmb()が呼び出される：
1. PopupMenuを表示
2. CLEAR_ITEM：選択アイテムのデータをクリア
3. CLEAR_ALL：全インスタンスのデータをクリア

### 8-引数取得

get_argument_list_for_instance()が呼び出され：
1. override_argsがtrueの場合：インスタンス固有引数のみ使用
2. override_argsがfalseの場合：メイン引数+インスタンス引数
3. %command%プレースホルダー対応（実行コマンド置換）

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| メイン引数保存 | project.godot | UPDATE | editor/run/main_run_args設定 |
| メインタグ保存 | EditorSettings | UPDATE | project_metadata保存 |
| インスタンス設定保存 | EditorSettings | UPDATE | project_metadata保存 |

### テーブル別更新項目詳細

#### EditorSettings project_metadata

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| SET | debug_options/run_main_feature_tags | main_features_edit->get_text() | メインフィーチャータグ |
| SET | debug_options/multiple_instances_enabled | checkbox->is_pressed() | マルチインスタンス有効フラグ |
| SET | debug_options/run_instances_config | TypedArray<Dictionary> | 各インスタンス設定 |
| SET | debug_options/run_instance_count | instance_count->get_value() | インスタンス数 |

#### インスタンス設定Dictionary

| キー | 値 | 説明 |
|-----|------|------|
| override_args | bool | メイン引数上書きフラグ |
| arguments | String | 起動引数 |
| override_features | bool | メインタグ上書きフラグ |
| features | String | フィーチャータグ |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------:|
| - | タイトル | Run Instances | ダイアログタイトル |
| - | ラベル | Main Run Args: | メイン引数ラベル |
| - | ラベル | Main Feature Tags: | メインタグラベル |
| - | チェック | Enable Multiple Instances | マルチインスタンスチェック |
| - | 列タイトル | Override Main Run Args | ツリー列1 |
| - | 列タイトル | Launch Arguments | ツリー列2 |
| - | 列タイトル | Override Main Tags | ツリー列3 |
| - | 列タイトル | Feature Tags | ツリー列4 |
| - | メニュー | Clear | 右クリックメニュー項目1 |
| - | メニュー | Clear All | 右クリックメニュー項目2 |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| インスタンス数超過 | instance_countの最大値20で制限 |
| 無効な引数形式 | _split_cmdline_args()でクォート文字列を考慮してパース |

## 備考

- AcceptDialogを継承（OKボタンのみ）
- Timerで0.5秒の遅延保存（連続入力時の負荷軽減）
- %command%プレースホルダーでSteam起動オプション風のカスタムコマンド対応
- singletonパターンでget_singleton()によるアクセス
- Tree列は4列：Override Args / Launch Arguments / Override Features / Feature Tags
- 右クリック選択を許可（set_allow_rmb_select(true)）
- SCROLL_HINT_MODE_BOTTOMでスクロールヒント表示

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

クラス定義とInstanceData構造体を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | run_instances_dialog.h | `editor/run/run_instances_dialog.h` | Columns列挙（46-51行目）、InstanceData構造体（53-60行目） |

**読解のコツ**: 4つの列（COLUMN_OVERRIDE_ARGS, COLUMN_LAUNCH_ARGUMENTS, COLUMN_OVERRIDE_FEATURES, COLUMN_FEATURE_TAGS）がツリーの構造を定義。InstanceDataがTreeItemへのラッパーとして機能。

#### Step 2: コンストラクタを理解する

UI構築とイベント接続を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | run_instances_dialog.cpp | `editor/run/run_instances_dialog.cpp` | コンストラクタ（296-405行目） |

**主要処理フロー**:
1. **300-310行目**: Timer初期化（main_apply_timer, instance_apply_timer）
2. **319-348行目**: メイン引数/タグ入力の初期化
3. **352-372行目**: マルチインスタンスチェックボックスとSpinBox
4. **379-404行目**: インスタンスツリー（4列）の初期化

#### Step 3: インスタンス生成を理解する

_refresh_argument_count()と_create_instance()の実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | run_instances_dialog.cpp | `editor/run/run_instances_dialog.cpp` | _refresh_argument_count()（61-79行目） |
| 3-2 | run_instances_dialog.cpp | `editor/run/run_instances_dialog.cpp` | _create_instance()（81-100行目） |

**主要処理フロー**:
- **62-63行目**: ツリークリアとルート作成
- **65-67行目**: stored_dataの拡張
- **72-78行目**: 各インスタンスの_create_instance()呼び出し
- **85-99行目**: TreeItemのセル設定（チェック/テキスト）

#### Step 4: 保存処理を理解する

_save_main_args()と_save_arguments()の実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | run_instances_dialog.cpp | `editor/run/run_instances_dialog.cpp` | _save_main_args()（102-107行目） |
| 4-2 | run_instances_dialog.cpp | `editor/run/run_instances_dialog.cpp` | _save_arguments()（109-121行目） |

**主要処理フロー**:
- **103-104行目**: ProjectSettingsにメイン引数保存
- **105-106行目**: EditorSettingsにメインタグ・有効フラグ保存
- **110-118行目**: 各インスタンスデータをDictionaryに変換
- **119-120行目**: project_metadataに保存

#### Step 5: 引数取得処理を理解する

get_argument_list_for_instance()の実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | run_instances_dialog.cpp | `editor/run/run_instances_dialog.cpp` | get_argument_list_for_instance()（210-268行目） |

**主要処理フロー**:
- **211-223行目**: 引数文字列の決定（override/追加）
- **233-234行目**: %command%プレースホルダーの検出
- **237-253行目**: プレースホルダー展開（実行コマンド置換）
- **260-266行目**: 通常の引数パース

### プログラム呼び出し階層図

```
RunInstancesDialog (AcceptDialog)
    │
    ├─ popup_dialog()                     [表示]
    │      └─ popup_centered_clamped()
    │
    ├─ _refresh_argument_count()          [ツリー再構築]
    │      ├─ instance_tree->clear()
    │      ├─ stored_data拡張
    │      └─ _create_instance()
    │
    ├─ _save_main_args()                  [メイン設定保存]
    │      ├─ ProjectSettings::set_setting()
    │      └─ EditorSettings::set_project_metadata()
    │
    ├─ _save_arguments()                  [インスタンス設定保存]
    │      └─ EditorSettings::set_project_metadata()
    │
    ├─ get_argument_list_for_instance()   [引数取得]
    │      ├─ override判定
    │      ├─ %command%プレースホルダー展開
    │      └─ _split_cmdline_args()
    │
    └─ apply_custom_features()            [フィーチャータグ適用]
           └─ OS::set_environment()
```

### データフロー図

```
[入力]                    [処理]                         [出力]

main_args_edit ─────────▶ text_changed ────────────────▶ Timer開始
                              │                          (0.5秒待機)
                              └─ _start_main_timer()
                                      │
                                      ▼
                              _save_main_args() ────────▶ ProjectSettings
                                                          EditorSettings

instance_count ─────────▶ value_changed ───────────────▶ ツリー再構築
SpinBox                       │
                              └─ _refresh_argument_count()
                                      │
                                      ▼
                              _create_instance() ───────▶ TreeItem作成

instance_tree ──────────▶ item_edited ─────────────────▶ Timer開始
設定変更                      │
                              └─ _start_instance_timer()
                                      │
                                      ▼
                              _save_arguments() ────────▶ EditorSettings

実行時 ─────────────────▶ get_argument_list_for_instance()
                              │                          ▼
                              ├─ override判定        引数リスト
                              └─ %command%展開
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| run_instances_dialog.cpp | `editor/run/run_instances_dialog.cpp` | ソース | ダイアログの実装 |
| run_instances_dialog.h | `editor/run/run_instances_dialog.h` | ヘッダ | クラス定義 |
| editor_settings.h | `editor/settings/editor_settings.h` | ヘッダ | project_metadata保存 |
| project_settings.h | `core/config/project_settings.h` | ヘッダ | プロジェクト設定 |
| tree.h | `scene/gui/tree.h` | ヘッダ | ツリーUI |
| spin_box.h | `scene/gui/spin_box.h` | ヘッダ | 数値入力 |
| timer.h | `scene/main/timer.h` | ヘッダ | 遅延保存タイマー |
