# 通知設計書 16-NOTIFICATION_ENTER_TREE

## 概要

本ドキュメントは、Godotエンジンにおける `NOTIFICATION_ENTER_TREE` 通知の設計と実装について記述する。この通知はNodeクラスの基本的なライフサイクル通知の一つで、ノードがシーンツリーに追加された時に発火する最も重要な初期化タイミングを提供する。

### 本通知の処理概要

`NOTIFICATION_ENTER_TREE` は、ノードがシーンツリーに入った瞬間に送信される通知である。この通知を受け取った時点で、ノードは完全にシーンツリーの一部となり、get_tree()、get_parent()、get_node()などのシーンツリー関連メソッドが正常に動作する状態になる。

**業務上の目的・背景**：ゲームやアプリケーション開発において、ノードがシーンの一部として機能を開始するタイミングを正確に把握することは極めて重要である。NOTIFICATION_ENTER_TREEは、ノードがシーンツリーに統合され、他のノードとの関係が確立された最初のタイミングを提供する。これにより、シーンツリー依存の初期化処理（親ノードへのアクセス、シグナル接続、グループ登録など）を安全に実行できる。

**通知の送信タイミング**：NOTIFICATION_ENTER_TREEは、以下の状況で送信される。(1) add_child()によってノードがシーンツリー内の親ノードに追加された時、(2) シーンがインスタンス化されてルートノードがSceneTreeに追加された時、(3) reparent()によってノードが別の親に移動した時（EXIT_TREE後に再度ENTER_TREE）。

**通知の受信者**：シーンツリーに追加されるすべてのNodeおよびその派生クラスが受信者となる。_notification()メソッドまたは_enter_tree()仮想関数をオーバーライドすることで処理を実装する。

**通知内容の概要**：通知値は整数定数10（Node::NOTIFICATION_ENTER_TREE）として定義されている。追加のパラメータは含まれない。

**期待されるアクション**：受信者は、シーンツリー依存の初期化処理を実行する。具体的には、process_modeの設定、input/shortcut_inputグループへの追加、物理補間モードの設定、アクセシビリティ更新の登録などが行われる。

## 通知種別

Nodeライフサイクル通知（内部通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高 |
| リトライ | 無 |
| 通知値 | 10 |

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

シーンツリーに追加されるノードとそのすべての子孫ノードに対して、深さ優先で順番に送信される。親ノードが先に通知を受け取り、その後子ノードが順次通知を受け取る。

## 通知テンプレート

### 定数定義

```cpp
enum {
    NOTIFICATION_ENTER_TREE = 10,
    // ...
};
```

### GDScript使用例

```gdscript
extends Node

func _enter_tree():
    # シーンツリーに入った時の処理
    print("ノードがシーンツリーに入りました: ", name)
    print("親ノード: ", get_parent().name if get_parent() else "なし")
    print("シーンツリー: ", get_tree())

# または_notification()を使用
func _notification(what):
    if what == NOTIFICATION_ENTER_TREE:
        _custom_enter_tree()

func _custom_enter_tree():
    # カスタム初期化処理
    pass
```

### 典型的な使用パターン

```gdscript
extends Node2D

var _is_initialized := false

func _enter_tree():
    # シグナル接続（シーンツリー内の他ノードへ）
    var player = get_tree().get_first_node_in_group("player")
    if player:
        player.health_changed.connect(_on_player_health_changed)

    # 入力処理の有効化
    set_process_input(true)

    _is_initialized = true

func _on_player_health_changed(new_health):
    print("プレイヤーHP: ", new_health)
```

## テンプレート変数

NOTIFICATION_ENTER_TREEはパラメータを持たないため、テンプレート変数は存在しない。

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ノード操作 | add_child() | 親がシーンツリー内 | ノードが親に追加される |
| シーン操作 | change_scene_to_*() | なし | 新しいシーンがロードされる |
| シーン操作 | シーンインスタンス化 | ルートに接続時 | pack.instantiate()後の追加 |
| ノード操作 | reparent() | 新しい親がシーンツリー内 | ノードの親が変更される |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 親がシーンツリー外 | 親ノードがシーンツリーに入っていない場合 |
| 既にシーンツリー内 | is_inside_tree()がtrueの場合（二重通知防止） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[add_child/reparent呼び出し] --> B{親がシーンツリー内?}
    B -->|Yes| C[_propagate_enter_tree開始]
    B -->|No| D[通知なし]
    C --> E[data.tree = 親のtree]
    E --> F[data.depth = 親のdepth + 1]
    F --> G[data.viewport設定]
    G --> H[グループ登録]
    H --> I[notification ENTER_TREE]
    I --> J[GDVIRTUAL_CALL _enter_tree]
    J --> K[emit_signal tree_entered]
    K --> L[tree->node_added]
    L --> M[親にchild_entered_tree発火]
    M --> N{子ノードあり?}
    N -->|Yes| O[子ノードに再帰]
    N -->|No| P[完了]
    O --> C
```

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

### 参照テーブル一覧

該当なし（NOTIFICATION_ENTER_TREEはデータベースを使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| get_viewport() null | ビューポートが見つからない | ERR_FAIL_NULLでエラーチェック |
| get_tree() null | シーンツリーが見つからない | ERR_FAIL_NULLでエラーチェック |
| ルートノードでINHERIT | ProcessModeがINHERITのルートノード | PAUSABLEに自動変更、エラーメッセージ出力 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし

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

- NOTIFICATION_ENTER_TREEはエンジン内部で管理され、ユーザーコードから直接トリガーすることは推奨されない
- _enter_tree()内で長時間の処理を行うとフレームレートに影響するため、重い処理はcall_deferred()で遅延させることを推奨
- ノードの追加はメインスレッドからのみ安全に実行可能

## 備考

- 通知後、tree_enteredシグナルが発火し、親ノードにはchild_entered_treeシグナルが発火する
- _enter_tree()は_ready()より前に呼ばれる
- ノードがシーンツリーに入ると、nodes_in_tree_countがインクリメントされる
- 物理補間モードがINHERITの場合、親の設定が継承される
- アクセシビリティサポートが有効な場合、アクセシビリティ更新がトリガーされる

---

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

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

### 推奨読解順序

#### Step 1: 定数定義を理解する

通知値の定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | node.h | `scene/main/node.h` | NOTIFICATION_ENTER_TREE定数の定義 |

**読解のコツ**: 通知値10として定義されており、他のライフサイクル通知と区別される。

**主要処理フロー**:
- **451行目**: `NOTIFICATION_ENTER_TREE = 10`

#### Step 2: 伝播処理を理解する

通知がどのように子ノードに伝播するかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | node.cpp | `scene/main/node.cpp` | _propagate_enter_tree()関数の実装 |

**主要処理フロー**:
1. **335-383行目**: _propagate_enter_tree関数全体
2. **338-343行目**: data.tree、data.depthの設定
3. **345-348行目**: data.viewport の設定
4. **350-352行目**: グループへの追加
5. **354行目**: `notification(NOTIFICATION_ENTER_TREE)`
6. **356行目**: `GDVIRTUAL_CALL(_enter_tree)`
7. **358行目**: `emit_signal(SceneStringName(tree_entered))`
8. **360行目**: `data.tree->node_added(this)`
9. **362-366行目**: 親ノードへのchild_entered_tree発火
10. **371-376行目**: 子ノードへの再帰

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

_notification()でのENTER_TREE処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | node.cpp | `scene/main/node.cpp` | _notification()内のNOTIFICATION_ENTER_TREE処理 |

**主要処理フロー**:
1. **99-178行目**: case NOTIFICATION_ENTER_TREE全体
2. **103-111行目**: アクセシビリティ更新
3. **113-124行目**: process_modeの更新
4. **126-145行目**: スレッド処理グループの更新
5. **147-153行目**: 物理補間モードの更新
6. **155-161行目**: auto_translate_modeの更新
7. **163-174行目**: 入力グループへの追加
8. **176行目**: nodes_in_tree_countのインクリメント

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

```
Node::add_child()
    │
    └─ Node::_propagate_enter_tree()
           │
           ├─ data.tree = parent.tree
           ├─ data.depth = parent.depth + 1
           ├─ data.viewport 設定
           │
           ├─ グループ登録
           │      └─ tree->add_to_group()
           │
           ├─ notification(NOTIFICATION_ENTER_TREE)
           │      └─ Node::_notification()
           │             ├─ アクセシビリティ更新
           │             ├─ process_mode更新
           │             ├─ thread_group更新
           │             ├─ physics_interpolation更新
           │             ├─ auto_translate更新
           │             ├─ input group追加
           │             └─ nodes_in_tree_count++
           │
           ├─ GDVIRTUAL_CALL(_enter_tree)
           │      └─ GDScript: _enter_tree()
           │
           ├─ emit_signal(tree_entered)
           │
           ├─ tree->node_added()
           │
           ├─ parent.emit_signal(child_entered_tree)
           │
           └─ 子ノードに再帰
                  └─ child._propagate_enter_tree()
```

### データフロー図

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

add_child(node)         ───▶ _propagate_enter_tree() ───▶ data.tree設定
                                    │
                                    ├─▶ data.depth設定
                                    │
                                    ├─▶ グループ登録
                                    │
                                    ├─▶ notification(ENTER_TREE)
                                    │       │
                                    │       └─▶ 各種初期化処理
                                    │
                                    ├─▶ _enter_tree()仮想関数
                                    │
                                    ├─▶ tree_enteredシグナル
                                    │
                                    ├─▶ node_added()
                                    │
                                    ├─▶ child_entered_treeシグナル
                                    │
                                    └─▶ 子ノードへ再帰
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| node.h | `scene/main/node.h` | ヘッダ | Node クラス定義、NOTIFICATION_ENTER_TREE定数 |
| node.cpp | `scene/main/node.cpp` | ソース | _propagate_enter_tree()、_notification()実装 |
| scene_tree.h | `scene/main/scene_tree.h` | ヘッダ | SceneTreeクラス定義 |
| scene_tree.cpp | `scene/main/scene_tree.cpp` | ソース | node_added()等の実装 |
| Node.xml | `doc/classes/Node.xml` | ドキュメント | APIリファレンス |
