llsettingsdaycycle.cpp 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  1. /**
  2. * @file llsettingsdaycycle.cpp
  3. * @brief The day cycles settings asset support class.
  4. *
  5. * $LicenseInfo:firstyear=2018&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2019, 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 "linden_common.h"
  33. #include "boost/pointer_cast.hpp"
  34. #include "llsettingsdaycycle.h"
  35. #include "llframetimer.h"
  36. #include "llsettingssky.h"
  37. #include "llsettingswater.h"
  38. // Helper functions
  39. template<typename T>
  40. LL_INLINE T get_wrapping_distance(T begin, T end)
  41. {
  42. if (begin < end)
  43. {
  44. return end - begin;
  45. }
  46. else if (begin > end)
  47. {
  48. return T(1) - begin + end;
  49. }
  50. return 0;
  51. }
  52. static LLSettingsDay::cycle_track_it_t get_wrapping_atafter(LLSettingsDay::cycle_track_t& coll,
  53. F32 key)
  54. {
  55. if (coll.empty())
  56. {
  57. return coll.end();
  58. }
  59. LLSettingsDay::cycle_track_it_t it = coll.upper_bound(key);
  60. if (it == coll.end())
  61. {
  62. // Wrap around
  63. it = coll.begin();
  64. }
  65. return it;
  66. }
  67. static LLSettingsDay::cycle_track_it_t get_wrapping_atbefore(LLSettingsDay::cycle_track_t& coll,
  68. F32 key)
  69. {
  70. if (coll.empty())
  71. {
  72. return coll.end();
  73. }
  74. LLSettingsDay::cycle_track_it_t it = coll.lower_bound(key);
  75. if (it == coll.end())
  76. {
  77. // All keyframes are lower, take the last one.
  78. --it; // we know the range is not empty
  79. }
  80. else if (it->first > key)
  81. {
  82. // The keyframe we are interested in is smaller than the found.
  83. if (it == coll.begin())
  84. {
  85. it = coll.end();
  86. }
  87. --it;
  88. }
  89. return it;
  90. }
  91. // Constants
  92. const std::string LLSettingsDay::SETTING_KEYID = "key_id";
  93. const std::string LLSettingsDay::SETTING_KEYNAME = "key_name";
  94. const std::string LLSettingsDay::SETTING_KEYKFRAME = "key_keyframe";
  95. const std::string LLSettingsDay::SETTING_KEYHASH = "key_hash";
  96. const std::string LLSettingsDay::SETTING_TRACKS = "tracks";
  97. const std::string LLSettingsDay::SETTING_FRAMES = "frames";
  98. const LLUUID LLSettingsDay::DEFAULT_ASSET_ID("5646d39e-d3d7-6aff-ed71-30fc87d64a91");
  99. // Minimum value to prevent multislider in edit floaters from eating up frames
  100. // that 'encroach' on one another's space
  101. constexpr F32 DEFAULT_MULTISLIDER_INCREMENT = 0.005f;
  102. LLSettingsDay::LLSettingsDay(const LLSD& data)
  103. : LLSettingsBase(data),
  104. mInitialized(false)
  105. {
  106. mDayTracks.resize(TRACK_MAX);
  107. }
  108. LLSettingsDay::LLSettingsDay()
  109. : LLSettingsBase(),
  110. mInitialized(false)
  111. {
  112. mDayTracks.resize(TRACK_MAX);
  113. }
  114. LLSD LLSettingsDay::getSettings() const
  115. {
  116. LLSD settings(LLSD::emptyMap());
  117. if (mSettings.has(SETTING_NAME))
  118. {
  119. settings[SETTING_NAME] = mSettings[SETTING_NAME];
  120. }
  121. if (mSettings.has(SETTING_ID))
  122. {
  123. settings[SETTING_ID] = mSettings[SETTING_ID];
  124. }
  125. if (mSettings.has(SETTING_ASSETID))
  126. {
  127. settings[SETTING_ASSETID] = mSettings[SETTING_ASSETID];
  128. }
  129. settings[SETTING_TYPE] = getSettingsType();
  130. typedef std::map<std::string, LLSettingsBase::ptr_t> str_ptr_map_t;
  131. str_ptr_map_t in_use;
  132. LLSD tracks(LLSD::emptyArray());
  133. for (cycle_list_t::const_iterator it1 = mDayTracks.begin(),
  134. end1 = mDayTracks.end();
  135. it1 != end1; ++it1)
  136. {
  137. LLSD trackout(LLSD::emptyArray());
  138. for (cycle_track_t::const_iterator it2 = it1->begin(),
  139. end2 = it1->end();
  140. it2 != end2; ++it2)
  141. {
  142. F32 frame = it2->first;
  143. LLSettingsBase::ptr_t data = it2->second;
  144. size_t datahash = data->getHash();
  145. std::stringstream keyname;
  146. keyname << datahash;
  147. trackout.append(LLSD(LLSDMap(SETTING_KEYKFRAME, LLSD::Real(frame))
  148. (SETTING_KEYNAME, keyname.str())));
  149. in_use[keyname.str()] = data;
  150. }
  151. tracks.append(trackout);
  152. }
  153. settings[SETTING_TRACKS] = tracks;
  154. LLSD frames(LLSD::emptyMap());
  155. for (str_ptr_map_t::iterator it = in_use.begin(), end = in_use.end();
  156. it != end; ++it)
  157. {
  158. LLSD framesettings =
  159. llsd_clone(it->second->getSettings(),
  160. LLSDMap("*", true)(SETTING_NAME, false)
  161. (SETTING_ID, false)(SETTING_HASH, false));
  162. frames[it->first] = framesettings;
  163. }
  164. settings[SETTING_FRAMES] = frames;
  165. return settings;
  166. }
  167. bool LLSettingsDay::initialize(bool validate_frames)
  168. {
  169. LLSD tracks = mSettings[SETTING_TRACKS];
  170. LLSD frames = mSettings[SETTING_FRAMES];
  171. // Save for later...
  172. LLUUID assetid;
  173. if (mSettings.has(SETTING_ASSETID))
  174. {
  175. assetid = mSettings[SETTING_ASSETID].asUUID();
  176. }
  177. std::map<std::string, LLSettingsBase::ptr_t> used;
  178. for (LLSD::map_const_iterator it = frames.beginMap(), end = frames.endMap();
  179. it != end; ++it)
  180. {
  181. const std::string& name = it->first;
  182. LLSD data = it->second;
  183. LLSettingsBase::ptr_t keyframe;
  184. if (data[SETTING_TYPE].asString() == "sky")
  185. {
  186. LL_DEBUGS("EnvSettings") << "Building sky frame: " << name
  187. << LL_ENDL;
  188. keyframe = buildSky(data);
  189. }
  190. else if (data[SETTING_TYPE].asString() == "water")
  191. {
  192. LL_DEBUGS("EnvSettings") << "Building water frame: " << name
  193. << LL_ENDL;
  194. keyframe = buildWater(data);
  195. }
  196. else
  197. {
  198. llwarns << "Unknown child setting type '"
  199. << data[SETTING_TYPE].asString() << "' named '" << name
  200. << "'" << llendl;
  201. }
  202. if (!keyframe)
  203. {
  204. llwarns << "Invalid frame data for child: " << name << llendl;
  205. continue;
  206. }
  207. used[name] = keyframe;
  208. }
  209. // We consider frame DEFAULT_FRAME_SLOP_FACTOR away as still encroaching,
  210. // so add minimum increment
  211. constexpr F32 MOVE_FACTOR = DEFAULT_FRAME_SLOP_FACTOR +
  212. DEFAULT_MULTISLIDER_INCREMENT;
  213. bool haswater = false;
  214. bool hassky = false;
  215. for (S32 i = 0, count = llmin((S32)tracks.size(), (S32)TRACK_MAX);
  216. i < count; ++i)
  217. {
  218. mDayTracks[i].clear();
  219. LLSD curtrack = tracks[i];
  220. for (LLSD::array_const_iterator it = curtrack.beginArray(),
  221. end = curtrack.endArray();
  222. it != end; ++it)
  223. {
  224. F32 keyframe = (*it)[SETTING_KEYKFRAME].asReal();
  225. keyframe = llclamp(keyframe, 0.f, 1.f);
  226. LLSettingsBase::ptr_t setting;
  227. if (it->has(SETTING_KEYNAME))
  228. {
  229. std::string key_name = (*it)[SETTING_KEYNAME];
  230. if (i == TRACK_WATER)
  231. {
  232. setting = used[key_name];
  233. if (setting && setting->getSettingsType() != "water")
  234. {
  235. llwarns << "Water track referencing "
  236. << setting->getSettingsType() << " frame at "
  237. << keyframe << "." << llendl;
  238. setting.reset();
  239. }
  240. }
  241. else
  242. {
  243. setting = used[key_name];
  244. if (setting && setting->getSettingsType() != "sky")
  245. {
  246. llwarns << "Sky track #" << i << " referencing "
  247. << setting->getSettingsType() << " frame at "
  248. << keyframe << "." << llendl;
  249. setting.reset();
  250. }
  251. }
  252. }
  253. if (!setting)
  254. {
  255. continue;
  256. }
  257. if (i == TRACK_WATER)
  258. {
  259. haswater = true;
  260. }
  261. else
  262. {
  263. hassky = true;
  264. }
  265. if (validate_frames && mDayTracks[i].size() > 0)
  266. {
  267. // Check if we hit close to anything in the list
  268. LLSettingsDay::cycle_track_t::value_type frame =
  269. getSettingsNearKeyframe(keyframe, i, DEFAULT_FRAME_SLOP_FACTOR);
  270. if (frame.second)
  271. {
  272. // Figure out direction of search
  273. F32 found = frame.first;
  274. F32 new_frame = keyframe;
  275. F32 total_frame_shift = 0;
  276. if ((new_frame < found &&
  277. found - new_frame <= DEFAULT_FRAME_SLOP_FACTOR) ||
  278. (new_frame > found &&
  279. new_frame - found > DEFAULT_FRAME_SLOP_FACTOR))
  280. {
  281. // Move backward
  282. cycle_track_rit_t iter = mDayTracks[i].rbegin();
  283. while (iter->first != found)
  284. {
  285. ++iter;
  286. }
  287. new_frame = found; // For total_frame_shift
  288. while (total_frame_shift < 1.f)
  289. {
  290. // Calculate shifted position from current found point
  291. total_frame_shift +=
  292. MOVE_FACTOR + new_frame -
  293. (found <= new_frame ? found : found - 1.f);
  294. new_frame = found - MOVE_FACTOR;
  295. if (new_frame < 0.f)
  296. {
  297. new_frame += 1.f;
  298. }
  299. // We know that current point is too close, go for
  300. // next one
  301. ++iter;
  302. if (iter == mDayTracks[i].rend())
  303. {
  304. iter = mDayTracks[i].rbegin();
  305. }
  306. if ((iter->first <= new_frame + DEFAULT_MULTISLIDER_INCREMENT &&
  307. new_frame - DEFAULT_FRAME_SLOP_FACTOR <= iter->first) ||
  308. (iter->first > new_frame &&
  309. new_frame - DEFAULT_FRAME_SLOP_FACTOR <= iter->first - 1.f))
  310. {
  311. // We are encroaching at new point as well
  312. found = iter->first;
  313. }
  314. else
  315. {
  316. // We have:
  317. // new_frame - DEFAULT_FRAME_SLOP_FACTOR >
  318. // iter->first
  319. // We found a clear spot.
  320. break;
  321. }
  322. }
  323. }
  324. else
  325. {
  326. // Move forward
  327. cycle_track_it_t iter = mDayTracks[i].find(found);
  328. new_frame = found; // For total_frame_shift
  329. while (total_frame_shift < 1.f)
  330. {
  331. // Calculate shifted position from previous found
  332. // point
  333. total_frame_shift +=
  334. MOVE_FACTOR - new_frame +
  335. (found >= new_frame ? found : found + 1.f);
  336. new_frame = found + MOVE_FACTOR;
  337. if (new_frame > 1.f)
  338. {
  339. new_frame -= 1.f;
  340. }
  341. // We know that current point is too close, go for
  342. // next one
  343. ++iter;
  344. if (iter == mDayTracks[i].end())
  345. {
  346. iter = mDayTracks[i].begin();
  347. }
  348. if ((iter->first >= new_frame - DEFAULT_MULTISLIDER_INCREMENT &&
  349. new_frame + DEFAULT_FRAME_SLOP_FACTOR >= iter->first) ||
  350. (iter->first < new_frame &&
  351. new_frame + DEFAULT_FRAME_SLOP_FACTOR >= iter->first + 1.f))
  352. {
  353. // We are encroaching at new point as well
  354. found = iter->first;
  355. }
  356. else
  357. {
  358. // We have:
  359. // new_frame + DEFAULT_FRAME_SLOP_FACTOR <
  360. // iter->first
  361. // We found clear spot.
  362. break;
  363. }
  364. }
  365. }
  366. if (total_frame_shift >= 1.f)
  367. {
  368. llwarns << "Could not fix frame position, adding as is to position: "
  369. << keyframe << llendl;
  370. }
  371. else
  372. {
  373. // Mark as new position
  374. keyframe = new_frame;
  375. }
  376. }
  377. }
  378. mDayTracks[i][keyframe] = setting;
  379. }
  380. }
  381. if (!haswater)
  382. {
  383. llwarns << "Must have one water frame !" << llendl;
  384. return false;
  385. }
  386. if (!hassky)
  387. {
  388. llwarns << "Must have at least one sky frame !" << llendl;
  389. return false;
  390. }
  391. // These are no longer needed and just take up space now.
  392. mSettings.erase(SETTING_TRACKS);
  393. mSettings.erase(SETTING_FRAMES);
  394. if (!assetid.isNull())
  395. {
  396. mSettings[SETTING_ASSETID] = assetid;
  397. }
  398. mInitialized = true;
  399. return true;
  400. }
  401. //static
  402. LLSD LLSettingsDay::defaults()
  403. {
  404. static LLSD dfltsetting;
  405. if (dfltsetting.size() == 0)
  406. {
  407. dfltsetting[SETTING_NAME] = "_default_";
  408. dfltsetting[SETTING_TYPE] = "daycycle";
  409. LLSD frames(LLSD::emptyMap());
  410. LLSD water_track;
  411. LLSD sky_track;
  412. constexpr U32 FRAME_COUNT = 8;
  413. constexpr F32 FRAME_STEP = 1.f / (F32)FRAME_COUNT;
  414. F32 time = 0.f;
  415. for (U32 i = 0; i < FRAME_COUNT; ++i)
  416. {
  417. std::string name = "_default_";
  418. name += 'a' + i;
  419. std::string water_frame_name = "water:" + name;
  420. std::string sky_frame_name = "sky:" + name;
  421. water_track[SETTING_KEYKFRAME] = time;
  422. water_track[SETTING_KEYNAME] = water_frame_name;
  423. sky_track[SETTING_KEYKFRAME] = time;
  424. sky_track[SETTING_KEYNAME] = sky_frame_name;
  425. frames[water_frame_name] = LLSettingsWater::defaults(time);
  426. frames[sky_frame_name] = LLSettingsSky::defaults(time);
  427. time += FRAME_STEP;
  428. }
  429. LLSD tracks;
  430. tracks.append(llsd::array(water_track));
  431. tracks.append(llsd::array(sky_track));
  432. dfltsetting[SETTING_TRACKS] = tracks;
  433. dfltsetting[SETTING_FRAMES] = frames;
  434. }
  435. return dfltsetting;
  436. }
  437. //static
  438. LLSD LLSettingsDay::buildCycleFromFixed(const LLSettingsSky::ptr_t& skyp,
  439. const LLSettingsWater::ptr_t& waterp)
  440. {
  441. LLSD sky;
  442. std::string sky_name;
  443. if (skyp)
  444. {
  445. sky = skyp->getSettings();
  446. sky_name = sky[SETTING_NAME].asString();
  447. }
  448. if (sky_name.empty())
  449. {
  450. sky_name = "_default_";
  451. }
  452. LLSD water;
  453. std::string water_name;
  454. if (waterp)
  455. {
  456. water = waterp->getSettings();
  457. water_name = water[SETTING_NAME].asString();
  458. }
  459. if (water_name.empty())
  460. {
  461. water_name = "_default_";
  462. }
  463. LLSD cycle;
  464. cycle[SETTING_TYPE] = "daycycle";
  465. cycle[SETTING_NAME] = sky_name;
  466. LLSD frames(LLSD::emptyMap());
  467. LLSD water_track;
  468. LLSD sky_track;
  469. constexpr U32 FRAME_COUNT = 8;
  470. constexpr F32 FRAME_STEP = 1.f / (F32)FRAME_COUNT;
  471. std::string sky_frame_name, water_frame_name;
  472. F32 time = 0.f;
  473. for (U32 i = 0; i < FRAME_COUNT; ++i)
  474. {
  475. sky_frame_name = "sky:" + sky_name;
  476. sky_frame_name += 'a' + i;
  477. water_frame_name = "water:" + water_name;
  478. water_frame_name += 'a' + i;
  479. water_track[SETTING_KEYKFRAME] = time;
  480. water_track[SETTING_KEYNAME] = water_frame_name;
  481. sky_track[SETTING_KEYKFRAME] = time;
  482. sky_track[SETTING_KEYNAME] = sky_frame_name;
  483. LLSettingsWater::adjustTime(water, time);
  484. frames[water_frame_name] = water;
  485. LLSettingsSky::adjustTime(sky, time);
  486. frames[sky_frame_name] = sky;
  487. time += FRAME_STEP;
  488. }
  489. LLSD tracks;
  490. tracks.append(llsd::array(water_track));
  491. tracks.append(llsd::array(sky_track));
  492. cycle[SETTING_TRACKS] = tracks;
  493. cycle[SETTING_FRAMES] = frames;
  494. return cycle;
  495. }
  496. void LLSettingsDay::blend(const LLSettingsBase::ptr_t&, F64)
  497. {
  498. llerrs << "Day cycles are not blendable !" << llendl;
  499. }
  500. bool LLSettingsDay::validateDayCycleTrack(LLSD& value, U32)
  501. {
  502. // Trim extra tracks.
  503. while (value.size() > LLSettingsDay::TRACK_MAX)
  504. {
  505. value.erase(value.size() - 1);
  506. }
  507. S32 framecount = 0;
  508. for (LLSD::array_iterator track = value.beginArray(),
  509. end = value.endArray();
  510. track != end; ++track)
  511. {
  512. size_t index = 0;
  513. while (index < track->size())
  514. {
  515. LLSD& elem = (*track)[index];
  516. ++framecount;
  517. if (index >= LLSettingsDay::FRAME_MAX)
  518. {
  519. track->erase(index);
  520. continue;
  521. }
  522. if (!elem.has(LLSettingsDay::SETTING_KEYKFRAME))
  523. {
  524. track->erase(index);
  525. continue;
  526. }
  527. if (!elem[LLSettingsDay::SETTING_KEYKFRAME].isReal())
  528. {
  529. track->erase(index);
  530. continue;
  531. }
  532. if (!elem.has(LLSettingsDay::SETTING_KEYNAME) &&
  533. !elem.has(LLSettingsDay::SETTING_KEYID))
  534. {
  535. track->erase(index);
  536. continue;
  537. }
  538. F32 frame = elem[LLSettingsDay::SETTING_KEYKFRAME].asReal();
  539. if (frame < 0.f || frame > 1.f)
  540. {
  541. frame = llclamp(frame, 0.f, 1.f);
  542. elem[LLSettingsDay::SETTING_KEYKFRAME] = frame;
  543. }
  544. ++index;
  545. }
  546. }
  547. S32 water_tracks = value[0].size();
  548. if (water_tracks < 1)
  549. {
  550. llwarns << "Missing water track" << llendl;
  551. return false;
  552. }
  553. if (framecount - water_tracks < 1)
  554. {
  555. llwarns << "Missing sky tracks" << llendl;
  556. return false;
  557. }
  558. return true;
  559. }
  560. bool LLSettingsDay::validateDayCycleFrames(LLSD& value, U32 flags)
  561. {
  562. bool has_sky = false;
  563. bool has_water = false;
  564. for (LLSD::map_iterator it = value.beginMap(), end = value.endMap();
  565. it != end; ++it)
  566. {
  567. LLSD frame = it->second;
  568. std::string ftype = frame[LLSettingsBase::SETTING_TYPE];
  569. if (ftype == "sky")
  570. {
  571. const LLSettingsSky::validation_list_t& valid_sky =
  572. LLSettingsSky::validationList();
  573. LLSD res_sky = LLSettingsBase::settingValidation(frame, valid_sky,
  574. flags);
  575. if (res_sky["success"].asInteger() == 0)
  576. {
  577. llwarns << "Sky setting named '" << it->first
  578. << "' validation failed: " << res_sky << " - Sky: "
  579. << frame << llendl;
  580. continue;
  581. }
  582. has_sky |= true;
  583. }
  584. else if (ftype == "water")
  585. {
  586. const LLSettingsWater::validation_list_t& valid_h2o =
  587. LLSettingsWater::validationList();
  588. LLSD res_h2o = LLSettingsBase::settingValidation(frame, valid_h2o,
  589. flags);
  590. if (res_h2o["success"].asInteger() == 0)
  591. {
  592. llwarns << "Water setting named '" << it->first
  593. << "' validation failed: " << res_h2o << " - Water: "
  594. << frame << llendl;
  595. continue;
  596. }
  597. has_water |= true;
  598. }
  599. else
  600. {
  601. llwarns << "Unknown settings block of type '" << ftype
  602. << "' named '" << it->first << "'" << llendl;
  603. return false;
  604. }
  605. }
  606. if (!(flags & LLSettingsBase::Validator::VALIDATION_PARTIAL))
  607. {
  608. if (!has_sky)
  609. {
  610. llwarns << "No skies defined." << llendl;
  611. return false;
  612. }
  613. if (!has_water)
  614. {
  615. llwarns << "No waters defined." << llendl;
  616. return false;
  617. }
  618. }
  619. return true;
  620. }
  621. //virtual
  622. const LLSettingsDay::validation_list_t& LLSettingsDay::getValidationList() const
  623. {
  624. return validationList();
  625. }
  626. //static
  627. const LLSettingsDay::validation_list_t& LLSettingsDay::validationList()
  628. {
  629. static validation_list_t validation;
  630. if (validation.empty())
  631. {
  632. validation.emplace_back(SETTING_TRACKS, true, LLSD::TypeArray,
  633. &validateDayCycleTrack);
  634. validation.emplace_back(SETTING_FRAMES, true, LLSD::TypeMap,
  635. &validateDayCycleFrames);
  636. }
  637. return validation;
  638. }
  639. LLSettingsDay::cycle_track_t& LLSettingsDay::getCycleTrack(S32 track)
  640. {
  641. static cycle_track_t empty;
  642. return (size_t)track < mDayTracks.size() ? mDayTracks[track] : empty;
  643. }
  644. const LLSettingsDay::cycle_track_t& LLSettingsDay::getCycleTrackConst(S32 track) const
  645. {
  646. static const cycle_track_t empty;
  647. return (size_t)track < mDayTracks.size() ? mDayTracks[track] : empty;
  648. }
  649. bool LLSettingsDay::clearCycleTrack(S32 track)
  650. {
  651. if (track < 0 || track >= TRACK_MAX)
  652. {
  653. llwarns << "Attempt to clear track (#" << track << ") out of range"
  654. << llendl;
  655. return false;
  656. }
  657. mDayTracks[track].clear();
  658. clearAssetId();
  659. setDirtyFlag(true);
  660. return true;
  661. }
  662. bool LLSettingsDay::replaceCycleTrack(S32 track, const cycle_track_t& source)
  663. {
  664. if (source.empty())
  665. {
  666. llwarns << "Attempt to copy an empty track." << llendl;
  667. return false;
  668. }
  669. {
  670. LLSettingsBase::ptr_t first(source.begin()->second);
  671. std::string setting_type = first->getSettingsType();
  672. if ((track && setting_type == "water") ||
  673. (!track && setting_type == "sky"))
  674. {
  675. llwarns << "Attempt to copy track missmatch" << llendl;
  676. return false;
  677. }
  678. }
  679. if (!clearCycleTrack(track))
  680. {
  681. return false;
  682. }
  683. mDayTracks[track] = source;
  684. return true;
  685. }
  686. bool LLSettingsDay::isTrackEmpty(S32 track) const
  687. {
  688. if (track < 0 || track >= TRACK_MAX)
  689. {
  690. llwarns << "Attempt to test track (#" << track << ") out of range"
  691. << llendl;
  692. return true;
  693. }
  694. return mDayTracks[track].empty();
  695. }
  696. void LLSettingsDay::startDayCycle()
  697. {
  698. if (!mInitialized)
  699. {
  700. llwarns << "Attempt to start day cycle on uninitialized object."
  701. << llendl;
  702. return;
  703. }
  704. }
  705. LLSettingsDay::keyframe_list_t LLSettingsDay::getTrackKeyframes(S32 trackno)
  706. {
  707. if (trackno < 0 || trackno >= TRACK_MAX)
  708. {
  709. llwarns << "Attempt get track (#" << trackno << ") out of range"
  710. << llendl;
  711. return keyframe_list_t();
  712. }
  713. keyframe_list_t keyframes;
  714. cycle_track_t& track = mDayTracks[trackno];
  715. keyframes.reserve(track.size());
  716. for (cycle_track_it_t it = track.begin(), end = track.end();
  717. it != end; ++it)
  718. {
  719. keyframes.push_back(it->first);
  720. }
  721. return keyframes;
  722. }
  723. bool LLSettingsDay::moveTrackKeyframe(S32 trackno, F32 old_frame,
  724. F32 new_frame)
  725. {
  726. if (trackno < 0 || trackno >= TRACK_MAX)
  727. {
  728. llwarns << "Attempt get track (#" << trackno << ") out of range"
  729. << llendl;
  730. return false;
  731. }
  732. if (fabsf(old_frame - new_frame) < F_APPROXIMATELY_ZERO)
  733. {
  734. return false;
  735. }
  736. cycle_track_t& track = mDayTracks[trackno];
  737. cycle_track_it_t iter = track.find(old_frame);
  738. if (iter != track.end())
  739. {
  740. LLSettingsBase::ptr_t base = iter->second;
  741. track.erase(iter);
  742. track[llclamp(new_frame, 0.f, 1.f)] = base;
  743. track[new_frame] = base;
  744. return true;
  745. }
  746. return false;
  747. }
  748. bool LLSettingsDay::removeTrackKeyframe(S32 trackno, F32 frame)
  749. {
  750. if (trackno < 0 || trackno >= TRACK_MAX)
  751. {
  752. llwarns << "Attempt get track (#" << trackno << ") out of range"
  753. << llendl;
  754. return false;
  755. }
  756. cycle_track_t& track = mDayTracks[trackno];
  757. cycle_track_it_t iter = track.find(frame);
  758. if (iter != track.end())
  759. {
  760. LLSettingsBase::ptr_t base = iter->second;
  761. track.erase(iter);
  762. return true;
  763. }
  764. return false;
  765. }
  766. void LLSettingsDay::setWaterAtKeyframe(const settings_water_ptr_t& water,
  767. F32 keyframe)
  768. {
  769. setSettingsAtKeyframe(water, keyframe, TRACK_WATER);
  770. }
  771. LLSettingsWater::ptr_t LLSettingsDay::getWaterAtKeyframe(F32 keyframe) const
  772. {
  773. LLSettingsBase* p = getSettingsAtKeyframe(keyframe, TRACK_WATER).get();
  774. return LLSettingsWater::ptr_t((LLSettingsWater*)p);
  775. }
  776. void LLSettingsDay::setSkyAtKeyframe(const LLSettingsSky::ptr_t& sky,
  777. F32 keyframe, S32 track)
  778. {
  779. if (track < 1 || track >= TRACK_MAX)
  780. {
  781. llwarns << "Attempt to set sky track (#" << track << ") out of range"
  782. << llendl;
  783. return;
  784. }
  785. setSettingsAtKeyframe(sky, keyframe, track);
  786. }
  787. LLSettingsSky::ptr_t LLSettingsDay::getSkyAtKeyframe(F32 keyframe, S32 track) const
  788. {
  789. if ((track < 1) || (track >= TRACK_MAX))
  790. {
  791. llwarns << "Attempt to set sky track (#" << track << ") out of range"
  792. << llendl;
  793. return LLSettingsSky::ptr_t();
  794. }
  795. return boost::dynamic_pointer_cast<LLSettingsSky>(getSettingsAtKeyframe(keyframe,
  796. track));
  797. }
  798. void LLSettingsDay::setSettingsAtKeyframe(const LLSettingsBase::ptr_t& settings,
  799. F32 keyframe, S32 track)
  800. {
  801. if (track < 0 || track >= TRACK_MAX)
  802. {
  803. llwarns << "Attempt to set track (#" << track << ") out of range"
  804. << llendl;
  805. return;
  806. }
  807. std::string type = settings->getSettingsType();
  808. if (track == TRACK_WATER && type != "water")
  809. {
  810. llwarns << "Attempt to add frame of type '" << type
  811. << "' to water track" << llendl;
  812. llassert(type == "water");
  813. return;
  814. }
  815. else if (track != TRACK_WATER && type != "sky")
  816. {
  817. llwarns << "Attempt to add frame of type '" << type
  818. << "' to sky track" << llendl;
  819. llassert(type == "sky");
  820. return;
  821. }
  822. mDayTracks[track][llclamp(keyframe, 0.f, 1.f)] = settings;
  823. setDirtyFlag(true);
  824. }
  825. LLSettingsBase::ptr_t LLSettingsDay::getSettingsAtKeyframe(F32 keyframe,
  826. S32 track) const
  827. {
  828. if (track < 0 || track >= TRACK_MAX)
  829. {
  830. llwarns << "Attempt to set track (#" << track << ") out of range"
  831. << llendl;
  832. return LLSettingsBase::ptr_t();
  833. }
  834. // *TODO: better way to identify keyframes ?
  835. cycle_track_t::const_iterator iter = mDayTracks[track].find(keyframe);
  836. if (iter != mDayTracks[track].end())
  837. {
  838. return iter->second;
  839. }
  840. return LLSettingsBase::ptr_t();
  841. }
  842. LLSettingsDay::cycle_track_t::value_type LLSettingsDay::getSettingsNearKeyframe(F32 keyframe,
  843. S32 track,
  844. F32 fudge) const
  845. {
  846. if (track < 0 || track >= TRACK_MAX)
  847. {
  848. llwarns << "Attempt to get track (#" << track << ") out of range"
  849. << llendl;
  850. return cycle_track_t::value_type(INVALID_TRACKPOS,
  851. LLSettingsBase::ptr_t());
  852. }
  853. if (mDayTracks[track].empty())
  854. {
  855. llinfos << "Empty track" << llendl;
  856. return cycle_track_t::value_type(INVALID_TRACKPOS,
  857. LLSettingsBase::ptr_t());
  858. }
  859. F32 startframe = keyframe - fudge;
  860. if (startframe < 0.f)
  861. {
  862. startframe += 1.f;
  863. }
  864. LLSettingsDay::cycle_track_t collection =
  865. const_cast<cycle_track_t&>(mDayTracks[track]);
  866. cycle_track_it_t it = get_wrapping_atafter(collection, startframe);
  867. F32 dist = get_wrapping_distance(startframe, it->first);
  868. cycle_track_it_t next_it = std::next(it);
  869. if (dist <= DEFAULT_MULTISLIDER_INCREMENT && next_it != collection.end())
  870. {
  871. return *next_it;
  872. }
  873. else if (dist <= fudge * 2.f)
  874. {
  875. return *it;
  876. }
  877. return cycle_track_t::value_type(INVALID_TRACKPOS,
  878. LLSettingsBase::ptr_t());
  879. }
  880. F32 LLSettingsDay::getUpperBoundFrame(S32 track, F32 keyframe)
  881. {
  882. return get_wrapping_atafter(mDayTracks[track], keyframe)->first;
  883. }
  884. F32 LLSettingsDay::getLowerBoundFrame(S32 track, F32 keyframe)
  885. {
  886. return get_wrapping_atbefore(mDayTracks[track], keyframe)->first;
  887. }
  888. LLSettingsDay::track_bound_t LLSettingsDay::getBoundingEntries(cycle_track_t& track,
  889. F32 keyframe)
  890. {
  891. return track_bound_t(get_wrapping_atbefore(track, keyframe),
  892. get_wrapping_atafter(track, keyframe));
  893. }
  894. const LLUUID& LLSettingsDay::getDefaultAssetId()
  895. {
  896. return DEFAULT_ASSET_ID;
  897. }