yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
palette_controls_panel.cc
Go to the documentation of this file.
2
3#include "absl/strings/str_format.h"
8#include "imgui/imgui.h"
9
10namespace yaze {
11namespace editor {
12
14
16 // Initialize with default palette group
20}
21
22void PaletteControlsPanel::Draw(bool* p_open) {
23 // EditorPanel interface - delegate to existing Update() logic
24 if (!rom_ || !rom_->is_loaded()) {
25 ImGui::TextDisabled("Load a ROM to manage palettes");
26 return;
27 }
28
30 ImGui::Separator();
32 ImGui::Separator();
34 ImGui::Separator();
36}
37
39 if (!rom_ || !rom_->is_loaded()) {
40 ImGui::TextDisabled("Load a ROM to manage palettes");
41 return absl::OkStatus();
42 }
43
45 ImGui::Separator();
47 ImGui::Separator();
49 ImGui::Separator();
51
52 return absl::OkStatus();
53}
54
56 gui::TextWithSeparators("Quick Presets");
57
58 if (ImGui::Button(ICON_MD_LANDSCAPE " Overworld")) {
59 state_->palette_group_index = 0; // Dungeon Main (used for overworld too)
62 }
63 HOVER_HINT("Standard overworld palette");
64
65 ImGui::SameLine();
66
67 if (ImGui::Button(ICON_MD_CASTLE " Dungeon")) {
68 state_->palette_group_index = 0; // Dungeon Main
71 }
72 HOVER_HINT("Standard dungeon palette");
73
74 ImGui::SameLine();
75
76 if (ImGui::Button(ICON_MD_PERSON " Sprites")) {
77 state_->palette_group_index = 4; // Sprites Aux1
80 }
81 HOVER_HINT("Sprite/enemy palette");
82
83 if (ImGui::Button(ICON_MD_ACCOUNT_BOX " Link")) {
84 state_->palette_group_index = 3; // Sprite Aux3 (Link's palettes)
87 }
88 HOVER_HINT("Link's palette");
89
90 ImGui::SameLine();
91
92 if (ImGui::Button(ICON_MD_MENU " HUD")) {
93 state_->palette_group_index = 6; // HUD palettes
96 }
97 HOVER_HINT("HUD/menu palette");
98}
99
101 gui::TextWithSeparators("Palette Selection");
102
103 // Palette group combo
104 ImGui::SetNextItemWidth(160);
105 if (ImGui::Combo("Group", reinterpret_cast<int*>(&state_->palette_group_index),
106 kPaletteGroupAddressesKeys,
107 IM_ARRAYSIZE(kPaletteGroupAddressesKeys))) {
108 state_->refresh_graphics = true;
109 }
110
111 // Palette index within group
112 ImGui::SetNextItemWidth(100);
113 int palette_idx = static_cast<int>(state_->palette_index);
114 if (ImGui::InputInt("Palette", &palette_idx)) {
115 state_->palette_index = static_cast<uint64_t>(std::max(0, palette_idx));
116 state_->refresh_graphics = true;
117 }
118 HOVER_HINT("Palette index within the group");
119
120 // Sub-palette index (for multi-row palettes)
121 ImGui::SetNextItemWidth(100);
122 int sub_idx = static_cast<int>(state_->sub_palette_index);
123 if (ImGui::InputInt("Sub-Palette", &sub_idx)) {
124 state_->sub_palette_index = static_cast<uint64_t>(std::max(0, sub_idx));
125 state_->refresh_graphics = true;
126 }
127 HOVER_HINT("Sub-palette row (0-7 for SNES 128-color palettes)");
128}
129
131 gui::TextWithSeparators("Current Palette");
132
133 // Get the current palette from GameData
134 if (!game_data_) return;
135 auto palette_group_result = game_data_->palette_groups.get_group(
136 kPaletteGroupAddressesKeys[state_->palette_group_index]);
137 if (!palette_group_result) {
138 ImGui::TextDisabled("Invalid palette group");
139 return;
140 }
141
142 auto palette_group = *palette_group_result;
143 if (state_->palette_index >= palette_group.size()) {
144 ImGui::TextDisabled("Invalid palette index");
145 return;
146 }
147
148 auto palette = palette_group.palette(state_->palette_index);
149
150 // Display palette colors in rows of 16
151 int colors_per_row = 16;
152 int total_colors = static_cast<int>(palette.size());
153 int num_rows = (total_colors + colors_per_row - 1) / colors_per_row;
154
155 for (int row = 0; row < num_rows; row++) {
156 for (int col = 0; col < colors_per_row; col++) {
157 int idx = row * colors_per_row + col;
158 if (idx >= total_colors) break;
159
160 if (col > 0) ImGui::SameLine();
161
162 auto& color = palette[idx];
163 ImVec4 im_color(color.rgb().x / 255.0f, color.rgb().y / 255.0f,
164 color.rgb().z / 255.0f, 1.0f);
165
166 // Highlight current sub-palette row
167 bool in_sub_palette =
168 (row == static_cast<int>(state_->sub_palette_index));
169 if (in_sub_palette) {
170 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f);
171 ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(1.0f, 1.0f, 0.0f, 1.0f));
172 }
173
174 std::string id = absl::StrFormat("##PalColor%d", idx);
175 if (ImGui::ColorButton(id.c_str(), im_color,
176 ImGuiColorEditFlags_NoTooltip, ImVec2(18, 18))) {
177 // Clicking a color in a row selects that sub-palette
178 state_->sub_palette_index = static_cast<uint64_t>(row);
179 state_->refresh_graphics = true;
180 }
181
182 if (in_sub_palette) {
183 ImGui::PopStyleColor();
184 ImGui::PopStyleVar();
185 }
186
187 if (ImGui::IsItemHovered()) {
188 ImGui::BeginTooltip();
189 ImGui::Text("Index: %d (Row %d, Col %d)", idx, row, col);
190 ImGui::Text("SNES: $%04X", color.snes());
191 ImGui::Text("RGB: %d, %d, %d", static_cast<int>(color.rgb().x),
192 static_cast<int>(color.rgb().y),
193 static_cast<int>(color.rgb().z));
194 ImGui::EndTooltip();
195 }
196 }
197 }
198
199 // Row selection buttons
200 ImGui::Text("Sub-palette Row:");
201 for (int i = 0; i < std::min(8, num_rows); i++) {
202 if (i > 0) ImGui::SameLine();
203 bool selected = (state_->sub_palette_index == static_cast<uint64_t>(i));
204 if (selected) {
205 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.3f, 0.5f, 0.8f, 1.0f));
206 }
207 if (ImGui::SmallButton(absl::StrFormat("%d", i).c_str())) {
208 state_->sub_palette_index = static_cast<uint64_t>(i);
209 state_->refresh_graphics = true;
210 }
211 if (selected) {
212 ImGui::PopStyleColor();
213 }
214 }
215}
216
218 gui::TextWithSeparators("Apply Palette");
219
220 // Apply to current sheet
221 ImGui::BeginDisabled(state_->open_sheets.empty());
222 if (ImGui::Button(ICON_MD_BRUSH " Apply to Current Sheet")) {
224 }
225 ImGui::EndDisabled();
226 HOVER_HINT("Apply palette to the currently selected sheet");
227
228 ImGui::SameLine();
229
230 // Apply to all sheets
231 if (ImGui::Button(ICON_MD_FORMAT_PAINT " Apply to All Sheets")) {
233 }
234 HOVER_HINT("Apply palette to all active graphics sheets");
235
236 // Apply to selected sheets (multi-select)
237 if (!state_->selected_sheets.empty()) {
238 if (ImGui::Button(
239 absl::StrFormat(ICON_MD_CHECKLIST " Apply to %zu Selected",
240 state_->selected_sheets.size())
241 .c_str())) {
242 for (uint16_t sheet_id : state_->selected_sheets) {
243 ApplyPaletteToSheet(sheet_id);
244 }
245 }
246 HOVER_HINT("Apply palette to all selected sheets in browser");
247 }
248
249 // Refresh button
250 ImGui::Separator();
251 if (ImGui::Button(ICON_MD_REFRESH " Refresh Graphics")) {
252 state_->refresh_graphics = true;
253 if (!state_->open_sheets.empty()) {
255 }
256 }
257 HOVER_HINT("Force refresh of current sheet graphics");
258}
259
261 if (!rom_ || !rom_->is_loaded() || !game_data_) return;
262
263 auto palette_group_result = game_data_->palette_groups.get_group(
264 kPaletteGroupAddressesKeys[state_->palette_group_index]);
265 if (!palette_group_result) return;
266
267 auto palette_group = *palette_group_result;
268 if (state_->palette_index >= palette_group.size()) return;
269
270 auto palette = palette_group.palette(state_->palette_index);
271
272 auto& sheet = gfx::Arena::Get().mutable_gfx_sheets()->at(sheet_id);
273 if (sheet.is_active() && sheet.surface()) {
274 sheet.SetPaletteWithTransparent(palette, state_->sub_palette_index);
276 }
277}
278
280 if (!rom_ || !rom_->is_loaded() || !game_data_) return;
281
282 auto palette_group_result = game_data_->palette_groups.get_group(
283 kPaletteGroupAddressesKeys[state_->palette_group_index]);
284 if (!palette_group_result) return;
285
286 auto palette_group = *palette_group_result;
287 if (state_->palette_index >= palette_group.size()) return;
288
289 auto palette = palette_group.palette(state_->palette_index);
290
291 for (int i = 0; i < zelda3::kNumGfxSheets; i++) {
292 auto& sheet = gfx::Arena::Get().mutable_gfx_sheets()->data()[i];
293 if (sheet.is_active() && sheet.surface()) {
294 sheet.SetPaletteWithTransparent(palette, state_->sub_palette_index);
296 }
297 }
298}
299
300} // namespace editor
301} // namespace yaze
bool is_loaded() const
Definition rom.h:128
absl::Status Update()
Legacy Update method for backward compatibility.
void DrawPresets()
Draw quick preset buttons.
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 ApplyPaletteToAllSheets()
Apply current palette to all active sheets.
void DrawPaletteGroupSelector()
Draw palette group selection.
auto mutable_gfx_sheets()
Get mutable reference to all graphics sheets.
Definition arena.h:127
void NotifySheetModified(int sheet_index)
Notify Arena that a graphics sheet has been modified.
Definition arena.cc:313
static Arena & Get()
Definition arena.cc:19
#define ICON_MD_LANDSCAPE
Definition icons.h:1059
#define ICON_MD_CHECKLIST
Definition icons.h:402
#define ICON_MD_BRUSH
Definition icons.h:325
#define ICON_MD_REFRESH
Definition icons.h:1572
#define ICON_MD_CASTLE
Definition icons.h:380
#define ICON_MD_PERSON
Definition icons.h:1415
#define ICON_MD_ACCOUNT_BOX
Definition icons.h:81
#define ICON_MD_MENU
Definition icons.h:1196
#define ICON_MD_FORMAT_PAINT
Definition icons.h:841
#define HOVER_HINT(string)
Definition macro.h:24
constexpr const char * kPaletteGroupAddressesKeys[]
void TextWithSeparators(const absl::string_view &text)
Definition style.cc:1317
constexpr uint32_t kNumGfxSheets
Definition game_data.h:25
PaletteGroup * get_group(const std::string &group_name)
auto palette(int i) const
gfx::PaletteGroupMap palette_groups
Definition game_data.h:89