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));
267 return absl::OkStatus();
271 for (
int i = 0; i < 186; i++) {
294 return absl::OkStatus();
299 if (ImGui::BeginTabBar(
"##DungeonMapTabs")) {
301 current_dungeon.nbr_of_floor + current_dungeon.nbr_of_basement;
302 for (
int i = 0; i < nbr_floors; i++) {
303 int basement_num = current_dungeon.nbr_of_basement - i;
304 std::string tab_name = absl::StrFormat(
"Basement %d", basement_num);
305 if (i >= current_dungeon.nbr_of_basement) {
306 tab_name = absl::StrFormat(
"Floor %d",
307 i - current_dungeon.nbr_of_basement + 1);
310 if (ImGui::BeginTabItem(tab_name.c_str())) {
315 auto boss_room = current_dungeon.boss_room;
316 for (
int j = 0; j < 25; j++) {
317 if (current_dungeon.floor_rooms[
floor_number][j] != 0x0F) {
318 int tile16_id = current_dungeon.floor_gfx[
floor_number][j];
319 int posX = ((j % 5) * 32);
320 int posY = ((j / 5) * 32);
364 const ImVec2 button_size = ImVec2(130, 0);
367 if (ImGui::Button(
"Add Floor", button_size) &&
368 current_dungeon.nbr_of_floor < 8) {
369 current_dungeon.nbr_of_floor++;
373 if (ImGui::Button(
"Remove Floor", button_size) &&
374 current_dungeon.nbr_of_floor > 0) {
375 current_dungeon.nbr_of_floor--;
380 if (ImGui::Button(
"Add Basement", button_size) &&
381 current_dungeon.nbr_of_basement < 8) {
382 current_dungeon.nbr_of_basement++;
386 if (ImGui::Button(
"Remove Basement", button_size) &&
387 current_dungeon.nbr_of_basement > 0) {
388 current_dungeon.nbr_of_basement--;
392 if (ImGui::Button(
"Copy Floor", button_size)) {
396 if (ImGui::Button(
"Paste Floor", button_size)) {
402 if (ImGui::BeginChild(
"##DungeonMapTiles", ImVec2(0, 0),
true)) {
442 if (ImGui::Button(
"Modify Tile16")) {
450 *
rom()->mutable_dungeon_palette(3));
461 ImGui::Text(
"Failed to load dungeon maps");
470 int current_tile8 = 0;
471 int tile_data_offset = 0;
472 for (
int i = 0; i < 4; ++i) {
473 for (
int j = 0; j < 32; j++) {
474 std::vector<uint8_t> tile_data(64, 0);
475 int tile_index = current_tile8 + j;
478 sheets_[i].Get8x8Tile(tile_index, 0, 0, tile_data, tile_data_offset);
481 *
rom()->mutable_dungeon_palette(3));
484 tile_data_offset = 0;
488 ImGui::Text(
"Failed to load dungeon map tile16");
492 if (ImGui::BeginTable(
"##DungeonMapToolset", 2,
493 ImGuiTableFlags_SizingFixedFit)) {
494 ImGui::TableSetupColumn(
"Draw Mode");
495 ImGui::TableSetupColumn(
"Edit Mode");
497 ImGui::TableNextColumn();
502 ImGui::TableNextColumn();
510 static std::vector<std::string> dungeon_names = {
511 "Sewers/Sanctuary",
"Hyrule Castle",
"Eastern Palace",
512 "Desert Palace",
"Tower of Hera",
"Agahnim's Tower",
513 "Palace of Darkness",
"Swamp Palace",
"Skull Woods",
514 "Thieves' Town",
"Ice Palace",
"Misery Mire",
515 "Turtle Rock",
"Ganon's Tower"};
517 if (ImGui::BeginTable(
"DungeonMapsTable", 4,
518 ImGuiTableFlags_Resizable |
519 ImGuiTableFlags_Reorderable |
520 ImGuiTableFlags_Hideable)) {
521 ImGui::TableSetupColumn(
"Dungeon");
522 ImGui::TableSetupColumn(
"Map");
523 ImGui::TableSetupColumn(
"Rooms Gfx");
524 ImGui::TableSetupColumn(
"Tiles Gfx");
525 ImGui::TableHeadersRow();
527 ImGui::TableNextColumn();
528 for (
int i = 0; i < dungeon_names.size(); i++) {
532 if (ImGui::IsItemClicked()) {
537 ImGui::TableNextColumn();
540 ImGui::TableNextColumn();
543 ImGui::TableNextColumn();
556 ImGui::Text(
"For use with custom inserted graphics assembly patches.");
557 if (ImGui::Button(
"Load GFX from BIN file"))
LoadBinaryGfx();
565 if (!bin_file.empty()) {
566 std::ifstream file(bin_file, std::ios::binary);
567 if (file.is_open()) {
569 std::vector<uint8_t> bin_data((std::istreambuf_iterator<char>(file)),
570 std::istreambuf_iterator<char>());
576 std::vector<std::vector<uint8_t>> gfx_sheets;
577 for (
int i = 0; i < 4; i++) {
578 gfx_sheets.emplace_back(converted_bin.begin() + (i * 0x1000),
579 converted_bin.begin() + ((i + 1) * 0x1000));
581 sheets_[i].SetPalette(*
rom()->mutable_dungeon_palette(3));
586 status_ = absl::InternalError(
"Failed to load dungeon map tile16");
594 if (ImGui::BeginTabItem(
"Title Screen")) {
600 if (ImGui::BeginTabItem(
"Naming Screen")) {
606 if (ImGui::BeginTabItem(
"Overworld Map")) {
612 static bool show_bg1 =
true;
613 static bool show_bg2 =
true;
614 static bool show_bg3 =
true;
616 static bool drawing_bg1 =
true;
617 static bool drawing_bg2 =
false;
618 static bool drawing_bg3 =
false;
620 ImGui::Checkbox(
"Show BG1", &show_bg1);
622 ImGui::Checkbox(
"Show BG2", &show_bg2);
624 ImGui::Checkbox(
"Draw BG1", &drawing_bg1);
626 ImGui::Checkbox(
"Draw BG2", &drawing_bg2);
628 ImGui::Checkbox(
"Draw BG3", &drawing_bg3);
static GraphicsSheetManager & GetInstance()
ResourceLabelManager * resource_label()
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)
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
void SelectableLabelWithNameEdit(bool selected, const std::string &type, const std::string &key, const std::string &defaultValue)