add sprites aux to palette editor, cleanup

This commit is contained in:
scawful
2024-07-14 12:20:00 -04:00
parent e8fe3721b8
commit 98b098c463
2 changed files with 231 additions and 170 deletions

View File

@@ -12,6 +12,68 @@ namespace yaze {
namespace app {
namespace editor {
using ImGui::AcceptDragDropPayload;
using ImGui::BeginChild;
using ImGui::BeginDragDropTarget;
using ImGui::BeginGroup;
using ImGui::BeginPopup;
using ImGui::BeginPopupContextItem;
using ImGui::BeginTable;
using ImGui::Button;
using ImGui::ColorButton;
using ImGui::ColorPicker4;
using ImGui::EndChild;
using ImGui::EndDragDropTarget;
using ImGui::EndGroup;
using ImGui::EndPopup;
using ImGui::EndTable;
using ImGui::GetContentRegionAvail;
using ImGui::GetStyle;
using ImGui::OpenPopup;
using ImGui::PopID;
using ImGui::PushID;
using ImGui::SameLine;
using ImGui::Selectable;
using ImGui::Separator;
using ImGui::SetClipboardText;
using ImGui::TableHeadersRow;
using ImGui::TableNextColumn;
using ImGui::TableNextRow;
using ImGui::TableSetColumnIndex;
using ImGui::TableSetupColumn;
using ImGui::Text;
using ImGui::TreeNode;
using ImGui::TreePop;
constexpr ImGuiTableFlags kPaletteTableFlags =
ImGuiTableFlags_Reorderable | ImGuiTableFlags_Resizable |
ImGuiTableFlags_SizingStretchSame;
namespace {
int CustomFormatString(char* buf, size_t buf_size, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
#ifdef IMGUI_USE_STB_SPRINTF
int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
#else
int w = vsnprintf(buf, buf_size, fmt, args);
#endif
va_end(args);
if (buf == nullptr) return w;
if (w == -1 || w >= (int)buf_size) w = (int)buf_size - 1;
buf[w] = 0;
return w;
}
static inline float color_saturate(float f) {
return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f;
}
#define F32_TO_INT8_SAT(_VAL) \
((int)(color_saturate(_VAL) * 255.0f + \
0.5f)) // Saturated, always output 0..255
} // namespace
absl::Status PaletteEditor::Update() {
if (rom()->is_loaded()) {
// Initialize the labels
@@ -22,25 +84,35 @@ absl::Status PaletteEditor::Update() {
}
}
if (ImGui::BeginTable("paletteEditorTable", 2,
ImGuiTableFlags_Reorderable |
ImGuiTableFlags_Resizable |
ImGuiTableFlags_SizingStretchSame,
ImVec2(0, 0))) {
ImGui::TableSetupColumn("Palette Groups",
ImGuiTableColumnFlags_WidthStretch,
ImGui::GetContentRegionAvail().x);
ImGui::TableSetupColumn("Editor", ImGuiTableColumnFlags_WidthStretch,
ImGui::GetContentRegionAvail().x);
ImGui::TableHeadersRow();
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (BeginTable("paletteEditorTable", 2, kPaletteTableFlags, ImVec2(0, 0))) {
TableSetupColumn("Palette Groups", ImGuiTableColumnFlags_WidthStretch,
GetContentRegionAvail().x);
TableSetupColumn("Metadata", ImGuiTableColumnFlags_WidthStretch,
GetContentRegionAvail().x);
TableHeadersRow();
TableNextRow();
TableNextColumn();
DisplayCategoryTable();
ImGui::TableNextColumn();
Separator();
if (gui::SnesColorEdit4("Color Picker", current_color_,
ImGuiColorEditFlags_NoAlpha)) {
// TODO: Implement new update color function
}
ImGui::EndTable();
TableNextColumn();
if (BeginTable("Palette Metadata", 2)) {
TableSetupColumn("Palette Name");
TableSetupColumn("Palette Size");
TableHeadersRow();
TableNextRow();
TableNextColumn();
Text("Palette Name");
TableNextColumn();
Text("Palette Size");
EndTable();
}
EndTable();
}
CLEAR_AND_RETURN_STATUS(status_)
@@ -49,77 +121,75 @@ absl::Status PaletteEditor::Update() {
}
void PaletteEditor::DisplayCategoryTable() {
// Check if the table is created successfully with 3 columns
if (ImGui::BeginTable("Category Table", 3)) { // 3 columns
if (BeginTable("Category Table", 6)) {
TableSetupColumn("Weapons and Gear");
TableSetupColumn("World and Global Sprites");
TableSetupColumn("Sprites Aux1");
TableSetupColumn("Sprites Aux2");
TableSetupColumn("Sprites Aux3");
TableSetupColumn("Maps and Items");
TableHeadersRow();
TableNextRow();
// Headers (optional, remove if you don't want headers)
ImGui::TableSetupColumn("Weapons and Gear");
ImGui::TableSetupColumn("World and Enemies");
ImGui::TableSetupColumn("Maps and Items");
ImGui::TableHeadersRow();
// Start the first row
ImGui::TableNextRow();
// Column 1 - Weapons and Gear
ImGui::TableSetColumnIndex(0);
if (ImGui::TreeNode("Sword")) {
status_ = DrawPaletteGroup(0);
ImGui::TreePop();
TableSetColumnIndex(0);
if (TreeNode("Sword")) {
status_ = DrawPaletteGroup(PaletteCategory::kSword);
TreePop();
}
if (ImGui::TreeNode("Shield")) {
status_ = DrawPaletteGroup(1);
ImGui::TreePop();
if (TreeNode("Shield")) {
status_ = DrawPaletteGroup(PaletteCategory::kShield);
TreePop();
}
if (ImGui::TreeNode("Clothes")) {
status_ = DrawPaletteGroup(2);
ImGui::TreePop();
if (TreeNode("Clothes")) {
status_ = DrawPaletteGroup(PaletteCategory::kClothes);
TreePop();
}
// Column 2 - World and Enemies
ImGui::TableSetColumnIndex(1);
if (ImGui::TreeNode("World Colors")) {
status_ = DrawPaletteGroup(3);
ImGui::TreePop();
TableSetColumnIndex(1);
if (TreeNode("World Colors")) {
status_ = DrawPaletteGroup(PaletteCategory::kWorldColors);
TreePop();
}
if (ImGui::TreeNode("Area Colors")) {
status_ = DrawPaletteGroup(4);
ImGui::TreePop();
if (TreeNode("Area Colors")) {
status_ = DrawPaletteGroup(PaletteCategory::kAreaColors);
TreePop();
}
if (ImGui::TreeNode("Enemies")) {
status_ = DrawPaletteGroup(5);
ImGui::TreePop();
if (TreeNode("Enemies")) {
status_ = DrawPaletteGroup(PaletteCategory::kGlobalSprites);
TreePop();
}
// Column 3 - Maps and Items
ImGui::TableSetColumnIndex(2);
if (ImGui::TreeNode("Dungeons")) {
status_ = DrawPaletteGroup(6);
ImGui::TreePop();
}
if (ImGui::TreeNode("World Map")) {
status_ = DrawPaletteGroup(7);
ImGui::TreePop();
}
if (ImGui::TreeNode("Dungeon Map")) {
status_ = DrawPaletteGroup(8);
ImGui::TreePop();
}
TableSetColumnIndex(2);
status_ = DrawPaletteGroup(PaletteCategory::kSpritesAux1);
// Additional items in the last column, if any
{
if (ImGui::TreeNode("Triforce")) {
status_ = DrawPaletteGroup(9);
ImGui::TreePop();
}
if (ImGui::TreeNode("Crystal")) {
status_ = DrawPaletteGroup(10);
ImGui::TreePop();
}
TableSetColumnIndex(3);
status_ = DrawPaletteGroup(PaletteCategory::kSpritesAux2);
TableSetColumnIndex(4);
status_ = DrawPaletteGroup(PaletteCategory::kSpritesAux3);
TableSetColumnIndex(5);
if (TreeNode("Dungeons")) {
status_ = DrawPaletteGroup(PaletteCategory::kDungeons);
TreePop();
}
// End the table
ImGui::EndTable();
if (TreeNode("World Map")) {
status_ = DrawPaletteGroup(PaletteCategory::kWorldMap);
TreePop();
}
if (TreeNode("Dungeon Map")) {
status_ = DrawPaletteGroup(PaletteCategory::kDungeonMap);
TreePop();
}
if (TreeNode("Triforce")) {
status_ = DrawPaletteGroup(PaletteCategory::kTriforce);
TreePop();
}
if (TreeNode("Crystal")) {
status_ = DrawPaletteGroup(PaletteCategory::kCrystal);
TreePop();
}
EndTable();
}
}
@@ -132,7 +202,7 @@ absl::Status PaletteEditor::EditColorInPalette(gfx::SnesPalette& palette,
// Get the current color
ASSIGN_OR_RETURN(auto color, palette.GetColor(index));
auto currentColor = color.rgb();
if (ImGui::ColorPicker4("Color Picker", (float*)&palette[index])) {
if (ColorPicker4("Color Picker", (float*)&palette[index])) {
// The color was modified, update it in the palette
palette(index, currentColor);
}
@@ -162,16 +232,15 @@ absl::Status PaletteEditor::DrawPaletteGroup(int category) {
static bool edit_color = false;
for (int j = 0; j < size; j++) {
ImGui::Text("%d", j);
// rom()->resource_label()->SelectableLabelWithNameEdit(
// false, "Palette Group Name", std::to_string(j),
// std::string(kPaletteGroupNames[category]));
rom()->resource_label()->SelectableLabelWithNameEdit(
false, "Palette Name", /*key=*/std::to_string(j), "Unnamed Palette");
gfx::SnesPalette* palette = palette_group.mutable_palette(j);
auto pal_size = palette->size();
for (int n = 0; n < pal_size; n++) {
ImGui::PushID(n);
if ((n % 7) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
PushID(n);
if ((n % 7) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
auto popup_id =
absl::StrCat(kPaletteCategoryNames[category].data(), j, "_", n);
@@ -183,7 +252,7 @@ absl::Status PaletteEditor::DrawPaletteGroup(int category) {
// EditColorInPalette(*palette, n);
}
if (ImGui::BeginPopupContextItem(popup_id.c_str())) {
if (BeginPopupContextItem(popup_id.c_str())) {
RETURN_IF_ERROR(HandleColorPopup(*palette, category, j, n))
}
@@ -192,37 +261,12 @@ absl::Status PaletteEditor::DrawPaletteGroup(int category) {
// EditColorInPalette(*palette, n);
// }
ImGui::PopID();
PopID();
}
}
return absl::OkStatus();
}
namespace {
int CustomFormatString(char* buf, size_t buf_size, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
#ifdef IMGUI_USE_STB_SPRINTF
int w = stbsp_vsnprintf(buf, (int)buf_size, fmt, args);
#else
int w = vsnprintf(buf, buf_size, fmt, args);
#endif
va_end(args);
if (buf == nullptr) return w;
if (w == -1 || w >= (int)buf_size) w = (int)buf_size - 1;
buf[w] = 0;
return w;
}
static inline float color_saturate(float f) {
return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f;
}
#define F32_TO_INT8_SAT(_VAL) \
((int)(color_saturate(_VAL) * 255.0f + \
0.5f)) // Saturated, always output 0..255
} // namespace
absl::Status PaletteEditor::HandleColorPopup(gfx::SnesPalette& palette, int i,
int j, int n) {
auto col = gfx::ToFloatArray(palette[n]);
@@ -230,8 +274,8 @@ absl::Status PaletteEditor::HandleColorPopup(gfx::SnesPalette& palette, int i,
// TODO: Implement new update color function
}
if (ImGui::Button("Copy as..", ImVec2(-1, 0))) ImGui::OpenPopup("Copy");
if (ImGui::BeginPopup("Copy")) {
if (Button("Copy as..", ImVec2(-1, 0))) OpenPopup("Copy");
if (BeginPopup("Copy")) {
int cr = F32_TO_INT8_SAT(col[0]);
int cg = F32_TO_INT8_SAT(col[1]);
int cb = F32_TO_INT8_SAT(col[2]);
@@ -240,15 +284,15 @@ absl::Status PaletteEditor::HandleColorPopup(gfx::SnesPalette& palette, int i,
CustomFormatString(buf, IM_ARRAYSIZE(buf), "(%.3ff, %.3ff, %.3ff)", col[0],
col[1], col[2]);
if (ImGui::Selectable(buf)) ImGui::SetClipboardText(buf);
if (Selectable(buf)) SetClipboardText(buf);
CustomFormatString(buf, IM_ARRAYSIZE(buf), "(%d,%d,%d)", cr, cg, cb);
if (ImGui::Selectable(buf)) ImGui::SetClipboardText(buf);
if (Selectable(buf)) SetClipboardText(buf);
CustomFormatString(buf, IM_ARRAYSIZE(buf), "#%02X%02X%02X", cr, cg, cb);
if (ImGui::Selectable(buf)) ImGui::SetClipboardText(buf);
ImGui::EndPopup();
if (Selectable(buf)) SetClipboardText(buf);
EndPopup();
}
ImGui::EndPopup();
EndPopup();
return absl::OkStatus();
}
@@ -266,67 +310,67 @@ void PaletteEditor::DisplayPalette(gfx::SnesPalette& palette, bool loaded) {
}
static ImVec4 backup_color;
bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
open_popup |= ImGui::Button("Palette");
bool open_popup = ColorButton("MyColor##3b", color, misc_flags);
SameLine(0, GetStyle().ItemInnerSpacing.x);
open_popup |= Button("Palette");
if (open_popup) {
ImGui::OpenPopup("mypicker");
OpenPopup("mypicker");
backup_color = color;
}
if (ImGui::BeginPopup("mypicker")) {
if (BeginPopup("mypicker")) {
TEXT_WITH_SEPARATOR("Current Overworld Palette");
ImGui::ColorPicker4("##picker", (float*)&color,
misc_flags | ImGuiColorEditFlags_NoSidePreview |
ImGuiColorEditFlags_NoSmallPreview);
ImGui::SameLine();
ColorPicker4("##picker", (float*)&color,
misc_flags | ImGuiColorEditFlags_NoSidePreview |
ImGuiColorEditFlags_NoSmallPreview);
SameLine();
ImGui::BeginGroup(); // Lock X position
ImGui::Text("Current ==>");
ImGui::SameLine();
ImGui::Text("Previous");
BeginGroup(); // Lock X position
Text("Current ==>");
SameLine();
Text("Previous");
if (ImGui::Button("Update Map Palette")) {
if (Button("Update Map Palette")) {
}
ImGui::ColorButton(
ColorButton(
"##current", color,
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
ImVec2(60, 40));
ImGui::SameLine();
SameLine();
if (ImGui::ColorButton(
if (ColorButton(
"##previous", backup_color,
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
ImVec2(60, 40)))
color = backup_color;
// List of Colors in Overworld Palette
ImGui::Separator();
ImGui::Text("Palette");
Separator();
Text("Palette");
for (int n = 0; n < IM_ARRAYSIZE(saved_palette_); n++) {
ImGui::PushID(n);
if ((n % 8) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
PushID(n);
if ((n % 8) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
if (ImGui::ColorButton("##palette", saved_palette_[n],
palette_button_flags_2, ImVec2(20, 20)))
if (ColorButton("##palette", saved_palette_[n], palette_button_flags_2,
ImVec2(20, 20)))
color = ImVec4(saved_palette_[n].x, saved_palette_[n].y,
saved_palette_[n].z, color.w); // Preserve alpha!
if (ImGui::BeginDragDropTarget()) {
if (BeginDragDropTarget()) {
if (const ImGuiPayload* payload =
ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
memcpy((float*)&saved_palette_[n], payload->Data, sizeof(float) * 3);
if (const ImGuiPayload* payload =
ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
memcpy((float*)&saved_palette_[n], payload->Data, sizeof(float) * 4);
ImGui::EndDragDropTarget();
EndDragDropTarget();
}
ImGui::PopID();
PopID();
}
ImGui::EndGroup();
ImGui::EndPopup();
EndGroup();
EndPopup();
}
}
@@ -338,34 +382,34 @@ void PaletteEditor::DrawPortablePalette(gfx::SnesPalette& palette) {
}
if (ImGuiID child_id = ImGui::GetID((void*)(intptr_t)100);
ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true,
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
ImGui::BeginGroup(); // Lock X position
ImGui::Text("Palette");
BeginChild(child_id, GetContentRegionAvail(), true,
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
BeginGroup(); // Lock X position
Text("Palette");
for (int n = 0; n < IM_ARRAYSIZE(saved_palette_); n++) {
ImGui::PushID(n);
if ((n % 8) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
PushID(n);
if ((n % 8) != 0) SameLine(0.0f, GetStyle().ItemSpacing.y);
if (ImGui::ColorButton("##palette", saved_palette_[n],
palette_button_flags_2, ImVec2(20, 20)))
if (ColorButton("##palette", saved_palette_[n], palette_button_flags_2,
ImVec2(20, 20)))
ImVec4(saved_palette_[n].x, saved_palette_[n].y, saved_palette_[n].z,
1.0f); // Preserve alpha!
if (ImGui::BeginDragDropTarget()) {
if (BeginDragDropTarget()) {
if (const ImGuiPayload* payload =
ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
memcpy((float*)&saved_palette_[n], payload->Data, sizeof(float) * 3);
if (const ImGuiPayload* payload =
ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
memcpy((float*)&saved_palette_[n], payload->Data, sizeof(float) * 4);
ImGui::EndDragDropTarget();
EndDragDropTarget();
}
ImGui::PopID();
PopID();
}
ImGui::EndGroup();
EndGroup();
}
ImGui::EndChild();
EndChild();
}
} // namespace editor

View File

@@ -14,17 +14,36 @@ namespace yaze {
namespace app {
namespace editor {
constexpr int kNumPalettes = 11;
constexpr int kNumPalettes = 14;
enum PaletteCategory {
kSword,
kShield,
kClothes,
kWorldColors,
kAreaColors,
kGlobalSprites,
kSpritesAux1,
kSpritesAux2,
kSpritesAux3,
kDungeons,
kWorldMap,
kDungeonMap,
kTriforce,
kCrystal
};
static constexpr absl::string_view kPaletteCategoryNames[] = {
"Sword", "Shield", "Clothes", "World Colors",
"Area Colors", "Enemies", "Dungeons", "World Map",
"Dungeon Map", "Triforce", "Crystal"};
"Sword", "Shield", "Clothes", "World Colors",
"Area Colors", "Global Sprites", "Sprites Aux1", "Sprites Aux2",
"Sprites Aux3", "Dungeons", "World Map", "Dungeon Map",
"Triforce", "Crystal"};
static constexpr absl::string_view kPaletteGroupNames[] = {
"swords", "shields", "armors", "ow_main",
"ow_aux", "global_sprites", "dungeon_main", "ow_mini_map",
"ow_mini_map", "3d_object", "3d_object"};
"swords", "shields", "armors", "ow_main",
"ow_aux", "global_sprites", "sprites_aux1", "sprites_aux2",
"sprites_aux3", "dungeon_main", "ow_mini_map", "ow_mini_map",
"3d_object", "3d_object"};
namespace palette_internal {
struct PaletteChange {
@@ -95,7 +114,6 @@ class PaletteEditor : public SharedRom, public Editor {
absl::Status Redo() override { return absl::OkStatus(); }
void DisplayCategoryTable();
absl::Status DrawPaletteGroups();
absl::Status EditColorInPalette(gfx::SnesPalette& palette, int index);
absl::Status ResetColorToOriginal(gfx::SnesPalette& palette, int index,
@@ -106,7 +124,6 @@ class PaletteEditor : public SharedRom, public Editor {
private:
absl::Status HandleColorPopup(gfx::SnesPalette& palette, int i, int j, int n);
absl::Status InitializeSavedPalette(const gfx::SnesPalette& palette) {
for (int n = 0; n < palette.size(); n++) {
ASSIGN_OR_RETURN(auto color, palette.GetColor(n));