From 6c09718a8e7218525736b24dea0d6c103f23630b Mon Sep 17 00:00:00 2001 From: Luan Luciano Date: Mon, 3 Jun 2024 16:37:32 -0300 Subject: [PATCH] feat: search option for items under walls/windows/doors (#63) --- data/menubar.xml | 2 + source/item.h | 3 ++ source/main_menubar.cpp | 95 ++++++++++++++++++++++++++++++++++++++++- source/main_menubar.h | 5 +++ 4 files changed, 104 insertions(+), 1 deletion(-) diff --git a/data/menubar.xml b/data/menubar.xml index 2adc40bd..c9f852e6 100644 --- a/data/menubar.xml +++ b/data/menubar.xml @@ -39,6 +39,7 @@ + @@ -93,6 +94,7 @@ + diff --git a/source/item.h b/source/item.h index 8b148133..104f4752 100644 --- a/source/item.h +++ b/source/item.h @@ -306,6 +306,9 @@ class Item : public ItemAttributes { bool hasElevation() const { return getItemType().hasElevation; } + bool isBlockMissiles() const { + return getItemType().blockMissiles; + } // Wall alignment (vertical, horizontal, pole, corner) BorderType getWallAlignment() const; diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index ef48a3a1..090cc16f 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -206,6 +206,9 @@ MainMenuBar::MainMenuBar(MainFrame* frame) : MAKE_ACTION(REMOVE_ON_MAP_DUPLICATE_ITEMS, wxITEM_NORMAL, OnRemoveForDuplicateItemsOnMap); MAKE_ACTION(REMOVE_ON_SELECTION_DUPLICATE_ITEMS, wxITEM_NORMAL, OnRemoveForDuplicateItemsOnSelection); + MAKE_ACTION(SEARCH_ON_MAP_WALLS_UPON_WALLS, wxITEM_NORMAL, OnSearchForWallsUponWallsOnMap); + MAKE_ACTION(SEARCH_ON_SELECTION_WALLS_UPON_WALLS, wxITEM_NORMAL, OnSearchForWallsUponWallsOnSelection); + // A deleter, this way the frame does not need // to bother deleting us. class CustomMenuBar : public wxMenuBar { @@ -419,6 +422,9 @@ void MainMenuBar::Update() { EnableItem(REMOVE_ON_MAP_DUPLICATE_ITEMS, is_local); EnableItem(REMOVE_ON_SELECTION_DUPLICATE_ITEMS, is_local && has_selection); + EnableItem(SEARCH_ON_MAP_WALLS_UPON_WALLS, is_host); + EnableItem(SEARCH_ON_SELECTION_WALLS_UPON_WALLS, is_host && has_selection); + UpdateFloorMenu(); UpdateIndicatorsMenu(); } @@ -1322,7 +1328,7 @@ namespace OnMapRemoveCorpses { g_gui.SetLoadDone((unsigned int)(100 * done / map.getTileCount())); } - return g_materials.isInTileset(item, "Corpses") & !item->isComplex(); + return g_materials.isInTileset(item, "Corpses") && !item->isComplex(); } }; } @@ -2273,6 +2279,7 @@ void MainMenuBar::SearchItems(bool unique, bool action, bool container, bool wri SearchResultWindow* result = g_gui.ShowSearchWindow(); result->Clear(); + for (std::vector>::iterator iter = found.begin(); iter != found.end(); ++iter) { result->AddPosition(searcher.desc(iter->second), iter->first->getPosition()); } @@ -2294,6 +2301,14 @@ void MainMenuBar::OnRemoveForDuplicateItemsOnSelection(wxCommandEvent &WXUNUSED( RemoveDuplicatesItems(true); } +void MainMenuBar::OnSearchForWallsUponWallsOnMap(wxCommandEvent &WXUNUSED(event)) { + SearchWallsUponWalls(false); +} + +void MainMenuBar::OnSearchForWallsUponWallsOnSelection(wxCommandEvent &WXUNUSED(event)) { + SearchWallsUponWalls(true); +} + namespace SearchDuplicatedItems { struct condition { std::unordered_set foundTiles; @@ -2432,3 +2447,81 @@ void MainMenuBar::RemoveDuplicatesItems(bool onSelection /* = false*/) { g_gui.GetCurrentMap().doChange(); } } + +namespace SearchWallsUponWalls { + struct condition { + std::unordered_set foundTiles; + + void operator()(const Map &map, Tile* tile, const Item* item, long long done) { + if (done % 0x8000 == 0) { + g_gui.SetLoadDone(static_cast(100 * done / map.getTileCount())); + } + + if (!tile) { + return; + } + + if (!item) { + return; + } + + if (!item->isBlockMissiles()) { + return; + } + + if (!item->isWall() && !item->isDoor()) { + return; + } + + std::unordered_set itemIDs; + for (const Item* itemInTile : tile->items) { + if (!itemInTile || (!itemInTile->isWall() && !itemInTile->isDoor())) { + continue; + } + + if (item->getID() != itemInTile->getID()) { + itemIDs.insert(itemInTile->getID()); + } + } + + if (!itemIDs.empty()) { + foundTiles.insert(tile); + } + + itemIDs.clear(); + } + }; +} + +void MainMenuBar::SearchWallsUponWalls(bool onSelection /* = false*/) { + if (!g_gui.IsEditorOpen()) { + return; + } + + if (onSelection) { + g_gui.CreateLoadBar("Searching on selected area..."); + } else { + g_gui.CreateLoadBar("Searching on map..."); + } + + SearchWallsUponWalls::condition finder; + + foreach_ItemOnMap(g_gui.GetCurrentMap(), finder, onSelection); + + const std::unordered_set &foundTiles = finder.foundTiles; + + g_gui.DestroyLoadBar(); + + size_t setSize = foundTiles.size(); + + wxString msg; + msg << setSize << " items under walls and doors founded."; + + g_gui.PopupDialog("Search completed", msg, wxOK); + + SearchResultWindow* result = g_gui.ShowSearchWindow(); + result->Clear(); + for (const Tile* tile : foundTiles) { + result->AddPosition("Item Under", tile->getPosition()); + } +} diff --git a/source/main_menubar.h b/source/main_menubar.h index d1a28de2..083525ad 100644 --- a/source/main_menubar.h +++ b/source/main_menubar.h @@ -161,6 +161,8 @@ namespace MenuBar { SEARCH_ON_SELECTION_DUPLICATE, REMOVE_ON_MAP_DUPLICATE_ITEMS, REMOVE_ON_SELECTION_DUPLICATE_ITEMS, + SEARCH_ON_MAP_WALLS_UPON_WALLS, + SEARCH_ON_SELECTION_WALLS_UPON_WALLS, }; } @@ -302,6 +304,8 @@ class MainMenuBar : public wxEvtHandler { void OnSearchForDuplicateItemsOnSelection(wxCommandEvent &event); void OnRemoveForDuplicateItemsOnMap(wxCommandEvent &event); void OnRemoveForDuplicateItemsOnSelection(wxCommandEvent &event); + void OnSearchForWallsUponWallsOnMap(wxCommandEvent &event); + void OnSearchForWallsUponWallsOnSelection(wxCommandEvent &event); protected: // Load and returns a menu item, also sets accelerator @@ -311,6 +315,7 @@ class MainMenuBar : public wxEvtHandler { void SearchItems(bool unique, bool action, bool container, bool writable, bool onSelection = false); void SearchDuplicatedItems(bool onSelection = false); void RemoveDuplicatesItems(bool onSelection = false); + void SearchWallsUponWalls(bool onSelection = false); protected: MainFrame* frame;