# 画面設計書 13-Property Editor

## 概要

本ドキュメントは、Dear ImGuiのサンプルアプリケーション「Property Editor」画面の設計仕様を定義する。本画面は、オブジェクトのプロパティを編集するエディタのサンプル実装である。

### 本画面の処理概要

本画面は、ゲームエンジンや3Dソフトウェアで一般的に見られるプロパティエディタのパターンを実演する。左側にオブジェクトのツリー構造を表示し、右側で選択されたオブジェクトのプロパティを編集できる。

**業務上の目的・背景**：ゲーム開発やデータ編集ツールでは、オブジェクト階層をナビゲートしながら各オブジェクトのプロパティを編集する機能が必要となる。本画面は、ImGuiでデータ駆動型のプロパティエディタを実装する方法を示す。ExampleMemberInfoによるフィールド定義と、データ型に応じた動的なウィジェット生成を学ぶことができる。

**画面へのアクセス方法**：Demo Windowのメニューバーから「Examples」メニューを選択し、「Property Editor」を選択することで表示される。または、アプリケーションコード内で`ShowExampleAppPropertyEditor(&show_app_property_editor, &demo_data)`を呼び出すことで直接表示可能。

**主要な操作・処理内容**：
1. 左側ツリービューでオブジェクト階層をナビゲート
2. フィルタ入力によるツリーノードの絞り込み（Ctrl+Fでフォーカス）
3. オブジェクト選択時に右側にプロパティを表示
4. データ型に応じたウィジェットでプロパティを編集（Bool, Int, Float, String）
5. ツリーノードの展開/折りたたみ

**画面遷移**：本画面はDemo Windowの「Examples」メニューから呼び出される。独立したウィンドウとして表示され、他の画面への直接的な遷移機能は持たない。

**権限による表示制御**：本画面は権限による表示制御を持たない。すべてのユーザーが同一の機能にアクセス可能である。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | Begin | 主機能 | プロパティエディタウィンドウの開始処理 |
| 25 | End | 主機能 | プロパティエディタウィンドウの終了処理 |
| 135 | TreeNode | 主機能 | プロパティのツリー表示 |
| 138 | TreePop | 主機能 | ツリーのポップ |
| 120 | InputText | 補助機能 | テキストプロパティの編集 |
| 123 | InputFloat | 補助機能 | 数値プロパティの編集 |
| 129 | ColorEdit3 | 補助機能 | カラープロパティの編集 |
| 96 | Checkbox | 補助機能 | ブールプロパティの編集 |

## 画面種別

編集（プロパティエディタ）

## URL/ルーティング

N/A（ImGuiはURLベースのルーティングを持たない。`ShowExampleAppPropertyEditor()`関数呼び出しによりウィンドウを表示）

## 入出力項目

| 項目名 | 型 | I/O | 必須 | 説明 |
|--------|-----|-----|------|------|
| p_open | bool* | I/O | No | ウィンドウの表示状態を制御するポインタ |
| demo_data | ImGuiDemoWindowData* | I/O | Yes | デモウィンドウのデータ（DemoTreeを含む） |
| Filter | ImGuiTextFilter | I | No | ツリーノードのフィルタリング文字列 |
| SelectedNode | ExampleTreeNode* | I/O | No | 現在選択されているノード |

## 表示項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ツリーノード | TreeNode | 階層構造のオブジェクト一覧 |
| フィルタ入力 | InputText | ノード名でフィルタリングするための入力欄 |
| ノード名 | Text | 選択されたノードの名前 |
| UID | TextDisabled | 選択されたノードの一意識別子 |
| プロパティテーブル | Table | プロパティ名と編集ウィジェットの2列テーブル |

## イベント仕様

### 1-ツリーノード選択

ツリービューでノードをクリックまたはキーボードナビゲーションで選択すると、SelectedNodeが更新され、右側のプロパティパネルに選択されたノードのプロパティが表示される。IsItemFocused()でフォーカス状態を検知して選択を更新。

### 2-フィルタ入力

フィルタ入力欄（Ctrl+Fでフォーカス可能）にテキストを入力すると、Filter.PassFilter()を使用してマッチするルートノードのみがツリーに表示される。ESCキーでフィルタをクリア。

### 3-プロパティ編集

選択されたノードのプロパティを各データ型に応じたウィジェットで編集する：
- Bool型: Checkbox
- S32型: DragScalarN
- Float型: SliderScalarN
- String型: InputText

### 4-ツリーノード展開/折りたたみ

ツリーノードの矢印をクリック、またはダブルクリックで子ノードの表示/非表示を切り替える。ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClickフラグを使用。

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

本画面はデータベースを使用しない。編集されたプロパティ値はExampleTreeNodeオブジェクトのメンバ変数に直接反映される。

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

N/A（データベースアクセスなし）

### メモリ操作詳細

| 操作 | 対象データ | 操作種別 | 概要 |
|-----|-----------|---------|------|
| プロパティ編集 | ExampleTreeNode.DataMyBool | UPDATE | ブール値の編集 |
| プロパティ編集 | ExampleTreeNode.DataMyInt | UPDATE | 整数値の編集 |
| プロパティ編集 | ExampleTreeNode.DataVec2 | UPDATE | 2次元ベクトルの編集 |

## メッセージ仕様

| 表示テキスト | 表示場所 | 説明 |
|-------------|---------|------|
| "UID: 0x%08X" | 右側パネル上部 | 選択されたノードのUID（16進数表示） |
| "incl,-excl" | フィルタ入力ヒント | フィルタの使用方法（含む/除外） |

## 例外処理

| 状態 | 処理内容 |
|------|----------|
| ウィンドウ非表示時 | Begin()がfalseを返した場合、End()を呼び出して即座にリターン |
| DemoTreeがNULL | ExampleTree_CreateDemoTree()で初期化 |
| SelectedNodeがNULL | 右側のプロパティパネルは空で表示 |
| HasDataがfalse | プロパティテーブルは空で表示 |

## 備考

- ExampleAppPropertyEditor構造体は再利用可能なプロパティエディタコンポーネントとして設計
- ExampleMemberInfoによるデータ駆動型のフィールド定義でプロパティを動的に生成
- TreeNodeExのImGuiTreeNodeFlags_DrawLinesToNodesフラグで階層構造を視覚化
- DataMyBoolがfalseのノードは無効化された色で表示される
- 左側ペインはリサイズ可能（ImGuiChildFlags_ResizeX）

---

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

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

### 推奨読解順序

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

まず、プロパティエディタが操作するデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_demo.cpp | `imgui_demo.cpp` | ExampleTreeNode構造体（存在する場合はその定義を確認） |
| 1-2 | imgui_demo.cpp | `imgui_demo.cpp` | ExampleMemberInfo構造体とExampleTreeNodeMemberInfos配列 |
| 1-3 | imgui_demo.cpp | `imgui_demo.cpp` | ExampleAppPropertyEditor構造体（9442-9566行） |

**読解のコツ**: ExampleMemberInfoはリフレクション的なアプローチで、フィールド名・オフセット・データ型を定義する。これによりループでプロパティを動的に生成できる。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_demo.cpp | `imgui_demo.cpp` | ShowExampleAppPropertyEditor()関数（9569-9585行） |

**主要処理フロー**:
1. **9571行**: SetNextWindowSizeで初期サイズ430x450を設定
2. **9572-9576行**: Begin()でウィンドウを開始、失敗時は早期リターン
3. **9580-9581行**: DemoTreeがNULLなら初期化
4. **9582行**: property_editor.Draw()で描画を委譲

#### Step 3: 描画処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_demo.cpp | `imgui_demo.cpp` | ExampleAppPropertyEditor::Draw()メソッド（9447-9535行） |

**主要処理フロー**:
- **9451-9468行**: 左側ツリーペインの描画（BeginChild, InputText, BeginTable）
- **9456-9457行**: フィルタ入力とビルド
- **9460-9466行**: ルートノードの子をループしてDrawTreeNode()を呼び出し
- **9471-9534行**: 右側プロパティペインの描画
- **9479-9531行**: プロパティテーブルの描画

#### Step 4: ツリーノード描画を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | imgui_demo.cpp | `imgui_demo.cpp` | ExampleAppPropertyEditor::DrawTreeNode()メソッド（9537-9565行） |

**主要処理フロー**:
- **9542-9550行**: TreeNodeFlagsの設定
- **9551-9555行**: 無効ノードのスタイル変更
- **9553行**: TreeNodeEx()でノードを描画
- **9556-9557行**: フォーカス時にSelectedNodeを更新
- **9558-9563行**: 再帰的に子ノードを描画

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

```
ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data)
    |
    +-- ImGui::SetNextWindowSize(430, 450)
    |
    +-- ImGui::Begin("Example: Property editor", p_open)
    |
    +-- [DemoTree初期化]
    |       +-- ExampleTree_CreateDemoTree()
    |
    +-- property_editor.Draw(demo_data->DemoTree)
            |
            +-- [左側ツリーペイン]
            |   +-- ImGui::BeginChild("##tree")
            |   +-- ImGui::InputTextWithHint("##Filter")
            |   +-- ImGui::BeginTable("##list")
            |           +-- for (root_node->Childs)
            |                   +-- DrawTreeNode(node)
            |                           +-- ImGui::TreeNodeEx()
            |                           +-- [再帰] DrawTreeNode(child)
            |
            +-- [右側プロパティペイン]
                +-- ImGui::BeginGroup()
                +-- ImGui::Text(node->Name)
                +-- ImGui::TextDisabled("UID: 0x%08X")
                +-- ImGui::BeginTable("##properties")
                        +-- for (ExampleTreeNodeMemberInfos)
                                +-- [データ型判定]
                                +-- ImGui::Checkbox() / DragScalarN() / SliderScalarN() / InputText()
```

### データフロー図

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

フィルタ入力 -----------> Filter.Build()
                          |
                          +-> PassFilter() -------------> ツリー表示の絞り込み

ツリーノードクリック ---> IsItemFocused()
                          |
                          +-> SelectedNode更新 ---------> プロパティパネル表示

プロパティ編集 ---------> ウィジェット操作
                          |
                          +-> field_ptr経由で直接更新 --> ExampleTreeNodeの値更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui_demo.cpp | `imgui_demo.cpp` | ソース | ExampleAppPropertyEditor構造体とShowExampleAppPropertyEditor()関数 |
| imgui.h | `imgui.h` | ヘッダー | ImGuiTextFilter, TreeNodeEx, BeginTable等の関数宣言 |
| imgui.cpp | `imgui.cpp` | ソース | Begin/End, BeginChild/EndChild, BeginGroup等の実装 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | TreeNodeEx, Checkbox, DragScalarN, SliderScalarN, InputTextの実装 |
| imgui_tables.cpp | `imgui_tables.cpp` | ソース | BeginTable, TableNextRow, TableNextColumn等の実装 |
