From 7da3a1eb4f14b67c698977eb1947ce06a312d507 Mon Sep 17 00:00:00 2001
From: Graham Linden <graham@lindenlab.com>
Date: Mon, 6 Aug 2018 17:49:50 +0100
Subject: [PATCH] WIP check-in to allow merge of upstream changes.

---
 indra/llinventory/llsettingssky.cpp           |  88 ++++---
 indra/llinventory/llsettingssky.h             |  24 +-
 indra/newview/CMakeLists.txt                  |   2 +
 indra/newview/lldensityctrl.cpp               | 225 ++++++++++++++++++
 indra/newview/lldensityctrl.h                 | 104 ++++++++
 indra/newview/llfloatereditextdaycycle.cpp    |  11 +
 indra/newview/llpaneleditsky.cpp              |  94 +++++++-
 indra/newview/llpaneleditsky.h                |  43 +++-
 .../xui/en/floater_edit_ext_day_cycle.xml     |   9 +
 .../xui/en/panel_settings_sky_density.xml     |  32 +++
 .../default/xui/en/widgets/density_ctrl.xml   | 164 +++++++++++++
 11 files changed, 759 insertions(+), 37 deletions(-)
 create mode 100644 indra/newview/lldensityctrl.cpp
 create mode 100644 indra/newview/lldensityctrl.h
 create mode 100644 indra/newview/skins/default/xui/en/panel_settings_sky_density.xml
 create mode 100644 indra/newview/skins/default/xui/en/widgets/density_ctrl.xml

diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index 4451bd753b2..a7f9aa78422 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -554,36 +554,53 @@ LLSettingsSky::validation_list_t LLSettingsSky::validationList()
     return validation;
 }
 
+LLSD LLSettingsSky::createDensityProfileLayer(
+    F32 width,
+    F32 exponential_term,
+    F32 exponential_scale_factor,
+    F32 linear_term,
+    F32 constant_term,
+    F32 aniso_factor)
+{
+    LLSD dflt_layer;
+    dflt_layer[SETTING_DENSITY_PROFILE_WIDTH]            = 0.0f; // 0 -> the entire atmosphere
+    dflt_layer[SETTING_DENSITY_PROFILE_EXP_TERM]         = 1.0f;
+    dflt_layer[SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR] = -1.0f / 8000.0f;
+    dflt_layer[SETTING_DENSITY_PROFILE_LINEAR_TERM]      = 0.0f;
+    dflt_layer[SETTING_DENSITY_PROFILE_CONSTANT_TERM]    = 0.0f;
+
+    if (aniso_factor != 0.0f)
+    {
+        dflt_layer[SETTING_MIE_ANISOTROPY_FACTOR] = aniso_factor;
+    }
+
+    return dflt_layer;
+}
+
+LLSD LLSettingsSky::createSingleLayerDensityProfile(
+    F32 width,
+    F32 exponential_term,
+    F32 exponential_scale_factor,
+    F32 linear_term,
+    F32 constant_term,
+    F32 aniso_factor)
+{
+    LLSD dflt;
+    LLSD dflt_layer = createDensityProfileLayer(width, exponential_term, exponential_scale_factor, linear_term, constant_term, aniso_factor);
+    dflt.append(dflt_layer);
+    return dflt;
+}
+
 LLSD LLSettingsSky::rayleighConfigDefault()
 {
-    LLSD dflt_rayleigh;
-    LLSD dflt_rayleigh_layer;
-    dflt_rayleigh_layer[SETTING_DENSITY_PROFILE_WIDTH]            = 0.0f; // 0 -> the entire atmosphere
-    dflt_rayleigh_layer[SETTING_DENSITY_PROFILE_EXP_TERM]         = 1.0f;
-    dflt_rayleigh_layer[SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR] = -1.0f / 8000.0f;
-    dflt_rayleigh_layer[SETTING_DENSITY_PROFILE_LINEAR_TERM]      = 0.0f;
-    dflt_rayleigh_layer[SETTING_DENSITY_PROFILE_CONSTANT_TERM]    = 0.0f;
-    dflt_rayleigh.append(dflt_rayleigh_layer);
-    return dflt_rayleigh;
+    return createSingleLayerDensityProfile(0.0f,  1.0f, -1.0f / 8000.0f, 0.0f, 0.0f);
 }
 
 LLSD LLSettingsSky::absorptionConfigDefault()
 {
 // absorption (ozone) has two linear ramping zones
-    LLSD dflt_absorption_layer_a;
-    dflt_absorption_layer_a[SETTING_DENSITY_PROFILE_WIDTH]            = 25000.0f; // 0 -> the entire atmosphere
-    dflt_absorption_layer_a[SETTING_DENSITY_PROFILE_EXP_TERM]         = 0.0f;
-    dflt_absorption_layer_a[SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR] = 0.0f;
-    dflt_absorption_layer_a[SETTING_DENSITY_PROFILE_LINEAR_TERM]      = -1.0f / 25000.0f;
-    dflt_absorption_layer_a[SETTING_DENSITY_PROFILE_CONSTANT_TERM]    = -2.0f / 3.0f;
-
-    LLSD dflt_absorption_layer_b;
-    dflt_absorption_layer_b[SETTING_DENSITY_PROFILE_WIDTH]            = 0.0f; // 0 -> remainder of the atmosphere
-    dflt_absorption_layer_b[SETTING_DENSITY_PROFILE_EXP_TERM]         = 0.0f;
-    dflt_absorption_layer_b[SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR] = 0.0f;
-    dflt_absorption_layer_b[SETTING_DENSITY_PROFILE_LINEAR_TERM]      = -1.0f / 15000.0f;
-    dflt_absorption_layer_b[SETTING_DENSITY_PROFILE_CONSTANT_TERM]    = 8.0f  / 3.0f;
-
+    LLSD dflt_absorption_layer_a = createDensityProfileLayer(25000.0f, 0.0f, 0.0f, -1.0f / 25000.0f, -2.0f / 3.0f);
+    LLSD dflt_absorption_layer_b = createDensityProfileLayer(0.0f, 0.0f, 0.0f, -1.0f / 15000.0f, 8.0f / 3.0f);
     LLSD dflt_absorption;
     dflt_absorption.append(dflt_absorption_layer_a);
     dflt_absorption.append(dflt_absorption_layer_b);
@@ -592,15 +609,7 @@ LLSD LLSettingsSky::absorptionConfigDefault()
 
 LLSD LLSettingsSky::mieConfigDefault()
 {
-    LLSD dflt_mie;
-    LLSD dflt_mie_layer;
-    dflt_mie_layer[SETTING_DENSITY_PROFILE_WIDTH]            = 0.0f; // 0 -> the entire atmosphere
-    dflt_mie_layer[SETTING_DENSITY_PROFILE_EXP_TERM]         = 1.0f;
-    dflt_mie_layer[SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR] = -1.0f / 1200.0f;
-    dflt_mie_layer[SETTING_DENSITY_PROFILE_LINEAR_TERM]      = 0.0f;
-    dflt_mie_layer[SETTING_DENSITY_PROFILE_CONSTANT_TERM]    = 0.0f;
-    dflt_mie_layer[SETTING_MIE_ANISOTROPY_FACTOR]            = 0.8f;
-    dflt_mie.append(dflt_mie_layer);
+    LLSD dflt_mie = createSingleLayerDensityProfile(0.0f,  1.0f, -1.0f / 1200.0f, 0.0f, 0.0f, 0.8f);
     return dflt_mie;
 }
 
@@ -1154,6 +1163,21 @@ LLSD LLSettingsSky::getAbsorptionConfigs() const
     return mSettings[SETTING_ABSORPTION_CONFIG];
 }
 
+void LLSettingsSky::setRayleighConfigs(const LLSD& rayleighConfig)
+{
+    mSettings[SETTING_RAYLEIGH_CONFIG] = rayleighConfig;
+}
+
+void LLSettingsSky::setMieConfigs(const LLSD& mieConfig)
+{
+    mSettings[SETTING_MIE_CONFIG] = mieConfig;
+}
+
+void LLSettingsSky::setAbsorptionConfigs(const LLSD& absorptionConfig)
+{
+    mSettings[SETTING_ABSORPTION_CONFIG] = absorptionConfig;
+}
+
 LLUUID LLSettingsSky::getBloomTextureId() const
 {
     return mSettings[SETTING_BLOOM_TEXTUREID].asUUID();
diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h
index 19a56566449..36d1053cf6c 100644
--- a/indra/llinventory/llsettingssky.h
+++ b/indra/llinventory/llsettingssky.h
@@ -72,7 +72,6 @@ class LLSettingsSky: public LLSettingsBase
     static const std::string SETTING_SKY_BOTTOM_RADIUS;
     static const std::string SETTING_SKY_TOP_RADIUS;
     static const std::string SETTING_SUN_ARC_RADIANS;
-    static const std::string SETTING_MIE_ANISOTROPY_FACTOR;
 
     static const std::string SETTING_RAYLEIGH_CONFIG;
     static const std::string SETTING_MIE_CONFIG;
@@ -84,7 +83,7 @@ class LLSettingsSky: public LLSettingsBase
         static const std::string SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR;
         static const std::string SETTING_DENSITY_PROFILE_LINEAR_TERM;
         static const std::string SETTING_DENSITY_PROFILE_CONSTANT_TERM;
-        
+        static const std::string SETTING_MIE_ANISOTROPY_FACTOR;    
 
     static const std::string SETTING_LEGACY_HAZE;
 
@@ -116,10 +115,13 @@ class LLSettingsSky: public LLSettingsBase
     F32 getMieAnisotropy() const;   
     LLSD getRayleighConfigs() const;
     LLSD getMieConfigs() const;
-
     LLSD getAbsorptionConfigs() const;
     LLUUID getBloomTextureId() const;
 
+    void setRayleighConfigs(const LLSD& rayleighConfig);
+    void setMieConfigs(const LLSD& mieConfig);
+    void setAbsorptionConfigs(const LLSD& absorptionConfig);
+
     //---------------------------------------------------------------------
     LLColor3 getAmbientColor() const;
     void setAmbientColor(const LLColor3 &val);
@@ -239,6 +241,22 @@ class LLSettingsSky: public LLSettingsBase
     static LLUUID GetDefaultCloudNoiseTextureId();
     static LLUUID GetDefaultBloomTextureId();
 
+    static LLSD createDensityProfileLayer(
+                    F32 width,
+                    F32 exponential_term,
+                    F32 exponential_scale_factor,
+                    F32 linear_term,
+                    F32 constant_term,
+                    F32 aniso_factor = 0.0f);
+
+    static LLSD createSingleLayerDensityProfile(
+                    F32 width,
+                    F32 exponential_term,
+                    F32 exponential_scale_factor,
+                    F32 linear_term,
+                    F32 constant_term,
+                    F32 aniso_factor = 0.0f);
+
 protected:
     static const std::string SETTING_LEGACY_EAST_ANGLE;
     static const std::string SETTING_LEGACY_ENABLE_CLOUD_SCROLL;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 5dd0c15a5fb..bdc9ce57dad 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -163,6 +163,7 @@ set(viewer_SOURCE_FILES
     lldebugview.cpp
     lldeferredsounds.cpp
     lldelayedgestureerror.cpp
+    lldensityctrl.cpp
     lldirpicker.cpp
     lldonotdisturbnotificationstorage.cpp
     lldndbutton.cpp
@@ -783,6 +784,7 @@ set(viewer_HEADER_FILES
     lldebugview.h
     lldeferredsounds.h
     lldelayedgestureerror.h
+    lldensityctrl.h
     lldirpicker.h
     lldonotdisturbnotificationstorage.h
     lldndbutton.h
diff --git a/indra/newview/lldensityctrl.cpp b/indra/newview/lldensityctrl.cpp
new file mode 100644
index 00000000000..298a309e7ca
--- /dev/null
+++ b/indra/newview/lldensityctrl.cpp
@@ -0,0 +1,225 @@
+/**
+* @file lldensityctrl.cpp
+* @brief Control for specifying density over a height range for sky settings.
+*
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, 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 "lldensityctrl.h"
+
+#include "llslider.h"
+#include "llsliderctrl.h"
+#include "llsettingssky.h"
+
+static LLDefaultChildRegistry::Register<LLDensityCtrl> register_density_control("densityctrl");
+
+const std::string LLDensityCtrl::DENSITY_RAYLEIGH("density_rayleigh");
+const std::string LLDensityCtrl::DENSITY_MIE("density_mie");
+const std::string LLDensityCtrl::DENSITY_ABSORPTION("density_absorption");
+
+namespace
+{   
+    const std::string   FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL("level_exponential");
+    const std::string   FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL_SCALE("exponential_scale");
+    const std::string   FIELD_SKY_DENSITY_PROFILE_LINEAR("level_linear");
+    const std::string   FIELD_SKY_DENSITY_PROFILE_CONSTANT("level_constant");
+    const std::string   FIELD_SKY_DENSITY_MAX_ALTITUDE("max_altitude");
+    const std::string   FIELD_SKY_DENSITY_ANISO_FACTOR("aniso_factor");
+    const std::string   FIELD_SKY_DENSITY_ANISO_FACTOR_LABEL("aniso_factor_label");
+}
+
+const std::string& LLDensityCtrl::NameForDensityProfileType(DensityProfileType t)
+{
+    switch (t)
+    {
+        case Rayleigh:   return DENSITY_RAYLEIGH;
+        case Mie:        return DENSITY_MIE;
+        case Absorption: return DENSITY_ABSORPTION;
+        default:
+            break;
+    }
+
+    llassert(false);
+    return DENSITY_RAYLEIGH;
+}
+
+LLDensityCtrl::Params::Params()
+: image_density_feedback("image_density_feedback")
+, lbl_exponential("label_exponential")
+, lbl_exponential_scale("label_exponential_scale")
+, lbl_linear("label_linear")
+, lbl_constant("label_constant")
+, lbl_max_altitude("label_max_altitude")
+, lbl_aniso_factor("label_aniso_factor")
+, profile_type(LLDensityCtrl::Rayleigh)
+{
+}
+
+LLDensityCtrl::LLDensityCtrl(const Params& params)
+: mProfileType(params.profile_type)
+, mImgDensityFeedback(params.image_density_feedback)
+{
+
+}
+
+LLSD LLDensityCtrl::getProfileConfig()
+{
+    LLSD config;
+    switch (mProfileType)
+    {
+        case Rayleigh:   return mSkySettings->getRayleighConfigs();
+        case Mie:        return mSkySettings->getMieConfigs();
+        case Absorption: return mSkySettings->getAbsorptionConfigs();
+        default:
+            break;
+    }
+    llassert(false);
+    return config;
+}
+
+BOOL LLDensityCtrl::postBuild()
+{
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onExponentialChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onExponentialScaleFactorChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_LINEAR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onLinearChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_CONSTANT)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onConstantChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MAX_ALTITUDE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMaxAltitudeChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onAnisoFactorChanged(); });
+
+    if (mProfileType != Mie)
+    {
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR_LABEL)->setValue(false);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR)->setVisible(false);
+    }
+
+    return TRUE;
+}
+
+void LLDensityCtrl::setEnabled(BOOL enabled)
+{
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL_SCALE)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_LINEAR)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_CONSTANT)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MAX_ALTITUDE)->setEnabled(enabled);
+
+    if (mProfileType == Mie)
+    {
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR)->setEnabled(enabled);
+    }
+}
+
+void LLDensityCtrl::refresh()
+{
+    if (!mSkySettings)
+    {
+        setAllChildrenEnabled(FALSE);
+        setEnabled(FALSE);
+        return;
+    }
+
+    setEnabled(TRUE);
+    setAllChildrenEnabled(TRUE);
+
+    LLSD config = getProfileConfig();
+
+    getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL)->setValue(config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM]);
+    getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL_SCALE)->setValue(config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR]);
+    getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_LINEAR)->setValue(config[LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM]);
+    getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_CONSTANT)->setValue(config[LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM]);
+    getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_MAX_ALTITUDE)->setValue(config[LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH]);
+
+    if (mProfileType == Mie)
+    {        
+        getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR)->setValue(config[LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR]);
+    }
+}
+
+void LLDensityCtrl::updateProfile()
+{
+    F32 exponential_term  = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL)->getValueF32();
+    F32 exponential_scale = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL_SCALE)->getValueF32();
+    F32 linear_term       = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_LINEAR)->getValueF32();
+    F32 constant_term     = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_CONSTANT)->getValueF32();
+    F32 max_alt           = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_MAX_ALTITUDE)->getValueF32();
+    F32 aniso_factor      = 0.0f;
+
+    if (mProfileType == Mie)
+    {
+        aniso_factor = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR)->getValueF32();
+    }
+
+    LLSD profile = LLSettingsSky::createSingleLayerDensityProfile(max_alt, exponential_term, exponential_scale, linear_term, constant_term, aniso_factor);
+
+    switch (mProfileType)
+    {
+        case Rayleigh: mSkySettings->setRayleighConfigs(profile); break;
+        case Mie: mSkySettings->setMieConfigs(profile); break;
+        case Absorption: mSkySettings->setAbsorptionConfigs(profile); break;
+        default:
+            break;
+    }
+}
+
+void LLDensityCtrl::onExponentialChanged()
+{
+    updateProfile();
+    updatePreview();
+}
+
+void LLDensityCtrl::onExponentialScaleFactorChanged()
+{
+    updateProfile();
+    updatePreview();
+}
+
+void LLDensityCtrl::onLinearChanged()
+{
+    updateProfile();
+    updatePreview();
+}
+
+void LLDensityCtrl::onConstantChanged()
+{
+    updateProfile();
+    updatePreview();
+}
+
+void LLDensityCtrl::onMaxAltitudeChanged()
+{
+    updateProfile();
+    updatePreview();
+}
+
+void LLDensityCtrl::onAnisoFactorChanged()
+{
+    updateProfile();
+}
+
+void LLDensityCtrl::updatePreview()
+{
+    // AdvancedAtmospherics TODO
+    // Generate image according to current density profile
+}
+
diff --git a/indra/newview/lldensityctrl.h b/indra/newview/lldensityctrl.h
new file mode 100644
index 00000000000..789022803c3
--- /dev/null
+++ b/indra/newview/lldensityctrl.h
@@ -0,0 +1,104 @@
+/**
+* @file lldensityctrl.h
+* @brief Control for specifying density over a height range for sky settings.
+*
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, 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 LLDENSITY_CTRL_H
+#define LLDENSITY_CTRL_H
+
+#include "lluictrl.h"
+#include "llsettingssky.h"
+#include "lltextbox.h"
+#include "llsliderctrl.h"
+
+class LLDensityCtrl : public LLUICtrl
+{
+public:
+    static const std::string DENSITY_RAYLEIGH;
+    static const std::string DENSITY_MIE;
+    static const std::string DENSITY_ABSORPTION;
+
+    // Type of density profile this tab is updating
+    enum DensityProfileType
+    {
+        Rayleigh,
+        Mie,
+        Absorption
+    };
+
+    static const std::string& NameForDensityProfileType(DensityProfileType t);
+
+    struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+    {
+        Optional<LLTextBox::Params>         lbl_exponential,
+            lbl_exponential_scale,
+            lbl_linear,
+            lbl_constant,
+            lbl_max_altitude,
+            lbl_aniso_factor;
+
+        Optional<LLSliderCtrl::Params> exponential_slider,
+        exponential_scale_slider,
+        linear_slider,
+        constant_slider,
+        aniso_factor_slider;
+
+        Optional<LLUIImage*> image_density_feedback;
+
+        DensityProfileType profile_type;
+        Params();
+    };
+
+    virtual BOOL	        postBuild() override;
+    virtual void	        setEnabled(BOOL enabled) override;
+
+    void setProfileType(DensityProfileType t) { mProfileType = t; }
+
+    void refresh();
+    void updateProfile();
+
+    LLSettingsSky::ptr_t    getSky() const                                          { return mSkySettings; }
+    void                    setSky(const LLSettingsSky::ptr_t &sky)                 { mSkySettings = sky; refresh(); }
+
+protected:
+    friend class LLUICtrlFactory;
+    LLDensityCtrl(const Params&);
+
+    LLSD getProfileConfig();
+    void updatePreview();
+
+private:
+    void onExponentialChanged();
+    void onExponentialScaleFactorChanged();
+    void onLinearChanged();
+    void onConstantChanged();
+    void onMaxAltitudeChanged();
+    void onAnisoFactorChanged();
+
+    DensityProfileType    mProfileType = Rayleigh;
+    LLUIImage*            mImgDensityFeedback = nullptr;
+    LLSettingsSky::ptr_t  mSkySettings;
+};
+
+#endif LLDENSITY_CTRL_H
diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp
index 554757840f4..81d098b9a38 100644
--- a/indra/newview/llfloatereditextdaycycle.cpp
+++ b/indra/newview/llfloatereditextdaycycle.cpp
@@ -693,6 +693,11 @@ void LLFloaterEditExtDayCycle::updateSkyTabs(const LLSettingsSkyPtr_t &p_sky)
     {
         panel->setSky(p_sky);
     }
+    panel = dynamic_cast<LLPanelSettingsDensityTab*>(tab_container->getChildView("advanced_atmo_panel"));
+    if (panel)
+    {
+        panel->setSky(p_sky);
+    }
 }
 
 void LLFloaterEditExtDayCycle::setWaterTabsEnabled(BOOL enable)
@@ -729,6 +734,12 @@ void LLFloaterEditExtDayCycle::setSkyTabsEnabled(BOOL enable)
         panel->setEnabled(enable);
         panel->setAllChildrenEnabled(enable);
     }
+    panel = dynamic_cast<LLPanelSettingsDensityTab*>(tab_container->getChildView("advanced_atmo_panel"));
+    if (panel)
+    {
+        panel->setEnabled(enable);
+        panel->setAllChildrenEnabled(enable);
+    }
 }
 
 void LLFloaterEditExtDayCycle::updateButtons()
diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp
index 87c0a21c423..16cdc7994d9 100644
--- a/indra/newview/llpaneleditsky.cpp
+++ b/indra/newview/llpaneleditsky.cpp
@@ -29,10 +29,13 @@
 #include "llpaneleditsky.h"
 
 #include "llslider.h"
+#include "llsliderctrl.h"
 #include "lltexturectrl.h"
 #include "llcolorswatch.h"
 #include "llvirtualtrackball.h"
+#include "llsettingssky.h"
 
+static LLDefaultChildRegistry::Register<LLDensityCtrl> register_density_control("densityctrl");
 
 namespace
 {   
@@ -59,7 +62,7 @@ namespace
     const std::string   FIELD_SKY_CLOUD_DETAIL_Y("cloud_detail_y");
     const std::string   FIELD_SKY_CLOUD_DETAIL_D("cloud_detail_d");
 
-    const std::string   FIELD_SKY_SUN_MOON_COLOR("sun_moon_color");
+    const std::string   FIELD_SKY_SUN_MOON_COLOR("-m_moon_color");
     const std::string   FIELD_SKY_GLOW_FOCUS("glow_focus");
     const std::string   FIELD_SKY_GLOW_SIZE("glow_size");
     const std::string   FIELD_SKY_STAR_BRIGHTNESS("star_brightness");
@@ -79,6 +82,7 @@ namespace
 static LLPanelInjector<LLPanelSettingsSkyAtmosTab> t_settings_atmos("panel_settings_atmos");
 static LLPanelInjector<LLPanelSettingsSkyCloudTab> t_settings_cloud("panel_settings_cloud");
 static LLPanelInjector<LLPanelSettingsSkySunMoonTab> t_settings_sunmoon("panel_settings_sunmoon");
+static LLPanelInjector<LLPanelSettingsDensityTab> t_settings_density("panel_settings_density");
 
 //==========================================================================
 LLPanelSettingsSky::LLPanelSettingsSky() :
@@ -424,3 +428,91 @@ void LLPanelSettingsSkySunMoonTab::onMoonImageChanged()
     mSkySettings->setMoonTextureId(getChild<LLTextureCtrl>(FIELD_SKY_MOON_IMAGE)->getValue().asUUID());
     mSkySettings->update();
 }
+ 
+LLPanelSettingsDensityTab::LLPanelSettingsDensityTab()
+{    
+}
+
+BOOL LLPanelSettingsDensityTab::postBuild()
+{
+    mControlName = LLDensityCtrl::NameForDensityProfileType(mProfileType);
+    getChild<LLDensityCtrl>(mControlName)->setProfileType(mProfileType);
+    refresh();
+    return TRUE;
+}
+
+void LLPanelSettingsDensityTab::setEnabled(BOOL enabled)
+{
+    LLPanelSettingsSky::setEnabled(enabled);
+    getChild<LLDensityCtrl>(mControlName)->setEnabled(enabled);
+}
+
+void LLPanelSettingsDensityTab::refresh()
+{
+    if (!mSkySettings)
+    {
+        setAllChildrenEnabled(FALSE);
+        setEnabled(FALSE);
+        return;
+    }
+
+    setEnabled(TRUE);
+    setAllChildrenEnabled(TRUE);
+    getChild<LLDensityCtrl>(mControlName)->setSky(mSkySettings);
+    getChild<LLDensityCtrl>(mControlName)->refresh();
+}
+
+void LLPanelSettingsDensityTab::updateProfile()
+{
+    getChild<LLDensityCtrl>(mControlName)->setSky(mSkySettings);
+    getChild<LLDensityCtrl>(mControlName)->updateProfile();
+    mSkySettings->update();
+}
+
+LLPanelSettingsDensity::LLPanelSettingsDensity()
+{    
+}
+
+BOOL LLPanelSettingsDensity::postBuild()
+{
+    //static_cast<LLPanelSettingsDensityTab*>(getChild<LLPanelSettingsDensityTab>(LLDensityCtrl::DENSITY_RAYLEIGH))->setProfileType(LLDensityCtrl::Rayleigh);
+    //static_cast<LLPanelSettingsDensityTab*>(getChild<LLPanelSettingsDensityTab>(LLDensityCtrl::DENSITY_MIE))->setProfileType(LLDensityCtrl::Mie);
+    //static_cast<LLPanelSettingsDensityTab*>(getChild<LLPanelSettingsDensityTab>(LLDensityCtrl::DENSITY_ABSORPTION))->setProfileType(LLDensityCtrl::Absorption);
+    refresh();
+    return TRUE;
+}
+
+void LLPanelSettingsDensity::setEnabled(BOOL enabled)
+{
+    LLPanelSettingsSky::setEnabled(enabled);
+
+    //getChild<LLPanelSettingsDensityTab>(LLDensityCtrl::DENSITY_RAYLEIGH)->setEnabled(enabled);
+    //getChild<LLPanelSettingsDensityTab>(LLDensityCtrl::DENSITY_MIE)->setEnabled(enabled);
+    //getChild<LLPanelSettingsDensityTab>(LLDensityCtrl::DENSITY_ABSORPTION)->setEnabled(enabled);
+}
+
+void LLPanelSettingsDensity::refresh()
+{
+    if (!mSkySettings)
+    {
+        setAllChildrenEnabled(FALSE);
+        setEnabled(FALSE);
+        return;
+    }
+
+    setEnabled(TRUE);
+    setAllChildrenEnabled(TRUE);
+
+    //getChild<LLDensityCtrl>(LLDensityCtrl::DENSITY_RAYLEIGH)->refresh();
+    //getChild<LLDensityCtrl>(LLDensityCtrl::DENSITY_MIE)->refresh();
+    //getChild<LLDensityCtrl>(LLDensityCtrl::DENSITY_ABSORPTION)->refresh();
+}
+
+void LLPanelSettingsDensity::updateProfile()
+{
+    //getChild<LLDensityCtrl>(LLDensityCtrl::DENSITY_RAYLEIGH)->updateProfile();
+    //getChild<LLDensityCtrl>(LLDensityCtrl::DENSITY_MIE)->updateProfile();
+    //getChild<LLDensityCtrl>(LLDensityCtrl::DENSITY_ABSORPTION)->updateProfile();
+    mSkySettings->update();
+}
+
diff --git a/indra/newview/llpaneleditsky.h b/indra/newview/llpaneleditsky.h
index 7c49c839ecb..c9e0e3bd565 100644
--- a/indra/newview/llpaneleditsky.h
+++ b/indra/newview/llpaneleditsky.h
@@ -29,13 +29,14 @@
 
 #include "llpanel.h"
 #include "llsettingssky.h"
-
 #include "llfloaterfixedenvironment.h"
+#include "lldensityctrl.h"
 
 //=========================================================================
 class LLSlider;
 class LLColorSwatchCtrl;
 class LLTextureCtrl;
+class LLDensityCtrl; // custom control for specifying various sky density settings
 
 //=========================================================================
 class LLPanelSettingsSky : public LLSettingsEditPanel
@@ -124,4 +125,44 @@ class LLPanelSettingsSkySunMoonTab : public LLPanelSettingsSky
     void                    onMoonRotationChanged();
     void                    onMoonImageChanged();
 };
+
+// single subtab of the density settings tab
+class LLPanelSettingsDensityTab : public LLPanelSettingsSky
+{
+    LOG_CLASS(LLPanelSettingsDensityTab);
+
+public:
+    LLPanelSettingsDensityTab();
+
+    virtual BOOL postBuild() override;
+    virtual void setEnabled(BOOL enabled) override;
+
+    void setProfileType(LLDensityCtrl::DensityProfileType t) { mProfileType = t; }
+
+protected:
+    virtual void refresh() override;
+
+    // update the settings for our profile type
+    void updateProfile();
+
+    LLDensityCtrl::DensityProfileType mProfileType;
+    std::string mControlName;
+};
+
+class LLPanelSettingsDensity : public LLPanelSettingsSky
+{
+    LOG_CLASS(LLPanelSettingsDensity);
+
+public:
+    LLPanelSettingsDensity();
+
+    virtual BOOL postBuild() override;
+    virtual void setEnabled(BOOL enabled) override;
+
+protected:
+    virtual void refresh() override;
+
+    // update the settings for our profile type
+    void updateProfile();
+};
 #endif // LLPANEL_EDIT_SKY_H
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 caf7153a5c5..80e58c8248b 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
@@ -526,6 +526,15 @@
                                 left_delta="0"
                                 top_pad="5"
                                 name="moon_panel" />
+                      <panel
+                                border="true"
+                                class="panel_settings_density"
+                                filename="panel_settings_sky_density.xml"
+                                label="Advanced Atmospherics"
+                                layout="topleft"
+                                left_delta="0"
+                                top_pad="5"
+                                name="advanced_atmo_panel" />
                     </tab_container>
                 </layout_panel>        
             </layout_stack>
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_density.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_density.xml
new file mode 100644
index 00000000000..05bd3c336a2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_density.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="all"
+ label="Density"
+ name="panel_settings_sky_density"
+ layout="topleft"
+ left="0"
+ top="0"
+ width="320"
+ height="240">
+<tab_container>
+  <panel>
+    name="panel_settings_sky_density_rayleigh"
+    <densityctrl>
+      name = "density_rayleigh"
+    </densityctrl>
+  </panel>
+  <panel>
+    name="panel_settings_sky_density_mie"
+    <densityctrl>
+      name = "density_mie"
+    </densityctrl>
+  </panel>
+  <panel>    
+    name="panel_settings_sky_density_absorption"
+    <densityctrl>
+       name = "density_absorption"
+    </densityctrl>
+  </panel>
+</tab_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/widgets/density_ctrl.xml b/indra/newview/skins/default/xui/en/widgets/density_ctrl.xml
new file mode 100644
index 00000000000..0f3f0159db4
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/density_ctrl.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<densityctrl
+ border="true"
+ follows="all"
+ label="Density"
+ name="density_ctrl"
+ layout="topleft"
+ left="0"
+ top="0"
+ width="320"
+ height="240">
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     left="15"
+     top_pad="-5"
+     width="120">
+Exponential Term
+    </text>
+    <slider
+     decimal_digits="2"
+     follows="left|top"
+     height="16"
+     increment="0.01"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="0"
+     max_val="1"
+     name="level_exponential"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+
+    <view
+     left_pad="15"
+     top="15"
+     name="preview_image"
+     height="140"
+     width="140"
+     follows="left|top"
+    />
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     left="15"
+     top_pad="-5"
+     width="120">
+Exponential Scale Factor
+    </text>
+    <slider
+     decimal_digits="2"
+     follows="left|top"
+     height="16"
+     increment="0.01"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="0"
+     max_val="1"
+     name="exponential_scale"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     left="15"
+     top_pad="-5"
+     width="120">
+Linear Term
+    </text>
+    <slider
+     decimal_digits="2"
+     follows="left|top"
+     height="16"
+     increment="0.01"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="0"
+     max_val="1"
+     name="level_linear"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     left="15"
+     top_pad="-5"
+     width="120">
+Constant Term
+    </text>
+    <slider
+     decimal_digits="2"
+     follows="left|top"
+     height="16"
+     increment="0.01"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="0"
+     max_val="1"
+     name="level_constant"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     left="15"
+     top_pad="15"
+     width="80">
+Max Altitude
+    </text>
+    <slider
+     decimal_digits="0"
+     follows="left|top"
+     height="16"
+     increment="1"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="1000"
+     max_val="40000"
+     name="max_altitude"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     name="aniso_factor_label"
+     left="15"
+     top_pad="15"
+     width="80">
+Anisotropy Factor
+    </text>
+    <slider
+     decimal_digits="0"
+     follows="left|top"
+     height="16"
+     increment="1"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="1000"
+     max_val="40000"
+     name="aniso_factor"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+</densityctrl>
-- 
GitLab