From f11e8f2aac89044242fb60bc27e7af40499c08ef Mon Sep 17 00:00:00 2001 From: Justin Scofield Date: Mon, 20 Jun 2022 17:54:14 -0400 Subject: [PATCH] expand tile library, consolidate rom features, work on overworld tile16 selection --- src/CMakeLists.txt | 2 +- src/app/core/controller.cc | 1 + src/app/gfx/bitmap.cc | 20 ++++- src/app/gfx/bitmap.h | 7 +- src/app/gfx/tile.cc | 121 ----------------------------- src/app/gfx/tile.h | 28 ++----- src/app/gfx/tile16.cc | 70 +++++++++++++++++ src/app/gfx/tile32.cc | 0 src/app/rom.cc | 37 +++------ src/app/rom.h | 17 ++-- src/app/zelda3/overworld.cc | 50 +++--------- src/app/zelda3/overworld.h | 11 ++- src/gui/editor/editor.cc | 9 ++- src/gui/editor/editor.h | 9 +-- src/gui/editor/overworld_editor.cc | 72 +++++++++++++++-- src/gui/editor/overworld_editor.h | 2 + test/CMakeLists.txt | 5 +- 17 files changed, 222 insertions(+), 239 deletions(-) delete mode 100644 src/app/gfx/tile.cc create mode 100644 src/app/gfx/tile16.cc create mode 100644 src/app/gfx/tile32.cc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3dc3a29f..4c7a4b41 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,7 +40,7 @@ add_executable( app/core/constants.cc app/core/controller.cc app/gfx/bitmap.cc - app/gfx/tile.cc + app/gfx/tile16.cc app/gfx/snes_palette.cc app/zelda3/overworld.cc app/zelda3/overworld_map.cc diff --git a/src/app/core/controller.cc b/src/app/core/controller.cc index 0943f013..035fd8c8 100644 --- a/src/app/core/controller.cc +++ b/src/app/core/controller.cc @@ -69,6 +69,7 @@ void Controller::onInput() { case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_CLOSE: + editor_.Shutdown(); quit(); break; case SDL_WINDOWEVENT_SIZE_CHANGED: diff --git a/src/app/gfx/bitmap.cc b/src/app/gfx/bitmap.cc index 6c2ad91a..48477c6c 100644 --- a/src/app/gfx/bitmap.cc +++ b/src/app/gfx/bitmap.cc @@ -10,6 +10,23 @@ namespace yaze { namespace app { namespace gfx { +Bitmap::Bitmap(int width, int height, int depth, char *data) + : width_(width), height_(height), depth_(depth), pixel_data_(data) { + surface_ = SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, + SDL_PIXELFORMAT_INDEX8); + // Default grayscale palette + for (int i = 0; i < 8; i++) { + surface_->format->palette->colors[i].r = i * 31; + surface_->format->palette->colors[i].g = i * 31; + surface_->format->palette->colors[i].b = i * 31; + } + surface_->pixels = data; +} + +SDL_Texture *Bitmap::CreateTexture(std::shared_ptr renderer) { + texture_ = SDL_CreateTextureFromSurface(renderer.get(), surface_); +} + int GetPCGfxAddress(char *romData, char id) { char **info1 = new char *[255]; int gfxPointer1 = @@ -30,7 +47,8 @@ int GetPCGfxAddress(char *romData, char id) { char gfxGamePointer3 = romData[gfxPointer3 + id]; return lorom_snes_to_pc( - yaze::app::rom::AddressFromBytes(gfxGamePointer1, gfxGamePointer2, gfxGamePointer3), + yaze::app::rom::AddressFromBytes(gfxGamePointer1, gfxGamePointer2, + gfxGamePointer3), info1); } diff --git a/src/app/gfx/bitmap.h b/src/app/gfx/bitmap.h index 62e2dbd7..98293ff3 100644 --- a/src/app/gfx/bitmap.h +++ b/src/app/gfx/bitmap.h @@ -14,16 +14,19 @@ namespace gfx { class Bitmap { public: Bitmap() = default; - Bitmap(int width, int height, char *data) - : width_(width), height_(height), pixel_data_(data) {} + Bitmap(int width, int height, int depth, char *data); int GetWidth() const { return width_; } int GetHeight() const { return height_; } + SDL_Texture *CreateTexture(std::shared_ptr renderer); private: int width_; int height_; + int depth_; char *pixel_data_; + SDL_Surface *surface_; + SDL_Texture *texture_; }; static bool isbpp3[core::constants::NumberOfSheets]; diff --git a/src/app/gfx/tile.cc b/src/app/gfx/tile.cc deleted file mode 100644 index 0212e62b..00000000 --- a/src/app/gfx/tile.cc +++ /dev/null @@ -1,121 +0,0 @@ -#include "tile.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "app/gfx/snes_palette.h" - - -namespace yaze { -namespace app { -namespace gfx { - -TilesPattern::TilesPattern() { - tiles_per_row_ = 16; - number_of_tiles_ = 16; - // transform_vector_.push_back(std::vector{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - // 8, - // 9, 10, 11, 12, 13, 14, 15}); - // transform_vector_.push_back(std::vector{}); - // transform_vector_.push_back(std::vector{}); - // transform_vector_.push_back(std::vector{}); - - transform_vector_.push_back(std::vector{0, 1, 2, 3}); - transform_vector_.push_back(std::vector{4, 5, 6, 7}); - transform_vector_.push_back(std::vector{8, 9, 10, 11}); - transform_vector_.push_back(std::vector{12, 13, 14, 15}); -} - -std::vector > TilesPattern::transform( - const std::vector &tiles) const { - uint repeatOffsetY = 0; - uint repeatOffsetX = 0; - uint tVectHeight = transform_vector_.size(); - uint tVectWidth = transform_vector_[0].size(); - uint repeat = 0; - std::vector > toret; - uint transPerRow = tiles_per_row_ / tVectWidth; - uint nbTransform = tiles.size() / number_of_tiles_; - printf("Tiles size : %d\nnbtransform : %d\npattern number of tiles : %d\n", - tiles.size(), nbTransform, number_of_tiles_); - - if (transPerRow > nbTransform) - toret.resize(tVectHeight); - else - toret.resize(((uint)(((double)nbTransform / (double)transPerRow) + 0.5)) * - tVectHeight); - - for (auto &each : toret) { - each.resize(tiles_per_row_); - } - - std::cout << toret[0].size() << " x " << toret.size(); - while (repeat != nbTransform) { - std::cout << "repeat" << repeat; - for (uint j = 0; j < tVectHeight; j++) { - for (uint i = 0; i < tVectWidth; i++) { - uint posTile = transform_vector_[j][i] + number_of_tiles_ * repeat; - uint posX = i + repeatOffsetX; - uint posY = j + repeatOffsetY; - printf("X: %d - Y: %d - posTile : %d \n", posX, posY, posTile); - toret.at(posY).at(posX) = tiles[posTile]; - } - } - if (repeatOffsetX + tVectWidth == tiles_per_row_) { - repeatOffsetX = 0; - repeatOffsetY += tVectHeight; - } else - repeatOffsetX += tVectWidth; - repeat++; - } - std::cout << "End of transform" << std::endl; - return toret; -} - -std::vector TilesPattern::reverse( - const std::vector &tiles) const { - uint repeatOffsetY = 0; - uint repeatOffsetX = 0; - uint tVectHeight = transform_vector_.size(); - uint tVectWidth = transform_vector_[0].size(); - uint repeat = 0; - uint nbTransPerRow = tiles_per_row_ / tVectWidth; - uint nbTiles = tiles.size(); - std::vector toretVec(tiles.size()); - - for (uint i = 0; i < nbTiles; i++) { - uint lineNb = i / tiles_per_row_; - uint lineInTab = lineNb % tVectHeight; - uint colInTab = i % tVectWidth; - uint tileNb = transform_vector_[lineInTab][colInTab]; - - uint lineBlock = i / (nbTransPerRow * number_of_tiles_); - uint blockNB = - (i % (nbTransPerRow * number_of_tiles_) % tiles_per_row_) / tVectWidth; - - std::cout << colInTab << lineInTab << " = " << tileNb; - uint pos = tileNb + (lineBlock + blockNB) * number_of_tiles_; - std::cout << i << "Goes to : " << pos; - toretVec[pos] = tiles[i]; - } - return toretVec; -} - -std::vector > TilesPattern::transform( - const TilesPattern &pattern, const std::vector &tiles) { - return pattern.transform(tiles); -} - -} // namespace gfx -} // namespace app -} // namespace yaze diff --git a/src/app/gfx/tile.h b/src/app/gfx/tile.h index dcf5769e..6f0aec6c 100644 --- a/src/app/gfx/tile.h +++ b/src/app/gfx/tile.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,7 @@ #include "app/gfx/snes_palette.h" + namespace yaze { namespace app { namespace gfx { @@ -55,6 +57,10 @@ class Tile32 { : tile0_(t0), tile1_(t1), tile2_(t2), tile3_(t3) {} }; +void BuildTiles16Gfx(); +void CopyTile16(int x, int y, int xx, int yy, int offset, TileInfo tile, + uchar* gfx16Pointer, uchar* gfx8Pointer); + class Tile16 { public: TileInfo tile0_; @@ -72,31 +78,9 @@ class Tile16 { } }; -class TilesPattern { - public: - TilesPattern(); - std::string name; - std::string description; - unsigned int tiles_per_row_; - unsigned int number_of_tiles_; - - static TilesPattern pattern(std::string name); - static std::vector> transform( - const TilesPattern& pattern, const std::vector& tiles); - - protected: - std::vector> transform( - const std::vector& tiles) const; - std::vector reverse(const std::vector& tiles) const; - - private: - std::vector> transform_vector_; -}; - class TilePreset { public: TilePreset() = default; - TilesPattern tilesPattern; bool no_zero_color_ = false; int pc_tiles_location_ = 0; int pc_palette_location_ = 0; diff --git a/src/app/gfx/tile16.cc b/src/app/gfx/tile16.cc new file mode 100644 index 00000000..aeb43c9a --- /dev/null +++ b/src/app/gfx/tile16.cc @@ -0,0 +1,70 @@ +#include +#include + +#include "app/core/constants.h" +#include "tile.h" + +namespace yaze { +namespace app { +namespace gfx { + +void BuildTiles16Gfx(std::shared_ptr mapblockset16, + std::shared_ptr currentOWgfx16Ptr, + std::vector& allTiles) { + auto gfx16Data = mapblockset16.get(); + auto gfx8Data = currentOWgfx16Ptr.get(); + const int offsets[4] = {0, 8, 1024, 1032}; + auto yy = 0; + auto xx = 0; + + // Number of tiles16 3748? // its 3752 + for (auto i = 0; i < core::constants::NumberOfMap16; i++) { + // 8x8 tile draw + // gfx8 = 4bpp so everyting is /2 + auto tiles = allTiles[i]; + + for (auto tile = 0; tile < 4; tile++) { + TileInfo info = tiles.tiles_info[tile]; + int offset = offsets[tile]; + + for (auto y = 0; y < 8; y++) { + for (auto x = 0; x < 4; x++) { + CopyTile16(x, y, xx, yy, offset, info, gfx16Data, gfx8Data); + } + } + } + + xx += 16; + if (xx >= 128) { + yy += 2048; + xx = 0; + } + } +} + +void CopyTile16(int x, int y, int xx, int yy, int offset, TileInfo tile, + uchar* gfx16Pointer, uchar* gfx8Pointer) // map,current +{ + int mx = x; + int my = y; + uchar r = 0; + + if (tile.horizontal_mirror_) { + mx = 3 - x; + r = 1; + } + if (tile.vertical_mirror_) { + my = 7 - y; + } + + int tx = ((tile.id_ / 16) * 512) + ((tile.id_ - ((tile.id_ / 16) * 16)) * 4); + auto index = xx + yy + offset + (mx * 2) + (my * 128); + auto pixel = gfx8Pointer[tx + (y * 64) + x]; + + gfx16Pointer[index + r ^ 1] = (uchar)((pixel & 0x0F) + tile.palette_ * 16); + gfx16Pointer[index + r] = (uchar)(((pixel >> 4) & 0x0F) + tile.palette_ * 16); +} + +} // namespace gfx +} // namespace app +} // namespace yaze \ No newline at end of file diff --git a/src/app/gfx/tile32.cc b/src/app/gfx/tile32.cc new file mode 100644 index 00000000..e69de29b diff --git a/src/app/rom.cc b/src/app/rom.cc index 81ed031c..bc531cb4 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -23,7 +23,7 @@ int AddressFromBytes(uchar addr1, uchar addr2, uchar addr3) { return (addr1 << 16) | (addr2 << 8) | addr3; } -ROM::~ROM() { +void ROM::Close() { if (loaded) { delete[] current_rom_; for (auto &each : decompressed_graphic_sheets_) { @@ -97,33 +97,14 @@ std::vector ROM::ExtractTiles(gfx::TilePreset &preset) { return rawTiles; } -gfx::SNESPalette ROM::ExtractPalette(gfx::TilePreset &preset) { - uint filePos = - GetRomPosition(preset.pc_palette_location_, preset.SNESPaletteLocation); - std::cout << "Palette pos : " << filePos << std::endl; // TODO: make this hex - uint palette_size = pow(2, preset.bits_per_pixel_); // - 1; - - auto palette_data = std::make_unique(palette_size * 2); - memcpy(palette_data.get(), current_rom_ + filePos, palette_size * 2); - - // char *ab = (char *)malloc(sizeof(char) * (palette_size * 2)); - // memcpy(ab, current_rom_ + filePos, palette_size * 2); - - for (int i = 0; i < palette_size; i++) { - std::cout << palette_data[i]; - } +gfx::SNESPalette ROM::ExtractPalette(uint addr, int bpp) { + uint filePos = addr; + uint palette_size = pow(2, bpp); + char *palette_data = (char *)malloc(sizeof(char) * (palette_size * 2)); + memcpy(palette_data, current_rom_ + filePos, palette_size * 2); + for (int i = 0; i < palette_size; i++) std::cout << palette_data[i]; std::cout << std::endl; - - const unsigned char *data = palette_data.get(); - gfx::SNESPalette pal(data); - if (preset.no_zero_color_) { - gfx::SNESColor col; - - col.setRgb(ImVec4(153, 153, 153, 255)); - pal.colors.push_back(col); - pal.colors.erase(pal.colors.begin(), - pal.colors.begin() + pal.colors.size() - 1); - } + gfx::SNESPalette pal(palette_data); return pal; } @@ -270,7 +251,7 @@ uchar *ROM::SNES3bppTo8bppSheet(uchar *buffer_in, return sheet_buffer_out; } -SDL_Texture *ROM::DrawgfxSheet(int offset) { +SDL_Texture *ROM::DrawGraphicsSheet(int offset) { SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, 128, 32, 8, SDL_PIXELFORMAT_INDEX8); std::cout << "Drawing surface #" << offset << std::endl; diff --git a/src/app/rom.h b/src/app/rom.h index f7b444f6..e605fa43 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -24,22 +24,17 @@ int AddressFromBytes(uchar addr1, uchar addr2, uchar addr3); class ROM { public: - ~ROM(); + void Close(); void SetupRenderer(std::shared_ptr renderer); void LoadFromFile(const std::string& path); std::vector ExtractTiles(gfx::TilePreset& preset); - gfx::SNESPalette ExtractPalette(gfx::TilePreset& preset); + gfx::SNESPalette ExtractPalette(uint addr, int bpp); uint32_t GetRomPosition(int direct_addr, uint snes_addr) const; char* Decompress(int pos, int size = 0x800, bool reversed = false); uchar* SNES3bppTo8bppSheet(uchar* buffer_in, int sheet_id = 0); - SDL_Texture* DrawgfxSheet(int offset); + SDL_Texture* DrawGraphicsSheet(int offset); - inline uchar* GetRawData() { return current_rom_; } - const uchar* getTitle() const { return title; } - long int getSize() const { return size_; } - char getVersion() const { return version_; } - bool isLoaded() const { return loaded; } unsigned int SnesToPc(unsigned int addr) { if (addr >= 0x808000) { @@ -48,6 +43,12 @@ class ROM { unsigned int temp = (addr & 0x7FFF) + ((addr / 2) & 0xFF8000); return (temp + 0x0); } + inline uchar* GetRawData() { return current_rom_; } + inline auto Renderer() { return sdl_renderer_; } + const uchar* getTitle() const { return title; } + long int getSize() const { return size_; } + char getVersion() const { return version_; } + bool isLoaded() const { return loaded; } private: bool loaded = false; diff --git a/src/app/zelda3/overworld.cc b/src/app/zelda3/overworld.cc index 8e989bab..74919492 100644 --- a/src/app/zelda3/overworld.cc +++ b/src/app/zelda3/overworld.cc @@ -22,7 +22,6 @@ Overworld::~Overworld() { free(allmapsTilesSP); delete[] overworldMapPointer; - delete[] owactualMapPointer; } } @@ -55,17 +54,17 @@ void Overworld::Load(app::rom::ROM& rom) { DecompressAllMapTiles(); // Map Initialization : - for (int i = 0; i < 160; i++) { - allmaps.push_back(OverworldMap(rom_, tiles16, (uchar)i)); - } - FetchLargeMaps(); - LoadOverworldMap(); + // for (int i = 0; i < 160; i++) { + // allmaps.push_back(OverworldMap(rom_, tiles16, (uchar)i)); + // } + // FetchLargeMaps(); + // LoadOverworldMap(); - auto size = tiles16.size(); - for (int i = 0; i < 160; i++) { - allmaps[i].BuildMap(mapParent, size, gameState, allmapsTilesLW, - allmapsTilesDW, allmapsTilesSP); - } + // auto size = tiles16.size(); + // for (int i = 0; i < 160; i++) { + // allmaps[i].BuildMap(mapParent, size, gameState, allmapsTilesLW, + // allmapsTilesDW, allmapsTilesSP); + // } isLoaded = true; } @@ -298,10 +297,8 @@ void Overworld::FetchLargeMaps() { } void Overworld::LoadOverworldMap() { - overworldMapBitmap = new Bitmap(128, 128, overworldMapPointer); - owactualMapBitmap = new Bitmap(512, 512, owactualMapPointer); + overworldMapBitmap = new Bitmap(128, 128, 8, overworldMapPointer); - // Mode 7 char* ptr = overworldMapPointer; int pos = 0; @@ -317,30 +314,7 @@ void Overworld::LoadOverworldMap() { } } - // ColorPalette cp = overworldMapBitmap.Palette; - // for (int i = 0; i < 256; i += 2) - // { - // //55B27 = US LW - // //55C27 = US DW - // cp.Entries[i / 2] = getColor((short)((ROM.DATA[0x55B27 + i + 1] << 8) + - // ROM.DATA[0x55B27 + i])); - - // int k = 0; - // int j = 0; - // for (int y = 10; y < 14; y++) - // { - // for (int x = 0; x < 15; x++) - // { - // cp.Entries[145 + k] = Palettes.globalSprite_Palettes[0][j]; - // k++; - // j++; - // } - // k++; - // } - // } - - // overworldMapBitmap.Palette = cp; - // owactualMapBitmap.Palette = cp; + overworld_map_texture = overworldMapBitmap->CreateTexture(rom_.Renderer()); } } // namespace zelda3 diff --git a/src/app/zelda3/overworld.h b/src/app/zelda3/overworld.h index ca2a9d02..9ebaf0bd 100644 --- a/src/app/zelda3/overworld.h +++ b/src/app/zelda3/overworld.h @@ -1,6 +1,7 @@ #ifndef YAZE_APP_DATA_OVERWORLD_H #define YAZE_APP_DATA_OVERWORLD_H +#include #include #include @@ -26,9 +27,6 @@ class Overworld { char* overworldMapPointer = new char[0x40000]; gfx::Bitmap* overworldMapBitmap; - char* owactualMapPointer = new char[0x40000]; - gfx::Bitmap* owactualMapBitmap; - private: app::rom::ROM rom_; int gameState = 1; @@ -48,6 +46,13 @@ class Overworld { std::vector tileLeftEntrance; std::vector tileRightEntrance; + std::shared_ptr mapblockset16; + std::shared_ptr currentOWgfx16Ptr; + + gfx::Bitmap mapblockset16Bitmap; + + SDL_Texture* overworld_map_texture; + int map32address[4] = { core::constants::map32TilesTL, core::constants::map32TilesTR, core::constants::map32TilesBL, core::constants::map32TilesBR}; diff --git a/src/gui/editor/editor.cc b/src/gui/editor/editor.cc index d396c39c..3bc35c4f 100644 --- a/src/gui/editor/editor.cc +++ b/src/gui/editor/editor.cc @@ -90,6 +90,7 @@ Editor::~Editor() { for (auto &each : imagesCache) { SDL_DestroyTexture(each.second); } + rom_.Close(); } void Editor::SetupScreen(std::shared_ptr renderer) { @@ -124,6 +125,10 @@ void Editor::UpdateScreen() { ImGui::End(); } +void Editor::Shutdown() { + +} + void Editor::DrawYazeMenu() { MENU_BAR() DrawFileMenu(); @@ -278,7 +283,7 @@ void Editor::DrawHelpMenu() const { } } -void Editor::DrawgfxSheet(int offset) { +void Editor::DrawGraphicsSheet(int offset) { SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, 128, 32, 8, SDL_PIXELFORMAT_INDEX8); std::cout << "Drawing surface" << std::endl; @@ -345,7 +350,7 @@ void Editor::DrawProjectEditor() { ImGui::InputInt("Tilesheet Offset", &tilesheet_offset); BASIC_BUTTON("Retrieve gfx") { if (rom_.isLoaded()) { - DrawgfxSheet(tilesheet_offset); + DrawGraphicsSheet(tilesheet_offset); loaded_image = true; } } diff --git a/src/gui/editor/editor.h b/src/gui/editor/editor.h index 982c3786..59ca8760 100644 --- a/src/gui/editor/editor.h +++ b/src/gui/editor/editor.h @@ -24,6 +24,7 @@ class Editor { ~Editor(); void SetupScreen(std::shared_ptr renderer); void UpdateScreen(); + void Shutdown(); private: void DrawYazeMenu(); @@ -32,7 +33,7 @@ class Editor { void DrawViewMenu(); void DrawHelpMenu() const; - void DrawgfxSheet(int offset = 0); + void DrawGraphicsSheet(int offset = 0); void DrawProjectEditor(); void DrawOverworldEditor(); @@ -46,17 +47,15 @@ class Editor { bool is_loaded_ = true; app::rom::ROM rom_; + app::gfx::TilePreset current_set_; + TextEditor asm_editor_; TextEditor::LanguageDefinition language_65816_; OverworldEditor overworld_editor_; - - std::vector tiles_; - std::vector> arranged_tiles_; std::unordered_map imagesCache; std::shared_ptr sdl_renderer_; ImVec4 current_palette_[8]; - app::gfx::TilePreset current_set_; ImGuiWindowFlags main_editor_flags_ = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | diff --git a/src/gui/editor/overworld_editor.cc b/src/gui/editor/overworld_editor.cc index 217ff901..ba04f6a5 100644 --- a/src/gui/editor/overworld_editor.cc +++ b/src/gui/editor/overworld_editor.cc @@ -63,7 +63,7 @@ void OverworldEditor::Update() { } void OverworldEditor::DrawToolset() { - if (ImGui::BeginTable("Toolset", 14, toolset_table_flags, ImVec2(0, 0))) { + if (ImGui::BeginTable("Toolset", 16, toolset_table_flags, ImVec2(0, 0))) { ImGui::TableSetupColumn("#undoTool"); ImGui::TableSetupColumn("#redoTool"); ImGui::TableSetupColumn("#drawTool"); @@ -78,6 +78,8 @@ void OverworldEditor::DrawToolset() { ImGui::TableSetupColumn("#spriteTool"); ImGui::TableSetupColumn("#transportTool"); ImGui::TableSetupColumn("#musicTool"); + ImGui::TableSetupColumn("#separator3"); + ImGui::TableSetupColumn("#reloadTool"); ImGui::TableNextColumn(); ImGui::Button(ICON_MD_UNDO); @@ -126,6 +128,14 @@ void OverworldEditor::DrawToolset() { ImGui::TableNextColumn(); ImGui::Button(ICON_MD_MUSIC_NOTE); + ImGui::TableNextColumn(); + ImGui::Text(ICON_MD_MORE_VERT); + + ImGui::TableNextColumn(); + if (ImGui::Button(ICON_MD_UPDATE)) { + overworld_.Load(rom_); + } + ImGui::EndTable(); } } @@ -274,6 +284,10 @@ void OverworldEditor::DrawOverworldCanvas() { void OverworldEditor::DrawTileSelector() { if (ImGui::BeginTabBar("##TabBar", ImGuiTabBarFlags_FittingPolicyScroll)) { + if (ImGui::BeginTabItem("Tile16")) { + DrawTile16Selector(); + ImGui::EndTabItem(); + } if (ImGui::BeginTabItem("Tile8")) { ImGuiStyle &style = ImGui::GetStyle(); ImGuiID child_id = ImGui::GetID((void *)(intptr_t)1); @@ -291,14 +305,62 @@ void OverworldEditor::DrawTileSelector() { ImGui::EndChild(); ImGui::EndTabItem(); } - if (ImGui::BeginTabItem("Tile16")) { - ImGui::EndTabItem(); - } ImGui::EndTabBar(); } } +void OverworldEditor::DrawTile16Selector() { + static ImVec2 scrolling(0.0f, 0.0f); + ImVec2 canvas_p0 = ImGui::GetCursorScreenPos(); + ImVec2 canvas_sz = ImVec2(256 + 1, kNumSheetsToLoad * 64 + 1); + ImVec2 canvas_p1 = + ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y); + + // Draw border and background color + const ImGuiIO &io = ImGui::GetIO(); + ImDrawList *draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(32, 32, 32, 255)); + draw_list->AddRect(canvas_p0, canvas_p1, IM_COL32(255, 255, 255, 255)); + + // This will catch our interactions + ImGui::InvisibleButton( + "Tile16SelectorCanvas", canvas_sz, + ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); + const bool is_hovered = ImGui::IsItemHovered(); // Hovered + const bool is_active = ImGui::IsItemActive(); // Held + const ImVec2 origin(canvas_p0.x + scrolling.x, + canvas_p0.y + scrolling.y); // Lock scrolled origin + const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x, + io.MousePos.y - origin.y); + + // Context menu (under default mouse threshold) + ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right); + if (drag_delta.x == 0.0f && drag_delta.y == 0.0f) + ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight); + if (ImGui::BeginPopup("context")) { + ImGui::EndPopup(); + } + + // Draw grid + all lines in the canvas + draw_list->PushClipRect(canvas_p0, canvas_p1, true); + if (opt_enable_grid) { + const float GRID_STEP = 32.0f; + for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x; + x += GRID_STEP) + draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y), + ImVec2(canvas_p0.x + x, canvas_p1.y), + IM_COL32(200, 200, 200, 40)); + for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y; + y += GRID_STEP) + draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y), + ImVec2(canvas_p1.x, canvas_p0.y + y), + IM_COL32(200, 200, 200, 40)); + } + + draw_list->PopClipRect(); +} + void OverworldEditor::DrawTile8Selector() { static ImVec2 scrolling(0.0f, 0.0f); ImVec2 canvas_p0 = ImGui::GetCursorScreenPos(); @@ -374,7 +436,7 @@ void OverworldEditor::DrawChangelist() { void OverworldEditor::Loadgfx() { for (int i = 0; i < kNumSheetsToLoad; i++) { - all_texture_sheet_[i] = rom_.DrawgfxSheet(i); + all_texture_sheet_[i] = rom_.DrawGraphicsSheet(i); } } diff --git a/src/gui/editor/overworld_editor.h b/src/gui/editor/overworld_editor.h index b8dbcbe2..ef4cce4f 100644 --- a/src/gui/editor/overworld_editor.h +++ b/src/gui/editor/overworld_editor.h @@ -25,7 +25,9 @@ class OverworldEditor { void DrawOverworldMapSettings(); void DrawOverworldCanvas(); void DrawTileSelector(); + void DrawTile16Selector(); void DrawTile8Selector(); + void DrawChangelist(); void Loadgfx(); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f62fbadd..673794f7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -17,8 +17,7 @@ add_executable( yaze_test yaze_test.cc ../src/app/rom.cc - ../src/app/gfx/tile.cc - ../src/app/gfx/tile.cc + ../src/app/gfx/tile16.cc ../src/app/gfx/snes_palette.cc ${SNESHACKING_PATH}/compressions/alttpcompression.c ${SNESHACKING_PATH}/compressions/stdnintendo.c @@ -32,7 +31,7 @@ add_executable( target_include_directories( yaze_test PUBLIC ../src/Library/ - ../src/application/ + ../src/ ${SNESHACKING_PATH} )