yaze 0.2.0
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
overworld_editor.cc
Go to the documentation of this file.
1#include "overworld_editor.h"
2
3#include <cmath>
4#include <future>
5#include <unordered_map>
6#include <vector>
7
8#include "absl/status/status.h"
9#include "absl/strings/str_format.h"
10#include "app/core/constants.h"
15#include "app/gfx/bitmap.h"
17#include "app/gui/canvas.h"
18#include "app/gui/icons.h"
19#include "app/gui/input.h"
20#include "app/gui/style.h"
21#include "app/gui/zeml.h"
22#include "app/rom.h"
24#include "imgui/imgui.h"
25
26namespace yaze {
27namespace app {
28namespace editor {
29
30using core::Renderer;
31
32using ImGui::BeginChild;
33using ImGui::BeginTabBar;
34using ImGui::BeginTabItem;
35using ImGui::BeginTable;
36using ImGui::BeginTooltip;
37using ImGui::Button;
38using ImGui::Checkbox;
39using ImGui::EndChild;
40using ImGui::EndTabBar;
41using ImGui::EndTabItem;
42using ImGui::EndTable;
43using ImGui::EndTooltip;
44using ImGui::IsItemHovered;
45using ImGui::NewLine;
46using ImGui::PopStyleColor;
47using ImGui::PushStyleColor;
48using ImGui::SameLine;
49using ImGui::Selectable;
50using ImGui::Separator;
51using ImGui::TableHeadersRow;
52using ImGui::TableNextColumn;
53using ImGui::TableNextRow;
54using ImGui::TableSetupColumn;
55using ImGui::Text;
56
57constexpr int kTile16Size = 0x10;
58
60 status_ = absl::OkStatus();
61 if (rom()->is_loaded() && !all_gfx_loaded_) {
66 all_gfx_loaded_ = true;
67 }
68
71 }
72
73 // Draw the overworld editor layout from the ZEML file
75 return status_;
76}
77
79 static bool use_work_area = true;
80 static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration |
81 ImGuiWindowFlags_NoMove |
82 ImGuiWindowFlags_NoSavedSettings;
83 const ImGuiViewport *viewport = ImGui::GetMainViewport();
84 ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos);
85 ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size);
86 if (ImGui::Begin("Fullscreen Overworld Editor", &overworld_canvas_fullscreen_,
87 flags)) {
88 // Draws the toolset for editing the Overworld.
91 }
92 ImGui::End();
93}
94
96 static bool show_gfx_group = false;
97 static bool show_properties = false;
98
99 if (BeginTable("OWToolset", 22, kToolsetTableFlags, ImVec2(0, 0))) {
100 for (const auto &name : kToolsetColumnNames)
101 ImGui::TableSetupColumn(name.data());
102
104 if (Button(ICON_MD_UNDO)) {
105 status_ = Undo();
106 }
107
109 if (Button(ICON_MD_REDO)) {
110 status_ = Redo();
111 }
112
113 TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
114
116 if (Button(ICON_MD_ZOOM_OUT)) {
118 }
119
121 if (Button(ICON_MD_ZOOM_IN)) {
123 }
124
126 if (Button(ICON_MD_OPEN_IN_FULL)) {
128 }
129 HOVER_HINT("Fullscreen Canvas")
130
131 TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
132
137 }
138 HOVER_HINT("Pan (Right click and drag)")
139
143 }
144 HOVER_HINT("Draw Tile")
145
149 HOVER_HINT("Entrances")
150
154 HOVER_HINT("Exits")
155
159 HOVER_HINT("Items")
160
162 if (Selectable(ICON_MD_PEST_CONTROL_RODENT,
165 HOVER_HINT("Sprites")
166
168 if (Selectable(ICON_MD_ADD_LOCATION,
171 HOVER_HINT("Transports")
172
176 HOVER_HINT("Music")
177
178 TableNextColumn();
179 if (Button(ICON_MD_GRID_VIEW)) {
181 }
182 HOVER_HINT("Tile16 Editor")
183
184 TableNextColumn();
185 if (Button(ICON_MD_TABLE_CHART)) {
186 show_gfx_group = !show_gfx_group;
187 }
188 HOVER_HINT("Gfx Group Editor")
189
190 TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
191
192 TableNextColumn();
193 if (Button(ICON_MD_CONTENT_COPY)) {
194 std::vector<uint8_t> png_data;
195 if (gfx::ConvertSurfaceToPNG(maps_bmp_[current_map_].surface(),
196 png_data)) {
198 } else {
199 status_ = absl::InternalError(
200 "Failed to convert overworld map surface to PNG");
201 }
202 }
203 HOVER_HINT("Copy Map to Clipboard");
204
205 TableNextColumn(); // Palette
207
208 TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
209
210 TableNextColumn();
211 Checkbox("Properties", &show_properties);
212
213 ImGui::EndTable();
214 }
215
217 // Create a table in ImGui for the Tile16 Editor
218 ImGui::Begin("Tile16 Editor", &show_tile16_editor_,
219 ImGuiWindowFlags_MenuBar);
221 ImGui::End();
222 }
223
224 if (show_gfx_group) {
225 gui::BeginWindowWithDisplaySettings("Gfx Group Editor", &show_gfx_group);
228 }
229
230 if (show_properties) {
231 ImGui::Begin("Properties", &show_properties);
233 ImGui::End();
234 }
235
236 // TODO: Customizable shortcuts for the Overworld Editor
237 if (!ImGui::IsAnyItemActive()) {
238 if (ImGui::IsKeyDown(ImGuiKey_1)) {
240 } else if (ImGui::IsKeyDown(ImGuiKey_2)) {
242 } else if (ImGui::IsKeyDown(ImGuiKey_3)) {
244 } else if (ImGui::IsKeyDown(ImGuiKey_4)) {
246 } else if (ImGui::IsKeyDown(ImGuiKey_5)) {
248 } else if (ImGui::IsKeyDown(ImGuiKey_6)) {
250 } else if (ImGui::IsKeyDown(ImGuiKey_7)) {
252 } else if (ImGui::IsKeyDown(ImGuiKey_8)) {
254 }
255 }
256}
257
258constexpr std::array<const char *, 8> kMapSettingsColumnNames = {
259 "##WorldId", "##GfxId", "##PalId", "##SprGfxId",
260 "##5thCol", "##6thCol", "##7thCol", "##8thCol"};
261
263 if (BeginTable(kOWMapTable.data(), 8, kOWMapFlags, ImVec2(0, 0), -1)) {
264 for (const auto &name : kMapSettingsColumnNames)
265 ImGui::TableSetupColumn(name);
266
267 TableNextColumn();
268 ImGui::SetNextItemWidth(120.f);
269 ImGui::Combo("##world", &current_world_, kWorldList.data(), 3);
270
271 TableNextColumn();
272 ImGui::BeginGroup();
273 if (gui::InputHexByte("Gfx",
275 ->mutable_area_graphics(),
279 }
280 ImGui::EndGroup();
281
282 TableNextColumn();
283 ImGui::BeginGroup();
284 if (gui::InputHexByte("Palette",
286 ->mutable_area_palette(),
291 }
292 ImGui::EndGroup();
293
294 TableNextColumn();
295 ImGui::BeginGroup();
296 gui::InputHexByte("Spr Gfx",
298 ->mutable_sprite_graphics(game_state_),
300 ImGui::EndGroup();
301
302 TableNextColumn();
303 ImGui::BeginGroup();
304 gui::InputHexByte("Spr Palette",
306 ->mutable_sprite_palette(game_state_),
308 ImGui::EndGroup();
309
310 TableNextColumn();
311 ImGui::BeginGroup();
313 "Msg Id",
314 overworld_.mutable_overworld_map(current_map_)->mutable_message_id(),
315 kInputFieldSize + 20);
316 ImGui::EndGroup();
317
318 TableNextColumn();
319 ImGui::SetNextItemWidth(100.f);
320 ImGui::Combo("##World", &game_state_, kGamePartComboString.data(), 3);
321
322 TableNextColumn();
323 ImGui::Checkbox(
324 "##mosaic",
326 HOVER_HINT("Enable Mosaic effect for the current map");
327
328 ImGui::EndTable();
329 }
330}
331
333 if (BeginTable(kOWMapTable.data(), 15, kOWMapFlags, ImVec2(0, 0), -1)) {
334 for (const auto &name : kMapSettingsColumnNames)
335 ImGui::TableSetupColumn(name);
336
337 TableNextColumn();
338 ImGui::SetNextItemWidth(120.f);
339 ImGui::Combo("##world", &current_world_, kWorldList.data(), 3);
340
341 static const std::array<std::string, 8> kCustomMapSettingsColumnNames = {
342 "TileGfx0", "TileGfx1", "TileGfx2", "TileGfx3",
343 "TileGfx4", "TileGfx5", "TileGfx6", "TileGfx7"};
344 for (int i = 0; i < 8; ++i) {
345 TableNextColumn();
346 ImGui::BeginGroup();
347 if (gui::InputHexByte(kCustomMapSettingsColumnNames[i].data(),
349 ->mutable_custom_tileset(i),
353 }
354 ImGui::EndGroup();
355 }
356
357 TableNextColumn();
358 ImGui::BeginGroup();
359 if (gui::InputHexByte("Palette",
361 ->mutable_area_palette(),
366 }
367 ImGui::EndGroup();
368
369 TableNextColumn();
370 ImGui::BeginGroup();
371 gui::InputHexByte("Spr Gfx",
373 ->mutable_sprite_graphics(game_state_),
375 ImGui::EndGroup();
376
377 TableNextColumn();
378 ImGui::BeginGroup();
379 gui::InputHexByte("Spr Palette",
381 ->mutable_sprite_palette(game_state_),
383 ImGui::EndGroup();
384
385 TableNextColumn();
386 ImGui::BeginGroup();
388 "Msg Id",
389 overworld_.mutable_overworld_map(current_map_)->mutable_message_id(),
390 kInputFieldSize + 20);
391 ImGui::EndGroup();
392
393 TableNextColumn();
394 ImGui::SetNextItemWidth(100.f);
395 ImGui::Combo("##World", &game_state_, kGamePartComboString.data(), 3);
396
397 TableNextColumn();
398 ImGui::Checkbox(
399 "##mosaic",
401 HOVER_HINT("Enable Mosaic effect for the current map");
402
403 ImGui::EndTable();
404 }
405}
406
408 int xx = 0;
409 int yy = 0;
410 for (int i = 0; i < 0x40; i++) {
411 int world_index = i + (current_world_ * 0x40);
412 int map_x = (xx * kOverworldMapSize * ow_map_canvas_.global_scale());
413 int map_y = (yy * kOverworldMapSize * ow_map_canvas_.global_scale());
414 ow_map_canvas_.DrawBitmap(maps_bmp_[world_index], map_x, map_y,
416 xx++;
417 if (xx >= 8) {
418 yy++;
419 xx = 0;
420 }
421 }
422}
423
425 // Determine which overworld map the user is currently editing.
426 auto mouse_position = ow_map_canvas_.drawn_tile_position();
427 int map_x = mouse_position.x / kOverworldMapSize;
428 int map_y = mouse_position.y / kOverworldMapSize;
429 current_map_ = map_x + map_y * 8;
430 if (current_world_ == 1) {
431 current_map_ += 0x40;
432 } else if (current_world_ == 2) {
433 current_map_ += 0x80;
434 }
435
436 // Render the updated map bitmap.
437 RenderUpdatedMapBitmap(mouse_position,
439
440 // Calculate the correct superX and superY values
441 int superY = current_map_ / 8;
442 int superX = current_map_ % 8;
443 int mouse_x = mouse_position.x;
444 int mouse_y = mouse_position.y;
445 // Calculate the correct tile16_x and tile16_y positions
446 int tile16_x = (mouse_x % kOverworldMapSize) / (kOverworldMapSize / 32);
447 int tile16_y = (mouse_y % kOverworldMapSize) / (kOverworldMapSize / 32);
448
449 // Update the overworld_.map_tiles() based on tile16 ID and current world
450 auto &selected_world =
451 (current_world_ == 0) ? overworld_.mutable_map_tiles()->light_world
452 : (current_world_ == 1) ? overworld_.mutable_map_tiles()->dark_world
453 : overworld_.mutable_map_tiles()->special_world;
454
455 int index_x = superX * 32 + tile16_x;
456 int index_y = superY * 32 + tile16_y;
457
458 selected_world[index_x][index_y] = current_tile16_;
459}
460
462 const ImVec2 &click_position, const std::vector<uint8_t> &tile_data) {
463 // Calculate the tile index for x and y based on the click_position
464 int tile_index_x =
465 (static_cast<int>(click_position.x) % kOverworldMapSize) / kTile16Size;
466 int tile_index_y =
467 (static_cast<int>(click_position.y) % kOverworldMapSize) / kTile16Size;
468
469 // Calculate the pixel start position based on tile index and tile size
470 ImVec2 start_position;
471 start_position.x = tile_index_x * kTile16Size;
472 start_position.y = tile_index_y * kTile16Size;
473
474 // Update the bitmap's pixel data based on the start_position and tile_data
475 gfx::Bitmap &current_bitmap = maps_bmp_[current_map_];
476 for (int y = 0; y < kTile16Size; ++y) {
477 for (int x = 0; x < kTile16Size; ++x) {
478 int pixel_index =
479 (start_position.y + y) * kOverworldMapSize + (start_position.x + x);
480 current_bitmap.WriteToPixel(pixel_index, tile_data[y * kTile16Size + x]);
481 }
482 }
483
484 current_bitmap.set_modified(true);
485}
486
489
490 // User has selected a tile they want to draw from the blockset.
491 if (!blockset_canvas_.points().empty() &&
493 // Left click is pressed
495 kTile16Size)) {
497 }
498 }
499
501 if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) ||
502 ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
503 auto &selected_world =
504 (current_world_ == 0) ? overworld_.mutable_map_tiles()->light_world
505 : (current_world_ == 1)
506 ? overworld_.mutable_map_tiles()->dark_world
507 : overworld_.mutable_map_tiles()->special_world;
508 // new_start_pos and new_end_pos
509 auto start = ow_map_canvas_.selected_points()[0];
510 auto end = ow_map_canvas_.selected_points()[1];
511
512 // Calculate the bounds of the rectangle in terms of 16x16 tile indices
513 int start_x = std::floor(start.x / kTile16Size) * kTile16Size;
514 int start_y = std::floor(start.y / kTile16Size) * kTile16Size;
515 int end_x = std::floor(end.x / kTile16Size) * kTile16Size;
516 int end_y = std::floor(end.y / kTile16Size) * kTile16Size;
517
518 if (start_x > end_x) std::swap(start_x, end_x);
519 if (start_y > end_y) std::swap(start_y, end_y);
520
521 constexpr int local_map_size = 512; // Size of each local map
522 // Number of tiles per local map (since each tile is 16x16)
523 constexpr int tiles_per_local_map = local_map_size / kTile16Size;
524
525 for (int y = start_y, i = 0; y <= end_y; y += kTile16Size) {
526 for (int x = start_x; x <= end_x; x += kTile16Size, ++i) {
527 // Determine which local map (512x512) the tile is in
528 int local_map_x = x / local_map_size;
529 int local_map_y = y / local_map_size;
530
531 // Calculate the tile's position within its local map
532 int tile16_x = (x % local_map_size) / kTile16Size;
533 int tile16_y = (y % local_map_size) / kTile16Size;
534
535 // Calculate the index within the overall map structure
536 int index_x = local_map_x * tiles_per_local_map + tile16_x;
537 int index_y = local_map_y * tiles_per_local_map + tile16_y;
538 int tile16_id = overworld_.GetTileFromPosition(
540 selected_world[index_x][index_y] = tile16_id;
541 }
542 }
543
545 }
546 }
547}
548
551
552 // Single tile case
553 if (ow_map_canvas_.selected_tile_pos().x != -1) {
557 }
558
559 static std::vector<int> tile16_ids;
561 // Get the tile16 IDs from the selected tile ID positions
562 if (tile16_ids.size() != 0) {
563 tile16_ids.clear();
564 }
565
566 if (ow_map_canvas_.selected_tiles().size() > 0) {
567 for (auto &each : ow_map_canvas_.selected_tiles()) {
568 tile16_ids.push_back(overworld_.GetTileFromPosition(each));
569 }
570 }
571 }
572 // Create a composite image of all the tile16s selected
574}
575
577 // 4096x4096, 512x512 maps and some are larges maps 1024x1024
578 const auto mouse_position = ImGui::GetIO().MousePos;
579 const int large_map_size = 1024;
580 const auto canvas_zero_point = ow_map_canvas_.zero_point();
581
582 // Calculate which small map the mouse is currently over
583 int map_x = (mouse_position.x - canvas_zero_point.x) / kOverworldMapSize;
584 int map_y = (mouse_position.y - canvas_zero_point.y) / kOverworldMapSize;
585
586 // Calculate the index of the map in the `maps_bmp_` vector
587 current_map_ = map_x + map_y * 8;
588 const int current_highlighted_map = current_map_;
589 if (current_world_ == 1) {
590 current_map_ += 0x40;
591 } else if (current_world_ == 2) {
592 current_map_ += 0x80;
593 }
594
596
597 if (overworld_.overworld_map(current_map_)->is_large_map() ||
598 overworld_.overworld_map(current_map_)->large_index() != 0) {
599 const int highlight_parent =
600 overworld_.overworld_map(current_highlighted_map)->parent();
601 const int parent_map_x = highlight_parent % 8;
602 const int parent_map_y = highlight_parent / 8;
604 parent_map_y * kOverworldMapSize, large_map_size,
605 large_map_size);
606 } else {
607 const int current_map_x = current_highlighted_map % 8;
608 const int current_map_y = current_highlighted_map / 8;
610 current_map_y * kOverworldMapSize,
612 }
613
614 if (maps_bmp_[current_map_].modified() ||
615 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
619 maps_bmp_[current_map_].set_modified(false);
620 }
621
622 return absl::OkStatus();
623}
624
626 if (ImGui::IsMouseDragging(ImGuiMouseButton_Middle)) {
631 }
632 if (ImGui::IsMouseReleased(ImGuiMouseButton_Middle) &&
637 }
638}
639
641 if (all_gfx_loaded_) {
642 if (flags()->overworld.kLoadCustomOverworld) {
644 } else {
646 }
647 Separator();
648 }
649
654
658 } else {
660 }
661
662 if (overworld_.is_loaded()) {
671 }
672 if (IsItemHovered()) status_ = CheckForCurrentMap();
673 }
674
677 EndChild();
678
679 // Handle mouse wheel activity
680 if (ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows) &&
681 ImGui::IsMouseDragging(ImGuiMouseButton_Middle)) {
682 ImGui::SetScrollX(ImGui::GetScrollX() + ImGui::GetIO().MouseWheelH * 16.0f);
683 ImGui::SetScrollY(ImGui::GetScrollY() + ImGui::GetIO().MouseWheel * 16.0f);
684 }
685}
686
689 ImGui::BeginGroup();
690 gui::BeginChildWithScrollbar("##Tile16SelectorScrollRegion");
693 {
697
699 // Open the tile16 editor to the tile
700 auto tile_pos = blockset_canvas_.points().front();
701 int grid_x = static_cast<int>(tile_pos.x / 32);
702 int grid_y = static_cast<int>(tile_pos.y / 32);
703 int id = grid_x + grid_y * 8;
705 show_tile16_editor_ = true;
706 }
707
708 if (ImGui::IsItemClicked() && !blockset_canvas_.points().empty()) {
709 int x = blockset_canvas_.points().front().x / 32;
710 int y = blockset_canvas_.points().front().y / 32;
711 current_tile16_ = x + (y * 8);
712 }
713
716 }
717 EndChild();
718 ImGui::EndGroup();
719 return absl::OkStatus();
720}
721
725 if (all_gfx_loaded_) {
726 int key = 0;
727 for (auto &value : rom()->gfx_sheets()) {
728 int offset = 0x40 * (key + 1);
729 int top_left_y = graphics_bin_canvas_.zero_point().y + 2;
730 if (key >= 1) {
731 top_left_y = graphics_bin_canvas_.zero_point().y + 0x40 * key;
732 }
733 auto texture = value.texture();
735 (ImTextureID)(intptr_t)texture,
736 ImVec2(graphics_bin_canvas_.zero_point().x + 2, top_left_y),
737 ImVec2(graphics_bin_canvas_.zero_point().x + 0x100,
738 graphics_bin_canvas_.zero_point().y + offset));
739 key++;
740 }
741 }
744}
745
747 if (overworld_.is_loaded() &&
751 gfx::Bitmap bmp;
752 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
754 palette_));
756 }
757
759 ImGui::BeginGroup();
760 gui::BeginChildWithScrollbar("##AreaGraphicsScrollRegion");
763 {
766 /*border_offset=*/2, overworld_.is_loaded());
770 }
771 EndChild();
772 ImGui::EndGroup();
773 return absl::OkStatus();
774}
775
777 if (BeginTabBar(kTileSelectorTab.data(),
778 ImGuiTabBarFlags_FittingPolicyScroll)) {
779 if (BeginTabItem("Tile16")) {
781 EndTabItem();
782 }
783 if (BeginTabItem("Tile8")) {
785 gui::BeginChildWithScrollbar("##Tile8SelectorScrollRegion");
787 EndChild();
789 EndTabItem();
790 }
791 if (BeginTabItem("Area Graphics")) {
793 EndTabItem();
794 }
795 EndTabBar();
796 }
797 return absl::OkStatus();
798}
799
800void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
801 bool holes) {
802 int i = 0;
803 for (auto &each : overworld_.entrances()) {
804 if (each.map_id_ < 0x40 + (current_world_ * 0x40) &&
805 each.map_id_ >= (current_world_ * 0x40) && !each.deleted) {
806 auto color = ImVec4(255, 255, 0, 100);
807 if (each.is_hole_) {
808 color = ImVec4(255, 255, 255, 200);
809 }
810 ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16, color);
811 std::string str = core::UppercaseHexByte(each.entrance_id_);
812
814 HandleEntityDragging(&each, canvas_p0, scrolling, is_dragging_entity_,
816
817 if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
818 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
819 jump_to_tab_ = each.entrance_id_;
820 }
821
822 if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
823 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
825 current_entrance_ = each;
826 }
827 }
828
829 ow_map_canvas_.DrawText(str, each.x_, each.y_);
830 }
831 i++;
832 }
833
835 // Get the deleted entrance ID and insert it at the mouse position
836 auto deleted_entrance_id = overworld_.deleted_entrances().back();
837 overworld_.deleted_entrances().pop_back();
838 auto &entrance = overworld_.entrances()[deleted_entrance_id];
839 entrance.map_id_ = current_map_;
840 entrance.entrance_id_ = deleted_entrance_id;
841 entrance.x_ = ow_map_canvas_.hover_mouse_pos().x;
842 entrance.y_ = ow_map_canvas_.hover_mouse_pos().y;
843 entrance.deleted = false;
844 }
845
847 const auto is_hovering =
848 IsMouseHoveringOverEntity(current_entrance_, canvas_p0, scrolling);
849
850 if (!is_hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
851 ImGui::OpenPopup("Entrance Inserter");
852 } else {
856 }
857
861 }
862 }
863 }
864}
865
866void OverworldEditor::DrawOverworldExits(ImVec2 canvas_p0, ImVec2 scrolling) {
867 int i = 0;
868 for (auto &each : *overworld_.mutable_exits()) {
869 if (each.map_id_ < 0x40 + (current_world_ * 0x40) &&
870 each.map_id_ >= (current_world_ * 0x40) && !each.deleted_) {
871 ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16,
872 ImVec4(255, 255, 255, 150));
874 each.entity_id_ = i;
878
879 if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
880 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
881 jump_to_tab_ = each.room_id_;
882 }
883
884 if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
885 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
887 current_exit_ = each;
888 current_entity_ = &each;
890 ImGui::OpenPopup("Exit editor");
891 }
892 }
893
894 std::string str = core::UppercaseHexByte(i);
895 ow_map_canvas_.DrawText(str, each.x_, each.y_);
896 }
897 i++;
898 }
899
902 const auto hovering = IsMouseHoveringOverEntity(
905
906 if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
907 ImGui::OpenPopup("Exit Inserter");
908 } else {
912 }
913 }
914 }
915}
916
918 int i = 0;
919 for (auto &item : *overworld_.mutable_all_items()) {
920 // Get the item's bitmap and real X and Y positions
921 if (item.room_map_id_ < 0x40 + (current_world_ * 0x40) &&
922 item.room_map_id_ >= (current_world_ * 0x40) && !item.deleted) {
923 ow_map_canvas_.DrawRect(item.x_, item.y_, 16, 16, ImVec4(255, 0, 0, 150));
924
926 // Check if this item is being clicked and dragged
930
931 const auto hovering = IsMouseHoveringOverEntity(
933 if (hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
935 current_item_ = item;
936 current_entity_ = &item;
937 }
938 }
939 std::string item_name = "";
940 if (item.id_ < zelda3::overworld::kSecretItemNames.size()) {
941 item_name = zelda3::overworld::kSecretItemNames[item.id_];
942 } else {
943 item_name = absl::StrFormat("0x%02X", item.id_);
944 }
945 ow_map_canvas_.DrawText(item_name, item.x_, item.y_);
946 }
947 i++;
948 }
949
952 const auto hovering = IsMouseHoveringOverEntity(
955
956 if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
957 ImGui::OpenPopup("Item Inserter");
958 } else {
962 }
963 }
964 }
965}
966
968 int i = 0;
969 for (auto &sprite : *overworld_.mutable_sprites(game_state_)) {
970 if (!sprite.deleted()) {
971 // int map_id = sprite.map_id();
972 // map x and map y are relative to the map
973 // So we need to check if the map is large or small then add the offset
974
975 // Calculate the superX and superY values
976 // int superY = map_id / 8;
977 // int superX = map_id % 8;
978
979 // Calculate the map_x and map_y values
980 int map_x = sprite.map_x();
981 int map_y = sprite.map_y();
982
983 // Calculate the actual map_x and map_y values
984 // map_x += superX * 512;
985 // map_y += superY * 512;
986
988 /*magenta*/ ImVec4(255, 0, 255, 150));
995 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
997 current_sprite_ = sprite;
998 }
999 }
1000 if (sprite_previews_[sprite.id()].is_active()) {
1001 ow_map_canvas_.DrawBitmap(sprite_previews_[sprite.id()], map_x, map_y,
1002 2.0f);
1003 }
1004
1005 ow_map_canvas_.DrawText(absl::StrFormat("%s", sprite.name()), map_x,
1006 map_y);
1007 }
1008 i++;
1009 }
1010
1013 const auto hovering = IsMouseHoveringOverEntity(
1016
1017 if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
1018 ImGui::OpenPopup("Sprite Inserter");
1019 } else {
1021 ->at(current_sprite_id_))) {
1024 }
1025 }
1026 }
1027}
1028
1030 if (flags()->overworld.kSaveOverworldMaps) {
1035 }
1036 if (flags()->overworld.kSaveOverworldEntrances) {
1038 }
1039 if (flags()->overworld.kSaveOverworldExits) {
1041 }
1042 if (flags()->overworld.kSaveOverworldItems) {
1044 }
1045 if (flags()->overworld.kSaveOverworldProperties) {
1047 }
1048 return absl::OkStatus();
1049}
1050
1052 // Load the Link to the Past overworld.
1055
1056 // Create the area graphics image
1057 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
1060
1061 // Create the tile16 blockset image
1062 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
1063 0x80, 0x2000, 0x08, overworld_.tile16_blockset_data(),
1065 map_blockset_loaded_ = true;
1066
1067 // Copy the tile16 data into individual tiles.
1068 auto tile16_data = overworld_.tile16_blockset_data();
1070
1071 // Loop through the tiles and copy their pixel data into separate vectors
1072 for (uint i = 0; i < zelda3::overworld::kNumTile16Individual; i++) {
1073 std::vector<uint8_t> tile_data(kTile16Size * kTile16Size, 0x00);
1074
1075 // Copy the pixel data for the current tile into the vector
1076 for (int ty = 0; ty < kTile16Size; ty++) {
1077 for (int tx = 0; tx < kTile16Size; tx++) {
1078 int position = tx + (ty * kTile16Size);
1079 uint8_t value =
1080 tile16_data[(i % 8 * kTile16Size) + (i / 8 * kTile16Size * 0x80) +
1081 (ty * 0x80) + tx];
1082 tile_data[position] = value;
1083 }
1084 }
1085
1086 // Add the vector for the current tile to the vector of tile pixel data
1087 tile16_individual_data_.push_back(tile_data);
1088 tile16_individual_.emplace_back();
1089 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
1092 }
1093
1094 // Render the overworld maps loaded from the ROM.
1095 for (int i = 0; i < zelda3::overworld::kNumOverworldMaps; ++i) {
1097 auto palette = overworld_.current_area_palette();
1098 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
1101 }
1102
1103 if (flags()->overworld.kDrawOverworldSprites) {
1105 }
1106
1107 return absl::OkStatus();
1108}
1109
1111 // Render the sprites for each Overworld map
1112 for (int i = 0; i < 3; i++)
1113 for (auto const &sprite : overworld_.sprites(i)) {
1114 int width = sprite.width();
1115 int height = sprite.height();
1116 int depth = 0x10;
1117 auto spr_gfx = sprite.PreviewGraphics();
1118 if (spr_gfx.empty() || width == 0 || height == 0) {
1119 continue;
1120 }
1121 sprite_previews_[sprite.id()].Create(width, height, depth, spr_gfx);
1122 RETURN_IF_ERROR(sprite_previews_[sprite.id()].ApplyPalette(palette_));
1124 }
1125 return absl::OkStatus();
1126}
1127
1129 overworld_.mutable_overworld_map(map_index)->LoadAreaGraphics();
1130 status_ = overworld_.mutable_overworld_map(map_index)->BuildTileset();
1132 status_ = overworld_.mutable_overworld_map(map_index)->BuildTiles16Gfx(
1135 status_ = overworld_.mutable_overworld_map(map_index)->BuildBitmap(
1137 maps_bmp_[map_index].set_data(
1138 overworld_.mutable_overworld_map(map_index)->bitmap_data());
1139 maps_bmp_[map_index].set_modified(true);
1141}
1142
1144 std::vector<std::future<void>> futures;
1145 int indices[4];
1146
1147 auto refresh_map_async = [this](int map_index) {
1148 RefreshChildMap(map_index);
1149 };
1150
1151 int source_map_id = current_map_;
1152 bool is_large = overworld_.overworld_map(current_map_)->is_large_map();
1153 if (is_large) {
1154 source_map_id = current_parent_;
1155 // We need to update the map and its siblings if it's a large map
1156 for (int i = 1; i < 4; i++) {
1157 int sibling_index = overworld_.overworld_map(source_map_id)->parent() + i;
1158 if (i >= 2) sibling_index += 6;
1159 futures.push_back(
1160 std::async(std::launch::async, refresh_map_async, sibling_index));
1161 indices[i] = sibling_index;
1162 }
1163 }
1164 indices[0] = source_map_id;
1165 futures.push_back(
1166 std::async(std::launch::async, refresh_map_async, source_map_id));
1167
1168 for (auto &each : futures) {
1169 each.get();
1170 }
1171 int n = is_large ? 4 : 1;
1172 // We do texture updating on the main thread
1173 for (int i = 0; i < n; ++i) {
1175 }
1176}
1177
1181 const auto current_map_palette = overworld_.current_area_palette();
1182
1183 if (overworld_.overworld_map(current_map_)->is_large_map()) {
1184 // We need to update the map and its siblings if it's a large map
1185 for (int i = 1; i < 4; i++) {
1186 int sibling_index = overworld_.overworld_map(current_map_)->parent() + i;
1187 if (i >= 2) sibling_index += 6;
1189 overworld_.mutable_overworld_map(sibling_index)->LoadPalette());
1191 maps_bmp_[sibling_index].ApplyPalette(current_map_palette));
1192 }
1193 }
1194
1195 RETURN_IF_ERROR(maps_bmp_[current_map_].ApplyPalette(current_map_palette));
1196 return absl::OkStatus();
1197}
1198
1200 auto &current_ow_map = *overworld_.mutable_overworld_map(current_map_);
1201 if (current_ow_map.is_large_map()) {
1202 // We need to copy the properties from the parent map to the children
1203 for (int i = 1; i < 4; i++) {
1204 int sibling_index = current_ow_map.parent() + i;
1205 if (i >= 2) {
1206 sibling_index += 6;
1207 }
1208 auto &map = *overworld_.mutable_overworld_map(sibling_index);
1209 map.set_area_graphics(current_ow_map.area_graphics());
1210 map.set_area_palette(current_ow_map.area_palette());
1211 map.set_sprite_graphics(game_state_,
1212 current_ow_map.sprite_graphics(game_state_));
1213 map.set_sprite_palette(game_state_,
1214 current_ow_map.sprite_palette(game_state_));
1215 map.set_message_id(current_ow_map.message_id());
1216 }
1217 }
1218}
1219
1221 if (current_blockset_ ==
1222 overworld_.overworld_map(current_map_)->area_graphics()) {
1223 return absl::OkStatus();
1224 }
1226
1229 // Create the tile16 blockset image
1232
1233 // Copy the tile16 data into individual tiles.
1234 const auto tile16_data = overworld_.tile16_blockset_data();
1235
1236 std::vector<std::future<void>> futures;
1237 // Loop through the tiles and copy their pixel data into separate vectors
1238 for (uint i = 0; i < zelda3::overworld::kNumTile16Individual; i++) {
1239 futures.push_back(std::async(
1240 std::launch::async,
1241 [&](int index) {
1242 std::vector<uint8_t> tile_data(16 * 16, 0x00);
1243 for (int ty = 0; ty < 16; ty++) {
1244 for (int tx = 0; tx < 16; tx++) {
1245 int position = tx + (ty * 0x10);
1246 uint8_t value =
1247 tile16_data[(index % 8 * 16) + (index / 8 * 16 * 0x80) +
1248 (ty * 0x80) + tx];
1249 tile_data[position] = value;
1250 }
1251 }
1252 tile16_individual_[index].set_data(tile_data);
1253 },
1254 i));
1255 }
1256
1257 for (auto &future : futures) {
1258 future.get();
1259 }
1260
1261 // Render the bitmaps of each tile.
1262 for (uint id = 0; id < zelda3::overworld::kNumTile16Individual; id++) {
1263 RETURN_IF_ERROR(tile16_individual_[id].ApplyPalette(palette_));
1265 }
1266
1267 return absl::OkStatus();
1268}
1269
1271 static bool init_properties = false;
1272
1273 if (!init_properties) {
1274 for (int i = 0; i < 0x40; i++) {
1275 std::string area_graphics_str = absl::StrFormat(
1276 "%02hX", overworld_.overworld_map(i)->area_graphics());
1278 ->push_back(area_graphics_str);
1279
1280 area_graphics_str = absl::StrFormat(
1281 "%02hX", overworld_.overworld_map(i + 0x40)->area_graphics());
1283 ->push_back(area_graphics_str);
1284
1285 std::string area_palette_str =
1286 absl::StrFormat("%02hX", overworld_.overworld_map(i)->area_palette());
1288 ->push_back(area_palette_str);
1289
1290 area_palette_str = absl::StrFormat(
1291 "%02hX", overworld_.overworld_map(i + 0x40)->area_palette());
1293 ->push_back(area_palette_str);
1294 std::string sprite_gfx_str = absl::StrFormat(
1295 "%02hX", overworld_.overworld_map(i)->sprite_graphics(1));
1297 ->push_back(sprite_gfx_str);
1298
1299 sprite_gfx_str = absl::StrFormat(
1300 "%02hX", overworld_.overworld_map(i)->sprite_graphics(2));
1302 ->push_back(sprite_gfx_str);
1303
1304 sprite_gfx_str = absl::StrFormat(
1305 "%02hX", overworld_.overworld_map(i + 0x40)->sprite_graphics(1));
1307 ->push_back(sprite_gfx_str);
1308
1309 sprite_gfx_str = absl::StrFormat(
1310 "%02hX", overworld_.overworld_map(i + 0x40)->sprite_graphics(2));
1312 ->push_back(sprite_gfx_str);
1313
1314 std::string sprite_palette_str = absl::StrFormat(
1315 "%02hX", overworld_.overworld_map(i)->sprite_palette(1));
1317 ->push_back(sprite_palette_str);
1318
1319 sprite_palette_str = absl::StrFormat(
1320 "%02hX", overworld_.overworld_map(i)->sprite_palette(2));
1322 ->push_back(sprite_palette_str);
1323
1324 sprite_palette_str = absl::StrFormat(
1325 "%02hX", overworld_.overworld_map(i + 0x40)->sprite_palette(1));
1327 ->push_back(sprite_palette_str);
1328
1329 sprite_palette_str = absl::StrFormat(
1330 "%02hX", overworld_.overworld_map(i + 0x40)->sprite_palette(2));
1332 ->push_back(sprite_palette_str);
1333 }
1334 init_properties = true;
1335 }
1336
1337 Text("Area Gfx LW/DW");
1338 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1340 SameLine();
1341 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1343 ImGui::Separator();
1344
1345 Text("Sprite Gfx LW/DW");
1346 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1348 SameLine();
1349 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1351 SameLine();
1352 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1354 SameLine();
1355 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1357 ImGui::Separator();
1358
1359 Text("Area Pal LW/DW");
1360 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1362 SameLine();
1363 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1365
1366 static bool show_gfx_group = false;
1367 Checkbox("Show Gfx Group Editor", &show_gfx_group);
1368 if (show_gfx_group) {
1369 gui::BeginWindowWithDisplaySettings("Gfx Group Editor", &show_gfx_group);
1372 }
1373}
1374
1376 if (BeginTable("UsageStatsTable", 3, kOWEditFlags, ImVec2(0, 0))) {
1377 TableSetupColumn("Entrances");
1378 TableSetupColumn("Grid", ImGuiTableColumnFlags_WidthStretch,
1379 ImGui::GetContentRegionAvail().x);
1380 TableSetupColumn("Usage", ImGuiTableColumnFlags_WidthFixed, 256);
1381 TableHeadersRow();
1382 TableNextRow();
1383
1384 TableNextColumn();
1385 if (BeginChild("UnusedSpritesetScroll", ImVec2(0, 0), true,
1386 ImGuiWindowFlags_HorizontalScrollbar)) {
1387 for (int i = 0; i < 0x81; i++) {
1388 auto entrance_name = rom()->resource_label()->GetLabel(
1389 "Dungeon Entrance Names", core::UppercaseHexByte(i));
1390 std::string str = absl::StrFormat("%#x - %s", i, entrance_name);
1391 if (Selectable(str.c_str(), selected_entrance_ == i,
1392 overworld_.entrances().at(i).deleted
1393 ? ImGuiSelectableFlags_Disabled
1394 : 0)) {
1396 selected_usage_map_ = overworld_.entrances().at(i).map_id_;
1398 }
1399 if (IsItemHovered()) {
1400 BeginTooltip();
1401 Text("Entrance ID: %d", i);
1402 Text("Map ID: %d", overworld_.entrances().at(i).map_id_);
1403 Text("Entrance ID: %d", overworld_.entrances().at(i).entrance_id_);
1404 Text("X: %d", overworld_.entrances().at(i).x_);
1405 Text("Y: %d", overworld_.entrances().at(i).y_);
1406 Text("Deleted? %s",
1407 overworld_.entrances().at(i).deleted ? "Yes" : "No");
1408 EndTooltip();
1409 }
1410 }
1411 EndChild();
1412 }
1413
1414 TableNextColumn();
1415 DrawUsageGrid();
1416
1417 TableNextColumn();
1419
1420 EndTable();
1421 }
1422 return absl::OkStatus();
1423}
1424
1426 // Create a grid of 8x8 squares
1427 int totalSquares = 128;
1428 int squaresWide = 8;
1429 int squaresTall = (totalSquares + squaresWide - 1) /
1430 squaresWide; // Ceiling of totalSquares/squaresWide
1431
1432 // Loop through each row
1433 for (int row = 0; row < squaresTall; ++row) {
1434 NewLine();
1435
1436 for (int col = 0; col < squaresWide; ++col) {
1437 if (row * squaresWide + col >= totalSquares) {
1438 break;
1439 }
1440 // Determine if this square should be highlighted
1441 bool highlight = selected_usage_map_ == (row * squaresWide + col);
1442
1443 // Set highlight color if needed
1444 if (highlight) {
1445 PushStyleColor(ImGuiCol_Button,
1446 ImVec4(1.0f, 0.5f, 0.0f,
1447 1.0f)); // Or any highlight color
1448 }
1449
1450 // Create a button or selectable for each square
1451 if (Button("##square", ImVec2(20, 20))) {
1452 // Switch over to the room editor tab
1453 // and add a room tab by the ID of the square
1454 // that was clicked
1455 }
1456
1457 // Reset style if it was highlighted
1458 if (highlight) {
1459 PopStyleColor();
1460 }
1461
1462 // Check if the square is hovered
1463 if (IsItemHovered()) {
1464 // Display a tooltip with all the room properties
1465 }
1466
1467 // Keep squares in the same line
1468 SameLine();
1469 }
1470 }
1471}
1472
1474 Text("Current Map: %d", current_map_);
1475 Text("Current Tile16: %d", current_tile16_);
1476 int relative_x = (int)ow_map_canvas_.drawn_tile_position().x % 512;
1477 int relative_y = (int)ow_map_canvas_.drawn_tile_position().y % 512;
1478 Text("Current Tile16 Drawn Position (Relative): %d, %d", relative_x,
1479 relative_y);
1480
1481 // Print the size of the overworld map_tiles per world
1482 Text("Light World Map Tiles: %d",
1483 (int)overworld_.mutable_map_tiles()->light_world.size());
1484 Text("Dark World Map Tiles: %d",
1485 (int)overworld_.mutable_map_tiles()->dark_world.size());
1486 Text("Special World Map Tiles: %d",
1487 (int)overworld_.mutable_map_tiles()->special_world.size());
1488
1489 static bool view_lw_map_tiles = false;
1490 static MemoryEditor mem_edit;
1491 // Let's create buttons which let me view containers in the memory editor
1492 if (Button("View Light World Map Tiles")) {
1493 view_lw_map_tiles = !view_lw_map_tiles;
1494 }
1495
1496 if (view_lw_map_tiles) {
1497 mem_edit.DrawContents(
1498 overworld_.mutable_map_tiles()->light_world[current_map_].data(),
1499 overworld_.mutable_map_tiles()->light_world[current_map_].size());
1500 }
1501}
1502
1504 // Load zeml string from layouts/overworld.zeml
1505 std::string layout = gui::zeml::LoadFile("overworld.zeml");
1506 // Parse the zeml string into a Node object
1508
1509 gui::zeml::Bind(&*layout_node_.GetNode("OverworldCanvas"),
1510 [this]() { DrawOverworldCanvas(); });
1511 gui::zeml::Bind(&*layout_node_.GetNode("OverworldTileSelector"),
1512 [this]() { status_ = DrawTileSelector(); });
1513 gui::zeml::Bind(&*layout_node_.GetNode("OwUsageStats"), [this]() {
1514 if (rom()->is_loaded()) {
1515 status_ = UpdateUsageStats();
1516 }
1517 });
1518 gui::zeml::Bind(&*layout_node_.GetNode("owToolset"),
1519 [this]() { DrawToolset(); });
1520 gui::zeml::Bind(&*layout_node_.GetNode("OwTile16Editor"), [this]() {
1521 if (rom()->is_loaded()) {
1522 status_ = tile16_editor_.Update();
1523 }
1524 });
1525 gui::zeml::Bind(&*layout_node_.GetNode("OwGfxGroupEditor"), [this]() {
1526 if (rom()->is_loaded()) {
1527 status_ = gfx_group_editor_.Update();
1528 }
1529 });
1530}
1531
1532} // namespace editor
1533} // namespace app
1534} // namespace yaze
void UpdateBitmap(gfx::Bitmap *bitmap)
Used to update a bitmap on the screen.
Definition renderer.h:56
static Renderer & GetInstance()
Definition renderer.h:27
void RenderBitmap(gfx::Bitmap *bitmap)
Used to render a bitmap to the screen.
Definition renderer.h:49
absl::Status LoadEntranceTileTypes(Rom &rom)
zelda3::overworld::OverworldItem current_item_
std::vector< gfx::Bitmap > tile16_individual_
std::vector< std::vector< uint8_t > > tile16_individual_data_
void DrawOverworldCanvas()
Allows the user to make changes to the overworld map.
void DrawCustomOverworldMapSettings()
Draw the overworld settings for ZSCustomOverworld.
void DrawOverworldEntrances(ImVec2 canvas_p, ImVec2 scrolling, bool holes=false)
void DrawFullscreenCanvas()
Draws the canvas, tile16 selector, and toolset in fullscreen.
absl::Status CheckForCurrentMap()
Check for changes to the overworld map. Calls RefreshOverworldMap and RefreshTile16Blockset on the cu...
void CheckForSelectRectangle()
Draw and create the tile16 IDs that are currently selected.
zelda3::overworld::Overworld overworld_
zelda3::overworld::OverworldExit current_exit_
zelda3::overworld::OverworldEntrance current_entrance_
void DrawOverworldExits(ImVec2 zero, ImVec2 scrolling)
void RenderUpdatedMapBitmap(const ImVec2 &click_position, const std::vector< uint8_t > &tile_data)
void CheckForOverworldEdits()
Check for changes to the overworld map.
absl::Status LoadGraphics()
Load the Bitmap objects for each OverworldMap.
void DrawToolset()
Toolset for entrances, exits, items, sprites, and transports.
void DrawOverworldMapSettings()
Draws the overworld map settings. Graphics, palettes, etc.
absl::Status SetCurrentTile(int id)
absl::Status InitBlockset(const gfx::Bitmap &tile16_blockset_bmp, const gfx::Bitmap &current_gfx_bmp, const std::vector< gfx::Bitmap > &tile16_individual, uint8_t all_tiles_types[0x200])
Represents a bitmap image.
Definition bitmap.h:67
absl::Status ApplyPalette(const SnesPalette &palette)
Copy color data from the SnesPalette into the SDL_Palette.
Definition bitmap.cc:327
void WriteToPixel(int position, uchar value)
Definition bitmap.h:134
void set_modified(bool modified)
Definition bitmap.h:191
bool DrawTileSelector(int size)
Definition canvas.cc:340
void DrawOutline(int x, int y, int w, int h)
Definition canvas.cc:511
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0), bool drag=false)
Definition canvas.cc:66
void DrawRect(int x, int y, int w, int h, ImVec4 color)
Definition canvas.cc:602
void UpdateInfoGrid(ImVec2 bg_size, int tile_size, float scale=1.0f, float grid_size=64.0f, int label_id=0)
Definition canvas.cc:58
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
Definition canvas.cc:686
void DrawBitmapGroup(std::vector< int > &group, std::vector< gfx::Bitmap > &tile16_individual_, int tile_size, float scale=1.0f)
Definition canvas.cc:536
auto draw_list() const
Definition canvas.h:156
void DrawText(std::string text, int x, int y)
Definition canvas.cc:615
auto hover_mouse_pos() const
Definition canvas.h:198
void DrawBitmap(const Bitmap &bitmap, int border_offset=0, bool ready=true)
Definition canvas.cc:461
auto set_draggable(bool value)
Definition canvas.h:167
auto selected_tile_pos() const
Definition canvas.h:193
auto selected_points() const
Definition canvas.h:196
auto mutable_labels(int i)
Definition canvas.h:175
void DrawSelectRect(int current_map, int tile_size=0x10, float scale=1.0f)
Definition canvas.cc:373
auto zero_point() const
Definition canvas.h:157
auto drawn_tile_position() const
Definition canvas.h:159
auto set_selected_tile_pos(ImVec2 pos)
Definition canvas.h:194
auto points() const
Definition canvas.h:153
auto global_scale() const
Definition canvas.h:162
bool DrawTilePainter(const Bitmap &bitmap, int size, float scale=1.0f)
Definition canvas.cc:206
auto selected_tiles() const
Definition canvas.h:190
bool select_rect_active() const
Definition canvas.h:195
void DrawContextMenu(gfx::Bitmap *bitmap=nullptr)
Definition canvas.cc:101
auto set_highlight_tile_id(int i)
Definition canvas.h:188
auto scrolling() const
Definition canvas.h:158
OWBlockset & GetMapTiles(int world_type)
Definition overworld.h:511
std::vector< gfx::Tile16 > tiles16() const
Definition overworld.h:529
int GetTileFromPosition(ImVec2 position) const
Definition overworld.h:501
#define PRINT_IF_ERROR(expression)
Definition constants.h:36
unsigned int uint
Definition constants.h:113
#define RETURN_IF_ERROR(expression)
Definition constants.h:62
#define NEXT_COLUMN()
Definition constants.h:27
#define TEXT_COLUMN(w)
Definition constants.h:16
#define HOVER_HINT(string)
Definition constants.h:33
#define ICON_MD_GRID_VIEW
Definition icons.h:895
#define ICON_MD_MORE_VERT
Definition icons.h:1241
#define ICON_MD_DRAW
Definition icons.h:623
#define ICON_MD_ZOOM_OUT
Definition icons.h:2191
#define ICON_MD_OPEN_IN_FULL
Definition icons.h:1351
#define ICON_MD_TABLE_CHART
Definition icons.h:1928
#define ICON_MD_REDO
Definition icons.h:1568
#define ICON_MD_GRASS
Definition icons.h:889
#define ICON_MD_DOOR_BACK
Definition icons.h:610
#define ICON_MD_MUSIC_NOTE
Definition icons.h:1262
#define ICON_MD_DOOR_FRONT
Definition icons.h:611
#define ICON_MD_ADD_LOCATION
Definition icons.h:98
#define ICON_MD_ZOOM_IN
Definition icons.h:2189
#define ICON_MD_PEST_CONTROL_RODENT
Definition icons.h:1428
#define ICON_MD_CONTENT_COPY
Definition icons.h:463
#define ICON_MD_UNDO
Definition icons.h:2034
#define ICON_MD_PAN_TOOL_ALT
Definition icons.h:1370
void CopyImageToClipboard(const std::vector< uint8_t > &data)
Definition clipboard.cc:10
std::string UppercaseHexByte(uint8_t byte, bool leading)
Definition common.cc:103
constexpr uint kOverworldMapSize
constexpr absl::string_view kTileSelectorTab
void DrawSpriteInserterPopup()
Definition entity.cc:431
constexpr absl::string_view kOWMapTable
bool IsMouseHoveringOverEntity(const zelda3::GameEntity &entity, ImVec2 canvas_p0, ImVec2 scrolling)
Definition entity.cc:21
constexpr std::array< const char *, 8 > kMapSettingsColumnNames
bool DrawEntranceInserterPopup()
Definition entity.cc:105
bool DrawExitEditorPopup(zelda3::overworld::OverworldExit &exit)
Definition entity.cc:181
constexpr ImGuiTableFlags kOWMapFlags
constexpr absl::string_view kGamePartComboString
bool DrawOverworldEntrancePopup(zelda3::overworld::OverworldEntrance &entrance)
Definition entity.cc:130
bool DrawSpriteEditorPopup(zelda3::Sprite &sprite)
Definition entity.cc:455
constexpr int kTile16Size
void DrawItemInsertPopup()
Definition entity.cc:313
void DrawExitInserterPopup()
Definition entity.cc:163
constexpr ImGuiTableFlags kOWEditFlags
constexpr ImGuiTableFlags kToolsetTableFlags
constexpr absl::string_view kWorldList
void HandleEntityDragging(zelda3::GameEntity *entity, ImVec2 canvas_p0, ImVec2 scrolling, bool &is_dragging_entity, zelda3::GameEntity *&dragged_entity, zelda3::GameEntity *&current_entity, bool free_movement)
Definition entity.cc:56
bool DrawItemEditorPopup(zelda3::overworld::OverworldItem &item)
Definition entity.cc:344
constexpr float kInputFieldSize
Definition entity.cc:19
absl::Status DisplayPalette(gfx::SnesPalette &palette, bool loaded)
Node Parse(const std::string &yazon_input, const std::map< std::string, void * > &data_bindings)
Parse a zeml string.
Definition zeml.cc:360
void Bind(Node *node, std::function< void()> callback)
Bind a callback to a node.
Definition zeml.cc:567
void Render(Node &node)
Render a zeml tree.
Definition zeml.cc:381
std::string LoadFile(const std::string &filename)
Definition zeml.cc:590
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
Definition input.cc:175
void EndPadding()
Definition style.cc:40
void BeginChildWithScrollbar(const char *str_id)
Definition style.cc:48
void BeginPadding(int i)
Definition style.cc:36
void BeginWindowWithDisplaySettings(const char *id, bool *active, const ImVec2 &size, ImGuiWindowFlags flags)
Definition style.cc:11
void BeginChildBothScrollbars(int id)
Definition style.cc:53
void EndNoPadding()
Definition style.cc:46
bool InputHexWord(const char *label, uint16_t *data, float input_width, bool no_step)
Definition input.cc:161
void BeginNoPadding()
Definition style.cc:42
void EndWindowWithDisplaySettings()
Definition style.cc:31
constexpr int kNumTile16Individual
Definition overworld.h:447
constexpr int kNumOverworldMaps
Definition overworld.h:446
const std::vector< std::string > kSecretItemNames
Definition overworld.h:39
Definition common.cc:22
Node * GetNode(const std::string &searchId)
Definition zeml.h:133