diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index aef202cb..f37c78f7 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -22,53 +22,17 @@ namespace yaze { namespace app { namespace editor { -namespace { -void UpdateSelectedTile16(int selected, gfx::Bitmap &tile16_blockset, - gfx::Bitmap &selected_tile) { - auto blockset = tile16_blockset.GetData(); - - int src_pos = ((selected - ((selected / 0x08) * 0x08)) * 0x10) + - ((selected / 0x08) * 2048); - for (int yy = 0; yy < 0x20; yy++) { - for (int xx = 0; xx < 0x20; xx++) { - int position = (xx + (yy * 0x20)); - uchar value = blockset[src_pos + xx + (yy * 0x80)]; - selected_tile.WriteToPixel(position, value); - } - } -} -} // namespace - -void OverworldEditor::SetupROM(ROM &rom) { rom_ = rom; } +// ---------------------------------------------------------------------------- absl::Status OverworldEditor::Update() { // Initialize overworld graphics, maps, and palettes if (rom_.isLoaded() && !all_gfx_loaded_) { - LoadGraphics(); + RETURN_IF_ERROR(LoadGraphics()) all_gfx_loaded_ = true; - - RETURN_IF_ERROR(overworld_.Load(rom_)) - palette_ = overworld_.AreaPalette(); - current_gfx_bmp_.Create(0x80, 0x200, 0x40, overworld_.AreaGraphics()); - current_gfx_bmp_.ApplyPalette(palette_); - rom_.RenderBitmap(¤t_gfx_bmp_); - - tile16_blockset_bmp_.Create(0x80, 8192, 0x80, overworld_.Tile16Blockset()); - tile16_blockset_bmp_.ApplyPalette(palette_); - rom_.RenderBitmap(&tile16_blockset_bmp_); - map_blockset_loaded_ = true; - - for (int i = 0; i < core::kNumOverworldMaps; ++i) { - overworld_.SetCurrentMap(i); - auto palette = overworld_.AreaPalette(); - maps_bmp_[i].Create(0x200, 0x200, 0x200, overworld_.BitmapData()); - maps_bmp_[i].ApplyPalette(palette); - rom_.RenderBitmap(&(maps_bmp_[i])); - } } - auto toolset_status = DrawToolset(); - RETURN_IF_ERROR(toolset_status) + // Draws the toolset for editing the Overworld. + RETURN_IF_ERROR(DrawToolset()) ImGui::Separator(); if (ImGui::BeginTable("#owEditTable", 2, ow_edit_flags, ImVec2(0, 0))) { @@ -174,10 +138,10 @@ void OverworldEditor::DrawOverworldEntrances() { for (const auto &each : overworld_.Entrances()) { if (each.map_id_ < 0x40 + (current_world_ * 0x40) && each.map_id_ >= (current_world_ * 0x40)) { - overworld_map_canvas_.DrawRect(each.x_, each.y_, 16, 16, - ImVec4(210, 24, 210, 150)); + ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16, + ImVec4(210, 24, 210, 150)); std::string str = absl::StrFormat("%#x", each.entrance_id_); - overworld_map_canvas_.DrawText(str, each.x_ - 4, each.y_ - 2); + ow_map_canvas_.DrawText(str, each.x_ - 4, each.y_ - 2); } } } @@ -191,7 +155,7 @@ void OverworldEditor::DrawOverworldMaps() { int world_index = i + (current_world_ * 0x40); int map_x = (xx * 0x200); int map_y = (yy * 0x200); - overworld_map_canvas_.DrawBitmap(maps_bmp_[world_index], map_x, map_y); + ow_map_canvas_.DrawBitmap(maps_bmp_[world_index], map_x, map_y); xx++; if (xx >= 8) { yy++; @@ -203,6 +167,8 @@ void OverworldEditor::DrawOverworldMaps() { // ---------------------------------------------------------------------------- +// Overworld Editor canvas +// Allows the user to make changes to the overworld map. void OverworldEditor::DrawOverworldCanvas() { DrawOverworldMapSettings(); ImGui::Separator(); @@ -210,28 +176,22 @@ void OverworldEditor::DrawOverworldCanvas() { ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar)) { - overworld_map_canvas_.DrawBackground(ImVec2(0x200 * 8, 0x200 * 8)); - overworld_map_canvas_.DrawContextMenu(); - overworld_map_canvas_.DrawTilePainter(selected_tile_bmp_, 32); + ow_map_canvas_.DrawBackground(ImVec2(0x200 * 8, 0x200 * 8)); + ow_map_canvas_.DrawContextMenu(); if (overworld_.isLoaded()) { DrawOverworldMaps(); + // User has selected a tile they want to draw from the blockset. + if (!blockset_canvas_.Points().empty()) { + int x = blockset_canvas_.Points().front().x / 32; + int y = blockset_canvas_.Points().front().y / 32; + std::cout << x << " " << y << std::endl; + current_tile16_ = x + (y * 8); + std::cout << current_tile16_ << std::endl; + ow_map_canvas_.DrawTilePainter(tile16_individual_[current_tile16_], 16); + } } - overworld_map_canvas_.DrawGrid(64.0f); - overworld_map_canvas_.DrawOverlay(); - - if (!blockset_canvas_.Points().empty() && all_gfx_loaded_) { - // TODO(scawful): update selected tile by getting position from canvas - // if (!selected_tile_loaded_) { - // selected_tile_loaded_ = true; - // } - - selected_tile_bmp_.Create(32, 32, 0x40, 1024); - UpdateSelectedTile16(selected_tile_, tile16_blockset_bmp_, - selected_tile_bmp_); - selected_tile_bmp_.ApplyPalette(palette_); - rom_.RenderBitmap(&selected_tile_bmp_); - update_selected_tile_ = false; - } + ow_map_canvas_.DrawGrid(64.0f); + ow_map_canvas_.DrawOverlay(); } ImGui::EndChild(); } @@ -277,6 +237,8 @@ void OverworldEditor::DrawTile8Selector() { // ---------------------------------------------------------------------------- +// Displays the graphics tilesheets that are available on the current selected +// overworld map. void OverworldEditor::DrawAreaGraphics() { current_gfx_canvas_.DrawBackground(ImVec2(256 + 1, 0x10 * 0x40 + 1)); current_gfx_canvas_.DrawContextMenu(); @@ -323,16 +285,66 @@ void OverworldEditor::DrawTileSelector() { // ---------------------------------------------------------------------------- -void OverworldEditor::LoadGraphics() { - for (int i = 0; i < 8; i++) { - current_palette_[i].x = (i * 0.21f); - current_palette_[i].y = (i * 0.21f); - current_palette_[i].z = (i * 0.21f); - current_palette_[i].w = 1.f; - } - +absl::Status OverworldEditor::LoadGraphics() { + // Load all of the graphics data from the game. PRINT_IF_ERROR(rom_.LoadAllGraphicsData()) graphics_bin_ = rom_.GetGraphicsBin(); + + // Load the Link to the Past overworld. + RETURN_IF_ERROR(overworld_.Load(rom_)) + palette_ = overworld_.AreaPalette(); + current_gfx_bmp_.Create(0x80, 0x200, 0x40, overworld_.AreaGraphics()); + current_gfx_bmp_.ApplyPalette(palette_); + rom_.RenderBitmap(¤t_gfx_bmp_); + + // Create the tile16 blockset image + tile16_blockset_bmp_.Create(0x80, 8192, 0x80, overworld_.Tile16Blockset()); + tile16_blockset_bmp_.ApplyPalette(palette_); + rom_.RenderBitmap(&tile16_blockset_bmp_); + map_blockset_loaded_ = true; + + // Copy the tile16 data into individual tiles. + auto tile16_data = overworld_.Tile16Blockset(); + + // Loop through the tiles and copy their pixel data into separate vectors + for (int i = 0; i < 4096; i++) { + // Create a new vector for the pixel data of the current tile + Bytes tile_data; + for (int j = 0; j < 32 * 32; j++) tile_data.push_back(0x00); + + // Copy the pixel data for the current tile into the vector + for (int ty = 0; ty < 32; ty++) { + for (int tx = 0; tx < 32; tx++) { + int position = (tx + (ty * 0x20)); + uchar value = tile16_data[i + tx + (ty * 0x80)]; + tile_data[position] = value; + } + } + + // Add the vector for the current tile to the vector of tile pixel data + tile16_individual_data_.push_back(tile_data); + } + + // Render the bitmaps of each tile. + for (int id = 0; id < 4096; id++) { + gfx::Bitmap new_tile16; + tile16_individual_.emplace_back(new_tile16); + tile16_individual_[id].Create(0x10, 0x10, 0x80, + tile16_individual_data_[id]); + tile16_individual_[id].ApplyPalette(palette_); + rom_.RenderBitmap(&tile16_individual_[id]); + } + + // Render the overworld maps loaded from the ROM. + for (int i = 0; i < core::kNumOverworldMaps; ++i) { + overworld_.SetCurrentMap(i); + auto palette = overworld_.AreaPalette(); + maps_bmp_[i].Create(0x200, 0x200, 0x200, overworld_.BitmapData()); + maps_bmp_[i].ApplyPalette(palette); + rom_.RenderBitmap(&(maps_bmp_[i])); + } + + return absl::OkStatus(); } } // namespace editor diff --git a/src/app/editor/overworld_editor.h b/src/app/editor/overworld_editor.h index 2934972b..4c664843 100644 --- a/src/app/editor/overworld_editor.h +++ b/src/app/editor/overworld_editor.h @@ -42,13 +42,13 @@ static constexpr absl::string_view kOverworldSettingsColumnNames[] = { class OverworldEditor { public: - void SetupROM(ROM &rom); absl::Status Update(); - absl::Status Undo() { return absl::UnimplementedError("Undo"); } - absl::Status Redo() { return absl::UnimplementedError("Redo"); } - absl::Status Cut() { return absl::UnimplementedError("Cut"); } - absl::Status Copy() { return absl::UnimplementedError("Copy"); } - absl::Status Paste() { return absl::UnimplementedError("Paste"); } + absl::Status Undo() const { return absl::UnimplementedError("Undo"); } + absl::Status Redo() const { return absl::UnimplementedError("Redo"); } + absl::Status Cut() const { return absl::UnimplementedError("Cut"); } + absl::Status Copy() const { return absl::UnimplementedError("Copy"); } + absl::Status Paste() const { return absl::UnimplementedError("Paste"); } + void SetupROM(ROM &rom) { rom_ = rom; } private: absl::Status DrawToolset(); @@ -62,10 +62,11 @@ class OverworldEditor { void DrawTile8Selector(); void DrawAreaGraphics(); void DrawTileSelector(); - void LoadGraphics(); + absl::Status LoadGraphics(); int current_world_ = 0; int current_map_ = 0; + int current_tile16_ = 0; int selected_tile_ = 0; char map_gfx_[3] = ""; char map_palette_[3] = ""; @@ -80,8 +81,6 @@ class OverworldEditor { bool selected_tile_loaded_ = false; bool update_selected_tile_ = true; - ImVec4 current_palette_[8]; - ImGuiTableFlags toolset_table_flags = ImGuiTableFlags_SizingFixedFit; ImGuiTableFlags ow_map_flags = ImGuiTableFlags_Borders; ImGuiTableFlags ow_edit_flags = ImGuiTableFlags_Reorderable | @@ -94,17 +93,20 @@ class OverworldEditor { std::unordered_map maps_bmp_; std::unordered_map sprite_previews_; + std::vector tile16_individual_data_; + std::vector tile16_individual_; + ROM rom_; PaletteEditor palette_editor_; zelda3::Overworld overworld_; gfx::SNESPalette palette_; + gfx::Bitmap selected_tile_bmp_; gfx::Bitmap tile16_blockset_bmp_; gfx::Bitmap current_gfx_bmp_; gfx::Bitmap all_gfx_bmp; - gfx::Bitmap selected_tile_bmp_; - gui::Canvas overworld_map_canvas_; + gui::Canvas ow_map_canvas_; gui::Canvas current_gfx_canvas_; gui::Canvas blockset_canvas_; gui::Canvas graphics_bin_canvas_; diff --git a/src/app/gfx/bitmap.cc b/src/app/gfx/bitmap.cc index d9c9ebaa..c4ab757b 100644 --- a/src/app/gfx/bitmap.cc +++ b/src/app/gfx/bitmap.cc @@ -39,6 +39,7 @@ Bitmap::Bitmap(int width, int height, int depth, uchar *data, int data_size) { // Pass raw pixel data directly to the surface void Bitmap::Create(int width, int height, int depth, uchar *data) { + active_ = true; width_ = width; height_ = height; depth_ = depth; @@ -53,6 +54,7 @@ void Bitmap::Create(int width, int height, int depth, uchar *data) { // Reserves data to later draw to surface via pointer void Bitmap::Create(int width, int height, int depth, int size) { + active_ = true; width_ = width; height_ = height; depth_ = depth; @@ -69,6 +71,7 @@ void Bitmap::Create(int width, int height, int depth, int size) { // Pass raw pixel data directly to the surface void Bitmap::Create(int width, int height, int depth, uchar *data, int size) { + active_ = true; width_ = width; height_ = height; depth_ = depth; @@ -83,6 +86,7 @@ void Bitmap::Create(int width, int height, int depth, uchar *data, int size) { } void Bitmap::Create(int width, int height, int depth, Bytes data) { + active_ = true; width_ = width; height_ = height; depth_ = depth; diff --git a/src/app/gfx/bitmap.h b/src/app/gfx/bitmap.h index 13f68af7..9ae90ee3 100644 --- a/src/app/gfx/bitmap.h +++ b/src/app/gfx/bitmap.h @@ -45,6 +45,7 @@ class Bitmap { auto GetByte(int i) const { return pixel_data_[i]; } auto GetTexture() const { return texture_.get(); } auto GetSurface() const { return surface_.get(); } + auto IsActive() const { return active_; } private: struct SDL_Texture_Deleter { @@ -71,6 +72,7 @@ class Bitmap { int depth_ = 0; int data_size_ = 0; bool freed_ = false; + bool active_ = false; uchar *pixel_data_; Bytes data_; gfx::SNESPalette palette_; diff --git a/src/gui/canvas.cc b/src/gui/canvas.cc index aff61d73..14b4ec86 100644 --- a/src/gui/canvas.cc +++ b/src/gui/canvas.cc @@ -63,7 +63,7 @@ void Canvas::DrawContextMenu() { } } -void Canvas::DrawTilePainter(const Bitmap& bitmap, int size) { +void Canvas::DrawTilePainter(const Bitmap &bitmap, int size) { const ImGuiIO &io = ImGui::GetIO(); const bool is_hovered = ImGui::IsItemHovered(); // Hovered const ImVec2 origin(canvas_p0_.x + scrolling_.x, @@ -85,10 +85,15 @@ void Canvas::DrawTilePainter(const Bitmap& bitmap, int size) { points_.push_back( ImVec2(draw_tile_outline_pos.x + size, draw_tile_outline_pos.y + size)); - draw_list_->AddImage((void *)bitmap.GetTexture(), - ImVec2(draw_tile_outline_pos.x, draw_tile_outline_pos.y), - ImVec2(draw_tile_outline_pos.x + (bitmap.GetWidth() * 2), - draw_tile_outline_pos.y + (bitmap.GetHeight() * 2))); + if (bitmap.IsActive()) { + draw_list_->AddImage( + (void *)bitmap.GetTexture(), + ImVec2(origin.x + draw_tile_outline_pos.x, + origin.y + draw_tile_outline_pos.y), + ImVec2(origin.x + draw_tile_outline_pos.x + bitmap.GetWidth(), + origin.y + draw_tile_outline_pos.y + bitmap.GetHeight())); + } + } else { points_.clear(); }