7#include "absl/strings/str_format.h"
8#include "absl/strings/string_view.h"
18#include "imgui/imgui.h"
34 if (ImGui::BeginTabBar(
"##ScreenEditorTabBar")) {
35 if (ImGui::BeginTabItem(
"Dungeon Maps")) {
36 if (
rom()->is_loaded()) {
53 static bool create =
false;
54 if (!create &&
rom()->is_loaded()) {
62 if (ImGui::BeginTable(
"InventoryScreen", 3, ImGuiTableFlags_Resizable)) {
63 ImGui::TableSetupColumn(
"Canvas");
64 ImGui::TableSetupColumn(
"Tiles");
65 ImGui::TableSetupColumn(
"Palette");
66 ImGui::TableHeadersRow();
68 ImGui::TableNextColumn();
75 ImGui::TableNextColumn();
82 ImGui::TableNextColumn();
92 if (ImGui::BeginTable(
"InventoryToolset", 8, ImGuiTableFlags_SizingFixedFit,
94 ImGui::TableSetupColumn(
"#drawTool");
95 ImGui::TableSetupColumn(
"#sep1");
96 ImGui::TableSetupColumn(
"#zoomOut");
97 ImGui::TableSetupColumn(
"#zoomIN");
98 ImGui::TableSetupColumn(
"#sep2");
99 ImGui::TableSetupColumn(
"#bg2Tool");
100 ImGui::TableSetupColumn(
"#bg3Tool");
101 ImGui::TableSetupColumn(
"#itemTool");
103 ImGui::TableNextColumn();
107 ImGui::TableNextColumn();
111 ImGui::TableNextColumn();
113 ImGui::TableNextColumn();
117 ImGui::TableNextColumn();
121 ImGui::TableNextColumn();
123 ImGui::TableNextColumn();
127 ImGui::TableNextColumn();
137 std::vector<std::array<uint8_t, 25>> current_floor_rooms_d;
138 std::vector<std::array<uint8_t, 25>> current_floor_gfx_d;
141 uint8_t nbr_basement_d;
143 for (
int d = 0; d < 14; d++) {
144 current_floor_rooms_d.clear();
145 current_floor_gfx_d.clear();
160 nbr_basement_d &= 0x0F;
165 nbr_floor_d = nbr_floor_d >> 4;
167 total_floors_d = nbr_basement_d + nbr_floor_d;
172 for (
int i = 0; i < total_floors_d; i++) {
175 std::array<uint8_t, 25> rdata;
176 std::array<uint8_t, 25> gdata;
179 for (
int j = 0; j < 25; j++) {
181 rdata[j] =
rom()->data()[pc_ptr + j + (i * 25)];
183 if (rdata[j] == 0x0F) {
186 gdata[j] =
rom()->data()[pc_ptr_gfx++];
193 current_floor_gfx_d.push_back(gdata);
194 current_floor_rooms_d.push_back(rdata);
197 dungeon_maps_.emplace_back(boss_room_d, nbr_floor_d, nbr_basement_d,
198 current_floor_rooms_d, current_floor_gfx_d);
201 return absl::OkStatus();
205 for (
int d = 0; d < 14; d++) {
213 for (
int i = 0; i < nbr_floors + nbr_basements; i++) {
214 for (
int j = 0; j < 25; j++) {
224 return absl::OkStatus();
228 const std::vector<uint8_t> &gfx_data,
bool bin_mode) {
231 for (
int i = 0; i < 186; i++) {
249 int sheet_offset = 212;
253 tile16_sheet_.ComposeTile16(gfx_data, t1, t2, t3, t4, sheet_offset);
257 *
rom()->mutable_dungeon_palette(3)));
268 return absl::OkStatus();
272 for (
int i = 0; i < 186; i++) {
295 return absl::OkStatus();
300 if (ImGui::BeginTabBar(
"##DungeonMapTabs")) {
302 current_dungeon.nbr_of_floor + current_dungeon.nbr_of_basement;
303 for (
int i = 0; i < nbr_floors; i++) {
304 int basement_num = current_dungeon.nbr_of_basement - i;
305 std::string tab_name = absl::StrFormat(
"Basement %d", basement_num);
306 if (i >= current_dungeon.nbr_of_basement) {
307 tab_name = absl::StrFormat(
"Floor %d",
308 i - current_dungeon.nbr_of_basement + 1);
311 if (ImGui::BeginTabItem(tab_name.c_str())) {
316 auto boss_room = current_dungeon.boss_room;
317 for (
int j = 0; j < 25; j++) {
318 if (current_dungeon.floor_rooms[
floor_number][j] != 0x0F) {
319 int tile16_id = current_dungeon.floor_gfx[
floor_number][j];
320 int posX = ((j % 5) * 32);
321 int posY = ((j / 5) * 32);
365 const ImVec2 button_size = ImVec2(130, 0);
368 if (ImGui::Button(
"Add Floor", button_size) &&
369 current_dungeon.nbr_of_floor < 8) {
370 current_dungeon.nbr_of_floor++;
374 if (ImGui::Button(
"Remove Floor", button_size) &&
375 current_dungeon.nbr_of_floor > 0) {
376 current_dungeon.nbr_of_floor--;
381 if (ImGui::Button(
"Add Basement", button_size) &&
382 current_dungeon.nbr_of_basement < 8) {
383 current_dungeon.nbr_of_basement++;
387 if (ImGui::Button(
"Remove Basement", button_size) &&
388 current_dungeon.nbr_of_basement > 0) {
389 current_dungeon.nbr_of_basement--;
393 if (ImGui::Button(
"Copy Floor", button_size)) {
397 if (ImGui::Button(
"Paste Floor", button_size)) {
403 if (ImGui::BeginChild(
"##DungeonMapTiles", ImVec2(0, 0),
true)) {
443 if (ImGui::Button(
"Modify Tile16")) {
451 *
rom()->mutable_dungeon_palette(3)));
462 ImGui::Text(
"Failed to load dungeon maps");
471 int current_tile8 = 0;
472 int tile_data_offset = 0;
473 for (
int i = 0; i < 4; ++i) {
474 for (
int j = 0; j < 32; j++) {
475 std::vector<uint8_t> tile_data(64, 0);
476 int tile_index = current_tile8 + j;
479 sheets_[i].Get8x8Tile(tile_index, 0, 0, tile_data, tile_data_offset);
482 *
rom()->mutable_dungeon_palette(3)));
485 tile_data_offset = 0;
489 ImGui::Text(
"Failed to load dungeon map tile16");
493 if (ImGui::BeginTable(
"##DungeonMapToolset", 2,
494 ImGuiTableFlags_SizingFixedFit)) {
495 ImGui::TableSetupColumn(
"Draw Mode");
496 ImGui::TableSetupColumn(
"Edit Mode");
498 ImGui::TableNextColumn();
503 ImGui::TableNextColumn();
511 static std::vector<std::string> dungeon_names = {
512 "Sewers/Sanctuary",
"Hyrule Castle",
"Eastern Palace",
513 "Desert Palace",
"Tower of Hera",
"Agahnim's Tower",
514 "Palace of Darkness",
"Swamp Palace",
"Skull Woods",
515 "Thieves' Town",
"Ice Palace",
"Misery Mire",
516 "Turtle Rock",
"Ganon's Tower"};
518 if (ImGui::BeginTable(
"DungeonMapsTable", 4,
519 ImGuiTableFlags_Resizable |
520 ImGuiTableFlags_Reorderable |
521 ImGuiTableFlags_Hideable)) {
522 ImGui::TableSetupColumn(
"Dungeon");
523 ImGui::TableSetupColumn(
"Map");
524 ImGui::TableSetupColumn(
"Rooms Gfx");
525 ImGui::TableSetupColumn(
"Tiles Gfx");
526 ImGui::TableHeadersRow();
528 ImGui::TableNextColumn();
529 for (
int i = 0; i < dungeon_names.size(); i++) {
530 rom()->resource_label()->SelectableLabelWithNameEdit(
533 if (ImGui::IsItemClicked()) {
538 ImGui::TableNextColumn();
541 ImGui::TableNextColumn();
544 ImGui::TableNextColumn();
557 ImGui::Text(
"For use with custom inserted graphics assembly patches.");
558 if (ImGui::Button(
"Load GFX from BIN file"))
LoadBinaryGfx();
566 if (!bin_file.empty()) {
567 std::ifstream file(bin_file, std::ios::binary);
568 if (file.is_open()) {
570 std::vector<uint8_t> bin_data((std::istreambuf_iterator<char>(file)),
571 std::istreambuf_iterator<char>());
577 std::vector<std::vector<uint8_t>> gfx_sheets;
578 for (
int i = 0; i < 4; i++) {
579 gfx_sheets.emplace_back(converted_bin.begin() + (i * 0x1000),
580 converted_bin.begin() + ((i + 1) * 0x1000));
589 status_ = absl::InternalError(
"Failed to load dungeon map tile16");
597 if (ImGui::BeginTabItem(
"Title Screen")) {
603 if (ImGui::BeginTabItem(
"Naming Screen")) {
609 if (ImGui::BeginTabItem(
"Overworld Map")) {
615 static bool show_bg1 =
true;
616 static bool show_bg2 =
true;
617 static bool show_bg3 =
true;
619 static bool drawing_bg1 =
true;
620 static bool drawing_bg2 =
false;
621 static bool drawing_bg3 =
false;
623 ImGui::Checkbox(
"Show BG1", &show_bg1);
625 ImGui::Checkbox(
"Show BG2", &show_bg2);
627 ImGui::Checkbox(
"Draw BG1", &drawing_bg1);
629 ImGui::Checkbox(
"Draw BG2", &drawing_bg2);
631 ImGui::Checkbox(
"Draw BG3", &drawing_bg3);
static GraphicsSheetManager & GetInstance()
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath.
void RenderBitmap(gfx::Bitmap *bitmap)
Used to render a bitmap to the screen.
static Renderer & GetInstance()
void DrawTitleScreenEditor()
absl::Status LoadDungeonMapTile16(const std::vector< uint8_t > &gfx_data, bool bin_mode=false)
void DrawDungeonMapsRoomGfx()
std::vector< gfx::Bitmap > tile8_individual_
gfx::SnesPalette palette_
absl::Status SaveDungeonMapTile16()
absl::Status SaveDungeonMaps()
bool dungeon_maps_loaded_
gui::Canvas tilemap_canvas_
absl::Status Load() override
absl::Status Update() override
gui::Canvas screen_canvas_
absl::Status LoadDungeonMaps()
std::vector< uint8_t > gfx_bin_data_
void Initialize() override
gfx::Tilesheet tile16_sheet_
gui::Canvas current_tile_canvas_
void DrawDungeonMapsEditor()
void DrawInventoryToolset()
std::vector< std::vector< std::array< std::string, 25 > > > dungeon_map_labels_
void DrawOverworldMapEditor()
zelda3::Inventory inventory_
EditingMode current_mode_
bool paste_button_pressed
gui::Canvas tilesheet_canvas_
void DrawNamingScreenEditor()
void DrawDungeonMapsTabs()
std::vector< zelda3::DungeonMap > dungeon_maps_
std::unordered_map< int, gfx::Bitmap > tile16_individual_
void DrawInventoryMenuEditor()
gfx::InternalTile16 current_tile16_info
Represents a bitmap image.
SNES 16-bit tile metadata container.
#define ICON_MD_MORE_VERT
#define RETURN_IF_ERROR(expression)
#define ASSIGN_OR_RETURN(type_variable_name, expression)
#define RETURN_VOID_IF_ERROR(expression)
Editors are the view controllers for the application.
constexpr uint32_t kRedPen
uint16_t TileInfoToWord(TileInfo tile_info)
TileInfo WordToTileInfo(uint16_t word)
std::vector< uint8_t > SnesTo8bppSheet(const std::vector< uint8_t > &sheet, int bpp, int num_sheets)
bool InputHexWord(const char *label, uint16_t *data, float input_width, bool no_step)
bool InputTileInfo(const char *label, gfx::TileInfo *tile_info)
absl::Status DisplayPalette(gfx::SnesPalette &palette, bool loaded)
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
std::string HexByte(uint8_t byte, HexStringParams params)
constexpr int kDungeonMapExpCheck
constexpr int kDungeonMapFloors
constexpr int kDungeonMapTile16
constexpr int kDungeonMapTile16Expanded
constexpr int kDungeonMapBossRooms
constexpr int kDungeonMapRoomsPtr
constexpr int kDungeonMapGfxPtr
Main namespace for the application.
uint32_t SnesToPc(uint32_t addr) noexcept