Changed: Show map search results in a list
--HG-- branch : develop
This commit is contained in:
parent
e625f2b3c7
commit
5b4759df72
3 changed files with 211 additions and 35 deletions
|
@ -204,6 +204,31 @@
|
||||||
|
|
||||||
<define id="map_min_size" value="256" />
|
<define id="map_min_size" value="256" />
|
||||||
|
|
||||||
|
<!-- used to override onclick handler -->
|
||||||
|
<proc id="dummy_proc" />
|
||||||
|
|
||||||
|
<template name="lm_search_result" keep="true" active="true" id="" x="0" y="0" w="0" h="17" posparent="parent" posref="TL TL"
|
||||||
|
hardtext="" fontsize="10" y_text="-2" onclick_l="lua" params_l="" tooltip="" index="0">
|
||||||
|
|
||||||
|
<group id="#id" active="#active" x="#x" y="#y" w="#w" h="#h" posparent="#posparent" posref="#posref" sizeref="w">
|
||||||
|
|
||||||
|
<ctrl type="button" id="over" sizeref="wh" w="0" h="0" posref="MM MM"
|
||||||
|
scale="true" tx_normal="blank.tga" tx_over="blank.tga" color="0 0 0 0" col_over="255 255 255 127"
|
||||||
|
onclick_l="land_mark_result_selected" params_l="map=ui:interface:map:content:map_content:actual_map|index=#index"
|
||||||
|
onclick_r="proc" params_r="dummy_proc"
|
||||||
|
tooltip="#tooltip" />
|
||||||
|
|
||||||
|
<view type="bitmap" id="icon" posref="ML ML" w="16" h="16"
|
||||||
|
scale="true" color="255 255 255 255" global_color="false" texture="blank.tga" />
|
||||||
|
|
||||||
|
<view type="text" id="title" posref="TL TL" x="16" y="#y_text"
|
||||||
|
color="255 255 255 255" global_color="true" fontsize="#fontsize" shadow="true" hardtext="#hardtext"
|
||||||
|
auto_clamp="true" over_extend_view_text="false" over_extend_parent_rect="false" />
|
||||||
|
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
<group id="map" type="container" posref="BL TL" min_w="%map_min_size" max_w="16384" w="256" h="256" x="352" y="200" min_h="%map_min_size" max_h="16384"
|
<group id="map" type="container" posref="BL TL" min_w="%map_min_size" max_w="16384" w="256" h="256" x="352" y="200" min_h="%map_min_size" max_h="16384"
|
||||||
resizer="true" pop_max_h="16384" pop_min_h="%map_min_size" pop_max_w="16384" pop_min_w="%map_min_size"
|
resizer="true" pop_max_h="16384" pop_min_h="%map_min_size" pop_max_w="16384" pop_min_w="%map_min_size"
|
||||||
openable="false" opened="true"
|
openable="false" opened="true"
|
||||||
|
@ -369,10 +394,15 @@
|
||||||
<group id="lm_search"
|
<group id="lm_search"
|
||||||
posparent="back"
|
posparent="back"
|
||||||
posref="TR TR"
|
posref="TR TR"
|
||||||
|
sizeref="h"
|
||||||
x="-2"
|
x="-2"
|
||||||
y="-2"
|
y="-2"
|
||||||
child_resize_w="true"
|
h="-4"
|
||||||
child_resize_h="true">
|
child_resize_w="true">
|
||||||
|
|
||||||
|
<view type="bitmap" id="bg" posref="ML ML" sizeref="wh" h="25"
|
||||||
|
scale="true" color="100 100 100 120" global_color="false" texture="blank.tga" />
|
||||||
|
|
||||||
<instance template="edit_box_widget"
|
<instance template="edit_box_widget"
|
||||||
id="search"
|
id="search"
|
||||||
posref="TR TR"
|
posref="TR TR"
|
||||||
|
@ -382,6 +412,7 @@
|
||||||
on_focus_lost="proc" on_focus_lost_params="map_search_focuslost"
|
on_focus_lost="proc" on_focus_lost_params="map_search_focuslost"
|
||||||
onenter=""
|
onenter=""
|
||||||
onchange="proc" onchange_params="map_search_onchange|ui:interface:map:content:map_content:lm_search:search:eb" />
|
onchange="proc" onchange_params="map_search_onchange|ui:interface:map:content:map_content:lm_search:search:eb" />
|
||||||
|
|
||||||
<ctrl type="button"
|
<ctrl type="button"
|
||||||
id="reset"
|
id="reset"
|
||||||
button_type="push_button"
|
button_type="push_button"
|
||||||
|
@ -394,6 +425,13 @@
|
||||||
onclick_l="proc" params_l="map_search_toggle"
|
onclick_l="proc" params_l="map_search_toggle"
|
||||||
tooltip="" />
|
tooltip="" />
|
||||||
<view type="text" id="lm_count" posparent="search" posref="BR TR" x="-2" color="200 200 200 255" fontsize="10" shadow="true" hardtext="0" />
|
<view type="text" id="lm_count" posparent="search" posref="BR TR" x="-2" color="200 200 200 255" fontsize="10" shadow="true" hardtext="0" />
|
||||||
|
|
||||||
|
<group id="result" posref="TR TR" x="0" y="-25" w="0" h="-20" over="true" sizeref="wh">
|
||||||
|
<group id="rows" x="10" w="-10" y="0" sizeref="w" posref="TL TL" child_resize_h="true" child_resize_hmargin="4" max_h="0" max_sizeref="h" max_sizeparent="parent">
|
||||||
|
<group id="lm_result" type="list" x="0" y="0" posref="TL TL" sizeref="w" dynamic_display_size="true" />
|
||||||
|
</group>
|
||||||
|
<ctrl style="skin_scroll" id="sv" posref="TL TL" x="0" y="0" target="rows" />
|
||||||
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<link expr="@UI:VARIABLES:ISACTIVE:MAP_SEARCH" target="lm_search:active" />
|
<link expr="@UI:VARIABLES:ISACTIVE:MAP_SEARCH" target="lm_search:active" />
|
||||||
|
|
||||||
|
|
|
@ -427,7 +427,7 @@ CGroupMap::CGroupMap(const TCtorParam ¶m)
|
||||||
_TargetLM = NULL;
|
_TargetLM = NULL;
|
||||||
_HomeLM = NULL;
|
_HomeLM = NULL;
|
||||||
_LandmarkFilter.clear();
|
_LandmarkFilter.clear();
|
||||||
_MatchedLandmarkCount = 0;
|
_MatchedLandmarks.clear();
|
||||||
//
|
//
|
||||||
_ScaleMax = 8.f;
|
_ScaleMax = 8.f;
|
||||||
_ScaleMaxR2 = 8.f;
|
_ScaleMaxR2 = 8.f;
|
||||||
|
@ -2249,6 +2249,31 @@ void CGroupMap::centerOnPlayer()
|
||||||
computeOffsets();
|
computeOffsets();
|
||||||
invalidateCoords();
|
invalidateCoords();
|
||||||
}
|
}
|
||||||
|
//============================================================================================================
|
||||||
|
void CGroupMap::centerOnWorldPos(const CVector2f &worldPos)
|
||||||
|
{
|
||||||
|
CVector2f mapPos;
|
||||||
|
worldToMap(mapPos, worldPos);
|
||||||
|
|
||||||
|
sint32 sx, sy;
|
||||||
|
mapToScreen(sx, sy, mapPos);
|
||||||
|
|
||||||
|
sint32 x, y, w, h;
|
||||||
|
computeMapRectInsideGroup(x, y, w, h);
|
||||||
|
|
||||||
|
sint32 dx, dy;
|
||||||
|
if (sx < getXReal())
|
||||||
|
dx = -(getXReal() - sx + w/2);
|
||||||
|
else
|
||||||
|
dx = sx - getXReal() - w/2;
|
||||||
|
|
||||||
|
if (sy < getYReal())
|
||||||
|
dy = -(getYReal() - sy + h/2);
|
||||||
|
else
|
||||||
|
dy = sy - getYReal() - h/2;
|
||||||
|
|
||||||
|
pan(dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================================================
|
//============================================================================================================
|
||||||
void CGroupMap::setScale(float newUserScale, const NLMISC::CVector2f &/* center */)
|
void CGroupMap::setScale(float newUserScale, const NLMISC::CVector2f &/* center */)
|
||||||
|
@ -2271,7 +2296,6 @@ void CGroupMap::setScale(float newScale)
|
||||||
setScale(newScale, mapCoords);
|
setScale(newScale, mapCoords);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================================================
|
//============================================================================================================
|
||||||
void CGroupMap::updateLandMarkList(TLandMarkButtonVect &lmVect)
|
void CGroupMap::updateLandMarkList(TLandMarkButtonVect &lmVect)
|
||||||
{
|
{
|
||||||
|
@ -2303,6 +2327,63 @@ void CGroupMap::updateLandMarkTextList(TLandMarkTextVect &lmVect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================================================
|
||||||
|
void CGroupMap::updateMatchedLandmarks()
|
||||||
|
{
|
||||||
|
CInterfaceGroup *gc = getParentContainer();
|
||||||
|
if (!gc) return;
|
||||||
|
|
||||||
|
// visible landmark count
|
||||||
|
CViewText *pVT = dynamic_cast<CViewText *>(gc->getView("lm_count"));
|
||||||
|
if (pVT)
|
||||||
|
{
|
||||||
|
// show total landmark count if search filter has not been set
|
||||||
|
uint c = _MatchedLandmarks.size();
|
||||||
|
if (c == 0 && _LandmarkFilter.size() == 0)
|
||||||
|
c = _UserLM.size();
|
||||||
|
|
||||||
|
pVT->setText(toString(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
// list of matched landmarks
|
||||||
|
CGroupList *pL = dynamic_cast<CGroupList *>(gc->getGroup("lm_result"));
|
||||||
|
if (!pL) return;
|
||||||
|
|
||||||
|
pL->clearGroups();
|
||||||
|
|
||||||
|
if (_LandmarkFilter.size() == 0) return;
|
||||||
|
|
||||||
|
// create result list
|
||||||
|
for(uint k = 0; k < _MatchedLandmarks.size(); ++k)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<string,string> > params;
|
||||||
|
params.clear();
|
||||||
|
params.push_back(std::pair<string,string>("id", toString("lm%d", k)));
|
||||||
|
params.push_back(std::pair<string,string>("tooltip", _MatchedLandmarks[k].Title.toUtf8()));
|
||||||
|
params.push_back(std::pair<string,string>("index", toString(k)));
|
||||||
|
|
||||||
|
CInterfaceGroup *g = CWidgetManager::getInstance()->getParser()->createGroupInstance("lm_search_result", pL->getId(), params);
|
||||||
|
if (g)
|
||||||
|
{
|
||||||
|
pL->addChild(g);
|
||||||
|
|
||||||
|
CViewText* t = dynamic_cast<CViewText *>(g->getView("title"));
|
||||||
|
if (t)
|
||||||
|
{
|
||||||
|
t->setSingleLineTextFormatTaged(_MatchedLandmarks[k].Title);
|
||||||
|
}
|
||||||
|
|
||||||
|
CViewBitmap* b = dynamic_cast<CViewBitmap *>(g->getView("icon"));
|
||||||
|
if (b)
|
||||||
|
{
|
||||||
|
b->setTexture(_MatchedLandmarks[k].Options.LandMarkTexNormal);
|
||||||
|
b->setColor(_MatchedLandmarks[k].Options.ColorNormal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pL->invalidateCoords();
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================================================
|
//============================================================================================================
|
||||||
void CGroupMap::removeLandMarks(TLandMarkButtonVect &lm)
|
void CGroupMap::removeLandMarks(TLandMarkButtonVect &lm)
|
||||||
{
|
{
|
||||||
|
@ -2320,6 +2401,9 @@ void CGroupMap::removeLandMarks(TLandMarkButtonVect &lm)
|
||||||
//============================================================================================================
|
//============================================================================================================
|
||||||
void CGroupMap::createLMWidgets(const std::vector<CContLandMark> &lms)
|
void CGroupMap::createLMWidgets(const std::vector<CContLandMark> &lms)
|
||||||
{
|
{
|
||||||
|
// disable any match in "world" mode
|
||||||
|
bool notWorldMode = _CurMap->Name != "world";
|
||||||
|
|
||||||
for (uint32 k = 0; k < lms.size(); ++k)
|
for (uint32 k = 0; k < lms.size(); ++k)
|
||||||
{
|
{
|
||||||
const CContLandMark &rCLM =lms[k];
|
const CContLandMark &rCLM =lms[k];
|
||||||
|
@ -2330,9 +2414,9 @@ void CGroupMap::createLMWidgets(const std::vector<CContLandMark> &lms)
|
||||||
const ucstring ucsTmp(CStringManagerClient::getPlaceLocalizedName(rCLM.TitleTextID));
|
const ucstring ucsTmp(CStringManagerClient::getPlaceLocalizedName(rCLM.TitleTextID));
|
||||||
const ucstring lcTitle = toLower(ucsTmp);
|
const ucstring lcTitle = toLower(ucsTmp);
|
||||||
|
|
||||||
bool searchMatch = _LandmarkFilter.size() > 0 && filterLandmark(lcTitle);
|
bool searchMatch = notWorldMode && _LandmarkFilter.size() > 0 && filterLandmark(lcTitle);
|
||||||
if (searchMatch)
|
if (searchMatch)
|
||||||
_MatchedLandmarkCount++;
|
_MatchedLandmarks.push_back(SMatchedLandmark(rCLM.Pos, ucsTmp, _ContinentLMOptions));
|
||||||
|
|
||||||
// Add button if not a region nor a place
|
// Add button if not a region nor a place
|
||||||
if ((rCLM.Type != CContLandMark::Region) && (rCLM.Type != CContLandMark::Place) &&
|
if ((rCLM.Type != CContLandMark::Region) && (rCLM.Type != CContLandMark::Place) &&
|
||||||
|
@ -2391,8 +2475,7 @@ void CGroupMap::createLMWidgets(const std::vector<CContLandMark> &lms)
|
||||||
void CGroupMap::createContinentLandMarks()
|
void CGroupMap::createContinentLandMarks()
|
||||||
{
|
{
|
||||||
uint32 k;
|
uint32 k;
|
||||||
|
_MatchedLandmarks.clear();
|
||||||
_MatchedLandmarkCount = 0;
|
|
||||||
|
|
||||||
if (_MapMode != MapMode_Normal) return;
|
if (_MapMode != MapMode_Normal) return;
|
||||||
if (_CurMap == NULL) return;
|
if (_CurMap == NULL) return;
|
||||||
|
@ -2411,12 +2494,9 @@ void CGroupMap::createContinentLandMarks()
|
||||||
if (_CurMap->Name == "world")
|
if (_CurMap->Name == "world")
|
||||||
{
|
{
|
||||||
createLMWidgets(ContinentMngr.WorldMap);
|
createLMWidgets(ContinentMngr.WorldMap);
|
||||||
invalidateCoords();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else if (_CurContinent)
|
||||||
if (_CurContinent == NULL) return;
|
{
|
||||||
|
|
||||||
// Continent Landmarks
|
// Continent Landmarks
|
||||||
createLMWidgets(_CurContinent->ContLandMarks);
|
createLMWidgets(_CurContinent->ContLandMarks);
|
||||||
// User Landmarks
|
// User Landmarks
|
||||||
|
@ -2425,24 +2505,24 @@ void CGroupMap::createContinentLandMarks()
|
||||||
NLMISC::CVector2f mapPos;
|
NLMISC::CVector2f mapPos;
|
||||||
worldToMap(mapPos, _CurContinent->UserLandMarks[k].Pos);
|
worldToMap(mapPos, _CurContinent->UserLandMarks[k].Pos);
|
||||||
|
|
||||||
|
CLandMarkOptions options = getUserLandMarkOptions(k);
|
||||||
|
addLandMark(_UserLM, mapPos, _CurContinent->UserLandMarks[k].Title, options);
|
||||||
|
|
||||||
|
if (_LandmarkFilter.size() > 0)
|
||||||
|
{
|
||||||
if (filterLandmark(_CurContinent->UserLandMarks[k].Title))
|
if (filterLandmark(_CurContinent->UserLandMarks[k].Title))
|
||||||
{
|
{
|
||||||
addLandMark(_UserLM, mapPos, _CurContinent->UserLandMarks[k].Title, getUserLandMarkOptions(k));
|
_MatchedLandmarks.push_back(SMatchedLandmark(_CurContinent->UserLandMarks[k].Pos, _CurContinent->UserLandMarks[k].Title, options));
|
||||||
_MatchedLandmarkCount++;
|
}
|
||||||
}
|
else
|
||||||
}
|
{
|
||||||
|
_UserLM.back()->setActive(false);
|
||||||
// update visible landmark count
|
}
|
||||||
CInterfaceGroup *gc = getParentContainer();
|
}
|
||||||
if (gc)
|
|
||||||
{
|
|
||||||
CViewText *pVT = dynamic_cast<CViewText *>(gc->getView("lm_count"));
|
|
||||||
if (pVT)
|
|
||||||
{
|
|
||||||
pVT->setText(toString(_MatchedLandmarkCount));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateMatchedLandmarks();
|
||||||
invalidateCoords();
|
invalidateCoords();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3035,6 +3115,30 @@ void CGroupMap::targetLandmark(CCtrlButton *lm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=========================================================================================================
|
||||||
|
void CGroupMap::targetLandmarkResult(uint32 index)
|
||||||
|
{
|
||||||
|
if (index > _MatchedLandmarks.size()) return;
|
||||||
|
|
||||||
|
CCompassTarget ct;
|
||||||
|
ct.Pos = _MatchedLandmarks[index].Pos;
|
||||||
|
ct.Name = _MatchedLandmarks[index].Title;
|
||||||
|
// type sets compass arrow color
|
||||||
|
ct.setType(CCompassTarget::UserLandMark);
|
||||||
|
|
||||||
|
centerOnWorldPos(ct.Pos);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//=========================================================================================================
|
//=========================================================================================================
|
||||||
void CGroupMap::getLandmarkPosition(const CCtrlButton *lm, NLMISC::CVector2f &worldPos)
|
void CGroupMap::getLandmarkPosition(const CCtrlButton *lm, NLMISC::CVector2f &worldPos)
|
||||||
{
|
{
|
||||||
|
@ -3255,6 +3359,25 @@ class CAHLandMarkFilter : public IActionHandler
|
||||||
};
|
};
|
||||||
REGISTER_ACTION_HANDLER(CAHLandMarkFilter, "land_mark_filter");
|
REGISTER_ACTION_HANDLER(CAHLandMarkFilter, "land_mark_filter");
|
||||||
|
|
||||||
|
//=========================================================================================================
|
||||||
|
// Landmark selected from result list
|
||||||
|
class CAHLandMarkResultSelected : public IActionHandler
|
||||||
|
{
|
||||||
|
virtual void execute (CCtrlBase * /* pCaller */, const string ¶ms)
|
||||||
|
{
|
||||||
|
string id = getParam(params, "map");
|
||||||
|
CGroupMap* map = dynamic_cast<CGroupMap*>(CWidgetManager::getInstance()->getElementFromId(id));
|
||||||
|
if (!map) return;
|
||||||
|
|
||||||
|
sint index;
|
||||||
|
string nr = getParam(params, "index");
|
||||||
|
if (!fromString(nr, index)) return;
|
||||||
|
|
||||||
|
map->targetLandmarkResult(index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REGISTER_ACTION_HANDLER(CAHLandMarkResultSelected, "land_mark_result_selected");
|
||||||
|
|
||||||
//=========================================================================================================
|
//=========================================================================================================
|
||||||
// A land mark button has been pushed
|
// A land mark button has been pushed
|
||||||
class CAHLandMarkSelected : public IActionHandler
|
class CAHLandMarkSelected : public IActionHandler
|
||||||
|
|
|
@ -139,6 +139,9 @@ public:
|
||||||
|
|
||||||
// center the map on the player
|
// center the map on the player
|
||||||
void centerOnPlayer();
|
void centerOnPlayer();
|
||||||
|
// center current map on world coords (if not out of map bounds)
|
||||||
|
void centerOnWorldPos(const NLMISC::CVector2f &worldPos);
|
||||||
|
|
||||||
void setPlayerPos(const NLMISC::CVector2f &p) { _PlayerPos = p; }
|
void setPlayerPos(const NLMISC::CVector2f &p) { _PlayerPos = p; }
|
||||||
NLMISC::CVector2f getPlayerPos() const { return _PlayerPos; }
|
NLMISC::CVector2f getPlayerPos() const { return _PlayerPos; }
|
||||||
// test if player is currently panning the map
|
// test if player is currently panning the map
|
||||||
|
@ -169,6 +172,7 @@ public:
|
||||||
CLandMarkOptions getUserLandMarkOptions(uint32 lmindex) const;
|
CLandMarkOptions getUserLandMarkOptions(uint32 lmindex) const;
|
||||||
// target the given landmark
|
// target the given landmark
|
||||||
void targetLandmark(CCtrlButton *lm);
|
void targetLandmark(CCtrlButton *lm);
|
||||||
|
void targetLandmarkResult(uint32 index);
|
||||||
// get the world position of a landmark or return vector Null if not found
|
// get the world position of a landmark or return vector Null if not found
|
||||||
void getLandmarkPosition(const CCtrlButton *lm, NLMISC::CVector2f &worldPos);
|
void getLandmarkPosition(const CCtrlButton *lm, NLMISC::CVector2f &worldPos);
|
||||||
|
|
||||||
|
@ -457,7 +461,17 @@ private:
|
||||||
|
|
||||||
// filter keywords
|
// filter keywords
|
||||||
std::vector<ucstring> _LandmarkFilter;
|
std::vector<ucstring> _LandmarkFilter;
|
||||||
uint32 _MatchedLandmarkCount;
|
struct SMatchedLandmark
|
||||||
|
{
|
||||||
|
SMatchedLandmark(const NLMISC::CVector2f pos, const ucstring &title, CLandMarkOptions opts)
|
||||||
|
: Pos(pos), Title(title), Options(opts)
|
||||||
|
{}
|
||||||
|
NLMISC::CVector2f Pos;
|
||||||
|
ucstring Title;
|
||||||
|
|
||||||
|
CLandMarkOptions Options;
|
||||||
|
};
|
||||||
|
std::vector<SMatchedLandmark> _MatchedLandmarks;
|
||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
// Respawn handling //
|
// Respawn handling //
|
||||||
|
@ -497,6 +511,7 @@ private:
|
||||||
*/
|
*/
|
||||||
void updateLandMarkList(TLandMarkButtonVect &lm);
|
void updateLandMarkList(TLandMarkButtonVect &lm);
|
||||||
void updateLandMarkTextList(TLandMarkTextVect &lm);
|
void updateLandMarkTextList(TLandMarkTextVect &lm);
|
||||||
|
void updateMatchedLandmarks();
|
||||||
//
|
//
|
||||||
void removeLandMarks(TLandMarkButtonVect &lm);
|
void removeLandMarks(TLandMarkButtonVect &lm);
|
||||||
/** create landmarks from the continent (and remove previous ones)
|
/** create landmarks from the continent (and remove previous ones)
|
||||||
|
|
Loading…
Reference in a new issue