# 画面設計書 22-Assets Browser

## 概要

本ドキュメントは、Dear ImGuiのサンプルアプリケーション「Assets Browser」画面の設計書です。ファイルエクスプローラー風のアセット閲覧UIのリファレンス実装として提供されています。

### 本画面の処理概要

**業務上の目的・背景**：本画面は、ファイルエクスプローラーやアセット管理ツールのようなグリッドベースのアイテムブラウザの実装パターンを示すサンプルです。10,000以上のアイテムを効率的に表示するためのクリッピング技術、マルチセレクション、ドラッグ＆ドロップ、ボックス選択、ズーム機能など、実用的なアセットブラウザに必要な高度な機能を網羅しています。ゲームエンジンやコンテンツ管理ツールの開発において参考となる実装です。

**画面へのアクセス方法**：Demo Windowのメニューバーから「Examples」→「Assets Browser」を選択することでウィンドウが表示されます。ShowExampleAppAssetsBrowser関数の呼び出しにより、bool型のポインタで表示/非表示を制御できます。

**主要な操作・処理内容**：
1. グリッド形式でのアセットアイコン表示
2. クリックによるアイテム選択（単一/複数）
3. Shift+クリックによる範囲選択
4. Ctrl+クリックによるトグル選択
5. ボックス選択（矩形ドラッグ）による複数選択
6. Ctrl+マウスホイールによるアイコンサイズのズーム
7. ドラッグ＆ドロップによるアイテム移動
8. Deleteキーによる選択アイテムの削除
9. テーブルヘッダーによるソート機能
10. コンテキストメニューからの削除操作

**画面遷移**：Demo Windowの「Examples」メニューから呼び出されます。独立したウィンドウとして動作し、他の画面との直接的な遷移関係はありません。

**権限による表示制御**：本サンプルでは権限による表示制御は実装されていません。すべての機能が常に利用可能です。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 24 | Begin | 主機能 | アセットブラウザウィンドウの開始処理 |
| 25 | End | 主機能 | アセットブラウザウィンドウの終了処理 |
| 141 | Selectable | 主機能 | アセットの選択可能アイテム |
| 26 | BeginChild | 主機能 | アセットリスト領域 |
| 27 | EndChild | 主機能 | 子ウィンドウの終了 |
| 100 | Image | 補助機能 | アセットのサムネイル表示 |

## 画面種別

グリッドベースアセット一覧

## URL/ルーティング

N/A（Dear ImGuiはImmediate Mode GUIライブラリのため、URL/ルーティングの概念は適用されません）

## 入出力項目

| 項目名 | 型 | 入力/出力 | 説明 |
|--------|-----|----------|------|
| p_open | bool* | 入出力 | ウィンドウの表示/非表示状態 |
| ShowTypeOverlay | bool | 入力 | タイプオーバーレイの表示設定 |
| AllowSorting | bool | 入力 | ソート機能の有効/無効 |
| AllowDragUnselected | bool | 入力 | 未選択アイテムのドラッグ許可 |
| AllowBoxSelect | bool | 入力 | ボックス選択の有効/無効 |
| IconSize | float | 入力 | アイコンサイズ（16.0f - 128.0f） |
| IconSpacing | int | 入力 | アイコン間スペース |
| IconHitSpacing | int | 入力 | ヒット判定スペース |
| StretchSpacing | bool | 入力 | スペースストレッチの有効/無効 |

## 表示項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| メニューバー | MenuBar | File/Edit/Options メニュー |
| ソート用テーブルヘッダー | Table | Index/Type列のソート制御 |
| アセットグリッド | Selectable | アイコン形式のアセット一覧 |
| アイコン背景 | AddRectFilled | ダークグレーの背景矩形 |
| タイプオーバーレイ | AddRectFilled | アセットタイプを示す色付き矩形 |
| アイテムラベル | AddText | アイテムID番号 |
| 選択数表示 | Text | 選択されたアイテム数 / 総アイテム数 |

## イベント仕様

### 1-アイテム選択

Selectableウィジェットをクリックすると、Selection.ApplyRequests()によって選択状態が更新されます。ImGuiMultiSelectIOを介してマルチセレクションが管理されます。

### 2-ボックス選択

AllowBoxSelectがtrueの場合、ImGuiMultiSelectFlags_BoxSelect2dフラグにより、2Dグリッドでの矩形ドラッグ選択が有効になります。

### 3-ズーム操作

Ctrl+マウスホイールでIconSizeを変更します。ZoomWheelAccumにホイール量を蓄積し、1.0f以上で実際のサイズ変更を実行します。サイズは16.0f〜128.0fの範囲に制限されます。

### 4-ドラッグ＆ドロップ

BeginDragDropSource()で選択されたアイテム（または未選択アイテム）のペイロードを作成します。ペイロードタイプは「ASSETS_BROWSER_ITEMS」で、選択されたアイテムIDの配列を含みます。

### 5-削除操作

Deleteキー押下またはコンテキストメニューの「Delete」を選択すると、RequestDelete=trueが設定され、Selection.ApplyDeletionPreLoop/PostLoopで削除処理が実行されます。

### 6-アイテム追加

Fileメニューの「Add 10000 items」を選択すると、AddItems(10000)が呼び出され、新しいアイテムが追加されます。

### 7-全アイテムクリア

Fileメニューの「Clear items」を選択すると、ClearItems()が呼び出され、全アイテムと選択状態がクリアされます。

### 8-ソート

AllowSortingがtrueの場合、テーブルヘッダーをクリックすることで、Index列またはType列でソートできます。TableGetSortSpecs()でソート仕様を取得し、ExampleAsset::SortWithSortSpecs()でqsortを実行します。

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

N/A（本サンプルはデータベースを使用しません。すべてのデータはメモリ内の構造体で管理されます）

## メッセージ仕様

| メッセージID | 種別 | 表示条件 | メッセージ内容 |
|--------------|------|----------|----------------|
| MSG-001 | 情報 | 常時 | "Selected: {n}/{total} items" |
| MSG-002 | 情報 | ドラッグ中 | "{n} assets" |

## 例外処理

| 例外状況 | 処理内容 |
|----------|----------|
| ウィンドウが非表示の場合 | Begin()がfalseを返した場合、End()のみ呼び出して早期リターン |
| アイテムが0件の場合 | グリッド描画をスキップ |
| アイテムが画面外の場合 | ImGuiListClipperによりカリング |

## 備考

- 10,000アイテムでも60fps以上を維持できるよう、ImGuiListClipperによる仮想スクロールを実装
- ExampleSelectionWithDeletionクラスにより、削除と選択の整合性を維持
- アセットIDはImGuiIDとして管理され、インデックスとは独立して一意性を保持
- ズーム時のスクロール位置は、ホバー中のアイテムを中心に維持されるよう調整される

---

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

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

### 推奨読解順序

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

まず、アセットを表現するデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_demo.cpp | `imgui_demo.cpp` | ExampleAsset構造体（行10539-10577）を理解する。ID、Type、ソート関数を持つ |
| 1-2 | imgui_demo.cpp | `imgui_demo.cpp` | ExampleAssetsBrowser構造体（行10579-10922）を理解する。Options、State、Layout計算、描画ロジックを含む |

**読解のコツ**: ExampleAssetはシンプルなデータ構造で、IDとTypeのみを持ちます。ソート用の静的メンバ関数とグローバル変数s_current_sort_specsを使ってqsortと連携します。

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

処理の起点となる関数を特定します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_demo.cpp | `imgui_demo.cpp` | ShowExampleAppAssetsBrowser関数（行10924-10929）がエントリーポイント。static変数でExampleAssetsBrowserインスタンスを保持 |
| 2-2 | imgui_demo.cpp | `imgui_demo.cpp` | ExampleAssetsBrowser::Draw関数（行10651-10921）が実際の描画ロジック |

**主要処理フロー**:
1. **行10653**: SetNextWindowSizeでデフォルトサイズを設定
2. **行10654**: Begin()でウィンドウを開始
3. **行10661-10702**: メニューバー処理
4. **行10705-10723**: ソート用テーブルヘッダー
5. **行10727-10917**: メインのアセットグリッド描画

#### Step 3: レイアウト計算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_demo.cpp | `imgui_demo.cpp` | UpdateLayoutSizes関数（行10630-10649）でグリッドレイアウトを計算 |

**主要処理フロー**:
- **行10638**: LayoutItemSizeをIconSizeから計算
- **行10639**: LayoutColumnCountを利用可能幅とアイテムサイズから計算
- **行10640**: LayoutLineCountをアイテム総数と列数から計算
- **行10646**: LayoutItemStepを計算（アイテムサイズ + スペース）

#### Step 4: マルチセレクションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | imgui_demo.cpp | `imgui_demo.cpp` | BeginMultiSelect/EndMultiSelect（行10756, 10881）の使用パターン |
| 4-2 | imgui_demo.cpp | `imgui_demo.cpp` | Selection.ApplyRequests()（行10761, 10882）による選択状態の更新 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | imgui_demo.cpp | `imgui_demo.cpp` | ImGuiListClipperによる仮想スクロール（行10781-10868） |
| 5-2 | imgui_demo.cpp | `imgui_demo.cpp` | ImDrawListへの直接描画（行10846-10861） |

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

```
ShowExampleAppAssetsBrowser()
    |
    +-- static ExampleAssetsBrowser assets_browser
    |
    +-- assets_browser.Draw()
            |
            +-- ImGui::Begin() ... ImGui::End()
            |       |
            |       +-- ImGui::BeginMenuBar() / EndMenuBar()
            |       |       |
            |       |       +-- ImGui::BeginMenu("File") -- AddItems() / ClearItems()
            |       |       +-- ImGui::BeginMenu("Edit") -- RequestDelete
            |       |       +-- ImGui::BeginMenu("Options") -- 各種設定
            |       |
            |       +-- ImGui::BeginTable() [ソート用ヘッダー]
            |       |       |
            |       |       +-- TableGetSortSpecs() -> ExampleAsset::SortWithSortSpecs()
            |       |
            |       +-- ImGui::BeginChild("Assets")
            |               |
            |               +-- UpdateLayoutSizes()
            |               |
            |               +-- ImGui::BeginMultiSelect()
            |               |       |
            |               |       +-- Selection.ApplyRequests()
            |               |
            |               +-- ImGuiListClipper [仮想スクロール]
            |               |       |
            |               |       +-- ImGui::Selectable() [各アイテム]
            |               |       |       |
            |               |       |       +-- ImGui::BeginDragDropSource()
            |               |       |       +-- draw_list->AddRectFilled()
            |               |       |       +-- draw_list->AddText()
            |               |
            |               +-- ImGui::BeginPopupContextWindow() [コンテキストメニュー]
            |               |
            |               +-- ImGui::EndMultiSelect()
            |               |       |
            |               |       +-- Selection.ApplyDeletionPostLoop()
            |               |
            |               +-- [Ctrl+Wheel ズーム処理]
            |
            +-- ImGui::Text("Selected: %d/%d")
```

### データフロー図

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

p_open (bool*) ---------> Draw() ------------------------> ウィンドウ表示
                              |
ユーザー操作 -----------> マルチセレクト処理 ------------> Selection更新
(クリック/ドラッグ)           |                                |
                              |                                v
マウスホイール ---------> ズーム処理 --------------------> IconSize更新
(Ctrl+Wheel)                  |                                |
                              v                                v
                         UpdateLayoutSizes() --------------> レイアウト計算
                              |                                |
                              v                                v
                         ListClipper + Draw --------------> 画面描画
                              |
                         ソート仕様 ----------------------> Items配列の順序
                         (TableGetSortSpecs)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui_demo.cpp | `imgui_demo.cpp` | ソース | ShowExampleAppAssetsBrowser関数の実装（行10534-10929） |
| imgui.h | `imgui.h` | ヘッダー | ImGuiMultiSelect関連API定義 |
| imgui.cpp | `imgui.cpp` | ソース | マルチセレクション・クリッパーの実装 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ExampleSelectionWithDeletion等の内部構造体 |
