Added: Command to search and target closest user landmark.
--HG-- branch : develop
This commit is contained in:
parent
11150e6b79
commit
923084a818
3 changed files with 186 additions and 5 deletions
|
@ -2493,6 +2493,33 @@ class CAHTarget : public IActionHandler
|
|||
};
|
||||
REGISTER_ACTION_HANDLER (CAHTarget, "target");
|
||||
|
||||
// ***************************************************************************
|
||||
class CAHTargetLandmark : public IActionHandler
|
||||
{
|
||||
virtual void execute (CCtrlBase * /* pCaller */, const string &Params)
|
||||
{
|
||||
string search = getParam(Params, "search");
|
||||
if (search.empty()) return;
|
||||
|
||||
bool startsWith = false;
|
||||
if (search.size() > 0 && (search[0] == '\'' || search[0] == '"') && search[0] == search[search.size()-1])
|
||||
{
|
||||
startsWith = true;
|
||||
search = trimQuotes(search);
|
||||
}
|
||||
|
||||
const std::string mapid = "ui:interface:map:content:map_content:actual_map";
|
||||
CGroupMap* cgMap = dynamic_cast<CGroupMap*>(CWidgetManager::getInstance()->getElementFromId(mapid));
|
||||
if (cgMap)
|
||||
{
|
||||
if (!cgMap->targetLandmarkByName(search, startsWith))
|
||||
{
|
||||
CInterfaceManager::getInstance()->displaySystemInfo(CI18N::get("uiTargetErrorCmd"));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
REGISTER_ACTION_HANDLER (CAHTargetLandmark, "target_landmark");
|
||||
|
||||
|
||||
class CAHAddShape : public IActionHandler
|
||||
|
|
|
@ -100,6 +100,12 @@ const uint32 ISLAND_PIXEL_PER_METER = 2;
|
|||
|
||||
static void setupFromZoom(CViewBase *pVB, CContLandMark::TContLMType t, float fMeterPerPixel);
|
||||
|
||||
// calculate distance (squared) between two points
|
||||
static float distsqr(const CVector2f a, const CVector2f b)
|
||||
{
|
||||
return pow(a.x - b.x, 2) + pow(a.y - b.y, 2);
|
||||
}
|
||||
|
||||
// popup the landmark name dialog
|
||||
|
||||
static void popupLandMarkNameDialog()
|
||||
|
@ -2671,21 +2677,38 @@ void CGroupMap::updateLandMarkButton(CLandMarkButton *lmb, const CLandMarkOption
|
|||
}
|
||||
|
||||
//============================================================================================================
|
||||
bool CGroupMap::filterLandmark(const ucstring &title) const
|
||||
bool CGroupMap::filterLandmark(const ucstring &title, const std::vector<ucstring> filter, bool startsWith) const
|
||||
{
|
||||
if (_LandmarkFilter.size() > 0)
|
||||
if (filter.size() > 0)
|
||||
{
|
||||
ucstring lcTitle = toLower(title);
|
||||
for(uint i = 0; i< _LandmarkFilter.size(); ++i) {
|
||||
if (lcTitle.find(_LandmarkFilter[i]) == ucstring::npos) {
|
||||
if (startsWith)
|
||||
{
|
||||
if (lcTitle.find(filter[0]) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(uint i = 0; i< filter.size(); ++i)
|
||||
{
|
||||
if (lcTitle.find(filter[i]) == ucstring::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================================================
|
||||
bool CGroupMap::filterLandmark(const ucstring &title) const
|
||||
{
|
||||
return filterLandmark(title, _LandmarkFilter);
|
||||
}
|
||||
|
||||
//============================================================================================================
|
||||
void CGroupMap::addLandMark(TLandMarkButtonVect &destList, const NLMISC::CVector2f &pos, const ucstring &title, const CLandMarkOptions &options)
|
||||
{
|
||||
|
@ -3186,6 +3209,129 @@ void CGroupMap::targetLandmarkResult(uint32 index)
|
|||
}
|
||||
}
|
||||
|
||||
//=========================================================================================================
|
||||
CGroupMap::CLandMarkButton* CGroupMap::findClosestLandmark(const CVector2f ¢er, const ucstring &search, bool startsWith, const TLandMarkButtonVect &landmarks, float &closest) const
|
||||
{
|
||||
CLandMarkButton *ret = NULL;
|
||||
|
||||
std::vector<ucstring> keywords;
|
||||
if (startsWith)
|
||||
keywords.push_back(search);
|
||||
else
|
||||
splitUCString(toLower(search), ucstring(" "), keywords);
|
||||
|
||||
closest = std::numeric_limits<float>::max();
|
||||
for(TLandMarkButtonVect::const_iterator it = landmarks.begin(); it != landmarks.end(); ++it)
|
||||
{
|
||||
ucstring lc;
|
||||
(*it)->getContextHelp(lc);
|
||||
if(filterLandmark(lc, keywords, startsWith)) {
|
||||
CVector2f pos;
|
||||
mapToWorld(pos, (*it)->Pos);
|
||||
float dist = distsqr(center, pos);
|
||||
if (dist < closest)
|
||||
{
|
||||
ret = (*it);
|
||||
closest = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//=========================================================================================================
|
||||
CGroupMap::CLandMarkText* CGroupMap::findClosestLandmark(const CVector2f ¢er, const ucstring &search, bool startsWith, const TLandMarkTextVect &landmarks, float &closest) const
|
||||
{
|
||||
CLandMarkText *ret = NULL;
|
||||
|
||||
std::vector<ucstring> keywords;
|
||||
if (startsWith)
|
||||
keywords.push_back(search);
|
||||
else
|
||||
splitUCString(toLower(search), ucstring(" "), keywords);
|
||||
|
||||
closest = std::numeric_limits<float>::max();
|
||||
for(TLandMarkTextVect::const_iterator it = landmarks.begin(); it != landmarks.end(); ++it)
|
||||
{
|
||||
ucstring lc;
|
||||
lc = (*it)->getText();
|
||||
if(filterLandmark(lc, keywords, startsWith)) {
|
||||
CVector2f pos;
|
||||
mapToWorld(pos, (*it)->Pos);
|
||||
float dist = distsqr(center, pos);
|
||||
if (dist < closest)
|
||||
{
|
||||
ret = (*it);
|
||||
closest = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CGroupMap::targetLandmarkByName(const ucstring &search, bool startsWith) const
|
||||
{
|
||||
CCompassTarget ct;
|
||||
CLandMarkButton* lm;
|
||||
float dist;
|
||||
float closest = std::numeric_limits<float>::max();
|
||||
bool found = false;
|
||||
CVector2f center;
|
||||
mapToWorld(center, _PlayerPos);
|
||||
|
||||
lm = findClosestLandmark(center, search, startsWith, _UserLM, dist);
|
||||
if (lm && dist < closest)
|
||||
{
|
||||
ct.setType(CCompassTarget::UserLandMark);
|
||||
mapToWorld(ct.Pos, lm->Pos);
|
||||
lm->getContextHelp(ct.Name);
|
||||
closest = dist;
|
||||
found = true;
|
||||
}
|
||||
|
||||
// only check other types if user landmark was not found
|
||||
if (!found)
|
||||
{
|
||||
lm = findClosestLandmark(center, search, startsWith, _ContinentLM, dist);
|
||||
if (lm && dist < closest)
|
||||
{
|
||||
ct.setType(CCompassTarget::ContinentLandMark);
|
||||
mapToWorld(ct.Pos, lm->Pos);
|
||||
lm->getContextHelp(ct.Name);
|
||||
closest = dist;
|
||||
found = true;
|
||||
}
|
||||
|
||||
CLandMarkText* lmt;
|
||||
lmt = findClosestLandmark(center, search, startsWith, _ContinentText, dist);
|
||||
if (lmt && dist < closest)
|
||||
{
|
||||
ct.setType(CCompassTarget::ContinentLandMark);
|
||||
mapToWorld(ct.Pos, lmt->Pos);
|
||||
ct.Name = lmt->getText();
|
||||
closest = dist;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
CInterfaceManager *im = CInterfaceManager::getInstance();
|
||||
CGroupCompas *gc = dynamic_cast<CGroupCompas *>(CWidgetManager::getInstance()->getElementFromId(_CompassId));
|
||||
if (gc)
|
||||
{
|
||||
gc->setActive(true);
|
||||
gc->setTarget(ct);
|
||||
gc->blink();
|
||||
CWidgetManager::getInstance()->setTopWindow(gc);
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
//=========================================================================================================
|
||||
void CGroupMap::getLandmarkPosition(const CCtrlButton *lm, NLMISC::CVector2f &worldPos)
|
||||
{
|
||||
|
|
|
@ -192,6 +192,8 @@ public:
|
|||
// target the given landmark
|
||||
void targetLandmark(CCtrlButton *lm);
|
||||
void targetLandmarkResult(uint32 index);
|
||||
// search matching landmark and target it. return true if landmark was targeted
|
||||
bool targetLandmarkByName(const ucstring &search, bool startsWith) const;
|
||||
// get the world position of a landmark or return vector Null if not found
|
||||
void getLandmarkPosition(const CCtrlButton *lm, NLMISC::CVector2f &worldPos);
|
||||
|
||||
|
@ -551,6 +553,12 @@ private:
|
|||
|
||||
// Test title against landmark filter
|
||||
bool filterLandmark(const ucstring &title) const;
|
||||
bool filterLandmark(const ucstring &title, const std::vector<ucstring> filter, bool startsWith = false) const;
|
||||
|
||||
// return closest landmark which matches (case insensitive) search string
|
||||
// center position must be in world coordindates
|
||||
CLandMarkButton* findClosestLandmark(const NLMISC::CVector2f ¢er, const ucstring &search, bool startsWith, const TLandMarkButtonVect &landmarks, float &closest) const;
|
||||
CLandMarkText* findClosestLandmark(const NLMISC::CVector2f ¢er, const ucstring &search, bool startsWith, const TLandMarkTextVect &landmarks, float &closest) const;
|
||||
|
||||
// update the scale depending on the window size and the user scale
|
||||
void updateScale();
|
||||
|
|
Loading…
Reference in a new issue