yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
content_registry.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <memory>
5#include <mutex>
6#include <string>
7#include <unordered_map>
8#include <vector>
9
10#include "app/editor/editor.h"
15#include "core/project.h"
16#include "rom/rom.h"
17#include "zelda3/game_data.h"
18
19namespace yaze::editor {
20
21namespace {
22
23// Singleton storage for ContentRegistry state
24// Uses lazy initialization to avoid static initialization order issues
25struct RegistryState {
26 std::mutex mutex;
27
28 // When global_context is set, Context delegates to it.
29 // The raw pointers below are fallback storage used only before
30 // GlobalEditorContext is wired in (early startup / tests).
31 GlobalEditorContext* global_context = nullptr;
32
33 Rom* current_rom = nullptr;
34 ::yaze::EventBus* event_bus = nullptr;
35 Editor* current_editor = nullptr;
36 std::unordered_map<std::string, Editor*> current_window_editors;
39 workflow::HackWorkflowBackend* hack_workflow_backend = nullptr;
40 ProjectWorkflowStatus build_workflow_status;
41 ProjectWorkflowStatus run_workflow_status;
42 std::string build_workflow_log;
43 std::vector<ProjectWorkflowHistoryEntry> workflow_history;
44 std::function<void()> start_build_workflow_callback;
45 std::function<void()> run_project_workflow_callback;
46 std::function<void()> show_workflow_output_callback;
47 std::function<void()> cancel_build_workflow_callback;
48 std::vector<std::unique_ptr<WindowContent>> panels;
49 std::vector<ContentRegistry::Panels::PanelFactory> factories;
50 std::vector<ContentRegistry::Editors::EditorFactory> editor_factories;
51 std::vector<ContentRegistry::Shortcuts::ShortcutDef> shortcuts;
52 std::vector<ContentRegistry::WorkflowActions::ActionDef> workflow_actions;
53 std::vector<ContentRegistry::Settings::SettingDef> settings;
54
55 static RegistryState& Get() {
56 static RegistryState instance;
57 return instance;
58 }
59};
60
61} // namespace
62
63// =============================================================================
64// Context Implementation
65// =============================================================================
66
67namespace ContentRegistry {
68
69namespace Context {
70
71void SetGlobalContext(GlobalEditorContext* ctx) {
72 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
73 RegistryState::Get().global_context = ctx;
74}
75
76Rom* rom() {
77 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
78 auto& state = RegistryState::Get();
79 if (state.global_context)
80 return state.global_context->GetCurrentRom();
81 return state.current_rom;
82}
83
84void SetRom(Rom* rom) {
85 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
86 auto& state = RegistryState::Get();
87 if (state.global_context) {
88 state.global_context->SetCurrentRom(rom);
89 }
90 state.current_rom = rom; // keep fallback in sync
91}
92
94 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
95 auto& state = RegistryState::Get();
96 if (state.global_context)
97 return &state.global_context->GetEventBus();
98 return state.event_bus;
99}
100
101void SetEventBus(::yaze::EventBus* bus) {
102 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
103 auto& state = RegistryState::Get();
104 // EventBus in GlobalEditorContext is a reference set at construction,
105 // so we don't update it here. Just keep fallback in sync.
106 state.event_bus = bus;
107}
108
109Editor* current_editor() {
110 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
111 auto& state = RegistryState::Get();
112 if (state.global_context)
113 return state.global_context->GetCurrentEditor();
114 return state.current_editor;
115}
116
117void SetCurrentEditor(Editor* editor) {
118 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
119 auto& state = RegistryState::Get();
120 if (state.global_context) {
121 state.global_context->SetCurrentEditor(editor);
122 }
123 state.current_editor = editor;
124}
125
126Editor* editor_window_context(const std::string& category) {
127 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
128 auto& state = RegistryState::Get();
129 auto it = state.current_window_editors.find(category);
130 return it != state.current_window_editors.end() ? it->second : nullptr;
131}
132
133void SetEditorWindowContext(const std::string& category, Editor* editor) {
134 if (category.empty()) {
135 return;
136 }
137 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
138 RegistryState::Get().current_window_editors[category] = editor;
139}
140
142 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
143 auto& state = RegistryState::Get();
144 if (state.global_context)
145 return state.global_context->GetGameData();
146 return state.game_data;
147}
148
150 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
151 auto& state = RegistryState::Get();
152 if (state.global_context) {
153 state.global_context->SetGameData(data);
154 }
155 state.game_data = data;
156}
157
159 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
160 auto& state = RegistryState::Get();
161 if (state.global_context)
162 return state.global_context->GetCurrentProject();
163 return state.current_project;
164}
165
167 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
168 auto& state = RegistryState::Get();
169 if (state.global_context) {
170 state.global_context->SetCurrentProject(project);
171 }
172 state.current_project = project;
173}
174
175workflow::HackWorkflowBackend* hack_workflow_backend() {
176 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
177 return RegistryState::Get().hack_workflow_backend;
178}
179
180workflow::ValidationCapability* hack_validation_backend() {
181 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
182 return dynamic_cast<workflow::ValidationCapability*>(
183 RegistryState::Get().hack_workflow_backend);
184}
185
186workflow::ProgressionCapability* hack_progression_backend() {
187 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
188 return dynamic_cast<workflow::ProgressionCapability*>(
189 RegistryState::Get().hack_workflow_backend);
190}
191
192workflow::PlanningCapability* hack_planning_backend() {
193 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
194 return dynamic_cast<workflow::PlanningCapability*>(
195 RegistryState::Get().hack_workflow_backend);
196}
197
198void SetHackWorkflowBackend(workflow::HackWorkflowBackend* backend) {
199 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
200 RegistryState::Get().hack_workflow_backend = backend;
201}
202
203ProjectWorkflowStatus build_workflow_status() {
204 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
205 return RegistryState::Get().build_workflow_status;
206}
207
208void SetBuildWorkflowStatus(const ProjectWorkflowStatus& status) {
209 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
210 RegistryState::Get().build_workflow_status = status;
211}
212
213ProjectWorkflowStatus run_workflow_status() {
214 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
215 return RegistryState::Get().run_workflow_status;
216}
217
218void SetRunWorkflowStatus(const ProjectWorkflowStatus& status) {
219 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
220 RegistryState::Get().run_workflow_status = status;
221}
222
223std::string build_workflow_log() {
224 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
225 return RegistryState::Get().build_workflow_log;
226}
227
228void SetBuildWorkflowLog(const std::string& output) {
229 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
230 RegistryState::Get().build_workflow_log = output;
231}
232
233std::vector<ProjectWorkflowHistoryEntry> workflow_history() {
234 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
235 return RegistryState::Get().workflow_history;
236}
237
238void AppendWorkflowHistory(const ProjectWorkflowHistoryEntry& entry) {
239 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
240 auto& history = RegistryState::Get().workflow_history;
241 history.insert(history.begin(), entry);
242 constexpr size_t kMaxEntries = 20;
243 if (history.size() > kMaxEntries) {
244 history.resize(kMaxEntries);
245 }
246}
247
249 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
250 RegistryState::Get().workflow_history.clear();
251}
252
253std::function<void()> start_build_workflow_callback() {
254 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
255 return RegistryState::Get().start_build_workflow_callback;
256}
257
258void SetStartBuildWorkflowCallback(std::function<void()> callback) {
259 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
260 RegistryState::Get().start_build_workflow_callback = std::move(callback);
261}
262
263std::function<void()> run_project_workflow_callback() {
264 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
265 return RegistryState::Get().run_project_workflow_callback;
266}
267
268void SetRunProjectWorkflowCallback(std::function<void()> callback) {
269 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
270 RegistryState::Get().run_project_workflow_callback = std::move(callback);
271}
272
273std::function<void()> show_workflow_output_callback() {
274 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
275 return RegistryState::Get().show_workflow_output_callback;
276}
277
278void SetShowWorkflowOutputCallback(std::function<void()> callback) {
279 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
280 RegistryState::Get().show_workflow_output_callback = std::move(callback);
281}
282
283std::function<void()> cancel_build_workflow_callback() {
284 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
285 return RegistryState::Get().cancel_build_workflow_callback;
286}
287
288void SetCancelBuildWorkflowCallback(std::function<void()> callback) {
289 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
290 RegistryState::Get().cancel_build_workflow_callback = std::move(callback);
291}
292
293void Clear() {
294 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
295 auto& state = RegistryState::Get();
296 if (state.global_context) {
297 state.global_context->Clear();
298 }
299 state.current_rom = nullptr;
300 state.event_bus = nullptr;
301 state.current_editor = nullptr;
302 state.game_data = nullptr;
303 state.current_project = nullptr;
304 state.hack_workflow_backend = nullptr;
305 state.current_window_editors.clear();
306 state.build_workflow_status = ProjectWorkflowStatus{};
307 state.run_workflow_status = ProjectWorkflowStatus{};
308 state.build_workflow_log.clear();
309 state.workflow_history.clear();
310 state.start_build_workflow_callback = nullptr;
311 state.run_project_workflow_callback = nullptr;
312 state.show_workflow_output_callback = nullptr;
313 state.cancel_build_workflow_callback = nullptr;
314}
315
316} // namespace Context
317
318// =============================================================================
319// Panels Implementation
320// =============================================================================
321
322namespace Panels {
323
324void RegisterFactory(PanelFactory factory) {
325 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
326 RegistryState::Get().factories.push_back(std::move(factory));
327}
328
329std::vector<std::unique_ptr<WindowContent>> CreateAll() {
330 std::vector<PanelFactory> factories;
331 {
332 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
333 factories = RegistryState::Get().factories;
334 }
335
336 std::vector<std::unique_ptr<WindowContent>> result;
337 result.reserve(factories.size());
338
339 for (const auto& factory : factories) {
340 if (auto panel = factory()) {
341 result.push_back(std::move(panel));
342 }
343 }
344 return result;
345}
346
347void Register(std::unique_ptr<WindowContent> panel) {
348 if (!panel)
349 return;
350
351 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
352 RegistryState::Get().panels.push_back(std::move(panel));
353}
354
355std::vector<WindowContent*> GetAll() {
356 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
357
358 std::vector<WindowContent*> result;
359 result.reserve(RegistryState::Get().panels.size());
360
361 for (const auto& panel : RegistryState::Get().panels) {
362 result.push_back(panel.get());
363 }
364
365 return result;
366}
367
368WindowContent* Get(const std::string& id) {
369 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
370
371 for (const auto& panel : RegistryState::Get().panels) {
372 if (panel->GetId() == id) {
373 return panel.get();
374 }
375 }
376
377 return nullptr;
378}
379
380void Clear() {
381 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
382 RegistryState::Get().panels.clear();
383}
384
385} // namespace Panels
386
387// =============================================================================
388// Editors Implementation
389// =============================================================================
390
391namespace Editors {
392
393void RegisterFactory(EditorFactory factory) {
394 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
395 RegistryState::Get().editor_factories.push_back(std::move(factory));
396}
397
398std::vector<std::unique_ptr<Editor>> CreateAll(const EditorDependencies& deps) {
399 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
400 std::vector<std::unique_ptr<Editor>> result;
401 result.reserve(RegistryState::Get().editor_factories.size());
402
403 for (const auto& factory : RegistryState::Get().editor_factories) {
404 if (auto editor = factory(deps)) {
405 result.push_back(std::move(editor));
406 }
407 }
408 return result;
409}
410
411} // namespace Editors
412
413// =============================================================================
414// Shortcuts Implementation
415// =============================================================================
416
417namespace Shortcuts {
418
419void Register(const ShortcutDef& shortcut) {
420 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
421 RegistryState::Get().shortcuts.push_back(shortcut);
422}
423
424void add(const std::string& id, const std::string& key,
425 const std::string& desc) {
426 Register({id, key, desc});
427}
428
429std::vector<ShortcutDef> GetAll() {
430 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
431 return RegistryState::Get().shortcuts;
432}
433
434} // namespace Shortcuts
435
436// =============================================================================
437// WorkflowActions Implementation
438// =============================================================================
439
440namespace WorkflowActions {
441
442void Register(const ActionDef& action) {
443 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
444 auto& actions = RegistryState::Get().workflow_actions;
445 auto it = std::find_if(
446 actions.begin(), actions.end(),
447 [&](const ActionDef& existing) { return existing.id == action.id; });
448 if (it != actions.end()) {
449 *it = action;
450 return;
451 }
452 actions.push_back(action);
453}
454
455std::vector<ActionDef> GetAll() {
456 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
457 return RegistryState::Get().workflow_actions;
458}
459
460void Clear() {
461 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
462 RegistryState::Get().workflow_actions.clear();
463}
464
465} // namespace WorkflowActions
466
467// =============================================================================
468// Settings Implementation
469// =============================================================================
470
471namespace Settings {
472
473void Register(const SettingDef& setting) {
474 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
475 RegistryState::Get().settings.push_back(setting);
476}
477
478void add(const std::string& section, const std::string& key,
479 const std::string& default_val, const std::string& desc) {
480 Register({key, section, default_val, desc});
481}
482
483std::vector<SettingDef> GetAll() {
484 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
485 return RegistryState::Get().settings;
486}
487
488} // namespace Settings
489
490} // namespace ContentRegistry
491
492} // namespace yaze::editor
std::vector< ProjectWorkflowHistoryEntry > workflow_history()
void SetGlobalContext(GlobalEditorContext *ctx)
void SetShowWorkflowOutputCallback(std::function< void()> callback)
void SetEditorWindowContext(const std::string &category, Editor *editor)
Rom * rom()
Get the current ROM instance.
void SetEventBus(::yaze::EventBus *bus)
Set the current EventBus instance.
::yaze::EventBus * event_bus()
Get the current EventBus instance.
void SetRom(Rom *rom)
Set the current ROM instance.
void SetGameData(::yaze::zelda3::GameData *data)
Set the current game data instance.
void AppendWorkflowHistory(const ProjectWorkflowHistoryEntry &entry)
Editor * current_editor()
Get the currently active editor.
void SetRunProjectWorkflowCallback(std::function< void()> callback)
void SetBuildWorkflowStatus(const ProjectWorkflowStatus &status)
void SetCancelBuildWorkflowCallback(std::function< void()> callback)
std::function< void()> cancel_build_workflow_callback()
void SetCurrentEditor(Editor *editor)
Set the currently active editor.
::yaze::zelda3::GameData * game_data()
Get the current game data instance.
ProjectWorkflowStatus build_workflow_status()
workflow::PlanningCapability * hack_planning_backend()
::yaze::project::YazeProject * current_project()
Get the current project instance.
void SetBuildWorkflowLog(const std::string &output)
void SetStartBuildWorkflowCallback(std::function< void()> callback)
void SetRunWorkflowStatus(const ProjectWorkflowStatus &status)
workflow::ValidationCapability * hack_validation_backend()
std::function< void()> run_project_workflow_callback()
void SetHackWorkflowBackend(workflow::HackWorkflowBackend *backend)
void Clear()
Clear all context state.
workflow::HackWorkflowBackend * hack_workflow_backend()
std::function< void()> show_workflow_output_callback()
std::function< void()> start_build_workflow_callback()
Editor * editor_window_context(const std::string &category)
workflow::ProgressionCapability * hack_progression_backend()
void SetCurrentProject(::yaze::project::YazeProject *project)
Set the current project instance.
void RegisterFactory(EditorFactory factory)
std::function< std::unique_ptr< Editor >(const EditorDependencies &)> EditorFactory
std::vector< std::unique_ptr< Editor > > CreateAll(const EditorDependencies &deps)
void Clear()
Clear all registered panels.
void Register(std::unique_ptr< WindowContent > panel)
Register a panel instance (Legacy/Global).
std::vector< WindowContent * > GetAll()
Get all registered panels.
WindowContent * Get(const std::string &id)
Get a specific panel by its ID.
std::function< std::unique_ptr< WindowContent >()> PanelFactory
void RegisterFactory(PanelFactory factory)
Register a panel factory.
std::vector< std::unique_ptr< WindowContent > > CreateAll()
Create new instances of all registered panels.
void Register(const SettingDef &setting)
void add(const std::string &section, const std::string &key, const std::string &default_val, const std::string &desc)
void add(const std::string &id, const std::string &key, const std::string &desc)
void Register(const ShortcutDef &shortcut)
Editors are the view controllers for the application.
Modern project structure with comprehensive settings consolidation.
Definition project.h:164