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
15#include "app/gui/core/icons.h"
16#include "imgui/imgui.h"
17#include "imgui/imgui_internal.h"
18#include "util/log.h"
19
20namespace yaze {
21namespace editor {
22
24 deps_ = deps;
25 initialized_ = true;
26
27 // Subscribe to navigation events via EventBus
28 if (deps_.event_bus) {
30 [this](const JumpToRoomRequestEvent& event) {
31 JumpToDungeonRoom(event.room_id);
32 });
33
35 [this](const JumpToMapRequestEvent& event) {
36 JumpToOverworldMap(event.map_id);
37 });
38
40 [this](const JumpToMessageRequestEvent& event) {
41 JumpToMessage(event.message_id);
42 });
43
45 [this](const JumpToAssemblySymbolRequestEvent& event) {
46 JumpToAssemblySymbol(event.symbol);
47 });
48
49 LOG_INFO("EditorActivator", "Subscribed to navigation events");
50 }
51}
52
53void EditorActivator::SwitchToEditor(EditorType editor_type, bool force_visible,
54 bool from_dialog) {
55 if (!initialized_) {
56 LOG_WARN("EditorActivator", "Not initialized, cannot switch editor");
57 return;
58 }
59
60 // Avoid touching ImGui docking state when outside a frame
61 ImGuiContext* imgui_ctx = ImGui::GetCurrentContext();
62 const bool frame_active = imgui_ctx != nullptr && imgui_ctx->WithinFrameScope;
63 if (!frame_active && deps_.queue_deferred_action) {
64 deps_.queue_deferred_action([this, editor_type, force_visible, from_dialog]() {
65 SwitchToEditor(editor_type, force_visible, from_dialog);
66 });
67 return;
68 }
69
70 // If NOT coming from dialog, close editor selection UI
71 if (!from_dialog && deps_.ui_coordinator) {
73 }
74
75 auto* editor_set = deps_.get_current_editor_set ? deps_.get_current_editor_set() : nullptr;
76 if (!editor_set) {
77 return;
78 }
79
80 // Toggle the editor in the active editors list
81 for (auto* editor : editor_set->active_editors_) {
82 if (editor->type() == editor_type) {
83 if (force_visible) {
84 editor->set_active(true);
85 } else {
86 editor->toggle_active();
87 }
88
89 if (EditorRegistry::IsPanelBasedEditor(editor_type)) {
90 if (*editor->active()) {
91 // Smooth transition: fade out old, then fade in new
92 // Panel refresh handled by OnEditorSwitch below
93 ActivatePanelBasedEditor(editor_type, editor);
94 } else {
95 DeactivatePanelBasedEditor(editor_type, editor, editor_set);
96 }
97 }
98 return;
99 }
100 }
101
102 // Handle non-editor-class cases (Assembly, Emulator, Hex, Settings, Agent)
103 HandleNonEditorClassSwitch(editor_type, force_visible);
104}
105
107 if (!deps_.panel_manager) return;
108
109 std::string old_category = deps_.panel_manager->GetActiveCategory();
110 std::string new_category = EditorRegistry::GetEditorCategory(type);
111
112 // Only trigger OnEditorSwitch if category actually changes
113 if (old_category != new_category) {
114 deps_.panel_manager->OnEditorSwitch(old_category, new_category);
115 }
116
117 // Initialize default layout on first activation
120 deps_.queue_deferred_action([this, type]() {
122 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
123 deps_.layout_manager->InitializeEditorLayout(type, dockspace_id);
124 }
125 });
126 }
127 }
128}
129
131 EditorSet* editor_set) {
132 if (!deps_.panel_manager || !editor_set) return;
133
134 // Switch to another active panel-based editor
135 for (auto* other : editor_set->active_editors_) {
136 if (*other->active() && EditorRegistry::IsPanelBasedEditor(other->type()) &&
137 other != editor) {
138 std::string old_category = deps_.panel_manager->GetActiveCategory();
139 std::string new_category = EditorRegistry::GetEditorCategory(other->type());
140 if (old_category != new_category) {
141 deps_.panel_manager->OnEditorSwitch(old_category, new_category);
142 }
143 break;
144 }
145 }
146}
147
149 switch (type) {
151 if (deps_.ui_coordinator) {
152 if (force_visible) {
154 } else {
157 }
158 }
159 break;
160
162 if (deps_.ui_coordinator) {
163 bool is_visible = !deps_.ui_coordinator->IsEmulatorVisible();
164 if (force_visible) is_visible = true;
165
167
168 if (is_visible && deps_.panel_manager) {
170
173 ImGuiContext* ctx = ImGui::GetCurrentContext();
174 if (deps_.layout_manager && ctx && ctx->WithinFrameScope) {
175 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
178 dockspace_id);
179 LOG_INFO("EditorActivator", "Initialized emulator layout");
180 }
181 }
182 });
183 }
184 }
185 }
186 break;
187
188 case EditorType::kHex:
191 }
192 break;
193
198 !force_visible) {
200 } else {
203 }
204 }
205 break;
206
207 default:
208 // Other editor types not handled here
209 break;
210 }
211}
212
214 if (!initialized_ || !deps_.layout_manager) return;
215
216 ImGuiContext* ctx = ImGui::GetCurrentContext();
217 if (!ctx || !ctx->WithinFrameScope) {
219 deps_.queue_deferred_action([this, type]() {
221 });
222 }
223 return;
224 }
225
227 ImGuiID dockspace_id = ImGui::GetID("MainDockSpace");
228 deps_.layout_manager->InitializeEditorLayout(type, dockspace_id);
229 LOG_INFO("EditorActivator", "Initialized layout for editor type %d",
230 static_cast<int>(type));
231 }
232}
233
235 auto* editor_set = deps_.get_current_editor_set ? deps_.get_current_editor_set() : nullptr;
236 if (!editor_set) return;
237
240 if (!status.ok()) {
241 if (deps_.toast_manager) {
243 "Failed to prepare Dungeon editor: " + std::string(status.message()),
245 }
246 return;
247 }
248 }
249
250 // Switch to dungeon editor
252
253 // Open the room in the dungeon editor
254 editor_set->GetDungeonEditor()->add_room(room_id);
255}
256
258 auto* editor_set = deps_.get_current_editor_set ? deps_.get_current_editor_set() : nullptr;
259 if (!editor_set) return;
260
262 const auto status =
264 if (!status.ok()) {
265 if (deps_.toast_manager) {
266 deps_.toast_manager->Show("Failed to prepare Overworld editor: " +
267 std::string(status.message()),
269 }
270 return;
271 }
272 }
273
274 // Switch to overworld editor
276
277 // Set the current map in the overworld editor
278 editor_set->GetOverworldEditor()->set_current_map(map_id);
279}
280
281void EditorActivator::JumpToMessage(int message_id) {
282 if (message_id < 0) return;
283
284 auto* editor_set =
286 if (!editor_set) return;
287
290 if (!status.ok()) {
291 if (deps_.toast_manager) {
292 deps_.toast_manager->Show("Failed to prepare Message editor: " +
293 std::string(status.message()),
295 }
296 return;
297 }
298 }
299
300 // Switch to message editor (force visible so this behaves like navigation).
301 SwitchToEditor(EditorType::kMessage, /*force_visible=*/true);
302
303 if (auto* message_editor = editor_set->GetMessageEditor()) {
304 if (!message_editor->OpenMessageById(message_id)) {
305 if (deps_.toast_manager) {
306 deps_.toast_manager->Show("Message ID not found: " +
307 std::to_string(message_id),
309 }
310 }
311 }
312}
313
314void EditorActivator::JumpToAssemblySymbol(const std::string& symbol) {
315 if (symbol.empty()) return;
316
317 auto* editor_set =
319 if (!editor_set) return;
320
322 const auto status =
324 if (!status.ok()) {
325 if (deps_.toast_manager) {
326 deps_.toast_manager->Show("Failed to prepare Assembly editor: " +
327 std::string(status.message()),
329 }
330 return;
331 }
332 }
333
334 // Switch to assembly editor (force visible so this behaves like navigation).
335 SwitchToEditor(EditorType::kAssembly, /*force_visible=*/true);
336
337 if (auto* asm_editor = editor_set->GetAssemblyEditor()) {
338 const auto status = asm_editor->JumpToReference(symbol);
339 if (!status.ok()) {
340 if (deps_.toast_manager) {
342 "Assembly jump failed: " + std::string(status.message()),
344 }
345 return;
346 }
347 }
348}
349
350} // namespace editor
351} // 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:236
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 OnEditorSwitch(const std::string &from_category, const std::string &to_category)
Handle editor/category switching for panel visibility.
void SetActiveCategory(const std::string &category, bool notify=true)
bool ShowPanel(size_t session_id, const std::string &base_card_id)
std::string GetActiveCategory() const
void ClosePanel()
Close the currently active panel.
PanelType GetActivePanel() const
Get the currently active panel type.
void OpenPanel(PanelType type)
Open a specific panel.
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)
#define LOG_WARN(category, format,...)
Definition log.h:107
#define LOG_INFO(category, format,...)
Definition log.h:105
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.