# 通知設計書 19-onStart

## 概要

本ドキュメントは、Three.jsのLoadingManagerにおける `onStart` コールバック通知の設計を記述する。このコールバックは、LoadingManagerでアイテムの読み込みが開始された際に呼び出される。

### 本通知の処理概要

この通知は、LoadingManagerが最初のアイテムの読み込みを開始した際に、登録されたonStartコールバック関数を呼び出すシステムである。

**業務上の目的・背景**：3Dアプリケーションでは、モデル、テクスチャ、サウンドなど多数のリソースを読み込む必要がある。onStartコールバックは、読み込み処理が開始されたことをアプリケーションに通知し、ローディング画面の表示、プログレスバーの初期化、ユーザーへのフィードバック開始などのトリガーとして使用される。これにより、ユーザーエクスペリエンスを向上させることができる。

**通知の送信タイミング**：LoadingManager.itemStart()メソッドが呼び出され、かつisLoading=falseの状態（まだ読み込みが開始されていない状態）の場合に発火する。つまり、読み込みセッションの最初のアイテムが開始された時点でのみ呼び出される。

**通知の受信者**：LoadingManagerインスタンスのonStartプロパティに設定されたコールバック関数。

**通知内容の概要**：コールバックには以下の引数が渡される：url（読み込み開始したアイテムのURL）、itemsLoaded（現在読み込み完了したアイテム数）、itemsTotal（読み込み対象の総アイテム数）。

**期待されるアクション**：受信者はコールバックを受け取った後、ローディングUIの表示開始、プログレスバーの初期化、読み込み開始のログ出力などの処理を実行することが期待される。

## 通知種別

コールバック通知（関数呼び出し）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 中 |
| リトライ | なし |

### 送信先決定ロジック

LoadingManagerインスタンスのonStartプロパティにコールバック関数が設定されている場合にのみ呼び出される。undefinedの場合は何も実行されない。

## 通知テンプレート

### コールバック形式

```javascript
onStart(url, itemsLoaded, itemsTotal)
```

### コールバック登録例

```javascript
const manager = new THREE.LoadingManager();
manager.onStart = function(url, itemsLoaded, itemsTotal) {
  console.log('Started loading:', url);
  console.log('Items loaded:', itemsLoaded, '/', itemsTotal);
  showLoadingScreen();
};
```

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| url | 読み込み開始したアイテムのURL | itemStart()の引数 | Yes |
| itemsLoaded | 現在読み込み完了したアイテム数 | 内部変数itemsLoaded | Yes |
| itemsTotal | 読み込み対象の総アイテム数 | 内部変数itemsTotal | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 内部処理 | LoadingManager.itemStart()呼び出し | isLoading === false かつ onStart !== undefined | 読み込みセッション開始時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| isLoading === true | 既に読み込みが進行中の場合、onStartは呼び出されない |
| onStart === undefined | コールバックが設定されていない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[itemStart呼び出し] --> B[itemsTotal++]
    B --> C{isLoading === false?}
    C -->|No| D[isLoading = true]
    C -->|Yes| E{onStart !== undefined?}
    E -->|No| D
    E -->|Yes| F[onStart呼び出し]
    F --> G["onStart(url, itemsLoaded, itemsTotal)"]
    G --> D
    D --> H[終了]
```

## データベース参照・更新仕様

本通知はデータベースを使用しない。すべての状態はメモリ上の変数で管理される。

### 参照・更新変数一覧

| 変数名 | 用途 | 備考 |
|--------|------|------|
| isLoading | 読み込み中フラグ | 読み込み開始時にtrueに設定 |
| itemsLoaded | 読み込み完了アイテム数 | 0から開始 |
| itemsTotal | 総アイテム数 | itemStart()呼び出しごとにインクリメント |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| コールバック内例外 | onStartコールバック内で例外発生 | 例外は呼び出し元に伝播し、読み込み処理に影響する可能性がある |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし。読み込み開始時に発火。

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

- URLには機密情報が含まれる可能性があるため、ログ出力時は注意
- onStartコールバックはアプリケーションコードで設定されるため、信頼されたコードのみが実行される

## 備考

- onStartはコンストラクタでは設定できない（GitHub issue #5689 参照）
- 読み込みセッション中に新しいアイテムが追加されても、onStartは最初の1回しか呼び出されない
- すべてのアイテムが読み込み完了すると、isLoadingがfalseに戻り、次の読み込みセッションでonStartが再度呼び出し可能になる

---

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

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

### 推奨読解順序

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

まず、LoadingManagerの状態管理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | LoadingManager.js | `src/loaders/LoadingManager.js` | isLoading, itemsLoaded, itemsTotal変数（31-33行目） |
| 1-2 | LoadingManager.js | `src/loaders/LoadingManager.js` | onStartプロパティ（46行目） |

**読解のコツ**: LoadingManagerはクロージャを使用して状態を管理している。isLoading, itemsLoaded, itemsTotalはコンストラクタ内のローカル変数として定義され、itemStart/itemEnd/itemErrorメソッドからアクセスされる。

#### Step 2: itemStartメソッドを理解する

onStartコールバックが呼び出されるロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | LoadingManager.js | `src/loaders/LoadingManager.js` | itemStart()メソッド（86-102行目） |

**主要処理フロー**:
- **88行目**: itemsTotal++（アイテム総数をインクリメント）
- **90行目**: isLoading === false のチェック
- **92-96行目**: onStartが設定されている場合にコールバック呼び出し
- **100行目**: isLoading = true に設定

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

```
Loader.load(url, ...)
    |
    +-- LoadingManager.itemStart(url)
           |
           +-- itemsTotal++
           |
           +-- [isLoading === false の場合]
           |      |
           |      +-- [onStart !== undefined の場合]
           |             |
           |             +-- onStart(url, itemsLoaded, itemsTotal)
           |
           +-- isLoading = true
```

### データフロー図

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

url ─────────────> itemStart() ─────────────> onStartコールバック
                       |                           |
                       v                           v
                 [状態更新]              onStart(url, 0, 1)
                 itemsTotal++                      |
                 isLoading = true                  v
                                          ローディングUI表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| LoadingManager.js | `src/loaders/LoadingManager.js` | ソース | LoadingManagerの実装 |
| Loader.js | `src/loaders/Loader.js` | ソース | ローダーの基底クラス |
| FileLoader.js | `src/loaders/FileLoader.js` | ソース | ファイル読み込みローダー（itemStartを呼び出す） |
| TextureLoader.js | `src/loaders/TextureLoader.js` | ソース | テクスチャ読み込みローダー |
