6#include "absl/strings/str_format.h"
43 ImGui::TextColored(ImVec4(1, 0, 0, 1),
"GameData not loaded");
65 ImGui::TextDisabled(
"Select a color to edit");
75 int num_palettes = dungeon_pal_group.
size();
77 ImGui::Text(
"Dungeon Palette:");
80 if (ImGui::BeginCombo(
83 for (
int i = 0; i < num_palettes; i++) {
85 if (ImGui::Selectable(absl::StrFormat(
"Palette %d", i).c_str(),
91 ImGui::SetItemDefaultFocus();
101 ImGui::SeparatorText(
111 ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_PickerHueWheel)) {
125 ImGui::Text(
"RGB (0-255): (%d, %d, %d)",
129 ImGui::Text(
"SNES BGR555: 0x%04X", original_color.snes());
133 ImVec4(original_color.rgb().x / 255.0f, original_color.rgb().y / 255.0f,
134 original_color.rgb().z / 255.0f, 1.0f);
147 const std::string& title) {
148 if (ImGui::BeginPopupModal(title.c_str(),
nullptr,
149 ImGuiWindowFlags_AlwaysAutoResize)) {
150 ImGui::Text(
"Enhanced Palette Editor");
156 if (ImGui::CollapsingHeader(
"Palette Analysis")) {
160 if (ImGui::CollapsingHeader(
"ROM Palette Manager") &&
rom_) {
182 ImGui::CloseCurrentPopup();
195 ImGui::Text(
"No ROM loaded");
208 ImGui::Text(
"Preview of %s:",
220 const std::string& title) {
225 ImGui::Text(
"Bitmap Color Analysis");
229 ImGui::Text(
"Bitmap is not active");
234 std::map<uint8_t, int> pixel_counts;
235 const auto& data = bitmap.
vector();
237 for (uint8_t pixel : data) {
238 uint8_t palette_index = pixel & 0x0F;
239 pixel_counts[palette_index]++;
242 ImGui::Text(
"Bitmap Size: %d x %d (%zu pixels)", bitmap.
width(),
243 bitmap.
height(), data.size());
246 ImGui::Text(
"Pixel Distribution:");
248 int total_pixels =
static_cast<int>(data.size());
252 .x_label =
"Palette Index",
254 .flags = ImPlotFlags_NoBoxSelect,
255 .x_axis_flags = ImPlotAxisFlags_AutoFit,
256 .y_axis_flags = ImPlotAxisFlags_AutoFit};
257 std::vector<double> x;
258 std::vector<double> y;
259 x.reserve(pixel_counts.size());
260 y.reserve(pixel_counts.size());
261 for (
const auto& [index, count] : pixel_counts) {
262 x.push_back(
static_cast<double>(index));
263 y.push_back(
static_cast<double>(count));
266 if (plot && !x.empty()) {
267 ImPlot::PlotBars(
"Usage", x.data(), y.data(),
static_cast<int>(x.size()),
268 0.67, 0.0, ImPlotBarsFlags_None);
285 if (palette_index >= 0 && palette_index < 8) {
297 }
catch (
const std::exception& e) {
324 for (
int i = 0; i < static_cast<int>(palette.
size()); i++) {
328 auto color = palette[i];
329 ImVec4 display_color = color.rgb();
332 if (ImGui::ColorButton(
"##color", display_color,
333 ImGuiColorEditFlags_NoTooltip, ImVec2(30, 30))) {
340 if (ImGui::BeginPopupContextItem()) {
341 ImGui::Text(
"Color %d (0x%04X)", i, color.snes());
343 if (ImGui::MenuItem(
"Edit Color")) {
349 if (ImGui::MenuItem(
"Reset to Black")) {
355 if (ImGui::IsItemHovered()) {
356 ImGui::SetTooltip(
"Color %d\nSNES: 0x%04X\nRGB: (%d, %d, %d)", i,
357 color.snes(),
static_cast<int>(display_color.x * 255),
358 static_cast<int>(display_color.y * 255),
359 static_cast<int>(display_color.z * 255));
367 std::string popup_id =
370 ImGui::OpenPopup(popup_id.c_str());
371 if (ImGui::BeginPopupModal(popup_id.c_str(),
nullptr,
372 ImGuiWindowFlags_AlwaysAutoResize)) {
374 if (ImGui::ColorEdit4(
376 ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_DisplayRGB)) {
382 ImGui::CloseCurrentPopup();
387 ImGui::CloseCurrentPopup();
400 ImGui::Text(
"No ROM palettes available");
404 ImGui::Text(
"Palette Group:");
407 [](
void* data,
int idx,
const char** out_text) ->
bool {
408 auto* names =
static_cast<std::vector<std::string>*
>(data);
409 if (idx < 0 || idx >=
static_cast<int>(names->size()))
411 *out_text = (*names)[idx].c_str();
417 ImGui::Text(
"Palette Index:");
421 ImGui::Text(
"Preview:");
423 for (
int i = 0; i < 8 && i < static_cast<int>(preview_palette.size());
427 auto color = preview_palette[i];
428 ImVec4 display_color = color.rgb();
429 ImGui::ColorButton((
"##preview" + std::to_string(i)).c_str(),
430 display_color, ImGuiColorEditFlags_NoTooltip,
438 ImVec4 rgba = color.
rgb();
440 ImGui::PushID(color_index);
442 if (ImGui::ColorEdit4(
443 "##color_edit", &rgba.x,
444 ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_DisplayRGB)) {
448 ImGui::Text(
"SNES Color: 0x%04X", color.
snes());
450 int r = (color.
snes() & 0x1F);
451 int g = (color.
snes() >> 5) & 0x1F;
452 int b = (color.
snes() >> 10) & 0x1F;
454 if (ImGui::SliderInt(
"Red", &r, 0, 31)) {
455 uint16_t new_color = (color.
snes() & 0xFFE0) | (r & 0x1F);
458 if (ImGui::SliderInt(
"Green", &g, 0, 31)) {
459 uint16_t new_color = (color.
snes() & 0xFC1F) | ((g & 0x1F) << 5);
462 if (ImGui::SliderInt(
"Blue", &b, 0, 31)) {
463 uint16_t new_color = (color.
snes() & 0x83FF) | ((b & 0x1F) << 10);
471 ImGui::Text(
"Palette Information:");
472 ImGui::Text(
"Size: %zu colors", palette.
size());
474 std::map<uint16_t, int> color_frequency;
475 for (
int i = 0; i < static_cast<int>(palette.
size()); i++) {
476 color_frequency[palette[i].snes()]++;
479 ImGui::Text(
"Unique Colors: %zu", color_frequency.size());
481 if (color_frequency.size() < palette.
size()) {
482 ImGui::TextColored(ImVec4(1, 1, 0, 1),
483 "Warning: Duplicate colors detected!");
484 if (ImGui::TreeNode(
"Duplicate Colors")) {
485 for (
const auto& [
snes_color, count] : color_frequency) {
488 ImGui::ColorButton((
"##dup" + std::to_string(
snes_color)).c_str(),
489 display_color, ImGuiColorEditFlags_NoTooltip,
492 ImGui::Text(
"0x%04X appears %d times",
snes_color, count);
504 .x_label =
"Color Index",
506 .flags = ImPlotFlags_NoBoxSelect,
507 .x_axis_flags = ImPlotAxisFlags_AutoFit,
508 .y_axis_flags = ImPlotAxisFlags_AutoFit};
509 std::vector<double> x;
510 std::vector<double> y;
511 x.reserve(color_frequency.size());
512 y.reserve(color_frequency.size());
513 for (
const auto& [
snes_color, count] : color_frequency) {
515 y.push_back(
static_cast<double>(count));
518 if (plot && !x.empty()) {
519 ImPlot::PlotBars(
"Count", x.data(), y.data(),
static_cast<int>(x.size()),
520 0.5, 0.0, ImPlotBarsFlags_None);
524 float total_brightness = 0.0f;
525 float min_brightness = 1.0f;
526 float max_brightness = 0.0f;
528 for (
int i = 0; i < static_cast<int>(palette.
size()); i++) {
529 ImVec4 color = palette[i].rgb();
530 float brightness = (color.x + color.y + color.z) / 3.0f;
531 total_brightness += brightness;
532 min_brightness = std::min(min_brightness, brightness);
533 max_brightness = std::max(max_brightness, brightness);
536 float avg_brightness = total_brightness / palette.
size();
539 ImGui::Text(
"Brightness Analysis:");
540 ImGui::Text(
"Average: %.2f", avg_brightness);
541 ImGui::Text(
"Range: %.2f - %.2f", min_brightness, max_brightness);
543 ImGui::Text(
"Brightness Distribution:");
544 ImGui::ProgressBar(avg_brightness, ImVec2(-1, 0),
"Avg");
556 if (palette_groups.overworld_main.size() > 0) {
560 if (palette_groups.overworld_aux.size() > 0) {
564 if (palette_groups.overworld_animated.size() > 0) {
568 if (palette_groups.dungeon_main.size() > 0) {
572 if (palette_groups.global_sprites.size() > 0) {
576 if (palette_groups.armors.size() > 0) {
580 if (palette_groups.swords.size() > 0) {
586 }
catch (
const std::exception& e) {
587 LOG_ERROR(
"Enhanced Palette Editor",
"Failed to load ROM palettes");
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
Represents a bitmap image optimized for SNES ROM hacking.
const SnesPalette & palette() const
const std::vector< uint8_t > & vector() const
void SetPalette(const SnesPalette &palette)
Set the palette for the bitmap using SNES palette format.
void SetPaletteWithTransparent(const SnesPalette &palette, size_t index, int length=7)
Set the palette with a transparent color.
constexpr ImVec4 rgb() const
Get RGB values (WARNING: stored as 0-255 in ImVec4)
constexpr uint16_t snes() const
Get SNES 15-bit color.
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
static ThemeManager & Get()
#define LOG_ERROR(category, format,...)
bool PrimaryButton(const char *label, const ImVec2 &size, const char *panel_id, const char *anim_id)
Draw a primary action button (accented color).
std::string MakePopupIdWithInstance(const std::string &editor_name, const std::string &popup_name, const void *instance)
Generate popup ID with instance pointer for guaranteed uniqueness.
bool ThemedButton(const char *label, const ImVec2 &size, const char *panel_id, const char *anim_id)
Draw a standard text button with theme colors.
ImVec4 ConvertSnesColorToImVec4(const gfx::SnesColor &color)
Convert SnesColor to standard ImVec4 for display.
IMGUI_API bool SnesColorEdit4(absl::string_view label, gfx::SnesColor *color, ImGuiColorEditFlags flags)
SNES color in 15-bit RGB format (BGR555)
PaletteGroup dungeon_main
gfx::PaletteGroupMap palette_groups