# 画面設計書 52-スケルトン3Dエディタ

## 概要

本ドキュメントは、Godot Engineエディターにおける「スケルトン3Dエディタ」の画面設計を定義するものである。スケルトン3Dエディタは、Skeleton3Dノードを選択した際にインスペクター内およびメニューパネル上に表示される専用編集インターフェースを提供し、3Dキャラクターのボーン構造やポーズを視覚的に編集できるエディタープラグインである。

### 本画面の処理概要

スケルトン3Dエディタは、3Dアニメーション開発において不可欠なスケルトン（骨格）の編集機能を提供する。ボーン階層の可視化、個々のボーンのトランスフォーム編集、ポーズのリセット・適用、物理ボーンの自動生成、スケルトンプロファイルのエクスポートなど、包括的なスケルトン管理機能を備える。

**業務上の目的・背景**：3Dゲームやアニメーション制作において、キャラクターやクリーチャーの動きを実現するにはスケルトン（骨格）システムが不可欠である。スケルトン3Dエディタは、インポートされた3Dモデルのボーン構造を確認・調整し、ポーズの編集やアニメーションキーフレームの挿入を効率的に行うためのツールを提供する。また、ラグドール物理シミュレーション用の物理ボーン自動生成機能により、物理演算対応キャラクターの作成を容易にする。

**画面へのアクセス方法**：シーンツリードックまたは3Dビューポートにて、Skeleton3Dノードを選択すると、インスペクタードック内に専用のスケルトン編集UIが表示される。同時に、3Dエディターのメニューパネル上部にもSkeleton3Dメニューとオプションボタンが表示される。

**主要な操作・処理内容**：
1. ボーン階層の表示・選択：ツリービューでボーン階層を確認し、個別のボーンを選択
2. ボーントランスフォーム編集：選択ボーンの位置（Position）、回転（Rotation）、スケール（Scale）を編集
3. ポーズリセット：全ボーンまたは選択ボーンのポーズをデフォルト状態にリセット
4. ポーズをRestに適用：現在のポーズをボーンのRest（基準）トランスフォームとして設定
5. 物理スケルトン作成：PhysicalBone3Dノードを自動生成してラグドール物理を設定
6. スケルトンプロファイルエクスポート：SkeletonProfileリソースとしてボーン構造を出力
7. アニメーションキー挿入：アニメーションエディターと連携してキーフレームを挿入
8. 編集モード切り替え：ボーン上に操作ハンドルを表示するモードを切り替え

**画面遷移**：エディタメイン画面のインスペクタードック内に統合されて表示される。Skeleton3Dノードの選択解除によりUIは非表示となる。ボーンメタデータの追加時はAddMetadataDialogが表示される。

**権限による表示制御**：特にロールベースの制御はない。エディター環境での利用が前提であり、すべてのユーザーが同等の機能にアクセス可能。ただし、キーフレーム挿入機能はアニメーションエディターがキーイングモード（keying enabled）の場合のみ有効。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 34 | スケルトン/ボーン | 主機能 | Skeleton3Dのボーン構造・ポーズ編集 |
| 35 | IK（逆運動学） | 補助機能 | IK設定・プレビュー |

## 画面種別

編集（3Dノード専用エディター/インスペクター拡張）

## URL/ルーティング

デスクトップアプリケーションのため、URLベースのルーティングは存在しない。Skeleton3Dノード選択時に自動的にアクティブ化される。

## 入出力項目

| 項目名 | 型 | 入力/出力 | 説明 |
|--------|------|----------|------|
| bone_enabled | bool | 入出力 | ボーンのポーズ有効/無効フラグ |
| bone_position | Vector3 | 入出力 | ボーンのポーズ位置 |
| bone_rotation | Quaternion | 入出力 | ボーンのポーズ回転 |
| bone_scale | Vector3 | 入出力 | ボーンのポーズスケール |
| bone_rest | Transform3D | 入出力 | ボーンのRest（基準）トランスフォーム |
| bone_parent | int | 入出力 | 親ボーンのインデックス |
| bone_meta | Variant | 入出力 | ボーンメタデータ（カスタムデータ） |

## 表示項目

| 項目名 | 型 | 説明 |
|--------|------|------|
| ボーンツリー | Tree | ボーン階層をツリー形式で表示 |
| ポーズエディター | VBoxContainer | 選択ボーンのトランスフォーム編集UI |
| Restセクション | EditorInspectorSection | 選択ボーンのRestトランスフォーム表示 |
| ボーンメタデータセクション | EditorInspectorSection | 選択ボーンのカスタムメタデータ編集 |
| Skeleton3Dメニュー | MenuButton | スケルトン操作メニュー |
| 編集モードボタン | Button | ボーンハンドル表示切り替え |
| キーイングボタン群 | HBoxContainer | アニメーションキー挿入関連ボタン |
| ボーンギズモ | 3D表示 | 3Dビューポート上のボーン表示・選択ハンドル |

## イベント仕様

### 1-ボーン選択

ボーンツリーでアイテムを選択すると、そのボーンが選択状態となり、ポーズエディターに選択ボーンのトランスフォームが表示される。3Dビューポート上のギズモも更新される。

### 2-ポーズ編集

ポーズエディター内のPosition/Rotation/Scaleプロパティを変更すると、対応するボーンのトランスフォームが更新される。Undo/Redo対応。

### 3-全ポーズリセット

Skeleton3Dメニュー > 「Reset All Bone Poses」を選択すると、すべてのボーンのポーズがデフォルト状態にリセットされる。

### 4-選択ポーズリセット

Skeleton3Dメニュー > 「Reset Selected Poses」を選択すると、現在選択中のボーンのポーズのみがリセットされる。

### 5-全ポーズをRestに適用

Skeleton3Dメニュー > 「Apply All Poses to Rests」を選択すると、現在のすべてのボーンポーズがRestトランスフォームとして設定される。

### 6-選択ポーズをRestに適用

Skeleton3Dメニュー > 「Apply Selected Poses to Rests」を選択すると、選択ボーンのポーズのみがRestに適用される。

### 7-物理スケルトン作成

Skeleton3Dメニュー > 「Create Physical Skeleton」を選択すると、PhysicalBoneSimulator3DおよびPhysicalBone3Dノードが自動生成され、ラグドール物理が設定される。

### 8-スケルトンプロファイルエクスポート

Skeleton3Dメニュー > 「Export Skeleton Profile」を選択すると、ファイルダイアログが開き、SkeletonProfileリソースとして現在のスケルトン構造を保存できる。

### 9-編集モード切り替え

Edit Modeボタンをトグルすると、3Dビューポート上にボーンハンドルが表示/非表示される。ハンドル表示時はボーンを直接クリックして選択可能。

### 10-キーフレーム挿入

位置/回転/スケールマスクボタンで挿入対象を選択し、キー挿入ボタンを押下すると、選択ボーンまたは全ボーンのトランスフォームがアニメーションにキーフレームとして挿入される。

### 11-ボーンのドラッグ＆ドロップ

ボーンツリー内でボーンをドラッグ＆ドロップすると、ボーンの親子関係を変更できる。

### 12-ボーンリバート

ボーンツリーの各ボーンに表示されるRevertボタンをクリックすると、そのボーンのプロパティがデフォルト値に戻される。

### 13-ボーンメタデータ追加

「Add Bone Metadata」ボタンをクリックすると、AddMetadataDialogが表示され、新規メタデータを追加できる。

## データベース更新仕様

本機能はデータベースを使用しない。編集内容はSkeleton3Dノードのプロパティおよびシーンファイル（.tscn/.scn）に保存される。

### 操作別データ影響一覧

| 操作（イベント） | 対象リソース | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ポーズ編集 | Skeleton3D | UPDATE | set_bone_pose_position/rotation/scale()で更新 |
| ポーズリセット | Skeleton3D | UPDATE | reset_bone_pose()/reset_bone_poses()で初期化 |
| RestへポーズをApply | Skeleton3D | UPDATE | set_bone_rest()でRestトランスフォーム更新 |
| 物理スケルトン作成 | シーン | INSERT | PhysicalBoneSimulator3D/PhysicalBone3D/CollisionShape3D追加 |
| ボーン親変更 | Skeleton3D | UPDATE | set_bone_parent()で親インデックス変更 |
| メタデータ編集 | Skeleton3D | UPDATE | set_bone_meta()でメタデータ設定 |
| プロファイルエクスポート | ファイル | INSERT | SkeletonProfileリソースファイル作成 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| MSG_NO_BONES | 警告 | Cannot create a physical skeleton for a Skeleton3D node with no bones. | ボーンなしで物理スケルトン作成試行時 |
| MSG_EXPORT_NO_BONES | 警告 | Cannot export a SkeletonProfile for a Skeleton3D node with no bones. | ボーンなしでプロファイルエクスポート試行時 |
| MSG_SAVE_ERROR | エラー | Error saving file: {path} | プロファイル保存失敗時 |
| ACTION_SET_TRANSFORM | 成功 | Set Bone Transform | ボーントランスフォーム変更時（Undo履歴用） |
| ACTION_SET_REST | 成功 | Set Bone Rest | Restトランスフォーム変更時（Undo履歴用） |
| ACTION_SET_PARENTAGE | 成功 | Set Bone Parentage | ボーン親子関係変更時（Undo履歴用） |
| ACTION_CREATE_PHYSICAL | 成功 | Create physical bones | 物理スケルトン作成時（Undo履歴用） |
| ACTION_REVERT | 成功 | Revert Bone | ボーンリバート時（Undo履歴用） |
| ACTION_ADD_META | 成功 | Add metadata '{name}' to bone '{bone}' | メタデータ追加時（Undo履歴用） |
| ACTION_MODIFY_META | 成功 | Modify metadata '{name}' for bone '{bone}' | メタデータ変更時（Undo履歴用） |
| ACTION_REMOVE_META | 成功 | Remove metadata '{name}' from bone '{bone}' | メタデータ削除時（Undo履歴用） |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| Skeleton3Dにボーンがない | 物理スケルトン作成・プロファイルエクスポートが無効化、警告メッセージ表示 |
| アニメーションエディターがキーイング無効 | キー挿入ボタン群が非表示 |
| アニメーションが読み取り専用 | キー挿入時に読み取り専用ダイアログ表示 |
| ボーン未選択時の選択操作 | 選択ポーズリセット/Apply操作がスキップされる |

## 備考

- すべての編集操作はUndo/Redo対応（EditorUndoRedoManager経由）
- ボーンツリーはドラッグ＆ドロップで親子関係変更が可能
- ボーンプロパティに変更がある場合、ツリーアイテムにRevertボタンが表示される
- 物理スケルトン作成時は、カプセル形状のCollisionShape3Dが各ボーン間に自動生成される
- アニメーションキー挿入は、アニメーションプレイヤーエディター（AnimationPlayerEditor）と連携して動作
- SkeletonProfileエクスポート時は、ボーン位置からハンドル位置が自動計算される

---

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

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

### 推奨読解順序

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

まず、Skeleton3Dノードのボーン管理方法を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | skeleton_3d.h | `scene/3d/skeleton_3d.h` | Skeleton3Dクラス定義、ボーン配列の構造 |
| 1-2 | skeleton_profile.h | `scene/resources/skeleton_profile.h` | SkeletonProfileリソースの構造 |

**読解のコツ**: Skeleton3Dは内部でボーンをVector<Bone>形式で保持し、各Boneがname, parent, rest, pose等を持つ構造を理解する。

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

プラグインの登録とインスペクターへの統合方法を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | skeleton_3d_editor_plugin.h | `editor/scene/3d/skeleton_3d_editor_plugin.h` | クラス定義、Skeleton3DEditor、EditorInspectorPluginSkeleton |
| 2-2 | skeleton_3d_editor_plugin.cpp | `editor/scene/3d/skeleton_3d_editor_plugin.cpp` | EditorInspectorPluginSkeleton::can_handle(), parse_begin() |

**主要処理フロー**:
1. **can_handle()**: Skeleton3Dオブジェクトかどうかを判定
2. **parse_begin()**: Skeleton3DEditorをインスペクターに追加

#### Step 3: UI構築を理解する

インスペクター内のUI構築とツールバー設置を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | skeleton_3d_editor_plugin.cpp | `editor/scene/3d/skeleton_3d_editor_plugin.cpp` | create_editors()メソッド（1026-1181行） |

**主要処理フロー**:
- **1039-1060行**: Skeleton3Dメニューの構築
- **1065-1073行**: Edit Modeボタンの設定
- **1081-1149行**: キーイングボタン群の設定
- **1151-1178行**: ボーンツリーとポーズエディターの設定

#### Step 4: ボーン編集処理を理解する

ポーズ編集、リセット、Rest適用などの主要操作を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | skeleton_3d_editor_plugin.cpp | `editor/scene/3d/skeleton_3d_editor_plugin.cpp` | _on_click_skeleton_option()（386-415行） |
| 4-2 | skeleton_3d_editor_plugin.cpp | `editor/scene/3d/skeleton_3d_editor_plugin.cpp` | reset_pose()（417-450行）、pose_to_rest()（511-540行） |

**主要処理フロー**:
- **386-415行**: メニューオプション選択時の振り分け
- **417-450行**: ポーズリセット処理（全体/選択）
- **511-540行**: ポーズをRestに適用

#### Step 5: 物理スケルトン生成を理解する

PhysicalBone3D自動生成の仕組みを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | skeleton_3d_editor_plugin.cpp | `editor/scene/3d/skeleton_3d_editor_plugin.cpp` | create_physical_skeleton()（542-603行） |
| 5-2 | skeleton_3d_editor_plugin.cpp | `editor/scene/3d/skeleton_3d_editor_plugin.cpp` | create_physical_bone()（605-644行） |

**主要処理フロー**:
- **542-603行**: PhysicalBoneSimulator3D作成、子ボーンごとにPhysicalBone3D生成
- **605-644行**: 個別PhysicalBone3DとCollisionShape3D（カプセル）の生成

#### Step 6: ボーンプロパティエディタを理解する

BonePropertiesEditorの構造と動作を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | skeleton_3d_editor_plugin.cpp | `editor/scene/3d/skeleton_3d_editor_plugin.cpp` | BonePropertiesEditor::create_editors()（53-121行） |
| 6-2 | skeleton_3d_editor_plugin.cpp | `editor/scene/3d/skeleton_3d_editor_plugin.cpp` | _value_changed()（133-150行） |

**主要処理フロー**:
- **53-121行**: Position/Rotation/Scale/Restプロパティエディタの構築
- **133-150行**: プロパティ変更時のUndo/Redo登録

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

```
Skeleton3DEditorPlugin (エディタープラグイン)
    │
    ├─ EditorInspectorPluginSkeleton (インスペクタープラグイン)
    │      ├─ can_handle() → Skeleton3D判定
    │      └─ parse_begin() → Skeleton3DEditor追加
    │
    ├─ Skeleton3DEditor (メインUI)
    │      ├─ create_editors() → UI構築
    │      ├─ update_joint_tree() → ボーンツリー更新
    │      ├─ reset_pose() → ポーズリセット
    │      ├─ pose_to_rest() → RestへApply
    │      ├─ create_physical_skeleton() → 物理ボーン生成
    │      ├─ export_skeleton_profile() → プロファイルエクスポート
    │      └─ insert_keys() → アニメーションキー挿入
    │
    ├─ BonePropertiesEditor (プロパティ編集)
    │      ├─ create_editors() → プロパティUI構築
    │      ├─ set_target() → 編集対象ボーン設定
    │      └─ _value_changed() → 値変更処理
    │
    └─ Skeleton3DGizmoPlugin (ギズモプラグイン)
           ├─ get_bones_mesh() → ボーンメッシュ生成
           ├─ skeleton_intersect_ray() → ボーン選択判定
           ├─ subgizmos_intersect_ray() → サブギズモ選択
           ├─ get_subgizmo_transform() → 選択ボーン位置取得
           ├─ set_subgizmo_transform() → ボーン位置更新
           └─ commit_subgizmos() → Undo登録
```

### データフロー図

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

ボーンツリー選択
        │
        ▼
_joint_tree_selection_changed()
        │
        ▼
pose_editor->set_target() ───▶ ポーズエディター更新
        │
        ▼
3Dギズモ更新

プロパティ変更
        │
        ▼
_value_changed()
        │
        ▼
EditorUndoRedoManager ───▶ Undo履歴登録
        │
        ▼
Skeleton3D::set_bone_pose_xxx() ───▶ ボーン更新
        │
        ▼
update_joint_tree() ───▶ UI更新

物理スケルトン作成
        │
        ▼
create_physical_skeleton()
        │
        ├─ PhysicalBoneSimulator3D作成
        │
        └─ 各ボーンペアに対して
              │
              ▼
        create_physical_bone()
              │
              ├─ PhysicalBone3D作成
              └─ CollisionShape3D（カプセル）作成
                    │
                    ▼
              シーンツリーに追加
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| skeleton_3d_editor_plugin.cpp | `editor/scene/3d/skeleton_3d_editor_plugin.cpp` | ソース | スケルトン3Dエディター本体実装 |
| skeleton_3d_editor_plugin.h | `editor/scene/3d/skeleton_3d_editor_plugin.h` | ヘッダー | クラス定義、列挙型、メンバ変数 |
| skeleton_3d.cpp | `scene/3d/skeleton_3d.cpp` | ソース | Skeleton3Dノード実装 |
| skeleton_3d.h | `scene/3d/skeleton_3d.h` | ヘッダー | Skeleton3Dノード定義 |
| skeleton_profile.cpp | `scene/resources/skeleton_profile.cpp` | ソース | SkeletonProfileリソース実装 |
| physical_bone_3d.cpp | `scene/3d/physics/physical_bone_3d.cpp` | ソース | PhysicalBone3D実装 |
| physical_bone_simulator_3d.cpp | `scene/3d/physics/physical_bone_simulator_3d.cpp` | ソース | PhysicalBoneSimulator3D実装 |
| animation_player_editor_plugin.cpp | `editor/animation/animation_player_editor_plugin.cpp` | ソース | アニメーションキー挿入連携 |
| editor_properties.cpp | `editor/inspector/editor_properties.cpp` | ソース | プロパティエディタ基盤 |
| add_metadata_dialog.cpp | `editor/inspector/add_metadata_dialog.cpp` | ソース | メタデータ追加ダイアログ |
