# 画面設計書 11-Menubar - Edit

## 概要

本ドキュメントは、three.js エディタにおける編集操作メニュー（Menubar - Edit）の画面設計書である。このメニューは、3Dシーン内のオブジェクトに対する基本的な編集操作（元に戻す、やり直し、複製、削除、中央配置）を提供する。

### 本画面の処理概要

**業務上の目的・背景**：3Dシーン編集において、ユーザーが行った操作を取り消したり、オブジェクトの複製・削除といった基本的な編集作業を効率的に行うために必要なメニュー機能を提供する。特にUndo/Redo機能は、試行錯誤を繰り返しながら3Dモデルを作成する際に不可欠な機能であり、ユーザーの作業効率と安心感を大幅に向上させる。

**画面へのアクセス方法**：エディタメイン画面（editor/index.html）のメニューバー領域に常時表示される。「Edit」メニュータイトルをクリックすると、ドロップダウン形式でオプションが展開される。

**主要な操作・処理内容**：
1. **Undo（元に戻す）**：直前の操作を取り消し、1つ前の状態に戻す（ショートカット: CTRL+Z）
2. **Redo（やり直し）**：Undoで取り消した操作を再実行する（ショートカット: CTRL+SHIFT+Z）
3. **Center（中央配置）**：選択中のオブジェクトをその境界ボックスの中心に基づいて原点に配置する
4. **Clone（複製）**：選択中のオブジェクトを複製し、シーンに追加する
5. **Delete（削除）**：選択中のオブジェクトをシーンから削除する（ショートカット: DEL）

**画面遷移**：このメニューから直接的な画面遷移は発生しない。メニュー操作はViewport上の3Dシーンに対して作用し、Sidebar - Objectパネルの表示内容が更新される。

**権限による表示制御**：特別な権限制御は存在しない。ただし、Undo/Redoの有効・無効は履歴の状態に応じて動的に切り替わる（履歴がない場合はinactiveクラスが適用される）。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | Object3D | 主機能 | オブジェクトのクローン・削除操作のベースクラス |
| 124 | Vector3 | 補助機能 | オブジェクトの位置リセット・中央配置計算 |
| 132 | Box3 | 補助機能 | オブジェクトの境界ボックスから中央位置を計算 |

## 画面種別

メニュー（ドロップダウン）

## URL/ルーティング

エディタメイン画面の一部として `editor/index.html` に含まれる。独立したルーティングは持たない。

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 説明 |
|--------|----------|---------|------|
| 選択オブジェクト | 入力 | Object3D | 現在選択されているオブジェクト（editor.selected） |
| 履歴スタック | 入力 | Array | Undo/Redo用の操作履歴（editor.history.undos, editor.history.redos） |

## 表示項目

| 項目 | 表示内容 | 条件 |
|------|---------|------|
| Undo | 「元に戻す」+ ショートカットキー「CTRL+Z」 | 履歴がない場合はinactiveスタイル適用 |
| Redo | 「やり直し」+ ショートカットキー「CTRL+SHIFT+Z」 | 履歴がない場合はinactiveスタイル適用 |
| Center | 「中央配置」 | 常時表示 |
| Clone | 「複製」 | 常時表示 |
| Delete | 「削除」+ ショートカットキー「DEL」 | 常時表示 |

## イベント仕様

### 1-Undo（元に戻す）

- **トリガー**：メニュー項目クリックまたはCTRL+Zキー押下
- **処理内容**：`editor.undo()` を呼び出し、履歴スタックから直前のコマンドを取り出して逆操作を実行
- **画面更新**：Viewportのシーンが更新され、関連するSidebarパネルの表示が更新される

### 2-Redo（やり直し）

- **トリガー**：メニュー項目クリックまたはCTRL+SHIFT+Zキー押下
- **処理内容**：`editor.redo()` を呼び出し、Undoで取り消されたコマンドを再実行
- **画面更新**：Viewportのシーンが更新され、関連するSidebarパネルの表示が更新される

### 3-Center（中央配置）

- **トリガー**：メニュー項目クリック
- **処理内容**：
  1. 選択オブジェクトの存在確認（nullまたはparentがnullの場合は処理中止）
  2. `Box3.setFromObject()` でオブジェクトの境界ボックスを計算
  3. `aabb.getCenter()` で中心座標を取得
  4. 新しい位置を計算（現在位置 - 中心座標）
  5. `SetPositionCommand` を実行してオブジェクトを移動
- **画面更新**：Viewportでオブジェクトが移動し、Sidebar - Objectの位置情報が更新される

### 4-Clone（複製）

- **トリガー**：メニュー項目クリック
- **処理内容**：
  1. 選択オブジェクトの存在確認
  2. `SkeletonUtils.clone()` を使用してオブジェクトを深くコピー
  3. `AddObjectCommand` を実行してシーンに追加
- **画面更新**：Viewportに複製オブジェクトが表示され、Sidebar - Sceneの階層に追加される

### 5-Delete（削除）

- **トリガー**：メニュー項目クリックまたはDELキー押下
- **処理内容**：
  1. 選択オブジェクトの存在確認
  2. `RemoveObjectCommand` を実行してシーンから削除
- **画面更新**：Viewportからオブジェクトが消え、Sidebar - Sceneの階層から削除される

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

本画面はブラウザ上で動作する3Dエディタであり、データベースへの直接的な更新は行わない。すべての操作はメモリ上のシーングラフに対して行われ、IndexedDBへの保存はFile > Save操作時に行われる。

## メッセージ仕様

| メッセージ種別 | メッセージ内容 | 表示条件 |
|---------------|---------------|---------|
| なし | - | 本メニューでは特別なメッセージ表示はない |

## 例外処理

| 例外状況 | 処理内容 |
|---------|---------|
| オブジェクト未選択時の操作 | Center, Clone, Deleteは処理を中止（return）して何もしない |
| カメラ・シーン選択時の操作 | parent === null のチェックにより処理を中止 |
| 履歴が空の状態でのUndo/Redo | メニュー項目にinactiveクラスが適用され、視覚的に無効化される |

## 備考

- Undo/Redo機能は `editor.signals.historyChanged` シグナルを監視し、履歴の状態に応じてメニュー項目のスタイルを動的に更新する
- Clone機能は `SkeletonUtils.clone()` を使用しているため、スキンメッシュやボーン構造も正しく複製される
- すべての操作はCommandパターンで実装されており、Undo/Redo対応している

---

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

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

### 推奨読解順序

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

まず、Commandパターンの基本構造と、Editor内での履歴管理を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Command.js | `editor/js/Command.js` | Commandの基底クラス、execute/undoのインターフェース |
| 1-2 | History.js | `editor/js/History.js` | 履歴スタック（undos, redos）の管理方法 |

**読解のコツ**: Commandパターンでは、各操作が独立したクラスとして実装され、execute()とundo()メソッドを持つ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Menubar.Edit.js | `editor/js/Menubar.Edit.js` | メニューUI構築とイベントハンドラの登録 |

**主要処理フロー**:
1. **10-25行目**: UIPanel/UIRowを使用したメニュー構造の構築
2. **26-50行目**: Undo/Redoメニュー項目の作成とonClickハンドラの登録
3. **52-74行目**: `onHistoryChanged()` 関数でUndo/Redo可否の動的更新
4. **80-102行目**: Centerメニュー項目の実装（Box3を使用した中央計算）
5. **104-120行目**: Cloneメニュー項目の実装（SkeletonUtils.clone使用）
6. **122-139行目**: Deleteメニュー項目の実装

#### Step 3: コマンドクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AddObjectCommand.js | `editor/js/commands/AddObjectCommand.js` | オブジェクト追加のexecute/undo処理 |
| 3-2 | RemoveObjectCommand.js | `editor/js/commands/RemoveObjectCommand.js` | オブジェクト削除と親・インデックスの保持 |
| 3-3 | SetPositionCommand.js | `editor/js/commands/SetPositionCommand.js` | 位置変更のexecute/undo処理 |

**主要処理フロー**:
- **AddObjectCommand 27-31行目**: execute()でeditor.addObject()とeditor.select()を呼び出し
- **RemoveObjectCommand 36-39行目**: execute()でeditor.removeObject()とeditor.deselect()を呼び出し
- **SetPositionCommand 38-43行目**: execute()でposition.copy()とupdateMatrixWorld()を呼び出し

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

```
MenubarEdit (Menubar.Edit.js)
    │
    ├─ undo.onClick()
    │      └─ editor.undo() → History.undo()
    │
    ├─ redo.onClick()
    │      └─ editor.redo() → History.redo()
    │
    ├─ center.onClick()
    │      ├─ Box3.setFromObject(object)
    │      ├─ aabb.getCenter(center)
    │      └─ editor.execute(SetPositionCommand)
    │
    ├─ clone.onClick()
    │      ├─ SkeletonUtils.clone(object)
    │      └─ editor.execute(AddObjectCommand)
    │
    └─ delete.onClick()
           └─ editor.execute(RemoveObjectCommand)
```

### データフロー図

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

editor.selected ───────▶ Menubar.Edit.js ──────────▶ シーングラフ更新
                              │
editor.history ────────────────┘                    ▶ Sidebar更新

                                                    ▶ Viewport再描画
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Menubar.Edit.js | `editor/js/Menubar.Edit.js` | ソース | Editメニューの主要実装 |
| AddObjectCommand.js | `editor/js/commands/AddObjectCommand.js` | ソース | オブジェクト追加コマンド |
| RemoveObjectCommand.js | `editor/js/commands/RemoveObjectCommand.js` | ソース | オブジェクト削除コマンド |
| SetPositionCommand.js | `editor/js/commands/SetPositionCommand.js` | ソース | 位置変更コマンド |
| SkeletonUtils.js | `examples/jsm/utils/SkeletonUtils.js` | ソース | スケルトン対応のclone関数 |
| ui.js | `editor/js/libs/ui.js` | ソース | UIコンポーネント（UIPanel, UIRow等） |
| Editor.js | `editor/js/Editor.js` | ソース | editor.undo(), editor.redo(), editor.execute()の実装 |
| History.js | `editor/js/History.js` | ソース | 履歴管理（undos, redos配列） |
