llpanelplaces.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:31k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /**
  2.  * @file llpanelplaces.cpp
  3.  * @brief Side Bar "Places" panel
  4.  *
  5.  * $LicenseInfo:firstyear=2009&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2009-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llpanelplaces.h"
  34. #include "llassettype.h"
  35. #include "lltimer.h"
  36. #include "llinventory.h"
  37. #include "lllandmark.h"
  38. #include "llparcel.h"
  39. #include "llcombobox.h"
  40. #include "llfiltereditor.h"
  41. #include "llfloaterreg.h"
  42. #include "llnotificationsutil.h"
  43. #include "lltabcontainer.h"
  44. #include "lltexteditor.h"
  45. #include "lltrans.h"
  46. #include "lluictrlfactory.h"
  47. #include "llwindow.h"
  48. #include "llagent.h"
  49. #include "llagentpicksinfo.h"
  50. #include "llavatarpropertiesprocessor.h"
  51. #include "llfloaterworldmap.h"
  52. #include "llinventorybridge.h"
  53. #include "llinventoryobserver.h"
  54. #include "llinventorymodel.h"
  55. #include "lllandmarkactions.h"
  56. #include "lllandmarklist.h"
  57. #include "llpanellandmarkinfo.h"
  58. #include "llpanellandmarks.h"
  59. #include "llpanelpick.h"
  60. #include "llpanelplaceprofile.h"
  61. #include "llpanelteleporthistory.h"
  62. #include "llremoteparcelrequest.h"
  63. #include "llteleporthistorystorage.h"
  64. #include "lltoggleablemenu.h"
  65. #include "llviewerinventory.h"
  66. #include "llviewermenu.h"
  67. #include "llviewermessage.h"
  68. #include "llviewerparcelmgr.h"
  69. #include "llviewerregion.h"
  70. #include "llviewerwindow.h"
  71. static const S32 LANDMARK_FOLDERS_MENU_WIDTH = 250;
  72. static const F32 PLACE_INFO_UPDATE_INTERVAL = 3.0;
  73. static const std::string AGENT_INFO_TYPE = "agent";
  74. static const std::string CREATE_LANDMARK_INFO_TYPE = "create_landmark";
  75. static const std::string LANDMARK_INFO_TYPE = "landmark";
  76. static const std::string REMOTE_PLACE_INFO_TYPE = "remote_place";
  77. static const std::string TELEPORT_HISTORY_INFO_TYPE = "teleport_history";
  78. // Helper functions
  79. static bool is_agent_in_selected_parcel(LLParcel* parcel);
  80. static void onSLURLBuilt(std::string& slurl);
  81. //Observer classes
  82. class LLPlacesParcelObserver : public LLParcelObserver
  83. {
  84. public:
  85. LLPlacesParcelObserver(LLPanelPlaces* places_panel) :
  86. LLParcelObserver(),
  87. mPlaces(places_panel)
  88. {}
  89. /*virtual*/ void changed()
  90. {
  91. if (mPlaces)
  92. mPlaces->changedParcelSelection();
  93. }
  94. private:
  95. LLPanelPlaces* mPlaces;
  96. };
  97. class LLPlacesInventoryObserver : public LLInventoryAddedObserver
  98. {
  99. public:
  100. LLPlacesInventoryObserver(LLPanelPlaces* places_panel) :
  101. mPlaces(places_panel),
  102. mTabsCreated(false)
  103. {}
  104. /*virtual*/ void changed(U32 mask)
  105. {
  106. LLInventoryAddedObserver::changed(mask);
  107. if (!mTabsCreated && mPlaces)
  108. {
  109. mPlaces->createTabs();
  110. mTabsCreated = true;
  111. }
  112. }
  113. protected:
  114. /*virtual*/ void done()
  115. {
  116. mPlaces->showAddedLandmarkInfo(mAdded);
  117. mAdded.clear();
  118. }
  119. private:
  120. LLPanelPlaces* mPlaces;
  121. bool mTabsCreated;
  122. };
  123. class LLPlacesRemoteParcelInfoObserver : public LLRemoteParcelInfoObserver
  124. {
  125. public:
  126. LLPlacesRemoteParcelInfoObserver(LLPanelPlaces* places_panel) :
  127. LLRemoteParcelInfoObserver(),
  128. mPlaces(places_panel)
  129. {}
  130. ~LLPlacesRemoteParcelInfoObserver()
  131. {
  132. // remove any in-flight observers
  133. std::set<LLUUID>::iterator it;
  134. for (it = mParcelIDs.begin(); it != mParcelIDs.end(); ++it)
  135. {
  136. const LLUUID &id = *it;
  137. LLRemoteParcelInfoProcessor::getInstance()->removeObserver(id, this);
  138. }
  139. mParcelIDs.clear();
  140. }
  141. /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data)
  142. {
  143. if (mPlaces)
  144. {
  145. mPlaces->changedGlobalPos(LLVector3d(parcel_data.global_x,
  146.  parcel_data.global_y,
  147.  parcel_data.global_z));
  148. }
  149. mParcelIDs.erase(parcel_data.parcel_id);
  150. LLRemoteParcelInfoProcessor::getInstance()->removeObserver(parcel_data.parcel_id, this);
  151. }
  152. /*virtual*/ void setParcelID(const LLUUID& parcel_id)
  153. {
  154. if (!parcel_id.isNull())
  155. {
  156. mParcelIDs.insert(parcel_id);
  157. LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
  158. LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
  159. }
  160. }
  161. /*virtual*/ void setErrorStatus(U32 status, const std::string& reason)
  162. {
  163. llerrs << "Can't complete remote parcel request. Http Status: "
  164.    << status << ". Reason : " << reason << llendl;
  165. }
  166. private:
  167. std::set<LLUUID> mParcelIDs;
  168. LLPanelPlaces* mPlaces;
  169. };
  170. static LLRegisterPanelClassWrapper<LLPanelPlaces> t_places("panel_places");
  171. LLPanelPlaces::LLPanelPlaces()
  172. : LLPanel(),
  173. mActivePanel(NULL),
  174. mFilterEditor(NULL),
  175. mPlaceProfile(NULL),
  176. mLandmarkInfo(NULL),
  177. mPickPanel(NULL),
  178. mItem(NULL),
  179. mPlaceMenu(NULL),
  180. mLandmarkMenu(NULL),
  181. mPosGlobal(),
  182. isLandmarkEditModeOn(false)
  183. {
  184. mParcelObserver = new LLPlacesParcelObserver(this);
  185. mInventoryObserver = new LLPlacesInventoryObserver(this);
  186. mRemoteParcelObserver = new LLPlacesRemoteParcelInfoObserver(this);
  187. gInventory.addObserver(mInventoryObserver);
  188. LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(
  189. boost::bind(&LLPanelPlaces::updateVerbs, this));
  190. //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_places.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
  191. }
  192. LLPanelPlaces::~LLPanelPlaces()
  193. {
  194. if (gInventory.containsObserver(mInventoryObserver))
  195. gInventory.removeObserver(mInventoryObserver);
  196. LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
  197. delete mInventoryObserver;
  198. delete mParcelObserver;
  199. delete mRemoteParcelObserver;
  200. }
  201. BOOL LLPanelPlaces::postBuild()
  202. {
  203. mTeleportBtn = getChild<LLButton>("teleport_btn");
  204. mTeleportBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onTeleportButtonClicked, this));
  205. mShowOnMapBtn = getChild<LLButton>("map_btn");
  206. mShowOnMapBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShowOnMapButtonClicked, this));
  207. mEditBtn = getChild<LLButton>("edit_btn");
  208. mEditBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
  209. mSaveBtn = getChild<LLButton>("save_btn");
  210. mSaveBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onSaveButtonClicked, this));
  211. mCancelBtn = getChild<LLButton>("cancel_btn");
  212. mCancelBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onCancelButtonClicked, this));
  213. mCloseBtn = getChild<LLButton>("close_btn");
  214. mCloseBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
  215. mOverflowBtn = getChild<LLButton>("overflow_btn");
  216. mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this));
  217. LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
  218. registrar.add("Places.OverflowMenu.Action",  boost::bind(&LLPanelPlaces::onOverflowMenuItemClicked, this, _2));
  219. LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
  220. enable_registrar.add("Places.OverflowMenu.Enable",  boost::bind(&LLPanelPlaces::onOverflowMenuItemEnable, this, _2));
  221. mPlaceMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_place.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  222. if (!mPlaceMenu)
  223. {
  224. llwarns << "Error loading Place menu" << llendl;
  225. }
  226. mLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
  227. if (!mLandmarkMenu)
  228. {
  229. llwarns << "Error loading Landmark menu" << llendl;
  230. }
  231. mTabContainer = getChild<LLTabContainer>("Places Tabs");
  232. if (mTabContainer)
  233. {
  234. mTabContainer->setCommitCallback(boost::bind(&LLPanelPlaces::onTabSelected, this));
  235. }
  236. mFilterEditor = getChild<LLFilterEditor>("Filter");
  237. if (mFilterEditor)
  238. {
  239. mFilterEditor->setCommitCallback(boost::bind(&LLPanelPlaces::onFilterEdit, this, _2, false));
  240. }
  241. mPlaceProfile = getChild<LLPanelPlaceProfile>("panel_place_profile");
  242. mLandmarkInfo = getChild<LLPanelLandmarkInfo>("panel_landmark_info");
  243. if (!mPlaceProfile || !mLandmarkInfo)
  244. return FALSE;
  245. mPlaceProfileBackBtn = mPlaceProfile->getChild<LLButton>("back_btn");
  246. mPlaceProfileBackBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
  247. mLandmarkInfoBackBtn = mLandmarkInfo->getChild<LLButton>("back_btn");
  248. mLandmarkInfoBackBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
  249. LLLineEditor* title_editor = mLandmarkInfo->getChild<LLLineEditor>("title_editor");
  250. title_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this), NULL);
  251. LLTextEditor* notes_editor = mLandmarkInfo->getChild<LLTextEditor>("notes_editor");
  252. notes_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
  253. LLComboBox* folder_combo = mLandmarkInfo->getChild<LLComboBox>("folder_combo");
  254. folder_combo->setCommitCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
  255. return TRUE;
  256. }
  257. void LLPanelPlaces::onOpen(const LLSD& key)
  258. {
  259. if (!mPlaceProfile || !mLandmarkInfo)
  260. return;
  261. if (key.size() != 0)
  262. {
  263. mFilterEditor->clear();
  264. onFilterEdit("", false);
  265. mPlaceInfoType = key["type"].asString();
  266. mPosGlobal.setZero();
  267. mItem = NULL;
  268. isLandmarkEditModeOn = false;
  269. togglePlaceInfoPanel(TRUE);
  270. if (mPlaceInfoType == AGENT_INFO_TYPE)
  271. {
  272. mPlaceProfile->setInfoType(LLPanelPlaceInfo::AGENT);
  273. }
  274. else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
  275. {
  276. mLandmarkInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
  277. if (key.has("x") && key.has("y") && key.has("z"))
  278. {
  279. mPosGlobal = LLVector3d(key["x"].asReal(),
  280. key["y"].asReal(),
  281. key["z"].asReal());
  282. }
  283. else
  284. {
  285. mPosGlobal = gAgent.getPositionGlobal();
  286. }
  287. mLandmarkInfo->displayParcelInfo(LLUUID(), mPosGlobal);
  288. // Disabling "Save", "Close" and "Back" buttons to prevent closing "Create Landmark"
  289. // panel before created landmark is loaded.
  290. // These buttons will be enabled when created landmark is added to inventory.
  291. mSaveBtn->setEnabled(FALSE);
  292. mCloseBtn->setEnabled(FALSE);
  293. mLandmarkInfoBackBtn->setEnabled(FALSE);
  294. }
  295. else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
  296. {
  297. mLandmarkInfo->setInfoType(LLPanelPlaceInfo::LANDMARK);
  298. LLInventoryItem* item = gInventory.getItem(key["id"].asUUID());
  299. if (!item)
  300. return;
  301. setItem(item);
  302. }
  303. else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
  304. {
  305. if (key.has("id"))
  306. {
  307. LLUUID parcel_id = key["id"].asUUID();
  308. mPlaceProfile->setParcelID(parcel_id);
  309. // query the server to get the global 3D position of this
  310. // parcel - we need this for teleport/mapping functions.
  311. mRemoteParcelObserver->setParcelID(parcel_id);
  312. }
  313. else
  314. {
  315. mPosGlobal = LLVector3d(key["x"].asReal(),
  316. key["y"].asReal(),
  317. key["z"].asReal());
  318. mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
  319. }
  320. mPlaceProfile->setInfoType(LLPanelPlaceInfo::PLACE);
  321. }
  322. else if (mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
  323. {
  324. S32 index = key["id"].asInteger();
  325. const LLTeleportHistoryStorage::slurl_list_t& hist_items =
  326. LLTeleportHistoryStorage::getInstance()->getItems();
  327. mPosGlobal = hist_items[index].mGlobalPos;
  328. mPlaceProfile->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY);
  329. mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
  330. }
  331. updateVerbs();
  332. }
  333. LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
  334. if (!parcel_mgr)
  335. return;
  336. // Start using LLViewerParcelMgr for land selection if
  337. // information about nearby land is requested.
  338. // Otherwise stop using land selection and deselect land.
  339. if (mPlaceInfoType == AGENT_INFO_TYPE)
  340. {
  341. // We don't know if we are already added to LLViewerParcelMgr observers list
  342. // so try to remove observer not to add an extra one.
  343. parcel_mgr->removeObserver(mParcelObserver);
  344. parcel_mgr->addObserver(mParcelObserver);
  345. parcel_mgr->selectParcelAt(gAgent.getPositionGlobal());
  346. }
  347. else
  348. {
  349. parcel_mgr->removeObserver(mParcelObserver);
  350. // Clear the reference to selection to allow its removal in deselectUnused().
  351. mParcel.clear();
  352. if (!parcel_mgr->selectionEmpty())
  353. {
  354. parcel_mgr->deselectUnused();
  355. }
  356. }
  357. }
  358. void LLPanelPlaces::setItem(LLInventoryItem* item)
  359. {
  360. if (!mLandmarkInfo || !item)
  361. return;
  362. mItem = item;
  363. LLAssetType::EType item_type = mItem->getActualType();
  364. if (item_type == LLAssetType::AT_LANDMARK || item_type == LLAssetType::AT_LINK)
  365. {
  366. // If the item is a link get a linked item
  367. if (item_type == LLAssetType::AT_LINK)
  368. {
  369. mItem = gInventory.getItem(mItem->getLinkedUUID());
  370. if (mItem.isNull())
  371. return;
  372. }
  373. }
  374. else
  375. {
  376. return;
  377. }
  378. // Check if item is in agent's inventory and he has the permission to modify it.
  379. BOOL is_landmark_editable = gInventory.isObjectDescendentOf(mItem->getUUID(), gInventory.getRootFolderID()) &&
  380. mItem->getPermissions().allowModifyBy(gAgent.getID());
  381. mEditBtn->setEnabled(is_landmark_editable);
  382. mSaveBtn->setEnabled(is_landmark_editable);
  383. mCloseBtn->setEnabled(TRUE);
  384. mLandmarkInfoBackBtn->setEnabled(TRUE);
  385. if (is_landmark_editable)
  386. {
  387. if(!mLandmarkInfo->setLandmarkFolder(mItem->getParentUUID()) && !mItem->getParentUUID().isNull())
  388. {
  389. const LLViewerInventoryCategory* cat = gInventory.getCategory(mItem->getParentUUID());
  390. if (cat)
  391. {
  392. std::string cat_fullname = LLPanelLandmarkInfo::getFullFolderName(cat);
  393. LLComboBox* folderList = mLandmarkInfo->getChild<LLComboBox>("folder_combo");
  394. folderList->add(cat_fullname, cat->getUUID(), ADD_TOP);
  395. }
  396. }
  397. }
  398. mLandmarkInfo->displayItemInfo(mItem);
  399. LLLandmark* lm = gLandmarkList.getAsset(mItem->getAssetUUID(),
  400. boost::bind(&LLPanelPlaces::onLandmarkLoaded, this, _1));
  401. if (lm)
  402. {
  403. onLandmarkLoaded(lm);
  404. }
  405. }
  406. S32 LLPanelPlaces::notifyParent(const LLSD& info)
  407. {
  408. if(info.has("update_verbs"))
  409. {
  410. if(mPosGlobal.isExactlyZero())
  411. {
  412. mPosGlobal.setVec(info["global_x"], info["global_y"], info["global_z"]);
  413. }
  414. updateVerbs();
  415. return 1;
  416. }
  417. return LLPanel::notifyParent(info);
  418. }
  419. void LLPanelPlaces::onLandmarkLoaded(LLLandmark* landmark)
  420. {
  421. if (!mLandmarkInfo)
  422. return;
  423. LLUUID region_id;
  424. landmark->getRegionID(region_id);
  425. landmark->getGlobalPos(mPosGlobal);
  426. mLandmarkInfo->displayParcelInfo(region_id, mPosGlobal);
  427. updateVerbs();
  428. }
  429. void LLPanelPlaces::onFilterEdit(const std::string& search_string, bool force_filter)
  430. {
  431. if (!mActivePanel)
  432. return;
  433. if (force_filter || mActivePanel->getFilterSubString() != search_string)
  434. {
  435. std::string string = search_string;
  436. // Searches are case-insensitive
  437. LLStringUtil::toUpper(string);
  438. LLStringUtil::trimHead(string);
  439. mActivePanel->onSearchEdit(string);
  440. }
  441. }
  442. void LLPanelPlaces::onTabSelected()
  443. {
  444. mActivePanel = dynamic_cast<LLPanelPlacesTab*>(mTabContainer->getCurrentPanel());
  445. if (!mActivePanel)
  446. return;
  447. onFilterEdit(mActivePanel->getFilterSubString(), true);
  448. mActivePanel->updateVerbs();
  449. }
  450. void LLPanelPlaces::onTeleportButtonClicked()
  451. {
  452. LLPanelPlaceInfo* panel = getCurrentInfoPanel();
  453. if (panel && panel->getVisible())
  454. {
  455. if (mPlaceInfoType == LANDMARK_INFO_TYPE)
  456. {
  457. LLSD payload;
  458. payload["asset_id"] = mItem->getAssetUUID();
  459. LLNotificationsUtil::add("TeleportFromLandmark", LLSD(), payload);
  460. }
  461. else if (mPlaceInfoType == AGENT_INFO_TYPE ||
  462.  mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
  463.  mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
  464. {
  465. LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
  466. if (!mPosGlobal.isExactlyZero() && worldmap_instance)
  467. {
  468. gAgent.teleportViaLocation(mPosGlobal);
  469. worldmap_instance->trackLocation(mPosGlobal);
  470. }
  471. }
  472. }
  473. else
  474. {
  475. if (mActivePanel)
  476. mActivePanel->onTeleport();
  477. }
  478. }
  479. void LLPanelPlaces::onShowOnMapButtonClicked()
  480. {
  481. LLPanelPlaceInfo* panel = getCurrentInfoPanel();
  482. if (panel && panel->getVisible())
  483. {
  484. LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
  485. if(!worldmap_instance)
  486. return;
  487. if (mPlaceInfoType == AGENT_INFO_TYPE ||
  488. mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE ||
  489. mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
  490. mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
  491. {
  492. if (!mPosGlobal.isExactlyZero())
  493. {
  494. worldmap_instance->trackLocation(mPosGlobal);
  495. LLFloaterReg::showInstance("world_map", "center");
  496. }
  497. }
  498. else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
  499. {
  500. LLLandmark* landmark = gLandmarkList.getAsset(mItem->getAssetUUID());
  501. if (!landmark)
  502. return;
  503. LLVector3d landmark_global_pos;
  504. if (!landmark->getGlobalPos(landmark_global_pos))
  505. return;
  506. if (!landmark_global_pos.isExactlyZero())
  507. {
  508. worldmap_instance->trackLocation(landmark_global_pos);
  509. LLFloaterReg::showInstance("world_map", "center");
  510. }
  511. }
  512. }
  513. else
  514. {
  515. if (mActivePanel)
  516. mActivePanel->onShowOnMap();
  517. }
  518. }
  519. void LLPanelPlaces::onEditButtonClicked()
  520. {
  521. if (!mLandmarkInfo || isLandmarkEditModeOn)
  522. return;
  523. isLandmarkEditModeOn = true;
  524. mLandmarkInfo->toggleLandmarkEditMode(TRUE);
  525. updateVerbs();
  526. }
  527. void LLPanelPlaces::onSaveButtonClicked()
  528. {
  529. if (!mLandmarkInfo || mItem.isNull())
  530. return;
  531. std::string current_title_value = mLandmarkInfo->getLandmarkTitle();
  532. std::string item_title_value = mItem->getName();
  533. std::string current_notes_value = mLandmarkInfo->getLandmarkNotes();
  534. std::string item_notes_value = mItem->getDescription();
  535. LLStringUtil::trim(current_title_value);
  536. LLStringUtil::trim(current_notes_value);
  537. LLUUID item_id = mItem->getUUID();
  538. LLUUID folder_id = mLandmarkInfo->getLandmarkFolder();
  539. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(mItem);
  540. if (!current_title_value.empty() &&
  541. (item_title_value != current_title_value || item_notes_value != current_notes_value))
  542. {
  543. new_item->rename(current_title_value);
  544. new_item->setDescription(current_notes_value);
  545. new_item->updateServer(FALSE);
  546. }
  547. if(folder_id != mItem->getParentUUID())
  548. {
  549. LLInventoryModel::update_list_t update;
  550. LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(),-1);
  551. update.push_back(old_folder);
  552. LLInventoryModel::LLCategoryUpdate new_folder(folder_id, 1);
  553. update.push_back(new_folder);
  554. gInventory.accountForUpdate(update);
  555. new_item->setParent(folder_id);
  556. new_item->updateParentOnServer(FALSE);
  557. }
  558. gInventory.updateItem(new_item);
  559. gInventory.notifyObservers();
  560. onCancelButtonClicked();
  561. }
  562. void LLPanelPlaces::onCancelButtonClicked()
  563. {
  564. if (!mLandmarkInfo)
  565. return;
  566. if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
  567. {
  568. onBackButtonClicked();
  569. }
  570. else
  571. {
  572. mLandmarkInfo->toggleLandmarkEditMode(FALSE);
  573. isLandmarkEditModeOn = false;
  574. updateVerbs();
  575. // Reload the landmark properties.
  576. mLandmarkInfo->displayItemInfo(mItem);
  577. }
  578. }
  579. void LLPanelPlaces::onOverflowButtonClicked()
  580. {
  581. LLToggleableMenu* menu;
  582. bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;
  583. if ((is_agent_place_info_visible ||
  584.  mPlaceInfoType == "remote_place" ||
  585.  mPlaceInfoType == "teleport_history") && mPlaceMenu != NULL)
  586. {
  587. menu = mPlaceMenu;
  588. // Enable adding a landmark only for agent current parcel and if
  589. // there is no landmark already pointing to that parcel in agent's inventory.
  590. menu->getChild<LLMenuItemCallGL>("landmark")->setEnabled(is_agent_place_info_visible &&
  591.  !LLLandmarkActions::landmarkAlreadyExists());
  592. }
  593. else if (mPlaceInfoType == LANDMARK_INFO_TYPE && mLandmarkMenu != NULL)
  594. {
  595. menu = mLandmarkMenu;
  596. BOOL is_landmark_removable = FALSE;
  597. if (mItem.notNull())
  598. {
  599. const LLUUID& item_id = mItem->getUUID();
  600. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  601. is_landmark_removable = gInventory.isObjectDescendentOf(item_id, gInventory.getRootFolderID()) &&
  602. !gInventory.isObjectDescendentOf(item_id, trash_id);
  603. }
  604. menu->getChild<LLMenuItemCallGL>("delete")->setEnabled(is_landmark_removable);
  605. }
  606. else
  607. {
  608. return;
  609. }
  610. if (!menu->toggleVisibility())
  611. return;
  612. if (menu->getButtonRect().isEmpty())
  613. {
  614. menu->setButtonRect(mOverflowBtn);
  615. }
  616. menu->updateParent(LLMenuGL::sMenuContainer);
  617. LLRect rect = mOverflowBtn->getRect();
  618. LLMenuGL::showPopup(this, menu, rect.mRight, rect.mTop);
  619. }
  620. bool LLPanelPlaces::onOverflowMenuItemEnable(const LLSD& param)
  621. {
  622. std::string value = param.asString();
  623. if("can_create_pick" == value)
  624. {
  625. return !LLAgentPicksInfo::getInstance()->isPickLimitReached();
  626. }
  627. return true;
  628. }
  629. void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)
  630. {
  631. std::string item = param.asString();
  632. if (item == "landmark")
  633. {
  634. LLSD key;
  635. key["type"] = CREATE_LANDMARK_INFO_TYPE;
  636. key["x"] = mPosGlobal.mdV[VX];
  637. key["y"] = mPosGlobal.mdV[VY];
  638. key["z"] = mPosGlobal.mdV[VZ];
  639. onOpen(key);
  640. }
  641. else if (item == "copy")
  642. {
  643. LLLandmarkActions::getSLURLfromPosGlobal(mPosGlobal, boost::bind(&onSLURLBuilt, _1));
  644. }
  645. else if (item == "delete")
  646. {
  647. gInventory.removeItem(mItem->getUUID());
  648. onBackButtonClicked();
  649. }
  650. else if (item == "pick")
  651. {
  652. if (mPickPanel == NULL)
  653. {
  654. mPickPanel = LLPanelPickEdit::create();
  655. addChild(mPickPanel);
  656. mPickPanel->setExitCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE));
  657. mPickPanel->setCancelCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE));
  658. mPickPanel->setSaveCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE));
  659. }
  660. togglePickPanel(TRUE);
  661. mPickPanel->onOpen(LLSD());
  662. LLPanelPlaceInfo* panel = getCurrentInfoPanel();
  663. if (panel)
  664. {
  665. panel->createPick(mPosGlobal, mPickPanel);
  666. }
  667. LLRect rect = getRect();
  668. mPickPanel->reshape(rect.getWidth(), rect.getHeight());
  669. mPickPanel->setRect(rect);
  670. }
  671. else if (item == "add_to_favbar")
  672. {
  673. if ( mItem.notNull() )
  674. {
  675. const LLUUID& favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
  676. if ( favorites_id.notNull() )
  677. {
  678. copy_inventory_item(gAgent.getID(),
  679. mItem->getPermissions().getOwner(),
  680. mItem->getUUID(),
  681. favorites_id,
  682. std::string(),
  683. LLPointer<LLInventoryCallback>(NULL));
  684. llinfos << "Copied inventory item #" << mItem->getUUID() << " to favorites." << llendl;
  685. }
  686. }
  687. }
  688. }
  689. void LLPanelPlaces::onBackButtonClicked()
  690. {
  691. togglePlaceInfoPanel(FALSE);
  692. // Resetting mPlaceInfoType when Place Info panel is closed.
  693. mPlaceInfoType = LLStringUtil::null;
  694. isLandmarkEditModeOn = false;
  695. updateVerbs();
  696. }
  697. void LLPanelPlaces::togglePickPanel(BOOL visible)
  698. {
  699. if (mPickPanel)
  700. mPickPanel->setVisible(visible);
  701. }
  702. void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
  703. {
  704. if (!mPlaceProfile || !mLandmarkInfo)
  705. return;
  706. mFilterEditor->setVisible(!visible);
  707. mTabContainer->setVisible(!visible);
  708. if (mPlaceInfoType == AGENT_INFO_TYPE ||
  709. mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
  710. mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
  711. {
  712. mPlaceProfile->setVisible(visible);
  713. if (visible)
  714. {
  715. mPlaceProfile->resetLocation();
  716. // Do not reset location info until mResetInfoTimer has expired
  717. // to avoid text blinking.
  718. mResetInfoTimer.setTimerExpirySec(PLACE_INFO_UPDATE_INTERVAL);
  719. LLRect rect = getRect();
  720. LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);
  721. mPlaceProfile->reshape(new_rect.getWidth(), new_rect.getHeight());
  722. mLandmarkInfo->setVisible(FALSE);
  723. }
  724. else if (mPlaceInfoType == AGENT_INFO_TYPE)
  725. {
  726. LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
  727. // Clear reference to parcel selection when closing place profile panel.
  728. // LLViewerParcelMgr removes the selection if it has 1 reference to it.
  729. mParcel.clear();
  730. }
  731. }
  732. else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE ||
  733.  mPlaceInfoType == LANDMARK_INFO_TYPE)
  734. {
  735. mLandmarkInfo->setVisible(visible);
  736. if (visible)
  737. {
  738. mLandmarkInfo->resetLocation();
  739. LLRect rect = getRect();
  740. LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);
  741. mLandmarkInfo->reshape(new_rect.getWidth(), new_rect.getHeight());
  742. mPlaceProfile->setVisible(FALSE);
  743. }
  744. else
  745. {
  746. LLLandmarksPanel* landmarks_panel =
  747. dynamic_cast<LLLandmarksPanel*>(mTabContainer->getPanelByName("Landmarks"));
  748. if (landmarks_panel && mItem.notNull())
  749. {
  750. // If a landmark info is being closed we open the landmarks tab
  751. // and set this landmark selected.
  752. mTabContainer->selectTabPanel(landmarks_panel);
  753. landmarks_panel->setItemSelected(mItem->getUUID(), TRUE);
  754. }
  755. }
  756. }
  757. }
  758. // virtual
  759. void LLPanelPlaces::handleVisibilityChange(BOOL new_visibility)
  760. {
  761. LLPanel::handleVisibilityChange(new_visibility);
  762. if (!new_visibility && mPlaceInfoType == AGENT_INFO_TYPE)
  763. {
  764. LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
  765. // Clear reference to parcel selection when closing places panel.
  766. mParcel.clear();
  767. }
  768. }
  769. void LLPanelPlaces::changedParcelSelection()
  770. {
  771. if (!mPlaceProfile)
  772. return;
  773. LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
  774. mParcel = parcel_mgr->getFloatingParcelSelection();
  775. LLParcel* parcel = mParcel->getParcel();
  776. LLViewerRegion* region = parcel_mgr->getSelectionRegion();
  777. if (!region || !parcel)
  778. return;
  779. LLVector3d prev_pos_global = mPosGlobal;
  780. // If agent is inside the selected parcel show agent's region<X, Y, Z>,
  781. // otherwise show region<X, Y, Z> of agent's selection point.
  782. bool is_current_parcel = is_agent_in_selected_parcel(parcel);
  783. if (is_current_parcel)
  784. {
  785. mPosGlobal = gAgent.getPositionGlobal();
  786. }
  787. else
  788. {
  789. LLVector3d pos_global = gViewerWindow->getLastPick().mPosGlobal;
  790. if (!pos_global.isExactlyZero())
  791. {
  792. mPosGlobal = pos_global;
  793. }
  794. }
  795. // Reset location info only if global position has changed
  796. // and update timer has expired to reduce unnecessary text and icons updates.
  797. if (prev_pos_global != mPosGlobal && mResetInfoTimer.hasExpired())
  798. {
  799. mPlaceProfile->resetLocation();
  800. mResetInfoTimer.setTimerExpirySec(PLACE_INFO_UPDATE_INTERVAL);
  801. }
  802. mPlaceProfile->displaySelectedParcelInfo(parcel, region, mPosGlobal, is_current_parcel);
  803. updateVerbs();
  804. }
  805. void LLPanelPlaces::createTabs()
  806. {
  807. if (!(gInventory.isInventoryUsable() && LLTeleportHistory::getInstance()))
  808. return;
  809. LLLandmarksPanel* landmarks_panel = new LLLandmarksPanel();
  810. if (landmarks_panel)
  811. {
  812. landmarks_panel->setPanelPlacesButtons(this);
  813. mTabContainer->addTabPanel(
  814. LLTabContainer::TabPanelParams().
  815. panel(landmarks_panel).
  816. label(getString("landmarks_tab_title")).
  817. insert_at(LLTabContainer::END));
  818. }
  819. LLTeleportHistoryPanel* teleport_history_panel = new LLTeleportHistoryPanel();
  820. if (teleport_history_panel)
  821. {
  822. teleport_history_panel->setPanelPlacesButtons(this);
  823. mTabContainer->addTabPanel(
  824. LLTabContainer::TabPanelParams().
  825. panel(teleport_history_panel).
  826. label(getString("teleport_history_tab_title")).
  827. insert_at(LLTabContainer::END));
  828. }
  829. mTabContainer->selectFirstTab();
  830. mActivePanel = dynamic_cast<LLPanelPlacesTab*>(mTabContainer->getCurrentPanel());
  831. // Filter applied to show all items.
  832. if (mActivePanel)
  833. mActivePanel->onSearchEdit(mActivePanel->getFilterSubString());
  834. }
  835. void LLPanelPlaces::changedGlobalPos(const LLVector3d &global_pos)
  836. {
  837. mPosGlobal = global_pos;
  838. updateVerbs();
  839. }
  840. void LLPanelPlaces::showAddedLandmarkInfo(const std::vector<LLUUID>& items)
  841. {
  842. for (std::vector<LLUUID>::const_iterator item_iter = items.begin();
  843.  item_iter != items.end();
  844.  ++item_iter)
  845. {
  846. const LLUUID& item_id = (*item_iter);
  847. if(!highlight_offered_item(item_id))
  848. {
  849. continue;
  850. }
  851. LLInventoryItem* item = gInventory.getItem(item_id);
  852. llassert(item);
  853. if (item && (LLAssetType::AT_LANDMARK == item->getType()) )
  854. {
  855. // Created landmark is passed to Places panel to allow its editing.
  856. // If the panel is closed we don't reopen it until created landmark is loaded.
  857. if("create_landmark" == getPlaceInfoType() && !getItem())
  858. {
  859. setItem(item);
  860. }
  861. }
  862. }
  863. }
  864. void LLPanelPlaces::updateVerbs()
  865. {
  866. bool is_place_info_visible;
  867. LLPanelPlaceInfo* panel = getCurrentInfoPanel();
  868. if (panel)
  869. {
  870. is_place_info_visible = panel->getVisible();
  871. }
  872. else
  873. {
  874. is_place_info_visible = false;
  875. }
  876. bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;
  877. bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE;
  878. bool have_3d_pos = ! mPosGlobal.isExactlyZero();
  879. mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
  880. mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
  881. mOverflowBtn->setVisible(is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn);
  882. mEditBtn->setVisible(mPlaceInfoType == LANDMARK_INFO_TYPE && !isLandmarkEditModeOn);
  883. mSaveBtn->setVisible(isLandmarkEditModeOn);
  884. mCancelBtn->setVisible(isLandmarkEditModeOn);
  885. mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn);
  886. mShowOnMapBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos);
  887. if (is_place_info_visible)
  888. {
  889. if (is_agent_place_info_visible)
  890. {
  891. // We don't need to teleport to the current location
  892. // so check if the location is not within the current parcel.
  893. mTeleportBtn->setEnabled(have_3d_pos &&
  894.  !LLViewerParcelMgr::getInstance()->inAgentParcel(mPosGlobal));
  895. }
  896. else if (mPlaceInfoType == LANDMARK_INFO_TYPE || mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
  897. {
  898. mTeleportBtn->setEnabled(have_3d_pos);
  899. }
  900. // Do not enable landmark info Back button when we are waiting
  901. // for newly created landmark to load.
  902. if (!is_create_landmark_visible)
  903. {
  904. mLandmarkInfoBackBtn->setEnabled(TRUE);
  905. }
  906. }
  907. else
  908. {
  909. if (mActivePanel)
  910. mActivePanel->updateVerbs();
  911. }
  912. }
  913. LLPanelPlaceInfo* LLPanelPlaces::getCurrentInfoPanel()
  914. {
  915. if (mPlaceInfoType == AGENT_INFO_TYPE ||
  916. mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
  917. mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
  918. {
  919. return mPlaceProfile;
  920. }
  921. else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE ||
  922.  mPlaceInfoType == LANDMARK_INFO_TYPE)
  923. {
  924. return mLandmarkInfo;
  925. }
  926. return NULL;
  927. }
  928. static bool is_agent_in_selected_parcel(LLParcel* parcel)
  929. {
  930. LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
  931. LLViewerRegion* region = parcel_mgr->getSelectionRegion();
  932. if (!region || !parcel)
  933. return false;
  934. return region == gAgent.getRegion() &&
  935. parcel->getLocalID() == parcel_mgr->getAgentParcel()->getLocalID();
  936. }
  937. static void onSLURLBuilt(std::string& slurl)
  938. {
  939. LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
  940. LLSD args;
  941. args["SLURL"] = slurl;
  942. LLNotificationsUtil::add("CopySLURL", args);
  943. }