3#include "absl/status/status.h"
4#include "absl/strings/str_cat.h"
8#include "imgui/imgui.h"
13using ImGui::AcceptDragDropPayload;
14using ImGui::BeginChild;
15using ImGui::BeginDragDropTarget;
16using ImGui::BeginGroup;
17using ImGui::BeginPopup;
18using ImGui::BeginPopupContextItem;
19using ImGui::BeginTable;
21using ImGui::ColorButton;
22using ImGui::ColorPicker4;
24using ImGui::EndDragDropTarget;
28using ImGui::GetContentRegionAvail;
30using ImGui::OpenPopup;
34using ImGui::Selectable;
35using ImGui::Separator;
36using ImGui::SetClipboardText;
37using ImGui::TableHeadersRow;
38using ImGui::TableNextColumn;
39using ImGui::TableNextRow;
40using ImGui::TableSetupColumn;
46 ImGuiTableFlags_Reorderable | ImGuiTableFlags_Resizable |
47 ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_Hideable;
49constexpr ImGuiColorEditFlags
kPalNoAlpha = ImGuiColorEditFlags_NoAlpha;
52 ImGuiColorEditFlags_NoPicker |
53 ImGuiColorEditFlags_NoTooltip;
56 ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha |
57 ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV |
58 ImGuiColorEditFlags_DisplayHex;
64#ifdef IMGUI_USE_STB_SPRINTF
65 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
67 int w = vsnprintf(buf, buf_size, fmt, args);
70 if (buf ==
nullptr)
return w;
71 if (w == -1 || w >= (
int)buf_size) w = (int)buf_size - 1;
76static inline float color_saturate(
float f) {
77 return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f;
80#define F32_TO_INT8_SAT(_VAL) \
81 ((int)(color_saturate(_VAL) * 255.0f + \
103 static ImVec4 color = ImVec4(0, 0, 0, 255.f);
104 static ImVec4 current_palette[256] = {};
105 ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview |
106 ImGuiColorEditFlags_NoDragDrop |
107 ImGuiColorEditFlags_NoOptions;
110 static bool init =
false;
111 if (loaded && !init) {
112 for (
int n = 0; n < palette.
size(); n++) {
113 auto color = palette[n];
114 current_palette[n].x = color.rgb().x / 255;
115 current_palette[n].y = color.rgb().y / 255;
116 current_palette[n].z = color.rgb().z / 255;
117 current_palette[n].w = 255;
122 static ImVec4 backup_color;
123 bool open_popup = ColorButton(
"MyColor##3b", color, misc_flags);
124 SameLine(0, GetStyle().ItemInnerSpacing.x);
125 open_popup |= Button(
"Palette");
127 OpenPopup(
"mypicker");
128 backup_color = color;
131 if (BeginPopup(
"mypicker")) {
133 ColorPicker4(
"##picker", (
float*)&color,
134 misc_flags | ImGuiColorEditFlags_NoSidePreview |
135 ImGuiColorEditFlags_NoSmallPreview);
143 if (Button(
"Update Map Palette")) {
148 ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
153 "##previous", backup_color,
154 ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
156 color = backup_color;
161 for (
int n = 0; n < IM_ARRAYSIZE(current_palette); n++) {
163 if ((n % 8) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
167 color = ImVec4(current_palette[n].x, current_palette[n].y,
168 current_palette[n].z, color.w);
170 if (BeginDragDropTarget()) {
171 if (
const ImGuiPayload* payload =
172 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
173 memcpy((
float*)¤t_palette[n], payload->Data,
sizeof(
float) * 3);
174 if (
const ImGuiPayload* payload =
175 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
176 memcpy((
float*)¤t_palette[n], payload->Data,
sizeof(
float) * 4);
186 return absl::OkStatus();
195 if (
rom()->is_loaded()) {
199 "Palette Group Name", std::to_string(i),
200 std::string(kPaletteGroupNames[i]));
203 return absl::NotFoundError(
"ROM not open, no palettes to display");
205 return absl::OkStatus();
209 static int current_palette_group = 0;
211 TableSetupColumn(
"Categories", ImGuiTableColumnFlags_WidthFixed, 200);
212 TableSetupColumn(
"Palette Editor", ImGuiTableColumnFlags_WidthStretch);
213 TableSetupColumn(
"Quick Access", ImGuiTableColumnFlags_WidthStretch);
219 static int selected_category = 0;
220 BeginChild(
"CategoryList", ImVec2(0, GetContentRegionAvail().y),
true);
223 const bool is_selected = (selected_category == i);
224 if (Selectable(std::string(kPaletteCategoryNames[i]).c_str(),
226 selected_category = i;
233 BeginChild(
"PaletteEditor", ImVec2(0, 0),
true);
235 Text(
"%s", std::string(kPaletteCategoryNames[selected_category]).c_str());
239 if (
rom()->is_loaded()) {
251 return absl::OkStatus();
255 BeginChild(
"QuickAccessPalettes", ImVec2(0, 0),
true);
257 Text(
"Custom Palette");
264 Text(
"Current Color");
274 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"RGB: %d, %d, %d", cr, cg, cb);
277 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"SNES: $%04X",
281 if (Button(
"Copy to Clipboard")) {
282 SetClipboardText(buf);
289 Text(
"Recently Used Colors");
292 if (i % 8 != 0) SameLine();
293 ImVec4 displayColor =
295 if (ImGui::ColorButton(
"##recent", displayColor)) {
321 if (BeginChild(
"ColorPalette", ImVec2(0, 40), ImGuiChildFlags_None,
322 ImGuiWindowFlags_HorizontalScrollbar)) {
325 if (i > 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
329 bool open_color_picker = ImGui::ColorButton(
330 absl::StrFormat(
"##customPal%d", i).c_str(), displayColor);
332 if (open_color_picker) {
335 ImGui::OpenPopup(
"CustomPaletteColorEdit");
338 if (BeginPopupContextItem()) {
347 if (Button(
"Delete", ImVec2(-1, 0))) {
353 if (BeginDragDropTarget()) {
354 if (
const ImGuiPayload* payload =
355 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) {
357 memcpy((
float*)&color, payload->Data,
sizeof(
float) * 3);
369 if (ImGui::Button(
"+")) {
374 if (ImGui::Button(
"Clear")) {
379 if (ImGui::Button(
"Export")) {
380 std::string clipboard;
382 clipboard += absl::StrFormat(
"$%04X,", color.snes());
384 SetClipboardText(clipboard.c_str());
390 if (ImGui::BeginPopup(
"CustomPaletteColorEdit")) {
406 if (!
rom()->is_loaded()) {
407 return absl::NotFoundError(
"ROM not open, no palettes to display");
410 auto palette_group_name = kPaletteGroupNames[category];
413 const auto size = palette_group->
size();
415 for (
int j = 0; j < size; j++) {
417 auto pal_size = palette->
size();
424 false, palette_group_name.data(), std::to_string(j),
428 for (
int n = 0; n < pal_size; n++) {
430 if (n > 0 && n % 8 != 0) SameLine(0.0f, 2.0f);
433 absl::StrCat(kPaletteCategoryNames[category].data(), j,
"_", n);
436 if (ImGui::ColorButton(popup_id.c_str(), displayColor)) {
441 if (BeginPopupContextItem(popup_id.c_str())) {
453 return absl::OkStatus();
458 auto it = std::find_if(
460 [&color](
const SnesColor& c) { return c.snes() == color.snes(); });
479 auto original_color = palette[n];
484 original_color, palette[n]);
485 palette[n].set_modified(
true);
497 Text(
"RGB: %d, %d, %d", cr, cg, cb);
498 Text(
"SNES: $%04X", palette[n].snes());
502 if (Button(
"Copy as..", ImVec2(-1, 0))) OpenPopup(
"Copy");
503 if (BeginPopup(
"Copy")) {
504 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%.3ff, %.3ff, %.3ff)", col[0],
506 if (Selectable(buf)) SetClipboardText(buf);
508 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%d,%d,%d)", cr, cg, cb);
509 if (Selectable(buf)) SetClipboardText(buf);
511 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"#%02X%02X%02X", cr, cg, cb);
512 if (Selectable(buf)) SetClipboardText(buf);
515 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"$%04X",
517 if (Selectable(buf)) SetClipboardText(buf);
523 if (Button(
"Add to Custom Palette", ImVec2(-1, 0))) {
528 return absl::OkStatus();
533 if (index >= palette.
size()) {
534 return absl::InvalidArgumentError(
"Index out of bounds");
538 auto color = palette[index];
539 auto currentColor = color.rgb();
540 if (ColorPicker4(
"Color Picker", (
float*)&palette[index])) {
547 return absl::OkStatus();
553 if (index >= palette.
size() || index >= originalPalette.
size()) {
554 return absl::InvalidArgumentError(
"Index out of bounds");
556 auto color = originalPalette[index];
557 auto originalColor = color.rgb();
559 return absl::OkStatus();
#define F32_TO_INT8_SAT(_VAL)
auto mutable_palette_group()
core::ResourceLabelManager * resource_label()
void Initialize() override
absl::Status DrawPaletteGroup(int category, bool right_side=false)
absl::Status ResetColorToOriginal(gfx::SnesPalette &palette, int index, const gfx::SnesPalette &originalPalette)
std::vector< gfx::SnesColor > custom_palette_
void DrawCustomPalette()
Draw custom palette editor with enhanced ROM hacking features.
void AddRecentlyUsedColor(const gfx::SnesColor &color)
absl::Status Update() override
absl::Status HandleColorPopup(gfx::SnesPalette &palette, int i, int j, int n)
gfx::SnesColor current_color_
void DrawQuickAccessTab()
std::vector< gfx::SnesColor > recently_used_colors_
palette_internal::PaletteEditorHistory history_
absl::Status Load() override
absl::Status EditColorInPalette(gfx::SnesPalette &palette, int index)
void RecordChange(const std::string &group_name, size_t palette_index, size_t color_index, const gfx::SnesColor &original_color, const gfx::SnesColor &new_color)
RAII timer for automatic timing management.
constexpr ImVec4 rgb() const
constexpr uint16_t snes() const
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
#define RETURN_IF_ERROR(expression)
#define TEXT_WITH_SEPARATOR(text)
int CustomFormatString(char *buf, size_t buf_size, const char *fmt,...)
constexpr ImGuiTableFlags kPaletteTableFlags
constexpr ImGuiColorEditFlags kPalNoAlpha
absl::Status DisplayPalette(gfx::SnesPalette &palette, bool loaded)
Display SNES palette with enhanced ROM hacking features.
constexpr ImGuiColorEditFlags kColorPopupFlags
constexpr ImGuiColorEditFlags kPalButtonFlags
constexpr int kNumPalettes
uint16_t ConvertRgbToSnes(const snes_color &color)
std::array< float, 4 > ToFloatArray(const SnesColor &color)
ImVec4 ConvertSnesColorToImVec4(const gfx::SnesColor &color)
IMGUI_API bool SnesColorEdit4(absl::string_view label, gfx::SnesColor *color, ImGuiColorEditFlags flags)
gfx::SnesColor ConvertImVec4ToSnesColor(const ImVec4 &color)
Main namespace for the application.
void SelectableLabelWithNameEdit(bool selected, const std::string &type, const std::string &key, const std::string &defaultValue)
std::string CreateOrGetLabel(const std::string &type, const std::string &key, const std::string &defaultValue)
Represents a group of palettes.
auto mutable_palette(int i)