diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp
index 7b29d92ea050eeb9523861dc515332eeb86c5185..8a0f875808ead68946ce8d110046aee2874290eb 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 4e4a224ef6e70a450332953bdc7420cf1137c0e0..c0cb1cc74a9df96fc06566a07648e17c6e6cad24 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 @@ class LLLoadingIndicator
 
 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 87669574c2543860de653344ef14484115fcb17e..8020ca802bd2df162653bc2acd89318fd088c58a 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 50cb9e663200f91c5b50ed2fc8f559c273c3b236..6a43477693b0f54b488ec8e0b1c0af75f4308faa 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -398,10 +398,10 @@ class LLUICachedControl : public LLCachedControl<T>
 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 1ffad4806e3bf5913c83d526998bc11d56f3fa55..f37947a50b6774a7f12b36d3acd124e04d38eda5 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 38107c112d71edfcccf3e0f6d2386938dd32082a..139d88e0ac65f51c11237a1a127c989998a278ea 100644
--- a/indra/llui/lluiimage.h
+++ b/indra/llui/lluiimage.h
@@ -92,22 +92,23 @@ class LLUIImage : public LLRefCount
 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 ac2412c928bd59b11b89cac0df1407b0d6ed036b..ce80183842382333dfdd362ec8e56571ebd12214 100644
--- a/indra/llui/tests/llurlentry_stub.cpp
+++ b/indra/llui/tests/llurlentry_stub.cpp
@@ -114,29 +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 ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue()
 	{}
 
 	void TypeValues<LLUIColor>::declareValues()
@@ -147,14 +148,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 +167,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 8f0a48018fb26132f0ca1b5257a1110850dce4d3..2f814f4200cad8bcc9b5a53b017656579a77668f 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 fdaab00f18bfc9787fecf42c4de5d76e1c2c137a..439d60b43dfd309ddbbcb4fb8cbe77ff2f3076bc 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,20 +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 ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue()
 	{}
 
 	void TypeValues<LLUIColor>::declareValues()
@@ -108,14 +122,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 +142,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 fcdbaa430973d93b62eda9283ee7f99f835c4246..3c4eb70a5d985836d336ecc8d05184c4c84f2ab1 100644
--- a/indra/llxuixml/llinitparam.cpp
+++ b/indra/llxuixml/llinitparam.cpp
@@ -43,9 +43,52 @@ namespace LLInitParam
 		mEnclosingBlockOffset = (U16)(my_addr - block_addr);
 	}
 
+	//
+	// 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(&param);
+			block_data.mUnnamedParams.push_back(param);
 		}
 		else
 		{
 			// don't use insert, since we want to overwrite existing entries
-			block_data.mNamedParams[name] = &param;
+			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(&param);
 		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 1f9045754a9c8b32d698ff6dd6a57f33edbb5575..39ba32e537b74c3a92c10d68cf7af12a24e7941e 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/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 75aec21f93b6c50732591715620b8d8e2bef8a97..48fa01f0d9aa62eb4f818f1553fe57924ce984cc 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/widgets/loading_indicator.xml b/indra/newview/skins/default/xui/en/widgets/loading_indicator.xml
index 6040d2412851b2ee21fd593dd4fcfc4afa024983..ea1d89c975c4eaed5802c8b93e46c75285193fb0 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