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::TableSetColumnIndex;
41using ImGui::TableSetupColumn;
49 ImGuiTableFlags_Reorderable | ImGuiTableFlags_Resizable |
50 ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_Hideable;
52constexpr ImGuiColorEditFlags
kPalNoAlpha = ImGuiColorEditFlags_NoAlpha;
55 ImGuiColorEditFlags_NoPicker |
56 ImGuiColorEditFlags_NoTooltip;
59 ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha;
65#ifdef IMGUI_USE_STB_SPRINTF
66 int w = stbsp_vsnprintf(buf, (
int)buf_size, fmt, args);
68 int w = vsnprintf(buf, buf_size, fmt, args);
71 if (buf ==
nullptr)
return w;
72 if (w == -1 || w >= (
int)buf_size) w = (int)buf_size - 1;
77static inline float color_saturate(
float f) {
78 return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f;
81#define F32_TO_INT8_SAT(_VAL) \
82 ((int)(color_saturate(_VAL) * 255.0f + \
87 static ImVec4 color = ImVec4(0, 0, 0, 255.f);
88 static ImVec4 current_palette[256] = {};
89 ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview |
90 ImGuiColorEditFlags_NoDragDrop |
91 ImGuiColorEditFlags_NoOptions;
94 static bool init =
false;
95 if (loaded && !init) {
96 for (
int n = 0; n < palette.
size(); n++) {
98 current_palette[n].x = color.rgb().x / 255;
99 current_palette[n].y = color.rgb().y / 255;
100 current_palette[n].z = color.rgb().z / 255;
101 current_palette[n].w = 255;
106 static ImVec4 backup_color;
107 bool open_popup = ColorButton(
"MyColor##3b", color, misc_flags);
108 SameLine(0, GetStyle().ItemInnerSpacing.x);
109 open_popup |= Button(
"Palette");
111 OpenPopup(
"mypicker");
112 backup_color = color;
115 if (BeginPopup(
"mypicker")) {
117 ColorPicker4(
"##picker", (
float*)&color,
118 misc_flags | ImGuiColorEditFlags_NoSidePreview |
119 ImGuiColorEditFlags_NoSmallPreview);
127 if (Button(
"Update Map Palette")) {
132 ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
137 "##previous", backup_color,
138 ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
140 color = backup_color;
145 for (
int n = 0; n < IM_ARRAYSIZE(current_palette); n++) {
147 if ((n % 8) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
151 color = ImVec4(current_palette[n].x, current_palette[n].y,
152 current_palette[n].z, color.w);
154 if (BeginDragDropTarget()) {
155 if (
const ImGuiPayload* payload =
156 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
157 memcpy((
float*)¤t_palette[n], payload->Data,
sizeof(
float) * 3);
158 if (
const ImGuiPayload* payload =
159 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
160 memcpy((
float*)¤t_palette[n], payload->Data,
sizeof(
float) * 4);
170 return absl::OkStatus();
174 if (
rom()->is_loaded()) {
177 rom()->resource_label()->CreateOrGetLabel(
178 "Palette Group Name", std::to_string(i),
179 std::string(kPaletteGroupNames[i]));
182 return absl::NotFoundError(
"ROM not open, no palettes to display");
186 TableSetupColumn(
"Palette Groups", ImGuiTableColumnFlags_WidthStretch,
187 GetContentRegionAvail().x);
188 TableSetupColumn(
"Palette Sets and Metadata",
189 ImGuiTableColumnFlags_WidthStretch,
190 GetContentRegionAvail().x);
199 ImGuiColorEditFlags_NoAlpha);
206 static bool in_use =
false;
207 ImGui::Checkbox(
"Palette in use? ", &in_use);
209 static std::string palette_notes =
"Notes about the palette";
210 ImGui::InputTextMultiline(
"Notes", palette_notes.data(), 1024,
211 ImVec2(-1, ImGui::GetTextLineHeight() * 4),
212 ImGuiInputTextFlags_AllowTabInput);
219 return absl::OkStatus();
223 if (BeginChild(
"ColorPalette", ImVec2(0, 40),
true,
224 ImGuiWindowFlags_HorizontalScrollbar)) {
227 SameLine(0.0f, GetStyle().ItemSpacing.y);
229 ImGuiColorEditFlags_NoInputs);
231 if (BeginDragDropTarget()) {
232 if (
const ImGuiPayload* payload =
233 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) {
234 ImVec4 color = ImVec4(0, 0, 0, 1.0f);
235 memcpy((
float*)&color, payload->Data,
sizeof(
float));
244 if (ImGui::Button(
"Add Color")) {
248 if (ImGui::Button(
"Export to Clipboard")) {
249 std::string clipboard;
251 clipboard += absl::StrFormat(
"$%04X,", color.snes());
253 SetClipboardText(clipboard.c_str());
260 if (BeginTable(
"Category Table", 8,
261 ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable |
262 ImGuiTableFlags_SizingStretchSame |
263 ImGuiTableFlags_Hideable,
265 TableSetupColumn(
"Weapons and Gear");
266 TableSetupColumn(
"Overworld and Area Colors");
267 TableSetupColumn(
"Global Sprites");
268 TableSetupColumn(
"Sprites Aux1");
269 TableSetupColumn(
"Sprites Aux2");
270 TableSetupColumn(
"Sprites Aux3");
271 TableSetupColumn(
"Maps and Items");
272 TableSetupColumn(
"Dungeons");
276 TableSetColumnIndex(0);
277 if (TreeNode(
"Sword")) {
281 if (TreeNode(
"Shield")) {
285 if (TreeNode(
"Clothes")) {
290 TableSetColumnIndex(1);
292 if (TreeNode(
"World Colors")) {
296 if (TreeNode(
"Area Colors")) {
302 TableSetColumnIndex(2);
305 TableSetColumnIndex(3);
308 TableSetColumnIndex(4);
311 TableSetColumnIndex(5);
314 TableSetColumnIndex(6);
316 if (TreeNode(
"World Map")) {
320 if (TreeNode(
"Dungeon Map")) {
324 if (TreeNode(
"Triforce")) {
328 if (TreeNode(
"Crystal")) {
334 TableSetColumnIndex(7);
344 if (!
rom()->is_loaded()) {
345 return absl::NotFoundError(
"ROM not open, no palettes to display");
348 auto palette_group_name = kPaletteGroupNames[category];
350 rom()->mutable_palette_group()->get_group(palette_group_name.data());
351 const auto size = palette_group->
size();
353 static bool edit_color =
false;
354 for (
int j = 0; j < size; j++) {
356 auto pal_size = palette->
size();
358 for (
int n = 0; n < pal_size; n++) {
361 if ((n % 7) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
363 if ((n % 15) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
367 absl::StrCat(kPaletteCategoryNames[category].data(), j,
"_", n);
375 if (BeginPopupContextItem(popup_id.c_str())) {
381 rom()->resource_label()->SelectableLabelWithNameEdit(
382 false, palette_group_name.data(), std::to_string(j),
384 if (right_side) Separator();
386 return absl::OkStatus();
390 if (BeginChild(
"ModifiedColors", ImVec2(0, 100),
true,
391 ImGuiWindowFlags_HorizontalScrollbar)) {
392 for (
int i = 0; i <
history_.size(); i++) {
395 ImGuiColorEditFlags_NoInputs);
396 SameLine(0.0f, GetStyle().ItemSpacing.y);
398 ImGuiColorEditFlags_NoInputs);
408 auto original_color = palette[n];
410 history_.RecordChange(std::string(kPaletteGroupNames[i]),
412 original_color, palette[n]);
413 palette[n].set_modified(
true);
416 if (Button(
"Copy as..", ImVec2(-1, 0))) OpenPopup(
"Copy");
417 if (BeginPopup(
"Copy")) {
423 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%.3ff, %.3ff, %.3ff)", col[0],
425 if (Selectable(buf)) SetClipboardText(buf);
427 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%d,%d,%d)", cr, cg, cb);
428 if (Selectable(buf)) SetClipboardText(buf);
430 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"#%02X%02X%02X", cr, cg, cb);
431 if (Selectable(buf)) SetClipboardText(buf);
434 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"$%04X",
436 if (Selectable(buf)) SetClipboardText(buf);
442 return absl::OkStatus();
447 if (index >= palette.
size()) {
448 return absl::InvalidArgumentError(
"Index out of bounds");
453 auto currentColor = color.rgb();
454 if (ColorPicker4(
"Color Picker", (
float*)&palette[index])) {
456 palette(index, currentColor);
458 return absl::OkStatus();
464 if (index >= palette.
size() || index >= originalPalette.
size()) {
465 return absl::InvalidArgumentError(
"Index out of bounds");
468 auto originalColor = color.rgb();
469 palette(index, originalColor);
470 return absl::OkStatus();
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 DisplayCategoryTable()
void DrawModifiedColors()
absl::Status Update() override
absl::Status HandleColorPopup(gfx::SnesPalette &palette, int i, int j, int n)
gfx::SnesColor current_color_
palette_internal::PaletteEditorHistory history_
GfxGroupEditor gfx_group_editor_
absl::Status EditColorInPalette(gfx::SnesPalette &palette, int 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,...)
Editors are the view controllers for the application.
constexpr ImGuiTableFlags kPaletteTableFlags
constexpr ImGuiColorEditFlags kPalNoAlpha
constexpr ImGuiColorEditFlags kPalButtonFlags2
absl::Status DisplayPalette(gfx::SnesPalette &palette, bool loaded)
constexpr ImGuiColorEditFlags kColorPopupFlags
uint16_t ConvertRgbToSnes(const snes_color &color)
std::array< float, 4 > ToFloatArray(const SnesColor &color)
constexpr int kNumPalettes
IMGUI_API bool SnesColorButton(absl::string_view id, gfx::SnesColor &color, ImGuiColorEditFlags flags, const ImVec2 &size_arg)
IMGUI_API bool SnesColorEdit4(absl::string_view label, gfx::SnesColor *color, ImGuiColorEditFlags flags)
void BeginChildWithScrollbar(const char *str_id)
Main namespace for the application.
#define F32_TO_INT8_SAT(_VAL)
Represents a group of palettes.
auto mutable_palette(int i)