1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-09-16 09:26:28 +02:00

Merge pull request #5939 from Laserlicht/search

Object search - allow searching all
This commit is contained in:
Ivan Savenko
2025-07-22 12:38:47 +03:00
committed by GitHub
5 changed files with 64 additions and 20 deletions

View File

@@ -459,46 +459,60 @@ void AdventureMapShortcuts::zoom( int distance)
}
void AdventureMapShortcuts::search(bool next)
{
// get all relevant objects
std::vector<ObjectInstanceID> visitableObjInstances;
for(auto & obj : GAME->interface()->cb->getAllVisitableObjs())
if(obj->ID != MapObjectID::MONSTER && obj->ID != MapObjectID::HERO && obj->ID != MapObjectID::TOWN)
visitableObjInstances.push_back(obj->id);
{
auto getColor = [](MapObjectID id ){
switch (id)
{
case MapObjectID::HERO:
return ColorRGBA{ 0, 192, 0};
case MapObjectID::MONSTER:
return ColorRGBA{ 255, 0, 0};
case MapObjectID::TOWN:
return ColorRGBA{ 100, 100, 255};
case MapObjectID::MINE:
return ColorRGBA{ 255, 153, 204};
case MapObjectID::RESOURCE:
return ColorRGBA{ 255, 51, 255};
case MapObjectID::ARTIFACT:
return ColorRGBA{ 192, 255, 0};
default:
return Colors::WHITE;
}
};
// count of elements for each group (map is already sorted)
std::map<std::string, int> mapObjCount;
for(auto & obj : visitableObjInstances)
mapObjCount[{ GAME->interface()->cb->getObjInstance(obj)->getObjectName() }]++;
std::map<std::pair<std::string, ColorRGBA>, int> mapObjCount;
for(auto & obj : GAME->interface()->cb->getAllVisitableObjs())
mapObjCount[{GAME->interface()->cb->getObjInstance(obj->id)->getObjectName(), getColor(obj->ID)}]++;
// convert to vector for indexed access
std::vector<std::pair<std::string, int>> textCountList;
std::vector<std::pair<std::pair<std::string, ColorRGBA>, int>> textCountList;
for (auto itr = mapObjCount.begin(); itr != mapObjCount.end(); ++itr)
textCountList.push_back(*itr);
textCountList.push_back({(*itr).first, (*itr).second});
// get pos of last selection
int lastSel = 0;
for(int i = 0; i < textCountList.size(); i++)
if(textCountList[i].first == searchLast)
if(textCountList[i].first.first == searchLast)
lastSel = i;
// create texts
std::vector<std::string> texts;
for(auto & obj : textCountList)
texts.push_back(obj.first + " (" + std::to_string(obj.second) + ")");
texts.push_back("{" + Colors::colorToHexString(obj.first.second) + "|" + obj.first.first + "}" + " (" + std::to_string(obj.second) + ")");
// function to center element from list on map
auto selectObjOnMap = [this, textCountList, visitableObjInstances](int index)
auto selectObjOnMap = [this, textCountList](int index)
{
auto selObj = textCountList[index].first;
// filter for matching objects
std::vector<ObjectInstanceID> selVisitableObjInstances;
for(auto & obj : visitableObjInstances)
if(selObj == GAME->interface()->cb->getObjInstance(obj)->getObjectName())
selVisitableObjInstances.push_back(obj);
for(auto & obj : GAME->interface()->cb->getAllVisitableObjs())
if(selObj.first == GAME->interface()->cb->getObjInstance(obj->id)->getObjectName())
selVisitableObjInstances.push_back(obj->id);
if(searchPos + 1 < selVisitableObjInstances.size() && searchLast == selObj)
if(searchPos + 1 < selVisitableObjInstances.size() && searchLast == selObj.first)
searchPos++;
else
searchPos = 0;

View File

@@ -53,3 +53,14 @@ std::optional<ColorRGBA> Colors::parseColor(std::string text)
return std::nullopt;
}
std::string Colors::colorToHexString(const ColorRGBA& color)
{
std::ostringstream oss;
oss << "#"
<< std::hex << std::uppercase
<< std::setw(2) << std::setfill('0') << static_cast<int>(color.r)
<< std::setw(2) << std::setfill('0') << static_cast<int>(color.g)
<< std::setw(2) << std::setfill('0') << static_cast<int>(color.b);
return oss.str();
}

View File

@@ -55,4 +55,6 @@ public:
/// parse color
static std::optional<ColorRGBA> parseColor(std::string text);
static std::string colorToHexString(const ColorRGBA& color);
};

View File

@@ -1641,13 +1641,22 @@ void CObjectListWindow::itemsSearchCallback(const std::string & text)
for(const auto & item : items)
{
if(auto score = TextOperations::textSearchSimilarityScore(text, item.second)) // Keep only relevant items
// remove color information
std::vector<std::string> parts;
boost::split(parts, item.second, boost::is_any_of("|"));
std::string name = parts.back();
boost::erase_all(name, "{");
boost::erase_all(name, "}");
if(auto score = TextOperations::textSearchSimilarityScore(text, name)) // Keep only relevant items
rankedItems.emplace_back(score.value(), item);
}
// Sort: Lower score is better match
std::sort(rankedItems.begin(), rankedItems.end(), [](const auto & a, const auto & b)
std::sort(rankedItems.begin(), rankedItems.end(), [text](const auto & a, const auto & b)
{
if(a.first == b.first || text.empty())
return a.second < b.second;
return a.first < b.first;
});

View File

@@ -62,6 +62,14 @@ public:
{
return r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a;
}
bool operator<(const ColorRGBA& rhs) const
{
auto mean_lhs = (r + g + b + a) / 4.0;
auto mean_rhs = (rhs.r + rhs.g + rhs.b + rhs.a) / 4.0;
return mean_lhs < mean_rhs;
}
};
namespace vstd