# 機能設計書 230-IsKeyPressed

## 概要

本ドキュメントは、Dear ImGuiライブラリにおける`IsKeyPressed`関数の機能設計書である。この関数は、指定されたキーが押された瞬間（!Down -> Downへの遷移）を検出するためのキーボード入力検出関数である。

### 本機能の処理概要

`IsKeyPressed`関数は、指定されたImGuiKeyが押された瞬間を検出し、オプションでリピート機能にも対応する。IsKeyDownとは異なり、この関数はキーが押された瞬間に一度だけtrue（またはリピート設定に応じて繰り返し）を返す。

**業務上の目的・背景**：GUIアプリケーションでは、キーが押された瞬間に一度だけアクションを実行したい場合が多い。例えば、Enterキーで確定、Escキーでキャンセル、矢印キーでの項目移動などは、キーが押された瞬間に一度だけ処理を実行する必要がある。また、矢印キーでのカーソル移動のように、押し続けることで繰り返し処理を行いたい場合もある。本機能は、これらの要件を満たすためのキー押下イベント検出手段を提供する。

**機能の利用シーン**：
- テキスト入力での確定（Enter）やキャンセル（Esc）の検出
- リスト項目間の移動（矢印キー）
- ショートカットキーの検出（ただしShortcut()の使用を推奨）
- ゲームやインタラクティブアプリでのキー入力イベント検出
- フォーム操作でのキーイベントハンドリング

**主要な処理内容**：
1. 指定されたキーのキーデータを取得
2. キーの押下時間（DownDuration）を確認
3. リピートが有効な場合、リピートレートに基づいて判定
4. キーオーナーシップのテスト（必要な場合）
5. 結果をブール値で返却

**関連システム・外部連携**：プラットフォームバックエンド（Win32、GLFW、SDL等）がキー入力イベントを受け取り、ImGuiIOを通じてキー状態を更新する。io.KeyRepeatDelayとio.KeyRepeatRateがリピート動作を制御する。

**権限による制御**：キーオーナーシップシステムにより、特定のウィジェットがキーを「所有」している場合、他のコードからの判定がブロックされることがある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 27 | Inputs | 主画面 | キーボード入力のデモ |

## 機能種別

入力判定（読み取り専用）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | ImGuiKey | Yes | 判定対象のキー | ImGuiKey_NamedKey_BEGIN以上の有効なキー値 |
| repeat | bool | No | リピート機能の有効/無効。デフォルトtrue | - |

### リピート動作の制御

| 設定項目 | デフォルト値 | 説明 |
|---------|------------|------|
| io.KeyRepeatDelay | 0.275f | リピート開始までの遅延（秒） |
| io.KeyRepeatRate | 0.050f | リピート間隔（秒） |

### 入力データソース

ImGuiIOのKeysData配列（バックエンドから更新される）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | キーが押された場合true、そうでない場合false |

### 動作の詳細

- **repeat=false**: キーが押された瞬間（DownDuration == 0）のみtrueを返す
- **repeat=true**: 初回押下時 + リピート間隔でtrueを返し続ける

### 出力先

呼び出し元への戻り値として返却

## 処理フロー

### 処理シーケンス

```
1. 公開API（引数2つ）の呼び出し
   └─ 内部API（フラグとオーナーID版）を呼び出し
2. キーデータの取得
   └─ GetKeyData(key)でImGuiKeyData*を取得
3. 押下状態の確認
   └─ key_data->Downがfalseなら即座にfalseを返す
4. 押下時間の確認
   └─ DownDuration < 0なら即座にfalseを返す
5. 初回押下の判定
   └─ DownDuration == 0ならpressed = true
6. リピート判定（リピート有効時）
   ├─ リピート遅延・レートを取得
   └─ GetKeyPressedAmountで繰り返し回数を判定
7. キーオーナーシップテスト
8. 結果を返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B["GetKeyData(key)"]
    B --> C{key_data->Down ?}
    C -->|No| D["return false"]
    C -->|Yes| E{DownDuration < 0 ?}
    E -->|Yes| D
    E -->|No| F{DownDuration == 0 ?}
    F -->|Yes| G["pressed = true"]
    F -->|No| H{repeat有効 ?}
    G --> I[TestKeyOwner]
    H -->|No| J["pressed = false"]
    H -->|Yes| K[GetKeyPressedAmount]
    K --> L{amount > 0 ?}
    L -->|Yes| G
    L -->|No| J
    J --> I
    I --> M{オーナーシップOK?}
    M -->|No| D
    M -->|Yes| N["return pressed"]
    D --> O[終了]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 初回押下検出 | DownDuration == 0の場合に初回押下として検出 | 常時 |
| BR-002 | リピート動作 | repeat=trueの場合、リピート遅延後にリピートレートで繰り返し | repeat引数がtrue |
| BR-003 | デフォルトリピート | レガシーIsKeyPressedはデフォルトでrepeat=true | 常時 |
| BR-004 | Shortcut推奨 | フォーカスルーティングが必要な場合はShortcut()を推奨 | ショートカット実装時 |

### 計算ロジック

```cpp
bool ImGui::IsKeyPressed(ImGuiKey key, bool repeat)
{
    return IsKeyPressed(key, repeat ? ImGuiInputFlags_Repeat : ImGuiInputFlags_None, ImGuiKeyOwner_Any);
}

bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiInputFlags flags, ImGuiID owner_id)
{
    const ImGuiKeyData* key_data = GetKeyData(key);
    if (!key_data->Down)
        return false;
    const float t = key_data->DownDuration;
    if (t < 0.0f)
        return false;

    bool pressed = (t == 0.0f);
    if (!pressed && (flags & ImGuiInputFlags_Repeat) != 0)
    {
        float repeat_delay, repeat_rate;
        GetTypematicRepeatRate(flags, &repeat_delay, &repeat_rate);
        pressed = (t > repeat_delay) && GetKeyPressedAmount(key, repeat_delay, repeat_rate) > 0;
    }

    if (!TestKeyOwner(key, owner_id))
        return false;
    return pressed;
}
```

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| なし | - | 本関数はエラーを発生させない | - |

### リトライ仕様

なし

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

該当なし

## パフォーマンス要件

- O(1)の時間計算量
- メモリアロケーションなし
- フレーム毎に複数回呼び出しても問題ない軽量関数

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

特になし

## 備考

- IsKeyDownとは異なり、キーが押された瞬間（+リピート）のみtrueを返す
- Shortcut()関数の方がより高機能で推奨される場合がある（フォーカスルーティング対応）
- ImGuiInputFlags_Repeatフラグで拡張的なリピート制御が可能（内部API）

---

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

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

### 推奨読解順序

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

まず、キー入力に関するデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | ImGuiKey列挙型（1551-1660行目付近）- キー識別子 |
| 1-2 | imgui.h | `imgui.h` | ImGuiKeyData構造体（2382-2390行目付近）- DownDurationメンバー |
| 1-3 | imgui.h | `imgui.h` | ImGuiInputFlags_（1680-1685行目付近）- リピートフラグ |

**読解のコツ**: ImGuiKeyDataのDownDurationは、キーが押されてからの経過時間を秒単位で保持。0.0fは押された瞬間、負の値はキーが押されていないことを示す。

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

IsKeyPressed関数のAPI宣言と実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui.h | `imgui.h` | 関数宣言（1059行目） |
| 2-2 | imgui.cpp | `imgui.cpp` | 関数実装（9755-9793行目） |

**主要処理フロー**:
1. **9755-9758行目**: 公開API（repeat引数をフラグに変換）
2. **9761-9793行目**: 内部API（フラグベースの処理）
3. **9773行目**: 初回押下判定（t == 0.0f）
4. **9774-9778行目**: リピート判定

#### Step 3: リピート関連関数を理解する

リピートレート取得とリピート回数計算を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui.cpp | `imgui.cpp` | GetTypematicRepeatRate関数 |
| 3-2 | imgui.cpp | `imgui.cpp` | GetKeyPressedAmount関数 |

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

```
ImGui::IsKeyPressed(ImGuiKey, bool)
    │
    └─ ImGui::IsKeyPressed(ImGuiKey, ImGuiInputFlags, ImGuiID)
           │
           ├─ GetKeyData(key)
           │      └─ ImGuiKeyData* 取得
           │
           ├─ GetTypematicRepeatRate(flags, ...)
           │      └─ リピート遅延・レート取得
           │
           ├─ GetKeyPressedAmount(key, delay, rate)
           │      └─ リピート回数計算
           │
           └─ TestKeyOwner(key, owner_id)
                  └─ キーオーナーシップ確認
```

### データフロー図

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

ImGuiKey      ───▶ GetKeyData() ───┐
                        │          │
                        ▼          │
              DownDuration確認 ────┤
                        │          │
                        ▼          │
repeat=true ──▶ GetKeyPressedAmount ─┤
                        │          │
                        ▼          │
              TestKeyOwner() ──────┴─▶ bool (true/false)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | 関数宣言、ImGuiKey列挙型、ImGuiKeyData構造体 |
| imgui.cpp | `imgui.cpp` | ソース | IsKeyPressed関数実装 |
| imgui_demo.cpp | `imgui_demo.cpp` | デモ | 使用例（488行目、2640行目） |
