# 通知設計書 74-property_list_changed

## 概要

本ドキュメントは、Godot Engineにおける`property_list_changed`シグナルの設計仕様を記載する。このシグナルはObjectクラスで定義され、オブジェクトのプロパティリストが変更された際に発火する。主にエディタのインスペクターやプラグインの更新に使用される。

### 本通知の処理概要

このシグナルは、`notify_property_list_changed()`メソッドが呼び出された際に発火する。プロパティリストの変更（プロパティの追加、削除、属性変更など）をUIや他のシステムに通知するために使用される。

**業務上の目的・背景**：Godotのプロパティシステムは動的であり、スクリプトやGDExtensionによってプロパティが動的に追加・削除される。エディタのインスペクターやカスタムエディタプラグインは、プロパティリストの変更を検知してUIを更新する必要がある。このシグナルにより、プロパティリスト変更の通知を受け取り、UIの再構築や再描画を行える。

**通知の送信タイミング**：以下のイベントでシグナルが発火する：
- `notify_property_list_changed()`メソッドが明示的に呼び出された時
- `set_script()`でスクリプトが変更された時（自動的に呼び出される）
- メタデータが追加・削除された時（`_`で始まらないキーの場合）

**通知の受信者**：シグナルに接続したすべてのオブジェクト。主な利用者：
- エディタインスペクター（EditorInspector）
- エディタプラグイン
- カスタムプロパティエディタ

**通知内容の概要**：シグナル自体にはパラメータがない。新しいプロパティリストは`get_property_list()`で取得可能。

**期待されるアクション**：シグナル受信者は以下のような処理を行う：
1. プロパティリストの再取得
2. UIの再構築
3. プロパティキャッシュのクリア

## 通知種別

シグナル（Signal）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| シグナル名 | `property_list_changed` |
| 定義クラス | Object |
| 送信方式 | 同期（emit_signal） |
| 優先度 | 中 |
| リトライ | なし |

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

シグナルは`notify_property_list_changed()`メソッドで直接発火される：
```cpp
void Object::notify_property_list_changed() {
    emit_signal(CoreStringName(property_list_changed));
}
```

## 通知テンプレート

### シグナル定義

```cpp
// object.cpp
ADD_SIGNAL(MethodInfo("property_list_changed"));
```

### 処理テンプレート（GDScript）

```gdscript
@tool
extends Node

@export var item_count: int = 3:
    set(value):
        item_count = value
        items.resize(item_count)
        notify_property_list_changed()  # UIを更新

var items: Array = []

func _get_property_list():
    var properties = []
    for i in range(item_count):
        properties.append({
            "name": "item_%d" % i,
            "type": TYPE_STRING,
        })
    return properties
```

### 処理テンプレート（C++）

```cpp
// プロパティリスト変更の通知
void MyClass::update_custom_properties() {
    // プロパティリストに影響する内部状態を変更
    _custom_properties_dirty = true;
    notify_property_list_changed();
}

// シグナル受信側
void MyEditor::_on_object_property_list_changed() {
    // プロパティリストを再取得してUI更新
    _refresh_property_list();
}
```

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| なし | シグナルにはパラメータがない | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | notify_property_list_changed() | なし | 明示的な通知要求 |
| 内部処理 | set_script() | スクリプト変更成功 | スクリプト変更時に自動呼び出し |
| 内部処理 | set_meta() | キーが_で始まらない | メタデータ追加時 |
| 内部処理 | remove_meta() | キーが_で始まらない | メタデータ削除時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| is_blocking_signals() | シグナルブロック中 |
| メタキーが_で始まる | インスペクターに表示されないメタデータ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[プロパティ変更要因発生] --> B{変更種別}
    B -->|set_script| C[スクリプト設定処理]
    B -->|set_meta| D{キーが_で始まる?}
    B -->|明示的呼び出し| E[notify_property_list_changed]
    C --> E
    D -->|Yes| F[シグナルなし]
    D -->|No| E
    E --> G[emit_signal property_list_changed]
    G --> H[接続先に通知]
    H --> I[UI更新等]
    I --> J[終了]
    F --> J
```

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

該当なし（本シグナルはエンジン内部のオブジェクトシステムで処理され、データベースは使用しない）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 特になし | - | - |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | なし（頻繁な呼び出しに注意） |

### 配信時間帯

制限なし

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

- 頻繁な呼び出しはエディタのパフォーマンスに影響する可能性があるため、必要な時のみ呼び出す
- プロパティリストはオブジェクトの構造を公開するため、センシティブな情報を含めない

## 備考

- エディタ専用のシグナルではないが、主にエディタで使用される
- `@tool`スクリプトでは`_get_property_list()`と組み合わせて動的プロパティを実現
- 公式ドキュメントの例では、プロパティ値の変更時に`notify_property_list_changed()`を呼び出すパターンが紹介されている

---

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

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

### 推奨読解順序

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

Objectクラスのプロパティシステム構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | object.h | `core/object/object.h` | プロパティリスト関連API宣言 |

**読解のコツ**: `_get_property_list()`仮想メソッドと`get_property_list()`メソッドの違いを理解する。前者はオーバーライド用、後者は統合されたリストを返す。

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

シグナルの発火元を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | object.cpp | `core/object/object.cpp` | notify_property_list_changed()実装（行1912-1914） |

**主要処理フロー**:
1. **行1912**: `void Object::notify_property_list_changed()`
2. **行1913**: `emit_signal(CoreStringName(property_list_changed));`

#### Step 3: 呼び出し元を理解する

notify_property_list_changed()の呼び出し箇所を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | object.cpp | `core/object/object.cpp` | set_script()内の呼び出し（行1096） |
| 3-2 | object.cpp | `core/object/object.cpp` | set_meta()内の呼び出し（行1145） |
| 3-3 | object.cpp | `core/object/object.cpp` | remove_meta()内の呼び出し（行1129） |

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

```
notify_property_list_changed()
    │
    └─ emit_signal("property_list_changed")
           │
           └─ 接続先Callableの呼び出し

呼び出し元：
    ├─ Object::set_script()
    ├─ Object::set_meta() [キーが_で始まらない場合]
    ├─ Object::remove_meta() [キーが_で始まらない場合]
    └─ ユーザースクリプト/プラグインからの明示的呼び出し
```

### データフロー図

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

プロパティ変更   ───▶ notify_property       ───▶ property_list
 - スクリプト変更     _list_changed()            _changedシグナル
 - メタデータ変更          │                          │
 - 明示的呼び出し          ▼                          ▼
                    emit_signal()            EditorInspector
                                             ::update()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| object.h | `core/object/object.h` | ヘッダ | notify_property_list_changed()宣言 |
| object.cpp | `core/object/object.cpp` | ソース | 実装とシグナル定義 |
| Object.xml | `doc/classes/Object.xml` | ドキュメント | 公式ドキュメント定義 |
| editor_inspector.cpp | `editor/inspector/editor_inspector.cpp` | ソース | エディタでの利用例 |
