diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 5223eead35dd61e55bdce75985fb15c07b543aa9..c5eac457fd4dd94ac29b5aa9f0687a68a2731eef 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -333,7 +333,6 @@ set(viewer_SOURCE_FILES
     llnameeditor.cpp
     llnamelistctrl.cpp
     llnavigationbar.cpp
-    llnavmeshstation.cpp
     llnearbychat.cpp
     llnearbychatbar.cpp
     llnearbychathandler.cpp
@@ -421,6 +420,7 @@ set(viewer_SOURCE_FILES
     llpathfindinglinkset.cpp
     llpathfindinglinksetlist.cpp
     llpathfindingmanager.cpp
+    llpathfindingnavmesh.cpp
     llphysicsmotion.cpp
     llphysicsshapebuilderutil.cpp
     llplacesinventorybridge.cpp
@@ -898,7 +898,6 @@ set(viewer_HEADER_FILES
     llnameeditor.h
     llnamelistctrl.h
     llnavigationbar.h
-    llnavmeshstation.h
     llnearbychat.h
     llnearbychatbar.h
     llnearbychathandler.h
@@ -975,6 +974,7 @@ set(viewer_HEADER_FILES
     llpathfindinglinkset.h
     llpathfindinglinksetlist.h
     llpathfindingmanager.h
+    llpathfindingnavmesh.h
     llphysicsmotion.h
     llphysicsshapebuilderutil.h
     llplacesinventorybridge.h
diff --git a/indra/newview/llfloaterpathfindingbasic.cpp b/indra/newview/llfloaterpathfindingbasic.cpp
index 04d830632d113acb8bee2ec179dc5d9c0e9f3b4a..d1103088abe8aa2a074d56e305452e361b90ca88 100644
--- a/indra/newview/llfloaterpathfindingbasic.cpp
+++ b/indra/newview/llfloaterpathfindingbasic.cpp
@@ -66,7 +66,7 @@ void LLFloaterPathfindingBasic::onOpen(const LLSD& pKey)
 
 	if (!mAgentStateSlot.connected())
 	{
-		mAgentStateSlot = LLPathfindingManager::getInstance()->registerAgentStateSignal(boost::bind(&LLFloaterPathfindingBasic::onAgentStateCB, this, _1));
+		mAgentStateSlot = LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLFloaterPathfindingBasic::onAgentStateCB, this, _1));
 	}
 	setAgentState(LLPathfindingManager::getInstance()->getAgentState());
 }
diff --git a/indra/newview/llfloaterpathfindingconsole.cpp b/indra/newview/llfloaterpathfindingconsole.cpp
index 2bf46175ee9aea5d9bd366b53ae10c713c744c34..02f2bf8d72dd964961d4680a6ff21c38c9dbf821 100644
--- a/indra/newview/llfloaterpathfindingconsole.cpp
+++ b/indra/newview/llfloaterpathfindingconsole.cpp
@@ -33,6 +33,7 @@
 #include "llsd.h"
 #include "llhandle.h"
 #include "llagent.h"
+#include "llpanel.h"
 #include "llbutton.h"
 #include "llradiogroup.h"
 #include "llsliderctrl.h"
@@ -40,12 +41,12 @@
 #include "lltextbase.h"
 #include "lltabcontainer.h"
 #include "llcombobox.h"
-#include "llnavmeshstation.h"
 #include "llfloaterreg.h"
 #include "llviewerregion.h"
 #include "llviewerwindow.h"
 #include "llviewercamera.h"
 #include "llviewercontrol.h"
+#include "llpathfindingnavmesh.h"
 #include "llpathfindingmanager.h"
 
 #include "LLPathingLib.h"
@@ -104,6 +105,12 @@ BOOL LLFloaterPathfindingConsole::postBuild()
 	mEditTestTabContainer = findChild<LLTabContainer>("edit_test_tab_container");
 	llassert(mEditTestTabContainer != NULL);
 
+	mEditTab = findChild<LLPanel>("edit_panel");
+	llassert(mEditTab != NULL);
+
+	mTestTab = findChild<LLPanel>("test_panel");
+	llassert(mTestTab != NULL);
+
 	mUnfreezeLabel = findChild<LLTextBase>("unfreeze_label");
 	llassert(mUnfreezeLabel != NULL);
 
@@ -157,14 +164,18 @@ void LLFloaterPathfindingConsole::onOpen(const LLSD& pKey)
 	}	
 	if ( LLPathingLib::getInstance() == NULL )
 	{ 
-		std::string str = getString("navmesh_library_not_implemented");
-		LLStyle::Params styleParams;
-		styleParams.color = LLUIColorTable::instance().getColor("DrYellow");
-		mPathfindingStatus->setText((LLStringExplicit)str, styleParams);
+		setConsoleState(kConsoleStateLibraryNotImplemented);
 		llwarns <<"Errror: cannout find pathing library implementation."<<llendl;
 	}
 	else
-	{	
+	{
+		LLPathfindingManager *pathfindingManagerInstance = LLPathfindingManager::getInstance();
+		if (!mNavMeshSlot.connected())
+		{
+			pathfindingManagerInstance->registerNavMeshListenerForCurrentRegion(boost::bind(&LLFloaterPathfindingConsole::onNavMeshDownloadCB, this, _1, _2, _3, _4));
+		}
+		pathfindingManagerInstance->requestGetNavMeshForCurrentRegion();
+#if 0
 		LLPathingLib::getInstance()->cleanupResidual();
 
 		mCurrentMDO = 0;
@@ -232,12 +243,14 @@ void LLFloaterPathfindingConsole::onOpen(const LLSD& pKey)
 				llinfos<<"Region has does not required caps of type ["<<capability<<"]"<<llendl;
 			}
 		}
+#endif
 	}		
 
 	if (!mAgentStateSlot.connected())
 	{
-		LLPathfindingManager::getInstance()->registerAgentStateSignal(boost::bind(&LLFloaterPathfindingConsole::onAgentStateCB, this, _1));
+		LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLFloaterPathfindingConsole::onAgentStateCB, this, _1));
 	}
+
 	setAgentState(LLPathfindingManager::getInstance()->getAgentState());
 	updatePathTestStatus();
 }
@@ -248,9 +261,16 @@ void LLFloaterPathfindingConsole::onClose(bool pIsAppQuitting)
 	{
 		mAgentStateSlot.disconnect();
 	}
-	LLPathingLib::getInstance()->cleanupResidual();
+
+	if (mNavMeshSlot.connected())
+	{
+		mNavMeshSlot.disconnect();
+	}
+
+	clearNavMesh();
 	LLFloater::onClose(pIsAppQuitting);
 	setHeartBeat( false );
+	setConsoleState(kConsoleStateUnknown);
 }
 
 BOOL LLFloaterPathfindingConsole::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
@@ -496,6 +516,7 @@ void LLFloaterPathfindingConsole::setCharacterType(ECharacterType pCharacterType
 	mCharacterTypeRadioGroup->setValue(radioGroupValue);
 }
 
+#if 0
 void LLFloaterPathfindingConsole::setHasNavMeshReceived()
 {
 	std::string str = getString("navmesh_fetch_complete_available");
@@ -513,6 +534,7 @@ void LLFloaterPathfindingConsole::setHasNoNavMesh()
 	std::string str = getString("navmesh_fetch_complete_none");
 	mPathfindingStatus->setText((LLStringExplicit)str);
 }
+#endif
 
 LLFloaterPathfindingConsole::LLFloaterPathfindingConsole(const LLSD& pSeed)
 	: LLFloater(pSeed),
@@ -527,6 +549,8 @@ LLFloaterPathfindingConsole::LLFloaterPathfindingConsole(const LLSD& pSeed)
 	mPathfindingStatus(NULL),
 	mViewCharactersButton(NULL),
 	mEditTestTabContainer(NULL),
+	mEditTab(NULL),
+	mTestTab(NULL),
 	mUnfreezeLabel(NULL),
 	mUnfreezeButton(NULL),
 	mLinksetsLabel(NULL),
@@ -537,38 +561,33 @@ LLFloaterPathfindingConsole::LLFloaterPathfindingConsole(const LLSD& pSeed)
 	mCharacterTypeRadioGroup(NULL),
 	mPathTestingStatus(NULL),
 	mClearPathButton(NULL),
+	mNavMeshSlot(),
 	mAgentStateSlot(),
+	mConsoleState(kConsoleStateUnknown),
+	mHasNavMesh(false),
+	mNavMeshRegionVersion(0U),
+	mNavMeshRegionUUID(),
+#if 0
 	mNavMeshCnt(0),
+	mNeighboringRegion( CURRENT_REGION ),
+#endif
 	mHasStartPoint(false),
 	mHasEndPoint(false),
-	mNeighboringRegion( CURRENT_REGION ),
 	mHeartBeat( false )
 {
 	mSelfHandle.bind(this);
-
+#if 0
 	for (int i=0;i<MAX_OBSERVERS;++i)
 	{
 		mNavMeshDownloadObserver[i].setPathfindingConsole(this);
 	}
+#endif
 }
 
 LLFloaterPathfindingConsole::~LLFloaterPathfindingConsole()
 {
 }
 
-std::string LLFloaterPathfindingConsole::getCurrentRegionCapabilityURL() const
-{
-	std::string capURL("");
-
-	LLViewerRegion *region = gAgent.getRegion();
-	if (region != NULL)
-	{
-		capURL = region->getCapability("RetrieveNavMeshSrc");
-	}
-
-	return capURL;
-}
-
 void LLFloaterPathfindingConsole::onShowWalkabilitySet()
 {
 	switch (getRenderHeatmapType())
@@ -686,17 +705,76 @@ void LLFloaterPathfindingConsole::onClearPathClicked()
 	updatePathTestStatus();
 }
 
+void LLFloaterPathfindingConsole::onNavMeshDownloadCB(LLPathfindingNavMesh::ENavMeshRequestStatus pNavMeshRequestStatus, const LLUUID &pRegionUUID, U32 pNavMeshVersion, const LLSD::Binary &pNavMeshData)
+{
+
+	switch (pNavMeshRequestStatus)
+	{
+	case LLPathfindingNavMesh::kNavMeshRequestStarted :
+		setConsoleState(kConsoleStateDownloading);
+		break;
+	case LLPathfindingNavMesh::kNavMeshRequestCompleted :
+		updateNavMesh(pRegionUUID, pNavMeshVersion, pNavMeshData);
+		setConsoleState(kConsoleStateHasNavMesh);
+		break;
+	case LLPathfindingNavMesh::kNavMeshRequestNotEnabled :
+		clearNavMesh();
+		setConsoleState(kConsoleStateRegionNotEnabled);
+		break;
+	case LLPathfindingNavMesh::kNavMeshRequestMessageError :
+		clearNavMesh();
+		setConsoleState(kConsoleStateDownloadError);
+		break;
+	case LLPathfindingNavMesh::kNavMeshRequestFormatError :
+		clearNavMesh();
+		setConsoleState(kConsoleStateNavMeshError);
+		break;
+	case LLPathfindingNavMesh::kNavMeshRequestUnknown :
+	default:
+		clearNavMesh();
+		setConsoleState(kConsoleStateUnknown);
+		llassert(0);
+		break;
+	}
+}
+
+void LLFloaterPathfindingConsole::updateNavMesh(const LLUUID &pRegionUUID, U32 pNavMeshVersion, const LLSD::Binary &pNavMeshData)
+{
+	if (!mHasNavMesh || (mNavMeshRegionUUID != pRegionUUID) || (mNavMeshRegionVersion != pNavMeshVersion))
+	{
+		llassert(!pNavMeshData.empty());
+		mHasNavMesh = true;
+		mNavMeshRegionUUID = pRegionUUID;
+		mNavMeshRegionVersion = pNavMeshVersion;
+		LLPathingLib::getInstance()->extractNavMeshSrcFromLLSD(pNavMeshData, CURRENT_REGION);
+	}
+}
+
+void LLFloaterPathfindingConsole::clearNavMesh()
+{
+	mHasNavMesh = false;
+	LLPathingLib::getInstance()->cleanupResidual();
+}
+
 void LLFloaterPathfindingConsole::onAgentStateCB(LLPathfindingManager::EAgentState pAgentState)
 {
 	setAgentState(pAgentState);
 }
 
-void LLFloaterPathfindingConsole::setAgentState(LLPathfindingManager::EAgentState pAgentState)
+void LLFloaterPathfindingConsole::setConsoleState(EConsoleState pConsoleState)
+{
+	mConsoleState = pConsoleState;
+	updateControlsOnConsoleState();
+	updateStatusOnConsoleState();
+}
+
+void LLFloaterPathfindingConsole::updateControlsOnConsoleState()
 {
-	switch (pAgentState)
+	switch (mConsoleState)
 	{
-	case LLPathfindingManager::kAgentStateUnknown :
-	case LLPathfindingManager::kAgentStateNotEnabled :
+	case kConsoleStateUnknown :
+	case kConsoleStateLibraryNotImplemented :
+	case kConsoleStateRegionNotEnabled :
 		mShowNavMeshCheckBox->setEnabled(FALSE);
 		mShowNavMeshWalkabilityComboBox->setEnabled(FALSE);
 		mShowWalkablesCheckBox->setEnabled(FALSE);
@@ -705,16 +783,35 @@ void LLFloaterPathfindingConsole::setAgentState(LLPathfindingManager::EAgentStat
 		mShowExclusionVolumesCheckBox->setEnabled(FALSE);
 		mShowWorldCheckBox->setEnabled(FALSE);
 		mViewCharactersButton->setEnabled(FALSE);
-		mEditTestTabContainer->setEnabled(FALSE);
+		mEditTestTabContainer->selectTab(0);
+		mTestTab->setEnabled(FALSE);
 		mCharacterWidthSlider->setEnabled(FALSE);
 		mCharacterTypeRadioGroup->setEnabled(FALSE);
 		mClearPathButton->setEnabled(FALSE);
-
+		mHasStartPoint = false;
+		mHasEndPoint = false;
+		break;
+	case kConsoleStateDownloading :
+	case kConsoleStateDownloadError :
+	case kConsoleStateNavMeshError :
+		mShowNavMeshCheckBox->setEnabled(FALSE);
+		mShowNavMeshWalkabilityComboBox->setEnabled(FALSE);
+		mShowWalkablesCheckBox->setEnabled(FALSE);
+		mShowStaticObstaclesCheckBox->setEnabled(FALSE);
+		mShowMaterialVolumesCheckBox->setEnabled(FALSE);
+		mShowExclusionVolumesCheckBox->setEnabled(FALSE);
+		mShowWorldCheckBox->setEnabled(FALSE);
+		mViewCharactersButton->setEnabled(TRUE);
 		mEditTestTabContainer->selectTab(0);
+		mTestTab->setEnabled(FALSE);
+		mCharacterWidthSlider->setEnabled(FALSE);
+		mCharacterTypeRadioGroup->setEnabled(FALSE);
+		mClearPathButton->setEnabled(FALSE);
 		mHasStartPoint = false;
 		mHasEndPoint = false;
 		break;
-	default :
+	case kConsoleStateHasNavMesh :
+	case kConsoleStateHasNavMeshDownloading :
 		mShowNavMeshCheckBox->setEnabled(TRUE);
 		mShowNavMeshWalkabilityComboBox->setEnabled(TRUE);
 		mShowWalkablesCheckBox->setEnabled(TRUE);
@@ -723,17 +820,71 @@ void LLFloaterPathfindingConsole::setAgentState(LLPathfindingManager::EAgentStat
 		mShowExclusionVolumesCheckBox->setEnabled(TRUE);
 		mShowWorldCheckBox->setEnabled(TRUE);
 		mViewCharactersButton->setEnabled(TRUE);
-		mEditTestTabContainer->setEnabled(TRUE);
+		mTestTab->setEnabled(TRUE);
 		mCharacterWidthSlider->setEnabled(TRUE);
 		mCharacterTypeRadioGroup->setEnabled(TRUE);
 		mClearPathButton->setEnabled(TRUE);
+		mTestTab->setEnabled(TRUE);
+		break;
+	default :
+		llassert(0);
 		break;
 	}
+}
 
+void LLFloaterPathfindingConsole::updateStatusOnConsoleState()
+{
+	static const LLColor4 warningColor = LLUIColorTable::instance().getColor("DrYellow");
+
+	std::string statusText("");
+	LLStyle::Params styleParams;
+
+	switch (mConsoleState)
+	{
+	case kConsoleStateUnknown :
+		statusText = getString("navmesh_status_unknown");
+		break;
+	case kConsoleStateLibraryNotImplemented :
+		statusText = getString("navmesh_status_library_not_implemented");
+		styleParams.color = warningColor;
+		break;
+	case kConsoleStateRegionNotEnabled :
+		statusText = getString("navmesh_status_region_not_enabled");
+		styleParams.color = warningColor;
+		break;
+	case kConsoleStateDownloading :
+		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 kConsoleStateDownloadError :
+		statusText = getString("navmesh_status_download_error");
+		styleParams.color = warningColor;
+		break;
+	case kConsoleStateNavMeshError :
+		statusText = getString("navmesh_status_navmesh_error");
+		styleParams.color = warningColor;
+		break;
+	default :
+		statusText = getString("navmesh_status_unknown");
+		llassert(0);
+		break;
+	}
+
+	mPathfindingStatus->setText((LLStringExplicit)statusText, styleParams);
+}
+
+void LLFloaterPathfindingConsole::setAgentState(LLPathfindingManager::EAgentState pAgentState)
+{
 	switch (LLPathfindingManager::getInstance()->getLastKnownNonErrorAgentState())
 	{
 	case LLPathfindingManager::kAgentStateUnknown :
 	case LLPathfindingManager::kAgentStateNotEnabled :
+		mEditTab->setEnabled(FALSE);
 		mUnfreezeLabel->setEnabled(FALSE);
 		mUnfreezeButton->setEnabled(FALSE);
 		mLinksetsLabel->setEnabled(FALSE);
@@ -742,6 +893,7 @@ void LLFloaterPathfindingConsole::setAgentState(LLPathfindingManager::EAgentStat
 		mFreezeButton->setEnabled(FALSE);
 		break;
 	case LLPathfindingManager::kAgentStateFrozen :
+		mEditTab->setEnabled(TRUE);
 		mUnfreezeLabel->setEnabled(TRUE);
 		mUnfreezeButton->setEnabled(TRUE);
 		mLinksetsLabel->setEnabled(FALSE);
@@ -750,6 +902,7 @@ void LLFloaterPathfindingConsole::setAgentState(LLPathfindingManager::EAgentStat
 		mFreezeButton->setEnabled(FALSE);
 		break;
 	case LLPathfindingManager::kAgentStateUnfrozen :
+		mEditTab->setEnabled(TRUE);
 		mUnfreezeLabel->setEnabled(FALSE);
 		mUnfreezeButton->setEnabled(FALSE);
 		mLinksetsLabel->setEnabled(TRUE);
@@ -803,36 +956,36 @@ void LLFloaterPathfindingConsole::updatePathTestStatus()
 }
 
 
-BOOL LLFloaterPathfindingConsole::isRenderAnyShapes() const
-{
-	if ( isRenderWalkables() || isRenderStaticObstacles() ||
-		 isRenderMaterialVolumes() ||  isRenderExclusionVolumes() )
-	{
-		return true;
-	}
-	
-	return false;
-}
-
-U32 LLFloaterPathfindingConsole::getRenderShapeFlags()
-{
-	resetShapeRenderFlags();
-
-	if ( isRenderWalkables() )			
-	{ 
-		setShapeRenderFlag( LLPathingLib::LLST_WalkableObjects ); 
-	}
-	if ( isRenderStaticObstacles() )	
-	{ 
-		setShapeRenderFlag( LLPathingLib::LLST_ObstacleObjects ); 
-	}
-	if ( isRenderMaterialVolumes() )	
-	{ 
-		setShapeRenderFlag( LLPathingLib::LLST_MaterialPhantoms ); 
-	}
-	if ( isRenderExclusionVolumes() )	
-	{ 
-		setShapeRenderFlag( LLPathingLib::LLST_ExclusionPhantoms ); 
-	}
-	return mShapeRenderFlags;
-}
+BOOL LLFloaterPathfindingConsole::isRenderAnyShapes() const
+{
+	if ( isRenderWalkables() || isRenderStaticObstacles() ||
+		 isRenderMaterialVolumes() ||  isRenderExclusionVolumes() )
+	{
+		return true;
+	}
+	
+	return false;
+}
+
+U32 LLFloaterPathfindingConsole::getRenderShapeFlags()
+{
+	resetShapeRenderFlags();
+
+	if ( isRenderWalkables() )			
+	{ 
+		setShapeRenderFlag( LLPathingLib::LLST_WalkableObjects ); 
+	}
+	if ( isRenderStaticObstacles() )	
+	{ 
+		setShapeRenderFlag( LLPathingLib::LLST_ObstacleObjects ); 
+	}
+	if ( isRenderMaterialVolumes() )	
+	{ 
+		setShapeRenderFlag( LLPathingLib::LLST_MaterialPhantoms ); 
+	}
+	if ( isRenderExclusionVolumes() )	
+	{ 
+		setShapeRenderFlag( LLPathingLib::LLST_ExclusionPhantoms ); 
+	}
+	return mShapeRenderFlags;
+}
diff --git a/indra/newview/llfloaterpathfindingconsole.h b/indra/newview/llfloaterpathfindingconsole.h
index 34a68ebed1ff170a230fe77141dcb4e0423534ce..237d4216bbf139b5787291bc47611cf4509ceb64 100644
--- a/indra/newview/llfloaterpathfindingconsole.h
+++ b/indra/newview/llfloaterpathfindingconsole.h
@@ -30,11 +30,12 @@
 
 #include "llfloater.h"
 #include "llhandle.h"
-#include "llnavmeshstation.h"
 #include "LLPathingLib.h"
 #include "llpathfindingmanager.h"
+#include "llpathfindingnavmesh.h"
 
 class LLSD;
+class LLPanel;
 class LLRadioGroup;
 class LLSliderCtrl;
 class LLLineEditor;
@@ -108,22 +109,29 @@ class LLFloaterPathfindingConsole
     ECharacterType getCharacterType() const;
     void           setCharacterType(ECharacterType pCharacterType);
 
-	void setHasNavMeshReceived();
-	void setHasNoNavMesh();
-
 	bool getHeartBeat() const { return mHeartBeat;}
 	void setHeartBeat( bool state ) { mHeartBeat=state; }
 
 protected:
 
 private:
+	typedef enum
+	{
+		kConsoleStateUnknown,
+		kConsoleStateLibraryNotImplemented,
+		kConsoleStateRegionNotEnabled,
+		kConsoleStateDownloading,
+		kConsoleStateHasNavMesh,
+		kConsoleStateHasNavMeshDownloading,
+		kConsoleStateDownloadError,
+		kConsoleStateNavMeshError
+	} EConsoleState;
+
 	// Does its own instance management, so clients not allowed
 	// to allocate or destroy.
 	LLFloaterPathfindingConsole(const LLSD& pSeed);
 	virtual ~LLFloaterPathfindingConsole();
 
-	std::string getCurrentRegionCapabilityURL() const;
-
 	void onShowWalkabilitySet();
 	void onShowWorldToggle();
 	void onCharacterWidthSet();
@@ -133,8 +141,16 @@ class LLFloaterPathfindingConsole
 	void onFreezeClicked();
 	void onViewEditLinksetClicked();
 	void onClearPathClicked();
+	void onNavMeshDownloadCB(LLPathfindingNavMesh::ENavMeshRequestStatus pNavMeshRequestStatus, const LLUUID &pRegionUUID, U32 pNavMeshVersion, const LLSD::Binary &pNavMeshData);
 	void onAgentStateCB(LLPathfindingManager::EAgentState pAgentState);
 
+	void setConsoleState(EConsoleState pConsoleState);
+	void updateNavMesh(const LLUUID &pRegionUUID, U32 pNavMeshVersion, const LLSD::Binary &pNavMeshData);
+	void clearNavMesh();
+
+	void updateControlsOnConsoleState();
+	void updateStatusOnConsoleState();
+
 	void setAgentState(LLPathfindingManager::EAgentState pAgentState);
 
 	void generatePath();
@@ -153,6 +169,8 @@ class LLFloaterPathfindingConsole
 	LLTextBase                                *mPathfindingStatus;
 	LLButton                                  *mViewCharactersButton;
 	LLTabContainer                            *mEditTestTabContainer;
+	LLPanel                                   *mEditTab;
+	LLPanel                                   *mTestTab;
 	LLTextBase                                *mUnfreezeLabel;
 	LLButton                                  *mUnfreezeButton;
 	LLTextBase                                *mLinksetsLabel;
@@ -163,12 +181,19 @@ class LLFloaterPathfindingConsole
 	LLRadioGroup                              *mCharacterTypeRadioGroup;
 	LLTextBase                                *mPathTestingStatus;
 	LLButton                                  *mClearPathButton;
+	LLPathfindingNavMesh::navmesh_slot_t      mNavMeshSlot;
 	LLPathfindingManager::agent_state_slot_t  mAgentStateSlot;
+	EConsoleState                             mConsoleState;
+	bool                                      mHasNavMesh;
+	U32                                       mNavMeshRegionVersion;
+	LLUUID                                    mNavMeshRegionUUID;
 
+#if 0
 	LLNavMeshDownloadObserver	mNavMeshDownloadObserver[10];
 	int							mCurrentMDO;
 	int							mNavMeshCnt;
 	U32							mNeighboringRegion;
+#endif
 	//Container that is populated and subsequently submitted to the LLPathingSystem for processing
 	LLPathingLib::PathingPacket		mPathData;
 	bool							mHasStartPoint;
diff --git a/indra/newview/llfloaterpathfindinglinksets.cpp b/indra/newview/llfloaterpathfindinglinksets.cpp
index 27047b4fd958020127d69c77ca1fb11c972d5343..8c4bbea1287406f5408974449f416d30794861f0 100644
--- a/indra/newview/llfloaterpathfindinglinksets.cpp
+++ b/indra/newview/llfloaterpathfindinglinksets.cpp
@@ -211,7 +211,7 @@ void LLFloaterPathfindingLinksets::onOpen(const LLSD& pKey)
 
 	if (!mAgentStateSlot.connected())
 	{
-		LLPathfindingManager::getInstance()->registerAgentStateSignal(boost::bind(&LLFloaterPathfindingLinksets::onAgentStateCB, this, _1));
+		LLPathfindingManager::getInstance()->registerAgentStateListener(boost::bind(&LLFloaterPathfindingLinksets::onAgentStateCB, this, _1));
 	}
 
 	if (!mSelectionUpdateSlot.connected())
diff --git a/indra/newview/llnavmeshstation.cpp b/indra/newview/llnavmeshstation.cpp
deleted file mode 100644
index 54a945e5621e5e7f7def978a75bcdbfe8144b56b..0000000000000000000000000000000000000000
--- a/indra/newview/llnavmeshstation.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/** 
- * @file llnavmeshstation.cpp
- * @brief 
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-#include "llnavmeshstation.h"
-#include "llcurl.h"
-#include "LLPathingLib.h"
-#include "llagent.h"
-#include "llviewerregion.h"
-#include "llsdutil.h"
-#include "llfloaterpathfindingconsole.h"
-#include "llsdserialize.h"
-//===============================================================================
-LLNavMeshStation::LLNavMeshStation()
-{
-}
-//===============================================================================
-class LLNavMeshDownloadResponder : public LLCurl::Responder
-{
-public:
-	LLNavMeshDownloadResponder( const LLHandle<LLNavMeshDownloadObserver>& observer_handle, int dir )
-	:  mObserverHandle( observer_handle )
-	,  mDir( dir )
-	{
-	}
-
-	void error( U32 statusNum, const std::string& reason )
-	{	
-		llwarns	<< "Transport error "<<reason<<llendl;			
-	}
-	
-	void result( const LLSD& content )
-	{		
-		llinfos<<"Content received"<<llendl;
-		if ( content.has("error") )
-		{
-			llwarns	<< "Error on fetched data"<< llendl;
-			//llinfos<<"LLsd buffer on error"<<ll_pretty_print_sd(content)<<llendl;
-		}
-		else 
-		{
-			LLNavMeshDownloadObserver* pObserver = mObserverHandle.get();
-			if ( pObserver )
-			{				
-				if ( content.has("navmesh_data") )
-				{
-					const std::vector<U8>& value = content["navmesh_data"].asBinary();
-					unsigned int binSize = value.size();
-					U8* pBinBuffer = new U8[binSize];
-					memcpy( &pBinBuffer[0], &value[0], binSize );
-					std::string newStr((char*) pBinBuffer, binSize );
-                    std::istringstream streamdecomp( newStr );                 
-					unsigned int decompBinSize = 0;
-					bool valid = false;
-					if ( pBinBuffer ) 
-					{
-						delete [] pBinBuffer ;
-					}
-					U8* pUncompressedNavMeshContainer = unzip_llsdNavMesh( valid, decompBinSize, streamdecomp, binSize ) ;
-					if ( !valid )
-                    {
-						if ( pUncompressedNavMeshContainer )
-						{
-							free( pUncompressedNavMeshContainer );
-						}
-                        llwarns << "Unable to decompress the navmesh llsd." << llendl;
-						pObserver->getPathfindingConsole()->setHasNoNavMesh();
-                        return;
-                    }
-                    else
-                    {                    
-						if ( pUncompressedNavMeshContainer )
-						{
-							std::vector<U8> lsd;
-							lsd.resize( decompBinSize );
-							memcpy( &lsd[0], &pUncompressedNavMeshContainer[0], decompBinSize );
-							LLPathingLib::getInstance()->extractNavMeshSrcFromLLSD( lsd, mDir );
-							pObserver->getPathfindingConsole()->setHasNavMeshReceived();
-							free( pUncompressedNavMeshContainer );
-						}
-                    }					
-				}
-				else
-				{
-					llwarns<<"No mesh data received"<<llendl;
-					pObserver->getPathfindingConsole()->setHasNoNavMesh();
-				}
-			}
-		}	
-}		
-private:
-	//Observer handle
-	LLHandle<LLNavMeshDownloadObserver> mObserverHandle;
-	int mDir;
-};
-//===============================================================================
-void LLNavMeshStation::downloadNavMeshSrc( const LLHandle<LLNavMeshDownloadObserver>& observerHandle, int dir ) 
-{	
-	if ( mNavMeshDownloadURL.empty() )
-	{
-		llinfos << "Unable to upload navmesh because of missing URL" << llendl;
-	}
-	else
-	{		
-		LLSD data;
-		data["agent_id"]  = gAgent.getID();
-		data["region_id"] = gAgent.getRegion()->getRegionID();
-		LLHTTPClient::post(mNavMeshDownloadURL, data, new LLNavMeshDownloadResponder( observerHandle, dir ) );
-	}
-}
-//===============================================================================
diff --git a/indra/newview/llnavmeshstation.h b/indra/newview/llnavmeshstation.h
deleted file mode 100644
index 72bf725688ba6873cf4f805dea5c50676d1947f4..0000000000000000000000000000000000000000
--- a/indra/newview/llnavmeshstation.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/** 
- * @file llnavmeshstation.h
- * @brief Client-side navmesh support
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_NAV_MESH_STATION_H
-#define LL_NAV_MESH_STATION_H
-
-//===============================================================================
-#include "llhandle.h"
-//===============================================================================
-class LLCurlRequest;
-class LLFloaterPathfindingConsole;
-//===============================================================================
-class LLNavMeshObserver
-{
-public:
-	//Ctor
-	LLNavMeshObserver()
-		: mPathfindingConsole(NULL)
-	{ mObserverHandle.bind(this); }
-	//Dtor
-	virtual ~LLNavMeshObserver() {}
-	//Accessor for the observers handle
-	const LLHandle<LLNavMeshObserver>& getObserverHandle() const { return mObserverHandle; }
-	LLFloaterPathfindingConsole *getPathfindingConsole() {return mPathfindingConsole;}
-	void                        setPathfindingConsole(LLFloaterPathfindingConsole *pPathfindingConsole) {mPathfindingConsole = pPathfindingConsole;}
-
-protected:
-	LLRootHandle<LLNavMeshObserver> mObserverHandle;	
-	LLFloaterPathfindingConsole     *mPathfindingConsole;
-};
-//===============================================================================
-class LLNavMeshDownloadObserver
-{
-public:
-	//Ctor
-	LLNavMeshDownloadObserver() { mObserverHandle.bind(this); }
-	//Dtor
-	virtual ~LLNavMeshDownloadObserver() {}
-	//Accessor for the observers handle
-	const LLHandle<LLNavMeshDownloadObserver>& getObserverHandle() const { return mObserverHandle; }
-	LLFloaterPathfindingConsole *getPathfindingConsole() {return mPathfindingConsole;}
-	void                        setPathfindingConsole(LLFloaterPathfindingConsole *pPathfindingConsole) {mPathfindingConsole = pPathfindingConsole;}
-
-protected:
-	LLRootHandle<LLNavMeshDownloadObserver> mObserverHandle;	
-	LLFloaterPathfindingConsole *mPathfindingConsole;
-};
-//===============================================================================
-class LLNavMeshStation : public LLSingleton<LLNavMeshStation>
-{
-public:
-	//Ctor
-	LLNavMeshStation();
-	//Facilitates the posting of a prepopulated llsd block to an existing url
-	bool postNavMeshToServer( LLSD& data, const LLHandle<LLNavMeshObserver>& observerHandle );
-	//Setter for the navmesh upload url
-	void setNavMeshUploadURL( std::string& url ) { mNavMeshUploadURL = url; }
-	//Setter for the navmesh download url
-	void setNavMeshDownloadURL( std::string& url ) { mNavMeshDownloadURL = url; }
-	//Callback to handle the requested src data for this regions navmesh src
-	static void processNavMeshSrc( LLMessageSystem* msg, void** );
-	//Initiate download of the navmesh source from the server
-	void downloadNavMeshSrc( const LLHandle<LLNavMeshDownloadObserver>& observerHandle, int dir );
-
-protected:	
-	//Curl object to facilitate posts to server
-	LLCurlRequest*	mCurlRequest;
-	//Maximum time in seconds to execute an uploading request.
-	S32				mMeshUploadTimeOut ; 
-	//URL used for uploading viewer generated navmesh
-	std::string		mNavMeshUploadURL;
-	//URL used for download the src data for a navmesh
-	std::string		mNavMeshDownloadURL;
-
-};
-//===============================================================================
-#endif  //LL_NAV_MESH_STATION_H
-
diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp
index 5c9293a28aed79b14441bd3a7a227c3d62d49d58..9a36923bd5f5d5a6f32b07e0e486be8bc3bb656a 100644
--- a/indra/newview/llpathfindingmanager.cpp
+++ b/indra/newview/llpathfindingmanager.cpp
@@ -33,6 +33,7 @@
 #include "llhttpclient.h"
 #include "llagent.h"
 #include "llviewerregion.h"
+#include "llpathfindingnavmesh.h"
 #include "llpathfindinglinkset.h"
 #include "llpathfindinglinksetlist.h"
 
@@ -47,6 +48,27 @@
 #define CAP_SERVICE_OBJECT_LINKSETS   "ObjectNavMeshProperties"
 #define CAP_SERVICE_TERRAIN_LINKSETS  "TerrainNavMeshProperties"
 
+//---------------------------------------------------------------------------
+// NavMeshResponder
+//---------------------------------------------------------------------------
+
+class NavMeshResponder : public LLHTTPClient::Responder
+{
+public:
+	NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr);
+	virtual ~NavMeshResponder();
+
+	virtual void result(const LLSD &pContent);
+	virtual void error(U32 pStatus, const std::string& pReason);
+
+protected:
+
+private:
+	std::string             mCapabilityURL;
+	U32                     mNavMeshVersion;
+	LLPathfindingNavMeshPtr mNavMeshPtr;
+};
+
 //---------------------------------------------------------------------------
 // AgentStateResponder
 //---------------------------------------------------------------------------
@@ -152,6 +174,8 @@ class TerrainLinksetsResponder : public LLHTTPClient::Responder
 
 LLPathfindingManager::LLPathfindingManager()
 	: LLSingleton<LLPathfindingManager>(),
+	mNavMeshMap(),
+	mNavMeshVersionXXX(0),
 	mAgentStateSignal(),
 	mAgentState(kAgentStateUnknown),
 	mLastKnownNonErrorAgentState(kAgentStateUnknown)
@@ -179,7 +203,49 @@ bool LLPathfindingManager::isAllowViewTerrainProperties() const
 	return (gAgent.isGodlike() || ((region != NULL) && region->canManageEstate()));
 }
 
-LLPathfindingManager::agent_state_slot_t LLPathfindingManager::registerAgentStateSignal(agent_state_callback_t pAgentStateCallback)
+LLPathfindingNavMesh::navmesh_slot_t LLPathfindingManager::registerNavMeshListenerForCurrentRegion(LLPathfindingNavMesh::navmesh_callback_t pNavMeshCallback)
+{
+	LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForCurrentRegion();
+	return navMeshPtr->registerNavMeshListener(pNavMeshCallback);
+}
+
+void LLPathfindingManager::requestGetNavMeshForCurrentRegion()
+{
+	LLPathfindingNavMeshPtr navMeshPtr = getNavMeshForCurrentRegion();
+
+	if (navMeshPtr->hasNavMeshVersion(mNavMeshVersionXXX))
+	{
+		navMeshPtr->handleRefresh();
+	}
+	else
+	{
+		LLViewerRegion *region = getCurrentRegion();
+		if (region == NULL)
+		{
+			navMeshPtr->handleNavMeshNotEnabled();
+		}
+		else
+		{
+			std::string navMeshURL = getRetrieveNavMeshURLForCurrentRegion();
+			if (navMeshURL.empty())
+			{
+				navMeshPtr->handleNavMeshNotEnabled();
+			}
+			else
+			{
+				navMeshPtr->handleNavMeshStart(mNavMeshVersionXXX);
+				LLHTTPClient::ResponderPtr responder = new NavMeshResponder(navMeshURL, mNavMeshVersionXXX, navMeshPtr);
+
+				LLSD postData;
+				postData["agent_id"] = gAgent.getID();
+				postData["region_id"] = region->getRegionID();
+				LLHTTPClient::post(navMeshURL, postData, responder);
+			}
+		}
+	}
+}
+
+LLPathfindingManager::agent_state_slot_t LLPathfindingManager::registerAgentStateListener(agent_state_callback_t pAgentStateCallback)
 {
 	return mAgentStateSignal.connect(pAgentStateCallback);
 }
@@ -301,6 +367,31 @@ LLPathfindingManager::ELinksetsRequestStatus LLPathfindingManager::requestSetLin
 	return status;
 }
 
+LLPathfindingNavMeshPtr LLPathfindingManager::getNavMeshForCurrentRegion()
+{
+
+	LLUUID regionUUID;
+	LLViewerRegion *region = getCurrentRegion();
+	if (region != NULL)
+	{
+		regionUUID = region->getRegionID();
+	}
+
+	LLPathfindingNavMeshPtr navMeshPtr;
+	NavMeshMap::iterator navMeshIter = mNavMeshMap.find(regionUUID);
+	if (navMeshIter == mNavMeshMap.end())
+	{
+		navMeshPtr = LLPathfindingNavMeshPtr(new LLPathfindingNavMesh(regionUUID));
+		mNavMeshMap.insert(std::pair<LLUUID, LLPathfindingNavMeshPtr>(regionUUID, navMeshPtr));
+	}
+	else
+	{
+		navMeshPtr = navMeshIter->second;
+	}
+
+	return navMeshPtr;
+}
+
 bool LLPathfindingManager::isValidAgentState(EAgentState pAgentState)
 {
 	return ((pAgentState == kAgentStateFrozen) || (pAgentState == kAgentStateUnfrozen));
@@ -398,6 +489,31 @@ LLViewerRegion *LLPathfindingManager::getCurrentRegion() const
 	return gAgent.getRegion();
 }
 
+//---------------------------------------------------------------------------
+// NavMeshResponder
+//---------------------------------------------------------------------------
+
+NavMeshResponder::NavMeshResponder(const std::string &pCapabilityURL, U32 pNavMeshVersion, LLPathfindingNavMeshPtr pNavMeshPtr)
+	: mCapabilityURL(pCapabilityURL),
+	mNavMeshVersion(pNavMeshVersion),
+	mNavMeshPtr(pNavMeshPtr)
+{
+}
+
+NavMeshResponder::~NavMeshResponder()
+{
+}
+
+void NavMeshResponder::result(const LLSD &pContent)
+{
+	mNavMeshPtr->handleNavMeshResult(pContent, mNavMeshVersion);
+}
+
+void NavMeshResponder::error(U32 pStatus, const std::string& pReason)
+{
+	mNavMeshPtr->handleNavMeshError(pStatus, pReason, mCapabilityURL, mNavMeshVersion);
+}
+
 //---------------------------------------------------------------------------
 // AgentStateResponder
 //---------------------------------------------------------------------------
diff --git a/indra/newview/llpathfindingmanager.h b/indra/newview/llpathfindingmanager.h
index 9a6bbb81b92551594411cc5ce0ee9868b4c25505..f034ddb9ea695b3567bf0f34b3faf79c27fe0a33 100644
--- a/indra/newview/llpathfindingmanager.h
+++ b/indra/newview/llpathfindingmanager.h
@@ -28,15 +28,18 @@
 #ifndef LL_LLPATHFINDINGMANAGER_H
 #define LL_LLPATHFINDINGMANAGER_H
 
+#include "llsingleton.h"
+#include "lluuid.h"
+#include "llpathfindingnavmesh.h"
+#include "llpathfindinglinkset.h"
+#include "llpathfindinglinksetlist.h"
+
 #include <string>
+#include <map>
 
 #include <boost/function.hpp>
 #include <boost/signals2.hpp>
 
-#include "llsingleton.h"
-#include "llpathfindinglinkset.h"
-#include "llpathfindinglinksetlist.h"
-
 class LLFloater;
 class LLViewerRegion;
 
@@ -44,6 +47,8 @@ class LLPathfindingManager : public LLSingleton<LLPathfindingManager>
 {
 	friend class AgentStateResponder;
 public:
+	typedef std::map<LLUUID, LLPathfindingNavMeshPtr> NavMeshMap;
+
 	typedef enum {
 		kAgentStateUnknown,
 		kAgentStateFrozen,
@@ -73,7 +78,10 @@ class LLPathfindingManager : public LLSingleton<LLPathfindingManager>
 	bool isAllowAlterPermanent();
 	bool isAllowViewTerrainProperties() const;
 
-	agent_state_slot_t registerAgentStateSignal(agent_state_callback_t pAgentStateCallback);
+	LLPathfindingNavMesh::navmesh_slot_t registerNavMeshListenerForCurrentRegion(LLPathfindingNavMesh::navmesh_callback_t pNavMeshCallback);
+	void requestGetNavMeshForCurrentRegion();
+
+	agent_state_slot_t registerAgentStateListener(agent_state_callback_t pAgentStateCallback);
 	EAgentState        getAgentState();
 	EAgentState        getLastKnownNonErrorAgentState() const;
 	void               requestSetAgentState(EAgentState pAgentState);
@@ -84,6 +92,8 @@ class LLPathfindingManager : public LLSingleton<LLPathfindingManager>
 protected:
 
 private:
+	LLPathfindingNavMeshPtr getNavMeshForCurrentRegion();
+
 	static bool isValidAgentState(EAgentState pAgentState);
 
 	void requestGetAgentState();
@@ -96,9 +106,12 @@ class LLPathfindingManager : public LLSingleton<LLPathfindingManager>
 	std::string getObjectLinksetsURLForCurrentRegion() const;
 	std::string getTerrainLinksetsURLForCurrentRegion() const;
 
-	std::string getCapabilityURLForCurrentRegion(const std::string &pCapabilityName) const;
+	std::string    getCapabilityURLForCurrentRegion(const std::string &pCapabilityName) const;
 	LLViewerRegion *getCurrentRegion() const;
 
+	NavMeshMap           mNavMeshMap;
+	U32                  mNavMeshVersionXXX; // XXX stinson 03/02/2012 : a hacky way of doing versions for now
+
 	agent_state_signal_t mAgentStateSignal;
 	EAgentState          mAgentState;
 	EAgentState          mLastKnownNonErrorAgentState;
diff --git a/indra/newview/llpathfindingnavmesh.cpp b/indra/newview/llpathfindingnavmesh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fd1a498e3bb51f53b920e85448ee42372818b0fd
--- /dev/null
+++ b/indra/newview/llpathfindingnavmesh.cpp
@@ -0,0 +1,133 @@
+/** 
+ * @file llpathfindingnavmesh.cpp
+ * @author William Todd Stinson
+ * @brief A class for representing the navmesh of a pathfinding region.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "lluuid.h"
+#include "llpathfindingnavmesh.h"
+#include "llsdserialize.h"
+
+#include <string>
+
+//---------------------------------------------------------------------------
+// LLPathfindingNavMesh
+//---------------------------------------------------------------------------
+
+LLPathfindingNavMesh::LLPathfindingNavMesh(const LLUUID &pRegionUUID)
+	: mRegionUUID(pRegionUUID),
+	mNavMeshRequestStatus(kNavMeshRequestUnknown),
+	mNavMeshSignal(),
+	mNavMeshData(),
+	mNavMeshVersion(0U)
+{
+}
+
+LLPathfindingNavMesh::~LLPathfindingNavMesh()
+{
+}
+
+LLPathfindingNavMesh::navmesh_slot_t LLPathfindingNavMesh::registerNavMeshListener(navmesh_callback_t pNavMeshCallback)
+{
+	return mNavMeshSignal.connect(pNavMeshCallback);
+}
+
+bool LLPathfindingNavMesh::hasNavMeshVersion(U32 pNavMeshVersion) const
+{
+	return (((mNavMeshRequestStatus == kNavMeshRequestStarted) || (mNavMeshRequestStatus == kNavMeshRequestCompleted)) && (mNavMeshVersion == pNavMeshVersion));
+}
+
+void LLPathfindingNavMesh::handleRefresh()
+{
+	mNavMeshSignal(mNavMeshRequestStatus, mRegionUUID, mNavMeshVersion, mNavMeshData);
+}
+
+void LLPathfindingNavMesh::handleNavMeshStart(U32 pNavMeshVersion)
+{
+	mNavMeshVersion = pNavMeshVersion;
+	setRequestStatus(kNavMeshRequestStarted);
+}
+
+void LLPathfindingNavMesh::handleNavMeshResult(const LLSD &pContent, U32 pNavMeshVersion)
+{
+	llassert(mNavMeshVersion == pNavMeshVersion);
+	if (mNavMeshVersion == pNavMeshVersion)
+	{
+		if ( pContent.has("navmesh_data") )
+		{
+			const LLSD::Binary &value = pContent["navmesh_data"].asBinary();
+			unsigned int binSize = value.size();
+			std::string newStr(reinterpret_cast<const char *>(&value[0]), binSize);
+			std::istringstream streamdecomp( newStr );                 
+			unsigned int decompBinSize = 0;
+			bool valid = false;
+			U8* pUncompressedNavMeshContainer = unzip_llsdNavMesh( valid, decompBinSize, streamdecomp, binSize ) ;
+			if ( !valid )
+			{
+				llwarns << "Unable to decompress the navmesh llsd." << llendl;
+				setRequestStatus(kNavMeshRequestFormatError);
+			}
+			else
+			{
+				llassert(pUncompressedNavMeshContainer);
+				mNavMeshData.resize( decompBinSize );
+				memcpy( &mNavMeshData[0], &pUncompressedNavMeshContainer[0], decompBinSize );
+				setRequestStatus(kNavMeshRequestCompleted);
+			}					
+			if ( pUncompressedNavMeshContainer )
+			{
+				free( pUncompressedNavMeshContainer );
+			}
+		}
+		else
+		{
+			llwarns << "No mesh data received" << llendl;
+			setRequestStatus(kNavMeshRequestMessageError);
+		}
+	}
+}
+
+void LLPathfindingNavMesh::handleNavMeshNotEnabled()
+{
+	mNavMeshData.clear();
+	setRequestStatus(kNavMeshRequestNotEnabled);
+}
+
+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)
+	{
+		setRequestStatus(kNavMeshRequestMessageError);
+	}
+}
+
+void LLPathfindingNavMesh::setRequestStatus(ENavMeshRequestStatus pNavMeshRequestStatus)
+{
+	mNavMeshRequestStatus = pNavMeshRequestStatus;
+	mNavMeshSignal(mNavMeshRequestStatus, mRegionUUID, mNavMeshVersion, mNavMeshData);
+}
diff --git a/indra/newview/llpathfindingnavmesh.h b/indra/newview/llpathfindingnavmesh.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f033e15c7690ac24d19718fd4d93b46c84d798f
--- /dev/null
+++ b/indra/newview/llpathfindingnavmesh.h
@@ -0,0 +1,86 @@
+/** 
+ * @file llpathfindingnavmesh.h
+ * @author William Todd Stinson
+ * @brief A class for representing the navmesh of a pathfinding region.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc. 
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPATHFINDINGNAVMESH_H
+#define LL_LLPATHFINDINGNAVMESH_H
+
+#include "llsd.h"
+#include "lluuid.h"
+
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <boost/signals2.hpp>
+
+class LLSD;
+class LLPathfindingNavMesh;
+
+typedef boost::shared_ptr<LLPathfindingNavMesh> LLPathfindingNavMeshPtr;
+
+class LLPathfindingNavMesh
+{
+public:
+	typedef enum {
+		kNavMeshRequestUnknown,
+		kNavMeshRequestStarted,
+		kNavMeshRequestCompleted,
+		kNavMeshRequestNotEnabled,
+		kNavMeshRequestMessageError,
+		kNavMeshRequestFormatError
+	} ENavMeshRequestStatus;
+
+	typedef boost::function<void (ENavMeshRequestStatus, const LLUUID &, U32, const LLSD::Binary &)>         navmesh_callback_t;
+	typedef boost::signals2::signal<void (ENavMeshRequestStatus, const LLUUID &, U32, const LLSD::Binary &)> navmesh_signal_t;
+	typedef boost::signals2::connection                                                                      navmesh_slot_t;
+
+	LLPathfindingNavMesh(const LLUUID &pRegionUUID);
+	virtual ~LLPathfindingNavMesh();
+
+	navmesh_slot_t registerNavMeshListener(navmesh_callback_t pNavMeshCallback);
+
+	bool hasNavMeshVersion(U32 pNavMeshVersion) const;
+
+	void handleRefresh();
+	void handleNavMeshStart(U32 pNavMeshVersion);
+	void handleNavMeshResult(const LLSD &pContent, U32 pNavMeshVersion);
+	void handleNavMeshNotEnabled();
+	void handleNavMeshError(U32 pStatus, const std::string &pReason, const std::string &pURL, U32 pNavMeshVersion);
+
+protected:
+
+private:
+	void setRequestStatus(ENavMeshRequestStatus pNavMeshRequestStatus);
+
+	LLUUID                mRegionUUID;
+	ENavMeshRequestStatus mNavMeshRequestStatus;
+	navmesh_signal_t      mNavMeshSignal;
+	LLSD::Binary          mNavMeshData;
+	U32                   mNavMeshVersion;
+};
+
+#endif // LL_LLPATHFINDINGNAVMESH_H
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 b608e513d585eba29079ad399783388610f26b22..557708330353d82aa548ec91ea7e371b28d25f42 100644
--- a/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml
+++ b/indra/newview/skins/default/xui/en/floater_pathfinding_console.xml
@@ -11,12 +11,14 @@
     single_instance="true"
     title="Pathfinding edit / test"
     width="456">
-  <floater.string name="navmesh_fetch_initial"></floater.string>
-  <floater.string name="navmesh_fetch_inprogress">Downloading the navmesh ...</floater.string>
-  <floater.string name="navmesh_fetch_complete_available">Navmesh received.</floater.string>
-  <floater.string name="navmesh_fetch_complete_none">No navmesh for region.</floater.string>
-  <floater.string name="navmesh_region_not_enabled">This region is not enabled for pathfinding.</floater.string>
-  <floater.string name="navmesh_library_not_implemented">Cannot find pathing library implementation.</floater.string>
+  <floater.string name="navmesh_status_unknown"></floater.string>
+  <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_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_download_error">Unable to download navmesh successfully.</floater.string>
+  <floater.string name="navmesh_status_navmesh_error">Unable to understand data format of the navmesh.</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>
   <floater.string name="pathing_choose_end_point">Please choose end point.</floater.string>