# 通知設計書 33-NOTIFICATION_LOCAL_TRANSFORM_CHANGED

## 概要

本ドキュメントは、GodotエンジンのCanvasItemクラスにおけるNOTIFICATION_LOCAL_TRANSFORM_CHANGED通知の設計仕様を記載する。この通知はノードのローカル変換（親座標系での位置・回転・スケール）が変更された際に発火され、ノード自身の変換変更を検出するための重要なライフサイクルイベントである。

### 本通知の処理概要

NOTIFICATION_LOCAL_TRANSFORM_CHANGEDは、CanvasItem（2D）またはNode3D（3D）ノードのローカルトランスフォームが変更された際にオプションで発行される通知である。グローバル変換の変更（NOTIFICATION_TRANSFORM_CHANGED）とは異なり、親ノードの変換変更では発火せず、自身の変換プロパティが直接変更された場合のみ発火する。

**業務上の目的・背景**：一部のノードは親の変換変更ではなく、自身の変換が直接変更されたかどうかを知る必要がある。例えば、Bone2D（スケルトンアニメーション）、CollisionShape2D（物理形状）、AnimatableBody2D（補間ボディ）などは、ローカル変換の変更を検出して内部状態を更新する。

**通知の送信タイミング**：set_notify_local_transform(true)が設定されたノードにおいて、position、rotation、scaleなどのローカル変換プロパティが直接変更された際に即座に発火される。親ノードの変換変更時には発火しない。

**通知の受信者**：notify_local_transformフラグがtrueに設定されたCanvasItemまたはNode3Dの派生クラス。Bone2D、Skeleton2D、CollisionShape2D、CollisionPolygon2D、RigidBody2Dなどが内部で自動的にこのフラグを有効化して使用する。

**通知内容の概要**：通知値は35（NOTIFICATION_LOCAL_TRANSFORM_CHANGED = 35）として定義され、ノードのローカル変換が変更されたことを示す。

**期待されるアクション**：受信ノードはローカル変換に依存する内部状態を即座に更新する。例えば、コリジョン形状は物理サーバーに新しい変換を通知し、ボーンはスケルトンの再計算をトリガーする。

## 通知種別

ゲームエンジン内部通知（Object._notificationで受信）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（変換変更時に即座に発行） |
| 優先度 | 高（即時応答が必要なケースが多い） |
| リトライ | なし（一度のみ発行） |

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

1. ノードがシーンツリー内に存在すること
2. set_notify_local_transform(true)でnotify_local_transformフラグが有効であること
3. block_transform_notifyフラグがfalseであること（一時的なブロックなし）
4. ローカル変換プロパティが直接変更されること（親の変換変更では発火しない）

## 通知テンプレート

### 内部通知の場合

| 項目 | 内容 |
|-----|------|
| 通知定数名 | NOTIFICATION_LOCAL_TRANSFORM_CHANGED |
| 通知値 | 35 |
| 逆順送信 | false（通常順） |
| 形式 | 整数値（int p_what） |

### 本文テンプレート

```cpp
// _notification()での受信例
void MyNode::_notification(int p_what) {
    switch (p_what) {
        case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
            // ローカル変換が変更された
            Transform2D local_transform = get_transform();
            // 内部状態を更新
            update_internal_state();
        } break;
    }
}

// GDScriptでの例
func _notification(what):
    if what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED:
        # ローカル変換変更時の処理
        pass
```

### 添付ファイル

該当なし（内部通知のため）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| p_what | 通知種別 | notification()引数 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 位置変更 | set_position() | notify_local_transform=true | ローカル位置の変更 |
| 回転変更 | set_rotation() / set_rotation_degrees() | notify_local_transform=true | ローカル回転の変更 |
| スケール変更 | set_scale() | notify_local_transform=true | ローカルスケールの変更 |
| 変換行列設定 | set_transform() | notify_local_transform=true | ローカル変換行列の直接設定 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| notify_local_transform=false | デフォルト状態。明示的に有効化が必要 |
| block_transform_notify=true | set_block_transform_notify(true)で一時的にブロック |
| ツリー外のノード | シーンツリーに追加されていないノード |
| 親の変換変更 | 親ノードの変換変更時には発火しない（重要な違い） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ローカル変換変更] --> B{is_inside_tree?}
    B -->|No| C[処理終了]
    B -->|Yes| D{block_transform_notify?}
    D -->|Yes| C
    D -->|No| E{notify_local_transform?}
    E -->|No| F[グローバル変換通知処理へ]
    E -->|Yes| G[notification LOCAL_TRANSFORM_CHANGED発行]
    G --> H[派生クラス_notification処理]
    H --> F
```

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

### 参照テーブル一覧

該当なし（ゲームエンジン内部処理のためデータベースは使用しない）

### テーブル別参照項目詳細

該当なし

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 無限ループ | 通知ハンドラ内でローカル変換を変更し再帰的に通知が発生 | block_transform_notifyで一時ブロック |
| 不整合 | ローカル変換とグローバル変換の不整合 | force_update_transform()で強制同期 |
| スレッド競合 | マルチスレッドアクセス | メインスレッドガードで保護 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

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

### 配信時間帯

エンジン実行中いつでも発火可能。ローカル変換変更時に即座に発火。

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

エンジン内部通知のため、外部からの直接的なセキュリティリスクはない。ただし、通知ハンドラ内での再帰的な変換変更は無限ループを引き起こす可能性があるため、適切なガードが必要。

## 備考

- NOTIFICATION_TRANSFORM_CHANGED（グローバル変換、値2000）とは異なり、ローカル変換のみを追跡
- 親の変換変更では発火しないため、純粋にノード自身の変換変更を検出可能
- Bone2D、CollisionShape2Dなどは内部で自動的にset_notify_local_transform(true)を呼び出す
- _notify_transform()インライン関数内でnotify_local_transformフラグがチェックされる

---

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

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

### 推奨読解順序

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

まず、CanvasItemクラスの構造と通知定数の定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | canvas_item.h | `scene/main/canvas_item.h` | NOTIFICATION_LOCAL_TRANSFORM_CHANGED = 35定義（215行目）、notify_local_transformフラグ（115行目） |

**読解のコツ**: 値35はCanvasItem固有の通知定数。NOTIFICATION_TRANSFORM_CHANGED（2000）とは明確に区別される。

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

ローカル変換通知のトリガーメカニズムを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | canvas_item.h | `scene/main/canvas_item.h` | _notify_transform()インライン関数（173-178行目） |

**主要処理フロー**:
1. **173行目**: _notify_transform()呼び出し開始
2. **174行目**: _notify_transform(this)でグローバル変換処理
3. **175行目**: is_inside_tree()チェック
4. **175行目**: block_transform_notifyチェック
5. **175行目**: notify_local_transformチェック
6. **176行目**: notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED)発行

#### Step 3: 通知の有効化を理解する

set_notify_local_transform()の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | canvas_item.cpp | `scene/main/canvas_item.cpp` | set_notify_local_transform()メソッド |
| 3-2 | canvas_item.cpp | `scene/main/canvas_item.cpp` | is_local_transform_notification_enabled()メソッド |

#### Step 4: 派生クラスでの使用例を理解する

Bone2Dなどの派生クラスでの具体的な使用パターンを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | skeleton_2d.cpp | `scene/2d/skeleton_2d.cpp` | NOTIFICATION_LOCAL_TRANSFORM_CHANGED処理 |
| 4-2 | collision_shape_2d.cpp | `scene/2d/physics/collision_shape_2d.cpp` | NOTIFICATION_LOCAL_TRANSFORM_CHANGED処理 |
| 4-3 | collision_polygon_2d.cpp | `scene/2d/physics/collision_polygon_2d.cpp` | NOTIFICATION_LOCAL_TRANSFORM_CHANGED処理 |
| 4-4 | remote_transform_2d.cpp | `scene/2d/remote_transform_2d.cpp` | NOTIFICATION_LOCAL_TRANSFORM_CHANGED処理 |

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

```
Node2D::set_position() / set_rotation() / set_scale()
    │
    └─ CanvasItem::_notify_transform()  [inline関数]
           │
           ├─ _notify_transform(this)  [グローバル変換処理]
           │
           └─ 条件チェック
                  │
                  ├─ is_inside_tree()
                  ├─ !block_transform_notify
                  └─ notify_local_transform
                         │
                         └─ notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED)
                                │
                                └─ 派生クラス::_notification()
                                       │
                                       └─ 内部状態更新
```

### データフロー図

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

position/rotation   ───▶ _notify_transform() ───▶ 即座に発行
scale変更                  │
(ローカルのみ)             ├─ notify_local_transform?
                           │      │
                           │      Yes
                           │      │
                           │      └─▶ NOTIFICATION_LOCAL_TRANSFORM_CHANGED
                           │                │
                           │                └─▶ 派生クラス処理
                           │                     (コリジョン更新等)
                           │
                           └─▶ グローバル変換処理へ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| canvas_item.h | `scene/main/canvas_item.h` | ヘッダ | CanvasItemクラス定義、NOTIFICATION定数 |
| canvas_item.cpp | `scene/main/canvas_item.cpp` | ソース | set_notify_local_transform()実装 |
| skeleton_2d.cpp | `scene/2d/skeleton_2d.cpp` | ソース | スケルトンでの通知処理例 |
| collision_shape_2d.cpp | `scene/2d/physics/collision_shape_2d.cpp` | ソース | コリジョン形状での通知処理例 |
| collision_polygon_2d.cpp | `scene/2d/physics/collision_polygon_2d.cpp` | ソース | コリジョンポリゴンでの通知処理例 |
| animatable_body_2d.cpp | `scene/2d/physics/animatable_body_2d.cpp` | ソース | アニメーション可能ボディでの通知処理例 |
| rigid_body_2d.cpp | `scene/2d/physics/rigid_body_2d.cpp` | ソース | リジッドボディでの通知処理例 |
| remote_transform_2d.cpp | `scene/2d/remote_transform_2d.cpp` | ソース | リモート変換での通知処理例 |
| tile_map.cpp | `scene/2d/tile_map.cpp` | ソース | タイルマップでの通知処理例 |
| node_3d.h | `scene/3d/node_3d.h` | ヘッダ | 3D版のNOTIFICATION_LOCAL_TRANSFORM_CHANGED |
| CanvasItem.xml | `doc/classes/CanvasItem.xml` | ドキュメント | 公式APIドキュメント（742-744行目） |
