From b766466b3013e39831bcfcaef5d1089c07202afb Mon Sep 17 00:00:00 2001
From: Rider Linden <rider@lindenlab.com>
Date: Mon, 26 Feb 2018 09:27:14 -0800
Subject: [PATCH] Added settings inventory object with subtype

---
 indra/llcommon/llassettype.h                  |   5 +-
 indra/llcommon/llsdserialize.cpp              |  10 +
 indra/llcommon/llsdserialize.h                |   2 +-
 indra/llinventory/CMakeLists.txt              |   1 +
 indra/llinventory/llinventorysettings.h       |  43 +++
 indra/llinventory/llsettingsbase.cpp          |  23 +-
 indra/llinventory/llsettingsbase.h            |  29 +-
 indra/llinventory/llsettingsdaycycle.cpp      |   1 +
 indra/llinventory/llsettingsdaycycle.h        |   2 +
 indra/llinventory/llsettingssky.h             |   4 +-
 indra/llinventory/llsettingswater.h           |   3 +-
 indra/llmessage/llassetstorage.cpp            |  34 +-
 indra/llmessage/llassetstorage.h              |  31 +-
 indra/newview/llagentwearables.cpp            |  11 +-
 indra/newview/llappearancemgr.cpp             |   3 +-
 indra/newview/llfloatereditextdaycycle.cpp    |  66 ++++
 indra/newview/llfloatereditextdaycycle.h      |   5 +
 indra/newview/llfloatergesture.cpp            |   2 +-
 indra/newview/llfloaternamedesc.cpp           |   4 +-
 indra/newview/llfriendcard.cpp                |   2 +-
 indra/newview/lllandmarkactions.cpp           |   2 +-
 indra/newview/lloutfitgallery.cpp             |   2 +-
 indra/newview/llpanelsnapshotpostcard.cpp     |   6 +-
 indra/newview/llpreviewgesture.cpp            |  10 +-
 indra/newview/llpreviewnotecard.cpp           |  13 +-
 indra/newview/llpreviewscript.cpp             |  14 +-
 indra/newview/llsettingsvo.cpp                | 307 ++++++++++++++++++
 indra/newview/llsettingsvo.h                  |  57 +++-
 indra/newview/llviewerassetstorage.h          |   6 +-
 indra/newview/llviewerassetupload.cpp         |   6 +-
 indra/newview/llviewerassetupload.h           |   6 +-
 indra/newview/llviewerinventory.cpp           |  35 +-
 indra/newview/llviewerinventory.h             |  22 +-
 indra/newview/llviewermenufile.cpp            |  10 +-
 indra/newview/llviewermenufile.h              |   2 +-
 indra/newview/llviewerregion.cpp              |   6 +-
 .../xui/en/floater_edit_ext_day_cycle.xml     |  16 +-
 37 files changed, 705 insertions(+), 96 deletions(-)
 create mode 100644 indra/llinventory/llinventorysettings.h

diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 3a660496e3b..32502d5e33c 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -124,10 +124,11 @@ class LL_COMMON_API LLAssetType
         AT_RESERVED_3 = 52,
         AT_RESERVED_4 = 53,
         AT_RESERVED_5 = 54,
+        AT_RESERVED_6 = 55,
 
-        AT_SETTINGS = 55,   // Collection of settings
+        AT_SETTINGS = 56,   // Collection of settings
             
-		AT_COUNT = 56,
+		AT_COUNT = 57,
 
 			// +*********************************************************+
 			// |  TO ADD AN ELEMENT TO THIS ENUM:                        |
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 3a219eb998c..f6ba64f0a98 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -54,6 +54,7 @@ static const int MAX_HDR_LEN = 20;
 static const char LEGACY_NON_HEADER[] = "<llsd>";
 const std::string LLSD_BINARY_HEADER("LLSD/Binary");
 const std::string LLSD_XML_HEADER("LLSD/XML");
+const std::string LLSD_NOTATION_HEADER("llsd/notation");
 
 //used to deflate a gzipped asset (currently used for navmeshes)
 #define windowBits 15
@@ -80,6 +81,11 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
 		f = new LLSDXMLFormatter;
 		break;
 
+    case LLSD_NOTATION:
+        str << "<? " << LLSD_NOTATION_HEADER << " ?>\n";
+        f = new LLSDNotationFormatter;
+        break;
+
 	default:
 		LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL;
 	}
@@ -167,6 +173,10 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
 	{
 		p = new LLSDXMLParser;
 	}
+    else if (header == LLSD_NOTATION_HEADER)
+    {
+        p = new LLSDNotationParser;
+    }
 	else
 	{
 		LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL;
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index 23a0c8cfb1e..cdca458e43d 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -694,7 +694,7 @@ class LL_COMMON_API LLSDSerialize
 public:
 	enum ELLSD_Serialize
 	{
-		LLSD_BINARY, LLSD_XML
+        LLSD_BINARY, LLSD_XML, LLSD_NOTATION
 	};
 
 	/**
diff --git a/indra/llinventory/CMakeLists.txt b/indra/llinventory/CMakeLists.txt
index 3eba746614a..2d40dd64432 100644
--- a/indra/llinventory/CMakeLists.txt
+++ b/indra/llinventory/CMakeLists.txt
@@ -45,6 +45,7 @@ set(llinventory_HEADER_FILES
     llfoldertype.h
     llinventory.h
     llinventorydefines.h
+    llinventorysettings.h
     llinventorytype.h
     lllandmark.h
     llnotecard.h
diff --git a/indra/llinventory/llinventorysettings.h b/indra/llinventory/llinventorysettings.h
new file mode 100644
index 00000000000..0d15542fecd
--- /dev/null
+++ b/indra/llinventory/llinventorysettings.h
@@ -0,0 +1,43 @@
+/**
+* @file llinventorysettings.h
+* @author optional
+* @brief A base class for asset based settings groups.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+#ifndef LL_INVENTORY_SETTINGS_H
+#define LL_INVENTORY_SETTINGS_H
+
+
+enum class LLSettingsType
+{
+    ST_SKY = 0,
+    ST_WATER = 1,
+    ST_DAYCYCLE = 2,
+
+    ST_INVALID = 255,
+    ST_NONE = -1
+};
+
+
+#endif
diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp
index 7ade3451682..3382716577a 100644
--- a/indra/llinventory/llsettingsbase.cpp
+++ b/indra/llinventory/llsettingsbase.cpp
@@ -38,6 +38,14 @@ namespace
     const F64 BREAK_POINT = 0.5;
 }
 
+//=========================================================================
+std::ostream &::operator <<(std::ostream& os, LLSettingsBase &settings)
+{
+    LLSDSerialize::serialize(settings.getSettings(), os, LLSDSerialize::LLSD_NOTATION);
+
+    return os;
+}
+
 //=========================================================================
 const std::string LLSettingsBase::SETTING_ID("id");
 const std::string LLSettingsBase::SETTING_NAME("name");
@@ -49,13 +57,15 @@ const F64Seconds LLSettingsBlender::DEFAULT_THRESHOLD(0.01);
 //=========================================================================
 LLSettingsBase::LLSettingsBase():
     mSettings(LLSD::emptyMap()),
-    mDirty(true)
+    mDirty(true),
+    mAssetID()
 {
 }
 
 LLSettingsBase::LLSettingsBase(const LLSD setting) :
     mSettings(setting),
-    mDirty(true)
+    mDirty(true),
+    mAssetID()
 {
 }
 
@@ -368,8 +378,14 @@ bool LLSettingsBase::Validator::verify(LLSD &data)
 {
     if (!data.has(mName) || (data.has(mName) && data[mName].isUndefined()))
     {
+        if (!mDefault.isUndefined())
+        {
+            LL_INFOS("SETTINGS") << "Inserting missing default for '" << mName << "'." << LL_ENDL;
+            data[mName] = mDefault;
+            return true;
+        }
         if (mRequired)
-            LL_WARNS("SETTINGS") << "Missing required setting '" << mName << "'" << LL_ENDL;
+            LL_WARNS("SETTINGS") << "Missing required setting '" << mName << "' with no default." << LL_ENDL;
         return !mRequired;
     }
 
@@ -514,7 +530,6 @@ bool LLSettingsBase::Validator::verifyIntegerRange(LLSD &value, LLSD range)
 }
 
 //=========================================================================
-
 void LLSettingsBlender::update(F64Seconds timedelta)
 {
     mTimeSpent += timedelta;
diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h
index 420bcb99432..c7ed9e9e214 100644
--- a/indra/llinventory/llsettingsbase.h
+++ b/indra/llinventory/llsettingsbase.h
@@ -42,6 +42,8 @@
 #include "v4color.h"
 #include "v3color.h"
 
+#include "llinventorysettings.h"
+
 class LLSettingsBase : 
     public std::enable_shared_from_this<LLSettingsBase>,
     private boost::noncopyable
@@ -49,6 +51,8 @@ class LLSettingsBase :
     friend class LLEnvironment;
     friend class LLSettingsDay;
 
+    friend std::ostream &operator <<(std::ostream& os, LLSettingsBase &settings);
+
 public:
     static const std::string SETTING_ID;
     static const std::string SETTING_NAME;
@@ -64,6 +68,8 @@ class LLSettingsBase :
     //---------------------------------------------------------------------
     virtual std::string getSettingType() const = 0;
 
+    virtual LLSettingsType getSettingTypeValue() const = 0;
+
     //---------------------------------------------------------------------
     // Settings status 
     inline bool hasSetting(const std::string &param) const { return mSettings.has(param); }
@@ -143,27 +149,28 @@ class LLSettingsBase :
     // Note this method is marked const but may modify the settings object.
     // (note the internal const cast).  This is so that it may be called without
     // special consideration from getters.
-    inline void update() const
+    inline void     update() const
     {
         if (!mDirty)
             return;
         (const_cast<LLSettingsBase *>(this))->updateSettings();
     }
 
-    virtual void blend(const ptr_t &end, F64 blendf) = 0;
+    virtual void    blend(const ptr_t &end, F64 blendf) = 0;
 
-    virtual bool validate();
+    virtual bool    validate();
 
     class Validator
     {
     public:
         typedef boost::function<bool(LLSD &)> verify_pr;
 
-        Validator(std::string name, bool required, LLSD::Type type, verify_pr verify = verify_pr()) :
+        Validator(std::string name, bool required, LLSD::Type type, verify_pr verify = verify_pr(), LLSD defval = LLSD())  :
             mName(name),
             mRequired(required),
             mType(type),
-            mVerify(verify)
+            mVerify(verify),
+            mDefault(defval)
         {   }
 
         std::string getName() const { return mName; }
@@ -187,6 +194,7 @@ class LLSettingsBase :
         bool        mRequired;
         LLSD::Type  mType;
         verify_pr   mVerify;
+        LLSD        mDefault;
     };
     typedef std::vector<Validator> validation_list_t;
 
@@ -223,15 +231,16 @@ class LLSettingsBase :
 
     virtual parammapping_t getParameterMap() const { return parammapping_t(); }
 
-    LLSD    mSettings;
-    bool    mIsValid;
+    LLSD        mSettings;
+    bool        mIsValid;
+    LLAssetID   mAssetID;
 
-    LLSD    cloneSettings() const;
+    LLSD        cloneSettings() const;
 
 private:
-    bool    mDirty;
+    bool        mDirty;
 
-    LLSD    combineSDMaps(const LLSD &first, const LLSD &other) const;
+    LLSD        combineSDMaps(const LLSD &first, const LLSD &other) const;
 
 };
 
diff --git a/indra/llinventory/llsettingsdaycycle.cpp b/indra/llinventory/llsettingsdaycycle.cpp
index a689dd37104..18add703cba 100644
--- a/indra/llinventory/llsettingsdaycycle.cpp
+++ b/indra/llinventory/llsettingsdaycycle.cpp
@@ -273,6 +273,7 @@ LLSD LLSettingsDay::defaults()
         (LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))(SETTING_KEYNAME, "_default_")));
     dfltsetting[SETTING_FRAMES] = LLSD::emptyMap();
 
+    dfltsetting[SETTING_TYPE] = "daycycle";
     return dfltsetting;
 }
 
diff --git a/indra/llinventory/llsettingsdaycycle.h b/indra/llinventory/llsettingsdaycycle.h
index 4c7ce011a1e..7703f7a0b48 100644
--- a/indra/llinventory/llsettingsdaycycle.h
+++ b/indra/llinventory/llsettingsdaycycle.h
@@ -72,6 +72,8 @@ class LLSettingsDay : public LLSettingsBase
 
     virtual ptr_t               buildClone() = 0;
     virtual LLSD                getSettings() const;
+    virtual LLSettingsType      getSettingTypeValue() const override { return LLSettingsType::ST_DAYCYCLE; }
+
 
     //---------------------------------------------------------------------
     virtual std::string         getSettingType() const { return std::string("daycycle"); }
diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h
index e9ffbdb32c2..23daf0c5dc0 100644
--- a/indra/llinventory/llsettingssky.h
+++ b/indra/llinventory/llsettingssky.h
@@ -72,7 +72,9 @@ class LLSettingsSky: public LLSettingsBase
     virtual ptr_t   buildClone() = 0;
 
     //---------------------------------------------------------------------
-    virtual std::string getSettingType() const { return std::string("sky"); }
+    virtual std::string getSettingType() const override { return std::string("sky"); }
+    virtual LLSettingsType getSettingTypeValue() const override { return LLSettingsType::ST_SKY; }
+
 
     // Settings status 
     virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf);
diff --git a/indra/llinventory/llsettingswater.h b/indra/llinventory/llsettingswater.h
index 4d206a1be03..16d5b2353a3 100644
--- a/indra/llinventory/llsettingswater.h
+++ b/indra/llinventory/llsettingswater.h
@@ -57,7 +57,8 @@ class LLSettingsWater : public LLSettingsBase
     virtual ptr_t   buildClone() = 0;
 
     //---------------------------------------------------------------------
-    virtual std::string getSettingType() const { return std::string("water"); }
+    virtual std::string     getSettingType() const override { return std::string("water"); }
+    virtual LLSettingsType  getSettingTypeValue() const override { return LLSettingsType::ST_WATER; }
 
     // Settings status 
     virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf);
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index 596d57c7b7b..3d93f5aeb8a 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -62,6 +62,24 @@ const LLUUID CATEGORIZE_LOST_AND_FOUND_ID(std::string("00000000-0000-0000-0000-0
 
 const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000);       // microseconds
 
+namespace
+{
+    template<typename T, typename... U>
+    bool operator == (const std::function<T(U...)> &a, const std::function <T(U...)> &b)
+    {
+        typedef T(fnType)(U...);
+
+        auto fnPtrA = a.target<T(*)(U...)>();
+        auto fnPtrB = b.target<T(*)(U...)>();
+        if (fnPtrA && fnPtrB)
+            return (*fnPtrA == *fnPtrB);
+        else if (!fnPtrA && !fnPtrB)
+            return true;
+        return false;
+    }
+
+}
+
 ///----------------------------------------------------------------------------
 /// LLAssetInfo
 ///----------------------------------------------------------------------------
@@ -160,7 +178,7 @@ void LLAssetInfo::setFromNameValue( const LLNameValue& nv )
 LLBaseDownloadRequest::LLBaseDownloadRequest(const LLUUID &uuid, const LLAssetType::EType type)
     : mUUID(uuid),
       mType(type),
-      mDownCallback(NULL),
+      mDownCallback(),
       mUserData(NULL),
       mHost(),
       mIsTemp(FALSE),
@@ -191,7 +209,7 @@ LLBaseDownloadRequest* LLBaseDownloadRequest::getCopy()
 
 LLAssetRequest::LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType type)
     :   LLBaseDownloadRequest(uuid, type),
-        mUpCallback( NULL ),
+        mUpCallback(),
         mInfoCallback( NULL ),
         mIsLocal(FALSE),
         mIsUserWaiting(FALSE),
@@ -496,7 +514,11 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
     BOOL exists = mVFS->getExists(uuid, type);
     LLVFile file(mVFS, uuid, type);
     U32 size = exists ? file.getSize() : 0;
-    
+
+// LAPRAS TESTING
+//     if (type == LLAssetType::AT_SETTINGS)
+//         size = 0;
+
     if (size > 0)
     {
         // we've already got the file
@@ -1326,9 +1348,13 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
          iter != mPendingDownloads.end();  )
     {
         LLAssetRequest* tmp = *iter++;
+
+        //void(*const* cbptr)(LLVFS *, const LLUUID &, LLAssetType::EType, void *, S32, LLExtStat) 
+        auto cbptr = tmp->mDownCallback.target<void(*)(LLVFS *, const LLUUID &, LLAssetType::EType, void *, S32, LLExtStat)>();
+
         if (type == tmp->getType() && 
             uuid == tmp->getUUID() &&
-            legacyGetDataCallback == tmp->mDownCallback &&
+            (cbptr && (*cbptr == legacyGetDataCallback)) &&
             callback == ((LLLegacyAssetRequest *)tmp->mUserData)->mDownCallback &&
             user_data == ((LLLegacyAssetRequest *)tmp->mUserData)->mUserData)
         {
diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h
index 33b88473b9d..c799d8eefc5 100644
--- a/indra/llmessage/llassetstorage.h
+++ b/indra/llmessage/llassetstorage.h
@@ -28,6 +28,7 @@
 #ifndef LL_LLASSETSTORAGE_H
 #define LL_LLASSETSTORAGE_H
 #include <string>
+#include <functional>
 
 #include "lluuid.h"
 #include "lltimer.h"
@@ -59,6 +60,14 @@ const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
 const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
 const int LL_ERR_PRICE_MISMATCH = -23018;
 
+// *TODO: these typedefs are passed into the VFS via a legacy C function pointer
+// future project would be to convert these to C++ callables (std::function<>) so that 
+// we can use bind and remove the userData parameter.
+// 
+typedef std::function<void(LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status)> LLGetAssetCallback;
+typedef std::function<void(const LLUUID &asset_id, void *user_data, S32 status, LLExtStat ext_status)> LLStoreAssetCallback;
+
+
 class LLAssetInfo
 {
 protected:
@@ -110,7 +119,8 @@ class LLBaseDownloadRequest
     LLAssetType::EType mType;
 
 public:
-    void(*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat);
+    LLGetAssetCallback mDownCallback;
+//    void(*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat);
 
     void	*mUserData;
     LLHost  mHost;
@@ -131,7 +141,8 @@ class LLAssetRequest : public LLBaseDownloadRequest
 
     virtual LLBaseDownloadRequest* getCopy();
 
-	void	(*mUpCallback)(const LLUUID&, void *, S32, LLExtStat);
+    LLStoreAssetCallback mUpCallback;
+//	void	(*mUpCallback)(const LLUUID&, void *, S32, LLExtStat);
 	void	(*mInfoCallback)(LLAssetInfo *, void *, S32);
 
 	BOOL	mIsLocal;
@@ -182,12 +193,7 @@ class LLEstateAssetRequest : public LLBaseDownloadRequest
 // Map of known bad assets
 typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t;
 
-// *TODO: these typedefs are passed into the VFS via a legacy C function pointer
-// future project would be to convert these to C++ callables (std::function<>) so that 
-// we can use bind and remove the userData parameter.
-// 
-typedef void (*LLGetAssetCallback)(LLVFS *vfs, const LLUUID &asset_id,
-                                   LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status);
+
 
 class LLAssetStorage
 {
@@ -195,7 +201,8 @@ class LLAssetStorage
 	// VFS member is public because static child methods need it :(
 	LLVFS *mVFS;
 	LLVFS *mStaticVFS;
-	typedef void (*LLStoreAssetCallback)(const LLUUID &asset_id, void *user_data, S32 status, LLExtStat ext_status);
+    typedef ::LLStoreAssetCallback LLStoreAssetCallback;
+    typedef ::LLGetAssetCallback LLGetAssetCallback;
 
 	enum ERequestType
 	{
@@ -377,8 +384,8 @@ class LLAssetStorage
 	void _cleanupRequests(BOOL all, S32 error);
 	void _callUploadCallbacks(const LLUUID &uuid, const LLAssetType::EType asset_type, BOOL success, LLExtStat ext_status);
 
-	virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type,
-								   void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
+	virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, LLGetAssetCallback callback,
+//								   void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
 								   void *user_data, BOOL duplicate,
 								   BOOL is_priority) = 0;
 
@@ -424,7 +431,7 @@ class LLLegacyAssetRequest
 {
 public:
 	void	(*mDownCallback)(const char *, const LLUUID&, void *, S32, LLExtStat);
-	LLAssetStorage::LLStoreAssetCallback mUpCallback;
+	LLStoreAssetCallback mUpCallback;
 
 	void	*mUserData;
 };
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 170e4063a15..2b865a1ae21 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -799,14 +799,13 @@ void LLAgentWearables::createStandardWearables()
 			((OnWearableItemCreatedCB*)(&(*cb)))->addPendingWearable(wearable);
 			// no need to update here...
 			LLUUID category_id = LLUUID::null;
-			create_inventory_item(gAgent.getID(),
+            create_inventory_wearable(gAgent.getID(),
 								  gAgent.getSessionID(),
 								  category_id,
 								  wearable->getTransactionID(),
 								  wearable->getName(),
 								  wearable->getDescription(),
 								  wearable->getAssetType(),
-								  LLInventoryType::IT_WEARABLE,
 								  wearable->getType(),
 								  wearable->getPermissions().getMaskNextOwner(),
 								  cb);
@@ -868,14 +867,13 @@ void LLAgentWearables::addWearableToAgentInventory(LLPointer<LLInventoryCallback
 												   const LLUUID& category_id,
 												   BOOL notify)
 {
-	create_inventory_item(gAgent.getID(),
+    create_inventory_wearable(gAgent.getID(),
 						  gAgent.getSessionID(),
 						  category_id,
 						  wearable->getTransactionID(),
 						  wearable->getName(),
 						  wearable->getDescription(),
 						  wearable->getAssetType(),
-						  LLInventoryType::IT_WEARABLE,
 						  wearable->getType(),
 						  wearable->getPermissions().getMaskNextOwner(),
 						  cb);
@@ -1540,7 +1538,6 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con
 
 	LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp);
 	LLAssetType::EType asset_type = wearable->getAssetType();
-	LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
 	LLPointer<LLInventoryCallback> cb;
 	if(wear)
 	{
@@ -1563,13 +1560,13 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con
 		folder_id = gInventory.findCategoryUUIDForType(folder_type);
 	}
 
-	create_inventory_item(gAgent.getID(),
+    create_inventory_wearable(gAgent.getID(),
 						  gAgent.getSessionID(),
 						  folder_id,
 						  wearable->getTransactionID(),
 						  wearable->getName(),
 						  wearable->getDescription(),
-						  asset_type, inv_type,
+						  asset_type,
 						  wearable->getType(),
 						  LLFloaterPerms::getNextOwnerPerms("Wearables"),
 						  cb);
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 0fb811a3867..534f3c7eb75 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1026,14 +1026,13 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type
 	const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
 	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(recovered_item_cb,_1,type,wearable,this));
 
-	create_inventory_item(gAgent.getID(),
+    create_inventory_wearable(gAgent.getID(),
 						  gAgent.getSessionID(),
 						  lost_and_found_id,
 						  wearable->getTransactionID(),
 						  wearable->getName(),
 						  wearable->getDescription(),
 						  wearable->getAssetType(),
-						  LLInventoryType::IT_WEARABLE,
 						  wearable->getType(),
 						  wearable->getPermissions().getMaskNextOwner(),
 						  cb);
diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp
index 0beb856456b..c1063218fb8 100644
--- a/indra/newview/llfloatereditextdaycycle.cpp
+++ b/indra/newview/llfloatereditextdaycycle.cpp
@@ -39,6 +39,8 @@
 #include "llspinctrl.h"
 #include "lltimectrl.h"
 
+#include "llsettingsvo.h"
+
 // newview
 #include "llagent.h"
 #include "llregioninfomodel.h"
@@ -73,12 +75,14 @@ BOOL LLFloaterEditExtDayCycle::postBuild()
 // 	mTimeCtrl = getChild<LLTimeCtrl>("time");
  	mSaveButton = getChild<LLButton>("save_btn");
     mCancelButton = getChild<LLButton>("cancel_btn");
+    mUploadButton = getChild<LLButton>("upload_btn");
 // 	mMakeDefaultCheckBox = getChild<LLCheckBoxCtrl>("make_default_cb");
 
 
     mDayPresetsCombo->setCommitCallback(boost::bind(&LLFloaterEditExtDayCycle::onDayPresetChanged, this));
     mSaveButton->setCommitCallback(boost::bind(&LLFloaterEditExtDayCycle::onBtnSave, this));
     mCancelButton->setCommitCallback(boost::bind(&LLFloaterEditExtDayCycle::onBtnCancel, this));
+    mUploadButton->setCommitCallback(boost::bind(&LLFloaterEditExtDayCycle::onUpload, this));
 
 	//initCallbacks();
 
@@ -90,6 +94,9 @@ BOOL LLFloaterEditExtDayCycle::postBuild()
 
 void LLFloaterEditExtDayCycle::onOpen(const LLSD& key)
 {
+    LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT);
+    LLEnvironment::instance().updateEnvironment();
+
     refreshSkyPresetsList();
 }
 
@@ -103,6 +110,65 @@ void LLFloaterEditExtDayCycle::onClose(bool app_quitting)
 	}
 }
 
+
+void LLFloaterEditExtDayCycle::onUpload()
+{
+    LLSettingsVOBase::createInventoryItem( mEditDay );
+
+#if 0
+    LLSettingsVOBase::storeAsAsset(mEditDay);
+
+    LLTransactionID tid;
+    tid.generate();
+    LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID());
+
+    const std::string filename = asset_id_to_filename(mAssetID, LL_PATH_CACHE);
+    if (!exportFile(filename))
+    {
+        std::string buffer = llformat("Unable to save '%s' to wearable file.", mName.c_str());
+        LL_WARNS() << buffer << LL_ENDL;
+
+        LLSD args;
+        args["NAME"] = mName;
+        LLNotificationsUtil::add("CannotSaveWearableOutOfSpace", args);
+        return;
+    }
+
+    if (gSavedSettings.getBOOL("LogWearableAssetSave"))
+    {
+        const std::string log_filename = asset_id_to_filename(mAssetID, LL_PATH_LOGS);
+        exportFile(log_filename);
+    }
+
+    // save it out to database
+    if (gAssetStorage)
+    {
+        /*
+        std::string url = gAgent.getRegion()->getCapability("NewAgentInventory");
+        if (!url.empty())
+        {
+        LL_INFOS() << "Update Agent Inventory via capability" << LL_ENDL;
+        LLSD body;
+        body["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetToFolderType(getAssetType()));
+        body["asset_type"] = LLAssetType::lookup(getAssetType());
+        body["inventory_type"] = LLInventoryType::lookup(LLInventoryType::IT_WEARABLE);
+        body["name"] = getName();
+        body["description"] = getDescription();
+        LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, filename));
+        }
+        else
+        {
+        }
+        */
+        LLWearableSaveData* data = new LLWearableSaveData;
+        data->mType = mType;
+        gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(),
+            &LLViewerWearable::onSaveNewAssetComplete,
+            (void*)data);
+    }
+#endif
+}
+
 void LLFloaterEditExtDayCycle::onVisibilityChange(BOOL new_visibility)
 {
     if (new_visibility)
diff --git a/indra/newview/llfloatereditextdaycycle.h b/indra/newview/llfloatereditextdaycycle.h
index 8b5a087edb4..18d0ce22590 100644
--- a/indra/newview/llfloatereditextdaycycle.h
+++ b/indra/newview/llfloatereditextdaycycle.h
@@ -54,6 +54,10 @@ class LLFloaterEditExtDayCycle : public LLFloater
  	void	onOpen(const LLSD& key);
  	void	onClose(bool app_quitting);
 
+
+    /*TEMP*/
+    void    onUpload();
+
     void    onVisibilityChange(BOOL new_visibility);
 
 // 	/*virtual*/ void	draw();
@@ -123,6 +127,7 @@ class LLFloaterEditExtDayCycle : public LLFloater
     LLComboBox*			mDayPresetsCombo;
     LLButton*			mSaveButton;
     LLButton*			mCancelButton;
+    LLButton*           mUploadButton;
 
     edit_commit_signal_t    mCommitSignal;
 
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index b840d37c4d9..57c010502ee 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -470,7 +470,7 @@ void LLFloaterGesture::onClickNew()
 						  "",
 						  LLAssetType::AT_GESTURE,
 						  LLInventoryType::IT_GESTURE,
-						  NOT_WEARABLE,
+                          NO_INV_SUBTYPE,
 						  PERM_MOVE | LLFloaterPerms::getNextOwnerPerms("Gestures"),
 						  cb);
 }
diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index c9a689281ea..7cde0615157 100644
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -161,7 +161,7 @@ void LLFloaterNameDesc::onBtnOK( )
 {
 	getChildView("ok_btn")->setEnabled(FALSE); // don't allow inadvertent extra uploads
 	
-	LLAssetStorage::LLStoreAssetCallback callback = NULL;
+	LLAssetStorage::LLStoreAssetCallback callback;
 	S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass).
 
     if (can_afford_transaction(expected_upload_cost))
@@ -169,7 +169,7 @@ void LLFloaterNameDesc::onBtnOK( )
         void *nruserdata = NULL;
         std::string display_name = LLStringUtil::null;
 
-        LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
+        LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLNewFileResourceUploadInfo>(
             mFilenameAndPath,
             getChild<LLUICtrl>("name_form")->getValue().asString(),
             getChild<LLUICtrl>("description_form")->getValue().asString(), 0,
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index 62cbea64012..0be748ace9d 100644
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -504,7 +504,7 @@ void LLFriendCardsManager::syncFriendsFolder()
 							  gAgentID.asString(),
 							  LLAssetType::AT_CALLINGCARD,
 							  LLInventoryType::IT_CALLINGCARD,
-							  NOT_WEARABLE,
+                              NO_INV_SUBTYPE,
 							  PERM_MOVE | PERM_TRANSFER,
 							  NULL);
 	}
diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp
index 9c00243f448..c243f8b4f01 100644
--- a/indra/newview/lllandmarkactions.cpp
+++ b/indra/newview/lllandmarkactions.cpp
@@ -272,7 +272,7 @@ void LLLandmarkActions::createLandmarkHere(
 		name, desc,
 		LLAssetType::AT_LANDMARK,
 		LLInventoryType::IT_LANDMARK,
-		NOT_WEARABLE, PERM_ALL, 
+        NO_INV_SUBTYPE, PERM_ALL,
 		NULL);
 }
 
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index c38d3ab1406..4df05ea4088 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -1219,7 +1219,7 @@ void LLOutfitGallery::uploadPhoto(LLUUID outfit_id)
             checkRemovePhoto(outfit_id);
             std::string upload_pending_name = outfit_id.asString();
             std::string upload_pending_desc = "";
-            LLAssetStorage::LLStoreAssetCallback callback = NULL;
+            LLAssetStorage::LLStoreAssetCallback callback;
             LLUUID photo_id = upload_new_resource(filename, // file
                 upload_pending_name,
                 upload_pending_desc,
diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp
index f3a4cf36eed..b8aa976657f 100644
--- a/indra/newview/llpanelsnapshotpostcard.cpp
+++ b/indra/newview/llpanelsnapshotpostcard.cpp
@@ -170,14 +170,16 @@ void LLPanelSnapshotPostcard::sendPostcard()
     std::string url = gAgent.getRegion()->getCapability("SendPostcard");
     if (!url.empty())
     {
-        LLResourceUploadInfo::ptr_t uploadInfo(new LLPostcardUploadInfo(
+        LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLPostcardUploadInfo>(
             getChild<LLUICtrl>("name_form")->getValue().asString(),
             getChild<LLUICtrl>("to_form")->getValue().asString(),
             getChild<LLUICtrl>("subject_form")->getValue().asString(),
             getChild<LLUICtrl>("msg_form")->getValue().asString(),
             mSnapshotFloater->getPosTakenGlobal(),
             mSnapshotFloater->getImageData(),
-            boost::bind(&LLPanelSnapshotPostcard::sendPostcardFinished, _4)));
+            [](LLUUID, LLUUID, LLUUID, LLSD response) {
+                LLPanelSnapshotPostcard::sendPostcardFinished(response);
+            }));
 
         LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
     }
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 787bd68e589..70ce2757344 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -1091,7 +1091,7 @@ void LLPreviewGesture::saveIfNeeded()
         const LLViewerRegion* region = gAgent.getRegion();
         if (!region)
         {
-            LL_WARNS() << "Not connected to a region, cannot save notecard." << LL_ENDL;
+            LL_WARNS() << "Not connected to a region, cannot save gesture." << LL_ENDL;
             return;
         }
         std::string agent_url = region->getCapability("UpdateGestureAgentInventory");
@@ -1111,13 +1111,15 @@ void LLPreviewGesture::saveIfNeeded()
                 refresh();
                 item->setComplete(true);
 
-                uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mItemUUID, LLAssetType::AT_GESTURE, buffer,
-                    boost::bind(&LLPreviewGesture::finishInventoryUpload, _1, _2)));
+                uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mItemUUID, LLAssetType::AT_GESTURE, buffer,
+                    [](LLUUID itemId, LLUUID newAssetId, LLUUID, LLSD) {
+                        LLPreviewGesture::finishInventoryUpload(itemId, newAssetId);
+                    });
                 url = agent_url;
             }
             else if (!mObjectUUID.isNull() && !task_url.empty())
             {
-                uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mObjectUUID, mItemUUID, LLAssetType::AT_GESTURE, buffer, NULL));
+                uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mObjectUUID, mItemUUID, LLAssetType::AT_GESTURE, buffer, nullptr);
                 url = task_url;
             }
 
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index d4a8bbdf453..fec16998d64 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -508,14 +508,19 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem)
 
                 if (mObjectUUID.isNull() && !agent_url.empty())
                 {
-                    uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mItemUUID, LLAssetType::AT_NOTECARD, buffer, 
-                        boost::bind(&LLPreviewNotecard::finishInventoryUpload, _1, _2, _3)));
+                    uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mItemUUID, LLAssetType::AT_NOTECARD, buffer, 
+                        [](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD) {
+                            LLPreviewNotecard::finishInventoryUpload(itemId, newAssetId, newItemId);
+                        });
                     url = agent_url;
                 }
                 else if (!mObjectUUID.isNull() && !task_url.empty())
                 {
-                    uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mObjectUUID, mItemUUID, LLAssetType::AT_NOTECARD, buffer, 
-                        boost::bind(&LLPreviewNotecard::finishTaskUpload, _1, _3, mObjectUUID)));
+                    LLUUID object_uuid(mObjectUUID);
+                    uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mObjectUUID, mItemUUID, LLAssetType::AT_NOTECARD, buffer, 
+                        [object_uuid](LLUUID itemId, LLUUID, LLUUID newAssetId, LLSD) {
+                            LLPreviewNotecard::finishTaskUpload(itemId, newAssetId, object_uuid);
+                        });
                     url = task_url;
                 }
 
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 3795e043ba8..72e6ba96090 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -1707,9 +1707,11 @@ void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/)
         if (!url.empty())
         {
             std::string buffer(mScriptEd->mEditor->getText());
-            LLBufferedAssetUploadInfo::invnUploadFinish_f proc = boost::bind(&LLPreviewLSL::finishedLSLUpload, _1, _4);
 
-            LLResourceUploadInfo::ptr_t uploadInfo(new LLScriptAssetUpload(mItemUUID, buffer, proc));
+            LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLScriptAssetUpload>(mItemUUID, buffer, 
+                [](LLUUID itemId, LLUUID, LLUUID, LLSD response) {
+                    LLPreviewLSL::finishedLSLUpload(itemId, response);
+                }));
 
             LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
         }
@@ -2241,11 +2243,13 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/)
     if (!url.empty())
     {
         std::string buffer(mScriptEd->mEditor->getText());
-        LLBufferedAssetUploadInfo::taskUploadFinish_f proc = boost::bind(&LLLiveLSLEditor::finishLSLUpload, _1, _2, _3, _4, isRunning);
 
-        LLResourceUploadInfo::ptr_t uploadInfo(new LLScriptAssetUpload(mObjectUUID, mItemUUID, 
+        LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLScriptAssetUpload>(mObjectUUID, mItemUUID, 
                 monoChecked() ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2, 
-                isRunning, mScriptEd->getAssociatedExperience(), buffer, proc));
+                isRunning, mScriptEd->getAssociatedExperience(), buffer, 
+                [isRunning](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) { 
+                    LLLiveLSLEditor::finishLSLUpload(itemId, taskId, newAssetId, response, isRunning);
+                }));
 
         LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
     }
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 6b1c663357c..aa3adfb8dd3 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -32,6 +32,7 @@
 #include "pipeline.h"
 
 #include <algorithm>
+#include <cstdio>
 #include <boost/make_shared.hpp>
 #include "lltrace.h"
 #include "llfasttimer.h"
@@ -40,9 +41,21 @@
 #include "llglslshader.h"
 #include "llviewershadermgr.h"
 
+#include "llagent.h"
+#include "llassettype.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"
+
 #undef  VERIFY_LEGACY_CONVERSION
 
 //=========================================================================
@@ -66,7 +79,257 @@ LLSD ensureArray4(LLSD in, F32 fill)
     }
     return out;
 }
+
+
+//-------------------------------------------------------------------------
+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;
+};
+
+}
+
+
+//=========================================================================
+#if 0
+void LLSettingsVOBase::storeAsAsset(const LLSettingsBase::ptr_t &settings)
+{
+    LLTransactionID tid;
+    tid.generate();
+
+    LLAssetID aid(tid.makeAssetID(gAgent.getSecureSessionID()));
+
+    const std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, aid.asString()) + ".setting";
+
+    if (!exportFile(settings, filename))
+    {
+        LL_WARNS("SETTINGS") << "Unable to save settings file named '" << filename << "'." << LL_ENDL;
+
+        LLSD args;
+        args["NAME"] = aid.asString() + "setting";
+        LLNotificationsUtil::add("CannotSaveWearableOutOfSpace", args);
+        return;
+    }
+
+    SettingsSaveData::ptr_t psave = std::make_shared<SettingsSaveData>();
+    psave->mType = settings->getSettingType();
+    psave->mSettings = settings;
+    psave->mTempFile = filename;
+    psave->mTransId = tid;
+
+    gAssetStorage->storeAssetData(filename, tid, LLAssetType::AT_SETTINGS,
+        [psave](const LLUUID &assetId, void *, S32 status, LLExtStat extstat) {
+            onSaveNewAssetComplete(assetId, psave, status, extstat);
+        },
+        nullptr);
+
+}
+
+void testingOnGotAsset(LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status)
+{
+    LL_WARNS("SETTINGS") << "Got back stored setting with id '" << asset_id << "' status is " << status << ":" << ext_status << LL_ENDL;
+}
+
+
+void LLSettingsVOBase::onSaveNewAssetComplete(const LLUUID& new_asset_id, const LLSettingsVOBase::SettingsSaveData::ptr_t &savedata, 
+        S32 status, LLExtStat ext_status)
+{
+    if (!status)
+    {
+        // Success
+        LL_INFOS("SETTINGS") << "Saved setting of type '" << savedata->mType << "' as " << new_asset_id << LL_ENDL;
+    }
+    else
+    {
+        LL_WARNS("SETTINGS") << "Unable to save '" << savedata->mType << "' to central asset store." << LL_ENDL;
+        LLSD args;
+        args["NAME"] = savedata->mType;
+        LLNotificationsUtil::add("CannotSaveToAssetStore", args);
+    }
+
+    gAssetStorage->getAssetData(new_asset_id, LLAssetType::AT_SETTINGS, &testingOnGotAsset, nullptr);
+
+    std::remove(savedata->mTempFile.c_str());
+}
+#endif
+
+
+void LLSettingsVOBase::createInventoryItem(const LLSettingsBase::ptr_t &settings)
+{
+    LLTransactionID tid;
+    LLUUID          parentFolder = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
+    U32             nextOwnerPerm = LLPermissions::DEFAULT.getMaskNextOwner();
+
+    tid.generate();
+
+    LLPointer<LLInventoryCallback> cb = new LLSettingsInventoryCB([settings](const LLUUID &inventoryId) {
+            LLSettingsVOBase::onInventoryItemCreated(inventoryId, settings);
+        });
+
+    create_inventory_settings(gAgent.getID(), gAgent.getSessionID(),
+        parentFolder, tid,
+        settings->getName(), "new settings collection.",
+        settings->getSettingTypeValue(), nextOwnerPerm, cb);
+}
+
+void LLSettingsVOBase::onInventoryItemCreated(const LLUUID &inventoryId, LLSettingsBase::ptr_t settings)
+{
+    // We need to update some inventory stuff here.... maybe.
+    uploadSettingsAsset(settings, inventoryId);
+}
+
+
+void LLSettingsVOBase::uploadSettingsAsset(const LLSettingsBase::ptr_t &settings, LLUUID inv_item_id)
+{
+    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 (agent_url.empty())
+    {
+        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
+        return;
+    }
+
+    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](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response) {
+            LLSettingsVOBase::onAgentAssetUploadComplete(itemId, newAssetId, newItemId, response, settings);
+        });
+
+    LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
+}
+
+void LLSettingsVOBase::uploadSettingsAsset(const LLSettingsBase::ptr_t &settings, LLUUID object_id, LLUUID inv_item_id)
+{
+    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 (agent_url.empty())
+    {
+        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
+        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](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) {
+        LLSettingsVOBase::onTaskAssetUploadComplete(itemId, taskId, newAssetId, response, settings);
+    });
+
+    LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
+}
+
+void LLSettingsVOBase::onAgentAssetUploadComplete(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response, LLSettingsBase::ptr_t psettings)
+{
+    LL_WARNS("SETTINGS") << "Upload to inventory complete!" << LL_ENDL;
+}
+
+void LLSettingsVOBase::onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, LLSettingsBase::ptr_t psettings)
+{
+    LL_WARNS("SETTINGS") << "Upload to task complete!" << LL_ENDL;
+}
+
+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 false;
+    }
+
+    std::string settingtype = settings[SETTING_NAME].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 '" << filename << "'." << LL_ENDL;
+    return LLSettingsBase::ptr_t();
 }
+
+
 //=========================================================================
 LLSettingsVOSky::LLSettingsVOSky(const LLSD &data):
     LLSettingsSky(data)
@@ -79,6 +342,20 @@ LLSettingsVOSky::LLSettingsVOSky():
 }
 
 //-------------------------------------------------------------------------
+LLSettingsSky::ptr_t LLSettingsVOSky::buildSky(LLSD settings)
+{
+    LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
+    LLSD results = LLSettingsSky::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);
+}
+
+
 LLSettingsSky::ptr_t LLSettingsVOSky::buildFromLegacyPreset(const std::string &name, const LLSD &legacy)
 {
 
@@ -253,6 +530,19 @@ LLSettingsVOWater::LLSettingsVOWater() :
 
 }
 
+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)
 {
@@ -410,6 +700,23 @@ 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 LLSD &oldsettings)
 {
diff --git a/indra/newview/llsettingsvo.h b/indra/newview/llsettingsvo.h
index ba96a19d3e6..55e04b5f3a3 100644
--- a/indra/newview/llsettingsvo.h
+++ b/indra/newview/llsettingsvo.h
@@ -33,11 +33,56 @@
 #include "llsettingswater.h"
 #include "llsettingsdaycycle.h"
 
+#include "llsdserialize.h"
+
+#include "llextendedstatus.h"
+
+//=========================================================================
+class LLSettingsVOBase : public LLSettingsBase
+{
+public:
+#if 0
+    static void     storeAsAsset(const LLSettingsBase::ptr_t &settings);
+#endif
+
+    static void     createInventoryItem(const LLSettingsBase::ptr_t &settings);
+    
+    static void     uploadSettingsAsset(const LLSettingsBase::ptr_t &settings, LLUUID inv_item_id);
+    static void     uploadSettingsAsset(const LLSettingsBase::ptr_t &settings, LLUUID object_id, LLUUID inv_item_id);
+
+
+    static bool     exportFile(const LLSettingsBase::ptr_t &settings, const std::string &filename, LLSDSerialize::ELLSD_Serialize format = LLSDSerialize::LLSD_NOTATION);
+    static LLSettingsBase::ptr_t importFile(const std::string &filename);
+
+private:
+    struct SettingsSaveData
+    {
+        typedef std::shared_ptr<SettingsSaveData> ptr_t;
+        std::string             mType;
+        std::string             mTempFile;
+        LLSettingsBase::ptr_t   mSettings;
+        LLTransactionID         mTransId;
+    };
+
+    LLSettingsVOBase() {}
+
+    static void     onInventoryItemCreated(const LLUUID &inventoryId, LLSettingsBase::ptr_t settings);
+
+#if 0
+    static void     onSaveNewAssetComplete(const LLUUID& new_asset_id, const SettingsSaveData::ptr_t &savedata, S32 status, LLExtStat ext_status);
+#endif
+    static void     onAgentAssetUploadComplete(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response, LLSettingsBase::ptr_t psettings);
+    static void     onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, LLSettingsBase::ptr_t psettings);
+};
+
+//=========================================================================
 class LLSettingsVOSky : public LLSettingsSky
 {
 public:
     LLSettingsVOSky(const LLSD &data);
 
+    static ptr_t    buildSky(LLSD settings);
+
     static ptr_t    buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings);
     static ptr_t    buildDefaultSky();
     virtual ptr_t   buildClone();
@@ -46,9 +91,9 @@ class LLSettingsVOSky : public LLSettingsSky
 protected:
     LLSettingsVOSky();
 
-    virtual void updateSettings();
+    virtual void    updateSettings();
 
-    virtual void        applySpecial(void *);
+    virtual void    applySpecial(void *);
 
     virtual parammapping_t getParameterMap() const;
 
@@ -60,6 +105,8 @@ class LLSettingsVOWater : public LLSettingsWater
 public:
     LLSettingsVOWater(const LLSD &data);
 
+    static ptr_t    buildWater(LLSD settings);
+
     static ptr_t    buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings);
     static ptr_t    buildDefaultWater();
     virtual ptr_t   buildClone();
@@ -68,8 +115,8 @@ class LLSettingsVOWater : public LLSettingsWater
 protected:
     LLSettingsVOWater();
 
-    virtual void updateSettings();
-    virtual void applySpecial(void *);
+    virtual void    updateSettings();
+    virtual void    applySpecial(void *);
 
     virtual parammapping_t getParameterMap() const;
 
@@ -85,6 +132,8 @@ class LLSettingsVODay : public LLSettingsDay
 public:
     LLSettingsVODay(const LLSD &data);
 
+    static ptr_t    buildDay(LLSD settings);
+
     static ptr_t    buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings);
     static ptr_t    buildFromLegacyMessage(const LLUUID &regionId, LLSD daycycle, LLSD skys, LLSD water);
     static ptr_t    buildDefaultDayCycle();
diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h
index 50131682e7f..cefe2154315 100644
--- a/indra/newview/llviewerassetstorage.h
+++ b/indra/newview/llviewerassetstorage.h
@@ -69,14 +69,14 @@ class LLViewerAssetStorage : public LLAssetStorage
 	// virtual
 	void _queueDataRequest(const LLUUID& uuid,
 						   LLAssetType::EType type,
-						   void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
+                           LLGetAssetCallback callback,
 						   void *user_data,
 						   BOOL duplicate,
 						   BOOL is_priority);
 
     void queueRequestHttp(const LLUUID& uuid,
                           LLAssetType::EType type,
-                          void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
+                          LLGetAssetCallback callback,
                           void *user_data,
                           BOOL duplicate,
                           BOOL is_priority);
@@ -86,7 +86,7 @@ class LLViewerAssetStorage : public LLAssetStorage
     void assetRequestCoro(LLViewerAssetRequest *req,
                           const LLUUID uuid,
                           LLAssetType::EType atype,
-                          void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
+                          LLGetAssetCallback callback,
                           void *user_data);
 
     std::string getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype);
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 01b4fcfbe17..fcb1bd40c72 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -482,7 +482,7 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType:
     mTaskId(LLUUID::null),
     mContents(buffer),
     mInvnFinishFn(finish),
-    mTaskFinishFn(NULL),
+    mTaskFinishFn(nullptr),
     mStoredToVFS(false)
 {
     setItemId(itemId);
@@ -496,7 +496,7 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LL
     mTaskId(LLUUID::null),
     mContents(),
     mInvnFinishFn(finish),
-    mTaskFinishFn(NULL),
+    mTaskFinishFn(nullptr),
     mStoredToVFS(false)
 {
     setItemId(itemId);
@@ -529,7 +529,7 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemI
     mTaskUpload(true),
     mTaskId(taskId),
     mContents(buffer),
-    mInvnFinishFn(NULL),
+    mInvnFinishFn(nullptr),
     mTaskFinishFn(finish),
     mStoredToVFS(false)
 {
diff --git a/indra/newview/llviewerassetupload.h b/indra/newview/llviewerassetupload.h
index 43e23a0d42f..e18b75489af 100644
--- a/indra/newview/llviewerassetupload.h
+++ b/indra/newview/llviewerassetupload.h
@@ -40,7 +40,7 @@
 class LLResourceUploadInfo
 {
 public:
-    typedef boost::shared_ptr<LLResourceUploadInfo> ptr_t;
+    typedef std::shared_ptr<LLResourceUploadInfo> ptr_t;
 
     LLResourceUploadInfo(
         LLTransactionID transactId,
@@ -165,8 +165,8 @@ class LLNewFileResourceUploadInfo : public LLResourceUploadInfo
 class LLBufferedAssetUploadInfo : public LLResourceUploadInfo
 {
 public:
-    typedef boost::function<void(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response)> invnUploadFinish_f;
-    typedef boost::function<void(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response)> taskUploadFinish_f;
+    typedef std::function<void(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response)> invnUploadFinish_f;
+    typedef std::function<void(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response)> taskUploadFinish_f;
 
     LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish);
     LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LLImageFormatted> image, invnUploadFinish_f finish);
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 1ab7ec0156d..d6f48a4c550 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1097,7 +1097,7 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
 						   const LLUUID& parent, const LLTransactionID& transaction_id,
 						   const std::string& name,
 						   const std::string& desc, LLAssetType::EType asset_type,
-						   LLInventoryType::EType inv_type, LLWearableType::EType wtype,
+						   LLInventoryType::EType inv_type, U8 subtype,
 						   U32 next_owner_perm,
 						   LLPointer<LLInventoryCallback> cb)
 {
@@ -1132,7 +1132,7 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
 	msg->addU32Fast(_PREHASH_NextOwnerMask, next_owner_perm);
 	msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
 	msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
-	msg->addU8Fast(_PREHASH_WearableType, (U8)wtype);
+	msg->addU8Fast(_PREHASH_WearableType, (U8)subtype);
 	msg->addStringFast(_PREHASH_Name, server_name);
 	msg->addStringFast(_PREHASH_Description, desc);
 	
@@ -1146,9 +1146,36 @@ void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent
 	LLAvatarNameCache::get(avatar_id, &av_name);
 	create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
 						  parent, LLTransactionID::tnull, av_name.getUserName(), item_desc, LLAssetType::AT_CALLINGCARD,
-						  LLInventoryType::IT_CALLINGCARD, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, cb);
+                          LLInventoryType::IT_CALLINGCARD, NO_INV_SUBTYPE, PERM_MOVE | PERM_TRANSFER, cb);
 }
 
+void create_inventory_wearable(const LLUUID& agent_id, const LLUUID& session_id,
+    const LLUUID& parent, const LLTransactionID& transaction_id,
+    const std::string& name,
+    const std::string& desc, LLAssetType::EType asset_type,
+    LLWearableType::EType wtype,
+    U32 next_owner_perm,
+    LLPointer<LLInventoryCallback> cb)
+{
+    create_inventory_item(agent_id, session_id, parent, transaction_id,
+        name, desc, asset_type, LLInventoryType::IT_WEARABLE, static_cast<U8>(wtype),
+        next_owner_perm, cb);
+}
+
+void create_inventory_settings(const LLUUID& agent_id, const LLUUID& session_id,
+    const LLUUID& parent, const LLTransactionID& transaction_id,
+    const std::string& name,
+    const std::string& desc, 
+    LLSettingsType settype,
+    U32 next_owner_perm,
+    LLPointer<LLInventoryCallback> cb)
+{
+    create_inventory_item(agent_id, session_id, parent, transaction_id,
+        name, desc, LLAssetType::AT_SETTINGS, LLInventoryType::IT_SETTINGS, 
+        static_cast<U8>(settype), next_owner_perm, cb);
+}
+
+
 void copy_inventory_item(
 	const LLUUID& agent_id,
 	const LLUUID& current_owner,
@@ -1700,7 +1727,7 @@ void create_new_item(const std::string& name,
 						  desc,
 						  asset_type,
 						  inv_type,
-						  NOT_WEARABLE,
+                          NO_INV_SUBTYPE,
 						  next_owner_perm,
 						  cb);
 }	
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index b3053e365bd..b89ed42829b 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -31,6 +31,7 @@
 #include "llframetimer.h"
 #include "llwearable.h"
 #include "llinitdestroyclass.h" //for LLDestroyClass
+#include "llinventorysettings.h"
 
 #include <boost/signals2.hpp>	// boost::signals2::trackable
 
@@ -295,7 +296,7 @@ class LLBoostFuncInventoryCallback: public LLInventoryCallback
 
 	// virtual
 	void fire(const LLUUID& item_id)
-{
+    {
 		mFireFunc(item_id);
 	}
 
@@ -336,17 +337,32 @@ class LLInventoryCallbackManager : public LLDestroyClass<LLInventoryCallbackMana
 extern LLInventoryCallbackManager gInventoryCallbacks;
 
 
-#define NOT_WEARABLE (LLWearableType::EType)0
+const U8 NO_INV_SUBTYPE{ 0 };
 
 // *TODO: Find a home for these
 void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
 						   const LLUUID& parent, const LLTransactionID& transaction_id,
 						   const std::string& name,
 						   const std::string& desc, LLAssetType::EType asset_type,
-						   LLInventoryType::EType inv_type, LLWearableType::EType wtype,
+						   LLInventoryType::EType inv_type, U8 subtype,
 						   U32 next_owner_perm,
 						   LLPointer<LLInventoryCallback> cb);
 
+void create_inventory_wearable(const LLUUID& agent_id, const LLUUID& session_id,
+    const LLUUID& parent, const LLTransactionID& transaction_id,
+    const std::string& name,
+    const std::string& desc, LLAssetType::EType asset_type,
+    LLWearableType::EType wtype,
+    U32 next_owner_perm,
+    LLPointer<LLInventoryCallback> cb);
+
+void create_inventory_settings(const LLUUID& agent_id, const LLUUID& session_id,
+    const LLUUID& parent, const LLTransactionID& transaction_id,
+    const std::string& name, const std::string& desc, 
+    LLSettingsType settype, 
+    U32 next_owner_perm, LLPointer<LLInventoryCallback> cb);
+
+
 void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent = LLUUID::null, LLPointer<LLInventoryCallback> cb=NULL);
 
 /**
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 90355b7166e..482de8a7228 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -441,7 +441,7 @@ class LLFileUploadBulk : public view_listener_t
                 LLStringUtil::stripNonprintable(asset_name);
                 LLStringUtil::trim(asset_name);
 
-                LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
+                LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLNewFileResourceUploadInfo>(
                     filename,
                     asset_name,
                     asset_name, 0,
@@ -451,7 +451,7 @@ class LLFileUploadBulk : public view_listener_t
                     LLFloaterPerms::getEveryonePerms("Uploads"),
                     expected_upload_cost));
 
-                upload_new_resource(uploadInfo, NULL, NULL);
+                upload_new_resource(uploadInfo);
 
                 filename = picker.getNextFile();
             }
@@ -647,7 +647,7 @@ LLUUID upload_new_resource(
 	void *userdata)
 {	
 
-    LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
+    LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLNewFileResourceUploadInfo>(
         src_filename,
         name, desc, compression_info,
         destination_folder_type, inv_type,
@@ -730,7 +730,7 @@ void upload_done_callback(
 					create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
 							      folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(),
 							      data->mAssetInfo.getDescription(), data->mAssetInfo.mType,
-							      data->mInventoryType, NOT_WEARABLE, next_owner_perms,
+                                  data->mInventoryType, NO_INV_SUBTYPE, next_owner_perms,
 							      LLPointer<LLInventoryCallback>(NULL));
 				}
 				else
@@ -766,7 +766,7 @@ void upload_done_callback(
 		LLStringUtil::trim(asset_name);
 
 		std::string display_name = LLStringUtil::null;
-		LLAssetStorage::LLStoreAssetCallback callback = NULL;
+		LLAssetStorage::LLStoreAssetCallback callback;
 		void *userdata = NULL;
 		upload_new_resource(
 			next_file,
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index 6941b4dc0e7..973739d7ac0 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -59,7 +59,7 @@ LLUUID upload_new_resource(
 
 void upload_new_resource(
     LLResourceUploadInfo::ptr_t &uploadInfo,
-    LLAssetStorage::LLStoreAssetCallback callback = NULL,
+    LLAssetStorage::LLStoreAssetCallback callback = LLAssetStorage::LLStoreAssetCallback(),
     void *userdata = NULL);
 
 
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index b272595d79e..1520ef7a2fc 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -2895,9 +2895,13 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("UpdateGestureTaskInventory");
 	capabilityNames.append("UpdateNotecardAgentInventory");
 	capabilityNames.append("UpdateNotecardTaskInventory");
+    capabilityNames.append("UpdateSettingsAgentInventory");
+    capabilityNames.append("UpdateSettingsTaskInventory");
 	capabilityNames.append("UpdateScriptAgent");
 	capabilityNames.append("UpdateScriptTask");
-	capabilityNames.append("UploadBakedTexture");
+    capabilityNames.append("UpdateSettingsAgentInventory");
+    capabilityNames.append("UpdateSettingsTaskInventory");
+    capabilityNames.append("UploadBakedTexture");
     capabilityNames.append("UserInfo");
 	capabilityNames.append("ViewerAsset"); 
 	capabilityNames.append("ViewerMetrics");
diff --git a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
index 0f0acea832c..88423ad023e 100644
--- a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
+++ b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
@@ -24,8 +24,8 @@
                 border="false"
                 auto_resize="false"
                 user_resize="true"
-                height="30"
-                min_height="30"
+                height="45"
+                min_height="45"
                 background_visible="false">
             <!-- This layout_panel is for loading legacy presets -->
             <text
@@ -34,8 +34,7 @@
                     height="10"
                     layout="topleft"
                     name="label"
-                    top_offset="20"
-                    left_offset="10"
+                    top_delta="70"
                     width="120">
                 Preset Name:
             </text>
@@ -138,6 +137,15 @@
                     name="cancel_btn"
                     width="100" /> 
 
+            <button
+                    follows="top|right"
+                    height="23"
+                    label="Upload"
+                    layout="topleft"
+                    left_pad="10"
+                    name="upload_btn"
+                    width="100" /> 
+                    
         </layout_panel>
     </layout_stack>
 
-- 
GitLab