llsettingsbase.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. /**
  2. * @file llsettingsbase.cpp
  3. * @brief A base class for asset based settings groups.
  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 <ostream>
  34. #include <sstream>
  35. #include "llsettingsbase.h"
  36. #include "llsdserialize.h"
  37. #define VALIDATION_DEBUG 0
  38. constexpr F32 BREAK_POINT = 0.5f;
  39. const std::string LLSettingsBase::SETTING_ID = "id";
  40. const std::string LLSettingsBase::SETTING_NAME = "name";
  41. const std::string LLSettingsBase::SETTING_HASH = "hash";
  42. const std::string LLSettingsBase::SETTING_TYPE = "type";
  43. const std::string LLSettingsBase::SETTING_ASSETID = "asset_id";
  44. const std::string LLSettingsBase::SETTING_FLAGS = "flags";
  45. std::ostream& operator<<(std::ostream& os, LLSettingsBase& settings)
  46. {
  47. LLSDSerialize::serialize(settings.getSettings(), os,
  48. LLSDSerialize::LLSD_NOTATION);
  49. return os;
  50. }
  51. LLSettingsBase::LLSettingsBase()
  52. : mSettings(LLSD::emptyMap()),
  53. mBlendedFactor(0.0),
  54. mDirty(true)
  55. {
  56. }
  57. LLSettingsBase::LLSettingsBase(const LLSD& setting)
  58. : mSettings(setting),
  59. mBlendedFactor(0.0),
  60. mDirty(true)
  61. {
  62. }
  63. void LLSettingsBase::lerpSettings(const LLSettingsBase& other, F64 mix)
  64. {
  65. mSettings = interpolateSDMap(mSettings, other.mSettings,
  66. other.getParameterMap(), mix);
  67. setDirtyFlag(true);
  68. }
  69. LLSD LLSettingsBase::combineSDMaps(const LLSD& settings,
  70. const LLSD& other) const
  71. {
  72. LLSD new_settings;
  73. for (LLSD::map_const_iterator it = settings.beginMap(),
  74. end = settings.endMap();
  75. it != end; ++it)
  76. {
  77. const std::string& key_name = it->first;
  78. const LLSD& value = it->second;
  79. LLSD::Type setting_type = value.type();
  80. switch (setting_type)
  81. {
  82. case LLSD::TypeMap:
  83. new_settings[key_name] = combineSDMaps(value, LLSD());
  84. break;
  85. case LLSD::TypeArray:
  86. new_settings[key_name] = LLSD::emptyArray();
  87. for (LLSD::array_const_iterator ita = value.beginArray(),
  88. enda = value.endArray();
  89. ita != enda; ++ita)
  90. {
  91. new_settings[key_name].append(*ita);
  92. }
  93. break;
  94. default:
  95. new_settings[key_name] = value;
  96. }
  97. }
  98. if (!other.isUndefined())
  99. {
  100. for (LLSD::map_const_iterator it = other.beginMap(),
  101. end = other.endMap();
  102. it !=end; ++it)
  103. {
  104. const std::string& key_name = it->first;
  105. const LLSD& value = it->second;
  106. LLSD::Type setting_type = value.type();
  107. switch (setting_type)
  108. {
  109. case LLSD::TypeMap:
  110. new_settings[key_name] = combineSDMaps(value, LLSD());
  111. break;
  112. case LLSD::TypeArray:
  113. new_settings[key_name] = LLSD::emptyArray();
  114. for (LLSD::array_const_iterator ita = value.beginArray(),
  115. enda = value.endArray();
  116. ita != enda; ++ita)
  117. {
  118. new_settings[key_name].append(*ita);
  119. }
  120. break;
  121. default:
  122. new_settings[key_name] = value;
  123. }
  124. }
  125. }
  126. return new_settings;
  127. }
  128. LLSD LLSettingsBase::interpolateSDMap(const LLSD& settings, const LLSD& other,
  129. const parammapping_t& defaults,
  130. F64 mix) const
  131. {
  132. llassert(mix >= 0.f && mix <= 1.f);
  133. LLSD new_settings;
  134. const stringset_t& skip = getSkipInterpolateKeys();
  135. const stringset_t& slerps = getSlerpKeys();
  136. for (LLSD::map_const_iterator it = settings.beginMap(),
  137. end = settings.endMap();
  138. it != end; ++it)
  139. {
  140. const std::string& key_name = it->first;
  141. if (skip.find(key_name) != skip.end())
  142. {
  143. continue;
  144. }
  145. const LLSD& value = it->second;
  146. LLSD other_value;
  147. if (other.has(key_name))
  148. {
  149. other_value = other[key_name];
  150. }
  151. else
  152. {
  153. parammapping_t::const_iterator def_it = defaults.find(key_name);
  154. if (def_it != defaults.end())
  155. {
  156. other_value = def_it->second.getDefaultValue();
  157. }
  158. else if (value.type() == LLSD::TypeMap)
  159. {
  160. // Interpolate in case there are defaults inside (part of legacy)
  161. other_value = LLSDMap();
  162. }
  163. else
  164. {
  165. // The other or defaults does not contain this setting, keep
  166. // the original value. *TODO: blend this out instead ?
  167. new_settings[key_name] = value;
  168. continue;
  169. }
  170. }
  171. new_settings[key_name] = interpolateSDValue(key_name, value,
  172. other_value, defaults, mix,
  173. slerps);
  174. }
  175. // Special handling cases
  176. if (settings.has(SETTING_FLAGS))
  177. {
  178. U32 flags = (U32)settings[SETTING_FLAGS].asInteger();
  179. if (other.has(SETTING_FLAGS))
  180. {
  181. flags |= (U32)other[SETTING_FLAGS].asInteger();
  182. }
  183. new_settings[SETTING_FLAGS] = LLSD::Integer(flags);
  184. }
  185. // Now add anything that is in other but not in the settings
  186. for (LLSD::map_const_iterator it = other.beginMap(), end = other.endMap();
  187. it != end; ++it)
  188. {
  189. const std::string& key_name = it->first;
  190. if (skip.find(key_name) != skip.end() || settings.has(key_name))
  191. {
  192. continue;
  193. }
  194. parammapping_t::const_iterator def_it = defaults.find(key_name);
  195. if (def_it != defaults.end())
  196. {
  197. // Blend against default value
  198. new_settings[key_name] =
  199. interpolateSDValue(key_name, def_it->second.getDefaultValue(),
  200. it->second, defaults, mix, slerps);
  201. }
  202. else if (it->second.type() == LLSD::TypeMap)
  203. {
  204. // Interpolate in case there are defaults inside (part of legacy)
  205. new_settings[key_name] = interpolateSDValue(key_name, LLSDMap(),
  206. it->second, defaults,
  207. mix, slerps);
  208. }
  209. // Else do nothing when no known defaults. *TODO: blend out instead ?
  210. }
  211. // Note: writes variables from skip list: bug ?
  212. for (LLSD::map_const_iterator it = other.beginMap(), end = other.endMap();
  213. it != end; ++it)
  214. {
  215. // *TODO: blend this in instead ?
  216. if (skip.find(it->first) == skip.end())
  217. {
  218. continue;
  219. }
  220. if (settings.has(it->first))
  221. {
  222. new_settings[it->first] = it->second;
  223. }
  224. }
  225. return new_settings;
  226. }
  227. LLSD LLSettingsBase::interpolateSDValue(const std::string& key_name,
  228. const LLSD& value,
  229. const LLSD& other_value,
  230. const parammapping_t& defaults,
  231. F64 mix,
  232. const stringset_t& slerps) const
  233. {
  234. LLSD::Type setting_type = value.type();
  235. if (other_value.type() != setting_type)
  236. {
  237. // The data type mismatched between this and other. Hard switch when we
  238. // pass the break point, but issue a warning.
  239. llwarns << "Setting lerp between mismatched types for '" << key_name
  240. << "'." << llendl;
  241. return mix > BREAK_POINT ? other_value : value;
  242. }
  243. LLSD new_value;
  244. switch (setting_type)
  245. {
  246. case LLSD::TypeInteger:
  247. // lerp between the two values rounding the result to the nearest
  248. // integer
  249. new_value = LLSD::Integer(ll_round(lerp(value.asReal(),
  250. other_value.asReal(), mix)));
  251. break;
  252. case LLSD::TypeReal:
  253. // lerp between the two values.
  254. new_value = LLSD::Real(lerp(value.asReal(), other_value.asReal(),
  255. mix));
  256. break;
  257. case LLSD::TypeMap:
  258. // Deep copy.
  259. new_value = interpolateSDMap(value, other_value, defaults, mix);
  260. break;
  261. case LLSD::TypeArray:
  262. {
  263. LLSD new_array(LLSD::emptyArray());
  264. if (slerps.find(key_name) != slerps.end())
  265. {
  266. LLQuaternion a(value);
  267. LLQuaternion b(other_value);
  268. LLQuaternion q = slerp(mix, a, b);
  269. new_array = q.getValue();
  270. }
  271. else
  272. {
  273. // *TODO: We could expand this to inspect the type and do a
  274. // deep lerp based on type. For now assume a heterogeneous
  275. // array of reals.
  276. for (U32 i = 0, len = llmax(value.size(), other_value.size());
  277. i < len; ++i)
  278. {
  279. new_array[i] = lerp(value[i].asReal(),
  280. other_value[i].asReal(), mix);
  281. }
  282. }
  283. new_value = new_array;
  284. break;
  285. }
  286. case LLSD::TypeUUID:
  287. new_value = value.asUUID();
  288. break;
  289. default:
  290. // Atomic or unknown data types. Lerping between them does not make
  291. // sense so switch at the break.
  292. new_value = mix > BREAK_POINT ? other_value : value;
  293. }
  294. return new_value;
  295. }
  296. //virtual
  297. const LLSettingsBase::stringset_t& LLSettingsBase::getSkipInterpolateKeys() const
  298. {
  299. static stringset_t skip_set;
  300. if (skip_set.empty())
  301. {
  302. skip_set.emplace(SETTING_FLAGS);
  303. skip_set.emplace(SETTING_HASH);
  304. }
  305. return skip_set;
  306. }
  307. //virtual
  308. const LLSettingsBase::stringset_t& LLSettingsBase::getSlerpKeys() const
  309. {
  310. static stringset_t slerp_keys;
  311. return slerp_keys;
  312. }
  313. //virtual
  314. const LLSettingsBase::parammapping_t& LLSettingsBase::getParameterMap() const
  315. {
  316. static parammapping_t param_mapping;
  317. return param_mapping;
  318. }
  319. LLSD LLSettingsBase::cloneSettings() const
  320. {
  321. U32 flags = getFlags();
  322. LLSD settings(combineSDMaps(getSettings(), LLSD()));
  323. if (flags)
  324. {
  325. settings[SETTING_FLAGS] = LLSD::Integer(flags);
  326. }
  327. return settings;
  328. }
  329. size_t LLSettingsBase::getHash() const
  330. {
  331. // Get a shallow copy of the LLSD filtering out values to not include in
  332. // the hash
  333. LLSD hash_settings =
  334. llsd_shallow(getSettings(),
  335. LLSDMap(SETTING_NAME, false)(SETTING_ID, false)(SETTING_HASH, false)("*", true));
  336. return hash_value(hash_settings);
  337. }
  338. bool LLSettingsBase::validate()
  339. {
  340. const validation_list_t& validations = getValidationList();
  341. if (!mSettings.has(SETTING_TYPE))
  342. {
  343. mSettings[SETTING_TYPE] = getSettingsType();
  344. }
  345. LLSD result = LLSettingsBase::settingValidation(mSettings, validations);
  346. if (result["errors"].size() > 0)
  347. {
  348. llwarns << "Validation errors: " << result["errors"] << llendl;
  349. }
  350. if (result["warnings"].size() > 0)
  351. {
  352. LL_DEBUGS("EnvSettings") << "Validation warnings: "
  353. << result["warnings"] << LL_ENDL;
  354. }
  355. return result["success"].asBoolean();
  356. }
  357. LLSD LLSettingsBase::settingValidation(LLSD& settings,
  358. const validation_list_t& validations,
  359. bool partial)
  360. {
  361. static Validator validateName(SETTING_NAME, false, LLSD::TypeString,
  362. boost::bind(&Validator::verifyStringLength,
  363. _1, _2, 63));
  364. static Validator validateId(SETTING_ID, false, LLSD::TypeUUID);
  365. static Validator validateHash(SETTING_HASH, false, LLSD::TypeInteger);
  366. static Validator validateType(SETTING_TYPE, false, LLSD::TypeString);
  367. static Validator validateAssetId(SETTING_ASSETID, false, LLSD::TypeUUID);
  368. static Validator validateFlags(SETTING_FLAGS, false, LLSD::TypeInteger);
  369. stringset_t validated, strip;
  370. bool is_valid = true;
  371. LLSD errors(LLSD::emptyArray());
  372. LLSD warnings(LLSD::emptyArray());
  373. U32 flags = 0;
  374. if (partial)
  375. {
  376. flags = Validator::VALIDATION_PARTIAL;
  377. }
  378. // Fields common to all settings.
  379. if (!validateName.verify(settings, flags))
  380. {
  381. errors.append(LLSD::String("Unable to validate 'name'."));
  382. is_valid = false;
  383. }
  384. validated.emplace(validateName.getName());
  385. if (!validateId.verify(settings, flags))
  386. {
  387. errors.append(LLSD::String("Unable to validate 'id'."));
  388. is_valid = false;
  389. }
  390. validated.emplace(validateId.getName());
  391. if (!validateHash.verify(settings, flags))
  392. {
  393. errors.append(LLSD::String("Unable to validate 'hash'."));
  394. is_valid = false;
  395. }
  396. validated.emplace(validateHash.getName());
  397. if (!validateAssetId.verify(settings, flags))
  398. {
  399. errors.append(LLSD::String("Invalid asset Id"));
  400. is_valid = false;
  401. }
  402. validated.emplace(validateAssetId.getName());
  403. if (!validateType.verify(settings, flags))
  404. {
  405. errors.append(LLSD::String("Unable to validate 'type'."));
  406. is_valid = false;
  407. }
  408. validated.emplace(validateType.getName());
  409. if (!validateFlags.verify(settings, flags))
  410. {
  411. errors.append(LLSD::String("Unable to validate 'flags'."));
  412. is_valid = false;
  413. }
  414. validated.emplace(validateFlags.getName());
  415. // Fields for specific settings.
  416. for (validation_list_t::const_iterator it = validations.begin(),
  417. end = validations.end();
  418. it != end; ++it)
  419. {
  420. #if VALIDATION_DEBUG
  421. LLSD oldvalue;
  422. if (settings.has(it->getName()))
  423. {
  424. oldvalue = llsd_clone(mSettings[it->getName()]);
  425. }
  426. #endif
  427. if (!it->verify(settings, flags))
  428. {
  429. std::stringstream errtext;
  430. errtext << "Settings LLSD fails validation and could not be corrected for '"
  431. << it->getName() << "'!\n";
  432. errors.append(errtext.str());
  433. is_valid = false;
  434. }
  435. validated.emplace(it->getName());
  436. #if VALIDATION_DEBUG
  437. if (!oldvalue.isUndefined() && !compare_llsd(settings[it->getName()],
  438. oldvalue))
  439. {
  440. llwarns << "Setting '" << it->getName() << "' was changed: "
  441. << oldvalue << " -> " << settings[it->getName()] << llendl;
  442. }
  443. #endif
  444. }
  445. // Strip extra entries
  446. for (LLSD::map_const_iterator it = settings.beginMap(),
  447. end = settings.endMap();
  448. it != end; ++it)
  449. {
  450. if (validated.find(it->first) == validated.end())
  451. {
  452. std::stringstream warntext;
  453. warntext << "Stripping setting '" << it->first << "'";
  454. warnings.append( warntext.str() );
  455. strip.emplace(it->first);
  456. }
  457. }
  458. for (stringset_t::iterator it = strip.begin(), end = strip.end();
  459. it != end; ++it)
  460. {
  461. settings.erase(*it);
  462. }
  463. return LLSDMap("success",
  464. LLSD::Boolean(is_valid))("errors", errors)("warnings", warnings);
  465. }
  466. bool LLSettingsBase::Validator::verify(LLSD& data, U32 flags) const
  467. {
  468. if (!data.has(mName) || (data.has(mName) && data[mName].isUndefined()))
  469. {
  470. if (flags & VALIDATION_PARTIAL)
  471. {
  472. // We are doing a partial validation; do no attempt to set a
  473. // default if missing (or fail even if required).
  474. return true;
  475. }
  476. if (!mDefault.isUndefined())
  477. {
  478. data[mName] = mDefault;
  479. return true;
  480. }
  481. if (mRequired)
  482. {
  483. llwarns << "Missing required setting '" << mName
  484. << "' with no default." << llendl;
  485. }
  486. return !mRequired;
  487. }
  488. if (data[mName].type() != mType)
  489. {
  490. llwarns << "Setting '" << mName << "' is incorrect type." << llendl;
  491. return false;
  492. }
  493. if (!mVerify.empty() && !mVerify(data[mName], flags))
  494. {
  495. llwarns << "Setting '" << mName << "' fails validation." << llendl;
  496. return false;
  497. }
  498. return true;
  499. }
  500. bool LLSettingsBase::Validator::verifyColor(LLSD& value, U32)
  501. {
  502. return value.size() == 3 || value.size() == 4;
  503. }
  504. bool LLSettingsBase::Validator::verifyVector(LLSD& value, U32, size_t length)
  505. {
  506. return value.size() == length;
  507. }
  508. bool LLSettingsBase::Validator::verifyVectorNormalized(LLSD& value, U32,
  509. size_t length)
  510. {
  511. if (value.size() != length)
  512. {
  513. return false;
  514. }
  515. LLSD newvector;
  516. switch (length)
  517. {
  518. case 2:
  519. {
  520. LLVector2 vect(value);
  521. if (is_approx_equal(vect.normalize(), 1.f))
  522. {
  523. return true;
  524. }
  525. newvector = vect.getValue();
  526. break;
  527. }
  528. case 3:
  529. {
  530. LLVector3 vect(value);
  531. if (is_approx_equal(vect.normalize(), 1.f))
  532. {
  533. return true;
  534. }
  535. newvector = vect.getValue();
  536. break;
  537. }
  538. case 4:
  539. {
  540. LLVector4 vect(value);
  541. if (is_approx_equal(vect.normalize(), 1.f))
  542. {
  543. return true;
  544. }
  545. newvector = vect.getValue();
  546. break;
  547. }
  548. default:
  549. return false;
  550. }
  551. for (size_t index = 0; index < length; ++index)
  552. {
  553. value[index] = newvector[index];
  554. }
  555. return true;
  556. }
  557. bool LLSettingsBase::Validator::verifyVectorMinMax(LLSD& value, U32,
  558. LLSD minvals, LLSD maxvals)
  559. {
  560. for (U32 index = 0, count = value.size(); index < count; ++index)
  561. {
  562. if (minvals[index].asString() != "*" &&
  563. minvals[index].asReal() > value[index].asReal())
  564. {
  565. value[index] = minvals[index].asReal();
  566. }
  567. if (maxvals[index].asString() != "*" &&
  568. maxvals[index].asReal() < value[index].asReal())
  569. {
  570. value[index] = maxvals[index].asReal();
  571. }
  572. }
  573. return true;
  574. }
  575. bool LLSettingsBase::Validator::verifyQuaternion(LLSD& value, U32)
  576. {
  577. return value.size() == 4;
  578. }
  579. bool LLSettingsBase::Validator::verifyQuaternionNormal(LLSD& value, U32)
  580. {
  581. if (value.size() != 4)
  582. {
  583. return false;
  584. }
  585. LLQuaternion quat(value);
  586. if (is_approx_equal(quat.normalize(), 1.f))
  587. {
  588. return true;
  589. }
  590. LLSD newquat = quat.getValue();
  591. for (S32 index = 0; index < 4; ++index)
  592. {
  593. value[index] = newquat[index];
  594. }
  595. return true;
  596. }
  597. bool LLSettingsBase::Validator::verifyFloatRange(LLSD& value, U32, LLSD range)
  598. {
  599. F64 real = value.asReal();
  600. F64 clampedval = llclamp(LLSD::Real(real), range[0].asReal(),
  601. range[1].asReal());
  602. if (!is_approx_equal(clampedval, real))
  603. {
  604. value = LLSD::Real(clampedval);
  605. }
  606. return true;
  607. }
  608. bool LLSettingsBase::Validator::verifyIntegerRange(LLSD& value, U32,
  609. LLSD range)
  610. {
  611. S32 ival = value.asInteger();
  612. S32 clampedval = llclamp(LLSD::Integer(ival), range[0].asInteger(),
  613. range[1].asInteger());
  614. if (clampedval != ival)
  615. {
  616. value = LLSD::Integer(clampedval);
  617. }
  618. return true;
  619. }
  620. bool LLSettingsBase::Validator::verifyStringLength(LLSD& value, U32,
  621. size_t length)
  622. {
  623. std::string sval = value.asString();
  624. if (!sval.empty())
  625. {
  626. sval = sval.substr(0, length);
  627. value = LLSD::String(sval);
  628. }
  629. return true;
  630. }
  631. void LLSettingsBlender::update(F64 blendf)
  632. {
  633. F64 res = setBlendFactor(blendf);
  634. if (res >= 0.0 && res < 1.0)
  635. {
  636. mTarget->update();
  637. }
  638. else
  639. {
  640. llassert(false);
  641. }
  642. }
  643. F64 LLSettingsBlender::setBlendFactor(F64 blendf_in)
  644. {
  645. F32 blendf = blendf_in;
  646. if (blendf >= 1.f)
  647. {
  648. triggerComplete();
  649. }
  650. blendf = llclamp(blendf, 0.f, 1.f);
  651. if (mTarget)
  652. {
  653. mTarget->replaceSettings(mInitial->getSettings());
  654. mTarget->blend(mFinal, blendf);
  655. }
  656. else
  657. {
  658. llwarns << "No target for settings blender." << llendl;
  659. }
  660. return blendf;
  661. }
  662. void LLSettingsBlender::triggerComplete()
  663. {
  664. if (mTarget)
  665. {
  666. mTarget->replaceSettings(mFinal->getSettings());
  667. }
  668. // Prevents this from deleting too soon
  669. LLSettingsBlender::ptr_t hold = shared_from_this();
  670. mTarget->update();
  671. mOnFinished(shared_from_this());
  672. }
  673. void LLSettingsBlender::reset(LLSettingsBase::ptr_t& initsetting,
  674. const LLSettingsBase::ptr_t& endsetting, F32)
  675. {
  676. // Note: the 'span' reset parameter is unused by the base class.
  677. if (!mInitial)
  678. {
  679. llwarns << "Reseting blender with empty initial setting. Expect badness in the future."
  680. << llendl;
  681. }
  682. mInitial = initsetting;
  683. mFinal = endsetting;
  684. if (!mFinal)
  685. {
  686. mFinal = mInitial;
  687. }
  688. if (mTarget)
  689. {
  690. mTarget->replaceSettings(mInitial->getSettings());
  691. }
  692. }
  693. F64 LLSettingsBlenderTimeDelta::calculateBlend(F32 spanpos, F32 spanlen) const
  694. {
  695. return fmod((F64)spanpos, (F64)spanlen) / (F64)spanlen;
  696. }
  697. bool LLSettingsBlenderTimeDelta::applyTimeDelta(F64 timedelta)
  698. {
  699. mTimeSpent += timedelta;
  700. if (mTimeSpent > mBlendSpan)
  701. {
  702. triggerComplete();
  703. return false;
  704. }
  705. F64 blendf = calculateBlend(mTimeSpent, mBlendSpan);
  706. if (fabs(mLastBlendF - blendf) < mBlendFMinDelta)
  707. {
  708. return false;
  709. }
  710. mLastBlendF = blendf;
  711. update(blendf);
  712. return true;
  713. }