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
14#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
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;
37 ::yaze::zelda3::GameData* game_data = nullptr;
38 ::yaze::project::YazeProject* current_project = nullptr;
39 workflow::HackWorkflowBackend* hack_workflow_backend = nullptr;
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
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) return state.global_context->GetCurrentRom();
80 return state.current_rom;
81}
82
83void SetRom(Rom* rom) {
84 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
85 auto& state = RegistryState::Get();
86 if (state.global_context) {
87 state.global_context->SetCurrentRom(rom);
88 }
89 state.current_rom = rom; // keep fallback in sync
90}
91
93 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
94 auto& state = RegistryState::Get();
95 if (state.global_context) return &state.global_context->GetEventBus();
96 return state.event_bus;
97}
98
100 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
101 auto& state = RegistryState::Get();
102 // EventBus in GlobalEditorContext is a reference set at construction,
103 // so we don't update it here. Just keep fallback in sync.
104 state.event_bus = bus;
105}
106
108 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
109 auto& state = RegistryState::Get();
110 if (state.global_context) return state.global_context->GetCurrentEditor();
111 return state.current_editor;
112}
113
115 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
116 auto& state = RegistryState::Get();
117 if (state.global_context) {
118 state.global_context->SetCurrentEditor(editor);
119 }
120 state.current_editor = editor;
121}
122
123Editor* editor_window_context(const std::string& category) {
124 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
125 auto& state = RegistryState::Get();
126 auto it = state.current_window_editors.find(category);
127 return it != state.current_window_editors.end() ? it->second : nullptr;
128}
129
130void SetEditorWindowContext(const std::string& category, Editor* editor) {
131 if (category.empty()) {
132 return;
133 }
134 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
135 RegistryState::Get().current_window_editors[category] = editor;
136}
137
139 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
140 auto& state = RegistryState::Get();
141 if (state.global_context) return state.global_context->GetGameData();
142 return state.game_data;
143}
144
146 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
147 auto& state = RegistryState::Get();
148 if (state.global_context) {
149 state.global_context->SetGameData(data);
150 }
151 state.game_data = data;
152}
153
155 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
156 auto& state = RegistryState::Get();
157 if (state.global_context) return state.global_context->GetCurrentProject();
158 return state.current_project;
159}
160
162 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
163 auto& state = RegistryState::Get();
164 if (state.global_context) {
165 state.global_context->SetCurrentProject(project);
166 }
167 state.current_project = project;
168}
169
171 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
172 return RegistryState::Get().hack_workflow_backend;
173}
174
176 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
177 return dynamic_cast<workflow::ValidationCapability*>(
178 RegistryState::Get().hack_workflow_backend);
179}
180
182 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
183 return dynamic_cast<workflow::ProgressionCapability*>(
184 RegistryState::Get().hack_workflow_backend);
185}
186
188 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
189 return dynamic_cast<workflow::PlanningCapability*>(
190 RegistryState::Get().hack_workflow_backend);
191}
192
194 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
195 RegistryState::Get().hack_workflow_backend = backend;
196}
197
199 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
200 return RegistryState::Get().build_workflow_status;
201}
202
204 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
205 RegistryState::Get().build_workflow_status = status;
206}
207
209 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
210 return RegistryState::Get().run_workflow_status;
211}
212
214 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
215 RegistryState::Get().run_workflow_status = status;
216}
217
218std::string build_workflow_log() {
219 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
220 return RegistryState::Get().build_workflow_log;
221}
222
223void SetBuildWorkflowLog(const std::string& output) {
224 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
225 RegistryState::Get().build_workflow_log = output;
226}
227
228std::vector<ProjectWorkflowHistoryEntry> workflow_history() {
229 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
230 return RegistryState::Get().workflow_history;
231}
232
234 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
235 auto& history = RegistryState::Get().workflow_history;
236 history.insert(history.begin(), entry);
237 constexpr size_t kMaxEntries = 20;
238 if (history.size() > kMaxEntries) {
239 history.resize(kMaxEntries);
240 }
241}
242
244 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
245 RegistryState::Get().workflow_history.clear();
246}
247
248std::function<void()> start_build_workflow_callback() {
249 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
250 return RegistryState::Get().start_build_workflow_callback;
251}
252
253void SetStartBuildWorkflowCallback(std::function<void()> callback) {
254 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
255 RegistryState::Get().start_build_workflow_callback = std::move(callback);
256}
257
258std::function<void()> run_project_workflow_callback() {
259 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
260 return RegistryState::Get().run_project_workflow_callback;
261}
262
263void SetRunProjectWorkflowCallback(std::function<void()> callback) {
264 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
265 RegistryState::Get().run_project_workflow_callback = std::move(callback);
266}
267
268std::function<void()> show_workflow_output_callback() {
269 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
270 return RegistryState::Get().show_workflow_output_callback;
271}
272
273void SetShowWorkflowOutputCallback(std::function<void()> callback) {
274 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
275 RegistryState::Get().show_workflow_output_callback = std::move(callback);
276}
277
278std::function<void()> cancel_build_workflow_callback() {
279 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
280 return RegistryState::Get().cancel_build_workflow_callback;
281}
282
283void SetCancelBuildWorkflowCallback(std::function<void()> callback) {
284 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
285 RegistryState::Get().cancel_build_workflow_callback = std::move(callback);
286}
287
288void Clear() {
289 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
290 auto& state = RegistryState::Get();
291 if (state.global_context) {
292 state.global_context->Clear();
293 }
294 state.current_rom = nullptr;
295 state.event_bus = nullptr;
296 state.current_editor = nullptr;
297 state.game_data = nullptr;
298 state.current_project = nullptr;
299 state.hack_workflow_backend = nullptr;
300 state.current_window_editors.clear();
301 state.build_workflow_status = ProjectWorkflowStatus{};
302 state.run_workflow_status = ProjectWorkflowStatus{};
303 state.build_workflow_log.clear();
304 state.workflow_history.clear();
305 state.start_build_workflow_callback = nullptr;
306 state.run_project_workflow_callback = nullptr;
307 state.show_workflow_output_callback = nullptr;
308 state.cancel_build_workflow_callback = nullptr;
309}
310
311} // namespace Context
312
313// =============================================================================
314// Panels Implementation
315// =============================================================================
316
317namespace Panels {
318
320 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
321 RegistryState::Get().factories.push_back(std::move(factory));
322}
323
324std::vector<std::unique_ptr<WindowContent>> CreateAll() {
325 std::vector<PanelFactory> factories;
326 {
327 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
328 factories = RegistryState::Get().factories;
329 }
330
331 std::vector<std::unique_ptr<WindowContent>> result;
332 result.reserve(factories.size());
333
334 for (const auto& factory : factories) {
335 if (auto panel = factory()) {
336 result.push_back(std::move(panel));
337 }
338 }
339 return result;
340}
341
342void Register(std::unique_ptr<WindowContent> panel) {
343 if (!panel) return;
344
345 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
346 RegistryState::Get().panels.push_back(std::move(panel));
347}
348
349std::vector<WindowContent*> GetAll() {
350 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
351
352 std::vector<WindowContent*> result;
353 result.reserve(RegistryState::Get().panels.size());
354
355 for (const auto& panel : RegistryState::Get().panels) {
356 result.push_back(panel.get());
357 }
358
359 return result;
360}
361
362WindowContent* Get(const std::string& id) {
363 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
364
365 for (const auto& panel : RegistryState::Get().panels) {
366 if (panel->GetId() == id) {
367 return panel.get();
368 }
369 }
370
371 return nullptr;
372}
373
374void Clear() {
375 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
376 RegistryState::Get().panels.clear();
377}
378
379} // namespace Panels
380
381// =============================================================================
382// Editors Implementation
383// =============================================================================
384
385namespace Editors {
386
388 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
389 RegistryState::Get().editor_factories.push_back(std::move(factory));
390}
391
392std::vector<std::unique_ptr<Editor>> CreateAll(const EditorDependencies& deps) {
393 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
394 std::vector<std::unique_ptr<Editor>> result;
395 result.reserve(RegistryState::Get().editor_factories.size());
396
397 for (const auto& factory : RegistryState::Get().editor_factories) {
398 if (auto editor = factory(deps)) {
399 result.push_back(std::move(editor));
400 }
401 }
402 return result;
403}
404
405} // namespace Editors
406
407// =============================================================================
408// Shortcuts Implementation
409// =============================================================================
410
411namespace Shortcuts {
412
413void Register(const ShortcutDef& shortcut) {
414 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
415 RegistryState::Get().shortcuts.push_back(shortcut);
416}
417
418void add(const std::string& id, const std::string& key, const std::string& desc) {
419 Register({id, key, desc});
420}
421
422std::vector<ShortcutDef> GetAll() {
423 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
424 return RegistryState::Get().shortcuts;
425}
426
427} // namespace Shortcuts
428
429// =============================================================================
430// WorkflowActions Implementation
431// =============================================================================
432
433namespace WorkflowActions {
434
435void Register(const ActionDef& action) {
436 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
437 auto& actions = RegistryState::Get().workflow_actions;
438 auto it = std::find_if(actions.begin(), actions.end(),
439 [&](const ActionDef& existing) {
440 return existing.id == action.id;
441 });
442 if (it != actions.end()) {
443 *it = action;
444 return;
445 }
446 actions.push_back(action);
447}
448
449std::vector<ActionDef> GetAll() {
450 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
451 return RegistryState::Get().workflow_actions;
452}
453
454void Clear() {
455 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
456 RegistryState::Get().workflow_actions.clear();
457}
458
459} // namespace WorkflowActions
460
461// =============================================================================
462// Settings Implementation
463// =============================================================================
464
465namespace Settings {
466
467void Register(const SettingDef& setting) {
468 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
469 RegistryState::Get().settings.push_back(setting);
470}
471
472void add(const std::string& section, const std::string& key, const std::string& default_val, const std::string& desc) {
473 Register({key, section, default_val, desc});
474}
475
476std::vector<SettingDef> GetAll() {
477 std::lock_guard<std::mutex> lock(RegistryState::Get().mutex);
478 return RegistryState::Get().settings;
479}
480
481} // namespace Settings
482
483} // namespace ContentRegistry
484
485} // namespace yaze::editor
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:28
Interface for editor classes.
Definition editor.h:240
Instance-based runtime context replacing ContentRegistry::Context.
Base interface for all logical window content components.
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.
Unified dependency container for all editor types.
Definition editor.h:164
std::vector< ContentRegistry::Editors::EditorFactory > editor_factories
std::vector< ContentRegistry::Panels::PanelFactory > factories
std::unordered_map< std::string, Editor * > current_window_editors
std::vector< ContentRegistry::Settings::SettingDef > settings
std::vector< ContentRegistry::WorkflowActions::ActionDef > workflow_actions
std::vector< ContentRegistry::Shortcuts::ShortcutDef > shortcuts
Modern project structure with comprehensive settings consolidation.
Definition project.h:164