# 機能設計書 111-DragScalar

## 概要

本ドキュメントは、Dear ImGuiライブラリにおける汎用スカラードラッグスライダー機能「DragScalar」の設計を詳細に記述したものである。

### 本機能の処理概要

DragScalarは、任意のデータ型（8/16/32/64ビットの整数・符号なし整数、単精度・倍精度浮動小数点数）に対応した汎用ドラッグスライダーウィジェットを作成する機能である。マウスドラッグによる直感的な値の調整と、Ctrl+クリックによるキーボード入力モードへの切り替えを提供する。

**業務上の目的・背景**：ゲーム開発やツール開発において、数値パラメータの調整は頻繁に行われる作業である。DragScalarは、データ型に依存しない汎用的な数値調整インターフェースを提供し、開発者が任意のスカラー型の値を効率的に編集できるようにする。DragFloat/DragIntなどの型固有のドラッグウィジェットは内部でこの関数を呼び出しており、コア実装の中心となる重要な機能である。

**機能の利用シーン**：
- カスタムデータ型（8ビット/16ビット整数など）の数値パラメータを編集するとき
- 汎用的なプロパティエディタを実装する際に、型情報に基づいて動的にウィジェットを生成するとき
- DragFloat/DragIntなどの高レベルAPIの代わりに、より細かい制御が必要なとき

**主要な処理内容**：
1. ウィンドウとスタイルの取得、ウィジェットIDの生成
2. フレーム領域とラベル領域の計算
3. マウスホバーとクリック検出によるアクティブ状態の制御
4. Ctrl+クリックまたはダブルクリックでテキスト入力モードへ切り替え
5. DragBehavior関数によるドラッグ操作の処理
6. フレームとテキストの描画、値の表示

**関連システム・外部連携**：本機能は単体で動作し、外部システムとの直接的な連携はない。内部的にTempInputScalar（テキスト入力モード）やDragBehavior（ドラッグ動作）と連携する。

**権限による制御**：ImGuiItemFlags_ReadOnlyフラグまたはImGuiSliderFlags_ReadOnlyフラグにより読み取り専用モードを設定可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | Widgets | 主画面 | DragScalarを内部的に使用するウィジェットのデモ表示 |

## 機能種別

インタラクティブウィジェット / ユーザー入力処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | const char* | Yes | ウィジェットのラベル（ID生成にも使用） | NULL不可 |
| data_type | ImGuiDataType | Yes | データ型の指定（S8/U8/S16/U16/S32/U32/S64/U64/Float/Double） | 有効な列挙値 |
| p_data | void* | Yes | 編集対象の値へのポインタ | NULL不可 |
| v_speed | float | No | ドラッグ速度（デフォルト: 1.0f） | 任意 |
| p_min | const void* | No | 最小値へのポインタ（NULL可） | data_typeに対応した型 |
| p_max | const void* | No | 最大値へのポインタ（NULL可） | data_typeに対応した型 |
| format | const char* | No | 表示フォーマット文字列（NULL時はデータ型のデフォルト） | printf形式 |
| flags | ImGuiSliderFlags | No | 動作制御フラグ（デフォルト: 0） | 有効なフラグの組み合わせ |

### 入力データソース

ユーザーからのマウス操作（ドラッグ）およびキーボード入力（テキスト入力モード時）。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | 値が変更された場合true |
| *p_data | void* | 更新されたスカラー値（p_dataが指す領域） |

### 出力先

呼び出し元への戻り値、およびp_dataが指すメモリ領域への値の書き込み。

## 処理フロー

### 処理シーケンス

```
1. ウィンドウ取得とスキップ判定
   └─ window->SkipItemsがtrueの場合は即座にfalseを返却
2. コンテキストとスタイルの取得
   └─ ImGuiContext、ImGuiStyleへの参照を取得
3. IDの生成と領域計算
   └─ labelからIDを生成し、フレーム領域・トータル領域を計算
4. ItemSizeとItemAddの呼び出し
   └─ レイアウトシステムにウィジェットを登録
5. デフォルトフォーマット文字列の設定
   └─ formatがNULLの場合、データ型に応じたデフォルトフォーマットを使用
6. ホバー・クリック検出とアクティブ状態制御
   └─ マウス操作に応じてアクティブIDを設定
7. テキスト入力モードの判定と処理
   └─ Ctrl+クリックまたはダブルクリックでTempInputScalarを呼び出し
8. フレームの描画
   └─ 背景色、ナビゲーションカーソル、ボーダーを描画
9. DragBehaviorの呼び出し
   └─ ドラッグ操作による値の更新処理
10. 値の表示
    └─ フォーマットに従って値をテキストとして描画
11. ラベルの描画
    └─ ラベルテキストを描画して処理完了
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{window->SkipItems?}
    B -->|Yes| C[return false]
    B -->|No| D[ID生成と領域計算]
    D --> E[ItemSize/ItemAdd]
    E --> F{ItemAdd成功?}
    F -->|No| C
    F -->|Yes| G[ホバー・クリック検出]
    G --> H{テキスト入力モード?}
    H -->|Yes| I[TempInputScalar]
    I --> J[return 結果]
    H -->|No| K[フレーム描画]
    K --> L[DragBehavior]
    L --> M{値が変更?}
    M -->|Yes| N[MarkItemEdited]
    M -->|No| O[値の表示]
    N --> O
    O --> P[ラベル描画]
    P --> Q[return value_changed]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-111-1 | 範囲制限 | p_minとp_maxが指定された場合、値はその範囲内にクランプされる | AlwaysClampフラグ設定時、または境界値到達時 |
| BR-111-2 | 速度調整 | Altキー押下で1/100倍、Shiftキー押下で10倍の速度調整 | ドラッグ中、NoSpeedTweaksフラグ未設定時 |
| BR-111-3 | ラップアラウンド | WrapAroundフラグ設定時、最大値を超えると最小値に戻る | is_bounded && WrapAroundフラグ設定時 |
| BR-111-4 | 対数スケール | Logarithmicフラグ設定時、対数スケールで値を調整 | Logarithmicフラグ設定時 |

### 計算ロジック

ドラッグ動作による値の変更は以下の式で計算される：

```
adjust_delta = mouse_delta * v_speed * modifier
  - modifier: Alt押下時 = 0.01, Shift押下時 = 10.0, 通常 = 1.0

対数モード時:
  v_new = ScaleValueFromRatio(current_ratio + adjust_delta)

線形モード時:
  v_new = v_current + adjust_delta
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | アサーション | 無効なImGuiSliderFlagsが渡された場合 | 正しいフラグ値を使用する |
| - | アサーション | data_typeがImGuiDataType_COUNTの場合 | 有効なデータ型を指定する |

### リトライ仕様

本機能はユーザー入力ウィジェットであり、リトライは適用されない。

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

本機能はトランザクション処理を行わない。

## パフォーマンス要件

フレームごとに呼び出されるため、軽量な処理が求められる。実装はテンプレート関数を使用して型ごとに最適化されている。

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

- ユーザー入力をそのまま処理するため、format文字列の検証は呼び出し側の責任
- バッファオーバーフロー対策として内部バッファサイズは64バイトに制限

## 備考

- DragFloat、DragInt等の高レベルAPIは内部でDragScalarを呼び出している
- DragScalarNは複数コンポーネント版で、内部でDragScalarを繰り返し呼び出す

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | ImGuiDataType列挙型とImGuiSliderFlags列挙型の定義を確認 |
| 1-2 | imgui_internal.h | `imgui_internal.h` | ImGuiDataTypeInfo構造体とGDataTypeInfo配列を確認 |

**読解のコツ**: ImGuiDataTypeは対応するデータ型を識別する列挙型であり、各型のサイズやデフォルトフォーマット文字列はGDataTypeInfo配列で管理されている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | DragScalar関数の実装（2685-2786行目） |

**主要処理フロー**:
1. **2687-2689行目**: ウィンドウ取得とスキップ判定
2. **2691-2699行目**: コンテキスト、スタイル取得とID生成、領域計算
3. **2701-2704行目**: ItemSizeとItemAddによるレイアウト登録
4. **2710-2744行目**: ホバー・クリック検出とアクティブ状態制御
5. **2746-2758行目**: テキスト入力モードの処理
6. **2761-2767行目**: フレームの描画
7. **2769-2772行目**: DragBehavior呼び出しと編集マーク
8. **2774-2782行目**: 値とラベルの表示

#### Step 3: ドラッグ動作処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | DragBehavior関数（2646-2681行目） |
| 3-2 | imgui_widgets.cpp | `imgui_widgets.cpp` | DragBehaviorTテンプレート関数（2515-2644行目） |

**主要処理フロー**:
- **2519-2523行目**: 軸の決定、境界・ラップ・対数モードの判定
- **2531-2548行目**: マウス/キーボード入力からの調整デルタ計算
- **2562-2571行目**: 累積値の管理と更新
- **2598-2600行目**: フォーマットに基づく丸め処理
- **2619-2637行目**: 境界クランプまたはラップアラウンド処理

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

```
DragScalar (imgui_widgets.cpp:2685)
    │
    ├─ GetCurrentWindow()
    ├─ CalcTextSize()
    ├─ ItemSize() / ItemAdd()
    ├─ ItemHoverable()
    │
    ├─ TempInputScalar() [テキスト入力モード時]
    │      └─ TempInputText()
    │             └─ InputTextEx()
    │
    ├─ RenderNavCursor() / RenderFrame() / RenderFrameBorder()
    │
    └─ DragBehavior (imgui_widgets.cpp:2646)
           └─ DragBehaviorT<TYPE> (imgui_widgets.cpp:2515)
                  ├─ ScaleRatioFromValueT() [対数モード時]
                  ├─ ScaleValueFromRatioT() [対数モード時]
                  └─ RoundScalarWithFormatT()
```

### データフロー図

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

p_data (値へのポインタ)
       │
       ▼
マウスドラッグ ────────▶ DragBehavior ────────▶ 更新された値 (*p_data)
       │                     │
       │                     ▼
Ctrl+Click ──────────▶ TempInputScalar ────▶ テキスト入力による値
       │
       ▼
flags/format ─────────▶ 描画処理 ──────────▶ 画面表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | API宣言、ImGuiDataType/ImGuiSliderFlags定義 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | 内部構造体・関数宣言、GDataTypeInfo定義 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | DragScalar/DragBehavior/DragBehaviorTの実装 |
