llcontrol.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:32k
源码类别:

游戏引擎

开发平台:

C++ Builder

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