diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index 61e31df663869d89f9dcb0bef8a32ab72b3d6f38..0093d84cef4470a59626f860901ab116a041c7f1 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -510,9 +510,9 @@ LLSettingsSky::validation_list_t LLSettingsSky::validationList()
                 LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
                 LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
         validation.push_back(Validator(SETTING_DENSITY_MULTIPLIER,  false,  LLSD::TypeReal,  
-            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0001f)(2.0f)))));
         validation.push_back(Validator(SETTING_DISTANCE_MULTIPLIER, false,  LLSD::TypeReal,  
-            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1000.0f)))));
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0001f)(1000.0f)))));
 
 
         validation.push_back(Validator(SETTING_BLOOM_TEXTUREID,     true,  LLSD::TypeUUID));
@@ -870,7 +870,7 @@ LLSD LLSettingsSky::translateLegacySettings(const LLSD& legacy)
         // original WL moon dir was diametrically opposed to the sun dir
         LLQuaternion moonquat = convert_azimuth_and_altitude_to_quat(azimuth + F_PI, -altitude);
 
-        newsettings[SETTING_SUN_ROTATION] = sunquat.getValue();
+        newsettings[SETTING_SUN_ROTATION]  = sunquat.getValue();
         newsettings[SETTING_MOON_ROTATION] = moonquat.getValue();
     }
 
@@ -943,6 +943,19 @@ LLVector3 LLSettingsSky::getLightDirection() const
     return LLVector3::z_axis;
 }
 
+LLColor3 LLSettingsSky::getAmbientColor() const
+{
+    if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_AMBIENT))
+    {
+        return LLColor3(mSettings[SETTING_LEGACY_HAZE][SETTING_AMBIENT]);
+    }
+    if (mSettings.has(SETTING_AMBIENT))
+    {
+        return LLColor3(mSettings[SETTING_AMBIENT]);
+    }
+    return LLColor3(0.25f, 0.25f, 0.25f);
+}
+
 LLColor3 LLSettingsSky::getBlueDensity() const
 {
     if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_BLUE_DENSITY))
@@ -1025,17 +1038,23 @@ void LLSettingsSky::setMieAnisotropy(F32 aniso_factor)
 
 void LLSettingsSky::setSkyMoistureLevel(F32 moisture_level)
 {
-    mSettings[SETTING_SKY_MOISTURE_LEVEL] = moisture_level;
+    setValue(SETTING_SKY_MOISTURE_LEVEL, moisture_level);
 }
 
 void LLSettingsSky::setSkyDropletRadius(F32 radius)
 {
-    mSettings[SETTING_SKY_DROPLET_RADIUS] = radius;
+    setValue(SETTING_SKY_DROPLET_RADIUS,radius);
 }
 
 void LLSettingsSky::setSkyIceLevel(F32 ice_level)
 {
-    mSettings[SETTING_SKY_ICE_LEVEL] = ice_level;
+    setValue(SETTING_SKY_ICE_LEVEL, ice_level);
+}
+
+void LLSettingsSky::setAmbientColor(const LLColor3 &val)
+{
+    mSettings[SETTING_LEGACY_HAZE][SETTING_AMBIENT] = val.getValue();
+    setDirtyFlag(true);
 }
 
 void LLSettingsSky::setBlueDensity(const LLColor3 &val)
@@ -1342,16 +1361,6 @@ LLUUID LLSettingsSky::getHaloTextureId() const
 }
 
 //---------------------------------------------------------------------
-LLColor3 LLSettingsSky::getAmbientColor() const
-{
-    return LLColor3(mSettings[SETTING_AMBIENT]);
-}
-
-void LLSettingsSky::setAmbientColor(const LLColor3 &val)
-{
-    setValue(SETTING_AMBIENT, val);
-}
-
 LLColor3 LLSettingsSky::getCloudColor() const
 {
     return LLColor3(mSettings[SETTING_CLOUD_COLOR]);
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 8e55ae395a6153d6541fde7db59d311912ddd1be..f13265ae84e92624326a1000a5b2be851781e698 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -1,1343 +1,1381 @@
-/**
-* @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 <cstdio>
-#include <boost/make_shared.hpp>
-#include "lltrace.h"
-#include "llfasttimer.h"
-#include "v3colorutil.h"
-
-#include "llglslshader.h"
-#include "llviewershadermgr.h"
-
-#include "llagent.h"
-#include "llassettype.h"
-#include "llfloaterperms.h"
-#include "llnotificationsutil.h"
-
-#include "llviewerregion.h"
-#include "llviewerassetupload.h"
-#include "llviewerinventory.h"
-
-#include "llenvironment.h"
-#include "llsky.h"
-
-#include "llpermissions.h"
-
-#include "llinventorymodel.h"
-#include "llassetstorage.h"
-#include "llvfile.h"
-#include "lldrawpoolwater.h"
-
-#include <boost/algorithm/string/replace.hpp>
-#include "llinventoryobserver.h"
-#include "llinventorydefines.h"
-
-#undef  VERIFY_LEGACY_CONVERSION
-
-//=========================================================================
-namespace 
-{
-    LLSD ensure_array_4(LLSD in, F32 fill);
-    LLSD read_legacy_preset_data(const std::string &name, const std::string& path);
-
-    //-------------------------------------------------------------------------
-    class LLSettingsInventoryCB : public LLInventoryCallback
-    {
-    public:
-        typedef std::function<void(const LLUUID &)> callback_t;
-
-        LLSettingsInventoryCB(callback_t cbfn) :
-            mCbfn(cbfn)
-        { }
-
-        void fire(const LLUUID& inv_item) override  { if (mCbfn) mCbfn(inv_item); }
-
-    private:
-        callback_t  mCbfn;
-    };
-
-    //-------------------------------------------------------------------------
-}
-
-
-//=========================================================================
-void LLSettingsVOBase::createNewInventoryItem(LLSettingsType::type_e stype, const LLUUID &parent_id, inventory_result_fn callback)
-{
-    LLTransactionID tid;
-    U32 nextOwnerPerm = LLFloaterPerms::getNextOwnerPerms("Settings");
-    nextOwnerPerm |= PERM_COPY;
-
-    if (!LLEnvironment::instance().isInventoryEnabled())
-    {
-        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
-        LLNotificationsUtil::add("SettingsUnsuported");
-        return;
-    }
-
-    tid.generate();
-
-    LLPointer<LLInventoryCallback> cb = new LLSettingsInventoryCB([callback](const LLUUID &inventoryId) {
-        LLSettingsVOBase::onInventoryItemCreated(inventoryId, LLSettingsBase::ptr_t(), callback);
-    });
-
-    create_inventory_settings(gAgent.getID(), gAgent.getSessionID(),
-        parent_id, LLTransactionID::tnull,
-        LLSettingsType::getDefaultName(stype), "",
-        stype, nextOwnerPerm, cb);
-}
-
-
-void LLSettingsVOBase::createInventoryItem(const LLSettingsBase::ptr_t &settings, const LLUUID &parent_id, std::string settings_name, inventory_result_fn callback)
-{
-    LLTransactionID tid;
-    U32             nextOwnerPerm = LLPermissions::DEFAULT.getMaskNextOwner();
-
-    if (!LLEnvironment::instance().isInventoryEnabled())
-    {
-        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
-        LLNotificationsUtil::add("SettingsUnsuported");
-        return;
-    }
-
-    tid.generate();
-
-    LLPointer<LLInventoryCallback> cb = new LLSettingsInventoryCB([settings, callback](const LLUUID &inventoryId) {
-            LLSettingsVOBase::onInventoryItemCreated(inventoryId, settings, callback);
-        });
-
-    if (settings_name.empty())
-    {
-        settings_name = settings->getName();
-    }
-    create_inventory_settings(gAgent.getID(), gAgent.getSessionID(),
-        parent_id, tid,
-        settings_name, "",
-        settings->getSettingsTypeValue(), nextOwnerPerm, cb);
-}
-
-void LLSettingsVOBase::onInventoryItemCreated(const LLUUID &inventoryId, LLSettingsBase::ptr_t settings, inventory_result_fn callback)
-{
-    if (!settings)
-    {   // The item was created as new with no settings passed in.  Simulator should have given it the default for the type... check ID, 
-        // no need to upload asset.
-        LLUUID asset_id;
-        LLViewerInventoryItem *pitem = gInventory.getItem(inventoryId);
-
-        if (pitem)
-        {
-            asset_id = pitem->getAssetUUID();
-        }
-        if (callback)
-            callback(asset_id, inventoryId, LLUUID::null, LLSD());
-        return;
-    }
-    // We need to update some inventory stuff here.... maybe.
-    updateInventoryItem(settings, inventoryId, callback, false);
-}
-
-void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID inv_item_id, inventory_result_fn callback, bool update_name)
-{
-    const LLViewerRegion* region = gAgent.getRegion();
-    if (!region)
-    {
-        LL_WARNS("SETTINGS") << "Not connected to a region, cannot save setting." << LL_ENDL;
-        return;
-    }
-
-    std::string agent_url(region->getCapability("UpdateSettingsAgentInventory"));
-
-    if (!LLEnvironment::instance().isInventoryEnabled())
-    {
-        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
-        LLNotificationsUtil::add("SettingsUnsuported");
-        return;
-    }
-
-    LLViewerInventoryItem *inv_item = gInventory.getItem(inv_item_id);
-    if (inv_item)
-    {
-        bool need_update(false);
-        LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
-
-        if (settings->getFlag(LLSettingsBase::FLAG_NOTRANS) && new_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
-        {
-            LLPermissions perm(inv_item->getPermissions());
-            perm.setBaseBits(LLUUID::null, FALSE, PERM_TRANSFER);
-            perm.setOwnerBits(LLUUID::null, FALSE, PERM_TRANSFER);
-            new_item->setPermissions(perm);
-            need_update |= true;
-        }
-        if (update_name && (settings->getName() != new_item->getName()))
-        {
-            new_item->rename(settings->getName());
-            settings->setName(new_item->getName()); // account for corrections
-            need_update |= true;
-        }
-        if (need_update)
-        {
-            new_item->updateServer(FALSE);
-            gInventory.updateItem(new_item);
-            gInventory.notifyObservers();
-        }
-    }
-
-    std::stringstream buffer; 
-    LLSD settingdata(settings->getSettings());
-    LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION);
-
-    LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(), 
-        [settings, callback](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response) {
-            LLSettingsVOBase::onAgentAssetUploadComplete(itemId, newAssetId, newItemId, response, settings, callback);
-        });
-
-    LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
-}
-
-void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID object_id, LLUUID inv_item_id, inventory_result_fn callback)
-{
-    const LLViewerRegion* region = gAgent.getRegion();
-    if (!region)
-    {
-        LL_WARNS("SETTINGS") << "Not connected to a region, cannot save setting." << LL_ENDL;
-        return;
-    }
-
-    std::string agent_url(region->getCapability("UpdateSettingsAgentInventory"));
-
-    if (!LLEnvironment::instance().isInventoryEnabled())
-    {
-        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
-        LLNotificationsUtil::add("SettingsUnsuported");
-        return;
-    }
-
-    std::stringstream buffer;
-    LLSD settingdata(settings->getSettings());
-
-    LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION);
-
-    LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(object_id, inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(),
-        [settings, callback](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) {
-        LLSettingsVOBase::onTaskAssetUploadComplete(itemId, taskId, newAssetId, response, settings, callback);
-    });
-
-    LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
-}
-
-void LLSettingsVOBase::onAgentAssetUploadComplete(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback)
-{
-    LL_INFOS("SETTINGS") << "itemId:" << itemId << " newAssetId:" << newAssetId << " newItemId:" << newItemId << " response:" << response << LL_ENDL;
-    psettings->setAssetId(newAssetId);
-    if (callback)
-        callback( newAssetId, itemId, LLUUID::null, response );
-
-#if 0
-    std::string exprtFile = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + newAssetId.asString() + ".llsd";
-
-    LLSettingsVOBase::exportFile(psettings, exprtFile, LLSDSerialize::LLSD_NOTATION);
-
-    LL_WARNS("LAPRAS") << "SETTINGS File written as: '" << exprtFile << "'" << LL_ENDL;
-#endif
-}
-
-void LLSettingsVOBase::onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback)
-{
-    LL_INFOS("SETTINGS") << "Upload to task complete!" << LL_ENDL;
-    psettings->setAssetId(newAssetId);
-    if (callback)
-        callback(newAssetId, itemId, taskId, response);
-}
-
-
-void LLSettingsVOBase::getSettingsAsset(const LLUUID &assetId, LLSettingsVOBase::asset_download_fn callback)
-{
-    gAssetStorage->getAssetData(assetId, LLAssetType::AT_SETTINGS,
-        [callback](LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType, void *, S32 status, LLExtStat ext_status) 
-            { onAssetDownloadComplete(vfs, asset_id, status, ext_status, callback); },
-        nullptr, true);
-
-}
-
-void LLSettingsVOBase::onAssetDownloadComplete(LLVFS *vfs, const LLUUID &asset_id, S32 status, LLExtStat ext_status, LLSettingsVOBase::asset_download_fn callback)
-{
-    LLSettingsBase::ptr_t settings;
-    if (!status)
-    {
-        LLVFile file(vfs, asset_id, LLAssetType::AT_SETTINGS, LLVFile::READ);
-        S32 size = file.getSize();
-
-        std::string buffer(size + 1, '\0');
-        file.read((U8 *)buffer.data(), size);
-
-        std::stringstream llsdstream(buffer);
-        LLSD llsdsettings;
-
-        if (LLSDSerialize::deserialize(llsdsettings, llsdstream, -1))
-        {
-            settings = createFromLLSD(llsdsettings);
-        }
-
-        if (!settings)
-        {
-            status = 1;
-            LL_WARNS("SETTINGS") << "Unable to create settings object." << LL_ENDL;
-        }
-        else
-        {
-            LL_WARNS("LAPRAS") << "Setting asset ID to " << asset_id << LL_ENDL;
-            settings->setAssetId(asset_id);
-        }
-    }
-    else
-    {
-        LL_WARNS("SETTINGS") << "Error retrieving asset " << asset_id << ". Status code=" << status << "(" << LLAssetStorage::getErrorString(status) << ") ext_status=" << ext_status << LL_ENDL;
-    }
-    if (callback)
-        callback(asset_id, settings, status, ext_status);
-}
-
-void LLSettingsVOBase::getSettingsInventory(const LLUUID &inventoryId, inventory_download_fn callback)
-{
-
-}
-
-bool LLSettingsVOBase::exportFile(const LLSettingsBase::ptr_t &settings, const std::string &filename, LLSDSerialize::ELLSD_Serialize format)
-{
-    try
-    {
-        std::ofstream file(filename, std::ios::out | std::ios::trunc);
-        file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
-
-        if (!file)
-        {
-            LL_WARNS("SETTINGS") << "Unable to open '" << filename << "' for writing." << LL_ENDL;
-            return false;
-        }
-
-        LLSDSerialize::serialize(settings->getSettings(), file, format);
-    }
-    catch (const std::ios_base::failure &e)
-    {
-        LL_WARNS("SETTINGS") << "Unable to save settings to file '" << filename << "': " << e.what() << LL_ENDL;
-        return false;
-    }
-
-    return true;
-}
-
-LLSettingsBase::ptr_t LLSettingsVOBase::importFile(const std::string &filename)
-{
-    LLSD settings;
-
-    try
-    {
-        std::ifstream file(filename, std::ios::in);
-        file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
-
-        if (!file)
-        {
-            LL_WARNS("SETTINGS") << "Unable to open '" << filename << "' for reading." << LL_ENDL;
-            return LLSettingsBase::ptr_t();
-        }
-
-        if (!LLSDSerialize::deserialize(settings, file, -1))
-        {
-            LL_WARNS("SETTINGS") << "Unable to deserialize settings from '" << filename << "'" << LL_ENDL;
-            return LLSettingsBase::ptr_t();
-        }
-    }
-    catch (const std::ios_base::failure &e)
-    {
-        LL_WARNS("SETTINGS") << "Unable to save settings to file '" << filename << "': " << e.what() << LL_ENDL;
-        return LLSettingsBase::ptr_t();
-    }
-
-    return createFromLLSD(settings);
-}
-
-LLSettingsBase::ptr_t LLSettingsVOBase::createFromLLSD(const LLSD &settings)
-{
-    if (!settings.has(SETTING_TYPE))
-    {
-        LL_WARNS("SETTINGS") << "No settings type in LLSD" << LL_ENDL;
-        return LLSettingsBase::ptr_t();
-    }
-
-    std::string settingtype = settings[SETTING_TYPE].asString();
-
-    LLSettingsBase::ptr_t psetting;
-
-    if (settingtype == "water")
-    {
-        return LLSettingsVOWater::buildWater(settings);
-    }
-    else if (settingtype == "sky")
-    {
-        return LLSettingsVOSky::buildSky(settings);
-    }
-    else if (settingtype == "daycycle")
-    {
-        return LLSettingsVODay::buildDay(settings);
-    }
-
-    LL_WARNS("SETTINGS") << "Unable to determine settings type for '" << settingtype << "'." << LL_ENDL;
-    return LLSettingsBase::ptr_t();
-
-}
-
-//=========================================================================
-LLSettingsVOSky::LLSettingsVOSky(const LLSD &data, bool isAdvanced)
-: LLSettingsSky(data)
-, m_isAdvanced(isAdvanced)
-{
-}
-
-LLSettingsVOSky::LLSettingsVOSky()
-: LLSettingsSky()
-, m_isAdvanced(false)
-{
-}
-
-//-------------------------------------------------------------------------
-LLSettingsSky::ptr_t LLSettingsVOSky::buildSky(LLSD settings)
-{
-    LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
-
-    LLSD results = LLSettingsBase::settingValidation(settings, validations);
-
-    if (!results["success"].asBoolean())
-    {
-        LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
-        LLSettingsSky::ptr_t();
-    }
-
-    return std::make_shared<LLSettingsVOSky>(settings, true);
-}
-
-
-LLSettingsSky::ptr_t LLSettingsVOSky::buildFromLegacyPreset(const std::string &name, const LLSD &legacy)
-{
-
-    LLSD newsettings = LLSettingsSky::translateLegacySettings(legacy);
-
-    newsettings[SETTING_NAME] = name;
-
-    LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
-    LLSD results = LLSettingsBase::settingValidation(newsettings, validations);
-    if (!results["success"].asBoolean())
-    {
-        LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
-        LLSettingsSky::ptr_t();
-    }
-
-    LLSettingsSky::ptr_t skyp = std::make_shared<LLSettingsVOSky>(newsettings);
-
-#ifdef VERIFY_LEGACY_CONVERSION
-    LLSD oldsettings = LLSettingsVOSky::convertToLegacy(skyp, isAdvanced());
-
-    if (!llsd_equals(legacy, oldsettings))
-    {
-        LL_WARNS("SKY") << "Conversion to/from legacy does not match!\n" 
-            << "Old: " << legacy
-            << "new: " << oldsettings << LL_ENDL;
-    }
-
-#endif
-
-    return skyp;
-}
-
-LLSettingsSky::ptr_t LLSettingsVOSky::buildFromLegacyPresetFile(const std::string &name, const std::string &path)
-{
-    LLSD legacy_data = read_legacy_preset_data(name, path);
-
-    if (!legacy_data)
-    {
-        LL_WARNS("SETTINGS") << "Could not load legacy Windlight \"" << name << "\" from " << path << LL_ENDL;
-        return ptr_t();
-    }
-
-    return buildFromLegacyPreset(name, legacy_data);
-}
-
-
-LLSettingsSky::ptr_t LLSettingsVOSky::buildDefaultSky()
-{
-    static LLSD default_settings;
-
-    if (!default_settings.size())
-    {
-        default_settings = LLSettingsSky::defaults();
-
-        default_settings[SETTING_NAME] = std::string("_default_");
-
-        LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
-        LLSD results = LLSettingsBase::settingValidation(default_settings, validations);
-        if (!results["success"].asBoolean())
-        {
-            LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
-            LLSettingsSky::ptr_t();
-        }
-    }
-
-    LLSettingsSky::ptr_t skyp = std::make_shared<LLSettingsVOSky>(default_settings);
-    return skyp;
-}
-
-LLSettingsSky::ptr_t LLSettingsVOSky::buildClone() const
-{
-    LLSD settings = cloneSettings();
-
-    LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
-    LLSD results = LLSettingsBase::settingValidation(settings, validations);
-    if (!results["success"].asBoolean())
-    {
-        LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
-        LLSettingsSky::ptr_t();
-    }
-
-    LLSettingsSky::ptr_t skyp = std::make_shared<LLSettingsVOSky>(settings);
-    return skyp;
-}
-
-void LLSettingsVOSky::convertAtmosphericsToLegacy(LLSD& legacy, LLSD& settings)
-{
-    // These will need to be inferred from new settings' density profiles
-    if (settings.has(SETTING_LEGACY_HAZE))
-    {
-        LLSD legacyhaze = settings[SETTING_LEGACY_HAZE];
-        legacy[SETTING_AMBIENT]             = ensure_array_4(legacyhaze[SETTING_AMBIENT], 1.0f);
-        legacy[SETTING_BLUE_DENSITY]        = ensure_array_4(legacyhaze[SETTING_BLUE_DENSITY], 1.0);
-        legacy[SETTING_BLUE_HORIZON]        = ensure_array_4(legacyhaze[SETTING_BLUE_HORIZON], 1.0);
-        legacy[SETTING_DENSITY_MULTIPLIER]  = LLSDArray(legacyhaze[SETTING_DENSITY_MULTIPLIER].asReal())(0.0f)(0.0f)(1.0f);
-        legacy[SETTING_DISTANCE_MULTIPLIER] = LLSDArray(legacyhaze[SETTING_DISTANCE_MULTIPLIER].asReal())(0.0f)(0.0f)(1.0f);
-        legacy[SETTING_HAZE_DENSITY]        = LLSDArray(legacyhaze[SETTING_HAZE_DENSITY])(0.0f)(0.0f)(1.0f);
-        legacy[SETTING_HAZE_HORIZON]        = LLSDArray(legacyhaze[SETTING_HAZE_HORIZON])(0.0f)(0.0f)(1.0f);
-    }
-}
-
-LLSD LLSettingsVOSky::convertToLegacy(const LLSettingsSky::ptr_t &psky, bool isAdvanced)
-{
-    LLSD legacy(LLSD::emptyMap());
-    LLSD settings = psky->getSettings();
-    
-    convertAtmosphericsToLegacy(legacy, settings);
-
-    legacy[SETTING_CLOUD_COLOR] = ensure_array_4(settings[SETTING_CLOUD_COLOR], 1.0);
-    legacy[SETTING_CLOUD_POS_DENSITY1] = ensure_array_4(settings[SETTING_CLOUD_POS_DENSITY1], 1.0);
-    legacy[SETTING_CLOUD_POS_DENSITY2] = ensure_array_4(settings[SETTING_CLOUD_POS_DENSITY2], 1.0);
-    legacy[SETTING_CLOUD_SCALE] = LLSDArray(settings[SETTING_CLOUD_SCALE])(LLSD::Real(0.0))(LLSD::Real(0.0))(LLSD::Real(1.0));       
-    legacy[SETTING_CLOUD_SCROLL_RATE] = settings[SETTING_CLOUD_SCROLL_RATE];
-    legacy[SETTING_LEGACY_ENABLE_CLOUD_SCROLL] = LLSDArray(LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][0].asReal())))
-        (LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][1].asReal())));     
-    legacy[SETTING_CLOUD_SHADOW] = LLSDArray(settings[SETTING_CLOUD_SHADOW].asReal())(0.0f)(0.0f)(1.0f);    
-    legacy[SETTING_GAMMA] = LLSDArray(settings[SETTING_GAMMA])(0.0f)(0.0f)(1.0f);
-    legacy[SETTING_GLOW] = ensure_array_4(settings[SETTING_GLOW], 1.0);
-    legacy[SETTING_LIGHT_NORMAL] = ensure_array_4(psky->getLightDirection().getValue(), 0.0f);
-    legacy[SETTING_MAX_Y] = LLSDArray(settings[SETTING_MAX_Y])(0.0f)(0.0f)(1.0f);
-    legacy[SETTING_STAR_BRIGHTNESS] = settings[SETTING_STAR_BRIGHTNESS];
-    legacy[SETTING_SUNLIGHT_COLOR] = ensure_array_4(settings[SETTING_SUNLIGHT_COLOR], 1.0f);
-    
-    LLQuaternion sunquat = psky->getSunRotation();
-
-    F32 roll;
-    F32 pitch;
-    F32 yaw;
-
-    // get euler angles in right-handed X right, Y up, Z at
-    sunquat.getEulerAngles(&roll, &pitch, &yaw);
-    
-    legacy[SETTING_LEGACY_EAST_ANGLE] = yaw;
-    legacy[SETTING_LEGACY_SUN_ANGLE]  = -pitch;
-
-    return legacy;    
-}
-
-//-------------------------------------------------------------------------
-void LLSettingsVOSky::updateSettings()
-{
-    LLSettingsSky::updateSettings();
-    LLVector3 sun_direction  = getSunDirection();
-    LLVector3 moon_direction = getMoonDirection();
-
-    F32 dp = getLightDirection() * LLVector3(0.0f, 0.0f, 1.0f);
-	if (dp < 0)
-	{
-		dp = 0;
-	}
-    dp = llmax(dp, 0.1f);
-
-	// Since WL scales everything by 2, there should always be at least a 2:1 brightness ratio
-	// between sunlight and point lights in windlight to normalize point lights.
-	F32 sun_dynamic_range = llmax(gSavedSettings.getF32("RenderSunDynamicRange"), 0.0001f);
-    mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp);
-
-    gSky.setSunAndMoonDirectionsCFR(sun_direction, moon_direction);
-    gSky.setSunTextures(getSunTextureId(), getNextSunTextureId());
-    gSky.setMoonTextures(getMoonTextureId(), getNextMoonTextureId());
-    gSky.setCloudNoiseTextures(getCloudNoiseTextureId(), getNextCloudNoiseTextureId());
-    gSky.setBloomTextures(getBloomTextureId(), getNextBloomTextureId());
-
-    gSky.setSunScale(getSunScale());
-    gSky.setMoonScale(getMoonScale());
-}
-
-void LLSettingsVOSky::applySpecial(void *ptarget)
-{
-    LLGLSLShader *shader = (LLGLSLShader *)ptarget;
-
-    LLVector4 light_direction = LLEnvironment::instance().getClampedSunNorm();
-
-    if (shader->mShaderGroup == LLGLSLShader::SG_DEFAULT)
-	{        
-        shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV);
-		shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
-	} 
-	else if (shader->mShaderGroup == LLGLSLShader::SG_SKY)
-	{
-        shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV);        
-
-        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);
-	}
-
-    shader->uniform1f(LLShaderMgr::SCENE_LIGHT_STRENGTH, mSceneLightStrength);
-    shader->uniform4f(LLShaderMgr::GAMMA, getGamma(), 0.0, 0.0, 1.0);
-}
-
-LLSettingsSky::parammapping_t LLSettingsVOSky::getParameterMap() const
-{
-    static parammapping_t param_map;
-
-    if (param_map.empty())
-    {
-// LEGACY_ATMOSPHERICS
-        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_HAZE_DENSITY] = LLShaderMgr::HAZE_DENSITY;
-        param_map[SETTING_HAZE_HORIZON] = LLShaderMgr::HAZE_HORIZON;
-        param_map[SETTING_DENSITY_MULTIPLIER] = LLShaderMgr::DENSITY_MULTIPLIER;
-        param_map[SETTING_DISTANCE_MULTIPLIER] = LLShaderMgr::DISTANCE_MULTIPLIER;
-
-        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_CLOUD_VARIANCE] = LLShaderMgr::CLOUD_VARIANCE;
-        param_map[SETTING_GLOW] = LLShaderMgr::GLOW;        
-        param_map[SETTING_MAX_Y] = LLShaderMgr::MAX_Y;
-        param_map[SETTING_SUNLIGHT_COLOR] = LLShaderMgr::SUNLIGHT_COLOR;
-        param_map[SETTING_MOON_BRIGHTNESS] = LLShaderMgr::MOON_BRIGHTNESS;
-        param_map[SETTING_SKY_MOISTURE_LEVEL] = LLShaderMgr::MOISTURE_LEVEL;
-        param_map[SETTING_SKY_DROPLET_RADIUS] = LLShaderMgr::DROPLET_RADIUS;
-        param_map[SETTING_SKY_ICE_LEVEL] = LLShaderMgr::ICE_LEVEL;
-
-// AdvancedAtmospherics TODO
-// Provide mappings for new shader params here
-    }
-
-    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::buildWater(LLSD settings)
-{
-    LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
-    LLSD results = LLSettingsWater::settingValidation(settings, validations);
-    if (!results["success"].asBoolean())
-    {
-        LL_WARNS("SETTINGS") << "Water setting validation failed!\n" << results << LL_ENDL;
-        LLSettingsWater::ptr_t();
-    }
-
-    return std::make_shared<LLSettingsVOWater>(settings);
-}
-
-//-------------------------------------------------------------------------
-LLSettingsWater::ptr_t LLSettingsVOWater::buildFromLegacyPreset(const std::string &name, const LLSD &legacy)
-{
-    LLSD newsettings(LLSettingsWater::translateLegacySettings(legacy));
-
-    newsettings[SETTING_NAME] = name; 
-    LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
-    LLSD results = LLSettingsWater::settingValidation(newsettings, validations);
-    if (!results["success"].asBoolean())
-    {
-        LL_WARNS("SETTINGS") << "Water setting validation failed!: " << results << LL_ENDL;
-        return LLSettingsWater::ptr_t();
-    }
-
-    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(newsettings);
-
-#ifdef VERIFY_LEGACY_CONVERSION
-    LLSD oldsettings = LLSettingsVOWater::convertToLegacy(waterp);
-
-    if (!llsd_equals(legacy, oldsettings))
-    {
-        LL_WARNS("WATER") << "Conversion to/from legacy does not match!\n"
-            << "Old: " << legacy
-            << "new: " << oldsettings << LL_ENDL;
-    }
-
-#endif
-    return waterp;
-}
-
-LLSettingsWater::ptr_t LLSettingsVOWater::buildFromLegacyPresetFile(const std::string &name, const std::string &path)
-{
-    LLSD legacy_data = read_legacy_preset_data(name, path);
-
-    if (!legacy_data)
-    {
-        LL_WARNS("SETTINGS") << "Could not load legacy Windlight \"" << name << "\" from " << path << LL_ENDL;
-        return ptr_t();
-    }
-
-    return buildFromLegacyPreset(name, legacy_data);
-}
-
-
-LLSettingsWater::ptr_t LLSettingsVOWater::buildDefaultWater()
-{
-    static LLSD default_settings;
-
-    if (!default_settings.size())
-    {
-        default_settings = LLSettingsWater::defaults();
-
-        default_settings[SETTING_NAME] = std::string("_default_");
-
-        LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
-        LLSD results = LLSettingsWater::settingValidation(default_settings, validations);
-        if (!results["success"].asBoolean())
-        {
-            LL_WARNS("SETTINGS") << "Water setting validation failed!: " << results << LL_ENDL;
-            return LLSettingsWater::ptr_t();
-        }
-    }
-
-    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(default_settings);
-
-    return waterp;
-}
-
-LLSettingsWater::ptr_t LLSettingsVOWater::buildClone() const
-{
-    LLSD settings = cloneSettings();
-    LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
-    LLSD results = LLSettingsWater::settingValidation(settings, validations);
-    if (!results["success"].asBoolean())
-    {
-        LL_WARNS("SETTINGS") << "Water setting validation failed!: " << results << LL_ENDL;
-        return LLSettingsWater::ptr_t();
-    }
-
-    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(settings);
-
-    return waterp;
-}
-
-LLSD LLSettingsVOWater::convertToLegacy(const LLSettingsWater::ptr_t &pwater)
-{
-    LLSD legacy(LLSD::emptyMap());
-    LLSD settings = pwater->getSettings();
-
-    legacy[SETTING_LEGACY_BLUR_MULTIPLIER] = settings[SETTING_BLUR_MULTIPLIER];
-    legacy[SETTING_LEGACY_FOG_COLOR] = ensure_array_4(settings[SETTING_FOG_COLOR], 1.0f);
-    legacy[SETTING_LEGACY_FOG_DENSITY] = settings[SETTING_FOG_DENSITY];
-    legacy[SETTING_LEGACY_FOG_MOD] = settings[SETTING_FOG_MOD];
-    legacy[SETTING_LEGACY_FRESNEL_OFFSET] = settings[SETTING_FRESNEL_OFFSET];
-    legacy[SETTING_LEGACY_FRESNEL_SCALE] = settings[SETTING_FRESNEL_SCALE];
-    legacy[SETTING_LEGACY_NORMAL_MAP] = settings[SETTING_NORMAL_MAP];
-    legacy[SETTING_LEGACY_NORMAL_SCALE] = settings[SETTING_NORMAL_SCALE];
-    legacy[SETTING_LEGACY_SCALE_ABOVE] = settings[SETTING_SCALE_ABOVE];
-    legacy[SETTING_LEGACY_SCALE_BELOW] = settings[SETTING_SCALE_BELOW];
-    legacy[SETTING_LEGACY_WAVE1_DIR] = settings[SETTING_WAVE1_DIR];
-    legacy[SETTING_LEGACY_WAVE2_DIR] = settings[SETTING_WAVE2_DIR];
-    
-    //_WARNS("LAPRAS") << "Legacy water: " << legacy << LL_ENDL;
-    return legacy;
-}
-//-------------------------------------------------------------------------
-//-------------------------------------------------------------------------
-void LLSettingsVOWater::applySpecial(void *ptarget)
-{
-    LLGLSLShader *shader = (LLGLSLShader *)ptarget;
-
-    if (shader->mShaderGroup == LLGLSLShader::SG_WATER)
-	{
-        //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);
-
-        LLVector4 waterPlane(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
-
-        shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, waterPlane.mV);
-
-        LLVector4 light_direction = LLEnvironment::instance().getClampedLightNorm();
-
-        F32 waterFogKS = 1.f / llmax(light_direction.mV[2], WATER_FOG_LIGHT_CLAMP);
-
-        shader->uniform1f(LLShaderMgr::WATER_FOGKS, waterFogKS);
-
-        F32 blend_factor = LLEnvironment::instance().getCurrentWater()->getBlendFactor();
-        shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
-
-        LLVector4 rotated_light_direction = LLEnvironment::instance().getRotatedLightNorm();
-        shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV);
-        shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
-        shader->uniform1f(LLViewerShaderMgr::DISTANCE_MULTIPLIER, 0);
-    }
-}
-
-void LLSettingsVOWater::updateSettings()
-{
-    // base class clears dirty flag so as to not trigger recursive update
-    LLSettingsBase::updateSettings();
-
-    LLDrawPoolWater* pwaterpool = (LLDrawPoolWater*)gPipeline.getPool(LLDrawPool::POOL_WATER);
-    if (pwaterpool)
-    {
-        pwaterpool->setTransparentTextures(getTransparentTextureID(), getNextTransparentTextureID());
-        pwaterpool->setOpaqueTexture(GetDefaultOpaqueTextureAssetId());
-        pwaterpool->setNormalMaps(getNormalMapID(), getNextNormalMapID());
-    }
-}
-
-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::buildDay(LLSD settings)
-{
-    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
-    LLSD results = LLSettingsDay::settingValidation(settings, validations);
-    if (!results["success"].asBoolean())
-    {
-        LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
-        LLSettingsDay::ptr_t();
-    }
-
-    LLSettingsDay::ptr_t pday = std::make_shared<LLSettingsVODay>(settings);
-    if (pday)
-        pday->initialize();
-
-    return pday;
-}
-
-//-------------------------------------------------------------------------
-LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPreset(const std::string &name, const std::string &path, const LLSD &oldsettings)
-{
-    LLSD newsettings(defaults());
-    std::set<std::string> framenames;
-    std::set<std::string> notfound;
-
-    std::string base_path(gDirUtilp->getDirName(path));
-    std::string water_path(base_path);
-    std::string sky_path(base_path);
-
-    gDirUtilp->append(water_path, "water");
-    gDirUtilp->append(sky_path, "skies");
-
-    newsettings[SETTING_NAME] = name;
-
-    LLSD watertrack = LLSDArray(
-        LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))
-        (SETTING_KEYNAME, "water:Default"));
-
-    LLSD skytrack = LLSD::emptyArray();
-
-    for (LLSD::array_const_iterator it = oldsettings.beginArray(); it != oldsettings.endArray(); ++it)
-    {
-        std::string framename = (*it)[1].asString();
-        LLSD entry = LLSDMap(SETTING_KEYKFRAME, (*it)[0].asReal())
-            (SETTING_KEYNAME, "sky:" + framename);
-        framenames.insert(framename);
-        skytrack.append(entry);
-    }
-
-    newsettings[SETTING_TRACKS] = LLSDArray(watertrack)(skytrack);
-
-    LLSD frames(LLSD::emptyMap());
-
-    {
-        LLSettingsWater::ptr_t pwater = LLSettingsVOWater::buildFromLegacyPresetFile("Default", water_path);
-        if (pwater)
-            frames["water:Default"] = pwater->getSettings();
-    }
-
-    for (std::set<std::string>::iterator itn = framenames.begin(); itn != framenames.end(); ++itn)
-    {
-        LLSettingsSky::ptr_t psky = LLSettingsVOSky::buildFromLegacyPresetFile((*itn), sky_path);
-        if (psky)
-            frames["sky:" + (*itn)] = psky->getSettings();
-    }
-
-    newsettings[SETTING_FRAMES] = frames;
-
-    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
-    LLSD results = LLSettingsDay::settingValidation(newsettings, validations);
-    if (!results["success"].asBoolean())
-    {
-        LL_WARNS("SETTINGS") << "Day setting validation failed!: " << results << LL_ENDL;
-        return LLSettingsDay::ptr_t();
-    }
-
-    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(newsettings);
-
-#ifdef VERIFY_LEGACY_CONVERSION
-    LLSD testsettings = LLSettingsVODay::convertToLegacy(dayp);
-
-    if (!llsd_equals(oldsettings, testsettings))
-    {
-        LL_WARNS("DAYCYCLE") << "Conversion to/from legacy does not match!\n" 
-            << "Old: " << oldsettings
-            << "new: " << testsettings << LL_ENDL;
-    }
-
-#endif
-
-    dayp->initialize();
-
-    return dayp;
-}
-
-LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPresetFile(const std::string &name, const std::string &path)
-{
-    LLSD legacy_data = read_legacy_preset_data(name, path);
-
-    if (!legacy_data)
-    {
-        LL_WARNS("SETTINGS") << "Could not load legacy Windlight \"" << name << "\" from " << path << LL_ENDL;
-        return ptr_t();
-    }
-
-    return buildFromLegacyPreset(name, path, legacy_data);
-}
-
-
-
-LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyMessage(const LLUUID &regionId, LLSD daycycle, LLSD skydefs, LLSD waterdef)
-{
-    LLSD frames(LLSD::emptyMap());
-
-    for (LLSD::map_iterator itm = skydefs.beginMap(); itm != skydefs.endMap(); ++itm)
-    {
-        std::string newname = "sky:" + (*itm).first;
-        LLSD newsettings = LLSettingsSky::translateLegacySettings((*itm).second);
-        
-        newsettings[SETTING_NAME] = newname;
-        frames[newname] = newsettings;
-
-        LL_WARNS("SETTINGS") << "created region sky '" << newname << "'" << LL_ENDL;
-    }
-
-    LLSD watersettings = LLSettingsWater::translateLegacySettings(waterdef);
-    std::string watername = "water:"+ watersettings[SETTING_NAME].asString();
-    watersettings[SETTING_NAME] = watername;
-    frames[watername] = watersettings;
-
-    LLSD watertrack = LLSDArray(
-            LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))
-            (SETTING_KEYNAME, watername));
-
-    LLSD skytrack(LLSD::emptyArray());
-    for (LLSD::array_const_iterator it = daycycle.beginArray(); it != daycycle.endArray(); ++it)
-    {
-        LLSD entry = LLSDMap(SETTING_KEYKFRAME, (*it)[0].asReal())
-            (SETTING_KEYNAME, "sky:" + (*it)[1].asString());
-        skytrack.append(entry);
-    }
-
-    LLSD newsettings = LLSDMap
-        ( SETTING_NAME, "Region (legacy)" )
-        ( SETTING_TRACKS, LLSDArray(watertrack)(skytrack))
-        ( SETTING_FRAMES, frames )
-        ( SETTING_TYPE, "daycycle" );
-
-    LL_WARNS("LAPRAS") << "newsettings=" << newsettings << LL_ENDL;
-
-    LLSettingsSky::validation_list_t validations = LLSettingsDay::validationList();
-    LLSD results = LLSettingsDay::settingValidation(newsettings, validations);
-    if (!results["success"].asBoolean())
-    {
-        LL_WARNS("SETTINGS") << "Day setting validation failed!:" << results << LL_ENDL;
-        return LLSettingsDay::ptr_t();
-    }
-
-    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(newsettings);
-    
-    if (dayp)
-    {
-        // true for validation - either validate here, or when cloning for floater.
-        dayp->initialize(true);
-    }
-    return dayp;
-}
-
-
-
-LLSettingsDay::ptr_t LLSettingsVODay::buildDefaultDayCycle()
-{
-    static LLSD default_settings;
-
-    if (!default_settings.size())
-    {
-        default_settings = LLSettingsDay::defaults();
-        default_settings[SETTING_NAME] = std::string("_default_");
-
-        LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
-        LLSD results = LLSettingsDay::settingValidation(default_settings, validations);
-        if (!results["success"].asBoolean())
-        {
-            LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
-            LLSettingsDay::ptr_t();
-        }
-    }
-
-    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(default_settings);
-
-    dayp->initialize();
-    return dayp;
-}
-
-LLSettingsDay::ptr_t LLSettingsVODay::buildFromEnvironmentMessage(LLSD settings)
-{
-    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
-    LLSD results = LLSettingsDay::settingValidation(settings, validations);
-    if (!results["success"].asBoolean())
-    {
-        LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
-        LLSettingsDay::ptr_t();
-    }
-
-    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(settings);
-
-    dayp->initialize();
-    return dayp;
-}
-
-
-void LLSettingsVODay::buildFromOtherSetting(LLSettingsBase::ptr_t settings, LLSettingsVODay::asset_built_fn cb)
-{
-    if (settings->getSettingsType() == "daycycle")
-    {
-        if (cb)
-            cb(std::static_pointer_cast<LLSettingsDay>(settings));
-    }
-    else
-    {
-        LLSettingsVOBase::getSettingsAsset(LLSettingsDay::GetDefaultAssetId(),
-            [settings, cb](LLUUID, LLSettingsBase::ptr_t pday, S32, LLExtStat){ combineIntoDayCycle(std::static_pointer_cast<LLSettingsDay>(pday), settings, cb); });
-    }
-}
-
-void LLSettingsVODay::combineIntoDayCycle(LLSettingsDay::ptr_t pday, LLSettingsBase::ptr_t settings, asset_built_fn cb)
-{
-    if (settings->getSettingsType() == "sky")
-    {
-        pday->setName("sky: " + settings->getName());
-        pday->clearCycleTrack(1);
-        pday->setSettingsAtKeyframe(settings, 0.0, 1);
-    }
-    else if (settings->getSettingsType() == "water")
-    {
-        pday->setName("water: " + settings->getName());
-        pday->clearCycleTrack(0);
-        pday->setSettingsAtKeyframe(settings, 0.0, 0);
-    }
-    else
-    {
-        pday.reset();
-    }
-
-    if (cb)
-        cb(pday);
-}
-
-
-LLSettingsDay::ptr_t LLSettingsVODay::buildClone() const
-{
-    LLSD settings = cloneSettings();
-
-    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
-    LLSD results = LLSettingsDay::settingValidation(settings, validations);
-    if (!results["success"].asBoolean())
-    {
-        LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
-        LLSettingsDay::ptr_t();
-    }
-
-    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(settings);
-
-    U32 flags = getFlags();
-    if (flags)
-        dayp->setFlags(flags);
-
-    dayp->initialize();
-    return dayp;
-}
-
-LLSettingsDay::ptr_t LLSettingsVODay::buildDeepCloneAndUncompress() const
-{
-    // no need for SETTING_TRACKS or SETTING_FRAMES, so take base LLSD
-    LLSD settings = llsd_clone(mSettings);
-
-    LLSettingsDay::ptr_t day_clone = std::make_shared<LLSettingsVODay>(settings);
-
-    for (S32 i = 0; i < LLSettingsDay::TRACK_MAX; ++i)
-    {
-        const LLSettingsDay::CycleTrack_t& track = getCycleTrackConst(i);
-        LLSettingsDay::CycleTrack_t::const_iterator iter = track.begin();
-        while (iter != track.end())
-        {
-            // 'Unpack', usually for editing
-            // - frames 'share' settings multiple times
-            // - settings can reuse LLSDs they were initialized from
-            // We do not want for edited frame to change multiple frames in same track, so do a clone
-            day_clone->setSettingsAtKeyframe(iter->second->buildDerivedClone(), iter->first, i);
-            iter++;
-        }
-    }
-    return day_clone;
-}
-
-LLSD LLSettingsVODay::convertToLegacy(const LLSettingsVODay::ptr_t &pday)
-{
-    CycleTrack_t &trackwater = pday->getCycleTrack(TRACK_WATER);
-
-    LLSettingsWater::ptr_t pwater;
-    if (!trackwater.empty())
-    {
-        pwater = std::static_pointer_cast<LLSettingsWater>((*trackwater.begin()).second);
-    }
-
-    if (!pwater)
-        pwater = LLSettingsVOWater::buildDefaultWater();
-    
-    LLSD llsdwater = LLSettingsVOWater::convertToLegacy(pwater);
-    
-    CycleTrack_t &tracksky = pday->getCycleTrack(1);   // first sky track
-    std::map<std::string, LLSettingsSky::ptr_t> skys;
-    
-    LLSD llsdcycle(LLSD::emptyArray());
-    
-    for(CycleTrack_t::iterator it = tracksky.begin(); it != tracksky.end(); ++it)
-    {
-        size_t hash = (*it).second->getHash();
-        std::stringstream name;
-        
-        name << hash;
-        
-        skys[name.str()] = std::static_pointer_cast<LLSettingsSky>((*it).second);
-        
-        F32 frame = ((tracksky.size() == 1) && (it == tracksky.begin())) ? -1.0f : (*it).first;
-        llsdcycle.append( LLSDArray(LLSD::Real(frame))(name.str()) );
-    }
-    //_WARNS("LAPRAS") << "Cycle created with " << llsdcycle.size() << "entries: " << llsdcycle << LL_ENDL;
-
-    LLSD llsdskylist(LLSD::emptyMap());
-    
-    for (std::map<std::string, LLSettingsSky::ptr_t>::iterator its = skys.begin(); its != skys.end(); ++its)
-    {
-        LLSD llsdsky = LLSettingsVOSky::convertToLegacy((*its).second, false);
-        llsdsky[SETTING_NAME] = (*its).first;
-        
-        llsdskylist[(*its).first] = llsdsky;
-    }
-
-    //_WARNS("LAPRAS") << "Sky map with " << llsdskylist.size() << " entries created: " << llsdskylist << LL_ENDL;
-    
-    return LLSDArray(LLSD::emptyMap())(llsdcycle)(llsdskylist)(llsdwater);
-}
-
-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 = std::make_shared<LLSettingsVOSky>(settings);
-
-    if (skyp->validate())
-        return skyp;
-
-    return LLSettingsSky::ptr_t();
-}
-
-LLSettingsWaterPtr_t LLSettingsVODay::buildWater(LLSD settings) const
-{
-    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(settings);
-
-    if (waterp->validate())
-        return waterp;
-
-    return LLSettingsWater::ptr_t();
-}
-
-//=========================================================================
-namespace
-{
-    LLSD ensure_array_4(LLSD in, F32 fill)
-    {
-        if (in.size() >= 4)
-            return in;
-
-        LLSD out(LLSD::emptyArray());
-
-        for (S32 idx = 0; idx < in.size(); ++idx)
-        {
-            out.append(in[idx]);
-        }
-
-        while (out.size() < 4)
-        {
-            out.append(LLSD::Real(fill));
-        }
-        return out;
-    }
-
-    // This is a disturbing hack
-    std::string legacy_name_to_filename(const std::string &name, bool convertdash = false)
-    {
-        std::string fixedname(LLURI::escape(name));
-
-        if (convertdash)
-            boost::algorithm::replace_all(fixedname, "-", "%2D");
-
-        return fixedname;
-    }
-
-    //---------------------------------------------------------------------
-    LLSD read_legacy_preset_data(const std::string &name, const std::string& path)
-    {
-        llifstream xml_file;
-
-        std::string full_path(path);
-        std::string full_name(name);
-        full_name += ".xml";
-        gDirUtilp->append(full_path, full_name);
-
-        xml_file.open(full_path.c_str());
-        if (!xml_file)
-        {
-            std::string bad_path(full_path);
-            full_path = path;
-            full_name = legacy_name_to_filename(name);
-            full_name += ".xml";
-            gDirUtilp->append(full_path, full_name);
-
-            LL_INFOS("LEGACYSETTING") << "Could not open \"" << bad_path << "\" trying escaped \"" << full_path << "\"" << LL_ENDL;
-
-            xml_file.open(full_path.c_str());
-            if (!xml_file)
-            {
-                LL_WARNS("LEGACYSETTING") << "Unable to open legacy windlight \"" << name << "\" from " << path << LL_ENDL;
-
-                full_path = path;
-                full_name = legacy_name_to_filename(name, true);
-                full_name += ".xml";
-                gDirUtilp->append(full_path, full_name);
-                xml_file.open(full_path.c_str());
-                if (!xml_file)
-                {
-                    LL_WARNS("LEGACYSETTING") << "Unable to open legacy windlight \"" << name << "\" from " << path << LL_ENDL;
-                    return LLSD();
-                }
-            }
-        }
-
-        LLSD params_data;
-        LLPointer<LLSDParser> parser = new LLSDXMLParser();
-        parser->parse(xml_file, params_data, LLSDSerialize::SIZE_UNLIMITED);
-        xml_file.close();
-
-        return params_data;
-    }
-}
+/**
+* @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 <cstdio>
+#include <boost/make_shared.hpp>
+#include "lltrace.h"
+#include "llfasttimer.h"
+#include "v3colorutil.h"
+
+#include "llglslshader.h"
+#include "llviewershadermgr.h"
+
+#include "llagent.h"
+#include "llassettype.h"
+#include "llfloaterperms.h"
+#include "llnotificationsutil.h"
+
+#include "llviewerregion.h"
+#include "llviewerassetupload.h"
+#include "llviewerinventory.h"
+
+#include "llenvironment.h"
+#include "llsky.h"
+
+#include "llpermissions.h"
+
+#include "llinventorymodel.h"
+#include "llassetstorage.h"
+#include "llvfile.h"
+#include "lldrawpoolwater.h"
+
+#include <boost/algorithm/string/replace.hpp>
+#include "llinventoryobserver.h"
+#include "llinventorydefines.h"
+
+#undef  VERIFY_LEGACY_CONVERSION
+
+//=========================================================================
+namespace 
+{
+    LLSD ensure_array_4(LLSD in, F32 fill);
+    LLSD read_legacy_preset_data(const std::string &name, const std::string& path);
+
+    //-------------------------------------------------------------------------
+    class LLSettingsInventoryCB : public LLInventoryCallback
+    {
+    public:
+        typedef std::function<void(const LLUUID &)> callback_t;
+
+        LLSettingsInventoryCB(callback_t cbfn) :
+            mCbfn(cbfn)
+        { }
+
+        void fire(const LLUUID& inv_item) override  { if (mCbfn) mCbfn(inv_item); }
+
+    private:
+        callback_t  mCbfn;
+    };
+
+    //-------------------------------------------------------------------------
+}
+
+
+//=========================================================================
+void LLSettingsVOBase::createNewInventoryItem(LLSettingsType::type_e stype, const LLUUID &parent_id, inventory_result_fn callback)
+{
+    LLTransactionID tid;
+    U32 nextOwnerPerm = LLFloaterPerms::getNextOwnerPerms("Settings");
+    nextOwnerPerm |= PERM_COPY;
+
+    if (!LLEnvironment::instance().isInventoryEnabled())
+    {
+        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
+        LLNotificationsUtil::add("SettingsUnsuported");
+        return;
+    }
+
+    tid.generate();
+
+    LLPointer<LLInventoryCallback> cb = new LLSettingsInventoryCB([callback](const LLUUID &inventoryId) {
+        LLSettingsVOBase::onInventoryItemCreated(inventoryId, LLSettingsBase::ptr_t(), callback);
+    });
+
+    create_inventory_settings(gAgent.getID(), gAgent.getSessionID(),
+        parent_id, LLTransactionID::tnull,
+        LLSettingsType::getDefaultName(stype), "",
+        stype, nextOwnerPerm, cb);
+}
+
+
+void LLSettingsVOBase::createInventoryItem(const LLSettingsBase::ptr_t &settings, const LLUUID &parent_id, std::string settings_name, inventory_result_fn callback)
+{
+    LLTransactionID tid;
+    U32             nextOwnerPerm = LLPermissions::DEFAULT.getMaskNextOwner();
+
+    if (!LLEnvironment::instance().isInventoryEnabled())
+    {
+        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
+        LLNotificationsUtil::add("SettingsUnsuported");
+        return;
+    }
+
+    tid.generate();
+
+    LLPointer<LLInventoryCallback> cb = new LLSettingsInventoryCB([settings, callback](const LLUUID &inventoryId) {
+            LLSettingsVOBase::onInventoryItemCreated(inventoryId, settings, callback);
+        });
+
+    if (settings_name.empty())
+    {
+        settings_name = settings->getName();
+    }
+    create_inventory_settings(gAgent.getID(), gAgent.getSessionID(),
+        parent_id, tid,
+        settings_name, "",
+        settings->getSettingsTypeValue(), nextOwnerPerm, cb);
+}
+
+void LLSettingsVOBase::onInventoryItemCreated(const LLUUID &inventoryId, LLSettingsBase::ptr_t settings, inventory_result_fn callback)
+{
+    if (!settings)
+    {   // The item was created as new with no settings passed in.  Simulator should have given it the default for the type... check ID, 
+        // no need to upload asset.
+        LLUUID asset_id;
+        LLViewerInventoryItem *pitem = gInventory.getItem(inventoryId);
+
+        if (pitem)
+        {
+            asset_id = pitem->getAssetUUID();
+        }
+        if (callback)
+            callback(asset_id, inventoryId, LLUUID::null, LLSD());
+        return;
+    }
+    // We need to update some inventory stuff here.... maybe.
+    updateInventoryItem(settings, inventoryId, callback, false);
+}
+
+void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID inv_item_id, inventory_result_fn callback, bool update_name)
+{
+    const LLViewerRegion* region = gAgent.getRegion();
+    if (!region)
+    {
+        LL_WARNS("SETTINGS") << "Not connected to a region, cannot save setting." << LL_ENDL;
+        return;
+    }
+
+    std::string agent_url(region->getCapability("UpdateSettingsAgentInventory"));
+
+    if (!LLEnvironment::instance().isInventoryEnabled())
+    {
+        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
+        LLNotificationsUtil::add("SettingsUnsuported");
+        return;
+    }
+
+    LLViewerInventoryItem *inv_item = gInventory.getItem(inv_item_id);
+    if (inv_item)
+    {
+        bool need_update(false);
+        LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
+
+        if (settings->getFlag(LLSettingsBase::FLAG_NOTRANS) && new_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+        {
+            LLPermissions perm(inv_item->getPermissions());
+            perm.setBaseBits(LLUUID::null, FALSE, PERM_TRANSFER);
+            perm.setOwnerBits(LLUUID::null, FALSE, PERM_TRANSFER);
+            new_item->setPermissions(perm);
+            need_update |= true;
+        }
+        if (update_name && (settings->getName() != new_item->getName()))
+        {
+            new_item->rename(settings->getName());
+            settings->setName(new_item->getName()); // account for corrections
+            need_update |= true;
+        }
+        if (need_update)
+        {
+            new_item->updateServer(FALSE);
+            gInventory.updateItem(new_item);
+            gInventory.notifyObservers();
+        }
+    }
+
+    std::stringstream buffer; 
+    LLSD settingdata(settings->getSettings());
+    LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION);
+
+    LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(), 
+        [settings, callback](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response) {
+            LLSettingsVOBase::onAgentAssetUploadComplete(itemId, newAssetId, newItemId, response, settings, callback);
+        });
+
+    LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
+}
+
+void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID object_id, LLUUID inv_item_id, inventory_result_fn callback)
+{
+    const LLViewerRegion* region = gAgent.getRegion();
+    if (!region)
+    {
+        LL_WARNS("SETTINGS") << "Not connected to a region, cannot save setting." << LL_ENDL;
+        return;
+    }
+
+    std::string agent_url(region->getCapability("UpdateSettingsAgentInventory"));
+
+    if (!LLEnvironment::instance().isInventoryEnabled())
+    {
+        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
+        LLNotificationsUtil::add("SettingsUnsuported");
+        return;
+    }
+
+    std::stringstream buffer;
+    LLSD settingdata(settings->getSettings());
+
+    LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION);
+
+    LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(object_id, inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(),
+        [settings, callback](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) {
+        LLSettingsVOBase::onTaskAssetUploadComplete(itemId, taskId, newAssetId, response, settings, callback);
+    });
+
+    LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
+}
+
+void LLSettingsVOBase::onAgentAssetUploadComplete(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback)
+{
+    LL_INFOS("SETTINGS") << "itemId:" << itemId << " newAssetId:" << newAssetId << " newItemId:" << newItemId << " response:" << response << LL_ENDL;
+    psettings->setAssetId(newAssetId);
+    if (callback)
+        callback( newAssetId, itemId, LLUUID::null, response );
+
+#if 0
+    std::string exprtFile = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + newAssetId.asString() + ".llsd";
+
+    LLSettingsVOBase::exportFile(psettings, exprtFile, LLSDSerialize::LLSD_NOTATION);
+
+    LL_WARNS("LAPRAS") << "SETTINGS File written as: '" << exprtFile << "'" << LL_ENDL;
+#endif
+}
+
+void LLSettingsVOBase::onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback)
+{
+    LL_INFOS("SETTINGS") << "Upload to task complete!" << LL_ENDL;
+    psettings->setAssetId(newAssetId);
+    if (callback)
+        callback(newAssetId, itemId, taskId, response);
+}
+
+
+void LLSettingsVOBase::getSettingsAsset(const LLUUID &assetId, LLSettingsVOBase::asset_download_fn callback)
+{
+    gAssetStorage->getAssetData(assetId, LLAssetType::AT_SETTINGS,
+        [callback](LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType, void *, S32 status, LLExtStat ext_status) 
+            { onAssetDownloadComplete(vfs, asset_id, status, ext_status, callback); },
+        nullptr, true);
+
+}
+
+void LLSettingsVOBase::onAssetDownloadComplete(LLVFS *vfs, const LLUUID &asset_id, S32 status, LLExtStat ext_status, LLSettingsVOBase::asset_download_fn callback)
+{
+    LLSettingsBase::ptr_t settings;
+    if (!status)
+    {
+        LLVFile file(vfs, asset_id, LLAssetType::AT_SETTINGS, LLVFile::READ);
+        S32 size = file.getSize();
+
+        std::string buffer(size + 1, '\0');
+        file.read((U8 *)buffer.data(), size);
+
+        std::stringstream llsdstream(buffer);
+        LLSD llsdsettings;
+
+        if (LLSDSerialize::deserialize(llsdsettings, llsdstream, -1))
+        {
+            settings = createFromLLSD(llsdsettings);
+        }
+
+        if (!settings)
+        {
+            status = 1;
+            LL_WARNS("SETTINGS") << "Unable to create settings object." << LL_ENDL;
+        }
+        else
+        {
+            LL_WARNS("LAPRAS") << "Setting asset ID to " << asset_id << LL_ENDL;
+            settings->setAssetId(asset_id);
+        }
+    }
+    else
+    {
+        LL_WARNS("SETTINGS") << "Error retrieving asset " << asset_id << ". Status code=" << status << "(" << LLAssetStorage::getErrorString(status) << ") ext_status=" << ext_status << LL_ENDL;
+    }
+    if (callback)
+        callback(asset_id, settings, status, ext_status);
+}
+
+void LLSettingsVOBase::getSettingsInventory(const LLUUID &inventoryId, inventory_download_fn callback)
+{
+
+}
+
+bool LLSettingsVOBase::exportFile(const LLSettingsBase::ptr_t &settings, const std::string &filename, LLSDSerialize::ELLSD_Serialize format)
+{
+    try
+    {
+        std::ofstream file(filename, std::ios::out | std::ios::trunc);
+        file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
+
+        if (!file)
+        {
+            LL_WARNS("SETTINGS") << "Unable to open '" << filename << "' for writing." << LL_ENDL;
+            return false;
+        }
+
+        LLSDSerialize::serialize(settings->getSettings(), file, format);
+    }
+    catch (const std::ios_base::failure &e)
+    {
+        LL_WARNS("SETTINGS") << "Unable to save settings to file '" << filename << "': " << e.what() << LL_ENDL;
+        return false;
+    }
+
+    return true;
+}
+
+LLSettingsBase::ptr_t LLSettingsVOBase::importFile(const std::string &filename)
+{
+    LLSD settings;
+
+    try
+    {
+        std::ifstream file(filename, std::ios::in);
+        file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
+
+        if (!file)
+        {
+            LL_WARNS("SETTINGS") << "Unable to open '" << filename << "' for reading." << LL_ENDL;
+            return LLSettingsBase::ptr_t();
+        }
+
+        if (!LLSDSerialize::deserialize(settings, file, -1))
+        {
+            LL_WARNS("SETTINGS") << "Unable to deserialize settings from '" << filename << "'" << LL_ENDL;
+            return LLSettingsBase::ptr_t();
+        }
+    }
+    catch (const std::ios_base::failure &e)
+    {
+        LL_WARNS("SETTINGS") << "Unable to save settings to file '" << filename << "': " << e.what() << LL_ENDL;
+        return LLSettingsBase::ptr_t();
+    }
+
+    return createFromLLSD(settings);
+}
+
+LLSettingsBase::ptr_t LLSettingsVOBase::createFromLLSD(const LLSD &settings)
+{
+    if (!settings.has(SETTING_TYPE))
+    {
+        LL_WARNS("SETTINGS") << "No settings type in LLSD" << LL_ENDL;
+        return LLSettingsBase::ptr_t();
+    }
+
+    std::string settingtype = settings[SETTING_TYPE].asString();
+
+    LLSettingsBase::ptr_t psetting;
+
+    if (settingtype == "water")
+    {
+        return LLSettingsVOWater::buildWater(settings);
+    }
+    else if (settingtype == "sky")
+    {
+        return LLSettingsVOSky::buildSky(settings);
+    }
+    else if (settingtype == "daycycle")
+    {
+        return LLSettingsVODay::buildDay(settings);
+    }
+
+    LL_WARNS("SETTINGS") << "Unable to determine settings type for '" << settingtype << "'." << LL_ENDL;
+    return LLSettingsBase::ptr_t();
+
+}
+
+//=========================================================================
+LLSettingsVOSky::LLSettingsVOSky(const LLSD &data, bool isAdvanced)
+: LLSettingsSky(data)
+, m_isAdvanced(isAdvanced)
+{
+}
+
+LLSettingsVOSky::LLSettingsVOSky()
+: LLSettingsSky()
+, m_isAdvanced(false)
+{
+}
+
+//-------------------------------------------------------------------------
+LLSettingsSky::ptr_t LLSettingsVOSky::buildSky(LLSD settings)
+{
+    LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
+
+    LLSD results = LLSettingsBase::settingValidation(settings, validations);
+
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsSky::ptr_t();
+    }
+
+    return std::make_shared<LLSettingsVOSky>(settings, true);
+}
+
+
+LLSettingsSky::ptr_t LLSettingsVOSky::buildFromLegacyPreset(const std::string &name, const LLSD &legacy)
+{
+
+    LLSD newsettings = LLSettingsSky::translateLegacySettings(legacy);
+
+    newsettings[SETTING_NAME] = name;
+
+    LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
+    LLSD results = LLSettingsBase::settingValidation(newsettings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsSky::ptr_t();
+    }
+
+    LLSettingsSky::ptr_t skyp = std::make_shared<LLSettingsVOSky>(newsettings);
+
+#ifdef VERIFY_LEGACY_CONVERSION
+    LLSD oldsettings = LLSettingsVOSky::convertToLegacy(skyp, isAdvanced());
+
+    if (!llsd_equals(legacy, oldsettings))
+    {
+        LL_WARNS("SKY") << "Conversion to/from legacy does not match!\n" 
+            << "Old: " << legacy
+            << "new: " << oldsettings << LL_ENDL;
+    }
+
+#endif
+
+    return skyp;
+}
+
+LLSettingsSky::ptr_t LLSettingsVOSky::buildFromLegacyPresetFile(const std::string &name, const std::string &path)
+{
+    LLSD legacy_data = read_legacy_preset_data(name, path);
+
+    if (!legacy_data)
+    {
+        LL_WARNS("SETTINGS") << "Could not load legacy Windlight \"" << name << "\" from " << path << LL_ENDL;
+        return ptr_t();
+    }
+
+    return buildFromLegacyPreset(name, legacy_data);
+}
+
+
+LLSettingsSky::ptr_t LLSettingsVOSky::buildDefaultSky()
+{
+    static LLSD default_settings;
+
+    if (!default_settings.size())
+    {
+        default_settings = LLSettingsSky::defaults();
+
+        default_settings[SETTING_NAME] = std::string("_default_");
+
+        LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
+        LLSD results = LLSettingsBase::settingValidation(default_settings, validations);
+        if (!results["success"].asBoolean())
+        {
+            LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
+            LLSettingsSky::ptr_t();
+        }
+    }
+
+    LLSettingsSky::ptr_t skyp = std::make_shared<LLSettingsVOSky>(default_settings);
+    return skyp;
+}
+
+LLSettingsSky::ptr_t LLSettingsVOSky::buildClone() const
+{
+    LLSD settings = cloneSettings();
+
+    LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
+    LLSD results = LLSettingsBase::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsSky::ptr_t();
+    }
+
+    LLSettingsSky::ptr_t skyp = std::make_shared<LLSettingsVOSky>(settings);
+    return skyp;
+}
+
+void LLSettingsVOSky::convertAtmosphericsToLegacy(LLSD& legacy, LLSD& settings)
+{
+    // These may need to be inferred from new settings' density profiles
+    // if the legacy settings values are not available.
+    if (settings.has(SETTING_LEGACY_HAZE))
+    {
+        LLSD legacyhaze = settings[SETTING_LEGACY_HAZE];
+
+        // work-around for setter formerly putting ambient values in wrong loc...
+        if (legacyhaze.has(SETTING_AMBIENT))
+        {
+            legacy[SETTING_AMBIENT] = ensure_array_4(legacyhaze[SETTING_AMBIENT], 1.0f);
+        }
+        else if (settings.has(SETTING_AMBIENT))
+        {
+            legacy[SETTING_AMBIENT] = ensure_array_4(settings[SETTING_AMBIENT], 1.0f);
+        }
+
+        legacy[SETTING_BLUE_DENSITY] = ensure_array_4(legacyhaze[SETTING_BLUE_DENSITY], 1.0);
+        legacy[SETTING_BLUE_HORIZON] = ensure_array_4(legacyhaze[SETTING_BLUE_HORIZON], 1.0);
+
+        F32 density_multiplier = legacyhaze[SETTING_DENSITY_MULTIPLIER].asReal();
+        density_multiplier = (density_multiplier < 0.0001f) ? 0.0001f : density_multiplier;
+        legacy[SETTING_DENSITY_MULTIPLIER] = LLSDArray(density_multiplier)(0.0f)(0.0f)(1.0f);
+
+        F32 distance_multiplier = legacyhaze[SETTING_DISTANCE_MULTIPLIER].asReal();
+        legacy[SETTING_DISTANCE_MULTIPLIER] = LLSDArray(distance_multiplier)(0.0f)(0.0f)(1.0f);
+
+        legacy[SETTING_HAZE_DENSITY]        = LLSDArray(legacyhaze[SETTING_HAZE_DENSITY])(0.0f)(0.0f)(1.0f);
+        legacy[SETTING_HAZE_HORIZON]        = LLSDArray(legacyhaze[SETTING_HAZE_HORIZON])(0.0f)(0.0f)(1.0f);
+    }
+}
+
+LLSD LLSettingsVOSky::convertToLegacy(const LLSettingsSky::ptr_t &psky, bool isAdvanced)
+{
+    LLSD legacy(LLSD::emptyMap());
+    LLSD settings = psky->getSettings();
+    
+    convertAtmosphericsToLegacy(legacy, settings);
+
+    legacy[SETTING_CLOUD_COLOR] = ensure_array_4(settings[SETTING_CLOUD_COLOR], 1.0);
+    legacy[SETTING_CLOUD_POS_DENSITY1] = ensure_array_4(settings[SETTING_CLOUD_POS_DENSITY1], 1.0);
+    legacy[SETTING_CLOUD_POS_DENSITY2] = ensure_array_4(settings[SETTING_CLOUD_POS_DENSITY2], 1.0);
+    legacy[SETTING_CLOUD_SCALE] = LLSDArray(settings[SETTING_CLOUD_SCALE])(LLSD::Real(0.0))(LLSD::Real(0.0))(LLSD::Real(1.0));       
+    legacy[SETTING_CLOUD_SCROLL_RATE] = settings[SETTING_CLOUD_SCROLL_RATE];
+    legacy[SETTING_LEGACY_ENABLE_CLOUD_SCROLL] = LLSDArray(LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][0].asReal())))
+        (LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][1].asReal())));     
+    legacy[SETTING_CLOUD_SHADOW] = LLSDArray(settings[SETTING_CLOUD_SHADOW].asReal())(0.0f)(0.0f)(1.0f);    
+    legacy[SETTING_GAMMA] = LLSDArray(settings[SETTING_GAMMA])(0.0f)(0.0f)(1.0f);
+    legacy[SETTING_GLOW] = ensure_array_4(settings[SETTING_GLOW], 1.0);
+    legacy[SETTING_LIGHT_NORMAL] = ensure_array_4(psky->getLightDirection().getValue(), 0.0f);
+    legacy[SETTING_MAX_Y] = LLSDArray(settings[SETTING_MAX_Y])(0.0f)(0.0f)(1.0f);
+    legacy[SETTING_STAR_BRIGHTNESS] = settings[SETTING_STAR_BRIGHTNESS];
+    legacy[SETTING_SUNLIGHT_COLOR] = ensure_array_4(settings[SETTING_SUNLIGHT_COLOR], 1.0f);
+    
+    LLVector3 dir = psky->getLightDirection();
+
+    F32 phi     = asin(dir.mV[2]);
+    F32 cos_phi = cosf(phi);
+    F32 theta   = (cos_phi != 0) ? asin(dir.mV[1] / cos_phi) : 0.0f;
+
+    theta = -theta;
+
+    // get angles back into valid ranges for legacy viewer...
+    //
+    while (theta < 0)
+    {
+        theta += F_PI * 2;
+    }
+    
+    if (theta > 4 * F_PI)
+    {
+        theta = fmod(theta, 2 * F_PI);
+    }
+    
+    while (phi < -F_PI)
+    {
+        phi += 2 * F_PI;
+    }
+    
+    if (phi > 3 * F_PI)
+    {
+        phi = F_PI + fmod(phi - F_PI, 2 * F_PI);
+    }
+
+    legacy[SETTING_LEGACY_EAST_ANGLE] = theta;
+    legacy[SETTING_LEGACY_SUN_ANGLE]  = phi;
+ 
+   return legacy;    
+}
+
+//-------------------------------------------------------------------------
+void LLSettingsVOSky::updateSettings()
+{
+    LLSettingsSky::updateSettings();
+    LLVector3 sun_direction  = getSunDirection();
+    LLVector3 moon_direction = getMoonDirection();
+
+    F32 dp = getLightDirection() * LLVector3(0.0f, 0.0f, 1.0f);
+	if (dp < 0)
+	{
+		dp = 0;
+	}
+    dp = llmax(dp, 0.1f);
+
+	// Since WL scales everything by 2, there should always be at least a 2:1 brightness ratio
+	// between sunlight and point lights in windlight to normalize point lights.
+	F32 sun_dynamic_range = llmax(gSavedSettings.getF32("RenderSunDynamicRange"), 0.0001f);
+    mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp);
+
+    gSky.setSunAndMoonDirectionsCFR(sun_direction, moon_direction);
+    gSky.setSunTextures(getSunTextureId(), getNextSunTextureId());
+    gSky.setMoonTextures(getMoonTextureId(), getNextMoonTextureId());
+    gSky.setCloudNoiseTextures(getCloudNoiseTextureId(), getNextCloudNoiseTextureId());
+    gSky.setBloomTextures(getBloomTextureId(), getNextBloomTextureId());
+
+    gSky.setSunScale(getSunScale());
+    gSky.setMoonScale(getMoonScale());
+}
+
+void LLSettingsVOSky::applySpecial(void *ptarget)
+{
+    LLGLSLShader *shader = (LLGLSLShader *)ptarget;
+
+    LLVector4 light_direction = LLEnvironment::instance().getClampedSunNorm();
+
+    if (shader->mShaderGroup == LLGLSLShader::SG_DEFAULT)
+	{        
+        shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV);
+		shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
+	} 
+	else if (shader->mShaderGroup == LLGLSLShader::SG_SKY)
+	{
+        shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV);        
+
+        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);
+	}
+
+    shader->uniform1f(LLShaderMgr::SCENE_LIGHT_STRENGTH, mSceneLightStrength);
+    shader->uniform4f(LLShaderMgr::GAMMA, getGamma(), 0.0, 0.0, 1.0);
+}
+
+LLSettingsSky::parammapping_t LLSettingsVOSky::getParameterMap() const
+{
+    static parammapping_t param_map;
+
+    if (param_map.empty())
+    {
+// LEGACY_ATMOSPHERICS
+        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_HAZE_DENSITY] = LLShaderMgr::HAZE_DENSITY;
+        param_map[SETTING_HAZE_HORIZON] = LLShaderMgr::HAZE_HORIZON;
+        param_map[SETTING_DENSITY_MULTIPLIER] = LLShaderMgr::DENSITY_MULTIPLIER;
+        param_map[SETTING_DISTANCE_MULTIPLIER] = LLShaderMgr::DISTANCE_MULTIPLIER;
+
+        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_CLOUD_VARIANCE] = LLShaderMgr::CLOUD_VARIANCE;
+        param_map[SETTING_GLOW] = LLShaderMgr::GLOW;        
+        param_map[SETTING_MAX_Y] = LLShaderMgr::MAX_Y;
+        param_map[SETTING_SUNLIGHT_COLOR] = LLShaderMgr::SUNLIGHT_COLOR;
+        param_map[SETTING_MOON_BRIGHTNESS] = LLShaderMgr::MOON_BRIGHTNESS;
+        param_map[SETTING_SKY_MOISTURE_LEVEL] = LLShaderMgr::MOISTURE_LEVEL;
+        param_map[SETTING_SKY_DROPLET_RADIUS] = LLShaderMgr::DROPLET_RADIUS;
+        param_map[SETTING_SKY_ICE_LEVEL] = LLShaderMgr::ICE_LEVEL;
+
+// AdvancedAtmospherics TODO
+// Provide mappings for new shader params here
+    }
+
+    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::buildWater(LLSD settings)
+{
+    LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
+    LLSD results = LLSettingsWater::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Water setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsWater::ptr_t();
+    }
+
+    return std::make_shared<LLSettingsVOWater>(settings);
+}
+
+//-------------------------------------------------------------------------
+LLSettingsWater::ptr_t LLSettingsVOWater::buildFromLegacyPreset(const std::string &name, const LLSD &legacy)
+{
+    LLSD newsettings(LLSettingsWater::translateLegacySettings(legacy));
+
+    newsettings[SETTING_NAME] = name; 
+    LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
+    LLSD results = LLSettingsWater::settingValidation(newsettings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Water setting validation failed!: " << results << LL_ENDL;
+        return LLSettingsWater::ptr_t();
+    }
+
+    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(newsettings);
+
+#ifdef VERIFY_LEGACY_CONVERSION
+    LLSD oldsettings = LLSettingsVOWater::convertToLegacy(waterp);
+
+    if (!llsd_equals(legacy, oldsettings))
+    {
+        LL_WARNS("WATER") << "Conversion to/from legacy does not match!\n"
+            << "Old: " << legacy
+            << "new: " << oldsettings << LL_ENDL;
+    }
+
+#endif
+    return waterp;
+}
+
+LLSettingsWater::ptr_t LLSettingsVOWater::buildFromLegacyPresetFile(const std::string &name, const std::string &path)
+{
+    LLSD legacy_data = read_legacy_preset_data(name, path);
+
+    if (!legacy_data)
+    {
+        LL_WARNS("SETTINGS") << "Could not load legacy Windlight \"" << name << "\" from " << path << LL_ENDL;
+        return ptr_t();
+    }
+
+    return buildFromLegacyPreset(name, legacy_data);
+}
+
+
+LLSettingsWater::ptr_t LLSettingsVOWater::buildDefaultWater()
+{
+    static LLSD default_settings;
+
+    if (!default_settings.size())
+    {
+        default_settings = LLSettingsWater::defaults();
+
+        default_settings[SETTING_NAME] = std::string("_default_");
+
+        LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
+        LLSD results = LLSettingsWater::settingValidation(default_settings, validations);
+        if (!results["success"].asBoolean())
+        {
+            LL_WARNS("SETTINGS") << "Water setting validation failed!: " << results << LL_ENDL;
+            return LLSettingsWater::ptr_t();
+        }
+    }
+
+    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(default_settings);
+
+    return waterp;
+}
+
+LLSettingsWater::ptr_t LLSettingsVOWater::buildClone() const
+{
+    LLSD settings = cloneSettings();
+    LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
+    LLSD results = LLSettingsWater::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Water setting validation failed!: " << results << LL_ENDL;
+        return LLSettingsWater::ptr_t();
+    }
+
+    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(settings);
+
+    return waterp;
+}
+
+LLSD LLSettingsVOWater::convertToLegacy(const LLSettingsWater::ptr_t &pwater)
+{
+    LLSD legacy(LLSD::emptyMap());
+    LLSD settings = pwater->getSettings();
+
+    legacy[SETTING_LEGACY_BLUR_MULTIPLIER] = settings[SETTING_BLUR_MULTIPLIER];
+    legacy[SETTING_LEGACY_FOG_COLOR] = ensure_array_4(settings[SETTING_FOG_COLOR], 1.0f);
+    legacy[SETTING_LEGACY_FOG_DENSITY] = settings[SETTING_FOG_DENSITY];
+    legacy[SETTING_LEGACY_FOG_MOD] = settings[SETTING_FOG_MOD];
+    legacy[SETTING_LEGACY_FRESNEL_OFFSET] = settings[SETTING_FRESNEL_OFFSET];
+    legacy[SETTING_LEGACY_FRESNEL_SCALE] = settings[SETTING_FRESNEL_SCALE];
+    legacy[SETTING_LEGACY_NORMAL_MAP] = settings[SETTING_NORMAL_MAP];
+    legacy[SETTING_LEGACY_NORMAL_SCALE] = settings[SETTING_NORMAL_SCALE];
+    legacy[SETTING_LEGACY_SCALE_ABOVE] = settings[SETTING_SCALE_ABOVE];
+    legacy[SETTING_LEGACY_SCALE_BELOW] = settings[SETTING_SCALE_BELOW];
+    legacy[SETTING_LEGACY_WAVE1_DIR] = settings[SETTING_WAVE1_DIR];
+    legacy[SETTING_LEGACY_WAVE2_DIR] = settings[SETTING_WAVE2_DIR];
+    
+    //_WARNS("LAPRAS") << "Legacy water: " << legacy << LL_ENDL;
+    return legacy;
+}
+//-------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+void LLSettingsVOWater::applySpecial(void *ptarget)
+{
+    LLGLSLShader *shader = (LLGLSLShader *)ptarget;
+
+    if (shader->mShaderGroup == LLGLSLShader::SG_WATER)
+	{
+        //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);
+
+        LLVector4 waterPlane(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
+
+        shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, waterPlane.mV);
+
+        LLVector4 light_direction = LLEnvironment::instance().getClampedLightNorm();
+
+        F32 waterFogKS = 1.f / llmax(light_direction.mV[2], WATER_FOG_LIGHT_CLAMP);
+
+        shader->uniform1f(LLShaderMgr::WATER_FOGKS, waterFogKS);
+
+        F32 blend_factor = LLEnvironment::instance().getCurrentWater()->getBlendFactor();
+        shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+
+        LLVector4 rotated_light_direction = LLEnvironment::instance().getRotatedLightNorm();
+        shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV);
+        shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
+        shader->uniform1f(LLViewerShaderMgr::DISTANCE_MULTIPLIER, 0);
+    }
+}
+
+void LLSettingsVOWater::updateSettings()
+{
+    // base class clears dirty flag so as to not trigger recursive update
+    LLSettingsBase::updateSettings();
+
+    LLDrawPoolWater* pwaterpool = (LLDrawPoolWater*)gPipeline.getPool(LLDrawPool::POOL_WATER);
+    if (pwaterpool)
+    {
+        pwaterpool->setTransparentTextures(getTransparentTextureID(), getNextTransparentTextureID());
+        pwaterpool->setOpaqueTexture(GetDefaultOpaqueTextureAssetId());
+        pwaterpool->setNormalMaps(getNormalMapID(), getNextNormalMapID());
+    }
+}
+
+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::buildDay(LLSD settings)
+{
+    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
+    LLSD results = LLSettingsDay::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsDay::ptr_t();
+    }
+
+    LLSettingsDay::ptr_t pday = std::make_shared<LLSettingsVODay>(settings);
+    if (pday)
+        pday->initialize();
+
+    return pday;
+}
+
+//-------------------------------------------------------------------------
+LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPreset(const std::string &name, const std::string &path, const LLSD &oldsettings)
+{
+    LLSD newsettings(defaults());
+    std::set<std::string> framenames;
+    std::set<std::string> notfound;
+
+    std::string base_path(gDirUtilp->getDirName(path));
+    std::string water_path(base_path);
+    std::string sky_path(base_path);
+
+    gDirUtilp->append(water_path, "water");
+    gDirUtilp->append(sky_path, "skies");
+
+    newsettings[SETTING_NAME] = name;
+
+    LLSD watertrack = LLSDArray(
+        LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))
+        (SETTING_KEYNAME, "water:Default"));
+
+    LLSD skytrack = LLSD::emptyArray();
+
+    for (LLSD::array_const_iterator it = oldsettings.beginArray(); it != oldsettings.endArray(); ++it)
+    {
+        std::string framename = (*it)[1].asString();
+        LLSD entry = LLSDMap(SETTING_KEYKFRAME, (*it)[0].asReal())
+            (SETTING_KEYNAME, "sky:" + framename);
+        framenames.insert(framename);
+        skytrack.append(entry);
+    }
+
+    newsettings[SETTING_TRACKS] = LLSDArray(watertrack)(skytrack);
+
+    LLSD frames(LLSD::emptyMap());
+
+    {
+        LLSettingsWater::ptr_t pwater = LLSettingsVOWater::buildFromLegacyPresetFile("Default", water_path);
+        if (pwater)
+            frames["water:Default"] = pwater->getSettings();
+    }
+
+    for (std::set<std::string>::iterator itn = framenames.begin(); itn != framenames.end(); ++itn)
+    {
+        LLSettingsSky::ptr_t psky = LLSettingsVOSky::buildFromLegacyPresetFile((*itn), sky_path);
+        if (psky)
+            frames["sky:" + (*itn)] = psky->getSettings();
+    }
+
+    newsettings[SETTING_FRAMES] = frames;
+
+    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
+    LLSD results = LLSettingsDay::settingValidation(newsettings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Day setting validation failed!: " << results << LL_ENDL;
+        return LLSettingsDay::ptr_t();
+    }
+
+    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(newsettings);
+
+#ifdef VERIFY_LEGACY_CONVERSION
+    LLSD testsettings = LLSettingsVODay::convertToLegacy(dayp);
+
+    if (!llsd_equals(oldsettings, testsettings))
+    {
+        LL_WARNS("DAYCYCLE") << "Conversion to/from legacy does not match!\n" 
+            << "Old: " << oldsettings
+            << "new: " << testsettings << LL_ENDL;
+    }
+
+#endif
+
+    dayp->initialize();
+
+    return dayp;
+}
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPresetFile(const std::string &name, const std::string &path)
+{
+    LLSD legacy_data = read_legacy_preset_data(name, path);
+
+    if (!legacy_data)
+    {
+        LL_WARNS("SETTINGS") << "Could not load legacy Windlight \"" << name << "\" from " << path << LL_ENDL;
+        return ptr_t();
+    }
+
+    return buildFromLegacyPreset(name, path, legacy_data);
+}
+
+
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyMessage(const LLUUID &regionId, LLSD daycycle, LLSD skydefs, LLSD waterdef)
+{
+    LLSD frames(LLSD::emptyMap());
+
+    for (LLSD::map_iterator itm = skydefs.beginMap(); itm != skydefs.endMap(); ++itm)
+    {
+        std::string newname = "sky:" + (*itm).first;
+        LLSD newsettings = LLSettingsSky::translateLegacySettings((*itm).second);
+        
+        newsettings[SETTING_NAME] = newname;
+        frames[newname] = newsettings;
+
+        LL_WARNS("SETTINGS") << "created region sky '" << newname << "'" << LL_ENDL;
+    }
+
+    LLSD watersettings = LLSettingsWater::translateLegacySettings(waterdef);
+    std::string watername = "water:"+ watersettings[SETTING_NAME].asString();
+    watersettings[SETTING_NAME] = watername;
+    frames[watername] = watersettings;
+
+    LLSD watertrack = LLSDArray(
+            LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))
+            (SETTING_KEYNAME, watername));
+
+    LLSD skytrack(LLSD::emptyArray());
+    for (LLSD::array_const_iterator it = daycycle.beginArray(); it != daycycle.endArray(); ++it)
+    {
+        LLSD entry = LLSDMap(SETTING_KEYKFRAME, (*it)[0].asReal())
+            (SETTING_KEYNAME, "sky:" + (*it)[1].asString());
+        skytrack.append(entry);
+    }
+
+    LLSD newsettings = LLSDMap
+        ( SETTING_NAME, "Region (legacy)" )
+        ( SETTING_TRACKS, LLSDArray(watertrack)(skytrack))
+        ( SETTING_FRAMES, frames )
+        ( SETTING_TYPE, "daycycle" );
+
+    LL_WARNS("LAPRAS") << "newsettings=" << newsettings << LL_ENDL;
+
+    LLSettingsSky::validation_list_t validations = LLSettingsDay::validationList();
+    LLSD results = LLSettingsDay::settingValidation(newsettings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Day setting validation failed!:" << results << LL_ENDL;
+        return LLSettingsDay::ptr_t();
+    }
+
+    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(newsettings);
+    
+    if (dayp)
+    {
+        // true for validation - either validate here, or when cloning for floater.
+        dayp->initialize(true);
+    }
+    return dayp;
+}
+
+
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildDefaultDayCycle()
+{
+    static LLSD default_settings;
+
+    if (!default_settings.size())
+    {
+        default_settings = LLSettingsDay::defaults();
+        default_settings[SETTING_NAME] = std::string("_default_");
+
+        LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
+        LLSD results = LLSettingsDay::settingValidation(default_settings, validations);
+        if (!results["success"].asBoolean())
+        {
+            LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
+            LLSettingsDay::ptr_t();
+        }
+    }
+
+    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(default_settings);
+
+    dayp->initialize();
+    return dayp;
+}
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildFromEnvironmentMessage(LLSD settings)
+{
+    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
+    LLSD results = LLSettingsDay::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsDay::ptr_t();
+    }
+
+    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(settings);
+
+    dayp->initialize();
+    return dayp;
+}
+
+
+void LLSettingsVODay::buildFromOtherSetting(LLSettingsBase::ptr_t settings, LLSettingsVODay::asset_built_fn cb)
+{
+    if (settings->getSettingsType() == "daycycle")
+    {
+        if (cb)
+            cb(std::static_pointer_cast<LLSettingsDay>(settings));
+    }
+    else
+    {
+        LLSettingsVOBase::getSettingsAsset(LLSettingsDay::GetDefaultAssetId(),
+            [settings, cb](LLUUID, LLSettingsBase::ptr_t pday, S32, LLExtStat){ combineIntoDayCycle(std::static_pointer_cast<LLSettingsDay>(pday), settings, cb); });
+    }
+}
+
+void LLSettingsVODay::combineIntoDayCycle(LLSettingsDay::ptr_t pday, LLSettingsBase::ptr_t settings, asset_built_fn cb)
+{
+    if (settings->getSettingsType() == "sky")
+    {
+        pday->setName("sky: " + settings->getName());
+        pday->clearCycleTrack(1);
+        pday->setSettingsAtKeyframe(settings, 0.0, 1);
+    }
+    else if (settings->getSettingsType() == "water")
+    {
+        pday->setName("water: " + settings->getName());
+        pday->clearCycleTrack(0);
+        pday->setSettingsAtKeyframe(settings, 0.0, 0);
+    }
+    else
+    {
+        pday.reset();
+    }
+
+    if (cb)
+        cb(pday);
+}
+
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildClone() const
+{
+    LLSD settings = cloneSettings();
+
+    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
+    LLSD results = LLSettingsDay::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsDay::ptr_t();
+    }
+
+    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(settings);
+
+    U32 flags = getFlags();
+    if (flags)
+        dayp->setFlags(flags);
+
+    dayp->initialize();
+    return dayp;
+}
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildDeepCloneAndUncompress() const
+{
+    // no need for SETTING_TRACKS or SETTING_FRAMES, so take base LLSD
+    LLSD settings = llsd_clone(mSettings);
+
+    LLSettingsDay::ptr_t day_clone = std::make_shared<LLSettingsVODay>(settings);
+
+    for (S32 i = 0; i < LLSettingsDay::TRACK_MAX; ++i)
+    {
+        const LLSettingsDay::CycleTrack_t& track = getCycleTrackConst(i);
+        LLSettingsDay::CycleTrack_t::const_iterator iter = track.begin();
+        while (iter != track.end())
+        {
+            // 'Unpack', usually for editing
+            // - frames 'share' settings multiple times
+            // - settings can reuse LLSDs they were initialized from
+            // We do not want for edited frame to change multiple frames in same track, so do a clone
+            day_clone->setSettingsAtKeyframe(iter->second->buildDerivedClone(), iter->first, i);
+            iter++;
+        }
+    }
+    return day_clone;
+}
+
+LLSD LLSettingsVODay::convertToLegacy(const LLSettingsVODay::ptr_t &pday)
+{
+    CycleTrack_t &trackwater = pday->getCycleTrack(TRACK_WATER);
+
+    LLSettingsWater::ptr_t pwater;
+    if (!trackwater.empty())
+    {
+        pwater = std::static_pointer_cast<LLSettingsWater>((*trackwater.begin()).second);
+    }
+
+    if (!pwater)
+        pwater = LLSettingsVOWater::buildDefaultWater();
+    
+    LLSD llsdwater = LLSettingsVOWater::convertToLegacy(pwater);
+    
+    CycleTrack_t &tracksky = pday->getCycleTrack(1);   // first sky track
+    std::map<std::string, LLSettingsSky::ptr_t> skys;
+    
+    LLSD llsdcycle(LLSD::emptyArray());
+    
+    for(CycleTrack_t::iterator it = tracksky.begin(); it != tracksky.end(); ++it)
+    {
+        size_t hash = (*it).second->getHash();
+        std::stringstream name;
+        
+        name << hash;
+        
+        skys[name.str()] = std::static_pointer_cast<LLSettingsSky>((*it).second);
+        
+        F32 frame = ((tracksky.size() == 1) && (it == tracksky.begin())) ? -1.0f : (*it).first;
+        llsdcycle.append( LLSDArray(LLSD::Real(frame))(name.str()) );
+    }
+    //_WARNS("LAPRAS") << "Cycle created with " << llsdcycle.size() << "entries: " << llsdcycle << LL_ENDL;
+
+    LLSD llsdskylist(LLSD::emptyMap());
+    
+    for (std::map<std::string, LLSettingsSky::ptr_t>::iterator its = skys.begin(); its != skys.end(); ++its)
+    {
+        LLSD llsdsky = LLSettingsVOSky::convertToLegacy((*its).second, false);
+        llsdsky[SETTING_NAME] = (*its).first;
+        
+        llsdskylist[(*its).first] = llsdsky;
+    }
+
+    //_WARNS("LAPRAS") << "Sky map with " << llsdskylist.size() << " entries created: " << llsdskylist << LL_ENDL;
+    
+    return LLSDArray(LLSD::emptyMap())(llsdcycle)(llsdskylist)(llsdwater);
+}
+
+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 = std::make_shared<LLSettingsVOSky>(settings);
+
+    if (skyp->validate())
+        return skyp;
+
+    return LLSettingsSky::ptr_t();
+}
+
+LLSettingsWaterPtr_t LLSettingsVODay::buildWater(LLSD settings) const
+{
+    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(settings);
+
+    if (waterp->validate())
+        return waterp;
+
+    return LLSettingsWater::ptr_t();
+}
+
+//=========================================================================
+namespace
+{
+    LLSD ensure_array_4(LLSD in, F32 fill)
+    {
+        if (in.size() >= 4)
+            return in;
+
+        LLSD out(LLSD::emptyArray());
+
+        for (S32 idx = 0; idx < in.size(); ++idx)
+        {
+            out.append(in[idx]);
+        }
+
+        while (out.size() < 4)
+        {
+            out.append(LLSD::Real(fill));
+        }
+        return out;
+    }
+
+    // This is a disturbing hack
+    std::string legacy_name_to_filename(const std::string &name, bool convertdash = false)
+    {
+        std::string fixedname(LLURI::escape(name));
+
+        if (convertdash)
+            boost::algorithm::replace_all(fixedname, "-", "%2D");
+
+        return fixedname;
+    }
+
+    //---------------------------------------------------------------------
+    LLSD read_legacy_preset_data(const std::string &name, const std::string& path)
+    {
+        llifstream xml_file;
+
+        std::string full_path(path);
+        std::string full_name(name);
+        full_name += ".xml";
+        gDirUtilp->append(full_path, full_name);
+
+        xml_file.open(full_path.c_str());
+        if (!xml_file)
+        {
+            std::string bad_path(full_path);
+            full_path = path;
+            full_name = legacy_name_to_filename(name);
+            full_name += ".xml";
+            gDirUtilp->append(full_path, full_name);
+
+            LL_INFOS("LEGACYSETTING") << "Could not open \"" << bad_path << "\" trying escaped \"" << full_path << "\"" << LL_ENDL;
+
+            xml_file.open(full_path.c_str());
+            if (!xml_file)
+            {
+                LL_WARNS("LEGACYSETTING") << "Unable to open legacy windlight \"" << name << "\" from " << path << LL_ENDL;
+
+                full_path = path;
+                full_name = legacy_name_to_filename(name, true);
+                full_name += ".xml";
+                gDirUtilp->append(full_path, full_name);
+                xml_file.open(full_path.c_str());
+                if (!xml_file)
+                {
+                    LL_WARNS("LEGACYSETTING") << "Unable to open legacy windlight \"" << name << "\" from " << path << LL_ENDL;
+                    return LLSD();
+                }
+            }
+        }
+
+        LLSD params_data;
+        LLPointer<LLSDParser> parser = new LLSDXMLParser();
+        parser->parse(xml_file, params_data, LLSDSerialize::SIZE_UNLIMITED);
+        xml_file.close();
+
+        return params_data;
+    }
+}