# 画面設計書 14-出力パネル

## 概要

本ドキュメントは、Godot Engineエディタにおける出力パネル（Output Panel / EditorLog）の画面設計書である。出力パネルは、エディタおよび実行中のプロジェクトからの標準出力、エラー、警告メッセージを表示するボトムパネルである。

### 本画面の処理概要

出力パネルは、エディタのログメッセージ、スクリプトの`print()`出力、エラーメッセージ、警告メッセージを一元的に表示する機能を提供する。メッセージタイプ別のフィルタリング、テキスト検索、重複メッセージの折りたたみ、エラー発生箇所へのジャンプなどの機能を持つ。

**業務上の目的・背景**：ゲーム開発では、デバッグ情報の出力やエラー/警告の確認が頻繁に必要となる。本画面は、プロジェクトの実行ログ、スクリプトエラー、エディタ操作のログを統合的に表示し、問題の早期発見と解決を支援する。特にエラー発生箇所へのワンクリックジャンプ機能は、デバッグ効率を大幅に向上させる。

**画面へのアクセス方法**：エディタ画面下部のボトムパネルに常設。ショートカットキー「Alt+O」（ED_SHORTCUTで定義された「bottom_panels/toggle_output_bottom_panel」）でトグル可能。デフォルトでは下部ドックスロット（DOCK_SLOT_BOTTOM）に配置される。

**主要な操作・処理内容**：
1. ログメッセージの表示: 標準出力、エラー、警告、エディタメッセージを色分け表示
2. メッセージフィルタリング: メッセージタイプ（標準/エラー/警告/エディタ）別のトグルフィルタ
3. テキスト検索: 検索ボックスによるメッセージのフィルタリング
4. 重複メッセージの折りたたみ: 同一メッセージの回数表示
5. ログのクリア: 全メッセージの消去
6. テキストのコピー: 選択テキストまたは全文のクリップボードコピー
7. エラー箇所へのジャンプ: エラーメッセージのURLクリックでソースコードへ遷移
8. 状態の永続化: フィルタ設定と表示状態の保存

**画面遷移**：エラーメッセージ内のファイルパスをクリックすると、スクリプトエディタで該当ファイルの該当行が開く。外部ソースファイル（.cpp/.h等）の場合は外部エディタで開く。

**権限による表示制御**：特になし。すべてのユーザーが全機能を利用可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | ScriptEditor | 遷移先機能 | エラー箇所へのジャンプ |
| - | InspectorDock | 遷移先機能 | リソース編集画面への遷移 |
| - | ErrorHandlerList | 主機能 | エラー/警告メッセージの受信 |
| - | UndoRedo | API連携 | エディタ操作ログの受信 |
| - | EditorSettings | API連携 | 表示行数上限の取得 |

## 画面種別

一覧（ボトムパネル）

## URL/ルーティング

エディタ内部ドック（URLなし）

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 必須 | 説明 |
|--------|----------|----------|------|------|
| メッセージ | 入力 | String | - | 表示するログメッセージ |
| メッセージタイプ | 入力 | MessageType | - | MSG_TYPE_STD/ERROR/WARNING/EDITOR |
| 検索テキスト | 入力 | String | - | フィルタリング用検索文字列 |
| フィルタ状態 | 入力 | bool | - | 各メッセージタイプの表示/非表示 |
| 折りたたみ状態 | 入力 | bool | - | 重複メッセージ折りたたみのオン/オフ |

## 表示項目

| 項目名 | データ型 | 表示形式 | 説明 |
|--------|----------|----------|------|
| ログメッセージ | RichTextLabel | BBCode対応テキスト | メッセージ本文 |
| エラーアイコン | Texture2D | 画像 | エラーメッセージのアイコン |
| 警告アイコン | Texture2D | 画像 | 警告メッセージのアイコン |
| メッセージカウント | int | ボタンテキスト | 各タイプのメッセージ件数 |
| 重複回数 | int | 太字テキスト | 折りたたみ時の重複回数表示 |

## イベント仕様

### 1-エラーハンドラ（_error_handler）

エンジン内部でエラー/警告が発生すると、メッセージが追加される。

- **処理フロー**:
  1. エラーハンドラコールバックが呼ばれる
  2. エラー情報からメッセージ文字列を構築（`[url]ファイル:行[/url] - エラー内容`形式）
  3. メインスレッドでない場合はMessageQueueを経由
  4. `add_message()`でメッセージを追加

### 2-メッセージ追加（add_message）

メッセージが追加されると、ログに表示される。

- **処理フロー**:
  1. 改行で分割して各行を個別メッセージとして処理
  2. `_process_message()`で重複チェック
  3. 前回と同一メッセージの場合はカウントを増加
  4. 異なるメッセージの場合はmessagesリストに追加
  5. `_add_log_line()`でRichTextLabelに表示
  6. メッセージタイプのカウンターを更新

### 3-ログクリア（_clear_request）

「Clear」ボタンをクリックすると、全メッセージが消去される。

- **処理フロー**:
  1. `log->clear()`でRichTextLabelをクリア
  2. `messages.clear()`でメッセージリストをクリア
  3. `_reset_message_counts()`で全カウンターをリセット
  4. ドックタブアイコンをクリア

### 4-テキストコピー（_copy_request）

「Copy」ボタンをクリックすると、テキストがクリップボードにコピーされる。

- **処理フロー**:
  1. 選択テキストを取得（`get_selected_text()`）
  2. 選択がない場合は全文を取得（`get_parsed_text()`）
  3. クリップボードにコピー

### 5-フィルタ切り替え（_set_filter_active）

フィルタボタンをトグルすると、該当タイプのメッセージ表示を切り替える。

- **処理フロー**:
  1. フィルタのactive状態を更新
  2. 状態保存タイマーを開始
  3. `_rebuild_log()`でログを再構築

### 6-検索テキスト変更（_search_changed）

検索ボックスにテキストを入力すると、メッセージがフィルタリングされる。

- **処理フロー**:
  1. `_rebuild_log()`でログを再構築
  2. `_check_display_message()`で各メッセージの表示可否を判定
  3. BBCodeタグを含むメッセージはパース後のテキストでも検索

### 7-折りたたみ切り替え（_set_collapse）

「Collapse」ボタンをトグルすると、重複メッセージの折りたたみを切り替える。

- **処理フロー**:
  1. `collapse`フラグを更新
  2. 状態保存タイマーを開始
  3. `_rebuild_log()`でログを再構築
  4. 折りたたみ時は同一メッセージを1行に集約し、回数を表示

### 8-メタクリック（_meta_clicked）

エラーメッセージ内のURLをクリックすると、該当ファイルが開く。

- **処理フロー**:
  1. URLから「ファイルパス:行番号」を抽出
  2. `res://`で始まるパスの場合: ResourceLoaderで読み込み、ScriptEditorで開く
  3. `.cpp/.h/.mm/.hpp`の場合: 外部エディタで開く、失敗時はシェルで開く
  4. その他: シェルでURLを開く

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

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

| 操作（イベント） | 対象ファイル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 状態保存 | editor_layout.cfg | UPDATE | フィルタ状態・折りたたみ状態・検索表示状態を保存 |

### テーブル別更新項目詳細

#### editor_layout.cfg（ConfigFile形式）

| 操作 | 項目（セクション/キー） | 更新値・取得条件 | 備考 |
|-----|------------------------|-----------------|------|
| UPDATE | editor_log/log_filter_0 | bool | MSG_TYPE_STDフィルタ状態 |
| UPDATE | editor_log/log_filter_1 | bool | MSG_TYPE_ERRORフィルタ状態 |
| UPDATE | editor_log/log_filter_3 | bool | MSG_TYPE_WARNINGフィルタ状態 |
| UPDATE | editor_log/log_filter_4 | bool | MSG_TYPE_EDITORフィルタ状態 |
| UPDATE | editor_log/collapse | bool | 折りたたみ状態 |
| UPDATE | editor_log/show_search | bool | 検索ボックス表示状態 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| - | 起動 | {GODOT_VERSION_FULL_NAME} (c) 2007-present Juan Linietsky, Ariel Manzur & Godot Contributors. | エディタ起動時 |
| - | エラー | ERROR: {エラー内容} | エラー発生時 |
| - | 警告 | WARNING: {警告内容} | 警告発生時 |
| - | プレースホルダ | Filter Messages | 検索ボックス |

## 例外処理

| 例外状態 | 処理内容 |
|---------|---------|
| 非メインスレッドからのメッセージ | MessageQueueを経由してメインスレッドで処理 |
| ログ更新中のメッセージ追加 | 無視してRTLデータ破損を防止 |
| 行数上限超過 | 古い行を削除（`remove_paragraph(0, true)`） |
| BBCode解析エラー | `pop_all()`で未クローズタグをクリア |

## 備考

- 行数上限はEditorSettings「run/output/max_lines」で設定可能（デフォルト10000行）
- RichTextLabelはスレッド処理（`set_threaded(true)`）で高速化
- 状態保存は2秒のタイマー遅延で頻繁な書き込みを抑制
- BBCode対応により、リンク、色、太字などの装飾が可能
- エラー/警告発生時はドックタブにアイコンが表示される

---

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

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

### 推奨読解順序

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

まず、ログメッセージとフィルタのデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | editor_log.h | `editor/editor_log.h` | MessageType列挙型（46-52行目）とLogMessage構造体（55-68行目）を確認 |
| 1-2 | editor_log.h | `editor/editor_log.h` | LogFilter構造体（81-124行目）のフィルタ管理ロジックを確認 |
| 1-3 | editor_log.h | `editor/editor_log.h` | theme_cache構造体（70-78行目）のテーマキャッシュを確認 |

**読解のコツ**: `MessageType`は5種類（STD, ERROR, STD_RICH, WARNING, EDITOR）あり、`LogFilter`はボタンとアクティブ状態、メッセージ件数を管理する。`type_filter_map`でMessageTypeからLogFilterへのマッピングを行う。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | editor_log.cpp | `editor/editor_log.cpp` | コンストラクタ（489-624行目）でUIの初期化を確認 |

**主要処理フロー**:
1. **489-494行目**: ドック設定（名前、アイコン、ショートカット、デフォルトスロット、レイアウト）
2. **496-500行目**: 状態保存タイマーの作成
3. **515-526行目**: RichTextLabel（ログ表示）の作成と設定
4. **529-536行目**: 検索ボックスの作成
5. **547-563行目**: Clear/Copyボタンの作成
6. **574-593行目**: Collapse/Searchボタンの作成
7. **598-617行目**: メッセージタイプフィルタボタンの作成
8. **621-623行目**: エラーハンドラの登録

#### Step 3: メッセージ処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | editor_log.cpp | `editor/editor_log.cpp` | `_error_handler()`（51-68行目）のエラー受信処理 |
| 3-2 | editor_log.cpp | `editor/editor_log.cpp` | `add_message()`（276-288行目）のメッセージ追加処理 |
| 3-3 | editor_log.cpp | `editor/editor_log.cpp` | `_process_message()`（258-274行目）の重複処理 |
| 3-4 | editor_log.cpp | `editor/editor_log.cpp` | `_add_log_line()`（383-463行目）のログ表示処理 |

**主要処理フロー**:
- **51-68行目**: エラーハンドラでエラー情報からBBCode形式のURLリンクを生成
- **282行目**: 改行で分割して各行を個別メッセージとして処理
- **259-263行目**: 前回と同一メッセージの場合はカウントを増加
- **406-432行目**: メッセージタイプに応じた色・アイコンの設定
- **436-440行目**: 折りたたみ時の回数表示

#### Step 4: フィルタ・検索処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | editor_log.cpp | `editor/editor_log.cpp` | `_set_filter_active()`（465-469行目）のフィルタ切り替え |
| 4-2 | editor_log.cpp | `editor/editor_log.cpp` | `_check_display_message()`（355-381行目）の表示判定 |
| 4-3 | editor_log.cpp | `editor/editor_log.cpp` | `_rebuild_log()`（304-353行目）のログ再構築 |

**主要処理フロー**:
- **356-361行目**: フィルタのアクティブ状態と検索テキストをチェック
- **363-378行目**: BBCodeタグを含むメッセージはパース後テキストでも検索
- **316-337行目**: 行数制限に基づいて開始位置を計算

#### Step 5: 状態永続化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | editor_log.cpp | `editor/editor_log.cpp` | `_save_state()`（166-181行目）の状態保存 |
| 5-2 | editor_log.cpp | `editor/editor_log.cpp` | `_load_state()`（183-203行目）の状態読み込み |

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

```
EditorLog（エントリーポイント）
    │
    ├─ コンストラクタ
    │      ├─ UI初期化（RichTextLabel, Button, LineEdit）
    │      ├─ LogFilter作成（STD, ERROR, WARNING, EDITOR）
    │      └─ add_error_handler()（エラーハンドラ登録）
    │
    ├─ _error_handler()（静的コールバック）
    │      └─ add_message()
    │
    ├─ add_message()
    │      └─ _process_message()
    │             ├─ messages配列への追加
    │             ├─ _add_log_line()
    │             │      ├─ _check_display_message()
    │             │      └─ log->append_text() / add_text()
    │             └─ type_filter_map更新
    │
    ├─ _set_filter_active()
    │      ├─ _start_state_save_timer()
    │      └─ _rebuild_log()
    │             └─ _add_log_line()（各メッセージ）
    │
    ├─ _search_changed()
    │      └─ _rebuild_log()
    │
    ├─ _clear_request()
    │      ├─ log->clear()
    │      ├─ messages.clear()
    │      └─ _reset_message_counts()
    │
    └─ _meta_clicked()
           ├─ ScriptEditor::edit()（res://パス）
           └─ ScriptEditorPlugin::open_in_external_editor()（.cpp/.h等）
```

### データフロー図

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

エンジンエラー ──────────▶ _error_handler() ──────────▶ メッセージ追加
                               │
print() ──────────────────────▶ add_message() ──────────▶ RichTextLabel表示
                               │
UndoRedo ─────────────────────▶ _undo_redo_cbk() ──────▶ エディタメッセージ
                               │
                               ▼
                        _process_message()
                               │
                               ▼
                        messages配列
                               │
                               ▼
                        _add_log_line()
                               │
                        ┌──────┴──────┐
                        ▼             ▼
               _check_display    log->append_text()
               _message()              │
                   │                   ▼
                   ▼             RichTextLabel
            フィルタ判定              （BBCode）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| editor_log.cpp | `editor/editor_log.cpp` | ソース | 出力パネルの実装 |
| editor_log.h | `editor/editor_log.h` | ヘッダ | 出力パネルのクラス定義 |
| editor_dock.h | `editor/docks/editor_dock.h` | ヘッダ | ドック基底クラス |
| rich_text_label.h | `scene/gui/rich_text_label.h` | ヘッダ | BBCode対応テキスト表示 |
| script_editor_plugin.cpp | `editor/script/script_editor_plugin.cpp` | ソース | スクリプトエディタ連携 |
| inspector_dock.cpp | `editor/docks/inspector_dock.cpp` | ソース | インスペクタ連携 |
| editor_paths.h | `editor/file_system/editor_paths.h` | ヘッダ | 設定ファイルパス取得 |
| editor_settings.h | `editor/settings/editor_settings.h` | ヘッダ | エディタ設定取得 |
