PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llxml/llcontrol.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 1309 lines | 1007 code | 201 blank | 101 comment | 119 complexity | 34ff542f0ded867cea613f60bd5c16c0 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llcontrol.cpp
  3. * @brief Holds global state for viewer.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "linden_common.h"
  27. #include <iostream>
  28. #include <fstream>
  29. #include <algorithm>
  30. #include "llcontrol.h"
  31. #include "llstl.h"
  32. #include "llstring.h"
  33. #include "v3math.h"
  34. #include "v3dmath.h"
  35. #include "v4coloru.h"
  36. #include "v4color.h"
  37. #include "v3color.h"
  38. #include "llrect.h"
  39. #include "llxmltree.h"
  40. #include "llsdserialize.h"
  41. #if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
  42. #define CONTROL_ERRS LL_ERRS("ControlErrors")
  43. #else
  44. #define CONTROL_ERRS LL_WARNS("ControlErrors")
  45. #endif
  46. template <> eControlType get_control_type<U32>();
  47. template <> eControlType get_control_type<S32>();
  48. template <> eControlType get_control_type<F32>();
  49. template <> eControlType get_control_type<bool>();
  50. // Yay BOOL, its really an S32.
  51. //template <> eControlType get_control_type<BOOL> () ;
  52. template <> eControlType get_control_type<std::string>();
  53. template <> eControlType get_control_type<LLVector3>();
  54. template <> eControlType get_control_type<LLVector3d>();
  55. template <> eControlType get_control_type<LLRect>();
  56. template <> eControlType get_control_type<LLColor4>();
  57. template <> eControlType get_control_type<LLColor3>();
  58. template <> eControlType get_control_type<LLColor4U>();
  59. template <> eControlType get_control_type<LLSD>();
  60. template <> LLSD convert_to_llsd<U32>(const U32& in);
  61. template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in);
  62. template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in);
  63. template <> LLSD convert_to_llsd<LLRect>(const LLRect& in);
  64. template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in);
  65. template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in);
  66. template <> LLSD convert_to_llsd<LLColor4U>(const LLColor4U& in);
  67. template <> bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::string& control_name);
  68. template <> S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string& control_name);
  69. template <> U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string& control_name);
  70. template <> F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string& control_name);
  71. template <> std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, const std::string& control_name);
  72. template <> LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const std::string& control_name);
  73. template <> LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const std::string& control_name);
  74. template <> LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const std::string& control_name);
  75. template <> LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name);
  76. template <> LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const std::string& control_name);
  77. template <> LLColor4U convert_from_llsd<LLColor4U>(const LLSD& sd, eControlType type, const std::string& control_name);
  78. template <> LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const std::string& control_name);
  79. template <> LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const std::string& control_name);
  80. //this defines the current version of the settings file
  81. const S32 CURRENT_VERSION = 101;
  82. bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b)
  83. {
  84. bool result = false;
  85. switch (mType)
  86. {
  87. case TYPE_U32:
  88. case TYPE_S32:
  89. result = a.asInteger() == b.asInteger();
  90. break;
  91. case TYPE_BOOLEAN:
  92. result = a.asBoolean() == b.asBoolean();
  93. break;
  94. case TYPE_F32:
  95. result = a.asReal() == b.asReal();
  96. break;
  97. case TYPE_VEC3:
  98. case TYPE_VEC3D:
  99. result = LLVector3d(a) == LLVector3d(b);
  100. break;
  101. case TYPE_RECT:
  102. result = LLRect(a) == LLRect(b);
  103. break;
  104. case TYPE_COL4:
  105. result = LLColor4(a) == LLColor4(b);
  106. break;
  107. case TYPE_COL3:
  108. result = LLColor3(a) == LLColor3(b);
  109. break;
  110. case TYPE_STRING:
  111. result = a.asString() == b.asString();
  112. break;
  113. default:
  114. break;
  115. }
  116. return result;
  117. }
  118. LLControlVariable::LLControlVariable(const std::string& name, eControlType type,
  119. LLSD initial, const std::string& comment,
  120. bool persist, bool hidefromsettingseditor)
  121. : mName(name),
  122. mComment(comment),
  123. mType(type),
  124. mPersist(persist),
  125. mHideFromSettingsEditor(hidefromsettingseditor)
  126. {
  127. if (mPersist && mComment.empty())
  128. {
  129. llerrs << "Must supply a comment for control " << mName << llendl;
  130. }
  131. //Push back versus setValue'ing here, since we don't want to call a signal yet
  132. mValues.push_back(initial);
  133. }
  134. LLControlVariable::~LLControlVariable()
  135. {
  136. }
  137. LLSD LLControlVariable::getComparableValue(const LLSD& value)
  138. {
  139. // *FIX:MEP - The following is needed to make the LLSD::ImplString
  140. // work with boolean controls...
  141. LLSD storable_value;
  142. if(TYPE_BOOLEAN == type() && value.isString())
  143. {
  144. BOOL temp;
  145. if(LLStringUtil::convertToBOOL(value.asString(), temp))
  146. {
  147. storable_value = (bool)temp;
  148. }
  149. else
  150. {
  151. storable_value = false;
  152. }
  153. }
  154. else if (TYPE_LLSD == type() && value.isString())
  155. {
  156. LLPointer<LLSDNotationParser> parser = new LLSDNotationParser;
  157. LLSD result;
  158. std::stringstream value_stream(value.asString());
  159. if (parser->parse(value_stream, result, LLSDSerialize::SIZE_UNLIMITED) != LLSDParser::PARSE_FAILURE)
  160. {
  161. storable_value = result;
  162. }
  163. else
  164. {
  165. storable_value = value;
  166. }
  167. }
  168. else
  169. {
  170. storable_value = value;
  171. }
  172. return storable_value;
  173. }
  174. void LLControlVariable::setValue(const LLSD& new_value, bool saved_value)
  175. {
  176. if (mValidateSignal(this, new_value) == false)
  177. {
  178. // can not set new value, exit
  179. return;
  180. }
  181. LLSD storable_value = getComparableValue(new_value);
  182. bool value_changed = llsd_compare(getValue(), storable_value) == FALSE;
  183. if(saved_value)
  184. {
  185. // If we're going to save this value, return to default but don't fire
  186. resetToDefault(false);
  187. if (llsd_compare(mValues.back(), storable_value) == FALSE)
  188. {
  189. mValues.push_back(storable_value);
  190. }
  191. }
  192. else
  193. {
  194. // This is an unsaved value. Its needs to reside at
  195. // mValues[2] (or greater). It must not affect
  196. // the result of getSaveValue()
  197. if (llsd_compare(mValues.back(), storable_value) == FALSE)
  198. {
  199. while(mValues.size() > 2)
  200. {
  201. // Remove any unsaved values.
  202. mValues.pop_back();
  203. }
  204. if(mValues.size() < 2)
  205. {
  206. // Add the default to the 'save' value.
  207. mValues.push_back(mValues[0]);
  208. }
  209. // Add the 'un-save' value.
  210. mValues.push_back(storable_value);
  211. }
  212. }
  213. if(value_changed)
  214. {
  215. mCommitSignal(this, storable_value);
  216. }
  217. }
  218. void LLControlVariable::setDefaultValue(const LLSD& value)
  219. {
  220. // Set the control variables value and make it
  221. // the default value. If the active value is changed,
  222. // send the signal.
  223. // *NOTE: Default values are not saved, only read.
  224. LLSD comparable_value = getComparableValue(value);
  225. bool value_changed = (llsd_compare(getValue(), comparable_value) == FALSE);
  226. resetToDefault(false);
  227. mValues[0] = comparable_value;
  228. if(value_changed)
  229. {
  230. firePropertyChanged();
  231. }
  232. }
  233. void LLControlVariable::setPersist(bool state)
  234. {
  235. mPersist = state;
  236. }
  237. void LLControlVariable::setHiddenFromSettingsEditor(bool hide)
  238. {
  239. mHideFromSettingsEditor = hide;
  240. }
  241. void LLControlVariable::setComment(const std::string& comment)
  242. {
  243. mComment = comment;
  244. }
  245. void LLControlVariable::resetToDefault(bool fire_signal)
  246. {
  247. //The first setting is always the default
  248. //Pop to it and fire off the listener
  249. while(mValues.size() > 1)
  250. {
  251. mValues.pop_back();
  252. }
  253. if(fire_signal)
  254. {
  255. firePropertyChanged();
  256. }
  257. }
  258. bool LLControlVariable::isSaveValueDefault()
  259. {
  260. return (mValues.size() == 1)
  261. || ((mValues.size() > 1) && llsd_compare(mValues[1], mValues[0]));
  262. }
  263. LLSD LLControlVariable::getSaveValue() const
  264. {
  265. //The first level of the stack is default
  266. //We assume that the second level is user preferences that should be saved
  267. if(mValues.size() > 1) return mValues[1];
  268. return mValues[0];
  269. }
  270. LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name)
  271. {
  272. ctrl_name_table_t::iterator iter = mNameTable.find(name);
  273. return iter == mNameTable.end() ? LLPointer<LLControlVariable>() : iter->second;
  274. }
  275. ////////////////////////////////////////////////////////////////////////////
  276. LLControlGroup::LLControlGroup(const std::string& name)
  277. : LLInstanceTracker<LLControlGroup, std::string>(name)
  278. {
  279. mTypeString[TYPE_U32] = "U32";
  280. mTypeString[TYPE_S32] = "S32";
  281. mTypeString[TYPE_F32] = "F32";
  282. mTypeString[TYPE_BOOLEAN] = "Boolean";
  283. mTypeString[TYPE_STRING] = "String";
  284. mTypeString[TYPE_VEC3] = "Vector3";
  285. mTypeString[TYPE_VEC3D] = "Vector3D";
  286. mTypeString[TYPE_RECT] = "Rect";
  287. mTypeString[TYPE_COL4] = "Color4";
  288. mTypeString[TYPE_COL3] = "Color3";
  289. mTypeString[TYPE_LLSD] = "LLSD";
  290. }
  291. LLControlGroup::~LLControlGroup()
  292. {
  293. cleanup();
  294. }
  295. void LLControlGroup::cleanup()
  296. {
  297. mNameTable.clear();
  298. }
  299. eControlType LLControlGroup::typeStringToEnum(const std::string& typestr)
  300. {
  301. for(int i = 0; i < (int)TYPE_COUNT; ++i)
  302. {
  303. if(mTypeString[i] == typestr) return (eControlType)i;
  304. }
  305. return (eControlType)-1;
  306. }
  307. std::string LLControlGroup::typeEnumToString(eControlType typeenum)
  308. {
  309. return mTypeString[typeenum];
  310. }
  311. BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor)
  312. {
  313. LLControlVariable* existing_control = getControl(name);
  314. if (existing_control)
  315. {
  316. if (persist && existing_control->isType(type))
  317. {
  318. if (!existing_control->llsd_compare(existing_control->getDefault(), initial_val))
  319. {
  320. // Sometimes we need to declare a control *after* it has been loaded from a settings file.
  321. LLSD cur_value = existing_control->getValue(); // get the current value
  322. existing_control->setDefaultValue(initial_val); // set the default to the declared value
  323. existing_control->setValue(cur_value); // now set to the loaded value
  324. }
  325. }
  326. else
  327. {
  328. llwarns << "Control named " << name << " already exists, ignoring new declaration." << llendl;
  329. }
  330. return TRUE;
  331. }
  332. // if not, create the control and add it to the name table
  333. LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist, hidefromsettingseditor);
  334. mNameTable[name] = control;
  335. return TRUE;
  336. }
  337. BOOL LLControlGroup::declareU32(const std::string& name, const U32 initial_val, const std::string& comment, BOOL persist)
  338. {
  339. return declareControl(name, TYPE_U32, (LLSD::Integer) initial_val, comment, persist);
  340. }
  341. BOOL LLControlGroup::declareS32(const std::string& name, const S32 initial_val, const std::string& comment, BOOL persist)
  342. {
  343. return declareControl(name, TYPE_S32, initial_val, comment, persist);
  344. }
  345. BOOL LLControlGroup::declareF32(const std::string& name, const F32 initial_val, const std::string& comment, BOOL persist)
  346. {
  347. return declareControl(name, TYPE_F32, initial_val, comment, persist);
  348. }
  349. BOOL LLControlGroup::declareBOOL(const std::string& name, const BOOL initial_val, const std::string& comment, BOOL persist)
  350. {
  351. return declareControl(name, TYPE_BOOLEAN, initial_val, comment, persist);
  352. }
  353. BOOL LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, BOOL persist)
  354. {
  355. return declareControl(name, TYPE_STRING, initial_val, comment, persist);
  356. }
  357. BOOL LLControlGroup::declareVec3(const std::string& name, const LLVector3 &initial_val, const std::string& comment, BOOL persist)
  358. {
  359. return declareControl(name, TYPE_VEC3, initial_val.getValue(), comment, persist);
  360. }
  361. BOOL LLControlGroup::declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist)
  362. {
  363. return declareControl(name, TYPE_VEC3D, initial_val.getValue(), comment, persist);
  364. }
  365. BOOL LLControlGroup::declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist)
  366. {
  367. return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist);
  368. }
  369. BOOL LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist )
  370. {
  371. return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist);
  372. }
  373. BOOL LLControlGroup::declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist )
  374. {
  375. return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist);
  376. }
  377. BOOL LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist )
  378. {
  379. return declareControl(name, TYPE_LLSD, initial_val, comment, persist);
  380. }
  381. BOOL LLControlGroup::getBOOL(const std::string& name)
  382. {
  383. return (BOOL)get<bool>(name);
  384. }
  385. S32 LLControlGroup::getS32(const std::string& name)
  386. {
  387. return get<S32>(name);
  388. }
  389. U32 LLControlGroup::getU32(const std::string& name)
  390. {
  391. return get<U32>(name);
  392. }
  393. F32 LLControlGroup::getF32(const std::string& name)
  394. {
  395. return get<F32>(name);
  396. }
  397. std::string LLControlGroup::getString(const std::string& name)
  398. {
  399. return get<std::string>(name);
  400. }
  401. LLWString LLControlGroup::getWString(const std::string& name)
  402. {
  403. return get<LLWString>(name);
  404. }
  405. std::string LLControlGroup::getText(const std::string& name)
  406. {
  407. std::string utf8_string = getString(name);
  408. LLStringUtil::replaceChar(utf8_string, '^', '\n');
  409. LLStringUtil::replaceChar(utf8_string, '%', ' ');
  410. return (utf8_string);
  411. }
  412. LLVector3 LLControlGroup::getVector3(const std::string& name)
  413. {
  414. return get<LLVector3>(name);
  415. }
  416. LLVector3d LLControlGroup::getVector3d(const std::string& name)
  417. {
  418. return get<LLVector3d>(name);
  419. }
  420. LLRect LLControlGroup::getRect(const std::string& name)
  421. {
  422. return get<LLRect>(name);
  423. }
  424. LLColor4 LLControlGroup::getColor(const std::string& name)
  425. {
  426. return get<LLColor4>(name);
  427. }
  428. LLColor4 LLControlGroup::getColor4(const std::string& name)
  429. {
  430. return get<LLColor4>(name);
  431. }
  432. LLColor3 LLControlGroup::getColor3(const std::string& name)
  433. {
  434. return get<LLColor3>(name);
  435. }
  436. LLSD LLControlGroup::getLLSD(const std::string& name)
  437. {
  438. return get<LLSD>(name);
  439. }
  440. BOOL LLControlGroup::controlExists(const std::string& name)
  441. {
  442. ctrl_name_table_t::iterator iter = mNameTable.find(name);
  443. return iter != mNameTable.end();
  444. }
  445. //-------------------------------------------------------------------
  446. // Set functions
  447. //-------------------------------------------------------------------
  448. void LLControlGroup::setBOOL(const std::string& name, BOOL val)
  449. {
  450. set<bool>(name, val);
  451. }
  452. void LLControlGroup::setS32(const std::string& name, S32 val)
  453. {
  454. set(name, val);
  455. }
  456. void LLControlGroup::setF32(const std::string& name, F32 val)
  457. {
  458. set(name, val);
  459. }
  460. void LLControlGroup::setU32(const std::string& name, U32 val)
  461. {
  462. set(name, val);
  463. }
  464. void LLControlGroup::setString(const std::string& name, const std::string &val)
  465. {
  466. set(name, val);
  467. }
  468. void LLControlGroup::setVector3(const std::string& name, const LLVector3 &val)
  469. {
  470. set(name, val);
  471. }
  472. void LLControlGroup::setVector3d(const std::string& name, const LLVector3d &val)
  473. {
  474. set(name, val);
  475. }
  476. void LLControlGroup::setRect(const std::string& name, const LLRect &val)
  477. {
  478. set(name, val);
  479. }
  480. void LLControlGroup::setColor4(const std::string& name, const LLColor4 &val)
  481. {
  482. set(name, val);
  483. }
  484. void LLControlGroup::setLLSD(const std::string& name, const LLSD& val)
  485. {
  486. set(name, val);
  487. }
  488. void LLControlGroup::setUntypedValue(const std::string& name, const LLSD& val)
  489. {
  490. if (name.empty())
  491. {
  492. return;
  493. }
  494. LLControlVariable* control = getControl(name);
  495. if (control)
  496. {
  497. control->setValue(val);
  498. }
  499. else
  500. {
  501. CONTROL_ERRS << "Invalid control " << name << llendl;
  502. }
  503. }
  504. //---------------------------------------------------------------
  505. // Load and save
  506. //---------------------------------------------------------------
  507. // Returns number of controls loaded, so 0 if failure
  508. U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require_declaration, eControlType declare_as)
  509. {
  510. std::string name;
  511. LLXmlTree xml_controls;
  512. if (!xml_controls.parseFile(filename))
  513. {
  514. llwarns << "Unable to open control file " << filename << llendl;
  515. return 0;
  516. }
  517. LLXmlTreeNode* rootp = xml_controls.getRoot();
  518. if (!rootp || !rootp->hasAttribute("version"))
  519. {
  520. llwarns << "No valid settings header found in control file " << filename << llendl;
  521. return 0;
  522. }
  523. U32 item = 0;
  524. U32 validitems = 0;
  525. S32 version;
  526. rootp->getAttributeS32("version", version);
  527. // Check file version
  528. if (version != CURRENT_VERSION)
  529. {
  530. llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl;
  531. return 0;
  532. }
  533. LLXmlTreeNode* child_nodep = rootp->getFirstChild();
  534. while(child_nodep)
  535. {
  536. name = child_nodep->getName();
  537. BOOL declared = controlExists(name);
  538. if (require_declaration && !declared)
  539. {
  540. // Declaration required, but this name not declared.
  541. // Complain about non-empty names.
  542. if (!name.empty())
  543. {
  544. //read in to end of line
  545. llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl;
  546. }
  547. child_nodep = rootp->getNextChild();
  548. continue;
  549. }
  550. // Got an item. Load it up.
  551. item++;
  552. // If not declared, assume it's a string
  553. if (!declared)
  554. {
  555. switch(declare_as)
  556. {
  557. case TYPE_COL4:
  558. declareColor4(name, LLColor4::white, LLStringUtil::null, NO_PERSIST);
  559. break;
  560. case TYPE_STRING:
  561. default:
  562. declareString(name, LLStringUtil::null, LLStringUtil::null, NO_PERSIST);
  563. break;
  564. }
  565. }
  566. // Control name has been declared in code.
  567. LLControlVariable *control = getControl(name);
  568. llassert(control);
  569. switch(control->mType)
  570. {
  571. case TYPE_F32:
  572. {
  573. F32 initial = 0.f;
  574. child_nodep->getAttributeF32("value", initial);
  575. control->set(initial);
  576. validitems++;
  577. }
  578. break;
  579. case TYPE_S32:
  580. {
  581. S32 initial = 0;
  582. child_nodep->getAttributeS32("value", initial);
  583. control->set(initial);
  584. validitems++;
  585. }
  586. break;
  587. case TYPE_U32:
  588. {
  589. U32 initial = 0;
  590. child_nodep->getAttributeU32("value", initial);
  591. control->set((LLSD::Integer) initial);
  592. validitems++;
  593. }
  594. break;
  595. case TYPE_BOOLEAN:
  596. {
  597. BOOL initial = FALSE;
  598. child_nodep->getAttributeBOOL("value", initial);
  599. control->set(initial);
  600. validitems++;
  601. }
  602. break;
  603. case TYPE_STRING:
  604. {
  605. std::string string;
  606. child_nodep->getAttributeString("value", string);
  607. control->set(string);
  608. validitems++;
  609. }
  610. break;
  611. case TYPE_VEC3:
  612. {
  613. LLVector3 vector;
  614. child_nodep->getAttributeVector3("value", vector);
  615. control->set(vector.getValue());
  616. validitems++;
  617. }
  618. break;
  619. case TYPE_VEC3D:
  620. {
  621. LLVector3d vector;
  622. child_nodep->getAttributeVector3d("value", vector);
  623. control->set(vector.getValue());
  624. validitems++;
  625. }
  626. break;
  627. case TYPE_RECT:
  628. {
  629. //RN: hack to support reading rectangles from a string
  630. std::string rect_string;
  631. child_nodep->getAttributeString("value", rect_string);
  632. std::istringstream istream(rect_string);
  633. S32 left, bottom, width, height;
  634. istream >> left >> bottom >> width >> height;
  635. LLRect rect;
  636. rect.setOriginAndSize(left, bottom, width, height);
  637. control->set(rect.getValue());
  638. validitems++;
  639. }
  640. break;
  641. case TYPE_COL4:
  642. {
  643. LLColor4 color;
  644. child_nodep->getAttributeColor4("value", color);
  645. control->set(color.getValue());
  646. validitems++;
  647. }
  648. break;
  649. case TYPE_COL3:
  650. {
  651. LLVector3 color;
  652. child_nodep->getAttributeVector3("value", color);
  653. control->set(LLColor3(color.mV).getValue());
  654. validitems++;
  655. }
  656. break;
  657. default:
  658. break;
  659. }
  660. child_nodep = rootp->getNextChild();
  661. }
  662. return validitems;
  663. }
  664. U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only)
  665. {
  666. LLSD settings;
  667. int num_saved = 0;
  668. for (ctrl_name_table_t::iterator iter = mNameTable.begin();
  669. iter != mNameTable.end(); iter++)
  670. {
  671. LLControlVariable* control = iter->second;
  672. if (!control)
  673. {
  674. llwarns << "Tried to save invalid control: " << iter->first << llendl;
  675. }
  676. if( control && control->isPersisted() )
  677. {
  678. if (!(nondefault_only && (control->isSaveValueDefault())))
  679. {
  680. settings[iter->first]["Type"] = typeEnumToString(control->type());
  681. settings[iter->first]["Comment"] = control->getComment();
  682. settings[iter->first]["Value"] = control->getSaveValue();
  683. ++num_saved;
  684. }
  685. else
  686. {
  687. // Debug spam
  688. // llinfos << "Skipping " << control->getName() << llendl;
  689. }
  690. }
  691. }
  692. llofstream file;
  693. file.open(filename);
  694. if (file.is_open())
  695. {
  696. LLSDSerialize::toPrettyXML(settings, file);
  697. file.close();
  698. llinfos << "Saved to " << filename << llendl;
  699. }
  700. else
  701. {
  702. // This is a warning because sometime we want to use settings files which can't be written...
  703. llwarns << "Unable to open settings file: " << filename << llendl;
  704. return 0;
  705. }
  706. return num_saved;
  707. }
  708. U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_values, bool save_values)
  709. {
  710. LLSD settings;
  711. llifstream infile;
  712. infile.open(filename);
  713. if(!infile.is_open())
  714. {
  715. llwarns << "Cannot find file " << filename << " to load." << llendl;
  716. return 0;
  717. }
  718. S32 ret = LLSDSerialize::fromXML(settings, infile);
  719. if (ret <= 0)
  720. {
  721. infile.close();
  722. llwarns << "Unable to open LLSD control file " << filename << ". Trying Legacy Method." << llendl;
  723. return loadFromFileLegacy(filename, TRUE, TYPE_STRING);
  724. }
  725. U32 validitems = 0;
  726. bool hidefromsettingseditor = false;
  727. for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr)
  728. {
  729. bool persist = true;
  730. std::string const & name = itr->first;
  731. LLSD const & control_map = itr->second;
  732. if(control_map.has("Persist"))
  733. {
  734. persist = control_map["Persist"].asInteger();
  735. }
  736. // Sometimes we want to use the settings system to provide cheap persistence, but we
  737. // don't want the settings themselves to be easily manipulated in the UI because
  738. // doing so can cause support problems. So we have this option:
  739. if(control_map.has("HideFromEditor"))
  740. {
  741. hidefromsettingseditor = control_map["HideFromEditor"].asInteger();
  742. }
  743. else
  744. {
  745. hidefromsettingseditor = false;
  746. }
  747. // If the control exists just set the value from the input file.
  748. LLControlVariable* existing_control = getControl(name);
  749. if(existing_control)
  750. {
  751. if(set_default_values)
  752. {
  753. // Override all previously set properties of this control.
  754. // ... except for type. The types must match.
  755. eControlType new_type = typeStringToEnum(control_map["Type"].asString());
  756. if(existing_control->isType(new_type))
  757. {
  758. existing_control->setDefaultValue(control_map["Value"]);
  759. existing_control->setPersist(persist);
  760. existing_control->setHiddenFromSettingsEditor(hidefromsettingseditor);
  761. existing_control->setComment(control_map["Comment"].asString());
  762. }
  763. else
  764. {
  765. llerrs << "Mismatched type of control variable '"
  766. << name << "' found while loading '"
  767. << filename << "'." << llendl;
  768. }
  769. }
  770. else if(existing_control->isPersisted())
  771. {
  772. existing_control->setValue(control_map["Value"], save_values);
  773. }
  774. // *NOTE: If not persisted and not setting defaults,
  775. // the value should not get loaded.
  776. }
  777. else
  778. {
  779. declareControl(name,
  780. typeStringToEnum(control_map["Type"].asString()),
  781. control_map["Value"],
  782. control_map["Comment"].asString(),
  783. persist,
  784. hidefromsettingseditor
  785. );
  786. }
  787. ++validitems;
  788. }
  789. return validitems;
  790. }
  791. void LLControlGroup::resetToDefaults()
  792. {
  793. ctrl_name_table_t::iterator control_iter;
  794. for (control_iter = mNameTable.begin();
  795. control_iter != mNameTable.end();
  796. ++control_iter)
  797. {
  798. LLControlVariable* control = (*control_iter).second;
  799. control->resetToDefault();
  800. }
  801. }
  802. void LLControlGroup::applyToAll(ApplyFunctor* func)
  803. {
  804. for (ctrl_name_table_t::iterator iter = mNameTable.begin();
  805. iter != mNameTable.end(); iter++)
  806. {
  807. func->apply(iter->first, iter->second);
  808. }
  809. }
  810. //============================================================================
  811. #ifdef TEST_HARNESS
  812. void main()
  813. {
  814. F32_CONTROL foo, getfoo;
  815. S32_CONTROL bar, getbar;
  816. BOOL_CONTROL baz;
  817. U32 count = gGlobals.loadFromFile("controls.ini");
  818. llinfos << "Loaded " << count << " controls" << llendl;
  819. // test insertion
  820. foo = new LLControlVariable<F32>("gFoo", 5.f, 1.f, 20.f);
  821. gGlobals.addEntry("gFoo", foo);
  822. bar = new LLControlVariable<S32>("gBar", 10, 2, 22);
  823. gGlobals.addEntry("gBar", bar);
  824. baz = new LLControlVariable<BOOL>("gBaz", FALSE);
  825. gGlobals.addEntry("gBaz", baz);
  826. // test retrieval
  827. getfoo = (LLControlVariable<F32>*) gGlobals.resolveName("gFoo");
  828. getfoo->dump();
  829. getbar = (S32_CONTROL) gGlobals.resolveName("gBar");
  830. getbar->dump();
  831. // change data
  832. getfoo->set(10.f);
  833. getfoo->dump();
  834. // Failure modes
  835. // ...min > max
  836. // badfoo = new LLControlVariable<F32>("gFoo2", 100.f, 20.f, 5.f);
  837. // ...initial > max
  838. // badbar = new LLControlVariable<S32>("gBar2", 10, 20, 100000);
  839. // ...misspelled name
  840. // getfoo = (F32_CONTROL) gGlobals.resolveName("fooMisspelled");
  841. // getfoo->dump();
  842. // ...invalid data type
  843. getfoo = (F32_CONTROL) gGlobals.resolveName("gFoo");
  844. getfoo->set(TRUE);
  845. getfoo->dump();
  846. // ...out of range data
  847. // getfoo->set(100000000.f);
  848. // getfoo->dump();
  849. // Clean Up
  850. delete foo;
  851. delete bar;
  852. delete baz;
  853. }
  854. #endif
  855. template <> eControlType get_control_type<U32>()
  856. {
  857. return TYPE_U32;
  858. }
  859. template <> eControlType get_control_type<S32>()
  860. {
  861. return TYPE_S32;
  862. }
  863. template <> eControlType get_control_type<F32>()
  864. {
  865. return TYPE_F32;
  866. }
  867. template <> eControlType get_control_type<bool> ()
  868. {
  869. return TYPE_BOOLEAN;
  870. }
  871. /*
  872. // Yay BOOL, its really an S32.
  873. template <> eControlType get_control_type<BOOL> ()
  874. {
  875. return TYPE_BOOLEAN;
  876. }
  877. */
  878. template <> eControlType get_control_type<std::string>()
  879. {
  880. return TYPE_STRING;
  881. }
  882. template <> eControlType get_control_type<LLVector3>()
  883. {
  884. return TYPE_VEC3;
  885. }
  886. template <> eControlType get_control_type<LLVector3d>()
  887. {
  888. return TYPE_VEC3D;
  889. }
  890. template <> eControlType get_control_type<LLRect>()
  891. {
  892. return TYPE_RECT;
  893. }
  894. template <> eControlType get_control_type<LLColor4>()
  895. {
  896. return TYPE_COL4;
  897. }
  898. template <> eControlType get_control_type<LLColor3>()
  899. {
  900. return TYPE_COL3;
  901. }
  902. template <> eControlType get_control_type<LLSD>()
  903. {
  904. return TYPE_LLSD;
  905. }
  906. template <> LLSD convert_to_llsd<U32>(const U32& in)
  907. {
  908. return (LLSD::Integer)in;
  909. }
  910. template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in)
  911. {
  912. return in.getValue();
  913. }
  914. template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in)
  915. {
  916. return in.getValue();
  917. }
  918. template <> LLSD convert_to_llsd<LLRect>(const LLRect& in)
  919. {
  920. return in.getValue();
  921. }
  922. template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in)
  923. {
  924. return in.getValue();
  925. }
  926. template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in)
  927. {
  928. return in.getValue();
  929. }
  930. template <> LLSD convert_to_llsd<LLColor4U>(const LLColor4U& in)
  931. {
  932. return in.getValue();
  933. }
  934. template<>
  935. bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::string& control_name)
  936. {
  937. if (type == TYPE_BOOLEAN)
  938. return sd.asBoolean();
  939. else
  940. {
  941. CONTROL_ERRS << "Invalid BOOL value for " << control_name << ": " << sd << llendl;
  942. return FALSE;
  943. }
  944. }
  945. template<>
  946. S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string& control_name)
  947. {
  948. if (type == TYPE_S32)
  949. return sd.asInteger();
  950. else
  951. {
  952. CONTROL_ERRS << "Invalid S32 value for " << control_name << ": " << sd << llendl;
  953. return 0;
  954. }
  955. }
  956. template<>
  957. U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string& control_name)
  958. {
  959. if (type == TYPE_U32)
  960. return sd.asInteger();
  961. else
  962. {
  963. CONTROL_ERRS << "Invalid U32 value for " << control_name << ": " << sd << llendl;
  964. return 0;
  965. }
  966. }
  967. template<>
  968. F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string& control_name)
  969. {
  970. if (type == TYPE_F32)
  971. return (F32) sd.asReal();
  972. else
  973. {
  974. CONTROL_ERRS << "Invalid F32 value for " << control_name << ": " << sd << llendl;
  975. return 0.0f;
  976. }
  977. }
  978. template<>
  979. std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, const std::string& control_name)
  980. {
  981. if (type == TYPE_STRING)
  982. return sd.asString();
  983. else
  984. {
  985. CONTROL_ERRS << "Invalid string value for " << control_name << ": " << sd << llendl;
  986. return LLStringUtil::null;
  987. }
  988. }
  989. template<>
  990. LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const std::string& control_name)
  991. {
  992. return utf8str_to_wstring(convert_from_llsd<std::string>(sd, type, control_name));
  993. }
  994. template<>
  995. LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const std::string& control_name)
  996. {
  997. if (type == TYPE_VEC3)
  998. return (LLVector3)sd;
  999. else
  1000. {
  1001. CONTROL_ERRS << "Invalid LLVector3 value for " << control_name << ": " << sd << llendl;
  1002. return LLVector3::zero;
  1003. }
  1004. }
  1005. template<>
  1006. LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const std::string& control_name)
  1007. {
  1008. if (type == TYPE_VEC3D)
  1009. return (LLVector3d)sd;
  1010. else
  1011. {
  1012. CONTROL_ERRS << "Invalid LLVector3d value for " << control_name << ": " << sd << llendl;
  1013. return LLVector3d::zero;
  1014. }
  1015. }
  1016. template<>
  1017. LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name)
  1018. {
  1019. if (type == TYPE_RECT)
  1020. return LLRect(sd);
  1021. else
  1022. {
  1023. CONTROL_ERRS << "Invalid rect value for " << control_name << ": " << sd << llendl;
  1024. return LLRect::null;
  1025. }
  1026. }
  1027. template<>
  1028. LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const std::string& control_name)
  1029. {
  1030. if (type == TYPE_COL4)
  1031. {
  1032. LLColor4 color(sd);
  1033. if (color.mV[VRED] < 0.f || color.mV[VRED] > 1.f)
  1034. {
  1035. llwarns << "Color " << control_name << " red value out of range: " << color << llendl;
  1036. }
  1037. else if (color.mV[VGREEN] < 0.f || color.mV[VGREEN] > 1.f)
  1038. {
  1039. llwarns << "Color " << control_name << " green value out of range: " << color << llendl;
  1040. }
  1041. else if (color.mV[VBLUE] < 0.f || color.mV[VBLUE] > 1.f)
  1042. {
  1043. llwarns << "Color " << control_name << " blue value out of range: " << color << llendl;
  1044. }
  1045. else if (color.mV[VALPHA] < 0.f || color.mV[VALPHA] > 1.f)
  1046. {
  1047. llwarns << "Color " << control_name << " alpha value out of range: " << color << llendl;
  1048. }
  1049. return LLColor4(sd);
  1050. }
  1051. else
  1052. {
  1053. CONTROL_ERRS << "Control " << control_name << " not a color" << llendl;
  1054. return LLColor4::white;
  1055. }
  1056. }
  1057. template<>
  1058. LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const std::string& control_name)
  1059. {
  1060. if (type == TYPE_COL3)
  1061. return sd;
  1062. else
  1063. {
  1064. CONTROL_ERRS << "Invalid LLColor3 value for " << control_name << ": " << sd << llendl;
  1065. return LLColor3::white;
  1066. }
  1067. }
  1068. template<>
  1069. LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const std::string& control_name)
  1070. {
  1071. return sd;
  1072. }
  1073. #if TEST_CACHED_CONTROL
  1074. #define DECL_LLCC(T, V) static LLCachedControl<T> mySetting_##T("TestCachedControl"#T, V)
  1075. DECL_LLCC(U32, (U32)666);
  1076. DECL_LLCC(S32, (S32)-666);
  1077. DECL_LLCC(F32, (F32)-666.666);
  1078. DECL_LLCC(bool, true);
  1079. DECL_LLCC(BOOL, FALSE);
  1080. static LLCachedControl<std::string> mySetting_string("TestCachedControlstring", "Default String Value");
  1081. DECL_LLCC(LLVector3, LLVector3(1.0f, 2.0f, 3.0f));
  1082. DECL_LLCC(LLVector3d, LLVector3d(6.0f, 5.0f, 4.0f));
  1083. DECL_LLCC(LLRect, LLRect(0, 0, 100, 500));
  1084. DECL_LLCC(LLColor4, LLColor4(0.0f, 0.5f, 1.0f));
  1085. DECL_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f));
  1086. DECL_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
  1087. LLSD test_llsd = LLSD()["testing1"] = LLSD()["testing2"];
  1088. DECL_LLCC(LLSD, test_llsd);
  1089. static LLCachedControl<std::string> test_BrowserHomePage("BrowserHomePage", "hahahahahha", "Not the real comment");
  1090. void test_cached_control()
  1091. {
  1092. #define TEST_LLCC(T, V) if((T)mySetting_##T != V) llerrs << "Fail "#T << llendl
  1093. TEST_LLCC(U32, 666);
  1094. TEST_LLCC(S32, (S32)-666);
  1095. TEST_LLCC(F32, (F32)-666.666);
  1096. TEST_LLCC(bool, true);
  1097. TEST_LLCC(BOOL, FALSE);
  1098. if((std::string)mySetting_string != "Default String Value") llerrs << "Fail string" << llendl;
  1099. TEST_LLCC(LLVector3, LLVector3(1.0f, 2.0f, 3.0f));
  1100. TEST_LLCC(LLVector3d, LLVector3d(6.0f, 5.0f, 4.0f));
  1101. TEST_LLCC(LLRect, LLRect(0, 0, 100, 500));
  1102. TEST_LLCC(LLColor4, LLColor4(0.0f, 0.5f, 1.0f));
  1103. TEST_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f));
  1104. TEST_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
  1105. //There's no LLSD comparsion for LLCC yet. TEST_LLCC(LLSD, test_llsd);
  1106. if((std::string)test_BrowserHomePage != "http://www.secondlife.com") llerrs << "Fail BrowserHomePage" << llendl;
  1107. }
  1108. #endif // TEST_CACHED_CONTROL