6#include "absl/strings/str_format.h"
42 ImGui::TextColored(ImVec4(1, 0, 0, 1),
"GameData not loaded");
64 ImGui::TextDisabled(
"Select a color to edit");
73 int num_palettes = dungeon_pal_group.
size();
75 ImGui::Text(
"Dungeon Palette:");
78 if (ImGui::BeginCombo(
81 for (
int i = 0; i < num_palettes; i++) {
83 if (ImGui::Selectable(absl::StrFormat(
"Palette %d", i).c_str(),
89 ImGui::SetItemDefaultFocus();
108 ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_PickerHueWheel)) {
122 ImGui::Text(
"RGB (0-255): (%d, %d, %d)",
126 ImGui::Text(
"SNES BGR555: 0x%04X", original_color.snes());
128 if (ImGui::Button(
"Reset to Original")) {
130 original_color.rgb().y / 255.0f,
131 original_color.rgb().z / 255.0f, 1.0f);
144 const std::string& title) {
145 if (ImGui::BeginPopupModal(title.c_str(),
nullptr,
146 ImGuiWindowFlags_AlwaysAutoResize)) {
147 ImGui::Text(
"Enhanced Palette Editor");
153 if (ImGui::CollapsingHeader(
"Palette Analysis")) {
157 if (ImGui::CollapsingHeader(
"ROM Palette Manager") &&
rom_) {
170 if (ImGui::Button(
"Save Backup")) {
174 if (ImGui::Button(
"Restore Backup")) {
178 if (ImGui::Button(
"Close")) {
179 ImGui::CloseCurrentPopup();
191 ImGui::Text(
"No ROM loaded");
204 ImGui::Text(
"Preview of %s:",
216 const std::string& title) {
220 ImGui::Text(
"Bitmap Color Analysis");
224 ImGui::Text(
"Bitmap is not active");
229 std::map<uint8_t, int> pixel_counts;
230 const auto& data = bitmap.
vector();
232 for (uint8_t pixel : data) {
233 uint8_t palette_index = pixel & 0x0F;
234 pixel_counts[palette_index]++;
237 ImGui::Text(
"Bitmap Size: %d x %d (%zu pixels)", bitmap.
width(),
238 bitmap.
height(), data.size());
241 ImGui::Text(
"Pixel Distribution:");
243 int total_pixels =
static_cast<int>(data.size());
246 .
id =
"Pixel Distribution",
247 .x_label =
"Palette Index",
249 .flags = ImPlotFlags_NoBoxSelect,
250 .x_axis_flags = ImPlotAxisFlags_AutoFit,
251 .y_axis_flags = ImPlotAxisFlags_AutoFit};
252 std::vector<double> x;
253 std::vector<double> y;
254 x.reserve(pixel_counts.size());
255 y.reserve(pixel_counts.size());
256 for (
const auto& [index, count] : pixel_counts) {
257 x.push_back(
static_cast<double>(index));
258 y.push_back(
static_cast<double>(count));
261 if (plot && !x.empty()) {
262 ImPlot::PlotBars(
"Usage", x.data(), y.data(),
static_cast<int>(x.size()),
263 0.67, 0.0, ImPlotBarsFlags_None);
280 if (palette_index >= 0 && palette_index < 8) {
292 }
catch (
const std::exception& e) {
319 for (
int i = 0; i < static_cast<int>(palette.
size()); i++) {
320 if (i % cols != 0) ImGui::SameLine();
322 auto color = palette[i];
323 ImVec4 display_color = color.rgb();
326 if (ImGui::ColorButton(
"##color", display_color,
327 ImGuiColorEditFlags_NoTooltip, ImVec2(30, 30))) {
334 if (ImGui::BeginPopupContextItem()) {
335 ImGui::Text(
"Color %d (0x%04X)", i, color.snes());
337 if (ImGui::MenuItem(
"Edit Color")) {
343 if (ImGui::MenuItem(
"Reset to Black")) {
349 if (ImGui::IsItemHovered()) {
350 ImGui::SetTooltip(
"Color %d\nSNES: 0x%04X\nRGB: (%d, %d, %d)", i,
351 color.snes(),
static_cast<int>(display_color.x * 255),
352 static_cast<int>(display_color.y * 255),
353 static_cast<int>(display_color.z * 255));
361 std::string popup_id =
364 ImGui::OpenPopup(popup_id.c_str());
365 if (ImGui::BeginPopupModal(popup_id.c_str(),
nullptr,
366 ImGuiWindowFlags_AlwaysAutoResize)) {
368 if (ImGui::ColorEdit4(
370 ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_DisplayRGB)) {
374 if (ImGui::Button(
"Apply")) {
376 ImGui::CloseCurrentPopup();
379 if (ImGui::Button(
"Cancel")) {
381 ImGui::CloseCurrentPopup();
394 ImGui::Text(
"No ROM palettes available");
398 ImGui::Text(
"Palette Group:");
401 [](
void* data,
int idx,
const char** out_text) ->
bool {
402 auto* names =
static_cast<std::vector<std::string>*
>(data);
403 if (idx < 0 || idx >=
static_cast<int>(names->size()))
405 *out_text = (*names)[idx].c_str();
411 ImGui::Text(
"Palette Index:");
415 ImGui::Text(
"Preview:");
417 for (
int i = 0; i < 8 && i < static_cast<int>(preview_palette.size());
421 auto color = preview_palette[i];
422 ImVec4 display_color = color.rgb();
423 ImGui::ColorButton((
"##preview" + std::to_string(i)).c_str(),
424 display_color, ImGuiColorEditFlags_NoTooltip,
432 ImVec4 rgba = color.
rgb();
434 ImGui::PushID(color_index);
436 if (ImGui::ColorEdit4(
437 "##color_edit", &rgba.x,
438 ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_DisplayRGB)) {
442 ImGui::Text(
"SNES Color: 0x%04X", color.
snes());
444 int r = (color.
snes() & 0x1F);
445 int g = (color.
snes() >> 5) & 0x1F;
446 int b = (color.
snes() >> 10) & 0x1F;
448 if (ImGui::SliderInt(
"Red", &r, 0, 31)) {
449 uint16_t new_color = (color.
snes() & 0xFFE0) | (r & 0x1F);
452 if (ImGui::SliderInt(
"Green", &g, 0, 31)) {
453 uint16_t new_color = (color.
snes() & 0xFC1F) | ((g & 0x1F) << 5);
456 if (ImGui::SliderInt(
"Blue", &b, 0, 31)) {
457 uint16_t new_color = (color.
snes() & 0x83FF) | ((b & 0x1F) << 10);
465 ImGui::Text(
"Palette Information:");
466 ImGui::Text(
"Size: %zu colors", palette.
size());
468 std::map<uint16_t, int> color_frequency;
469 for (
int i = 0; i < static_cast<int>(palette.
size()); i++) {
470 color_frequency[palette[i].snes()]++;
473 ImGui::Text(
"Unique Colors: %zu", color_frequency.size());
475 if (color_frequency.size() < palette.
size()) {
476 ImGui::TextColored(ImVec4(1, 1, 0, 1),
477 "Warning: Duplicate colors detected!");
478 if (ImGui::TreeNode(
"Duplicate Colors")) {
479 for (
const auto& [
snes_color, count] : color_frequency) {
482 ImGui::ColorButton((
"##dup" + std::to_string(
snes_color)).c_str(),
483 display_color, ImGuiColorEditFlags_NoTooltip,
486 ImGui::Text(
"0x%04X appears %d times",
snes_color, count);
497 .
id =
"Palette Color Frequency",
498 .x_label =
"Color Index",
500 .flags = ImPlotFlags_NoBoxSelect,
501 .x_axis_flags = ImPlotAxisFlags_AutoFit,
502 .y_axis_flags = ImPlotAxisFlags_AutoFit};
503 std::vector<double> x;
504 std::vector<double> y;
505 x.reserve(color_frequency.size());
506 y.reserve(color_frequency.size());
507 for (
const auto& [
snes_color, count] : color_frequency) {
509 y.push_back(
static_cast<double>(count));
512 if (plot && !x.empty()) {
513 ImPlot::PlotBars(
"Count", x.data(), y.data(),
static_cast<int>(x.size()),
514 0.5, 0.0, ImPlotBarsFlags_None);
518 float total_brightness = 0.0f;
519 float min_brightness = 1.0f;
520 float max_brightness = 0.0f;
522 for (
int i = 0; i < static_cast<int>(palette.
size()); i++) {
523 ImVec4 color = palette[i].rgb();
524 float brightness = (color.x + color.y + color.z) / 3.0f;
525 total_brightness += brightness;
526 min_brightness = std::min(min_brightness, brightness);
527 max_brightness = std::max(max_brightness, brightness);
530 float avg_brightness = total_brightness / palette.
size();
533 ImGui::Text(
"Brightness Analysis:");
534 ImGui::Text(
"Average: %.2f", avg_brightness);
535 ImGui::Text(
"Range: %.2f - %.2f", min_brightness, max_brightness);
537 ImGui::Text(
"Brightness Distribution:");
538 ImGui::ProgressBar(avg_brightness, ImVec2(-1, 0),
"Avg");
550 if (palette_groups.overworld_main.size() > 0) {
554 if (palette_groups.overworld_aux.size() > 0) {
558 if (palette_groups.overworld_animated.size() > 0) {
562 if (palette_groups.dungeon_main.size() > 0) {
566 if (palette_groups.global_sprites.size() > 0) {
570 if (palette_groups.armors.size() > 0) {
574 if (palette_groups.swords.size() > 0) {
580 }
catch (
const std::exception& e) {
581 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,...)
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.
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