diff options
author | Todd Stinson <stinson@lindenlab.com> | 2012-03-08 12:34:11 -0800 |
---|---|---|
committer | Todd Stinson <stinson@lindenlab.com> | 2012-03-08 12:34:11 -0800 |
commit | f578181af9cbe3277374578c27487e2e72956079 (patch) | |
tree | ab7c041c277d708f805dc3bf9e80418616c19277 | |
parent | dcf7ed021b11b2ec990625389aa185081eeab915 (diff) |
PATH-304: Adding functionality to handle the reloading of out-of-date navmeshes.
-rw-r--r-- | etc/message.xml | 12 | ||||
-rw-r--r-- | indra/newview/llfloaterpathfindingconsole.cpp | 20 | ||||
-rw-r--r-- | indra/newview/llfloaterpathfindingconsole.h | 4 | ||||
-rw-r--r-- | indra/newview/llpathfindingmanager.cpp | 60 | ||||
-rw-r--r-- | indra/newview/llpathfindingmanager.h | 2 | ||||
-rw-r--r-- | indra/newview/llpathfindingnavmesh.cpp | 11 | ||||
-rw-r--r-- | indra/newview/llpathfindingnavmesh.h | 2 | ||||
-rw-r--r-- | indra/newview/llpathfindingnavmeshzone.cpp | 58 | ||||
-rw-r--r-- | indra/newview/llpathfindingnavmeshzone.h | 7 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_pathfinding_console.xml | 2 |
10 files changed, 153 insertions, 25 deletions
diff --git a/etc/message.xml b/etc/message.xml index 3445975545..9407888a92 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -546,8 +546,16 @@ <key>trusted-sender</key> <boolean>true</boolean> </map> - - <!-- UDPDeprecated Messages --> + + <key>NavmeshStatusUpdate</key> + <map> + <key>flavor</key> + <string>llsd</string> + <key>trusted-sender</key> + <boolean>true</boolean> + </map> + + <!-- UDPDeprecated Messages --> <key>ScriptRunningReply</key> <map> <key>flavor</key> diff --git a/indra/newview/llfloaterpathfindingconsole.cpp b/indra/newview/llfloaterpathfindingconsole.cpp index 6824e629c9..493b4617b5 100644 --- a/indra/newview/llfloaterpathfindingconsole.cpp +++ b/indra/newview/llfloaterpathfindingconsole.cpp @@ -171,6 +171,7 @@ void LLFloaterPathfindingConsole::onOpen(const LLSD& pKey) mNavMeshZoneSlot = mNavMeshZone.registerNavMeshZoneListener(boost::bind(&LLFloaterPathfindingConsole::onNavMeshZoneCB, this, _1));
}
+ mIsNavMeshUpdating = false;
mNavMeshZone.initialize();
mNavMeshZone.enable();
@@ -478,6 +479,7 @@ LLFloaterPathfindingConsole::LLFloaterPathfindingConsole(const LLSD& pSeed) mClearPathButton(NULL),
mNavMeshZoneSlot(),
mNavMeshZone(),
+ mIsNavMeshUpdating(false),
mAgentStateSlot(),
mConsoleState(kConsoleStateUnknown),
mPathData(),
@@ -616,10 +618,15 @@ void LLFloaterPathfindingConsole::onNavMeshZoneCB(LLPathfindingNavMeshZone::ENav case LLPathfindingNavMeshZone::kNavMeshZoneRequestUnknown :
setConsoleState(kConsoleStateUnknown);
break;
+ case LLPathfindingNavMeshZone::kNavMeshZoneRequestNeedsUpdate :
+ mIsNavMeshUpdating = true;
+ mNavMeshZone.refresh();
+ break;
case LLPathfindingNavMeshZone::kNavMeshZoneRequestStarted :
setConsoleState(kConsoleStateDownloading);
break;
case LLPathfindingNavMeshZone::kNavMeshZoneRequestCompleted :
+ mIsNavMeshUpdating = false;
setConsoleState(kConsoleStateHasNavMesh);
break;
case LLPathfindingNavMeshZone::kNavMeshZoneRequestNotEnabled :
@@ -689,7 +696,6 @@ void LLFloaterPathfindingConsole::updateControlsOnConsoleState() mHasEndPoint = false;
break;
case kConsoleStateHasNavMesh :
- case kConsoleStateHasNavMeshDownloading :
mShowNavMeshCheckBox->setEnabled(TRUE);
mShowNavMeshWalkabilityComboBox->setEnabled(TRUE);
mShowWalkablesCheckBox->setEnabled(TRUE);
@@ -731,14 +737,18 @@ void LLFloaterPathfindingConsole::updateStatusOnConsoleState() styleParams.color = warningColor;
break;
case kConsoleStateDownloading :
- statusText = getString("navmesh_status_downloading");
+ if (mIsNavMeshUpdating)
+ {
+ statusText = getString("navmesh_status_updating");
+ }
+ else
+ {
+ statusText = getString("navmesh_status_downloading");
+ }
break;
case kConsoleStateHasNavMesh :
statusText = getString("navmesh_status_has_navmesh");
break;
- case kConsoleStateHasNavMeshDownloading :
- statusText = getString("navmesh_status_has_navmesh_downloading");
- break;
case kConsoleStateError :
statusText = getString("navmesh_status_error");
styleParams.color = warningColor;
diff --git a/indra/newview/llfloaterpathfindingconsole.h b/indra/newview/llfloaterpathfindingconsole.h index b1886fb716..8c29bf5909 100644 --- a/indra/newview/llfloaterpathfindingconsole.h +++ b/indra/newview/llfloaterpathfindingconsole.h @@ -122,7 +122,6 @@ private: kConsoleStateRegionNotEnabled, kConsoleStateDownloading, kConsoleStateHasNavMesh, - kConsoleStateHasNavMeshDownloading, kConsoleStateError } EConsoleState; @@ -179,9 +178,10 @@ private: LLTextBase *mPathTestingStatus; LLButton *mClearPathButton; - LLPathfindingNavMeshZone::navmesh_zone_slot_t mNavMeshZoneSlot; LLPathfindingNavMeshZone mNavMeshZone; + bool mIsNavMeshUpdating; + LLPathfindingManager::agent_state_slot_t mAgentStateSlot; EConsoleState mConsoleState; diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp index cba0501ad2..ebefebbb64 100644 --- a/indra/newview/llpathfindingmanager.cpp +++ b/indra/newview/llpathfindingmanager.cpp @@ -26,8 +26,10 @@ */
#include <string>
+#include <vector>
#include "llviewerprecompiledheaders.h"
+#include "llsd.h"
#include "llpathfindingmanager.h"
#include "llsingleton.h"
#include "llhttpclient.h"
@@ -36,6 +38,7 @@ #include "llpathfindingnavmesh.h"
#include "llpathfindinglinkset.h"
#include "llpathfindinglinksetlist.h"
+#include "llhttpnode.h"
#include <boost/function.hpp>
#include <boost/signals2.hpp>
@@ -49,6 +52,20 @@ #define CAP_SERVICE_OBJECT_LINKSETS "ObjectNavMeshProperties"
#define CAP_SERVICE_TERRAIN_LINKSETS "TerrainNavMeshProperties"
+#define SIM_MESSAGE_NAVMESH_STATUS_UPDATE "/message/NavmeshStatusUpdate"
+
+//---------------------------------------------------------------------------
+// LLNavMeshSimStateChangeNode
+//---------------------------------------------------------------------------
+
+class LLNavMeshSimStateChangeNode : public LLHTTPNode
+{
+public:
+ virtual void post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const;
+};
+
+LLHTTPRegistration<LLNavMeshSimStateChangeNode> gHTTPRegistrationNavMeshSimStateChangeNode(SIM_MESSAGE_NAVMESH_STATUS_UPDATE);
+
//---------------------------------------------------------------------------
// NavMeshResponder
//---------------------------------------------------------------------------
@@ -243,6 +260,12 @@ void LLPathfindingManager::requestGetNavMeshForRegion(LLViewerRegion *pRegion) }
}
+void LLPathfindingManager::handleNavMeshUpdate(const LLUUID &pRegionUUID, U32 pNavMeshVersion)
+{
+ LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForRegion(pRegionUUID);
+ navMeshPtr->handleNavMeshNewVersion(++mNavMeshVersionXXX);
+}
+
LLPathfindingManager::agent_state_slot_t LLPathfindingManager::registerAgentStateListener(agent_state_callback_t pAgentStateCallback)
{
return mAgentStateSignal.connect(pAgentStateCallback);
@@ -368,21 +391,14 @@ LLPathfindingManager::ELinksetsRequestStatus LLPathfindingManager::requestSetLin return status;
}
-LLPathfindingNavMeshPtr LLPathfindingManager::getNavMeshForRegion(LLViewerRegion *pRegion)
+LLPathfindingNavMeshPtr LLPathfindingManager::getNavMeshForRegion(const LLUUID &pRegionUUID)
{
-
- LLUUID regionUUID;
- if (pRegion != NULL)
- {
- regionUUID = pRegion->getRegionID();
- }
-
LLPathfindingNavMeshPtr navMeshPtr;
- NavMeshMap::iterator navMeshIter = mNavMeshMap.find(regionUUID);
+ NavMeshMap::iterator navMeshIter = mNavMeshMap.find(pRegionUUID);
if (navMeshIter == mNavMeshMap.end())
{
- navMeshPtr = LLPathfindingNavMeshPtr(new LLPathfindingNavMesh(regionUUID));
- mNavMeshMap.insert(std::pair<LLUUID, LLPathfindingNavMeshPtr>(regionUUID, navMeshPtr));
+ navMeshPtr = LLPathfindingNavMeshPtr(new LLPathfindingNavMesh(pRegionUUID));
+ mNavMeshMap.insert(std::pair<LLUUID, LLPathfindingNavMeshPtr>(pRegionUUID, navMeshPtr));
}
else
{
@@ -392,6 +408,17 @@ LLPathfindingNavMeshPtr LLPathfindingManager::getNavMeshForRegion(LLViewerRegion return navMeshPtr;
}
+LLPathfindingNavMeshPtr LLPathfindingManager::getNavMeshForRegion(LLViewerRegion *pRegion)
+{
+ LLUUID regionUUID;
+ if (pRegion != NULL)
+ {
+ regionUUID = pRegion->getRegionID();
+ }
+
+ return getNavMeshForRegion(regionUUID);
+}
+
bool LLPathfindingManager::isValidAgentState(EAgentState pAgentState)
{
return ((pAgentState == kAgentStateFrozen) || (pAgentState == kAgentStateUnfrozen));
@@ -514,6 +541,17 @@ LLViewerRegion *LLPathfindingManager::getCurrentRegion() const }
//---------------------------------------------------------------------------
+// LLNavMeshSimStateChangeNode
+//---------------------------------------------------------------------------
+
+void LLNavMeshSimStateChangeNode::post(ResponsePtr pResponse, const LLSD &pContext, const LLSD &pInput) const
+{
+ LLViewerRegion *region = gAgent.getRegion();
+ U32 navMeshVersion = 0U;
+ LLPathfindingManager::getInstance()->handleNavMeshUpdate(region->getRegionID(), navMeshVersion);
+}
+
+//---------------------------------------------------------------------------
// NavMeshResponder
//---------------------------------------------------------------------------
diff --git a/indra/newview/llpathfindingmanager.h b/indra/newview/llpathfindingmanager.h index eb8704e308..3e85cb1291 100644 --- a/indra/newview/llpathfindingmanager.h +++ b/indra/newview/llpathfindingmanager.h @@ -80,6 +80,7 @@ public: LLPathfindingNavMesh::navmesh_slot_t registerNavMeshListenerForRegion(LLViewerRegion *pRegion, LLPathfindingNavMesh::navmesh_callback_t pNavMeshCallback);
void requestGetNavMeshForRegion(LLViewerRegion *pRegion);
+ void handleNavMeshUpdate(const LLUUID &pRegionUUID, U32 pNavMeshVersion);
agent_state_slot_t registerAgentStateListener(agent_state_callback_t pAgentStateCallback);
EAgentState getAgentState();
@@ -92,6 +93,7 @@ public: protected:
private:
+ LLPathfindingNavMeshPtr getNavMeshForRegion(const LLUUID &pRegionUUID);
LLPathfindingNavMeshPtr getNavMeshForRegion(LLViewerRegion *pRegion);
static bool isValidAgentState(EAgentState pAgentState);
diff --git a/indra/newview/llpathfindingnavmesh.cpp b/indra/newview/llpathfindingnavmesh.cpp index 469972efa9..84343cf31e 100644 --- a/indra/newview/llpathfindingnavmesh.cpp +++ b/indra/newview/llpathfindingnavmesh.cpp @@ -64,6 +64,13 @@ void LLPathfindingNavMesh::handleRefresh() mNavMeshSignal(mNavMeshRequestStatus, mRegionUUID, mNavMeshVersion, mNavMeshData);
}
+void LLPathfindingNavMesh::handleNavMeshNewVersion(U32 pNavMeshVersion)
+{
+ mNavMeshData.clear();
+ mNavMeshVersion = pNavMeshVersion;
+ setRequestStatus(kNavMeshRequestNeedsUpdate);
+}
+
void LLPathfindingNavMesh::handleNavMeshStart(U32 pNavMeshVersion)
{
mNavMeshVersion = pNavMeshVersion;
@@ -72,7 +79,6 @@ void LLPathfindingNavMesh::handleNavMeshStart(U32 pNavMeshVersion) void LLPathfindingNavMesh::handleNavMeshResult(const LLSD &pContent, U32 pNavMeshVersion)
{
- llassert(mNavMeshVersion == pNavMeshVersion);
if (mNavMeshVersion == pNavMeshVersion)
{
if ( pContent.has("navmesh_data") )
@@ -118,10 +124,9 @@ void LLPathfindingNavMesh::handleNavMeshNotEnabled() void LLPathfindingNavMesh::handleNavMeshError(U32 pStatus, const std::string &pReason, const std::string &pURL, U32 pNavMeshVersion)
{
llwarns << "error with request to URL '" << pURL << "' because " << pReason << " (statusCode:" << pStatus << ")" << llendl;
- llassert(mNavMeshVersion == pNavMeshVersion);
- mNavMeshData.clear();
if (mNavMeshVersion == pNavMeshVersion)
{
+ mNavMeshData.clear();
setRequestStatus(kNavMeshRequestError);
}
}
diff --git a/indra/newview/llpathfindingnavmesh.h b/indra/newview/llpathfindingnavmesh.h index 26ef21f90e..eb9ef9683d 100644 --- a/indra/newview/llpathfindingnavmesh.h +++ b/indra/newview/llpathfindingnavmesh.h @@ -47,6 +47,7 @@ class LLPathfindingNavMesh public:
typedef enum {
kNavMeshRequestUnknown,
+ kNavMeshRequestNeedsUpdate,
kNavMeshRequestStarted,
kNavMeshRequestCompleted,
kNavMeshRequestNotEnabled,
@@ -65,6 +66,7 @@ public: bool hasNavMeshVersion(U32 pNavMeshVersion) const;
void handleRefresh();
+ void handleNavMeshNewVersion(U32 pNavMeshVersion);
void handleNavMeshStart(U32 pNavMeshVersion);
void handleNavMeshResult(const LLSD &pContent, U32 pNavMeshVersion);
void handleNavMeshNotEnabled();
diff --git a/indra/newview/llpathfindingnavmeshzone.cpp b/indra/newview/llpathfindingnavmeshzone.cpp index 983b88fe05..3767834655 100644 --- a/indra/newview/llpathfindingnavmeshzone.cpp +++ b/indra/newview/llpathfindingnavmeshzone.cpp @@ -67,6 +67,24 @@ void LLPathfindingNavMeshZone::initialize() {
mNavMeshLocationPtrs.clear();
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ LLViewerRegion *currentRegion = gAgent.getRegion();
+ if (currentRegion != NULL)
+ {
+ llinfos << "STINSON DEBUG: currentRegion: '" << currentRegion->getName() << "' (" << currentRegion->getRegionID().asString() << ")" << llendl;
+ std::vector<S32> availableRegions;
+ currentRegion->getNeighboringRegionsStatus( availableRegions );
+ std::vector<LLViewerRegion*> neighborRegionsPtrs;
+ currentRegion->getNeighboringRegions( neighborRegionsPtrs );
+ for (std::vector<S32>::const_iterator statusIter = availableRegions.begin();
+ statusIter != availableRegions.end(); ++statusIter)
+ {
+ LLViewerRegion *region = neighborRegionsPtrs[statusIter - availableRegions.begin()];
+ llinfos << "STINSON DEBUG: region #" << *statusIter << ": '" << region->getName() << "' (" << region->getRegionID().asString() << ")" << llendl;
+ }
+ }
+
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
NavMeshLocationPtr centerNavMeshPtr(new NavMeshLocation(CENTER_REGION, boost::bind(&LLPathfindingNavMeshZone::handleNavMeshLocation, this)));
mNavMeshLocationPtrs.push_back(centerNavMeshPtr);
@@ -122,20 +140,30 @@ void LLPathfindingNavMeshZone::handleNavMeshLocation() void LLPathfindingNavMeshZone::updateStatus()
{
bool hasRequestUnknown = false;
+ bool hasRequestNeedsUpdate = false;
bool hasRequestStarted = false;
bool hasRequestCompleted = false;
bool hasRequestNotEnabled = false;
bool hasRequestError = false;
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ llinfos << "STINSON DEBUG: Navmesh zone update BEGIN" << llendl;
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
for (NavMeshLocationPtrs::iterator navMeshLocationPtrIter = mNavMeshLocationPtrs.begin();
navMeshLocationPtrIter != mNavMeshLocationPtrs.end(); ++navMeshLocationPtrIter)
{
NavMeshLocationPtr navMeshLocationPtr = *navMeshLocationPtrIter;
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ llinfos << "STINSON DEBUG: region #" << navMeshLocationPtr->getDirection() << ": region(" << navMeshLocationPtr->getRegionUUID().asString() << ") status:" << navMeshLocationPtr->getRequestStatus() << llendl;
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
switch (navMeshLocationPtr->getRequestStatus())
{
case LLPathfindingNavMesh::kNavMeshRequestUnknown :
hasRequestUnknown = true;
break;
+ case LLPathfindingNavMesh::kNavMeshRequestNeedsUpdate :
+ hasRequestNeedsUpdate = true;
+ break;
case LLPathfindingNavMesh::kNavMeshRequestStarted :
hasRequestStarted = true;
break;
@@ -156,34 +184,62 @@ void LLPathfindingNavMeshZone::updateStatus() }
ENavMeshZoneRequestStatus zoneRequestStatus = kNavMeshZoneRequestUnknown;
- if (hasRequestStarted)
+ if (hasRequestNeedsUpdate)
+ {
+ zoneRequestStatus = kNavMeshZoneRequestNeedsUpdate;
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ llinfos << "STINSON DEBUG: Navmesh zone update is NEEDS UPDATE" << llendl;
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
+ }
+ else if (hasRequestStarted)
{
zoneRequestStatus = kNavMeshZoneRequestStarted;
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ llinfos << "STINSON DEBUG: Navmesh zone update is STARTED" << llendl;
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
}
else if (hasRequestError)
{
zoneRequestStatus = kNavMeshZoneRequestError;
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ llinfos << "STINSON DEBUG: Navmesh zone update is ERROR" << llendl;
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
}
else if (hasRequestUnknown)
{
zoneRequestStatus = kNavMeshZoneRequestUnknown;
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ llinfos << "STINSON DEBUG: Navmesh zone update is UNKNOWN" << llendl;
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
}
else if (hasRequestCompleted)
{
zoneRequestStatus = kNavMeshZoneRequestCompleted;
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ llinfos << "STINSON DEBUG: Navmesh zone update is stitching" << llendl;
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
llassert(LLPathingLib::getInstance() != NULL);
if (LLPathingLib::getInstance() != NULL)
{
LLPathingLib::getInstance()->stitchNavMeshes( gSavedSettings.getBOOL("EnableVBOForNavMeshVisualization") );
}
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ llinfos << "STINSON DEBUG: Navmesh zone update is COMPLETED" << llendl;
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
}
else if (hasRequestNotEnabled)
{
zoneRequestStatus = kNavMeshZoneRequestNotEnabled;
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ llinfos << "STINSON DEBUG: Navmesh zone update is NOT ENABLED" << llendl;
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
}
else
{
zoneRequestStatus = kNavMeshZoneRequestError;
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ llinfos << "STINSON DEBUG: Navmesh zone update is BAD ERROR" << llendl;
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
llassert(0);
}
diff --git a/indra/newview/llpathfindingnavmeshzone.h b/indra/newview/llpathfindingnavmeshzone.h index 8489b5899b..7084869b33 100644 --- a/indra/newview/llpathfindingnavmeshzone.h +++ b/indra/newview/llpathfindingnavmeshzone.h @@ -38,11 +38,14 @@ #include <boost/function.hpp>
#include <boost/signals2.hpp>
+#define XXX_STINSON_DEBUG_NAVMESH_ZONE
+
class LLPathfindingNavMeshZone
{
public:
typedef enum {
kNavMeshZoneRequestUnknown,
+ kNavMeshZoneRequestNeedsUpdate,
kNavMeshZoneRequestStarted,
kNavMeshZoneRequestCompleted,
kNavMeshZoneRequestNotEnabled,
@@ -78,6 +81,10 @@ private: void disable();
LLPathfindingNavMesh::ENavMeshRequestStatus getRequestStatus() const;
+#ifdef XXX_STINSON_DEBUG_NAVMESH_ZONE
+ const LLUUID &getRegionUUID() const {return mRegionUUID;};
+ S32 getDirection() const {return mDirection;};
+#endif // XXX_STINSON_DEBUG_NAVMESH_ZONE
protected:
diff --git a/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml b/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml index 6c97af2878..75465f1aea 100644 --- a/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml +++ b/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml @@ -15,8 +15,8 @@ <floater.string name="navmesh_status_library_not_implemented">Cannot find pathing library implementation.</floater.string> <floater.string name="navmesh_status_region_not_enabled">This region is not enabled for pathfinding.</floater.string> <floater.string name="navmesh_status_downloading">Downloading the navmesh ...</floater.string> + <floater.string name="navmesh_status_updating">The navmesh has changed on the server. Downloading the latest navmesh ...</floater.string> <floater.string name="navmesh_status_has_navmesh">Navmesh received.</floater.string> - <floater.string name="navmesh_status_has_navmesh_downloading">Downloading the latest navmesh ...</floater.string> <floater.string name="navmesh_status_error">Unable to download navmesh successfully.</floater.string> <floater.string name="pathing_choose_start_and_end_points">Please choose start and end points.</floater.string> <floater.string name="pathing_choose_start_point">Please choose start point.</floater.string> |