7#include "absl/strings/str_format.h"
15#include "imgui/imgui.h"
29 size_t palette_size) {
30 if (group_name ==
"ow_main" || group_name ==
"ow_aux" ||
31 group_name ==
"ow_animated" || group_name ==
"sprites_aux1" ||
32 group_name ==
"sprites_aux2" || group_name ==
"sprites_aux3") {
35 if (group_name ==
"global_sprites" || group_name ==
"armors" ||
36 group_name ==
"dungeon_main") {
39 if (group_name ==
"hud" || group_name ==
"ow_mini_map") {
42 if (group_name ==
"swords") {
45 if (group_name ==
"shields") {
48 if (group_name ==
"grass") {
51 if (group_name ==
"3d_object") {
55 if (palette_size % 16 == 0) {
58 if (palette_size % 15 == 0) {
61 if (palette_size % 7 == 0) {
65 int fallback = palette_size > 0 ?
static_cast<int>(palette_size) : 1;
66 return {fallback,
false};
70 if (colors_per_row <= 0) {
73 return static_cast<int>((palette_size + colors_per_row - 1) / colors_per_row);
78 size_t& out_offset,
int& out_length) {
79 if (palette.
empty()) {
86 const int clamped_row = std::clamp(row_index, 0, std::max(0, max_rows - 1));
87 const int row_offset = clamped_row * layout.colors_per_row;
88 const size_t offset =
static_cast<size_t>(
89 row_offset + (layout.has_explicit_transparent ? 1 : 0));
91 layout.colors_per_row - (layout.has_explicit_transparent ? 1 : 0);
92 length = std::clamp(length, 1, 15);
94 if (offset >= palette.
size()) {
98 if (offset + length > palette.
size()) {
99 length =
static_cast<int>(palette.
size() - offset);
104 return out_length > 0;
118 ImGui::TextDisabled(
"Load a ROM to manage palettes");
133 ImGui::TextDisabled(
"Load a ROM to manage palettes");
134 return absl::OkStatus();
145 return absl::OkStatus();
198 if (ImGui::Combo(
"Group",
200 kPaletteGroupAddressesKeys,
201 IM_ARRAYSIZE(kPaletteGroupAddressesKeys))) {
206 ImGui::SetNextItemWidth(
209 if (ImGui::InputInt(
"Palette", &palette_idx)) {
216 ImGui::SetNextItemWidth(
219 if (ImGui::InputInt(
"Sub-Palette", &sub_idx)) {
223 HOVER_HINT(
"Sub-palette row (0-7 for SNES 128-color palettes)");
234 if (!palette_group_result) {
235 ImGui::TextDisabled(
"Invalid palette group");
239 auto palette_group = *palette_group_result;
241 ImGui::TextDisabled(
"Invalid palette index");
247 auto palette_group_name =
249 auto layout = GetPaletteRowLayout(palette_group_name, palette.size());
251 int colors_per_row = layout.colors_per_row;
252 int total_colors =
static_cast<int>(palette.size());
253 int num_rows = GetPaletteRowCount(palette.size(), colors_per_row);
258 for (
int row = 0; row < num_rows; row++) {
259 for (
int col = 0; col < colors_per_row; col++) {
260 int idx = row * colors_per_row + col;
261 if (idx >= total_colors)
267 auto& color = palette[idx];
268 ImVec4 im_color(color.rgb().x / 255.0f, color.rgb().y / 255.0f,
269 color.rgb().z / 255.0f, 1.0f);
272 bool in_sub_palette =
274 std::optional<gui::StyleVarGuard> pal_border_var;
275 std::optional<gui::StyleColorGuard> pal_border_color;
276 if (in_sub_palette) {
277 pal_border_var.emplace(ImGuiStyleVar_FrameBorderSize, 2.0f);
281 std::string
id = absl::StrFormat(
"##PalColor%d", idx);
282 if (ImGui::ColorButton(
id.c_str(), im_color,
283 ImGuiColorEditFlags_NoTooltip, ImVec2(18, 18))) {
289 pal_border_color.reset();
290 pal_border_var.reset();
292 if (ImGui::IsItemHovered()) {
293 ImGui::BeginTooltip();
294 ImGui::Text(
"Index: %d (Row %d, Col %d)", idx, row, col);
295 ImGui::Text(
"SNES: $%04X", color.snes());
296 ImGui::Text(
"RGB: %d, %d, %d",
static_cast<int>(color.rgb().x),
297 static_cast<int>(color.rgb().y),
298 static_cast<int>(color.rgb().z));
305 ImGui::Text(
"Sub-palette Row:");
306 for (
int i = 0; i < std::min(8, num_rows); i++) {
311 std::optional<gui::StyleColorGuard> sel_guard;
315 if (ImGui::SmallButton(absl::StrFormat(
"%d", i).c_str())) {
328 ImGui::BeginDisabled(no_sheets);
329 if (ImGui::Button(
ICON_MD_BRUSH " Apply to Current Sheet")) {
332 ImGui::EndDisabled();
333 if (no_sheets && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
334 ImGui::SetTooltip(
"Open a graphics sheet first");
336 HOVER_HINT(
"Apply palette to the currently selected sheet");
345 HOVER_HINT(
"Apply palette to all active graphics sheets");
350 " Apply to %zu Selected",
357 HOVER_HINT(
"Apply palette to all selected sheets in browser");
368 HOVER_HINT(
"Force refresh of current sheet graphics");
375 auto palette_group_name =
377 auto palette_group_result =
379 if (!palette_group_result)
382 auto palette_group = *palette_group_result;
387 if (palette.empty()) {
392 if (sheet.is_active() && sheet.surface()) {
393 size_t palette_offset = 0;
394 int palette_length = 0;
395 if (ComputePaletteSlice(palette_group_name, palette,
397 palette_offset, palette_length)) {
398 sheet.SetPaletteWithTransparent(palette, palette_offset, palette_length);
400 sheet.SetPaletteWithTransparent(
401 palette, 0, std::min(7,
static_cast<int>(palette.size())));
411 auto palette_group_name =
413 auto palette_group_result =
415 if (!palette_group_result)
418 auto palette_group = *palette_group_result;
423 if (palette.empty()) {
426 size_t palette_offset = 0;
427 int palette_length = 0;
428 const bool has_slice = ComputePaletteSlice(
430 palette_offset, palette_length);
434 if (sheet.is_active() && sheet.surface()) {
436 sheet.SetPaletteWithTransparent(palette, palette_offset,
439 sheet.SetPaletteWithTransparent(
440 palette, 0, std::min(7,
static_cast<int>(palette.size())));
std::set< uint16_t > selected_sheets
uint16_t current_sheet_id
std::set< uint16_t > open_sheets
uint64_t sub_palette_index
uint64_t palette_group_index
absl::Status Update()
Legacy Update method for backward compatibility.
void DrawPresets()
Draw quick preset buttons.
GraphicsEditorState * state_
void Draw(bool *p_open) override
Draw the palette controls UI (EditorPanel interface)
void ApplyPaletteToSheet(uint16_t sheet_id)
Apply current palette to specified sheet.
void DrawPaletteDisplay()
Draw the current palette display.
void DrawApplyButtons()
Draw apply buttons.
void Initialize()
Initialize the panel.
void ApplyPaletteToAllSheets()
Apply current palette to all active sheets.
void DrawPaletteGroupSelector()
Draw palette group selection.
zelda3::GameData * game_data_
auto mutable_gfx_sheets()
Get mutable reference to all graphics sheets.
void NotifySheetModified(int sheet_index)
Notify Arena that a graphics sheet has been modified.
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
static float GetComboWidth()
static float GetStandardInputWidth()
#define ICON_MD_LANDSCAPE
#define ICON_MD_CHECKLIST
#define ICON_MD_ACCOUNT_BOX
#define ICON_MD_FORMAT_PAINT
#define HOVER_HINT(string)
PaletteRowLayout GetPaletteRowLayout(std::string_view group_name, size_t palette_size)
bool ComputePaletteSlice(std::string_view group_name, const gfx::SnesPalette &palette, int row_index, size_t &out_offset, int &out_length)
int GetPaletteRowCount(size_t palette_size, int colors_per_row)
constexpr const char * kPaletteGroupAddressesKeys[]
ImVec4 GetSelectedColor()
void TextWithSeparators(const absl::string_view &text)
constexpr uint32_t kNumGfxSheets
bool has_explicit_transparent
PaletteGroup * get_group(const std::string &group_name)
auto palette(int i) const
gfx::PaletteGroupMap palette_groups