# 機能設計書 102-ImageButton

## 概要

本ドキュメントは、ImGuiライブラリにおける`ImageButton`関数の機能設計を記載する。

### 本機能の処理概要

`ImageButton`関数は、テクスチャ画像を使用したクリック可能なボタンウィジェットを作成する機能である。通常のボタンと同様のインタラクション（ホバー、押下、クリック）をサポートしながら、画像をボタン面に表示することで、アイコンボタンやツールバーボタンなどの視覚的に豊かなUIコンポーネントを実現する。

**業務上の目的・背景**：現代のGUIアプリケーションでは、テキストだけでなくアイコンやグラフィカルな要素でユーザー操作を促すことが一般的である。画像ボタンは、ツールバー、パレット、カードUI、ゲームUIなど様々な場面で使用され、直感的で視覚的に魅力的なインターフェースを構築するために不可欠な機能である。ImGui 1.89以降、明示的なstring ID引数が必須となり、複数の同一画像ボタンを正しく識別できるようになった。

**機能の利用シーン**：
- ツールバーのアイコンボタン（編集、削除、設定など）
- カラーパレットやテクスチャパレットの選択ボタン
- ゲームUIのスキルボタンやアイテムスロット
- アセットブラウザでのサムネイルクリック操作
- カスタムコントロールの作成

**主要な処理内容**：
1. ウィンドウとスキップ状態を確認
2. 文字列IDからユニークIDを生成
3. バウンディングボックスを計算（画像サイズ + FramePadding * 2）
4. ボタン動作を処理（ButtonBehavior）
5. ボタンの視覚状態に応じたフレームを描画
6. 背景色が指定されている場合は背景を描画
7. 画像を丸み設定に応じて描画

**関連システム・外部連携**：
- ImDrawList: 描画コマンドの発行
- ImTextureRef: テクスチャ参照
- スタイルシステム: FramePadding, FrameRounding, ImageRounding
- ボタンカラー: ImGuiCol_Button, ImGuiCol_ButtonHovered, ImGuiCol_ButtonActive

**権限による制御**：特になし（GUI描画機能のため）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 8 | Font Atlas | 補助機能 | フォントアトラス画像のクリック操作 |
| 22 | Assets Browser | 補助機能 | アセットサムネイルのクリック操作 |

## 機能種別

ウィジェット描画処理 / インタラクション処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| str_id | const char* | Yes | ボタンの一意識別子 | NULL不可、空文字可 |
| tex_ref | ImTextureRef | Yes | 表示するテクスチャの参照 | 有効なテクスチャIDであること |
| image_size | const ImVec2& | Yes | 画像の表示サイズ（ピクセル） | 正の値 |
| uv0 | const ImVec2& | No | テクスチャ座標の開始点（デフォルト: 0,0） | 0.0〜1.0の範囲 |
| uv1 | const ImVec2& | No | テクスチャ座標の終了点（デフォルト: 1,1） | 0.0〜1.0の範囲 |
| bg_col | const ImVec4& | No | 内部背景色（デフォルト: 透明） | RGBA各成分0.0〜1.0 |
| tint_col | const ImVec4& | No | ティント色（デフォルト: 白） | RGBA各成分0.0〜1.0 |

### 入力データソース

- ユーザー指定のパラメータ（関数引数）
- ImGuiスタイル設定（FramePadding, FrameRounding, ImageRounding）
- 現在のウィンドウ状態（CursorPos, SkipItems）
- マウス入力状態

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | ボタンがクリックされた場合true |

### 出力先

- ImDrawList（描画コマンドリスト）
  - ボタンフレーム
  - 背景色（設定時）
  - テクスチャ画像
- 戻り値によるユーザーコールバック

## 処理フロー

### 処理シーケンス

```
1. ウィンドウ状態確認
   └─ window->SkipItems がtrueの場合、falseを返す
2. ID生成
   └─ str_idからウィンドウIDを生成
3. 内部関数呼び出し
   └─ ImageButtonExに処理を委譲
4. ImageButtonEx内処理:
   4-1. バウンディングボックス計算
        └─ CursorPos + image_size + FramePadding*2
   4-2. アイテム登録
        └─ ItemSize(), ItemAdd()
   4-3. ボタン動作処理
        └─ ButtonBehavior()でhovered, held, pressedを取得
   4-4. フレーム描画
        └─ RenderNavCursor(), RenderFrame()
   4-5. 背景描画（bg_col.w > 0の場合）
        └─ AddRectFilled()
   4-6. 画像描画
        └─ AddImageRounded() or AddImage()
5. 押下状態を返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{SkipItems?}
    B -->|Yes| C[return false]
    B -->|No| D[GetID str_id]
    D --> E[ImageButtonEx呼出]
    E --> F[バウンディングボックス計算]
    F --> G[ItemSize/ItemAdd]
    G --> H{ItemAdd成功?}
    H -->|No| C
    H -->|Yes| I[ButtonBehavior]
    I --> J[RenderNavCursor]
    J --> K[RenderFrame]
    K --> L{bg_col.w > 0?}
    L -->|Yes| M[背景色描画]
    L -->|No| N{rounding > 0?}
    M --> N
    N -->|Yes| O[AddImageRounded]
    N -->|No| P[AddImage]
    O --> Q[return pressed]
    P --> Q
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-102-1 | パディング計算 | FramePaddingを画像の周囲に適用 | 常時 |
| BR-102-2 | 背景色描画判定 | bg_col.w > 0の場合のみ内部背景を描画 | bg_col指定時 |
| BR-102-3 | 丸み計算 | image_rounding = max(FrameRounding - max(padding.x, padding.y), ImageRounding) | 常時 |
| BR-102-4 | ボタン色状態 | held && hovered: ButtonActive, hovered: ButtonHovered, else: Button | 常時 |

### 計算ロジック

バウンディングボックス計算:
```
padding = g.Style.FramePadding
bb.Min = window->DC.CursorPos
bb.Max = window->DC.CursorPos + image_size + padding * 2.0f
```

画像丸み計算:
```
image_rounding = ImMax(g.Style.FrameRounding - ImMax(padding.x, padding.y), g.Style.ImageRounding)
```

## データベース操作仕様

該当なし（GUI描画機能のためデータベース操作は行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 描画スキップ | window->SkipItemsがtrue | falseを返して終了（正常動作） |
| - | アイテム追加失敗 | ItemAdd()がfalseを返す | falseを返して終了（正常動作） |

### リトライ仕様

リトライなし（フレーム単位の描画・インタラクション処理のため）

## トランザクション仕様

該当なし

## パフォーマンス要件

- 単一フレーム内で複数回呼び出し可能
- 描画コマンドはImDrawListにバッファリングされ、Render()時に一括処理
- ホバー判定はフレームごとに更新

## セキュリティ考慮事項

- テクスチャIDの検証はバックエンド実装に依存
- 不正なテクスチャ参照は未定義動作を引き起こす可能性あり

## 備考

- ImGui 1.89でAPI変更：明示的なstr_id引数が必須に
- 旧APIではテクスチャIDをボタンIDとして使用していた（複数ボタンで問題発生）
- `ImageButton`はフレームパディングを適用するが、`Image`は境界線パディングを使用（異なる挙動）
- 内部的に`ImageButtonEx`関数を呼び出す

---

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

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

### 推奨読解順序

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

まず、画像ボタンに関連するデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | ImVec2, ImVec4, ImTextureRef の定義を確認 |
| 1-2 | imgui.h | `imgui.h` | ImGuiStyle構造体のFramePadding, FrameRounding を確認 |

**読解のコツ**: FramePaddingはボタン系ウィジェット共通のパディング、FrameRoundingは角丸の半径を決定する。

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

処理の起点となる関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.h | `imgui.h` | 654行目: ImageButton関数の宣言 |
| 2-2 | imgui_widgets.cpp | `imgui_widgets.cpp` | 1183-1191行目: ImageButton関数の実装 |

**主要処理フロー**:
1. **1186-1188行目**: ウィンドウ取得とSkipItems確認
2. **1190行目**: GetIDでstring IDからユニークIDを生成
3. **1190行目**: ImageButtonExに処理を委譲

#### Step 3: 内部実装を理解する

ImageButtonExの詳細な処理を追跡する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | 1150-1179行目: ImageButtonEx実装 |

**主要処理フロー**:
- **1157-1158行目**: パディングとバウンディングボックス計算
- **1163-1164行目**: ButtonBehaviorでインタラクション処理
- **1167行目**: ボタン状態に応じた色決定
- **1168-1169行目**: ナビゲーションカーソルとフレーム描画
- **1170-1171行目**: 背景色描画判定と実行
- **1172-1176行目**: 画像丸み計算と描画

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

```
ImGui::ImageButton()
    │
    ├─ GetCurrentWindow()
    │      └─ GImGui->CurrentWindow を取得
    │
    ├─ window->GetID()
    │      └─ str_idからユニークIDを生成
    │
    └─ ImageButtonEx()
           │
           ├─ ItemSize()
           ├─ ItemAdd()
           ├─ ButtonBehavior()
           │      └─ hovered, held, pressed を計算
           ├─ GetColorU32()
           ├─ RenderNavCursor()
           ├─ RenderFrame()
           └─ window->DrawList->
                  ├─ AddRectFilled() ... 背景色描画
                  ├─ AddImageRounded() ... 丸み付き画像
                  └─ AddImage() ... 通常画像
```

### データフロー図

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

str_id      ───┐
tex_ref     ───┼──▶ ImageButton()
image_size  ───┤         │
uv0/uv1     ───┤         ▼
bg_col      ───┤    ImageButtonEx()  ───┬──▶ bool (pressed)
tint_col    ───┘         │              │
                         │              └──▶ ImDrawList
マウス状態  ────────────▶│                    (描画コマンド)
                         ▼
                    ButtonBehavior()
                    - hovered判定
                    - held判定
                    - pressed判定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | 関数宣言、型定義 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | ImageButton, ImageButtonEx実装 |
| imgui_draw.cpp | `imgui_draw.cpp` | ソース | ImDrawListの描画コマンド実装 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ButtonBehavior等の内部関数宣言 |
