# 機能設計書 9-EndFrame

## 概要

本ドキュメントはDear ImGuiライブラリのEndFrame関数に関する機能設計書である。EndFrameはImGuiフレームを終了し、フレームの後処理を行う関数である。

### 本機能の処理概要

EndFrame関数は、NewFrameで開始されたImGuiフレームを終了し、内部状態のクリーンアップやナビゲーション処理等のフレーム終了時処理を行う。この関数はRender()から自動的に呼び出されるため、通常は明示的に呼び出す必要はない。

**業務上の目的・背景**：ImGuiのフレームサイクルはNewFrame→ウィジェット呼び出し→EndFrame/Renderの順で構成される。EndFrameはフレームの論理的な終了を担当し、ナビゲーション更新、ドラッグ&ドロップ処理、エラーリカバリ、IME（入力メソッドエディタ）通知などを行う。描画データの生成はRender()で行われるため、描画せずにフレームを終了する場合にEndFrameを直接呼び出すことができる。

**機能の利用シーン**：
- Render()から自動呼び出し（通常のケース）
- 描画をスキップする場合に明示的に呼び出し
- フレームを論理的に終了するが描画データは不要な場合

**主要な処理内容**：
1. 重複呼び出しの防止
2. エラーリカバリ処理
3. エラーチェック（スタックバランス等）
4. IME通知
5. 暗黙のDebugウィンドウの非表示処理
6. ナビゲーション終了処理
7. ドラッグ&ドロップ処理
8. テクスチャ更新終了処理
9. フレーム終了フック呼び出し

**関連システム・外部連携**：
- IME（入力メソッドエディタ）：カーソル位置の通知
- プラットフォームバックエンド：IMEデータ設定

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 全ての画面のフレーム終了処理 |

## 機能種別

フレーム管理 / 終了処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | 引数なし | - |

### 入力データソース

- GImGuiグローバル変数（現在のコンテキスト）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | void | 戻り値なし |

### 出力先

- コンテキスト内部状態の更新
- g.FrameCountEndedの更新

## 処理フロー

### 処理シーケンス

```
1. 初期化確認
   └─ g.Initializedを確認

2. 重複呼び出しチェック
   └─ g.FrameCountEnded == g.FrameCountなら早期リターン

3. フレームスコープ確認
   └─ WithinFrameScopeがtrueであることを確認

4. コンテキストフック呼び出し
   └─ CallContextHooks(ImGuiContextHookType_EndFramePre)

5. エラーリカバリ
   └─ ErrorRecoveryTryToRecoverState() [ConfigErrorRecovery有効時]

6. エラーチェック
   ├─ ErrorCheckEndFrameSanityChecks()
   └─ ErrorCheckEndFrameFinalizeErrorTooltip()

7. IME通知
   └─ Platform_SetImeDataFn() [データ変更時]

8. Debugウィンドウ処理
   ├─ WithinFrameScopeWithImplicitWindow = false
   └─ 未使用なら非アクティブ化、End()呼び出し

9. ナビゲーション終了処理
   └─ NavEndFrame()

10. ドラッグ&ドロップ処理
    └─ 配送完了または期限切れでClearDragDrop()

11. テクスチャ更新終了
    └─ UpdateTexturesEndFrame()

12. フレーム終了フック
    └─ CallContextHooks(ImGuiContextHookType_EndFramePost)

13. フレームカウント更新
    └─ g.FrameCountEnded = g.FrameCount
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{g.Initialized?}
    B -->|No| C[アサート失敗]
    B -->|Yes| D{既に終了済み?}
    D -->|Yes| E[早期リターン]
    D -->|No| F[EndFramePreフック]
    F --> G[エラーリカバリ]
    G --> H[エラーチェック]
    H --> I[IME通知]
    I --> J[Debugウィンドウ処理]
    J --> K[ナビゲーション終了]
    K --> L[D&D処理]
    L --> M[テクスチャ更新終了]
    M --> N[EndFramePostフック]
    N --> O[FrameCountEnded更新]
    O --> P[終了]
    E --> P
    C --> Q[プログラム停止]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 初期化必須 | g.Initializedがfalseの場合アサート失敗 | 常に |
| BR-02 | 重複呼び出し防止 | 同一フレームで複数回呼び出されても1回だけ処理 | g.FrameCountEnded == g.FrameCount |
| BR-03 | NewFrame必須 | NewFrameが呼ばれていない場合エラー | WithinFrameScope == false |
| BR-04 | Render自動呼び出し | Render()がEndFrame()を自動的に呼び出す | 常に |

### 計算ロジック

特になし

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IM_ASSERT | アサート失敗 | 未初期化 | NewFrame()を呼び出す |
| IM_ASSERT_USER_ERROR | ユーザーエラー | NewFrame未呼び出し | NewFrame()を呼び出す |
| エラーリカバリ | 自動修復 | スタック不整合 | ConfigErrorRecovery有効時に自動修復 |

### リトライ仕様

特になし

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

該当なし

## パフォーマンス要件

- 毎フレーム呼び出されるため、効率的な実装が必要
- 通常は1ms未満で完了

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

- 特になし

## 備考

- 通常はRender()から自動呼び出しされるため、明示的に呼ぶ必要はない
- 描画をスキップする場合のみ直接呼び出す
- 描画不要でもNewFrameを呼んだらEndFrame/Renderを呼ぶべき

---

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

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

### 推奨読解順序

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

EndFrameで更新される主要なコンテキストメンバを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui_internal.h | `imgui_internal.h` | ImGuiContext: FrameCountEnded, WithinFrameScope等 |

**読解のコツ**:
- `int FrameCountEnded` - EndFrame呼び出し済みフレーム番号
- `bool WithinFrameScope` - フレームスコープフラグ
- `bool WithinFrameScopeWithImplicitWindow` - 暗黙ウィンドウ有りスコープフラグ

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.h | `imgui.h` | 402行目: EndFrameのAPI宣言 |
| 2-2 | imgui.cpp | `imgui.cpp` | 5930-6028行目: EndFrame関数の実装 |

**主要処理フロー**:
1. **5933行目**: 初期化確認 `IM_ASSERT(g.Initialized)`
2. **5936-5937行目**: 重複呼び出しチェック
3. **5938行目**: フレームスコープ確認
4. **5940行目**: EndFramePreフック
5. **5943-5946行目**: エラーリカバリ・チェック
6. **5949-5956行目**: IME通知
7. **5960-5963行目**: Debugウィンドウ処理
8. **5966行目**: ナビゲーション終了
9. **5969-5975行目**: ドラッグ&ドロップ処理

#### Step 3: Render()との関係を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.cpp | `imgui.cpp` | 6031-6100行目: Render関数の実装 |

**読解のコツ**:
- Render()は最初にEndFrame()を呼び出す（6036-6037行目）
- 描画データ生成はRender()で行われる

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

```
ImGui::EndFrame()
    │
    ├─ CallContextHooks(ImGuiContextHookType_EndFramePre)
    │
    ├─ ErrorRecoveryTryToRecoverState() [optional]
    │
    ├─ ErrorCheckEndFrameSanityChecks()
    │
    ├─ ErrorCheckEndFrameFinalizeErrorTooltip()
    │
    ├─ Platform_SetImeDataFn() [if data changed]
    │
    ├─ End() [for implicit Debug window]
    │
    ├─ NavEndFrame()
    │
    ├─ ClearDragDrop() [if needed]
    │
    ├─ UpdateTexturesEndFrame()
    │
    └─ CallContextHooks(ImGuiContextHookType_EndFramePost)
```

### データフロー図

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

コンテキスト状態 ────────▶ EndFrame() ─────────────────────▶ 更新されたコンテキスト
  - WithinFrameScope=true      │                            - FrameCountEnded更新
  - 各種スタック                │                            - WithinFrameScope=false
                               ▼                            - D&D状態クリア
                       フレーム終了処理
                       内部状態クリーンアップ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | パブリックAPI宣言（402行目） |
| imgui.cpp | `imgui.cpp` | ソース | 実装（5930-6028行目） |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | ImGuiContext構造体定義 |
