Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Luan Luciano committed Nov 2, 2023
1 parent b1c0df5 commit b0b6208
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 1 deletion.
2 changes: 2 additions & 0 deletions data/menubar.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<item name="Find $Action" action="SEARCH_ON_MAP_ACTION" help="Find all items with an action ID on map."/>
<item name="Find $Container" action="SEARCH_ON_MAP_CONTAINER" help="Find all containers on map."/>
<item name="Find $Writeable" action="SEARCH_ON_MAP_WRITEABLE" help="Find all writeable items on map."/>
<item name="Find $Duplicate Items" action="SEARCH_ON_MAP_DUPLICATE" help="Find all positions where there are duplicate items on the map."/>
</menu>
<separator/>
<menu name="$Border Options">
Expand All @@ -52,6 +53,7 @@
<item name="$Remove Items by ID..." action="MAP_REMOVE_ITEMS" help="Removes all items with the selected ID from the map."/>
<item name="Remove $all corpses..." action="MAP_REMOVE_CORPSES" help="Removes all corpses from the map."/>
<item name="Remove all $unreachable tiles..." action="MAP_REMOVE_UNREACHABLE_TILES" help="Removes all tiles that cannot be reached (or seen) by the player from the map."/>
<item name="Remove all $duplicates items..." action="REMOVE_ON_MAP_DUPLICATE_ITEMS" help="Removes all items duplicates on map."/>
<item name="Remove empty monsters spawns" action="MAP_REMOVE_EMPTY_MONSTERS_SPAWNS" help="Removes all empty monsters spawns from the map."/>
<item name="Remove empty npcs spawns" action="MAP_REMOVE_EMPTY_NPCS_SPAWNS" help="Removes all empty npcs spawns from the map."/>
<item name="$Clear Invalid Houses" action="CLEAR_INVALID_HOUSES" help="Clears house tiles not belonging to any house."/>
Expand Down
3 changes: 3 additions & 0 deletions source/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@ class Item : public ItemAttributes {
bool isMetaItem() const {
return getItemType().isMetaItem();
}
bool hasElevation() const {
return getItemType().hasElevation();
}

// Wall alignment (vertical, horizontal, pole, corner)
BorderType getWallAlignment() const;
Expand Down
3 changes: 3 additions & 0 deletions source/items.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@ class ItemType {
return is_metaitem;
}

bool hasElevation() const noexcept {
return hasElevation;
}
bool isFloorChange() const noexcept;

float getWeight() const noexcept {
Expand Down
165 changes: 165 additions & 0 deletions source/main_menubar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ MainMenuBar::MainMenuBar(MainFrame* frame) :
MAKE_ACTION(GOTO_WEBSITE, wxITEM_NORMAL, OnGotoWebsite);
MAKE_ACTION(ABOUT, wxITEM_NORMAL, OnAbout);

MAKE_ACTION(SEARCH_ON_MAP_DUPLICATE, wxITEM_NORMAL, OnSearchForDuplicateItemsOnMap);
MAKE_ACTION(SEARCH_ON_SELECTION_DUPLICATE, wxITEM_NORMAL, OnSearchForDuplicateItemsOnSelection);
MAKE_ACTION(REMOVE_ON_MAP_DUPLICATE_ITEMS, wxITEM_NORMAL, OnRemoveForDuplicateItemsOnMap);
MAKE_ACTION(REMOVE_ON_SELECTION_DUPLICATE_ITEMS, wxITEM_NORMAL, OnRemoveForDuplicateItemsOnSelection);

// A deleter, this way the frame does not need
// to bother deleting us.
class CustomMenuBar : public wxMenuBar {
Expand Down Expand Up @@ -405,6 +410,11 @@ void MainMenuBar::Update() {

EnableItem(DEBUG_VIEW_DAT, loaded);

EnableItem(SEARCH_ON_MAP_DUPLICATE, is_host);
EnableItem(SEARCH_ON_SELECTION_DUPLICATE, has_selection && is_host);
EnableItem(REMOVE_ON_MAP_DUPLICATE_ITEMS, is_local);
EnableItem(REMOVE_ON_SELECTION_DUPLICATE_ITEMS, is_local && has_selection);

UpdateFloorMenu();
UpdateIndicatorsMenu();
}
Expand Down Expand Up @@ -2241,3 +2251,158 @@ void MainMenuBar::SearchItems(bool unique, bool action, bool container, bool wri
result->AddPosition(searcher.desc(iter->second), iter->first->getPosition());
}
}

void MainMenuBar::OnSearchForDuplicateItemsOnMap(wxCommandEvent &WXUNUSED(event)) {
SearchDuplicatedItems(false);
}

void MainMenuBar::OnSearchForDuplicateItemsOnSelection(wxCommandEvent &WXUNUSED(event)) {
SearchDuplicatedItems(true);
}

void MainMenuBar::OnRemoveForDuplicateItemsOnMap(wxCommandEvent &WXUNUSED(event)) {
RemoveDuplicatesItems(false);
}

void MainMenuBar::OnRemoveForDuplicateItemsOnSelection(wxCommandEvent &WXUNUSED(event)) {
RemoveDuplicatesItems(true);
}

namespace SearchDuplicatedItems {
struct condition {
std::unordered_set<Tile*> foundTiles;

void operator()(Map& map, Tile* tile, Item* item, long long done) {
if (done % 0x8000 == 0) {
g_gui.SetLoadDone((unsigned int)(100 * done / map.getTileCount()));
}

if (!tile) {
return;
}

if (!item) {
return;
}

if (item->isGroundTile()) {
return;
}

if (foundTiles.count(tile) == 0) {
std::unordered_set<int> itemIDs;
for (Item* existingItem : tile->items) {
if (itemIDs.count(existingItem->getID()) > 0) {
foundTiles.insert(tile);
break;
}
itemIDs.insert(existingItem->getID());
}
}
}
};
}

void MainMenuBar::SearchDuplicatedItems(bool onSelection/* = false*/) {
if (!g_gui.IsEditorOpen()) {
return;
}

if (onSelection) {
g_gui.CreateLoadBar("Searching on selected area...");
} else {
g_gui.CreateLoadBar("Searching on map...");
}

SearchDuplicatedItems::condition finder;

foreach_ItemOnMap(g_gui.GetCurrentMap(), finder, onSelection);
std::unordered_set<Tile*>& foundTiles = finder.foundTiles;

g_gui.DestroyLoadBar();

size_t setSize = foundTiles.size();

wxString msg;
msg << setSize << " duplicate items founded.";

g_gui.PopupDialog("Search completed", msg, wxOK);

SearchResultWindow* result = g_gui.ShowSearchWindow();
result->Clear();
for (const Tile* tile : foundTiles) {
result->AddPosition("Duplicate items", tile->getPosition());
}
}

namespace RemoveDuplicatesItems {
struct condition {
bool operator()(Map& map, Tile* tile, Item* item, long long removed, long long done) {
if (done % 0x8000 == 0) {
g_gui.SetLoadDone((unsigned int)(100 * done / map.getTileCount()));
}

if (!tile) {
return false;
}

if (!item) {
return false;
}

if (item->isGroundTile()) {
return false;
}

if (item->isMoveable() && item->hasElevation()) {
return false;
}

std::unordered_set<int> itemIDsDuplicates;
for (Item* itemInTile : tile->items) {
if (itemInTile && itemInTile->getID() == item->getID()) {
if (itemIDsDuplicates.count(itemInTile->getID()) > 0) {
itemIDsDuplicates.clear();
return true;
}
itemIDsDuplicates.insert(itemInTile->getID());
}
}

itemIDsDuplicates.clear();
return false;
}
};
}

void MainMenuBar::RemoveDuplicatesItems(bool onSelection/* = false*/) {
if (!g_gui.IsEditorOpen()) {
return;
}

int ok = g_gui.PopupDialog("Remove Duplicate Items", "Do you want to remove all duplicates items from the map?", wxYES | wxNO);

if(ok == wxID_YES) {
g_gui.GetCurrentEditor()->getSelection().clear();
g_gui.GetCurrentEditor()->clearActions();

RemoveDuplicatesItems::condition func;

if (onSelection) {
g_gui.CreateLoadBar("Searching on selected area for items to remove...");
} else {
g_gui.CreateLoadBar("Searching on map for items to remove...");
}

long long removed = RemoveItemDuplicateOnMap(g_gui.GetCurrentMap(), func, onSelection);

g_gui.DestroyLoadBar();

wxString msg;
msg << removed << " duplicate items deleted.";

g_gui.PopupDialog("Search completed", msg, wxOK);

g_gui.GetCurrentMap().doChange();
}
}
11 changes: 10 additions & 1 deletion source/main_menubar.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ namespace MenuBar {
EXTENSIONS,
GOTO_WEBSITE,
ABOUT,
SEARCH_ON_MAP_DUPLICATE,
SEARCH_ON_SELECTION_DUPLICATE,
REMOVE_ON_MAP_DUPLICATE_ITEMS,
REMOVE_ON_SELECTION_DUPLICATE_ITEMS,
};
}

Expand Down Expand Up @@ -290,14 +294,19 @@ class MainMenuBar : public wxEvtHandler {
void OnListExtensions(wxCommandEvent &event);
void OnGotoWebsite(wxCommandEvent &event);
void OnAbout(wxCommandEvent &event);
void OnSearchForDuplicateItemsOnMap(wxCommandEvent &event);
void OnSearchForDuplicateItemsOnSelection(wxCommandEvent &event);
void OnRemoveForDuplicateItemsOnMap(wxCommandEvent &event);
void OnRemoveForDuplicateItemsOnSelection(wxCommandEvent &event);

protected:
// Load and returns a menu item, also sets accelerator
wxObject* LoadItem(pugi::xml_node node, wxMenu* parent, wxArrayString &warnings, wxString &error);
// Checks the items in the menus according to the settings (in config)
void LoadValues();
void SearchItems(bool unique, bool action, bool container, bool writable, bool onSelection = false);

void SearchDuplicatedItems(bool onSelection = false);
void RemoveDuplicatesItems(bool onSelection = false);
protected:
MainFrame* frame;
wxMenuBar* menubar;
Expand Down
39 changes: 39 additions & 0 deletions source/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,4 +312,43 @@ inline int64_t RemoveItemOnMap(Map &map, RemoveIfType &condition, bool selectedO
return removed;
}

template <typename RemoveIfType>
inline int64_t RemoveItemDuplicateOnMap(Map &map, RemoveIfType &condition, bool selectedOnly) {
int64_t done = 0;
int64_t removed = 0;

MapIterator it = map.begin();
MapIterator end = map.end();

while (it != end) {
++done;
Tile* tile = (*it)->get();
if (selectedOnly && !tile->isSelected()) {
++it;
continue;
}

if (tile->ground) {
if (condition(map, tile, tile->ground, removed, done)) {
delete tile->ground;
tile->ground = nullptr;
++removed;
}
}

for (auto iit = tile->items.begin(); iit != tile->items.end();) {
Item* item = *iit;
if (condition(map, tile, item, removed, done)) {
iit = tile->items.erase(iit);
delete item;
++removed;
} else {
++iit;
}
}
++it;
}
return removed;
}

#endif

0 comments on commit b0b6208

Please sign in to comment.