21 if (ImGui::BeginPopupModal(title.c_str(),
nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
22 ImGui::Text(
"Enhanced Palette Editor");
31 if (ImGui::CollapsingHeader(
"Palette Analysis")) {
35 if (ImGui::CollapsingHeader(
"ROM Palette Manager") &&
rom_) {
48 if (ImGui::Button(
"Save Backup")) {
52 if (ImGui::Button(
"Restore Backup")) {
56 if (ImGui::Button(
"Close")) {
57 ImGui::CloseCurrentPopup();
69 ImGui::Text(
"No ROM loaded");
97 ImGui::Text(
"Bitmap Color Analysis");
101 ImGui::Text(
"Bitmap is not active");
107 std::map<uint8_t, int> pixel_counts;
108 const auto& data = bitmap.
vector();
110 for (uint8_t pixel : data) {
111 uint8_t palette_index = pixel & 0x0F;
112 pixel_counts[palette_index]++;
115 ImGui::Text(
"Bitmap Size: %d x %d (%zu pixels)",
119 ImGui::Text(
"Pixel Distribution:");
122 int total_pixels =
static_cast<int>(data.size());
123 for (
const auto& [index, count] : pixel_counts) {
124 float percentage = (
static_cast<float>(count) / total_pixels) * 100.0f;
125 ImGui::Text(
"Index %d: %d pixels (%.1f%%)", index, count, percentage);
129 ImGui::ProgressBar(percentage / 100.0f, ImVec2(100, 0));
132 if (index <
static_cast<int>(bitmap.
palette().
size())) {
134 auto color = bitmap.
palette()[index];
135 ImVec4 display_color = color.rgb();
136 ImGui::ColorButton((
"##color" + std::to_string(index)).c_str(),
137 display_color, ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20));
138 if (ImGui::IsItemHovered()) {
139 ImGui::SetTooltip(
"SNES Color: 0x%04X\nRGB: (%d, %d, %d)",
141 static_cast<int>(display_color.x * 255),
142 static_cast<int>(display_color.y * 255),
143 static_cast<int>(display_color.z * 255));
164 if (palette_index >= 0 && palette_index < 8) {
179 }
catch (
const std::exception& e) {
207 for (
int i = 0; i < static_cast<int>(palette.
size()); i++) {
208 if (i % cols != 0) ImGui::SameLine();
210 auto color = palette[i];
211 ImVec4 display_color = color.rgb();
216 if (ImGui::ColorButton(
"##color", display_color,
217 ImGuiColorEditFlags_NoTooltip, ImVec2(30, 30))) {
223 if (ImGui::BeginPopupContextItem()) {
224 ImGui::Text(
"Color %d (0x%04X)", i, color.snes());
227 if (ImGui::MenuItem(
"Edit Color")) {
232 if (ImGui::MenuItem(
"Copy Color")) {
236 if (ImGui::MenuItem(
"Reset to Black")) {
244 if (ImGui::IsItemHovered()) {
245 ImGui::SetTooltip(
"Color %d\nSNES: 0x%04X\nRGB: (%d, %d, %d)\nClick to edit",
247 static_cast<int>(display_color.x * 255),
248 static_cast<int>(display_color.y * 255),
249 static_cast<int>(display_color.z * 255));
257 ImGui::OpenPopup(
"Edit Color");
259 if (ImGui::BeginPopupModal(
"Edit Color",
nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
263 ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_DisplayRGB)) {
269 if (ImGui::Button(
"Apply")) {
271 ImGui::CloseCurrentPopup();
274 if (ImGui::Button(
"Cancel")) {
276 ImGui::CloseCurrentPopup();
290 ImGui::Text(
"No ROM palettes available");
295 ImGui::Text(
"Palette Group:");
297 [](
void* data,
int idx,
const char** out_text) ->
bool {
298 auto* names =
static_cast<std::vector<std::string>*
>(data);
299 if (idx < 0 || idx >=
static_cast<int>(names->size()))
return false;
300 *out_text = (*names)[idx].c_str();
307 ImGui::Text(
"Palette Index:");
312 ImGui::Text(
"Preview:");
316 for (
int i = 0; i < 8 && i < static_cast<int>(preview_palette.size()); i++) {
317 if (i > 0) ImGui::SameLine();
318 auto color = preview_palette[i];
319 ImVec4 display_color = color.rgb();
320 ImGui::ColorButton((
"##preview" + std::to_string(i)).c_str(),
321 display_color, ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20));
327 ImVec4 rgba = color.
rgb();
329 ImGui::PushID(color_index);
331 if (ImGui::ColorEdit4(
"##color_edit", &rgba.x,
332 ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_DisplayRGB)) {
337 ImGui::Text(
"SNES Color: 0x%04X", color.
snes());
340 int r = (color.
snes() & 0x1F);
341 int g = (color.
snes() >> 5) & 0x1F;
342 int b = (color.
snes() >> 10) & 0x1F;
344 if (ImGui::SliderInt(
"Red", &r, 0, 31)) {
345 uint16_t new_color = (color.
snes() & 0xFFE0) | (r & 0x1F);
349 if (ImGui::SliderInt(
"Green", &g, 0, 31)) {
350 uint16_t new_color = (color.
snes() & 0xFC1F) | ((g & 0x1F) << 5);
354 if (ImGui::SliderInt(
"Blue", &b, 0, 31)) {
355 uint16_t new_color = (color.
snes() & 0x83FF) | ((b & 0x1F) << 10);
363 ImGui::Text(
"Palette Information:");
364 ImGui::Text(
"Size: %zu colors", palette.
size());
367 std::map<uint16_t, int> color_frequency;
368 for (
int i = 0; i < static_cast<int>(palette.
size()); i++) {
369 color_frequency[palette[i].snes()]++;
372 ImGui::Text(
"Unique Colors: %zu", color_frequency.size());
374 if (color_frequency.size() < palette.
size()) {
375 ImGui::TextColored(ImVec4(1, 1, 0, 1),
"Warning: Duplicate colors detected!");
377 if (ImGui::TreeNode(
"Duplicate Colors")) {
378 for (
const auto& [
snes_color, count] : color_frequency) {
381 ImGui::ColorButton((
"##dup" + std::to_string(
snes_color)).c_str(),
382 display_color, ImGuiColorEditFlags_NoTooltip, ImVec2(16, 16));
384 ImGui::Text(
"0x%04X appears %d times",
snes_color, count);
392 float total_brightness = 0.0f;
393 float min_brightness = 1.0f;
394 float max_brightness = 0.0f;
396 for (
int i = 0; i < static_cast<int>(palette.
size()); i++) {
397 ImVec4 color = palette[i].rgb();
398 float brightness = (color.x + color.y + color.z) / 3.0f;
399 total_brightness += brightness;
400 min_brightness = std::min(min_brightness, brightness);
401 max_brightness = std::max(max_brightness, brightness);
404 float avg_brightness = total_brightness / palette.
size();
407 ImGui::Text(
"Brightness Analysis:");
408 ImGui::Text(
"Average: %.2f", avg_brightness);
409 ImGui::Text(
"Range: %.2f - %.2f", min_brightness, max_brightness);
412 ImGui::Text(
"Brightness Distribution:");
413 ImGui::ProgressBar(avg_brightness, ImVec2(-1, 0),
"Avg");
425 if (palette_groups.overworld_main.size() > 0) {
429 if (palette_groups.overworld_aux.size() > 0) {
433 if (palette_groups.overworld_animated.size() > 0) {
437 if (palette_groups.dungeon_main.size() > 0) {
441 if (palette_groups.global_sprites.size() > 0) {
445 if (palette_groups.armors.size() > 0) {
449 if (palette_groups.swords.size() > 0) {
456 }
catch (
const std::exception& e) {
457 LOG_ERROR(
"Enhanced Palette Editor",
"Failed to load ROM palettes");
The Rom class is used to load, save, and modify Rom data.
auto palette_group() const
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.
void SetPaletteWithTransparent(const SnesPalette &palette, size_t index, int length=7)
Set the palette with a transparent color.
constexpr ImVec4 rgb() const
constexpr uint16_t snes() const
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
#define LOG_ERROR(category, format,...)
Main namespace for the application.
SNES color in 15-bit RGB format (BGR555)