diff --git a/src/app/editor/master_editor.cc b/src/app/editor/master_editor.cc index e3987b0d..07b853de 100644 --- a/src/app/editor/master_editor.cc +++ b/src/app/editor/master_editor.cc @@ -103,6 +103,7 @@ void MasterEditor::DrawFileDialog() { status_ = rom_.LoadFromFile(filePathName); overworld_editor_.SetupROM(rom_); screen_editor_.SetupROM(rom_); + palette_editor_.SetupROM(rom_); } ImGuiFileDialog::Instance()->Close(); } diff --git a/src/app/editor/overworld_editor.cc b/src/app/editor/overworld_editor.cc index 98a3077e..36448510 100644 --- a/src/app/editor/overworld_editor.cc +++ b/src/app/editor/overworld_editor.cc @@ -95,7 +95,7 @@ absl::Status OverworldEditor::Update() { } absl::Status OverworldEditor::DrawToolset() { - if (ImGui::BeginTable("OWToolset", 15, toolset_table_flags, ImVec2(0, 0))) { + if (ImGui::BeginTable("OWToolset", 17, toolset_table_flags, ImVec2(0, 0))) { for (const auto &name : kToolsetColumnNames) ImGui::TableSetupColumn(name.data()); @@ -134,6 +134,13 @@ absl::Status OverworldEditor::DrawToolset() { ImGui::TableNextColumn(); ImGui::Button(ICON_MD_MUSIC_NOTE); + // Separator + ImGui::TableNextColumn(); + ImGui::Text(ICON_MD_MORE_VERT); + // Music + ImGui::TableNextColumn(); + palette_editor_.DisplayPalette(palette_, overworld_.isLoaded()); + ImGui::EndTable(); } return absl::OkStatus(); diff --git a/src/app/editor/overworld_editor.h b/src/app/editor/overworld_editor.h index 2a4a07ac..7e0b83f3 100644 --- a/src/app/editor/overworld_editor.h +++ b/src/app/editor/overworld_editor.h @@ -9,6 +9,7 @@ #include "absl/container/flat_hash_map.h" #include "absl/status/status.h" #include "absl/status/statusor.h" +#include "app/editor/palette_editor.h" #include "app/gfx/bitmap.h" #include "app/gfx/snes_palette.h" #include "app/gfx/snes_tile.h" @@ -88,6 +89,7 @@ class OverworldEditor { ROM rom_; zelda3::Overworld overworld_; + PaletteEditor palette_editor_; gfx::SNESPalette palette_; gfx::Bitmap tile16_blockset_bmp_; diff --git a/src/app/editor/palette_editor.cc b/src/app/editor/palette_editor.cc index e22f88a6..ca676fe3 100644 --- a/src/app/editor/palette_editor.cc +++ b/src/app/editor/palette_editor.cc @@ -12,10 +12,28 @@ namespace app { namespace editor { absl::Status PaletteEditor::Update() { - for (const auto &name : kPaletteCategoryNames) { - if (ImGui::TreeNode(name.data())) { - ImGui::SameLine(); - if (ImGui::SmallButton("button")) { + for (int i = 0; i < 11; ++i) { + if (ImGui::TreeNode(kPaletteCategoryNames[i].data())) { + auto size = rom_.GetPaletteGroup(kPaletteGroupNames[i].data()).size; + auto palettes = rom_.GetPaletteGroup(kPaletteGroupNames[i].data()); + for (int j = 0; j < size; j++) { + ImGui::Text("%d", j); + auto palette = palettes[j]; + for (int n = 0; n < size; n++) { + ImGui::PushID(n); + if ((n % 8) != 0) + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); + + ImGuiColorEditFlags palette_button_flags = + ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker; + if (ImGui::ColorButton("##palette", palette[n].RGB(), + palette_button_flags, ImVec2(20, 20))) + current_color_ = + ImVec4(palette[n].rgb.x, palette[n].rgb.y, palette[n].rgb.z, + current_color_.w); // Preserve alpha! + + ImGui::PopID(); + } } ImGui::TreePop(); } @@ -23,6 +41,90 @@ absl::Status PaletteEditor::Update() { return absl::OkStatus(); } +absl::Status PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, + bool loaded) { + static ImVec4 color = ImVec4(0, 0, 0, 255.f); + ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview | + ImGuiColorEditFlags_NoDragDrop | + ImGuiColorEditFlags_NoOptions; + + // Generate a default palette. The palette will persist and can be edited. + static bool init = false; + static ImVec4 saved_palette[256] = {}; + if (loaded && !init) { + for (int n = 0; n < palette.size_; n++) { + 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; + } + + static ImVec4 backup_color; + bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags); + ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x); + open_popup |= ImGui::Button("Palette"); + if (open_popup) { + ImGui::OpenPopup("mypicker"); + backup_color = color; + } + if (ImGui::BeginPopup("mypicker")) { + ImGui::Text("Current Overworld Palette"); + ImGui::Separator(); + ImGui::ColorPicker4("##picker", (float*)&color, + misc_flags | ImGuiColorEditFlags_NoSidePreview | + ImGuiColorEditFlags_NoSmallPreview); + ImGui::SameLine(); + + ImGui::BeginGroup(); // Lock X position + ImGui::Text("Current ==>"); + ImGui::SameLine(); + ImGui::Text("Previous"); + + ImGui::ColorButton( + "##current", color, + ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, + ImVec2(60, 40)); + ImGui::SameLine(); + + if (ImGui::ColorButton( + "##previous", backup_color, + ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, + ImVec2(60, 40))) + color = backup_color; + ImGui::Separator(); + ImGui::Text("Palette"); + for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) { + ImGui::PushID(n); + if ((n % 8) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); + + ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | + ImGuiColorEditFlags_NoPicker | + ImGuiColorEditFlags_NoTooltip; + if (ImGui::ColorButton("##palette", saved_palette[n], + palette_button_flags, ImVec2(20, 20))) + color = ImVec4(saved_palette[n].x, saved_palette[n].y, + saved_palette[n].z, color.w); // Preserve alpha! + + if (ImGui::BeginDragDropTarget()) { + if (const ImGuiPayload* payload = + ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) + memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3); + if (const ImGuiPayload* payload = + ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F)) + memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4); + ImGui::EndDragDropTarget(); + } + + ImGui::PopID(); + } + ImGui::EndGroup(); + ImGui::EndPopup(); + } + return absl::OkStatus(); +} + } // namespace editor } // namespace app } // namespace yaze \ No newline at end of file diff --git a/src/app/editor/palette_editor.h b/src/app/editor/palette_editor.h index 939d2d55..d27551b8 100644 --- a/src/app/editor/palette_editor.h +++ b/src/app/editor/palette_editor.h @@ -5,6 +5,7 @@ #include "absl/status/status.h" #include "app/gfx/snes_palette.h" +#include "app/rom.h" #include "gui/canvas.h" #include "gui/icons.h" @@ -17,11 +18,21 @@ static constexpr absl::string_view kPaletteCategoryNames[] = { "Area Colors", "Enemies", "Dungeons", "World Map", "Dungeon Map", "Triforce", "Crystal"}; +static constexpr absl::string_view kPaletteGroupNames[] = { + "swords", "shields", "armors", "ow_main", + "ow_aux", "global_sprites", "dungeon_main", "ow_mini_map", + "ow_mini_map", "3d_object", "3d_object"}; + class PaletteEditor { public: absl::Status Update(); + absl::Status DisplayPalette(gfx::SNESPalette& palette, bool loaded); + + auto SetupROM(ROM& rom) { rom_ = rom; } private: + ImVec4 current_color_; + ROM rom_; }; } // namespace editor diff --git a/src/app/gfx/bitmap.cc b/src/app/gfx/bitmap.cc index c8e6a21d..0b5f7989 100644 --- a/src/app/gfx/bitmap.cc +++ b/src/app/gfx/bitmap.cc @@ -107,12 +107,15 @@ void Bitmap::ApplyPalette(const SNESPalette &palette) { palette_ = palette; for (int i = 0; i < palette.size_; ++i) { if (palette.GetColor(i).transparent) { + surface_->format->palette->colors[i].r = 0; + surface_->format->palette->colors[i].g = 0; + surface_->format->palette->colors[i].b = 0; surface_->format->palette->colors[i].a = 0; } else { surface_->format->palette->colors[i].r = palette.GetColor(i).rgb.x; surface_->format->palette->colors[i].g = palette.GetColor(i).rgb.y; surface_->format->palette->colors[i].b = palette.GetColor(i).rgb.z; - surface_->format->palette->colors[i].a = 255; + surface_->format->palette->colors[i].a = palette.GetColor(i).rgb.w; } } } diff --git a/src/app/gfx/snes_palette.cc b/src/app/gfx/snes_palette.cc index c3fad32a..5ff1c878 100644 --- a/src/app/gfx/snes_palette.cc +++ b/src/app/gfx/snes_palette.cc @@ -66,8 +66,8 @@ SNESColor::SNESColor() : rgb(ImVec4(0.f, 0.f, 0.f, 0.f)) {} SNESColor::SNESColor(snes_color val) { rgb.x = val.red; - rgb.y = val.blue; - rgb.z = val.green; + rgb.y = val.green; + rgb.z = val.blue; } SNESColor::SNESColor(ImVec4 val) : rgb(val) { @@ -88,13 +88,13 @@ void SNESColor::setRgb(ImVec4 val) { } void SNESColor::setSNES(snes_color val) { - rgb = ImVec4(val.red, val.green, val.blue, 1.f); + rgb = ImVec4(val.red, val.green, val.blue, 255.f); } void SNESColor::setSNES(uint16_t val) { snes = val; snes_color col = ConvertSNEStoRGB(val); - rgb = ImVec4(col.red, col.green, col.blue, 1.f); + rgb = ImVec4(col.red, col.green, col.blue, 0.f); } // ============================================================================ diff --git a/src/app/gfx/snes_palette.h b/src/app/gfx/snes_palette.h index f0481184..1c0e4143 100644 --- a/src/app/gfx/snes_palette.h +++ b/src/app/gfx/snes_palette.h @@ -47,6 +47,10 @@ struct SNESColor { void setSNES(uint16_t); void setTransparent(bool t) { transparent = t; } + auto RGB() { + return ImVec4(rgb.x / 255, rgb.y / 255, rgb.z / 255, rgb.w); + } + bool transparent = false; uint16_t snes = 0; ImVec4 rgb;