# 通知設計書 23-NOTIFICATION_PARENTED

## 概要

本ドキュメントは、Godot EngineのNodeクラスにおける`NOTIFICATION_PARENTED`通知の設計仕様を記載する。この通知はノードが親ノードに追加された際に発火し、ノードの階層構造変更を検知するための重要なライフサイクル通知である。

### 本通知の処理概要

NOTIFICATION_PARENTEDは、ノードが別のノードの子として追加された直後に発行されるシステム通知である。この通知はシーンツリーへの追加有無に関わらず発火するため、ノードの親子関係の変更を検知する最も早いタイミングで処理を実行できる。

**業務上の目的・背景**：ゲーム開発において、ノードの親子関係はシーン構造の基盤となる。ノードが親に追加された際に、親の情報に基づいた初期化処理（Transform継承の設定、親のプロパティ参照など）を行う必要がある場合がある。NOTIFICATION_PARENTEDは、シーンツリーへの追加（NOTIFICATION_ENTER_TREE）よりも前に発火するため、ツリー追加前の準備処理に最適である。

**通知の送信タイミング**：ノードがadd_child()またはadd_sibling()によって親ノードに追加された直後。具体的には_add_child_nocheck()内で、子ノードのdata.parentが設定された後に送信される。重要な点として、この時点ではまだノードはシーンツリーに追加されていない可能性がある。

**通知の受信者**：親ノードに追加された子ノード自身。親ノードには送信されない（親ノードにはadd_child_notify仮想関数が呼ばれる）。

**通知内容の概要**：通知IDは整数値18（NOTIFICATION_PARENTED = 18）。追加のパラメータは含まない。

**期待されるアクション**：
- 親ノードの参照を取得し、必要な初期化を実行
- 親のTransformや設定に依存する処理の準備
- 親子関係に基づくコンポーネント接続
- CanvasItem派生クラスでのTransform通知トリガー

## 通知種別

エンジン内部通知（Engine Internal Notification）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高（ライフサイクル通知） |
| リトライ | 無し |

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

1. add_child()またはadd_sibling()が呼ばれる
2. _add_child_nocheck()が実行される
3. p_child->data.parent = this; で親が設定される
4. 子ノードにNOTIFICATION_PARENTEDを送信
5. その後、シーンツリーへの追加処理（_set_tree）が実行される

## 通知テンプレート

### システム通知の場合

| 項目 | 内容 |
|-----|------|
| 通知ID | 18 |
| 通知名 | NOTIFICATION_PARENTED |
| 定義箇所 | scene/main/node.h |

### 通知ハンドリング例

```cpp
void MyNode::_notification(int p_notification) {
    switch (p_notification) {
        case NOTIFICATION_PARENTED: {
            // 親が設定された際の処理
            Node *parent = get_parent();
            if (parent) {
                // 親に基づく初期化
            }
        } break;
    }
}
```

```gdscript
func _notification(what):
    if what == NOTIFICATION_PARENTED:
        var parent = get_parent()
        if parent:
            # 親に基づく初期化
            pass
```

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| p_notification | 通知ID（18） | エンジン内部 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | Node.add_child(child) | 常に | 子ノード追加時 |
| API呼び出し | Node.add_sibling(sibling) | 常に | 兄弟ノード追加時（内部でadd_childを使用） |
| 内部処理 | _add_child_nocheck() | 常に | 子追加の内部処理 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | 親への追加時は常に送信される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[add_child呼び出し] --> B[バリデーションチェック]
    B --> C[_validate_child_name]
    C --> D[_add_child_nocheck]
    D --> E[子ノード名を設定]
    E --> F[children HashMapに追加]
    F --> G[internal_modeとindexを設定]
    G --> H[data.parent = this]
    H --> I[NOTIFICATION_PARENTED送信]
    I --> J{親がツリー内?}
    J -->|Yes| K[_set_tree実行]
    J -->|No| L[ツリー追加なし]
    K --> M[add_child_notify呼び出し]
    L --> M
    M --> N[NOTIFICATION_CHILD_ORDER_CHANGED送信]
    N --> O[終了]
```

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

### 参照データ一覧

| データ | 用途 | 備考 |
|--------|------|------|
| Node::data.parent | 親ノードの参照 | この通知時点で設定済み |
| Node::data.tree | シーンツリーの参照 | この通知時点ではnullの可能性あり |
| Node::data.name | ノード名 | 設定済み |

### 更新データ一覧

| データ | 操作 | 概要 |
|--------|------|------|
| Node::data.parent | 設定 | 親ノードへの参照が設定される（通知前） |
| Node::data.index | 設定 | 兄弟間のインデックスが設定される（通知前） |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 自己追加 | add_child(this) | エラーログ出力、処理中止 |
| 既に親がいる | p_child->data.parent != nullptr | エラーログ出力、処理中止 |
| 循環参照 | 子が祖先である | エラーログ出力、処理中止（DEBUG_ENABLED） |
| ブロック中 | data.blocked > 0 | エラーログ出力、call_deferred推奨 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（エンジン実行中いつでも発生可能）

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

- メインスレッドからのみ子ノード追加が許可される（ツリー内のノードの場合）
- スクリプトからnotification()を直接呼び出すことは可能だが、状態の不整合を招く可能性がある

## 備考

- NOTIFICATION_ENTER_TREEよりも前に発火する
- NOTIFICATION_UNPARENTEDとペアで使用される対照的な通知
- この通知時点ではget_tree()がnullを返す可能性がある
- CanvasItem派生クラスでは_notify_transform()を呼び出すために使用される

---

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

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

### 推奨読解順序

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

ノードの親子関係に関するデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | node.h | `scene/main/node.h` | NOTIFICATION_PARENTED定数の定義（459行目） |
| 1-2 | node.h | `scene/main/node.h` | Data構造体のparent、childrenフィールド（200-204行目） |

**読解のコツ**: parentはNode*型のポインタで、childrenはHashMap<StringName, Node*>で管理されていることを理解する。

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

処理の起点となる関数を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | node.cpp | `scene/main/node.cpp` | add_child関数（1699-1721行目）のバリデーションと呼び出し |
| 2-2 | node.cpp | `scene/main/node.cpp` | _add_child_nocheck関数（1652-1697行目）の内部処理 |

**主要処理フロー**:
1. **1699-1709行目**: add_childでのバリデーション（自己追加、既存親、循環参照チェック）
2. **1679行目**: p_child->data.parent = this; で親を設定
3. **1687行目**: p_child->notification(NOTIFICATION_PARENTED); 通知送信
4. **1689-1691行目**: 親がツリー内なら_set_treeでツリーに追加

#### Step 3: 通知ハンドラを理解する

派生クラスでの通知処理例を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | canvas_item.cpp | `scene/main/canvas_item.cpp` | CanvasItemでのPARENTED処理（444-449行目） |
| 3-2 | control.cpp | `scene/gui/control.cpp` | ControlでのPARENTED処理 |

**主要処理フロー**:
- **canvas_item.cpp 448行目**: _notify_transform()を呼び出してTransform更新をトリガー

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

```
Node::add_child(p_child)
    │
    ├─ ERR_FAIL_COND チェック群
    │      ├─ 自己追加チェック
    │      ├─ 既存親チェック
    │      └─ 循環参照チェック
    │
    ├─ _validate_child_name(p_child)
    │
    └─ _add_child_nocheck(p_child, name, internal_mode)
           │
           ├─ data.children.insert(name, p_child)
           │
           ├─ p_child->data.parent = this
           │
           ├─ p_child->notification(NOTIFICATION_PARENTED)
           │      └─ [派生クラスの_notification]
           │
           ├─ _set_tree(data.tree) [親がツリー内の場合]
           │      └─ NOTIFICATION_ENTER_TREE
           │
           ├─ add_child_notify(p_child) [仮想関数]
           │
           └─ notification(NOTIFICATION_CHILD_ORDER_CHANGED)
```

### データフロー図

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

Node* p_child ──────────▶ add_child ─────────────────────▶ NOTIFICATION_PARENTED
       │                       │                                  │
       │                       ▼                                  ▼
       │              _validate_child_name              [子ノードで処理]
       │                       │
       ▼                       ▼
StringName name ────────▶ _add_child_nocheck ──────────▶ NOTIFICATION_ENTER_TREE
       │                       │                         [ツリー追加時のみ]
       │                       ▼
       │              data.parent = this
       │                       │
       └───────────────────────┴───────────────────────▶ add_child_notify
                                                         [親ノードで処理]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| node.h | `scene/main/node.h` | ヘッダー | Node基底クラス定義、通知定数 |
| node.cpp | `scene/main/node.cpp` | ソース | add_child、_add_child_nocheckの実装 |
| canvas_item.cpp | `scene/main/canvas_item.cpp` | ソース | CanvasItemでのPARENTED処理例 |
| control.cpp | `scene/gui/control.cpp` | ソース | ControlでのPARENTED処理例 |
| collision_shape_2d.cpp | `scene/2d/physics/collision_shape_2d.cpp` | ソース | CollisionShape2DでのPARENTED処理例 |
| collision_shape_3d.cpp | `scene/3d/physics/collision_shape_3d.cpp` | ソース | CollisionShape3DでのPARENTED処理例 |
| navigation_agent_2d.cpp | `scene/2d/navigation/navigation_agent_2d.cpp` | ソース | NavigationAgent2DでのPARENTED処理例 |
