00001
00032 #include "linden_common.h"
00033
00034 #include <iostream>
00035 #include <fstream>
00036 #include <algorithm>
00037
00038 #include "llcontrol.h"
00039
00040 #include "llstl.h"
00041
00042 #include "linked_lists.h"
00043 #include "llstring.h"
00044 #include "v3math.h"
00045 #include "v3dmath.h"
00046 #include "v4coloru.h"
00047 #include "v4color.h"
00048 #include "v3color.h"
00049 #include "llrect.h"
00050 #include "llxmltree.h"
00051 #include "llsdserialize.h"
00052
00053 #if LL_RELEASE_FOR_DOWNLOAD
00054 #define CONTROL_ERRS llwarns
00055 #else
00056 #define CONTROL_ERRS llerrs
00057 #endif
00058
00059
00060 U32 LLControlBase::sMaxControlNameLength = 0;
00061
00062
00063 std::list<S32> LLControlBase::mFreeIDs;
00064 std::list<S32> LLControlBase::mUsedIDs;
00065
00066 S32 LLControlBase::mTopID;
00067
00068 std::set<LLControlBase*> LLControlBase::mChangedControls;
00069
00070 const S32 CURRENT_VERSION = 101;
00071
00072 BOOL control_insert_before( LLControlBase* first, LLControlBase* second );
00073
00074 BOOL LLControl::llsd_compare(const LLSD& a, const LLSD & b)
00075 {
00076 switch (mType)
00077 {
00078 case TYPE_U32:
00079 case TYPE_S32:
00080 return a.asInteger() == b.asInteger();
00081 case TYPE_BOOLEAN:
00082 return a.asBoolean() == b.asBoolean();
00083 case TYPE_F32:
00084 return a.asReal() == b.asReal();
00085 case TYPE_VEC3:
00086 case TYPE_VEC3D:
00087 return LLVector3d(a) == LLVector3d(b);
00088 case TYPE_RECT:
00089 return LLRect(a) == LLRect(b);
00090 case TYPE_COL4:
00091 return LLColor4(a) == LLColor4(b);
00092 case TYPE_COL3:
00093 return LLColor3(a) == LLColor3(b);
00094 case TYPE_COL4U:
00095 return LLColor4U(a) == LLColor4U(b);
00096 case TYPE_STRING:
00097 return a.asString() == b.asString();
00098 default:
00099
00100 break;
00101 }
00102
00103 return FALSE;
00104 }
00105
00106 LLControlBase::~LLControlBase()
00107 {
00108 }
00109
00110
00111 void LLControlBase::resetToDefault()
00112 {
00113 }
00114
00115 LLControlGroup::LLControlGroup(): mNameTable()
00116 {
00117
00118 }
00119
00120 LLControlGroup::~LLControlGroup()
00121 {
00122 }
00123
00124 LLSD LLControlBase::registerListener(LLSimpleListenerObservable *listener, LLSD userdata)
00125 {
00126
00127 addListener(listener, "", userdata);
00128 listener->addListener(this, "", userdata);
00129 return getValue();
00130 }
00131
00132 void LLControlGroup::cleanup()
00133 {
00134 mNameTable.clear();
00135 }
00136
00137 LLControlBase* LLControlGroup::getControl(const LLString& name)
00138 {
00139 ctrl_name_table_t::iterator iter = mNameTable.find(name);
00140 return iter == mNameTable.end() ? NULL : (LLControlBase*)iter->second;
00141 }
00142
00143 BOOL LLControlGroup::declareControl(const LLString& name, eControlType type, const LLSD initial_val, const LLString& comment, BOOL persist)
00144 {
00145 if(!mNameTable[name])
00146 {
00147
00148 LLControl* control = new LLControl(name, type, initial_val, comment, persist);
00149 mNameTable[name] = control;
00150 return TRUE;
00151 }
00152 else
00153 {
00154 llwarns << "LLControlGroup::declareControl: Control named " << name << " already exists." << llendl;
00155 mNameTable.erase(name);
00156 return FALSE;
00157 }
00158 }
00159
00160 BOOL LLControlGroup::declareU32(const LLString& name, const U32 initial_val, const LLString& comment, BOOL persist)
00161 {
00162 return declareControl(name, TYPE_U32, (LLSD::Integer) initial_val, comment, persist);
00163 }
00164
00165 BOOL LLControlGroup::declareS32(const LLString& name, const S32 initial_val, const LLString& comment, BOOL persist)
00166 {
00167 return declareControl(name, TYPE_S32, initial_val, comment, persist);
00168 }
00169
00170 BOOL LLControlGroup::declareF32(const LLString& name, const F32 initial_val, const LLString& comment, BOOL persist)
00171 {
00172 return declareControl(name, TYPE_F32, initial_val, comment, persist);
00173 }
00174
00175 BOOL LLControlGroup::declareBOOL(const LLString& name, const BOOL initial_val, const LLString& comment, BOOL persist)
00176 {
00177 return declareControl(name, TYPE_BOOLEAN, initial_val, comment, persist);
00178 }
00179
00180 BOOL LLControlGroup::declareString(const LLString& name, const LLString& initial_val, const LLString& comment, BOOL persist)
00181 {
00182 return declareControl(name, TYPE_STRING, initial_val, comment, persist);
00183 }
00184
00185 BOOL LLControlGroup::declareVec3(const LLString& name, const LLVector3 &initial_val, const LLString& comment, BOOL persist)
00186 {
00187 return declareControl(name, TYPE_VEC3, initial_val.getValue(), comment, persist);
00188 }
00189
00190 BOOL LLControlGroup::declareVec3d(const LLString& name, const LLVector3d &initial_val, const LLString& comment, BOOL persist)
00191 {
00192 return declareControl(name, TYPE_VEC3D, initial_val.getValue(), comment, persist);
00193 }
00194
00195 BOOL LLControlGroup::declareRect(const LLString& name, const LLRect &initial_val, const LLString& comment, BOOL persist)
00196 {
00197 return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist);
00198 }
00199
00200 BOOL LLControlGroup::declareColor4U(const LLString& name, const LLColor4U &initial_val, const LLString& comment, BOOL persist )
00201 {
00202 return declareControl(name, TYPE_COL4U, initial_val.getValue(), comment, persist);
00203 }
00204
00205 BOOL LLControlGroup::declareColor4(const LLString& name, const LLColor4 &initial_val, const LLString& comment, BOOL persist )
00206 {
00207 return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist);
00208 }
00209
00210 BOOL LLControlGroup::declareColor3(const LLString& name, const LLColor3 &initial_val, const LLString& comment, BOOL persist )
00211 {
00212 return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist);
00213 }
00214
00215 LLSD LLControlGroup::registerListener(const LLString& name, LLSimpleListenerObservable *listener)
00216 {
00217 LLControlBase *control = getControl(name);
00218 if (control)
00219 {
00220 return control->registerListener(listener);
00221 }
00222 return LLSD();
00223 }
00224
00225 BOOL LLControlGroup::getBOOL(const LLString& name)
00226 {
00227 LLControlBase* control = getControl(name);
00228
00229 if (control && control->isType(TYPE_BOOLEAN))
00230 return control->get().asBoolean();
00231 else
00232 {
00233 CONTROL_ERRS << "Invalid BOOL control " << name << llendl;
00234 return FALSE;
00235 }
00236 }
00237
00238 S32 LLControlGroup::getS32(const LLString& name)
00239 {
00240 LLControlBase* control = getControl(name);
00241
00242 if (control && control->isType(TYPE_S32))
00243 return control->get().asInteger();
00244 else
00245 {
00246 CONTROL_ERRS << "Invalid S32 control " << name << llendl;
00247 return 0;
00248 }
00249 }
00250
00251 U32 LLControlGroup::getU32(const LLString& name)
00252 {
00253 LLControlBase* control = getControl(name);
00254
00255 if (control && control->isType(TYPE_U32))
00256 return control->get().asInteger();
00257 else
00258 {
00259 CONTROL_ERRS << "Invalid U32 control " << name << llendl;
00260 return 0;
00261 }
00262 }
00263
00264 F32 LLControlGroup::getF32(const LLString& name)
00265 {
00266 LLControlBase* control = getControl(name);
00267
00268 if (control && control->isType(TYPE_F32))
00269 return (F32) control->get().asReal();
00270 else
00271 {
00272 CONTROL_ERRS << "Invalid F32 control " << name << llendl;
00273 return 0.0f;
00274 }
00275 }
00276
00277 LLString LLControlGroup::findString(const LLString& name)
00278 {
00279 LLControlBase* control = getControl(name);
00280
00281 if (control && control->isType(TYPE_STRING))
00282 return control->get().asString();
00283 return LLString::null;
00284 }
00285
00286 LLString LLControlGroup::getString(const LLString& name)
00287 {
00288 LLControlBase* control = getControl(name);
00289
00290 if (control && control->isType(TYPE_STRING))
00291 return control->get().asString();
00292 else
00293 {
00294 CONTROL_ERRS << "Invalid string control " << name << llendl;
00295 return LLString::null;
00296 }
00297 }
00298
00299 LLWString LLControlGroup::getWString(const LLString& name)
00300 {
00301 return utf8str_to_wstring(getString(name));
00302 }
00303
00304 LLString LLControlGroup::getText(const LLString& name)
00305 {
00306 LLString utf8_string = getString(name);
00307 LLString::replaceChar(utf8_string, '^', '\n');
00308 LLString::replaceChar(utf8_string, '%', ' ');
00309 return (utf8_string);
00310 }
00311
00312 LLVector3 LLControlGroup::getVector3(const LLString& name)
00313 {
00314 LLControlBase* control = getControl(name);
00315
00316 if (control && control->isType(TYPE_VEC3))
00317 return control->get();
00318 else
00319 {
00320 CONTROL_ERRS << "Invalid LLVector3 control " << name << llendl;
00321 return LLVector3::zero;
00322 }
00323 }
00324
00325 LLVector3d LLControlGroup::getVector3d(const LLString& name)
00326 {
00327 LLControlBase* control = getControl(name);
00328
00329 if (control && control->isType(TYPE_VEC3D))
00330 return control->get();
00331 else
00332 {
00333 CONTROL_ERRS << "Invalid LLVector3d control " << name << llendl;
00334 return LLVector3d::zero;
00335 }
00336 }
00337
00338 LLRect LLControlGroup::getRect(const LLString& name)
00339 {
00340 LLControlBase* control = getControl(name);
00341
00342 if (control && control->isType(TYPE_RECT))
00343 return control->get();
00344 else
00345 {
00346 CONTROL_ERRS << "Invalid rect control " << name << llendl;
00347 return LLRect::null;
00348 }
00349 }
00350
00351
00352 LLColor4 LLControlGroup::getColor(const LLString& name)
00353 {
00354 ctrl_name_table_t::const_iterator i = mNameTable.find(name);
00355
00356 if (i != mNameTable.end())
00357 {
00358 LLControlBase* control = i->second;
00359
00360 switch(control->mType)
00361 {
00362 case TYPE_COL4:
00363 {
00364 return LLColor4(control->get());
00365 }
00366 case TYPE_COL4U:
00367 {
00368 return LLColor4(LLColor4U(control->get()));
00369 }
00370 default:
00371 {
00372 CONTROL_ERRS << "Control " << name << " not a color" << llendl;
00373 return LLColor4::white;
00374 }
00375 }
00376 }
00377 else
00378 {
00379 CONTROL_ERRS << "Invalid getColor control " << name << llendl;
00380 return LLColor4::white;
00381 }
00382 }
00383
00384 LLColor4U LLControlGroup::getColor4U(const LLString& name)
00385 {
00386 LLControlBase* control = getControl(name);
00387
00388 if (control && control->isType(TYPE_COL4U))
00389 return control->get();
00390 else
00391 {
00392 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
00393 return LLColor4U::white;
00394 }
00395 }
00396
00397 LLColor4 LLControlGroup::getColor4(const LLString& name)
00398 {
00399 LLControlBase* control = getControl(name);
00400
00401 if (control && control->isType(TYPE_COL4))
00402 return control->get();
00403 else
00404 {
00405 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
00406 return LLColor4::white;
00407 }
00408 }
00409
00410 LLColor3 LLControlGroup::getColor3(const LLString& name)
00411 {
00412 LLControlBase* control = getControl(name);
00413
00414 if (control && control->isType(TYPE_COL3))
00415 return control->get();
00416 else
00417 {
00418 CONTROL_ERRS << "Invalid LLColor3 control " << name << llendl;
00419 return LLColor3::white;
00420 }
00421 }
00422
00423 BOOL LLControlGroup::controlExists(const LLString& name)
00424 {
00425 ctrl_name_table_t::iterator iter = mNameTable.find(name);
00426 return iter != mNameTable.end();
00427 }
00428
00429
00430
00431
00432
00433 void LLControlGroup::setBOOL(const LLString& name, BOOL val)
00434 {
00435 LLControlBase* control = getControl(name);
00436
00437 if (control && control->isType(TYPE_BOOLEAN))
00438 {
00439 control->set(val);
00440 }
00441 else
00442 {
00443 CONTROL_ERRS << "Invalid control " << name << llendl;
00444 }
00445 }
00446
00447
00448 void LLControlGroup::setS32(const LLString& name, S32 val)
00449 {
00450 LLControlBase* control = getControl(name);
00451
00452 if (control && control->isType(TYPE_S32))
00453 {
00454 control->set(val);
00455 }
00456 else
00457 {
00458 CONTROL_ERRS << "Invalid control " << name << llendl;
00459 }
00460 }
00461
00462
00463 void LLControlGroup::setF32(const LLString& name, F32 val)
00464 {
00465 LLControlBase* control = getControl(name);
00466
00467 if (control && control->isType(TYPE_F32))
00468 {
00469 control->set(val);
00470 }
00471 else
00472 {
00473 CONTROL_ERRS << "Invalid control " << name << llendl;
00474 }
00475 }
00476
00477
00478 void LLControlGroup::setU32(const LLString& name, U32 val)
00479 {
00480 LLControlBase* control = getControl(name);
00481
00482 if (control && control->isType(TYPE_U32))
00483 {
00484 control->set((LLSD::Integer) val);
00485 }
00486 else
00487 {
00488 CONTROL_ERRS << "Invalid control " << name << llendl;
00489 }
00490 }
00491
00492
00493 void LLControlGroup::setString(const LLString& name, const LLString &val)
00494 {
00495 LLControlBase* control = getControl(name);
00496
00497 if (control && control->isType(TYPE_STRING))
00498 {
00499 control->set(val);
00500 }
00501 else
00502 {
00503 CONTROL_ERRS << "Invalid control " << name << llendl;
00504 }
00505 }
00506
00507
00508 void LLControlGroup::setVector3(const LLString& name, const LLVector3 &val)
00509 {
00510 LLControlBase* control = getControl(name);
00511
00512 if (control && control->isType(TYPE_VEC3))
00513 {
00514 control->set(val.getValue());
00515 }
00516 else
00517 {
00518 CONTROL_ERRS << "Invalid control " << name << llendl;
00519 }
00520 }
00521
00522 void LLControlGroup::setVector3d(const LLString& name, const LLVector3d &val)
00523 {
00524 LLControlBase* control = getControl(name);
00525
00526 if (control && control->isType(TYPE_VEC3D))
00527 {
00528 control->set(val.getValue());
00529 }
00530 else
00531 {
00532 CONTROL_ERRS << "Invalid control " << name << llendl;
00533 }
00534 }
00535
00536 void LLControlGroup::setRect(const LLString& name, const LLRect &val)
00537 {
00538 LLControlBase* control = getControl(name);
00539
00540 if (control && control->isType(TYPE_RECT))
00541 {
00542 control->set(val.getValue());
00543 }
00544 else
00545 {
00546 CONTROL_ERRS << "Invalid rect control " << name << llendl;
00547 }
00548 }
00549
00550 void LLControlGroup::setColor4U(const LLString& name, const LLColor4U &val)
00551 {
00552 LLControlBase* control = getControl(name);
00553
00554 if (control && control->isType(TYPE_COL4U))
00555 {
00556 control->set(val.getValue());
00557 }
00558 else
00559 {
00560 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
00561 }
00562 }
00563
00564 void LLControlGroup::setColor4(const LLString& name, const LLColor4 &val)
00565 {
00566 LLControlBase* control = getControl(name);
00567
00568 if (control && control->isType(TYPE_COL4))
00569 {
00570 control->set(val.getValue());
00571 }
00572 else
00573 {
00574 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
00575 }
00576 }
00577
00578 void LLControlGroup::setValue(const LLString& name, const LLSD& val)
00579 {
00580 if (name.empty())
00581 {
00582 return;
00583 }
00584
00585 LLControlBase* control = getControl(name);
00586
00587 if (control)
00588 {
00589 control->set(val);
00590 }
00591 else
00592 {
00593 CONTROL_ERRS << "Invalid control " << name << llendl;
00594 }
00595 }
00596
00597
00598
00599
00600
00601 U32 LLControlGroup::loadFromFileLegacy(const LLString& filename, BOOL require_declaration, eControlType declare_as)
00602 {
00603 U32 item = 0;
00604 U32 validitems = 0;
00605 llifstream file;
00606 S32 version;
00607
00608 file.open(filename.c_str());
00609
00610 if (!file)
00611 {
00612 llinfos << "LLControlGroup::loadFromFile unable to open." << llendl;
00613 return 0;
00614 }
00615
00616
00617 LLString name;
00618 file >> name;
00619 file >> version;
00620 if (name != "version" || version != CURRENT_VERSION)
00621 {
00622 llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl;
00623 return 0;
00624 }
00625
00626 while (!file.eof())
00627 {
00628 file >> name;
00629
00630 if (name.empty())
00631 {
00632 continue;
00633 }
00634
00635 if (name.substr(0,2) == "//")
00636 {
00637
00638 char buffer[MAX_STRING];
00639 file.getline(buffer, MAX_STRING);
00640 continue;
00641 }
00642
00643 BOOL declared = mNameTable.find(name) != mNameTable.end();
00644
00645 if (require_declaration && !declared)
00646 {
00647
00648
00649 if (!name.empty())
00650 {
00651
00652 char buffer[MAX_STRING];
00653 file.getline(buffer, MAX_STRING);
00654 llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl;
00655 }
00656 continue;
00657 }
00658
00659
00660 item++;
00661
00662
00663 if (!declared)
00664 {
00665 switch(declare_as)
00666 {
00667 case TYPE_COL4:
00668 declareColor4(name, LLColor4::white, LLString::null, NO_PERSIST);
00669 break;
00670 case TYPE_COL4U:
00671 declareColor4U(name, LLColor4U::white, LLString::null, NO_PERSIST);
00672 break;
00673 case TYPE_STRING:
00674 default:
00675 declareString(name, LLString::null, LLString::null, NO_PERSIST);
00676 break;
00677 }
00678 }
00679
00680
00681 LLControlBase *control = getControl(name);
00682
00683 llassert(control);
00684
00685 switch(control->mType)
00686 {
00687 case TYPE_F32:
00688 {
00689 F32 initial;
00690
00691 file >> initial;
00692
00693 control->set(initial);
00694 validitems++;
00695 }
00696 break;
00697 case TYPE_S32:
00698 {
00699 S32 initial;
00700
00701 file >> initial;
00702
00703 control->set(initial);
00704 validitems++;
00705 }
00706 break;
00707 case TYPE_U32:
00708 {
00709 U32 initial;
00710
00711 file >> initial;
00712 control->set((LLSD::Integer) initial);
00713 validitems++;
00714 }
00715 break;
00716 case TYPE_BOOLEAN:
00717 {
00718 char boolstring[256];
00719 BOOL valid = FALSE;
00720 BOOL initial = FALSE;
00721
00722 file >> boolstring;
00723 if (!strcmp("TRUE", boolstring))
00724 {
00725 initial = TRUE;
00726 valid = TRUE;
00727 }
00728 else if (!strcmp("FALSE", boolstring))
00729 {
00730 initial = FALSE;
00731 valid = TRUE;
00732 }
00733
00734 if (valid)
00735 {
00736 control->set(initial);
00737 }
00738 else
00739 {
00740 llinfos << filename << "Item " << item << ": Invalid BOOL control " << name << ", " << boolstring << llendl;
00741 }
00742
00743 validitems++;
00744 }
00745 break;
00746 case TYPE_STRING:
00747 {
00748 LLString string;
00749
00750 file >> string;
00751
00752 control->set(string);
00753 validitems++;
00754 }
00755 break;
00756 case TYPE_VEC3:
00757 {
00758 F32 x, y, z;
00759
00760 file >> x >> y >> z;
00761
00762 LLVector3 vector(x, y, z);
00763
00764 control->set(vector.getValue());
00765 validitems++;
00766 }
00767 break;
00768 case TYPE_VEC3D:
00769 {
00770 F64 x, y, z;
00771
00772 file >> x >> y >> z;
00773
00774 LLVector3d vector(x, y, z);
00775
00776 control->set(vector.getValue());
00777 validitems++;
00778 }
00779 break;
00780 case TYPE_RECT:
00781 {
00782 S32 left, bottom, width, height;
00783
00784 file >> left >> bottom >> width >> height;
00785
00786 LLRect rect;
00787 rect.setOriginAndSize(left, bottom, width, height);
00788
00789 control->set(rect.getValue());
00790 validitems++;
00791 }
00792 break;
00793 case TYPE_COL4U:
00794 {
00795 S32 red, green, blue, alpha;
00796 LLColor4U color;
00797 file >> red >> green >> blue >> alpha;
00798 color.setVec(red, green, blue, alpha);
00799 control->set(color.getValue());
00800 validitems++;
00801 }
00802 break;
00803 case TYPE_COL4:
00804 {
00805 LLColor4 color;
00806 file >> color.mV[VRED] >> color.mV[VGREEN]
00807 >> color.mV[VBLUE] >> color.mV[VALPHA];
00808 control->set(color.getValue());
00809 validitems++;
00810 }
00811 break;
00812 case TYPE_COL3:
00813 {
00814 LLColor3 color;
00815 file >> color.mV[VRED] >> color.mV[VGREEN]
00816 >> color.mV[VBLUE];
00817 control->set(color.getValue());
00818 validitems++;
00819 }
00820 break;
00821 }
00822 }
00823
00824 file.close();
00825
00826 return validitems;
00827 }
00828
00829
00830 U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declaration, eControlType declare_as)
00831 {
00832 LLString name;
00833
00834 LLXmlTree xml_controls;
00835
00836 if (!xml_controls.parseFile(filename))
00837 {
00838 llwarns << "Unable to open control file " << filename << llendl;
00839 return 0;
00840 }
00841
00842 LLXmlTreeNode* rootp = xml_controls.getRoot();
00843 if (!rootp || !rootp->hasAttribute("version"))
00844 {
00845 llwarns << "No valid settings header found in control file " << filename << llendl;
00846 return 0;
00847 }
00848
00849 U32 item = 0;
00850 U32 validitems = 0;
00851 S32 version;
00852
00853 rootp->getAttributeS32("version", version);
00854
00855
00856 if (version != CURRENT_VERSION)
00857 {
00858 llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl;
00859 return 0;
00860 }
00861
00862 LLXmlTreeNode* child_nodep = rootp->getFirstChild();
00863 while(child_nodep)
00864 {
00865 name = child_nodep->getName();
00866
00867 BOOL declared = controlExists(name);
00868
00869 if (require_declaration && !declared)
00870 {
00871
00872
00873 if (!name.empty())
00874 {
00875
00876 llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl;
00877 }
00878 child_nodep = rootp->getNextChild();
00879 continue;
00880 }
00881
00882
00883 item++;
00884
00885
00886 if (!declared)
00887 {
00888 switch(declare_as)
00889 {
00890 case TYPE_COL4:
00891 declareColor4(name, LLColor4::white, "", NO_PERSIST);
00892 break;
00893 case TYPE_COL4U:
00894 declareColor4U(name, LLColor4U::white, "", NO_PERSIST);
00895 break;
00896 case TYPE_STRING:
00897 default:
00898 declareString(name, LLString::null, "", NO_PERSIST);
00899 break;
00900 }
00901 }
00902
00903
00904 LLControlBase *control = getControl(name);
00905
00906 llassert(control);
00907
00908 switch(control->mType)
00909 {
00910 case TYPE_F32:
00911 {
00912 F32 initial = 0.f;
00913
00914 child_nodep->getAttributeF32("value", initial);
00915
00916 control->set(initial);
00917 validitems++;
00918 }
00919 break;
00920 case TYPE_S32:
00921 {
00922 S32 initial = 0;
00923
00924 child_nodep->getAttributeS32("value", initial);
00925
00926 control->set(initial);
00927 validitems++;
00928 }
00929 break;
00930 case TYPE_U32:
00931 {
00932 U32 initial = 0;
00933 child_nodep->getAttributeU32("value", initial);
00934 control->set((LLSD::Integer) initial);
00935 validitems++;
00936 }
00937 break;
00938 case TYPE_BOOLEAN:
00939 {
00940 BOOL initial = FALSE;
00941
00942 child_nodep->getAttributeBOOL("value", initial);
00943 control->set(initial);
00944
00945 validitems++;
00946 }
00947 break;
00948 case TYPE_STRING:
00949 {
00950 LLString string;
00951 child_nodep->getAttributeString("value", string);
00952 if (string == LLString::null)
00953 {
00954 string = "";
00955 }
00956 control->set(string);
00957 validitems++;
00958 }
00959 break;
00960 case TYPE_VEC3:
00961 {
00962 LLVector3 vector;
00963
00964 child_nodep->getAttributeVector3("value", vector);
00965 control->set(vector.getValue());
00966 validitems++;
00967 }
00968 break;
00969 case TYPE_VEC3D:
00970 {
00971 LLVector3d vector;
00972
00973 child_nodep->getAttributeVector3d("value", vector);
00974
00975 control->set(vector.getValue());
00976 validitems++;
00977 }
00978 break;
00979 case TYPE_RECT:
00980 {
00981
00982 LLString rect_string;
00983
00984 child_nodep->getAttributeString("value", rect_string);
00985 std::istringstream istream(rect_string);
00986 S32 left, bottom, width, height;
00987
00988 istream >> left >> bottom >> width >> height;
00989
00990 LLRect rect;
00991 rect.setOriginAndSize(left, bottom, width, height);
00992
00993 control->set(rect.getValue());
00994 validitems++;
00995 }
00996 break;
00997 case TYPE_COL4U:
00998 {
00999 LLColor4U color;
01000
01001 child_nodep->getAttributeColor4U("value", color);
01002 control->set(color.getValue());
01003 validitems++;
01004 }
01005 break;
01006 case TYPE_COL4:
01007 {
01008 LLColor4 color;
01009
01010 child_nodep->getAttributeColor4("value", color);
01011 control->set(color.getValue());
01012 validitems++;
01013 }
01014 break;
01015 case TYPE_COL3:
01016 {
01017 LLVector3 color;
01018
01019 child_nodep->getAttributeVector3("value", color);
01020 control->set(LLColor3(color.mV).getValue());
01021 validitems++;
01022 }
01023 break;
01024 }
01025
01026 child_nodep = rootp->getNextChild();
01027 }
01028
01029 return validitems;
01030 }
01031
01032
01033 U32 LLControlGroup::saveToFile(const LLString& filename, BOOL nondefault_only)
01034 {
01035 const char ENDL = '\n';
01036
01037 llinfos << "Saving settings to file: " << filename << llendl;
01038
01039
01040
01041 LLLinkedList< LLControlBase > controls;
01042 controls.setInsertBefore( &control_insert_before );
01043 LLString name;
01044 for (ctrl_name_table_t::iterator iter = mNameTable.begin();
01045 iter != mNameTable.end(); iter++)
01046 {
01047 name = iter->first;
01048 if (name.empty())
01049 {
01050 CONTROL_ERRS << "Control with no name found!!!" << llendl;
01051 break;
01052 }
01053
01054 LLControlBase* control = (LLControlBase *)iter->second;
01055 if (!control)
01056 {
01057 llwarns << "Tried to save invalid control: " << name << llendl;
01058 }
01059
01060 if( control && control->mPersist )
01061 {
01062 if (!(nondefault_only && (control->mIsDefault)))
01063 {
01064 controls.addDataSorted( control );
01065 }
01066 else
01067 {
01068
01069
01070 }
01071 }
01072 }
01073
01074 llofstream file;
01075 file.open(filename.c_str());
01076
01077 if (!file.is_open())
01078 {
01079
01080 llwarns << "LLControlGroup::saveToFile unable to open file for writing" << llendl;
01081 return 0;
01082 }
01083
01084
01085 file << "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n";
01086 file << "<settings version = \"" << CURRENT_VERSION << "\">\n";
01087 for( LLControlBase* control = controls.getFirstData();
01088 control != NULL;
01089 control = controls.getNextData() )
01090 {
01091 file << "\t<!--" << control->comment() << "-->" << ENDL;
01092 name = control->name();
01093 switch (control->type())
01094 {
01095 case TYPE_U32:
01096 {
01097 file << "\t<" << name << " value=\"" << (U32) control->get().asInteger() << "\"/>\n";
01098 break;
01099 }
01100 case TYPE_S32:
01101 {
01102 file << "\t<" << name << " value=\"" << (S32) control->get().asInteger() << "\"/>\n";
01103 break;
01104 }
01105 case TYPE_F32:
01106 {
01107 file << "\t<" << name << " value=\"" << (F32) control->get().asReal() << "\"/>\n";
01108 break;
01109 }
01110 case TYPE_VEC3:
01111 {
01112 LLVector3 vector(control->get());
01113 file << "\t<" << name << " value=\"" << vector.mV[VX] << " " << vector.mV[VY] << " " << vector.mV[VZ] << "\"/>\n";
01114 break;
01115 }
01116 case TYPE_VEC3D:
01117 {
01118 LLVector3d vector(control->get());
01119 file << "\t<" << name << " value=\"" << vector.mdV[VX] << " " << vector.mdV[VY] << " " << vector.mdV[VZ] << "\"/>\n";
01120 break;
01121 }
01122 case TYPE_RECT:
01123 {
01124 LLRect rect(control->get());
01125 file << "\t<" << name << " value=\"" << rect.mLeft << " " << rect.mBottom << " " << rect.getWidth() << " " << rect.getHeight() << "\"/>\n";
01126 break;
01127 }
01128 case TYPE_COL4:
01129 {
01130 LLColor4 color(control->get());
01131 file << "\t<" << name << " value=\"" << color.mV[VRED] << ", " << color.mV[VGREEN] << ", " << color.mV[VBLUE] << ", " << color.mV[VALPHA] << "\"/>\n";
01132 break;
01133 }
01134 case TYPE_COL3:
01135 {
01136 LLColor3 color(control->get());
01137 file << "\t<" << name << " value=\"" << color.mV[VRED] << ", " << color.mV[VGREEN] << ", " << color.mV[VBLUE] << "\"/>\n";
01138 break;
01139 }
01140 case TYPE_BOOLEAN:
01141 {
01142 file << "\t<" << name << " value=\"" << (control->get().asBoolean() ? "TRUE" : "FALSE") << "\"/>\n";
01143 break;
01144 }
01145 case TYPE_STRING:
01146 {
01147 file << "\t<" << name << " value=\"" << LLSDXMLFormatter::escapeString(control->get().asString()) << "\"/>\n";
01148 break;
01149 }
01150 default:
01151 {
01152 CONTROL_ERRS << "LLControlGroup::saveToFile - unknown control type!" << llendl;
01153 break;
01154 }
01155 }
01156
01157
01158
01159 }
01160
01161 file << "</settings>\n";
01162 file.close();
01163
01164 return controls.getLength();
01165 }
01166
01167 void LLControlGroup::applyOverrides(const std::map<std::string, std::string>& overrides)
01168 {
01169 for (std::map<std::string, std::string>::const_iterator iter = overrides.begin();
01170 iter != overrides.end(); ++iter)
01171 {
01172 const std::string& command = iter->first;
01173 const std::string& value = iter->second;
01174 LLControlBase* control = (LLControlBase *)mNameTable[command];
01175 if (control)
01176 {
01177 switch(control->mType)
01178 {
01179 case TYPE_U32:
01180 control->set((LLSD::Integer)atof(value.c_str()));
01181 break;
01182 case TYPE_S32:
01183 control->set((S32)atof(value.c_str()));
01184 break;
01185 case TYPE_F32:
01186 control->set((F32)atof(value.c_str()));
01187 break;
01188 case TYPE_BOOLEAN:
01189 if (!LLString::compareInsensitive(value.c_str(), "TRUE"))
01190 {
01191 control->set(TRUE);
01192 }
01193 else if (!LLString::compareInsensitive(value.c_str(), "FALSE"))
01194 {
01195 control->set(FALSE);
01196 }
01197 else
01198 {
01199 control->set((BOOL)atof(value.c_str()));
01200 }
01201 break;
01202 case TYPE_STRING:
01203 control->set(value);
01204 break;
01205
01206
01207
01208
01209
01210 case TYPE_VEC3:
01211 case TYPE_VEC3D:
01212 case TYPE_COL4:
01213 case TYPE_COL3:
01214 default:
01215 break;
01216 }
01217 }
01218 else
01219 {
01220 llinfos << "There is no control variable " << command << llendl;
01221 }
01222 }
01223 }
01224
01225 void LLControlGroup::resetToDefaults()
01226 {
01227 ctrl_name_table_t::iterator control_iter;
01228 for (control_iter = mNameTable.begin();
01229 control_iter != mNameTable.end();
01230 ++control_iter)
01231 {
01232 LLControlBase* control = (*control_iter).second;
01233 control->resetToDefault();
01234 }
01235 }
01236
01237
01238
01239
01240
01241 void LLControlGroup::addWarning(const LLString& name)
01242 {
01243 LLString warnname = "Warn" + name;
01244 if(!mNameTable[warnname])
01245 {
01246 LLString comment = LLString("Enables ") + name + LLString(" warning dialog");
01247 declareBOOL(warnname, TRUE, comment);
01248 mWarnings.insert(warnname);
01249 }
01250 }
01251
01252 BOOL LLControlGroup::getWarning(const LLString& name)
01253 {
01254 LLString warnname = "Warn" + name;
01255 return getBOOL(warnname);
01256 }
01257
01258 void LLControlGroup::setWarning(const LLString& name, BOOL val)
01259 {
01260 LLString warnname = "Warn" + name;
01261 setBOOL(warnname, val);
01262 }
01263
01264 void LLControlGroup::resetWarnings()
01265 {
01266 for (std::set<LLString>::iterator iter = mWarnings.begin();
01267 iter != mWarnings.end(); ++iter)
01268 {
01269 setBOOL(*iter, TRUE);
01270 }
01271 }
01272
01273
01274
01275
01276
01277
01278 void LLControlBase::releaseListenerID(S32 id)
01279 {
01280 mFreeIDs.push_back(id);
01281 }
01282
01283 S32 LLControlBase::allocateListenerID()
01284 {
01285 if(mFreeIDs.size() == 0)
01286 {
01287 for(int t=0;t<32;t++)
01288 {
01289 mFreeIDs.push_back(mTopID++);
01290 }
01291 }
01292 S32 rtn = mFreeIDs.front();
01293 mFreeIDs.pop_front();
01294 mUsedIDs.push_back(rtn);
01295 return rtn;
01296 }
01297
01298 bool LLControlBase::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
01299 {
01300 if (event->desc() == "value_changed")
01301 {
01302 setValue(((LLValueChangedEvent*)(LLEvent*)event)->mValue);
01303 return TRUE;
01304 }
01305 return TRUE;
01306 }
01307
01308 void LLControlBase::firePropertyChanged()
01309 {
01310 LLValueChangedEvent *evt = new LLValueChangedEvent(this, getValue());
01311 fireEvent(evt, "");
01312 }
01313
01314
01315
01316
01317 S32 LLControl::addListener(LLControl::tListenerCallback* cbfn)
01318 {
01319 S32 id = allocateListenerID();
01320 mListeners.push_back(cbfn);
01321 mListenerIDs.push_back( id );
01322 return id;
01323 }
01324
01325 void LLControl::updateListeners() {
01326 LLControl::tPropertyChangedListIter iter = mChangeEvents.begin();
01327 while(iter!=mChangeEvents.end()){
01328 LLControl::tPropertyChangedEvent& evt = *iter;
01329 (*evt.mCBFN)(evt.mNewValue,evt.mID,*this);
01330 iter++;
01331 }
01332 mChangeEvents.clear();
01333 }
01334
01335
01336 void LLControlBase::updateAllListeners()
01337 {
01338 std::set< LLControlBase* >::iterator iter = mChangedControls.begin();
01339 while(iter != mChangedControls.end()){
01340 (*iter)->updateListeners();
01341 iter++;
01342 }
01343 mChangedControls.clear();
01344 }
01345
01346 LLControl::LLControl(
01347 const LLString& name,
01348 eControlType type,
01349 LLSD initial,
01350 const LLString& comment,
01351 BOOL persist) :
01352 LLControlBase(name, type, comment, persist),
01353 mCurrent(initial),
01354 mDefault(initial)
01355 {
01356 }
01357
01358
01359
01360 #ifdef TEST_HARNESS
01361 void main()
01362 {
01363 F32_CONTROL foo, getfoo;
01364
01365 S32_CONTROL bar, getbar;
01366
01367 BOOL_CONTROL baz;
01368
01369 U32 count = gGlobals.loadFromFile("controls.ini");
01370 llinfos << "Loaded " << count << " controls" << llendl;
01371
01372
01373 foo = new LLControl<F32>("gFoo", 5.f, 1.f, 20.f);
01374 gGlobals.addEntry("gFoo", foo);
01375
01376 bar = new LLControl<S32>("gBar", 10, 2, 22);
01377 gGlobals.addEntry("gBar", bar);
01378
01379 baz = new LLControl<BOOL>("gBaz", FALSE);
01380 gGlobals.addEntry("gBaz", baz);
01381
01382
01383 getfoo = (LLControl<F32>*) gGlobals.resolveName("gFoo");
01384 getfoo->dump();
01385
01386 getbar = (S32_CONTROL) gGlobals.resolveName("gBar");
01387 getbar->dump();
01388
01389
01390 getfoo->set(10.f);
01391 getfoo->dump();
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406 getfoo = (F32_CONTROL) gGlobals.resolveName("gFoo");
01407 getfoo->set(TRUE);
01408 getfoo->dump();
01409
01410
01411
01412
01413
01414
01415 delete foo;
01416 delete bar;
01417 delete baz;
01418 }
01419 #endif
01420
01421 BOOL control_insert_before( LLControlBase* first, LLControlBase* second )
01422 {
01423 return ( first->getName().compare(second->getName()) < 0 );
01424 }
01425