Bicameral Engine
GPU-resident engine for a magic-research open-world game
Loading...
Searching...
No Matches
editor_overlay.h
Go to the documentation of this file.
1// editor_overlay.h — エディタの殻: 窓に重ねる Dear ImGui のパネル(T-0023、docs/design/14 §1〜§3・§2「実装(T-0023)」)。
2//
3// データの流れ:
4// 窓のメッセージ → Window の MessageHook → ImGui(Win32 の backend)。ImGui が使っている入力は、フレームのループが
5// WantsPointer / WantsKeyboard を見てカメラとつつきに渡さない。
6// フレームのループ → EditorStatus(読み戻した刻み・ハッシュ・重さ。読むだけ)→ Build がパネルを作る
7// → 押されたボタンは TimeRequest(editor/time_control)で返す。世界には触れない(CPU は View と Controller。D-107)。
8// → Submit がシーンの描画の後・Present の前に、バックバッファへパネルを重ねるリストを direct キューへ投げる。
9// エディタは CPU を好きなだけ使ってよい(ADR-0001)。世界を変える操作は、ここからもコマンド(sim/command.h)として渡す
10// (実験室〔editor/lab_panel〕の箱に物を置く操作もコマンド。T-0142)。
11#pragma once
12
13#include <array>
14#include <cstdint>
15#include <expected>
16#include <memory>
17#include <string>
18#include <string_view>
19#include <vector>
20
21#include "editor/graph_panel.h"
22#include "editor/lab_panel.h"
23#include "editor/time_control.h"
24#include "gpu/com_ptr.h"
25#include "gpu/queue.h"
26
27struct ImGui_ImplDX12_InitInfo;
28
29namespace bicameral {
30 class Window;
31}
32
33namespace bicameral::editor {
34
35 // パネルに出す 1 フレームの状態(フレームのループが詰める)
36 // 反応表とホットリロード(T-0139。frame/table_hot_reload)
38 uint64_t version = 0; // 世界が使っている表の版
39 uint32_t swaps = 0; // 差し替えた回数
40 uint32_t failures = 0; // 読み直せなかった回数
41 bool watching = false; // ファイルを見ている(--editor。再生中は見ない)
42 bool waiting = false; // 読めた表が刻みの境界を待っている(止めている間など)
43 bool lastFailed = false;
44 std::string message; // 最後の読み直しの結果(誤りならファイル:行:列: 何が違うか)
45 };
46
47 struct EditorStatus {
48 // --- 世界の時間 ---
49 uint64_t tick = 0; // 次に投げる単位の刻み(SimScheduler のカーソル)
50 uint32_t unit = 0; // 刻みの中の単位の番号(0 = 刻みの境界)
51 uint32_t unitsPerTick = 1;
52 double pendingTicks = 0.0; // 現実の時間からみて、まだ始めていない刻み
53 uint64_t droppedTicks = 0; // 追いつけずに捨てた刻み(世界が遅れた分。D-202)
54
55 // --- 最後に読み戻した刻みの状態(待たない読み戻し。数フレーム遅れる)---
56 uint64_t hashedTick = 0;
57 uint64_t worldHash = 0; // セル + 物(再生ファイルで突き合わせる値)
58 uint64_t energyMillijoules = 0;
59 uint32_t scheduledBlocks = 0;
60
61 // --- 重さ(直近の 1 秒)---
62 double framesPerSecond = 0.0;
63 double ticksPerSecond = 0.0;
64 double cpuMilliseconds = 0.0;
65 double simGpuMilliseconds = 0.0; // シミュのリスト 1 回あたり
67 double budgetMilliseconds = 0.0;
68
69 // --- 入力と表示 ---
70 std::string view; // デバッグ表示の設定(DebugViewController::Describe)
71 bool replaying = false;
72 bool recording = false;
73 size_t waitingCommands = 0; // まだ GPU に渡していないコマンド(止めている間のつつきはここで待つ)
74
75 // --- 巻き戻し(T-0143)---
76 std::vector<uint64_t> savePointTicks; // 戻れる保存点の刻み(昇順)
77 uint64_t saveIntervalTicks = 0; // 何刻みごとに写すか
78 std::string rewindUnavailable; // 空でなければ巻き戻せない理由
79
80 // --- Work Graphs と性能(直近 1 秒。T-0143)---
82
83 // --- 反応表(T-0139)---
85 };
86
88 public:
89 // ImGui の文脈と Win32・DX12 の backend を作る。frameCount はバックバッファの数(リストを使い回す枠の数)
90 [[nodiscard]] static std::expected<std::unique_ptr<EditorOverlay>, std::string> Create(
91 Window& window, ID3D12Device* device, gpu::Queue& direct, DXGI_FORMAT format, uint32_t frameCount);
92
94 EditorOverlay(const EditorOverlay&) = delete;
98
99 // ImGui がポインタ・キーを使っている(前のフレームのパネルの上にある・文字を打っている)
100 [[nodiscard]] bool WantsPointer() const;
101 [[nodiscard]] bool WantsKeyboard() const;
102
103 // パネルを作る(ImGui の NewFrame〜Render)。押されたボタンとキー(Space・N)を時間の操作の依頼にして返す
104 [[nodiscard]] TimeRequest Build(const EditorStatus& status, const TimeControl& time);
105
106 // Build で作ったパネルをバックバッファに重ねるリストを記録して direct キューへ投げる。
107 // backBuffer は PRESENT の状態で受け取り、PRESENT に戻す。記録に失敗したら false
108 [[nodiscard]] bool Submit(gpu::Queue& direct, ID3D12Resource* backBuffer,
109 D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView);
110
111 // 実験室のパネル(T-0142)
112 [[nodiscard]] LabPanel& Lab() { return *m_lab; }
113
114 private:
115 EditorOverlay(Window& window, uint32_t frameCount);
116
117 // --- 作る ---
118 [[nodiscard]] bool CreateGpuObjects(ID3D12Device* device, uint32_t frameCount);
119 [[nodiscard]] bool InitializeBackends(ID3D12Device* device, gpu::Queue& direct, DXGI_FORMAT format);
120 void LoadJapaneseFont();
121
122 // --- ImGui の DX12 backend に渡す SRV の記述子(フォントの画像など。1.92 から複数使う)---
123 static void AllocateDescriptor(::ImGui_ImplDX12_InitInfo* info, D3D12_CPU_DESCRIPTOR_HANDLE* cpuHandle,
124 D3D12_GPU_DESCRIPTOR_HANDLE* gpuHandle);
125 static void FreeDescriptor(::ImGui_ImplDX12_InitInfo* info, D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle,
126 D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle);
127
128 // --- パネル ---
129 [[nodiscard]] TimeRequest BuildTimePanel(const EditorStatus& status, const TimeControl& time) const;
130 [[nodiscard]] uint64_t BuildRewind(const EditorStatus& status) const;
131 void BuildStatusPanel(const EditorStatus& status) const;
132 void BuildReactionTable(const ReactionTableStatus& table) const;
133 [[nodiscard]] TimeRequest TakeShortcuts(const TimeControl& time) const;
134
135 // --- 描画の枠(バックバッファごと)---
136 struct FrameSlot {
137 ComPtr<ID3D12CommandAllocator> allocator;
138 uint64_t fence = 0; // このリストを最後に投げた direct のフェンスの値(0 = まだ)
139 };
140
142 std::unique_ptr<LabPanel> m_lab;
143 bool m_contextCreated = false;
144 bool m_win32Initialized = false;
145 bool m_dx12Initialized = false;
146
147 std::vector<FrameSlot> m_frames; // ImGui の DX12 backend の頂点のバッファと同じ順で回す(投げるたびに 1 つ進む)
148 uint64_t m_submitCount = 0;
149 ComPtr<ID3D12GraphicsCommandList> m_list;
150
151 // --- SRV の記述子の山(shader visible)と空きの番号 ---
152 ComPtr<ID3D12DescriptorHeap> m_srvHeap;
153 uint32_t m_srvIncrement = 0;
154 std::vector<uint32_t> m_freeSrvSlots;
155 };
156
157} // namespace bicameral::editor
EditorOverlay & operator=(EditorOverlay &&)=delete
static void AllocateDescriptor(::ImGui_ImplDX12_InitInfo *info, D3D12_CPU_DESCRIPTOR_HANDLE *cpuHandle, D3D12_GPU_DESCRIPTOR_HANDLE *gpuHandle)
EditorOverlay(EditorOverlay &&)=delete
bool CreateGpuObjects(ID3D12Device *device, uint32_t frameCount)
EditorOverlay & operator=(const EditorOverlay &)=delete
EditorOverlay(const EditorOverlay &)=delete
std::unique_ptr< LabPanel > m_lab
void BuildStatusPanel(const EditorStatus &status) const
TimeRequest TakeShortcuts(const TimeControl &time) const
ComPtr< ID3D12DescriptorHeap > m_srvHeap
bool Submit(gpu::Queue &direct, ID3D12Resource *backBuffer, D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView)
uint64_t BuildRewind(const EditorStatus &status) const
void BuildReactionTable(const ReactionTableStatus &table) const
TimeRequest BuildTimePanel(const EditorStatus &status, const TimeControl &time) const
static std::expected< std::unique_ptr< EditorOverlay >, std::string > Create(Window &window, ID3D12Device *device, gpu::Queue &direct, DXGI_FORMAT format, uint32_t frameCount)
static void FreeDescriptor(::ImGui_ImplDX12_InitInfo *info, D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle, D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle)
ComPtr< ID3D12GraphicsCommandList > m_list
std::vector< uint32_t > m_freeSrvSlots
bool InitializeBackends(ID3D12Device *device, gpu::Queue &direct, DXGI_FORMAT format)
TimeRequest Build(const EditorStatus &status, const TimeControl &time)
std::vector< FrameSlot > m_frames
ComPtr< ID3D12CommandAllocator > allocator
std::vector< uint64_t > savePointTicks
ReactionTableStatus reactionTable