From 6620211bff5dca7df0667cf9220da1a9e7ce079c Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 27 Mar 2020 00:13:33 +0200
Subject: [PATCH] SL-12911 Add Debug setting EnvironmentPersistAcrossLogin

---
 indra/llinventory/llsettingsbase.cpp        |   1 +
 indra/llinventory/llsettingsbase.h          |   1 +
 indra/llinventory/llsettingsdaycycle.cpp    |   4 +-
 indra/newview/llappviewer.cpp               |   7 +
 indra/newview/llenvironment.cpp             | 204 ++++++++++++++++++++
 indra/newview/llenvironment.h               |   3 +
 indra/newview/llfloatereditextdaycycle.cpp  |   1 +
 indra/newview/llfloaterfixedenvironment.cpp |   1 +
 indra/newview/llsettingsvo.cpp              |   6 +-
 9 files changed, 223 insertions(+), 5 deletions(-)

diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp
index ec26959718e..61b59e35aac 100644
--- a/indra/llinventory/llsettingsbase.cpp
+++ b/indra/llinventory/llsettingsbase.cpp
@@ -39,6 +39,7 @@ namespace
 }
 
 const LLSettingsBase::TrackPosition LLSettingsBase::INVALID_TRACKPOS(-1.0);
+const std::string LLSettingsBase::DEFAULT_SETTINGS_NAME("_default_");
 
 //=========================================================================
 std::ostream &operator <<(std::ostream& os, LLSettingsBase &settings)
diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h
index 56e28fc8993..1d118f07899 100644
--- a/indra/llinventory/llsettingsbase.h
+++ b/indra/llinventory/llsettingsbase.h
@@ -64,6 +64,7 @@ class LLSettingsBase :
     typedef F64        BlendFactor;
     typedef F32        TrackPosition; // 32-bit as these are stored in LLSD as such
     static const TrackPosition INVALID_TRACKPOS;
+    static const std::string DEFAULT_SETTINGS_NAME;
 
     static const std::string SETTING_ID;
     static const std::string SETTING_NAME;
diff --git a/indra/llinventory/llsettingsdaycycle.cpp b/indra/llinventory/llsettingsdaycycle.cpp
index 8498425f4e8..457e5b74789 100644
--- a/indra/llinventory/llsettingsdaycycle.cpp
+++ b/indra/llinventory/llsettingsdaycycle.cpp
@@ -408,7 +408,7 @@ LLSD LLSettingsDay::defaults()
 
     if (dfltsetting.size() == 0)
     {
-        dfltsetting[SETTING_NAME] = "_default_";
+        dfltsetting[SETTING_NAME] = DEFAULT_SETTINGS_NAME;
         dfltsetting[SETTING_TYPE] = "daycycle";
 
         LLSD frames(LLSD::emptyMap());
@@ -421,7 +421,7 @@ LLSD LLSettingsDay::defaults()
         F32 time = 0.0f;
         for (U32 i = 0; i < FRAME_COUNT; i++)
         {
-            std::string name("_default_");
+            std::string name(DEFAULT_SETTINGS_NAME);
             name += ('a' + i);
 
             std::string water_frame_name("water:");
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 118edb8beb6..cbb47d71f7c 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -33,6 +33,7 @@
 #include "llfeaturemanager.h"
 #include "lluictrlfactory.h"
 #include "lltexteditor.h"
+#include "llenvironment.h"
 #include "llerrorcontrol.h"
 #include "lleventtimer.h"
 #include "llviewertexturelist.h"
@@ -1908,6 +1909,12 @@ bool LLAppViewer::cleanup()
 	// Store the time of our current logoff
 	gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
 
+    if (LLEnvironment::instanceExists())
+    {
+        //Store environment settings if nessesary
+        LLEnvironment::getInstance()->saveToSettings();
+    }
+
 	// Must do this after all panels have been deleted because panels that have persistent rects
 	// save their rects on delete.
 	gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index c6d878769d6..85fe2a7c95b 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -101,6 +101,8 @@ namespace
     const std::string LISTENER_NAME("LLEnvironmentSingleton");
     const std::string PUMP_EXPERIENCE("experience_permission");
 
+    const std::string LOCAL_ENV_STORAGE_FILE("local_environment_data.bin");
+
     //---------------------------------------------------------------------
     LLTrace::BlockTimerStatHandle   FTM_ENVIRONMENT_UPDATE("Update Environment Tick");
     LLTrace::BlockTimerStatHandle   FTM_SHADER_PARAM_UPDATE("Update Shader Parameters");
@@ -849,6 +851,8 @@ void LLEnvironment::initSingleton()
     }
 
     LLEventPumps::instance().obtain(PUMP_EXPERIENCE).listen(LISTENER_NAME, [this](LLSD message) { listenExperiencePump(message); return false; });
+
+    loadFromSettings();
 }
 
 void LLEnvironment::cleanupSingleton()
@@ -2686,6 +2690,206 @@ void LLEnvironment::DayTransition::animate()
     });
 }
 
+void LLEnvironment::saveToSettings()
+{
+    std::string user_dir = gDirUtilp->getLindenUserDir();
+    if (user_dir.empty())
+    {
+        // not logged in
+        return;
+    }
+    bool has_data = false;
+
+    if (gSavedSettings.getBOOL("EnvironmentPersistAcrossLogin"))
+    {
+        DayInstance::ptr_t environment = getEnvironmentInstance(ENV_LOCAL);
+        if (environment)
+        {
+            // Environment is 'layered'. No data in ENV_LOCAL means we are using parcel/region
+            // Store local environment for next session
+            LLSD env_data;
+
+            LLSettingsDay::ptr_t day = environment->getDayCycle();
+            if (day)
+            {
+                const std::string name = day->getName();
+                const LLUUID asset_id = day->getAssetId();
+                if (asset_id.notNull())
+                {
+                    // just save the id
+                    env_data["day_id"] = asset_id;
+                    env_data["day_length"] = LLSD::Integer(environment->getDayLength());
+                    env_data["day_offset"] = LLSD::Integer(environment->getDayOffset());
+                    has_data = true;
+                }
+                else if (!name.empty() && name != LLSettingsBase::DEFAULT_SETTINGS_NAME)
+                {
+                    // This setting was created locally and was not saved
+                    // The only option is to save the whole thing
+                    env_data["day_llsd"] = day->getSettings();
+                    env_data["day_length"] = LLSD::Integer(environment->getDayLength());
+                    env_data["day_offset"] = LLSD::Integer(environment->getDayOffset());
+                    has_data = true;
+                }
+            }
+
+            LLSettingsSky::ptr_t sky = environment->getSky();
+            if ((environment->getFlags() & DayInstance::NO_ANIMATE_SKY) && sky)
+            {
+                const std::string name = sky->getName();
+                const LLUUID asset_id = sky->getAssetId();
+                if (asset_id.notNull())
+                {
+                    // just save the id
+                    env_data["sky_id"] = asset_id;
+                    has_data = true;
+                }
+                else if (!name.empty() && name != LLSettingsBase::DEFAULT_SETTINGS_NAME)
+                {
+                    // This setting was created locally and was not saved
+                    // The only option is to save the whole thing
+                    env_data["sky_llsd"] = sky->getSettings();
+                    has_data = true;
+                }
+                has_data = true;
+            }
+
+            LLSettingsWater::ptr_t water = environment->getWater();
+            if ((environment->getFlags() & DayInstance::NO_ANIMATE_WATER) && water)
+            {
+                const std::string name = water->getName();
+                const LLUUID asset_id = water->getAssetId();
+                if (asset_id.notNull())
+                {
+                    // just save the id
+                    env_data["water_id"] = asset_id;
+                    has_data = true;
+                }
+                else if (!name.empty() && name != LLSettingsBase::DEFAULT_SETTINGS_NAME)
+                {
+                    // This setting was created locally and was not saved
+                    // The only option is to save the whole thing
+                    env_data["water_llsd"] = water->getSettings();
+                    has_data = true;
+                }
+            }
+
+            std::string user_filepath = user_dir + gDirUtilp->getDirDelimiter() + LOCAL_ENV_STORAGE_FILE;
+            llofstream out(user_filepath.c_str(), std::ios_base::out | std::ios_base::binary);
+            if (out.good())
+            {
+                LLSDSerialize::toBinary(env_data, out);
+                out.close();
+            }
+            else
+            {
+                LL_WARNS("ENVIRONMENT") << "Unable to open " << user_filepath << " for output." << LL_ENDL;
+            }
+        }
+    }
+
+    if (!has_data)
+    {
+        LLFile::remove(user_dir + gDirUtilp->getDirDelimiter() + LOCAL_ENV_STORAGE_FILE, ENOENT);
+    }
+}
+
+bool LLEnvironment::loadFromSettings()
+{
+    if (!gSavedSettings.getBOOL("EnvironmentPersistAcrossLogin"))
+    {
+        return false;
+    }
+
+    std::string user_path = gDirUtilp->getLindenUserDir();
+    if (user_path.empty())
+    {
+        LL_WARNS("ENVIRONMENT") << "Can't load previous environment, Environment was initialized before user logged in" << LL_ENDL;
+        return false;
+    }
+    std::string user_filepath(user_path + gDirUtilp->getDirDelimiter() + LOCAL_ENV_STORAGE_FILE);
+    if (!gDirUtilp->fileExists(user_filepath))
+    {
+        // No previous environment
+        return false;
+    }
+
+    LLSD env_data;
+    llifstream file(user_filepath.c_str(), std::ios_base::in | std::ios_base::binary);
+    if (file.is_open())
+    {
+        LLSDSerialize::fromBinary(env_data, file, LLSDSerialize::SIZE_UNLIMITED);
+        if (env_data.isUndefined())
+        {
+            LL_WARNS("ENVIRONMENT") << "error loading " << user_filepath << LL_ENDL;
+            return false;
+        }
+        else
+        {
+            LL_INFOS("ENVIRONMENT") << "Loaded previous session environment from: " << user_filepath << LL_ENDL;
+        }
+        file.close();
+    }
+    else
+    {
+        LL_INFOS("ENVIRONMENT") << "Unable to open previous session environment file " << user_filepath << LL_ENDL;
+    }
+
+    if (!env_data.isMap() || env_data.emptyMap())
+    {
+        LL_DEBUGS("ENVIRONMENT") << "Empty map loaded from: " << user_filepath << LL_ENDL;
+        return false;
+    }
+
+    bool valid = false;
+
+    if (env_data.has("day_id"))
+    {
+        S32 length = env_data["day_length"].asInteger();
+        S32 offset = env_data["day_offset"].asInteger();
+        setEnvironment(ENV_LOCAL, env_data["day_id"].asUUID(), LLSettingsDay::Seconds(length), LLSettingsDay::Seconds(offset));
+        valid = true;
+    }
+    else if (env_data.has("day_llsd"))
+    {
+        S32 length = env_data["day_length"].asInteger();
+        S32 offset = env_data["day_offset"].asInteger();
+        LLSettingsDay::ptr_t day = std::make_shared<LLSettingsVODay>(env_data["day_llsd"]);
+        setEnvironment(ENV_LOCAL, day, LLSettingsDay::Seconds(length), LLSettingsDay::Seconds(offset));
+        valid = true;
+    }
+
+    if (env_data.has("sky_id"))
+    {
+        setEnvironment(ENV_LOCAL, env_data["sky_id"].asUUID());
+        valid = true;
+    }
+    else if (env_data.has("sky_llsd"))
+    {
+        LLSettingsSky::ptr_t sky = std::make_shared<LLSettingsVOSky>(env_data["sky_llsd"]);
+        setEnvironment(ENV_LOCAL, sky);
+        valid = true;
+    }
+
+    if (env_data.has("water_id"))
+    {
+        setEnvironment(ENV_LOCAL, env_data["water_id"].asUUID());
+        valid = true;
+    }
+    else if (env_data.has("water_llsd"))
+    {
+        LLSettingsWater::ptr_t sky = std::make_shared<LLSettingsVOWater>(env_data["water_llsd"]);
+        setEnvironment(ENV_LOCAL, sky);
+        valid = true;
+    }
+
+    if (valid)
+    {
+        updateEnvironment(TRANSITION_INSTANT, true);
+    }
+    return valid;
+}
+
 void LLEnvironment::saveBeaconsState()
 {
     if (mEditorCounter == 0)
diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h
index 97cc3c8740a..cf8231168f0 100644
--- a/indra/newview/llenvironment.h
+++ b/indra/newview/llenvironment.h
@@ -169,6 +169,8 @@ class LLEnvironment : public LLSingleton<LLEnvironment>
     bool                        getIsSunUp() const;
     bool                        getIsMoonUp() const;
 
+    void                        saveToSettings();
+    bool                        loadFromSettings();
     void                        saveBeaconsState();
     void                        revertBeaconsState();
 
@@ -275,6 +277,7 @@ class LLEnvironment : public LLSingleton<LLEnvironment>
 
         void                            setFlags(U32 flag) { mAnimateFlags |= flag; }
         void                            clearFlags(U32 flag) { mAnimateFlags &= ~flag; }
+        U32                             getFlags() { return mAnimateFlags; }
 
     protected:
 
diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp
index f57a54163db..ea22043de88 100644
--- a/indra/newview/llfloatereditextdaycycle.cpp
+++ b/indra/newview/llfloatereditextdaycycle.cpp
@@ -1715,6 +1715,7 @@ void LLFloaterEditExtDayCycle::doApplyEnvironment(const std::string &where, cons
 
     if (where == ACTION_APPLY_LOCAL)
     {
+        day->setName("Local"); // To distinguish and make sure there is a name. Safe, because this is a copy.
         LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, day);
     }
     else if (where == ACTION_APPLY_PARCEL)
diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
index 41d9a6d99b4..37e162b2493 100644
--- a/indra/newview/llfloaterfixedenvironment.cpp
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -580,6 +580,7 @@ void LLFloaterFixedEnvironment::doApplyEnvironment(const std::string &where, con
 
     if (where == ACTION_APPLY_LOCAL)
     {
+        settings->setName("Local"); // To distinguish and make sure there is a name. Safe, because this is a copy.
         LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, settings);
     }
     else if (where == ACTION_APPLY_PARCEL)
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index d96f276a71e..c72a0706cdc 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -514,7 +514,7 @@ LLSettingsSky::ptr_t LLSettingsVOSky::buildDefaultSky()
     {
         default_settings = LLSettingsSky::defaults();
 
-        default_settings[SETTING_NAME] = std::string("_default_");
+        default_settings[SETTING_NAME] = DEFAULT_SETTINGS_NAME;
 
         LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
         LLSD results = LLSettingsBase::settingValidation(default_settings, validations);
@@ -841,7 +841,7 @@ LLSettingsWater::ptr_t LLSettingsVOWater::buildDefaultWater()
     {
         default_settings = LLSettingsWater::defaults();
 
-        default_settings[SETTING_NAME] = std::string("_default_");
+        default_settings[SETTING_NAME] = DEFAULT_SETTINGS_NAME;
 
         LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
         LLSD results = LLSettingsWater::settingValidation(default_settings, validations);
@@ -1169,7 +1169,7 @@ LLSettingsDay::ptr_t LLSettingsVODay::buildDefaultDayCycle()
     if (!default_settings.size())
     {
         default_settings = LLSettingsDay::defaults();
-        default_settings[SETTING_NAME] = std::string("_default_");
+        default_settings[SETTING_NAME] = DEFAULT_SETTINGS_NAME;
 
         LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
         LLSD results = LLSettingsDay::settingValidation(default_settings, validations);
-- 
GitLab