aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llxml/llcontrol.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llxml/llcontrol.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llxml/llcontrol.cpp')
-rw-r--r--linden/indra/llxml/llcontrol.cpp1420
1 files changed, 1420 insertions, 0 deletions
diff --git a/linden/indra/llxml/llcontrol.cpp b/linden/indra/llxml/llcontrol.cpp
new file mode 100644
index 0000000..79fd522
--- /dev/null
+++ b/linden/indra/llxml/llcontrol.cpp
@@ -0,0 +1,1420 @@
1/**
2 * @file llcontrol.cpp
3 * @brief Holds global state for viewer.
4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "linden_common.h"
29
30#include <iostream>
31#include <fstream>
32#include <algorithm>
33
34#include "llcontrol.h"
35
36#include "llstl.h"
37
38#include "linked_lists.h"
39#include "llstring.h"
40#include "v3math.h"
41#include "v3dmath.h"
42#include "v4coloru.h"
43#include "v4color.h"
44#include "v3color.h"
45#include "llrect.h"
46#include "llxmltree.h"
47#include "llsdserialize.h"
48
49#if LL_RELEASE_FOR_DOWNLOAD
50#define CONTROL_ERRS llwarns
51#else
52#define CONTROL_ERRS llerrs
53#endif
54
55//this defines the current version of the settings file
56U32 LLControlBase::sMaxControlNameLength = 0;
57
58//These lists are used to store the ID's of registered event listeners.
59std::list<S32> LLControlBase::mFreeIDs;
60std::list<S32> LLControlBase::mUsedIDs;
61
62S32 LLControlBase::mTopID;
63
64std::set<LLControlBase*> LLControlBase::mChangedControls;
65
66const S32 CURRENT_VERSION = 101;
67
68BOOL control_insert_before( LLControlBase* first, LLControlBase* second );
69
70BOOL LLControl::llsd_compare(const LLSD& a, const LLSD & b)
71{
72 switch (mType)
73 {
74 case TYPE_U32:
75 case TYPE_S32:
76 return a.asInteger() == b.asInteger();
77 case TYPE_BOOLEAN:
78 return a.asBoolean() == b.asBoolean();
79 case TYPE_F32:
80 return a.asReal() == b.asReal();
81 case TYPE_VEC3:
82 case TYPE_VEC3D:
83 return LLVector3d(a) == LLVector3d(b);
84 case TYPE_RECT:
85 return LLRect(a) == LLRect(b);
86 case TYPE_COL4:
87 return LLColor4(a) == LLColor4(b);
88 case TYPE_COL3:
89 return LLColor3(a) == LLColor3(b);
90 case TYPE_COL4U:
91 return LLColor4U(a) == LLColor4U(b);
92 case TYPE_STRING:
93 return a.asString() == b.asString();
94 default:
95 // no-op
96 break;
97 }
98
99 return FALSE;
100}
101
102LLControlBase::~LLControlBase()
103{
104}
105
106// virtual
107void LLControlBase::resetToDefault()
108{
109}
110
111LLControlGroup::LLControlGroup(): mNameTable()
112{
113 //mFreeStringOffset = 0;
114}
115
116LLControlGroup::~LLControlGroup()
117{
118}
119
120LLSD LLControlBase::registerListener(LLSimpleListenerObservable *listener, LLSD userdata)
121{
122 // Symmetric listener relationship
123 addListener(listener, "", userdata);
124 listener->addListener(this, "", userdata);
125 return getValue();
126}
127
128void LLControlGroup::cleanup()
129{
130 mNameTable.clear();
131}
132
133LLControlBase* LLControlGroup::getControl(const LLString& name)
134{
135 return mNameTable[name];
136}
137
138BOOL LLControlGroup::declareControl(const LLString& name, eControlType type, const LLSD initial_val, const LLString& comment, BOOL persist)
139{
140 if(!mNameTable[name])
141 {
142 // if not, create the control and add it to the name table
143 LLControl* control = new LLControl(name, type, initial_val, comment, persist);
144 mNameTable[name] = control;
145 return TRUE;
146 } else
147 {
148 llwarns << "LLControlGroup::declareControl: Control named " << name << " already exists." << llendl;
149 return FALSE;
150 }
151}
152
153BOOL LLControlGroup::declareU32(const LLString& name, const U32 initial_val, const LLString& comment, BOOL persist)
154{
155 return declareControl(name, TYPE_U32, (LLSD::Integer) initial_val, comment, persist);
156}
157
158BOOL LLControlGroup::declareS32(const LLString& name, const S32 initial_val, const LLString& comment, BOOL persist)
159{
160 return declareControl(name, TYPE_S32, initial_val, comment, persist);
161}
162
163BOOL LLControlGroup::declareF32(const LLString& name, const F32 initial_val, const LLString& comment, BOOL persist)
164{
165 return declareControl(name, TYPE_F32, initial_val, comment, persist);
166}
167
168BOOL LLControlGroup::declareBOOL(const LLString& name, const BOOL initial_val, const LLString& comment, BOOL persist)
169{
170 return declareControl(name, TYPE_BOOLEAN, initial_val, comment, persist);
171}
172
173BOOL LLControlGroup::declareString(const LLString& name, const LLString& initial_val, const LLString& comment, BOOL persist)
174{
175 return declareControl(name, TYPE_STRING, initial_val, comment, persist);
176}
177
178BOOL LLControlGroup::declareVec3(const LLString& name, const LLVector3 &initial_val, const LLString& comment, BOOL persist)
179{
180 return declareControl(name, TYPE_VEC3, initial_val.getValue(), comment, persist);
181}
182
183BOOL LLControlGroup::declareVec3d(const LLString& name, const LLVector3d &initial_val, const LLString& comment, BOOL persist)
184{
185 return declareControl(name, TYPE_VEC3D, initial_val.getValue(), comment, persist);
186}
187
188BOOL LLControlGroup::declareRect(const LLString& name, const LLRect &initial_val, const LLString& comment, BOOL persist)
189{
190 return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist);
191}
192
193BOOL LLControlGroup::declareColor4U(const LLString& name, const LLColor4U &initial_val, const LLString& comment, BOOL persist )
194{
195 return declareControl(name, TYPE_COL4U, initial_val.getValue(), comment, persist);
196}
197
198BOOL LLControlGroup::declareColor4(const LLString& name, const LLColor4 &initial_val, const LLString& comment, BOOL persist )
199{
200 return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist);
201}
202
203BOOL LLControlGroup::declareColor3(const LLString& name, const LLColor3 &initial_val, const LLString& comment, BOOL persist )
204{
205 return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist);
206}
207
208LLSD LLControlGroup::registerListener(const LLString& name, LLSimpleListenerObservable *listener)
209{
210 LLControlBase *control = mNameTable[name];
211 if (control)
212 {
213 return control->registerListener(listener);
214 }
215 return LLSD();
216}
217
218BOOL LLControlGroup::getBOOL(const LLString& name)
219{
220 LLControlBase* control = mNameTable[name];
221
222 if (control && control->isType(TYPE_BOOLEAN))
223 return control->get().asBoolean();
224 else
225 {
226 CONTROL_ERRS << "Invalid BOOL control " << name << llendl;
227 return FALSE;
228 }
229}
230
231S32 LLControlGroup::getS32(const LLString& name)
232{
233 LLControlBase* control = mNameTable[name];
234
235 if (control && control->isType(TYPE_S32))
236 return control->get().asInteger();
237 else
238 {
239 CONTROL_ERRS << "Invalid S32 control " << name << llendl;
240 return 0;
241 }
242}
243
244U32 LLControlGroup::getU32(const LLString& name)
245{
246 LLControlBase* control = mNameTable[name];
247
248 if (control && control->isType(TYPE_U32))
249 return control->get().asInteger();
250 else
251 {
252 CONTROL_ERRS << "Invalid U32 control " << name << llendl;
253 return 0;
254 }
255}
256
257F32 LLControlGroup::getF32(const LLString& name)
258{
259 LLControlBase* control = mNameTable[name];
260
261 if (control && control->isType(TYPE_F32))
262 return (F32) control->get().asReal();
263 else
264 {
265 CONTROL_ERRS << "Invalid F32 control " << name << llendl;
266 return 0.0f;
267 }
268}
269
270LLString LLControlGroup::findString(const LLString& name)
271{
272 LLControlBase* control = mNameTable[name];
273
274 if (control && control->isType(TYPE_STRING))
275 return control->get().asString();
276 return LLString::null;
277}
278
279LLString LLControlGroup::getString(const LLString& name)
280{
281 LLControlBase* control = mNameTable[name];
282
283 if (control && control->isType(TYPE_STRING))
284 return control->get().asString();
285 else
286 {
287 CONTROL_ERRS << "Invalid string control " << name << llendl;
288 return LLString::null;
289 }
290}
291
292LLWString LLControlGroup::getWString(const LLString& name)
293{
294 return utf8str_to_wstring(getString(name));
295}
296
297LLString LLControlGroup::getText(const LLString& name)
298{
299 LLString utf8_string = getString(name);
300 LLString::replaceChar(utf8_string, '^', '\n');
301 LLString::replaceChar(utf8_string, '%', ' ');
302 return (utf8_string);
303}
304
305LLVector3 LLControlGroup::getVector3(const LLString& name)
306{
307 LLControlBase* control = mNameTable[name];
308
309 if (control && control->isType(TYPE_VEC3))
310 return control->get();
311 else
312 {
313 CONTROL_ERRS << "Invalid LLVector3 control " << name << llendl;
314 return LLVector3::zero;
315 }
316}
317
318LLVector3d LLControlGroup::getVector3d(const LLString& name)
319{
320 LLControlBase* control = mNameTable[name];
321
322 if (control && control->isType(TYPE_VEC3D))
323 return control->get();
324 else
325 {
326 CONTROL_ERRS << "Invalid LLVector3d control " << name << llendl;
327 return LLVector3d::zero;
328 }
329}
330
331LLRect LLControlGroup::getRect(const LLString& name)
332{
333 LLControlBase* control = mNameTable[name];
334
335 if (control && control->isType(TYPE_RECT))
336 return control->get();
337 else
338 {
339 CONTROL_ERRS << "Invalid rect control " << name << llendl;
340 return LLRect::null;
341 }
342}
343
344
345LLColor4 LLControlGroup::getColor(const LLString& name)
346{
347 ctrl_name_table_t::const_iterator i = mNameTable.find(name);
348
349 if (i != mNameTable.end())
350 {
351 LLControlBase* control = i->second;
352
353 switch(control->mType)
354 {
355 case TYPE_COL4:
356 {
357 return LLColor4(control->get());
358 }
359 case TYPE_COL4U:
360 {
361 return LLColor4(LLColor4U(control->get()));
362 }
363 default:
364 {
365 CONTROL_ERRS << "Control " << name << " not a color" << llendl;
366 return LLColor4::white;
367 }
368 }
369 }
370 else
371 {
372 CONTROL_ERRS << "Invalid getColor control " << name << llendl;
373 return LLColor4::white;
374 }
375}
376
377LLColor4U LLControlGroup::getColor4U(const LLString& name)
378{
379 LLControlBase* control = mNameTable[name];
380
381 if (control && control->isType(TYPE_COL4U))
382 return control->get();
383 else
384 {
385 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
386 return LLColor4U::white;
387 }
388}
389
390LLColor4 LLControlGroup::getColor4(const LLString& name)
391{
392 LLControlBase* control = mNameTable[name];
393
394 if (control && control->isType(TYPE_COL4))
395 return control->get();
396 else
397 {
398 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
399 return LLColor4::white;
400 }
401}
402
403LLColor3 LLControlGroup::getColor3(const LLString& name)
404{
405 LLControlBase* control = mNameTable[name];
406
407 if (control && control->isType(TYPE_COL3))
408 return control->get();
409 else
410 {
411 CONTROL_ERRS << "Invalid LLColor3 control " << name << llendl;
412 return LLColor3::white;
413 }
414}
415
416BOOL LLControlGroup::controlExists(const LLString& name)
417{
418 void *control = mNameTable[name];
419
420 return (control != 0);
421}
422
423//-------------------------------------------------------------------
424// Set functions
425//-------------------------------------------------------------------
426
427void LLControlGroup::setBOOL(const LLString& name, BOOL val)
428{
429 LLControlBase* control = mNameTable[name];
430
431 if (control && control->isType(TYPE_BOOLEAN))
432 {
433 control->set(val);
434 }
435 else
436 {
437 CONTROL_ERRS << "Invalid control " << name << llendl;
438 }
439}
440
441
442void LLControlGroup::setS32(const LLString& name, S32 val)
443{
444 LLControlBase* control = mNameTable[name];
445
446 if (control && control->isType(TYPE_S32))
447 {
448 control->set(val);
449 }
450 else
451 {
452 CONTROL_ERRS << "Invalid control " << name << llendl;
453 }
454}
455
456
457void LLControlGroup::setF32(const LLString& name, F32 val)
458{
459 LLControlBase* control = mNameTable[name];
460
461 if (control && control->isType(TYPE_F32))
462 {
463 control->set(val);
464 }
465 else
466 {
467 CONTROL_ERRS << "Invalid control " << name << llendl;
468 }
469}
470
471
472void LLControlGroup::setU32(const LLString& name, U32 val)
473{
474 LLControlBase* control = mNameTable[name];
475
476 if (control && control->isType(TYPE_U32))
477 {
478 control->set((LLSD::Integer) val);
479 }
480 else
481 {
482 CONTROL_ERRS << "Invalid control " << name << llendl;
483 }
484}
485
486
487void LLControlGroup::setString(const LLString& name, const LLString &val)
488{
489 LLControlBase* control = mNameTable[name];
490
491 if (control && control->isType(TYPE_STRING))
492 {
493 control->set(val);
494 }
495 else
496 {
497 CONTROL_ERRS << "Invalid control " << name << llendl;
498 }
499}
500
501
502void LLControlGroup::setVector3(const LLString& name, const LLVector3 &val)
503{
504 LLControlBase* control = mNameTable[name];
505
506 if (control && control->isType(TYPE_VEC3))
507 {
508 control->set(val.getValue());
509 }
510 else
511 {
512 CONTROL_ERRS << "Invalid control " << name << llendl;
513 }
514}
515
516void LLControlGroup::setVector3d(const LLString& name, const LLVector3d &val)
517{
518 LLControlBase* control = mNameTable[name];
519
520 if (control && control->isType(TYPE_VEC3D))
521 {
522 control->set(val.getValue());
523 }
524 else
525 {
526 CONTROL_ERRS << "Invalid control " << name << llendl;
527 }
528}
529
530void LLControlGroup::setRect(const LLString& name, const LLRect &val)
531{
532 LLControlBase* control = mNameTable[name];
533
534 if (control && control->isType(TYPE_RECT))
535 {
536 control->set(val.getValue());
537 }
538 else
539 {
540 CONTROL_ERRS << "Invalid rect control " << name << llendl;
541 }
542}
543
544void LLControlGroup::setColor4U(const LLString& name, const LLColor4U &val)
545{
546 LLControlBase* control = mNameTable[name];
547
548 if (control && control->isType(TYPE_COL4U))
549 {
550 control->set(val.getValue());
551 }
552 else
553 {
554 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
555 }
556}
557
558void LLControlGroup::setColor4(const LLString& name, const LLColor4 &val)
559{
560 LLControlBase* control = mNameTable[name];
561
562 if (control && control->isType(TYPE_COL4))
563 {
564 control->set(val.getValue());
565 }
566 else
567 {
568 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
569 }
570}
571
572void LLControlGroup::setValue(const LLString& name, const LLSD& val)
573{
574 if (name.empty())
575 {
576 return;
577 }
578
579 LLControlBase* control = mNameTable[name];
580
581 if (control)
582 {
583 control->set(val);
584 }
585 else
586 {
587 CONTROL_ERRS << "Invalid control " << name << llendl;
588 }
589}
590
591//---------------------------------------------------------------
592// Load and save
593//---------------------------------------------------------------
594
595U32 LLControlGroup::loadFromFileLegacy(const LLString& filename, BOOL require_declaration, eControlType declare_as)
596{
597 U32 item = 0;
598 U32 validitems = 0;
599 llifstream file;
600 S32 version;
601
602 file.open(filename.c_str());
603
604 if (!file)
605 {
606 llinfos << "LLControlGroup::loadFromFile unable to open." << llendl;
607 return 0;
608 }
609
610 // Check file version
611 LLString name;
612 file >> name;
613 file >> version;
614 if (name != "version" || version != CURRENT_VERSION)
615 {
616 llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl;
617 return 0;
618 }
619
620 while (!file.eof())
621 {
622 file >> name;
623
624 if (name.empty())
625 {
626 continue;
627 }
628
629 if (name.substr(0,2) == "//")
630 {
631 // This is a comment.
632 char buffer[MAX_STRING];
633 file.getline(buffer, MAX_STRING);
634 continue;
635 }
636
637 BOOL declared = mNameTable.find(name) != mNameTable.end();
638
639 if (require_declaration && !declared)
640 {
641 // Declaration required, but this name not declared.
642 // Complain about non-empty names.
643 if (!name.empty())
644 {
645 //read in to end of line
646 char buffer[MAX_STRING];
647 file.getline(buffer, MAX_STRING);
648 llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl;
649 }
650 continue;
651 }
652
653 // Got an item. Load it up.
654 item++;
655
656 // If not declared, assume it's a string
657 if (!declared)
658 {
659 switch(declare_as)
660 {
661 case TYPE_COL4:
662 declareColor4(name, LLColor4::white, LLString::null, NO_PERSIST);
663 break;
664 case TYPE_COL4U:
665 declareColor4U(name, LLColor4U::white, LLString::null, NO_PERSIST);
666 break;
667 case TYPE_STRING:
668 default:
669 declareString(name, LLString::null, LLString::null, NO_PERSIST);
670 break;
671 }
672 }
673
674 // Control name has been declared in code.
675 LLControlBase *control = getControl(name);
676
677 llassert(control);
678
679 switch(control->mType)
680 {
681 case TYPE_F32:
682 {
683 F32 initial;
684
685 file >> initial;
686
687 control->set(initial);
688 validitems++;
689 }
690 break;
691 case TYPE_S32:
692 {
693 S32 initial;
694
695 file >> initial;
696
697 control->set(initial);
698 validitems++;
699 }
700 break;
701 case TYPE_U32:
702 {
703 U32 initial;
704
705 file >> initial;
706 control->set((LLSD::Integer) initial);
707 validitems++;
708 }
709 break;
710 case TYPE_BOOLEAN:
711 {
712 char boolstring[256];
713 BOOL valid = FALSE;
714 BOOL initial = FALSE;
715
716 file >> boolstring;
717 if (!strcmp("TRUE", boolstring))
718 {
719 initial = TRUE;
720 valid = TRUE;
721 }
722 else if (!strcmp("FALSE", boolstring))
723 {
724 initial = FALSE;
725 valid = TRUE;
726 }
727
728 if (valid)
729 {
730 control->set(initial);
731 }
732 else
733 {
734 llinfos << filename << "Item " << item << ": Invalid BOOL control " << name << ", " << boolstring << llendl;
735 }
736
737 validitems++;
738 }
739 break;
740 case TYPE_STRING:
741 {
742 LLString string;
743
744 file >> string;
745
746 control->set(string);
747 validitems++;
748 }
749 break;
750 case TYPE_VEC3:
751 {
752 F32 x, y, z;
753
754 file >> x >> y >> z;
755
756 LLVector3 vector(x, y, z);
757
758 control->set(vector.getValue());
759 validitems++;
760 }
761 break;
762 case TYPE_VEC3D:
763 {
764 F64 x, y, z;
765
766 file >> x >> y >> z;
767
768 LLVector3d vector(x, y, z);
769
770 control->set(vector.getValue());
771 validitems++;
772 }
773 break;
774 case TYPE_RECT:
775 {
776 S32 left, bottom, width, height;
777
778 file >> left >> bottom >> width >> height;
779
780 LLRect rect;
781 rect.setOriginAndSize(left, bottom, width, height);
782
783 control->set(rect.getValue());
784 validitems++;
785 }
786 break;
787 case TYPE_COL4U:
788 {
789 S32 red, green, blue, alpha;
790 LLColor4U color;
791 file >> red >> green >> blue >> alpha;
792 color.setVec(red, green, blue, alpha);
793 control->set(color.getValue());
794 validitems++;
795 }
796 break;
797 case TYPE_COL4:
798 {
799 LLColor4 color;
800 file >> color.mV[VRED] >> color.mV[VGREEN]
801 >> color.mV[VBLUE] >> color.mV[VALPHA];
802 control->set(color.getValue());
803 validitems++;
804 }
805 break;
806 case TYPE_COL3:
807 {
808 LLColor3 color;
809 file >> color.mV[VRED] >> color.mV[VGREEN]
810 >> color.mV[VBLUE];
811 control->set(color.getValue());
812 validitems++;
813 }
814 break;
815 }
816 }
817
818 file.close();
819
820 return validitems;
821}
822
823// Returns number of controls loaded, so 0 if failure
824U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declaration, eControlType declare_as)
825{
826 LLString name;
827
828 LLXmlTree xml_controls;
829
830 if (!xml_controls.parseFile(filename))
831 {
832 llwarns << "Unable to open control file " << filename << llendl;
833 return 0;
834 }
835
836 LLXmlTreeNode* rootp = xml_controls.getRoot();
837 if (!rootp || !rootp->hasAttribute("version"))
838 {
839 llwarns << "No valid settings header found in control file " << filename << llendl;
840 return 0;
841 }
842
843 U32 item = 0;
844 U32 validitems = 0;
845 S32 version;
846
847 rootp->getAttributeS32("version", version);
848
849 // Check file version
850 if (version != CURRENT_VERSION)
851 {
852 llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl;
853 return 0;
854 }
855
856 LLXmlTreeNode* child_nodep = rootp->getFirstChild();
857 while(child_nodep)
858 {
859 name = child_nodep->getName();
860
861 BOOL declared = (mNameTable[name].notNull());
862
863 if (require_declaration && !declared)
864 {
865 // Declaration required, but this name not declared.
866 // Complain about non-empty names.
867 if (!name.empty())
868 {
869 //read in to end of line
870 llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl;
871 }
872 child_nodep = rootp->getNextChild();
873 continue;
874 }
875
876 // Got an item. Load it up.
877 item++;
878
879 // If not declared, assume it's a string
880 if (!declared)
881 {
882 switch(declare_as)
883 {
884 case TYPE_COL4:
885 declareColor4(name, LLColor4::white, "", NO_PERSIST);
886 break;
887 case TYPE_COL4U:
888 declareColor4U(name, LLColor4U::white, "", NO_PERSIST);
889 break;
890 case TYPE_STRING:
891 default:
892 declareString(name, LLString::null, "", NO_PERSIST);
893 break;
894 }
895 }
896
897 // Control name has been declared in code.
898 LLControlBase *control = getControl(name);
899
900 llassert(control);
901
902 switch(control->mType)
903 {
904 case TYPE_F32:
905 {
906 F32 initial = 0.f;
907
908 child_nodep->getAttributeF32("value", initial);
909
910 control->set(initial);
911 validitems++;
912 }
913 break;
914 case TYPE_S32:
915 {
916 S32 initial = 0;
917
918 child_nodep->getAttributeS32("value", initial);
919
920 control->set(initial);
921 validitems++;
922 }
923 break;
924 case TYPE_U32:
925 {
926 U32 initial = 0;
927 child_nodep->getAttributeU32("value", initial);
928 control->set((LLSD::Integer) initial);
929 validitems++;
930 }
931 break;
932 case TYPE_BOOLEAN:
933 {
934 BOOL initial = FALSE;
935
936 child_nodep->getAttributeBOOL("value", initial);
937 control->set(initial);
938
939 validitems++;
940 }
941 break;
942 case TYPE_STRING:
943 {
944 LLString string;
945 child_nodep->getAttributeString("value", string);
946 if (string == LLString::null)
947 {
948 string = "";
949 }
950 control->set(string);
951 validitems++;
952 }
953 break;
954 case TYPE_VEC3:
955 {
956 LLVector3 vector;
957
958 child_nodep->getAttributeVector3("value", vector);
959 control->set(vector.getValue());
960 validitems++;
961 }
962 break;
963 case TYPE_VEC3D:
964 {
965 LLVector3d vector;
966
967 child_nodep->getAttributeVector3d("value", vector);
968
969 control->set(vector.getValue());
970 validitems++;
971 }
972 break;
973 case TYPE_RECT:
974 {
975 //RN: hack to support reading rectangles from a string
976 LLString rect_string;
977
978 child_nodep->getAttributeString("value", rect_string);
979 std::istringstream istream(rect_string);
980 S32 left, bottom, width, height;
981
982 istream >> left >> bottom >> width >> height;
983
984 LLRect rect;
985 rect.setOriginAndSize(left, bottom, width, height);
986
987 control->set(rect.getValue());
988 validitems++;
989 }
990 break;
991 case TYPE_COL4U:
992 {
993 LLColor4U color;
994
995 child_nodep->getAttributeColor4U("value", color);
996 control->set(color.getValue());
997 validitems++;
998 }
999 break;
1000 case TYPE_COL4:
1001 {
1002 LLColor4 color;
1003
1004 child_nodep->getAttributeColor4("value", color);
1005 control->set(color.getValue());
1006 validitems++;
1007 }
1008 break;
1009 case TYPE_COL3:
1010 {
1011 LLVector3 color;
1012
1013 child_nodep->getAttributeVector3("value", color);
1014 control->set(LLColor3(color.mV).getValue());
1015 validitems++;
1016 }
1017 break;
1018 }
1019
1020 child_nodep = rootp->getNextChild();
1021 }
1022
1023 return validitems;
1024}
1025
1026
1027U32 LLControlGroup::saveToFile(const LLString& filename, BOOL nondefault_only)
1028{
1029 const char ENDL = '\n';
1030
1031 llinfos << "Saving settings to file: " << filename << llendl;
1032
1033 // place the objects in a temporary container that enforces a sort
1034 // order to ease manual editing of the file
1035 LLLinkedList< LLControlBase > controls;
1036 controls.setInsertBefore( &control_insert_before );
1037 LLString name;
1038 for (ctrl_name_table_t::iterator iter = mNameTable.begin();
1039 iter != mNameTable.end(); iter++)
1040 {
1041 name = iter->first;
1042 if (name.empty())
1043 {
1044 CONTROL_ERRS << "Control with no name found!!!" << llendl;
1045 break;
1046 }
1047
1048 LLControlBase* control = (LLControlBase *)mNameTable[name];
1049
1050 if (!control)
1051 {
1052 llwarns << "Tried to save invalid control: " << name << llendl;
1053 }
1054
1055 if( control && control->mPersist )
1056 {
1057 if (!(nondefault_only && (control->mIsDefault)))
1058 {
1059 controls.addDataSorted( control );
1060 }
1061 else
1062 {
1063 // Debug spam
1064 // llinfos << "Skipping " << control->getName() << llendl;
1065 }
1066 }
1067 }
1068
1069 llofstream file;
1070 file.open(filename.c_str());
1071
1072 if (!file.is_open())
1073 {
1074 // This is a warning because sometime we want to use settings files which can't be written...
1075 llwarns << "LLControlGroup::saveToFile unable to open file for writing" << llendl;
1076 return 0;
1077 }
1078
1079 // Write file version
1080 file << "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n";
1081 file << "<settings version = \"" << CURRENT_VERSION << "\">\n";
1082 for( LLControlBase* control = controls.getFirstData();
1083 control != NULL;
1084 control = controls.getNextData() )
1085 {
1086 file << "\t<!--" << control->comment() << "-->" << ENDL;
1087 name = control->name();
1088 switch (control->type())
1089 {
1090 case TYPE_U32:
1091 {
1092 file << "\t<" << name << " value=\"" << (U32) control->get().asInteger() << "\"/>\n";
1093 break;
1094 }
1095 case TYPE_S32:
1096 {
1097 file << "\t<" << name << " value=\"" << (S32) control->get().asInteger() << "\"/>\n";
1098 break;
1099 }
1100 case TYPE_F32:
1101 {
1102 file << "\t<" << name << " value=\"" << (F32) control->get().asReal() << "\"/>\n";
1103 break;
1104 }
1105 case TYPE_VEC3:
1106 {
1107 LLVector3 vector(control->get());
1108 file << "\t<" << name << " value=\"" << vector.mV[VX] << " " << vector.mV[VY] << " " << vector.mV[VZ] << "\"/>\n";
1109 break;
1110 }
1111 case TYPE_VEC3D:
1112 {
1113 LLVector3d vector(control->get());
1114 file << "\t<" << name << " value=\"" << vector.mdV[VX] << " " << vector.mdV[VY] << " " << vector.mdV[VZ] << "\"/>\n";
1115 break;
1116 }
1117 case TYPE_RECT:
1118 {
1119 LLRect rect(control->get());
1120 file << "\t<" << name << " value=\"" << rect.mLeft << " " << rect.mBottom << " " << rect.getWidth() << " " << rect.getHeight() << "\"/>\n";
1121 break;
1122 }
1123 case TYPE_COL4:
1124 {
1125 LLColor4 color(control->get());
1126 file << "\t<" << name << " value=\"" << color.mV[VRED] << ", " << color.mV[VGREEN] << ", " << color.mV[VBLUE] << ", " << color.mV[VALPHA] << "\"/>\n";
1127 break;
1128 }
1129 case TYPE_COL3:
1130 {
1131 LLColor3 color(control->get());
1132 file << "\t<" << name << " value=\"" << color.mV[VRED] << ", " << color.mV[VGREEN] << ", " << color.mV[VBLUE] << "\"/>\n";
1133 break;
1134 }
1135 case TYPE_BOOLEAN:
1136 {
1137 file << "\t<" << name << " value=\"" << (control->get().asBoolean() ? "TRUE" : "FALSE") << "\"/>\n";
1138 break;
1139 }
1140 case TYPE_STRING:
1141 {
1142 file << "\t<" << name << " value=\"" << LLSDXMLFormatter::escapeString(control->get().asString()) << "\"/>\n";
1143 break;
1144 }
1145 default:
1146 {
1147 CONTROL_ERRS << "LLControlGroup::saveToFile - unknown control type!" << llendl;
1148 break;
1149 }
1150 }
1151
1152 // Debug spam
1153 // llinfos << name << " " << control->getValue().asString() << llendl;
1154 }// next
1155
1156 file << "</settings>\n";
1157 file.close();
1158
1159 return controls.getLength();
1160}
1161
1162void LLControlGroup::applyOverrides(const std::map<std::string, std::string>& overrides)
1163{
1164 for (std::map<std::string, std::string>::const_iterator iter = overrides.begin();
1165 iter != overrides.end(); ++iter)
1166 {
1167 const std::string& command = iter->first;
1168 const std::string& value = iter->second;
1169 LLControlBase* control = (LLControlBase *)mNameTable[command];
1170 if (control)
1171 {
1172 switch(control->mType)
1173 {
1174 case TYPE_U32:
1175 control->set((LLSD::Integer)atof(value.c_str()));
1176 break;
1177 case TYPE_S32:
1178 control->set((S32)atof(value.c_str()));
1179 break;
1180 case TYPE_F32:
1181 control->set((F32)atof(value.c_str()));
1182 break;
1183 case TYPE_BOOLEAN:
1184 if (!LLString::compareInsensitive(value.c_str(), "TRUE"))
1185 {
1186 control->set(TRUE);
1187 }
1188 else if (!LLString::compareInsensitive(value.c_str(), "FALSE"))
1189 {
1190 control->set(FALSE);
1191 }
1192 else
1193 {
1194 control->set((BOOL)atof(value.c_str()));
1195 }
1196 break;
1197 case TYPE_STRING:
1198 control->set(value);
1199 break;
1200// // *FIX: implement this given time and need.
1201// case TYPE_UUID:
1202// break;
1203 // we don't support command line overrides of vec3 or col4
1204 // yet - requires parsing of multiple values
1205 case TYPE_VEC3:
1206 case TYPE_VEC3D:
1207 case TYPE_COL4:
1208 case TYPE_COL3:
1209 default:
1210 break;
1211 }
1212 }
1213 else
1214 {
1215 llinfos << "There is no control variable " << command << llendl;
1216 }
1217 }
1218}
1219
1220void LLControlGroup::resetToDefaults()
1221{
1222 ctrl_name_table_t::iterator control_iter;
1223 for (control_iter = mNameTable.begin();
1224 control_iter != mNameTable.end();
1225 ++control_iter)
1226 {
1227 LLControlBase* control = (*control_iter).second;
1228 control->resetToDefault();
1229 }
1230}
1231
1232//============================================================================
1233// FIrst-use
1234
1235
1236void LLControlGroup::addWarning(const LLString& name)
1237{
1238 LLString warnname = "Warn" + name;
1239 if(!mNameTable[warnname])
1240 {
1241 LLString comment = LLString("Enables ") + name + LLString(" warning dialog");
1242 declareBOOL(warnname, TRUE, comment);
1243 mWarnings.insert(warnname);
1244 }
1245}
1246
1247BOOL LLControlGroup::getWarning(const LLString& name)
1248{
1249 LLString warnname = "Warn" + name;
1250 return getBOOL(warnname);
1251}
1252
1253void LLControlGroup::setWarning(const LLString& name, BOOL val)
1254{
1255 LLString warnname = "Warn" + name;
1256 setBOOL(warnname, val);
1257}
1258
1259void LLControlGroup::resetWarnings()
1260{
1261 for (std::set<LLString>::iterator iter = mWarnings.begin();
1262 iter != mWarnings.end(); ++iter)
1263 {
1264 setBOOL(*iter, TRUE);
1265 }
1266}
1267
1268
1269
1270//=============================================================================
1271// Listener ID generator/management
1272
1273void LLControlBase::releaseListenerID(S32 id)
1274{
1275 mFreeIDs.push_back(id);
1276}
1277
1278S32 LLControlBase::allocateListenerID()
1279{
1280 if(mFreeIDs.size() == 0)
1281 { //Out of IDs so generate some new ones.
1282 for(int t=0;t<32;t++)
1283 {
1284 mFreeIDs.push_back(mTopID++);
1285 }
1286 }
1287 S32 rtn = mFreeIDs.front();
1288 mFreeIDs.pop_front();
1289 mUsedIDs.push_back(rtn);
1290 return rtn;
1291}
1292
1293bool LLControlBase::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
1294{
1295 if (event->desc() == "value_changed")
1296 {
1297 setValue(((LLValueChangedEvent*)(LLEvent*)event)->mValue);
1298 return TRUE;
1299 }
1300 return TRUE;
1301}
1302
1303void LLControlBase::firePropertyChanged()
1304{
1305 LLValueChangedEvent *evt = new LLValueChangedEvent(this, getValue());
1306 fireEvent(evt, "");
1307}
1308
1309//============================================================================
1310// Used to add a listener callback that will be called on the frame that the controls value changes
1311
1312S32 LLControl::addListener(LLControl::tListenerCallback* cbfn)
1313{
1314 S32 id = allocateListenerID();
1315 mListeners.push_back(cbfn);
1316 mListenerIDs.push_back( id );
1317 return id;
1318}
1319
1320void LLControl::updateListeners() {
1321 LLControl::tPropertyChangedListIter iter = mChangeEvents.begin();
1322 while(iter!=mChangeEvents.end()){
1323 LLControl::tPropertyChangedEvent& evt = *iter;
1324 (*evt.mCBFN)(evt.mNewValue,evt.mID,*this);
1325 iter++;
1326 }
1327 mChangeEvents.clear();
1328}
1329
1330//static
1331void LLControlBase::updateAllListeners()
1332{
1333 std::set< LLControlBase* >::iterator iter = mChangedControls.begin();
1334 while(iter != mChangedControls.end()){
1335 (*iter)->updateListeners();
1336 iter++;
1337 }
1338 mChangedControls.clear();
1339}
1340
1341LLControl::LLControl(
1342 const LLString& name,
1343 eControlType type,
1344 LLSD initial,
1345 const LLString& comment,
1346 BOOL persist) :
1347 LLControlBase(name, type, comment, persist),
1348 mCurrent(initial),
1349 mDefault(initial)
1350{
1351}
1352
1353//============================================================================
1354
1355#ifdef TEST_HARNESS
1356void main()
1357{
1358 F32_CONTROL foo, getfoo;
1359
1360 S32_CONTROL bar, getbar;
1361
1362 BOOL_CONTROL baz;
1363
1364 U32 count = gGlobals.loadFromFile("controls.ini");
1365 llinfos << "Loaded " << count << " controls" << llendl;
1366
1367 // test insertion
1368 foo = new LLControl<F32>("gFoo", 5.f, 1.f, 20.f);
1369 gGlobals.addEntry("gFoo", foo);
1370
1371 bar = new LLControl<S32>("gBar", 10, 2, 22);
1372 gGlobals.addEntry("gBar", bar);
1373
1374 baz = new LLControl<BOOL>("gBaz", FALSE);
1375 gGlobals.addEntry("gBaz", baz);
1376
1377 // test retrieval
1378 getfoo = (LLControl<F32>*) gGlobals.resolveName("gFoo");
1379 getfoo->dump();
1380
1381 getbar = (S32_CONTROL) gGlobals.resolveName("gBar");
1382 getbar->dump();
1383
1384 // change data
1385 getfoo->set(10.f);
1386 getfoo->dump();
1387
1388 // Failure modes
1389
1390 // ...min > max
1391 // badfoo = new LLControl<F32>("gFoo2", 100.f, 20.f, 5.f);
1392
1393 // ...initial > max
1394 // badbar = new LLControl<S32>("gBar2", 10, 20, 100000);
1395
1396 // ...misspelled name
1397 // getfoo = (F32_CONTROL) gGlobals.resolveName("fooMisspelled");
1398 // getfoo->dump();
1399
1400 // ...invalid data type
1401 getfoo = (F32_CONTROL) gGlobals.resolveName("gFoo");
1402 getfoo->set(TRUE);
1403 getfoo->dump();
1404
1405 // ...out of range data
1406 // getfoo->set(100000000.f);
1407 // getfoo->dump();
1408
1409 // Clean Up
1410 delete foo;
1411 delete bar;
1412 delete baz;
1413}
1414#endif
1415
1416BOOL control_insert_before( LLControlBase* first, LLControlBase* second )
1417{
1418 return ( first->getName().compare(second->getName()) < 0 );
1419}
1420