- Added a comprehensive testing framework with support for unit, integration, and UI tests, improving overall test coverage and reliability. - Integrated ImGui Test Engine for UI testing, allowing for real-time feedback and visualization of test results. - Updated CMake configuration to conditionally include testing components based on build options, enhancing flexibility for developers. - Introduced a new command in the CLI for running asset loading tests on ROMs, providing a straightforward way to validate functionality. - Enhanced error handling and resource management during testing, ensuring stability and clarity in test execution. - Improved user interface with a dedicated test dashboard for monitoring test progress and results, enhancing developer experience.
265 lines
8.9 KiB
C++
265 lines
8.9 KiB
C++
#include "color.h"
|
|
|
|
#include "app/gfx/snes_color.h"
|
|
#include "app/gfx/snes_palette.h"
|
|
#include "imgui/imgui.h"
|
|
|
|
namespace yaze {
|
|
namespace gui {
|
|
|
|
ImVec4 ConvertSnesColorToImVec4(const gfx::SnesColor& color) {
|
|
return ImVec4(color.rgb().x / 255.0f, color.rgb().y / 255.0f,
|
|
color.rgb().z / 255.0f, 1.0f);
|
|
}
|
|
|
|
gfx::SnesColor ConvertImVec4ToSnesColor(const ImVec4& color) {
|
|
return gfx::SnesColor(color);
|
|
}
|
|
|
|
IMGUI_API bool SnesColorButton(absl::string_view id, gfx::SnesColor& color,
|
|
ImGuiColorEditFlags flags,
|
|
const ImVec2& size_arg) {
|
|
// Convert the SNES color values to ImGui color values
|
|
ImVec4 displayColor = ConvertSnesColorToImVec4(color);
|
|
|
|
// Call the original ImGui::ColorButton with the converted color
|
|
bool pressed = ImGui::ColorButton(id.data(), displayColor, flags, size_arg);
|
|
// Add the SNES color representation to the tooltip
|
|
if (ImGui::IsItemHovered()) {
|
|
ImGui::BeginTooltip();
|
|
ImGui::Text("SNES: $%04X", color.snes());
|
|
ImGui::EndTooltip();
|
|
}
|
|
return pressed;
|
|
}
|
|
|
|
IMGUI_API bool SnesColorEdit4(absl::string_view label, gfx::SnesColor* color,
|
|
ImGuiColorEditFlags flags) {
|
|
ImVec4 displayColor = ConvertSnesColorToImVec4(*color);
|
|
|
|
// Call the original ImGui::ColorEdit4 with the converted color
|
|
bool pressed =
|
|
ImGui::ColorEdit4(label.data(), (float*)&displayColor.x, flags);
|
|
|
|
color->set_rgb(displayColor);
|
|
color->set_snes(gfx::ConvertRgbToSnes(displayColor));
|
|
|
|
return pressed;
|
|
}
|
|
|
|
IMGUI_API bool DisplayPalette(gfx::SnesPalette& palette, bool loaded) {
|
|
static ImVec4 color = ImVec4(0, 0, 0, 255.f);
|
|
ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview |
|
|
ImGuiColorEditFlags_NoDragDrop |
|
|
ImGuiColorEditFlags_NoOptions;
|
|
|
|
// Generate a default palette. The palette will persist and can be edited.
|
|
static bool init = false;
|
|
static ImVec4 saved_palette[32] = {};
|
|
if (loaded && !init) {
|
|
for (int n = 0; n < palette.size(); n++) {
|
|
auto color = palette[n];
|
|
saved_palette[n].x = color.rgb().x / 255;
|
|
saved_palette[n].y = color.rgb().y / 255;
|
|
saved_palette[n].z = color.rgb().z / 255;
|
|
saved_palette[n].w = 255; // Alpha
|
|
}
|
|
init = true;
|
|
}
|
|
|
|
static ImVec4 backup_color;
|
|
ImGui::Text("Current ==>");
|
|
ImGui::SameLine();
|
|
ImGui::Text("Previous");
|
|
|
|
ImGui::ColorButton(
|
|
"##current", color,
|
|
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
|
|
ImVec2(60, 40));
|
|
ImGui::SameLine();
|
|
|
|
if (ImGui::ColorButton(
|
|
"##previous", backup_color,
|
|
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
|
|
ImVec2(60, 40)))
|
|
color = backup_color;
|
|
ImGui::Separator();
|
|
|
|
ImGui::BeginGroup(); // Lock X position
|
|
ImGui::Text("Palette");
|
|
for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) {
|
|
ImGui::PushID(n);
|
|
if ((n % 4) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
|
|
|
ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha |
|
|
ImGuiColorEditFlags_NoPicker |
|
|
ImGuiColorEditFlags_NoTooltip;
|
|
if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags,
|
|
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 (const ImGuiPayload* payload =
|
|
ImGui::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))
|
|
memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
|
|
ImGui::EndDragDropTarget();
|
|
}
|
|
|
|
ImGui::PopID();
|
|
}
|
|
ImGui::EndGroup();
|
|
ImGui::SameLine();
|
|
|
|
ImGui::ColorPicker4("##picker", (float*)&color,
|
|
misc_flags | ImGuiColorEditFlags_NoSidePreview |
|
|
ImGuiColorEditFlags_NoSmallPreview);
|
|
return true;
|
|
}
|
|
|
|
void SelectablePalettePipeline(uint64_t& palette_id, bool& refresh_graphics,
|
|
gfx::SnesPalette& palette) {
|
|
const auto palette_row_size = 7;
|
|
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");
|
|
for (int n = 0; n < palette.size(); n++) {
|
|
ImGui::PushID(n);
|
|
if ((n % palette_row_size) != 0)
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
|
|
|
// Check if the current row is selected
|
|
bool is_selected = (palette_id == n / palette_row_size);
|
|
|
|
// Add outline rectangle to the selected row
|
|
if (is_selected) {
|
|
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(1.0f, 1.0f, 0.0f, 1.0f));
|
|
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f);
|
|
}
|
|
|
|
if (gui::SnesColorButton("##palette", palette[n],
|
|
ImGuiColorEditFlags_NoAlpha |
|
|
ImGuiColorEditFlags_NoPicker |
|
|
ImGuiColorEditFlags_NoTooltip,
|
|
ImVec2(20, 20))) {
|
|
palette_id = n / palette_row_size;
|
|
refresh_graphics = true;
|
|
}
|
|
|
|
if (is_selected) {
|
|
ImGui::PopStyleColor();
|
|
ImGui::PopStyleVar();
|
|
}
|
|
|
|
ImGui::PopID();
|
|
}
|
|
ImGui::EndGroup();
|
|
}
|
|
ImGui::EndChild();
|
|
}
|
|
|
|
absl::Status DisplayEditablePalette(gfx::SnesPalette& palette,
|
|
const std::string& title,
|
|
bool show_color_picker, int colors_per_row,
|
|
ImGuiColorEditFlags flags) {
|
|
// Default flags if none provided
|
|
if (flags == 0) {
|
|
flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker |
|
|
ImGuiColorEditFlags_NoTooltip;
|
|
}
|
|
|
|
// Display title if provided
|
|
if (!title.empty()) {
|
|
ImGui::Text("%s", title.c_str());
|
|
}
|
|
static int selected_color = 0;
|
|
|
|
if (show_color_picker) {
|
|
ImGui::Separator();
|
|
static ImVec4 current_color = ImVec4(0, 0, 0, 1.0f);
|
|
|
|
if (ImGui::ColorPicker4("Color Picker", (float*)¤t_color,
|
|
ImGuiColorEditFlags_NoSidePreview |
|
|
ImGuiColorEditFlags_NoSmallPreview)) {
|
|
// Convert the selected color to SNES format and add it to the palette
|
|
gfx::SnesColor snes_color(current_color);
|
|
palette.UpdateColor(selected_color, snes_color);
|
|
}
|
|
}
|
|
|
|
// Display the palette colors in a grid
|
|
ImGui::BeginGroup(); // Lock X position
|
|
for (int n = 0; n < palette.size(); n++) {
|
|
ImGui::PushID(n);
|
|
if ((n % colors_per_row) != 0) {
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
|
}
|
|
|
|
// Create a unique ID for this color button
|
|
std::string button_id = "##palette_" + std::to_string(n);
|
|
|
|
// Display the color button
|
|
if (SnesColorButton(button_id, palette[n], flags, ImVec2(20, 20))) {
|
|
// Color was clicked, could be used to select this color
|
|
selected_color = n;
|
|
}
|
|
|
|
if (ImGui::BeginPopupContextItem()) {
|
|
if (ImGui::MenuItem("Edit Color")) {
|
|
// Open color picker for this color
|
|
ImGui::OpenPopup(("Edit Color##" + std::to_string(n)).c_str());
|
|
}
|
|
|
|
if (ImGui::MenuItem("Copy as SNES Value")) {
|
|
std::string clipboard = absl::StrFormat("$%04X", palette[n].snes());
|
|
ImGui::SetClipboardText(clipboard.c_str());
|
|
}
|
|
|
|
if (ImGui::MenuItem("Copy as RGB")) {
|
|
auto rgb = palette[n].rgb();
|
|
std::string clipboard =
|
|
absl::StrFormat("(%d,%d,%d)", (int)(rgb.x * 255),
|
|
(int)(rgb.y * 255), (int)(rgb.z * 255));
|
|
ImGui::SetClipboardText(clipboard.c_str());
|
|
}
|
|
|
|
if (ImGui::MenuItem("Copy as Hex")) {
|
|
auto rgb = palette[n].rgb();
|
|
std::string clipboard =
|
|
absl::StrFormat("#%02X%02X%02X", (int)(rgb.x * 255),
|
|
(int)(rgb.y * 255), (int)(rgb.z * 255));
|
|
ImGui::SetClipboardText(clipboard.c_str());
|
|
}
|
|
|
|
ImGui::EndPopup();
|
|
}
|
|
|
|
// Color picker popup
|
|
if (ImGui::BeginPopup(("Edit Color##" + std::to_string(n)).c_str())) {
|
|
ImGuiColorEditFlags picker_flags = ImGuiColorEditFlags_NoSidePreview |
|
|
ImGuiColorEditFlags_NoSmallPreview;
|
|
|
|
ImVec4 color = ConvertSnesColorToImVec4(palette[n]);
|
|
if (ImGui::ColorPicker4("##picker", (float*)&color, picker_flags)) {
|
|
// Update the SNES color when the picker changes
|
|
palette[n] = ConvertImVec4ToSnesColor(color);
|
|
}
|
|
|
|
ImGui::EndPopup();
|
|
}
|
|
|
|
ImGui::PopID();
|
|
}
|
|
ImGui::EndGroup();
|
|
|
|
return absl::OkStatus();
|
|
}
|
|
|
|
} // namespace gui
|
|
} // namespace yaze
|