7#include <emscripten/bind.h>
9#include "absl/strings/str_format.h"
22#include "nlohmann/json.hpp"
33editor::EditorManager* WasmControlApi::editor_manager_ =
nullptr;
34bool WasmControlApi::initialized_ =
false;
40EM_JS(
void, SetupYazeControlApi, (), {
41 if (typeof Module ===
'undefined')
return;
49 window.yaze.control = {
51 switchEditor: function(editorName) {
52 if (Module.controlSwitchEditor) {
53 try {
return JSON.parse(Module.controlSwitchEditor(editorName)); }
54 catch(e) {
return {error: e.message}; }
56 return {error:
"API not ready"};
59 getCurrentEditor: function() {
60 if (Module.controlGetCurrentEditor) {
61 try {
return JSON.parse(Module.controlGetCurrentEditor()); }
62 catch(e) {
return {error: e.message}; }
64 return {error:
"API not ready"};
67 getAvailableEditors: function() {
68 if (Module.controlGetAvailableEditors) {
69 try {
return JSON.parse(Module.controlGetAvailableEditors()); }
70 catch(e) {
return {error: e.message}; }
72 return {error:
"API not ready"};
76 openPanel: function(cardId) {
77 if (Module.controlOpenPanel) {
78 try {
return JSON.parse(Module.controlOpenPanel(cardId)); }
79 catch(e) {
return {error: e.message}; }
81 return {error:
"API not ready"};
84 closePanel: function(cardId) {
85 if (Module.controlClosePanel) {
86 try {
return JSON.parse(Module.controlClosePanel(cardId)); }
87 catch(e) {
return {error: e.message}; }
89 return {error:
"API not ready"};
93 if (Module.controlTogglePanel) {
94 try {
return JSON.parse(Module.controlTogglePanel(cardId)); }
95 catch(e) {
return {error: e.message}; }
97 return {error:
"API not ready"};
101 openPanel: function(panelId) {
return this.openPanel(panelId); },
102 closePanel: function(panelId) {
return this.closePanel(panelId); },
105 getVisiblePanels: function() {
106 if (Module.controlGetVisiblePanels) {
107 try {
return JSON.parse(Module.controlGetVisiblePanels()); }
108 catch(e) {
return {error: e.message}; }
110 return {error:
"API not ready"};
113 getVisiblePanels: function() {
return this.getVisiblePanels(); },
115 getAvailablePanels: function() {
116 if (Module.controlGetAvailablePanels) {
117 try {
return JSON.parse(Module.controlGetAvailablePanels()); }
118 catch(e) {
return {error: e.message}; }
120 return {error:
"API not ready"};
123 getAvailablePanels: function() {
return this.getAvailablePanels(); },
126 if (Module.controlGetPanelsInCategory) {
127 try {
return JSON.parse(Module.controlGetPanelsInCategory(category)); }
128 catch(e) {
return {error: e.message}; }
130 return {error:
"API not ready"};
135 showAllPanels: function() {
136 if (Module.controlShowAllPanels) {
137 try {
return JSON.parse(Module.controlShowAllPanels()); }
138 catch(e) {
return {error: e.message}; }
140 return {error:
"API not ready"};
143 showAllPanels: function() {
return this.showAllPanels(); },
145 hideAllPanels: function() {
146 if (Module.controlHideAllPanels) {
147 try {
return JSON.parse(Module.controlHideAllPanels()); }
148 catch(e) {
return {error: e.message}; }
150 return {error:
"API not ready"};
153 hideAllPanels: function() {
return this.hideAllPanels(); },
155 showAllPanelsInCategory: function(category) {
156 if (Module.controlShowAllPanelsInCategory) {
157 try {
return JSON.parse(Module.controlShowAllPanelsInCategory(category)); }
158 catch(e) {
return {error: e.message}; }
160 return {error:
"API not ready"};
163 showAllPanelsInCategory: function(category) {
return this.showAllPanelsInCategory(category); },
165 hideAllPanelsInCategory: function(category) {
166 if (Module.controlHideAllPanelsInCategory) {
167 try {
return JSON.parse(Module.controlHideAllPanelsInCategory(category)); }
168 catch(e) {
return {error: e.message}; }
170 return {error:
"API not ready"};
173 hideAllPanelsInCategory: function(category) {
return this.hideAllPanelsInCategory(category); },
175 showOnlyPanel: function(cardId) {
176 if (Module.controlShowOnlyPanel) {
177 try {
return JSON.parse(Module.controlShowOnlyPanel(cardId)); }
178 catch(e) {
return {error: e.message}; }
180 return {error:
"API not ready"};
183 showOnlyPanel: function(panelId) {
return this.showOnlyPanel(panelId); },
186 setPanelLayout: function(layoutName) {
187 if (Module.controlSetPanelLayout) {
188 try {
return JSON.parse(Module.controlSetPanelLayout(layoutName)); }
189 catch(e) {
return {error: e.message}; }
191 return {error:
"API not ready"};
194 setPanelLayout: function(layoutName) {
return this.setPanelLayout(layoutName); },
196 getAvailableLayouts: function() {
197 if (Module.controlGetAvailableLayouts) {
198 try {
return JSON.parse(Module.controlGetAvailableLayouts()); }
199 catch(e) {
return {error: e.message}; }
201 return {error:
"API not ready"};
204 saveCurrentLayout: function(layoutName) {
205 if (Module.controlSaveCurrentLayout) {
206 try {
return JSON.parse(Module.controlSaveCurrentLayout(layoutName)); }
207 catch(e) {
return {error: e.message}; }
209 return {error:
"API not ready"};
213 triggerMenuAction: function(actionPath) {
214 if (Module.controlTriggerMenuAction) {
215 try {
return JSON.parse(Module.controlTriggerMenuAction(actionPath)); }
216 catch(e) {
return {error: e.message}; }
218 return {error:
"API not ready"};
221 getAvailableMenuActions: function() {
222 if (Module.controlGetAvailableMenuActions) {
223 try {
return JSON.parse(Module.controlGetAvailableMenuActions()); }
224 catch(e) {
return {error: e.message}; }
226 return {error:
"API not ready"};
230 getSessionInfo: function() {
231 if (Module.controlGetSessionInfo) {
232 try {
return JSON.parse(Module.controlGetSessionInfo()); }
233 catch(e) {
return {error: e.message}; }
235 return {error:
"API not ready"};
238 createSession: function() {
239 if (Module.controlCreateSession) {
240 try {
return JSON.parse(Module.controlCreateSession()); }
241 catch(e) {
return {error: e.message}; }
243 return {error:
"API not ready"};
246 switchSession: function(sessionIndex) {
247 if (Module.controlSwitchSession) {
248 try {
return JSON.parse(Module.controlSwitchSession(sessionIndex)); }
249 catch(e) {
return {error: e.message}; }
251 return {error:
"API not ready"};
256 if (Module.controlGetRomStatus) {
257 try {
return JSON.parse(Module.controlGetRomStatus()); }
258 catch(e) {
return {error: e.message}; }
260 return {error:
"API not ready"};
265 if (Module.controlReadRomBytes) {
266 try {
return JSON.parse(Module.controlReadRomBytes(address, count)); }
267 catch(e) {
return {error: e.message}; }
269 return {error:
"API not ready"};
272 writeRomBytes: function(address, bytes) {
273 if (Module.controlWriteRomBytes) {
274 try {
return JSON.parse(Module.controlWriteRomBytes(address, JSON.stringify(bytes))); }
275 catch(e) {
return {error: e.message}; }
277 return {error:
"API not ready"};
280 saveRom: function() {
281 if (Module.controlSaveRom) {
282 try {
return JSON.parse(Module.controlSaveRom()); }
283 catch(e) {
return {error: e.message}; }
285 return {error:
"API not ready"};
289 isReady: function() {
290 return Module.controlIsReady ? Module.controlIsReady() :
false;
294 getPlatformInfo: function() {
295 if (Module.controlGetPlatformInfo) {
296 try {
return JSON.parse(Module.controlGetPlatformInfo()); }
297 catch(e) {
return {error: e.message}; }
299 return {error:
"API not ready"};
304 window.yaze.editor = {
305 getSnapshot: function() {
306 if (Module.editorGetSnapshot) {
307 try {
return JSON.parse(Module.editorGetSnapshot()); }
308 catch(e) {
return {error: e.message}; }
310 return {error:
"API not ready"};
313 getCurrentRoom: function() {
314 if (Module.editorGetCurrentDungeonRoom) {
315 try {
return JSON.parse(Module.editorGetCurrentDungeonRoom()); }
316 catch(e) {
return {error: e.message}; }
318 return {error:
"API not ready"};
321 getCurrentMap: function() {
322 if (Module.editorGetCurrentOverworldMap) {
323 try {
return JSON.parse(Module.editorGetCurrentOverworldMap()); }
324 catch(e) {
return {error: e.message}; }
326 return {error:
"API not ready"};
329 getSelection: function() {
330 if (Module.editorGetSelection) {
331 try {
return JSON.parse(Module.editorGetSelection()); }
332 catch(e) {
return {error: e.message}; }
334 return {error:
"API not ready"};
341 getRoomTiles: function(roomId) {
342 if (Module.dataGetRoomTileData) {
343 try {
return JSON.parse(Module.dataGetRoomTileData(roomId)); }
344 catch(e) {
return {error: e.message}; }
346 return {error:
"API not ready"};
349 getRoomObjects: function(roomId) {
350 if (Module.dataGetRoomObjects) {
351 try {
return JSON.parse(Module.dataGetRoomObjects(roomId)); }
352 catch(e) {
return {error: e.message}; }
354 return {error:
"API not ready"};
357 getRoomProperties: function(roomId) {
358 if (Module.dataGetRoomProperties) {
359 try {
return JSON.parse(Module.dataGetRoomProperties(roomId)); }
360 catch(e) {
return {error: e.message}; }
362 return {error:
"API not ready"};
366 getMapTiles: function(mapId) {
367 if (Module.dataGetMapTileData) {
368 try {
return JSON.parse(Module.dataGetMapTileData(mapId)); }
369 catch(e) {
return {error: e.message}; }
371 return {error:
"API not ready"};
374 getMapEntities: function(mapId) {
375 if (Module.dataGetMapEntities) {
376 try {
return JSON.parse(Module.dataGetMapEntities(mapId)); }
377 catch(e) {
return {error: e.message}; }
379 return {error:
"API not ready"};
382 getMapProperties: function(mapId) {
383 if (Module.dataGetMapProperties) {
384 try {
return JSON.parse(Module.dataGetMapProperties(mapId)); }
385 catch(e) {
return {error: e.message}; }
387 return {error:
"API not ready"};
391 getPalette: function(groupName, paletteId) {
392 if (Module.dataGetPaletteData) {
393 try {
return JSON.parse(Module.dataGetPaletteData(groupName, paletteId)); }
394 catch(e) {
return {error: e.message}; }
396 return {error:
"API not ready"};
399 getPaletteGroups: function() {
400 if (Module.dataListPaletteGroups) {
401 try {
return JSON.parse(Module.dataListPaletteGroups()); }
402 catch(e) {
return {error: e.message}; }
404 return {error:
"API not ready"};
409 window.yaze.agent = {
411 sendMessage: function(message) {
412 if (Module.agentSendMessage) {
413 try {
return JSON.parse(Module.agentSendMessage(message)); }
414 catch(e) {
return {error: e.message}; }
416 return {error:
"API not ready"};
420 getChatHistory: function() {
421 if (Module.agentGetChatHistory) {
422 try {
return JSON.parse(Module.agentGetChatHistory()); }
423 catch(e) {
return {error: e.message}; }
425 return {error:
"API not ready"};
429 getConfig: function() {
430 if (Module.agentGetConfig) {
431 try {
return JSON.parse(Module.agentGetConfig()); }
432 catch(e) {
return {error: e.message}; }
434 return {error:
"API not ready"};
438 setConfig: function(config) {
439 if (Module.agentSetConfig) {
440 try {
return JSON.parse(Module.agentSetConfig(JSON.stringify(config))); }
441 catch(e) {
return {error: e.message}; }
443 return {error:
"API not ready"};
447 getProviders: function() {
448 if (Module.agentGetProviders) {
449 try {
return JSON.parse(Module.agentGetProviders()); }
450 catch(e) {
return {error: e.message}; }
452 return {error:
"API not ready"};
456 getProposals: function() {
457 if (Module.agentGetProposals) {
458 try {
return JSON.parse(Module.agentGetProposals()); }
459 catch(e) {
return {error: e.message}; }
461 return {error:
"API not ready"};
465 acceptProposal: function(proposalId) {
466 if (Module.agentAcceptProposal) {
467 try {
return JSON.parse(Module.agentAcceptProposal(proposalId)); }
468 catch(e) {
return {error: e.message}; }
470 return {error:
"API not ready"};
474 rejectProposal: function(proposalId) {
475 if (Module.agentRejectProposal) {
476 try {
return JSON.parse(Module.agentRejectProposal(proposalId)); }
477 catch(e) {
return {error: e.message}; }
479 return {error:
"API not ready"};
483 getProposalDetails: function(proposalId) {
484 if (Module.agentGetProposalDetails) {
485 try {
return JSON.parse(Module.agentGetProposalDetails(proposalId)); }
486 catch(e) {
return {error: e.message}; }
488 return {error:
"API not ready"};
492 openSidebar: function() {
493 if (Module.agentOpenSidebar) {
494 try {
return JSON.parse(Module.agentOpenSidebar()); }
495 catch(e) {
return {error: e.message}; }
497 return {error:
"API not ready"};
500 closeSidebar: function() {
501 if (Module.agentCloseSidebar) {
502 try {
return JSON.parse(Module.agentCloseSidebar()); }
503 catch(e) {
return {error: e.message}; }
505 return {error:
"API not ready"};
509 isReady: function() {
510 return Module.agentIsReady ? Module.agentIsReady() :
false;
514 console.log(
"[yaze] window.yaze.control API initialized");
515 console.log(
"[yaze] window.yaze.editor API initialized");
516 console.log(
"[yaze] window.yaze.data API initialized");
517 console.log(
"[yaze] window.yaze.agent API initialized");
524void WasmControlApi::Initialize(editor::EditorManager* editor_manager) {
525 editor_manager_ = editor_manager;
526 initialized_ = (editor_manager_ !=
nullptr);
529 SetupJavaScriptBindings();
530 LOG_INFO(
"WasmControlApi",
"Control API initialized");
534bool WasmControlApi::IsReady() {
535 return initialized_ && editor_manager_ !=
nullptr;
538void WasmControlApi::SetupJavaScriptBindings() {
539 SetupYazeControlApi();
546editor::PanelManager* WasmControlApi::GetPanelRegistry() {
547 if (!IsReady() || !editor_manager_) {
550 return &editor_manager_->card_registry();
553std::string WasmControlApi::EditorTypeToString(
int type) {
560int WasmControlApi::StringToEditorType(
const std::string& name) {
563 return static_cast<int>(i);
573std::string WasmControlApi::SwitchEditor(
const std::string& editor_name) {
574 nlohmann::json result;
577 result[
"success"] =
false;
578 result[
"error"] =
"Control API not initialized";
579 return result.dump();
582 int editor_type = StringToEditorType(editor_name);
583 if (editor_type == 0 && editor_name !=
"Unknown") {
584 result[
"success"] =
false;
585 result[
"error"] =
"Unknown editor: " + editor_name;
586 return result.dump();
591 result[
"success"] =
true;
592 result[
"editor"] = editor_name;
593 return result.dump();
596std::string WasmControlApi::GetCurrentEditor() {
597 nlohmann::json result;
600 result[
"error"] =
"Control API not initialized";
601 return result.dump();
604 auto* current = editor_manager_->GetCurrentEditor();
606 result[
"name"] = EditorTypeToString(
static_cast<int>(current->type()));
607 result[
"type"] =
static_cast<int>(current->type());
608 result[
"active"] = *current->active();
610 result[
"name"] =
"None";
612 result[
"active"] =
false;
615 return result.dump();
618std::string WasmControlApi::GetAvailableEditors() {
619 nlohmann::json result = nlohmann::json::array();
622 nlohmann::json editor_info;
624 editor_info[
"type"] =
static_cast<int>(i);
625 result.push_back(editor_info);
628 return result.dump();
635std::string WasmControlApi::OpenPanel(
const std::string& card_id) {
636 nlohmann::json result;
639 result[
"success"] =
false;
640 result[
"error"] =
"Control API not initialized";
641 return result.dump();
644 auto* registry = GetPanelRegistry();
647 constexpr size_t session_id = 0;
648 bool found = registry->ShowPanel(session_id, card_id);
650 result[
"success"] = found;
651 result[
"card_id"] = card_id;
652 result[
"visible"] =
true;
654 result[
"error"] =
"Panel not found";
657 result[
"success"] =
false;
658 result[
"error"] =
"Panel registry not available";
661 LOG_INFO(
"WasmControlApi",
"OpenPanel: %s", card_id.c_str());
662 return result.dump();
665std::string WasmControlApi::ClosePanel(
const std::string& card_id) {
666 nlohmann::json result;
669 result[
"success"] =
false;
670 result[
"error"] =
"Control API not initialized";
671 return result.dump();
674 auto* registry = GetPanelRegistry();
676 constexpr size_t session_id = 0;
677 bool found = registry->HidePanel(session_id, card_id);
679 result[
"success"] = found;
680 result[
"card_id"] = card_id;
681 result[
"visible"] =
false;
683 result[
"error"] =
"Panel not found";
686 result[
"success"] =
false;
687 result[
"error"] =
"Panel registry not available";
690 LOG_INFO(
"WasmControlApi",
"ClosePanel: %s", card_id.c_str());
691 return result.dump();
694std::string WasmControlApi::TogglePanel(
const std::string& card_id) {
695 nlohmann::json result;
698 result[
"success"] =
false;
699 result[
"error"] =
"Control API not initialized";
700 return result.dump();
703 auto* registry = GetPanelRegistry();
705 constexpr size_t session_id = 0;
706 bool found = registry->TogglePanel(session_id, card_id);
708 result[
"success"] = found;
709 result[
"card_id"] = card_id;
711 result[
"error"] =
"Panel not found";
713 result[
"visible"] = registry->IsPanelVisible(session_id, card_id);
716 result[
"success"] =
false;
717 result[
"error"] =
"Panel registry not available";
720 LOG_INFO(
"WasmControlApi",
"TogglePanel: %s", card_id.c_str());
721 return result.dump();
724std::string WasmControlApi::GetVisiblePanels() {
725 nlohmann::json result = nlohmann::json::array();
728 return result.dump();
731 auto* registry = GetPanelRegistry();
733 return result.dump();
737 constexpr size_t session_id = 0;
738 auto card_ids = registry->GetPanelsInSession(session_id);
739 for (
const auto& card_id : card_ids) {
741 std::string base_id = card_id;
742 if (base_id.size() > 3 && base_id[0] ==
's' && base_id[2] ==
'.') {
743 base_id = base_id.substr(3);
745 if (registry->IsPanelVisible(session_id, base_id)) {
746 result.push_back(base_id);
750 return result.dump();
753std::string WasmControlApi::GetAvailablePanels() {
754 nlohmann::json result = nlohmann::json::array();
757 return result.dump();
760 auto* registry = GetPanelRegistry();
762 return result.dump();
766 constexpr size_t session_id = 0;
767 auto categories = registry->GetAllCategories(session_id);
769 for (
const auto& category : categories) {
770 auto panels = registry->GetPanelsInCategory(session_id, category);
771 for (
const auto& panel : panels) {
772 nlohmann::json card_json;
773 card_json[
"id"] = panel.card_id;
774 card_json[
"display_name"] = panel.display_name;
775 card_json[
"window_title"] = panel.window_title;
776 card_json[
"icon"] = panel.icon;
777 card_json[
"category"] = panel.category;
778 card_json[
"priority"] = panel.priority;
779 card_json[
"visible"] = registry->IsPanelVisible(session_id, panel.card_id);
780 card_json[
"shortcut_hint"] = panel.shortcut_hint;
781 if (panel.enabled_condition) {
782 card_json[
"enabled"] = panel.enabled_condition();
784 card_json[
"enabled"] =
true;
786 result.push_back(card_json);
790 return result.dump();
793std::string WasmControlApi::GetPanelsInCategory(
const std::string& category) {
794 nlohmann::json result = nlohmann::json::array();
797 return result.dump();
800 auto* registry = GetPanelRegistry();
802 return result.dump();
806 constexpr size_t session_id = 0;
807 auto panels = registry->GetPanelsInCategory(session_id, category);
809 for (
const auto& panel : panels) {
810 nlohmann::json card_json;
811 card_json[
"id"] = panel.card_id;
812 card_json[
"display_name"] = panel.display_name;
813 card_json[
"window_title"] = panel.window_title;
814 card_json[
"icon"] = panel.icon;
815 card_json[
"category"] = panel.category;
816 card_json[
"priority"] = panel.priority;
817 card_json[
"visible"] = registry->IsPanelVisible(session_id, panel.card_id);
818 result.push_back(card_json);
821 return result.dump();
824std::string WasmControlApi::ShowAllPanels() {
825 nlohmann::json result;
828 result[
"success"] =
false;
829 result[
"error"] =
"Control API not initialized";
830 return result.dump();
833 auto* registry = GetPanelRegistry();
835 constexpr size_t session_id = 0;
836 registry->ShowAllPanelsInSession(session_id);
837 result[
"success"] =
true;
839 result[
"success"] =
false;
840 result[
"error"] =
"Panel registry not available";
843 return result.dump();
846std::string WasmControlApi::HideAllPanels() {
847 nlohmann::json result;
850 result[
"success"] =
false;
851 result[
"error"] =
"Control API not initialized";
852 return result.dump();
855 auto* registry = GetPanelRegistry();
857 constexpr size_t session_id = 0;
858 registry->HideAllPanelsInSession(session_id);
859 result[
"success"] =
true;
861 result[
"success"] =
false;
862 result[
"error"] =
"Panel registry not available";
865 return result.dump();
868std::string WasmControlApi::ShowAllPanelsInCategory(
const std::string& category) {
869 nlohmann::json result;
872 result[
"success"] =
false;
873 result[
"error"] =
"Control API not initialized";
874 return result.dump();
877 auto* registry = GetPanelRegistry();
879 constexpr size_t session_id = 0;
880 registry->ShowAllPanelsInCategory(session_id, category);
881 result[
"success"] =
true;
884 result[
"success"] =
false;
885 result[
"error"] =
"Panel registry not available";
888 return result.dump();
891std::string WasmControlApi::HideAllPanelsInCategory(
const std::string& category) {
892 nlohmann::json result;
895 result[
"success"] =
false;
896 result[
"error"] =
"Control API not initialized";
897 return result.dump();
900 auto* registry = GetPanelRegistry();
902 constexpr size_t session_id = 0;
903 registry->HideAllPanelsInCategory(session_id, category);
904 result[
"success"] =
true;
907 result[
"success"] =
false;
908 result[
"error"] =
"Panel registry not available";
911 return result.dump();
914std::string WasmControlApi::ShowOnlyPanel(
const std::string& card_id) {
915 nlohmann::json result;
918 result[
"success"] =
false;
919 result[
"error"] =
"Control API not initialized";
920 return result.dump();
923 auto* registry = GetPanelRegistry();
925 constexpr size_t session_id = 0;
926 registry->ShowOnlyPanel(session_id, card_id);
927 result[
"success"] =
true;
928 result[
"card_id"] = card_id;
930 result[
"success"] =
false;
931 result[
"error"] =
"Panel registry not available";
934 return result.dump();
941std::string WasmControlApi::SetPanelLayout(
const std::string& layout_name) {
942 nlohmann::json result;
945 result[
"success"] =
false;
946 result[
"error"] =
"Control API not initialized";
947 return result.dump();
951 result[
"success"] =
true;
952 result[
"layout"] = layout_name;
954 LOG_INFO(
"WasmControlApi",
"SetPanelLayout: %s", layout_name.c_str());
955 return result.dump();
958std::string WasmControlApi::GetAvailableLayouts() {
959 nlohmann::json result = nlohmann::json::array();
962 result.push_back(
"overworld_default");
963 result.push_back(
"dungeon_default");
964 result.push_back(
"graphics_default");
965 result.push_back(
"debug_default");
966 result.push_back(
"minimal");
967 result.push_back(
"all_cards");
969 return result.dump();
972std::string WasmControlApi::SaveCurrentLayout(
const std::string& layout_name) {
973 nlohmann::json result;
976 result[
"success"] =
false;
977 result[
"error"] =
"Control API not initialized";
978 return result.dump();
982 result[
"success"] =
true;
983 result[
"layout"] = layout_name;
985 return result.dump();
992std::string WasmControlApi::TriggerMenuAction(
const std::string& action_path) {
993 nlohmann::json result;
996 result[
"success"] =
false;
997 result[
"error"] =
"Control API not initialized";
998 return result.dump();
1004 if (action_path ==
"File.Save") {
1005 auto status = editor_manager_->SaveRom();
1006 result[
"success"] = status.ok();
1008 result[
"error"] = status.ToString();
1010 }
else if (action_path ==
"View.ShowEmulator") {
1011 editor_manager_->ui_coordinator()->SetEmulatorVisible(
true);
1012 result[
"success"] =
true;
1013 }
else if (action_path ==
"View.ShowWelcome") {
1014 editor_manager_->ui_coordinator()->SetWelcomeScreenVisible(
true);
1015 result[
"success"] =
true;
1017 result[
"success"] =
false;
1018 result[
"error"] =
"Unknown action: " + action_path;
1021 return result.dump();
1024std::string WasmControlApi::GetAvailableMenuActions() {
1025 nlohmann::json result = nlohmann::json::array();
1028 result.push_back(
"File.Open");
1029 result.push_back(
"File.Save");
1030 result.push_back(
"File.SaveAs");
1031 result.push_back(
"File.NewProject");
1032 result.push_back(
"File.OpenProject");
1035 result.push_back(
"Edit.Undo");
1036 result.push_back(
"Edit.Redo");
1037 result.push_back(
"Edit.Cut");
1038 result.push_back(
"Edit.Copy");
1039 result.push_back(
"Edit.Paste");
1042 result.push_back(
"View.ShowEmulator");
1043 result.push_back(
"View.ShowWelcome");
1044 result.push_back(
"View.ShowPanelBrowser");
1045 result.push_back(
"View.ShowMemoryEditor");
1046 result.push_back(
"View.ShowHexEditor");
1049 result.push_back(
"Tools.GlobalSearch");
1050 result.push_back(
"Tools.CommandPalette");
1052 return result.dump();
1059std::string WasmControlApi::GetSessionInfo() {
1060 nlohmann::json result;
1063 result[
"error"] =
"Control API not initialized";
1064 return result.dump();
1067 result[
"session_index"] = editor_manager_->GetCurrentSessionIndex();
1068 result[
"session_count"] = editor_manager_->GetActiveSessionCount();
1070 auto* rom = editor_manager_->GetCurrentRom();
1071 if (rom && rom->is_loaded()) {
1072 result[
"rom_loaded"] =
true;
1073 result[
"rom_filename"] = rom->filename();
1074 result[
"rom_title"] = rom->title();
1076 result[
"rom_loaded"] =
false;
1079 auto* current_editor = editor_manager_->GetCurrentEditor();
1080 if (current_editor) {
1081 result[
"current_editor"] = EditorTypeToString(
static_cast<int>(current_editor->type()));
1084 return result.dump();
1087std::string WasmControlApi::CreateSession() {
1088 nlohmann::json result;
1091 result[
"success"] =
false;
1092 result[
"error"] =
"Control API not initialized";
1093 return result.dump();
1096 editor_manager_->CreateNewSession();
1097 result[
"success"] =
true;
1098 result[
"session_index"] = editor_manager_->GetCurrentSessionIndex();
1100 return result.dump();
1103std::string WasmControlApi::SwitchSession(
int session_index) {
1104 nlohmann::json result;
1107 result[
"success"] =
false;
1108 result[
"error"] =
"Control API not initialized";
1109 return result.dump();
1112 if (session_index < 0 ||
static_cast<size_t>(session_index) >= editor_manager_->GetActiveSessionCount()) {
1113 result[
"success"] =
false;
1114 result[
"error"] =
"Invalid session index";
1115 return result.dump();
1118 editor_manager_->SwitchToSession(
static_cast<size_t>(session_index));
1119 result[
"success"] =
true;
1120 result[
"session_index"] = session_index;
1122 return result.dump();
1129std::string WasmControlApi::GetRomStatus() {
1130 nlohmann::json result;
1133 result[
"error"] =
"Control API not initialized";
1134 return result.dump();
1137 auto* rom = editor_manager_->GetCurrentRom();
1138 if (rom && rom->is_loaded()) {
1139 result[
"loaded"] =
true;
1140 result[
"filename"] = rom->filename();
1141 result[
"title"] = rom->title();
1142 result[
"size"] = rom->size();
1143 result[
"dirty"] = rom->dirty();
1145 result[
"loaded"] =
false;
1148 return result.dump();
1151std::string WasmControlApi::ReadRomBytes(
int address,
int count) {
1152 nlohmann::json result;
1155 result[
"error"] =
"Control API not initialized";
1156 return result.dump();
1159 auto* rom = editor_manager_->GetCurrentRom();
1160 if (!rom || !rom->is_loaded()) {
1161 result[
"error"] =
"No ROM loaded";
1162 return result.dump();
1166 count = std::min(count, 256);
1168 if (address < 0 ||
static_cast<size_t>(address + count) > rom->size()) {
1169 result[
"error"] =
"Address out of range";
1170 return result.dump();
1173 result[
"address"] = address;
1174 result[
"count"] = count;
1176 nlohmann::json bytes = nlohmann::json::array();
1177 for (
int i = 0; i < count; ++i) {
1178 auto byte_result = rom->ReadByte(address + i);
1179 if (byte_result.ok()) {
1180 bytes.push_back(*byte_result);
1185 result[
"bytes"] = bytes;
1187 return result.dump();
1190std::string WasmControlApi::WriteRomBytes(
int address,
const std::string& bytes_json) {
1191 nlohmann::json result;
1194 result[
"success"] =
false;
1195 result[
"error"] =
"Control API not initialized";
1196 return result.dump();
1199 auto* rom = editor_manager_->GetCurrentRom();
1200 if (!rom || !rom->is_loaded()) {
1201 result[
"success"] =
false;
1202 result[
"error"] =
"No ROM loaded";
1203 return result.dump();
1207 auto bytes = nlohmann::json::parse(bytes_json);
1208 if (!bytes.is_array()) {
1209 result[
"success"] =
false;
1210 result[
"error"] =
"Invalid bytes format - expected array";
1211 return result.dump();
1214 for (
size_t i = 0; i < bytes.size(); ++i) {
1215 uint8_t value = bytes[i].get<uint8_t>();
1216 auto status = rom->WriteByte(address +
static_cast<int>(i), value);
1218 result[
"success"] =
false;
1219 result[
"error"] = status.ToString();
1220 return result.dump();
1224 result[
"success"] =
true;
1225 result[
"bytes_written"] = bytes.size();
1227 }
catch (
const std::exception& e) {
1228 result[
"success"] =
false;
1229 result[
"error"] = e.what();
1232 return result.dump();
1235std::string WasmControlApi::SaveRom() {
1236 nlohmann::json result;
1239 result[
"success"] =
false;
1240 result[
"error"] =
"Control API not initialized";
1241 return result.dump();
1244 auto status = editor_manager_->SaveRom();
1245 result[
"success"] = status.ok();
1247 result[
"error"] = status.ToString();
1250 return result.dump();
1257std::string WasmControlApi::GetEditorSnapshot() {
1258 nlohmann::json result;
1261 result[
"error"] =
"Control API not initialized";
1262 return result.dump();
1265 auto* current = editor_manager_->GetCurrentEditor();
1267 result[
"editor_type"] =
"none";
1268 result[
"active"] =
false;
1269 return result.dump();
1272 result[
"editor_type"] = EditorTypeToString(
static_cast<int>(current->type()));
1273 result[
"editor_type_id"] =
static_cast<int>(current->type());
1274 result[
"active"] = *current->active();
1277 auto* rom = editor_manager_->GetCurrentRom();
1278 if (rom && rom->is_loaded()) {
1279 result[
"rom_loaded"] =
true;
1280 result[
"rom_title"] = rom->title();
1282 result[
"rom_loaded"] =
false;
1286 nlohmann::json active_data;
1287 auto* editor_set = editor_manager_->GetCurrentEditorSet();
1290 auto* dungeon = editor_set->GetDungeonEditor();
1292 active_data[
"current_room_id"] = dungeon->current_room_id();
1294 nlohmann::json active_rooms = nlohmann::json::array();
1295 for (
int i = 0; i < dungeon->active_rooms().size(); ++i) {
1296 active_rooms.push_back(dungeon->active_rooms()[i]);
1298 active_data[
"active_rooms"] = active_rooms;
1299 active_data[
"room_count"] = dungeon->active_rooms().size();
1303 auto* overworld = editor_set->GetOverworldEditor();
1305 active_data[
"current_map"] = overworld->overworld().current_map_id();
1306 active_data[
"current_world"] = overworld->overworld().current_world();
1311 result[
"active_data"] = active_data;
1313 return result.dump();
1316std::string WasmControlApi::GetCurrentDungeonRoom() {
1317 nlohmann::json result;
1320 result[
"error"] =
"Control API not initialized";
1321 return result.dump();
1324 auto* current = editor_manager_->GetCurrentEditor();
1326 result[
"error"] =
"Dungeon editor not active";
1327 result[
"editor_type"] = current ? EditorTypeToString(
static_cast<int>(current->type())) :
"none";
1328 return result.dump();
1331 auto* editor_set = editor_manager_->GetCurrentEditorSet();
1333 result[
"error"] =
"No editor set available";
1334 return result.dump();
1337 auto* dungeon = editor_set->GetDungeonEditor();
1339 result[
"error"] =
"Dungeon editor not available";
1340 return result.dump();
1342 result[
"room_id"] = dungeon->current_room_id();
1345 nlohmann::json active_rooms = nlohmann::json::array();
1346 for (
int i = 0; i < dungeon->active_rooms().size(); ++i) {
1347 active_rooms.push_back(dungeon->active_rooms()[i]);
1349 result[
"active_rooms"] = active_rooms;
1350 result[
"room_count"] = dungeon->active_rooms().size();
1353 nlohmann::json cards;
1363 result[
"visible_cards"] = cards;
1365 return result.dump();
1368std::string WasmControlApi::GetCurrentOverworldMap() {
1369 nlohmann::json result;
1372 result[
"error"] =
"Control API not initialized";
1373 return result.dump();
1376 auto* current = editor_manager_->GetCurrentEditor();
1378 result[
"error"] =
"Overworld editor not active";
1379 result[
"editor_type"] = current ? EditorTypeToString(
static_cast<int>(current->type())) :
"none";
1380 return result.dump();
1383 auto* editor_set = editor_manager_->GetCurrentEditorSet();
1385 result[
"error"] =
"No editor set available";
1386 return result.dump();
1389 auto* overworld = editor_set->GetOverworldEditor();
1391 result[
"error"] =
"Overworld editor not available";
1392 return result.dump();
1394 auto& ow_data = overworld->overworld();
1396 result[
"map_id"] = ow_data.current_map_id();
1397 result[
"world"] = ow_data.current_world();
1398 result[
"world_name"] = ow_data.current_world() == 0 ?
"Light World" :
1399 (ow_data.current_world() == 1 ?
"Dark World" :
"Special World");
1402 return result.dump();
1405std::string WasmControlApi::GetEditorSelection() {
1406 nlohmann::json result;
1409 result[
"error"] =
"Control API not initialized";
1410 return result.dump();
1413 auto* current = editor_manager_->GetCurrentEditor();
1415 result[
"error"] =
"No editor active";
1416 return result.dump();
1419 result[
"editor_type"] = EditorTypeToString(
static_cast<int>(current->type()));
1420 result[
"selection"] = nlohmann::json::array();
1424 result[
"has_selection"] =
false;
1426 return result.dump();
1433std::string WasmControlApi::GetRoomTileData(
int room_id) {
1434 nlohmann::json result;
1437 result[
"error"] =
"Control API not initialized";
1438 return result.dump();
1441 if (room_id < 0 || room_id >= 296) {
1442 result[
"error"] =
"Invalid room ID (must be 0-295)";
1443 return result.dump();
1446 auto* rom = editor_manager_->GetCurrentRom();
1447 if (!rom || !rom->is_loaded()) {
1448 result[
"error"] =
"ROM not loaded";
1449 return result.dump();
1454 auto* game_data = editor_manager_->GetCurrentGameData();
1456 room.SetGameData(game_data);
1458 room.LoadRoomGraphics();
1461 result[
"room_id"] = room_id;
1462 result[
"width"] = 512;
1463 result[
"height"] = 512;
1466 const auto& layout = room.GetLayout();
1467 const auto& layout_objects = layout.GetObjects();
1470 nlohmann::json layer1_tiles = nlohmann::json::array();
1471 nlohmann::json layer2_tiles = nlohmann::json::array();
1473 for (
const auto& obj : layout_objects) {
1474 nlohmann::json tile_obj;
1475 tile_obj[
"x"] = obj.x();
1476 tile_obj[
"y"] = obj.y();
1478 auto tile_result = obj.GetTile(0);
1479 if (tile_result.ok()) {
1480 const auto* tile_info = tile_result.value();
1481 tile_obj[
"tile_id"] = tile_info->id_;
1482 tile_obj[
"palette"] = tile_info->palette_;
1483 tile_obj[
"priority"] = tile_info->over_;
1484 tile_obj[
"h_flip"] = tile_info->horizontal_mirror_;
1485 tile_obj[
"v_flip"] = tile_info->vertical_mirror_;
1487 if (obj.GetLayerValue() == 1) {
1488 layer2_tiles.push_back(tile_obj);
1490 layer1_tiles.push_back(tile_obj);
1495 result[
"layer1"] = layer1_tiles;
1496 result[
"layer2"] = layer2_tiles;
1497 result[
"layer1_count"] = layer1_tiles.size();
1498 result[
"layer2_count"] = layer2_tiles.size();
1500 return result.dump();
1503std::string WasmControlApi::GetRoomObjects(
int room_id) {
1504 nlohmann::json result = nlohmann::json::array();
1507 nlohmann::json error;
1508 error[
"error"] =
"Control API not initialized";
1509 return error.dump();
1512 if (room_id < 0 || room_id >= 296) {
1513 nlohmann::json error;
1514 error[
"error"] =
"Invalid room ID (must be 0-295)";
1515 return error.dump();
1518 auto* rom = editor_manager_->GetCurrentRom();
1519 if (!rom || !rom->is_loaded()) {
1520 nlohmann::json error;
1521 error[
"error"] =
"ROM not loaded";
1522 return error.dump();
1530 const auto& tile_objects = room.GetTileObjects();
1532 for (
const auto& obj : tile_objects) {
1533 nlohmann::json obj_data;
1534 obj_data[
"id"] = obj.id_;
1535 obj_data[
"x"] = obj.x();
1536 obj_data[
"y"] = obj.y();
1537 obj_data[
"size"] = obj.size();
1538 obj_data[
"layer"] = obj.GetLayerValue();
1541 auto options =
static_cast<int>(obj.options());
1548 result.push_back(obj_data);
1551 return result.dump();
1554std::string WasmControlApi::GetRoomProperties(
int room_id) {
1555 nlohmann::json result;
1558 result[
"error"] =
"Control API not initialized";
1559 return result.dump();
1562 if (room_id < 0 || room_id >= 296) {
1563 result[
"error"] =
"Invalid room ID (must be 0-295)";
1564 return result.dump();
1567 auto* rom = editor_manager_->GetCurrentRom();
1568 if (!rom || !rom->is_loaded()) {
1569 result[
"error"] =
"ROM not loaded";
1570 return result.dump();
1576 result[
"room_id"] = room_id;
1577 result[
"blockset"] = room.blockset;
1578 result[
"spriteset"] = room.spriteset;
1579 result[
"palette"] = room.palette;
1580 result[
"floor1"] = room.floor1();
1581 result[
"floor2"] = room.floor2();
1582 result[
"layout"] = room.layout;
1583 result[
"holewarp"] = room.holewarp;
1584 result[
"message_id"] = room.message_id_;
1587 result[
"effect"] =
static_cast<int>(room.effect());
1588 result[
"tag1"] =
static_cast<int>(room.tag1());
1589 result[
"tag2"] =
static_cast<int>(room.tag2());
1590 result[
"collision"] =
static_cast<int>(room.collision());
1593 const auto& layer_merge = room.layer_merging();
1594 result[
"layer_merging"] = {
1595 {
"id", layer_merge.ID},
1596 {
"name", layer_merge.Name},
1597 {
"layer2_visible", layer_merge.Layer2Visible},
1598 {
"layer2_on_top", layer_merge.Layer2OnTop},
1599 {
"layer2_translucent", layer_merge.Layer2Translucent}
1602 result[
"is_light"] = room.IsLight();
1603 result[
"is_loaded"] = room.IsLoaded();
1605 return result.dump();
1608std::string WasmControlApi::GetMapTileData(
int map_id) {
1609 nlohmann::json result;
1612 result[
"error"] =
"Control API not initialized";
1613 return result.dump();
1617 result[
"error"] =
"Invalid map ID (must be 0-159)";
1618 return result.dump();
1621 auto* overworld = editor_manager_->overworld();
1623 result[
"error"] =
"Overworld not loaded";
1624 return result.dump();
1627 auto* map = overworld->overworld_map(map_id);
1629 result[
"error"] =
"Map not found";
1630 return result.dump();
1633 result[
"map_id"] = map_id;
1634 result[
"width"] = 32;
1635 result[
"height"] = 32;
1638 auto blockset = map->current_tile16_blockset();
1641 result[
"has_tile_data"] = !blockset.empty();
1642 result[
"tile_count"] = blockset.size();
1643 result[
"is_built"] = map->is_built();
1644 result[
"is_large_map"] = map->is_large_map();
1648 if (blockset.size() >= 64) {
1649 nlohmann::json sample_tiles = nlohmann::json::array();
1651 for (
int i = 0; i < 64; i++) {
1652 sample_tiles.push_back(
static_cast<int>(blockset[i]));
1654 result[
"sample_tiles"] = sample_tiles;
1655 result[
"sample_note"] =
"First 8x8 tiles from top-left corner";
1658 return result.dump();
1661std::string WasmControlApi::GetMapEntities(
int map_id) {
1662 nlohmann::json result;
1665 result[
"error"] =
"Control API not initialized";
1666 return result.dump();
1670 result[
"error"] =
"Invalid map ID (must be 0-159)";
1671 return result.dump();
1674 auto* overworld = editor_manager_->overworld();
1676 result[
"error"] =
"Overworld not loaded";
1677 return result.dump();
1680 result[
"map_id"] = map_id;
1681 result[
"entrances"] = nlohmann::json::array();
1682 result[
"exits"] = nlohmann::json::array();
1683 result[
"items"] = nlohmann::json::array();
1684 result[
"sprites"] = nlohmann::json::array();
1687 for (
const auto& entrance : overworld->entrances()) {
1688 if (entrance.map_id_ ==
static_cast<uint16_t
>(map_id)) {
1690 e[
"id"] = entrance.entrance_id_;
1691 e[
"x"] = entrance.x_;
1692 e[
"y"] = entrance.y_;
1693 e[
"map_id"] = entrance.map_id_;
1694 result[
"entrances"].push_back(e);
1699 auto* exits = overworld->exits();
1701 for (
const auto& exit : *exits) {
1702 if (exit.map_id_ ==
static_cast<uint16_t
>(map_id)) {
1706 ex[
"map_id"] = exit.map_id_;
1707 ex[
"room_id"] = exit.room_id_;
1708 result[
"exits"].push_back(ex);
1714 for (
const auto& item : overworld->all_items()) {
1715 if (item.map_id_ ==
static_cast<uint16_t
>(map_id)) {
1720 result[
"items"].push_back(i);
1724 return result.dump();
1727std::string WasmControlApi::GetMapProperties(
int map_id) {
1728 nlohmann::json result;
1731 result[
"error"] =
"Control API not initialized";
1732 return result.dump();
1736 result[
"error"] =
"Invalid map ID (must be 0-159)";
1737 return result.dump();
1740 auto* overworld = editor_manager_->overworld();
1742 result[
"error"] =
"Overworld not loaded";
1743 return result.dump();
1746 auto* map = overworld->overworld_map(map_id);
1748 result[
"error"] =
"Map not found";
1749 return result.dump();
1752 result[
"map_id"] = map_id;
1753 result[
"world"] = map_id / 64;
1754 result[
"parent_id"] = map->parent();
1755 result[
"area_graphics"] = map->area_graphics();
1756 result[
"area_palette"] = map->area_palette();
1757 result[
"sprite_graphics"] = {map->sprite_graphics(0), map->sprite_graphics(1), map->sprite_graphics(2)};
1758 result[
"sprite_palette"] = {map->sprite_palette(0), map->sprite_palette(1), map->sprite_palette(2)};
1759 result[
"message_id"] = map->message_id();
1760 result[
"is_large_map"] = map->is_large_map();
1762 return result.dump();
1765std::string WasmControlApi::GetPaletteData(
const std::string& group_name,
int palette_id) {
1766 nlohmann::json result;
1769 result[
"error"] =
"Control API not initialized";
1770 return result.dump();
1773 auto* rom = editor_manager_->GetCurrentRom();
1774 if (!rom || !rom->is_loaded()) {
1775 result[
"error"] =
"ROM not loaded";
1776 return result.dump();
1779 result[
"group"] = group_name;
1780 result[
"palette_id"] = palette_id;
1783 auto* game_data = editor_manager_->GetCurrentGameData();
1785 result[
"error"] =
"GameData not available";
1786 return result.dump();
1788 auto* group = game_data->palette_groups.get_group(group_name);
1791 result[
"error"] =
"Invalid palette group name";
1792 return result.dump();
1795 if (palette_id < 0 || palette_id >=
static_cast<int>(group->size())) {
1796 result[
"error"] =
"Invalid palette ID for this group";
1797 result[
"max_palette_id"] = group->size() - 1;
1798 return result.dump();
1801 auto palette = (*group)[palette_id];
1802 nlohmann::json colors = nlohmann::json::array();
1805 for (
size_t i = 0; i < palette.size(); i++) {
1806 const auto& color = palette[i];
1807 nlohmann::json color_data;
1808 color_data[
"index"] = i;
1812 auto rgb_color = color.rgb();
1815 int r =
static_cast<int>(rgb_color.x * 255);
1816 int g =
static_cast<int>(rgb_color.y * 255);
1817 int b =
static_cast<int>(rgb_color.z * 255);
1818 color_data[
"r"] = r;
1819 color_data[
"g"] = g;
1820 color_data[
"b"] = b;
1821 color_data[
"hex"] = absl::StrFormat(
"#%02X%02X%02X", r, g, b);
1824 colors.push_back(color_data);
1827 result[
"colors"] = colors;
1828 result[
"color_count"] = palette.size();
1830 }
catch (
const std::exception& e) {
1831 result[
"error"] = std::string(
"Failed to extract palette: ") + e.what();
1834 return result.dump();
1837std::string WasmControlApi::ListPaletteGroups() {
1838 nlohmann::json result = nlohmann::json::array();
1841 result.push_back(
"ow_main");
1842 result.push_back(
"ow_aux");
1843 result.push_back(
"ow_animated");
1844 result.push_back(
"hud");
1845 result.push_back(
"global_sprites");
1846 result.push_back(
"armors");
1847 result.push_back(
"swords");
1848 result.push_back(
"shields");
1849 result.push_back(
"sprites_aux1");
1850 result.push_back(
"sprites_aux2");
1851 result.push_back(
"sprites_aux3");
1852 result.push_back(
"dungeon_main");
1853 result.push_back(
"grass");
1854 result.push_back(
"3d_object");
1855 result.push_back(
"ow_mini_map");
1857 return result.dump();
1860std::string WasmControlApi::LoadFont(
const std::string& name,
const std::string& data,
float size) {
1861 nlohmann::json result;
1862 auto status = yaze::platform::WasmSettings::LoadUserFont(name, data, size);
1864 result[
"success"] =
true;
1866 result[
"success"] =
false;
1867 result[
"error"] = status.ToString();
1869 return result.dump();
1876std::string WasmControlApi::GetUIElementTree() {
1877 nlohmann::json result;
1880 result[
"error"] =
"Control API not initialized";
1881 result[
"elements"] = nlohmann::json::array();
1882 return result.dump();
1887 const auto& all_widgets = registry.GetAllWidgets();
1889 nlohmann::json elements = nlohmann::json::array();
1892 for (
const auto& [path, info] : all_widgets) {
1893 nlohmann::json elem;
1894 elem[
"id"] = info.full_path;
1895 elem[
"type"] = info.type;
1896 elem[
"label"] = info.label;
1897 elem[
"enabled"] = info.enabled;
1898 elem[
"visible"] = info.visible;
1899 elem[
"window"] = info.window_name;
1902 if (info.bounds.valid) {
1904 {
"x", info.bounds.min_x},
1905 {
"y", info.bounds.min_y},
1906 {
"width", info.bounds.max_x - info.bounds.min_x},
1907 {
"height", info.bounds.max_y - info.bounds.min_y}
1911 {
"x", 0}, {
"y", 0}, {
"width", 0}, {
"height", 0}
1916 if (!info.description.empty()) {
1917 elem[
"description"] = info.description;
1919 elem[
"imgui_id"] =
static_cast<uint32_t
>(info.imgui_id);
1920 elem[
"last_seen_frame"] = info.last_seen_frame;
1922 elements.push_back(elem);
1925 result[
"elements"] = elements;
1926 result[
"count"] = elements.size();
1927 result[
"source"] =
"WidgetIdRegistry";
1929 return result.dump();
1932std::string WasmControlApi::GetUIElementBounds(
const std::string& element_id) {
1933 nlohmann::json result;
1936 result[
"error"] =
"Control API not initialized";
1937 return result.dump();
1942 const auto* widget_info = registry.GetWidgetInfo(element_id);
1944 result[
"id"] = element_id;
1946 if (widget_info ==
nullptr) {
1947 result[
"found"] =
false;
1948 result[
"error"] =
"Element not found: " + element_id;
1949 return result.dump();
1952 result[
"found"] =
true;
1953 result[
"visible"] = widget_info->visible;
1954 result[
"enabled"] = widget_info->enabled;
1955 result[
"type"] = widget_info->type;
1956 result[
"label"] = widget_info->label;
1957 result[
"window"] = widget_info->window_name;
1960 if (widget_info->bounds.valid) {
1961 result[
"x"] = widget_info->bounds.min_x;
1962 result[
"y"] = widget_info->bounds.min_y;
1963 result[
"width"] = widget_info->bounds.max_x - widget_info->bounds.min_x;
1964 result[
"height"] = widget_info->bounds.max_y - widget_info->bounds.min_y;
1965 result[
"bounds_valid"] =
true;
1969 result[
"width"] = 0;
1970 result[
"height"] = 0;
1971 result[
"bounds_valid"] =
false;
1975 result[
"imgui_id"] =
static_cast<uint32_t
>(widget_info->imgui_id);
1976 result[
"last_seen_frame"] = widget_info->last_seen_frame;
1978 if (!widget_info->description.empty()) {
1979 result[
"description"] = widget_info->description;
1982 return result.dump();
1985std::string WasmControlApi::SetSelection(
const std::string& ids_json) {
1986 nlohmann::json result;
1989 result[
"success"] =
false;
1990 result[
"error"] =
"Control API not initialized";
1991 return result.dump();
1995 auto ids = nlohmann::json::parse(ids_json);
1999 result[
"success"] =
true;
2000 result[
"selected_ids"] = ids;
2001 result[
"note"] =
"Selection setting not yet fully implemented";
2003 }
catch (
const std::exception& e) {
2004 result[
"success"] =
false;
2005 result[
"error"] = std::string(
"Invalid JSON: ") + e.what();
2008 return result.dump();
2015std::string WasmControlApi::GetPlatformInfo() {
2016 nlohmann::json result;
2024 result[
"platform"] =
"Windows";
2027 result[
"platform"] =
"macOS";
2030 result[
"platform"] =
"Linux";
2033 result[
"platform"] =
"WebMac";
2036 result[
"platform"] =
"WebOther";
2039 result[
"platform"] =
"Unknown";
2047 result[
"shift_display"] =
"Shift";
2054 return result.dump();
2061bool WasmControlApi::AgentIsReady() {
2062 if (!initialized_ || !editor_manager_) {
2066 auto* agent_editor = editor_manager_->GetAgentEditor();
2067 return agent_editor !=
nullptr;
2070std::string WasmControlApi::AgentSendMessage(
const std::string& message) {
2071 nlohmann::json result;
2073 if (!initialized_ || !editor_manager_) {
2074 result[
"success"] =
false;
2075 result[
"error"] =
"API not initialized";
2076 return result.dump();
2079 auto* agent_editor = editor_manager_->GetAgentEditor();
2080 if (!agent_editor) {
2081 result[
"success"] =
false;
2082 result[
"error"] =
"Agent editor not available";
2083 return result.dump();
2086 auto* agent_chat = agent_editor->GetAgentChat();
2088 result[
"success"] =
false;
2089 result[
"error"] =
"Agent chat not available";
2090 return result.dump();
2095 result[
"success"] =
true;
2096 result[
"status"] =
"queued";
2097 result[
"message"] = message;
2102 return result.dump();
2105std::string WasmControlApi::AgentGetChatHistory() {
2106 nlohmann::json result = nlohmann::json::array();
2108 if (!initialized_ || !editor_manager_) {
2109 return result.dump();
2112 auto* agent_editor = editor_manager_->GetAgentEditor();
2113 if (!agent_editor) {
2114 return result.dump();
2117 auto* agent_chat = agent_editor->GetAgentChat();
2119 return result.dump();
2126 return result.dump();
2129std::string WasmControlApi::AgentGetConfig() {
2130 nlohmann::json result;
2132 if (!initialized_ || !editor_manager_) {
2133 result[
"error"] =
"API not initialized";
2134 return result.dump();
2137 auto* agent_editor = editor_manager_->GetAgentEditor();
2138 if (!agent_editor) {
2139 result[
"error"] =
"Agent editor not available";
2140 return result.dump();
2143 auto config = agent_editor->GetCurrentConfig();
2144 result[
"provider"] = config.provider;
2145 result[
"model"] = config.model;
2146 result[
"ollama_host"] = config.ollama_host;
2147 result[
"verbose"] = config.verbose;
2148 result[
"show_reasoning"] = config.show_reasoning;
2149 result[
"max_tool_iterations"] = config.max_tool_iterations;
2151 return result.dump();
2154std::string WasmControlApi::AgentSetConfig(
const std::string& config_json) {
2155 nlohmann::json result;
2157 if (!initialized_ || !editor_manager_) {
2158 result[
"success"] =
false;
2159 result[
"error"] =
"API not initialized";
2160 return result.dump();
2163 auto* agent_editor = editor_manager_->GetAgentEditor();
2164 if (!agent_editor) {
2165 result[
"success"] =
false;
2166 result[
"error"] =
"Agent editor not available";
2167 return result.dump();
2171 auto config_data = nlohmann::json::parse(config_json);
2173 editor::AgentEditor::AgentConfig config;
2174 if (config_data.contains(
"provider")) {
2175 config.provider = config_data[
"provider"].get<std::string>();
2177 if (config_data.contains(
"model")) {
2178 config.model = config_data[
"model"].get<std::string>();
2180 if (config_data.contains(
"ollama_host")) {
2181 config.ollama_host = config_data[
"ollama_host"].get<std::string>();
2183 if (config_data.contains(
"verbose")) {
2184 config.verbose = config_data[
"verbose"].get<
bool>();
2186 if (config_data.contains(
"show_reasoning")) {
2187 config.show_reasoning = config_data[
"show_reasoning"].get<
bool>();
2189 if (config_data.contains(
"max_tool_iterations")) {
2190 config.max_tool_iterations = config_data[
"max_tool_iterations"].get<
int>();
2193 agent_editor->ApplyConfig(config);
2194 result[
"success"] =
true;
2195 }
catch (
const std::exception& e) {
2196 result[
"success"] =
false;
2197 result[
"error"] = e.what();
2200 return result.dump();
2203std::string WasmControlApi::AgentGetProviders() {
2204 nlohmann::json result = nlohmann::json::array();
2209 {
"name",
"Mock Provider"},
2210 {
"description",
"Testing provider that echoes messages"}
2215 {
"description",
"Local Ollama server"},
2216 {
"requires_host",
true}
2220 {
"name",
"Google Gemini"},
2221 {
"description",
"Google's Gemini API"},
2222 {
"requires_api_key",
true}
2225 return result.dump();
2228std::string WasmControlApi::AgentGetProposals() {
2229 nlohmann::json result = nlohmann::json::array();
2231 if (!initialized_ || !editor_manager_) {
2232 return result.dump();
2238 return result.dump();
2241std::string WasmControlApi::AgentAcceptProposal(
const std::string& proposal_id) {
2242 nlohmann::json result;
2244 if (!initialized_ || !editor_manager_) {
2245 result[
"success"] =
false;
2246 result[
"error"] =
"API not initialized";
2247 return result.dump();
2251 result[
"success"] =
false;
2252 result[
"error"] =
"Proposal system not yet integrated";
2253 result[
"proposal_id"] = proposal_id;
2255 return result.dump();
2258std::string WasmControlApi::AgentRejectProposal(
const std::string& proposal_id) {
2259 nlohmann::json result;
2261 if (!initialized_ || !editor_manager_) {
2262 result[
"success"] =
false;
2263 result[
"error"] =
"API not initialized";
2264 return result.dump();
2268 result[
"success"] =
false;
2269 result[
"error"] =
"Proposal system not yet integrated";
2270 result[
"proposal_id"] = proposal_id;
2272 return result.dump();
2275std::string WasmControlApi::AgentGetProposalDetails(
const std::string& proposal_id) {
2276 nlohmann::json result;
2278 if (!initialized_ || !editor_manager_) {
2279 result[
"error"] =
"API not initialized";
2280 return result.dump();
2284 result[
"error"] =
"Proposal system not yet integrated";
2285 result[
"proposal_id"] = proposal_id;
2287 return result.dump();
2290std::string WasmControlApi::AgentOpenSidebar() {
2291 nlohmann::json result;
2293 if (!initialized_ || !editor_manager_) {
2294 result[
"success"] =
false;
2295 result[
"error"] =
"API not initialized";
2296 return result.dump();
2299 auto* agent_editor = editor_manager_->GetAgentEditor();
2300 if (!agent_editor) {
2301 result[
"success"] =
false;
2302 result[
"error"] =
"Agent editor not available";
2303 return result.dump();
2306 agent_editor->SetChatActive(
true);
2307 result[
"success"] =
true;
2308 result[
"sidebar_open"] =
true;
2310 return result.dump();
2313std::string WasmControlApi::AgentCloseSidebar() {
2314 nlohmann::json result;
2316 if (!initialized_ || !editor_manager_) {
2317 result[
"success"] =
false;
2318 result[
"error"] =
"API not initialized";
2319 return result.dump();
2322 auto* agent_editor = editor_manager_->GetAgentEditor();
2323 if (!agent_editor) {
2324 result[
"success"] =
false;
2325 result[
"error"] =
"Agent editor not available";
2326 return result.dump();
2329 agent_editor->SetChatActive(
false);
2330 result[
"success"] =
true;
2331 result[
"sidebar_open"] =
false;
2333 return result.dump();
2341 emscripten::function(
"controlIsReady", &WasmControlApi::IsReady);
2342 emscripten::function(
"controlSwitchEditor", &WasmControlApi::SwitchEditor);
2343 emscripten::function(
"controlGetCurrentEditor", &WasmControlApi::GetCurrentEditor);
2344 emscripten::function(
"controlGetAvailableEditors", &WasmControlApi::GetAvailableEditors);
2345 emscripten::function(
"controlOpenPanel", &WasmControlApi::OpenPanel);
2346 emscripten::function(
"controlClosePanel", &WasmControlApi::ClosePanel);
2347 emscripten::function(
"controlTogglePanel", &WasmControlApi::TogglePanel);
2348 emscripten::function(
"controlGetVisiblePanels", &WasmControlApi::GetVisiblePanels);
2349 emscripten::function(
"controlGetAvailablePanels", &WasmControlApi::GetAvailablePanels);
2350 emscripten::function(
"controlGetPanelsInCategory", &WasmControlApi::GetPanelsInCategory);
2351 emscripten::function(
"controlSetPanelLayout", &WasmControlApi::SetPanelLayout);
2352 emscripten::function(
"controlGetAvailableLayouts", &WasmControlApi::GetAvailableLayouts);
2353 emscripten::function(
"controlSaveCurrentLayout", &WasmControlApi::SaveCurrentLayout);
2354 emscripten::function(
"controlTriggerMenuAction", &WasmControlApi::TriggerMenuAction);
2355 emscripten::function(
"controlGetAvailableMenuActions", &WasmControlApi::GetAvailableMenuActions);
2356 emscripten::function(
"controlGetSessionInfo", &WasmControlApi::GetSessionInfo);
2357 emscripten::function(
"controlCreateSession", &WasmControlApi::CreateSession);
2358 emscripten::function(
"controlSwitchSession", &WasmControlApi::SwitchSession);
2359 emscripten::function(
"controlGetRomStatus", &WasmControlApi::GetRomStatus);
2360 emscripten::function(
"controlReadRomBytes", &WasmControlApi::ReadRomBytes);
2361 emscripten::function(
"controlWriteRomBytes", &WasmControlApi::WriteRomBytes);
2362 emscripten::function(
"controlSaveRom", &WasmControlApi::SaveRom);
2365 emscripten::function(
"editorGetSnapshot", &WasmControlApi::GetEditorSnapshot);
2366 emscripten::function(
"editorGetCurrentDungeonRoom", &WasmControlApi::GetCurrentDungeonRoom);
2367 emscripten::function(
"editorGetCurrentOverworldMap", &WasmControlApi::GetCurrentOverworldMap);
2368 emscripten::function(
"editorGetSelection", &WasmControlApi::GetEditorSelection);
2371 emscripten::function(
"dataGetRoomTileData", &WasmControlApi::GetRoomTileData);
2372 emscripten::function(
"dataGetRoomObjects", &WasmControlApi::GetRoomObjects);
2373 emscripten::function(
"dataGetRoomProperties", &WasmControlApi::GetRoomProperties);
2374 emscripten::function(
"dataGetMapTileData", &WasmControlApi::GetMapTileData);
2375 emscripten::function(
"dataGetMapEntities", &WasmControlApi::GetMapEntities);
2376 emscripten::function(
"dataGetMapProperties", &WasmControlApi::GetMapProperties);
2377 emscripten::function(
"dataGetPaletteData", &WasmControlApi::GetPaletteData);
2378 emscripten::function(
"dataListPaletteGroups", &WasmControlApi::ListPaletteGroups);
2381 emscripten::function(
"guiGetUIElementTree", &WasmControlApi::GetUIElementTree);
2382 emscripten::function(
"guiGetUIElementBounds", &WasmControlApi::GetUIElementBounds);
2383 emscripten::function(
"guiSetSelection", &WasmControlApi::SetSelection);
2386 emscripten::function(
"settingsGetCurrentThemeData", &yaze::platform::WasmSettings::GetCurrentThemeData);
2387 emscripten::function(
"settingsLoadFont", &WasmControlApi::LoadFont);
2390 emscripten::function(
"controlGetPlatformInfo", &WasmControlApi::GetPlatformInfo);
2393 emscripten::function(
"agentIsReady", &WasmControlApi::AgentIsReady);
2394 emscripten::function(
"agentSendMessage", &WasmControlApi::AgentSendMessage);
2395 emscripten::function(
"agentGetChatHistory", &WasmControlApi::AgentGetChatHistory);
2396 emscripten::function(
"agentGetConfig", &WasmControlApi::AgentGetConfig);
2397 emscripten::function(
"agentSetConfig", &WasmControlApi::AgentSetConfig);
2398 emscripten::function(
"agentGetProviders", &WasmControlApi::AgentGetProviders);
2399 emscripten::function(
"agentGetProposals", &WasmControlApi::AgentGetProposals);
2400 emscripten::function(
"agentAcceptProposal", &WasmControlApi::AgentAcceptProposal);
2401 emscripten::function(
"agentRejectProposal", &WasmControlApi::AgentRejectProposal);
2402 emscripten::function(
"agentGetProposalDetails", &WasmControlApi::AgentGetProposalDetails);
2403 emscripten::function(
"agentOpenSidebar", &WasmControlApi::AgentOpenSidebar);
2404 emscripten::function(
"agentCloseSidebar", &WasmControlApi::AgentCloseSidebar);
struct snes_color snes_color
SNES color in 15-bit RGB format (BGR555)
#define LOG_INFO(category, format,...)
EM_JS(void, CallJsAiDriver,(const char *history_json), { if(window.yaze &&window.yaze.ai &&window.yaze.ai.processAgentRequest) { window.yaze.ai.processAgentRequest(UTF8ToString(history_json));} else { console.error("AI Driver not found in window.yaze.ai.processAgentRequest");} })
constexpr std::array< const char *, 14 > kEditorNames
const char * GetCtrlDisplayName()
Get the display name for the primary modifier key.
std::string FormatCtrlShiftShortcut(ImGuiKey key)
Convenience function for Ctrl+Shift+key shortcuts.
Platform GetCurrentPlatform()
Get the current platform at runtime.
bool IsMacPlatform()
Check if running on macOS (native or web)
const char * GetAltDisplayName()
Get the display name for the secondary modifier key.
std::string FormatCtrlShortcut(ImGuiKey key)
Convenience function for Ctrl+key shortcuts.
constexpr int kNumOverworldMaps
Room LoadRoomFromRom(Rom *rom, int room_id)
SNES color in 15-bit RGB format (BGR555)
std::string togglePanel(std::string card_id)
Toggle a card's visibility.
std::string getPanelsInCategory(std::string category)
Get cards in a specific category.
std::string getRomStatus()
EMSCRIPTEN_BINDINGS(yaze_debug_inspector)
std::string readRomBytes(int address, int count)