# 機能設計書 169-Controls

## 概要

本ドキュメントは、Three.jsライブラリにおけるControls機能の設計仕様を記述する。Controlsは、カメラやオブジェクトのインタラクティブな制御を提供するための抽象基底クラスである。

### 本機能の処理概要

Controlsクラスは、EventDispatcherを継承し、カメラコントロールの共通インターフェースを定義する。マウス、タッチ、キーボード入力に応答してオブジェクト（通常はカメラ）を操作するための基盤を提供し、OrbitControls、TrackballControls、FlyControlsなどの派生クラスの共通機能を実装する。

**業務上の目的・背景**：3Dアプリケーションにおいて、ユーザーがシーンを自由に操作できることは重要な機能である。カメラの回転、パン、ズームなどのインタラクションを統一されたインターフェースで提供することで、一貫したユーザー体験と開発効率の向上を実現する。

**機能の利用シーン**：
- 3Dビューアーでのカメラ操作
- エディタでのオブジェクト操作
- VR/ARコントローラー入力
- ゲームのキャラクター移動

**主要な処理内容**：
1. object - 制御対象オブジェクト（通常カメラ）の管理
2. domElement - イベントリスナー用DOM要素
3. enabled - コントロールの有効/無効切り替え
4. state - 内部状態管理
5. keys - キーボード入力設定
6. mouseButtons / touches - マウス/タッチ入力設定
7. connect() / disconnect() - DOM接続/切断
8. update() - フレーム更新

**関連システム・外部連携**：Camera、EventDispatcher、DOM Events、各種コントロール派生クラスと連携。

**権限による制御**：特になし。すべてのユーザーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 31 | その他サンプル | 主機能 | カメラコントロールの実装 |

## 機能種別

ユーザーインタラクション / イベント処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| object | Object3D | Yes | 制御対象オブジェクト | 有効なObject3D |
| domElement | HTMLElement | No | イベントリスナー用DOM要素（デフォルト: null） | 有効なHTMLElement |
| delta | number | No | 更新時のデルタタイム（秒） | 正の数値 |

### 入力データソース

DOM イベント（mousedown, mousemove, mouseup, wheel, keydown, touchstart, touchmove, touchend）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| イベント | Event | change, start, endイベント |
| object.position | Vector3 | 更新されたオブジェクト位置 |
| object.rotation | Euler | 更新されたオブジェクト回転 |

### 出力先

制御対象オブジェクトのtransformプロパティに反映。EventDispatcher経由でイベント発行。

## 処理フロー

### 処理シーケンス

```
1. Controlsインスタンス生成
   └─ object, domElementを保存
   └─ enabled, state, keys等を初期化
2. connect(element)呼び出し
   └─ 既存の接続を切断
   └─ DOM要素にイベントリスナーを追加
3. ユーザー入力
   └─ イベントハンドラが呼び出される
   └─ 内部状態を更新
4. update(delta)呼び出し（毎フレーム）
   └─ 入力に基づいてオブジェクトを更新
5. disconnect()呼び出し
   └─ イベントリスナーを削除
6. dispose()呼び出し
   └─ リソースを解放
```

### フローチャート

```mermaid
flowchart TD
    A[Controls生成] --> B[プロパティ初期化]
    B --> C[connect呼び出し]
    C --> D{既存接続あり?}
    D -->|Yes| E[disconnect]
    D -->|No| F[イベントリスナー追加]
    E --> F
    F --> G[ユーザー入力待機]
    G --> H{入力あり?}
    H -->|Yes| I[イベントハンドラ実行]
    I --> J[状態更新]
    J --> G
    H -->|update| K[オブジェクト更新]
    K --> G
    G --> L{終了?}
    L -->|Yes| M[disconnect]
    M --> N[dispose]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 有効状態 | enabled=falseの場合は入力を無視 | 常時 |
| BR-002 | 状態管理 | stateで内部状態を追跡（-1=NONE） | 常時 |
| BR-003 | 接続管理 | connect()前にdisconnect()を呼び出し | connect() |
| BR-004 | DOM要素必須 | connect()にはelement引数が必要（警告あり） | connect() |

### 計算ロジック

派生クラスで実装。Controlsクラスは抽象メソッドのみ定義。

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

該当なし（クライアントサイドのインタラクション機能）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Warning | connect()にelement引数がない | elementを渡す |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- update()は毎フレーム呼び出されるため、軽量な実装が必要
- イベントハンドラは高頻度で呼び出されるため、効率的な処理が必要

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

特になし

## 備考

- 抽象基底クラスのため、直接使用することは想定されていない
- 派生クラス: OrbitControls, TrackballControls, FlyControls, FirstPersonControls, PointerLockControls, DragControls等

---

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

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

### 推奨読解順序

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

ControlsはEventDispatcherを継承し、制御対象オブジェクトとDOM要素を保持する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Controls.js | `src/extras/Controls.js` | クラス定義とプロパティ構造（10-76行目） |

**読解のコツ**: object（制御対象）、domElement（イベント元）、enabled（有効状態）、state（内部状態）が主要プロパティ。keys、mouseButtons、touchesで入力マッピングを定義。

#### Step 2: コンストラクタを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Controls.js | `src/extras/Controls.js` | constructor (18-76行目) |

**主要処理フロー**:
1. **20行目**: super()でEventDispatcherを初期化
2. **28行目**: this.objectに制御対象を保存
3. **35行目**: this.domElementにDOM要素を保存（デフォルトnull）
4. **43行目**: this.enabled = true（デフォルト有効）
5. **51行目**: this.state = -1（NONE状態）
6. **58行目**: this.keys = {}（キーボード設定）
7. **65行目**: this.mouseButtons = { LEFT: null, MIDDLE: null, RIGHT: null }
8. **74行目**: this.touches = { ONE: null, TWO: null }

#### Step 3: 接続・切断メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Controls.js | `src/extras/Controls.js` | connect (84-97行目) |
| 3-2 | Controls.js | `src/extras/Controls.js` | disconnect (102行目) |
| 3-3 | Controls.js | `src/extras/Controls.js` | dispose (108行目) |

**主要処理フロー**:
- **86-89行目**: element未定義の場合は警告を出して終了
- **93行目**: 既存接続があればdisconnect()
- **95行目**: domElementを更新
- **102行目**: disconnect()は空の抽象メソッド
- **108行目**: dispose()は空の抽象メソッド

#### Step 4: 更新メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Controls.js | `src/extras/Controls.js` | update (116行目) |

**主要処理フロー**:
- **116行目**: update()は空の抽象メソッド（派生クラスで実装）

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

```
Controls extends EventDispatcher
    │
    ├─ constructor(object, domElement)
    │      ├─ super()
    │      ├─ object, domElement保存
    │      └─ enabled, state, keys, mouseButtons, touches初期化
    │
    ├─ connect(element)
    │      ├─ 引数チェック（警告）
    │      ├─ disconnect()
    │      └─ domElement更新
    │
    ├─ disconnect() [抽象]
    │      └─ 派生クラスで実装
    │
    ├─ dispose() [抽象]
    │      └─ 派生クラスで実装
    │
    └─ update(delta) [抽象]
           └─ 派生クラスで実装
```

### データフロー図

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

DOM Events ────────────▶ イベントハンドラ ────────────▶ state更新
  (mouse, touch, key)      └─ 派生クラス実装

delta (number) ─────────▶ update() ────────────────────▶ object transform
                           └─ 派生クラス実装              (position, rotation)

connect/disconnect ─────▶ DOM接続管理 ─────────────────▶ イベントリスナー
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Controls.js | `src/extras/Controls.js` | ソース | 本機能のメイン実装（抽象基底クラス） |
| EventDispatcher.js | `src/core/EventDispatcher.js` | ソース | 基底クラス（イベント管理） |
| OrbitControls.js | `examples/jsm/controls/OrbitControls.js` | サンプル | 軌道カメラコントロール |
| TrackballControls.js | `examples/jsm/controls/TrackballControls.js` | サンプル | トラックボールコントロール |
| FlyControls.js | `examples/jsm/controls/FlyControls.js` | サンプル | 飛行コントロール |
| FirstPersonControls.js | `examples/jsm/controls/FirstPersonControls.js` | サンプル | 一人称コントロール |
| PointerLockControls.js | `examples/jsm/controls/PointerLockControls.js` | サンプル | ポインターロックコントロール |
| DragControls.js | `examples/jsm/controls/DragControls.js` | サンプル | ドラッグコントロール |
| TransformControls.js | `examples/jsm/controls/TransformControls.js` | サンプル | 変形コントロール |
