diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llui/llloadingindicator.cpp | 67 | ||||
| -rw-r--r-- | indra/llui/llloadingindicator.h | 30 | ||||
| -rw-r--r-- | indra/llui/llui.cpp | 103 | ||||
| -rw-r--r-- | indra/llui/llui.h | 79 | ||||
| -rw-r--r-- | indra/llui/lluiimage.cpp | 12 | ||||
| -rw-r--r-- | indra/llui/lluiimage.h | 17 | ||||
| -rw-r--r-- | indra/llui/tests/llurlentry_stub.cpp | 34 | ||||
| -rw-r--r-- | indra/llui/tests/llurlentry_test.cpp | 16 | ||||
| -rw-r--r-- | indra/llui/tests/llurlmatch_test.cpp | 52 | ||||
| -rw-r--r-- | indra/llxuixml/llinitparam.cpp | 101 | ||||
| -rw-r--r-- | indra/llxuixml/llinitparam.h | 1132 | ||||
| -rw-r--r-- | indra/newview/llcommandhandler.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llfloaterpreference.cpp | 30 | ||||
| -rw-r--r-- | indra/newview/llviewerwindow.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/skins/default/colors.xml | 17 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/notifications.xml | 23 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_preferences_privacy.xml | 2 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/widgets/loading_indicator.xml | 20 | 
18 files changed, 918 insertions, 824 deletions
| diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp index 7b29d92ea0..8a0f875808 100644 --- a/indra/llui/llloadingindicator.cpp +++ b/indra/llui/llloadingindicator.cpp @@ -39,56 +39,24 @@  //static LLDefaultChildRegistry::Register<LLLoadingIndicator> r("loading_indicator");  /////////////////////////////////////////////////////////////////////////////// -// LLLoadingIndicator::Data class +// LLLoadingIndicator class  /////////////////////////////////////////////////////////////////////////////// -/** - * Pre-loaded images shared by all instances of the widget - */ -class LLLoadingIndicator::Data: public LLSingleton<LLLoadingIndicator::Data> +LLLoadingIndicator::LLLoadingIndicator(const Params& p) +:	LLUICtrl(p),  +	mImagesPerSec(p.images_per_sec > 0 ? p.images_per_sec : 1.0f),  +	mCurImageIdx(0)  { -public: -	/*virtual*/ void		initSingleton(); // from LLSingleton - -	LLPointer<LLUIImage>	getNextImage(S8& idx) const; -	U8						getImagesCount() const	{ return NIMAGES; } -private: - -	static const U8			NIMAGES = 12; -	LLPointer<LLUIImage>	mImages[NIMAGES]; -}; +} -// virtual -// Called right after the instance gets constructed. -void LLLoadingIndicator::Data::initSingleton() +void LLLoadingIndicator::initFromParams(const Params& p)  { -	// Load images. -	for (U8 i = 0; i < NIMAGES; ++i) +	for (LLInitParam::ParamIterator<LLUIImage*>::const_iterator it = p.images().image.begin(), end_it = p.images().image.end(); +		it != end_it; +		++it)  	{ -		std::string img_name = llformat("Progress_%d", i+1); -		mImages[i] = LLUI::getUIImage(img_name, 0); -		llassert(mImages[i]); +		mImages.push_back(it->getValue());  	} -} - -LLPointer<LLUIImage> LLLoadingIndicator::Data::getNextImage(S8& idx) const -{ -	// Calculate next index, performing array bounds checking. -	idx = (idx >= NIMAGES || idx < 0) ? 0 : (idx + 1) % NIMAGES;  -	return mImages[idx]; -} - -/////////////////////////////////////////////////////////////////////////////// -// LLLoadingIndicator class -/////////////////////////////////////////////////////////////////////////////// - -LLLoadingIndicator::LLLoadingIndicator(const Params& p) -:	LLUICtrl(p) -	, mRotationsPerSec(p.rotations_per_sec > 0 ? p.rotations_per_sec : 1.0f) -	, mCurImageIdx(-1) -{ -	// Select initial image. -	mCurImagep = Data::instance().getNextImage(mCurImageIdx);  	// Start timer for switching images.  	start(); @@ -100,16 +68,21 @@ void LLLoadingIndicator::draw()  	if (mImageSwitchTimer.getStarted() && mImageSwitchTimer.hasExpired())  	{  		// Switch to the next image. -		mCurImagep = Data::instance().getNextImage(mCurImageIdx); +		if (!mImages.empty()) +		{ +			mCurImageIdx = (mCurImageIdx + 1) % mImages.size(); +		}  		// Restart timer.  		start();  	} +	LLUIImagePtr cur_image = mImages.empty() ? NULL : mImages[mCurImageIdx]; +  	// Draw current image. -	if( mCurImagep.notNull() ) +	if( cur_image.notNull() )  	{ -		mCurImagep->draw(getLocalRect(), LLColor4::white % getDrawContext().mAlpha); +		cur_image->draw(getLocalRect(), LLColor4::white % getDrawContext().mAlpha);  	}  	LLUICtrl::draw(); @@ -123,6 +96,6 @@ void LLLoadingIndicator::stop()  void LLLoadingIndicator::start()  {  	mImageSwitchTimer.start(); -	F32 period = 1.0f / (Data::instance().getImagesCount() * mRotationsPerSec); +	F32 period = 1.0f / (mImages.size() * mImagesPerSec);  	mImageSwitchTimer.setTimerExpirySec(period);  } diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h index 4e4a224ef6..c0cb1cc74a 100644 --- a/indra/llui/llloadingindicator.h +++ b/indra/llui/llloadingindicator.h @@ -36,8 +36,8 @@  /**   * Perpetual loading indicator (a la MacOSX or YouTube)   *  - * Number of rotations per second can be overriden - * with the "roations_per_sec" parameter. + * Number of rotations per second can be overridden + * with the "images_per_sec" parameter.   *    * Can start/stop spinning.   *  @@ -49,11 +49,24 @@ class LLLoadingIndicator  {  	LOG_CLASS(LLLoadingIndicator);  public: + +	struct Images : public LLInitParam::Block<Images> +	{ +		Multiple<LLUIImage*>	image; + +		Images() +		:	image("image") +		{} +	}; +  	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>  	{ -		Optional<F32>	rotations_per_sec; +		Optional<F32>			images_per_sec; +		Batch<Images>			images; +  		Params() -		:	rotations_per_sec("rotations_per_sec", 1.0f) +		:	images_per_sec("images_per_sec", 1.0f), +			images("images")  		{}  	}; @@ -74,14 +87,15 @@ public:  private:  	LLLoadingIndicator(const Params&); -	friend class LLUICtrlFactory; +	void initFromParams(const Params&); -	class Data; +	friend class LLUICtrlFactory; -	F32						mRotationsPerSec; +	F32						mImagesPerSec;  	S8						mCurImageIdx; -	LLPointer<LLUIImage>	mCurImagep;  	LLFrameTimer			mImageSwitchTimer; + +	std::vector<LLUIImagePtr> mImages;  };  #endif // LL_LLLOADINGINDICATOR_H diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 87669574c2..8020ca802b 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1626,8 +1626,8 @@ void LLUI::cleanupClass()  {  	if(sImageProvider)  	{ -		sImageProvider->cleanUp(); -	} +	sImageProvider->cleanUp(); +}  }  void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup,  const clear_popups_t& clear_popups) @@ -2074,32 +2074,32 @@ const LLView* LLUI::resolvePath(const LLView* context, const std::string& path)  namespace LLInitParam  { -	TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) -	:	super_t(descriptor, name, value, func, min_count, max_count), +	ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) +	:	super_t(color),  		red("red"),  		green("green"),  		blue("blue"),  		alpha("alpha"),  		control("")  	{ -		setBlockFromValue(); +		updateBlockFromValue();  	} -	void TypedParam<LLUIColor>::setValueFromBlock() const +	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock()  	{  		if (control.isProvided())  		{ -			mData.mValue = LLUIColorTable::instance().getColor(control); +			updateValue(LLUIColorTable::instance().getColor(control));  		}  		else  		{ -			mData.mValue = LLColor4(red, green, blue, alpha); +			updateValue(LLColor4(red, green, blue, alpha));  		}  	} -	void TypedParam<LLUIColor>::setBlockFromValue() +	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue()  	{ -		LLColor4 color = mData.mValue.get(); +		LLColor4 color = getValue();  		red.set(color.mV[VRED], false);  		green.set(color.mV[VGREEN], false);  		blue.set(color.mV[VBLUE], false); @@ -2107,38 +2107,32 @@ namespace LLInitParam  		control.set("", false);  	} -	void TypeValues<LLUIColor>::declareValues() -	{ -		declare("white", LLColor4::white); -		declare("black", LLColor4::black); -		declare("red", LLColor4::red); -		declare("green", LLColor4::green); -		declare("blue", LLColor4::blue); -	} -  	bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)  	{  		return !(a->getFontDesc() < b->getFontDesc())  			&& !(b->getFontDesc() < a->getFontDesc());  	} -	TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) -	:	super_t(descriptor, _name, value, func, min_count, max_count), +	ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) +	:	super_t(fontp),  		name("name"),  		size("size"),  		style("style")  	{ -		setBlockFromValue(); +		if (!fontp) +		{ +			updateValue(LLFontGL::getFontDefault()); +		}  		addSynonym(name, ""); -		setBlockFromValue(); +		updateBlockFromValue();  	} -	void TypedParam<const LLFontGL*>::setValueFromBlock() const +	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock()  	{  		const LLFontGL* res_fontp = LLFontGL::getFontByName(name);  		if (res_fontp)  		{ -			mData.mValue = res_fontp; +			updateValue(res_fontp);  			return;  		} @@ -2148,22 +2142,26 @@ namespace LLInitParam  		const LLFontGL* fontp = LLFontGL::getFont(desc);  		if (fontp)  		{ -			mData.mValue = fontp; -		}		 +			updateValue(fontp); +		} +		else +		{ +			updateValue(LLFontGL::getFontDefault()); +		}  	} -	void TypedParam<const LLFontGL*>::setBlockFromValue() +	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue()  	{ -		if (mData.mValue) +		if (getValue())  		{ -			name.set(LLFontGL::nameFromFont(mData.mValue), false); -			size.set(LLFontGL::sizeFromFont(mData.mValue), false); -			style.set(LLFontGL::getStringFromStyle(mData.mValue->getFontDesc().getStyle()), false); +			name.set(LLFontGL::nameFromFont(getValue()), false); +			size.set(LLFontGL::sizeFromFont(getValue()), false); +			style.set(LLFontGL::getStringFromStyle(getValue()->getFontDesc().getStyle()), false);  		}  	} -	TypedParam<LLRect>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) -	:	super_t(descriptor, name, value, func, min_count, max_count), +	ParamValue<LLRect, TypeValues<LLRect> >::ParamValue(const LLRect& rect) +	:	super_t(rect),  		left("left"),  		top("top"),  		right("right"), @@ -2171,10 +2169,10 @@ namespace LLInitParam  		width("width"),  		height("height")  	{ -		setBlockFromValue(); +		updateBlockFromValue();  	} -	void TypedParam<LLRect>::setValueFromBlock() const +	void ParamValue<LLRect, TypeValues<LLRect> >::updateValueFromBlock()  	{  		LLRect rect; @@ -2235,40 +2233,41 @@ namespace LLInitParam  			rect.mBottom = bottom;  			rect.mTop = top;  		} -		mData.mValue = rect; +		updateValue(rect);  	} -	void TypedParam<LLRect>::setBlockFromValue() +	void ParamValue<LLRect, TypeValues<LLRect> >::updateBlockFromValue()  	{  		// because of the ambiguity in specifying a rect by position and/or dimensions  		// we clear the "provided" flag so that values from xui/etc have priority  		// over those calculated from the rect object -		left.set(mData.mValue.mLeft, false); -		right.set(mData.mValue.mRight, false); -		bottom.set(mData.mValue.mBottom, false); -		top.set(mData.mValue.mTop, false); -		width.set(mData.mValue.getWidth(), false); -		height.set(mData.mValue.getHeight(), false); +		LLRect& value = getValue(); +		left.set(value.mLeft, false); +		right.set(value.mRight, false); +		bottom.set(value.mBottom, false); +		top.set(value.mTop, false); +		width.set(value.getWidth(), false); +		height.set(value.getHeight(), false);  	} -	TypedParam<LLCoordGL>::TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) -	:	super_t(descriptor, name, value, func, min_count, max_count), +	ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::ParamValue(const LLCoordGL& coord) +	:	super_t(coord),  		x("x"),  		y("y")  	{ -		setBlockFromValue(); +		updateBlockFromValue();  	} -	void TypedParam<LLCoordGL>::setValueFromBlock() const +	void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateValueFromBlock()  	{ -		mData.mValue.set(x, y); +		updateValue(LLCoordGL(x, y));  	} -	void TypedParam<LLCoordGL>::setBlockFromValue() +	void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateBlockFromValue()  	{ -		x.set(mData.mValue.mX, false); -		y.set(mData.mValue.mY, false); +		x.set(getValue().mX, false); +		y.set(getValue().mY, false);  	} diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 50cb9e6632..6a43477693 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -398,10 +398,10 @@ public:  namespace LLInitParam  {  	template<> -	class TypedParam<LLRect>  -	:	public BlockValue<LLRect> +	class ParamValue<LLRect, TypeValues<LLRect> >  +	:	public CustomParamValue<LLRect>  	{ -        typedef BlockValue<LLRect> super_t; +        typedef CustomParamValue<LLRect> super_t;  	public:  		Optional<S32>	left,  						top, @@ -410,62 +410,43 @@ namespace LLInitParam  						width,  						height; -		TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); +		ParamValue(const LLRect& value); -		void setValueFromBlock() const; -		void setBlockFromValue(); +		void updateValueFromBlock(); +		void updateBlockFromValue();  	};  	template<> -	struct TypeValues<LLUIColor> : public TypeValuesHelper<LLUIColor> +	class ParamValue<LLUIColor, TypeValues<LLUIColor> >  +	:	public CustomParamValue<LLUIColor>  	{ -		static void declareValues(); -	}; +        typedef CustomParamValue<LLUIColor> super_t; -	template<> -	class TypedParam<LLUIColor>  -	:	public BlockValue<LLUIColor> -	{ -        typedef BlockValue<LLUIColor> super_t;  	public: -		Optional<F32>	red, -						green, -						blue, -						alpha; -		Optional<std::string> control; - -		TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); -		void setValueFromBlock() const; -		void setBlockFromValue(); +		Optional<F32>			red, +								green, +								blue, +								alpha; +		Optional<std::string>	control; + +		ParamValue(const LLUIColor& color); +		void updateValueFromBlock(); +		void updateBlockFromValue();  	}; -	// provide a better default for Optional<const LLFontGL*> than NULL -	template <> -	struct DefaultInitializer<const LLFontGL*> -	{ -		// return reference to a single default instance of T -		// built-in types will be initialized to zero, default constructor otherwise -		static const LLFontGL* get()  -		{  -			static const LLFontGL* sDefaultFont = LLFontGL::getFontDefault();   -			return sDefaultFont; -		}  -	}; - -  	template<> -	class TypedParam<const LLFontGL*>  -	:	public BlockValue<const LLFontGL*> +	class ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >  +	:	public CustomParamValue<const LLFontGL* >  	{ -        typedef BlockValue<const LLFontGL*> super_t; +        typedef CustomParamValue<const LLFontGL*> super_t;  	public:  		Optional<std::string>	name,  								size,  								style; -		TypedParam(BlockDescriptor& descriptor, const char* name, const LLFontGL* const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); -		void setValueFromBlock() const; -		void setBlockFromValue(); +		ParamValue(const LLFontGL* value); +		void updateValueFromBlock(); +		void updateBlockFromValue();  	};  	template<> @@ -494,17 +475,17 @@ namespace LLInitParam  	template<> -	class TypedParam<LLCoordGL> -	:	public BlockValue<LLCoordGL> +	class ParamValue<LLCoordGL, TypeValues<LLCoordGL> > +	:	public CustomParamValue<LLCoordGL>  	{ -		typedef BlockValue<LLCoordGL> super_t; +		typedef CustomParamValue<LLCoordGL> super_t;  	public:  		Optional<S32>	x,  						y; -		TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count); -		void setValueFromBlock() const; -		void setBlockFromValue(); +		ParamValue(const LLCoordGL& val); +		void updateValueFromBlock(); +		void updateBlockFromValue();  	};  } diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp index 1ffad4806e..f37947a50b 100644 --- a/indra/llui/lluiimage.cpp +++ b/indra/llui/lluiimage.cpp @@ -155,32 +155,32 @@ void LLUIImage::onImageLoaded()  namespace LLInitParam  { -	void TypedParam<LLUIImage*>::setValueFromBlock() const +	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock()  	{  		// The keyword "none" is specifically requesting a null image  		// do not default to current value. Used to overwrite template images.   		if (name() == "none")  		{ -			mData.mValue = NULL; +			updateValue(NULL);  			return;  		}  		LLUIImage* imagep =  LLUI::getUIImage(name());  		if (imagep)  		{ -			mData.mValue = imagep; +			updateValue(imagep);  		}  	} -	void TypedParam<LLUIImage*>::setBlockFromValue() +	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue()  	{ -		if (mData.mValue == NULL) +		if (getValue() == NULL)  		{  			name.set("none", false);  		}  		else  		{ -			name.set(mData.mValue->getName(), false); +			name.set(getValue()->getName(), false);  		}  	} diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h index 38107c112d..139d88e0ac 100644 --- a/indra/llui/lluiimage.h +++ b/indra/llui/lluiimage.h @@ -92,22 +92,23 @@ protected:  namespace LLInitParam  {  	template<> -	class TypedParam<LLUIImage*, TypeValues<LLUIImage*>, false>  -	:	public BlockValue<LLUIImage*> +	class ParamValue<LLUIImage*, TypeValues<LLUIImage*> >  +	:	public CustomParamValue<LLUIImage*>  	{  		typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type	T_const_ref; -		typedef BlockValue<LLUIImage*> super_t; +		typedef CustomParamValue<LLUIImage*> super_t;  	public:  		Optional<std::string> name; -		TypedParam(BlockDescriptor& descriptor, const char* name, super_t::value_assignment_t value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) -		:	super_t(descriptor, name, value, func, min_count, max_count) +		ParamValue(LLUIImage* const& image) +		:	super_t(image)  		{ -			setBlockFromValue(); +			updateBlockFromValue(); +			addSynonym(name, "name");  		} -		void setValueFromBlock() const; -		void setBlockFromValue(); +		void updateValueFromBlock(); +		void updateBlockFromValue();  	};  	// Need custom comparison function for our test app, which only loads diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index ac2412c928..75946b2416 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -114,32 +114,30 @@ namespace LLInitParam  		const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);  		mEnclosingBlockOffset = (U16)(my_addr - block_addr);  	} -	void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {} +	void BaseBlock::paramChanged(const Param& last_param, bool user_provided) {} -	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){} +	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){} +	void BaseBlock::addSynonym(Param& param, const std::string& synonym) {}  	param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}  	void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)  	{  		descriptor.mCurrentBlockPtr = this;  	} -	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; } -	bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; } -	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; } +	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation){ return true; } +	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const {} +	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_value, S32 max_value) const { return true; }  	bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }  	bool BaseBlock::validateBlock(bool emit_errors) const { return true; } -	TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) -	:	super_t(descriptor, name, value, func, min_count, max_count) +	ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) +	:	super_t(color)  	{} -	void TypedParam<LLUIColor>::setValueFromBlock() const +	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock()   	{} -	void TypedParam<LLUIColor>::setBlockFromValue() -	{} - -	void TypeValues<LLUIColor>::declareValues() +	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue()  	{}  	bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -147,14 +145,14 @@ namespace LLInitParam  		return false;  	} -	TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) -	:	super_t(descriptor, _name, value, func, min_count, max_count) +	ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) +	:	super_t(fontp)  	{} -	void TypedParam<const LLFontGL*>::setValueFromBlock() const +	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock()  	{} -	void TypedParam<const LLFontGL*>::setBlockFromValue() +	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue()  	{}  	void TypeValues<LLFontGL::HAlign>::declareValues() @@ -166,10 +164,10 @@ namespace LLInitParam  	void TypeValues<LLFontGL::ShadowType>::declareValues()  	{} -	void TypedParam<LLUIImage*>::setValueFromBlock() const +	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock()  	{} -	void TypedParam<LLUIImage*>::setBlockFromValue() +	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue()  	{} diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index 8f0a48018f..2f814f4200 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -70,6 +70,22 @@ S32 LLUIImage::getHeight() const  	return 0;  } +namespace LLInitParam +{ +	S32 Parser::sNextParseGeneration = 0; +	BlockDescriptor::BlockDescriptor() {} +	ParamDescriptor::ParamDescriptor(param_handle_t p,  +						merge_func_t merge_func,  +						deserialize_func_t deserialize_func,  +						serialize_func_t serialize_func, +						validation_func_t validation_func, +						inspect_func_t inspect_func, +						S32 min_count, +						S32 max_count){} +	ParamDescriptor::~ParamDescriptor() {} + +} +  namespace tut  {  	struct LLUrlEntryData diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index fdaab00f18..aea605c9f2 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -66,11 +66,25 @@ namespace LLInitParam  	BaseBlock::BaseBlock() {}  	BaseBlock::~BaseBlock() {} -	void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {} - -	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){} +	S32 Parser::sNextParseGeneration = 0; + +	BlockDescriptor::BlockDescriptor() {} +	ParamDescriptor::ParamDescriptor(param_handle_t p,  +						merge_func_t merge_func,  +						deserialize_func_t deserialize_func,  +						serialize_func_t serialize_func, +						validation_func_t validation_func, +						inspect_func_t inspect_func, +						S32 min_count, +						S32 max_count){} +	ParamDescriptor::~ParamDescriptor() {} + +	void BaseBlock::paramChanged(const Param& last_param, bool user_provided) {} + +	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){}  	param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;} -	 +	void BaseBlock::addSynonym(Param& param, const std::string& synonym) {} +  	void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)  	{  		descriptor.mCurrentBlockPtr = this; @@ -84,23 +98,20 @@ namespace LLInitParam  		mEnclosingBlockOffset = (U16)(my_addr - block_addr);  	} -	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; } -	bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; } -	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; } +	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation){ return true; } +	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const {} +	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const { return true; }  	bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }  	bool BaseBlock::validateBlock(bool emit_errors) const { return true; } -	TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) -	:	super_t(descriptor, name, value, func, min_count, max_count) +	ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) +	:	super_t(color)  	{} -	void TypedParam<LLUIColor>::setValueFromBlock() const +	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock()  	{} -	void TypedParam<LLUIColor>::setBlockFromValue() -	{} - -	void TypeValues<LLUIColor>::declareValues() +	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue()  	{}  	bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -108,14 +119,15 @@ namespace LLInitParam  		return false;  	} -	TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count) -	:	super_t(descriptor, _name, value, func, min_count, max_count) + +	ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) +	:	super_t(fontp)  	{} -	void TypedParam<const LLFontGL*>::setValueFromBlock() const +	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock()  	{} -	void TypedParam<const LLFontGL*>::setBlockFromValue() +	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue()  	{}  	void TypeValues<LLFontGL::HAlign>::declareValues() @@ -127,10 +139,10 @@ namespace LLInitParam  	void TypeValues<LLFontGL::ShadowType>::declareValues()  	{} -	void TypedParam<LLUIImage*>::setValueFromBlock() const +	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock()  	{} -	void TypedParam<LLUIImage*>::setBlockFromValue() +	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue()  	{}  	bool ParamCompare<LLUIImage*, false>::equals( diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index fcdbaa4309..3c4eb70a5d 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -44,8 +44,51 @@ namespace LLInitParam  	}  	// +	// ParamDescriptor +	// +	ParamDescriptor::ParamDescriptor(param_handle_t p,  +									merge_func_t merge_func,  +									deserialize_func_t deserialize_func,  +									serialize_func_t serialize_func, +									validation_func_t validation_func, +									inspect_func_t inspect_func, +									S32 min_count, +									S32 max_count) +	:	mParamHandle(p), +		mMergeFunc(merge_func), +		mDeserializeFunc(deserialize_func), +		mSerializeFunc(serialize_func), +		mValidationFunc(validation_func), +		mInspectFunc(inspect_func), +		mMinCount(min_count), +		mMaxCount(max_count), +		mGeneration(0), +		mUserData(NULL) +	{} + +	ParamDescriptor::ParamDescriptor() +	:	mParamHandle(0), +		mMergeFunc(NULL), +		mDeserializeFunc(NULL), +		mSerializeFunc(NULL), +		mValidationFunc(NULL), +		mInspectFunc(NULL), +		mMinCount(0), +		mMaxCount(0), +		mGeneration(0), +		mUserData(NULL) +	{} + +	ParamDescriptor::~ParamDescriptor() +	{ +		delete mUserData; +	} + +	//  	// Parser  	// +	S32 Parser::sNextParseGeneration = 0; +  	Parser::~Parser()  	{} @@ -73,6 +116,12 @@ namespace LLInitParam  		std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));  	} +	BlockDescriptor::BlockDescriptor() +	:	mMaxParamOffset(0), +		mInitializationState(UNINITIALIZED), +		mCurrentBlockPtr(NULL) +	{} +  	//  	// BaseBlock  	// @@ -115,7 +164,7 @@ namespace LLInitParam  	bool BaseBlock::submitValue(const Parser::name_stack_t& name_stack, Parser& p, bool silent)  	{ -		if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()))) +		if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), -1))  		{  			if (!silent)  			{ @@ -145,7 +194,7 @@ namespace LLInitParam  		return true;  	} -	bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const +	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const  	{  		// named param is one like LLView::Params::follows  		// unnamed param is like LLView::Params::rect - implicit @@ -212,11 +261,9 @@ namespace LLInitParam  				name_stack.pop_back();  			}  		} - -		return true;  	} -	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const +	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const  	{  		// named param is one like LLView::Params::follows  		// unnamed param is like LLView::Params::rect - implicit @@ -273,11 +320,13 @@ namespace LLInitParam  		return true;  	} -	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack) +	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 parent_generation)  	{  		BlockDescriptor& block_data = mostDerivedBlockDescriptor();  		bool names_left = name_stack.first != name_stack.second; +		S32 parse_generation = name_stack.first == name_stack.second ? -1 : name_stack.first->second; +  		if (names_left)  		{  			const std::string& top_name = name_stack.first->first; @@ -294,7 +343,7 @@ namespace LLInitParam  				Parser::name_stack_range_t new_name_stack(name_stack.first, name_stack.second);  				++new_name_stack.first; -				return deserialize_func(*paramp, p, new_name_stack, name_stack.first == name_stack.second ? -1 : name_stack.first->second); +				return deserialize_func(*paramp, p, new_name_stack, parse_generation);  			}  		} @@ -306,7 +355,7 @@ namespace LLInitParam  			Param* paramp = getParamFromHandle((*it)->mParamHandle);  			ParamDescriptor::deserialize_func_t deserialize_func = (*it)->mDeserializeFunc; -			if (deserialize_func && deserialize_func(*paramp, p, name_stack, name_stack.first == name_stack.second ? -1 : name_stack.first->second)) +			if (deserialize_func && deserialize_func(*paramp, p, name_stack, parse_generation))  			{  				return true;  			} @@ -324,32 +373,32 @@ namespace LLInitParam  	}  	//static  -	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name) +	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name)  	{  		// create a copy of the paramdescriptor in allparams  		// so other data structures can store a pointer to it  		block_data.mAllParams.push_back(in_param); -		ParamDescriptor& param(block_data.mAllParams.back()); +		ParamDescriptorPtr param(block_data.mAllParams.back());  		std::string name(char_name); -		if ((size_t)param.mParamHandle > block_data.mMaxParamOffset) +		if ((size_t)param->mParamHandle > block_data.mMaxParamOffset)  		{  			llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;  		}  		if (name.empty())  		{ -			block_data.mUnnamedParams.push_back(¶m); +			block_data.mUnnamedParams.push_back(param);  		}  		else  		{  			// don't use insert, since we want to overwrite existing entries -			block_data.mNamedParams[name] = ¶m; +			block_data.mNamedParams[name] = param;  		} -		if (param.mValidationFunc) +		if (param->mValidationFunc)  		{ -			block_data.mValidationList.push_back(std::make_pair(param.mParamHandle, param.mValidationFunc)); +			block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc));  		}  	} @@ -367,7 +416,7 @@ namespace LLInitParam  				llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;  			} -			ParamDescriptor* param_descriptor = findParamDescriptor(handle); +			ParamDescriptorPtr param_descriptor = findParamDescriptor(param);  			if (param_descriptor)  			{  				if (synonym.empty()) @@ -382,7 +431,7 @@ namespace LLInitParam  		}  	} -	void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) +	void BaseBlock::paramChanged(const Param& changed_param, bool user_provided)  	{   		if (user_provided)  		{ @@ -404,17 +453,18 @@ namespace LLInitParam  		return LLStringUtil::null;  	} -	ParamDescriptor* BaseBlock::findParamDescriptor(param_handle_t handle) +	ParamDescriptorPtr BaseBlock::findParamDescriptor(const Param& param)  	{ +		param_handle_t handle = getHandleFromParam(¶m);  		BlockDescriptor& descriptor = mostDerivedBlockDescriptor();  		BlockDescriptor::all_params_list_t::iterator end_it = descriptor.mAllParams.end();  		for (BlockDescriptor::all_params_list_t::iterator it = descriptor.mAllParams.begin();  			it != end_it;  			++it)  		{ -			if (it->mParamHandle == handle) return &(*it); +			if ((*it)->mParamHandle == handle) return *it;  		} -		return NULL; +		return ParamDescriptorPtr();  	}  	// take all provided params from other and apply to self @@ -427,19 +477,14 @@ namespace LLInitParam  			it != end_it;  			++it)  		{ -			const Param* other_paramp = other.getParamFromHandle(it->mParamHandle); -			ParamDescriptor::merge_func_t merge_func = it->mMergeFunc; +			const Param* other_paramp = other.getParamFromHandle((*it)->mParamHandle); +			ParamDescriptor::merge_func_t merge_func = (*it)->mMergeFunc;  			if (merge_func)  			{ -				Param* paramp = getParamFromHandle(it->mParamHandle); +				Param* paramp = getParamFromHandle((*it)->mParamHandle);  				some_param_changed |= merge_func(*paramp, *other_paramp, overwrite);  			}  		}  		return some_param_changed;  	} - -	bool ParamCompare<LLSD, false>::equals(const LLSD &a, const LLSD &b) -	{ -		return false; -	}  } diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 1f9045754a..39ba32e537 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -1,5 +1,5 @@  /**  -f * @file llinitparam.h + * @file llinitparam.h   * @brief parameter block abstraction for creating complex objects and    * parsing construction parameters from xml and LLSD   * @@ -29,18 +29,14 @@ f * @file llinitparam.h  #define LL_LLPARAM_H  #include <vector> - -#include <stddef.h>  #include <boost/function.hpp> -#include <boost/bind.hpp>  #include <boost/type_traits/is_convertible.hpp>  #include <boost/unordered_map.hpp> -#include "llregistry.h" -#include "llmemory.h" - +#include <boost/shared_ptr.hpp>  namespace LLInitParam  { +	template<typename T> const T& defaultValue() { static T value; return value; }  	template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value >      struct ParamCompare  @@ -61,122 +57,119 @@ namespace LLInitParam  		}  	}; -	// default constructor adaptor for InitParam Values -	// constructs default instances of the given type, returned by const reference -	template <typename T> -	struct DefaultInitializer +	template<>  +	struct ParamCompare<LLSD, false>  	{ -		typedef const T&			T_const_ref; -		// return reference to a single default instance of T -		// built-in types will be initialized to zero, default constructor otherwise -		static T_const_ref get() { static T t = T(); return t; }  +		static bool equals(const LLSD &a, const LLSD &b) { return false; }  	};  	// helper functions and classes  	typedef ptrdiff_t param_handle_t; +	// empty default implementation of key cache +	// leverages empty base class optimization  	template <typename T>  	class TypeValues  	{  	public: -		// empty default implemenation of key cache -		class KeyCache +		typedef std::map<std::string, T> value_name_map_t; + +		void setValueName(const std::string& key) {} +		std::string getValueName() const { return ""; } +		void clearValueName() const {} + +		static bool getValueFromName(const std::string& name, T& value)  		{ -		public: -			void setKey(const std::string& key) {} -			std::string getKey() const { return ""; } -			void clearKey(){} -		}; +			return false; +		} -		static bool get(const std::string& name, T& value) +		static bool valueNamesExist()  		{  			return false;  		} -		static bool empty() +		static std::vector<std::string>* getPossibleValues()  		{ -			return true; +			return NULL;  		} -		static std::vector<std::string>* getPossibleValues() { return NULL; } +		static value_name_map_t* getValueNames() {return NULL;}  	};  	template <typename T, typename DERIVED_TYPE = TypeValues<T> >  	class TypeValuesHelper -	:	public LLRegistrySingleton<std::string, T, DERIVED_TYPE >  	{ -		typedef LLRegistrySingleton<std::string, T, DERIVED_TYPE>	super_t; -		typedef LLSingleton<DERIVED_TYPE>							singleton_t;  	public: +		typedef std::map<std::string, T> value_name_map_t;  		//TODO: cache key by index to save on param block size -		class KeyCache +		void setValueName(const std::string& value_name)   		{ -		public: -			void setKey(const std::string& key)  -			{ -				mKey = key;  -			} - -			void clearKey() -			{ -				mKey = ""; -			} +			mValueName = value_name;  +		} -			std::string getKey() const -			{  -				return mKey;  -			} +		std::string getValueName() const +		{  +			return mValueName;  +		} -		private: -			std::string mKey; -		}; +		void clearValueName() const +		{ +			mValueName.clear(); +		} -		static bool get(const std::string& name, T& value) +		static bool getValueFromName(const std::string& name, T& value)  		{ -			if (!singleton_t::instance().exists(name)) return false; +			value_name_map_t* map = getValueNames(); +			value_name_map_t::iterator found_it = map->find(name); +			if (found_it == map->end()) return false; -			value = *singleton_t::instance().getValue(name); +			value = found_it->second;  			return true;  		} -		static bool empty() +		static bool valueNamesExist()  		{ -			return singleton_t::instance().LLRegistry<std::string, T>::empty(); +			return !getValueNames()->empty();  		} -		//override this to add name value pairs -		static void declareValues() {} -	 -		void initSingleton() +		static value_name_map_t* getValueNames()  		{ -			DERIVED_TYPE::declareValues(); -		} +			static value_name_map_t sMap; +			static bool sInitialized = false; -		static const std::vector<std::string>* getPossibleValues()  -		{  -			// in order to return a pointer to a member, we lazily -			// evaluate the result and store it in mValues here -			if (singleton_t::instance().mValues.empty()) +			if (!sInitialized)  			{ -				typename super_t::Registrar::registry_map_t::const_iterator it; -				for (it = super_t::defaultRegistrar().beginItems(); it != super_t::defaultRegistrar().endItems(); ++it) -				{ -					singleton_t::instance().mValues.push_back(it->first); -				} +				sInitialized = true; +				DERIVED_TYPE::declareValues();  			} -			return &singleton_t::instance().mValues;  +			return &sMap;  		} +		static std::vector<std::string>* getPossibleValues() +		{ +			static std::vector<std::string> sValues; + +			value_name_map_t* map = getValueNames(); +			for (value_name_map_t::iterator it = map->begin(), end_it = map->end(); +				 it != end_it; +				 ++it) +			{ +				sValues.push_back(it->first); +			} +			return &sValues; +		} -	protected:  		static void declare(const std::string& name, const T& value)  		{ -			super_t::defaultRegistrar().add(name, value); +			(*getValueNames())[name] = value;  		} -	private: -		std::vector<std::string> mValues; +	protected: +		static void getName(const std::string& name, const T& value) +		{} + +		mutable std::string	mValueName;  	};  	class Parser @@ -193,9 +186,9 @@ namespace LLInitParam  			}  		}; -		typedef std::vector<std::pair<std::string, S32> >			name_stack_t; +		typedef std::vector<std::pair<std::string, S32> >								name_stack_t;  		typedef std::pair<name_stack_t::const_iterator, name_stack_t::const_iterator>	name_stack_range_t; -		typedef std::vector<std::string>							possible_values_t; +		typedef std::vector<std::string>												possible_values_t;  		typedef bool (*parser_read_func_t)(Parser& parser, void* output);  		typedef bool (*parser_write_func_t)(Parser& parser, const void*, const name_stack_t&); @@ -207,7 +200,7 @@ namespace LLInitParam  		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)  		:	mParseSilently(false), -			mParseGeneration(0), +			mParseGeneration(sNextParseGeneration),  			mParserReadFuncs(&read_map),  			mParserWriteFuncs(&write_map),  			mParserInspectFuncs(&inspect_map) @@ -252,7 +245,7 @@ namespace LLInitParam  		void setParseSilently(bool silent) { mParseSilently = silent; }  		S32 getParseGeneration() { return mParseGeneration; } -		S32 newParseGeneration() { return ++mParseGeneration; } +		S32 newParseGeneration() { return mParseGeneration = ++sNextParseGeneration; }  	protected: @@ -276,6 +269,8 @@ namespace LLInitParam  		parser_write_func_map_t*	mParserWriteFuncs;  		parser_inspect_func_map_t*	mParserInspectFuncs;  		S32	mParseGeneration; + +		static S32					sNextParseGeneration;  	};  	// used to indicate no matching value to a given name when parsing @@ -295,12 +290,13 @@ namespace LLInitParam  		Param(class BaseBlock* enclosing_block);  		// store pointer to enclosing block as offset to reduce space and allow for quick copying -		BaseBlock& enclosingBlock() const +		class BaseBlock& enclosingBlock() const  		{   			const U8* my_addr = reinterpret_cast<const U8*>(this);  			// get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class -			return *const_cast<BaseBlock*>( -							reinterpret_cast<const BaseBlock*>(my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset)); +			return *const_cast<class BaseBlock*> +				(reinterpret_cast<const class BaseBlock*> +					(my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset));  		}  	private: @@ -313,7 +309,11 @@ namespace LLInitParam  	// various callbacks and constraints associated with an individual param  	struct ParamDescriptor  	{ -	public: +		struct UserData +		{ +			virtual ~UserData() {} +		}; +  		typedef bool(*merge_func_t)(Param&, const Param&, bool);  		typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, S32);  		typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param); @@ -321,40 +321,18 @@ namespace LLInitParam  		typedef bool(*validation_func_t)(const Param*);  		ParamDescriptor(param_handle_t p,  -				merge_func_t merge_func,  -				deserialize_func_t deserialize_func,  -				serialize_func_t serialize_func, -				validation_func_t validation_func, -				inspect_func_t inspect_func, -				S32 min_count, -				S32 max_count) -		:	mParamHandle(p), -			mMergeFunc(merge_func), -			mDeserializeFunc(deserialize_func), -			mSerializeFunc(serialize_func), -			mValidationFunc(validation_func), -			mInspectFunc(inspect_func), -			mMinCount(min_count), -			mMaxCount(max_count), -			mGeneration(0), -			mNumRefs(0) -		{} +						merge_func_t merge_func,  +						deserialize_func_t deserialize_func,  +						serialize_func_t serialize_func, +						validation_func_t validation_func, +						inspect_func_t inspect_func, +						S32 min_count, +						S32 max_count); -		ParamDescriptor() -		:	mParamHandle(0), -			mMergeFunc(NULL), -			mDeserializeFunc(NULL), -			mSerializeFunc(NULL), -			mValidationFunc(NULL), -			mInspectFunc(NULL), -			mMinCount(0), -			mMaxCount(0), -			mGeneration(0), -			mNumRefs(0) -		{} +		ParamDescriptor(); +		~ParamDescriptor();  		param_handle_t		mParamHandle; -	  		merge_func_t		mMergeFunc;  		deserialize_func_t	mDeserializeFunc;  		serialize_func_t	mSerializeFunc; @@ -364,17 +342,16 @@ namespace LLInitParam  		S32					mMaxCount;  		S32					mGeneration;  		S32					mNumRefs; +		UserData*			mUserData;  	}; +	typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr; +  	// each derived Block class keeps a static data structure maintaining offsets to various params  	class BlockDescriptor  	{  	public: -		BlockDescriptor() -		:	mMaxParamOffset(0), -			mInitializationState(UNINITIALIZED), -			mCurrentBlockPtr(NULL) -		{} +		BlockDescriptor();  		typedef enum e_initialization_state  		{ @@ -385,12 +362,10 @@ namespace LLInitParam  		void aggregateBlockData(BlockDescriptor& src_block_data); -	public: -		typedef boost::unordered_map<const std::string, ParamDescriptor*> param_map_t; // references param descriptors stored in mAllParams -		typedef std::vector<ParamDescriptor*> param_list_t;  - -		typedef std::list<ParamDescriptor> all_params_list_t;// references param descriptors stored in mAllParams -		typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> > param_validation_list_t; +		typedef boost::unordered_map<const std::string, ParamDescriptorPtr>						param_map_t;  +		typedef std::vector<ParamDescriptorPtr>													param_list_t;  +		typedef std::list<ParamDescriptorPtr>														all_params_list_t; +		typedef std::vector<std::pair<param_handle_t, ParamDescriptor::validation_func_t> >		param_validation_list_t;  		param_map_t						mNamedParams;			// parameters with associated names  		param_list_t					mUnnamedParams;			// parameters with_out_ associated names @@ -456,6 +431,7 @@ namespace LLInitParam  		Param* getParamFromHandle(const param_handle_t param_handle)  		{  			if (param_handle == 0) return NULL; +  			U8* baseblock_address = reinterpret_cast<U8*>(this);  			return reinterpret_cast<Param*>(baseblock_address + param_handle);  		} @@ -469,14 +445,13 @@ namespace LLInitParam  		void addSynonym(Param& param, const std::string& synonym);  		// Blocks can override this to do custom tracking of changes -		virtual void setLastChangedParam(const Param& last_param, bool user_provided); +		virtual void paramChanged(const Param& changed_param, bool user_provided);  		S32 getLastChangeVersion() const { return mChangeVersion; } -		bool isDefault() const { return mChangeVersion == 0; } -		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack); -		bool serializeBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const; -		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t()) const; +		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, S32 generation); +		void serializeBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const; +		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;  		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }  		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } @@ -493,7 +468,10 @@ namespace LLInitParam  			return false;  		} -		static void addParam(BlockDescriptor& block_data, const ParamDescriptor& param, const char* name); +		static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name); + +		ParamDescriptorPtr findParamDescriptor(const Param& param); +  	protected:  		void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size); @@ -512,63 +490,132 @@ namespace LLInitParam  	private:  		const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; -		ParamDescriptor* findParamDescriptor(param_handle_t handle); -	}; - - -	template<typename T> -	struct ParamIterator -	{ -		typedef typename std::vector<T>::const_iterator		const_iterator; -		typedef typename std::vector<T>::iterator			iterator;  	};  	// these templates allow us to distinguish between template parameters  	// that derive from BaseBlock and those that don't -	// this is supposedly faster than boost::is_convertible and its ilk  	template<typename T, typename Void = void> -	struct IsBaseBlock +	struct IsBlock  	{  		static const bool value = false;  	};  	template<typename T> -	struct IsBaseBlock<T, typename T::baseblock_base_class_t> +	struct IsBlock<T, typename T::baseblock_base_class_t>  	{  		static const bool value = true;  	}; +	template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value> +	class ParamValue : public NAME_VALUE_LOOKUP +	{ +	public: +		typedef const T&							value_assignment_t; + +		ParamValue(): mValue() {} +		ParamValue(const T& other) : mValue(other) {} + +		void setValue(value_assignment_t val) +		{ +			mValue = val; +		} + +		value_assignment_t getValue() const +		{ +			return mValue; +		} + +		T& getValue() +		{ +			return mValue; +		} + +	private: +		T mValue; +	}; + +	template<typename T, typename NAME_VALUE_LOOKUP> +	class ParamValue<T, NAME_VALUE_LOOKUP, true>  +	:	public T, +		public NAME_VALUE_LOOKUP +	{ +	public: +		typedef const T&							value_assignment_t; + +		S32 			mKeyVersion; +		mutable S32 	mValidatedVersion; +		mutable bool 	mValidated; // lazy validation flag + +		ParamValue()  +		:	T(), +			mKeyVersion(0), +			mValidatedVersion(-1), +			mValidated(false) +		{} + +		ParamValue(const T& other) +		:	T(other), +			mKeyVersion(0), +			mValidatedVersion(-1), +			mValidated(false) +		{ +		} + +		void setValue(value_assignment_t val) +		{ +			*this = val; +		} + +		value_assignment_t getValue() const +		{ +			return *this; +		} + +		T& getValue() +		{ +			return *this; +		} +	}; + +	template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > +	struct ParamIterator +	{ +		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator		const_iterator; +		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator			iterator; +	}; +  	// specialize for custom parsing/decomposition of specific classes  	// e.g. TypedParam<LLRect> has left, top, right, bottom, etc...  	template<typename	T,  			typename	NAME_VALUE_LOOKUP = TypeValues<T>,  			bool		HAS_MULTIPLE_VALUES = false, -			bool		VALUE_IS_BLOCK = IsBaseBlock<T>::value> +			bool		VALUE_IS_BLOCK = IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>  	class TypedParam  -	:	public Param +	:	public Param,  +		public ParamValue<T, NAME_VALUE_LOOKUP>  	{  	public: -		typedef const T&																	value_const_ref_t; -		typedef value_const_ref_t															value_assignment_t; -		typedef typename NAME_VALUE_LOOKUP::KeyCache										key_cache_t; +		typedef const T&																	value_assignment_t;  		typedef	TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK>		self_t; +		typedef NAME_VALUE_LOOKUP															name_value_lookup_t;  		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)   		:	Param(block_descriptor.mCurrentBlockPtr)  		{  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + 				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),  												&mergeWith,  												&deserializeParam,  												&serializeParam,  												validate_func,  												&inspectParam, -												min_count, max_count); +												min_count, max_count));  				BaseBlock::addParam(block_descriptor, param_descriptor, name);  			} -			mData.mValue = value; +			setValue(value);  		}   		bool isProvided() const { return Param::anyProvided(); } @@ -579,27 +626,27 @@ namespace LLInitParam  			// no further names in stack, attempt to parse value now  			if (name_stack.first == name_stack.second)  			{ -				if (parser.readValue(typed_param.mData.mValue)) +				if (parser.readValue(typed_param.getValue()))  				{ -					typed_param.mData.clearKey(); +					typed_param.clearValueName();  					typed_param.setProvided(true); -					typed_param.enclosingBlock().setLastChangedParam(param, true); +					typed_param.enclosingBlock().paramChanged(param, true);  					return true;  				}  				// try to parse a known named value -				if(!NAME_VALUE_LOOKUP::empty()) +				if(name_value_lookup_t::valueNamesExist())  				{  					// try to parse a known named value  					std::string name;  					if (parser.readValue(name))  					{  						// try to parse a per type named value -						if (NAME_VALUE_LOOKUP::get(name, typed_param.mData.mValue)) +						if (name_value_lookup_t::getValueFromName(name, typed_param.getValue()))  						{ -							typed_param.mData.setKey(name); +							typed_param.setValueName(name);  							typed_param.setProvided(true); -							typed_param.enclosingBlock().setLastChangedParam(param, true); +							typed_param.enclosingBlock().paramChanged(param, true);  							return true;  						} @@ -619,13 +666,13 @@ namespace LLInitParam  				name_stack.back().second = parser.newParseGeneration();  			} -			std::string key = typed_param.mData.getKey(); +			std::string key = typed_param.getValueName();  			// first try to write out name of name/value pair  			if (!key.empty())  			{ -				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->mData.getKey(), key)) +				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))  				{  					if (!parser.writeValue(key, name_stack))  					{ @@ -634,8 +681,9 @@ namespace LLInitParam  				}  			}  			// then try to serialize value directly -			else if (!diff_param || !ParamCompare<T>::equals(typed_param.get(), static_cast<const self_t*>(diff_param)->get()))					{ -				if (!parser.writeValue(typed_param.mData.mValue, name_stack))  +			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue())) +			{ +				if (!parser.writeValue(typed_param.getValue(), name_stack))   				{  					return;  				} @@ -647,18 +695,18 @@ namespace LLInitParam  			// tell parser about our actual type  			parser.inspectValue<T>(name_stack, min_count, max_count, NULL);  			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) -			if (NAME_VALUE_LOOKUP::getPossibleValues()) +			if (name_value_lookup_t::getPossibleValues())  			{ -				parser.inspectValue<std::string>(name_stack, min_count, max_count, NAME_VALUE_LOOKUP::getPossibleValues()); +				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues());  			}  		}  		void set(value_assignment_t val, bool flag_as_provided = true)  		{ -			mData.mValue = val; -			mData.clearKey(); +			setValue(val); +			clearValueName();  			setProvided(flag_as_provided); -			Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided); +			Param::enclosingBlock().paramChanged(*this, flag_as_provided);  		}  		void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) @@ -670,65 +718,55 @@ namespace LLInitParam  		}  		// implicit conversion -		operator value_assignment_t() const { return get(); }  +		operator value_assignment_t() const { return getValue(); }   		// explicit conversion -		value_assignment_t operator()() const { return get(); }  +		value_assignment_t operator()() const { return getValue(); }   	protected: -		value_assignment_t get() const -		{ -			return mData.mValue; -		}  		static bool mergeWith(Param& dst, const Param& src, bool overwrite)  		{  			const self_t& src_typed_param = static_cast<const self_t&>(src);  			self_t& dst_typed_param = static_cast<self_t&>(dst); +  			if (src_typed_param.isProvided()  				&& (overwrite || !dst_typed_param.isProvided()))  			{ -				dst_typed_param.mData.clearKey(); -				dst_typed_param.set(src_typed_param.get()); +				dst_typed_param.clearValueName(); +				dst_typed_param.set(src_typed_param.getValue());  				return true;  			}  			return false;  		} - -		struct Data : public key_cache_t -		{ -			T mValue; -		}; - -		Data		mData;  	};  	// parameter that is a block  	template <typename T, typename NAME_VALUE_LOOKUP>  	class TypedParam<T, NAME_VALUE_LOOKUP, false, true>  -	:	public T, -		public Param +	:	public Param, +		public ParamValue<T, NAME_VALUE_LOOKUP>  	{  	public:  		typedef const T											value_const_t;  		typedef T												value_t; -		typedef value_const_t&									value_const_ref_t; -		typedef value_const_ref_t								value_assignment_t; -		typedef typename NAME_VALUE_LOOKUP::KeyCache			key_cache_t; +		typedef value_const_t&									value_assignment_t;  		typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true>	self_t; +		typedef NAME_VALUE_LOOKUP								name_value_lookup_t;  		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  		:	Param(block_descriptor.mCurrentBlockPtr), -			T(value) +			ParamValue(value)  		{  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),  												&mergeWith,  												&deserializeParam,  												&serializeParam,  												validate_func,   												&inspectParam, -												min_count, max_count); +												min_count, max_count));  				BaseBlock::addParam(block_descriptor, param_descriptor, name);  			}  		} @@ -737,25 +775,27 @@ namespace LLInitParam  		{   			self_t& typed_param = static_cast<self_t&>(param);  			// attempt to parse block... -			if(typed_param.deserializeBlock(parser, name_stack)) +			if(typed_param.deserializeBlock(parser, name_stack, generation))  			{ -				typed_param.mData.clearKey(); -				typed_param.enclosingBlock().setLastChangedParam(param, true); +				typed_param.clearValueName(); +				typed_param.enclosingBlock().paramChanged(param, true); +				typed_param.setProvided(true);  				return true;  			} -			if(!NAME_VALUE_LOOKUP::empty()) +			if(name_value_lookup_t::valueNamesExist())  			{  				// try to parse a known named value  				std::string name;  				if (parser.readValue(name))  				{  					// try to parse a per type named value -					if (NAME_VALUE_LOOKUP::get(name, typed_param)) +					if (name_value_lookup_t::getValueFromName(name, typed_param.getValue()))  					{ -						typed_param.enclosingBlock().setLastChangedParam(param, true); -						typed_param.mData.setKey(name); -						typed_param.mData.mKeyVersion = typed_param.getLastChangeVersion(); +						typed_param.enclosingBlock().paramChanged(param, true); +						typed_param.setValueName(name); +						typed_param.setProvided(true); +						typed_param.mKeyVersion = typed_param.getLastChangeVersion();  						return true;  					} @@ -767,13 +807,15 @@ namespace LLInitParam  		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)  		{  			const self_t& typed_param = static_cast<const self_t&>(param); +			if (!typed_param.isProvided()) return; +  			if (!name_stack.empty())  			{  				name_stack.back().second = parser.newParseGeneration();  			} -			std::string key = typed_param.mData.getKey(); -			if (!key.empty() && typed_param.mData.mKeyVersion == typed_param.getLastChangeVersion()) +			std::string key = typed_param.getValueName(); +			if (!key.empty() && typed_param.mKeyVersion == typed_param.getLastChangeVersion())  			{  				if (!parser.writeValue(key, name_stack))  				{ @@ -790,33 +832,33 @@ namespace LLInitParam  		{  			// I am a param that is also a block, so just recurse into my contents  			const self_t& typed_param = static_cast<const self_t&>(param); -			typed_param.inspectBlock(parser, name_stack); +			typed_param.inspectBlock(parser, name_stack, min_count, max_count);  		}  		// a param-that-is-a-block is provided when the user has set one of its child params  		// *and* the block as a whole validates  		bool isProvided() const   		{  -			// only validate block when it hasn't already passed validation and user has supplied *some* value -			if (Param::anyProvided() && mData.mValidatedVersion < T::getLastChangeVersion()) +			// only validate block when it hasn't already passed validation with current data +			if (Param::anyProvided() && mValidatedVersion < getLastChangeVersion())  			{  				// a sub-block is "provided" when it has been filled in enough to be valid -				mData.mValidated = T::validateBlock(false); -				mData.mValidatedVersion = T::getLastChangeVersion(); +				mValidated = validateBlock(false); +				mValidatedVersion = getLastChangeVersion();  			} -			return Param::anyProvided() && mData.mValidated; +			return Param::anyProvided() && mValidated;  		}  		// assign block contents to this param-that-is-a-block  		void set(value_assignment_t val, bool flag_as_provided = true)  		{ -			value_t::operator=(val); -			mData.clearKey(); +			setValue(val); +			clearValueName();  			// force revalidation of block by clearing known provided version  			// next call to isProvided() will update provision status based on validity -			mData.mValidatedVersion = 0; +			mValidatedVersion = -1;  			setProvided(flag_as_provided); -			Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided); +			Param::enclosingBlock().paramChanged(*this, flag_as_provided);  		}  		void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) @@ -828,10 +870,10 @@ namespace LLInitParam  		}  		// propagate changed status up to enclosing block -		/*virtual*/ void setLastChangedParam(const Param& last_param, bool user_provided) +		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)  		{  -			T::setLastChangedParam(last_param, user_provided); -			Param::enclosingBlock().setLastChangedParam(*this, user_provided); +			ParamValue<T, NAME_VALUE_LOOKUP>::paramChanged(changed_param, user_provided); +			Param::enclosingBlock().paramChanged(*this, user_provided);  			if (user_provided)  			{  				// a child param has been explicitly changed @@ -841,41 +883,28 @@ namespace LLInitParam  		}  		// implicit conversion -		operator value_assignment_t() const { return get(); }  +		operator value_assignment_t() const { return getValue(); }   		// explicit conversion -		value_assignment_t operator()() const { return get(); }  +		value_assignment_t operator()() const { return getValue(); }   	protected: -		value_assignment_t get() const -		{ -			return *this; -		}  		static bool mergeWith(Param& dst, const Param& src, bool overwrite)  		{  			const self_t& src_typed_param = static_cast<const self_t&>(src);  			self_t& dst_typed_param = static_cast<self_t&>(dst); -			if (dst_typed_param.T::merge(T::selfBlockDescriptor(), src_typed_param, overwrite)) + +			if (src_typed_param.isProvided() +				&& (overwrite || !dst_typed_param.isProvided()))  			{ -				dst_typed_param.mData.clearKey(); -				return true; +				if (dst_typed_param.merge(selfBlockDescriptor(), src_typed_param, overwrite)) +				{ +					dst_typed_param.clearValueName(); +					return true; +				}  			}  			return false;  		} - -		struct Data : public key_cache_t -		{ -			S32 			mKeyVersion; -			mutable S32 	mValidatedVersion; -			mutable bool 	mValidated; // lazy validation flag - -			Data()  -			:	mKeyVersion(0), -				mValidatedVersion(0), -				mValidated(false) -			{} -		}; -		Data	mData;  	};  	// container of non-block parameters @@ -885,29 +914,27 @@ namespace LLInitParam  	{  	public:  		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>		self_t; -		typedef typename std::vector<VALUE_TYPE>							container_t; +		typedef typename std::vector<ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP> >	container_t;  		typedef const container_t&											value_assignment_t;  		typedef VALUE_TYPE													value_t; -		typedef value_t&													value_ref_t; -		typedef const value_t&												value_const_ref_t; +		typedef NAME_VALUE_LOOKUP											name_value_lookup_t; -		typedef typename NAME_VALUE_LOOKUP::KeyCache						key_cache_t; -  		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)   		:	Param(block_descriptor.mCurrentBlockPtr), -			mValues(value)  		{ -			mCachedKeys.resize(mValues.size()); +			std::copy(value.begin(), value.end(), std::back_inserter(mValues)); +  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),  												&mergeWith,  												&deserializeParam,  												&serializeParam,  												validate_func,  												&inspectParam, -												min_count, max_count); +												min_count, max_count));  				BaseBlock::addParam(block_descriptor, param_descriptor, name);  			}  		}  @@ -924,29 +951,22 @@ namespace LLInitParam  				// attempt to read value directly  				if (parser.readValue(value))  				{ -					typed_param.mValues.push_back(value); -					// save an empty name/value key as a placeholder -					typed_param.mCachedKeys.push_back(key_cache_t()); -					typed_param.enclosingBlock().setLastChangedParam(param, true); -					typed_param.setProvided(true); +					typed_param.add(value);  					return true;  				}  				// try to parse a known named value -				if(!NAME_VALUE_LOOKUP::empty()) +				if(name_value_lookup_t::valueNamesExist())  				{  					// try to parse a known named value  					std::string name;  					if (parser.readValue(name))  					{  						// try to parse a per type named value -						if (NAME_VALUE_LOOKUP::get(name, typed_param.mValues)) +						if (name_value_lookup_t::getValueFromName(name, typed_param.mValues))  						{ -							typed_param.mValues.push_back(value); -							typed_param.mCachedKeys.push_back(key_cache_t()); -							typed_param.mCachedKeys.back().setKey(name); -							typed_param.enclosingBlock().setLastChangedParam(param, true); -							typed_param.setProvided(true); +							typed_param.add(value); +							typed_param.mValues.back().setValueName(name);  							return true;  						} @@ -961,25 +981,27 @@ namespace LLInitParam  			const self_t& typed_param = static_cast<const self_t&>(param);  			if (!typed_param.isProvided() || name_stack.empty()) return; -			const_iterator it = typed_param.mValues.begin(); -			for (typename std::vector<key_cache_t>::const_iterator key_it = typed_param.mCachedKeys.begin(); -				it != typed_param.mValues.end(); -				++key_it, ++it) +			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); +				it != end_it; +				++it)  			{ -				std::string key = key_it->get(); +				std::string key = it->getValue();  				name_stack.back().second = parser.newParseGeneration(); -				if(!key.empty()) +				if(key.empty()) +				// not parsed via name values, write out value directly  				{ -					if(!parser.writeValue(key, name_stack)) +					if (!parser.writeValue(*it, name_stack))  					{ -						return; +						break;  					}  				} -				// not parse via name values, write out value directly -				else if (!parser.writeValue(*it, name_stack)) +				else   				{ -					return; +					if(!parser.writeValue(key, name_stack)) +					{ +						break; +					}  				}  			}  		} @@ -987,19 +1009,17 @@ namespace LLInitParam  		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)  		{  			parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL); -			if (NAME_VALUE_LOOKUP::getPossibleValues()) +			if (name_value_lookup_t::getPossibleValues())  			{ -				parser.inspectValue<std::string>(name_stack, min_count, max_count, NAME_VALUE_LOOKUP::getPossibleValues()); +				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues());  			}  		}  		void set(value_assignment_t val, bool flag_as_provided = true)  		{  			mValues = val; -			mCachedKeys.clear(); -			mCachedKeys.resize(mValues.size());  			setProvided(flag_as_provided); -			Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided); +			Param::enclosingBlock().paramChanged(*this, flag_as_provided);  		} @@ -1011,23 +1031,23 @@ namespace LLInitParam  			}  		} -		value_ref_t add() +		value_t& add()  		{ -			mValues.push_back(value_t()); -			mCachedKeys.push_back(key_cache_t()); +			mValues.push_back(ParamValue(value_t()));  			setProvided(true); +			Param::enclosingBlock().paramChanged(*this, true);  			return mValues.back();  		} -		void add(value_const_ref_t item) +		void add(const value_t& item)  		{ -			mValues.push_back(item); -			mCachedKeys.push_back(key_cache_t()); +			mValues.push_back(ParamValue(item));  			setProvided(true); +			Param::enclosingBlock().paramChanged(*this, true);  		}  		// implicit conversion -		operator value_assignment_t() const { return self_t::get(); }  +		operator value_assignment_t() const { return mValues; }   		typedef typename container_t::iterator iterator;  		typedef typename container_t::const_iterator const_iterator; @@ -1044,27 +1064,25 @@ namespace LLInitParam  		}  	protected: -		value_assignment_t get() const -		{ -			return mValues; -		} -  		static bool mergeWith(Param& dst, const Param& src, bool overwrite)  		{  			const self_t& src_typed_param = static_cast<const self_t&>(src);  			self_t& dst_typed_param = static_cast<self_t&>(dst); -			if (src_typed_param.isProvided() -				&& (overwrite || !dst_typed_param.isProvided())) +			if (overwrite)  			{ -				dst_typed_param.set(src_typed_param.get()); -				return true; +				std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));  			} -			return false; +			else +			{ +				container_t new_values(src_typed_param.mValues); +				std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values)); +				std::swap(dst_typed_param.mValues, new_values); +			} +			return true;  		}  		container_t		mValues; -		std::vector<key_cache_t>	mCachedKeys;  	};  	// container of block parameters @@ -1074,80 +1092,76 @@ namespace LLInitParam  	{  	public:  		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>	self_t; -		typedef typename std::vector<VALUE_TYPE>						container_t; +		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>				param_value_t; +		typedef typename std::vector<param_value_t>						container_t;  		typedef const container_t&										value_assignment_t; -  		typedef VALUE_TYPE												value_t; -		typedef value_t&												value_ref_t; -		typedef const value_t&											value_const_ref_t; - -		typedef typename NAME_VALUE_LOOKUP::KeyCache					key_cache_t; +		typedef NAME_VALUE_LOOKUP										name_value_lookup_t;  		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)   		:	Param(block_descriptor.mCurrentBlockPtr), -			mValues(value), -			mLastParamGeneration(0) +			mLastParseGeneration(0)  		{ -			mCachedKeys.resize(mValues.size()); +			std::copy(value.begin(), value.end(), back_inserter(mValues)); +  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),  												&mergeWith,  												&deserializeParam,  												&serializeParam,  												validate_func,  												&inspectParam, -												min_count, max_count); +												min_count, max_count));  				BaseBlock::addParam(block_descriptor, param_descriptor, name);  			}  		}   		bool isProvided() const { return Param::anyProvided(); } -		value_ref_t operator[](S32 index) { return mValues[index]; } -		value_const_ref_t operator[](S32 index) const { return mValues[index]; } -  		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)   		{   			self_t& typed_param = static_cast<self_t&>(param);  			bool new_value = false; -			if (generation != typed_param.mLastParamGeneration || typed_param.mValues.empty()) + +			if (generation != typed_param.mLastParseGeneration  +				|| typed_param.mValues.empty())  			{  				new_value = true;  				typed_param.mValues.push_back(value_t()); -				typed_param.mCachedKeys.push_back(Data());  			} -			value_ref_t value = typed_param.mValues.back(); +			param_value_t& value = typed_param.mValues.back();  			// attempt to parse block... -			if(value.deserializeBlock(parser, name_stack)) +			if(value.deserializeBlock(parser, name_stack, generation))  			{  				if (new_value)  				{	// successfully parsed new value, let's keep it -					typed_param.mLastParamGeneration = generation; +					typed_param.mLastParseGeneration = generation;  				} -				typed_param.enclosingBlock().setLastChangedParam(param, true); +				typed_param.enclosingBlock().paramChanged(param, true);  				typed_param.setProvided(true);  				return true;  			} -			else if(!NAME_VALUE_LOOKUP::empty()) +			else if(name_value_lookup_t::valueNamesExist())  			{  				// try to parse a known named value  				std::string name;  				if (parser.readValue(name))  				{  					// try to parse a per type named value -					if (NAME_VALUE_LOOKUP::get(name, value)) +					if (name_value_lookup_t::getValueFromName(name, value.getValue()))  					{  						if (new_value)  						{	// successfully parsed new value, let's keep it -							typed_param.mLastParamGeneration = generation; +							typed_param.mLastParseGeneration = generation;  						} -						typed_param.mCachedKeys.back().setKey(name); -						typed_param.mCachedKeys.back().mKeyVersion = value.getLastChangeVersion(); -						typed_param.enclosingBlock().setLastChangedParam(param, true); +						typed_param.mValues.back().setValueName(name); +						typed_param.mValues.back().mKeyVersion = value.getLastChangeVersion(); +						typed_param.enclosingBlock().paramChanged(param, true);  						typed_param.setProvided(true);  						return true;  					} @@ -1158,7 +1172,6 @@ namespace LLInitParam  			if (new_value)  			{	// failed to parse new value, pop it off  				typed_param.mValues.pop_back(); -				typed_param.mCachedKeys.pop_back();  			}  			return false; @@ -1169,26 +1182,22 @@ namespace LLInitParam  			const self_t& typed_param = static_cast<const self_t&>(param);  			if (!typed_param.isProvided() || name_stack.empty()) return; -			const_iterator it = typed_param.mValues.begin(); -			for (typename std::vector<Data>::const_iterator key_it = typed_param.mCachedKeys.begin(); -				it != typed_param.mValues.end(); -				++key_it, ++it) +			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); +				it != end_it; +				++it)  			{  				name_stack.back().second = parser.newParseGeneration(); -				std::string key = key_it->getKey(); -				if (!key.empty() && key_it->mKeyVersion == it->getLastChangeVersion()) +				std::string key = it->getValueName(); +				if (!key.empty() && it->mKeyVersion == it->getLastChangeVersion())  				{ -					if(!parser.writeValue(key, name_stack)) -					{ -						return; -					} +					parser.writeValue(key, name_stack);  				}  				// Not parsed via named values, write out value directly  				// NOTE: currently we don't worry about removing default values in Multiple -				else if (!it->serializeBlock(parser, name_stack, NULL)) +				else   				{ -					return; +					it->serializeBlock(parser, name_stack, NULL);  				}  			}  		} @@ -1196,16 +1205,14 @@ namespace LLInitParam  		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)  		{  			// I am a vector of blocks, so describe my contents recursively -			value_t().inspectBlock(parser, name_stack); +			param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count);  		}  		void set(value_assignment_t val, bool flag_as_provided = true)  		{  			mValues = val; -			mCachedKeys.clear(); -			mCachedKeys.resize(mValues.size());  			setProvided(flag_as_provided); -			Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided); +			Param::enclosingBlock().paramChanged(*this, flag_as_provided);  		}  		void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) @@ -1216,23 +1223,23 @@ namespace LLInitParam  			}  		} -		value_ref_t add() +		value_t& add()  		{  			mValues.push_back(value_t()); -			mCachedKeys.push_back(Data());  			setProvided(true); +			Param::enclosingBlock().paramChanged(*this, true);  			return mValues.back();  		} -		void add(value_const_ref_t item) +		void add(const value_t& item)  		{  			mValues.push_back(item); -			mCachedKeys.push_back(Data());  			setProvided(true); +			Param::enclosingBlock().paramChanged(*this, true);  		}  		// implicit conversion -		operator value_assignment_t() const { return self_t::get(); }  +		operator value_assignment_t() const { return mValues; }   		typedef typename container_t::iterator iterator;  		typedef typename container_t::const_iterator const_iterator; @@ -1246,8 +1253,8 @@ namespace LLInitParam  		U32 numValidElements() const  		{  			U32 count = 0; -			for (const_iterator it = mValues.begin(); -				it != mValues.end(); +			for (const_iterator it = mValues.begin(), end_it = mValues.end(); +				it != end_it;  				++it)  			{  				if(it->validateBlock(false)) count++; @@ -1256,43 +1263,35 @@ namespace LLInitParam  		}  	protected: -		value_assignment_t get() const -		{ -			return mValues; -		}  		static bool mergeWith(Param& dst, const Param& src, bool overwrite)  		{  			const self_t& src_typed_param = static_cast<const self_t&>(src);  			self_t& dst_typed_param = static_cast<self_t&>(dst); -			if (src_typed_param.isProvided() -				&& (overwrite || !dst_typed_param.isProvided())) +			if (overwrite)  			{ -				dst_typed_param.set(src_typed_param.get()); -				return true; +				std::copy(src_typed_param.begin(), src_typed_param.end(), std::back_inserter(dst_typed_param.mValues));  			} -			return false; +			else +			{ +				container_t new_values(src_typed_param.mValues); +				std::copy(dst_typed_param.begin(), dst_typed_param.end(), std::back_inserter(new_values)); +				std::swap(dst_typed_param.mValues, new_values); +			} +			return true;  		} -		struct Data : public key_cache_t -		{ -			S32 mKeyVersion;	// version of block for which key was last valid - -			Data() : mKeyVersion(0) {} -		}; -  		container_t			mValues; -		std::vector<Data>	mCachedKeys; -		S32			mLastParamGeneration; +		S32			mLastParseGeneration;  	};  	template <typename DERIVED_BLOCK>  	class Choice : public BaseBlock  	{ -		typedef Choice<DERIVED_BLOCK> self_t; -		typedef Choice<DERIVED_BLOCK> enclosing_block_t; +		typedef Choice<DERIVED_BLOCK>	self_t; +		typedef Choice<DERIVED_BLOCK>	enclosing_block_t;  		LOG_CLASS(self_t);  	public: @@ -1321,9 +1320,9 @@ namespace LLInitParam  		}  		// clear out old choice when param has changed -		/*virtual*/ void setLastChangedParam(const Param& last_param, bool user_provided) +		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)  		{  -			param_handle_t changed_param_handle = BaseBlock::getHandleFromParam(&last_param); +			param_handle_t changed_param_handle = BaseBlock::getHandleFromParam(&changed_param);  			// if we have a new choice...  			if (changed_param_handle != mCurChoice)  			{ @@ -1335,7 +1334,7 @@ namespace LLInitParam  				}  				mCurChoice = changed_param_handle;  			} -			BaseBlock::setLastChangedParam(last_param, user_provided); +			BaseBlock::paramChanged(changed_param, user_provided);  		}  		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } @@ -1358,20 +1357,21 @@ namespace LLInitParam  			friend class Choice<DERIVED_BLOCK>;  			typedef Alternative<T, NAME_VALUE_LOOKUP>									self_t; -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value>		super_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;  			typedef typename super_t::value_assignment_t								value_assignment_t; -			explicit Alternative(const char* name, value_assignment_t val = DefaultInitializer<T>::get()) +			explicit Alternative(const char* name, value_assignment_t val = defaultValue<T>())  			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1),  				mOriginalValue(val)  			{  				// assign initial choice to first declared option  				DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr); -				if (LL_UNLIKELY( -						DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING -							&& blockp->mCurChoice == 0)) +				if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING))  				{ -					blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this); +					if(blockp->mCurChoice == 0) +					{ +						blockp->mCurChoice = Param::enclosingBlock().getHandleFromParam(this); +					}  				}  			} @@ -1390,7 +1390,7 @@ namespace LLInitParam  			{   				if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)  				{ -					return super_t::get();  +					return super_t::getValue();   				}  				return mOriginalValue;  			}  @@ -1399,7 +1399,7 @@ namespace LLInitParam  			{   				if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)  				{ -					return super_t::get();  +					return super_t::getValue();   				}  				return mOriginalValue;  			}  @@ -1433,8 +1433,8 @@ namespace LLInitParam  	class Block   	:	public BASE_BLOCK  	{ -		typedef Block<DERIVED_BLOCK, BASE_BLOCK> self_t; -		typedef Block<DERIVED_BLOCK, BASE_BLOCK> block_t; +		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	self_t; +		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	block_t;  	public:  		typedef BASE_BLOCK base_block_t; @@ -1442,13 +1442,13 @@ namespace LLInitParam  		// take all provided params from other and apply to self  		bool overwriteFrom(const self_t& other)  		{ -			return BaseBlock::merge(selfBlockDescriptor(), other, true); +			return static_cast<DERIVED_BLOCK*>(this)->merge(selfBlockDescriptor(), other, true);  		}  		// take all provided params that are not already provided, and apply to self  		bool fillFrom(const self_t& other)  		{ -			return BaseBlock::merge(selfBlockDescriptor(), other, false); +			return static_cast<DERIVED_BLOCK*>(this)->merge(selfBlockDescriptor(), other, false);  		}  		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } @@ -1468,10 +1468,10 @@ namespace LLInitParam  		class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>  		{  		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value>		super_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;  			typedef typename super_t::value_assignment_t								value_assignment_t; -			explicit Optional(const char* name = "", value_assignment_t val = DefaultInitializer<T>::get()) +			explicit Optional(const char* name = "", value_assignment_t val = defaultValue<T>())  			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1)  			{  				//#pragma message("Parsing LLInitParam::Block::Optional") @@ -1483,7 +1483,7 @@ namespace LLInitParam  				return *this;  			} -			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) +			DERIVED_BLOCK& operator()(value_assignment_t val)  			{  				super_t::set(val);  				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1495,12 +1495,12 @@ namespace LLInitParam  		class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>  		{  		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBaseBlock<T>::value>		super_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t;  			typedef Mandatory<T, NAME_VALUE_LOOKUP>										self_t;  			typedef typename super_t::value_assignment_t								value_assignment_t;  			// mandatory parameters require a name to be parseable -			explicit Mandatory(const char* name = "", value_assignment_t val = DefaultInitializer<T>::get()) +			explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue<T>())  			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1)  			{} @@ -1529,15 +1529,15 @@ namespace LLInitParam  		class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>  		{  		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBaseBlock<T>::value>	super_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>	super_t;  			typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP>							self_t;  			typedef typename super_t::container_t									container_t;  			typedef typename super_t::value_assignment_t							value_assignment_t;  			typedef typename super_t::iterator										iterator;  			typedef typename super_t::const_iterator								const_iterator; -			explicit Multiple(const char* name = "", value_assignment_t val = DefaultInitializer<container_t>::get()) -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, RANGE::minCount(), RANGE::maxCount()) +			explicit Multiple(const char* name = "") +			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount(), RANGE::maxCount())  			{}  			Multiple& operator=(value_assignment_t val) @@ -1545,7 +1545,7 @@ namespace LLInitParam  				set(val);  				return *this;  			} -			 +  			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val)  			{  				super_t::set(val); @@ -1559,6 +1559,95 @@ namespace LLInitParam  			}  		}; +		template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		class Batch : private TypedParam<T, NAME_VALUE_LOOKUP, false> +		{ +		public: +			typedef ParamValue<T, NAME_VALUE_LOOKUP>										param_value_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<param_value_t>::value>	super_t; +			typedef Batch<T, RANGE, NAME_VALUE_LOOKUP>										self_t; +			typedef typename super_t::value_assignment_t									value_assignment_t; + +			struct BatchDefaultValue : public ParamDescriptor::UserData +			{ +				BatchDefaultValue(const T& value) +				:	mValue(value) +				{} + +				T mValue; +			}; + +			explicit Batch(const char* name, value_assignment_t val) +			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1), +				mLastParseGeneration(-1) +			{ +				BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); +				if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) +				{ +					ParamDescriptorPtr param_descriptorp = block_descriptor.mCurrentBlockPtr->findParamDescriptor(*this); + +					if (param_descriptorp) +					{ +						param_descriptorp->mDeserializeFunc = &deserializeParam; +						param_descriptorp->mUserData = new BatchDefaultValue(new _value_t(val)); +					} +				} +			} + +			explicit Batch(const char* name = "") +			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, defaultValue<T>(), NULL, 0, 1), +				mLastParseGeneration(-1) +			{ +				BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); +				if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) +				{ +					ParamDescriptorPtr param_descriptorp = block_descriptor.mCurrentBlockPtr->findParamDescriptor(*this); + +					if (param_descriptorp) +					{ +						param_descriptorp->mDeserializeFunc = &deserializeParam; +					} +				} +			} + +			Batch& operator=(value_assignment_t val) +			{ +				set(val); +				return *this; +			} + +			DERIVED_BLOCK& operator()(value_assignment_t val) +			{ +				super_t::set(val); +				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); +			} + +			using super_t::operator(); + +		private: +			static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)  +			{ +				self_t& typed_param = static_cast<self_t&>(param); + +				if (generation != typed_param.mLastParseGeneration) +				{ +					ParamDescriptorPtr descriptor = typed_param.enclosingBlock().findParamDescriptor(param); +					if (descriptor && static_cast<BatchDefaultValue*>(descriptor->mUserData)) +					{ +						static_cast<param_value_t&>(typed_param) = (static_cast<BatchDefaultValue*>(descriptor->mUserData))->mValue; +					} +					else +					{ +						static_cast<param_value_t&>(typed_param) = param_value_t(value_t()); +					} +					typed_param.mLastParseGeneration = generation; +				} +				return super_t::deserializeParam(param, parser, name_stack, generation); +			} + +			S32 mLastParseGeneration; +		}; +  		class Deprecated : public Param  		{  		public: @@ -1568,13 +1657,14 @@ namespace LLInitParam  				BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor();  				if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  				{ -					ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +					ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +													block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),  													NULL,  													&deserializeParam,  													NULL,  													NULL,  													NULL,  -													0, S32_MAX); +													0, S32_MAX));  					BaseBlock::addParam(block_descriptor, param_descriptor, name);  				}  			} @@ -1602,137 +1692,91 @@ namespace LLInitParam  		}  	}; -	template<typename T, typename DERIVED = TypedParam<T> > -	class BlockValue -	:	public Block<TypedParam<T, TypeValues<T>, false> >, -		public Param +	template<typename T> +	class CustomParamValue +	:	public Block<ParamValue<T, TypeValues<T> > >, +		public TypeValues<T>  	{  	public:  		typedef enum e_value_age  		{	 -			OLDER_THAN_BLOCK,	// mData.mValue needs to be refreshed from the block parameters -			NEWER_THAN_BLOCK,	// mData.mValue holds the authoritative value (which has been replicated to the block parameters via setBlockFromValue) -			SAME_AS_BLOCK		// mData.mValue is derived from the block parameters, which are authoritative +			VALUE_NEEDS_UPDATE,		// mValue needs to be refreshed from the block parameters +			VALUE_AUTHORITATIVE,	// mValue holds the authoritative value (which has been replicated to the block parameters via updateBlockFromValue) +			BLOCK_AUTHORITATIVE		// mValue is derived from the block parameters, which are authoritative  		} EValueAge; -		typedef BlockValue<T>										self_t; -		typedef Block<TypedParam<T, TypeValues<T>, false> >			block_t; -		typedef const T&											value_const_ref_t; -		typedef value_const_ref_t									value_assignment_t; -		typedef typename TypeValues<T>::KeyCache					key_cache_t; +		typedef ParamValue<T, TypeValues<T> >	derived_t; +		typedef CustomParamValue<T>				self_t; +		typedef Block<typename derived_t>		block_t; +		typedef const T&						value_assignment_t; -		BlockValue(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) -		:	Param(block_descriptor.mCurrentBlockPtr), -			mData(value, NEWER_THAN_BLOCK) -		{ -			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) -			{ -				ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func, -												&inspectParam, -												min_count, max_count); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); -			} -		} - -		// implicit conversion -		operator value_assignment_t() const { return get(); }  -		// explicit conversion -		value_assignment_t operator()() const { return get(); }  +		CustomParamValue(const T& value = T()) +		:	mValue(value), +			mValueAge(VALUE_AUTHORITATIVE), +			mKeyVersion(0), +			mValidatedVersion(-1) +		{} -		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation) +		bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack, S32 generation)  		{ -			DERIVED& typed_param = static_cast<DERIVED&>(param); +			derived_t& typed_param = static_cast<derived_t&>(*this);  			// type to apply parse direct value T  			if (name_stack.first == name_stack.second)  			{ -				if(parser.readValue(typed_param.mData.mValue)) +				if(parser.readValue(typed_param.mValue))  				{ -					typed_param.enclosingBlock().setLastChangedParam(param, true); -					typed_param.setProvided(true); -					typed_param.mData.clearKey(); -					typed_param.mData.mValueAge = NEWER_THAN_BLOCK; -					typed_param.setBlockFromValue(); +					typed_param.clearValueName(); +					typed_param.mValueAge = VALUE_AUTHORITATIVE; +					typed_param.updateBlockFromValue();  					return true;  				} - -				if(!TypeValues<T>::empty()) -				{ -					// try to parse a known named value -					std::string name; -					if (parser.readValue(name)) -					{ -						// try to parse a per type named value -						if (TypeValues<T>::get(name, typed_param.mData.mValue)) -						{ -							typed_param.mData.setKey(name); -							typed_param.enclosingBlock().setLastChangedParam(param, true); -							typed_param.setProvided(true); -							typed_param.mData.mValueAge = NEWER_THAN_BLOCK; -							typed_param.setBlockFromValue(); - -							return true; -						} -					} -				}  			}  			// fall back on parsing block components for T  			// if we deserialized at least one component... -			if (typed_param.BaseBlock::deserializeBlock(parser, name_stack)) +			if (typed_param.BaseBlock::deserializeBlock(parser, name_stack, generation))  			{ -				// ...our block is provided, and considered changed -				typed_param.enclosingBlock().setLastChangedParam(param, true); -				typed_param.setProvided(true);  				return true;  			} +  			return false;  		} -		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) +		void serializeBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), const BaseBlock* diff_block = NULL) const  		{ -			const self_t& typed_param = static_cast<const self_t&>(param); +			const self_t& typed_param = static_cast<const self_t&>(*this); +			const self_t* diff_param = static_cast<const self_t*>(diff_block); -			if (!typed_param.isProvided()) return; -			 -			std::string key = typed_param.mData.getKey(); +			std::string key = typed_param.getValueName();  			// first try to write out name of name/value pair  			if (!key.empty())  			{ -				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->mData.getKey(), key)) +				if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key))  				{ -					if (!parser.writeValue(key, name_stack)) -					{ -						return; -					} +					parser.writeValue(key, name_stack);  				}  			}  			// then try to serialize value directly -			else if (!diff_param || !ParamCompare<T>::equals(typed_param.get(), (static_cast<const self_t*>(diff_param))->get()))	 +			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))              { -				if (parser.writeValue(typed_param.mData.mValue, name_stack))  +				if (!parser.writeValue(typed_param.getValue(), name_stack))   				{ -					return; +					//RN: *always* serialize provided components of BlockValue (don't pass diff_param on), +					// since these tend to be viewed as the constructor arguments for the value T.  It seems +					// cleaner to treat the uniqueness of a BlockValue according to the generated value, and +					// not the individual components.  This way <color red="0" green="1" blue="0"/> will not +					// be exported as <color green="1"/>, since it was probably the intent of the user to  +					// be specific about the RGB color values.  This also fixes an issue where we distinguish +					// between rect.left not being provided and rect.left being explicitly set to 0 (same as default) +					block_t::serializeBlock(parser, name_stack, NULL);  				} - -				//RN: *always* serialize provided components of BlockValue (don't pass diff_param on), -				// since these tend to be viewed as the constructor arguments for the value T.  It seems -				// cleaner to treat the uniqueness of a BlockValue according to the generated value, and -				// not the individual components.  This way <color red="0" green="1" blue="0"/> will not -				// be exported as <color green="1"/>, since it was probably the intent of the user to  -				// be specific about the RGB color values.  This also fixes an issue where we distinguish -				// between rect.left not being provided and rect.left being explicitly set to 0 (same as default) -				typed_param.BaseBlock::serializeBlock(parser, name_stack, NULL);  			}  		} -		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) +		bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const  		{  			// first, inspect with actual type...  			parser.inspectValue<T>(name_stack, min_count, max_count, NULL); @@ -1742,25 +1786,19 @@ namespace LLInitParam  				parser.inspectValue<std::string>(name_stack, min_count, max_count, TypeValues<T>::getPossibleValues());  			}  			// then recursively inspect contents... -			const self_t& typed_param = static_cast<const self_t&>(param); -			typed_param.inspectBlock(parser, name_stack); +			return block_t::inspectBlock(parser, name_stack, min_count, max_count);  		} - -		bool isProvided() const  +		bool validateBlock(bool emit_errors = true) const  		{ -			if (!Param::anyProvided()) return false; - -			// block has an updated parameter -			// if cached value is stale, regenerate from params -			if (mData.mValueAge == OLDER_THAN_BLOCK) +			if (mValueAge == VALUE_NEEDS_UPDATE)  			{ -				if (block_t::validateBlock(false)) +				if (block_t::validateBlock(emit_errors))  				{ -					static_cast<const DERIVED*>(this)->setValueFromBlock();  					// clear stale keyword associated with old value -					mData.clearKey(); -					mData.mValueAge = SAME_AS_BLOCK; +					clearValueName(); +					mValueAge = BLOCK_AUTHORITATIVE; +					static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock();  					return true;  				}  				else @@ -1777,104 +1815,74 @@ namespace LLInitParam  			}  		} -		void set(value_assignment_t val, bool flag_as_provided = true) -		{ -			Param::enclosingBlock().setLastChangedParam(*this, flag_as_provided); -			 -			// set param version number to be up to date, so we ignore block contents -			mData.mValueAge = NEWER_THAN_BLOCK; - -			mData.mValue = val; -			mData.clearKey(); -			setProvided(flag_as_provided); -			static_cast<DERIVED*>(this)->setBlockFromValue(); -		} - -		void setIfNotProvided(value_assignment_t val, bool flag_as_provided = true) -		{ -			// don't override any user provided value -			if (!isProvided()) -			{ -				set(val, flag_as_provided); -			} -		} -   		// propagate change status up to enclosing block -		/*virtual*/ void setLastChangedParam(const Param& last_param, bool user_provided) +		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)  		{  -			BaseBlock::setLastChangedParam(last_param, user_provided); -			Param::enclosingBlock().setLastChangedParam(*this, user_provided); +			BaseBlock::paramChanged(changed_param, user_provided);  			if (user_provided) -			{ -				setProvided(true);  // some component provided +		{  				// a parameter changed, so our value is out of date -				mData.mValueAge = OLDER_THAN_BLOCK; +				mValueAge = VALUE_NEEDS_UPDATE;  			}  		} - -	protected: -		value_assignment_t get() const +			 +		void setValue(value_assignment_t val)  		{ -			// if some parameters were provided, issue warnings on invalid blocks -			if (Param::anyProvided() && (mData.mValueAge == OLDER_THAN_BLOCK)) -			{ -				// go ahead and issue warnings at this point if any param is invalid -				if(block_t::validateBlock(true)) -				{ -					static_cast<const DERIVED*>(this)->setValueFromBlock(); -					mData.clearKey(); -					mData.mValueAge = SAME_AS_BLOCK; -				} -			} - -			return mData.mValue; +			// set param version number to be up to date, so we ignore block contents +			mValueAge = VALUE_AUTHORITATIVE; +			mValue = val; +			clearValueName(); +			static_cast<derived_t*>(const_cast<self_t*>(this))->updateBlockFromValue();  		} +		value_assignment_t getValue() const +		{ +			validateBlock(true); +			return mValue; +		} -		struct Data : public key_cache_t +		T& getValue()   		{ -			Data(const T& value, EValueAge age)  -			:	mValue(value), -				mValueAge(age) -			{} +			validateBlock(true); +			return mValue; +		} -			T			mValue; -			EValueAge	mValueAge; -		}; +		S32 				mKeyVersion; -		// mutable to allow lazy updates on get -		mutable Data		mData; +	protected: -	private: -		static bool mergeWith(Param& dst, const Param& src, bool overwrite) +		// use this from within updateValueFromBlock() to set the value without making it authoritative +		void updateValue(value_assignment_t value)  		{ -			const DERIVED& src_typed_param = static_cast<const DERIVED&>(src); -			DERIVED& dst_typed_param = static_cast<DERIVED&>(dst); +			mValue = value; +		} -			if (src_typed_param.isProvided() -				&& (overwrite || !dst_typed_param.isProvided())) +		bool merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) +		{ +			const derived_t& src_typed_param = static_cast<const derived_t&>(other); + +			if (src_typed_param.mValueAge == VALUE_AUTHORITATIVE)  			{ -				if (src_typed_param.mData.mValueAge == NEWER_THAN_BLOCK) -				{ -					// copy value over -					dst_typed_param.set(src_typed_param.get()); -				} -				else -				{ -					// merge individual parameters into destination -					dst_typed_param.merge(block_t::selfBlockDescriptor(), src_typed_param, overwrite); -				} +				// copy value over +				setValue(src_typed_param.getValue());  				return true;  			} -			return false; +			else +			{ +				// merge individual parameters into destination +				return block_t::merge(block_t::selfBlockDescriptor(), src_typed_param, overwrite); +			}  		} -	}; -	template<>  -	struct ParamCompare<LLSD, false> -	{ -		static bool equals(const LLSD &a, const LLSD &b); +		mutable S32			mValidatedVersion; +		mutable bool 		mValidated; // lazy validation flag + +	private: + +		mutable T			mValue; +		mutable EValueAge	mValueAge;  	};  } +  #endif // LL_LLPARAM_H diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index bb1fb41fae..19dba3f917 100644 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -35,7 +35,7 @@  // system includes  #include <boost/tokenizer.hpp> -#define THROTTLE_PERIOD    20    // required secs between throttled commands +#define THROTTLE_PERIOD    5    // required seconds between throttled commands  static LLCommandDispatcherListener sCommandDispatcherListener; @@ -134,7 +134,7 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,  			if (cur_time < last_throttle_time + THROTTLE_PERIOD)  			{  				// block request from external browser if it happened -				// within THROTTLE_PERIOD secs of the last command +				// within THROTTLE_PERIOD seconds of the last command  				LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL;  				if (! slurl_throttled)  				{ diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 5444c7dc6e..1a9d0af9af 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -344,7 +344,7 @@ void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType t  	if ( APT_PROPERTIES == type )  	{  		const LLAvatarData* pAvatarData = static_cast<const LLAvatarData*>( pData ); -		if( pAvatarData && gAgent.getID() == pAvatarData->avatar_id ) +		if (pAvatarData && (gAgent.getID() == pAvatarData->avatar_id) && (pAvatarData->avatar_id != LLUUID::null))  		{  			storeAvatarProperties( pAvatarData );  			processProfileProperties( pAvatarData ); @@ -354,9 +354,9 @@ void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType t  void LLFloaterPreference::storeAvatarProperties( const LLAvatarData* pAvatarData )  { -	if (gAgent.isInitialized() && (gAgent.getID() != LLUUID::null)) +	if (LLStartUp::getStartupState() == STATE_STARTED)  	{ -		mAvatarProperties.avatar_id		= gAgent.getID(); +		mAvatarProperties.avatar_id		= pAvatarData->avatar_id;  		mAvatarProperties.image_id		= pAvatarData->image_id;  		mAvatarProperties.fl_image_id   = pAvatarData->fl_image_id;  		mAvatarProperties.about_text	= pAvatarData->about_text; @@ -376,19 +376,32 @@ void LLFloaterPreference::processProfileProperties(const LLAvatarData* pAvatarDa  void LLFloaterPreference::saveAvatarProperties( void )  { -	mAvatarProperties.allow_publish = getChild<LLUICtrl>("online_searchresults")->getValue(); -	if (mAvatarProperties.allow_publish) +	const BOOL allowPublish = getChild<LLUICtrl>("online_searchresults")->getValue(); + +	if (allowPublish)  	{  		mAvatarProperties.flags |= AVATAR_ALLOW_PUBLISH;  	} -	if (mAvatarDataInitialized) +	// +	// NOTE: We really don't want to send the avatar properties unless we absolutely +	//       need to so we can avoid the accidental profile reset bug, so, if we're +	//       logged in, the avatar data has been initialized and we have a state change +	//       for the "allow publish" flag, then set the flag to its new value and send +	//       the properties update. +	// +	// NOTE: The only reason we can not remove this update altogether is because of the +	//       "allow publish" flag, the last remaining profile setting in the viewer +	//       that doesn't exist in the web profile. +	// +	if ((LLStartUp::getStartupState() == STATE_STARTED) && mAvatarDataInitialized && (allowPublish != mAvatarProperties.allow_publish))  	{ +		mAvatarProperties.allow_publish = allowPublish; +  		LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate( &mAvatarProperties );  	}  } -  BOOL LLFloaterPreference::postBuild()  {  	gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2)); @@ -1364,6 +1377,8 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im  		mOriginalHideOnlineStatus = true;  	} +	getChild<LLUICtrl>("online_searchresults")->setEnabled(TRUE); +  	getChildView("include_im_in_chat_history")->setEnabled(TRUE);  	getChildView("show_timestamps_check_im")->setEnabled(TRUE);  	getChildView("friends_online_notify_checkbox")->setEnabled(TRUE); @@ -1743,7 +1758,6 @@ void LLPanelPreferenceGraphics::draw()  		bool enable = hasDirtyChilds();  		button_apply->setEnabled(enable); -  	}  }  bool LLPanelPreferenceGraphics::hasDirtyChilds() diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index a6404058b0..e020296842 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1317,7 +1317,8 @@ void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data)  		std::string url = (const char*)data;  		LLMediaCtrl* web = NULL;  		const bool trusted_browser = false; -		if (LLURLDispatcher::dispatch(url, "clicked", web, trusted_browser)) +		// don't treat slapps coming from external browsers as "clicks" as this would bypass throttling +		if (LLURLDispatcher::dispatch(url, "", web, trusted_browser))  		{  			// bring window to foreground, as it has just been "launched" from a URL  			mWindow->bringToFront(); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 75aec21f93..48fa01f0d9 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -763,4 +763,21 @@      <color       name="MenuBarProjectBgColor"       reference="MdBlue" /> +   +    <!-- Generic color names (legacy) --> +  <color +    name="white" +    value="1 1 1 1"/> +  <color +    name="black" +    value="0 0 0 1"/> +  <color +    name="red" +    value="1 0 0 1"/> +  <color +    name="green" +    value="0 1 0 1"/> +  <color +    name="blue" +    value="0 0 1 1"/>  </colors> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index cd25a2a8dd..3fb3717e68 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -7022,27 +7022,28 @@ Hiding the Speak button will disable the voice feature.    </notification>    <notification -  name="HintDisplayName" -  label="Display Name" -  type="hint" -  unique="true"> -    Set your customizable display name here. This is in addition to your unique username, which can't be changed. You can change how you see other people's names in your preferences. -  </notification> - -  <notification    name="HintMoveClick" -  label="Move" +  label=""    type="hint"    unique="true"> -Click to Walk +1. Click to Walk  Click anywhere on the ground to walk to that spot. -Click and Drag to Rotate View +2. Click and Drag to Rotate View  Click and drag anywhere on the world to rotate your view      <tag>custom_skin</tag>    </notification>    <notification +  name="HintDisplayName" +  label="Display Name" +  type="hint" +  unique="true"> +    Set your customizable display name here. This is in addition to your unique username, which can't be changed. You can change how you see other people's names in your preferences. +  </notification> + + +  <notification    name="HintView"    label="View"    type="hint" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index ef25588ca3..6954a8b53a 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -42,7 +42,7 @@      </text>      <check_box  	 height="16" -     enabled="true" +     enabled="false"       label="Show me in Search results"       layout="topleft"       left="30" diff --git a/indra/newview/skins/default/xui/en/widgets/loading_indicator.xml b/indra/newview/skins/default/xui/en/widgets/loading_indicator.xml index 6040d24128..ea1d89c975 100644 --- a/indra/newview/skins/default/xui/en/widgets/loading_indicator.xml +++ b/indra/newview/skins/default/xui/en/widgets/loading_indicator.xml @@ -3,6 +3,20 @@      follows="left|top"      mouse_opaque="false"      name="loading_indicator" -    rotations_per_sec="1.0" -    tab_stop="false" -/> +    images_per_sec="1.0" +    tab_stop="false"> +  <images> +    <image name="Progress_1"/> +    <image name="Progress_2"/> +    <image name="Progress_3"/> +    <image name="Progress_4"/> +    <image name="Progress_5"/> +    <image name="Progress_6"/> +    <image name="Progress_7"/> +    <image name="Progress_8"/> +    <image name="Progress_9"/> +    <image name="Progress_10"/> +    <image name="Progress_11"/> +    <image name="Progress_12"/> +  </images> +</loading_indicator>
\ No newline at end of file | 
