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();
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");
186 return absl::OkStatus();
191 TableSetupColumn(
"Palette Groups", ImGuiTableColumnFlags_WidthStretch,
192 GetContentRegionAvail().x);
193 TableSetupColumn(
"Palette Sets and Metadata",
194 ImGuiTableColumnFlags_WidthStretch,
195 GetContentRegionAvail().x);
204 ImGuiColorEditFlags_NoAlpha);
211 static bool in_use =
false;
212 ImGui::Checkbox(
"Palette in use? ", &in_use);
214 static std::string palette_notes =
"Notes about the palette";
215 ImGui::InputTextMultiline(
"Notes", palette_notes.data(), 1024,
216 ImVec2(-1, ImGui::GetTextLineHeight() * 4),
217 ImGuiInputTextFlags_AllowTabInput);
224 return absl::OkStatus();
228 if (BeginChild(
"ColorPalette", ImVec2(0, 40),
true,
229 ImGuiWindowFlags_HorizontalScrollbar)) {
232 SameLine(0.0f, GetStyle().ItemSpacing.y);
234 ImGuiColorEditFlags_NoInputs);
236 if (BeginDragDropTarget()) {
237 if (
const ImGuiPayload* payload =
238 AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) {
239 ImVec4 color = ImVec4(0, 0, 0, 1.0f);
240 memcpy((
float*)&color, payload->Data,
sizeof(
float));
249 if (ImGui::Button(
"Add Color")) {
253 if (ImGui::Button(
"Export to Clipboard")) {
254 std::string clipboard;
256 clipboard += absl::StrFormat(
"$%04X,", color.snes());
258 SetClipboardText(clipboard.c_str());
265 if (BeginTable(
"Category Table", 8,
266 ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable |
267 ImGuiTableFlags_SizingStretchSame |
268 ImGuiTableFlags_Hideable,
270 TableSetupColumn(
"Weapons and Gear");
271 TableSetupColumn(
"Overworld and Area Colors");
272 TableSetupColumn(
"Global Sprites");
273 TableSetupColumn(
"Sprites Aux1");
274 TableSetupColumn(
"Sprites Aux2");
275 TableSetupColumn(
"Sprites Aux3");
276 TableSetupColumn(
"Maps and Items");
277 TableSetupColumn(
"Dungeons");
281 TableSetColumnIndex(0);
282 if (TreeNode(
"Sword")) {
286 if (TreeNode(
"Shield")) {
290 if (TreeNode(
"Clothes")) {
295 TableSetColumnIndex(1);
297 if (TreeNode(
"World Colors")) {
301 if (TreeNode(
"Area Colors")) {
307 TableSetColumnIndex(2);
310 TableSetColumnIndex(3);
313 TableSetColumnIndex(4);
316 TableSetColumnIndex(5);
319 TableSetColumnIndex(6);
321 if (TreeNode(
"World Map")) {
325 if (TreeNode(
"Dungeon Map")) {
329 if (TreeNode(
"Triforce")) {
333 if (TreeNode(
"Crystal")) {
339 TableSetColumnIndex(7);
349 if (!
rom()->is_loaded()) {
350 return absl::NotFoundError(
"ROM not open, no palettes to display");
353 auto palette_group_name = kPaletteGroupNames[category];
355 rom()->mutable_palette_group()->get_group(palette_group_name.data());
356 const auto size = palette_group->
size();
358 static bool edit_color =
false;
359 for (
int j = 0; j < size; j++) {
361 auto pal_size = palette->
size();
363 for (
int n = 0; n < pal_size; n++) {
366 if ((n % 7) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
368 if ((n % 15) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
372 absl::StrCat(kPaletteCategoryNames[category].data(), j,
"_", n);
380 if (BeginPopupContextItem(popup_id.c_str())) {
386 rom()->resource_label()->SelectableLabelWithNameEdit(
387 false, palette_group_name.data(), std::to_string(j),
389 if (right_side) Separator();
391 return absl::OkStatus();
395 if (BeginChild(
"ModifiedColors", ImVec2(0, 100),
true,
396 ImGuiWindowFlags_HorizontalScrollbar)) {
397 for (
int i = 0; i <
history_.size(); i++) {
400 ImGuiColorEditFlags_NoInputs);
401 SameLine(0.0f, GetStyle().ItemSpacing.y);
403 ImGuiColorEditFlags_NoInputs);
413 auto original_color = palette[n];
415 history_.RecordChange(std::string(kPaletteGroupNames[i]),
417 original_color, palette[n]);
418 palette[n].set_modified(
true);
421 if (Button(
"Copy as..", ImVec2(-1, 0))) OpenPopup(
"Copy");
422 if (BeginPopup(
"Copy")) {
428 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%.3ff, %.3ff, %.3ff)", col[0],
430 if (Selectable(buf)) SetClipboardText(buf);
432 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"(%d,%d,%d)", cr, cg, cb);
433 if (Selectable(buf)) SetClipboardText(buf);
435 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"#%02X%02X%02X", cr, cg, cb);
436 if (Selectable(buf)) SetClipboardText(buf);
439 CustomFormatString(buf, IM_ARRAYSIZE(buf),
"$%04X",
441 if (Selectable(buf)) SetClipboardText(buf);
447 return absl::OkStatus();
452 if (index >= palette.
size()) {
453 return absl::InvalidArgumentError(
"Index out of bounds");
458 auto currentColor = color.rgb();
459 if (ColorPicker4(
"Color Picker", (
float*)&palette[index])) {
461 palette(index, currentColor);
463 return absl::OkStatus();
469 if (index >= palette.
size() || index >= originalPalette.
size()) {
470 return absl::InvalidArgumentError(
"Index out of bounds");
473 auto originalColor = color.rgb();
474 palette(index, originalColor);
475 return absl::OkStatus();
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 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_
absl::Status Load() override
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)