From 590ec6b3a364537355a15c48ad57433767038f25 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Wed, 6 May 2026 02:34:05 -0700 Subject: [PATCH] feat(editor): NPC spawn list has name filter for fast lookup A zone with 50+ creatures made finding a specific spawn tedious. Added a case-insensitive name-filter input above the list, capped at 200 visible entries with a 'refine filter' hint when exceeded. --- tools/editor/editor_ui.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/editor/editor_ui.cpp b/tools/editor/editor_ui.cpp index 0dd70028..889c3b67 100644 --- a/tools/editor/editor_ui.cpp +++ b/tools/editor/editor_ui.cpp @@ -1910,10 +1910,24 @@ void EditorUI::renderNpcPanel(EditorApp& app) { // ---- Spawned list ---- if (ImGui::CollapsingHeader("Spawned Creatures", ImGuiTreeNodeFlags_DefaultOpen)) { + static char spawnFilter[128] = ""; ImGui::Text("%zu placed (double-click to fly to)", spawner.spawnCount()); + ImGui::SetNextItemWidth(-1); + ImGui::InputTextWithHint("##spawnfilter", "Filter by name...", spawnFilter, sizeof(spawnFilter)); + std::string filterLower(spawnFilter); + std::transform(filterLower.begin(), filterLower.end(), filterLower.begin(), + [](unsigned char c) { return std::tolower(c); }); + int shown = 0; ImGui::BeginChild("SpawnList", ImVec2(0, 100), true); for (int i = 0; i < static_cast(spawner.spawnCount()); i++) { auto& s = spawner.getSpawns()[i]; + if (!filterLower.empty()) { + std::string nameLower = s.name; + std::transform(nameLower.begin(), nameLower.end(), nameLower.begin(), + [](unsigned char c) { return std::tolower(c); }); + if (nameLower.find(filterLower) == std::string::npos) continue; + } + if (++shown > 200) { ImGui::Text("... refine filter"); break; } bool sel = (i == spawner.getSelectedIndex()); char label[128]; std::snprintf(label, sizeof(label), "%s Lv%u (%.0f,%.0f,%.0f)",