3#include "absl/status/status.h"
4#include "absl/strings/str_cat.h"
8#include "imgui/imgui.h"
14using ImGui::AcceptDragDropPayload;
15using ImGui::BeginChild;
16using ImGui::BeginDragDropTarget;
17using ImGui::BeginGroup;
18using ImGui::BeginPopup;
19using ImGui::BeginPopupContextItem;
20using ImGui::BeginTable;
22using ImGui::ColorButton;
23using ImGui::ColorPicker4;
25using ImGui::EndDragDropTarget;
29using ImGui::GetContentRegionAvail;
31using ImGui::OpenPopup;
35using ImGui::Selectable;
36using ImGui::Separator;
37using ImGui::SetClipboardText;
38using ImGui::TableHeadersRow;
39using ImGui::TableNextColumn;
40using ImGui::TableNextRow;
41using ImGui::TableSetColumnIndex;
42using ImGui::TableSetupColumn;
50 ImGuiTableFlags_Reorderable | ImGuiTableFlags_Resizable |
51 ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_Hideable;
53constexpr ImGuiColorEditFlags
kPalNoAlpha = ImGuiColorEditFlags_NoAlpha;
56 ImGuiColorEditFlags_NoPicker |
57 ImGuiColorEditFlags_NoTooltip;
60 ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha;
66#ifdef IMGUI_USE_STB_SPRINTF
67 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
69 int w = vsnprintf(buf, buf_size, fmt, args);
72 if (buf ==
nullptr)
return w;
73 if (w == -1 || w >= (
int)buf_size) w = (int)buf_size - 1;
78static inline float color_saturate(
float f) {
79 return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f;
82#define F32_TO_INT8_SAT(_VAL) \
83 ((int)(color_saturate(_VAL) * 255.0f + \
88 static ImVec4 color = ImVec4(0, 0, 0, 255.f);
89 static ImVec4 current_palette[256] = {};
90 ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview |
91 ImGuiColorEditFlags_NoDragDrop |
92 ImGuiColorEditFlags_NoOptions;
95 static bool init =
false;
96 if (loaded && !init) {
97 for (
int n = 0; n < palette.
size(); n++) {
99 current_palette[n].x = color.rgb().x / 255;
100 current_palette[n].y = color.rgb().y / 255;
101 current_palette[n].z = color.rgb().z / 255;
102 current_palette[n].w = 255;
107 static ImVec4 backup_color;
108 bool open_popup = ColorButton(
"MyColor##3b", color, misc_flags);
109 SameLine(0, GetStyle().ItemInnerSpacing.x);
110 open_popup |= Button(
"Palette");
112 OpenPopup(
"mypicker");
113 backup_color = color;
116 if (BeginPopup(
"mypicker")) {
118 ColorPicker4(
"##picker", (
float*)&color,
119 misc_flags | ImGuiColorEditFlags_NoSidePreview |
120 ImGuiColorEditFlags_NoSmallPreview);
128 if (Button(
"Update Map Palette")) {
133 ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
138 "##previous", backup_color,
139 ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
141 color = backup_color;
146 for (
int n = 0; n < IM_ARRAYSIZE(current_palette); n++) {
148 if ((n % 8) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
152 color = ImVec4(current_palette[n].x, current_palette[n].y,
153 current_palette[n].z, color.w);
155 if (BeginDragDropTarget()) {
156 if (
const ImGuiPayload* payload =
157 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
158 memcpy((
float*)¤t_palette[n], payload->Data,
sizeof(
float) * 3);
159 if (
const ImGuiPayload* payload =
160 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
161 memcpy((
float*)¤t_palette[n], payload->Data,
sizeof(
float) * 4);
171 return absl::OkStatus();
175 if (
rom()->is_loaded()) {
178 rom()->resource_label()->CreateOrGetLabel(
179 "Palette Group Name", std::to_string(i),
180 std::string(kPaletteGroupNames[i]));
183 return absl::NotFoundError(
"ROM not open, no palettes to display");
187 TableSetupColumn(
"Palette Groups", ImGuiTableColumnFlags_WidthStretch,
188 GetContentRegionAvail().x);
189 TableSetupColumn(
"Palette Sets and Metadata",
190 ImGuiTableColumnFlags_WidthStretch,
191 GetContentRegionAvail().x);
200 ImGuiColorEditFlags_NoAlpha);
207 static bool in_use =
false;
208 ImGui::Checkbox(
"Palette in use? ", &in_use);
210 static std::string palette_notes =
"Notes about the palette";
211 ImGui::InputTextMultiline(
"Notes", palette_notes.data(), 1024,
212 ImVec2(-1, ImGui::GetTextLineHeight() * 4),
213 ImGuiInputTextFlags_AllowTabInput);
220 return absl::OkStatus();
224 if (BeginChild(
"ColorPalette", ImVec2(0, 40),
true,
225 ImGuiWindowFlags_HorizontalScrollbar)) {
228 SameLine(0.0f, GetStyle().ItemSpacing.y);
230 ImGuiColorEditFlags_NoInputs);
232 if (BeginDragDropTarget()) {
233 if (
const ImGuiPayload* payload =
234 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) {
235 ImVec4 color = ImVec4(0, 0, 0, 1.0f);
236 memcpy((
float*)&color, payload->Data,
sizeof(
float));
245 if (ImGui::Button(
"Add Color")) {
249 if (ImGui::Button(
"Export to Clipboard")) {
250 std::string clipboard;
252 clipboard += absl::StrFormat(
"$%04X,", color.snes());
254 SetClipboardText(clipboard.c_str());
261 if (BeginTable(
"Category Table", 8,
262 ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable |
263 ImGuiTableFlags_SizingStretchSame |
264 ImGuiTableFlags_Hideable,
266 TableSetupColumn(
"Weapons and Gear");
267 TableSetupColumn(
"Overworld and Area Colors");
268 TableSetupColumn(
"Global Sprites");
269 TableSetupColumn(
"Sprites Aux1");
270 TableSetupColumn(
"Sprites Aux2");
271 TableSetupColumn(
"Sprites Aux3");
272 TableSetupColumn(
"Maps and Items");
273 TableSetupColumn(
"Dungeons");
277 TableSetColumnIndex(0);
278 if (TreeNode(
"Sword")) {
282 if (TreeNode(
"Shield")) {
286 if (TreeNode(
"Clothes")) {
291 TableSetColumnIndex(1);
293 if (TreeNode(
"World Colors")) {
297 if (TreeNode(
"Area Colors")) {
303 TableSetColumnIndex(2);
306 TableSetColumnIndex(3);
309 TableSetColumnIndex(4);
312 TableSetColumnIndex(5);
315 TableSetColumnIndex(6);
317 if (TreeNode(
"World Map")) {
321 if (TreeNode(
"Dungeon Map")) {
325 if (TreeNode(
"Triforce")) {
329 if (TreeNode(
"Crystal")) {
335 TableSetColumnIndex(7);
345 if (!
rom()->is_loaded()) {
346 return absl::NotFoundError(
"ROM not open, no palettes to display");
349 auto palette_group_name = kPaletteGroupNames[category];
351 rom()->mutable_palette_group()->get_group(palette_group_name.data());
352 const auto size = palette_group->
size();
354 static bool edit_color =
false;
355 for (
int j = 0; j < size; j++) {
357 auto pal_size = palette->
size();
359 for (
int n = 0; n < pal_size; n++) {
362 if ((n % 7) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
364 if ((n % 15) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
368 absl::StrCat(kPaletteCategoryNames[category].data(), j,
"_", n);
376 if (BeginPopupContextItem(popup_id.c_str())) {
382 rom()->resource_label()->SelectableLabelWithNameEdit(
383 false, palette_group_name.data(), std::to_string(j),
385 if (right_side) Separator();
387 return absl::OkStatus();
391 if (BeginChild(
"ModifiedColors", ImVec2(0, 100),
true,
392 ImGuiWindowFlags_HorizontalScrollbar)) {
396 ImGuiColorEditFlags_NoInputs);
397 SameLine(0.0f, GetStyle().ItemSpacing.y);
399 ImGuiColorEditFlags_NoInputs);
409 auto original_color = palette[n];
413 original_color, palette[n]);
414 palette[n].set_modified(
true);
417 if (Button(
"Copy as..", ImVec2(-1, 0))) OpenPopup(
"Copy");
418 if (BeginPopup(
"Copy")) {
424 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%.3ff, %.3ff, %.3ff)", col[0],
426 if (Selectable(buf)) SetClipboardText(buf);
428 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%d,%d,%d)", cr, cg, cb);
429 if (Selectable(buf)) SetClipboardText(buf);
431 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"#%02X%02X%02X", cr, cg, cb);
432 if (Selectable(buf)) SetClipboardText(buf);
435 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"$%04X",
437 if (Selectable(buf)) SetClipboardText(buf);
443 return absl::OkStatus();
448 if (index >= palette.
size()) {
449 return absl::InvalidArgumentError(
"Index out of bounds");
454 auto currentColor = color.rgb();
455 if (ColorPicker4(
"Color Picker", (
float*)&palette[index])) {
457 palette(index, currentColor);
459 return absl::OkStatus();
465 if (index >= palette.
size() || index >= originalPalette.
size()) {
466 return absl::InvalidArgumentError(
"Index out of bounds");
469 auto originalColor = color.rgb();
470 palette(index, originalColor);
471 return absl::OkStatus();
absl::Status ResetColorToOriginal(gfx::SnesPalette &palette, int index, const gfx::SnesPalette &originalPalette)
void DisplayCategoryTable()
absl::Status Update() override
GfxGroupEditor gfx_group_editor_
absl::Status HandleColorPopup(gfx::SnesPalette &palette, int i, int j, int n)
gfx::SnesColor current_color_
void DrawModifiedColors()
std::vector< gfx::SnesColor > custom_palette_
absl::Status EditColorInPalette(gfx::SnesPalette &palette, int index)
absl::Status DrawPaletteGroup(int category, bool right_side=false)
palette_internal::PaletteEditorHistory history_
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)
gfx::SnesColor & GetOriginalColor(size_t index)
gfx::SnesColor & GetModifiedColor(size_t index)
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
auto mutable_color(int i)
absl::StatusOr< SnesColor > GetColor(int i) const
#define RETURN_IF_ERROR(expression)
#define TEXT_WITH_SEPARATOR(text)
#define ASSIGN_OR_RETURN(type_variable_name, expression)
#define CLEAR_AND_RETURN_STATUS(status)
int CustomFormatString(char *buf, size_t buf_size, const char *fmt,...)
constexpr ImGuiColorEditFlags kColorPopupFlags
constexpr ImGuiColorEditFlags kPalNoAlpha
constexpr ImGuiColorEditFlags kPalButtonFlags2
constexpr ImGuiTableFlags kPaletteTableFlags
absl::Status DisplayPalette(gfx::SnesPalette &palette, bool loaded)
std::array< float, 4 > ToFloatArray(const SnesColor &color)
constexpr int kNumPalettes
uint16_t ConvertRgbToSnes(const snes_color &color)
IMGUI_API bool SnesColorEdit4(absl::string_view label, SnesColor *color, ImGuiColorEditFlags flags)
void BeginChildWithScrollbar(const char *str_id)
IMGUI_API bool SnesColorButton(absl::string_view id, SnesColor &color, ImGuiColorEditFlags flags, const ImVec2 &size_arg)
#define F32_TO_INT8_SAT(_VAL)
Represents a group of palettes.
auto mutable_palette(int i)