hbpanellandenvironment.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. /**
  2. * @file hbpanellandenvironment.cpp
  3. * @brief Configuration of environmemt settings for land (parcel or region).
  4. *
  5. * $LicenseInfo:firstyear=2019&license=viewergpl$
  6. *
  7. * Copyright (c) 2019-2023 Henri Beauchamp
  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 "boost/pointer_cast.hpp"
  34. #include "hbpanellandenvironment.h"
  35. #include "llbutton.h"
  36. #include "llcheckboxctrl.h"
  37. #include "lldate.h"
  38. #include "llmultisliderctrl.h"
  39. #include "llnotifications.h"
  40. #include "llparcel.h"
  41. #include "llsliderctrl.h"
  42. #include "lltextbox.h"
  43. #include "lluictrlfactory.h"
  44. #include "llagent.h"
  45. #include "llappviewer.h" // For gFrameTimeSeconds
  46. #include "llenvsettings.h"
  47. #include "hbfloatereditenvsettings.h"
  48. #include "hbfloaterinvitemspicker.h"
  49. #include "llfloaterregioninfo.h" // For LLEstateInfoModel
  50. #include "llinventorymodel.h"
  51. #include "llviewerparcelmgr.h"
  52. #include "llviewerregion.h"
  53. #include "llworld.h"
  54. #include "roles_constants.h"
  55. //-----------------------------------------------------------------------------
  56. // HBSettingsDropTarget class - UI element for settings drop targets. It also
  57. // handles automatically click-selection via the inventory items picker.
  58. //-----------------------------------------------------------------------------
  59. class HBSettingsDropTarget final : public LLView
  60. {
  61. protected:
  62. LOG_CLASS(HBSettingsDropTarget);
  63. public:
  64. HBSettingsDropTarget(LLView* parentp, HBPanelLandEnvironment* panelp,
  65. S32 track)
  66. : LLView(parentp->getName() + "_area", false),
  67. mLandEnvironmentPanel(panelp),
  68. mTrack(track)
  69. {
  70. setFollows(FOLLOWS_LEFT | FOLLOWS_TOP);
  71. LLRect rect = parentp->getRect();
  72. setRect(rect);
  73. // Adjust rect so to be within the parent view (usually a view border)
  74. ++rect.mBottom;
  75. --rect.mTop;
  76. rect.mLeft += 2;
  77. rect.mRight -= 2;
  78. // Create a text box associated with our drop target view
  79. mDropTargetText = new LLTextBox(parentp->getName() + "_text", rect, "",
  80. LLFontGL::getFontSansSerifSmall(),
  81. true); // Opaque text box
  82. // Add as a child of our owner panel
  83. panelp->addChild(mDropTargetText);
  84. // Add ourselves as a child of the panel: this must be done *after* the
  85. // text box was added, so that the drop target view is on top (note
  86. // that it is however not opaque to mouse: tool tip hovers and clicks
  87. // do get to the underlying text box).
  88. panelp->addChild(this);
  89. // Prettify the text box with centered text and an adequate tool tip
  90. mDropTargetText->setHAlign(LLFontGL::HCENTER);
  91. std::string tooltip = panelp->getString(track ? "sky_tool_tip"
  92. : "water_tool_tip");
  93. mDropTargetText->setToolTip(tooltip);
  94. // Setup click-action on the text of the drop target (inventory picker
  95. // call)
  96. mDropTargetText->setClickedCallback(onTextClicked, this);
  97. }
  98. void setEnabled(bool enabled) override
  99. {
  100. mDropTargetText->setEnabled(enabled);
  101. LLView::setEnabled(enabled);
  102. }
  103. bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
  104. EDragAndDropType cargo_type,
  105. void* cargo_data, EAcceptance* accept,
  106. std::string& tooltip_msg) override
  107. {
  108. // Careful: pointInView() gets f*cked up whenever the panel is embedded
  109. // inside a layout stack.
  110. if (!getEnabled() || !pointInView(x, y))
  111. {
  112. return false;
  113. }
  114. *accept = ACCEPT_NO;
  115. if (cargo_type == DAD_SETTINGS)
  116. {
  117. LLSettingsType::EType type = mTrack ? LLSettingsType::ST_SKY
  118. : LLSettingsType::ST_WATER;
  119. LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)cargo_data;
  120. if (itemp && gInventory.getItem(itemp->getUUID()) &&
  121. itemp->getSettingsType() == type)
  122. {
  123. *accept = ACCEPT_YES_COPY_SINGLE;
  124. if (drop)
  125. {
  126. // Auto-update our text with the dropped item name
  127. mDropTargetText->setText(itemp->getName());
  128. // Inform our owner about the user choice
  129. mLandEnvironmentPanel->onChoosenItem(itemp, mTrack);
  130. }
  131. }
  132. }
  133. return true;
  134. }
  135. LL_INLINE void setText(const std::string& text)
  136. {
  137. mDropTargetText->setText(text);
  138. }
  139. LL_INLINE const std::string& getText()
  140. {
  141. return mDropTargetText->getText();
  142. }
  143. private:
  144. static void invItemsPickerCallback(const std::vector<std::string>&,
  145. const uuid_vec_t& ids, void* userdata,
  146. bool)
  147. {
  148. HBSettingsDropTarget* self = (HBSettingsDropTarget*)userdata;
  149. if (!self || ids.empty())
  150. {
  151. return;
  152. }
  153. LLUUID inv_id = ids[0];
  154. // Make sure we are not trying to use a link and get the linked item
  155. // Id in that case.
  156. if (inv_id.notNull())
  157. {
  158. inv_id = gInventory.getLinkedItemID(inv_id);
  159. }
  160. LLViewerInventoryItem* itemp = gInventory.getItem(inv_id);
  161. if (itemp)
  162. {
  163. // Auto-update our text with the dropped item name
  164. self->mDropTargetText->setText(itemp->getName());
  165. // Inform our owner about the user choice
  166. self->mLandEnvironmentPanel->onChoosenItem(itemp, self->mTrack);
  167. }
  168. }
  169. static void onTextClicked(void* userdata)
  170. {
  171. HBSettingsDropTarget* self = (HBSettingsDropTarget*)userdata;
  172. if (!self || !self->getEnabled())
  173. {
  174. return;
  175. }
  176. HBFloaterInvItemsPicker* pickerp =
  177. new HBFloaterInvItemsPicker(self, invItemsPickerCallback, self);
  178. if (pickerp)
  179. {
  180. S32 sub_type = self->mTrack ? LLSettingsType::ST_SKY
  181. : LLSettingsType::ST_WATER;
  182. pickerp->setAssetType(LLAssetType::AT_SETTINGS, sub_type);
  183. }
  184. }
  185. private:
  186. HBPanelLandEnvironment* mLandEnvironmentPanel;
  187. LLTextBox* mDropTargetText;
  188. S32 mTrack;
  189. };
  190. //-----------------------------------------------------------------------------
  191. // HBPanelLandEnvironment class proper
  192. //-----------------------------------------------------------------------------
  193. static LLSafeHandle<LLParcelSelection> sDummyParcelHandle;
  194. HBPanelLandEnvironment::HBPanelLandEnvironment(LLParcelSelectionHandle& parcel)
  195. : mParcel(parcel),
  196. mRegionHandle(0),
  197. mIsRegion(false),
  198. mDayParametersDirty(false),
  199. mEnvOverrideCheck(false),
  200. mLastEnabledState(false),
  201. mLastParametersChange(0.f),
  202. mLastTimeOfDayUpdate(0.f),
  203. mCurEnvVersion(INVALID_PARCEL_ENVIRONMENT_VERSION),
  204. mLastParcelId(INVALID_PARCEL_ID)
  205. {
  206. LLUICtrlFactory::getInstance()->buildPanel(this,
  207. "panel_land_environment.xml");
  208. }
  209. HBPanelLandEnvironment::HBPanelLandEnvironment(U64 region_handle)
  210. : mParcel(sDummyParcelHandle),
  211. mRegionHandle(region_handle),
  212. mIsRegion(true),
  213. mDayParametersDirty(false),
  214. mLastParametersChange(0.f),
  215. mCurEnvVersion(INVALID_PARCEL_ENVIRONMENT_VERSION),
  216. mLastParcelId(INVALID_PARCEL_ID)
  217. {
  218. LLUICtrlFactory::getInstance()->buildPanel(this,
  219. "panel_land_environment.xml");
  220. }
  221. //virtual
  222. HBPanelLandEnvironment::~HBPanelLandEnvironment()
  223. {
  224. if (mChangeConnection.connected())
  225. {
  226. mChangeConnection.disconnect();
  227. }
  228. closeEditFloater(true);
  229. }
  230. //virtual
  231. bool HBPanelLandEnvironment::postBuild()
  232. {
  233. mUseDefaultBtn = getChild<LLButton>("use_default_btn");
  234. mUseDefaultBtn->setClickedCallback(onBtnDefault, this);
  235. if (!mIsRegion)
  236. {
  237. mUseDefaultBtn->setLabel(getString("region_settings_label"));
  238. }
  239. mUseInventoryBtn = getChild<LLButton>("use_inventory_btn");
  240. mUseInventoryBtn->setClickedCallback(onBtnInventory, this);
  241. mUseCustomBtn = getChild<LLButton>("use_custom_btn");
  242. mUseCustomBtn->setClickedCallback(onBtnCustom, this);
  243. mResetAltitudesBtn = getChild<LLButton>("reset_alts_btn");
  244. mResetAltitudesBtn->setClickedCallback(onBtnReset, this);
  245. mAllowOverrideCheck = getChild<LLCheckBoxCtrl>("allow_override_chk");
  246. if (mIsRegion)
  247. {
  248. mAllowOverrideCheck->setCommitCallback(onAllowOverride);
  249. mAllowOverrideCheck->setCallbackUserData(this);
  250. }
  251. else
  252. {
  253. mAllowOverrideCheck->setVisible(false);
  254. }
  255. mDayLengthSlider = getChild<LLSliderCtrl>("day_length_sld");
  256. mDayLengthSlider->setCommitCallback(onDayParametersChanged);
  257. mDayLengthSlider->setCallbackUserData(this);
  258. mDayOffsetSlider = getChild<LLSliderCtrl>("day_offset_sld");
  259. mDayOffsetSlider->setCommitCallback(onDayParametersChanged);
  260. mDayOffsetSlider->setCallbackUserData(this);
  261. mApparentDayLengthText = getChild<LLTextBox>("day_time_value_txt");
  262. mAltitude2ValueText = getChild<LLTextBox>("alt2_value_txt");
  263. mAltitude3ValueText = getChild<LLTextBox>("alt3_value_txt");
  264. mAltitude4ValueText = getChild<LLTextBox>("alt4_value_txt");
  265. mAltitudesSlider = getChild<LLMultiSliderCtrl>("altitudes_sld");
  266. mAltitudesSlider->setCommitCallback(onAltSliderCommit);
  267. mAltitudesSlider->setCallbackUserData(this);
  268. mAltitudesSlider->setSliderMouseUpCallback(onAltSliderMouseUp);
  269. mAltitudesSlider->addSlider(1000.f, "sld1");
  270. mAltitudesSlider->addSlider(2000.f, "sld2");
  271. mAltitudesSlider->addSlider(3000.f, "sld3");
  272. LLView* parent_viewp = getChild<LLView>("water_drop_tgt");
  273. HBSettingsDropTarget* targetp = new HBSettingsDropTarget(parent_viewp,
  274. this, 0);
  275. mDropTargets.push_back(targetp);
  276. parent_viewp = getChild<LLView>("alt1_drop_tgt");
  277. targetp = new HBSettingsDropTarget(parent_viewp, this, 1);
  278. mDropTargets.push_back(targetp);
  279. parent_viewp = getChild<LLView>("alt2_drop_tgt");
  280. targetp = new HBSettingsDropTarget(parent_viewp, this, 2);
  281. mDropTargets.push_back(targetp);
  282. parent_viewp = getChild<LLView>("alt3_drop_tgt");
  283. targetp = new HBSettingsDropTarget(parent_viewp, this, 3);
  284. mDropTargets.push_back(targetp);
  285. parent_viewp = getChild<LLView>("alt4_drop_tgt");
  286. targetp = new HBSettingsDropTarget(parent_viewp, this, 4);
  287. mDropTargets.push_back(targetp);
  288. refresh();
  289. mChangeConnection =
  290. gEnvironment.setEnvironmentChanged([this](LLEnvironment::EEnvSelection env,
  291. S32 version)
  292. {
  293. onEnvironmentChanged(env, version);
  294. });
  295. if (mIsRegion)
  296. {
  297. refreshFromRegion();
  298. }
  299. return true;
  300. }
  301. //virtual
  302. void HBPanelLandEnvironment::setEnabled(bool enabled)
  303. {
  304. bool inv_ok = enabled && gAgent.hasInventorySettings();
  305. mUseDefaultBtn->setEnabled(enabled);
  306. mUseInventoryBtn->setEnabled(inv_ok);
  307. mUseCustomBtn->setEnabled(enabled);
  308. mAllowOverrideCheck->setEnabled(enabled);
  309. mDayLengthSlider->setEnabled(enabled);
  310. mDayOffsetSlider->setEnabled(enabled);
  311. mAltitudesSlider->setEnabled(enabled && mIsRegion);
  312. mResetAltitudesBtn->setEnabled(enabled && mIsRegion);
  313. for (U32 i = 0, count = mDropTargets.size(); i < count; ++i)
  314. {
  315. mDropTargets[i]->setEnabled(inv_ok);
  316. }
  317. LLPanel::setEnabled(enabled);
  318. }
  319. //virtual
  320. void HBPanelLandEnvironment::draw()
  321. {
  322. if (!mIsRegion && mLastParcelId != getParcelId())
  323. {
  324. refreshFromParcel();
  325. }
  326. if (mDayParametersDirty && gFrameTimeSeconds - mLastParametersChange > 1.f)
  327. {
  328. mDayParametersDirty = false;
  329. commitDayParametersChanges();
  330. }
  331. // While the editor floater is opened, disable all other ways to change
  332. // the land settings...
  333. bool enable = getEnabled() && mEditFloaterHandle.isDead();
  334. if (mLastEnabledState != enable)
  335. {
  336. mUseDefaultBtn->setEnabled(enable);
  337. mUseCustomBtn->setEnabled(enable);
  338. mUseInventoryBtn->setEnabled(enable);
  339. for (U32 i = 0, count = mDropTargets.size(); i < count; ++i)
  340. {
  341. mDropTargets[i]->setEnabled(enable);
  342. }
  343. mLastEnabledState = enable;
  344. }
  345. // Update the apparent time of day text every 5 seconds (meaning every 30
  346. // seconds of apparent day time when the day length is set to the minimum
  347. // of 4 hours), which is more than enough.
  348. if (gFrameTimeSeconds - mLastTimeOfDayUpdate > 5.f)
  349. {
  350. updateApparentTimeOfDay();
  351. }
  352. LLPanel::draw();
  353. }
  354. //virtual
  355. void HBPanelLandEnvironment::refresh()
  356. {
  357. bool edit_ok = false;
  358. if (isAgentRegion())
  359. {
  360. LLViewerRegion* regionp = gAgent.getRegion();
  361. bool can_override_region = regionp->getAllowEnvironmentOverride();
  362. if (mIsRegion)
  363. {
  364. edit_ok = LLEnvironment::canAgentUpdateRegionEnvironment();
  365. mEnvOverrideCheck =
  366. can_override_region ||
  367. LLEstateInfoModel::getAllowEnvironmentOverride();
  368. mAllowOverrideCheck->set(mEnvOverrideCheck);
  369. }
  370. else
  371. {
  372. LLParcel* parcelp = mParcel->getParcel();
  373. edit_ok = parcelp && can_override_region &&
  374. LLEnvironment::canAgentUpdateParcelEnvironment(parcelp);
  375. }
  376. }
  377. setEnabled(edit_ok);
  378. // Update day length and offset sliders
  379. if (mCurrentEnvironment)
  380. {
  381. constexpr F32 SEC2HOURS = 1.f / 3600.f;
  382. F32 day_length = mCurrentEnvironment->mDayLength * SEC2HOURS;
  383. mDayLengthSlider->setValue(day_length);
  384. F32 day_offset = mCurrentEnvironment->mDayOffset * SEC2HOURS;
  385. if (day_offset > 12.f)
  386. {
  387. day_offset -= 24.f;
  388. }
  389. mDayOffsetSlider->setValue(day_offset);
  390. }
  391. updateApparentTimeOfDay();
  392. if (mCurrentEnvironment)
  393. {
  394. F32 min = mAltitudesSlider->getMinValue();
  395. F32 max = mAltitudesSlider->getMaxValue();
  396. LLEnvironment::altitude_list_t alts = mCurrentEnvironment->mAltitudes;
  397. // Manually unrolled loop to avoid llformat() usage for slider names
  398. F32 altitude = llclamp(alts[1], min, max);
  399. mAltitudesSlider->setSliderValue("sld1", altitude);
  400. altitude = llclamp(alts[2], min, max);
  401. mAltitudesSlider->setSliderValue("sld2", altitude);
  402. altitude = llclamp(alts[3], min, max);
  403. mAltitudesSlider->setSliderValue("sld3", altitude);
  404. }
  405. updateAltitudeLabels();
  406. updateTrackNames();
  407. }
  408. void HBPanelLandEnvironment::resetOverride()
  409. {
  410. mAllowOverrideCheck->set(mEnvOverrideCheck);
  411. }
  412. void HBPanelLandEnvironment::updateApparentTimeOfDay()
  413. {
  414. mLastTimeOfDayUpdate = gFrameTimeSeconds;
  415. if (!mCurrentEnvironment || mCurrentEnvironment->mDayLength < 1 ||
  416. mCurrentEnvironment->mDayOffset < 1)
  417. {
  418. mApparentDayLengthText->setVisible(false);
  419. return;
  420. }
  421. mApparentDayLengthText->setVisible(true);
  422. S64 now = LLTimer::getEpochSeconds() + mCurrentEnvironment->mDayOffset;
  423. F32 percent = F32(now % mCurrentEnvironment->mDayLength) /
  424. F32(mCurrentEnvironment->mDayLength);
  425. S32 seconds = S32(86400.f * percent);
  426. S32 hours = seconds / 3600;
  427. S32 minutes = (seconds - 3600 * hours) / 60;
  428. if (minutes == 60)
  429. {
  430. ++hours;
  431. minutes = 0;
  432. }
  433. std::string time;
  434. if (minutes < 10)
  435. {
  436. time = llformat("%d:0%d", hours, minutes);
  437. }
  438. else
  439. {
  440. time = llformat("%d:%d", hours, minutes);
  441. }
  442. if (hours < 10)
  443. {
  444. time = llformat("%d%% (0%s)", (S32)(percent * 100.f),
  445. time.c_str());
  446. }
  447. else
  448. {
  449. time = llformat("%d%% (%s)", (S32)(percent * 100.f), time.c_str());
  450. }
  451. mApparentDayLengthText->setText(time);
  452. }
  453. void HBPanelLandEnvironment::updateAltitudeLabels()
  454. {
  455. std::set<S32> alts; // Using a std::set to auto-sort by value on insertion
  456. // Manually unrolled loop to avoid llformat() usage for slider names
  457. alts.insert((S32)mAltitudesSlider->getSliderValue("sld1"));
  458. alts.insert((S32)mAltitudesSlider->getSliderValue("sld2"));
  459. alts.insert((S32)mAltitudesSlider->getSliderValue("sld3"));
  460. std::set<S32>::iterator it = alts.begin();
  461. mAltitude2ValueText->setTextArg("[ALT]", llformat("%d", *it));
  462. mAltitude3ValueText->setTextArg("[ALT]", llformat("%d", *(++it)));
  463. mAltitude4ValueText->setTextArg("[ALT]", llformat("%d", *(++it)));
  464. }
  465. void HBPanelLandEnvironment::updateTrackNames()
  466. {
  467. for (S32 i = 0, count = mDropTargets.size(); i < count; ++i)
  468. {
  469. HBSettingsDropTarget* targetp = mDropTargets[i];
  470. targetp->setText(getNameForTrack(i));
  471. }
  472. }
  473. std::string HBPanelLandEnvironment::getNameForTrack(S32 track)
  474. {
  475. if (!mCurrentEnvironment || track < LLSettingsDay::TRACK_WATER ||
  476. track >= LLSettingsDay::TRACK_MAX)
  477. {
  478. return getString("empty");
  479. }
  480. std::string name;
  481. if (mCurrentEnvironment->mDayCycleName.empty())
  482. {
  483. name = mCurrentEnvironment->mNameList[track];
  484. if (name.empty() && track <= LLSettingsDay::TRACK_GROUND_LEVEL)
  485. {
  486. name = getString(mIsRegion ? "empty" : "region_env");
  487. }
  488. }
  489. else if (!mCurrentEnvironment->mDayCycle->isTrackEmpty(track))
  490. {
  491. name = mCurrentEnvironment->mDayCycleName;
  492. }
  493. if (name.empty())
  494. {
  495. name = getNameForTrack(track - 1);
  496. }
  497. return name;
  498. }
  499. void HBPanelLandEnvironment::setRegionHandle(U64 handle)
  500. {
  501. mRegionHandle = handle;
  502. refresh(); // Refresh unconditionnally
  503. }
  504. LLViewerRegion* HBPanelLandEnvironment::getRegion()
  505. {
  506. return mIsRegion ? gWorld.getRegionFromHandle(mRegionHandle) : NULL;
  507. }
  508. LLParcel* HBPanelLandEnvironment::getParcel()
  509. {
  510. return !mIsRegion && mParcel ? mParcel->getParcel() : NULL;
  511. }
  512. S32 HBPanelLandEnvironment::getParcelId()
  513. {
  514. LLParcel* parcelp = getParcel();
  515. return parcelp ? parcelp->getLocalID() : INVALID_PARCEL_ID;
  516. }
  517. bool HBPanelLandEnvironment::isAgentRegion()
  518. {
  519. LLViewerRegion* selected_regionp = gViewerParcelMgr.getSelectionRegion();
  520. LLViewerRegion* agent_regionp = gAgent.getRegion();
  521. return agent_regionp &&
  522. (!selected_regionp ||
  523. selected_regionp->getRegionID() == agent_regionp->getRegionID());
  524. }
  525. void HBPanelLandEnvironment::refreshFromRegion()
  526. {
  527. LLHandle<LLPanel> handle = getHandle();
  528. gEnvironment.requestRegion([handle](S32 parcel_id,
  529. LLEnvironment::envinfo_ptr_t info)
  530. {
  531. HBPanelLandEnvironment* self =
  532. (HBPanelLandEnvironment*)handle.get();
  533. if (!self) return;
  534. self->onEnvironmentReceived(parcel_id, info);
  535. });
  536. }
  537. void HBPanelLandEnvironment::refreshFromParcel()
  538. {
  539. LLParcel* parcelp = getParcel();
  540. if (!parcelp || !isAgentRegion())
  541. {
  542. mLastParcelId = INVALID_PARCEL_ID;
  543. mCurrentEnvironment.reset();
  544. mCurEnvVersion = INVALID_PARCEL_ENVIRONMENT_VERSION;
  545. refresh();
  546. return;
  547. }
  548. // Parcel is valid; poceeed...
  549. mLastParcelId = parcelp->getLocalID();
  550. if (mCurEnvVersion < UNSET_PARCEL_ENVIRONMENT_VERSION)
  551. {
  552. // Mark as pending
  553. mCurEnvVersion = parcelp->getParcelEnvironmentVersion();
  554. }
  555. LLHandle<LLPanel> handle = getHandle();
  556. gEnvironment.requestParcel(mLastParcelId,
  557. [handle](S32 parcel_id,
  558. LLEnvironment::envinfo_ptr_t info)
  559. {
  560. HBPanelLandEnvironment* self =
  561. (HBPanelLandEnvironment*)handle.get();
  562. if (!self) return;
  563. self->onEnvironmentReceived(parcel_id, info);
  564. });
  565. }
  566. void HBPanelLandEnvironment::onEnvironmentChanged(LLEnvironment::EEnvSelection env,
  567. S32 version)
  568. {
  569. if (version < INVALID_PARCEL_ENVIRONMENT_VERSION)
  570. {
  571. // This is likely a cleanup or local change; we are only interested in
  572. // changes sent by server, so ignore that.
  573. return;
  574. }
  575. // Environment comes from different sources: update callbacks, hovers
  576. // (causes callbacks on version change) and from personal requests.
  577. // Filter out duplicates and out of order packets by checking parcel
  578. // environment version.
  579. if (mIsRegion)
  580. {
  581. // 'version' should be always growing. UNSET_PARCEL_ENVIRONMENT_VERSION
  582. // is the backup case.
  583. if (env == LLEnvironment::ENV_REGION && version > mCurEnvVersion &&
  584. mCurEnvVersion >= UNSET_PARCEL_ENVIRONMENT_VERSION)
  585. {
  586. if (version >= UNSET_PARCEL_ENVIRONMENT_VERSION)
  587. {
  588. // Set a "pending state" to prevent re-request on following
  589. // onEnvironmentChanged should there be any...
  590. mCurEnvVersion = version;
  591. }
  592. mCurrentEnvironment.reset();
  593. refreshFromRegion();
  594. }
  595. }
  596. else if (env == LLEnvironment::ENV_PARCEL &&
  597. gViewerParcelMgr.getAgentParcelId() == getParcelId())
  598. {
  599. LLParcel* parcelp = getParcel();
  600. if (!parcelp)
  601. {
  602. return;
  603. }
  604. // First test for parcel own settings, second for when the parcel uses
  605. // the region settings
  606. if (version > mCurEnvVersion ||
  607. version == UNSET_PARCEL_ENVIRONMENT_VERSION)
  608. {
  609. // Set a "pending state" to prevent re-request on following
  610. // onEnvironmentChanged should there be any...
  611. mCurEnvVersion = version;
  612. mCurrentEnvironment.reset();
  613. refreshFromParcel();
  614. }
  615. else if (mCurrentEnvironment)
  616. {
  617. refresh(); // Update the UI anyway
  618. }
  619. }
  620. }
  621. void HBPanelLandEnvironment::onEnvironmentReceived(S32 parcel_id,
  622. LLEnvironment::envinfo_ptr_t info)
  623. {
  624. if (parcel_id != getParcelId())
  625. {
  626. llwarns << "Got environment for parcel " << parcel_id
  627. << " while expecting " << getParcelId() << ". Discarding."
  628. << llendl;
  629. return;
  630. }
  631. mCurrentEnvironment = info;
  632. if (mCurrentEnvironment->mEnvVersion > INVALID_PARCEL_ENVIRONMENT_VERSION)
  633. {
  634. mCurEnvVersion = mCurrentEnvironment->mEnvVersion;
  635. }
  636. else
  637. {
  638. llwarns << "Environment version was not provided for " << parcel_id
  639. << ". Retaining old version: " << mCurEnvVersion << llendl;
  640. }
  641. refresh();
  642. }
  643. void HBPanelLandEnvironment::commitDayParametersChanges()
  644. {
  645. if (!mCurrentEnvironment)
  646. {
  647. return;
  648. }
  649. LLHandle<LLPanel> handle = getHandle();
  650. gEnvironment.updateParcel(getParcelId(), LLSettingsDay::ptr_t(),
  651. mCurrentEnvironment->mDayLength,
  652. mCurrentEnvironment->mDayOffset,
  653. LLEnvironment::altitudes_vect_t(),
  654. [handle](S32 parcel_id,
  655. LLEnvironment::envinfo_ptr_t info)
  656. {
  657. HBPanelLandEnvironment* self =
  658. (HBPanelLandEnvironment*)handle.get();
  659. if (!self) return;
  660. self->onEnvironmentReceived(parcel_id, info);
  661. });
  662. }
  663. void HBPanelLandEnvironment::onChoosenItem(LLViewerInventoryItem* itemp,
  664. S32 track)
  665. {
  666. LLHandle<LLPanel> handle = getHandle();
  667. S32 day_length = -1;
  668. S32 day_offset = -1;
  669. if (mCurrentEnvironment)
  670. {
  671. day_length = mCurrentEnvironment->mDayLength;
  672. day_offset = mCurrentEnvironment->mDayOffset;
  673. }
  674. U32 flags = 0;
  675. const LLPermissions& perms = itemp->getPermissions();
  676. if (!perms.allowModifyBy(gAgentID))
  677. {
  678. flags |= LLSettingsBase::FLAG_NOMOD;
  679. }
  680. if (!perms.allowTransferBy(gAgentID))
  681. {
  682. flags |= LLSettingsBase::FLAG_NOTRANS;
  683. }
  684. gEnvironment.updateParcel(getParcelId(), itemp->getAssetUUID(),
  685. itemp->getName(), track,
  686. day_length, day_offset, flags,
  687. LLEnvironment::altitudes_vect_t(),
  688. [handle](S32 parcel_id,
  689. LLEnvironment::envinfo_ptr_t info)
  690. {
  691. HBPanelLandEnvironment* self =
  692. (HBPanelLandEnvironment*)handle.get();
  693. if (!self) return;
  694. self->onEnvironmentReceived(parcel_id, info);
  695. });
  696. }
  697. void HBPanelLandEnvironment::applyDayCycle(LLSettingsDay::ptr_t dayp,
  698. bool edited)
  699. {
  700. if (edited)
  701. {
  702. gEnvironment.clearEnvironment(LLEnvironment::ENV_EDIT);
  703. gEnvironment.updateEnvironment();
  704. }
  705. if (!dayp)
  706. {
  707. llwarns << "No day cycle to apply." << llendl;
  708. return;
  709. }
  710. if (mCurrentEnvironment && mCurrentEnvironment->mDayCycle &&
  711. mCurrentEnvironment->mDayCycle->getHash() == dayp->getHash())
  712. {
  713. llinfos << "No change in environment. Nothing to do." << llendl;
  714. // Nothing changed.
  715. return;
  716. }
  717. if (edited)
  718. {
  719. dayp->setName(getString("custom"));
  720. #if 0 // This does not work, alas...
  721. // *FIXME: environment track names are not displaying properly after
  722. // using "Customized settings" when the former settings were set on
  723. // a per-track basis (via drag and drop or water/sky settings picker).
  724. for (S32 i = 0; i < LLSettingsDay::TRACK_MAX; ++i)
  725. {
  726. LLSettingsDay::cycle_track_t& track = dayp->getCycleTrack(i);
  727. for (LLSettingsDay::cycle_track_it_t it = track.begin(),
  728. end = track.end();
  729. it != end; ++it)
  730. {
  731. it->second->setName("");
  732. }
  733. }
  734. #endif
  735. }
  736. LLHandle<LLPanel> handle = getHandle();
  737. S32 day_length = -1;
  738. S32 day_offset = -1;
  739. if (mCurrentEnvironment)
  740. {
  741. day_length = mCurrentEnvironment->mDayLength;
  742. day_offset = mCurrentEnvironment->mDayOffset;
  743. }
  744. gEnvironment.updateParcel(getParcelId(), dayp, day_length, day_offset,
  745. LLEnvironment::altitudes_vect_t(),
  746. [handle](S32 parcel_id,
  747. LLEnvironment::envinfo_ptr_t info)
  748. {
  749. HBPanelLandEnvironment* self =
  750. (HBPanelLandEnvironment*)handle.get();
  751. if (!self) return;
  752. self->onEnvironmentReceived(parcel_id, info);
  753. });
  754. }
  755. void HBPanelLandEnvironment::loadInventoryItem(LLUUID inv_item_id)
  756. {
  757. // Make sure we are not trying to edit a link and get the linked item Id
  758. // in that case.
  759. if (inv_item_id.notNull())
  760. {
  761. inv_item_id = gInventory.getLinkedItemID(inv_item_id);
  762. }
  763. if (inv_item_id.isNull())
  764. {
  765. llwarns << "Null UUID for inventory item. Aborted." << llendl;
  766. return;
  767. }
  768. LLViewerInventoryItem* itemp = gInventory.getItem(inv_item_id);
  769. if (!itemp || itemp->getIsBrokenLink())
  770. {
  771. llwarns << "Could not find inventory item: " << inv_item_id
  772. << ". Aborted." << llendl;
  773. return;
  774. }
  775. if (!itemp->isSettingsType())
  776. {
  777. llwarns << "Inventory item " << inv_item_id
  778. << " is not an environment settings item. Aborted."
  779. << llendl;
  780. return;
  781. }
  782. LLSettingsType::EType type = itemp->getSettingsType();
  783. if (type != LLSettingsType::ST_DAYCYCLE)
  784. {
  785. llwarns << "Bad environment settings type for inventory item: "
  786. << inv_item_id
  787. << ". Was expecting day cycle type and got type " << type
  788. << ". Aborted." << llendl;
  789. return;
  790. }
  791. const LLUUID& asset_id = itemp->getAssetUUID();
  792. if (asset_id.isNull())
  793. {
  794. llwarns << "Null asset Id for inventory item: " << inv_item_id
  795. << ". Aborted." << llendl;
  796. return;
  797. }
  798. std::string name = itemp->getName();
  799. LLHandle<LLPanel> handle = getHandle();
  800. LLEnvSettingsBase::getSettingsAsset(asset_id,
  801. [handle, name](LLUUID id,
  802. LLSettingsBase::ptr_t settings,
  803. S32 status, LLExtStat)
  804. {
  805. HBPanelLandEnvironment* self =
  806. (HBPanelLandEnvironment*)handle.get();
  807. if (!self) return;
  808. self->onAssetLoaded(name, id,
  809. settings,
  810. status);
  811. });
  812. }
  813. void HBPanelLandEnvironment::onAssetLoaded(const std::string& name,
  814. const LLUUID& asset_id,
  815. LLSettingsBase::ptr_t settings,
  816. S32 status)
  817. {
  818. if (!settings || status)
  819. {
  820. gNotifications.add("CantFindInvItem");
  821. return;
  822. }
  823. LLHandle<LLPanel> handle = getHandle();
  824. LLEnvSettingsDay::buildFromOtherSetting(settings,
  825. [handle, name](LLSettingsDay::ptr_t dayp)
  826. {
  827. HBPanelLandEnvironment* self =
  828. (HBPanelLandEnvironment*)handle.get();
  829. if (!self || !dayp) return;
  830. dayp->setName(name);
  831. self->applyDayCycle(dayp);
  832. });
  833. }
  834. bool HBPanelLandEnvironment::closeEditFloater(bool force)
  835. {
  836. HBFloaterEditEnvSettings* floaterp =
  837. (HBFloaterEditEnvSettings*)mEditFloaterHandle.get();
  838. if (floaterp)
  839. {
  840. if (!force && floaterp->isDirty())
  841. {
  842. return false;
  843. }
  844. if (mCommitConnection.connected())
  845. {
  846. mCommitConnection.disconnect();
  847. }
  848. floaterp->close();
  849. }
  850. return true;
  851. }
  852. //static
  853. void HBPanelLandEnvironment::onBtnDefault(void* userdata)
  854. {
  855. HBPanelLandEnvironment* self = (HBPanelLandEnvironment*)userdata;
  856. if (!self) return;
  857. LLHandle<LLPanel> handle = self->getHandle();
  858. gEnvironment.resetParcel(self->getParcelId(),
  859. [handle](S32 parcel_id,
  860. LLEnvironment::envinfo_ptr_t info)
  861. {
  862. HBPanelLandEnvironment* panelp =
  863. (HBPanelLandEnvironment*)handle.get();
  864. if (!panelp) return;
  865. panelp->onEnvironmentReceived(parcel_id, info);
  866. });
  867. }
  868. //static
  869. void HBPanelLandEnvironment::invPickerCallback(const std::vector<std::string>&,
  870. const uuid_vec_t& ids,
  871. void* userdata, bool)
  872. {
  873. HBPanelLandEnvironment* self = (HBPanelLandEnvironment*)userdata;
  874. if (self && !ids.empty())
  875. {
  876. self->loadInventoryItem(ids[0]);
  877. }
  878. }
  879. //static
  880. void HBPanelLandEnvironment::onBtnInventory(void* userdata)
  881. {
  882. HBPanelLandEnvironment* self = (HBPanelLandEnvironment*)userdata;
  883. if (!self) return;
  884. HBFloaterInvItemsPicker* pickerp =
  885. new HBFloaterInvItemsPicker(self, invPickerCallback, self);
  886. if (pickerp)
  887. {
  888. pickerp->setAssetType(LLAssetType::AT_SETTINGS,
  889. LLSettingsType::ST_DAYCYCLE);
  890. }
  891. }
  892. //static
  893. void HBPanelLandEnvironment::onBtnCustom(void* userdata)
  894. {
  895. HBPanelLandEnvironment* self = (HBPanelLandEnvironment*)userdata;
  896. if (!self) return;
  897. if (!self->closeEditFloater())
  898. {
  899. llwarns << "Editing in progress with unsaved changes. Aborting."
  900. << llendl;
  901. return;
  902. }
  903. HBFloaterEditEnvSettings* floaterp =
  904. HBFloaterEditEnvSettings::create(LLSettingsType::ST_DAYCYCLE);
  905. if (!floaterp) return;
  906. self->mEditFloaterHandle = floaterp->getHandle();
  907. if (self->mIsRegion)
  908. {
  909. floaterp->setEditContextRegion();
  910. }
  911. else
  912. {
  913. floaterp->setEditContextParcel();
  914. }
  915. if (self->mCurrentEnvironment && self->mCurrentEnvironment->mDayCycle)
  916. {
  917. floaterp->setSettings(self->mCurrentEnvironment->mDayCycle);
  918. }
  919. else
  920. {
  921. floaterp->loadDefaultSettings();
  922. }
  923. S32 day_length = 4 * 3600; // Four hours by default
  924. if (self->mCurrentEnvironment)
  925. {
  926. day_length = self->mCurrentEnvironment->mDayLength;
  927. }
  928. floaterp->setDayLength(day_length);
  929. LLHandle<LLPanel> handle = self->getHandle();
  930. self->mCommitConnection =
  931. floaterp->setCommitCB([handle](LLSettingsBase::ptr_t settings)
  932. {
  933. HBPanelLandEnvironment* panelp =
  934. (HBPanelLandEnvironment*)handle.get();
  935. if (!panelp || !settings) return;
  936. LLSettingsDay::ptr_t dayp =
  937. boost::static_pointer_cast<LLSettingsDay>(settings);
  938. panelp->applyDayCycle(dayp, true);
  939. });
  940. }
  941. //static
  942. void HBPanelLandEnvironment::onBtnReset(void* userdata)
  943. {
  944. HBPanelLandEnvironment* self = (HBPanelLandEnvironment*)userdata;
  945. if (!self) return;
  946. LLHandle<LLPanel> handle = self->getHandle();
  947. LLEnvironment::altitudes_vect_t alts;
  948. alts.push_back(1000.f);
  949. alts.push_back(2000.f);
  950. alts.push_back(3000.f);
  951. S32 day_length = -1;
  952. S32 day_offset = -1;
  953. if (self->mCurrentEnvironment)
  954. {
  955. day_length = self->mCurrentEnvironment->mDayLength;
  956. day_offset = self->mCurrentEnvironment->mDayOffset;
  957. }
  958. gEnvironment.updateParcel(self->getParcelId(), LLSettingsDay::ptr_t(),
  959. day_length, day_offset, alts,
  960. [handle](S32 parcel_id,
  961. LLEnvironment::envinfo_ptr_t info)
  962. {
  963. HBPanelLandEnvironment* panelp =
  964. (HBPanelLandEnvironment*)handle.get();
  965. if (!panelp) return;
  966. panelp->onEnvironmentReceived(parcel_id, info);
  967. });
  968. }
  969. //static
  970. void HBPanelLandEnvironment::onAllowOverride(LLUICtrl* ctrl, void* userdata)
  971. {
  972. HBPanelLandEnvironment* self = (HBPanelLandEnvironment*)userdata;
  973. LLCheckBoxCtrl* check = (LLCheckBoxCtrl*)ctrl;
  974. if (!ctrl || !self)
  975. {
  976. return;
  977. }
  978. LLViewerRegion* regionp = self->getRegion();
  979. if (regionp)
  980. {
  981. bool allow = check->get();
  982. self->mEnvOverrideCheck = !allow; // Old value
  983. LLEstateInfoModel::setAllowEnvironmentOverride(allow);
  984. LLPanelEstateInfo* panelp = LLFloaterRegionInfo::getPanelEstate();
  985. if (panelp)
  986. {
  987. panelp->sendUpdate();
  988. }
  989. }
  990. }
  991. //static
  992. void HBPanelLandEnvironment::onDayParametersChanged(LLUICtrl*, void* userdata)
  993. {
  994. HBPanelLandEnvironment* self = (HBPanelLandEnvironment*)userdata;
  995. if (self)
  996. {
  997. self->mDayParametersDirty = true;
  998. self->mLastParametersChange = gFrameTimeSeconds;
  999. if (self->mCurrentEnvironment)
  1000. {
  1001. self->mCurrentEnvironment->mDayLength =
  1002. self->mDayLengthSlider->getValueF32() * 3600.f;
  1003. F32 day_offset = self->mDayOffsetSlider->getValueF32();
  1004. if (day_offset <= 0.f)
  1005. {
  1006. day_offset += 24.f;
  1007. }
  1008. self->mCurrentEnvironment->mDayOffset = day_offset * 3600.f;
  1009. self->updateApparentTimeOfDay();
  1010. }
  1011. }
  1012. }
  1013. //static
  1014. void HBPanelLandEnvironment::onAltSliderCommit(LLUICtrl* ctrl, void* userdata)
  1015. {
  1016. HBPanelLandEnvironment* self = (HBPanelLandEnvironment*)userdata;
  1017. if (self)
  1018. {
  1019. self->updateAltitudeLabels();
  1020. }
  1021. }
  1022. //static
  1023. void HBPanelLandEnvironment::onAltSliderMouseUp(S32, S32, void* userdata)
  1024. {
  1025. HBPanelLandEnvironment* self = (HBPanelLandEnvironment*)userdata;
  1026. if (!self || !self->mIsRegion)
  1027. {
  1028. return;
  1029. }
  1030. std::set<S32> alts; // Using a std::set to auto-sort by value on insertion
  1031. // Manually unrolled loop to avoid llformat() usage for slider names
  1032. alts.insert((S32)self->mAltitudesSlider->getSliderValue("sld1"));
  1033. alts.insert((S32)self->mAltitudesSlider->getSliderValue("sld2"));
  1034. alts.insert((S32)self->mAltitudesSlider->getSliderValue("sld3"));
  1035. // Push the sorted values into the altitudes vector
  1036. std::set<S32>::iterator it = alts.begin();
  1037. LLEnvironment::altitudes_vect_t alts_vec;
  1038. alts_vec.push_back(*it);
  1039. alts_vec.push_back(*(++it));
  1040. alts_vec.push_back(*(++it));
  1041. S32 day_length = -1;
  1042. S32 day_offset = -1;
  1043. if (self->mCurrentEnvironment)
  1044. {
  1045. day_length = self->mCurrentEnvironment->mDayLength;
  1046. day_offset = self->mCurrentEnvironment->mDayOffset;
  1047. }
  1048. gEnvironment.updateParcel(self->getParcelId(), LLSettingsDay::ptr_t(),
  1049. day_length, day_offset, alts_vec);
  1050. }