llfloaterpathfindinglinksets.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. /**
  2. * @file llfloaterpathfindinglinksets.cpp
  3. * @brief Pathfinding linksets floater, allowing manipulation of the linksets
  4. * on the current region.
  5. *
  6. * $LicenseInfo:firstyear=2012&license=viewergpl$
  7. *
  8. * Copyright (c) 2012, Linden Research, Inc.
  9. *
  10. * Second Life Viewer Source Code
  11. * The source code in this file ("Source Code") is provided by Linden Lab
  12. * to you under the terms of the GNU General Public License, version 2.0
  13. * ("GPL"), unless you have obtained a separate licensing agreement
  14. * ("Other License"), formally executed by you and Linden Lab. Terms of
  15. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17. *
  18. * There are special exceptions to the terms and conditions of the GPL as
  19. * it is applied to this Source Code. View the full text of the exception
  20. * in the file doc/FLOSS-exception.txt in this software distribution, or
  21. * online at
  22. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23. *
  24. * By copying, modifying or distributing this software, you acknowledge
  25. * that you have read and understood your obligations described above,
  26. * and agree to abide by those obligations.
  27. *
  28. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30. * COMPLETENESS OR PERFORMANCE.
  31. * $/LicenseInfo$
  32. */
  33. #include "llviewerprecompiledheaders.h"
  34. #include "llfloaterpathfindinglinksets.h"
  35. #include "llbutton.h"
  36. #include "llcombobox.h"
  37. #include "llnotifications.h"
  38. #include "lllineeditor.h"
  39. #include "llscrolllistctrl.h"
  40. #include "lltextbox.h"
  41. #include "lluictrlfactory.h"
  42. #include "llagent.h"
  43. #include "llfloaterpathfindingobjects.h"
  44. #include "llpathfindinglinkset.h"
  45. #include "llpathfindinglinksetlist.h"
  46. #include "llpathfindingmanager.h"
  47. //MK
  48. #include "mkrlinterface.h"
  49. //mk
  50. #define XUI_LINKSET_USE_NONE 0
  51. #define XUI_LINKSET_USE_WALKABLE 1
  52. #define XUI_LINKSET_USE_STATIC_OBSTACLE 2
  53. #define XUI_LINKSET_USE_DYNAMIC_OBSTACLE 3
  54. #define XUI_LINKSET_USE_MATERIAL_VOLUME 4
  55. #define XUI_LINKSET_USE_EXCLUSION_VOLUME 5
  56. #define XUI_LINKSET_USE_DYNAMIC_PHANTOM 6
  57. //static
  58. void LLFloaterPathfindingLinksets::openLinksetsWithSelectedObjects()
  59. {
  60. LLFloaterPathfindingLinksets* self = findInstance();
  61. if (self)
  62. {
  63. self->open();
  64. }
  65. else
  66. {
  67. self = getInstance(); // creates a new instance
  68. self->clearFilters();
  69. self->showFloaterWithSelectionObjects();
  70. }
  71. }
  72. LLFloaterPathfindingLinksets::LLFloaterPathfindingLinksets(const LLSD&)
  73. : mPreviousValueA(MAX_WALKABILITY_VALUE),
  74. mPreviousValueB(MAX_WALKABILITY_VALUE),
  75. mPreviousValueC(MAX_WALKABILITY_VALUE),
  76. mPreviousValueD(MAX_WALKABILITY_VALUE),
  77. mHasKnownScripedStatus(false),
  78. mScriptedColumnWidth(60)
  79. {
  80. LLUICtrlFactory::getInstance()->buildFloater(this,
  81. "floater_pathfinding_linksets.xml");
  82. }
  83. bool LLFloaterPathfindingLinksets::postBuild()
  84. {
  85. mBeaconColor =
  86. LLUI::sColorsGroup->getColor("PathfindingLinksetBeaconColor");
  87. mFilterByName = getChild<LLLineEditor>("filter_by_name");
  88. mFilterByName->setCommitCallback(onApplyAllFilters);
  89. mFilterByName->setCallbackUserData(this);
  90. mFilterByName->setSelectAllonFocusReceived(true);
  91. mFilterByName->setCommitOnFocusLost(true);
  92. mFilterByDescription = getChild<LLLineEditor>("filter_by_description");
  93. mFilterByDescription->setCommitCallback(onApplyAllFilters);
  94. mFilterByDescription->setCallbackUserData(this);
  95. mFilterByDescription->setSelectAllonFocusReceived(true);
  96. mFilterByDescription->setCommitOnFocusLost(true);
  97. mFilterByLinksetUse = getChild<LLComboBox>("filter_by_linkset_use");
  98. mFilterByLinksetUse->setCommitCallback(onApplyAllFilters);
  99. mFilterByDescription->setCallbackUserData(this);
  100. childSetAction("apply_filters", onApplyAllFiltersClicked, this);
  101. childSetAction("clear_filters", onClearFiltersClicked, this);
  102. mEditLinksetUse = getChild<LLComboBox>("edit_linkset_use");
  103. mEditLinksetUse->clearRows();
  104. mUseUnset = mEditLinksetUse->add(getString("linkset_choose_use"),
  105. XUI_LINKSET_USE_NONE);
  106. mUseWalkable =
  107. mEditLinksetUse->add(getLinksetUseString(LLPathfindingLinkset::kWalkable),
  108. XUI_LINKSET_USE_WALKABLE);
  109. mUseStaticObstacle =
  110. mEditLinksetUse->add(getLinksetUseString(LLPathfindingLinkset::kStaticObstacle),
  111. XUI_LINKSET_USE_STATIC_OBSTACLE);
  112. mUseDynamicObstacle =
  113. mEditLinksetUse->add(getLinksetUseString(LLPathfindingLinkset::kDynamicObstacle),
  114. XUI_LINKSET_USE_DYNAMIC_OBSTACLE);
  115. mUseMaterialVolume =
  116. mEditLinksetUse->add(getLinksetUseString(LLPathfindingLinkset::kMaterialVolume),
  117. XUI_LINKSET_USE_MATERIAL_VOLUME);
  118. mUseExclusionVolume =
  119. mEditLinksetUse->add(getLinksetUseString(LLPathfindingLinkset::kExclusionVolume),
  120. XUI_LINKSET_USE_EXCLUSION_VOLUME);
  121. mUseDynamicPhantom =
  122. mEditLinksetUse->add(getLinksetUseString(LLPathfindingLinkset::kDynamicPhantom),
  123. XUI_LINKSET_USE_DYNAMIC_PHANTOM);
  124. mEditLinksetUse->selectFirstItem();
  125. mLabelCoefficients = getChild<LLTextBox>("walkability_coefficients_label");
  126. mLabelEditA = getChild<LLTextBox>("edit_a_label");
  127. mLabelSuggestedUseA = getChild<LLTextBox>("suggested_use_a_label");
  128. mEditA = getChild<LLLineEditor>("edit_a_value");
  129. mEditA->setPrevalidate(LLLineEditor::prevalidateNonNegativeS32);
  130. mEditA->setCommitCallback(onWalkabilityCoefficientEntered);
  131. mEditA->setCallbackUserData(this);
  132. mLabelEditB = getChild<LLTextBox>("edit_b_label");
  133. mLabelSuggestedUseB = getChild<LLTextBox>("suggested_use_b_label");
  134. mEditB = getChild<LLLineEditor>("edit_b_value");
  135. mEditB->setPrevalidate(LLLineEditor::prevalidateNonNegativeS32);
  136. mEditB->setCommitCallback(onWalkabilityCoefficientEntered);
  137. mEditB->setCallbackUserData(this);
  138. mLabelEditC = getChild<LLTextBox>("edit_c_label");
  139. mLabelSuggestedUseC = getChild<LLTextBox>("suggested_use_c_label");
  140. mEditC = getChild<LLLineEditor>("edit_c_value");
  141. mEditC->setPrevalidate(LLLineEditor::prevalidateNonNegativeS32);
  142. mEditC->setCommitCallback(onWalkabilityCoefficientEntered);
  143. mEditC->setCallbackUserData(this);
  144. mLabelEditD = getChild<LLTextBox>("edit_d_label");
  145. mLabelSuggestedUseD = getChild<LLTextBox>("suggested_use_d_label");
  146. mEditD = getChild<LLLineEditor>("edit_d_value");
  147. mEditD->setPrevalidate(LLLineEditor::prevalidateNonNegativeS32);
  148. mEditD->setCommitCallback(onWalkabilityCoefficientEntered);
  149. mEditD->setCallbackUserData(this);
  150. mApplyEditsButton = getChild<LLButton>("apply_edit_values");
  151. mApplyEditsButton->setClickedCallback(onApplyChangesClicked, this);
  152. return LLFloaterPathfindingObjects::postBuild();
  153. }
  154. void LLFloaterPathfindingLinksets::requestGetObjects()
  155. {
  156. LL_DEBUGS("NavMesh") << "Requesting linksets list" << LL_ENDL;
  157. LLPathfindingManager* mngrp = LLPathfindingManager::getInstance();
  158. mngrp->requestGetLinksets(getNewRequestId(),
  159. boost::bind(&LLFloaterPathfindingLinksets::newObjectList,
  160. _1, _2, _3));
  161. }
  162. LLSD LLFloaterPathfindingLinksets::buildLinksetScrollListItemData(const LLPathfindingLinkset* linksetp,
  163. const LLVector3& av_pos)
  164. {
  165. llassert(linksetp != NULL);
  166. LLSD columns = LLSD::emptyArray();
  167. if (linksetp->isTerrain())
  168. {
  169. columns[0]["column"] = "name";
  170. columns[0]["value"] = getString("linkset_terrain_name");
  171. columns[1]["column"] = "description";
  172. columns[1]["value"] = getString("linkset_terrain_description");
  173. columns[2]["column"] = "owner";
  174. columns[2]["value"] = getString("linkset_terrain_owner");
  175. columns[3]["column"] = "scripted";
  176. columns[3]["value"] = getString("linkset_terrain_scripted");
  177. columns[4]["column"] = "land_impact";
  178. columns[4]["value"] = getString("linkset_terrain_land_impact");
  179. columns[5]["column"] = "dist_from_you";
  180. columns[5]["value"] = getString("linkset_terrain_dist_from_you");
  181. }
  182. else
  183. {
  184. columns[0]["column"] = "name";
  185. columns[0]["value"] = linksetp->getName();
  186. columns[1]["column"] = "description";
  187. columns[1]["value"] = linksetp->getDescription();
  188. columns[2]["column"] = "owner";
  189. columns[2]["value"] = getOwnerName(linksetp);
  190. std::string scripted;
  191. if (!linksetp->hasIsScripted())
  192. {
  193. scripted = getString("linkset_is_unknown_scripted");
  194. }
  195. else if (linksetp->isScripted())
  196. {
  197. scripted = getString("linkset_is_scripted");
  198. mHasKnownScripedStatus = true;
  199. }
  200. else
  201. {
  202. scripted = getString("linkset_is_not_scripted");
  203. mHasKnownScripedStatus = true;
  204. }
  205. columns[3]["column"] = "scripted";
  206. columns[3]["value"] = scripted;
  207. columns[4]["column"] = "land_impact";
  208. columns[4]["value"] = llformat("%1d", linksetp->getLandImpact());
  209. columns[5]["column"] = "dist_from_you";
  210. columns[5]["value"] = llformat("%1.0f m", dist_vec(av_pos, linksetp->getLocation()));
  211. }
  212. columns[0]["font"] = "SANSSERIF";
  213. columns[1]["font"] = "SANSSERIF";
  214. columns[2]["font"] = "SANSSERIF";
  215. columns[3]["font"] = "SANSSERIF";
  216. columns[4]["font"] = "SANSSERIF";
  217. columns[5]["font"] = "SANSSERIF";
  218. columns[6]["column"] = "linkset_use";
  219. std::string use_str = getLinksetUseString(linksetp->getLinksetUse());
  220. if (linksetp->isTerrain())
  221. {
  222. use_str += (" " + getString("linkset_is_terrain"));
  223. }
  224. else if (!linksetp->isModifiable() && linksetp->canBeVolume())
  225. {
  226. use_str += (" " + getString("linkset_is_restricted_state"));
  227. }
  228. else if (linksetp->isModifiable() && !linksetp->canBeVolume())
  229. {
  230. use_str += (" " + getString("linkset_is_non_volume_state"));
  231. }
  232. else if (!linksetp->isModifiable() && !linksetp->canBeVolume())
  233. {
  234. use_str += (" " + getString("linkset_is_restricted_non_volume_state"));
  235. }
  236. columns[6]["value"] = use_str;
  237. columns[6]["font"] = "SANSSERIF";
  238. columns[7]["column"] = "a_percent";
  239. columns[7]["value"] = llformat("%3d %%",
  240. linksetp->getWalkabilityCoefficientA());
  241. columns[7]["font"] = "SANSSERIF";
  242. columns[8]["column"] = "b_percent";
  243. columns[8]["value"] = llformat("%3d %%",
  244. linksetp->getWalkabilityCoefficientB());
  245. columns[8]["font"] = "SANSSERIF";
  246. columns[9]["column"] = "c_percent";
  247. columns[9]["value"] = llformat("%3d %%",
  248. linksetp->getWalkabilityCoefficientC());
  249. columns[9]["font"] = "SANSSERIF";
  250. columns[10]["column"] = "d_percent";
  251. columns[10]["value"] = llformat("%3d %%",
  252. linksetp->getWalkabilityCoefficientD());
  253. columns[10]["font"] = "SANSSERIF";
  254. LLSD row;
  255. row["id"] = linksetp->getUUID();
  256. row["columns"] = columns;
  257. return row;
  258. }
  259. void LLFloaterPathfindingLinksets::addObjectsIntoScrollList(const LLPathfindingObjectList::ptr_t pobjects)
  260. {
  261. if (!pobjects || pobjects->isEmpty())
  262. {
  263. llassert(false);
  264. return;
  265. }
  266. LLScrollListColumn* scripted = mObjectsScrollList->getColumn(3);
  267. if (scripted && scripted->getWidth() > 0)
  268. {
  269. // Store the current width (the first time the list is built and,
  270. // subsequently, in case the column was resized by the user).
  271. mScriptedColumnWidth = scripted->getWidth();
  272. }
  273. const LLVector3& av_pos = gAgent.getPositionAgent();
  274. std::string terrain;
  275. std::string name_filter = mFilterByName->getText();
  276. bool filter_by_name = !name_filter.empty();
  277. if (filter_by_name)
  278. {
  279. LLStringUtil::toUpper(name_filter);
  280. terrain = getString("linkset_terrain_name");
  281. }
  282. std::string desc_filter = mFilterByDescription->getText();
  283. bool filter_by_desc = !desc_filter.empty();
  284. if (filter_by_desc)
  285. {
  286. LLStringUtil::toUpper(desc_filter);
  287. }
  288. LLPathfindingLinkset::ELinksetUse use_filter = getFilterLinksetUse();
  289. bool filter_by_use = use_filter != LLPathfindingLinkset::kUnknown;
  290. std::string tmp;
  291. for (LLPathfindingObjectList::const_iterator iter = pobjects->begin(),
  292. end = pobjects->end();
  293. iter != end; ++iter)
  294. {
  295. const LLPathfindingObject::ptr_t objp = iter->second;
  296. if (!objp) continue;
  297. const LLPathfindingLinkset* linksetp = objp.get()->asLinkset();
  298. if (!linksetp) continue;
  299. if (filter_by_use && linksetp->getLinksetUse() != use_filter)
  300. {
  301. continue;
  302. }
  303. if (filter_by_name)
  304. {
  305. tmp = linksetp->isTerrain() ? terrain : linksetp->getName();
  306. LLStringUtil::toUpper(tmp);
  307. if (tmp.find(name_filter) == std::string::npos)
  308. {
  309. continue;
  310. }
  311. }
  312. if (filter_by_desc)
  313. {
  314. tmp = linksetp->getDescription();
  315. LLStringUtil::toUpper(tmp);
  316. if (tmp.find(desc_filter) == std::string::npos)
  317. {
  318. continue;
  319. }
  320. }
  321. LLSD row = buildLinksetScrollListItemData(linksetp, av_pos);
  322. mObjectsScrollList->addElement(row, ADD_BOTTOM);
  323. if (linksetp->hasOwner() && !linksetp->hasOwnerName())
  324. {
  325. rebuildScrollListAfterAvatarNameLoads(objp);
  326. }
  327. }
  328. if (scripted)
  329. {
  330. // Set the column width to zero if no script info is available,
  331. // or to its last non-zero width if that info exists.
  332. scripted->setWidth(mHasKnownScripedStatus ? mScriptedColumnWidth : 0);
  333. }
  334. }
  335. //static
  336. void LLFloaterPathfindingLinksets::handleObjectNameResponse(const LLPathfindingObject* pobj)
  337. {
  338. LLFloaterPathfindingLinksets* self = findInstance();
  339. if (!self) return;
  340. uuid_list_t::iterator it = self->mLoadingNameObjects.find(pobj->getUUID());
  341. if (it != self->mLoadingNameObjects.end())
  342. {
  343. self->mLoadingNameObjects.hset_erase(it);
  344. if (self->mLoadingNameObjects.empty())
  345. {
  346. self->rebuildObjectsScrollList();
  347. }
  348. }
  349. }
  350. void LLFloaterPathfindingLinksets::rebuildScrollListAfterAvatarNameLoads(const LLPathfindingObject::ptr_t pobj)
  351. {
  352. mLoadingNameObjects.emplace(pobj->getUUID());
  353. pobj->registerOwnerNameListener(boost::bind(&LLFloaterPathfindingLinksets::handleObjectNameResponse,
  354. _1));
  355. }
  356. // NOTE: we need a static function to prevent crash in case the floater is
  357. // closed while the object list is being received... This static function
  358. // then calls the inherited parent class' function only when the floater
  359. // instance still exists. HB
  360. //static
  361. void LLFloaterPathfindingLinksets::newObjectList(LLPathfindingManager::request_id_t request_id,
  362. LLPathfindingManager::ERequestStatus req_status,
  363. LLPathfindingObjectList::ptr_t pobjects)
  364. {
  365. LLFloaterPathfindingLinksets* self = findInstance();
  366. if (self)
  367. {
  368. self->handleNewObjectList(request_id, req_status, pobjects);
  369. }
  370. }
  371. void LLFloaterPathfindingLinksets::updateControlsOnScrollListChange()
  372. {
  373. LLFloaterPathfindingObjects::updateControlsOnScrollListChange();
  374. updateEditFieldValues();
  375. updateStateOnEditFields();
  376. updateStateOnEditLinksetUse();
  377. }
  378. std::string LLFloaterPathfindingLinksets::getOwnerName(const LLPathfindingObject* obj) const
  379. {
  380. if (!obj->hasOwner())
  381. {
  382. static std::string unknown = getString("linkset_owner_unknown");
  383. return unknown;
  384. }
  385. if (!obj->hasOwnerName())
  386. {
  387. static std::string loading = getString("linkset_owner_loading");
  388. return loading;
  389. }
  390. std::string owner = obj->getOwnerName();
  391. //MK
  392. if (gRLenabled &&
  393. (gRLInterface.mContainsShownames ||
  394. gRLInterface.mContainsShownametags) &&
  395. !obj->isGroupOwned())
  396. {
  397. owner = gRLInterface.getDummyName(owner);
  398. }
  399. //mk
  400. if (obj->isGroupOwned())
  401. {
  402. static std::string group = " " + getString("linkset_owner_group");
  403. owner += group;
  404. }
  405. return owner;
  406. }
  407. LLPathfindingObjectList::ptr_t LLFloaterPathfindingLinksets::getEmptyObjectList() const
  408. {
  409. LLPathfindingObjectList::ptr_t list(new LLPathfindingLinksetList());
  410. return list;
  411. }
  412. void LLFloaterPathfindingLinksets::requestSetLinksets(LLPathfindingObjectList::ptr_t linkset_list,
  413. LLPathfindingLinkset::ELinksetUse use,
  414. S32 a, S32 b, S32 c,
  415. S32 d)
  416. {
  417. LLPathfindingManager* mngp = LLPathfindingManager::getInstance();
  418. mngp->requestSetLinksets(getNewRequestId(), linkset_list, use, a, b, c, d,
  419. boost::bind(&LLFloaterPathfindingLinksets::handleUpdateObjectList,
  420. this, _1, _2, _3));
  421. }
  422. //static
  423. void LLFloaterPathfindingLinksets::onApplyAllFilters(LLUICtrl* ctrl, void* data)
  424. {
  425. LLFloaterPathfindingLinksets* self = (LLFloaterPathfindingLinksets*)data;
  426. if (self)
  427. {
  428. self->rebuildObjectsScrollList();
  429. }
  430. }
  431. //static
  432. void LLFloaterPathfindingLinksets::onApplyAllFiltersClicked(void* data)
  433. {
  434. LLFloaterPathfindingLinksets* self = (LLFloaterPathfindingLinksets*)data;
  435. if (self)
  436. {
  437. self->rebuildObjectsScrollList();
  438. }
  439. }
  440. //static
  441. void LLFloaterPathfindingLinksets::onClearFiltersClicked(void* data)
  442. {
  443. LLFloaterPathfindingLinksets* self = (LLFloaterPathfindingLinksets*)data;
  444. if (self)
  445. {
  446. self->clearFilters();
  447. self->rebuildObjectsScrollList();
  448. }
  449. }
  450. //static
  451. void LLFloaterPathfindingLinksets::onWalkabilityCoefficientEntered(LLUICtrl* ctrl,
  452. void* data)
  453. {
  454. LLFloaterPathfindingLinksets* self = (LLFloaterPathfindingLinksets*)data;
  455. LLLineEditor* line_editor = (LLLineEditor*)ctrl;
  456. if (!self || !line_editor) return;
  457. const std::string& value_str = line_editor->getText();
  458. bool set_value = false;
  459. S32 value;
  460. if (value_str.empty())
  461. {
  462. if (line_editor == self->mEditA)
  463. {
  464. value = self->mPreviousValueA;
  465. }
  466. else if (line_editor == self->mEditB)
  467. {
  468. value = self->mPreviousValueB;
  469. }
  470. else if (line_editor == self->mEditC)
  471. {
  472. value = self->mPreviousValueC;
  473. }
  474. else if (line_editor == self->mEditD)
  475. {
  476. value = self->mPreviousValueD;
  477. }
  478. else
  479. {
  480. llwarns << "Invalid call: no corresponding line editor." << llendl;
  481. value = MAX_WALKABILITY_VALUE;
  482. }
  483. set_value = true;
  484. }
  485. else if (LLStringUtil::convertToS32(value_str, value))
  486. {
  487. if (value < MIN_WALKABILITY_VALUE || value > MAX_WALKABILITY_VALUE)
  488. {
  489. value = llclamp(value, MIN_WALKABILITY_VALUE,
  490. MAX_WALKABILITY_VALUE);
  491. set_value = true;
  492. }
  493. }
  494. else
  495. {
  496. value = MAX_WALKABILITY_VALUE;
  497. set_value = true;
  498. }
  499. if (set_value)
  500. {
  501. line_editor->setValue(LLSD(value));
  502. }
  503. }
  504. //static
  505. void LLFloaterPathfindingLinksets::onApplyChangesClicked(void* data)
  506. {
  507. LLFloaterPathfindingLinksets* self = (LLFloaterPathfindingLinksets*)data;
  508. if (self)
  509. {
  510. self->applyEdit();
  511. }
  512. }
  513. void LLFloaterPathfindingLinksets::clearFilters()
  514. {
  515. mFilterByName->clear();
  516. mFilterByDescription->clear();
  517. setFilterLinksetUse(LLPathfindingLinkset::kUnknown);
  518. }
  519. void LLFloaterPathfindingLinksets::updateEditFieldValues()
  520. {
  521. if (getNumSelectedObjects() <= 0)
  522. {
  523. mEditLinksetUse->selectFirstItem();
  524. mEditA->clear();
  525. mEditB->clear();
  526. mEditC->clear();
  527. mEditD->clear();
  528. return;
  529. }
  530. LLPathfindingObject::ptr_t objectp = getFirstSelectedObject();
  531. if (!objectp) return;
  532. const LLPathfindingLinkset* linksetp = objectp.get()->asLinkset();
  533. if (!linksetp) return;
  534. setEditLinksetUse(linksetp->getLinksetUse());
  535. mPreviousValueA = linksetp->getWalkabilityCoefficientA();
  536. mPreviousValueB = linksetp->getWalkabilityCoefficientB();
  537. mPreviousValueC = linksetp->getWalkabilityCoefficientC();
  538. mPreviousValueD = linksetp->getWalkabilityCoefficientD();
  539. mEditA->setValue(LLSD(mPreviousValueA));
  540. mEditB->setValue(LLSD(mPreviousValueB));
  541. mEditC->setValue(LLSD(mPreviousValueC));
  542. mEditD->setValue(LLSD(mPreviousValueD));
  543. }
  544. bool LLFloaterPathfindingLinksets::showUnmodifiablePhantomWarning(LLPathfindingLinkset::ELinksetUse use) const
  545. {
  546. if (use == LLPathfindingLinkset::kUnknown)
  547. {
  548. return false;
  549. }
  550. LLPathfindingObjectList::ptr_t objects = getSelectedObjects();
  551. if (!objects || objects->isEmpty())
  552. {
  553. return false;
  554. }
  555. const LLPathfindingLinksetList* listp = objects.get()->asLinksetList();
  556. return listp && listp->showUnmodifiablePhantomWarning(use);
  557. }
  558. bool LLFloaterPathfindingLinksets::showPhantomToggleWarning(LLPathfindingLinkset::ELinksetUse use) const
  559. {
  560. if (use == LLPathfindingLinkset::kUnknown)
  561. {
  562. return false;
  563. }
  564. LLPathfindingObjectList::ptr_t objects = getSelectedObjects();
  565. if (!objects || objects->isEmpty())
  566. {
  567. return false;
  568. }
  569. const LLPathfindingLinksetList* listp = objects.get()->asLinksetList();
  570. return listp && listp->showPhantomToggleWarning(use);
  571. }
  572. bool LLFloaterPathfindingLinksets::showCannotBeVolumeWarning(LLPathfindingLinkset::ELinksetUse use) const
  573. {
  574. if (use == LLPathfindingLinkset::kUnknown)
  575. {
  576. return false;
  577. }
  578. LLPathfindingObjectList::ptr_t objects = getSelectedObjects();
  579. if (!objects || objects->isEmpty())
  580. {
  581. return false;
  582. }
  583. const LLPathfindingLinksetList* listp = objects.get()->asLinksetList();
  584. return listp && listp->showCannotBeVolumeWarning(use);
  585. }
  586. void LLFloaterPathfindingLinksets::updateStateOnEditFields()
  587. {
  588. bool enabled = getNumSelectedObjects() > 0;
  589. mEditLinksetUse->setEnabled(enabled);
  590. mLabelCoefficients->setEnabled(enabled);
  591. mLabelEditA->setEnabled(enabled);
  592. mLabelEditB->setEnabled(enabled);
  593. mLabelEditC->setEnabled(enabled);
  594. mLabelEditD->setEnabled(enabled);
  595. mLabelSuggestedUseA->setEnabled(enabled);
  596. mLabelSuggestedUseB->setEnabled(enabled);
  597. mLabelSuggestedUseC->setEnabled(enabled);
  598. mLabelSuggestedUseD->setEnabled(enabled);
  599. mEditA->setEnabled(enabled);
  600. mEditB->setEnabled(enabled);
  601. mEditC->setEnabled(enabled);
  602. mEditD->setEnabled(enabled);
  603. mApplyEditsButton->setEnabled(enabled &&
  604. getMessagingState() == kMessagingComplete);
  605. }
  606. void LLFloaterPathfindingLinksets::updateStateOnEditLinksetUse()
  607. {
  608. bool walkable = false;
  609. bool static_obstacle = false;
  610. bool dynamic_obstacle = false;
  611. bool material_volume = false;
  612. bool exclusion_volume = false;
  613. bool dynamic_phantom = false;
  614. LLPathfindingObjectList::ptr_t objects = getSelectedObjects();
  615. if (objects && !objects->isEmpty())
  616. {
  617. const LLPathfindingLinksetList* listp = objects.get()->asLinksetList();
  618. if (listp)
  619. {
  620. listp->determinePossibleStates(walkable, static_obstacle,
  621. dynamic_obstacle, material_volume,
  622. exclusion_volume, dynamic_phantom);
  623. }
  624. }
  625. mUseWalkable->setEnabled(walkable);
  626. mUseStaticObstacle->setEnabled(static_obstacle);
  627. mUseDynamicObstacle->setEnabled(dynamic_obstacle);
  628. mUseMaterialVolume->setEnabled(material_volume);
  629. mUseExclusionVolume->setEnabled(exclusion_volume);
  630. mUseDynamicPhantom->setEnabled(dynamic_phantom);
  631. }
  632. void LLFloaterPathfindingLinksets::applyEdit()
  633. {
  634. LLPathfindingLinkset::ELinksetUse use = getEditLinksetUse();
  635. bool warn_phantom = showPhantomToggleWarning(use);
  636. bool warn_nomod = showUnmodifiablePhantomWarning(use);
  637. bool warn_no_vol = showCannotBeVolumeWarning(use);
  638. if (!warn_phantom && !warn_nomod && !warn_no_vol)
  639. {
  640. doApplyEdit();
  641. return;
  642. }
  643. LLPathfindingLinkset::ELinksetUse restricted_use =
  644. LLPathfindingLinkset::getLinksetUseWithToggledPhantom(use);
  645. LLSD substitutions;
  646. substitutions["REQUESTED_TYPE"] = getLinksetUseString(use);
  647. substitutions["RESTRICTED_TYPE"] = getLinksetUseString(restricted_use);
  648. // Build one of the following notifications names
  649. // - PathfindingLinksets_WarnOnPhantom
  650. // - PathfindingLinksets_WarnOnPhantom_MismatchOnRestricted
  651. // - PathfindingLinksets_WarnOnPhantom_MismatchOnVolume
  652. // - PathfindingLinksets_WarnOnPhantom_MismatchOnRestricted_MismatchOnVolume
  653. // - PathfindingLinksets_MismatchOnRestricted
  654. // - PathfindingLinksets_MismatchOnVolume
  655. // - PathfindingLinksets_MismatchOnRestricted_MismatchOnVolume
  656. std::string notification = "PathfindingLinksets";
  657. if (warn_phantom)
  658. {
  659. notification += "_WarnOnPhantom";
  660. }
  661. if (warn_nomod)
  662. {
  663. notification += "_MismatchOnRestricted";
  664. }
  665. if (warn_no_vol)
  666. {
  667. notification += "_MismatchOnVolume";
  668. }
  669. gNotifications.add(notification, substitutions, LLSD(),
  670. boost::bind(&LLFloaterPathfindingLinksets::handleApplyEdit,
  671. this, _1, _2));
  672. }
  673. void LLFloaterPathfindingLinksets::handleApplyEdit(const LLSD& notification,
  674. const LLSD& response)
  675. {
  676. if (LLNotification::getSelectedOption(notification, response) == 0)
  677. {
  678. doApplyEdit();
  679. }
  680. }
  681. void LLFloaterPathfindingLinksets::doApplyEdit()
  682. {
  683. LLPathfindingObjectList::ptr_t objects = getSelectedObjects();
  684. if (objects && !objects->isEmpty())
  685. {
  686. S32 a = atoi(mEditA->getText().c_str());
  687. S32 b = atoi(mEditB->getText().c_str());
  688. S32 c = atoi(mEditC->getText().c_str());
  689. S32 d = atoi(mEditD->getText().c_str());
  690. requestSetLinksets(objects, getEditLinksetUse(), a, b, c, d);
  691. }
  692. }
  693. std::string LLFloaterPathfindingLinksets::getLinksetUseString(LLPathfindingLinkset::ELinksetUse use) const
  694. {
  695. switch (use)
  696. {
  697. case LLPathfindingLinkset::kWalkable:
  698. {
  699. static std::string walkable = getString("linkset_use_walkable");
  700. return walkable;
  701. }
  702. case LLPathfindingLinkset::kStaticObstacle:
  703. {
  704. static std::string sobstacle =
  705. getString("linkset_use_static_obstacle");
  706. return sobstacle;
  707. }
  708. case LLPathfindingLinkset::kMaterialVolume:
  709. {
  710. static std::string material =
  711. getString("linkset_use_material_volume");
  712. return material;
  713. }
  714. case LLPathfindingLinkset::kExclusionVolume:
  715. {
  716. static std::string exclusion =
  717. getString("linkset_use_exclusion_volume");
  718. return exclusion;
  719. }
  720. case LLPathfindingLinkset::kDynamicPhantom:
  721. {
  722. static std::string phantom =
  723. getString("linkset_use_dynamic_phantom");
  724. return phantom;
  725. }
  726. default:
  727. {
  728. llassert(use == LLPathfindingLinkset::kDynamicObstacle);
  729. static std::string dobstacle =
  730. getString("linkset_use_dynamic_obstacle");
  731. return dobstacle;
  732. }
  733. }
  734. }
  735. LLPathfindingLinkset::ELinksetUse LLFloaterPathfindingLinksets::getFilterLinksetUse() const
  736. {
  737. return convertToLinksetUse(mFilterByLinksetUse->getValue());
  738. }
  739. void LLFloaterPathfindingLinksets::setFilterLinksetUse(LLPathfindingLinkset::ELinksetUse use)
  740. {
  741. mFilterByLinksetUse->setValue(convertToXuiValue(use));
  742. }
  743. LLPathfindingLinkset::ELinksetUse LLFloaterPathfindingLinksets::getEditLinksetUse() const
  744. {
  745. return convertToLinksetUse(mEditLinksetUse->getValue());
  746. }
  747. void LLFloaterPathfindingLinksets::setEditLinksetUse(LLPathfindingLinkset::ELinksetUse use)
  748. {
  749. mEditLinksetUse->setValue(convertToXuiValue(use));
  750. }
  751. LLPathfindingLinkset::ELinksetUse LLFloaterPathfindingLinksets::convertToLinksetUse(LLSD value) const
  752. {
  753. switch (value.asInteger())
  754. {
  755. case XUI_LINKSET_USE_NONE:
  756. return LLPathfindingLinkset::kUnknown;
  757. case XUI_LINKSET_USE_WALKABLE:
  758. return LLPathfindingLinkset::kWalkable;
  759. case XUI_LINKSET_USE_STATIC_OBSTACLE:
  760. return LLPathfindingLinkset::kStaticObstacle;
  761. case XUI_LINKSET_USE_DYNAMIC_OBSTACLE:
  762. return LLPathfindingLinkset::kDynamicObstacle;
  763. case XUI_LINKSET_USE_MATERIAL_VOLUME:
  764. return LLPathfindingLinkset::kMaterialVolume;
  765. case XUI_LINKSET_USE_EXCLUSION_VOLUME:
  766. return LLPathfindingLinkset::kExclusionVolume;
  767. case XUI_LINKSET_USE_DYNAMIC_PHANTOM:
  768. return LLPathfindingLinkset::kDynamicPhantom;
  769. default:
  770. llassert(false);
  771. return LLPathfindingLinkset::kUnknown;
  772. }
  773. }
  774. LLSD LLFloaterPathfindingLinksets::convertToXuiValue(LLPathfindingLinkset::ELinksetUse use) const
  775. {
  776. switch (use)
  777. {
  778. case LLPathfindingLinkset::kUnknown:
  779. return LLSD(XUI_LINKSET_USE_NONE);
  780. case LLPathfindingLinkset::kWalkable:
  781. return LLSD(XUI_LINKSET_USE_WALKABLE);
  782. case LLPathfindingLinkset::kStaticObstacle:
  783. return LLSD(XUI_LINKSET_USE_STATIC_OBSTACLE);
  784. case LLPathfindingLinkset::kDynamicObstacle:
  785. return LLSD(XUI_LINKSET_USE_DYNAMIC_OBSTACLE);
  786. case LLPathfindingLinkset::kMaterialVolume:
  787. return LLSD(XUI_LINKSET_USE_MATERIAL_VOLUME);
  788. case LLPathfindingLinkset::kExclusionVolume:
  789. return LLSD(XUI_LINKSET_USE_EXCLUSION_VOLUME);
  790. case LLPathfindingLinkset::kDynamicPhantom:
  791. return LLSD(XUI_LINKSET_USE_DYNAMIC_PHANTOM);
  792. default:
  793. llassert(false);
  794. return LLSD(XUI_LINKSET_USE_NONE);
  795. }
  796. }