# 機能設計書 94-InvisibleButton

## 概要

本ドキュメントはImGuiのInvisibleButton機能について、その処理内容、入出力仕様、実装詳細を記述した機能設計書である。

### 本機能の処理概要

InvisibleButtonは、視覚的な描画を行わない透明なボタンを作成するためのUI機能である。ボタンのインタラクション動作（クリック検出、ホバー状態）は通常のボタンと同様に機能するが、背景やラベルの描画は行わない。カスタム描画を行いたい場合や、特定の領域にクリック検出を追加したい場合に使用される。

**業務上の目的・背景**：GUIアプリケーションにおいて、既存のグラフィックス上にインタラクティブな領域を追加したい場合がある。例えば、カスタム描画したグラフの特定部分をクリック可能にしたり、画像の一部にホットスポットを設定したりする場合である。InvisibleButtonはこれらのニーズに対応し、描画とインタラクションを分離することで、柔軟なUI設計を可能にする。

**機能の利用シーン**：カスタム描画ウィジェットのクリック領域定義、画像のホットスポット作成、ドラッグ操作のハンドル領域、グラフやチャートのインタラクティブポイント、ゲームUIのクリック領域などで使用される。

**主要な処理内容**：
1. 指定されたサイズでバウンディングボックスを作成する
2. 文字列IDからウィジェットIDを生成する
3. 領域を確保し、描画リストに登録する（描画はしない）
4. ButtonBehaviorでクリック・ホバー・ホールド状態を判定する
5. ナビゲーションカーソルのみを描画する
6. 押下状態（pressed）を戻り値として返す

**関連システム・外部連携**：ImGuiのButtonBehavior関数、ナビゲーションシステムと連携。IsItemActive、IsItemHoveredなどの状態クエリ関数と組み合わせて使用することが多い。

**権限による制御**：BeginDisabled/EndDisabledで無効化可能。ImGuiButtonFlags_EnableNavフラグでナビゲーション対応を制御可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | Custom Rendering | 補助機能 | カスタム描画領域の作成 |

## 機能種別

UIウィジェット / ユーザー入力処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| str_id | const char* | Yes | ボタンの識別子文字列 | NULL終端文字列 |
| size | const ImVec2& | Yes | ボタンのサイズ | 正の値推奨。0の場合は-FLT_MINに変換 |
| flags | ImGuiButtonFlags | No | ボタンの動作フラグ | デフォルト: 0 |

### 入力データソース

- 呼び出し元からの直接指定

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| pressed | bool | ボタンが押されたかどうか |

### 出力先

- 戻り値として呼び出し元に返却
- ImDrawList（ナビゲーションカーソルのみ）

## 処理フロー

### 処理シーケンス

```
1. ウィンドウの取得とスキップチェック
   └─ GetCurrentWindow()で現在のウィンドウを取得
   └─ SkipItemsがtrueの場合はfalseを返す

2. サイズの調整
   └─ size.xまたはsize.yが0の場合、-FLT_MINに変換
   └─ CalcItemSize()で最終サイズを決定

3. ID生成とアイテム登録
   └─ window->GetID(str_id)でIDを生成
   └─ ItemSize()でレイアウト領域を確保
   └─ ItemAdd()で描画リストに追加

4. インタラクション判定
   └─ ButtonBehavior()でhovered/held/pressed状態を取得

5. 描画（最小限）
   └─ RenderNavCursor()でナビゲーションカーソルのみ描画

6. 結果返却
   └─ pressed状態を返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始: InvisibleButton] --> B{SkipItems?}
    B -->|Yes| C[return false]
    B -->|No| D[サイズ調整<br/>0→-FLT_MIN]
    D --> E[CalcItemSize]
    E --> F[GetID]
    F --> G[ItemSize/ItemAdd]
    G --> H{ItemAdd成功?}
    H -->|No| C
    H -->|Yes| I[ButtonBehavior]
    I --> J[RenderNavCursor]
    J --> K[return pressed]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-94-01 | ゼロサイズ処理 | size.x/yが0の場合、-FLT_MINに変換して残りスペースにフィット | size.x == 0 または size.y == 0 |
| BR-94-02 | 描画なし | 背景、ラベル等の視覚的な描画は行わない | 常時 |
| BR-94-03 | ナビゲーション制御 | EnableNavフラグがない場合、ナビゲーション対象外 | フラグによる |

### 計算ロジック

- サイズ変換: `size = CalcItemSize(ImVec2(size_arg.x != 0 ? size_arg.x : -FLT_MIN, size_arg.y != 0 ? size_arg.y : -FLT_MIN), 0, 0)`

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

データベース操作なし（UI処理のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 早期リターン | window->SkipItems == true | falseを返す |
| - | 早期リターン | ItemAdd失敗 | falseを返す |

### リトライ仕様

リトライ不要（フレームごとに再評価）

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

トランザクション管理なし（即時処理）

## パフォーマンス要件

- 描画を行わないため、通常のButtonより軽量
- カスタム描画と組み合わせても、インタラクション判定は高速

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

- str_idは表示されないが、IDスタック機構に影響を与える

## 備考

- InvisibleButtonはカスタム描画と組み合わせて使用することが多い
- IsItemActive()、IsItemHovered()、GetItemRectMin/Max()などと組み合わせて、ドラッグ操作やカスタムウィジェットを実装できる
- デフォルトではキーボード/ゲームパッドナビゲーションの対象外（ImGuiButtonFlags_EnableNavで有効化可能）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | 634行目: InvisibleButton関数のAPI宣言を確認 |
| 1-2 | imgui.h | `imgui.h` | ImGuiButtonFlagsの定義を確認 |

**読解のコツ**: InvisibleButtonは「描画しないボタン」であることを意識する。通常のButtonとの違いは、視覚的な描画が省略されている点のみ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | 833-855行目: InvisibleButton関数の実装 |

**主要処理フロー**:
1. **836-838行目**: ウィンドウ取得とスキップチェック
2. **841行目**: サイズ調整（0→-FLT_MIN変換）
3. **843行目**: GetIDでID生成
4. **844-846行目**: ItemSize/ItemAdd
5. **849-850行目**: ButtonBehavior呼び出し
6. **851行目**: RenderNavCursor（ナビカーソルのみ描画）

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

```
ImGui::InvisibleButton(str_id, size_arg, flags)
    │
    ├─ GetCurrentWindow()
    │      └─ 現在のウィンドウコンテキストを取得
    │
    ├─ CalcItemSize()
    │      └─ サイズを計算（0を-FLT_MINに変換）
    │
    ├─ window->GetID(str_id)
    │      └─ 文字列からIDを生成
    │
    ├─ ItemSize() / ItemAdd()
    │      └─ レイアウトシステムに登録
    │
    ├─ ButtonBehavior(bb, id, &hovered, &held, flags)
    │      └─ クリック/ホバー/ホールド状態を判定
    │
    └─ RenderNavCursor()
           └─ ナビゲーションカーソルを描画（背景は描画しない）
```

### データフロー図

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

str_id (文字列) ────────────> GetID ─────────────────────────> ImGuiID
                                │
size_arg ───────────────────> CalcItemSize ─────────────────> 最終サイズ
                                │
                            ItemSize/ItemAdd
                                │
マウス/キーボード状態 ─────> ButtonBehavior ─────────────────> hovered, held, pressed
                                │
                            RenderNavCursor ────────────────> DrawList (最小限)
                                │
                            return pressed ─────────────────> bool (戻り値)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | InvisibleButton APIの宣言 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ImGuiButtonFlags定義 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | InvisibleButtonの実装 |
| imgui.cpp | `imgui.cpp` | ソース | ButtonBehavior、ItemSize、ItemAdd等のコア関数 |
