yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
editor_activator.cc
Go to the documentation of this file.
1#include "editor_activator.h"
2
16#include "app/gui/core/icons.h"
17#include "imgui/imgui.h"
18#include "imgui/imgui_internal.h"
19#include "util/log.h"
20
21namespace yaze {
22namespace editor {
23
24void EditorActivator::Initialize(const Dependencies& deps) {
25 deps_ = deps;
26 initialized_ = true;
27
28 // Subscribe to navigation events via EventBus
29 if (deps_.event_bus) {
30 deps_.event_bus->Subscribe<JumpToRoomRequestEvent>(
31 [this](const JumpToRoomRequestEvent& event) {
32 JumpToDungeonRoom(event.room_id);
33 });
34
35 deps_.event_bus->Subscribe<JumpToMapRequestEvent>(
36 [this](const JumpToMapRequestEvent& event) {
37 JumpToOverworldMap(event.map_id);
38 });
39
40 deps_.event_bus->Subscribe<JumpToMessageRequestEvent>(
41 [this](const JumpToMessageRequestEvent& event) {
42 JumpToMessage(event.message_id);
43 });
44
45 deps_.event_bus->Subscribe<JumpToAssemblySymbolRequestEvent>(
46 [this](const JumpToAssemblySymbolRequestEvent& event) {
47 JumpToAssemblySymbol(event.symbol);
48 });
49
50 LOG_INFO("EditorActivator", "Subscribed to navigation events");
51 }
52}
53
54void EditorActivator::SwitchToEditor(EditorType editor_type, bool force_visible,
55 bool from_dialog) {
56 if (!initialized_) {
57 LOG_WARN("EditorActivator", "Not initialized, cannot switch editor");
58 return;
59 }
60
61 // Avoid touching ImGui docking state when outside a frame
62 ImGuiContext* imgui_ctx = ImGui::GetCurrentContext();
63 const bool frame_active = imgui_ctx != nullptr && imgui_ctx->WithinFrameScope;
64 if (!frame_active && deps_.queue_deferred_action) {
66 [this, editor_type, force_visible, from_dialog]() {
67 SwitchToEditor(editor_type, force_visible, from_dialog);
68 });
69 return;
70 }
71
72 // If NOT coming from dialog, close editor selection UI
73 if (!from_dialog && deps_.ui_coordinator) {
75 }
76
77 auto* editor_set =
79 if (!editor_set) {
80 return;
81 }
82
84 switch (editor_type) {
94 const auto status = deps_.ensure_editor_assets_loaded(editor_type);
95 if (!status.ok()) {
96 if (deps_.toast_manager) {
98 "Failed to prepare editor: " + std::string(status.message()),
100 }
101 return;
102 }
103 break;
104 }
105 default:
106 break;
107 }
108 }
109
110 // Toggle the editor in the active editors list
111 for (auto* editor : editor_set->active_editors_) {
112 if (editor->type() == editor_type) {
113 if (force_visible) {
114 editor->set_active(true);
115 } else {
116 editor->toggle_active();
117 }
118
119 if (EditorRegistry::IsPanelBasedEditor(editor_type)) {
120 if (*editor->active()) {
121 // Smooth transition: fade out old, then fade in new
122 // Panel refresh handled by OnEditorSwitch below
123 ActivatePanelBasedEditor(editor_type, editor);
124 } else {
125 DeactivatePanelBasedEditor(editor_type, editor, editor_set);
126 }
127 }
128 return;
129 }
130 }
131
132 // Handle non-editor-class cases (Assembly, Emulator, Hex, Settings, Agent)
133 HandleNonEditorClassSwitch(editor_type, force_visible);
134}
135
137 Editor* editor) {
139 return;
140
141 std::string old_category = deps_.window_manager->GetActiveCategory();
142 std::string new_category = EditorRegistry::GetEditorCategory(type);
143
144 // Only trigger OnEditorSwitch if category actually changes
145 if (old_category != new_category) {
146 // Kill any in-flight panel transitions from the previous editor so the
147 // new editor's windows start their fade from a clean state. Without this,
148 // stale alpha values leave old bitmap surfaces ghosted during the switch.
150 deps_.window_manager->OnEditorSwitch(old_category, new_category);
151 }
152
153 // Initialize default layout on first activation
154 if (deps_.layout_manager &&
157 deps_.queue_deferred_action([this, type]() {
158 if (deps_.layout_manager &&
160 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
161 deps_.layout_manager->InitializeEditorLayout(type, dockspace_id);
162 }
163 });
164 }
165 }
166}
167
169 Editor* editor,
170 EditorSet* editor_set) {
171 if (!deps_.window_manager || !editor_set)
172 return;
173
174 // Switch to another active panel-based editor
175 for (auto* other : editor_set->active_editors_) {
176 if (*other->active() && EditorRegistry::IsPanelBasedEditor(other->type()) &&
177 other != editor) {
178 std::string old_category = deps_.window_manager->GetActiveCategory();
179 std::string new_category =
181 if (old_category != new_category) {
183 deps_.window_manager->OnEditorSwitch(old_category, new_category);
184 }
185 break;
186 }
187 }
188}
189
191 bool force_visible) {
192 switch (type) {
194 if (deps_.ui_coordinator) {
195 bool is_visible = !deps_.ui_coordinator->IsAsmEditorVisible();
196 if (force_visible) {
197 is_visible = true;
198 }
199
201
202 if (is_visible && deps_.window_manager) {
205 }
206 }
207 break;
208
210 if (deps_.ui_coordinator) {
211 bool is_visible = !deps_.ui_coordinator->IsEmulatorVisible();
212 if (force_visible)
213 is_visible = true;
214
216
217 if (is_visible && deps_.window_manager) {
219
222 ImGuiContext* ctx = ImGui::GetCurrentContext();
223 if (deps_.layout_manager && ctx && ctx->WithinFrameScope) {
224 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
228 EditorType::kEmulator, dockspace_id);
229 LOG_INFO("EditorActivator", "Initialized emulator layout");
230 }
231 }
232 });
233 }
234 }
235 }
236 break;
237
238 case EditorType::kHex:
241 "Hex Editor");
242 }
243 break;
244
249 !force_visible) {
251 } else {
254 }
255 }
256 break;
257
258 default:
259 // Other editor types not handled here
260 break;
261 }
262}
263
266 return;
267
268 ImGuiContext* ctx = ImGui::GetCurrentContext();
269 if (!ctx || !ctx->WithinFrameScope) {
272 [this, type]() { InitializeEditorLayout(type); });
273 }
274 return;
275 }
276
278 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
279 deps_.layout_manager->InitializeEditorLayout(type, dockspace_id);
280 LOG_INFO("EditorActivator", "Initialized layout for editor type %d",
281 static_cast<int>(type));
282 }
283}
284
285void EditorActivator::JumpToDungeonRoom(int room_id) {
286 auto* editor_set =
288 if (!editor_set)
289 return;
290
293 if (!status.ok()) {
294 if (deps_.toast_manager) {
295 deps_.toast_manager->Show("Failed to prepare Dungeon editor: " +
296 std::string(status.message()),
298 }
299 return;
300 }
301 }
302
303 // Switch to dungeon editor
305
306 // Open the room in the dungeon editor
307 editor_set->GetDungeonEditor()->add_room(room_id);
308}
309
311 auto* editor_set =
313 if (!editor_set)
314 return;
315
317 const auto status =
319 if (!status.ok()) {
320 if (deps_.toast_manager) {
321 deps_.toast_manager->Show("Failed to prepare Overworld editor: " +
322 std::string(status.message()),
324 }
325 return;
326 }
327 }
328
329 // Switch to overworld editor
331
332 // Set the current map in the overworld editor
333 editor_set->GetOverworldEditor()->set_current_map(map_id);
334}
335
336void EditorActivator::JumpToMessage(int message_id) {
337 if (message_id < 0)
338 return;
339
340 auto* editor_set =
342 if (!editor_set)
343 return;
344
347 if (!status.ok()) {
348 if (deps_.toast_manager) {
349 deps_.toast_manager->Show("Failed to prepare Message editor: " +
350 std::string(status.message()),
352 }
353 return;
354 }
355 }
356
357 // Switch to message editor (force visible so this behaves like navigation).
358 SwitchToEditor(EditorType::kMessage, /*force_visible=*/true);
359
360 if (auto* message_editor = editor_set->GetMessageEditor()) {
361 if (!message_editor->OpenMessageById(message_id)) {
362 if (deps_.toast_manager) {
364 "Message ID not found: " + std::to_string(message_id),
366 }
367 }
368 }
369}
370
371void EditorActivator::JumpToAssemblySymbol(const std::string& symbol) {
372 if (symbol.empty())
373 return;
374
375 auto* editor_set =
377 if (!editor_set)
378 return;
379
381 const auto status =
383 if (!status.ok()) {
384 if (deps_.toast_manager) {
385 deps_.toast_manager->Show("Failed to prepare Assembly editor: " +
386 std::string(status.message()),
388 }
389 return;
390 }
391 }
392
393 // Switch to assembly editor (force visible so this behaves like navigation).
394 SwitchToEditor(EditorType::kAssembly, /*force_visible=*/true);
395
396 if (auto* asm_editor = editor_set->GetAssemblyEditor()) {
397 const auto status = asm_editor->JumpToReference(symbol);
398 if (!status.ok()) {
399 if (deps_.toast_manager) {
401 "Assembly jump failed: " + std::string(status.message()),
403 }
404 return;
405 }
406 }
407}
408
409} // namespace editor
410} // namespace yaze
HandlerId Subscribe(std::function< void(const T &)> handler)
Definition event_bus.h:22
void HandleNonEditorClassSwitch(EditorType type, bool force_visible)
void ActivatePanelBasedEditor(EditorType type, Editor *editor)
void JumpToAssemblySymbol(const std::string &symbol)
Jump to an assembly symbol definition in the Assembly editor.
void SwitchToEditor(EditorType type, bool force_visible=false, bool from_dialog=false)
Switch to an editor, optionally forcing visibility.
void Initialize(const Dependencies &deps)
void JumpToMessage(int message_id)
Jump to a specific message ID in the Message editor.
void InitializeEditorLayout(EditorType type)
Initialize the DockBuilder layout for an editor.
void JumpToDungeonRoom(int room_id)
Jump to a specific dungeon room.
void JumpToOverworldMap(int map_id)
Jump to a specific overworld map.
void DeactivatePanelBasedEditor(EditorType type, Editor *editor, EditorSet *editor_set)
static bool IsPanelBasedEditor(EditorType type)
static std::string GetEditorCategory(EditorType type)
bool IsLayoutInitialized(EditorType type) const
Check if a layout has been initialized for an editor.
void InitializeEditorLayout(EditorType type, ImGuiID dockspace_id)
Initialize the default layout for a specific editor type.
void OpenDrawer(DrawerType type)
Open a specific drawer.
DrawerType GetActiveDrawer() const
Get the currently active drawer type.
void CloseDrawer()
Close the currently active drawer.
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
void SetEmulatorVisible(bool visible)
void SetAsmEditorVisible(bool visible)
void SetEditorSelectionVisible(bool visible)
void SetActiveCategory(const std::string &category, bool notify=true)
void OnEditorSwitch(const std::string &from_category, const std::string &to_category)
Handle editor/category switching for panel visibility.
bool OpenWindow(size_t session_id, const std::string &base_window_id)
void ClearWorkspaceTransitionState()
Definition animator.cc:89
#define LOG_WARN(category, format,...)
Definition log.h:107
#define LOG_INFO(category, format,...)
Definition log.h:105
Animator & GetAnimator()
Definition animator.cc:318
std::function< EditorSet *()> get_current_editor_set
std::function< void(std::function< void()>)> queue_deferred_action
std::function< absl::Status(EditorType)> ensure_editor_assets_loaded