3#include "absl/status/status.h"
4#include "absl/strings/str_cat.h"
7#include "imgui/imgui.h"
12using ImGui::AcceptDragDropPayload;
13using ImGui::BeginChild;
14using ImGui::BeginDragDropTarget;
15using ImGui::BeginGroup;
16using ImGui::BeginPopup;
17using ImGui::BeginPopupContextItem;
18using ImGui::BeginTable;
20using ImGui::ColorButton;
21using ImGui::ColorPicker4;
23using ImGui::EndDragDropTarget;
27using ImGui::GetContentRegionAvail;
29using ImGui::OpenPopup;
33using ImGui::Selectable;
34using ImGui::Separator;
35using ImGui::SetClipboardText;
36using ImGui::TableHeadersRow;
37using ImGui::TableNextColumn;
38using ImGui::TableNextRow;
39using ImGui::TableSetupColumn;
45 ImGuiTableFlags_Reorderable | ImGuiTableFlags_Resizable |
46 ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_Hideable;
48constexpr ImGuiColorEditFlags
kPalNoAlpha = ImGuiColorEditFlags_NoAlpha;
51 ImGuiColorEditFlags_NoPicker |
52 ImGuiColorEditFlags_NoTooltip;
55 ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha |
56 ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHSV |
57 ImGuiColorEditFlags_DisplayHex;
63#ifdef IMGUI_USE_STB_SPRINTF
64 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
66 int w = vsnprintf(buf, buf_size, fmt, args);
69 if (buf ==
nullptr)
return w;
70 if (w == -1 || w >= (
int)buf_size) w = (int)buf_size - 1;
75static inline float color_saturate(
float f) {
76 return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f;
79#define F32_TO_INT8_SAT(_VAL) \
80 ((int)(color_saturate(_VAL) * 255.0f + \
85 static ImVec4 color = ImVec4(0, 0, 0, 255.f);
86 static ImVec4 current_palette[256] = {};
87 ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview |
88 ImGuiColorEditFlags_NoDragDrop |
89 ImGuiColorEditFlags_NoOptions;
92 static bool init =
false;
93 if (loaded && !init) {
94 for (
int n = 0; n < palette.
size(); n++) {
95 auto color = palette[n];
96 current_palette[n].x = color.rgb().x / 255;
97 current_palette[n].y = color.rgb().y / 255;
98 current_palette[n].z = color.rgb().z / 255;
99 current_palette[n].w = 255;
104 static ImVec4 backup_color;
105 bool open_popup = ColorButton(
"MyColor##3b", color, misc_flags);
106 SameLine(0, GetStyle().ItemInnerSpacing.x);
107 open_popup |= Button(
"Palette");
109 OpenPopup(
"mypicker");
110 backup_color = color;
113 if (BeginPopup(
"mypicker")) {
115 ColorPicker4(
"##picker", (
float*)&color,
116 misc_flags | ImGuiColorEditFlags_NoSidePreview |
117 ImGuiColorEditFlags_NoSmallPreview);
125 if (Button(
"Update Map Palette")) {
130 ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
135 "##previous", backup_color,
136 ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
138 color = backup_color;
143 for (
int n = 0; n < IM_ARRAYSIZE(current_palette); n++) {
145 if ((n % 8) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
149 color = ImVec4(current_palette[n].x, current_palette[n].y,
150 current_palette[n].z, color.w);
152 if (BeginDragDropTarget()) {
153 if (
const ImGuiPayload* payload =
154 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
155 memcpy((
float*)¤t_palette[n], payload->Data,
sizeof(
float) * 3);
156 if (
const ImGuiPayload* payload =
157 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
158 memcpy((
float*)¤t_palette[n], payload->Data,
sizeof(
float) * 4);
168 return absl::OkStatus();
174 if (
rom()->is_loaded()) {
178 "Palette Group Name", std::to_string(i),
179 std::string(kPaletteGroupNames[i]));
182 return absl::NotFoundError(
"ROM not open, no palettes to display");
184 return absl::OkStatus();
188 static int current_palette_group = 0;
190 TableSetupColumn(
"Categories", ImGuiTableColumnFlags_WidthFixed, 200);
191 TableSetupColumn(
"Palette Editor", ImGuiTableColumnFlags_WidthStretch);
192 TableSetupColumn(
"Quick Access", ImGuiTableColumnFlags_WidthStretch);
198 static int selected_category = 0;
199 BeginChild(
"CategoryList", ImVec2(0, GetContentRegionAvail().y),
true);
202 const bool is_selected = (selected_category == i);
203 if (Selectable(std::string(kPaletteCategoryNames[i]).c_str(),
205 selected_category = i;
212 BeginChild(
"PaletteEditor", ImVec2(0, 0),
true);
214 Text(
"%s", std::string(kPaletteCategoryNames[selected_category]).c_str());
218 if (
rom()->is_loaded()) {
230 return absl::OkStatus();
234 BeginChild(
"QuickAccessPalettes", ImVec2(0, 0),
true);
236 Text(
"Custom Palette");
243 Text(
"Current Color");
253 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"RGB: %d, %d, %d", cr, cg, cb);
256 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"SNES: $%04X",
260 if (Button(
"Copy to Clipboard")) {
261 SetClipboardText(buf);
268 Text(
"Recently Used Colors");
271 if (i % 8 != 0) SameLine();
272 ImVec4 displayColor =
274 if (ImGui::ColorButton(
"##recent", displayColor)) {
285 if (BeginChild(
"ColorPalette", ImVec2(0, 40), ImGuiChildFlags_None,
286 ImGuiWindowFlags_HorizontalScrollbar)) {
289 if (i > 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
293 bool open_color_picker = ImGui::ColorButton(
294 absl::StrFormat(
"##customPal%d", i).c_str(), displayColor);
296 if (open_color_picker) {
299 ImGui::OpenPopup(
"CustomPaletteColorEdit");
302 if (BeginPopupContextItem()) {
311 if (Button(
"Delete", ImVec2(-1, 0))) {
317 if (BeginDragDropTarget()) {
318 if (
const ImGuiPayload* payload =
319 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) {
321 memcpy((
float*)&color, payload->Data,
sizeof(
float) * 3);
333 if (ImGui::Button(
"+")) {
338 if (ImGui::Button(
"Clear")) {
343 if (ImGui::Button(
"Export")) {
344 std::string clipboard;
346 clipboard += absl::StrFormat(
"$%04X,", color.snes());
348 SetClipboardText(clipboard.c_str());
354 if (ImGui::BeginPopup(
"CustomPaletteColorEdit")) {
370 if (!
rom()->is_loaded()) {
371 return absl::NotFoundError(
"ROM not open, no palettes to display");
374 auto palette_group_name = kPaletteGroupNames[category];
377 const auto size = palette_group->
size();
379 for (
int j = 0; j < size; j++) {
381 auto pal_size = palette->
size();
388 false, palette_group_name.data(), std::to_string(j),
392 for (
int n = 0; n < pal_size; n++) {
394 if (n > 0 && n % 8 != 0) SameLine(0.0f, 2.0f);
397 absl::StrCat(kPaletteCategoryNames[category].data(), j,
"_", n);
400 if (ImGui::ColorButton(popup_id.c_str(), displayColor)) {
405 if (BeginPopupContextItem(popup_id.c_str())) {
417 return absl::OkStatus();
422 auto it = std::find_if(
424 [&color](
const SnesColor& c) { return c.snes() == color.snes(); });
443 auto original_color = palette[n];
446 history_.RecordChange(std::string(kPaletteGroupNames[i]),
448 original_color, palette[n]);
449 palette[n].set_modified(
true);
461 Text(
"RGB: %d, %d, %d", cr, cg, cb);
462 Text(
"SNES: $%04X", palette[n].snes());
466 if (Button(
"Copy as..", ImVec2(-1, 0))) OpenPopup(
"Copy");
467 if (BeginPopup(
"Copy")) {
468 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%.3ff, %.3ff, %.3ff)", col[0],
470 if (Selectable(buf)) SetClipboardText(buf);
472 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%d,%d,%d)", cr, cg, cb);
473 if (Selectable(buf)) SetClipboardText(buf);
475 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"#%02X%02X%02X", cr, cg, cb);
476 if (Selectable(buf)) SetClipboardText(buf);
479 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"$%04X",
481 if (Selectable(buf)) SetClipboardText(buf);
487 if (Button(
"Add to Custom Palette", ImVec2(-1, 0))) {
492 return absl::OkStatus();
497 if (index >= palette.
size()) {
498 return absl::InvalidArgumentError(
"Index out of bounds");
502 auto color = palette[index];
503 auto currentColor = color.rgb();
504 if (ColorPicker4(
"Color Picker", (
float*)&palette[index])) {
511 return absl::OkStatus();
517 if (index >= palette.
size() || index >= originalPalette.
size()) {
518 return absl::InvalidArgumentError(
"Index out of bounds");
520 auto color = originalPalette[index];
521 auto originalColor = color.rgb();
523 return absl::OkStatus();
auto mutable_palette_group()
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 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)
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,...)
Editors are the view controllers for the application.
constexpr ImGuiTableFlags kPaletteTableFlags
constexpr ImGuiColorEditFlags kPalNoAlpha
absl::Status DisplayPalette(gfx::SnesPalette &palette, bool loaded)
constexpr ImGuiColorEditFlags kColorPopupFlags
constexpr ImGuiColorEditFlags kPalButtonFlags
uint16_t ConvertRgbToSnes(const snes_color &color)
std::array< float, 4 > ToFloatArray(const SnesColor &color)
constexpr int kNumPalettes
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.
#define F32_TO_INT8_SAT(_VAL)
std::string CreateOrGetLabel(const std::string &type, const std::string &key, const std::string &defaultValue)
void SelectableLabelWithNameEdit(bool selected, const std::string &type, const std::string &key, const std::string &defaultValue)
Represents a group of palettes.
auto mutable_palette(int i)