From d7dd10b88bc3fda88f6528ecc5936e4889f019f3 Mon Sep 17 00:00:00 2001
From: Rider Linden <rider@lindenlab.com>
Date: Thu, 30 Nov 2017 11:32:22 -0800
Subject: [PATCH] Split for viewer/simhost sync LLSD with simhost.

---
 indra/llcommon/llsd.cpp                       |  26 +-
 indra/llcommon/llsd.h                         |   5 +-
 indra/llcommon/llsdutil.cpp                   | 275 ++++++++++++
 indra/llcommon/llsdutil.h                     |  30 ++
 indra/llinventory/CMakeLists.txt              |   8 +
 .../llsettingsbase.cpp                        | 118 ++---
 .../{newview => llinventory}/llsettingsbase.h |  18 +-
 .../llsettingsdaycycle.cpp                    | 272 +++++-------
 .../llsettingsdaycycle.h                      |  29 +-
 .../llsettingssky.cpp                         | 280 ++++--------
 .../{newview => llinventory}/llsettingssky.h  |  22 +-
 .../llsettingswater.cpp                       | 179 ++------
 .../llsettingswater.h                         |  24 +-
 indra/newview/CMakeLists.txt                  |  10 +-
 indra/newview/llenvironment.cpp               |  22 +-
 indra/newview/llenvironment.h                 |   3 +
 indra/newview/llsettingsvo.cpp                | 420 ++++++++++++++++++
 indra/newview/llsettingsvo.h                  | 103 +++++
 18 files changed, 1178 insertions(+), 666 deletions(-)
 rename indra/{newview => llinventory}/llsettingsbase.cpp (86%)
 rename indra/{newview => llinventory}/llsettingsbase.h (96%)
 rename indra/{newview => llinventory}/llsettingsdaycycle.cpp (69%)
 rename indra/{newview => llinventory}/llsettingsdaycycle.h (83%)
 rename indra/{newview => llinventory}/llsettingssky.cpp (76%)
 rename indra/{newview => llinventory}/llsettingssky.h (96%)
 rename indra/{newview => llinventory}/llsettingswater.cpp (58%)
 rename indra/{newview => llinventory}/llsettingswater.h (92%)
 create mode 100644 indra/newview/llsettingsvo.cpp
 create mode 100644 indra/newview/llsettingsvo.h

diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 57aa7d9c07c..57b746889d8 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -132,6 +132,7 @@ class LLSD::Impl
 	
 	virtual bool has(const String&) const		{ return false; }
 	virtual LLSD get(const String&) const		{ return LLSD(); }
+	virtual LLSD getKeys() const				{ return LLSD::emptyArray(); }
 	virtual void erase(const String&)			{ }
 	virtual const LLSD& ref(const String&) const{ return undef(); }
 	
@@ -380,7 +381,8 @@ namespace
 		using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer)
 		using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer)
 		virtual LLSD get(const LLSD::String&) const; 
-		void insert(const LLSD::String& k, const LLSD& v);
+		virtual LLSD getKeys() const; 
+		        void insert(const LLSD::String& k, const LLSD& v);
 		virtual void erase(const LLSD::String&);
 		              LLSD& ref(const LLSD::String&);
 		virtual const LLSD& ref(const LLSD::String&) const;
@@ -421,7 +423,19 @@ namespace
 		DataMap::const_iterator i = mData.find(k);
 		return (i != mData.end()) ? i->second : LLSD();
 	}
-	
+
+	LLSD ImplMap::getKeys() const
+	{ 
+		LLSD keys = LLSD::emptyArray();
+		DataMap::const_iterator iter = mData.begin();
+		while (iter != mData.end())
+		{
+			keys.append((*iter).first);
+			iter++;
+		}
+		return keys;
+	}
+
 	void ImplMap::insert(const LLSD::String& k, const LLSD& v)
 	{
 		mData.insert(DataMap::value_type(k, v));
@@ -502,7 +516,7 @@ namespace
 		virtual LLSD get(LLSD::Integer) const;
 		        void set(LLSD::Integer, const LLSD&);
 		        void insert(LLSD::Integer, const LLSD&);
-		        void append(const LLSD&);
+		        LLSD& append(const LLSD&);
 		virtual void erase(LLSD::Integer);
 		              LLSD& ref(LLSD::Integer);
 		virtual const LLSD& ref(LLSD::Integer) const; 
@@ -570,9 +584,10 @@ namespace
 		mData.insert(mData.begin() + index, v);
 	}
 	
-	void ImplArray::append(const LLSD& v)
+	LLSD& ImplArray::append(const LLSD& v)
 	{
 		mData.push_back(v);
+		return mData.back();
 	}
 	
 	void ImplArray::erase(LLSD::Integer i)
@@ -862,6 +877,7 @@ LLSD LLSD::emptyMap()
 
 bool LLSD::has(const String& k) const	{ return safe(impl).has(k); }
 LLSD LLSD::get(const String& k) const	{ return safe(impl).get(k); } 
+LLSD LLSD::getKeys() const				{ return safe(impl).getKeys(); } 
 void LLSD::insert(const String& k, const LLSD& v) {	makeMap(impl).insert(k, v); }
 
 LLSD& LLSD::with(const String& k, const LLSD& v)
@@ -895,7 +911,7 @@ LLSD& LLSD::with(Integer i, const LLSD& v)
 											makeArray(impl).insert(i, v); 
 											return *this;
 										}
-void LLSD::append(const LLSD& v)		{ makeArray(impl).append(v); }
+LLSD& LLSD::append(const LLSD& v)		{ return makeArray(impl).append(v); }
 void LLSD::erase(Integer i)				{ makeArray(impl).erase(i); }
 
 LLSD&		LLSD::operator[](Integer i)
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index 7b9b1285f59..5b6d5545af1 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -79,7 +79,7 @@
 	an LLSD array).
 	
 	An array is a sequence of zero or more LLSD values.
-	
+
 	Thread Safety
 
 	In general, these LLSD classes offer *less* safety than STL container
@@ -284,6 +284,7 @@ class LL_COMMON_API LLSD
 		
 		bool has(const String&) const;
 		LLSD get(const String&) const;
+		LLSD getKeys() const;				// Return an LLSD array with keys as strings
 		void insert(const String&, const LLSD&);
 		void erase(const String&);
 		LLSD& with(const String&, const LLSD&);
@@ -301,7 +302,7 @@ class LL_COMMON_API LLSD
 		LLSD get(Integer) const;
 		void set(Integer, const LLSD&);
 		void insert(Integer, const LLSD&);
-		void append(const LLSD&);
+		LLSD& append(const LLSD&);
 		void erase(Integer);
 		LLSD& with(Integer, const LLSD&);
 		
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 6ad4a971494..0171f2880e9 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -314,6 +314,180 @@ BOOL compare_llsd_with_template(
 	return TRUE;
 }
 
+// filter_llsd_with_template() is a direct clone (copy-n-paste) of 
+// compare_llsd_with_template with the following differences:
+// (1) bool vs BOOL return types
+// (2) A map with the key value "*" is a special value and maps any key in the
+//     test llsd that doesn't have an explicitly matching key in the template.
+// (3) The element of an array with exactly one element is taken as a template
+//     for *all* the elements of the test array.  If the template array is of
+//     different size, compare_llsd_with_template() semantics apply.
+bool filter_llsd_with_template(
+	const LLSD & llsd_to_test,
+	const LLSD & template_llsd,
+	LLSD & resultant_llsd)
+{
+	if (llsd_to_test.isUndefined() && template_llsd.isDefined())
+	{
+		resultant_llsd = template_llsd;
+		return true;
+	}
+	else if (llsd_to_test.type() != template_llsd.type())
+	{
+		resultant_llsd = LLSD();
+		return false;
+	}
+
+	if (llsd_to_test.isArray())
+	{
+		//they are both arrays
+		//we loop over all the items in the template
+		//verifying that the to_test has a subset (in the same order)
+		//any shortcoming in the testing_llsd are just taken
+		//to be the rest of the template
+		LLSD data;
+		LLSD::array_const_iterator test_iter;
+		LLSD::array_const_iterator template_iter;
+
+		resultant_llsd = LLSD::emptyArray();
+		test_iter = llsd_to_test.beginArray();
+
+		if (1 == template_llsd.size())
+		{
+			// If the template has a single item, treat it as
+			// the template for *all* items in the test LLSD.
+			template_iter = template_llsd.beginArray();
+
+			for (; test_iter != llsd_to_test.endArray(); ++test_iter)
+			{
+				if (! filter_llsd_with_template(*test_iter, *template_iter, data))
+				{
+					resultant_llsd = LLSD();
+					return false;
+				}
+				else
+				{
+					resultant_llsd.append(data);
+				}
+			}
+		}
+		else
+		{
+			// Traditional compare_llsd_with_template matching
+			
+			for (template_iter = template_llsd.beginArray();
+				 template_iter != template_llsd.endArray() &&
+					 test_iter != llsd_to_test.endArray();
+				 ++template_iter, ++test_iter)
+			{
+				if (! filter_llsd_with_template(*test_iter, *template_iter, data))
+				{
+					resultant_llsd = LLSD();
+					return false;
+				}
+				else
+				{
+					resultant_llsd.append(data);
+				}
+			}
+
+			//so either the test or the template ended
+			//we do another loop now to the end of the template
+			//grabbing the default values
+			for (;
+				 template_iter != template_llsd.endArray();
+				 ++template_iter)
+			{
+				resultant_llsd.append(*template_iter);
+			}
+		}
+	}
+	else if (llsd_to_test.isMap())
+	{
+		resultant_llsd = LLSD::emptyMap();
+		
+		//now we loop over the keys of the two maps
+		//any excess is taken from the template
+		//excess is ignored in the test
+
+		// Special tag for wildcarded LLSD map key templates
+		const LLSD::String wildcard_tag("*");
+
+		const bool template_has_wildcard = template_llsd.has(wildcard_tag);
+		LLSD wildcard_value;
+		LLSD value;
+
+		const LLSD::map_const_iterator template_iter_end(template_llsd.endMap());
+		for (LLSD::map_const_iterator template_iter(template_llsd.beginMap());
+			 template_iter_end != template_iter;
+			 ++template_iter)
+		{
+			if (wildcard_tag == template_iter->first)
+			{
+				wildcard_value = template_iter->second;
+			}
+			else if (llsd_to_test.has(template_iter->first))
+			{
+				//the test LLSD has the same key
+				if (! filter_llsd_with_template(llsd_to_test[template_iter->first],
+												template_iter->second,
+												value))
+				{
+					resultant_llsd = LLSD();
+					return false;
+				}
+				else
+				{
+					resultant_llsd[template_iter->first] = value;
+				}
+			}
+			else if (! template_has_wildcard)
+			{
+				// test llsd doesn't have it...take the
+				// template as default value
+				resultant_llsd[template_iter->first] = template_iter->second;
+			}
+		}
+		if (template_has_wildcard)
+		{
+			LLSD sub_value;
+			LLSD::map_const_iterator test_iter;
+			
+			for (test_iter = llsd_to_test.beginMap();
+				 test_iter != llsd_to_test.endMap();
+				 ++test_iter)
+			{
+				if (resultant_llsd.has(test_iter->first))
+				{
+					// Final value has test key, assume more specific
+					// template matched and we shouldn't modify it again.
+					continue;
+				}
+				else if (! filter_llsd_with_template(test_iter->second,
+													 wildcard_value,
+													 sub_value))
+				{
+					// Test value doesn't match wildcarded template
+					resultant_llsd = LLSD();
+					return false;
+				}
+				else
+				{
+					// Test value matches template, add the actuals.
+					resultant_llsd[test_iter->first] = sub_value;
+				}
+			}
+		}
+	}
+	else
+	{
+		//of same type...take the test llsd's value
+		resultant_llsd = llsd_to_test;
+	}
+
+	return true;
+}
+
 /*****************************************************************************
 *   Helpers for llsd_matches()
 *****************************************************************************/
@@ -673,3 +847,104 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits)
         return false;               // pacify the compiler
     }
 }
+
+// Construct a deep partial clone of of an LLSD object. primitive types share 
+// references, however maps, arrays and binary objects are duplicated. An optional
+// filter may be include to exclude/include keys in a map. 
+LLSD llsd_clone(LLSD value, LLSD filter)
+{
+    LLSD clone;
+    bool has_filter(filter.isMap());
+
+    switch (value.type())
+    {
+    case LLSD::TypeMap:
+        clone = LLSD::emptyMap();
+        for (LLSD::map_const_iterator itm = value.beginMap(); itm != value.endMap(); ++itm)
+        {
+            if (has_filter)
+            {
+                if (filter.has((*itm).first))
+                {
+                    if (!filter[(*itm).first].asBoolean())
+                        continue;
+                }
+                else if (filter.has("*"))
+                {
+                    if (!filter["*"].asBoolean())
+                        continue;
+                }
+                else
+                {
+                    continue;
+                }
+            }
+            clone[(*itm).first] = llsd_clone((*itm).second, filter);
+        }
+        break;
+    case LLSD::TypeArray:
+        clone = LLSD::emptyArray();
+        for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+        {
+            clone.append(llsd_clone(*ita, filter));
+        }
+        break;
+
+    case LLSD::TypeBinary:
+    {
+        LLSD::Binary bin(value.asBinary().begin(), value.asBinary().end());
+        clone = LLSD::Binary(bin);
+        break;
+    }
+    default:
+        clone = value;
+    }
+
+    return clone;
+}
+
+LLSD llsd_shallow(LLSD value, LLSD filter)
+{
+    LLSD shallow;
+    bool has_filter(filter.isMap());
+
+    if (value.isMap())
+    {
+        shallow = LLSD::emptyMap();
+        for (LLSD::map_const_iterator itm = value.beginMap(); itm != value.endMap(); ++itm)
+        {
+            if (has_filter)
+            {
+                if (filter.has((*itm).first))
+                {
+                    if (!filter[(*itm).first].asBoolean())
+                        continue;
+                }
+                else if (filter.has("*"))
+                {
+                    if (!filter["*"].asBoolean())
+                        continue;
+                }
+                else
+                {
+                    continue;
+                }
+            }
+            shallow[(*itm).first] = (*itm).second;
+        }
+    }
+    else if (value.isArray())
+    {
+        shallow = LLSD::emptyArray();
+        for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+        {
+            shallow.append(*ita);
+        }
+    }
+    else
+    {
+        return value;
+    }
+
+    return shallow;
+}
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index c100454e15c..33befef85b8 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -69,6 +69,19 @@ LL_COMMON_API BOOL compare_llsd_with_template(
 	const LLSD& template_llsd,
 	LLSD& resultant_llsd);
 
+// filter_llsd_with_template() is a direct clone (copy-n-paste) of 
+// compare_llsd_with_template with the following differences:
+// (1) bool vs BOOL return types
+// (2) A map with the key value "*" is a special value and maps any key in the
+//     test llsd that doesn't have an explicitly matching key in the template.
+// (3) The element of an array with exactly one element is taken as a template
+//     for *all* the elements of the test array.  If the template array is of
+//     different size, compare_llsd_with_template() semantics apply.
+bool filter_llsd_with_template(
+	const LLSD & llsd_to_test,
+	const LLSD & template_llsd,
+	LLSD & resultant_llsd);
+
 /**
  * Recursively determine whether a given LLSD data block "matches" another
  * LLSD prototype. The returned string is empty() on success, non-empty() on
@@ -421,6 +434,23 @@ class inMap
 } // namespace llsd
 
 
+// Creates a deep clone of an LLSD object.  Maps, Arrays and binary objects 
+// are duplicated, atomic primitives (Boolean, Integer, Real, etc) simply
+// use a shared reference. 
+// Optionally a filter may be specified to control what is duplicated. The 
+// map takes the form "keyname/boolean".
+// If the value is true the value will be duplicated otherwise it will be skipped 
+// when encountered in a map. A key name of "*" can be specified as a wild card
+// and will specify the default behavior.  If no wild card is given and the clone
+// encounters a name not in the filter, that value will be skipped.
+LLSD llsd_clone(LLSD value, LLSD filter = LLSD());
+
+// Creates a shallow copy of a map or array.  If passed any other type of LLSD 
+// object it simply returns that value.  See llsd_clone for a description of 
+// the filter parameter.
+LLSD llsd_shallow(LLSD value, LLSD filter = LLSD());
+
+
 // Specialization for generating a hash value from an LLSD block. 
 template <>
 struct boost::hash<LLSD>
diff --git a/indra/llinventory/CMakeLists.txt b/indra/llinventory/CMakeLists.txt
index 68dd00d8806..3eba746614a 100644
--- a/indra/llinventory/CMakeLists.txt
+++ b/indra/llinventory/CMakeLists.txt
@@ -29,6 +29,10 @@ set(llinventory_SOURCE_FILES
     llparcel.cpp
     llpermissions.cpp
     llsaleinfo.cpp
+    llsettingsbase.cpp
+    llsettingsdaycycle.cpp
+    llsettingssky.cpp
+    llsettingswater.cpp
     lltransactionflags.cpp
     lluserrelations.cpp
     )
@@ -49,6 +53,10 @@ set(llinventory_HEADER_FILES
     llpermissions.h
     llpermissionsflags.h
     llsaleinfo.h
+    llsettingsbase.h
+    llsettingsdaycycle.h
+    llsettingssky.h
+    llsettingswater.h
     lltransactionflags.h
     lltransactiontypes.h
     lluserrelations.h
diff --git a/indra/newview/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp
similarity index 86%
rename from indra/newview/llsettingsbase.cpp
rename to indra/llinventory/llsettingsbase.cpp
index e36c6d4a84d..e4291d80803 100644
--- a/indra/newview/llsettingsbase.cpp
+++ b/indra/llinventory/llsettingsbase.cpp
@@ -25,7 +25,6 @@
 * $/LicenseInfo$
 */
 
-#include "llviewerprecompiledheaders.h"
 #include "llsettingsbase.h"
 
 #include "llmath.h"
@@ -42,21 +41,21 @@ namespace
 //=========================================================================
 const std::string LLSettingsBase::SETTING_ID("id");
 const std::string LLSettingsBase::SETTING_NAME("name");
+const std::string LLSettingsBase::SETTING_HASH("hash");
+const std::string LLSettingsBase::SETTING_TYPE("type");
 
 const F32Seconds LLSettingsBlender::DEFAULT_THRESHOLD(0.01);
 
 //=========================================================================
 LLSettingsBase::LLSettingsBase():
     mSettings(LLSD::emptyMap()),
-    mDirty(true),
-    mHashValue(0)
+    mDirty(true)
 {
 }
 
 LLSettingsBase::LLSettingsBase(const LLSD setting) :
     mSettings(setting),
-    mDirty(true),
-    mHashValue(0)
+    mDirty(true)
 {
 }
 
@@ -245,85 +244,27 @@ LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, F
     return newSettings;
 }
 
-LLSD LLSettingsBase::cloneSettings() const
+LLSD LLSettingsBase::getSettings() const
 {
-    return combineSDMaps(mSettings, LLSD());
+    return mSettings;
 }
 
-void LLSettingsBase::exportSettings(std::string name) const
+LLSD LLSettingsBase::cloneSettings() const
 {
-    LLSD exprt = LLSDMap("type", LLSD::String(getSettingType()))
-        ("name", LLSD::String(name))
-        ("settings", mSettings);
-
-    std::string path_name = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, name + ".settings");
+    return combineSDMaps(mSettings, LLSD());
+}
 
-    // write to file
-    llofstream presetsXML(path_name.c_str());
-    if (presetsXML.is_open())
-    {
-        LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
-        formatter->format(exprt, presetsXML, LLSDFormatter::OPTIONS_PRETTY);
-        presetsXML.close();
+size_t LLSettingsBase::getHash() const
+{   // get a shallow copy of the LLSD filtering out values to not include in the hash
+    LLSD hash_settings = llsd_shallow(getSettings(), 
+        LLSDMap(SETTING_NAME, false)(SETTING_ID, false)(SETTING_HASH, false)("*", true));
 
-        LL_DEBUGS() << "saved preset '" << name << "'; " << mSettings.size() << " settings" << LL_ENDL;
-    }
-    else
-    {
-        LL_WARNS("Presets") << "Cannot open for output preset file " << path_name << LL_ENDL;
-    }
+    return boost::hash<LLSD>{}(hash_settings);
 }
 
 #ifdef VALIDATION_DEBUG
 namespace
 {
-    LLSD clone_llsd(LLSD value)
-    {
-        LLSD clone;
-
-        switch (value.type())
-        {
-//         case LLSD::TypeMap:
-//             newSettings[key_name] = combineSDMaps(value, LLSD());
-//             break;
-        case LLSD::TypeArray:
-            clone = LLSD::emptyArray();
-            for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
-            {
-                clone.append( clone_llsd(*ita) );
-            }
-            break;
-        case LLSD::TypeInteger:
-            clone = LLSD::Integer(value.asInteger());
-            break;
-        case LLSD::TypeReal:
-            clone = LLSD::Real(value.asReal());
-            break;
-        case LLSD::TypeBoolean:
-            clone = LLSD::Boolean(value.asBoolean());
-            break;
-        case LLSD::TypeString:
-            clone = LLSD::String(value.asString());
-            break;
-        case LLSD::TypeUUID:
-            clone = LLSD::UUID(value.asUUID());
-            break;
-        case LLSD::TypeURI:
-            clone = LLSD::URI(value.asURI());
-            break;
-        case LLSD::TypeDate:
-            clone = LLSD::Date(value.asDate());
-            break;
-        //case LLSD::TypeBinary:
-        //    break;
-        //default:
-        //    newSettings[key_name] = value;
-        //    break;
-        }
-
-        return clone;
-    }
-
     bool compare_llsd(LLSD valA, LLSD valB)
     {
         if (valA.type() != valB.type())
@@ -376,14 +317,21 @@ bool LLSettingsBase::validate()
 {
     static Validator  validateName(SETTING_NAME, false, LLSD::TypeString);
     static Validator  validateId(SETTING_ID, false, LLSD::TypeUUID);
+    static Validator  validateHash(SETTING_HASH, false, LLSD::TypeInteger);
+    static Validator  validateType(SETTING_TYPE, false, LLSD::TypeString);
     validation_list_t validations = getValidationList();
     stringset_t       validated;
     stringset_t       strip;
 
+    if (!mSettings.has(SETTING_TYPE))
+    {
+        mSettings[SETTING_TYPE] = getSettingType();
+    }
+
     // Fields common to all settings.
     if (!validateName.verify(mSettings))
     {
-        LL_WARNS("SETTINGS") << "Unable to validate name." << LL_ENDL;
+        LL_WARNS("SETTINGS") << "Unable to validate Name." << LL_ENDL;
         mIsValid = false;
         return false;
     }
@@ -397,6 +345,22 @@ bool LLSettingsBase::validate()
     }
     validated.insert(validateId.getName());
 
+    if (!validateHash.verify(mSettings))
+    {
+        LL_WARNS("SETTINGS") << "Unable to validate Hash." << LL_ENDL;
+        mIsValid = false;
+        return false;
+    }
+    validated.insert(validateHash.getName());
+
+    if (!validateType.verify(mSettings))
+    {
+        LL_WARNS("SETTINGS") << "Unable to validate Type." << LL_ENDL;
+        mIsValid = false;
+        return false;
+    }
+    validated.insert(validateType.getName());
+
     // Fields for specific settings.
     for (validation_list_t::iterator itv = validations.begin(); itv != validations.end(); ++itv)
     {
@@ -404,13 +368,13 @@ bool LLSettingsBase::validate()
         LLSD oldvalue;
         if (mSettings.has((*itv).getName()))
         {
-            oldvalue = clone_llsd(mSettings[(*itv).getName()]);
+            oldvalue = llsd_clone(mSettings[(*itv).getName()]);
         }
 #endif
 
         if (!(*itv).verify(mSettings))
         {
-            LL_WARNS("SETTINGS") << "Settings LLSD fails validation and could not be corrected!" << LL_ENDL;
+            LL_WARNS("SETTINGS") << "Settings LLSD fails validation and could not be corrected for '" << (*itv).getName() << "'!" << LL_ENDL;
             mIsValid = false;
             return false;
         }
@@ -448,7 +412,7 @@ bool LLSettingsBase::validate()
 //=========================================================================
 bool LLSettingsBase::Validator::verify(LLSD &data)
 {
-    if (!data.has(mName))
+    if (!data.has(mName) || (data.has(mName) && data[mName].isUndefined()))
     {
         if (mRequired)
             LL_WARNS("SETTINGS") << "Missing required setting '" << mName << "'" << LL_ENDL;
diff --git a/indra/newview/llsettingsbase.h b/indra/llinventory/llsettingsbase.h
similarity index 96%
rename from indra/newview/llsettingsbase.h
rename to indra/llinventory/llsettingsbase.h
index d304b8702ae..2b59a103ad0 100644
--- a/indra/newview/llsettingsbase.h
+++ b/indra/llinventory/llsettingsbase.h
@@ -32,6 +32,7 @@
 #include <map>
 #include <vector>
 #include <boost/enable_shared_from_this.hpp>
+#include <boost/signals2.hpp>
 
 #include "llsd.h"
 #include "llsdutil.h"
@@ -40,6 +41,7 @@
 #include "v4math.h"
 #include "llquaternion.h"
 #include "v4color.h"
+#include "v3color.h"
 
 class LLSettingsBase : 
     public boost::enable_shared_from_this<LLSettingsBase>,
@@ -51,6 +53,8 @@ class LLSettingsBase :
 public:
     static const std::string SETTING_ID;
     static const std::string SETTING_NAME;
+    static const std::string SETTING_HASH;
+    static const std::string SETTING_TYPE;
 
     typedef std::map<std::string, S32>  parammapping_t;
 
@@ -67,10 +71,7 @@ class LLSettingsBase :
     inline bool isDirty() const { return mDirty; }
     inline void setDirtyFlag(bool dirty) { mDirty = dirty; }
 
-    inline size_t getHash() const
-    {
-        return boost::hash<LLSD>{}(mSettings);
-    }
+    size_t getHash() const; // Hash will not include Name, ID or a previously stored Hash
 
     inline LLUUID getId() const
     {
@@ -93,10 +94,7 @@ class LLSettingsBase :
         setDirtyFlag(true);
     }
 
-    inline LLSD getSettings() const
-    {
-        return mSettings;
-    }
+    virtual LLSD getSettings() const;
 
     //---------------------------------------------------------------------
     // 
@@ -153,9 +151,6 @@ class LLSettingsBase :
         (const_cast<LLSettingsBase *>(this))->updateSettings();
     }
 
-    // TODO: This is temporary 
-    virtual void exportSettings(std::string name) const;
-
     virtual void blend(const ptr_t &end, F32 blendf) = 0;
 
     virtual bool validate();
@@ -232,7 +227,6 @@ class LLSettingsBase :
 
 private:
     bool    mDirty;
-    size_t  mHashValue;
 
     LLSD    combineSDMaps(const LLSD &first, const LLSD &other) const;
 
diff --git a/indra/newview/llsettingsdaycycle.cpp b/indra/llinventory/llsettingsdaycycle.cpp
similarity index 69%
rename from indra/newview/llsettingsdaycycle.cpp
rename to indra/llinventory/llsettingsdaycycle.cpp
index a579f991824..687210e127d 100644
--- a/indra/newview/llsettingsdaycycle.cpp
+++ b/indra/llinventory/llsettingsdaycycle.cpp
@@ -25,8 +25,6 @@
 * $/LicenseInfo$
 */
 
-#include "llviewerprecompiledheaders.h"
-#include "llviewercontrol.h"
 #include "llsettingsdaycycle.h"
 #include <algorithm>
 #include <boost/make_shared.hpp>
@@ -34,21 +32,10 @@
 #include "llfasttimer.h"
 #include "v3colorutil.h"
 
-#include "llglslshader.h"
-#include "llviewershadermgr.h"
-
-#include "llenvironment.h"
-
-#include "llagent.h"
-#include "pipeline.h"
-
 #include "llsettingssky.h"
 #include "llsettingswater.h"
 
-#include "llenvironment.h"
-
-#include "llworld.h"
-
+#include "llframetimer.h"
 //=========================================================================
 namespace
 {
@@ -113,7 +100,9 @@ const std::string LLSettingsDay::SETTING_DAYLENGTH("day_length");
 const std::string LLSettingsDay::SETTING_KEYID("key_id");
 const std::string LLSettingsDay::SETTING_KEYNAME("key_name");
 const std::string LLSettingsDay::SETTING_KEYKFRAME("key_keyframe");
+const std::string LLSettingsDay::SETTING_KEYHASH("key_hash");
 const std::string LLSettingsDay::SETTING_TRACKS("tracks");
+const std::string LLSettingsDay::SETTING_FRAMES("frames");
 
 const S64 LLSettingsDay::MINIMUM_DAYLENGTH(  300); // 5 mins
 
@@ -127,120 +116,91 @@ const S32 LLSettingsDay::FRAME_MAX(56);
 //=========================================================================
 LLSettingsDay::LLSettingsDay(const LLSD &data) :
     LLSettingsBase(data),
-    mHasParsed(false)
+    mInitialized(false)
 {
     mDayTracks.resize(TRACK_MAX);
 }
 
 LLSettingsDay::LLSettingsDay() :
     LLSettingsBase(),
-    mHasParsed(false)
+    mInitialized(false)
 {
     mDayTracks.resize(TRACK_MAX);
 }
 
 //=========================================================================
-LLSD LLSettingsDay::defaults()
+LLSD LLSettingsDay::getSettings() const
 {
-    LLSD dfltsetting;
+    LLSD settings(LLSD::emptyMap());
 
-    dfltsetting[SETTING_NAME] = "_default_";
-    dfltsetting[SETTING_DAYLENGTH] = static_cast<S32>(MINIMUM_DAYLENGTH);
-    dfltsetting[SETTING_TRACKS] = LLSDArray(
-        LLSDArray(LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))(SETTING_KEYNAME, "_default_"))
-        (LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))(SETTING_KEYNAME, "_default_")));
+    if (mSettings.has(SETTING_NAME))
+        settings[SETTING_NAME] = mSettings[SETTING_NAME];
 
-    return dfltsetting;
-}
-
-LLSettingsDay::ptr_t LLSettingsDay::buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings)
-{
-    LLSD newsettings(defaults());
-
-    newsettings[SETTING_NAME] = name;
-    newsettings[SETTING_DAYLENGTH] = static_cast<S32>(MINIMUM_DAYLENGTH);
-
-    LLSD watertrack = LLSDArray( 
-        LLSDMap ( SETTING_KEYKFRAME, LLSD::Real(0.0f) )
-                ( SETTING_KEYNAME, "Default" ));
+    if (mSettings.has(SETTING_ID))
+        settings[SETTING_ID] = mSettings[SETTING_ID];
 
-    LLSD skytrack = LLSD::emptyArray();
+    std::map<std::string, LLSettingsBase::ptr_t> in_use;
 
-    for (LLSD::array_const_iterator it = oldsettings.beginArray(); it != oldsettings.endArray(); ++it)
+    LLSD tracks(LLSD::emptyArray());
+    
+    for (CycleList_t::const_iterator itTrack = mDayTracks.begin(); itTrack != mDayTracks.end(); ++itTrack)
     {
-        LLSD entry = LLSDMap(SETTING_KEYKFRAME, (*it)[0].asReal())
-            (SETTING_KEYNAME, (*it)[1].asString());
-        skytrack.append(entry);
-    }
-
-    newsettings[SETTING_TRACKS] = LLSDArray(watertrack)(skytrack);
-
-    LLSettingsDay::ptr_t dayp = boost::make_shared<LLSettingsDay>(newsettings);
-    dayp->parseFromLLSD(dayp->mSettings);
-
-    if (dayp->validate())
-        return dayp;
-
-    return LLSettingsDay::ptr_t();
-}
+        LLSD trackout(LLSD::emptyArray());
 
-LLSettingsDay::ptr_t LLSettingsDay::buildFromLegacyMessage(const LLUUID &regionId, LLSD daycycle, LLSD skydefs, LLSD waterdef)
-{
-    LLSettingsWater::ptr_t water = LLSettingsWater::buildFromLegacyPreset("Region", waterdef);
-    LLEnvironment::namedSettingMap_t skys;
+        for (CycleTrack_t::const_iterator itFrame = (*itTrack).begin(); itFrame != (*itTrack).end(); ++itFrame)
+        {
+            F32 frame = (*itFrame).first;
+            LLSettingsBase::ptr_t data = (*itFrame).second;
+            size_t datahash = data->getHash();
 
-    for (LLSD::map_iterator itm = skydefs.beginMap(); itm != skydefs.endMap(); ++itm)
-    {
-        std::string name = (*itm).first;
-        LLSettingsSky::ptr_t sky = LLSettingsSky::buildFromLegacyPreset(name, (*itm).second);
+            std::stringstream keyname;
+            keyname << datahash;
 
-        skys[name] = sky;
-        LL_WARNS("WindlightCaps") << "created region sky '" << name << "'" << LL_ENDL;
+            trackout.append(LLSD(LLSDMap(SETTING_KEYKFRAME, LLSD::Real(frame))(SETTING_KEYNAME, keyname.str())));
+            in_use[keyname.str()] = data;
+        }
+        tracks.append(trackout);
     }
+    settings[SETTING_TRACKS] = tracks;
 
-    LLSettingsDay::ptr_t dayp = buildFromLegacyPreset("Region (legacy)", daycycle);
-
-    dayp->setWaterAtKeyframe(water, 0.0f);
-
-    for (LLSD::array_iterator ita = daycycle.beginArray(); ita != daycycle.endArray(); ++ita)
+    LLSD frames(LLSD::emptyMap());
+    for (std::map<std::string, LLSettingsBase::ptr_t>::iterator itFrame = in_use.begin(); itFrame != in_use.end(); ++itFrame)
     {
-        F32 frame = (*ita)[0].asReal();
-        std::string name = (*ita)[1].asString();
-
-        LLEnvironment::namedSettingMap_t::iterator it = skys.find(name);
-
-        if (it == skys.end())
-            continue;
-        dayp->setSkyAtKeyframe(boost::static_pointer_cast<LLSettingsSky>((*it).second), frame, 1);
+        LLSD framesettings = llsd_clone((*itFrame).second->getSettings(),
+            LLSDMap("*", true)(SETTING_NAME, false)(SETTING_ID, false)(SETTING_HASH, false));
 
-        LL_WARNS("WindlightCaps") << "Added '" << name << "' to region day cycle at " << frame << LL_ENDL;
+        frames[(*itFrame).first] = framesettings;
     }
+    settings[SETTING_FRAMES] = frames;
 
-    dayp->mHasParsed = true;
-
-    if (dayp->validate())
-        return dayp;
-
-    return LLSettingsDay::ptr_t();
+    return settings;
 }
 
-LLSettingsDay::ptr_t LLSettingsDay::buildDefaultDayCycle()
+void LLSettingsDay::initialize()
 {
-    LLSD settings = LLSettingsDay::defaults();
-
-    LLSettingsDay::ptr_t dayp = boost::make_shared<LLSettingsDay>(settings);
-    dayp->parseFromLLSD(dayp->mSettings);
+    LLSD tracks = mSettings[SETTING_TRACKS];
+    LLSD frames = mSettings[SETTING_FRAMES];
 
-    if (dayp->validate())
-        return dayp;
+    std::map<std::string, LLSettingsBase::ptr_t> used;
 
-    return LLSettingsDay::ptr_t();
-}
+    for (LLSD::map_const_iterator itFrame = frames.beginMap(); itFrame != frames.endMap(); ++itFrame)
+    {
+        std::string name = (*itFrame).first;
+        LLSD data = (*itFrame).second;
 
-void LLSettingsDay::parseFromLLSD(LLSD &data)
-{
-    LLEnvironment &environment(LLEnvironment::instance());
-    LLSD tracks = data[SETTING_TRACKS];
+        if (data[SETTING_TYPE].asString() == "sky")
+        {
+            used[name] = buildSky(data);
+        }
+        else if (data[SETTING_TYPE].asString() == "water")
+        {
+            used[name] = buildWater(data);
+        }
+        else
+        {
+            LL_WARNS("DAYCYCLE") << "Unknown child setting type '" << data[SETTING_TYPE].asString() << "' named '" << name << "'" << LL_ENDL;
+        }
+    }
 
     for (S32 i = 0; (i < tracks.size()) && (i < TRACK_MAX); ++i)
     {
@@ -255,30 +215,55 @@ void LLSettingsDay::parseFromLLSD(LLSD &data)
             if ((*it).has(SETTING_KEYNAME))
             {
                 if (i == TRACK_WATER)
-                    setting = environment.findWaterByName((*it)[SETTING_KEYNAME]);
+                {
+                    setting = used[(*it)[SETTING_KEYNAME]];
+                    if (!setting)
+                        setting = getNamedWater((*it)[SETTING_KEYNAME]);
+                    if (setting && setting->getSettingType() != "water")
+                    {
+                        LL_WARNS("DAYCYCLE") << "Water track referencing " << setting->getSettingType() << " frame at " << keyframe << "." << LL_ENDL;
+                        setting.reset();
+                    }
+                }
                 else
-                    setting = environment.findSkyByName((*it)[SETTING_KEYNAME]);
-            }
-            else if ((*it).has(SETTING_KEYID))
-            {
-
+                {
+                    setting = used[(*it)[SETTING_KEYNAME]];
+                    if (!setting)
+                        setting = getNamedSky((*it)[SETTING_KEYNAME]);
+                    if (setting && setting->getSettingType() != "sky")
+                    {
+                        LL_WARNS("DAYCYCLE") << "Sky track #" << i << " referencing " << setting->getSettingType() << " frame at " << keyframe << "." << LL_ENDL;
+                        setting.reset();
+                    }
+                }
             }
 
             if (setting)
                 mDayTracks[i][keyframe] = setting;
         }
     }
-    mHasParsed = true;
+
+    // these are no longer needed and just take up space now.
+    mSettings.erase(SETTING_TRACKS);
+    mSettings.erase(SETTING_FRAMES);
+
+    mInitialized = true;
 }
 
 
-LLSettingsDay::ptr_t LLSettingsDay::buildClone()
+//=========================================================================
+LLSD LLSettingsDay::defaults()
 {
-    LLSD settings = cloneSettings();
+    LLSD dfltsetting;
 
-    LLSettingsDay::ptr_t dayp = boost::make_shared<LLSettingsDay>(settings);
+    dfltsetting[SETTING_NAME] = "_default_";
+    dfltsetting[SETTING_DAYLENGTH] = static_cast<S32>(MINIMUM_DAYLENGTH);
+    dfltsetting[SETTING_TRACKS] = LLSDArray(
+        LLSDArray(LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))(SETTING_KEYNAME, "_default_"))
+        (LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))(SETTING_KEYNAME, "_default_")));
+    dfltsetting[SETTING_FRAMES] = LLSD::emptyMap();
 
-    return dayp;
+    return dfltsetting;
 }
 
 void LLSettingsDay::blend(const LLSettingsBase::ptr_t &other, F32 mix)
@@ -341,8 +326,9 @@ LLSettingsDay::validation_list_t LLSettingsDay::getValidationList() const
 
     if (validation.empty())
     {
-        validation.push_back(Validator(SETTING_TRACKS, true, LLSD::TypeArray, 
+        validation.push_back(Validator(SETTING_TRACKS, false, LLSD::TypeArray, 
             &validateDayCycleTrack));
+        validation.push_back(Validator(SETTING_FRAMES, false, LLSD::TypeMap));
         validation.push_back(Validator(SETTING_DAYLENGTH, false, LLSD::TypeInteger,
             boost::bind(&Validator::verifyIntegerRange, _1, 
                 LLSD(LLSDArray(LLSD::Integer(MINIMUM_DAYLENGTH))(LLSD::Integer(MAXIMUM_DAYLENGTH))))));
@@ -371,8 +357,11 @@ void LLSettingsDay::startDayCycle()
 {
     F64Seconds now(LLDate::now().secondsSinceEpoch());
 
-    if (!mHasParsed)
-        parseFromLLSD(mSettings);
+    if (!mInitialized)
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to start day cycle on uninitialized object." << LL_ENDL;
+        return;
+    }
 
     // water
     if (mDayTracks[0].empty())
@@ -391,7 +380,7 @@ void LLSettingsDay::startDayCycle()
 
         F64Seconds timespan = F64Seconds( getDayLength() * get_wrapping_distance((*bounds.first).first, (*bounds.second).first));
 
-        mBlendedWater = LLSettingsWater::buildDefaultWater();
+        mBlendedWater = getDefaultWater();
         mWaterBlender = boost::make_shared<LLSettingsBlender>(mBlendedWater,
             (*bounds.first).second, (*bounds.second).second, timespan);
         mWaterBlender->setOnFinished(boost::bind(&LLSettingsDay::onWaterTransitionDone, this, _1));
@@ -413,7 +402,7 @@ void LLSettingsDay::startDayCycle()
         TrackBound_t bounds = getBoundingEntries(mDayTracks[1], now);
         F64Seconds timespan = F64Seconds(getDayLength() * get_wrapping_distance((*bounds.first).first, (*bounds.second).first));
 
-        mBlendedSky = LLSettingsSky::buildDefaultSky();
+        mBlendedSky = getDefaultSky();
         mSkyBlender = boost::make_shared<LLSettingsBlender>(mBlendedSky,
             (*bounds.first).second, (*bounds.second).second, timespan);
         mSkyBlender->setOnFinished(boost::bind(&LLSettingsDay::onSkyTransitionDone, this, 1, _1));
@@ -432,63 +421,6 @@ void LLSettingsDay::updateSettings()
         mSkyBlender->update(delta);
     if (mWaterBlender)
         mWaterBlender->update(delta);
-
-#if 0
-    //F64Seconds time_now(LLWorld::instance().getSpaceTimeUSec());
-    F64Seconds time_now(LLDate::now().secondsSinceEpoch());
-
-    // base class clears dirty flag so as to not trigger recursive update
-    LLSettingsBase::updateSettings();
-
-    if (!mBlendedWater)
-    {
-        mBlendedWater = LLEnvironment::instance().getCurrentWater()->buildClone();
-        LLEnvironment::instance().selectWater(mBlendedWater);
-    }
-
-    if (!mBlendedSky)
-    {
-        mBlendedSky = LLEnvironment::instance().getCurrentSky()->buildClone();
-        LLEnvironment::instance().selectSky(mBlendedSky);
-    }
-
-
-    if ((time_now < mLastUpdateTime) || ((time_now - mLastUpdateTime) > static_cast<F64Seconds>(0.1)))
-    {
-        F64Seconds daylength = static_cast<F64Seconds>(getDayLength());
-        F32 frame = fmod(time_now.value(), daylength.value()) / daylength.value();
-
-        CycleList_t::iterator itTrack = mDayTracks.begin();
-        TrackBound_t bounds = getBoundingEntries(*itTrack, frame);
-
-        mBlendedWater->replaceSettings((*bounds.first).second->getSettings());
-        if (bounds.first != bounds.second)
-        {
-            F32 blendf = get_wrapping_distance((*bounds.first).first, frame) / get_wrapping_distance((*bounds.first).first, (*bounds.second).first);
-
-            mBlendedWater->blend((*bounds.second).second, blendf);
-        }
-
-        ++itTrack;
-        bounds = getBoundingEntries(*itTrack, frame);
-
-        //_WARNS("RIDER") << "Sky blending: frame=" << frame << " start=" << F64Seconds((*bounds.first).first) << " end=" << F64Seconds((*bounds.second).first) << LL_ENDL;
-
-        mBlendedSky->replaceSettings((*bounds.first).second->getSettings());
-        if (bounds.first != bounds.second)
-        {
-            F32 blendf = get_wrapping_distance((*bounds.first).first, frame) / get_wrapping_distance((*bounds.first).first, (*bounds.second).first);
-            //_WARNS("RIDER") << "Distance=" << get_wrapping_distance((*bounds.first).first, frame) << "/" << get_wrapping_distance((*bounds.first).first, (*bounds.second).first) << " Blend factor=" << blendf << LL_ENDL;
-
-            mBlendedSky->blend((*bounds.second).second, blendf);
-        }
-
-        mLastUpdateTime = time_now;
-    }
-
-    // Always mark the day cycle as dirty.So that the blend check can be handled.
-    setDirtyFlag(true);
-#endif
 }
 
 //=========================================================================
@@ -590,7 +522,7 @@ void LLSettingsDay::onSkyTransitionDone(S32 track, const LLSettingsBlender::ptr_
     F32 distance = get_wrapping_distance((*bounds.first).first, (*bounds.second).first);
     F64Seconds timespan = F64Seconds(distance * getDayLength());
 
-    LL_WARNS("RIDER") << "New sky blender. now=" << now <<
+    LL_DEBUGS("DAYCYCLE") << "New sky blender. now=" << now <<
         " start=" << (*bounds.first).first << " end=" << (*bounds.second).first <<
         " span=" << timespan << LL_ENDL;
 
diff --git a/indra/newview/llsettingsdaycycle.h b/indra/llinventory/llsettingsdaycycle.h
similarity index 83%
rename from indra/newview/llsettingsdaycycle.h
rename to indra/llinventory/llsettingsdaycycle.h
index 804d7aee266..3b24ce9f974 100644
--- a/indra/newview/llsettingsdaycycle.h
+++ b/indra/llinventory/llsettingsdaycycle.h
@@ -43,7 +43,9 @@ class LLSettingsDay : public LLSettingsBase
     static const std::string    SETTING_KEYID;
     static const std::string    SETTING_KEYNAME;
     static const std::string    SETTING_KEYKFRAME;
+    static const std::string    SETTING_KEYHASH;
     static const std::string    SETTING_TRACKS;
+    static const std::string    SETTING_FRAMES;
 
     static const S64            MINIMUM_DAYLENGTH;
     static const S64            MAXIMUM_DAYLENGTH;
@@ -63,18 +65,18 @@ class LLSettingsDay : public LLSettingsBase
     LLSettingsDay(const LLSD &data);
     virtual ~LLSettingsDay() { };
 
-    static ptr_t    buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings);
-    static ptr_t    buildFromLegacyMessage(const LLUUID &regionId, LLSD daycycle, LLSD skys, LLSD water);
-    static ptr_t    buildDefaultDayCycle();
-    ptr_t           buildClone();
+    void                        initialize();
+
+    virtual ptr_t               buildClone() = 0;
+    virtual LLSD                getSettings() const;
 
     //---------------------------------------------------------------------
-    virtual std::string getSettingType() const { return std::string("daycycle"); }
+    virtual std::string         getSettingType() const { return std::string("daycycle"); }
 
     // Settings status 
-    virtual void blend(const LLSettingsBase::ptr_t &other, F32 mix);
+    virtual void                blend(const LLSettingsBase::ptr_t &other, F32 mix);
 
-    static LLSD defaults();
+    static LLSD                 defaults();
 
     //---------------------------------------------------------------------
     S64Seconds getDayLength() const
@@ -105,6 +107,16 @@ class LLSettingsDay : public LLSettingsBase
         return mBlendedWater;
     }
 
+    virtual LLSettingsSkyPtr_t  getDefaultSky() const = 0;
+    virtual LLSettingsWaterPtr_t getDefaultWater() const = 0;
+
+    virtual LLSettingsSkyPtr_t  buildSky(LLSD) const = 0;
+    virtual LLSettingsWaterPtr_t buildWater(LLSD) const = 0;
+
+    virtual LLSettingsSkyPtr_t  getNamedSky(const std::string &) const = 0;
+    virtual LLSettingsWaterPtr_t getNamedWater(const std::string &) const = 0;
+
+    void    setInitialized(bool value = true) { mInitialized = value; }
 protected:
     LLSettingsDay();
 
@@ -112,6 +124,8 @@ class LLSettingsDay : public LLSettingsBase
 
     virtual validation_list_t   getValidationList() const;
 
+    bool                        mInitialized;
+
 private:
     LLSettingsBlender::ptr_t    mSkyBlender;    // convert to [] for altitudes 
     LLSettingsBlender::ptr_t    mWaterBlender;
@@ -121,7 +135,6 @@ class LLSettingsDay : public LLSettingsBase
 
     CycleList_t                 mDayTracks;
 
-    bool                        mHasParsed;
     F64Seconds                  mLastUpdateTime;
 
     F32                         secondsToKeyframe(S64Seconds seconds);
diff --git a/indra/newview/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
similarity index 76%
rename from indra/newview/llsettingssky.cpp
rename to indra/llinventory/llsettingssky.cpp
index f1825792d99..ecc89165e81 100644
--- a/indra/newview/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -25,21 +25,13 @@
 * $/LicenseInfo$
 */
 
-#include "llviewerprecompiledheaders.h"
-#include "llviewercontrol.h"
 #include "llsettingssky.h"
+#include "indra_constants.h"
 #include <algorithm>
-#include <boost/make_shared.hpp>
 #include "lltrace.h"
 #include "llfasttimer.h"
 #include "v3colorutil.h"
 
-#include "llglslshader.h"
-#include "llviewershadermgr.h"
-
-#include "llenvironment.h"
-#include "llsky.h"
-
 //=========================================================================
 namespace
 {
@@ -57,6 +49,9 @@ namespace
 const F32 LLSettingsSky::DOME_OFFSET(0.96f);
 const F32 LLSettingsSky::DOME_RADIUS(15000.f);
 
+const F32 LLSettingsSky::NIGHTTIME_ELEVATION(-8.0f); // degrees
+const F32 LLSettingsSky::NIGHTTIME_ELEVATION_COS((F32)sin(NIGHTTIME_ELEVATION*DEG_TO_RAD));
+
 //=========================================================================
 const std::string LLSettingsSky::SETTING_AMBIENT("ambient");
 const std::string LLSettingsSky::SETTING_BLOOM_TEXTUREID("bloom_id");
@@ -230,48 +225,88 @@ LLSettingsSky::validation_list_t LLSettingsSky::getValidationList() const
     return validation;
 }
 
-LLSettingsSky::ptr_t LLSettingsSky::buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings)
+
+LLSD LLSettingsSky::defaults()
 {
-    LLSD newsettings(defaults());
+    LLSD dfltsetting;
+
+    
+    LLQuaternion sunquat;
+    sunquat.setEulerAngles(1.39626, 0.0, 0.0); // 80deg Azumith/0deg East
+    LLQuaternion moonquat = ~sunquat;
+
+    // Magic constants copied form dfltsetting.xml 
+    dfltsetting[SETTING_AMBIENT]            = LLColor4::white.getValue();
+    dfltsetting[SETTING_BLUE_DENSITY]       = LLColor4(0.2447, 0.4487, 0.7599, 0.0).getValue();
+    dfltsetting[SETTING_BLUE_HORIZON]       = LLColor4(0.4954, 0.4954, 0.6399, 0.0).getValue();
+    dfltsetting[SETTING_CLOUD_COLOR]        = LLColor4(0.4099, 0.4099, 0.4099, 0.0).getValue();
+    dfltsetting[SETTING_CLOUD_POS_DENSITY1] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue();
+    dfltsetting[SETTING_CLOUD_POS_DENSITY2] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue();
+    dfltsetting[SETTING_CLOUD_SCALE]        = LLSD::Real(0.4199);
+    dfltsetting[SETTING_CLOUD_SCROLL_RATE]  = LLSDArray(10.1999)(10.0109);
+    dfltsetting[SETTING_CLOUD_SHADOW]       = LLSD::Real(0.2699);
+    dfltsetting[SETTING_DENSITY_MULTIPLIER] = LLSD::Real(0.0001);
+    dfltsetting[SETTING_DISTANCE_MULTIPLIER] = LLSD::Real(0.8000);
+    dfltsetting[SETTING_DOME_OFFSET]        = LLSD::Real(0.96f);
+    dfltsetting[SETTING_DOME_RADIUS]        = LLSD::Real(15000.f);
+    dfltsetting[SETTING_GAMMA]              = LLSD::Real(1.0);
+    dfltsetting[SETTING_GLOW]               = LLColor4(5.000, 0.0010, -0.4799, 1.0).getValue();
+    dfltsetting[SETTING_HAZE_DENSITY]       = LLSD::Real(0.6999);
+    dfltsetting[SETTING_HAZE_HORIZON]       = LLSD::Real(0.1899);
+    dfltsetting[SETTING_LIGHT_NORMAL]       = LLVector3(0.0000, 0.9126, -0.4086).getValue();
+    dfltsetting[SETTING_MAX_Y]              = LLSD::Real(1605);
+    dfltsetting[SETTING_MOON_ROTATION]      = moonquat.getValue();
+    dfltsetting[SETTING_STAR_BRIGHTNESS]    = LLSD::Real(0.0000);
+    dfltsetting[SETTING_SUNLIGHT_COLOR]     = LLColor4(0.7342, 0.7815, 0.8999, 0.0).getValue();
+    dfltsetting[SETTING_SUN_ROTATION]       = sunquat.getValue();
+
+    dfltsetting[SETTING_BLOOM_TEXTUREID]    = LLUUID::null;
+    dfltsetting[SETTING_CLOUD_TEXTUREID]    = LLUUID::null;
+    dfltsetting[SETTING_MOON_TEXTUREID]     = IMG_MOON; // gMoonTextureID;   // These two are returned by the login... wow!
+    dfltsetting[SETTING_SUN_TEXUTUREID]     = IMG_SUN;  // gSunTextureID;
 
-    newsettings[SETTING_NAME] = name;
+    return dfltsetting;
+}
 
+LLSD LLSettingsSky::translateLegacySettings(LLSD legacy)
+{
+    LLSD newsettings(defaults());
 
-    if (oldsettings.has(SETTING_AMBIENT))
+    if (legacy.has(SETTING_AMBIENT))
     {
-        newsettings[SETTING_AMBIENT] = LLColor3(oldsettings[SETTING_AMBIENT]).getValue();
+        newsettings[SETTING_AMBIENT] = LLColor3(legacy[SETTING_AMBIENT]).getValue();
     }
-    if (oldsettings.has(SETTING_BLUE_DENSITY))
+    if (legacy.has(SETTING_BLUE_DENSITY))
     {
-        newsettings[SETTING_BLUE_DENSITY] = LLColor3(oldsettings[SETTING_BLUE_DENSITY]).getValue();
+        newsettings[SETTING_BLUE_DENSITY] = LLColor3(legacy[SETTING_BLUE_DENSITY]).getValue();
     }
-    if (oldsettings.has(SETTING_BLUE_HORIZON))
+    if (legacy.has(SETTING_BLUE_HORIZON))
     {
-        newsettings[SETTING_BLUE_HORIZON] = LLColor3(oldsettings[SETTING_BLUE_HORIZON]).getValue();
+        newsettings[SETTING_BLUE_HORIZON] = LLColor3(legacy[SETTING_BLUE_HORIZON]).getValue();
     }
-    if (oldsettings.has(SETTING_CLOUD_COLOR))
+    if (legacy.has(SETTING_CLOUD_COLOR))
     {
-        newsettings[SETTING_CLOUD_COLOR] = LLColor3(oldsettings[SETTING_CLOUD_COLOR]).getValue();
+        newsettings[SETTING_CLOUD_COLOR] = LLColor3(legacy[SETTING_CLOUD_COLOR]).getValue();
     }
-    if (oldsettings.has(SETTING_CLOUD_POS_DENSITY1))
+    if (legacy.has(SETTING_CLOUD_POS_DENSITY1))
     {
-        newsettings[SETTING_CLOUD_POS_DENSITY1] = LLColor3(oldsettings[SETTING_CLOUD_POS_DENSITY1]).getValue();
+        newsettings[SETTING_CLOUD_POS_DENSITY1] = LLColor3(legacy[SETTING_CLOUD_POS_DENSITY1]).getValue();
     }
-    if (oldsettings.has(SETTING_CLOUD_POS_DENSITY2))
+    if (legacy.has(SETTING_CLOUD_POS_DENSITY2))
     {
-        newsettings[SETTING_CLOUD_POS_DENSITY2] = LLColor3(oldsettings[SETTING_CLOUD_POS_DENSITY2]).getValue();
+        newsettings[SETTING_CLOUD_POS_DENSITY2] = LLColor3(legacy[SETTING_CLOUD_POS_DENSITY2]).getValue();
     }
-    if (oldsettings.has(SETTING_CLOUD_SCALE))
+    if (legacy.has(SETTING_CLOUD_SCALE))
     {
-        newsettings[SETTING_CLOUD_SCALE] = LLSD::Real(oldsettings[SETTING_CLOUD_SCALE][0].asReal());
+        newsettings[SETTING_CLOUD_SCALE] = LLSD::Real(legacy[SETTING_CLOUD_SCALE][0].asReal());
     }
-    if (oldsettings.has(SETTING_CLOUD_SCROLL_RATE))
+    if (legacy.has(SETTING_CLOUD_SCROLL_RATE))
     {
-        LLVector2 cloud_scroll(oldsettings[SETTING_CLOUD_SCROLL_RATE]);
+        LLVector2 cloud_scroll(legacy[SETTING_CLOUD_SCROLL_RATE]);
 
-        if (oldsettings.has(SETTING_LEGACY_ENABLE_CLOUD_SCROLL))
+        if (legacy.has(SETTING_LEGACY_ENABLE_CLOUD_SCROLL))
         {
-            LLSD enabled = oldsettings[SETTING_LEGACY_ENABLE_CLOUD_SCROLL];
+            LLSD enabled = legacy[SETTING_LEGACY_ENABLE_CLOUD_SCROLL];
             if (!enabled[0].asBoolean())
                 cloud_scroll.mV[0] = 0.0f;
             if (!enabled[1].asBoolean())
@@ -280,55 +315,55 @@ LLSettingsSky::ptr_t LLSettingsSky::buildFromLegacyPreset(const std::string &nam
 
         newsettings[SETTING_CLOUD_SCROLL_RATE] = cloud_scroll.getValue();
     }
-    if (oldsettings.has(SETTING_CLOUD_SHADOW))
+    if (legacy.has(SETTING_CLOUD_SHADOW))
     {
-        newsettings[SETTING_CLOUD_SHADOW] = LLSD::Real(oldsettings[SETTING_CLOUD_SHADOW][0].asReal());
+        newsettings[SETTING_CLOUD_SHADOW] = LLSD::Real(legacy[SETTING_CLOUD_SHADOW][0].asReal());
     }
-    if (oldsettings.has(SETTING_DENSITY_MULTIPLIER))
+    if (legacy.has(SETTING_DENSITY_MULTIPLIER))
     {
-        newsettings[SETTING_DENSITY_MULTIPLIER] = LLSD::Real(oldsettings[SETTING_DENSITY_MULTIPLIER][0].asReal());
+        newsettings[SETTING_DENSITY_MULTIPLIER] = LLSD::Real(legacy[SETTING_DENSITY_MULTIPLIER][0].asReal());
     }
-    if (oldsettings.has(SETTING_DISTANCE_MULTIPLIER))
+    if (legacy.has(SETTING_DISTANCE_MULTIPLIER))
     {
-        newsettings[SETTING_DISTANCE_MULTIPLIER] = LLSD::Real(oldsettings[SETTING_DISTANCE_MULTIPLIER][0].asReal());
+        newsettings[SETTING_DISTANCE_MULTIPLIER] = LLSD::Real(legacy[SETTING_DISTANCE_MULTIPLIER][0].asReal());
     }
-    if (oldsettings.has(SETTING_GAMMA))
+    if (legacy.has(SETTING_GAMMA))
     {
-        newsettings[SETTING_GAMMA] = oldsettings[SETTING_GAMMA][0].asReal();
+        newsettings[SETTING_GAMMA] = legacy[SETTING_GAMMA][0].asReal();
     }
-    if (oldsettings.has(SETTING_GLOW))
+    if (legacy.has(SETTING_GLOW))
     {
-        newsettings[SETTING_GLOW] = LLColor3(oldsettings[SETTING_GLOW]).getValue();
+        newsettings[SETTING_GLOW] = LLColor3(legacy[SETTING_GLOW]).getValue();
     }
-    if (oldsettings.has(SETTING_HAZE_DENSITY))
+    if (legacy.has(SETTING_HAZE_DENSITY))
     {
-        newsettings[SETTING_HAZE_DENSITY] = LLSD::Real(oldsettings[SETTING_HAZE_DENSITY][0].asReal());
+        newsettings[SETTING_HAZE_DENSITY] = LLSD::Real(legacy[SETTING_HAZE_DENSITY][0].asReal());
     }
-    if (oldsettings.has(SETTING_HAZE_HORIZON))
+    if (legacy.has(SETTING_HAZE_HORIZON))
     {
-        newsettings[SETTING_HAZE_HORIZON] = LLSD::Real(oldsettings[SETTING_HAZE_HORIZON][0].asReal());
+        newsettings[SETTING_HAZE_HORIZON] = LLSD::Real(legacy[SETTING_HAZE_HORIZON][0].asReal());
     }
-    if (oldsettings.has(SETTING_LIGHT_NORMAL))
+    if (legacy.has(SETTING_LIGHT_NORMAL))
     {
-        newsettings[SETTING_LIGHT_NORMAL] = LLVector3(oldsettings[SETTING_LIGHT_NORMAL]).getValue();
+        newsettings[SETTING_LIGHT_NORMAL] = LLVector3(legacy[SETTING_LIGHT_NORMAL]).getValue();
     }
-    if (oldsettings.has(SETTING_MAX_Y))
+    if (legacy.has(SETTING_MAX_Y))
     {
-        newsettings[SETTING_MAX_Y] = LLSD::Real(oldsettings[SETTING_MAX_Y][0].asReal());
+        newsettings[SETTING_MAX_Y] = LLSD::Real(legacy[SETTING_MAX_Y][0].asReal());
     }
-    if (oldsettings.has(SETTING_STAR_BRIGHTNESS))
+    if (legacy.has(SETTING_STAR_BRIGHTNESS))
     {
-        newsettings[SETTING_STAR_BRIGHTNESS] = LLSD::Real(oldsettings[SETTING_STAR_BRIGHTNESS].asReal());
+        newsettings[SETTING_STAR_BRIGHTNESS] = LLSD::Real(legacy[SETTING_STAR_BRIGHTNESS].asReal());
     }
-    if (oldsettings.has(SETTING_SUNLIGHT_COLOR))
+    if (legacy.has(SETTING_SUNLIGHT_COLOR))
     {
-        newsettings[SETTING_SUNLIGHT_COLOR] = LLColor4(oldsettings[SETTING_SUNLIGHT_COLOR]).getValue();
+        newsettings[SETTING_SUNLIGHT_COLOR] = LLColor4(legacy[SETTING_SUNLIGHT_COLOR]).getValue();
     }
 
-    if (oldsettings.has(SETTING_LEGACY_EAST_ANGLE) && oldsettings.has(SETTING_LEGACY_SUN_ANGLE))
+    if (legacy.has(SETTING_LEGACY_EAST_ANGLE) && legacy.has(SETTING_LEGACY_SUN_ANGLE))
     {   // convert the east and sun angles into a quaternion.
-        F32 azimuth = oldsettings[SETTING_LEGACY_EAST_ANGLE].asReal();
-        F32 altitude = oldsettings[SETTING_LEGACY_SUN_ANGLE].asReal();
+        F32 azimuth = legacy[SETTING_LEGACY_EAST_ANGLE].asReal();
+        F32 altitude = legacy[SETTING_LEGACY_SUN_ANGLE].asReal();
 
         LLQuaternion sunquat = ::body_position_from_angles(azimuth, altitude);
         LLQuaternion moonquat = ::body_position_from_angles(azimuth + F_PI, -altitude);
@@ -340,79 +375,7 @@ LLSettingsSky::ptr_t LLSettingsSky::buildFromLegacyPreset(const std::string &nam
         newsettings[SETTING_MOON_ROTATION] = moonquat.getValue();
     }
 
-    LLSettingsSky::ptr_t skyp = boost::make_shared<LLSettingsVOSky>(newsettings);
- 
-    if (skyp->validate())
-        return skyp;
-
-    return LLSettingsSky::ptr_t();
-}
-
-LLSettingsSky::ptr_t LLSettingsSky::buildDefaultSky()
-{
-    LLSD settings = LLSettingsSky::defaults();
-
-    LLSettingsSky::ptr_t skyp = boost::make_shared<LLSettingsVOSky>(settings);
-    if (skyp->validate())
-        return skyp;
-
-    return LLSettingsSky::ptr_t();
-}
-
-LLSettingsSky::ptr_t LLSettingsSky::buildClone()
-{
-    LLSD settings = cloneSettings();
-
-    LLSettingsSky::ptr_t skyp = boost::make_shared<LLSettingsVOSky>(settings);
-
-    if (skyp->validate())
-        return skyp;
-
-    return LLSettingsSky::ptr_t();
-}
-
-
-LLSD LLSettingsSky::defaults()
-{
-    LLSD dfltsetting;
-
-    
-    LLQuaternion sunquat;
-    sunquat.setEulerAngles(1.39626, 0.0, 0.0); // 80deg Azumith/0deg East
-    LLQuaternion moonquat = ~sunquat;
-
-    // Magic constants copied form dfltsetting.xml 
-    dfltsetting[SETTING_AMBIENT]            = LLColor4::white.getValue();
-    dfltsetting[SETTING_BLUE_DENSITY]       = LLColor4(0.2447, 0.4487, 0.7599, 0.0).getValue();
-    dfltsetting[SETTING_BLUE_HORIZON]       = LLColor4(0.4954, 0.4954, 0.6399, 0.0).getValue();
-    dfltsetting[SETTING_CLOUD_COLOR]        = LLColor4(0.4099, 0.4099, 0.4099, 0.0).getValue();
-    dfltsetting[SETTING_CLOUD_POS_DENSITY1] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue();
-    dfltsetting[SETTING_CLOUD_POS_DENSITY2] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue();
-    dfltsetting[SETTING_CLOUD_SCALE]        = LLSD::Real(0.4199);
-    dfltsetting[SETTING_CLOUD_SCROLL_RATE]  = LLSDArray(10.1999)(10.0109);
-    dfltsetting[SETTING_CLOUD_SHADOW]       = LLSD::Real(0.2699);
-    dfltsetting[SETTING_DENSITY_MULTIPLIER] = LLSD::Real(0.0001);
-    dfltsetting[SETTING_DISTANCE_MULTIPLIER] = LLSD::Real(0.8000);
-    dfltsetting[SETTING_DOME_OFFSET]        = LLSD::Real(0.96f);
-    dfltsetting[SETTING_DOME_RADIUS]        = LLSD::Real(15000.f);
-    dfltsetting[SETTING_GAMMA]              = LLSD::Real(1.0);
-    dfltsetting[SETTING_GLOW]               = LLColor4(5.000, 0.0010, -0.4799, 1.0).getValue();
-    dfltsetting[SETTING_HAZE_DENSITY]       = LLSD::Real(0.6999);
-    dfltsetting[SETTING_HAZE_HORIZON]       = LLSD::Real(0.1899);
-    dfltsetting[SETTING_LIGHT_NORMAL]       = LLVector3(0.0000, 0.9126, -0.4086).getValue();
-    dfltsetting[SETTING_MAX_Y]              = LLSD::Real(1605);
-    dfltsetting[SETTING_MOON_ROTATION]      = moonquat.getValue();
-    dfltsetting[SETTING_NAME]               = std::string("_default_");
-    dfltsetting[SETTING_STAR_BRIGHTNESS]    = LLSD::Real(0.0000);
-    dfltsetting[SETTING_SUNLIGHT_COLOR]     = LLColor4(0.7342, 0.7815, 0.8999, 0.0).getValue();
-    dfltsetting[SETTING_SUN_ROTATION]       = sunquat.getValue();
-
-    dfltsetting[SETTING_BLOOM_TEXTUREID]    = LLUUID::null;
-    dfltsetting[SETTING_CLOUD_TEXTUREID]    = LLUUID::null;
-    dfltsetting[SETTING_MOON_TEXTUREID]     = IMG_MOON; // gMoonTextureID;   // These two are returned by the login... wow!
-    dfltsetting[SETTING_SUN_TEXUTUREID]     = IMG_SUN;  // gSunTextureID;
-
-    return dfltsetting;
+    return newsettings;
 }
 
 void LLSettingsSky::updateSettings()
@@ -434,19 +397,12 @@ void LLSettingsSky::calculateHeavnlyBodyPositions()
     mMoonDirection = DUE_EAST * getMoonRotation();
     mMoonDirection.normalize();
 
-    {   // set direction (in CRF) and don't allow overriding
-        LLVector3 crf_sunDirection(mSunDirection.mV[2], mSunDirection.mV[0], mSunDirection.mV[1]);
-        LLVector3 crf_moonDirection(mMoonDirection.mV[2], mMoonDirection.mV[0], mMoonDirection.mV[1]);
-
-        gSky.setSunDirection(crf_sunDirection, crf_moonDirection);
-    }
-
     // is the normal from the sun or the moon
     if (mSunDirection.mV[1] >= 0.0)
     {
         mLightDirection = mSunDirection;
     }
-    else if (mSunDirection.mV[1] < 0.0 && mSunDirection.mV[1] > LLSky::NIGHTTIME_ELEVATION_COS)
+    else if (mSunDirection.mV[1] < 0.0 && mSunDirection.mV[1] > NIGHTTIME_ELEVATION_COS)
     {
         // clamp v1 to 0 so sun never points up and causes weirdness on some machines
         LLVector3 vec(mSunDirection);
@@ -506,7 +462,7 @@ void LLSettingsSky::calculateLightSettings()
 
         // and vary_sunlight will work properly with moon light
         F32 lighty = lightnorm[1];
-        if (lighty < LLSky::NIGHTTIME_ELEVATION_COS)
+        if (lighty < NIGHTTIME_ELEVATION_COS)
         {
             lighty = -lighty;
         }
@@ -562,31 +518,6 @@ void LLSettingsSky::calculateLightSettings()
     mFadeColor.setAlpha(0);
 }
 
-LLSettingsSky::parammapping_t LLSettingsSky::getParameterMap() const
-{
-    static parammapping_t param_map;
-
-    if (param_map.empty())
-    {
-        param_map[SETTING_AMBIENT] = LLShaderMgr::AMBIENT;
-        param_map[SETTING_BLUE_DENSITY] = LLShaderMgr::BLUE_DENSITY;
-        param_map[SETTING_BLUE_HORIZON] = LLShaderMgr::BLUE_HORIZON;
-        param_map[SETTING_CLOUD_COLOR] = LLShaderMgr::CLOUD_COLOR;
-
-        param_map[SETTING_CLOUD_POS_DENSITY2] = LLShaderMgr::CLOUD_POS_DENSITY2;
-        param_map[SETTING_CLOUD_SCALE] = LLShaderMgr::CLOUD_SCALE;
-        param_map[SETTING_CLOUD_SHADOW] = LLShaderMgr::CLOUD_SHADOW;
-        param_map[SETTING_DENSITY_MULTIPLIER] = LLShaderMgr::DENSITY_MULTIPLIER;
-        param_map[SETTING_DISTANCE_MULTIPLIER] = LLShaderMgr::DISTANCE_MULTIPLIER;
-        param_map[SETTING_GLOW] = LLShaderMgr::GLOW;
-        param_map[SETTING_HAZE_DENSITY] = LLShaderMgr::HAZE_DENSITY;
-        param_map[SETTING_HAZE_HORIZON] = LLShaderMgr::HAZE_HORIZON;
-        param_map[SETTING_MAX_Y] = LLShaderMgr::MAX_Y;
-        param_map[SETTING_SUNLIGHT_COLOR] = LLShaderMgr::SUNLIGHT_COLOR;
-    }
-
-    return param_map;
-}
 
 //=========================================================================
 namespace
@@ -627,29 +558,4 @@ namespace
     }
 }
 
-//=========================================================================
-LLSettingsVOSky::LLSettingsVOSky(const LLSD &data):
-    LLSettingsSky(data)
-{
-}
-
-LLSettingsVOSky::LLSettingsVOSky():
-    LLSettingsSky()
-{
-}
-
-void LLSettingsVOSky::applySpecial(void *ptarget)
-{
-    LLGLSLShader *shader = (LLGLSLShader *)ptarget;
-
-    shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, getClampedLightDirection().mV);
-
-    shader->uniform4f(LLShaderMgr::GAMMA, getGamma(), 0.0, 0.0, 1.0);
-
-    {
-        LLVector4 vect_c_p_d1(mSettings[SETTING_CLOUD_POS_DENSITY1]);
-        vect_c_p_d1 += LLVector4(LLEnvironment::instance().getCloudScrollDelta());
-        shader->uniform4fv(LLShaderMgr::CLOUD_POS_DENSITY1, 1, vect_c_p_d1.mV);
-    }
-}
 
diff --git a/indra/newview/llsettingssky.h b/indra/llinventory/llsettingssky.h
similarity index 96%
rename from indra/newview/llsettingssky.h
rename to indra/llinventory/llsettingssky.h
index 3f564d2605e..ff4b62f86e3 100644
--- a/indra/newview/llsettingssky.h
+++ b/indra/llinventory/llsettingssky.h
@@ -29,6 +29,7 @@
 #define LL_SETTINGS_SKY_H
 
 #include "llsettingsbase.h"
+#include "v4coloru.h"
 
 class LLSettingsSky: public LLSettingsBase
 {
@@ -68,9 +69,7 @@ class LLSettingsSky: public LLSettingsBase
     LLSettingsSky(const LLSD &data);
     virtual ~LLSettingsSky() { };
 
-    static ptr_t    buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings);
-    static ptr_t    buildDefaultSky();
-    ptr_t           buildClone();
+    virtual ptr_t   buildClone() = 0;
 
     //---------------------------------------------------------------------
     virtual std::string getSettingType() const { return std::string("sky"); }
@@ -417,15 +416,18 @@ class LLSettingsSky: public LLSettingsBase
 
     virtual validation_list_t getValidationList() const;
 
-    virtual void        updateSettings();
+    virtual void    updateSettings();
 
-    virtual parammapping_t getParameterMap() const;
+    static LLSD     translateLegacySettings(LLSD legacy);
 
 private:
     static const std::string SETTING_LEGACY_EAST_ANGLE;
     static const std::string SETTING_LEGACY_ENABLE_CLOUD_SCROLL;
     static const std::string SETTING_LEGACY_SUN_ANGLE;
 
+    static const F32         NIGHTTIME_ELEVATION;
+    static const F32         NIGHTTIME_ELEVATION_COS;
+
     void        calculateHeavnlyBodyPositions();
     void        calculateLightSettings();
 
@@ -450,14 +452,4 @@ class LLSettingsSky: public LLSettingsBase
     static mapNameToUniformId_t sNameToUniformMapping;
 };
 
-class LLSettingsVOSky : public LLSettingsSky
-{
-public:
-    LLSettingsVOSky(const LLSD &data);
-protected:
-    LLSettingsVOSky();
-
-    virtual void        applySpecial(void *);
-};
-
 #endif
diff --git a/indra/newview/llsettingswater.cpp b/indra/llinventory/llsettingswater.cpp
similarity index 58%
rename from indra/newview/llsettingswater.cpp
rename to indra/llinventory/llsettingswater.cpp
index caf7a4b7cca..1b960746d57 100644
--- a/indra/newview/llsettingswater.cpp
+++ b/indra/llinventory/llsettingswater.cpp
@@ -25,22 +25,13 @@
 * $/LicenseInfo$
 */
 
-#include "llviewerprecompiledheaders.h"
-#include "llviewercontrol.h"
 #include "llsettingswater.h"
 #include <algorithm>
 #include <boost/make_shared.hpp>
 #include "lltrace.h"
 #include "llfasttimer.h"
 #include "v3colorutil.h"
-
-#include "llglslshader.h"
-#include "llviewershadermgr.h"
-
-#include "llenvironment.h"
-
-#include "llagent.h"
-#include "pipeline.h"
+#include "indra_constants.h"
 
 //=========================================================================
 namespace
@@ -112,92 +103,60 @@ LLSD LLSettingsWater::defaults()
     return dfltsetting;
 }
 
-LLSettingsWater::ptr_t LLSettingsWater::buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings)
+LLSD LLSettingsWater::translateLegacySettings(LLSD legacy)
 {
     LLSD newsettings(defaults());
 
-    newsettings[SETTING_NAME] = name;
-
-
-    if (oldsettings.has(SETTING_LEGACY_BLUR_MULTIPILER))
+    if (legacy.has(SETTING_LEGACY_BLUR_MULTIPILER))
     {
-        newsettings[SETTING_BLUR_MULTIPILER] = LLSD::Real(oldsettings[SETTING_LEGACY_BLUR_MULTIPILER].asReal());
+        newsettings[SETTING_BLUR_MULTIPILER] = LLSD::Real(legacy[SETTING_LEGACY_BLUR_MULTIPILER].asReal());
     }
-    if (oldsettings.has(SETTING_LEGACY_FOG_COLOR))
+    if (legacy.has(SETTING_LEGACY_FOG_COLOR))
     {
-        newsettings[SETTING_FOG_COLOR] = LLColor3(oldsettings[SETTING_LEGACY_FOG_COLOR]).getValue();
+        newsettings[SETTING_FOG_COLOR] = LLColor3(legacy[SETTING_LEGACY_FOG_COLOR]).getValue();
     }
-    if (oldsettings.has(SETTING_LEGACY_FOG_DENSITY))
+    if (legacy.has(SETTING_LEGACY_FOG_DENSITY))
     {
-        newsettings[SETTING_FOG_DENSITY] = LLSD::Real(oldsettings[SETTING_LEGACY_FOG_DENSITY]);
+        newsettings[SETTING_FOG_DENSITY] = LLSD::Real(legacy[SETTING_LEGACY_FOG_DENSITY]);
     }
-    if (oldsettings.has(SETTING_LEGACY_FOG_MOD))
+    if (legacy.has(SETTING_LEGACY_FOG_MOD))
     {
-        newsettings[SETTING_FOG_MOD] = LLSD::Real(oldsettings[SETTING_LEGACY_FOG_MOD].asReal());
+        newsettings[SETTING_FOG_MOD] = LLSD::Real(legacy[SETTING_LEGACY_FOG_MOD].asReal());
     }
-    if (oldsettings.has(SETTING_LEGACY_FRESNEL_OFFSET))
+    if (legacy.has(SETTING_LEGACY_FRESNEL_OFFSET))
     {
-        newsettings[SETTING_FRESNEL_OFFSET] = LLSD::Real(oldsettings[SETTING_LEGACY_FRESNEL_OFFSET].asReal());
+        newsettings[SETTING_FRESNEL_OFFSET] = LLSD::Real(legacy[SETTING_LEGACY_FRESNEL_OFFSET].asReal());
     }
-    if (oldsettings.has(SETTING_LEGACY_FRESNEL_SCALE))
+    if (legacy.has(SETTING_LEGACY_FRESNEL_SCALE))
     {
-        newsettings[SETTING_FRESNEL_SCALE] = LLSD::Real(oldsettings[SETTING_LEGACY_FRESNEL_SCALE].asReal());
+        newsettings[SETTING_FRESNEL_SCALE] = LLSD::Real(legacy[SETTING_LEGACY_FRESNEL_SCALE].asReal());
     }
-    if (oldsettings.has(SETTING_LEGACY_NORMAL_MAP))
+    if (legacy.has(SETTING_LEGACY_NORMAL_MAP))
     {
-        newsettings[SETTING_NORMAL_MAP] = LLSD::UUID(oldsettings[SETTING_LEGACY_NORMAL_MAP].asUUID());
+        newsettings[SETTING_NORMAL_MAP] = LLSD::UUID(legacy[SETTING_LEGACY_NORMAL_MAP].asUUID());
     }
-    if (oldsettings.has(SETTING_LEGACY_NORMAL_SCALE))
+    if (legacy.has(SETTING_LEGACY_NORMAL_SCALE))
     {
-        newsettings[SETTING_NORMAL_SCALE] = LLVector3(oldsettings[SETTING_LEGACY_NORMAL_SCALE]).getValue();
+        newsettings[SETTING_NORMAL_SCALE] = LLVector3(legacy[SETTING_LEGACY_NORMAL_SCALE]).getValue();
     }
-    if (oldsettings.has(SETTING_LEGACY_SCALE_ABOVE))
+    if (legacy.has(SETTING_LEGACY_SCALE_ABOVE))
     {
-        newsettings[SETTING_SCALE_ABOVE] = LLSD::Real(oldsettings[SETTING_LEGACY_SCALE_ABOVE].asReal());
+        newsettings[SETTING_SCALE_ABOVE] = LLSD::Real(legacy[SETTING_LEGACY_SCALE_ABOVE].asReal());
     }
-    if (oldsettings.has(SETTING_LEGACY_SCALE_BELOW))
+    if (legacy.has(SETTING_LEGACY_SCALE_BELOW))
     {
-        newsettings[SETTING_SCALE_BELOW] = LLSD::Real(oldsettings[SETTING_LEGACY_SCALE_BELOW].asReal());
+        newsettings[SETTING_SCALE_BELOW] = LLSD::Real(legacy[SETTING_LEGACY_SCALE_BELOW].asReal());
     }
-    if (oldsettings.has(SETTING_LEGACY_WAVE1_DIR))
+    if (legacy.has(SETTING_LEGACY_WAVE1_DIR))
     {
-        newsettings[SETTING_WAVE1_DIR] = LLVector2(oldsettings[SETTING_LEGACY_WAVE1_DIR]).getValue();
+        newsettings[SETTING_WAVE1_DIR] = LLVector2(legacy[SETTING_LEGACY_WAVE1_DIR]).getValue();
     }
-    if (oldsettings.has(SETTING_LEGACY_WAVE2_DIR))
+    if (legacy.has(SETTING_LEGACY_WAVE2_DIR))
     {
-        newsettings[SETTING_WAVE2_DIR] = LLVector2(oldsettings[SETTING_LEGACY_WAVE2_DIR]).getValue();
+        newsettings[SETTING_WAVE2_DIR] = LLVector2(legacy[SETTING_LEGACY_WAVE2_DIR]).getValue();
     }
 
-    LLSettingsWater::ptr_t waterp = boost::make_shared<LLSettingsWater>(newsettings);
-
-    if (waterp->validate())
-        return waterp;
-
-    return LLSettingsWater::ptr_t();
-}
-
-LLSettingsWater::ptr_t LLSettingsWater::buildDefaultWater()
-{
-    LLSD settings = LLSettingsWater::defaults();
-
-    LLSettingsWater::ptr_t waterp = boost::make_shared<LLSettingsWater>(settings);
-
-    if (waterp->validate())
-        return waterp;
-
-    return LLSettingsWater::ptr_t();
-}
-
-LLSettingsWater::ptr_t LLSettingsWater::buildClone()
-{
-    LLSD settings = cloneSettings();
-
-    LLSettingsWater::ptr_t waterp = boost::make_shared<LLSettingsWater>(settings);
-
-    if (waterp->validate())
-        return waterp;
-
-    return LLSettingsWater::ptr_t();
+    return newsettings;
 }
 
 void LLSettingsWater::blend(const LLSettingsBase::ptr_t &end, F32 blendf) 
@@ -254,87 +213,3 @@ LLSettingsWater::validation_list_t LLSettingsWater::getValidationList() const
     return validation;
 }
 
-//=========================================================================
-
-LLSettingsWater::parammapping_t LLSettingsWater::getParameterMap() const
-{
-    static parammapping_t param_map;
-
-    if (param_map.empty())
-    {
-        param_map[SETTING_FOG_COLOR] = LLShaderMgr::WATER_FOGCOLOR;
-        param_map[SETTING_FOG_DENSITY] = LLShaderMgr::WATER_FOGDENSITY;
-
-
-    }
-    return param_map;
-}
-
-//=========================================================================
-const F32 LLSettingsVOWater::WATER_FOG_LIGHT_CLAMP(0.3f);
-
-//=========================================================================
-LLSettingsVOWater::LLSettingsVOWater(const LLSD &data):
-    LLSettingsWater(data)
-{
-
-}
-
-LLSettingsVOWater::LLSettingsVOWater() :
-    LLSettingsWater()
-{
-
-}
-
-void LLSettingsVOWater::applySpecial(void *ptarget)
-{
-    LLGLSLShader *shader = (LLGLSLShader *)ptarget;
-
-    shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, getWaterPlane().mV);
-    shader->uniform1f(LLShaderMgr::WATER_FOGKS, getWaterFogKS());
-
-    shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, LLEnvironment::instance().getRotatedLight().mV);
-    shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
-    shader->uniform1f(LLViewerShaderMgr::DISTANCE_MULTIPLIER, 0);
-
-
-}
-
-void LLSettingsVOWater::updateSettings()
-{
-    //    LL_RECORD_BLOCK_TIME(FTM_UPDATE_WATERVALUES);
-    //    LL_INFOS("WINDLIGHT", "WATER", "EEP") << "Water Parameters are dirty.  Reticulating Splines..." << LL_ENDL;
-
-    // base class clears dirty flag so as to not trigger recursive update
-    LLSettingsBase::updateSettings();
-
-    // only do this if we're dealing with shaders
-    if (gPipeline.canUseVertexShaders())
-    {
-        //transform water plane to eye space
-        glh::vec3f norm(0.f, 0.f, 1.f);
-        glh::vec3f p(0.f, 0.f, LLEnvironment::instance().getWaterHeight() + 0.1f);
-
-        F32 modelView[16];
-        for (U32 i = 0; i < 16; i++)
-        {
-            modelView[i] = (F32)gGLModelView[i];
-        }
-
-        glh::matrix4f mat(modelView);
-        glh::matrix4f invtrans = mat.inverse().transpose();
-        glh::vec3f enorm;
-        glh::vec3f ep;
-        invtrans.mult_matrix_vec(norm, enorm);
-        enorm.normalize();
-        mat.mult_matrix_vec(p, ep);
-
-        mWaterPlane = LLVector4(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
-
-        LLVector4 light_direction = LLEnvironment::instance().getLightDirection();
-
-        mWaterFogKS = 1.f / llmax(light_direction.mV[2], WATER_FOG_LIGHT_CLAMP);
-    }
-
-}
-
diff --git a/indra/newview/llsettingswater.h b/indra/llinventory/llsettingswater.h
similarity index 92%
rename from indra/newview/llsettingswater.h
rename to indra/llinventory/llsettingswater.h
index aa60861bd4c..5d6a482d56f 100644
--- a/indra/newview/llsettingswater.h
+++ b/indra/llinventory/llsettingswater.h
@@ -54,9 +54,7 @@ class LLSettingsWater : public LLSettingsBase
     LLSettingsWater(const LLSD &data);
     virtual ~LLSettingsWater() { };
 
-    static ptr_t    buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings);
-    static ptr_t    buildDefaultWater();
-    ptr_t           buildClone();
+    virtual ptr_t   buildClone() = 0;
 
     //---------------------------------------------------------------------
     virtual std::string getSettingType() const { return std::string("water"); }
@@ -203,12 +201,13 @@ class LLSettingsWater : public LLSettingsBase
 protected:
     LLSettingsWater();
 
-    virtual parammapping_t getParameterMap() const;
-
     virtual validation_list_t getValidationList() const;
 
+    static LLSD         translateLegacySettings(LLSD legacy);
+
     LLVector4           mWaterPlane;
     F32                 mWaterFogKS;
+
 private:
     static const std::string SETTING_LEGACY_BLUR_MULTIPILER;
     static const std::string SETTING_LEGACY_FOG_COLOR;
@@ -222,21 +221,6 @@ class LLSettingsWater : public LLSettingsBase
     static const std::string SETTING_LEGACY_SCALE_BELOW;
     static const std::string SETTING_LEGACY_WAVE1_DIR;
     static const std::string SETTING_LEGACY_WAVE2_DIR;
-};
-
-class LLSettingsVOWater : public LLSettingsWater
-{
-public:
-    LLSettingsVOWater(const LLSD &data);
-
-protected:
-    LLSettingsVOWater();
-
-    virtual void updateSettings();
-    virtual void applySpecial(void *);
-
-private:
-    static const F32 WATER_FOG_LIGHT_CLAMP;
 
 };
 
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index bbe32866f61..4579ef14e2b 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -532,10 +532,7 @@ set(viewer_SOURCE_FILES
     llsecapi.cpp
     llsechandler_basic.cpp
     llselectmgr.cpp
-    llsettingsbase.cpp
-    llsettingsdaycycle.cpp
-    llsettingssky.cpp
-    llsettingswater.cpp
+    llsettingsvo.cpp
     llshareavatarhandler.cpp
     llsidepanelappearance.cpp
     llsidepanelinventory.cpp
@@ -1141,10 +1138,7 @@ set(viewer_HEADER_FILES
     llsecapi.h
     llsechandler_basic.h
     llselectmgr.h
-    llsettingsbase.h
-    llsettingsdaycycle.h
-    llsettingssky.h
-    llsettingswater.h
+    llsettingsvo.h
     llsidepanelappearance.h
     llsidepanelinventory.h
     llsidepanelinventorysubpanel.h
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 8b879710dab..e8c9db045c8 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -44,6 +44,8 @@
 #include "llsdserialize.h"
 #include "lldiriterator.h"
 
+#include "llsettingsvo.h"
+
 #include <boost/make_shared.hpp>
 //=========================================================================
 namespace
@@ -82,15 +84,15 @@ LLEnvironment::LLEnvironment():
 
 void LLEnvironment::initSingleton()
 {
-    LLSettingsSky::ptr_t p_default_sky = LLSettingsSky::buildDefaultSky();
+    LLSettingsSky::ptr_t p_default_sky = LLSettingsVOSky::buildDefaultSky();
     addSky(p_default_sky);
     mCurrentSky = p_default_sky;
 
-    LLSettingsWater::ptr_t p_default_water = LLSettingsWater::buildDefaultWater();
+    LLSettingsWater::ptr_t p_default_water = LLSettingsVOWater::buildDefaultWater();
     addWater(p_default_water);
     mCurrentWater = p_default_water;
 
-    LLSettingsDay::ptr_t p_default_day = LLSettingsDay::buildDefaultDayCycle();
+    LLSettingsDay::ptr_t p_default_day = LLSettingsVODay::buildDefaultDayCycle();
     addDayCycle(p_default_day);
     mCurrentDay.reset();
 
@@ -155,7 +157,7 @@ void LLEnvironment::onLegacyRegionSettings(LLSD data)
     if (data[1].isUndefined())
         regionday = LLEnvironment::findDayCycleByName("Default");
     else
-        regionday = LLSettingsDay::buildFromLegacyMessage(regionId, data[1], data[2], data[3]);
+        regionday = LLSettingsVODay::buildFromLegacyMessage(regionId, data[1], data[2], data[3]);
 
     setSkyFor(ENV_REGION, LLSettingsSky::ptr_t());
     setWaterFor(ENV_REGION, LLSettingsWater::ptr_t());
@@ -826,7 +828,7 @@ void LLEnvironment::legacyLoadAllPresets()
             {
                 std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), true));
 
-                LLSettingsSky::ptr_t sky = LLSettingsSky::buildFromLegacyPreset(name, data);
+                LLSettingsSky::ptr_t sky = LLSettingsVOSky::buildFromLegacyPreset(name, data);
                 LLEnvironment::instance().addSky(sky);
             }
         }
@@ -845,7 +847,7 @@ void LLEnvironment::legacyLoadAllPresets()
             {
                 std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), true));
 
-                LLSettingsSky::ptr_t sky = LLSettingsSky::buildFromLegacyPreset(name, data);
+                LLSettingsSky::ptr_t sky = LLSettingsVOSky::buildFromLegacyPreset(name, data);
                 LLEnvironment::instance().addSky(sky);
             }
         }
@@ -864,7 +866,7 @@ void LLEnvironment::legacyLoadAllPresets()
             {
                 std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), true));
 
-                LLSettingsWater::ptr_t water = LLSettingsWater::buildFromLegacyPreset(name, data);
+                LLSettingsWater::ptr_t water = LLSettingsVOWater::buildFromLegacyPreset(name, data);
                 LLEnvironment::instance().addWater(water);
             }
         }
@@ -883,7 +885,7 @@ void LLEnvironment::legacyLoadAllPresets()
             {
                 std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), true));
 
-                LLSettingsWater::ptr_t water = LLSettingsWater::buildFromLegacyPreset(name, data);
+                LLSettingsWater::ptr_t water = LLSettingsVOWater::buildFromLegacyPreset(name, data);
                 LLEnvironment::instance().addWater(water);
             }
         }
@@ -902,7 +904,7 @@ void LLEnvironment::legacyLoadAllPresets()
             {
                 std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), true));
 
-                LLSettingsDay::ptr_t day = LLSettingsDay::buildFromLegacyPreset(name, data);
+                LLSettingsDay::ptr_t day = LLSettingsVODay::buildFromLegacyPreset(name, data);
                 LLEnvironment::instance().addDayCycle(day);
             }
         }
@@ -921,7 +923,7 @@ void LLEnvironment::legacyLoadAllPresets()
             {
                 std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), true));
 
-                LLSettingsDay::ptr_t day = LLSettingsDay::buildFromLegacyPreset(name, data);
+                LLSettingsDay::ptr_t day = LLSettingsVODay::buildFromLegacyPreset(name, data);
                 LLEnvironment::instance().addDayCycle(day);
             }
         }
diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h
index ce8c08f6925..4d3d1f6a57d 100644
--- a/indra/newview/llenvironment.h
+++ b/indra/newview/llenvironment.h
@@ -27,6 +27,7 @@
 #ifndef LL_ENVIRONMENT_H
 #define LL_ENVIRONMENT_H
 
+#include "llsingleton.h"
 #include "llmemory.h"
 #include "llsd.h"
 
@@ -35,6 +36,8 @@
 #include "llsettingswater.h"
 #include "llsettingsdaycycle.h"
 
+#include <boost/signals2.hpp>
+
 //-------------------------------------------------------------------------
 class LLViewerCamera;
 class LLGLSLShader;
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
new file mode 100644
index 00000000000..76a67545738
--- /dev/null
+++ b/indra/newview/llsettingsvo.cpp
@@ -0,0 +1,420 @@
+/**
+* @file llsettingsvo.cpp
+* @author Rider Linden
+* @brief Subclasses for viewer specific settings behaviors.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+#include "llviewercontrol.h"
+#include "llsettingsvo.h"
+
+#include "pipeline.h"
+
+#include <algorithm>
+#include <boost/make_shared.hpp>
+#include "lltrace.h"
+#include "llfasttimer.h"
+#include "v3colorutil.h"
+
+#include "llglslshader.h"
+#include "llviewershadermgr.h"
+
+#include "llenvironment.h"
+#include "llsky.h"
+
+//=========================================================================
+LLSettingsVOSky::LLSettingsVOSky(const LLSD &data):
+    LLSettingsSky(data)
+{
+}
+
+LLSettingsVOSky::LLSettingsVOSky():
+    LLSettingsSky()
+{
+}
+
+//-------------------------------------------------------------------------
+LLSettingsSky::ptr_t LLSettingsVOSky::buildFromLegacyPreset(const std::string &name, const LLSD &legacy)
+{
+
+    LLSD newsettings = LLSettingsSky::translateLegacySettings(legacy);
+
+    newsettings[SETTING_NAME] = name;
+
+    LLSettingsSky::ptr_t skyp = boost::make_shared<LLSettingsVOSky>(newsettings);
+
+    if (skyp->validate())
+        return skyp;
+
+    return LLSettingsSky::ptr_t();
+}
+
+LLSettingsSky::ptr_t LLSettingsVOSky::buildDefaultSky()
+{
+    LLSD settings = LLSettingsSky::defaults();
+    settings[SETTING_NAME] = std::string("_default_");
+
+
+    LLSettingsSky::ptr_t skyp = boost::make_shared<LLSettingsVOSky>(settings);
+    if (skyp->validate())
+        return skyp;
+
+    return LLSettingsSky::ptr_t();
+}
+
+LLSettingsSky::ptr_t LLSettingsVOSky::buildClone()
+{
+    LLSD settings = cloneSettings();
+
+    LLSettingsSky::ptr_t skyp = boost::make_shared<LLSettingsVOSky>(settings);
+
+    if (skyp->validate())
+        return skyp;
+
+    return LLSettingsSky::ptr_t();
+}
+
+//-------------------------------------------------------------------------
+void LLSettingsVOSky::updateSettings()
+{
+    LLSettingsSky::updateSettings();
+
+    LLVector3 sun_direction = getSunDirection();
+    LLVector3 moon_direction = getMoonDirection();
+
+    // set direction (in CRF) and don't allow overriding
+    LLVector3 crf_sunDirection(sun_direction.mV[2], sun_direction.mV[0], sun_direction.mV[1]);
+    LLVector3 crf_moonDirection(moon_direction.mV[2], moon_direction.mV[0], moon_direction.mV[1]);
+
+    gSky.setSunDirection(crf_sunDirection, crf_moonDirection);
+}
+
+void LLSettingsVOSky::applySpecial(void *ptarget)
+{
+    LLGLSLShader *shader = (LLGLSLShader *)ptarget;
+
+    shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, getClampedLightDirection().mV);
+
+    shader->uniform4f(LLShaderMgr::GAMMA, getGamma(), 0.0, 0.0, 1.0);
+
+    {
+        LLVector4 vect_c_p_d1(mSettings[SETTING_CLOUD_POS_DENSITY1]);
+        vect_c_p_d1 += LLVector4(LLEnvironment::instance().getCloudScrollDelta());
+        shader->uniform4fv(LLShaderMgr::CLOUD_POS_DENSITY1, 1, vect_c_p_d1.mV);
+    }
+}
+
+LLSettingsSky::parammapping_t LLSettingsVOSky::getParameterMap() const
+{
+    static parammapping_t param_map;
+
+    if (param_map.empty())
+    {
+        param_map[SETTING_AMBIENT] = LLShaderMgr::AMBIENT;
+        param_map[SETTING_BLUE_DENSITY] = LLShaderMgr::BLUE_DENSITY;
+        param_map[SETTING_BLUE_HORIZON] = LLShaderMgr::BLUE_HORIZON;
+        param_map[SETTING_CLOUD_COLOR] = LLShaderMgr::CLOUD_COLOR;
+
+        param_map[SETTING_CLOUD_POS_DENSITY2] = LLShaderMgr::CLOUD_POS_DENSITY2;
+        param_map[SETTING_CLOUD_SCALE] = LLShaderMgr::CLOUD_SCALE;
+        param_map[SETTING_CLOUD_SHADOW] = LLShaderMgr::CLOUD_SHADOW;
+        param_map[SETTING_DENSITY_MULTIPLIER] = LLShaderMgr::DENSITY_MULTIPLIER;
+        param_map[SETTING_DISTANCE_MULTIPLIER] = LLShaderMgr::DISTANCE_MULTIPLIER;
+        param_map[SETTING_GLOW] = LLShaderMgr::GLOW;
+        param_map[SETTING_HAZE_DENSITY] = LLShaderMgr::HAZE_DENSITY;
+        param_map[SETTING_HAZE_HORIZON] = LLShaderMgr::HAZE_HORIZON;
+        param_map[SETTING_MAX_Y] = LLShaderMgr::MAX_Y;
+        param_map[SETTING_SUNLIGHT_COLOR] = LLShaderMgr::SUNLIGHT_COLOR;
+    }
+
+    return param_map;
+}
+
+//=========================================================================
+const F32 LLSettingsVOWater::WATER_FOG_LIGHT_CLAMP(0.3f);
+
+//-------------------------------------------------------------------------
+LLSettingsVOWater::LLSettingsVOWater(const LLSD &data) :
+    LLSettingsWater(data)
+{
+
+}
+
+LLSettingsVOWater::LLSettingsVOWater() :
+    LLSettingsWater()
+{
+
+}
+
+//-------------------------------------------------------------------------
+LLSettingsWater::ptr_t LLSettingsVOWater::buildFromLegacyPreset(const std::string &name, const LLSD &legacy)
+{
+    LLSD newsettings(LLSettingsWater::translateLegacySettings(legacy));
+
+    newsettings[SETTING_NAME] = name; 
+
+    LLSettingsWater::ptr_t waterp = boost::make_shared<LLSettingsVOWater>(newsettings);
+
+    if (waterp->validate())
+        return waterp;
+
+    return LLSettingsWater::ptr_t();
+}
+
+LLSettingsWater::ptr_t LLSettingsVOWater::buildDefaultWater()
+{
+    LLSD settings = LLSettingsWater::defaults();
+    settings[SETTING_NAME] = std::string("_default_");
+
+    LLSettingsWater::ptr_t waterp = boost::make_shared<LLSettingsVOWater>(settings);
+
+    if (waterp->validate())
+        return waterp;
+
+    return LLSettingsWater::ptr_t();
+}
+
+LLSettingsWater::ptr_t LLSettingsVOWater::buildClone()
+{
+    LLSD settings = cloneSettings();
+
+    LLSettingsWater::ptr_t waterp = boost::make_shared<LLSettingsVOWater>(settings);
+
+    if (waterp->validate())
+        return waterp;
+
+    return LLSettingsWater::ptr_t();
+}
+
+//-------------------------------------------------------------------------
+void LLSettingsVOWater::applySpecial(void *ptarget)
+{
+    LLGLSLShader *shader = (LLGLSLShader *)ptarget;
+
+    shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, getWaterPlane().mV);
+    shader->uniform1f(LLShaderMgr::WATER_FOGKS, getWaterFogKS());
+
+    shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, LLEnvironment::instance().getRotatedLight().mV);
+    shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
+    shader->uniform1f(LLViewerShaderMgr::DISTANCE_MULTIPLIER, 0);
+}
+
+void LLSettingsVOWater::updateSettings()
+{
+    //    LL_RECORD_BLOCK_TIME(FTM_UPDATE_WATERVALUES);
+    //    LL_INFOS("WINDLIGHT", "WATER", "EEP") << "Water Parameters are dirty.  Reticulating Splines..." << LL_ENDL;
+
+    // base class clears dirty flag so as to not trigger recursive update
+    LLSettingsBase::updateSettings();
+
+    // only do this if we're dealing with shaders
+    if (gPipeline.canUseVertexShaders())
+    {
+        //transform water plane to eye space
+        glh::vec3f norm(0.f, 0.f, 1.f);
+        glh::vec3f p(0.f, 0.f, LLEnvironment::instance().getWaterHeight() + 0.1f);
+
+        F32 modelView[16];
+        for (U32 i = 0; i < 16; i++)
+        {
+            modelView[i] = (F32)gGLModelView[i];
+        }
+
+        glh::matrix4f mat(modelView);
+        glh::matrix4f invtrans = mat.inverse().transpose();
+        glh::vec3f enorm;
+        glh::vec3f ep;
+        invtrans.mult_matrix_vec(norm, enorm);
+        enorm.normalize();
+        mat.mult_matrix_vec(p, ep);
+
+        mWaterPlane = LLVector4(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
+
+        LLVector4 light_direction = LLEnvironment::instance().getLightDirection();
+
+        mWaterFogKS = 1.f / llmax(light_direction.mV[2], WATER_FOG_LIGHT_CLAMP);
+    }
+}
+
+LLSettingsWater::parammapping_t LLSettingsVOWater::getParameterMap() const
+{
+    static parammapping_t param_map;
+
+    if (param_map.empty())
+    {
+        param_map[SETTING_FOG_COLOR] = LLShaderMgr::WATER_FOGCOLOR;
+        param_map[SETTING_FOG_DENSITY] = LLShaderMgr::WATER_FOGDENSITY;
+    }
+    return param_map;
+}
+
+//=========================================================================
+LLSettingsVODay::LLSettingsVODay(const LLSD &data):
+    LLSettingsDay(data)
+{}
+
+LLSettingsVODay::LLSettingsVODay():
+    LLSettingsDay()
+{}
+
+//-------------------------------------------------------------------------
+LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings)
+{
+    LLSD newsettings(defaults());
+
+    newsettings[SETTING_NAME] = name;
+    newsettings[SETTING_DAYLENGTH] = static_cast<S32>(MINIMUM_DAYLENGTH);
+
+    LLSD watertrack = LLSDArray(
+        LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))
+        (SETTING_KEYNAME, "Default"));
+
+    LLSD skytrack = LLSD::emptyArray();
+
+    for (LLSD::array_const_iterator it = oldsettings.beginArray(); it != oldsettings.endArray(); ++it)
+    {
+        LLSD entry = LLSDMap(SETTING_KEYKFRAME, (*it)[0].asReal())
+            (SETTING_KEYNAME, (*it)[1].asString());
+        skytrack.append(entry);
+    }
+
+    newsettings[SETTING_TRACKS] = LLSDArray(watertrack)(skytrack);
+
+    LLSettingsDay::ptr_t dayp = boost::make_shared<LLSettingsVODay>(newsettings);
+
+    if (dayp->validate())
+    {
+        dayp->initialize();
+        return dayp;
+    }
+
+    return LLSettingsDay::ptr_t();
+}
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyMessage(const LLUUID &regionId, LLSD daycycle, LLSD skydefs, LLSD waterdef)
+{
+    LLSettingsWater::ptr_t water = LLSettingsVOWater::buildFromLegacyPreset("Region", waterdef);
+    LLEnvironment::namedSettingMap_t skys;
+
+    for (LLSD::map_iterator itm = skydefs.beginMap(); itm != skydefs.endMap(); ++itm)
+    {
+        std::string name = (*itm).first;
+        LLSettingsSky::ptr_t sky = LLSettingsVOSky::buildFromLegacyPreset(name, (*itm).second);
+
+        skys[name] = sky;
+        LL_WARNS("WindlightCaps") << "created region sky '" << name << "'" << LL_ENDL;
+    }
+
+    LLSettingsDay::ptr_t dayp = buildFromLegacyPreset("Region (legacy)", daycycle);
+
+    dayp->setWaterAtKeyframe(water, 0.0f);
+
+    for (LLSD::array_iterator ita = daycycle.beginArray(); ita != daycycle.endArray(); ++ita)
+    {
+        F32 frame = (*ita)[0].asReal();
+        std::string name = (*ita)[1].asString();
+
+        LLEnvironment::namedSettingMap_t::iterator it = skys.find(name);
+
+        if (it == skys.end())
+            continue;
+        dayp->setSkyAtKeyframe(boost::static_pointer_cast<LLSettingsSky>((*it).second), frame, 1);
+
+        LL_WARNS("WindlightCaps") << "Added '" << name << "' to region day cycle at " << frame << LL_ENDL;
+    }
+
+    dayp->setInitialized();
+
+    if (dayp->validate())
+    {
+        return dayp;
+    }
+
+    return LLSettingsDay::ptr_t();
+}
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildDefaultDayCycle()
+{
+    LLSD settings = LLSettingsDay::defaults();
+    settings[SETTING_NAME] = std::string("_default_");
+
+    LLSettingsDay::ptr_t dayp = boost::make_shared<LLSettingsVODay>(settings);
+
+    if (dayp->validate())
+    {
+        dayp->initialize();
+        return dayp;
+    }
+
+    return LLSettingsDay::ptr_t();
+}
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildClone()
+{
+    LLSD settings = cloneSettings();
+
+    LLSettingsDay::ptr_t dayp = boost::make_shared<LLSettingsVODay>(settings);
+
+    return dayp;
+}
+
+LLSettingsSkyPtr_t  LLSettingsVODay::getDefaultSky() const
+{
+    return LLSettingsVOSky::buildDefaultSky();
+}
+
+LLSettingsWaterPtr_t LLSettingsVODay::getDefaultWater() const
+{
+    return LLSettingsVOWater::buildDefaultWater();
+}
+
+LLSettingsSkyPtr_t LLSettingsVODay::buildSky(LLSD settings) const
+{
+    LLSettingsSky::ptr_t skyp = boost::make_shared<LLSettingsVOSky>(settings);
+
+    if (skyp->validate())
+        return skyp;
+
+    return LLSettingsSky::ptr_t();
+}
+
+LLSettingsWaterPtr_t LLSettingsVODay::buildWater(LLSD settings) const
+{
+    LLSettingsWater::ptr_t waterp = boost::make_shared<LLSettingsVOWater>(settings);
+
+    if (waterp->validate())
+        return waterp;
+
+    return LLSettingsWater::ptr_t();
+}
+
+LLSettingsSkyPtr_t LLSettingsVODay::getNamedSky(const std::string &name) const
+{
+    return LLEnvironment::instance().findSkyByName(name);
+}
+
+LLSettingsWaterPtr_t LLSettingsVODay::getNamedWater(const std::string &name) const
+{
+    return LLEnvironment::instance().findWaterByName(name);
+}
diff --git a/indra/newview/llsettingsvo.h b/indra/newview/llsettingsvo.h
new file mode 100644
index 00000000000..6ef7290ba45
--- /dev/null
+++ b/indra/newview/llsettingsvo.h
@@ -0,0 +1,103 @@
+/**
+* @file llsettingsvo.h
+* @author Rider Linden
+* @brief Subclasses for viewer specific settings behaviors.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_SETTINGS_VO_H
+#define LL_SETTINGS_VO_H
+
+#include "llsettingsbase.h"
+#include "llsettingssky.h"
+#include "llsettingswater.h"
+#include "llsettingsdaycycle.h"
+
+class LLSettingsVOSky : public LLSettingsSky
+{
+public:
+    LLSettingsVOSky(const LLSD &data);
+
+    static ptr_t    buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings);
+    static ptr_t    buildDefaultSky();
+    virtual ptr_t   buildClone();
+
+protected:
+    LLSettingsVOSky();
+
+    virtual void updateSettings();
+
+    virtual void        applySpecial(void *);
+
+    virtual parammapping_t getParameterMap() const;
+
+};
+
+//=========================================================================
+class LLSettingsVOWater : public LLSettingsWater
+{
+public:
+    LLSettingsVOWater(const LLSD &data);
+
+    static ptr_t    buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings);
+    static ptr_t    buildDefaultWater();
+    virtual ptr_t   buildClone();
+
+protected:
+    LLSettingsVOWater();
+
+    virtual void updateSettings();
+    virtual void applySpecial(void *);
+
+    virtual parammapping_t getParameterMap() const;
+
+
+private:
+    static const F32 WATER_FOG_LIGHT_CLAMP;
+
+};
+
+//=========================================================================
+class LLSettingsVODay : public LLSettingsDay
+{
+public:
+    LLSettingsVODay(const LLSD &data);
+
+    static ptr_t    buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings);
+    static ptr_t    buildFromLegacyMessage(const LLUUID &regionId, LLSD daycycle, LLSD skys, LLSD water);
+    static ptr_t    buildDefaultDayCycle();
+    virtual ptr_t   buildClone();
+
+    virtual LLSettingsSkyPtr_t      getDefaultSky() const;
+    virtual LLSettingsWaterPtr_t    getDefaultWater() const;
+    virtual LLSettingsSkyPtr_t      buildSky(LLSD) const;
+    virtual LLSettingsWaterPtr_t    buildWater(LLSD) const;
+    virtual LLSettingsSkyPtr_t      getNamedSky(const std::string &) const;
+    virtual LLSettingsWaterPtr_t    getNamedWater(const std::string &) const;
+
+protected:
+    LLSettingsVODay();
+};
+
+
+#endif
-- 
GitLab