diff --git a/src/app/editor/dungeon_editor.cc b/src/app/editor/dungeon_editor.cc index af3cc966..62cba73a 100644 --- a/src/app/editor/dungeon_editor.cc +++ b/src/app/editor/dungeon_editor.cc @@ -49,7 +49,7 @@ absl::Status DungeonEditor::Update() { int pId = paletteid / 180; auto color = rom()->palette_group("dungeon_main")[pId][3]; - room_palette_[rooms_[i].palette] = color.GetRGB(); + room_palette_[rooms_[i].palette] = color.rgb(); } std::map> roomsByBank; @@ -96,8 +96,11 @@ absl::Status DungeonEditor::Update() { graphics_bin_ = rom()->graphics_bin(); full_palette_ = rom()->palette_group("dungeon_main")[current_palette_group_id_]; - current_palette_group_ = + auto current_palette_group_status = gfx::CreatePaletteGroupFromLargePalette(full_palette_); + if (current_palette_group_status.ok()) { + current_palette_group_ = current_palette_group_status.value(); + } // Create a vector of pointers to the current block bitmaps for (int block : rooms_[current_room_id_].blocks()) { diff --git a/src/app/editor/graphics_editor.cc b/src/app/editor/graphics_editor.cc index 847f41a4..5c525a24 100644 --- a/src/app/editor/graphics_editor.cc +++ b/src/app/editor/graphics_editor.cc @@ -151,8 +151,8 @@ void GraphicsEditor::DrawGfxEditToolset() { for (int i = 0; i < 8; i++) { ImGui::SameLine(); auto color = - ImVec4(palette[i].GetRGB().x / 255.0f, palette[i].GetRGB().y / 255.0f, - palette[i].GetRGB().z / 255.0f, 255.0f); + ImVec4(palette[i].rgb().x / 255.0f, palette[i].rgb().y / 255.0f, + palette[i].rgb().z / 255.0f, 255.0f); if (ImGui::ColorButton(absl::StrFormat("Palette Color %d", i).c_str(), color)) { current_color_ = color; @@ -177,43 +177,48 @@ absl::Status GraphicsEditor::UpdateGfxSheetList() { ImGuiWindowFlags_NoDecoration); ImGui::PopStyleVar(); gui::Canvas graphics_bin_canvas_; - auto select_tile_event = [&]() { - if (value.get()->is_active()) { - auto texture = value.get()->texture(); - graphics_bin_canvas_.draw_list()->AddImage( - (void*)texture, - ImVec2(graphics_bin_canvas_.zero_point().x + 2, - graphics_bin_canvas_.zero_point().y + 2), - ImVec2(graphics_bin_canvas_.zero_point().x + - value.get()->width() * sheet_scale_, - graphics_bin_canvas_.zero_point().y + - value.get()->height() * sheet_scale_)); + // auto select_tile_event = [&]() { + // }; + // graphics_bin_canvas_.UpdateEvent( + // select_tile_event, ImVec2(0x100 + 1, 0x40 + 1), 0x20, sheet_scale_, + // /*grid_size=*/16.0f); - if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { - current_sheet_ = key; - open_sheets_.insert(key); - } + graphics_bin_canvas_.DrawBackground(ImVec2(0x100 + 1, 0x40 + 1)); + graphics_bin_canvas_.DrawContextMenu(); + if (value.get()->is_active()) { + auto texture = value.get()->texture(); + graphics_bin_canvas_.draw_list()->AddImage( + (void*)texture, + ImVec2(graphics_bin_canvas_.zero_point().x + 2, + graphics_bin_canvas_.zero_point().y + 2), + ImVec2(graphics_bin_canvas_.zero_point().x + + value.get()->width() * sheet_scale_, + graphics_bin_canvas_.zero_point().y + + value.get()->height() * sheet_scale_)); - // Add a slightly transparent rectangle behind the text - ImVec2 text_pos(graphics_bin_canvas_.zero_point().x + 2, - graphics_bin_canvas_.zero_point().y + 2); - ImVec2 text_size = - ImGui::CalcTextSize(absl::StrFormat("%02X", key).c_str()); - ImVec2 rent_min(text_pos.x, text_pos.y); - ImVec2 rent_max(text_pos.x + text_size.x, text_pos.y + text_size.y); - - graphics_bin_canvas_.draw_list()->AddRectFilled( - rent_min, rent_max, IM_COL32(0, 125, 0, 128)); - - graphics_bin_canvas_.draw_list()->AddText( - text_pos, IM_COL32(125, 255, 125, 255), - absl::StrFormat("%02X", key).c_str()); + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) { + current_sheet_ = key; + open_sheets_.insert(key); } - }; - graphics_bin_canvas_.UpdateEvent( - select_tile_event, ImVec2(0x100 + 1, 0x40 + 1), 0x20, sheet_scale_, - /*grid_size=*/16.0f); + // Add a slightly transparent rectangle behind the text + ImVec2 text_pos(graphics_bin_canvas_.zero_point().x + 2, + graphics_bin_canvas_.zero_point().y + 2); + ImVec2 text_size = + ImGui::CalcTextSize(absl::StrFormat("%02X", key).c_str()); + ImVec2 rent_min(text_pos.x, text_pos.y); + ImVec2 rent_max(text_pos.x + text_size.x, text_pos.y + text_size.y); + + graphics_bin_canvas_.draw_list()->AddRectFilled(rent_min, rent_max, + IM_COL32(0, 125, 0, 128)); + + graphics_bin_canvas_.draw_list()->AddText( + text_pos, IM_COL32(125, 255, 125, 255), + absl::StrFormat("%02X", key).c_str()); + } + graphics_bin_canvas_.DrawGrid(16.0f); + graphics_bin_canvas_.DrawOverlay(); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::EndChild(); } @@ -257,16 +262,15 @@ absl::Status GraphicsEditor::UpdateGfxTabView() { *rom()->mutable_bitmap_manager()->mutable_bitmap(sheet_id); auto draw_tile_event = [&]() { - current_sheet_canvas_.DrawTileOnBitmap(tile_size_, current_bitmap, + current_sheet_canvas_.DrawTileOnBitmap(tile_size_, ¤t_bitmap, current_color_); - rom()->UpdateBitmap(¤t_bitmap); + rom()->UpdateBitmap(¤t_bitmap, true); }; current_sheet_canvas_.UpdateColorPainter( *rom()->bitmap_manager()[sheet_id], current_color_, draw_tile_event, tile_size_, current_scale_); - ImGui::EndChild(); ImGui::EndTabItem(); } @@ -539,7 +543,11 @@ absl::Status GraphicsEditor::DrawPaletteControls() { if (col_file_palette_group_.size() != 0) { col_file_palette_group_.Clear(); } - col_file_palette_group_ = gfx::CreatePaletteGroupFromColFile(col_data_); + auto col_file_palette_group_status = + gfx::CreatePaletteGroupFromColFile(col_data_); + if (col_file_palette_group_status.ok()) { + col_file_palette_group_ = col_file_palette_group_status.value(); + } col_file_palette_ = gfx::SnesPalette(col_data_); // gigaleak dev format based code diff --git a/src/app/editor/modules/palette_editor.cc b/src/app/editor/modules/palette_editor.cc index 8c7fb766..4024a804 100644 --- a/src/app/editor/modules/palette_editor.cc +++ b/src/app/editor/modules/palette_editor.cc @@ -71,7 +71,7 @@ void PaletteEditor::EditColorInPalette(gfx::SnesPalette& palette, int index) { } // Get the current color - auto currentColor = palette.GetColor(index).GetRGB(); + auto currentColor = palette.GetColor(index).rgb(); if (ImGui::ColorPicker4("Color Picker", (float*)&palette[index])) { // The color was modified, update it in the palette palette(index, currentColor); @@ -86,7 +86,7 @@ void PaletteEditor::ResetColorToOriginal( return; } - auto originalColor = originalPalette.GetColor(index).GetRGB(); + auto originalColor = originalPalette.GetColor(index).rgb(); palette(index, originalColor); } diff --git a/src/app/editor/modules/palette_editor.h b/src/app/editor/modules/palette_editor.h index c74322a1..98ac21be 100644 --- a/src/app/editor/modules/palette_editor.h +++ b/src/app/editor/modules/palette_editor.h @@ -92,9 +92,9 @@ class PaletteEditor : public SharedROM { void InitializeSavedPalette(const gfx::SnesPalette& palette) { for (int n = 0; n < palette.size(); n++) { - saved_palette_[n].x = palette.GetColor(n).GetRGB().x / 255; - saved_palette_[n].y = palette.GetColor(n).GetRGB().y / 255; - saved_palette_[n].z = palette.GetColor(n).GetRGB().z / 255; + saved_palette_[n].x = palette.GetColor(n).rgb().x / 255; + saved_palette_[n].y = palette.GetColor(n).rgb().y / 255; + saved_palette_[n].z = palette.GetColor(n).rgb().z / 255; saved_palette_[n].w = 255; // Alpha } } diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index d98f0fbe..585dc35c 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -11,6 +11,7 @@ #include "absl/strings/str_format.h" #include "app/core/common.h" #include "app/core/constants.h" +#include "app/core/platform/clipboard.h" #include "app/editor/modules/palette_editor.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" @@ -125,7 +126,7 @@ absl::Status OverworldEditor::DrawToolset() { static bool show_gfx_group = false; static bool show_properties = false; - if (BeginTable("OWToolset", 22, kToolsetTableFlags, ImVec2(0, 0))) { + if (BeginTable("OWToolset", 23, kToolsetTableFlags, ImVec2(0, 0))) { for (const auto &name : kToolsetColumnNames) ImGui::TableSetupColumn(name.data()); @@ -229,6 +230,19 @@ absl::Status OverworldEditor::DrawToolset() { TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator + TableNextColumn(); + if (Button(ICON_MD_CONTENT_COPY)) { + std::vector png_data; + if (gfx::ConvertSurfaceToPNG(maps_bmp_[current_map_].surface(), + png_data)) { + CopyImageToClipboard(png_data); + } else { + status_ = absl::InternalError( + "Failed to convert overworld map surface to PNG"); + } + } + HOVER_HINT("Copy Map to Clipboard"); + TableNextColumn(); // Palette palette_editor_.DisplayPalette(palette_, overworld_.is_loaded()); diff --git a/src/app/gui/canvas.cc b/src/app/gui/canvas.cc index 3876fde4..e63ae1ba 100644 --- a/src/app/gui/canvas.cc +++ b/src/app/gui/canvas.cc @@ -95,7 +95,7 @@ void Canvas::DrawBackground(ImVec2 canvas_size, bool can_drag) { } } -void Canvas::DrawContextMenu() { +void Canvas::DrawContextMenu(gfx::Bitmap *bitmap) { const ImGuiIO &io = ImGui::GetIO(); auto scaled_sz = ImVec2(canvas_sz_.x * global_scale_, canvas_sz_.y * global_scale_); @@ -122,10 +122,13 @@ void Canvas::DrawContextMenu() { ImGui::Text("Mouse Position: %.0f x %.0f", mouse_pos.x, mouse_pos.y); ImGui::EndMenu(); } - if (ImGui::BeginMenu("Bitmap Properties")) { - ImGui::Text("Bitmap Size: %.0f x %.0f", scaled_sz.x, scaled_sz.y); - ImGui::Text("Bitmap Position: %.0f x %.0f", origin.x, origin.y); - ImGui::EndMenu(); + if (bitmap != nullptr) { + if (ImGui::BeginMenu("Bitmap Properties")) { + ImGui::Text("Size: %.0f x %.0f", scaled_sz.x, scaled_sz.y); + ImGui::Text("Pitch: %s", + absl::StrFormat("%d", bitmap->surface()->pitch).c_str()); + ImGui::EndMenu(); + } } ImGui::Separator(); if (ImGui::BeginMenu("Grid Tile Size")) { @@ -261,7 +264,7 @@ bool Canvas::DrawSolidTilePainter(const ImVec4 &color, int tile_size) { return false; } -void Canvas::DrawTileOnBitmap(int tile_size, gfx::Bitmap &bitmap, +void Canvas::DrawTileOnBitmap(int tile_size, gfx::Bitmap *bitmap, ImVec4 color) { const ImVec2 position = drawn_tile_pos_; int tile_index_x = static_cast(position.x / global_scale_) / tile_size; @@ -274,10 +277,10 @@ void Canvas::DrawTileOnBitmap(int tile_size, gfx::Bitmap &bitmap, for (int x = 0; x < tile_size; ++x) { // Calculate the actual pixel index in the bitmap int pixel_index = - (start_position.y + y) * bitmap.width() + (start_position.x + x); + (start_position.y + y) * bitmap->width() + (start_position.x + x); // Write the color to the pixel - bitmap.WriteColor(pixel_index, color); + bitmap->WriteColor(pixel_index, color); } } } diff --git a/src/app/gui/canvas.h b/src/app/gui/canvas.h index 909a5949..af6f796c 100644 --- a/src/app/gui/canvas.h +++ b/src/app/gui/canvas.h @@ -62,7 +62,7 @@ class Canvas { // Context Menu refers to what happens when the right mouse button is pressed // This routine also handles the scrolling for the canvas. - void DrawContextMenu(); + void DrawContextMenu(gfx::Bitmap* bitmap = nullptr); // Tile painter shows a preview of the currently selected tile // and allows the user to left click to paint the tile or right @@ -71,7 +71,7 @@ class Canvas { bool DrawSolidTilePainter(const ImVec4& color, int size); // Draws a tile on the canvas at the specified position - void DrawTileOnBitmap(int tile_size, gfx::Bitmap& bitmap, ImVec4 color); + void DrawTileOnBitmap(int tile_size, gfx::Bitmap* bitmap, ImVec4 color); // Dictates which tile is currently selected based on what the user clicks // in the canvas window. Represented and split apart into a grid of tiles. diff --git a/src/app/gui/color.cc b/src/app/gui/color.cc index 7703969c..21cf2f59 100644 --- a/src/app/gui/color.cc +++ b/src/app/gui/color.cc @@ -13,9 +13,9 @@ namespace app { namespace gui { ImVec4 ConvertSNESColorToImVec4(const SnesColor& color) { - return ImVec4(static_cast(color.GetRGB().x) / 255.0f, - static_cast(color.GetRGB().y) / 255.0f, - static_cast(color.GetRGB().z) / 255.0f, + return ImVec4(static_cast(color.rgb().x) / 255.0f, + static_cast(color.rgb().y) / 255.0f, + static_cast(color.rgb().z) / 255.0f, 1.0f // Assuming alpha is always fully opaque for SNES colors, // adjust if necessary ); @@ -45,9 +45,9 @@ void DisplayPalette(app::gfx::SnesPalette& palette, bool loaded) { static ImVec4 saved_palette[32] = {}; if (loaded && !init) { for (int n = 0; n < palette.size(); n++) { - saved_palette[n].x = palette.GetColor(n).GetRGB().x / 255; - saved_palette[n].y = palette.GetColor(n).GetRGB().y / 255; - saved_palette[n].z = palette.GetColor(n).GetRGB().z / 255; + saved_palette[n].x = palette.GetColor(n).rgb().x / 255; + saved_palette[n].y = palette.GetColor(n).rgb().y / 255; + saved_palette[n].z = palette.GetColor(n).rgb().z / 255; saved_palette[n].w = 255; // Alpha } init = true; diff --git a/src/app/rom.cc b/src/app/rom.cc index f362b247..ddd036a7 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -35,7 +35,7 @@ absl::Status LoadOverworldMainPalettes(const Bytes& rom_data, auto data = rom_data.data(); for (int i = 0; i < 6; i++) { RETURN_IF_ERROR(palette_groups["ow_main"].AddPalette( - gfx::ReadPaletteFromROM(core::overworldPaletteMain + (i * (35 * 2)), + gfx::ReadPaletteFromRom(core::overworldPaletteMain + (i * (35 * 2)), /*num_colors*/ 35, data))) } return absl::OkStatus(); @@ -45,7 +45,7 @@ absl::Status LoadOverworldAuxiliaryPalettes(const Bytes& rom_data, PaletteGroupMap& palette_groups) { auto data = rom_data.data(); for (int i = 0; i < 20; i++) { - RETURN_IF_ERROR(palette_groups["ow_aux"].AddPalette(gfx::ReadPaletteFromROM( + RETURN_IF_ERROR(palette_groups["ow_aux"].AddPalette(gfx::ReadPaletteFromRom( core::overworldPaletteAuxialiary + (i * (21 * 2)), /*num_colors*/ 21, data))) } @@ -57,7 +57,7 @@ absl::Status LoadOverworldAnimatedPalettes(const Bytes& rom_data, auto data = rom_data.data(); for (int i = 0; i < 14; i++) { RETURN_IF_ERROR( - palette_groups["ow_animated"].AddPalette(gfx::ReadPaletteFromROM( + palette_groups["ow_animated"].AddPalette(gfx::ReadPaletteFromRom( core::overworldPaletteAnimated + (i * (7 * 2)), 7, data))) } return absl::OkStatus(); @@ -68,7 +68,7 @@ absl::Status LoadHUDPalettes(const Bytes& rom_data, auto data = rom_data.data(); for (int i = 0; i < 2; i++) { RETURN_IF_ERROR(palette_groups["hud"].AddPalette( - gfx::ReadPaletteFromROM(core::hudPalettes + (i * 64), 32, data))) + gfx::ReadPaletteFromRom(core::hudPalettes + (i * 64), 32, data))) } return absl::OkStatus(); } @@ -77,9 +77,9 @@ absl::Status LoadGlobalSpritePalettes(const Bytes& rom_data, PaletteGroupMap& palette_groups) { auto data = rom_data.data(); RETURN_IF_ERROR(palette_groups["global_sprites"].AddPalette( - gfx::ReadPaletteFromROM(core::globalSpritePalettesLW, 60, data))) + gfx::ReadPaletteFromRom(core::globalSpritePalettesLW, 60, data))) RETURN_IF_ERROR(palette_groups["global_sprites"].AddPalette( - gfx::ReadPaletteFromROM(core::globalSpritePalettesDW, 60, data))) + gfx::ReadPaletteFromRom(core::globalSpritePalettesDW, 60, data))) return absl::OkStatus(); } @@ -88,7 +88,7 @@ absl::Status LoadArmorPalettes(const Bytes& rom_data, auto data = rom_data.data(); for (int i = 0; i < 5; i++) { RETURN_IF_ERROR(palette_groups["armors"].AddPalette( - gfx::ReadPaletteFromROM(core::armorPalettes + (i * 30), 15, data))) + gfx::ReadPaletteFromRom(core::armorPalettes + (i * 30), 15, data))) } return absl::OkStatus(); } @@ -98,7 +98,7 @@ absl::Status LoadSwordPalettes(const Bytes& rom_data, auto data = rom_data.data(); for (int i = 0; i < 4; i++) { RETURN_IF_ERROR(palette_groups["swords"].AddPalette( - gfx::ReadPaletteFromROM(core::swordPalettes + (i * 6), 3, data))) + gfx::ReadPaletteFromRom(core::swordPalettes + (i * 6), 3, data))) } return absl::OkStatus(); } @@ -108,7 +108,7 @@ absl::Status LoadShieldPalettes(const Bytes& rom_data, auto data = rom_data.data(); for (int i = 0; i < 3; i++) { RETURN_IF_ERROR(palette_groups["shields"].AddPalette( - gfx::ReadPaletteFromROM(core::shieldPalettes + (i * 8), 4, data))) + gfx::ReadPaletteFromRom(core::shieldPalettes + (i * 8), 4, data))) } return absl::OkStatus(); } @@ -118,7 +118,7 @@ absl::Status LoadSpriteAux1Palettes(const Bytes& rom_data, auto data = rom_data.data(); for (int i = 0; i < 12; i++) { RETURN_IF_ERROR(palette_groups["sprites_aux1"].AddPalette( - gfx::ReadPaletteFromROM(core::spritePalettesAux1 + (i * 14), 7, data))) + gfx::ReadPaletteFromRom(core::spritePalettesAux1 + (i * 14), 7, data))) } return absl::OkStatus(); } @@ -128,7 +128,7 @@ absl::Status LoadSpriteAux2Palettes(const Bytes& rom_data, auto data = rom_data.data(); for (int i = 0; i < 11; i++) { RETURN_IF_ERROR(palette_groups["sprites_aux2"].AddPalette( - gfx::ReadPaletteFromROM(core::spritePalettesAux2 + (i * 14), 7, data))) + gfx::ReadPaletteFromRom(core::spritePalettesAux2 + (i * 14), 7, data))) } return absl::OkStatus(); } @@ -138,7 +138,7 @@ absl::Status LoadSpriteAux3Palettes(const Bytes& rom_data, auto data = rom_data.data(); for (int i = 0; i < 24; i++) { RETURN_IF_ERROR(palette_groups["sprites_aux3"].AddPalette( - gfx::ReadPaletteFromROM(core::spritePalettesAux3 + (i * 14), 7, data))) + gfx::ReadPaletteFromRom(core::spritePalettesAux3 + (i * 14), 7, data))) } return absl::OkStatus(); } @@ -148,7 +148,7 @@ absl::Status LoadDungeonMainPalettes(const Bytes& rom_data, auto data = rom_data.data(); for (int i = 0; i < 20; i++) { RETURN_IF_ERROR( - palette_groups["dungeon_main"].AddPalette(gfx::ReadPaletteFromROM( + palette_groups["dungeon_main"].AddPalette(gfx::ReadPaletteFromRom( core::dungeonMainPalettes + (i * 180), 90, data))) } return absl::OkStatus(); @@ -169,9 +169,9 @@ absl::Status Load3DObjectPalettes(const Bytes& rom_data, PaletteGroupMap& palette_groups) { auto data = rom_data.data(); RETURN_IF_ERROR(palette_groups["3d_object"].AddPalette( - gfx::ReadPaletteFromROM(core::triforcePalette, 8, data))) + gfx::ReadPaletteFromRom(core::triforcePalette, 8, data))) RETURN_IF_ERROR(palette_groups["3d_object"].AddPalette( - gfx::ReadPaletteFromROM(core::crystalPalette, 8, data))) + gfx::ReadPaletteFromRom(core::crystalPalette, 8, data))) return absl::OkStatus(); } @@ -180,7 +180,7 @@ absl::Status LoadOverworldMiniMapPalettes(const Bytes& rom_data, auto data = rom_data.data(); for (int i = 0; i < 2; i++) { RETURN_IF_ERROR( - palette_groups["ow_mini_map"].AddPalette(gfx::ReadPaletteFromROM( + palette_groups["ow_mini_map"].AddPalette(gfx::ReadPaletteFromRom( core::overworldMiniMapPalettes + (i * 256), 128, data))) } return absl::OkStatus(); diff --git a/src/app/rom.h b/src/app/rom.h index acb92dbe..9994ad67 100644 --- a/src/app/rom.h +++ b/src/app/rom.h @@ -453,9 +453,8 @@ class ROM : public core::ExperimentFlags { } absl::Status WriteColor(uint32_t address, const gfx::SnesColor& color) { - uint16_t bgr = ((color.GetSNES() >> 10) & 0x1F) | - ((color.GetSNES() & 0x1F) << 10) | - (color.GetSNES() & 0x7C00); + uint16_t bgr = ((color.snes() >> 10) & 0x1F) | + ((color.snes() & 0x1F) << 10) | (color.snes() & 0x7C00); // Write the 16-bit color value to the ROM at the specified address core::Logger::log(absl::StrFormat("WriteColor: %#06X: %s", address, @@ -561,9 +560,9 @@ class ROM : public core::ExperimentFlags { } } - void UpdateBitmap(gfx::Bitmap* bitmap) { + void UpdateBitmap(gfx::Bitmap* bitmap, bool use_sdl_update = false) { if (flags()->kLoadTexturesAsStreaming) { - bitmap->UpdateTexture(renderer_.get()); + bitmap->UpdateTexture(renderer_.get(), use_sdl_update); } else { bitmap->UpdateTexture(renderer_); }