678 static bool show_advanced_controls =
false;
679 static bool show_debug_info =
false;
682 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(8, 4));
683 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8, 4));
687 ImGui::TextColored(ImVec4(0.8f, 0.9f, 1.0f, 1.0f),
"Tile16 Editor");
691 ImGui::TextDisabled(
"|");
696 if (show_debug_info) {
699 ImGui::TextDisabled(
"(Slot: %d)", actual_slot);
705 ImGui::SameLine(ImGui::GetContentRegionAvail().x - 180);
706 if (ImGui::Button(
"Debug Info", ImVec2(80, 0))) {
707 show_debug_info = !show_debug_info;
710 if (ImGui::Button(
"Advanced", ImVec2(80, 0))) {
711 show_advanced_controls = !show_advanced_controls;
714 ImGui::PopStyleVar(2);
719 if (ImGui::BeginTable(
"##Tile16EditLayout", 3,
720 ImGuiTableFlags_Resizable |
721 ImGuiTableFlags_BordersInnerV |
722 ImGuiTableFlags_SizingStretchProp)) {
723 ImGui::TableSetupColumn(
"Tile16 Blockset",
724 ImGuiTableColumnFlags_WidthStretch, 0.35f);
725 ImGui::TableSetupColumn(
"Tile8 Source", ImGuiTableColumnFlags_WidthStretch,
727 ImGui::TableSetupColumn(
"Editor & Controls",
728 ImGuiTableColumnFlags_WidthStretch, 0.30f);
730 ImGui::TableHeadersRow();
731 ImGui::TableNextRow();
734 ImGui::TableNextColumn();
737 ImGui::TextColored(ImVec4(0.9f, 0.9f, 0.9f, 1.0f),
"Tile16 Blockset");
740 if (BeginChild(
"##BlocksetScrollable",
741 ImVec2(0, ImGui::GetContentRegionAvail().y),
true,
742 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
748 bool tile_selected =
false;
751 if (ImGui::IsItemClicked(ImGuiMouseButton_Left) &&
753 tile_selected =
true;
757 const ImGuiIO& io = ImGui::GetIO();
760 ImVec2(io.MousePos.x - canvas_pos.x, io.MousePos.y - canvas_pos.y);
762 int grid_x =
static_cast<int>(mouse_pos.x /
764 int grid_y =
static_cast<int>(mouse_pos.y /
766 int selected_tile = grid_x + grid_y * 8;
770 util::logf(
"Selected Tile16 from blockset: %d", selected_tile);
782 ImGui::TableNextColumn();
785 ImGui::TextColored(ImVec4(0.9f, 0.9f, 0.9f, 1.0f),
"Tile8 Source");
790 if (BeginChild(
"##Tile8SourceScrollable", ImVec2(0, 0),
true,
791 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
797 bool tile8_selected =
false;
801 if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
802 tile8_selected =
true;
805 if (tile8_selected) {
806 const ImGuiIO& io = ImGui::GetIO();
809 ImVec2(io.MousePos.x - canvas_pos.x, io.MousePos.y - canvas_pos.y);
812 int tile_x =
static_cast<int>(
815 int tile_y =
static_cast<int>(mouse_pos.y / (8 * 4));
819 int new_tile8 = tile_x + (tile_y * tiles_per_row);
842 if (ImGui::BeginChild(
"##Tile16FixedCanvas", ImVec2(90, 90),
true,
843 ImGuiWindowFlags_NoScrollbar |
844 ImGuiWindowFlags_NoScrollWithMouse)) {
863 std::vector<uint8_t> tile_data =
868 display_tile.
Create(8, 8, 8, tile_data);
883 for (
int y = 0; y < 8; ++y) {
884 for (
int x = 0; x < 4; ++x) {
885 std::swap(data[y * 8 + x], data[y * 8 + (7 - x)]);
891 for (
int y = 0; y < 4; ++y) {
892 for (
int x = 0; x < 8; ++x) {
893 std::swap(data[y * 8 + x], data[(7 - y) * 8 + x]);
909 if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
910 const ImGuiIO& io = ImGui::GetIO();
912 ImVec2 mouse_pos = ImVec2(io.MousePos.x - canvas_pos.x,
913 io.MousePos.y - canvas_pos.y);
916 int tile_x =
static_cast<int>(mouse_pos.x /
918 int tile_y =
static_cast<int>(mouse_pos.y /
922 tile_x = std::max(0, std::min(15, tile_x));
923 tile_y = std::max(0, std::min(15, tile_y));
925 util::logf(
"Tile16 canvas click: (%.2f, %.2f) -> Tile16: (%d, %d)",
926 mouse_pos.x, mouse_pos.y, tile_x, tile_y);
933 if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
934 const ImGuiIO& io = ImGui::GetIO();
936 ImVec2 mouse_pos = ImVec2(io.MousePos.x - canvas_pos.x,
937 io.MousePos.y - canvas_pos.y);
940 int tile_x =
static_cast<int>(mouse_pos.x /
942 int tile_y =
static_cast<int>(mouse_pos.y /
946 tile_x = std::max(0, std::min(15, tile_x));
947 tile_y = std::max(0, std::min(15, tile_y));
950 util::logf(
"Right-clicked to pick tile8 from tile16 at (%d, %d)",
972 ImGui::Image((ImTextureID)(intptr_t)tile8_texture, ImVec2(24, 24));
977 Checkbox(
"X Flip", &
x_flip);
979 Checkbox(
"Y Flip", &
y_flip);
987 if (show_debug_info) {
990 ImGui::TextDisabled(
"(Slot %d)", actual_slot);
995 float available_width = ImGui::GetContentRegionAvail().x;
996 float button_size = std::min(32.0f, (available_width - 16.0f) / 4.0f);
998 for (
int row = 0; row < 2; ++row) {
999 for (
int col = 0; col < 4; ++col) {
1003 int i = row * 4 + col;
1010 ImGui::PushStyleColor(ImGuiCol_Button,
1011 ImVec4(0.2f, 0.7f, 0.3f, 1.0f));
1012 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
1013 ImVec4(0.3f, 0.8f, 0.4f, 1.0f));
1014 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
1015 ImVec4(0.1f, 0.6f, 0.2f, 1.0f));
1017 ImGui::PushStyleColor(ImGuiCol_Button,
1018 ImVec4(0.3f, 0.3f, 0.35f, 1.0f));
1019 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
1020 ImVec4(0.4f, 0.4f, 0.45f, 1.0f));
1021 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
1022 ImVec4(0.25f, 0.25f, 0.3f, 1.0f));
1026 ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
1027 ImGui::PushStyleColor(ImGuiCol_Border,
1028 is_current ? ImVec4(0.4f, 0.9f, 0.5f, 1.0f)
1029 : ImVec4(0.5f, 0.5f, 0.5f, 0.3f));
1031 if (ImGui::Button(absl::StrFormat(
"%d", i).c_str(),
1032 ImVec2(button_size, button_size))) {
1038 status.message().data());
1040 util::logf(
"Palette successfully changed to %d",
1046 ImGui::PopStyleColor(4);
1047 ImGui::PopStyleVar(1);
1051 if (ImGui::IsItemHovered()) {
1052 ImGui::BeginTooltip();
1053 if (show_debug_info) {
1054 ImGui::Text(
"Palette %d → Slots:", i);
1060 ImGui::Text(
"Palette %d", i);
1062 ImGui::TextColored(ImVec4(0.3f, 0.8f, 0.3f, 1.0f),
"Active");
1065 ImGui::EndTooltip();
1074 if (Button(
"Clear", ImVec2(-1, 0))) {
1078 if (Button(
"Copy", ImVec2(-1, 0))) {
1082 if (Button(
"Paste", ImVec2(-1, 0))) {
1089 if (Button(
"Save Changes", ImVec2(-1, 0))) {
1092 HOVER_HINT(
"Apply changes to overworld and regenerate blockset");
1094 if (Button(
"Discard Changes", ImVec2(-1, 0))) {
1097 HOVER_HINT(
"Reload tile16 from ROM, discarding local changes");
1104 if (Button(
"Undo", ImVec2(-1, 0))) {
1111 if (show_advanced_controls) {
1115 if (Button(
"Palette Settings", ImVec2(-1, 0))) {
1119 if (Button(
"Manual Edit", ImVec2(-1, 0))) {
1120 ImGui::OpenPopup(
"ManualTile8Editor");
1123 if (Button(
"Refresh Blockset", ImVec2(-1, 0))) {
1136 if (show_debug_info) {
1145 ImGui::TextDisabled(
"Sheet:%d Slot:%d", sheet_index, actual_slot);
1149 if (ImGui::CollapsingHeader(
"Palette Map",
1150 ImGuiTreeNodeFlags_DefaultOpen)) {
1151 ImGui::BeginChild(
"##PaletteMappingScroll", ImVec2(0, 120),
true);
1152 if (ImGui::BeginTable(
"##PalMap", 3,
1153 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
1154 ImGuiTableFlags_SizingFixedFit)) {
1155 ImGui::TableSetupColumn(
"Btn", ImGuiTableColumnFlags_WidthFixed, 30);
1156 ImGui::TableSetupColumn(
"S0,3-4", ImGuiTableColumnFlags_WidthFixed,
1158 ImGui::TableSetupColumn(
"S1-2", ImGuiTableColumnFlags_WidthFixed, 50);
1159 ImGui::TableHeadersRow();
1161 for (
int i = 0; i < 8; ++i) {
1162 ImGui::TableNextRow();
1163 ImGui::TableNextColumn();
1164 ImGui::Text(
"%d", i);
1165 ImGui::TableNextColumn();
1167 ImGui::TableNextColumn();
1176 if (ImGui::CollapsingHeader(
"Colors")) {
1179 ImGui::Text(
"Slot %d:", actual_slot);
1185 int color_index = actual_slot + i;
1187 ImVec4 display_color = color.rgb();
1189 ImGui::ColorButton(absl::StrFormat(
"##c%d", i).c_str(),
1190 display_color, ImGuiColorEditFlags_NoTooltip,
1192 if (ImGui::IsItemHovered()) {
1193 ImGui::SetTooltip(
"%d:0x%04X", color_index, color.snes());
1196 if ((i + 1) % 4 != 0)
1218 return absl::OkStatus();
2208 Text(
"Pixel Normalization & Color Correction:");
2211 if (SliderInt(
"Normalization Mask", &mask_value, 1, 255,
"0x%02X")) {
2217 if (Button(
"Apply to All Graphics")) {
2219 if (!reload_result.ok()) {
2220 Text(
"Error: %s", reload_result.message().data());
2225 if (Button(
"Reset Defaults")) {
2229 (void)reload_result;
2233 Text(
"Current State:");
2234 static constexpr std::array<const char*, 7> palette_group_names = {
2235 "OW Main",
"OW Aux",
"OW Anim",
"Dungeon",
2236 "Sprites",
"Armor",
"Sword"};
2244 Text(
"Sheet-Specific Fixes:");
2247 static bool fix_sheet_0 =
true;
2248 static bool fix_sprite_sheets =
true;
2249 static bool use_transparent_for_terrain =
false;
2251 if (Checkbox(
"Fix Sheet 0 (Trees)", &fix_sheet_0)) {
2253 if (!reload_result.ok()) {
2254 Text(
"Error reloading: %s", reload_result.message().data());
2258 "Use direct palette for sheet 0 instead of transparent palette");
2260 if (Checkbox(
"Fix Sprite Sheets", &fix_sprite_sheets)) {
2262 if (!reload_result.ok()) {
2263 Text(
"Error reloading: %s", reload_result.message().data());
2266 HOVER_HINT(
"Use direct palette for sprite graphics sheets");
2268 if (Checkbox(
"Transparent for Terrain", &use_transparent_for_terrain)) {
2270 if (!reload_result.ok()) {
2271 Text(
"Error reloading: %s", reload_result.message().data());
2274 HOVER_HINT(
"Force transparent palette for terrain graphics");
2277 Text(
"Color Analysis:");
2281 Text(
"Selected Tile8 Analysis:");
2282 const auto& tile_data =
2284 std::map<uint8_t, int> pixel_counts;
2285 for (uint8_t pixel : tile_data) {
2286 pixel_counts[pixel & 0x0F]++;
2289 Text(
"Pixel Value Distribution:");
2290 for (
const auto& pair : pixel_counts) {
2291 int value = pair.first;
2292 int count = pair.second;
2293 Text(
" Value %d (0x%X): %d pixels", value, value, count);
2296 Text(
"Palette Colors Used:");
2298 for (
const auto& pair : pixel_counts) {
2299 int value = pair.first;
2300 int count = pair.second;
2301 if (value <
static_cast<int>(palette.size())) {
2302 auto color = palette[value];
2303 ImVec4 display_color = color.rgb();
2304 ImGui::ColorButton((
"##analysis" + std::to_string(value)).c_str(),
2305 display_color, ImGuiColorEditFlags_NoTooltip,
2307 if (ImGui::IsItemHovered()) {
2308 ImGui::SetTooltip(
"Index %d: 0x%04X (%d pixels)", value,
2309 color.snes(), count);
2319 if (CollapsingHeader(
"ROM Palette Manager") &&
rom_) {
2320 Text(
"Experimental ROM Palette Selection:");
2322 "Use ROM palettes to experiment with different color schemes");
2324 if (Button(
"Open Enhanced Palette Editor")) {
2328 if (Button(
"Show Color Analysis")) {
2333 static int quick_group = 0;
2334 static int quick_index = 0;
2336 SliderInt(
"ROM Group", &quick_group, 0, 6);
2337 SliderInt(
"Palette Index", &quick_index, 0, 7);
2339 if (Button(
"Apply to Tile8 Source")) {
2341 util::logf(
"Applied ROM palette group %d, index %d to Tile8 source",
2342 quick_group, quick_index);
2346 if (Button(
"Apply to Tile16 Editor")) {
2349 "Applied ROM palette group %d, index %d to Tile16 editor",
2350 quick_group, quick_index);