PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/newview/llfloaterworldmap.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1633 lines | 1198 code | 256 blank | 179 comment | 178 complexity | e8e1b56ac84f22ef749ebb130834c462 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llfloaterworldmap.cpp
  3. * @author James Cook, Tom Yedwab
  4. * @brief LLFloaterWorldMap class implementation
  5. *
  6. * $LicenseInfo:firstyear=2003&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. */
  27. /*
  28. * Map of the entire world, with multiple background images,
  29. * avatar tracking, teleportation by double-click, etc.
  30. */
  31. #include "llviewerprecompiledheaders.h"
  32. #include "llfloaterworldmap.h"
  33. #include "llagent.h"
  34. #include "llagentcamera.h"
  35. #include "llbutton.h"
  36. #include "llcallingcard.h"
  37. #include "llcombobox.h"
  38. #include "llviewercontrol.h"
  39. #include "llcommandhandler.h"
  40. #include "lldraghandle.h"
  41. //#include "llfirstuse.h"
  42. #include "llfloaterreg.h" // getTypedInstance()
  43. #include "llfocusmgr.h"
  44. #include "llinventoryfunctions.h"
  45. #include "llinventorymodel.h"
  46. #include "llinventorymodelbackgroundfetch.h"
  47. #include "llinventoryobserver.h"
  48. #include "lllandmarklist.h"
  49. #include "llsearcheditor.h"
  50. #include "llnotificationsutil.h"
  51. #include "llregionhandle.h"
  52. #include "llscrolllistctrl.h"
  53. #include "llslurl.h"
  54. #include "lltextbox.h"
  55. #include "lltracker.h"
  56. #include "lltrans.h"
  57. #include "llviewerinventory.h" // LLViewerInventoryItem
  58. #include "llviewermenu.h"
  59. #include "llviewerregion.h"
  60. #include "llviewerstats.h"
  61. #include "llviewertexture.h"
  62. #include "llworldmap.h"
  63. #include "llworldmapmessage.h"
  64. #include "llworldmapview.h"
  65. #include "lluictrlfactory.h"
  66. #include "llappviewer.h"
  67. #include "llmapimagetype.h"
  68. #include "llweb.h"
  69. #include "llsliderctrl.h"
  70. #include "message.h"
  71. #include "llwindow.h" // copyTextToClipboard()
  72. #include <algorithm>
  73. //---------------------------------------------------------------------------
  74. // Constants
  75. //---------------------------------------------------------------------------
  76. static const F32 MAP_ZOOM_TIME = 0.2f;
  77. // Merov: we switched from using the "world size" (which varies depending where the user went) to a fixed
  78. // width of 512 regions max visible at a time. This makes the zoom slider works in a consistent way across
  79. // sessions and doesn't prevent the user to pan the world if it was to grow a lot beyond that limit.
  80. // Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window.
  81. static const S32 MAX_VISIBLE_REGIONS = 512;
  82. // It would be more logical to have this inside the method where it is used but to compile under gcc this
  83. // struct has to be here.
  84. struct SortRegionNames
  85. {
  86. inline bool operator ()(std::pair <U64, LLSimInfo*> const& _left, std::pair <U64, LLSimInfo*> const& _right)
  87. {
  88. return(LLStringUtil::compareInsensitive(_left.second->getName(), _right.second->getName()) < 0);
  89. }
  90. };
  91. enum EPanDirection
  92. {
  93. PAN_UP,
  94. PAN_DOWN,
  95. PAN_LEFT,
  96. PAN_RIGHT
  97. };
  98. // Values in pixels per region
  99. static const F32 ZOOM_MAX = 128.f;
  100. //---------------------------------------------------------------------------
  101. // Globals
  102. //---------------------------------------------------------------------------
  103. // handle secondlife:///app/worldmap/{NAME}/{COORDS} URLs
  104. class LLWorldMapHandler : public LLCommandHandler
  105. {
  106. public:
  107. // requires trusted browser to trigger
  108. LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE ) { }
  109. bool handle(const LLSD& params, const LLSD& query_map,
  110. LLMediaCtrl* web)
  111. {
  112. if (!LLUI::sSettingGroups["config"]->getBOOL("EnableWorldMap"))
  113. {
  114. LLNotificationsUtil::add("NoWorldMap", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
  115. return true;
  116. }
  117. if (params.size() == 0)
  118. {
  119. // support the secondlife:///app/worldmap SLapp
  120. LLFloaterReg::showInstance("world_map", "center");
  121. return true;
  122. }
  123. // support the secondlife:///app/worldmap/{LOCATION}/{COORDS} SLapp
  124. const std::string region_name = LLURI::unescape(params[0].asString());
  125. S32 x = (params.size() > 1) ? params[1].asInteger() : 128;
  126. S32 y = (params.size() > 2) ? params[2].asInteger() : 128;
  127. S32 z = (params.size() > 3) ? params[3].asInteger() : 0;
  128. LLFloaterWorldMap::getInstance()->trackURL(region_name, x, y, z);
  129. LLFloaterReg::showInstance("world_map", "center");
  130. return true;
  131. }
  132. };
  133. LLWorldMapHandler gWorldMapHandler;
  134. // SocialMap handler secondlife:///app/maptrackavatar/id
  135. class LLMapTrackAvatarHandler : public LLCommandHandler
  136. {
  137. public:
  138. // requires trusted browser to trigger
  139. LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_THROTTLE)
  140. {
  141. }
  142. bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
  143. {
  144. if (!LLUI::sSettingGroups["config"]->getBOOL("EnableWorldMap"))
  145. {
  146. LLNotificationsUtil::add("NoWorldMap", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
  147. return true;
  148. }
  149. //Make sure we have some parameters
  150. if (params.size() == 0)
  151. {
  152. return false;
  153. }
  154. //Get the ID
  155. LLUUID id;
  156. if (!id.set( params[0], FALSE ))
  157. {
  158. return false;
  159. }
  160. LLFloaterWorldMap::getInstance()->avatarTrackFromSlapp( id );
  161. LLFloaterReg::showInstance( "world_map", "center" );
  162. return true;
  163. }
  164. };
  165. LLMapTrackAvatarHandler gMapTrackAvatar;
  166. LLFloaterWorldMap* gFloaterWorldMap = NULL;
  167. class LLMapInventoryObserver : public LLInventoryObserver
  168. {
  169. public:
  170. LLMapInventoryObserver() {}
  171. virtual ~LLMapInventoryObserver() {}
  172. virtual void changed(U32 mask);
  173. };
  174. void LLMapInventoryObserver::changed(U32 mask)
  175. {
  176. // if there's a change we're interested in.
  177. if((mask & (LLInventoryObserver::CALLING_CARD | LLInventoryObserver::ADD |
  178. LLInventoryObserver::REMOVE)) != 0)
  179. {
  180. gFloaterWorldMap->inventoryChanged();
  181. }
  182. }
  183. class LLMapFriendObserver : public LLFriendObserver
  184. {
  185. public:
  186. LLMapFriendObserver() {}
  187. virtual ~LLMapFriendObserver() {}
  188. virtual void changed(U32 mask);
  189. };
  190. void LLMapFriendObserver::changed(U32 mask)
  191. {
  192. // if there's a change we're interested in.
  193. if((mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE | LLFriendObserver::POWERS)) != 0)
  194. {
  195. gFloaterWorldMap->friendsChanged();
  196. }
  197. }
  198. //---------------------------------------------------------------------------
  199. // Statics
  200. //---------------------------------------------------------------------------
  201. // Used as a pretend asset and inventory id to mean "landmark at my home location."
  202. const LLUUID LLFloaterWorldMap::sHomeID( "10000000-0000-0000-0000-000000000001" );
  203. //---------------------------------------------------------------------------
  204. // Construction and destruction
  205. //---------------------------------------------------------------------------
  206. LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key)
  207. : LLFloater(key),
  208. mInventory(NULL),
  209. mInventoryObserver(NULL),
  210. mFriendObserver(NULL),
  211. mCompletingRegionName(),
  212. mCompletingRegionPos(),
  213. mWaitingForTracker(FALSE),
  214. mIsClosing(FALSE),
  215. mSetToUserPosition(TRUE),
  216. mTrackedLocation(0,0,0),
  217. mTrackedStatus(LLTracker::TRACKING_NOTHING),
  218. mListFriendCombo(NULL),
  219. mListLandmarkCombo(NULL),
  220. mListSearchResults(NULL)
  221. {
  222. gFloaterWorldMap = this;
  223. mFactoryMap["objects_mapview"] = LLCallbackMap(createWorldMapView, NULL);
  224. mCommitCallbackRegistrar.add("WMap.Coordinates", boost::bind(&LLFloaterWorldMap::onCoordinatesCommit, this));
  225. mCommitCallbackRegistrar.add("WMap.Location", boost::bind(&LLFloaterWorldMap::onLocationCommit, this));
  226. mCommitCallbackRegistrar.add("WMap.AvatarCombo", boost::bind(&LLFloaterWorldMap::onAvatarComboCommit, this));
  227. mCommitCallbackRegistrar.add("WMap.Landmark", boost::bind(&LLFloaterWorldMap::onLandmarkComboCommit, this));
  228. mCommitCallbackRegistrar.add("WMap.SearchResult", boost::bind(&LLFloaterWorldMap::onCommitSearchResult, this));
  229. mCommitCallbackRegistrar.add("WMap.GoHome", boost::bind(&LLFloaterWorldMap::onGoHome, this));
  230. mCommitCallbackRegistrar.add("WMap.Teleport", boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this));
  231. mCommitCallbackRegistrar.add("WMap.ShowTarget", boost::bind(&LLFloaterWorldMap::onShowTargetBtn, this));
  232. mCommitCallbackRegistrar.add("WMap.ShowAgent", boost::bind(&LLFloaterWorldMap::onShowAgentBtn, this));
  233. mCommitCallbackRegistrar.add("WMap.Clear", boost::bind(&LLFloaterWorldMap::onClearBtn, this));
  234. mCommitCallbackRegistrar.add("WMap.CopySLURL", boost::bind(&LLFloaterWorldMap::onCopySLURL, this));
  235. gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLFloaterWorldMap::onChangeMaturity, this));
  236. }
  237. // static
  238. void* LLFloaterWorldMap::createWorldMapView(void* data)
  239. {
  240. return new LLWorldMapView();
  241. }
  242. BOOL LLFloaterWorldMap::postBuild()
  243. {
  244. mPanel = getChild<LLPanel>("objects_mapview");
  245. LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo");
  246. avatar_combo->selectFirstItem();
  247. avatar_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onAvatarComboPrearrange, this) );
  248. avatar_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
  249. mListFriendCombo = dynamic_cast<LLCtrlListInterface *>(avatar_combo);
  250. LLSearchEditor *location_editor = getChild<LLSearchEditor>("location");
  251. location_editor->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1));
  252. location_editor->setKeystrokeCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this));
  253. getChild<LLScrollListCtrl>("search_results")->setDoubleClickCallback( boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this));
  254. mListSearchResults = childGetListInterface("search_results");
  255. LLComboBox *landmark_combo = getChild<LLComboBox>( "landmark combo");
  256. landmark_combo->selectFirstItem();
  257. landmark_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onLandmarkComboPrearrange, this) );
  258. landmark_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
  259. mListLandmarkCombo = dynamic_cast<LLCtrlListInterface *>(landmark_combo);
  260. mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f);
  261. getChild<LLUICtrl>("zoom slider")->setValue(LLWorldMapView::sMapScale);
  262. setDefaultBtn(NULL);
  263. mZoomTimer.stop();
  264. onChangeMaturity();
  265. return TRUE;
  266. }
  267. // virtual
  268. LLFloaterWorldMap::~LLFloaterWorldMap()
  269. {
  270. // All cleaned up by LLView destructor
  271. mPanel = NULL;
  272. // Inventory deletes all observers on shutdown
  273. mInventory = NULL;
  274. mInventoryObserver = NULL;
  275. // avatar tracker will delete this for us.
  276. mFriendObserver = NULL;
  277. gFloaterWorldMap = NULL;
  278. }
  279. //static
  280. LLFloaterWorldMap* LLFloaterWorldMap::getInstance()
  281. {
  282. return LLFloaterReg::getTypedInstance<LLFloaterWorldMap>("world_map");
  283. }
  284. // virtual
  285. void LLFloaterWorldMap::onClose(bool app_quitting)
  286. {
  287. // While we're not visible, discard the overlay images we're using
  288. LLWorldMap::getInstance()->clearImageRefs();
  289. }
  290. // virtual
  291. void LLFloaterWorldMap::onOpen(const LLSD& key)
  292. {
  293. bool center_on_target = (key.asString() == "center");
  294. mIsClosing = FALSE;
  295. LLWorldMapView* map_panel;
  296. map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel;
  297. map_panel->clearLastClick();
  298. {
  299. // reset pan on show, so it centers on you again
  300. if (!center_on_target)
  301. {
  302. LLWorldMapView::setPan(0, 0, TRUE);
  303. }
  304. map_panel->updateVisibleBlocks();
  305. // Reload items as they may have changed
  306. LLWorldMap::getInstance()->reloadItems();
  307. // We may already have a bounding box for the regions of the world,
  308. // so use that to adjust the view.
  309. adjustZoomSliderBounds();
  310. // Could be first show
  311. //LLFirstUse::useMap();
  312. // Start speculative download of landmarks
  313. const LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
  314. LLInventoryModelBackgroundFetch::instance().start(landmark_folder_id);
  315. getChild<LLUICtrl>("location")->setFocus( TRUE);
  316. gFocusMgr.triggerFocusFlash();
  317. buildAvatarIDList();
  318. buildLandmarkIDLists();
  319. // If nothing is being tracked, set flag so the user position will be found
  320. mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
  321. }
  322. if (center_on_target)
  323. {
  324. centerOnTarget(FALSE);
  325. }
  326. }
  327. // static
  328. void LLFloaterWorldMap::reloadIcons(void*)
  329. {
  330. LLWorldMap::getInstance()->reloadItems();
  331. }
  332. // virtual
  333. BOOL LLFloaterWorldMap::handleHover(S32 x, S32 y, MASK mask)
  334. {
  335. BOOL handled;
  336. handled = LLFloater::handleHover(x, y, mask);
  337. return handled;
  338. }
  339. BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks)
  340. {
  341. if (!isMinimized() && isFrontmost())
  342. {
  343. if(mPanel->pointInView(x, y))
  344. {
  345. F32 slider_value = (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal();
  346. slider_value += ((F32)clicks * -0.3333f);
  347. getChild<LLUICtrl>("zoom slider")->setValue(LLSD(slider_value));
  348. return TRUE;
  349. }
  350. }
  351. return LLFloater::handleScrollWheel(x, y, clicks);
  352. }
  353. // virtual
  354. void LLFloaterWorldMap::reshape( S32 width, S32 height, BOOL called_from_parent )
  355. {
  356. LLFloater::reshape( width, height, called_from_parent );
  357. }
  358. // virtual
  359. void LLFloaterWorldMap::draw()
  360. {
  361. static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white);
  362. static LLUIColor map_track_disabled_color = LLUIColorTable::instance().getColor("MapTrackDisabledColor", LLColor4::white);
  363. // On orientation island, users don't have a home location yet, so don't
  364. // let them teleport "home". It dumps them in an often-crowed welcome
  365. // area (infohub) and they get confused. JC
  366. LLViewerRegion* regionp = gAgent.getRegion();
  367. bool agent_on_prelude = (regionp && regionp->isPrelude());
  368. bool enable_go_home = gAgent.isGodlike() || !agent_on_prelude;
  369. getChildView("Go Home")->setEnabled(enable_go_home);
  370. updateLocation();
  371. LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
  372. if (LLTracker::TRACKING_AVATAR == tracking_status)
  373. {
  374. getChild<LLUICtrl>("avatar_icon")->setColor( map_track_color);
  375. }
  376. else
  377. {
  378. getChild<LLUICtrl>("avatar_icon")->setColor( map_track_disabled_color);
  379. }
  380. if (LLTracker::TRACKING_LANDMARK == tracking_status)
  381. {
  382. getChild<LLUICtrl>("landmark_icon")->setColor( map_track_color);
  383. }
  384. else
  385. {
  386. getChild<LLUICtrl>("landmark_icon")->setColor( map_track_disabled_color);
  387. }
  388. if (LLTracker::TRACKING_LOCATION == tracking_status)
  389. {
  390. getChild<LLUICtrl>("location_icon")->setColor( map_track_color);
  391. }
  392. else
  393. {
  394. if (mCompletingRegionName != "")
  395. {
  396. F64 seconds = LLTimer::getElapsedSeconds();
  397. double value = fmod(seconds, 2);
  398. value = 0.5 + 0.5*cos(value * F_PI);
  399. LLColor4 loading_color(0.0, F32(value/2), F32(value), 1.0);
  400. getChild<LLUICtrl>("location_icon")->setColor( loading_color);
  401. }
  402. else
  403. {
  404. getChild<LLUICtrl>("location_icon")->setColor( map_track_disabled_color);
  405. }
  406. }
  407. // check for completion of tracking data
  408. if (mWaitingForTracker)
  409. {
  410. centerOnTarget(TRUE);
  411. }
  412. getChildView("Teleport")->setEnabled((BOOL)tracking_status);
  413. // getChildView("Clear")->setEnabled((BOOL)tracking_status);
  414. getChildView("Show Destination")->setEnabled((BOOL)tracking_status || LLWorldMap::getInstance()->isTracking());
  415. getChildView("copy_slurl")->setEnabled((mSLURL.isValid()) );
  416. setMouseOpaque(TRUE);
  417. getDragHandle()->setMouseOpaque(TRUE);
  418. //RN: snaps to zoom value because interpolation caused jitter in the text rendering
  419. if (!mZoomTimer.getStarted() && mCurZoomVal != (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal())
  420. {
  421. mZoomTimer.start();
  422. }
  423. F32 interp = mZoomTimer.getElapsedTimeF32() / MAP_ZOOM_TIME;
  424. if (interp > 1.f)
  425. {
  426. interp = 1.f;
  427. mZoomTimer.stop();
  428. }
  429. mCurZoomVal = lerp(mCurZoomVal, (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal(), interp);
  430. F32 map_scale = 256.f*pow(2.f, mCurZoomVal);
  431. LLWorldMapView::setScale( map_scale );
  432. // Enable/disable checkboxes depending on the zoom level
  433. // If above threshold level (i.e. low res) -> Disable all checkboxes
  434. // If under threshold level (i.e. high res) -> Enable all checkboxes
  435. bool enable = LLWorldMapView::showRegionInfo();
  436. getChildView("people_chk")->setEnabled(enable);
  437. getChildView("infohub_chk")->setEnabled(enable);
  438. getChildView("telehub_chk")->setEnabled(enable);
  439. getChildView("land_for_sale_chk")->setEnabled(enable);
  440. getChildView("event_chk")->setEnabled(enable);
  441. getChildView("events_mature_chk")->setEnabled(enable);
  442. getChildView("events_adult_chk")->setEnabled(enable);
  443. LLFloater::draw();
  444. }
  445. //-------------------------------------------------------------------------
  446. // Internal utility functions
  447. //-------------------------------------------------------------------------
  448. void LLFloaterWorldMap::trackAvatar( const LLUUID& avatar_id, const std::string& name )
  449. {
  450. LLCtrlSelectionInterface *iface = childGetSelectionInterface("friend combo");
  451. if (!iface) return;
  452. buildAvatarIDList();
  453. if(iface->setCurrentByID(avatar_id) || gAgent.isGodlike())
  454. {
  455. // *HACK: Adjust Z values automatically for liaisons & gods so
  456. // they swoop down when they click on the map. Requested
  457. // convenience.
  458. if(gAgent.isGodlike())
  459. {
  460. getChild<LLUICtrl>("spin z")->setValue(LLSD(200.f));
  461. }
  462. // Don't re-request info if we already have it or we won't have it in time to teleport
  463. if (mTrackedStatus != LLTracker::TRACKING_AVATAR || name != mTrackedAvatarName)
  464. {
  465. mTrackedStatus = LLTracker::TRACKING_AVATAR;
  466. mTrackedAvatarName = name;
  467. LLTracker::trackAvatar(avatar_id, name);
  468. }
  469. }
  470. else
  471. {
  472. LLTracker::stopTracking(NULL);
  473. }
  474. setDefaultBtn("Teleport");
  475. }
  476. void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id )
  477. {
  478. LLCtrlSelectionInterface *iface = childGetSelectionInterface("landmark combo");
  479. if (!iface) return;
  480. buildLandmarkIDLists();
  481. BOOL found = FALSE;
  482. S32 idx;
  483. for (idx = 0; idx < mLandmarkItemIDList.count(); idx++)
  484. {
  485. if ( mLandmarkItemIDList.get(idx) == landmark_item_id)
  486. {
  487. found = TRUE;
  488. break;
  489. }
  490. }
  491. if (found && iface->setCurrentByID( landmark_item_id ) )
  492. {
  493. LLUUID asset_id = mLandmarkAssetIDList.get( idx );
  494. std::string name;
  495. LLComboBox* combo = getChild<LLComboBox>( "landmark combo");
  496. if (combo) name = combo->getSimple();
  497. mTrackedStatus = LLTracker::TRACKING_LANDMARK;
  498. LLTracker::trackLandmark(mLandmarkAssetIDList.get( idx ), // assetID
  499. mLandmarkItemIDList.get( idx ), // itemID
  500. name); // name
  501. if( asset_id != sHomeID )
  502. {
  503. // start the download process
  504. gLandmarkList.getAsset( asset_id);
  505. }
  506. // We have to download both region info and landmark data, so set busy. JC
  507. // getWindow()->incBusyCount();
  508. }
  509. else
  510. {
  511. LLTracker::stopTracking(NULL);
  512. }
  513. setDefaultBtn("Teleport");
  514. }
  515. void LLFloaterWorldMap::trackEvent(const LLItemInfo &event_info)
  516. {
  517. mTrackedStatus = LLTracker::TRACKING_LOCATION;
  518. LLTracker::trackLocation(event_info.getGlobalPosition(), event_info.getName(), event_info.getToolTip(), LLTracker::LOCATION_EVENT);
  519. setDefaultBtn("Teleport");
  520. }
  521. void LLFloaterWorldMap::trackGenericItem(const LLItemInfo &item)
  522. {
  523. mTrackedStatus = LLTracker::TRACKING_LOCATION;
  524. LLTracker::trackLocation(item.getGlobalPosition(), item.getName(), item.getToolTip(), LLTracker::LOCATION_ITEM);
  525. setDefaultBtn("Teleport");
  526. }
  527. void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
  528. {
  529. LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromPosGlobal(pos_global);
  530. if (!sim_info)
  531. {
  532. // We haven't found a region for that point yet, leave the tracking to the world map
  533. LLWorldMap::getInstance()->setTracking(pos_global);
  534. LLTracker::stopTracking(NULL);
  535. S32 world_x = S32(pos_global.mdV[0] / 256);
  536. S32 world_y = S32(pos_global.mdV[1] / 256);
  537. LLWorldMapMessage::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true);
  538. setDefaultBtn("");
  539. // clicked on a non-region - turn off coord display
  540. enableTeleportCoordsDisplay( false );
  541. return;
  542. }
  543. if (sim_info->isDown())
  544. {
  545. // Down region. Show the blue circle of death!
  546. // i.e. let the world map that this and tell it it's invalid
  547. LLWorldMap::getInstance()->setTracking(pos_global);
  548. LLWorldMap::getInstance()->setTrackingInvalid();
  549. LLTracker::stopTracking(NULL);
  550. setDefaultBtn("");
  551. // clicked on a down region - turn off coord display
  552. enableTeleportCoordsDisplay( false );
  553. return;
  554. }
  555. std::string sim_name = sim_info->getName();
  556. F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS );
  557. F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS );
  558. std::string full_name = llformat("%s (%d, %d, %d)",
  559. sim_name.c_str(),
  560. llround(region_x),
  561. llround(region_y),
  562. llround((F32)pos_global.mdV[VZ]));
  563. std::string tooltip("");
  564. mTrackedStatus = LLTracker::TRACKING_LOCATION;
  565. LLTracker::trackLocation(pos_global, full_name, tooltip);
  566. LLWorldMap::getInstance()->cancelTracking(); // The floater is taking over the tracking
  567. LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal();
  568. updateTeleportCoordsDisplay( coord_pos );
  569. // we have a valid region - turn on coord display
  570. enableTeleportCoordsDisplay( true );
  571. setDefaultBtn("Teleport");
  572. }
  573. // enable/disable teleport destination coordinates
  574. void LLFloaterWorldMap::enableTeleportCoordsDisplay( bool enabled )
  575. {
  576. childSetEnabled("teleport_coordinate_x", enabled );
  577. childSetEnabled("teleport_coordinate_y", enabled );
  578. childSetEnabled("teleport_coordinate_z", enabled );
  579. }
  580. // update display of teleport destination coordinates - pos is in global coordinates
  581. void LLFloaterWorldMap::updateTeleportCoordsDisplay( const LLVector3d& pos )
  582. {
  583. // if we're going to update their value, we should also enable them
  584. enableTeleportCoordsDisplay( true );
  585. // convert global specified position to a local one
  586. F32 region_local_x = (F32)fmod( pos.mdV[VX], (F64)REGION_WIDTH_METERS );
  587. F32 region_local_y = (F32)fmod( pos.mdV[VY], (F64)REGION_WIDTH_METERS );
  588. F32 region_local_z = (F32)llclamp( pos.mdV[VZ], 0.0, (F64)REGION_HEIGHT_METERS );
  589. // write in the values
  590. childSetValue("teleport_coordinate_x", region_local_x );
  591. childSetValue("teleport_coordinate_y", region_local_y );
  592. childSetValue("teleport_coordinate_z", region_local_z );
  593. }
  594. void LLFloaterWorldMap::updateLocation()
  595. {
  596. bool gotSimName;
  597. LLTracker::ETrackingStatus status = LLTracker::getTrackingStatus();
  598. // These values may get updated by a message, so need to check them every frame
  599. // The fields may be changed by the user, so only update them if the data changes
  600. LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
  601. if (pos_global.isExactlyZero())
  602. {
  603. LLVector3d agentPos = gAgent.getPositionGlobal();
  604. // Set to avatar's current postion if nothing is selected
  605. if ( status == LLTracker::TRACKING_NOTHING && mSetToUserPosition )
  606. {
  607. // Make sure we know where we are before setting the current user position
  608. std::string agent_sim_name;
  609. gotSimName = LLWorldMap::getInstance()->simNameFromPosGlobal( agentPos, agent_sim_name );
  610. if ( gotSimName )
  611. {
  612. mSetToUserPosition = FALSE;
  613. // Fill out the location field
  614. getChild<LLUICtrl>("location")->setValue(agent_sim_name);
  615. // update the coordinate display with location of avatar in region
  616. updateTeleportCoordsDisplay( agentPos );
  617. // Figure out where user is
  618. // Set the current SLURL
  619. mSLURL = LLSLURL(agent_sim_name, gAgent.getPositionGlobal());
  620. }
  621. }
  622. return; // invalid location
  623. }
  624. std::string sim_name;
  625. gotSimName = LLWorldMap::getInstance()->simNameFromPosGlobal( pos_global, sim_name );
  626. if ((status != LLTracker::TRACKING_NOTHING) &&
  627. (status != mTrackedStatus || pos_global != mTrackedLocation || sim_name != mTrackedSimName))
  628. {
  629. mTrackedStatus = status;
  630. mTrackedLocation = pos_global;
  631. mTrackedSimName = sim_name;
  632. if (status == LLTracker::TRACKING_AVATAR)
  633. {
  634. // *HACK: Adjust Z values automatically for liaisons &
  635. // gods so they swoop down when they click on the
  636. // map. Requested convenience.
  637. if(gAgent.isGodlike())
  638. {
  639. pos_global[2] = 200;
  640. }
  641. }
  642. getChild<LLUICtrl>("location")->setValue(sim_name);
  643. // refresh coordinate display to reflect where user clicked.
  644. LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal();
  645. updateTeleportCoordsDisplay( coord_pos );
  646. // simNameFromPosGlobal can fail, so don't give the user an invalid SLURL
  647. if ( gotSimName )
  648. {
  649. mSLURL = LLSLURL(sim_name, pos_global);
  650. }
  651. else
  652. { // Empty SLURL will disable the "Copy SLURL to clipboard" button
  653. mSLURL = LLSLURL();
  654. }
  655. }
  656. }
  657. void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S32 y_coord, S32 z_coord)
  658. {
  659. LLSimInfo* sim_info = LLWorldMap::getInstance()->simInfoFromName(region_name);
  660. z_coord = llclamp(z_coord, 0, 4096);
  661. if (sim_info)
  662. {
  663. LLVector3 local_pos;
  664. local_pos.mV[VX] = (F32)x_coord;
  665. local_pos.mV[VY] = (F32)y_coord;
  666. local_pos.mV[VZ] = (F32)z_coord;
  667. LLVector3d global_pos = sim_info->getGlobalPos(local_pos);
  668. trackLocation(global_pos);
  669. setDefaultBtn("Teleport");
  670. }
  671. else
  672. {
  673. // fill in UI based on URL
  674. gFloaterWorldMap->getChild<LLUICtrl>("location")->setValue(region_name);
  675. // Save local coords to highlight position after region global
  676. // position is returned.
  677. gFloaterWorldMap->mCompletingRegionPos.set(
  678. (F32)x_coord, (F32)y_coord, (F32)z_coord);
  679. // pass sim name to combo box
  680. gFloaterWorldMap->mCompletingRegionName = region_name;
  681. LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name);
  682. LLStringUtil::toLower(gFloaterWorldMap->mCompletingRegionName);
  683. LLWorldMap::getInstance()->setTrackingCommit();
  684. }
  685. }
  686. void LLFloaterWorldMap::observeInventory(LLInventoryModel* model)
  687. {
  688. if(mInventory)
  689. {
  690. mInventory->removeObserver(mInventoryObserver);
  691. delete mInventoryObserver;
  692. mInventory = NULL;
  693. mInventoryObserver = NULL;
  694. }
  695. if(model)
  696. {
  697. mInventory = model;
  698. mInventoryObserver = new LLMapInventoryObserver;
  699. // Inventory deletes all observers on shutdown
  700. mInventory->addObserver(mInventoryObserver);
  701. inventoryChanged();
  702. }
  703. }
  704. void LLFloaterWorldMap::inventoryChanged()
  705. {
  706. if(!LLTracker::getTrackedLandmarkItemID().isNull())
  707. {
  708. LLUUID item_id = LLTracker::getTrackedLandmarkItemID();
  709. buildLandmarkIDLists();
  710. trackLandmark(item_id);
  711. }
  712. }
  713. void LLFloaterWorldMap::observeFriends()
  714. {
  715. if(!mFriendObserver)
  716. {
  717. mFriendObserver = new LLMapFriendObserver;
  718. LLAvatarTracker::instance().addObserver(mFriendObserver);
  719. friendsChanged();
  720. }
  721. }
  722. void LLFloaterWorldMap::friendsChanged()
  723. {
  724. LLAvatarTracker& t = LLAvatarTracker::instance();
  725. const LLUUID& avatar_id = t.getAvatarID();
  726. buildAvatarIDList();
  727. if(avatar_id.notNull())
  728. {
  729. LLCtrlSelectionInterface *iface = childGetSelectionInterface("friend combo");
  730. const LLRelationship* buddy_info = t.getBuddyInfo(avatar_id);
  731. if(!iface ||
  732. !iface->setCurrentByID(avatar_id) ||
  733. (buddy_info && !buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)) ||
  734. gAgent.isGodlike())
  735. {
  736. LLTracker::stopTracking(NULL);
  737. }
  738. }
  739. }
  740. // No longer really builds a list. Instead, just updates mAvatarCombo.
  741. void LLFloaterWorldMap::buildAvatarIDList()
  742. {
  743. LLCtrlListInterface *list = mListFriendCombo;
  744. if (!list) return;
  745. // Delete all but the "None" entry
  746. S32 list_size = list->getItemCount();
  747. if (list_size > 1)
  748. {
  749. list->selectItemRange(1, -1);
  750. list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
  751. }
  752. // Get all of the calling cards for avatar that are currently online
  753. LLCollectMappableBuddies collector;
  754. LLAvatarTracker::instance().applyFunctor(collector);
  755. LLCollectMappableBuddies::buddy_map_t::iterator it;
  756. LLCollectMappableBuddies::buddy_map_t::iterator end;
  757. it = collector.mMappable.begin();
  758. end = collector.mMappable.end();
  759. for( ; it != end; ++it)
  760. {
  761. list->addSimpleElement((*it).first, ADD_BOTTOM, (*it).second);
  762. }
  763. list->setCurrentByID( LLAvatarTracker::instance().getAvatarID() );
  764. list->selectFirstItem();
  765. }
  766. void LLFloaterWorldMap::buildLandmarkIDLists()
  767. {
  768. LLCtrlListInterface *list = mListLandmarkCombo;
  769. if (!list) return;
  770. // Delete all but the "None" entry
  771. S32 list_size = list->getItemCount();
  772. if (list_size > 1)
  773. {
  774. list->selectItemRange(1, -1);
  775. list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
  776. }
  777. mLandmarkItemIDList.reset();
  778. mLandmarkAssetIDList.reset();
  779. // Get all of the current landmarks
  780. mLandmarkAssetIDList.put( LLUUID::null );
  781. mLandmarkItemIDList.put( LLUUID::null );
  782. mLandmarkAssetIDList.put( sHomeID );
  783. mLandmarkItemIDList.put( sHomeID );
  784. LLInventoryModel::cat_array_t cats;
  785. LLInventoryModel::item_array_t items;
  786. LLIsType is_landmark(LLAssetType::AT_LANDMARK);
  787. gInventory.collectDescendentsIf(gInventory.getRootFolderID(),
  788. cats,
  789. items,
  790. LLInventoryModel::EXCLUDE_TRASH,
  791. is_landmark);
  792. std::sort(items.begin(), items.end(), LLViewerInventoryItem::comparePointers());
  793. S32 count = items.count();
  794. for(S32 i = 0; i < count; ++i)
  795. {
  796. LLInventoryItem* item = items.get(i);
  797. list->addSimpleElement(item->getName(), ADD_BOTTOM, item->getUUID());
  798. mLandmarkAssetIDList.put( item->getAssetUUID() );
  799. mLandmarkItemIDList.put( item->getUUID() );
  800. }
  801. list->selectFirstItem();
  802. }
  803. F32 LLFloaterWorldMap::getDistanceToDestination(const LLVector3d &destination,
  804. F32 z_attenuation) const
  805. {
  806. LLVector3d delta = destination - gAgent.getPositionGlobal();
  807. // by attenuating the z-component we effectively
  808. // give more weight to the x-y plane
  809. delta.mdV[VZ] *= z_attenuation;
  810. F32 distance = (F32)delta.magVec();
  811. return distance;
  812. }
  813. void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui)
  814. {
  815. LLCtrlListInterface *list = mListSearchResults;
  816. if (list)
  817. {
  818. list->operateOnAll(LLCtrlListInterface::OP_DELETE);
  819. }
  820. LLWorldMap::getInstance()->cancelTracking();
  821. mCompletingRegionName = "";
  822. }
  823. void LLFloaterWorldMap::clearLandmarkSelection(BOOL clear_ui)
  824. {
  825. if (clear_ui || !childHasKeyboardFocus("landmark combo"))
  826. {
  827. LLCtrlListInterface *list = mListLandmarkCombo;
  828. if (list)
  829. {
  830. list->selectByValue( "None" );
  831. }
  832. }
  833. }
  834. void LLFloaterWorldMap::clearAvatarSelection(BOOL clear_ui)
  835. {
  836. if (clear_ui || !childHasKeyboardFocus("friend combo"))
  837. {
  838. mTrackedStatus = LLTracker::TRACKING_NOTHING;
  839. LLCtrlListInterface *list = mListFriendCombo;
  840. if (list)
  841. {
  842. list->selectByValue( "None" );
  843. }
  844. }
  845. }
  846. // Adjust the maximally zoomed out limit of the zoom slider so you
  847. // can see the whole world, plus a little.
  848. void LLFloaterWorldMap::adjustZoomSliderBounds()
  849. {
  850. // Merov: we switched from using the "world size" (which varies depending where the user went) to a fixed
  851. // width of 512 regions max visible at a time. This makes the zoom slider works in a consistent way across
  852. // sessions and doesn't prevent the user to pan the world if it was to grow a lot beyond that limit.
  853. // Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window.
  854. S32 world_width_regions = MAX_VISIBLE_REGIONS;
  855. S32 world_height_regions = MAX_VISIBLE_REGIONS;
  856. // Find how much space we have to display the world
  857. LLWorldMapView* map_panel;
  858. map_panel = (LLWorldMapView*)mPanel;
  859. LLRect view_rect = map_panel->getRect();
  860. // View size in pixels
  861. S32 view_width = view_rect.getWidth();
  862. S32 view_height = view_rect.getHeight();
  863. // Pixels per region to display entire width/height
  864. F32 width_pixels_per_region = (F32) view_width / (F32) world_width_regions;
  865. F32 height_pixels_per_region = (F32) view_height / (F32) world_height_regions;
  866. F32 pixels_per_region = llmin(width_pixels_per_region,
  867. height_pixels_per_region);
  868. // Round pixels per region to an even number of slider increments
  869. S32 slider_units = llfloor(pixels_per_region / 0.2f);
  870. pixels_per_region = slider_units * 0.2f;
  871. // Make sure the zoom slider can be moved at least a little bit.
  872. // Likewise, less than the increment pixels per region is just silly.
  873. pixels_per_region = llclamp(pixels_per_region, 1.f, ZOOM_MAX);
  874. F32 min_power = log(pixels_per_region/256.f)/log(2.f);
  875. getChild<LLSliderCtrl>("zoom slider")->setMinValue(min_power);
  876. }
  877. //-------------------------------------------------------------------------
  878. // User interface widget callbacks
  879. //-------------------------------------------------------------------------
  880. void LLFloaterWorldMap::onGoHome()
  881. {
  882. gAgent.teleportHome();
  883. closeFloater();
  884. }
  885. void LLFloaterWorldMap::onLandmarkComboPrearrange( )
  886. {
  887. if( mIsClosing )
  888. {
  889. return;
  890. }
  891. LLCtrlListInterface *list = mListLandmarkCombo;
  892. if (!list) return;
  893. LLUUID current_choice = list->getCurrentID();
  894. buildLandmarkIDLists();
  895. if( current_choice.isNull() || !list->setCurrentByID( current_choice ) )
  896. {
  897. LLTracker::stopTracking(NULL);
  898. }
  899. }
  900. void LLFloaterWorldMap::onComboTextEntry()
  901. {
  902. // Reset the tracking whenever we start typing into any of the search fields,
  903. // so that hitting <enter> does an auto-complete versus teleporting us to the
  904. // previously selected landmark/friend.
  905. LLTracker::stopTracking(NULL);
  906. }
  907. void LLFloaterWorldMap::onSearchTextEntry( )
  908. {
  909. onComboTextEntry();
  910. updateSearchEnabled();
  911. }
  912. void LLFloaterWorldMap::onLandmarkComboCommit()
  913. {
  914. if( mIsClosing )
  915. {
  916. return;
  917. }
  918. LLCtrlListInterface *list = mListLandmarkCombo;
  919. if (!list) return;
  920. LLUUID asset_id;
  921. LLUUID item_id = list->getCurrentID();
  922. LLTracker::stopTracking(NULL);
  923. //RN: stopTracking() clears current combobox selection, need to reassert it here
  924. list->setCurrentByID(item_id);
  925. if( item_id.isNull() )
  926. {
  927. }
  928. else if( item_id == sHomeID )
  929. {
  930. asset_id = sHomeID;
  931. }
  932. else
  933. {
  934. LLInventoryItem* item = gInventory.getItem( item_id );
  935. if( item )
  936. {
  937. asset_id = item->getAssetUUID();
  938. }
  939. else
  940. {
  941. // Something went wrong, so revert to a safe value.
  942. item_id.setNull();
  943. }
  944. }
  945. trackLandmark( item_id);
  946. onShowTargetBtn();
  947. // Reset to user postion if nothing is tracked
  948. mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
  949. }
  950. // static
  951. void LLFloaterWorldMap::onAvatarComboPrearrange( )
  952. {
  953. if( mIsClosing )
  954. {
  955. return;
  956. }
  957. LLCtrlListInterface *list = mListFriendCombo;
  958. if (!list) return;
  959. LLUUID current_choice;
  960. if( LLAvatarTracker::instance().haveTrackingInfo() )
  961. {
  962. current_choice = LLAvatarTracker::instance().getAvatarID();
  963. }
  964. buildAvatarIDList();
  965. if( !list->setCurrentByID( current_choice ) || current_choice.isNull() )
  966. {
  967. LLTracker::stopTracking(NULL);
  968. }
  969. }
  970. void LLFloaterWorldMap::onAvatarComboCommit()
  971. {
  972. if( mIsClosing )
  973. {
  974. return;
  975. }
  976. LLCtrlListInterface *list = mListFriendCombo;
  977. if (!list) return;
  978. const LLUUID& new_avatar_id = list->getCurrentID();
  979. if (new_avatar_id.notNull())
  980. {
  981. std::string name;
  982. LLComboBox* combo = getChild<LLComboBox>("friend combo");
  983. if (combo) name = combo->getSimple();
  984. trackAvatar(new_avatar_id, name);
  985. onShowTargetBtn();
  986. }
  987. else
  988. { // Reset to user postion if nothing is tracked
  989. mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
  990. }
  991. }
  992. void LLFloaterWorldMap::avatarTrackFromSlapp( const LLUUID& id )
  993. {
  994. trackAvatar( id, "av" );
  995. onShowTargetBtn();
  996. }
  997. void LLFloaterWorldMap::onLocationFocusChanged( LLFocusableElement* focus )
  998. {
  999. updateSearchEnabled();
  1000. }
  1001. void LLFloaterWorldMap::updateSearchEnabled()
  1002. {
  1003. if (childHasKeyboardFocus("location") &&
  1004. getChild<LLUICtrl>("location")->getValue().asString().length() > 0)
  1005. {
  1006. setDefaultBtn("DoSearch");
  1007. }
  1008. else
  1009. {
  1010. setDefaultBtn(NULL);
  1011. }
  1012. }
  1013. void LLFloaterWorldMap::onLocationCommit()
  1014. {
  1015. if( mIsClosing )
  1016. {
  1017. return;
  1018. }
  1019. clearLocationSelection(FALSE);
  1020. mCompletingRegionName = "";
  1021. mLastRegionName = "";
  1022. std::string str = getChild<LLUICtrl>("location")->getValue().asString();
  1023. // Trim any leading and trailing spaces in the search target
  1024. std::string saved_str = str;
  1025. LLStringUtil::trim( str );
  1026. if ( str != saved_str )
  1027. { // Set the value in the UI if any spaces were removed
  1028. getChild<LLUICtrl>("location")->setValue(str);
  1029. }
  1030. // Don't try completing empty name (STORM-1427).
  1031. if (str.empty())
  1032. {
  1033. return;
  1034. }
  1035. LLStringUtil::toLower(str);
  1036. mCompletingRegionName = str;
  1037. LLWorldMap::getInstance()->setTrackingCommit();
  1038. if (str.length() >= 3)
  1039. {
  1040. LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str);
  1041. }
  1042. else
  1043. {
  1044. str += "#";
  1045. LLWorldMapMessage::getInstance()->sendNamedRegionRequest(str);
  1046. }
  1047. }
  1048. void LLFloaterWorldMap::onCoordinatesCommit()
  1049. {
  1050. if( mIsClosing )
  1051. {
  1052. return;
  1053. }
  1054. S32 x_coord = (S32)childGetValue("teleport_coordinate_x").asReal();
  1055. S32 y_coord = (S32)childGetValue("teleport_coordinate_y").asReal();
  1056. S32 z_coord = (S32)childGetValue("teleport_coordinate_z").asReal();
  1057. const std::string region_name = childGetValue("location").asString();
  1058. trackURL( region_name, x_coord, y_coord, z_coord );
  1059. }
  1060. void LLFloaterWorldMap::onClearBtn()
  1061. {
  1062. mTrackedStatus = LLTracker::TRACKING_NOTHING;
  1063. LLTracker::stopTracking((void *)(intptr_t)TRUE);
  1064. LLWorldMap::getInstance()->cancelTracking();
  1065. mSLURL = LLSLURL(); // Clear the SLURL since it's invalid
  1066. mSetToUserPosition = TRUE; // Revert back to the current user position
  1067. }
  1068. void LLFloaterWorldMap::onShowTargetBtn()
  1069. {
  1070. centerOnTarget(TRUE);
  1071. }
  1072. void LLFloaterWorldMap::onShowAgentBtn()
  1073. {
  1074. LLWorldMapView::setPan( 0, 0, FALSE); // FALSE == animate
  1075. // Set flag so user's location will be displayed if not tracking anything else
  1076. mSetToUserPosition = TRUE;
  1077. }
  1078. void LLFloaterWorldMap::onClickTeleportBtn()
  1079. {
  1080. teleport();
  1081. }
  1082. void LLFloaterWorldMap::onCopySLURL()
  1083. {
  1084. getWindow()->copyTextToClipboard(utf8str_to_wstring(mSLURL.getSLURLString()));
  1085. LLSD args;
  1086. args["SLURL"] = mSLURL.getSLURLString();
  1087. LLNotificationsUtil::add("CopySLURL", args);
  1088. }
  1089. // protected
  1090. void LLFloaterWorldMap::centerOnTarget(BOOL animate)
  1091. {
  1092. LLVector3d pos_global;
  1093. if(LLTracker::getTrackingStatus() != LLTracker::TRACKING_NOTHING)
  1094. {
  1095. LLVector3d tracked_position = LLTracker::getTrackedPositionGlobal();
  1096. //RN: tracker doesn't allow us to query completion, so we check for a tracking position of
  1097. // absolute zero, and keep trying in the draw loop
  1098. if (tracked_position.isExactlyZero())
  1099. {
  1100. mWaitingForTracker = TRUE;
  1101. return;
  1102. }
  1103. else
  1104. {
  1105. // We've got the position finally, so we're no longer busy. JC
  1106. // getWindow()->decBusyCount();
  1107. pos_global = LLTracker::getTrackedPositionGlobal() - gAgentCamera.getCameraPositionGlobal();
  1108. }
  1109. }
  1110. else if(LLWorldMap::getInstance()->isTracking())
  1111. {
  1112. pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal() - gAgentCamera.getCameraPositionGlobal();;
  1113. }
  1114. else
  1115. {
  1116. // default behavior = center on agent
  1117. pos_global.clearVec();
  1118. }
  1119. LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)),
  1120. -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)),
  1121. !animate);
  1122. mWaitingForTracker = FALSE;
  1123. }
  1124. // protected
  1125. void LLFloaterWorldMap::fly()
  1126. {
  1127. LLVector3d pos_global = LLTracker::getTrackedPositionGlobal();
  1128. // Start the autopilot and close the floater,
  1129. // so we can see where we're flying
  1130. if (!pos_global.isExactlyZero())
  1131. {
  1132. gAgent.startAutoPilotGlobal( pos_global );
  1133. closeFloater();
  1134. }
  1135. else
  1136. {
  1137. make_ui_sound("UISndInvalidOp");
  1138. }
  1139. }
  1140. // protected
  1141. void LLFloaterWorldMap::teleport()
  1142. {
  1143. BOOL teleport_home = FALSE;
  1144. LLVector3d pos_global;
  1145. LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
  1146. LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus();
  1147. if (LLTracker::TRACKING_AVATAR == tracking_status
  1148. && av_tracker.haveTrackingInfo() )
  1149. {
  1150. pos_global = av_tracker.getGlobalPos();
  1151. pos_global.mdV[VZ] = getChild<LLUICtrl>("spin z")->getValue();
  1152. }
  1153. else if ( LLTracker::TRACKING_LANDMARK == tracking_status)
  1154. {
  1155. if( LLTracker::getTrackedLandmarkAssetID() == sHomeID )
  1156. {
  1157. teleport_home = TRUE;
  1158. }
  1159. else
  1160. {
  1161. LLLandmark* landmark = gLandmarkList.getAsset( LLTracker::getTrackedLandmarkAssetID() );
  1162. LLUUID region_id;
  1163. if(landmark
  1164. && !landmark->getGlobalPos(pos_global)
  1165. && landmark->getRegionID(region_id))
  1166. {
  1167. LLLandmark::requestRegionHandle(
  1168. gMessageSystem,
  1169. gAgent.getRegionHost(),
  1170. region_id,
  1171. NULL);
  1172. }
  1173. }
  1174. }
  1175. else if ( LLTracker::TRACKING_LOCATION == tracking_status)
  1176. {
  1177. pos_global = LLTracker::getTrackedPositionGlobal();
  1178. }
  1179. else
  1180. {
  1181. make_ui_sound("UISndInvalidOp");
  1182. }
  1183. // Do the teleport, which will also close the floater
  1184. if (teleport_home)
  1185. {
  1186. gAgent.teleportHome();
  1187. }
  1188. else if (!pos_global.isExactlyZero())
  1189. {
  1190. if(LLTracker::TRACKING_LANDMARK == tracking_status)
  1191. {
  1192. gAgent.teleportViaLandmark(LLTracker::getTrackedLandmarkAssetID());
  1193. }
  1194. else
  1195. {
  1196. gAgent.teleportViaLocation( pos_global );
  1197. }
  1198. }
  1199. }
  1200. void LLFloaterWorldMap::flyToLandmark()
  1201. {
  1202. LLVector3d destination_pos_global;
  1203. if( !LLTracker::getTrackedLandmarkAssetID().isNull() )
  1204. {
  1205. if (LLTracker::hasLandmarkPosition())
  1206. {
  1207. gAgent.startAutoPilotGlobal( LLTracker::getTrackedPositionGlobal() );
  1208. }
  1209. }
  1210. }
  1211. void LLFloaterWorldMap::teleportToLandmark()
  1212. {
  1213. BOOL has_destination = FALSE;
  1214. LLUUID destination_id; // Null means "home"
  1215. if( LLTracker::getTrackedLandmarkAssetID() == sHomeID )
  1216. {
  1217. has_destination = TRUE;
  1218. }
  1219. else
  1220. {
  1221. LLLandmark* landmark = gLandmarkList.getAsset( LLTracker::getTrackedLandmarkAssetID() );
  1222. LLVector3d global_pos;
  1223. if(landmark && landmark->getGlobalPos(global_pos))
  1224. {
  1225. destination_id = LLTracker::getTrackedLandmarkAssetID();
  1226. has_destination = TRUE;
  1227. }
  1228. else if(landmark)
  1229. {
  1230. // pop up an anonymous request request.
  1231. LLUUID region_id;
  1232. if(landmark->getRegionID(region_id))
  1233. {
  1234. LLLandmark::requestRegionHandle(
  1235. gMessageSystem,
  1236. gAgent.getRegionHost(),
  1237. region_id,
  1238. NULL);
  1239. }
  1240. }
  1241. }
  1242. if( has_destination )
  1243. {
  1244. gAgent.teleportViaLandmark( destination_id );
  1245. }
  1246. }
  1247. void LLFloaterWorldMap::teleportToAvatar()
  1248. {
  1249. LLAvatarTracker& av_tracker = LLAvatarTracker::instance();
  1250. if(av_tracker.haveTrackingInfo())
  1251. {
  1252. LLVector3d pos_global = av_tracker.getGlobalPos();
  1253. gAgent.teleportViaLocation( pos_global );
  1254. }
  1255. }
  1256. void LLFloaterWorldMap::flyToAvatar()
  1257. {
  1258. if( LLAvatarTracker::instance().haveTrackingInfo() )
  1259. {
  1260. gAgent.startAutoPilotGlobal( LLAvatarTracker::instance().getGlobalPos() );
  1261. }
  1262. }
  1263. void LLFloaterWorldMap::updateSims(bool found_null_sim)
  1264. {
  1265. if (mCompletingRegionName == "")
  1266. {
  1267. return;
  1268. }
  1269. LLScrollListCtrl *list = getChild<LLScrollListCtrl>("search_results");
  1270. list->operateOnAll(LLCtrlListInterface::OP_DELETE);
  1271. S32 name_length = mCompletingRegionName.length();
  1272. LLSD match;
  1273. S32 num_results = 0;
  1274. std::vector<std::pair <U64, LLSimInfo*> > sim_info_vec(LLWorldMap::getInstance()->getRegionMap().begin(), LLWorldMap::getInstance()->getRegionMap().end());
  1275. std::sort(sim_info_vec.begin(), sim_info_vec.end(), SortRegionNames());
  1276. for (std::vector<std::pair <U64, LLSimInfo*> >::const_iterator it = sim_info_vec.begin(); it != sim_info_vec.end(); ++it)
  1277. {
  1278. LLSimInfo* info = it->second;
  1279. std::string sim_name_lower = info->getName();
  1280. LLStringUtil::toLower(sim_name_lower);
  1281. if (sim_name_lower.substr(0, name_length) == mCompletingRegionName)
  1282. {
  1283. if (sim_name_lower == mCompletingRegionName)
  1284. {
  1285. match = info->getName();
  1286. }
  1287. LLSD value;
  1288. value["id"] = info->getName();
  1289. value["columns"][0]["column"] = "sim_name";
  1290. value["columns"][0]["value"] = info->getName();
  1291. list->addElement(value);
  1292. num_results++;
  1293. }
  1294. }
  1295. if (found_null_sim)
  1296. {
  1297. mCompletingRegionName = "";
  1298. }
  1299. if (num_results > 0)
  1300. {
  1301. // if match found, highlight it and go
  1302. if (!match.isUndefined())
  1303. {
  1304. list->selectByValue(match);
  1305. }
  1306. // else select first found item
  1307. else
  1308. {
  1309. list->selectFirstItem();
  1310. }
  1311. getChild<LLUICtrl>("search_results")->setFocus(TRUE);
  1312. onCommitSearchResult();
  1313. }
  1314. else
  1315. {
  1316. // if we found nothing, say "none"
  1317. list->setCommentText(LLTrans::getString("worldmap_results_none_found"));
  1318. list->operateOnAll(LLCtrlListInterface::OP_DESELECT);
  1319. }
  1320. }
  1321. void LLFloaterWorldMap::onCommitSearchResult()
  1322. {
  1323. LLCtrlListInterface *list = mListSearchResults;
  1324. if (!list) return;
  1325. LLSD selected_value = list->getSelectedValue();
  1326. std::string sim_name = selected_value.asString();
  1327. if (sim_name.empty())
  1328. {
  1329. return;
  1330. }
  1331. LLStringUtil::toLower(sim_name);
  1332. std::map<U64, LLSimInfo*>::const_iterator it;
  1333. for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it)
  1334. {
  1335. LLSimInfo* info = it->second;
  1336. if (info->isName(sim_name))
  1337. {
  1338. LLVector3d pos_global = info->getGlobalOrigin();
  1339. const F64 SIM_COORD_DEFAULT = 128.0;
  1340. LLVector3 pos_local(SIM_COORD_DEFAULT, SIM_COORD_DEFAULT, 0.0f);
  1341. // Did this value come from a trackURL() request?
  1342. if (!mCompletingRegionPos.isExactlyZero())
  1343. {
  1344. pos_local = mCompletingRegionPos;
  1345. mCompletingRegionPos.clear();
  1346. }
  1347. pos_global.mdV[VX] += (F64)pos_local.mV[VX];
  1348. pos_global.mdV[VY] += (F64)pos_local.mV[VY];
  1349. pos_global.mdV[VZ] = (F64)pos_local.mV[VZ];
  1350. getChild<LLUICtrl>("location")->setValue(sim_name);
  1351. trackLocation(pos_global);
  1352. setDefaultBtn("Teleport");
  1353. break;
  1354. }
  1355. }
  1356. onShowTargetBtn();
  1357. }
  1358. void LLFloaterWorldMap::onChangeMaturity()
  1359. {
  1360. bool can_access_mature = gAgent.canAccessMature();
  1361. bool can_access_adult = gAgent.canAccessAdult();
  1362. getChildView("events_mature_icon")->setVisible( can_access_mature);
  1363. getChildView("events_mature_label")->setVisible( can_access_mature);
  1364. getChildView("events_mature_chk")->setVisible( can_access_mature);
  1365. getChildView("events_adult_icon")->setVisible( can_access_adult);
  1366. getChildView("events_adult_label")->setVisible( can_access_adult);
  1367. getChildView("events_adult_chk")->setVisible( can_access_adult);
  1368. // disable mature / adult events.
  1369. if (!can_access_mature)
  1370. {
  1371. gSavedSettings.setBOOL("ShowMatureEvents", FALSE);
  1372. }
  1373. if (!can_access_adult)
  1374. {
  1375. gSavedSettings.setBOOL("ShowAdultEvents", FALSE);
  1376. }
  1377. }