# 機能設計書 110-DragInt2/3/4

## 概要

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

### 本機能の処理概要

`DragInt2`、`DragInt3`、`DragInt4`関数は、それぞれ2、3、4要素の整数配列を同時に編集できるドラッグスライダーウィジェットを作成する関数群である。`DragFloat2/3/4`の整数版として、各要素は横に並んで表示され、個別にドラッグ操作が可能である。ベクトル値（2D/3D座標、色チャンネルなど）の整数表現の編集に特に有用で、複数の関連する整数値を一括で表示・編集できる。

**業務上の目的・背景**：ゲーム開発やグラフィックスアプリケーションでは、ピクセル座標(X,Y)、解像度(幅,高さ)、グリッドサイズ(X,Y,Z)、色値(R,G,B,A)など、複数の整数要素を持つデータの編集が頻繁に発生する。これらの値を個別のDragIntで編集すると画面スペースを消費し、関連性も分かりにくくなる。DragIntN関数群は、これらの複合整数値を効率的に表示・編集するためのソリューションを提供する。

**機能の利用シーン**：
- 画像解像度（幅、高さ）の設定
- ピクセル座標の編集
- グリッドサイズの設定（X, Y, Z）
- 8ビット色チャンネル値の編集（0-255）
- タイルマップのセルサイズ設定
- ウィンドウサイズ・位置の設定

**主要な処理内容**：
1. ラベルからIDを生成しグループを開始
2. 各要素の幅を計算（PushMultiItemsWidths）
3. 要素数分のループを実行
4. 各要素でDragScalarを呼び出し（ImGuiDataType_S32）
5. 要素間にItemInnerSpacing分のスペースを挿入
6. ラベルを表示
7. グループを終了して戻り値を返す

**関連システム・外部連携**：
- DragScalarN: 汎用マルチ要素ドラッグ（内部呼び出し）
- DragScalar: 単一要素のドラッグ処理
- スタイルシステム: ItemInnerSpacing

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 23 | Widgets | 主機能 | マルチ要素整数ドラッグスライダーのデモ |

## 機能種別

ウィジェット描画処理 / 入力処理

## 入力仕様

### 入力パラメータ（DragInt2）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | const char* | Yes | ウィジェットのラベル | NULL不可 |
| v | int[2] | Yes | 編集対象の2要素配列 | 有効な配列 |
| v_speed | float | No | ドラッグ速度係数（デフォルト: 1.0f） | 正の値推奨 |
| v_min | int | No | 最小値（デフォルト: 0） | v_min >= v_maxで無制限 |
| v_max | int | No | 最大値（デフォルト: 0） | v_min >= v_maxで無制限 |
| format | const char* | No | 表示フォーマット（デフォルト: "%d"） | printf形式 |
| flags | ImGuiSliderFlags | No | スライダーフラグ（デフォルト: 0） | 有効なフラグ |

### 入力パラメータ（DragInt3）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | const char* | Yes | ウィジェットのラベル | NULL不可 |
| v | int[3] | Yes | 編集対象の3要素配列 | 有効な配列 |
| v_speed | float | No | ドラッグ速度係数（デフォルト: 1.0f） | 正の値推奨 |
| v_min | int | No | 最小値（デフォルト: 0） | v_min >= v_maxで無制限 |
| v_max | int | No | 最大値（デフォルト: 0） | v_min >= v_maxで無制限 |
| format | const char* | No | 表示フォーマット（デフォルト: "%d"） | printf形式 |
| flags | ImGuiSliderFlags | No | スライダーフラグ（デフォルト: 0） | 有効なフラグ |

### 入力パラメータ（DragInt4）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| label | const char* | Yes | ウィジェットのラベル | NULL不可 |
| v | int[4] | Yes | 編集対象の4要素配列 | 有効な配列 |
| v_speed | float | No | ドラッグ速度係数（デフォルト: 1.0f） | 正の値推奨 |
| v_min | int | No | 最小値（デフォルト: 0） | v_min >= v_maxで無制限 |
| v_max | int | No | 最大値（デフォルト: 0） | v_min >= v_maxで無制限 |
| format | const char* | No | 表示フォーマット（デフォルト: "%d"） | printf形式 |
| flags | ImGuiSliderFlags | No | スライダーフラグ（デフォルト: 0） | 有効なフラグ |

### 入力データソース

- ユーザー指定のパラメータ（関数引数）
- マウス入力（各要素へのドラッグ）
- キーボード入力（Ctrl、テキスト入力モード時）
- ImGuiスタイル設定（ItemInnerSpacing）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | bool | いずれかの値が変更された場合true |
| v | int[N] | 変更後の値配列（変更時に更新） |

### 出力先

- vパラメータ（配列値の更新）
- ImDrawList（描画コマンドリスト）

## 処理フロー

### 処理シーケンス

```
1. DragScalarN呼び出し
   └─ DragInt2/3/4 は DragScalarN のラッパー
   └─ データ型: ImGuiDataType_S32
2. DragScalarN内処理:
   2-1. ウィンドウ・スキップ確認
   2-2. グループ開始（BeginGroup）
   2-3. ラベルIDをプッシュ（PushID）
   2-4. 各要素の幅を計算（PushMultiItemsWidths）
   2-5. 要素ループ
        └─ 要素IDをプッシュ
        └─ 2番目以降はSameLineでスペース追加
        └─ ColorMarkersフラグ時はマーカー設定
        └─ DragScalarを呼び出し
        └─ 要素IDをポップ
        └─ 幅をポップ
        └─ データポインタを進める（sizeof(int) = 4バイト）
   2-6. ラベルIDをポップ
   2-7. ラベルテキストを表示
   2-8. グループ終了（EndGroup）
3. 戻り値を返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[DragScalarN呼び出し]
    B --> C{SkipItems?}
    C -->|Yes| D[return false]
    C -->|No| E[BeginGroup]
    E --> F[PushID label]
    F --> G[PushMultiItemsWidths]
    G --> H[i = 0]
    H --> I{i < components?}
    I -->|No| J[PopID]
    I -->|Yes| K[PushID i]
    K --> L{i > 0?}
    L -->|Yes| M[SameLine]
    L -->|No| N{ColorMarkers?}
    M --> N
    N -->|Yes| O[SetNextItemColorMarker]
    N -->|No| P[DragScalar S32]
    O --> P
    P --> Q[PopID, PopItemWidth]
    Q --> R[p_data += sizeof int]
    R --> S[i++]
    S --> I
    J --> T[ラベル表示]
    T --> U[EndGroup]
    U --> V[return value_changed]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-110-1 | 均等幅配置 | 各要素は利用可能な幅を均等に分割 | 常時 |
| BR-110-2 | 要素間スペース | ItemInnerSpacing.xで要素を区切る | 常時 |
| BR-110-3 | カラーマーカー | ColorMarkersフラグで各要素に色マーカー表示 | フラグ設定時 |
| BR-110-4 | OR結合 | いずれかの要素が変更された場合trueを返す | 常時 |
| BR-110-5 | 整数型処理 | ImGuiDataType_S32として処理 | 常時 |

### 計算ロジック

要素幅計算:
```cpp
// PushMultiItemsWidths(components, CalcItemWidth())
total_width = CalcItemWidth()
inner_spacing = (components - 1) * ItemInnerSpacing.x
element_width = (total_width - inner_spacing) / components
```

データポインタ進行:
```cpp
// 各要素処理後
p_data = (void*)((char*)p_data + type_size)
// type_size = sizeof(int) = 4
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 描画スキップ | window->SkipItemsがtrue | falseを返して終了 |

### リトライ仕様

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

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

該当なし

## パフォーマンス要件

- 単一フレーム内で複数呼び出し可能
- 各要素のDragScalarが個別に処理される

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

- 特になし（GUI描画機能のため）

## 備考

- DragInt2/3/4はDragScalarNのラッパー関数
- 配列引数は連続したメモリ領域を想定
- ColorMarkersフラグでR/G/B/A色マーカーを表示可能（主に色値編集用）
- 各要素は独立して編集可能
- DragFloat2/3/4と同様のインターフェースを持つ

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | imgui.h | `imgui.h` | 683-685行目: DragInt2/3/4関数の宣言 |
| 1-2 | imgui_widgets.cpp | `imgui_widgets.cpp` | 2884-2897行目: DragInt2/3/4関数の実装 |

**主要処理フロー**:
- **2886行目**: DragInt2 → DragScalarN(S32, components=2)
- **2891行目**: DragInt3 → DragScalarN(S32, components=3)
- **2896行目**: DragInt4 → DragScalarN(S32, components=4)

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

DragScalarNの詳細な処理を追跡する（DragFloat2/3/4と共通）。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | imgui_widgets.cpp | `imgui_widgets.cpp` | 2788-2823行目: DragScalarN実装 |

**読解のコツ**:
- DragInt2/3/4とDragFloat2/3/4はDragScalarNを共有
- 違いはデータ型（S32 vs Float）とデフォルトフォーマット

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

```
ImGui::DragInt2/3/4()
    │
    └─ ImGui::DragScalarN(data_type = ImGuiDataType_S32)
           │
           ├─ GetCurrentWindow()
           ├─ BeginGroup()
           ├─ PushID(label)
           ├─ PushMultiItemsWidths(components, width)
           │
           ├─ for i in 0..components:
           │      ├─ PushID(i)
           │      ├─ SameLine() ... i > 0の場合
           │      ├─ SetNextItemColorMarker() ... フラグ時
           │      ├─ DragScalar(S32)
           │      │      └─ 単一要素の整数ドラッグ処理
           │      ├─ PopID()
           │      └─ PopItemWidth()
           │
           ├─ PopID()
           ├─ SameLine()
           ├─ TextEx(label)
           └─ EndGroup()
```

### データフロー図

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

label       ───┐
v[N]        ───┼──▶ DragIntN()
v_speed     ───┤         │
v_min/v_max ───┤         ▼
format      ───┤    DragScalarN(S32)
flags       ───┘         │
                         │
                    ┌────┴────┐
                    │ 要素ループ │
                    │  [0] [1] │
                    │  [2] [3] │
                    └────┬────┘
                         │
マウスドラッグ ────────▶ 各DragScalar
                         │
                         ▼
                    v[N]更新 + bool戻り値
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| imgui.h | `imgui.h` | ヘッダー | DragInt2/3/4宣言 |
| imgui_widgets.cpp | `imgui_widgets.cpp` | ソース | DragInt2/3/4, DragScalarN実装 |
| imgui_internal.h | `imgui_internal.h` | ヘッダー | PushMultiItemsWidths等 |
