diff options
| author | Graham Linden <graham@lindenlab.com> | 2018-10-10 00:44:34 +0100 | 
|---|---|---|
| committer | Graham Linden <graham@lindenlab.com> | 2018-10-10 00:44:34 +0100 | 
| commit | 4b174a31c8db1bf7f378f9b088c1335651a34ec5 (patch) | |
| tree | e731f5895870a2ba07281245e4a30665001a25bd | |
| parent | 6015e2a5059a03c54c7024e84bb3467bf32c4436 (diff) | |
Move moisture/ice/droplet radius controls to atmos tab instead of (hidden) density tab.
Make frag shader version of vert WL shader to include rainbow/halo effect in non-advanced WL sky.
6 files changed, 343 insertions, 94 deletions
| diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl new file mode 100644 index 0000000000..3232f81cd9 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl @@ -0,0 +1,197 @@ +/**  + * @file class2/deferred/skyF.glsl + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2005, 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$ + */ + +uniform mat4 modelview_projection_matrix; + +// SKY //////////////////////////////////////////////////////////////////////// +// The vertex shader for creating the atmospheric sky +/////////////////////////////////////////////////////////////////////////////// + +// Inputs +uniform vec3 camPosLocal; + +uniform vec4 lightnorm; +uniform vec4 sunlight_color; +uniform vec4 ambient; +uniform vec4 blue_horizon; +uniform vec4 blue_density; +uniform float haze_horizon; +uniform float haze_density; + +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float max_y; + +uniform vec4 glow; + +uniform vec4 cloud_color; + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_data[3]; +#else +#define frag_data gl_FragData +#endif + +VARYING vec3 pos; + +///////////////////////////////////////////////////////////////////////// +// The fragment shader for the sky +///////////////////////////////////////////////////////////////////////// + +uniform vec4 gamma; +uniform sampler2D rainbow_map; +uniform sampler2D halo_map; + +uniform float moisture_level; +uniform float droplet_radius; +uniform float ice_level; + +vec3 rainbow(float d) +{ +   float rad = (droplet_radius - 5.0f) / 1024.0f; +   return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level; +} + +vec3 halo22(float d) +{ +   float v = sqrt(max(0, 1 - (d*d))); +   return texture2D(halo_map, vec2(0, v)).rgb * ice_level; +} + +/// Soft clips the light with a gamma correction +vec3 scaleSoftClip(vec3 light); + +void main() +{ + +	// World / view / projection +	// Get relative position +	vec3 P = pos.xyz - camPosLocal.xyz + vec3(0,50,0); + +	// Set altitude +	if (P.y > 0.) +	{ +		P *= (max_y / P.y); +	} +	else +	{ +		P *= (-32000. / P.y); +	} + +	// Can normalize then +	vec3 Pn = normalize(P); +	float  Plen = length(P); + +	// Initialize temp variables +	vec4 temp1 = vec4(0.); +	vec4 temp2 = vec4(0.); +	vec4 blue_weight; +	vec4 haze_weight; +	vec4 sunlight = sunlight_color; +	vec4 light_atten; + + +	// Sunlight attenuation effect (hue and brightness) due to atmosphere +	// this is used later for sunlight modulation at various altitudes +	light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); + +	// Calculate relative weights +	temp1 = blue_density + haze_density; +	blue_weight = blue_density / temp1; +	haze_weight = haze_density / temp1; + +	// Compute sunlight from P & lightnorm (for long rays like sky) +	temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y ); +	temp2.y = 1. / temp2.y; +	sunlight *= exp( - light_atten * temp2.y); + +	// Distance +	temp2.z = Plen * density_multiplier; + +	// Transparency (-> temp1) +	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati +	// compiler gets confused. +	temp1 = exp(-temp1 * temp2.z); + + +	// Compute haze glow +	temp2.x = dot(Pn, lightnorm.xyz); +	temp2.x = 1. - temp2.x; +		// temp2.x is 0 at the sun and increases away from sun +	temp2.x = max(temp2.x, .001);	 +		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) +	temp2.x *= glow.x; +		// Higher glow.x gives dimmer glow (because next step is 1 / "angle") +	temp2.x = pow(temp2.x, glow.z); +		// glow.z should be negative, so we're doing a sort of (1 / "angle") function + +	// Add "minimum anti-solar illumination" +	temp2.x += .25; + + +	// Haze color above cloud +	vec4 color = (	  blue_horizon * blue_weight * (sunlight + ambient) +				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient) +			 );	 + + +	// Increase ambient when there are more clouds +	vec4 tmpAmbient = ambient; +	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;  + +	// Dim sunlight by cloud shadow percentage +	sunlight *= (1. - cloud_shadow); + +	// Haze color below cloud +	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient) +				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient) +			 );	 + +	// Final atmosphere additive +	color *= (1. - temp1); +	 +	// Attenuate cloud color by atmosphere +	temp1 = sqrt(temp1);	//less atmos opacity (more transparency) below clouds + +	// At horizon, blend high altitude sky color towards the darker color below the clouds +	color += (additiveColorBelowCloud - color) * (1. - sqrt(temp1)); +	 +    float optic_d = dot(Pn, lightnorm.xyz); + +    vec3 halo_22 = halo22(optic_d); + +    if (optic_d <= 0) +    color.rgb += rainbow(optic_d); + +    color.rgb += halo_22; + +	color *= 2.; + +	/// Gamma correct for WL (soft clip effect). +	frag_data[0] = vec4(scaleSoftClip(color.rgb), 1.0); +	frag_data[1] = vec4(0.0,0.0,0.0,0.0); +	frag_data[2] = vec4(0.5,0.5,0.0,1.0); //1.0 in norm.w masks off fog +} + diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl new file mode 100644 index 0000000000..bcf775577a --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl @@ -0,0 +1,42 @@ +/**  + * @file WLSkyV.glsl + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2005, 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$ + */ + +uniform mat4 modelview_projection_matrix; + +ATTRIBUTE vec3 position; + +// SKY //////////////////////////////////////////////////////////////////////// +// The vertex shader for creating the atmospheric sky +/////////////////////////////////////////////////////////////////////////////// + +VARYING vec3 pos; + +void main() +{ + +	// World / view / projection +    pos = position.xyz; +	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); +} diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp index d0e916363d..1ae220a5ca 100644 --- a/indra/newview/llpaneleditsky.cpp +++ b/indra/newview/llpaneleditsky.cpp @@ -137,7 +137,9 @@ BOOL LLPanelSettingsSkyAtmosTab::postBuild()      getChild<LLUICtrl>(FIELD_SKY_DENSITY_MULTIP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onDensityMultipChanged(); });      getChild<LLUICtrl>(FIELD_SKY_DISTANCE_MULTIP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onDistanceMultipChanged(); });      getChild<LLUICtrl>(FIELD_SKY_MAX_ALT)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMaxAltChanged(); }); - +    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoistureLevelChanged(); }); +    getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onDropletRadiusChanged(); }); +    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onIceLevelChanged(); });      refresh();      return TRUE; @@ -153,6 +155,9 @@ void LLPanelSettingsSkyAtmosTab::setEnabled(BOOL enabled)      getChild<LLUICtrl>(FIELD_SKY_DENSITY_MULTIP)->setEnabled(enabled);      getChild<LLUICtrl>(FIELD_SKY_DISTANCE_MULTIP)->setEnabled(enabled);      getChild<LLUICtrl>(FIELD_SKY_MAX_ALT)->setEnabled(enabled); +    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setEnabled(enabled); +    getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setEnabled(enabled); +    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setEnabled(enabled);  }  void LLPanelSettingsSkyAtmosTab::refresh() @@ -178,6 +183,13 @@ void LLPanelSettingsSkyAtmosTab::refresh()      getChild<LLUICtrl>(FIELD_SKY_DISTANCE_MULTIP)->setValue(mSkySettings->getDistanceMultiplier());      getChild<LLUICtrl>(FIELD_SKY_MAX_ALT)->setValue(mSkySettings->getMaxY()); +    F32 moisture_level  = mSkySettings->getSkyMoistureLevel(); +    F32 droplet_radius  = mSkySettings->getSkyDropletRadius(); +    F32 ice_level       = mSkySettings->getSkyIceLevel(); + +    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setValue(moisture_level); +    getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setValue(droplet_radius); +    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setValue(ice_level);  }  //------------------------------------------------------------------------- @@ -244,13 +256,36 @@ void LLPanelSettingsSkyAtmosTab::onMaxAltChanged()      setIsDirty();  } +void LLPanelSettingsSkyAtmosTab::onMoistureLevelChanged() +{ +    F32 moisture_level  = getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->getValue().asReal(); +    mSkySettings->setSkyMoistureLevel(moisture_level); +    mSkySettings->update(); +    setIsDirty(); +} + +void LLPanelSettingsSkyAtmosTab::onDropletRadiusChanged() +{     +    F32 droplet_radius = getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->getValue().asReal(); +    mSkySettings->setSkyDropletRadius(droplet_radius); +    mSkySettings->update(); +    setIsDirty(); +} + +void LLPanelSettingsSkyAtmosTab::onIceLevelChanged() +{ +    F32 ice_level = getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->getValue().asReal(); +    mSkySettings->setSkyIceLevel(ice_level); +    mSkySettings->update(); +    setIsDirty(); +} +  //==========================================================================  LLPanelSettingsSkyCloudTab::LLPanelSettingsSkyCloudTab() :      LLPanelSettingsSky()  {  } -  BOOL LLPanelSettingsSkyCloudTab::postBuild()  {      getChild<LLUICtrl>(FIELD_SKY_CLOUD_COLOR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudColorChanged(); }); @@ -564,10 +599,6 @@ BOOL LLPanelSettingsSkyDensityTab::postBuild()      getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_MAX_ALTITUDE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onAbsorptionMaxAltitudeChanged(); }); -    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoistureLevelChanged(); }); -    getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onDropletRadiusChanged(); }); -    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onIceLevelChanged(); }); -      refresh();      return TRUE;  } @@ -594,11 +625,6 @@ void LLPanelSettingsSkyDensityTab::setEnabled(BOOL enabled)      getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_LINEAR)->setEnabled(enabled);      getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_CONSTANT)->setEnabled(enabled);      getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_MAX_ALTITUDE)->setEnabled(enabled); - -    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setEnabled(enabled); -    getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setEnabled(enabled); -    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setEnabled(enabled); -  }  void LLPanelSettingsSkyDensityTab::refresh() @@ -637,10 +663,6 @@ void LLPanelSettingsSkyDensityTab::refresh()      F32 absorption_constant_term     = absorption_config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM].asReal();      F32 absorption_max_alt           = absorption_config[LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH].asReal(); -    F32 moisture_level  = mSkySettings->getSkyMoistureLevel(); -    F32 droplet_radius  = mSkySettings->getSkyDropletRadius(); -    F32 ice_level       = mSkySettings->getSkyIceLevel(); -      getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL)->setValue(rayleigh_exponential_term);      getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL_SCALE)->setValue(rayleigh_exponential_scale);      getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_LINEAR)->setValue(rayleigh_linear_term); @@ -659,10 +681,6 @@ void LLPanelSettingsSkyDensityTab::refresh()      getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_LINEAR)->setValue(absorption_linear_term);      getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_CONSTANT)->setValue(absorption_constant_term);      getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_MAX_ALTITUDE)->setValue(absorption_max_alt); - -    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setValue(moisture_level); -    getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setValue(droplet_radius); -    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setValue(ice_level);  }  void LLPanelSettingsSkyDensityTab::updateProfile() @@ -690,10 +708,6 @@ void LLPanelSettingsSkyDensityTab::updateProfile()      LLSD mie_config         = LLSettingsSky::createSingleLayerDensityProfile(mie_max_alt, mie_exponential_term, mie_exponential_scale, mie_linear_term, mie_constant_term, mie_aniso_factor);      LLSD absorption_layer   = LLSettingsSky::createSingleLayerDensityProfile(absorption_max_alt, absorption_exponential_term, absorption_exponential_scale, absorption_linear_term, absorption_constant_term); -    F32 moisture_level  = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->getValueF32(); -    F32 droplet_radius  = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->getValueF32(); -    F32 ice_level       = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->getValueF32(); -      static LLSD absorption_layer_ozone = LLSettingsSky::createDensityProfileLayer(0.0f, 0.0f, 0.0f, -1.0f / 15000.0f, 8.0f / 3.0f);      LLSD absorption_config; @@ -703,9 +717,6 @@ void LLPanelSettingsSkyDensityTab::updateProfile()      mSkySettings->setRayleighConfigs(rayleigh_config);      mSkySettings->setMieConfigs(mie_config);      mSkySettings->setAbsorptionConfigs(absorption_config); -    mSkySettings->setSkyMoistureLevel(moisture_level); -    mSkySettings->setSkyDropletRadius(droplet_radius); -    mSkySettings->setSkyIceLevel(ice_level);      mSkySettings->update();      setIsDirty(); @@ -796,18 +807,3 @@ void LLPanelSettingsSkyDensityTab::onAbsorptionMaxAltitudeChanged()  {      updateProfile();  } - -void LLPanelSettingsSkyDensityTab::onMoistureLevelChanged() -{ -    updateProfile(); -} - -void LLPanelSettingsSkyDensityTab::onDropletRadiusChanged() -{ -    updateProfile(); -} - -void LLPanelSettingsSkyDensityTab::onIceLevelChanged() -{ -    updateProfile(); -} diff --git a/indra/newview/llpaneleditsky.h b/indra/newview/llpaneleditsky.h index 002586b550..c02c9c95a0 100644 --- a/indra/newview/llpaneleditsky.h +++ b/indra/newview/llpaneleditsky.h @@ -76,6 +76,10 @@ private:      void                    onDensityMultipChanged();      void                    onDistanceMultipChanged();      void                    onMaxAltChanged(); +    void                    onMoistureLevelChanged(); +    void                    onDropletRadiusChanged(); +    void                    onIceLevelChanged(); +  };  class LLPanelSettingsSkyCloudTab : public LLPanelSettingsSky @@ -160,9 +164,6 @@ protected:      void onAbsorptionLinearChanged();      void onAbsorptionConstantChanged();      void onAbsorptionMaxAltitudeChanged(); -    void onMoistureLevelChanged(); -    void onDropletRadiusChanged(); -    void onIceLevelChanged();      // update the settings for our profile type      void updateProfile(); diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml index 18c2ac0db9..5af009e3aa 100644 --- a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml +++ b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml @@ -154,6 +154,69 @@                              left_delta="-5"                              top_delta="25"                              width="80"> +                        Moisture Level: +                    </text> +                     <slider +                            decimal_digits="3" +                            follows="left|top" +                            height="14" +                            increment="0.001" +                            initial_value="0" +                            layout="topleft" +                            min_val="0" +                            max_val="1" +                            name="moisture_level" +                            width="207" +                            can_edit_text="true"/> +                    <text +                            follows="left|top" +                            height="10" +                            layout="topleft" +                            left_delta="-5" +                            top_delta="25" +                            width="80"> +                        Droplet Radius: +                    </text> +                    <slider +                            decimal_digits="2" +                            follows="left|top" +                            height="14" +                            increment="0.01" +                            initial_value="0" +                            layout="topleft" +                            min_val="5.0" +                            max_val="1000.0" +                            name="droplet_radius" +                            width="207" +                            can_edit_text="true"/> +                    <text +                            follows="left|top" +                            height="10" +                            layout="topleft" +                            left_delta="-5" +                            top_delta="25" +                            width="80"> +                        Ice Level: +                    </text> +                    <slider +                            decimal_digits="1" +                            follows="left|top" +                            height="14" +                            increment="0.1" +                            initial_value="0" +                            layout="topleft" +                            min_val="0" +                            max_val="1" +                            name="ice_level" +                            width="207" +                            can_edit_text="true"/> +                    <text +                            follows="left|top" +                            height="10" +                            layout="topleft" +                            left_delta="-5" +                            top_delta="25" +                            width="80">                          Scene Gamma:                      </text>                      <slider 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 index a21ba44b32..b3a33961bc 100644 --- a/indra/newview/skins/default/xui/en/panel_settings_sky_density.xml +++ b/indra/newview/skins/default/xui/en/panel_settings_sky_density.xml @@ -269,55 +269,5 @@                      label_width="160"                      can_edit_text="true"/>          </layout_panel> -        <layout_panel -                border="true" -                bevel_style="in" -                auto_resize="true" -                user_resize="false" -                visible="true" -                height="14"> -             <slider -                    decimal_digits="3" -                    follows="left|top" -                    height="14" -                    increment="0.001" -                    initial_value="0" -                    layout="topleft" -                    min_val="0" -                    max_val="1" -                    name="moisture_level" -                    label="Moisture Level:" -                    width="400" -                    label_width="160" -                    can_edit_text="true"/> -            <slider -                    decimal_digits="2" -                    follows="left|top" -                    height="14" -                    increment="0.01" -                    initial_value="0" -                    layout="topleft" -                    min_val="5.0" -                    max_val="1000.0" -                    name="droplet_radius" -                    label="Droplet Radius:" -                    width="400" -                    label_width="160" -                    can_edit_text="true"/> -            <slider -                    decimal_digits="1" -                    follows="left|top" -                    height="14" -                    increment="0.1" -                    initial_value="0" -                    layout="topleft" -                    min_val="0" -                    max_val="1" -                    name="ice_level" -                    label="Ice Level:" -                    width="400" -                    label_width="160" -                    can_edit_text="true"/> -        </layout_panel>      </layout_stack>  </panel>  | 
