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 <unordered_map>
5#include <vector>
6
7#include "absl/status/status.h"
8#include "absl/strings/str_format.h"
14#include "app/gfx/bitmap.h"
16#include "app/gui/canvas.h"
17#include "app/gui/icons.h"
18#include "app/gui/input.h"
19#include "app/gui/style.h"
20#include "app/gui/zeml.h"
21#include "app/rom.h"
23#include "imgui/imgui.h"
24
25namespace yaze {
26namespace app {
27namespace editor {
28
29using core::Renderer;
30
31using ImGui::BeginChild;
32using ImGui::BeginTabBar;
33using ImGui::BeginTabItem;
34using ImGui::BeginTable;
35using ImGui::BeginTooltip;
36using ImGui::Button;
37using ImGui::Checkbox;
38using ImGui::EndChild;
39using ImGui::EndTabBar;
40using ImGui::EndTabItem;
41using ImGui::EndTable;
42using ImGui::EndTooltip;
43using ImGui::IsItemHovered;
44using ImGui::NewLine;
45using ImGui::PopStyleColor;
46using ImGui::PushStyleColor;
47using ImGui::SameLine;
48using ImGui::Selectable;
49using ImGui::Separator;
50using ImGui::TableHeadersRow;
51using ImGui::TableNextColumn;
52using ImGui::TableNextRow;
53using ImGui::TableSetupColumn;
54using ImGui::Text;
55
56constexpr int kTile16Size = 0x10;
57
59 status_ = absl::OkStatus();
60 if (rom()->is_loaded() && !all_gfx_loaded_) {
65 all_gfx_loaded_ = true;
66 }
67
70 }
71
72 // Draw the overworld editor layout from the ZEML file
74 return status_;
75}
76
78 static bool use_work_area = true;
79 static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration |
80 ImGuiWindowFlags_NoMove |
81 ImGuiWindowFlags_NoSavedSettings;
82 const ImGuiViewport *viewport = ImGui::GetMainViewport();
83 ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos);
84 ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size);
85 if (ImGui::Begin("Fullscreen Overworld Editor", &overworld_canvas_fullscreen_,
86 flags)) {
87 // Draws the toolset for editing the Overworld.
90 }
91 ImGui::End();
92}
93
95 static bool show_gfx_group = false;
96 static bool show_properties = false;
97
98 if (BeginTable("OWToolset", 22, kToolsetTableFlags, ImVec2(0, 0))) {
99 for (const auto &name : kToolsetColumnNames)
100 ImGui::TableSetupColumn(name.data());
101
103 if (Button(ICON_MD_UNDO)) {
104 status_ = Undo();
105 }
106
108 if (Button(ICON_MD_REDO)) {
109 status_ = Redo();
110 }
111
112 TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
113
115 if (Button(ICON_MD_ZOOM_OUT)) {
117 }
118
120 if (Button(ICON_MD_ZOOM_IN)) {
122 }
123
125 if (Button(ICON_MD_OPEN_IN_FULL)) {
127 }
128 HOVER_HINT("Fullscreen Canvas")
129
130 TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
131
136 }
137 HOVER_HINT("Pan (Right click and drag)")
138
142 }
143 HOVER_HINT("Draw Tile")
144
148 HOVER_HINT("Entrances")
149
153 HOVER_HINT("Exits")
154
158 HOVER_HINT("Items")
159
161 if (Selectable(ICON_MD_PEST_CONTROL_RODENT,
164 HOVER_HINT("Sprites")
165
167 if (Selectable(ICON_MD_ADD_LOCATION,
170 HOVER_HINT("Transports")
171
175 HOVER_HINT("Music")
176
177 TableNextColumn();
178 if (Button(ICON_MD_GRID_VIEW)) {
180 }
181 HOVER_HINT("Tile16 Editor")
182
183 TableNextColumn();
184 if (Button(ICON_MD_TABLE_CHART)) {
185 show_gfx_group = !show_gfx_group;
186 }
187 HOVER_HINT("Gfx Group Editor")
188
189 TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
190
191 TableNextColumn();
192 if (Button(ICON_MD_CONTENT_COPY)) {
193 std::vector<uint8_t> png_data;
194 if (gfx::ConvertSurfaceToPNG(maps_bmp_[current_map_].surface(),
195 png_data)) {
197 } else {
198 status_ = absl::InternalError(
199 "Failed to convert overworld map surface to PNG");
200 }
201 }
202 HOVER_HINT("Copy Map to Clipboard");
203
204 TableNextColumn(); // Palette
206
207 TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
208
209 TableNextColumn();
210 Checkbox("Properties", &show_properties);
211
212 ImGui::EndTable();
213 }
214
216 // Create a table in ImGui for the Tile16 Editor
217 ImGui::Begin("Tile16 Editor", &show_tile16_editor_,
218 ImGuiWindowFlags_MenuBar);
220 ImGui::End();
221 }
222
223 if (show_gfx_group) {
224 gui::BeginWindowWithDisplaySettings("Gfx Group Editor", &show_gfx_group);
227 }
228
229 if (show_properties) {
230 ImGui::Begin("Properties", &show_properties);
232 ImGui::End();
233 }
234
235 // TODO: Customizable shortcuts for the Overworld Editor
236 if (!ImGui::IsAnyItemActive()) {
237 if (ImGui::IsKeyDown(ImGuiKey_1)) {
239 } else if (ImGui::IsKeyDown(ImGuiKey_2)) {
241 } else if (ImGui::IsKeyDown(ImGuiKey_3)) {
243 } else if (ImGui::IsKeyDown(ImGuiKey_4)) {
245 } else if (ImGui::IsKeyDown(ImGuiKey_5)) {
247 } else if (ImGui::IsKeyDown(ImGuiKey_6)) {
249 } else if (ImGui::IsKeyDown(ImGuiKey_7)) {
251 } else if (ImGui::IsKeyDown(ImGuiKey_8)) {
253 }
254 }
255}
256
257constexpr std::array<const char *, 8> kMapSettingsColumnNames = {
258 "##WorldId", "##GfxId", "##PalId", "##SprGfxId",
259 "##5thCol", "##6thCol", "##7thCol", "##8thCol"};
260
262 if (BeginTable(kOWMapTable.data(), 8, kOWMapFlags, ImVec2(0, 0), -1)) {
263 for (const auto &name : kMapSettingsColumnNames)
264 ImGui::TableSetupColumn(name);
265
266 TableNextColumn();
267 ImGui::SetNextItemWidth(120.f);
268 ImGui::Combo("##world", &current_world_, kWorldList.data(), 3);
269
270 TableNextColumn();
271 ImGui::BeginGroup();
272 if (gui::InputHexByte("Gfx",
274 ->mutable_area_graphics(),
278 }
279 ImGui::EndGroup();
280
281 TableNextColumn();
282 ImGui::BeginGroup();
283 if (gui::InputHexByte("Palette",
285 ->mutable_area_palette(),
290 }
291 ImGui::EndGroup();
292
293 TableNextColumn();
294 ImGui::BeginGroup();
295 gui::InputHexByte("Spr Gfx",
297 ->mutable_sprite_graphics(game_state_),
299 ImGui::EndGroup();
300
301 TableNextColumn();
302 ImGui::BeginGroup();
303 gui::InputHexByte("Spr Palette",
305 ->mutable_sprite_palette(game_state_),
307 ImGui::EndGroup();
308
309 TableNextColumn();
310 ImGui::BeginGroup();
312 "Msg Id",
313 overworld_.mutable_overworld_map(current_map_)->mutable_message_id(),
314 kInputFieldSize + 20);
315 ImGui::EndGroup();
316
317 TableNextColumn();
318 ImGui::SetNextItemWidth(100.f);
319 ImGui::Combo("##World", &game_state_, kGamePartComboString.data(), 3);
320
321 TableNextColumn();
322 ImGui::Checkbox(
323 "##mosaic",
325 HOVER_HINT("Enable Mosaic effect for the current map");
326
327 ImGui::EndTable();
328 }
329}
330
332 if (BeginTable(kOWMapTable.data(), 15, kOWMapFlags, ImVec2(0, 0), -1)) {
333 for (const auto &name : kMapSettingsColumnNames)
334 ImGui::TableSetupColumn(name);
335
336 TableNextColumn();
337 ImGui::SetNextItemWidth(120.f);
338 ImGui::Combo("##world", &current_world_, kWorldList.data(), 3);
339
340 static const std::array<std::string, 8> kCustomMapSettingsColumnNames = {
341 "TileGfx0", "TileGfx1", "TileGfx2", "TileGfx3",
342 "TileGfx4", "TileGfx5", "TileGfx6", "TileGfx7"};
343 for (int i = 0; i < 8; ++i) {
344 TableNextColumn();
345 ImGui::BeginGroup();
346 if (gui::InputHexByte(kCustomMapSettingsColumnNames[i].data(),
348 ->mutable_custom_tileset(i),
352 }
353 ImGui::EndGroup();
354 }
355
356 TableNextColumn();
357 ImGui::BeginGroup();
358 if (gui::InputHexByte("Palette",
360 ->mutable_area_palette(),
365 }
366 ImGui::EndGroup();
367
368 TableNextColumn();
369 ImGui::BeginGroup();
370 gui::InputHexByte("Spr Gfx",
372 ->mutable_sprite_graphics(game_state_),
374 ImGui::EndGroup();
375
376 TableNextColumn();
377 ImGui::BeginGroup();
378 gui::InputHexByte("Spr Palette",
380 ->mutable_sprite_palette(game_state_),
382 ImGui::EndGroup();
383
384 TableNextColumn();
385 ImGui::BeginGroup();
387 "Msg Id",
388 overworld_.mutable_overworld_map(current_map_)->mutable_message_id(),
389 kInputFieldSize + 20);
390 ImGui::EndGroup();
391
392 TableNextColumn();
393 ImGui::SetNextItemWidth(100.f);
394 ImGui::Combo("##World", &game_state_, kGamePartComboString.data(), 3);
395
396 TableNextColumn();
397 ImGui::Checkbox(
398 "##mosaic",
400 HOVER_HINT("Enable Mosaic effect for the current map");
401
402 ImGui::EndTable();
403 }
404}
405
407 int xx = 0;
408 int yy = 0;
409 for (int i = 0; i < 0x40; i++) {
410 int world_index = i + (current_world_ * 0x40);
411 int map_x = (xx * kOverworldMapSize * ow_map_canvas_.global_scale());
412 int map_y = (yy * kOverworldMapSize * ow_map_canvas_.global_scale());
413 ow_map_canvas_.DrawBitmap(maps_bmp_[world_index], map_x, map_y,
415 xx++;
416 if (xx >= 8) {
417 yy++;
418 xx = 0;
419 }
420 }
421}
422
424 // Determine which overworld map the user is currently editing.
425 auto mouse_position = ow_map_canvas_.drawn_tile_position();
426 int map_x = mouse_position.x / kOverworldMapSize;
427 int map_y = mouse_position.y / kOverworldMapSize;
428 current_map_ = map_x + map_y * 8;
429 if (current_world_ == 1) {
430 current_map_ += 0x40;
431 } else if (current_world_ == 2) {
432 current_map_ += 0x80;
433 }
434
435 // Render the updated map bitmap.
436 RenderUpdatedMapBitmap(mouse_position,
438
439 // Calculate the correct superX and superY values
440 int superY = current_map_ / 8;
441 int superX = current_map_ % 8;
442 int mouse_x = mouse_position.x;
443 int mouse_y = mouse_position.y;
444 // Calculate the correct tile16_x and tile16_y positions
445 int tile16_x = (mouse_x % kOverworldMapSize) / (kOverworldMapSize / 32);
446 int tile16_y = (mouse_y % kOverworldMapSize) / (kOverworldMapSize / 32);
447
448 // Update the overworld_.map_tiles() based on tile16 ID and current world
449 auto &selected_world =
450 (current_world_ == 0) ? overworld_.mutable_map_tiles()->light_world
451 : (current_world_ == 1) ? overworld_.mutable_map_tiles()->dark_world
452 : overworld_.mutable_map_tiles()->special_world;
453
454 int index_x = superX * 32 + tile16_x;
455 int index_y = superY * 32 + tile16_y;
456
457 selected_world[index_x][index_y] = current_tile16_;
458}
459
461 const ImVec2 &click_position, const std::vector<uint8_t> &tile_data) {
462 // Calculate the tile index for x and y based on the click_position
463 int tile_index_x =
464 (static_cast<int>(click_position.x) % kOverworldMapSize) / kTile16Size;
465 int tile_index_y =
466 (static_cast<int>(click_position.y) % kOverworldMapSize) / kTile16Size;
467
468 // Calculate the pixel start position based on tile index and tile size
469 ImVec2 start_position;
470 start_position.x = tile_index_x * kTile16Size;
471 start_position.y = tile_index_y * kTile16Size;
472
473 // Update the bitmap's pixel data based on the start_position and tile_data
474 gfx::Bitmap &current_bitmap = maps_bmp_[current_map_];
475 for (int y = 0; y < kTile16Size; ++y) {
476 for (int x = 0; x < kTile16Size; ++x) {
477 int pixel_index =
478 (start_position.y + y) * kOverworldMapSize + (start_position.x + x);
479 current_bitmap.WriteToPixel(pixel_index, tile_data[y * kTile16Size + x]);
480 }
481 }
482
483 current_bitmap.set_modified(true);
484}
485
488
489 // User has selected a tile they want to draw from the blockset.
490 if (!blockset_canvas_.points().empty() &&
492 // Left click is pressed
494 kTile16Size)) {
496 }
497 }
498
500 if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) ||
501 ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
502 auto &selected_world =
503 (current_world_ == 0) ? overworld_.mutable_map_tiles()->light_world
504 : (current_world_ == 1)
505 ? overworld_.mutable_map_tiles()->dark_world
506 : overworld_.mutable_map_tiles()->special_world;
507 // new_start_pos and new_end_pos
508 auto start = ow_map_canvas_.selected_points()[0];
509 auto end = ow_map_canvas_.selected_points()[1];
510
511 // Calculate the bounds of the rectangle in terms of 16x16 tile indices
512 int start_x = std::floor(start.x / kTile16Size) * kTile16Size;
513 int start_y = std::floor(start.y / kTile16Size) * kTile16Size;
514 int end_x = std::floor(end.x / kTile16Size) * kTile16Size;
515 int end_y = std::floor(end.y / kTile16Size) * kTile16Size;
516
517 if (start_x > end_x) std::swap(start_x, end_x);
518 if (start_y > end_y) std::swap(start_y, end_y);
519
520 constexpr int local_map_size = 512; // Size of each local map
521 // Number of tiles per local map (since each tile is 16x16)
522 constexpr int tiles_per_local_map = local_map_size / kTile16Size;
523
524 for (int y = start_y, i = 0; y <= end_y; y += kTile16Size) {
525 for (int x = start_x; x <= end_x; x += kTile16Size, ++i) {
526 // Determine which local map (512x512) the tile is in
527 int local_map_x = x / local_map_size;
528 int local_map_y = y / local_map_size;
529
530 // Calculate the tile's position within its local map
531 int tile16_x = (x % local_map_size) / kTile16Size;
532 int tile16_y = (y % local_map_size) / kTile16Size;
533
534 // Calculate the index within the overall map structure
535 int index_x = local_map_x * tiles_per_local_map + tile16_x;
536 int index_y = local_map_y * tiles_per_local_map + tile16_y;
537 int tile16_id = overworld_.GetTileFromPosition(
539 selected_world[index_x][index_y] = tile16_id;
540 }
541 }
542
544 }
545 }
546}
547
550
551 // Single tile case
552 if (ow_map_canvas_.selected_tile_pos().x != -1) {
556 }
557
558 static std::vector<int> tile16_ids;
560 // Get the tile16 IDs from the selected tile ID positions
561 if (tile16_ids.size() != 0) {
562 tile16_ids.clear();
563 }
564
565 if (ow_map_canvas_.selected_tiles().size() > 0) {
566 for (auto &each : ow_map_canvas_.selected_tiles()) {
567 tile16_ids.push_back(overworld_.GetTileFromPosition(each));
568 }
569 }
570 }
571 // Create a composite image of all the tile16s selected
573}
574
576 // 4096x4096, 512x512 maps and some are larges maps 1024x1024
577 const auto mouse_position = ImGui::GetIO().MousePos;
578 const int large_map_size = 1024;
579 const auto canvas_zero_point = ow_map_canvas_.zero_point();
580
581 // Calculate which small map the mouse is currently over
582 int map_x = (mouse_position.x - canvas_zero_point.x) / kOverworldMapSize;
583 int map_y = (mouse_position.y - canvas_zero_point.y) / kOverworldMapSize;
584
585 // Calculate the index of the map in the `maps_bmp_` vector
586 current_map_ = map_x + map_y * 8;
587 const int current_highlighted_map = current_map_;
588 if (current_world_ == 1) {
589 current_map_ += 0x40;
590 } else if (current_world_ == 2) {
591 current_map_ += 0x80;
592 }
593
595
596 if (overworld_.overworld_map(current_map_)->is_large_map() ||
597 overworld_.overworld_map(current_map_)->large_index() != 0) {
598 const int highlight_parent =
599 overworld_.overworld_map(current_highlighted_map)->parent();
600 const int parent_map_x = highlight_parent % 8;
601 const int parent_map_y = highlight_parent / 8;
603 parent_map_y * kOverworldMapSize, large_map_size,
604 large_map_size);
605 } else {
606 const int current_map_x = current_highlighted_map % 8;
607 const int current_map_y = current_highlighted_map / 8;
609 current_map_y * kOverworldMapSize,
611 }
612
613 if (maps_bmp_[current_map_].modified() ||
614 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
618 maps_bmp_[current_map_].set_modified(false);
619 }
620
621 return absl::OkStatus();
622}
623
625 if (ImGui::IsMouseDragging(ImGuiMouseButton_Middle)) {
630 }
631 if (ImGui::IsMouseReleased(ImGuiMouseButton_Middle) &&
636 }
637}
638
640 if (all_gfx_loaded_) {
641 if (flags()->overworld.kLoadCustomOverworld) {
643 } else {
645 }
646 Separator();
647 }
648
653
657 } else {
659 }
660
661 if (overworld_.is_loaded()) {
670 }
671 if (IsItemHovered()) status_ = CheckForCurrentMap();
672 }
673
676 EndChild();
677
678 // Handle mouse wheel activity
679 if (ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows) &&
680 ImGui::IsMouseDragging(ImGuiMouseButton_Middle)) {
681 ImGui::SetScrollX(ImGui::GetScrollX() + ImGui::GetIO().MouseWheelH * 16.0f);
682 ImGui::SetScrollY(ImGui::GetScrollY() + ImGui::GetIO().MouseWheel * 16.0f);
683 }
684}
685
688 ImGui::BeginGroup();
689 gui::BeginChildWithScrollbar("##Tile16SelectorScrollRegion");
692 {
696
698 // Open the tile16 editor to the tile
699 auto tile_pos = blockset_canvas_.points().front();
700 int grid_x = static_cast<int>(tile_pos.x / 32);
701 int grid_y = static_cast<int>(tile_pos.y / 32);
702 int id = grid_x + grid_y * 8;
704 show_tile16_editor_ = true;
705 }
706
707 if (ImGui::IsItemClicked() && !blockset_canvas_.points().empty()) {
708 int x = blockset_canvas_.points().front().x / 32;
709 int y = blockset_canvas_.points().front().y / 32;
710 current_tile16_ = x + (y * 8);
711 }
712
715 }
716 EndChild();
717 ImGui::EndGroup();
718 return absl::OkStatus();
719}
720
724 if (all_gfx_loaded_) {
725 int key = 0;
726 for (auto &value : rom()->gfx_sheets()) {
727 int offset = 0x40 * (key + 1);
728 int top_left_y = graphics_bin_canvas_.zero_point().y + 2;
729 if (key >= 1) {
730 top_left_y = graphics_bin_canvas_.zero_point().y + 0x40 * key;
731 }
732 auto texture = value.texture();
734 (void *)texture,
735 ImVec2(graphics_bin_canvas_.zero_point().x + 2, top_left_y),
736 ImVec2(graphics_bin_canvas_.zero_point().x + 0x100,
737 graphics_bin_canvas_.zero_point().y + offset));
738 key++;
739 }
740 }
743}
744
746 if (overworld_.is_loaded() &&
750 gfx::Bitmap bmp;
751 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
753 palette_));
755 }
756
758 ImGui::BeginGroup();
759 gui::BeginChildWithScrollbar("##AreaGraphicsScrollRegion");
762 {
765 /*border_offset=*/2, overworld_.is_loaded());
769 }
770 EndChild();
771 ImGui::EndGroup();
772 return absl::OkStatus();
773}
774
776 if (BeginTabBar(kTileSelectorTab.data(),
777 ImGuiTabBarFlags_FittingPolicyScroll)) {
778 if (BeginTabItem("Tile16")) {
780 EndTabItem();
781 }
782 if (BeginTabItem("Tile8")) {
784 gui::BeginChildWithScrollbar("##Tile8SelectorScrollRegion");
786 EndChild();
788 EndTabItem();
789 }
790 if (BeginTabItem("Area Graphics")) {
792 EndTabItem();
793 }
794 EndTabBar();
795 }
796 return absl::OkStatus();
797}
798
799void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
800 bool holes) {
801 int i = 0;
802 for (auto &each : overworld_.entrances()) {
803 if (each.map_id_ < 0x40 + (current_world_ * 0x40) &&
804 each.map_id_ >= (current_world_ * 0x40) && !each.deleted) {
805 auto color = ImVec4(255, 255, 0, 100);
806 if (each.is_hole_) {
807 color = ImVec4(255, 255, 255, 200);
808 }
809 ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16, color);
810 std::string str = core::UppercaseHexByte(each.entrance_id_);
811
813 HandleEntityDragging(&each, canvas_p0, scrolling, is_dragging_entity_,
815
816 if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
817 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
818 jump_to_tab_ = each.entrance_id_;
819 }
820
821 if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
822 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
824 current_entrance_ = each;
825 }
826 }
827
828 ow_map_canvas_.DrawText(str, each.x_, each.y_);
829 }
830 i++;
831 }
832
834 // Get the deleted entrance ID and insert it at the mouse position
835 auto deleted_entrance_id = overworld_.deleted_entrances().back();
836 overworld_.deleted_entrances().pop_back();
837 auto &entrance = overworld_.entrances()[deleted_entrance_id];
838 entrance.map_id_ = current_map_;
839 entrance.entrance_id_ = deleted_entrance_id;
840 entrance.x_ = ow_map_canvas_.hover_mouse_pos().x;
841 entrance.y_ = ow_map_canvas_.hover_mouse_pos().y;
842 entrance.deleted = false;
843 }
844
846 const auto is_hovering =
847 IsMouseHoveringOverEntity(current_entrance_, canvas_p0, scrolling);
848
849 if (!is_hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
850 ImGui::OpenPopup("Entrance Inserter");
851 } else {
855 }
856
860 }
861 }
862 }
863}
864
865void OverworldEditor::DrawOverworldExits(ImVec2 canvas_p0, ImVec2 scrolling) {
866 int i = 0;
867 for (auto &each : *overworld_.mutable_exits()) {
868 if (each.map_id_ < 0x40 + (current_world_ * 0x40) &&
869 each.map_id_ >= (current_world_ * 0x40) && !each.deleted_) {
870 ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16,
871 ImVec4(255, 255, 255, 150));
873 each.entity_id_ = i;
877
878 if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
879 ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
880 jump_to_tab_ = each.room_id_;
881 }
882
883 if (IsMouseHoveringOverEntity(each, canvas_p0, scrolling) &&
884 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
886 current_exit_ = each;
887 current_entity_ = &each;
889 ImGui::OpenPopup("Exit editor");
890 }
891 }
892
893 std::string str = core::UppercaseHexByte(i);
894 ow_map_canvas_.DrawText(str, each.x_, each.y_);
895 }
896 i++;
897 }
898
901 const auto hovering = IsMouseHoveringOverEntity(
904
905 if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
906 ImGui::OpenPopup("Exit Inserter");
907 } else {
911 }
912 }
913 }
914}
915
917 int i = 0;
918 for (auto &item : *overworld_.mutable_all_items()) {
919 // Get the item's bitmap and real X and Y positions
920 if (item.room_map_id_ < 0x40 + (current_world_ * 0x40) &&
921 item.room_map_id_ >= (current_world_ * 0x40) && !item.deleted) {
922 ow_map_canvas_.DrawRect(item.x_, item.y_, 16, 16, ImVec4(255, 0, 0, 150));
923
925 // Check if this item is being clicked and dragged
929
930 const auto hovering = IsMouseHoveringOverEntity(
932 if (hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
934 current_item_ = item;
935 current_entity_ = &item;
936 }
937 }
938 std::string item_name = "";
939 if (item.id_ < zelda3::overworld::kSecretItemNames.size()) {
940 item_name = zelda3::overworld::kSecretItemNames[item.id_];
941 } else {
942 item_name = absl::StrFormat("0x%02X", item.id_);
943 }
944 ow_map_canvas_.DrawText(item_name, item.x_, item.y_);
945 }
946 i++;
947 }
948
951 const auto hovering = IsMouseHoveringOverEntity(
954
955 if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
956 ImGui::OpenPopup("Item Inserter");
957 } else {
961 }
962 }
963 }
964}
965
967 int i = 0;
968 for (auto &sprite : *overworld_.mutable_sprites(game_state_)) {
969 if (!sprite.deleted()) {
970 // int map_id = sprite.map_id();
971 // map x and map y are relative to the map
972 // So we need to check if the map is large or small then add the offset
973
974 // Calculate the superX and superY values
975 // int superY = map_id / 8;
976 // int superX = map_id % 8;
977
978 // Calculate the map_x and map_y values
979 int map_x = sprite.map_x();
980 int map_y = sprite.map_y();
981
982 // Calculate the actual map_x and map_y values
983 // map_x += superX * 512;
984 // map_y += superY * 512;
985
987 /*magenta*/ ImVec4(255, 0, 255, 150));
994 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
996 current_sprite_ = sprite;
997 }
998 }
999 ow_map_canvas_.DrawText(absl::StrFormat("%s", sprite.name()), map_x,
1000 map_y);
1001 }
1002 i++;
1003 }
1004
1007 const auto hovering = IsMouseHoveringOverEntity(
1010
1011 if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
1012 ImGui::OpenPopup("Sprite Inserter");
1013 } else {
1015 ->at(current_sprite_id_))) {
1018 }
1019 }
1020 }
1021}
1022
1024 if (flags()->overworld.kSaveOverworldMaps) {
1029 }
1030 if (flags()->overworld.kSaveOverworldEntrances) {
1032 }
1033 if (flags()->overworld.kSaveOverworldExits) {
1035 }
1036 if (flags()->overworld.kSaveOverworldItems) {
1038 }
1039 if (flags()->overworld.kSaveOverworldProperties) {
1041 }
1042 return absl::OkStatus();
1043}
1044
1046 // Load the Link to the Past overworld.
1049
1050 // Create the area graphics image
1051 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
1054
1055 // Create the tile16 blockset image
1056 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
1057 0x80, 0x2000, 0x08, overworld_.tile16_blockset_data(),
1059 map_blockset_loaded_ = true;
1060
1061 // Copy the tile16 data into individual tiles.
1062 auto tile16_data = overworld_.tile16_blockset_data();
1064
1065 // Loop through the tiles and copy their pixel data into separate vectors
1066 for (uint i = 0; i < zelda3::overworld::kNumTile16Individual; i++) {
1067 std::vector<uint8_t> tile_data(kTile16Size * kTile16Size, 0x00);
1068
1069 // Copy the pixel data for the current tile into the vector
1070 for (int ty = 0; ty < kTile16Size; ty++) {
1071 for (int tx = 0; tx < kTile16Size; tx++) {
1072 int position = tx + (ty * kTile16Size);
1073 uint8_t value =
1074 tile16_data[(i % 8 * kTile16Size) + (i / 8 * kTile16Size * 0x80) +
1075 (ty * 0x80) + tx];
1076 tile_data[position] = value;
1077 }
1078 }
1079
1080 // Add the vector for the current tile to the vector of tile pixel data
1081 tile16_individual_data_.push_back(tile_data);
1082 tile16_individual_.emplace_back();
1083 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
1086 }
1087
1088 // Render the overworld maps loaded from the ROM.
1089 for (int i = 0; i < zelda3::overworld::kNumOverworldMaps; ++i) {
1091 auto palette = overworld_.current_area_palette();
1092 RETURN_IF_ERROR(Renderer::GetInstance().CreateAndRenderBitmap(
1095 }
1096
1097 if (flags()->overworld.kDrawOverworldSprites) {
1099 }
1100
1101 return absl::OkStatus();
1102}
1103
1105 // Render the sprites for each Overworld map
1106 for (int i = 0; i < 3; i++)
1107 for (auto const &sprite : overworld_.sprites(i)) {
1108 int width = sprite.Width();
1109 int height = sprite.Height();
1110 int depth = 0x40;
1111 auto spr_gfx = sprite.PreviewGraphics();
1112 sprite_previews_[sprite.id()].Create(width, height, depth, spr_gfx);
1113 RETURN_IF_ERROR(sprite_previews_[sprite.id()].ApplyPalette(palette_));
1115 }
1116 return absl::OkStatus();
1117}
1118
1120 overworld_.mutable_overworld_map(map_index)->LoadAreaGraphics();
1121 status_ = overworld_.mutable_overworld_map(map_index)->BuildTileset();
1123 status_ = overworld_.mutable_overworld_map(map_index)->BuildTiles16Gfx(
1126 status_ = overworld_.mutable_overworld_map(map_index)->BuildBitmap(
1128 maps_bmp_[map_index].set_data(
1129 overworld_.mutable_overworld_map(map_index)->bitmap_data());
1130 maps_bmp_[map_index].set_modified(true);
1132}
1133
1135 std::vector<std::future<void>> futures;
1136 int indices[4];
1137
1138 auto refresh_map_async = [this](int map_index) {
1139 RefreshChildMap(map_index);
1140 };
1141
1142 int source_map_id = current_map_;
1143 bool is_large = overworld_.overworld_map(current_map_)->is_large_map();
1144 if (is_large) {
1145 source_map_id = current_parent_;
1146 // We need to update the map and its siblings if it's a large map
1147 for (int i = 1; i < 4; i++) {
1148 int sibling_index = overworld_.overworld_map(source_map_id)->parent() + i;
1149 if (i >= 2) sibling_index += 6;
1150 futures.push_back(
1151 std::async(std::launch::async, refresh_map_async, sibling_index));
1152 indices[i] = sibling_index;
1153 }
1154 }
1155 indices[0] = source_map_id;
1156 futures.push_back(
1157 std::async(std::launch::async, refresh_map_async, source_map_id));
1158
1159 for (auto &each : futures) {
1160 each.get();
1161 }
1162 int n = is_large ? 4 : 1;
1163 // We do texture updating on the main thread
1164 for (int i = 0; i < n; ++i) {
1166 }
1167}
1168
1172 const auto current_map_palette = overworld_.current_area_palette();
1173
1174 if (overworld_.overworld_map(current_map_)->is_large_map()) {
1175 // We need to update the map and its siblings if it's a large map
1176 for (int i = 1; i < 4; i++) {
1177 int sibling_index = overworld_.overworld_map(current_map_)->parent() + i;
1178 if (i >= 2) sibling_index += 6;
1180 overworld_.mutable_overworld_map(sibling_index)->LoadPalette());
1182 maps_bmp_[sibling_index].ApplyPalette(current_map_palette));
1183 }
1184 }
1185
1186 RETURN_IF_ERROR(maps_bmp_[current_map_].ApplyPalette(current_map_palette));
1187 return absl::OkStatus();
1188}
1189
1191 auto &current_ow_map = *overworld_.mutable_overworld_map(current_map_);
1192 if (current_ow_map.is_large_map()) {
1193 // We need to copy the properties from the parent map to the children
1194 for (int i = 1; i < 4; i++) {
1195 int sibling_index = current_ow_map.parent() + i;
1196 if (i >= 2) {
1197 sibling_index += 6;
1198 }
1199 auto &map = *overworld_.mutable_overworld_map(sibling_index);
1200 map.set_area_graphics(current_ow_map.area_graphics());
1201 map.set_area_palette(current_ow_map.area_palette());
1202 map.set_sprite_graphics(game_state_,
1203 current_ow_map.sprite_graphics(game_state_));
1204 map.set_sprite_palette(game_state_,
1205 current_ow_map.sprite_palette(game_state_));
1206 map.set_message_id(current_ow_map.message_id());
1207 }
1208 }
1209}
1210
1212 if (current_blockset_ ==
1213 overworld_.overworld_map(current_map_)->area_graphics()) {
1214 return absl::OkStatus();
1215 }
1217
1220 // Create the tile16 blockset image
1223
1224 // Copy the tile16 data into individual tiles.
1225 const auto tile16_data = overworld_.tile16_blockset_data();
1226
1227 std::vector<std::future<void>> futures;
1228 // Loop through the tiles and copy their pixel data into separate vectors
1229 for (uint i = 0; i < zelda3::overworld::kNumTile16Individual; i++) {
1230 futures.push_back(std::async(
1231 std::launch::async,
1232 [&](int index) {
1233 std::vector<uint8_t> tile_data(16 * 16, 0x00);
1234 for (int ty = 0; ty < 16; ty++) {
1235 for (int tx = 0; tx < 16; tx++) {
1236 int position = tx + (ty * 0x10);
1237 uint8_t value =
1238 tile16_data[(index % 8 * 16) + (index / 8 * 16 * 0x80) +
1239 (ty * 0x80) + tx];
1240 tile_data[position] = value;
1241 }
1242 }
1243 tile16_individual_[index].set_data(tile_data);
1244 },
1245 i));
1246 }
1247
1248 for (auto &future : futures) {
1249 future.get();
1250 }
1251
1252 // Render the bitmaps of each tile.
1253 for (uint id = 0; id < zelda3::overworld::kNumTile16Individual; id++) {
1254 RETURN_IF_ERROR(tile16_individual_[id].ApplyPalette(palette_));
1256 }
1257
1258 return absl::OkStatus();
1259}
1260
1262 static bool init_properties = false;
1263
1264 if (!init_properties) {
1265 for (int i = 0; i < 0x40; i++) {
1266 std::string area_graphics_str = absl::StrFormat(
1267 "%02hX", overworld_.overworld_map(i)->area_graphics());
1269 ->push_back(area_graphics_str);
1270
1271 area_graphics_str = absl::StrFormat(
1272 "%02hX", overworld_.overworld_map(i + 0x40)->area_graphics());
1274 ->push_back(area_graphics_str);
1275
1276 std::string area_palette_str =
1277 absl::StrFormat("%02hX", overworld_.overworld_map(i)->area_palette());
1279 ->push_back(area_palette_str);
1280
1281 area_palette_str = absl::StrFormat(
1282 "%02hX", overworld_.overworld_map(i + 0x40)->area_palette());
1284 ->push_back(area_palette_str);
1285 std::string sprite_gfx_str = absl::StrFormat(
1286 "%02hX", overworld_.overworld_map(i)->sprite_graphics(1));
1288 ->push_back(sprite_gfx_str);
1289
1290 sprite_gfx_str = absl::StrFormat(
1291 "%02hX", overworld_.overworld_map(i)->sprite_graphics(2));
1293 ->push_back(sprite_gfx_str);
1294
1295 sprite_gfx_str = absl::StrFormat(
1296 "%02hX", overworld_.overworld_map(i + 0x40)->sprite_graphics(1));
1298 ->push_back(sprite_gfx_str);
1299
1300 sprite_gfx_str = absl::StrFormat(
1301 "%02hX", overworld_.overworld_map(i + 0x40)->sprite_graphics(2));
1303 ->push_back(sprite_gfx_str);
1304
1305 std::string sprite_palette_str = absl::StrFormat(
1306 "%02hX", overworld_.overworld_map(i)->sprite_palette(1));
1308 ->push_back(sprite_palette_str);
1309
1310 sprite_palette_str = absl::StrFormat(
1311 "%02hX", overworld_.overworld_map(i)->sprite_palette(2));
1313 ->push_back(sprite_palette_str);
1314
1315 sprite_palette_str = absl::StrFormat(
1316 "%02hX", overworld_.overworld_map(i + 0x40)->sprite_palette(1));
1318 ->push_back(sprite_palette_str);
1319
1320 sprite_palette_str = absl::StrFormat(
1321 "%02hX", overworld_.overworld_map(i + 0x40)->sprite_palette(2));
1323 ->push_back(sprite_palette_str);
1324 }
1325 init_properties = true;
1326 }
1327
1328 Text("Area Gfx LW/DW");
1329 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1331 SameLine();
1332 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1334 ImGui::Separator();
1335
1336 Text("Sprite Gfx LW/DW");
1337 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1339 SameLine();
1340 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1342 SameLine();
1343 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1345 SameLine();
1346 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1348 ImGui::Separator();
1349
1350 Text("Area Pal LW/DW");
1351 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1353 SameLine();
1354 properties_canvas_.UpdateInfoGrid(ImVec2(256, 256), 8, 2.0f, 32,
1356
1357 static bool show_gfx_group = false;
1358 Checkbox("Show Gfx Group Editor", &show_gfx_group);
1359 if (show_gfx_group) {
1360 gui::BeginWindowWithDisplaySettings("Gfx Group Editor", &show_gfx_group);
1363 }
1364}
1365
1367 if (BeginTable("UsageStatsTable", 3, kOWEditFlags, ImVec2(0, 0))) {
1368 TableSetupColumn("Entrances");
1369 TableSetupColumn("Grid", ImGuiTableColumnFlags_WidthStretch,
1370 ImGui::GetContentRegionAvail().x);
1371 TableSetupColumn("Usage", ImGuiTableColumnFlags_WidthFixed, 256);
1372 TableHeadersRow();
1373 TableNextRow();
1374
1375 TableNextColumn();
1376 if (BeginChild("UnusedSpritesetScroll", ImVec2(0, 0), true,
1377 ImGuiWindowFlags_HorizontalScrollbar)) {
1378 for (int i = 0; i < 0x81; i++) {
1379 auto entrance_name = rom()->resource_label()->GetLabel(
1380 "Dungeon Entrance Names", core::UppercaseHexByte(i));
1381 std::string str = absl::StrFormat("%#x - %s", i, entrance_name);
1382 if (Selectable(str.c_str(), selected_entrance_ == i,
1383 overworld_.entrances().at(i).deleted
1384 ? ImGuiSelectableFlags_Disabled
1385 : 0)) {
1387 selected_usage_map_ = overworld_.entrances().at(i).map_id_;
1389 }
1390 if (IsItemHovered()) {
1391 BeginTooltip();
1392 Text("Entrance ID: %d", i);
1393 Text("Map ID: %d", overworld_.entrances().at(i).map_id_);
1394 Text("Entrance ID: %d", overworld_.entrances().at(i).entrance_id_);
1395 Text("X: %d", overworld_.entrances().at(i).x_);
1396 Text("Y: %d", overworld_.entrances().at(i).y_);
1397 Text("Deleted? %s",
1398 overworld_.entrances().at(i).deleted ? "Yes" : "No");
1399 EndTooltip();
1400 }
1401 }
1402 EndChild();
1403 }
1404
1405 TableNextColumn();
1406 DrawUsageGrid();
1407
1408 TableNextColumn();
1410
1411 EndTable();
1412 }
1413 return absl::OkStatus();
1414}
1415
1417 // Create a grid of 8x8 squares
1418 int totalSquares = 128;
1419 int squaresWide = 8;
1420 int squaresTall = (totalSquares + squaresWide - 1) /
1421 squaresWide; // Ceiling of totalSquares/squaresWide
1422
1423 // Loop through each row
1424 for (int row = 0; row < squaresTall; ++row) {
1425 NewLine();
1426
1427 for (int col = 0; col < squaresWide; ++col) {
1428 if (row * squaresWide + col >= totalSquares) {
1429 break;
1430 }
1431 // Determine if this square should be highlighted
1432 bool highlight = selected_usage_map_ == (row * squaresWide + col);
1433
1434 // Set highlight color if needed
1435 if (highlight) {
1436 PushStyleColor(
1437 ImGuiCol_Button,
1438 ImVec4(1.0f, 0.5f, 0.0f, 1.0f)); // Or any highlight color
1439 }
1440
1441 // Create a button or selectable for each square
1442 if (Button("##square", ImVec2(20, 20))) {
1443 // Switch over to the room editor tab
1444 // and add a room tab by the ID of the square
1445 // that was clicked
1446 }
1447
1448 // Reset style if it was highlighted
1449 if (highlight) {
1450 PopStyleColor();
1451 }
1452
1453 // Check if the square is hovered
1454 if (IsItemHovered()) {
1455 // Display a tooltip with all the room properties
1456 }
1457
1458 // Keep squares in the same line
1459 SameLine();
1460 }
1461 }
1462}
1463
1465 Text("Current Map: %d", current_map_);
1466 Text("Current Tile16: %d", current_tile16_);
1467 int relative_x = (int)ow_map_canvas_.drawn_tile_position().x % 512;
1468 int relative_y = (int)ow_map_canvas_.drawn_tile_position().y % 512;
1469 Text("Current Tile16 Drawn Position (Relative): %d, %d", relative_x,
1470 relative_y);
1471
1472 // Print the size of the overworld map_tiles per world
1473 Text("Light World Map Tiles: %d",
1474 (int)overworld_.mutable_map_tiles()->light_world.size());
1475 Text("Dark World Map Tiles: %d",
1476 (int)overworld_.mutable_map_tiles()->dark_world.size());
1477 Text("Special World Map Tiles: %d",
1478 (int)overworld_.mutable_map_tiles()->special_world.size());
1479
1480 static bool view_lw_map_tiles = false;
1481 static MemoryEditor mem_edit;
1482 // Let's create buttons which let me view containers in the memory editor
1483 if (Button("View Light World Map Tiles")) {
1484 view_lw_map_tiles = !view_lw_map_tiles;
1485 }
1486
1487 if (view_lw_map_tiles) {
1488 mem_edit.DrawContents(
1489 overworld_.mutable_map_tiles()->light_world[current_map_].data(),
1490 overworld_.mutable_map_tiles()->light_world[current_map_].size());
1491 }
1492}
1493
1495 // Load zeml string from layouts/overworld.zeml
1496 std::string layout = gui::zeml::LoadFile("overworld.zeml");
1497 // Parse the zeml string into a Node object
1499
1500 gui::zeml::Bind(&*layout_node_.GetNode("OverworldCanvas"),
1501 [this]() { DrawOverworldCanvas(); });
1502 gui::zeml::Bind(&*layout_node_.GetNode("OverworldTileSelector"),
1503 [this]() { status_ = DrawTileSelector(); });
1504 gui::zeml::Bind(&*layout_node_.GetNode("OwUsageStats"), [this]() {
1505 if (rom()->is_loaded()) {
1506 status_ = UpdateUsageStats();
1507 }
1508 });
1509 gui::zeml::Bind(&*layout_node_.GetNode("owToolset"),
1510 [this]() { DrawToolset(); });
1511 gui::zeml::Bind(&*layout_node_.GetNode("OwTile16Editor"), [this]() {
1512 if (rom()->is_loaded()) {
1513 status_ = tile16_editor_.Update();
1514 }
1515 });
1516 gui::zeml::Bind(&*layout_node_.GetNode("OwGfxGroupEditor"), [this]() {
1517 if (rom()->is_loaded()) {
1518 status_ = gfx_group_editor_.Update();
1519 }
1520 });
1521}
1522
1523} // namespace editor
1524} // namespace app
1525} // namespace yaze
static Renderer & GetInstance()
Definition renderer.h:30
void RenderBitmap(gfx::Bitmap *bitmap)
Used to render a bitmap to the screen.
Definition renderer.h:52
void UpdateBitmap(gfx::Bitmap *bitmap, bool use_sdl_update=false)
Used to update a bitmap on the screen.
Definition renderer.h:63
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 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:70
absl::Status ApplyPalette(const SnesPalette &palette)
Copy color data from the SnesPalette into the SDL_Palette.
Definition bitmap.cc:346
void WriteToPixel(int position, uchar value)
Definition bitmap.h:141
void set_modified(bool modified)
Definition bitmap.h:198
bool DrawTileSelector(int size)
Definition canvas.cc:343
void DrawOutline(int x, int y, int w, int h)
Definition canvas.cc:514
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0), bool drag=false)
Definition canvas.cc:69
void DrawRect(int x, int y, int w, int h, ImVec4 color)
Definition canvas.cc:605
void UpdateInfoGrid(ImVec2 bg_size, int tile_size, float scale=1.0f, float grid_size=64.0f, int label_id=0)
Definition canvas.cc:61
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
Definition canvas.cc:689
void DrawBitmapGroup(std::vector< int > &group, std::vector< gfx::Bitmap > &tile16_individual_, int tile_size, float scale=1.0f)
Definition canvas.cc:539
auto draw_list() const
Definition canvas.h:146
void DrawText(std::string text, int x, int y)
Definition canvas.cc:618
auto hover_mouse_pos() const
Definition canvas.h:188
void DrawBitmap(const Bitmap &bitmap, int border_offset=0, bool ready=true)
Definition canvas.cc:464
auto set_draggable(bool value)
Definition canvas.h:157
auto selected_tile_pos() const
Definition canvas.h:183
auto selected_points() const
Definition canvas.h:186
auto mutable_labels(int i)
Definition canvas.h:165
void DrawSelectRect(int current_map, int tile_size=0x10, float scale=1.0f)
Definition canvas.cc:376
auto zero_point() const
Definition canvas.h:147
auto drawn_tile_position() const
Definition canvas.h:149
auto set_selected_tile_pos(ImVec2 pos)
Definition canvas.h:184
auto points() const
Definition canvas.h:143
auto global_scale() const
Definition canvas.h:152
bool DrawTilePainter(const Bitmap &bitmap, int size, float scale=1.0f)
Definition canvas.cc:209
auto selected_tiles() const
Definition canvas.h:180
bool select_rect_active() const
Definition canvas.h:185
void DrawContextMenu(gfx::Bitmap *bitmap=nullptr)
Definition canvas.cc:104
auto set_highlight_tile_id(int i)
Definition canvas.h:178
auto scrolling() const
Definition canvas.h:148
OWBlockset & GetMapTiles(int world_type)
Definition overworld.h:495
std::vector< gfx::Tile16 > tiles16() const
Definition overworld.h:513
int GetTileFromPosition(ImVec2 position) const
Definition overworld.h:485
#define PRINT_IF_ERROR(expression)
Definition constants.h:43
unsigned int uint
Definition constants.h:120
#define RETURN_IF_ERROR(expression)
Definition constants.h:69
#define NEXT_COLUMN()
Definition constants.h:34
#define TEXT_COLUMN(w)
Definition constants.h:23
#define HOVER_HINT(string)
Definition constants.h:40
#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 labeling.cc:21
constexpr uint kOverworldMapSize
constexpr absl::string_view kTileSelectorTab
void DrawSpriteInserterPopup()
Definition entity.cc:429
constexpr absl::string_view kOWMapTable
bool IsMouseHoveringOverEntity(const zelda3::GameEntity &entity, ImVec2 canvas_p0, ImVec2 scrolling)
Definition entity.cc:19
constexpr std::array< const char *, 8 > kMapSettingsColumnNames
bool DrawEntranceInserterPopup()
Definition entity.cc:103
bool DrawExitEditorPopup(zelda3::overworld::OverworldExit &exit)
Definition entity.cc:179
constexpr ImGuiTableFlags kOWMapFlags
constexpr absl::string_view kGamePartComboString
bool DrawOverworldEntrancePopup(zelda3::overworld::OverworldEntrance &entrance)
Definition entity.cc:128
bool DrawSpriteEditorPopup(zelda3::Sprite &sprite)
Definition entity.cc:453
constexpr int kTile16Size
void DrawItemInsertPopup()
Definition entity.cc:311
void DrawExitInserterPopup()
Definition entity.cc:161
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:54
bool DrawItemEditorPopup(zelda3::overworld::OverworldItem &item)
Definition entity.cc:342
constexpr float kInputFieldSize
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:361
void Bind(Node *node, std::function< void()> callback)
Bind a callback to a node.
Definition zeml.cc:568
void Render(Node &node)
Render a zeml tree.
Definition zeml.cc:382
std::string LoadFile(const std::string &filename)
Definition zeml.cc:591
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
Definition input.cc:176
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:162
void BeginNoPadding()
Definition style.cc:42
void EndWindowWithDisplaySettings()
Definition style.cc:31
constexpr int kNumTile16Individual
Definition overworld.h:434
constexpr int kNumOverworldMaps
Definition overworld.h:433
const std::vector< std::string > kSecretItemNames
Definition overworld.h:42
Definition common.cc:21
Node * GetNode(const std::string &searchId)
Definition zeml.h:135