7#include "absl/strings/str_format.h"
12#include "imgui/imgui.h"
26 size_t palette_size) {
27 if (group_name ==
"ow_main" || group_name ==
"ow_aux" ||
28 group_name ==
"ow_animated" || group_name ==
"sprites_aux1" ||
29 group_name ==
"sprites_aux2" || group_name ==
"sprites_aux3") {
32 if (group_name ==
"global_sprites" || group_name ==
"armors" ||
33 group_name ==
"dungeon_main") {
36 if (group_name ==
"hud" || group_name ==
"ow_mini_map") {
39 if (group_name ==
"swords") {
42 if (group_name ==
"shields") {
45 if (group_name ==
"grass") {
48 if (group_name ==
"3d_object") {
52 if (palette_size % 16 == 0) {
55 if (palette_size % 15 == 0) {
58 if (palette_size % 7 == 0) {
62 int fallback = palette_size > 0 ?
static_cast<int>(palette_size) : 1;
63 return {fallback,
false};
67 if (colors_per_row <= 0) {
70 return static_cast<int>((palette_size + colors_per_row - 1) / colors_per_row);
75 size_t& out_offset,
int& out_length) {
76 if (palette.
empty()) {
83 const int clamped_row = std::clamp(row_index, 0, std::max(0, max_rows - 1));
84 const int row_offset = clamped_row * layout.colors_per_row;
85 const size_t offset =
static_cast<size_t>(
86 row_offset + (layout.has_explicit_transparent ? 1 : 0));
88 layout.colors_per_row - (layout.has_explicit_transparent ? 1 : 0);
89 length = std::clamp(length, 1, 15);
91 if (offset >= palette.
size()) {
95 if (offset + length > palette.
size()) {
96 length =
static_cast<int>(palette.
size() - offset);
101 return out_length > 0;
115 ImGui::TextDisabled(
"Load a ROM to manage palettes");
130 ImGui::TextDisabled(
"Load a ROM to manage palettes");
131 return absl::OkStatus();
142 return absl::OkStatus();
194 ImGui::SetNextItemWidth(160);
195 if (ImGui::Combo(
"Group",
197 kPaletteGroupAddressesKeys,
198 IM_ARRAYSIZE(kPaletteGroupAddressesKeys))) {
203 ImGui::SetNextItemWidth(100);
205 if (ImGui::InputInt(
"Palette", &palette_idx)) {
212 ImGui::SetNextItemWidth(100);
214 if (ImGui::InputInt(
"Sub-Palette", &sub_idx)) {
218 HOVER_HINT(
"Sub-palette row (0-7 for SNES 128-color palettes)");
229 if (!palette_group_result) {
230 ImGui::TextDisabled(
"Invalid palette group");
234 auto palette_group = *palette_group_result;
236 ImGui::TextDisabled(
"Invalid palette index");
242 auto palette_group_name =
244 auto layout = GetPaletteRowLayout(palette_group_name, palette.size());
246 int colors_per_row = layout.colors_per_row;
247 int total_colors =
static_cast<int>(palette.size());
248 int num_rows = GetPaletteRowCount(palette.size(), colors_per_row);
253 for (
int row = 0; row < num_rows; row++) {
254 for (
int col = 0; col < colors_per_row; col++) {
255 int idx = row * colors_per_row + col;
256 if (idx >= total_colors)
262 auto& color = palette[idx];
263 ImVec4 im_color(color.rgb().x / 255.0f, color.rgb().y / 255.0f,
264 color.rgb().z / 255.0f, 1.0f);
267 bool in_sub_palette =
269 if (in_sub_palette) {
270 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f);
271 ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(1.0f, 1.0f, 0.0f, 1.0f));
274 std::string
id = absl::StrFormat(
"##PalColor%d", idx);
275 if (ImGui::ColorButton(
id.c_str(), im_color,
276 ImGuiColorEditFlags_NoTooltip, ImVec2(18, 18))) {
282 if (in_sub_palette) {
283 ImGui::PopStyleColor();
284 ImGui::PopStyleVar();
287 if (ImGui::IsItemHovered()) {
288 ImGui::BeginTooltip();
289 ImGui::Text(
"Index: %d (Row %d, Col %d)", idx, row, col);
290 ImGui::Text(
"SNES: $%04X", color.snes());
291 ImGui::Text(
"RGB: %d, %d, %d",
static_cast<int>(color.rgb().x),
292 static_cast<int>(color.rgb().y),
293 static_cast<int>(color.rgb().z));
300 ImGui::Text(
"Sub-palette Row:");
301 for (
int i = 0; i < std::min(8, num_rows); i++) {
306 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.3f, 0.5f, 0.8f, 1.0f));
308 if (ImGui::SmallButton(absl::StrFormat(
"%d", i).c_str())) {
313 ImGui::PopStyleColor();
323 if (ImGui::Button(
ICON_MD_BRUSH " Apply to Current Sheet")) {
326 ImGui::EndDisabled();
327 HOVER_HINT(
"Apply palette to the currently selected sheet");
335 HOVER_HINT(
"Apply palette to all active graphics sheets");
340 " Apply to %zu Selected",
347 HOVER_HINT(
"Apply palette to all selected sheets in browser");
358 HOVER_HINT(
"Force refresh of current sheet graphics");
365 auto palette_group_name =
367 auto palette_group_result =
369 if (!palette_group_result)
372 auto palette_group = *palette_group_result;
377 if (palette.empty()) {
382 if (sheet.is_active() && sheet.surface()) {
383 size_t palette_offset = 0;
384 int palette_length = 0;
385 if (ComputePaletteSlice(palette_group_name, palette,
387 palette_offset, palette_length)) {
388 sheet.SetPaletteWithTransparent(palette, palette_offset, palette_length);
390 sheet.SetPaletteWithTransparent(
391 palette, 0, std::min(7,
static_cast<int>(palette.size())));
401 auto palette_group_name =
403 auto palette_group_result =
405 if (!palette_group_result)
408 auto palette_group = *palette_group_result;
413 if (palette.empty()) {
416 size_t palette_offset = 0;
417 int palette_length = 0;
418 const bool has_slice = ComputePaletteSlice(
420 palette_offset, palette_length);
424 if (sheet.is_active() && sheet.surface()) {
426 sheet.SetPaletteWithTransparent(palette, palette_offset,
429 sheet.SetPaletteWithTransparent(
430 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).
#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[]
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