# 通知設計書 20-onProgress

## 概要

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

### 本通知の処理概要

この通知は、LoadingManagerで管理されているアイテムの読み込みが1つ完了するごとに、登録されたonProgressコールバック関数を呼び出すシステムである。

**業務上の目的・背景**：3Dアプリケーションでは、複数のリソースを読み込む際に進捗状況をユーザーに表示することが重要である。onProgressコールバックは、アイテムごとの読み込み完了を通知し、プログレスバーの更新、読み込み進捗率の計算、ユーザーへのフィードバック更新などのトリガーとして使用される。これにより、ユーザーは読み込み処理の進行状況を視覚的に確認できる。

**通知の送信タイミング**：LoadingManager.itemEnd()メソッドが呼び出された際に発火する。これは各ローダーがアイテムの読み込みを完了した時点で呼び出される。

**通知の受信者**：LoadingManagerインスタンスのonProgressプロパティに設定されたコールバック関数。コンストラクタの第2引数としても設定可能。

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

**期待されるアクション**：受信者はコールバックを受け取った後、プログレスバーの更新、進捗率の表示更新、読み込み完了アイテムのログ出力などの処理を実行することが期待される。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

## 通知テンプレート

### コールバック形式

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

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

```javascript
const manager = new THREE.LoadingManager();
manager.onProgress = function(url, itemsLoaded, itemsTotal) {
  const progress = (itemsLoaded / itemsTotal) * 100;
  console.log('Loading:', url);
  console.log('Progress:', progress.toFixed(2) + '%');
  updateProgressBar(progress);
};

// または、コンストラクタで設定
const manager = new THREE.LoadingManager(
  onLoadComplete,    // onLoad
  function(url, itemsLoaded, itemsTotal) {  // onProgress
    console.log('Progress:', (itemsLoaded / itemsTotal * 100) + '%');
  },
  onError
);
```

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| url | 読み込み完了したアイテムのURL | itemEnd()の引数 | Yes |
| itemsLoaded | 現在読み込み完了したアイテム数 | 内部変数itemsLoaded（インクリメント後） | Yes |
| itemsTotal | 読み込み対象の総アイテム数 | 内部変数itemsTotal | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 内部処理 | LoadingManager.itemEnd()呼び出し | onProgress !== undefined | アイテム読み込み完了時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| onProgress === undefined | コールバックが設定されていない場合 |

## 処理フロー

### 送信フロー

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

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

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

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

| 変数名 | 用途 | 備考 |
|--------|------|------|
| isLoading | 読み込み中フラグ | 全アイテム完了時にfalseに設定 |
| itemsLoaded | 読み込み完了アイテム数 | itemEnd()呼び出しごとにインクリメント |
| itemsTotal | 総アイテム数 | 参照のみ |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| コールバック内例外 | onProgressコールバック内で例外発生 | 例外は呼び出し元に伝播し、後続の処理（onLoad呼び出し等）に影響する可能性がある |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし。アイテム読み込み完了ごとに発火。

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

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

## 備考

- onProgressは各アイテムの完了ごとに呼び出されるため、アイテム数が多い場合は頻繁に呼び出される
- itemsLoaded / itemsTotal で進捗率を計算可能
- 最後のアイテム完了時は、onProgress呼び出し後にonLoadも呼び出される
- onProgressはコンストラクタの第2引数として設定可能

---

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

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

### 推奨読解順序

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

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

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

**読解のコツ**: onProgressはコンストラクタの引数として渡すことも、後からプロパティとして設定することも可能。どちらの場合もthis.onProgressに格納される。

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

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

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

**主要処理フロー**:
- **112行目**: itemsLoaded++（完了アイテム数をインクリメント）
- **114-118行目**: onProgressが設定されている場合にコールバック呼び出し
- **120-122行目**: itemsLoaded === itemsTotal の場合にisLoading = false
- **124-128行目**: 全アイテム完了時にonLoadを呼び出し

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

```
Loader.load(url, ...) 完了時
    |
    +-- LoadingManager.itemEnd(url)
           |
           +-- itemsLoaded++
           |
           +-- [onProgress !== undefined の場合]
           |      |
           |      +-- onProgress(url, itemsLoaded, itemsTotal)
           |
           +-- [itemsLoaded === itemsTotal の場合]
                  |
                  +-- isLoading = false
                  |
                  +-- [onLoad !== undefined の場合]
                         |
                         +-- onLoad()
```

### データフロー図

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

url ─────────────> itemEnd() ─────────────> onProgressコールバック
                       |                           |
                       v                           v
                 [状態更新]              onProgress(url, n, total)
                 itemsLoaded++                     |
                       |                           v
                       v                    プログレスバー更新
              [完了チェック]
                       |
                 ┌─────┴─────┐
                 |           |
                 v           v
              継続中      全完了
                            |
                            v
                       onLoad()
```

### 関連ファイル一覧

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