111 static const char* kCategories[] = {
112 "All",
"Enemies",
"NPCs",
"Bosses",
"Items"
114 ImGui::SetNextItemWidth(100);
115 ImGui::Combo(
"##Category", &
selected_category_, kCategories, IM_ARRAYSIZE(kCategories));
119 ImGui::SetNextItemWidth(120);
123 float available_height = ImGui::GetContentRegionAvail().y;
125 float reserved_height = 120.0f;
127 float grid_height = std::max(150.0f, std::min(400.0f, available_height - reserved_height));
130 float panel_width = ImGui::GetContentRegionAvail().x;
131 float sprite_size = std::max(28.0f, std::min(40.0f, (panel_width - 40.0f) / 8.0f));
132 int items_per_row = std::max(1,
static_cast<int>(panel_width / (sprite_size + 6)));
134 ImGui::BeginChild(
"##SpriteGrid", ImVec2(0, grid_height),
true,
135 ImGuiWindowFlags_HorizontalScrollbar);
138 for (
int i = 0; i < 256; ++i) {
149 button_color.x = std::min(1.0f, button_color.x + 0.2f);
150 button_color.y = std::min(1.0f, button_color.y + 0.2f);
151 button_color.z = std::min(1.0f, button_color.z + 0.2f);
154 ImGui::PushStyleColor(ImGuiCol_Button, button_color);
155 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
156 ImVec4(std::min(1.0f, button_color.x + 0.1f),
157 std::min(1.0f, button_color.y + 0.1f),
158 std::min(1.0f, button_color.z + 0.1f), 1.0f));
159 ImGui::PushStyleColor(ImGuiCol_ButtonActive,
160 ImVec4(std::min(1.0f, button_color.x + 0.2f),
161 std::min(1.0f, button_color.y + 0.2f),
162 std::min(1.0f, button_color.z + 0.2f), 1.0f));
166 std::string label = absl::StrFormat(
"%s\n%02X", icon, i);
167 if (ImGui::Button(label.c_str(), ImVec2(sprite_size, sprite_size))) {
175 ImGui::PopStyleColor(3);
177 if (ImGui::IsItemHovered()) {
179 ImGui::SetTooltip(
"%s (0x%02X)\n[%s]\nClick to select for placement",
185 ImVec2 min = ImGui::GetItemRectMin();
186 ImVec2 max = ImGui::GetItemRectMax();
187 ImU32 sel_color = ImGui::ColorConvertFloat4ToU32(theme.dungeon_selection_primary);
188 ImGui::GetWindowDrawList()->AddRect(min, max, sel_color, 0.0f, 0, 2.0f);
194 if (col < items_per_row) {
207 const auto& sprites = room.GetSprites();
209 ImGui::Text(
ICON_MD_LIST " Room Sprites (%zu):", sprites.size());
211 if (sprites.empty()) {
212 ImGui::TextColored(theme.text_secondary_gray,
218 float list_height = std::max(120.0f, ImGui::GetContentRegionAvail().y - 10.0f);
219 ImGui::BeginChild(
"##SpriteList", ImVec2(0, list_height),
true);
220 for (
size_t i = 0; i < sprites.size(); ++i) {
221 const auto& sprite = sprites[i];
223 ImGui::PushID(
static_cast<int>(i));
225 ImGui::Text(
"[%zu] %s (0x%02X)", i,
228 ImGui::TextColored(theme.text_secondary_gray,
229 "@ (%d,%d) L%d", sprite.x(), sprite.y(), sprite.layer());
234 mutable_room.GetSprites().erase(
235 mutable_room.GetSprites().begin() +
static_cast<long>(i));
247 bool is_enemy = (sprite_id >= 0x09 && sprite_id <= 0x7F);
248 bool is_npc = (sprite_id >= 0x80 && sprite_id <= 0xBF);
249 bool is_boss = (sprite_id >= 0xC0 && sprite_id <= 0xD8);
250 bool is_item = (sprite_id >= 0xD9 && sprite_id <= 0xFF);
262 std::string name_lower = name;
264 for (
auto& c : name_lower) c =
static_cast<char>(tolower(c));
265 for (
auto& c : filter_lower) c =
static_cast<char>(tolower(c));
266 if (name_lower.find(filter_lower) == std::string::npos) {