# 画面設計書: メッシュライブラリエディタ

## 基本情報

| 項目 | 内容 |
|------|------|
| 画面ID | 48 |
| 画面名 | メッシュライブラリエディタ |
| ファイルパス | `editor/scene/3d/mesh_library_editor_plugin.h`, `editor/scene/3d/mesh_library_editor_plugin.cpp` |
| 主要クラス | `MeshLibraryEditor`, `MeshLibraryEditorPlugin` |
| 基底クラス | `Control`, `EditorPlugin` |

## 概要

メッシュライブラリエディタはMeshLibraryリソースを編集するためのプラグインです。GridMapで使用する3Dメッシュのコレクションを管理します。シーンからメッシュをインポートし、プレビュー画像を自動生成する機能を備えています。

### 主な機能

1. **アイテム管理**: メッシュアイテムの追加・削除
2. **シーンインポート**: PackedSceneからメッシュを自動抽出
3. **トランスフォーム適用**: インポート時にノードのトランスフォームを適用可能
4. **プレビュー生成**: メッシュのプレビュー画像を自動生成
5. **シーン更新**: 元のシーンファイルからライブラリを更新

## 画面構成

### レイアウト構造

```
+------------------------------------------------------------------+
| Node3DEditor Menu Panel                                           |
| +------------------------------------------------------------+   |
| | [MeshLibrary v]                                             |   |
| +------------------------------------------------------------+   |
| | Add Item                                                    |   |
| | Remove Selected Item                                        |   |
| | -------------------------------------------                 |   |
| | Import from Scene (Ignore Transforms)                       |   |
| | Import from Scene (Apply Transforms)                        |   |
| | Update from Scene                                           |   |
| +------------------------------------------------------------+   |
+------------------------------------------------------------------+
```

## 表示項目

### メニューボタン

| 項目 | 種類 | 説明 | ソースコード参照 |
|------|------|------|------------------|
| menu | MenuButton | MeshLibraryメニュー | L46, L276-291 |

### ダイアログ

| 項目 | 種類 | 説明 | ソースコード参照 |
|------|------|------|------------------|
| file | EditorFileDialog | シーンファイル選択ダイアログ | L49, L263-274 |
| cd_remove | ConfirmationDialog | アイテム削除確認ダイアログ | L47, L293-295 |
| cd_update | ConfirmationDialog | シーン更新確認ダイアログ | L48, L296-300 |

## メニューオプション

| ID | メニュー項目 | 説明 | ソースコード参照 |
|----|-------------|------|------------------|
| MENU_OPTION_ADD_ITEM | Add Item | 新規アイテム追加 | L54, L283 |
| MENU_OPTION_REMOVE_ITEM | Remove Selected Item | 選択アイテム削除 | L55, L284 |
| MENU_OPTION_IMPORT_FROM_SCENE | Import from Scene (Ignore Transforms) | トランスフォーム無視でインポート | L57, L286 |
| MENU_OPTION_IMPORT_FROM_SCENE_APPLY_XFORMS | Import from Scene (Apply Transforms) | トランスフォーム適用でインポート | L58, L287 |
| MENU_OPTION_UPDATE_FROM_SCENE | Update from Scene | 元シーンから更新 | L56, L288 |

## イベント仕様

### メニュー操作

| イベント | 関数名 | 処理内容 | ソースコード参照 |
|----------|--------|----------|------------------|
| メニュー選択 | _menu_cbk() | メニューオプションに応じた処理を実行 | L233-260 |
| 削除確認OK | _menu_remove_confirm() | アイテムを削除 | L54-62 |
| 更新確認OK | _menu_update_confirm() | シーンから更新実行 | L64-70 |
| ファイル選択 | _import_scene_cbk() | 選択シーンをインポート | L107-120 |

### メニューオプション別処理

| オプション | 処理内容 | ソースコード参照 |
|-----------|----------|------------------|
| ADD_ITEM | get_last_unused_item_id()で新規ID取得、create_item()でアイテム作成 | L236-238 |
| REMOVE_ITEM | インスペクタで選択中のアイテムIDを取得、確認ダイアログ表示 | L239-246 |
| IMPORT_FROM_SCENE | apply_xforms=false、ファイルダイアログ表示 | L247-250 |
| IMPORT_FROM_SCENE_APPLY_XFORMS | apply_xforms=true、ファイルダイアログ表示 | L251-254 |
| UPDATE_FROM_SCENE | メタデータからソースシーンパスを取得、確認ダイアログ表示 | L255-258 |

## シーンインポート処理

### インポート処理フロー

```
_import_scene_cbk()
└── ResourceLoader::load(PackedScene)
    └── ps->instantiate()
        └── _import_scene()
            ├── [!p_merge] p_library->clear()
            ├── _import_scene_parse_node() [再帰処理]
            │   ├── MeshInstance3Dノードを探索
            │   ├── メッシュをライブラリに追加
            │   ├── シャドウ設定を継承
            │   ├── StaticBody3D子ノードから衝突形状を抽出
            │   └── NavigationRegion3D子ノードからナビメッシュを抽出
            └── EditorInterface::make_mesh_previews()
                └── プレビュー画像生成
```

### パース処理詳細

| 処理ステップ | 内容 | ソースコード参照 |
|-------------|------|------------------|
| ノード探索 | MeshInstance3Dを再帰的に検索 | L122-131 |
| メッシュ取得 | get_mesh()でソースメッシュ取得 | L133-136 |
| アイテムID決定 | 名前でfind_item_by_name、なければ新規ID | L138-145 |
| メッシュ複製 | source_mesh->duplicate()でコピー | L148 |
| マテリアル継承 | surface_override_materialを適用 | L149-154 |
| シャドウ設定 | get_cast_shadows_setting()を継承 | L157-174 |
| トランスフォーム | p_apply_xformsに応じて変換行列を設定 | L176-180 |
| 衝突形状 | StaticBody3Dから形状を抽出 | L182-211 |
| ナビメッシュ | NavigationRegion3Dからナビメッシュを抽出 | L213-225 |

## 確認ダイアログ

### 削除確認ダイアログ（cd_remove）

| 項目 | 内容 | ソースコード参照 |
|------|------|------------------|
| テキスト | "Remove item %d?" | L243 |
| サイズ | 300 x 60 | L244 |
| OKボタン | _menu_remove_confirm()呼び出し | L295 |

### 更新確認ダイアログ（cd_update）

| 項目 | 内容 | ソースコード参照 |
|------|------|------------------|
| テキスト | "Update from existing scene?:\n%s" | L256 |
| サイズ | 500 x 60 | L257 |
| OKボタンテキスト | "Apply without Transforms" | L298 |
| OKボタン | _menu_update_confirm(false)呼び出し | L299 |
| 追加ボタン | "Apply with Transforms"、_menu_update_confirm(true)呼び出し | L300 |

## ファイルダイアログ

| 項目 | 内容 | ソースコード参照 |
|------|------|------------------|
| モード | FILE_MODE_OPEN_FILE | L264 |
| タイトル | "Import Scene" | L269 |
| フィルタ | PackedScene対応拡張子 | L266-272 |
| 選択時 | _import_scene_cbk()呼び出し | L274 |

## メタデータ

| キー | 用途 | ソースコード参照 |
|------|------|------------------|
| _editor_source_scene | インポート元シーンパス | L67, L117, L119, L256 |

## プレビュー生成

| 処理 | 内容 | ソースコード参照 |
|------|------|------------------|
| サイズ取得 | EDITOR_GET("editors/grid_map/preview_size") | L96 |
| 生成関数 | EditorInterface::make_mesh_previews() | L96 |
| 設定関数 | p_library->set_item_preview() | L100 |

## シャドウキャスティング設定マッピング

| GeometryInstance3D | RenderingServer | ソースコード参照 |
|--------------------|-----------------|------------------|
| SHADOW_CASTING_SETTING_OFF | SHADOW_CASTING_SETTING_OFF | L159-161 |
| SHADOW_CASTING_SETTING_ON | SHADOW_CASTING_SETTING_ON | L162-164 |
| SHADOW_CASTING_SETTING_DOUBLE_SIDED | SHADOW_CASTING_SETTING_DOUBLE_SIDED | L165-167 |
| SHADOW_CASTING_SETTING_SHADOWS_ONLY | SHADOW_CASTING_SETTING_SHADOWS_ONLY | L168-170 |

## プラグイン設定

| 設定 | 値 | ソースコード参照 |
|------|-----|------------------|
| プラグイン名 | "MeshLibrary" | L85 |
| has_main_screen | false | L86 |
| 初期表示 | 非表示 | L291, L333 |

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

### 推奨読解順序

1. **データ構造** (mesh_library_editor_plugin.h L41-77)
   - MeshLibraryEditorクラス定義
   - メニューオプションenum

2. **プラグインクラス** (mesh_library_editor_plugin.h L79-92)
   - MeshLibraryEditorPlugin定義
   - EditorPlugin仮想関数オーバーライド

3. **コンストラクタ** (mesh_library_editor_plugin.cpp L262-301)
   - ファイルダイアログ作成
   - メニュー構築
   - 確認ダイアログ作成

4. **メニュー処理** (mesh_library_editor_plugin.cpp L233-260)
   - _menu_cbk()各オプション処理

5. **インポート処理** (mesh_library_editor_plugin.cpp L72-226)
   - _import_scene()メイン処理
   - _import_scene_parse_node()再帰パース
   - 衝突形状・ナビメッシュ抽出

6. **プラグイン連携** (mesh_library_editor_plugin.cpp L303-334)
   - edit()、handles()、make_visible()実装

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

```
MeshLibraryEditorPlugin::edit()
└── MeshLibraryEditor::edit()
    └── mesh_library = p_mesh_library
        └── menu->get_popup()->set_item_disabled(UPDATE_FROM_SCENE, ...)

_menu_cbk(MENU_OPTION_ADD_ITEM)
└── mesh_library->create_item(mesh_library->get_last_unused_item_id())

_menu_cbk(MENU_OPTION_REMOVE_ITEM)
├── InspectorDock::get_inspector_singleton()->get_selected_path()
├── to_erase = path.get_slicec('/', 1).to_int()
└── cd_remove->popup_centered()
    └── [OK] _menu_remove_confirm()
        └── mesh_library->remove_item(to_erase)

_menu_cbk(MENU_OPTION_IMPORT_FROM_SCENE)
└── file->popup_file_dialog()
    └── [file_selected] _import_scene_cbk()
        ├── ResourceLoader::load(PackedScene)
        ├── ps->instantiate()
        ├── _import_scene(scene, mesh_library, false, apply_xforms)
        │   ├── [!merge] p_library->clear()
        │   ├── _import_scene_parse_node() [再帰]
        │   │   ├── MeshInstance3D検出
        │   │   ├── p_library->create_item() or find_item_by_name()
        │   │   ├── p_library->set_item_mesh()
        │   │   ├── p_library->set_item_mesh_cast_shadow()
        │   │   ├── p_library->set_item_mesh_transform()
        │   │   ├── p_library->set_item_shapes() [StaticBody3Dから]
        │   │   └── p_library->set_item_navigation_mesh() [NavigationRegion3Dから]
        │   └── EditorInterface::make_mesh_previews()
        │       └── p_library->set_item_preview()
        ├── memdelete(scene)
        └── mesh_library->set_meta("_editor_source_scene", p_str)

_menu_cbk(MENU_OPTION_UPDATE_FROM_SCENE)
└── cd_update->popup_centered()
    └── [OK] _menu_update_confirm(apply_xforms)
        └── _import_scene_cbk(existing_path)
```

### データフロー図

```
[PackedSceneファイル]
    |
    | (ResourceLoader::load)
    v
[PackedScene]
    |
    | (instantiate)
    v
[Node3Dシーン]
    |
    | (_import_scene_parse_node)
    v
+----------------------------+
| MeshInstance3D             |
| - mesh                     |
| - cast_shadows_setting     |
| - surface_override_material|
+----------------------------+
    |
    +---> [MeshLibrary]
    |       - item_mesh
    |       - item_mesh_transform
    |       - item_mesh_cast_shadow
    |
    +---> [StaticBody3D子ノード]
    |       |
    |       v
    |     [CollisionShape3D]
    |       |
    |       v
    |     [item_shapes]
    |
    +---> [NavigationRegion3D子ノード]
            |
            v
          [item_navigation_mesh]
```

### 関連ファイル一覧

| ファイル | 役割 |
|----------|------|
| `editor/scene/3d/mesh_library_editor_plugin.h` | エディタクラス定義 |
| `editor/scene/3d/mesh_library_editor_plugin.cpp` | エディタ実装 |
| `scene/resources/3d/mesh_library.h` | MeshLibraryリソース定義 |
| `scene/resources/3d/mesh_library.cpp` | MeshLibraryリソース実装 |
| `scene/3d/mesh_instance_3d.h` | MeshInstance3Dノード |
| `scene/3d/physics/static_body_3d.h` | StaticBody3D（衝突用） |
| `scene/3d/navigation/navigation_region_3d.h` | NavigationRegion3D（ナビメッシュ用） |
| `editor/scene/3d/node_3d_editor_plugin.h` | Node3DEditor（メニュー配置先） |
| `editor/docks/inspector_dock.h` | InspectorDock（選択パス取得） |
| `editor/gui/editor_file_dialog.h` | ファイルダイアログ |
