yaze 0.2.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
zeml.cc
Go to the documentation of this file.
1
2#include "app/gui/zeml.h"
3
4#include <cctype>
5#include <fstream>
6#include <functional>
7#include <map>
8#include <sstream>
9#include <string>
10#include <vector>
11
13#include "app/gui/canvas.h"
14#include "app/gui/input.h"
15#include "imgui/imgui.h"
16
17namespace yaze {
18namespace gui {
19namespace zeml {
20
21std::vector<Token> Tokenize(const std::string& input) {
22 std::vector<Token> tokens;
23 std::istringstream stream(input);
24 char ch;
25
26 while (stream.get(ch)) {
27 if (isspace(ch)) continue;
28
29 if (ch == '{') {
30 tokens.push_back({TokenType::OpenBrace, "{"});
31 } else if (ch == '}') {
32 tokens.push_back({TokenType::CloseBrace, "}"});
33 } else if (ch == ',') {
34 tokens.push_back({TokenType::Comma, ","});
35 } else if (std::isalnum(ch) || ch == '_') {
36 std::string ident(1, ch);
37 while (stream.get(ch) && (std::isalnum(ch) || ch == '_')) {
38 ident += ch;
39 }
40 stream.unget();
41 tokens.push_back({TokenType::Identifier, ident});
42 } else if (ch == '"' || ch == '\'') {
43 std::string str;
44 char quoteType = ch;
45 while (stream.get(ch) && ch != quoteType) {
46 str += ch;
47 }
48 tokens.push_back({TokenType::String, str});
49 }
50 }
51
52 tokens.push_back({TokenType::EndOfStream, ""});
53 return tokens;
54}
55
56WidgetType MapType(const std::string& type) {
57 static std::map<std::string, WidgetType> typeMap = {
58 {"Window", WidgetType::Window},
59 {"Button", WidgetType::Button},
60 {"Slider", WidgetType::Slider},
61 {"Text", WidgetType::Text},
62 {"CollapsingHeader", WidgetType::CollapsingHeader},
63 {"Columns", WidgetType::Columns},
64 {"Checkbox", WidgetType::Checkbox},
65 {"HexInputByte", WidgetType::HexInputByte},
66 {"HexInputWord", WidgetType::HexInputWord},
67 {"Table", WidgetType::Table},
68 {"Selectable", WidgetType::Selectable},
69 {"TableSetupColumn", WidgetType::TableSetupColumn},
70 {"TableHeadersRow", WidgetType::TableHeadersRow},
71 {"TableNextColumn", WidgetType::TableNextColumn},
72 {"Function", WidgetType::Function},
73 {"BeginChild", WidgetType::BeginChild},
74 {"BeginMenu", WidgetType::BeginMenu},
75 {"MenuItem", WidgetType::MenuItem},
76 {"BeginMenuBar", WidgetType::BeginMenuBar},
77 {"Separator", WidgetType::Separator},
78 {"BeginTabBar", WidgetType::BeginTabBar},
79 {"BeginTabItem", WidgetType::BeginTabItem},
80 {"Canvas", WidgetType::Canvas},
82 };
83 return typeMap[type];
84}
85
86Node ParseNode(const std::vector<Token>& tokens, size_t& index,
87 const std::map<std::string, void*>& data_bindings,
88 const std::map<std::string, Node>& definitions) {
89 Node node;
90 if (index >= tokens.size() || tokens[index].type == TokenType::EndOfStream) {
91 return node;
92 }
93
94 while (index < tokens.size() &&
95 tokens[index].type != TokenType::EndOfStream) {
96 Token token = tokens[index];
97 if (token.type == TokenType::Identifier) {
98 node.type = MapType(token.value);
99 index++; // Move to the next token for attributes
100 if (node.type == WidgetType::Definition) {
101 if (definitions.find(token.value) != definitions.end()) {
102 node = definitions.at(token.value);
103 }
104 } else {
105 node.attributes =
106 ParseAttributes(tokens, index, node.type, data_bindings);
107 }
108 }
109
110 // Handle the opening brace indicating the start of child nodes
111 if (index < tokens.size() && tokens[index].type == TokenType::OpenBrace) {
112 index++; // Skip the opening brace
113
114 while (index < tokens.size() &&
115 tokens[index].type != TokenType::CloseBrace) {
116 if (tokens[index].type == TokenType::Comma) {
117 index++; // Skip commas
118 } else {
119 node.children.push_back(ParseNode(tokens, index, data_bindings));
120 }
121 }
122
123 if (index < tokens.size() &&
124 tokens[index].type == TokenType::CloseBrace) {
125 index++; // Ensure closing brace is skipped before returning
126 }
127 }
128
129 break; // Exit after processing one complete node
130 }
131 return node;
132}
133
134void ParseFlags(const WidgetType& type, const std::string& flags,
135 WidgetAttributes& attributes) {
136 // Parse the flags for the `|` character
137 std::vector<std::string> flag_tokens;
138 std::string token;
139 std::istringstream tokenStream(flags);
140 while (std::getline(tokenStream, token, '|')) {
141 flag_tokens.push_back(token);
142 }
143
144 switch (type) {
146 static std::map<std::string, ImGuiWindowFlags> flagMap = {
147 {"None", ImGuiWindowFlags_None},
148 {"NoTitleBar", ImGuiWindowFlags_NoTitleBar},
149 {"NoResize", ImGuiWindowFlags_NoResize},
150 {"NoMove", ImGuiWindowFlags_NoMove},
151 {"NoScrollbar", ImGuiWindowFlags_NoScrollbar},
152 {"NoScrollWithMouse", ImGuiWindowFlags_NoScrollWithMouse},
153 {"NoCollapse", ImGuiWindowFlags_NoCollapse},
154 {"AlwaysAutoResize", ImGuiWindowFlags_AlwaysAutoResize},
155 {"NoSavedSettings", ImGuiWindowFlags_NoSavedSettings},
156 {"NoInputs", ImGuiWindowFlags_NoInputs},
157 {"MenuBar", ImGuiWindowFlags_MenuBar},
158 {"HorizontalScrollbar", ImGuiWindowFlags_HorizontalScrollbar},
159 {"NoFocusOnAppearing", ImGuiWindowFlags_NoFocusOnAppearing},
160 {"NoBringToFrontOnFocus", ImGuiWindowFlags_NoBringToFrontOnFocus},
161 {"AlwaysVerticalScrollbar", ImGuiWindowFlags_AlwaysVerticalScrollbar},
162 {"AlwaysHorizontalScrollbar",
163 ImGuiWindowFlags_AlwaysHorizontalScrollbar},
164 {"AlwaysUseWindowPadding", ImGuiWindowFlags_AlwaysUseWindowPadding},
165 {"NoNavInputs", ImGuiWindowFlags_NoNavInputs},
166 {"NoNavFocus", ImGuiWindowFlags_NoNavFocus},
167 {"UnsavedDocument", ImGuiWindowFlags_UnsavedDocument},
168 {"NoNav", ImGuiWindowFlags_NoNav},
169 {"NoDecoration", ImGuiWindowFlags_NoDecoration},
170 {"NoInputs", ImGuiWindowFlags_NoInputs},
171 {"NoFocusOnAppearing", ImGuiWindowFlags_NoFocusOnAppearing},
172 {"NoBringToFrontOnFocus", ImGuiWindowFlags_NoBringToFrontOnFocus},
173 {"AlwaysAutoResize", ImGuiWindowFlags_AlwaysAutoResize},
174 {"NoSavedSettings", ImGuiWindowFlags_NoSavedSettings},
175 {"NoMouseInputs", ImGuiWindowFlags_NoMouseInputs},
176 {"NoMouseInputs", ImGuiWindowFlags_NoMouseInputs},
177 {"NoTitleBar", ImGuiWindowFlags_NoTitleBar},
178 {"NoResize", ImGuiWindowFlags_NoResize},
179 {"NoMove", ImGuiWindowFlags_NoMove},
180 {"NoScrollbar", ImGuiWindowFlags_NoScrollbar},
181 {"NoScrollWithMouse", ImGuiWindowFlags_NoScrollWithMouse},
182 {"NoCollapse", ImGuiWindowFlags_NoCollapse},
183 {"AlwaysVerticalScrollbar", ImGuiWindowFlags_AlwaysVerticalScrollbar},
184 {"AlwaysHorizontalScrollbar",
185 ImGuiWindowFlags_AlwaysHorizontalScrollbar}};
186 ImGuiWindowFlags windowFlags = ImGuiWindowFlags_None;
187 for (const auto& flag : flag_tokens) {
188 if (flagMap.find(flag) != flagMap.end()) {
189 windowFlags |= flagMap[flag];
190 }
191 }
192 attributes.flags = std::make_unique<ImGuiWindowFlags>(windowFlags);
193 break;
194 }
196 // Create a flag map using the tree node flags
197 static std::map<std::string, ImGuiTreeNodeFlags> flagMap = {
198 {"None", ImGuiTreeNodeFlags_None},
199 {"Selected", ImGuiTreeNodeFlags_Selected},
200 {"Framed", ImGuiTreeNodeFlags_Framed},
201 {"AllowItemOverlap", ImGuiTreeNodeFlags_AllowItemOverlap},
202 {"NoTreePushOnOpen", ImGuiTreeNodeFlags_NoTreePushOnOpen},
203 {"NoAutoOpenOnLog", ImGuiTreeNodeFlags_NoAutoOpenOnLog},
204 {"DefaultOpen", ImGuiTreeNodeFlags_DefaultOpen},
205 {"OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick},
206 {"OpenOnArrow", ImGuiTreeNodeFlags_OpenOnArrow},
207 {"Leaf", ImGuiTreeNodeFlags_Leaf},
208 {"Bullet", ImGuiTreeNodeFlags_Bullet},
209 {"FramePadding", ImGuiTreeNodeFlags_FramePadding},
210 {"NavLeftJumpsBackHere", ImGuiTreeNodeFlags_NavLeftJumpsBackHere},
211 {"CollapsingHeader", ImGuiTreeNodeFlags_CollapsingHeader}};
212 ImGuiTreeNodeFlags treeFlags = ImGuiTreeNodeFlags_None;
213 for (const auto& flag : flag_tokens) {
214 if (flagMap.find(flag) != flagMap.end()) {
215 treeFlags |= flagMap[flag];
216 }
217 }
218 attributes.flags = std::make_unique<ImGuiTreeNodeFlags>(treeFlags);
219 break;
220 }
221 case WidgetType::Table: {
222 // Create a flag map
223 static std::map<std::string, ImGuiTableFlags> flagMap = {
224 {"None", ImGuiTableFlags_None},
225 {"Resizable", ImGuiTableFlags_Resizable},
226 {"Reorderable", ImGuiTableFlags_Reorderable},
227 {"Hideable", ImGuiTableFlags_Hideable},
228 {"Sortable", ImGuiTableFlags_Sortable},
229 {"NoSavedSettings", ImGuiTableFlags_NoSavedSettings},
230 {"ContextMenuInBody", ImGuiTableFlags_ContextMenuInBody},
231 {"RowBg", ImGuiTableFlags_RowBg},
232 {"BordersInnerH", ImGuiTableFlags_BordersInnerH},
233 {"BordersOuterH", ImGuiTableFlags_BordersOuterH},
234 {"BordersInnerV", ImGuiTableFlags_BordersInnerV},
235 {"BordersOuterV", ImGuiTableFlags_BordersOuterV},
236 {"BordersH", ImGuiTableFlags_BordersH},
237 {"BordersV", ImGuiTableFlags_BordersV},
238 {"Borders", ImGuiTableFlags_Borders},
239 {"NoBordersInBody", ImGuiTableFlags_NoBordersInBody},
240 {"NoBordersInBodyUntilResize",
241 ImGuiTableFlags_NoBordersInBodyUntilResize},
242 {"SizingFixedFit", ImGuiTableFlags_SizingFixedFit},
243 {"SizingFixedSame", ImGuiTableFlags_SizingFixedSame},
244 {"SizingStretchProp", ImGuiTableFlags_SizingStretchProp},
245 {"SizingStretchSame", ImGuiTableFlags_SizingStretchSame},
246 {"NoHostExtendX", ImGuiTableFlags_NoHostExtendX},
247 {"NoHostExtendY", ImGuiTableFlags_NoHostExtendY},
248 {"NoKeepColumnsVisible", ImGuiTableFlags_NoKeepColumnsVisible},
249 {"PreciseWidths", ImGuiTableFlags_PreciseWidths},
250 {"NoClip", ImGuiTableFlags_NoClip},
251 {"PadOuterX", ImGuiTableFlags_PadOuterX},
252 {"NoPadOuterX", ImGuiTableFlags_NoPadOuterX},
253 {"NoPadInnerX", ImGuiTableFlags_NoPadInnerX},
254 {"ScrollX", ImGuiTableFlags_ScrollX},
255 {"ScrollY", ImGuiTableFlags_ScrollY},
256 {"SortMulti", ImGuiTableFlags_SortMulti},
257 {"SortTristate", ImGuiTableFlags_SortTristate}};
258 ImGuiTableFlags tableFlags = ImGuiTableFlags_None;
259 for (const auto& flag : flag_tokens) {
260 if (flagMap.find(flag) != flagMap.end()) {
261 tableFlags |= flagMap[flag];
262 }
263 }
264 // Reserve data to the void* pointer and assign flags
265 attributes.flags = std::make_unique<ImGuiTableFlags>(tableFlags);
266 } break;
268 static std::map<std::string, ImGuiTableColumnFlags> flagMap = {
269 {"None", ImGuiTableColumnFlags_None},
270 {"DefaultHide", ImGuiTableColumnFlags_DefaultHide},
271 {"DefaultSort", ImGuiTableColumnFlags_DefaultSort},
272 {"WidthStretch", ImGuiTableColumnFlags_WidthStretch},
273 {"WidthFixed", ImGuiTableColumnFlags_WidthFixed},
274 {"NoResize", ImGuiTableColumnFlags_NoResize},
275 {"NoReorder", ImGuiTableColumnFlags_NoReorder},
276 {"NoHide", ImGuiTableColumnFlags_NoHide},
277 {"NoClip", ImGuiTableColumnFlags_NoClip},
278 {"NoSort", ImGuiTableColumnFlags_NoSort},
279 {"NoSortAscending", ImGuiTableColumnFlags_NoSortAscending},
280 {"NoSortDescending", ImGuiTableColumnFlags_NoSortDescending},
281 {"NoHeaderWidth", ImGuiTableColumnFlags_NoHeaderWidth},
282 {"PreferSortAscending", ImGuiTableColumnFlags_PreferSortAscending},
283 {"PreferSortDescending", ImGuiTableColumnFlags_PreferSortDescending},
284 {"IndentEnable", ImGuiTableColumnFlags_IndentEnable},
285 {"IndentDisable", ImGuiTableColumnFlags_IndentDisable},
286 {"IsEnabled", ImGuiTableColumnFlags_IsEnabled},
287 {"IsVisible", ImGuiTableColumnFlags_IsVisible},
288 {"IsSorted", ImGuiTableColumnFlags_IsSorted},
289 {"IsHovered", ImGuiTableColumnFlags_IsHovered}};
290 ImGuiTableColumnFlags columnFlags = ImGuiTableColumnFlags_None;
291 for (const auto& flag : flag_tokens) {
292 if (flagMap.find(flag) != flagMap.end()) {
293 columnFlags |= flagMap[flag];
294 }
295 }
296 // Reserve data to the void* pointer and assign flags
297 attributes.flags = std::make_unique<ImGuiTableColumnFlags>(columnFlags);
298 }
299 default:
300 break;
301 }
302}
303
305 const std::vector<Token>& tokens, size_t& index, const WidgetType& type,
306 const std::map<std::string, void*>& data_bindings) {
307 WidgetAttributes attributes;
308
309 while (index < tokens.size() && tokens[index].type != TokenType::CloseBrace) {
310 if (tokens[index].type == TokenType::Identifier) {
311 Token keyToken = tokens[index];
312 index++; // Move to the value token.
313 if (index < tokens.size() && tokens[index].type == TokenType::String) {
314 std::string value = tokens[index].value;
315 index++; // Move past the value.
316
317 if (keyToken.value == "id")
318 attributes.id = value;
319 else if (keyToken.value == "title")
320 attributes.title = value;
321 else if (keyToken.value == "min")
322 attributes.min = std::stod(value);
323 else if (keyToken.value == "max")
324 attributes.max = std::stod(value);
325 else if (keyToken.value == "value")
326 attributes.value = std::stod(value);
327 else if (keyToken.value == "width")
328 if (value == "autox")
329 attributes.width = ImGui::GetContentRegionAvail().x;
330 else if (value == "autoy")
331 attributes.width = ImGui::GetContentRegionAvail().y;
332 else
333 attributes.width = std::stod(value);
334 else if (keyToken.value == "text")
335 attributes.text = value;
336 else if (keyToken.value == "data" &&
337 data_bindings.find(value) != data_bindings.end()) {
338 attributes.data = data_bindings.at(value);
339 } else if (keyToken.value == "count") {
340 attributes.count = std::stoi(value);
341 } else if (keyToken.value == "flags") {
342 ParseFlags(type, value, attributes);
343 } else if (keyToken.value == "size") {
344 std::string sizeX, sizeY;
345 std::istringstream sizeStream(value);
346 std::getline(sizeStream, sizeX, ',');
347 std::getline(sizeStream, sizeY, ',');
348 attributes.size = ImVec2(std::stod(sizeX), std::stod(sizeY));
349 }
350 }
351 } else {
352 // If it's not an identifier or we encounter an open brace, break out.
353 break;
354 }
355 }
356 return attributes;
357}
358
359Node Parse(const std::string& yazon_input,
360 const std::map<std::string, void*>& data_bindings) {
361 size_t index = 0;
362 auto tokens = Tokenize(yazon_input);
363
364 std::map<std::string, Node> definitions;
365 if (tokens[index].value == "Definitions") {
366 index++; // Skip the "Definitions" token
367 while (index < tokens.size() &&
368 tokens[index].value != "Layout") { // Skip the definitions
369 // Get the definition name and parse the node
370 std::string definition_name = tokens[index].value;
371 index++; // Move to the definition node
372 definitions[definition_name] = ParseNode(tokens, index, data_bindings);
373 index++;
374 }
375 }
376
377 return ParseNode(tokens, index, data_bindings);
378}
379
380void Render(Node& node) {
381 switch (node.type) {
382 case WidgetType::Window: {
383 ImGuiWindowFlags flags = ImGuiWindowFlags_None;
384 if (node.attributes.flags) {
385 flags = *(ImGuiWindowFlags*)node.attributes.flags.get();
386 }
387 if (ImGui::Begin(node.attributes.title.c_str(), nullptr, flags)) {
388 for (auto& child : node.children) {
389 Render(child);
390 }
391 ImGui::End();
392 }
393 } break;
395 if (node.attributes.data) {
396 // Format the text with the data value
397 char formattedText[256];
398 snprintf(formattedText, sizeof(formattedText),
399 node.attributes.text.c_str(), *(int*)node.attributes.data);
400 if (ImGui::Button(formattedText)) {
402 }
403 } else {
404 if (ImGui::Button(node.attributes.text.c_str())) {
406 }
407 }
408 break;
410 ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_None;
411 if (node.attributes.flags) {
412 flags = *(ImGuiTreeNodeFlags*)node.attributes.flags.get();
413 }
414 if (ImGui::CollapsingHeader(node.attributes.title.c_str(), flags)) {
415 for (auto& child : node.children) {
416 Render(child);
417 }
418 }
419 } break;
421 ImGui::Columns(node.attributes.count, node.attributes.title.c_str());
422 ImGui::Separator();
423 for (auto& child : node.children) {
424 Render(child);
425 ImGui::NextColumn();
426 }
427 ImGui::Columns(1);
428 ImGui::Separator();
429 break;
431 if (ImGui::Checkbox(node.attributes.title.c_str(),
432 (bool*)node.attributes.data)) {
434 }
435 break;
436 case WidgetType::Table: {
437 ImGuiTableFlags flags = ImGuiTableFlags_None;
438 if (node.attributes.flags) {
439 flags = *(ImGuiTableFlags*)node.attributes.flags.get();
440 }
441 if (ImGui::BeginTable(node.attributes.id.c_str(), node.attributes.count,
442 flags)) {
443 for (auto& child : node.children) {
444 Render(child);
445 }
446 }
447 ImGui::EndTable();
448 } break;
450 ImGuiTableColumnFlags flags = ImGuiTableColumnFlags_None;
451 if (node.attributes.flags) {
452 flags = *(ImGuiTableColumnFlags*)node.attributes.flags.get();
453 }
454 ImGui::TableSetupColumn(node.attributes.title.c_str(), flags);
455 } break;
457 ImGui::TableHeadersRow();
458 break;
460 ImGui::TableNextColumn();
461 break;
462 case WidgetType::Text:
463 if (node.attributes.data) {
464 // Assuming all data-bound Text widgets use string formatting
465 char formattedText[128];
466 snprintf(formattedText, sizeof(formattedText),
467 node.attributes.text.c_str(),
468 *(int*)node.attributes.data & 0xFFFF);
469 ImGui::Text("%s", formattedText);
470 } else {
471 ImGui::Text("%s", node.attributes.text.c_str());
472 }
473 break;
475 node.actions[0].callback();
476 break;
477 }
479 if (ImGui::BeginChild(node.attributes.id.c_str(), node.attributes.size)) {
480 for (auto& child : node.children) {
481 Render(child);
482 }
483 ImGui::EndChild();
484 }
485 break;
487 if (ImGui::BeginMenuBar()) {
488 for (auto& child : node.children) {
489 Render(child);
490 }
491 ImGui::EndMenuBar();
492 }
493 break;
495 if (ImGui::BeginMenu(node.attributes.title.c_str())) {
496 for (auto& child : node.children) {
497 Render(child);
498 }
499 ImGui::EndMenu();
500 }
501 break;
502 }
504 if (ImGui::MenuItem(node.attributes.title.c_str())) {
506 }
507 break;
508 }
510 ImGui::Separator();
511 break;
513 if (ImGui::Selectable(node.attributes.title.c_str(),
514 (bool*)node.attributes.selected)) {
516 }
517 break;
519 if (ImGui::BeginTabBar(node.attributes.title.c_str())) {
520 for (auto& child : node.children) {
521 Render(child);
522 }
523 ImGui::EndTabBar();
524 }
525 break;
527 if (ImGui::BeginTabItem(node.attributes.title.c_str())) {
528 for (auto& child : node.children) {
529 Render(child);
530 }
531 ImGui::EndTabItem();
532 }
533 break;
535 gui::InputHexByte(node.attributes.id.c_str(),
536 (uint8_t*)node.attributes.data);
537 break;
539 gui::InputHexWord(node.attributes.id.c_str(),
540 (uint16_t*)node.attributes.data);
541 break;
542 case WidgetType::Canvas: {
543 gui::Canvas* canvas = (gui::Canvas*)node.attributes.data;
544 if (canvas) {
545 canvas->DrawBackground();
546 canvas->DrawContextMenu();
547
548 canvas->DrawGrid();
549 canvas->DrawOverlay();
550 }
551 break;
552 }
553 default:
554 break;
555 }
556}
557
558void ExecuteActions(const std::vector<Action>& actions, ActionType type) {
559 for (const auto& action : actions) {
560 if (action.type == type) {
561 action.callback(); // Execute the callback associated with the action
562 }
563 }
564}
565
566void Bind(Node* node, std::function<void()> callback) {
567 if (node) {
568 Action action = {ActionType::Click, callback};
569 node->actions.push_back(action);
570 }
571}
572
573void BindAction(Node* node, ActionType type, std::function<void()> callback) {
574 if (node) {
575 Action action = {type, callback};
576 node->actions.push_back(action);
577 }
578}
579
580void BindSelectable(Node* node, bool* selected,
581 std::function<void()> callback) {
582 if (node) {
583 Action action = {ActionType::Click, callback};
584 node->actions.push_back(action);
585 node->attributes.selected = selected;
586 }
587}
588
589std::string LoadFile(const std::string& filename) {
590 std::string fileContents;
591 const std::string kPath = "assets/layouts/";
592
593#ifdef __APPLE__
594#if TARGET_OS_IOS == 1
595 const std::string kBundlePath = core::GetBundleResourcePath();
596 std::ifstream file(kBundlePath + filename);
597#else
598 const std::string kBundlePath = core::GetBundleResourcePath();
599 std::ifstream file(kBundlePath + "Contents/Resources/layouts/" + filename);
600#endif
601#else
602 std::ifstream file(kPath + filename);
603#endif
604
605 if (file.is_open()) {
606 std::string line;
607 while (std::getline(file, line)) {
608 fileContents += line;
609 }
610 file.close();
611 } else {
612 fileContents = "File not found: " + filename;
613 std::cout << fileContents << std::endl;
614 }
615 return fileContents;
616}
617
618} // namespace zeml
619} // namespace gui
620
621} // namespace yaze
Represents a canvas for drawing and manipulating graphics.
Definition canvas.h:34
void DrawOverlay()
Definition canvas.cc:736
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0), bool drag=false)
Definition canvas.cc:65
void DrawContextMenu(gfx::Bitmap *bitmap=nullptr)
Definition canvas.cc:100
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
Definition canvas.cc:685
std::string GetBundleResourcePath()
GetBundleResourcePath returns the path to the bundle resource directory. Specific to MacOS.
Zelda Editor Markup Language Functions.
Definition zeml.cc:19
void ParseFlags(const WidgetType &type, const std::string &flags, WidgetAttributes &attributes)
Definition zeml.cc:134
WidgetType MapType(const std::string &type)
Map a string to a widget type.
Definition zeml.cc:56
void BindAction(Node *node, ActionType type, std::function< void()> callback)
Bind an action to a node.
Definition zeml.cc:573
std::vector< Token > Tokenize(const std::string &input)
Tokenize a zeml string.
Definition zeml.cc:21
void Render(Node &node)
Render a zeml tree.
Definition zeml.cc:380
std::string LoadFile(const std::string &filename)
Definition zeml.cc:589
void Bind(Node *node, std::function< void()> callback)
Bind a callback to a node.
Definition zeml.cc:566
Node Parse(const std::string &yazon_input, const std::map< std::string, void * > &data_bindings)
Parse a zeml string.
Definition zeml.cc:359
void BindSelectable(Node *node, bool *selected, std::function< void()> callback)
Bind a selectable node.
Definition zeml.cc:580
WidgetAttributes ParseAttributes(const std::vector< Token > &tokens, size_t &index, const WidgetType &type, const std::map< std::string, void * > &data_bindings)
ParseNode attributes for a widget.
Definition zeml.cc:304
Node ParseNode(const std::vector< Token > &tokens, size_t &index, const std::map< std::string, void * > &data_bindings, const std::map< std::string, Node > &definitions)
Parse a zeml node.
Definition zeml.cc:86
void ExecuteActions(const std::vector< Action > &actions, ActionType type)
Execute actions for a node.
Definition zeml.cc:558
Graphical User Interface (GUI) components for the application.
Definition canvas.cc:15
bool InputHexWord(const char *label, uint16_t *data, float input_width, bool no_step)
Definition input.cc:153
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
Definition input.cc:167
Main namespace for the application.
Definition controller.cc:18
Node for a zeml tree.
Definition zeml.h:124
WidgetAttributes attributes
Definition zeml.h:126
std::vector< Action > actions
Definition zeml.h:127
std::vector< Node > children
Definition zeml.h:128
WidgetType type
Definition zeml.h:125
TokenType type
Definition zeml.h:38
std::string value
Definition zeml.h:39
Attributes for a widget.
Definition zeml.h:87
std::shared_ptr< void > flags
Definition zeml.h:98