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#include "zelda3/common.h"
21
22namespace yaze {
23namespace editor {
24
26 deps_ = deps;
27 initialized_ = true;
28
29 // Subscribe to navigation events via EventBus
30 if (deps_.event_bus) {
32 [this](const JumpToRoomRequestEvent& event) {
33 JumpToDungeonRoom(event.room_id);
34 });
35
37 [this](const JumpToMapRequestEvent& event) {
38 JumpToOverworldMap(event.map_id);
39 });
40
42 [this](const JumpToMessageRequestEvent& event) {
43 JumpToMessage(event.message_id);
44 });
45
47 [this](const JumpToAssemblySymbolRequestEvent& event) {
48 JumpToAssemblySymbol(event.symbol);
49 });
50
51 LOG_INFO("EditorActivator", "Subscribed to navigation events");
52 }
53}
54
55void EditorActivator::SwitchToEditor(EditorType editor_type, bool force_visible,
56 bool from_dialog) {
57 if (!initialized_) {
58 LOG_WARN("EditorActivator", "Not initialized, cannot switch editor");
59 return;
60 }
61
62 // Avoid touching ImGui docking state when outside a frame
63 ImGuiContext* imgui_ctx = ImGui::GetCurrentContext();
64 const bool frame_active = imgui_ctx != nullptr && imgui_ctx->WithinFrameScope;
65 if (!frame_active && deps_.queue_deferred_action) {
67 [this, editor_type, force_visible, from_dialog]() {
68 SwitchToEditor(editor_type, force_visible, from_dialog);
69 });
70 return;
71 }
72
73 // If NOT coming from dialog, close editor selection UI
74 if (!from_dialog && deps_.ui_coordinator) {
76 }
77
78 auto* editor_set =
80 if (!editor_set) {
81 return;
82 }
83
85 switch (editor_type) {
95 const auto status = deps_.ensure_editor_assets_loaded(editor_type);
96 if (!status.ok()) {
97 if (deps_.toast_manager) {
99 "Failed to prepare editor: " + std::string(status.message()),
101 }
102 return;
103 }
104 break;
105 }
106 default:
107 break;
108 }
109 }
110
111 // Toggle the editor in the active editors list
112 for (auto* editor : editor_set->active_editors_) {
113 if (editor->type() == editor_type) {
114 if (force_visible) {
115 editor->set_active(true);
116 } else {
117 editor->toggle_active();
118 }
119
120 if (EditorRegistry::IsPanelBasedEditor(editor_type)) {
121 if (*editor->active()) {
122 // Smooth transition: fade out old, then fade in new
123 // Panel refresh handled by OnEditorSwitch below
124 ActivatePanelBasedEditor(editor_type, editor);
125 } else {
126 DeactivatePanelBasedEditor(editor_type, editor, editor_set);
127 }
128 }
129 return;
130 }
131 }
132
133 // Handle non-editor-class cases (Assembly, Emulator, Hex, Settings, Agent)
134 HandleNonEditorClassSwitch(editor_type, force_visible);
135}
136
138 Editor* editor) {
140 return;
141
142 std::string old_category = deps_.window_manager->GetActiveCategory();
143 std::string new_category = EditorRegistry::GetEditorCategory(type);
144
145 // Only trigger OnEditorSwitch if category actually changes
146 if (old_category != new_category) {
147 // Kill any in-flight panel transitions from the previous editor so the
148 // new editor's windows start their fade from a clean state. Without this,
149 // stale alpha values leave old bitmap surfaces ghosted during the switch.
151 deps_.window_manager->OnEditorSwitch(old_category, new_category);
152 }
153
154 // Initialize default layout on first activation
155 if (deps_.layout_manager &&
158 deps_.queue_deferred_action([this, type]() {
159 if (deps_.layout_manager &&
161 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
162 deps_.layout_manager->InitializeEditorLayout(type, dockspace_id);
163 }
164 });
165 }
166 }
167}
168
170 Editor* editor,
171 EditorSet* editor_set) {
172 if (!deps_.window_manager || !editor_set)
173 return;
174
175 // Switch to another active panel-based editor
176 for (auto* other : editor_set->active_editors_) {
177 if (*other->active() && EditorRegistry::IsPanelBasedEditor(other->type()) &&
178 other != editor) {
179 std::string old_category = deps_.window_manager->GetActiveCategory();
180 std::string new_category =
182 if (old_category != new_category) {
184 deps_.window_manager->OnEditorSwitch(old_category, new_category);
185 }
186 break;
187 }
188 }
189}
190
192 bool force_visible) {
193 switch (type) {
195 if (deps_.ui_coordinator) {
196 bool is_visible = !deps_.ui_coordinator->IsAsmEditorVisible();
197 if (force_visible) {
198 is_visible = true;
199 }
200
202
203 if (is_visible && deps_.window_manager) {
206 }
207 }
208 break;
209
211 if (deps_.ui_coordinator) {
212 bool is_visible = !deps_.ui_coordinator->IsEmulatorVisible();
213 if (force_visible)
214 is_visible = true;
215
217
218 if (is_visible && deps_.window_manager) {
220
223 ImGuiContext* ctx = ImGui::GetCurrentContext();
224 if (deps_.layout_manager && ctx && ctx->WithinFrameScope) {
225 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
229 EditorType::kEmulator, dockspace_id);
230 LOG_INFO("EditorActivator", "Initialized emulator layout");
231 }
232 }
233 });
234 }
235 }
236 }
237 break;
238
239 case EditorType::kHex:
242 "Hex Editor");
243 }
244 break;
245
250 !force_visible) {
252 } else {
255 }
256 }
257 break;
258
259 default:
260 // Other editor types not handled here
261 break;
262 }
263}
264
267 return;
268
269 ImGuiContext* ctx = ImGui::GetCurrentContext();
270 if (!ctx || !ctx->WithinFrameScope) {
273 [this, type]() { InitializeEditorLayout(type); });
274 }
275 return;
276 }
277
279 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
280 deps_.layout_manager->InitializeEditorLayout(type, dockspace_id);
281 LOG_INFO("EditorActivator", "Initialized layout for editor type %d",
282 static_cast<int>(type));
283 }
284}
285
287 auto* editor_set =
289 if (!editor_set)
290 return;
291
294 if (!status.ok()) {
295 if (deps_.toast_manager) {
296 deps_.toast_manager->Show("Failed to prepare Dungeon editor: " +
297 std::string(status.message()),
299 }
300 return;
301 }
302 }
303
304 // Switch to dungeon editor
306
307 // Open the room in the dungeon editor
308 editor_set->GetDungeonEditor()->add_room(room_id);
309}
310
312 if (map_id < 0 || map_id >= zelda3::kNumOverworldMaps) {
313 LOG_WARN("EditorActivator", "Rejected invalid overworld map jump target %d",
314 map_id);
315 if (deps_.toast_manager) {
317 "Invalid overworld map ID: " + std::to_string(map_id),
319 }
320 return;
321 }
322
323 auto* editor_set =
325 if (!editor_set)
326 return;
327
329 const auto status =
331 if (!status.ok()) {
332 if (deps_.toast_manager) {
333 deps_.toast_manager->Show("Failed to prepare Overworld editor: " +
334 std::string(status.message()),
336 }
337 return;
338 }
339 }
340
341 // Switch to overworld editor
343
344 // Set the current map in the overworld editor
345 editor_set->GetOverworldEditor()->set_current_map(map_id);
346}
347
348void EditorActivator::JumpToMessage(int message_id) {
349 if (message_id < 0)
350 return;
351
352 auto* editor_set =
354 if (!editor_set)
355 return;
356
359 if (!status.ok()) {
360 if (deps_.toast_manager) {
361 deps_.toast_manager->Show("Failed to prepare Message editor: " +
362 std::string(status.message()),
364 }
365 return;
366 }
367 }
368
369 // Switch to message editor (force visible so this behaves like navigation).
370 SwitchToEditor(EditorType::kMessage, /*force_visible=*/true);
371
372 if (auto* message_editor = editor_set->GetMessageEditor()) {
373 if (!message_editor->OpenMessageById(message_id)) {
374 if (deps_.toast_manager) {
376 "Message ID not found: " + std::to_string(message_id),
378 }
379 }
380 }
381}
382
383void EditorActivator::JumpToAssemblySymbol(const std::string& symbol) {
384 if (symbol.empty())
385 return;
386
387 auto* editor_set =
389 if (!editor_set)
390 return;
391
393 const auto status =
395 if (!status.ok()) {
396 if (deps_.toast_manager) {
397 deps_.toast_manager->Show("Failed to prepare Assembly editor: " +
398 std::string(status.message()),
400 }
401 return;
402 }
403 }
404
405 // Switch to assembly editor (force visible so this behaves like navigation).
406 SwitchToEditor(EditorType::kAssembly, /*force_visible=*/true);
407
408 if (auto* asm_editor = editor_set->GetAssemblyEditor()) {
409 const auto status = asm_editor->JumpToReference(symbol);
410 if (!status.ok()) {
411 if (deps_.toast_manager) {
413 "Assembly jump failed: " + std::string(status.message()),
415 }
416 return;
417 }
418 }
419}
420
421} // namespace editor
422} // 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)
Contains a complete set of editors for a single ROM instance.
std::vector< Editor * > active_editors_
Interface for editor classes.
Definition editor.h:245
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
constexpr int kNumOverworldMaps
Definition common.h:85
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
Request to navigate to an assembly symbol definition.
Request to navigate to a specific overworld map.
Request to navigate to a specific message ID.
Request to navigate to a specific dungeon room.