3#include "absl/status/status.h"
9#include "imgui/imgui.h"
15using ImGui::AcceptDragDropPayload;
16using ImGui::BeginChild;
17using ImGui::BeginDragDropTarget;
18using ImGui::BeginGroup;
19using ImGui::BeginPopup;
20using ImGui::BeginPopupContextItem;
21using ImGui::BeginTable;
23using ImGui::ColorButton;
24using ImGui::ColorPicker4;
26using ImGui::EndDragDropTarget;
30using ImGui::GetContentRegionAvail;
32using ImGui::OpenPopup;
36using ImGui::Selectable;
37using ImGui::Separator;
38using ImGui::SetClipboardText;
39using ImGui::TableHeadersRow;
40using ImGui::TableNextColumn;
41using ImGui::TableNextRow;
42using ImGui::TableSetColumnIndex;
43using ImGui::TableSetupColumn;
51 ImGuiTableFlags_Reorderable | ImGuiTableFlags_Resizable |
52 ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_Hideable;
54constexpr ImGuiColorEditFlags
kPalNoAlpha = ImGuiColorEditFlags_NoAlpha;
57 ImGuiColorEditFlags_NoPicker |
58 ImGuiColorEditFlags_NoTooltip;
61 ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha;
67#ifdef IMGUI_USE_STB_SPRINTF
68 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
70 int w = vsnprintf(buf, buf_size, fmt, args);
73 if (buf ==
nullptr)
return w;
74 if (w == -1 || w >= (
int)buf_size) w = (int)buf_size - 1;
79static inline float color_saturate(
float f) {
80 return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f;
83#define F32_TO_INT8_SAT(_VAL) \
84 ((int)(color_saturate(_VAL) * 255.0f + \
89 static ImVec4 color = ImVec4(0, 0, 0, 255.f);
90 static ImVec4 current_palette[256] = {};
91 ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview |
92 ImGuiColorEditFlags_NoDragDrop |
93 ImGuiColorEditFlags_NoOptions;
96 static bool init =
false;
97 if (loaded && !init) {
98 for (
int n = 0; n < palette.
size(); n++) {
100 current_palette[n].x = color.rgb().x / 255;
101 current_palette[n].y = color.rgb().y / 255;
102 current_palette[n].z = color.rgb().z / 255;
103 current_palette[n].w = 255;
108 static ImVec4 backup_color;
109 bool open_popup = ColorButton(
"MyColor##3b", color, misc_flags);
110 SameLine(0, GetStyle().ItemInnerSpacing.x);
111 open_popup |= Button(
"Palette");
113 OpenPopup(
"mypicker");
114 backup_color = color;
117 if (BeginPopup(
"mypicker")) {
119 ColorPicker4(
"##picker", (
float*)&color,
120 misc_flags | ImGuiColorEditFlags_NoSidePreview |
121 ImGuiColorEditFlags_NoSmallPreview);
129 if (Button(
"Update Map Palette")) {
134 ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
139 "##previous", backup_color,
140 ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
142 color = backup_color;
147 for (
int n = 0; n < IM_ARRAYSIZE(current_palette); n++) {
149 if ((n % 8) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
153 color = ImVec4(current_palette[n].x, current_palette[n].y,
154 current_palette[n].z, color.w);
156 if (BeginDragDropTarget()) {
157 if (
const ImGuiPayload* payload =
158 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
159 memcpy((
float*)¤t_palette[n], payload->Data,
sizeof(
float) * 3);
160 if (
const ImGuiPayload* payload =
161 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
162 memcpy((
float*)¤t_palette[n], payload->Data,
sizeof(
float) * 4);
172 return absl::OkStatus();
176 if (
rom()->is_loaded()) {
179 rom()->resource_label()->CreateOrGetLabel(
180 "Palette Group Name", std::to_string(i),
181 std::string(kPaletteGroupNames[i]));
184 return absl::NotFoundError(
"ROM not open, no palettes to display");
188 TableSetupColumn(
"Palette Groups", ImGuiTableColumnFlags_WidthStretch,
189 GetContentRegionAvail().x);
190 TableSetupColumn(
"Palette Sets and Metadata",
191 ImGuiTableColumnFlags_WidthStretch,
192 GetContentRegionAvail().x);
201 ImGuiColorEditFlags_NoAlpha);
208 static bool in_use =
false;
209 ImGui::Checkbox(
"Palette in use? ", &in_use);
211 static std::string palette_notes =
"Notes about the palette";
212 ImGui::InputTextMultiline(
"Notes", palette_notes.data(), 1024,
213 ImVec2(-1, ImGui::GetTextLineHeight() * 4),
214 ImGuiInputTextFlags_AllowTabInput);
221 return absl::OkStatus();
225 if (BeginChild(
"ColorPalette", ImVec2(0, 40),
true,
226 ImGuiWindowFlags_HorizontalScrollbar)) {
229 SameLine(0.0f, GetStyle().ItemSpacing.y);
231 ImGuiColorEditFlags_NoInputs);
233 if (BeginDragDropTarget()) {
234 if (
const ImGuiPayload* payload =
235 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) {
236 ImVec4 color = ImVec4(0, 0, 0, 1.0f);
237 memcpy((
float*)&color, payload->Data,
sizeof(
float));
246 if (ImGui::Button(
"Add Color")) {
250 if (ImGui::Button(
"Export to Clipboard")) {
251 std::string clipboard;
253 clipboard += absl::StrFormat(
"$%04X,", color.snes());
255 SetClipboardText(clipboard.c_str());
262 if (BeginTable(
"Category Table", 8,
263 ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable |
264 ImGuiTableFlags_SizingStretchSame |
265 ImGuiTableFlags_Hideable,
267 TableSetupColumn(
"Weapons and Gear");
268 TableSetupColumn(
"Overworld and Area Colors");
269 TableSetupColumn(
"Global Sprites");
270 TableSetupColumn(
"Sprites Aux1");
271 TableSetupColumn(
"Sprites Aux2");
272 TableSetupColumn(
"Sprites Aux3");
273 TableSetupColumn(
"Maps and Items");
274 TableSetupColumn(
"Dungeons");
278 TableSetColumnIndex(0);
279 if (TreeNode(
"Sword")) {
283 if (TreeNode(
"Shield")) {
287 if (TreeNode(
"Clothes")) {
292 TableSetColumnIndex(1);
294 if (TreeNode(
"World Colors")) {
298 if (TreeNode(
"Area Colors")) {
304 TableSetColumnIndex(2);
307 TableSetColumnIndex(3);
310 TableSetColumnIndex(4);
313 TableSetColumnIndex(5);
316 TableSetColumnIndex(6);
318 if (TreeNode(
"World Map")) {
322 if (TreeNode(
"Dungeon Map")) {
326 if (TreeNode(
"Triforce")) {
330 if (TreeNode(
"Crystal")) {
336 TableSetColumnIndex(7);
346 if (!
rom()->is_loaded()) {
347 return absl::NotFoundError(
"ROM not open, no palettes to display");
350 auto palette_group_name = kPaletteGroupNames[category];
352 rom()->mutable_palette_group()->get_group(palette_group_name.data());
353 const auto size = palette_group->
size();
355 static bool edit_color =
false;
356 for (
int j = 0; j < size; j++) {
358 auto pal_size = palette->
size();
360 for (
int n = 0; n < pal_size; n++) {
363 if ((n % 7) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
365 if ((n % 15) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
369 absl::StrCat(kPaletteCategoryNames[category].data(), j,
"_", n);
377 if (BeginPopupContextItem(popup_id.c_str())) {
383 rom()->resource_label()->SelectableLabelWithNameEdit(
384 false, palette_group_name.data(), std::to_string(j),
386 if (right_side) Separator();
388 return absl::OkStatus();
392 if (BeginChild(
"ModifiedColors", ImVec2(0, 100),
true,
393 ImGuiWindowFlags_HorizontalScrollbar)) {
397 ImGuiColorEditFlags_NoInputs);
398 SameLine(0.0f, GetStyle().ItemSpacing.y);
400 ImGuiColorEditFlags_NoInputs);
410 auto original_color = palette[n];
414 original_color, palette[n]);
415 palette[n].set_modified(
true);
418 if (Button(
"Copy as..", ImVec2(-1, 0))) OpenPopup(
"Copy");
419 if (BeginPopup(
"Copy")) {
425 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%.3ff, %.3ff, %.3ff)", col[0],
427 if (Selectable(buf)) SetClipboardText(buf);
429 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%d,%d,%d)", cr, cg, cb);
430 if (Selectable(buf)) SetClipboardText(buf);
432 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"#%02X%02X%02X", cr, cg, cb);
433 if (Selectable(buf)) SetClipboardText(buf);
436 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"$%04X",
438 if (Selectable(buf)) SetClipboardText(buf);
444 return absl::OkStatus();
449 if (index >= palette.
size()) {
450 return absl::InvalidArgumentError(
"Index out of bounds");
455 auto currentColor = color.rgb();
456 if (ColorPicker4(
"Color Picker", (
float*)&palette[index])) {
458 palette(index, currentColor);
460 return absl::OkStatus();
466 if (index >= palette.
size() || index >= originalPalette.
size()) {
467 return absl::InvalidArgumentError(
"Index out of bounds");
470 auto originalColor = color.rgb();
471 palette(index, originalColor);
472 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)
uint16_t ConvertRGBtoSNES(const snes_color &color)
std::array< float, 4 > ToFloatArray(const SnesColor &color)
constexpr int kNumPalettes
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)