summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorRunitai Linden <davep@lindenlab.com>2020-03-24 11:58:31 -0500
committerRunitai Linden <davep@lindenlab.com>2020-03-24 11:58:31 -0500
commitcbe83442790927349d5d7a374c80185d761c1f41 (patch)
tree84f985bbcb891e1d3ecc78a3e92b76d41bcc698c /indra/newview
parent3d22273726ab4d40f2eb9afc5ceeac37471a9dfa (diff)
parent1370c6d0c03ed81c47db19a1cae78fdc272d9729 (diff)
Merge branch 'DRTVWR-440' of bitbucket.org:lindenlab/viewer into davep/DRTVWR-440
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl29
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/materialF.glsl871
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/skyV.glsl4
-rw-r--r--indra/newview/llagent.cpp3
-rw-r--r--indra/newview/llagentbenefits.cpp236
-rw-r--r--indra/newview/llagentbenefits.h88
-rw-r--r--indra/newview/llfloaterbvhpreview.cpp21
-rw-r--r--indra/newview/llfloatergroups.cpp5
-rw-r--r--indra/newview/llfloaterimagepreview.cpp4
-rw-r--r--indra/newview/llfloatermodelpreview.cpp1
-rw-r--r--indra/newview/llfloaternamedesc.cpp36
-rw-r--r--indra/newview/llfloaternamedesc.h3
-rw-r--r--indra/newview/llfloaterreporter.cpp6
-rw-r--r--indra/newview/llgroupactions.cpp4
-rw-r--r--indra/newview/llgroupmgr.cpp5
-rw-r--r--indra/newview/lllegacyatmospherics.cpp15
-rw-r--r--indra/newview/llmeshrepository.cpp1
-rw-r--r--indra/newview/lloutfitgallery.cpp5
-rw-r--r--indra/newview/lloutfitslist.cpp2
-rw-r--r--indra/newview/llpanelcontents.cpp1
-rw-r--r--indra/newview/llpanelgroup.cpp41
-rw-r--r--indra/newview/llpanelgroup.h3
-rw-r--r--indra/newview/llpanelgroupcreate.cpp237
-rw-r--r--indra/newview/llpanelgroupcreate.h73
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp58
-rw-r--r--indra/newview/llpanelgroupgeneral.h1
-rw-r--r--indra/newview/llpanelmaininventory.cpp46
-rw-r--r--indra/newview/llpanelobject.cpp1
-rw-r--r--indra/newview/llpanelpeople.cpp59
-rw-r--r--indra/newview/llpanelsnapshot.cpp3
-rw-r--r--indra/newview/llpanelsnapshotinventory.cpp8
-rw-r--r--indra/newview/llpanelsnapshotoptions.cpp11
-rw-r--r--indra/newview/llpanelvolume.cpp1
-rw-r--r--indra/newview/llselectmgr.cpp1
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp4
-rw-r--r--indra/newview/llstartup.cpp94
-rw-r--r--indra/newview/llstartup.h1
-rw-r--r--indra/newview/lltoastalertpanel.cpp5
-rw-r--r--indra/newview/llviewerassetupload.cpp82
-rw-r--r--indra/newview/llviewerassetupload.h4
-rw-r--r--indra/newview/llviewermenu.cpp56
-rw-r--r--indra/newview/llviewermenufile.cpp116
-rw-r--r--indra/newview/llviewermessage.cpp15
-rw-r--r--indra/newview/llviewerregion.cpp2
-rw-r--r--indra/newview/llvoavatar.cpp35
-rw-r--r--indra/newview/skins/default/xui/de/floater_about_land.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml19
-rw-r--r--indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml15
-rw-r--r--indra/newview/skins/default/xui/en/floater_image_preview.xml15
-rw-r--r--indra/newview/skins/default/xui/en/floater_people.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_sound_preview.xml19
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory_add.xml4
-rw-r--r--indra/newview/skins/default/xui/en/menu_outfit_gear.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml11
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml83
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_creation_sidetray.xml314
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml11
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml10
-rw-r--r--indra/newview/skins/default/xui/en/panel_people.xml3
-rw-r--r--indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_snapshot_options.xml14
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml8
-rw-r--r--indra/newview/skins/default/xui/it/menu_inventory_add.xml2
-rw-r--r--indra/newview/skins/default/xui/it/menu_viewer.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/menu_viewer.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/menu_inventory_add.xml2
68 files changed, 2003 insertions, 848 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 289346a5c0..c9d5fb89ba 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -115,6 +115,7 @@ set(viewer_SOURCE_FILES
llaisapi.cpp
llagent.cpp
llagentaccess.cpp
+ llagentbenefits.cpp
llagentcamera.cpp
llagentdata.cpp
llagentlanguage.cpp
@@ -441,6 +442,7 @@ set(viewer_SOURCE_FILES
llpanelface.cpp
llpanelgenerictip.cpp
llpanelgroup.cpp
+ llpanelgroupcreate.cpp
llpanelgroupbulk.cpp
llpanelgroupbulkban.cpp
llpanelgroupexperiences.cpp
@@ -737,6 +739,7 @@ set(viewer_HEADER_FILES
llaisapi.h
llagent.h
llagentaccess.h
+ llagentbenefits.h
llagentcamera.h
llagentdata.h
llagentlanguage.h
@@ -1056,6 +1059,7 @@ set(viewer_HEADER_FILES
llpanelface.h
llpanelgenerictip.h
llpanelgroup.h
+ llpanelgroupcreate.h
llpanelgroupbulk.h
llpanelgroupbulkimpl.h
llpanelgroupbulkban.h
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
index 8e90c1481f..caa4fe1f65 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
@@ -67,13 +67,28 @@ uniform vec4 cloud_color;
uniform float cloud_scale;
+// NOTE: Keep these in sync!
+// indra\newview\app_settings\shaders\class1\deferred\skyV.glsl
+// indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl
+// indra\newview\lllegacyatmospherics.cpp
void main()
{
// World / view / projection
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ // Texture coords
vary_texcoord0 = texcoord0;
+ vary_texcoord0.xy -= 0.5;
+ vary_texcoord0.xy /= cloud_scale;
+ vary_texcoord0.xy += 0.5;
+
+ vary_texcoord1 = vary_texcoord0;
+ vary_texcoord1.x += lightnorm.x * 0.0125;
+ vary_texcoord1.y += lightnorm.z * 0.0125;
+
+ vary_texcoord2 = vary_texcoord0 * 16.;
+ vary_texcoord3 = vary_texcoord1 * 16.;
// Get relative position
vec3 P = position.xyz - camPosLocal.xyz + vec3(0,50,0);
@@ -87,6 +102,7 @@ void main()
}
else
{
+ altitude_blend_factor = 0; // SL-11589 Fix clouds drooping below horizon
P *= (-32000. / P.y);
}
@@ -175,19 +191,6 @@ void main()
vary_CloudDensity = 2. * (cloud_shadow - 0.25);
- // Texture coords
- vary_texcoord0 = texcoord0;
- vary_texcoord0.xy -= 0.5;
- vary_texcoord0.xy /= cloud_scale;
- vary_texcoord0.xy += 0.5;
-
- vary_texcoord1 = vary_texcoord0;
- vary_texcoord1.x += lightnorm.x * 0.0125;
- vary_texcoord1.y += lightnorm.z * 0.0125;
-
- vary_texcoord2 = vary_texcoord0 * 16.;
- vary_texcoord3 = vary_texcoord1 * 16.;
-
// Combine these to minimize register use
vary_CloudColorAmbient += oHazeColorBelowCloud;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index 85d664ea1f..4644fe3f2b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -1,432 +1,439 @@
-/**
-* @file materialF.glsl
-*
-* $LicenseInfo:firstyear=2007&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2007, 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$
-*/
-
-/*[EXTRA_CODE_HERE]*/
-
-//class1/deferred/materialF.glsl
-
-// This shader is used for both writing opaque/masked content to the gbuffer and writing blended content to the framebuffer during the alpha pass.
-
-#define DIFFUSE_ALPHA_MODE_NONE 0
-#define DIFFUSE_ALPHA_MODE_BLEND 1
-#define DIFFUSE_ALPHA_MODE_MASK 2
-#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
-
-uniform float emissive_brightness; // fullbright flag, 1.0 == fullbright, 0.0 otherwise
-uniform int sun_up_factor;
-
-#ifdef WATER_FOG
-vec4 applyWaterFogView(vec3 pos, vec4 color);
-#endif
-
-vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
-vec3 scaleSoftClipFrag(vec3 l);
-
-vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
-vec3 fullbrightScaleSoftClip(vec3 light);
-
-void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
-
-vec3 srgb_to_linear(vec3 cs);
-vec3 linear_to_srgb(vec3 cs);
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-#ifdef HAS_SUN_SHADOW
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
-#endif
-
-uniform samplerCube environmentMap;
-uniform sampler2D lightFunc;
-
-// Inputs
-uniform vec4 morphFactor;
-uniform vec3 camPosLocal;
-uniform mat3 env_mat;
-
-uniform vec3 sun_dir;
-uniform vec3 moon_dir;
-VARYING vec2 vary_fragcoord;
-
-VARYING vec3 vary_position;
-
-uniform mat4 proj_mat;
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
-uniform vec4 light_position[8];
-uniform vec3 light_direction[8];
-uniform vec4 light_attenuation[8];
-uniform vec3 light_diffuse[8];
-
-float getAmbientClamp();
-
-vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance)
-{
- vec3 col = vec3(0);
-
- //get light vector
- vec3 lv = lp.xyz - v;
-
- //get distance
- float dist = length(lv);
- float da = 1.0;
-
- dist /= la;
-
- if (dist > 0.0 && la > 0.0)
- {
- //normalize light vector
- lv = normalize(lv);
-
- //distance attenuation
- float dist_atten = clamp(1.0 - (dist - 1.0*(1.0 - fa)) / fa, 0.0, 1.0);
- dist_atten *= dist_atten;
- dist_atten *= 2.0f;
-
- if (dist_atten <= 0.0)
- {
- return col;
- }
-
- // spotlight coefficient.
- float spot = max(dot(-ln, lv), is_pointlight);
- da *= spot*spot; // GL_SPOT_EXPONENT=2
-
- //angular attenuation
- da *= dot(n, lv);
-
- float lit = 0.0f;
-
- float amb_da = ambiance;
- if (da >= 0)
- {
- lit = max(da * dist_atten, 0.0);
- col = lit * light_col * diffuse;
- amb_da += (da*0.5 + 0.5) * ambiance;
- }
- amb_da += (da*da*0.5 + 0.5) * ambiance;
- amb_da *= dist_atten;
- amb_da = min(amb_da, 1.0f - lit);
-
- // SL-10969 need to see why these are blown out
- //col.rgb += amb_da * light_col * diffuse;
-
- if (spec.a > 0.0)
- {
- //vec3 ref = dot(pos+lv, norm);
- vec3 h = normalize(lv + npos);
- float nh = dot(n, h);
- float nv = dot(n, npos);
- float vh = dot(npos, h);
- float sa = nh;
- float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
-
- float gtdenom = 2 * nh;
- float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-
- if (nh > 0.0)
- {
- float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
- vec3 speccol = lit*scol*light_col.rgb*spec.rgb;
- speccol = clamp(speccol, vec3(0), vec3(1));
- col += speccol;
-
- float cur_glare = max(speccol.r, speccol.g);
- cur_glare = max(cur_glare, speccol.b);
- glare = max(glare, speccol.r);
- glare += max(cur_glare, 0.0);
- }
- }
- }
-
- return max(col, vec3(0.0, 0.0, 0.0));
-}
-
-#else
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-#endif
-
-uniform sampler2D diffuseMap; //always in sRGB space
-
-#ifdef HAS_NORMAL_MAP
-uniform sampler2D bumpMap;
-#endif
-
-#ifdef HAS_SPECULAR_MAP
-uniform sampler2D specularMap;
-
-VARYING vec2 vary_texcoord2;
-#endif
-
-uniform float env_intensity;
-uniform vec4 specular_color; // specular color RGB and specular exponent (glossiness) in alpha
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
-uniform float minimum_alpha;
-#endif
-
-#ifdef HAS_NORMAL_MAP
-VARYING vec3 vary_mat0;
-VARYING vec3 vary_mat1;
-VARYING vec3 vary_mat2;
-VARYING vec2 vary_texcoord1;
-#else
-VARYING vec3 vary_normal;
-#endif
-
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-vec2 encode_normal(vec3 n);
-
-void main()
-{
- vec2 pos_screen = vary_texcoord0.xy;
-
- vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
- diffcol.rgb *= vertex_color.rgb;
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
- if (diffcol.a < minimum_alpha)
- {
- discard;
- }
-#endif
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
- vec3 gamma_diff = diffcol.rgb;
- diffcol.rgb = srgb_to_linear(diffcol.rgb);
-#endif
-
-#if HAS_SPECULAR_MAP != 0
- vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
- spec.rgb *= specular_color.rgb;
-#else
- vec4 spec = vec4(specular_color.rgb, 1.0);
-#endif
-
-#if HAS_NORMAL_MAP
- vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
-
- norm.xyz = norm.xyz * 2 - 1;
-
- vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
- dot(norm.xyz,vary_mat1),
- dot(norm.xyz,vary_mat2));
-#else
- vec4 norm = vec4(0,0,0,1.0);
- vec3 tnorm = vary_normal;
-#endif
-
- norm.xyz = normalize(tnorm.xyz);
-
- vec2 abnormal = encode_normal(norm.xyz);
-
- vec4 final_color = diffcol;
-
-#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
- final_color.a = emissive_brightness;
-#else
- final_color.a = max(final_color.a, emissive_brightness);
-#endif
-
- vec4 final_specular = spec;
-
-#if HAS_SPECULAR_MAP != 0
- vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0);
- final_specular.a = specular_color.a * norm.a;
-#else
- vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0);
- final_specular.a = specular_color.a;
-#endif
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-
- //forward rendering, output just lit sRGBA
- vec3 pos = vary_position;
-
- float shadow = 1.0f;
-
-#ifdef HAS_SUN_SHADOW
- shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
-#endif
-
- spec = final_specular;
- vec4 diffuse = final_color;
- float envIntensity = final_normal.z;
-
- vec3 color = vec3(0,0,0);
-
- vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
-
- float bloom = 0.0;
- vec3 sunlit;
- vec3 amblit;
- vec3 additive;
- vec3 atten;
-
- calcAtmosphericVars(pos.xyz, light_dir, 1.0, sunlit, amblit, additive, atten, false);
-
-
- vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
-
- //we're in sRGB space, so gamma correct this dot product so
- // lighting from the sun stays sharp
- float da = clamp(dot(normalize(norm.xyz), light_dir.xyz), 0.0, 1.0);
- da = pow(da, 1.0 / 1.3);
-
- color = amblit;
-
- //darken ambient for normals perpendicular to light vector so surfaces in shadow
- // and facing away from light still have some definition to them.
- // do NOT gamma correct this dot product so ambient lighting stays soft
- float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
- ambient *= 0.5;
- ambient *= ambient;
- ambient = (1.0 - ambient);
-
- vec3 sun_contrib = min(da, shadow) * sunlit;
-
- color *= ambient;
-
- color += sun_contrib;
-
- color *= gamma_diff.rgb;
-
- float glare = 0.0;
-
- if (spec.a > 0.0) // specular reflection
- {
-#if 1 //EEP
-
- vec3 npos = -normalize(pos.xyz);
-
- //vec3 ref = dot(pos+lv, norm);
- vec3 h = normalize(light_dir.xyz + npos);
- float nh = dot(norm.xyz, h);
- float nv = dot(norm.xyz, npos);
- float vh = dot(npos, h);
- float sa = nh;
- float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
-
- float gtdenom = 2 * nh;
- float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-
- if (nh > 0.0)
- {
- float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
- vec3 sp = sun_contrib*scol / 6.0f;
- sp = clamp(sp, vec3(0), vec3(1));
- bloom = dot(sp, sp) / 4.0;
- color += sp * spec.rgb;
- }
-#else // PRODUCTION
- float sa = dot(refnormpersp, sun_dir.xyz);
- vec3 dumbshiny = sunlit*shadow*(texture2D(lightFunc, vec2(sa, spec.a)).r);
-
- // add the two types of shiny together
- vec3 spec_contrib = dumbshiny * spec.rgb;
- bloom = dot(spec_contrib, spec_contrib) / 6;
-
- glare = max(spec_contrib.r, spec_contrib.g);
- glare = max(glare, spec_contrib.b);
-
- color += spec_contrib;
-#endif
- }
-
- color = mix(color.rgb, diffcol.rgb, diffuse.a);
-
- if (envIntensity > 0.0)
- {
- //add environmentmap
- vec3 env_vec = env_mat * refnormpersp;
-
- vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
-
- color = mix(color, reflected_color, envIntensity);
-
- float cur_glare = max(reflected_color.r, reflected_color.g);
- cur_glare = max(cur_glare, reflected_color.b);
- cur_glare *= envIntensity*4.0;
- glare += cur_glare;
- }
-
- color = atmosFragLighting(color, additive, atten);
- color = scaleSoftClipFrag(color);
-
- //convert to linear before adding local lights
- color = srgb_to_linear(color);
-
- vec3 npos = normalize(-pos.xyz);
-
- vec3 light = vec3(0, 0, 0);
-
-#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w );
-
- LIGHT_LOOP(1)
- LIGHT_LOOP(2)
- LIGHT_LOOP(3)
- LIGHT_LOOP(4)
- LIGHT_LOOP(5)
- LIGHT_LOOP(6)
- LIGHT_LOOP(7)
-
- color += light;
-
- glare = min(glare, 1.0);
- float al = max(diffcol.a, glare)*vertex_color.a;
-
- //convert to srgb as this color is being written post gamma correction
- color = linear_to_srgb(color);
-
-#ifdef WATER_FOG
- vec4 temp = applyWaterFogView(pos, vec4(color, al));
- color = temp.rgb;
- al = temp.a;
-#endif
-
- frag_color = vec4(color, al);
-
-#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
-
- // deferred path
- frag_data[0] = final_color; //gbuffer is sRGB
- frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
- frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity.
-#endif
-}
-
+/**
+* @file materialF.glsl
+*
+* $LicenseInfo:firstyear=2007&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2007, 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$
+*/
+
+/*[EXTRA_CODE_HERE]*/
+
+//class1/deferred/materialF.glsl
+
+// This shader is used for both writing opaque/masked content to the gbuffer and writing blended content to the framebuffer during the alpha pass.
+
+#define DIFFUSE_ALPHA_MODE_NONE 0
+#define DIFFUSE_ALPHA_MODE_BLEND 1
+#define DIFFUSE_ALPHA_MODE_MASK 2
+#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
+
+uniform float emissive_brightness; // fullbright flag, 1.0 == fullbright, 0.0 otherwise
+uniform int sun_up_factor;
+
+#ifdef WATER_FOG
+vec4 applyWaterFogView(vec3 pos, vec4 color);
+#endif
+
+vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
+vec3 scaleSoftClipFrag(vec3 l);
+
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
+
+vec3 srgb_to_linear(vec3 cs);
+vec3 linear_to_srgb(vec3 cs);
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+#ifdef HAS_SUN_SHADOW
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
+#endif
+
+uniform samplerCube environmentMap;
+uniform sampler2D lightFunc;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+uniform mat3 env_mat;
+
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+VARYING vec2 vary_fragcoord;
+
+VARYING vec3 vary_position;
+
+uniform mat4 proj_mat;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+uniform vec4 light_position[8];
+uniform vec3 light_direction[8];
+uniform vec4 light_attenuation[8];
+uniform vec3 light_diffuse[8];
+
+float getAmbientClamp();
+
+vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance)
+{
+ vec3 col = vec3(0);
+
+ //get light vector
+ vec3 lv = lp.xyz - v;
+
+ //get distance
+ float dist = length(lv);
+ float da = 1.0;
+
+ dist /= la;
+
+ if (dist > 0.0 && la > 0.0)
+ {
+ //normalize light vector
+ lv = normalize(lv);
+
+ //distance attenuation
+ float dist_atten = clamp(1.0 - (dist - 1.0*(1.0 - fa)) / fa, 0.0, 1.0);
+ dist_atten *= dist_atten;
+ dist_atten *= 2.0f;
+
+ if (dist_atten <= 0.0)
+ {
+ return col;
+ }
+
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
+
+ //angular attenuation
+ da *= dot(n, lv);
+
+ float lit = 0.0f;
+
+ float amb_da = ambiance;
+ if (da >= 0)
+ {
+ lit = max(da * dist_atten, 0.0);
+ col = lit * light_col * diffuse;
+ amb_da += (da*0.5 + 0.5) * ambiance;
+ }
+ amb_da += (da*da*0.5 + 0.5) * ambiance;
+ amb_da *= dist_atten;
+ amb_da = min(amb_da, 1.0f - lit);
+
+ // SL-10969 need to see why these are blown out
+ //col.rgb += amb_da * light_col * diffuse;
+
+ if (spec.a > 0.0)
+ {
+ //vec3 ref = dot(pos+lv, norm);
+ vec3 h = normalize(lv + npos);
+ float nh = dot(n, h);
+ float nv = dot(n, npos);
+ float vh = dot(npos, h);
+ float sa = nh;
+ float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
+
+ float gtdenom = 2 * nh;
+ float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
+
+ if (nh > 0.0)
+ {
+ float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
+ vec3 speccol = lit*scol*light_col.rgb*spec.rgb;
+ speccol = clamp(speccol, vec3(0), vec3(1));
+ col += speccol;
+
+ float cur_glare = max(speccol.r, speccol.g);
+ cur_glare = max(cur_glare, speccol.b);
+ glare = max(glare, speccol.r);
+ glare += max(cur_glare, 0.0);
+ }
+ }
+ }
+
+ return max(col, vec3(0.0, 0.0, 0.0));
+}
+
+#else
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+#endif
+
+uniform sampler2D diffuseMap; //always in sRGB space
+
+#ifdef HAS_NORMAL_MAP
+uniform sampler2D bumpMap;
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+uniform sampler2D specularMap;
+
+VARYING vec2 vary_texcoord2;
+#endif
+
+uniform float env_intensity;
+uniform vec4 specular_color; // specular color RGB and specular exponent (glossiness) in alpha
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
+uniform float minimum_alpha;
+#endif
+
+#ifdef HAS_NORMAL_MAP
+VARYING vec3 vary_mat0;
+VARYING vec3 vary_mat1;
+VARYING vec3 vary_mat2;
+VARYING vec2 vary_texcoord1;
+#else
+VARYING vec3 vary_normal;
+#endif
+
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+vec2 encode_normal(vec3 n);
+
+void main()
+{
+ vec2 pos_screen = vary_texcoord0.xy;
+
+ vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
+ diffcol.rgb *= vertex_color.rgb;
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
+
+ // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points
+ float bias = 0.001953125; // 1/512, or half an 8-bit quantization
+ if (diffuse_linear.a < minimum_alpha-bias)
+ {
+ discard;
+ }
+#endif
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+ vec3 gamma_diff = diffcol.rgb;
+ diffcol.rgb = srgb_to_linear(diffcol.rgb);
+#endif
+
+#if HAS_SPECULAR_MAP != 0
+ vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
+ spec.rgb *= specular_color.rgb;
+#else
+ vec4 spec = vec4(specular_color.rgb, 1.0);
+#endif
+
+#if HAS_NORMAL_MAP
+ vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
+
+ norm.xyz = norm.xyz * 2 - 1;
+
+ vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
+ dot(norm.xyz,vary_mat1),
+ dot(norm.xyz,vary_mat2));
+#else
+ vec4 norm = vec4(0,0,0,1.0);
+ vec3 tnorm = vary_normal;
+#endif
+
+ norm.xyz = normalize(tnorm.xyz);
+
+ vec2 abnormal = encode_normal(norm.xyz);
+
+ vec4 final_color = diffcol;
+
+#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
+ final_color.a = emissive_brightness;
+#else
+ final_color.a = max(final_color.a, emissive_brightness);
+#endif
+
+ vec4 final_specular = spec;
+
+#if HAS_SPECULAR_MAP != 0
+ vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0);
+ final_specular.a = specular_color.a * norm.a;
+#else
+ vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0);
+ final_specular.a = specular_color.a;
+#endif
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+
+ //forward rendering, output just lit sRGBA
+ vec3 pos = vary_position;
+
+ float shadow = 1.0f;
+
+#ifdef HAS_SUN_SHADOW
+ shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
+#endif
+
+ spec = final_specular;
+ vec4 diffuse = final_color;
+ float envIntensity = final_normal.z;
+
+ vec3 color = vec3(0,0,0);
+
+ vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
+
+ float bloom = 0.0;
+ vec3 sunlit;
+ vec3 amblit;
+ vec3 additive;
+ vec3 atten;
+
+ calcAtmosphericVars(pos.xyz, light_dir, 1.0, sunlit, amblit, additive, atten, false);
+
+ // This call breaks the Mac GLSL compiler/linker for unknown reasons (17Mar2020)
+ // The call is either a no-op or a pure (pow) gamma adjustment, depending on GPU level
+ // TODO: determine if we want to re-apply the gamma adjustment, and if so understand & fix Mac breakage
+ //color = fullbrightScaleSoftClip(color);
+
+ vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+
+ //we're in sRGB space, so gamma correct this dot product so
+ // lighting from the sun stays sharp
+ float da = clamp(dot(normalize(norm.xyz), light_dir.xyz), 0.0, 1.0);
+ da = pow(da, 1.0 / 1.3);
+
+ color = amblit;
+
+ //darken ambient for normals perpendicular to light vector so surfaces in shadow
+ // and facing away from light still have some definition to them.
+ // do NOT gamma correct this dot product so ambient lighting stays soft
+ float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
+ ambient *= 0.5;
+ ambient *= ambient;
+ ambient = (1.0 - ambient);
+
+ vec3 sun_contrib = min(da, shadow) * sunlit;
+
+ color *= ambient;
+
+ color += sun_contrib;
+
+ color *= gamma_diff.rgb;
+
+ float glare = 0.0;
+
+ if (spec.a > 0.0) // specular reflection
+ {
+#if 1 //EEP
+
+ vec3 npos = -normalize(pos.xyz);
+
+ //vec3 ref = dot(pos+lv, norm);
+ vec3 h = normalize(light_dir.xyz + npos);
+ float nh = dot(norm.xyz, h);
+ float nv = dot(norm.xyz, npos);
+ float vh = dot(npos, h);
+ float sa = nh;
+ float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
+
+ float gtdenom = 2 * nh;
+ float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
+
+ if (nh > 0.0)
+ {
+ float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
+ vec3 sp = sun_contrib*scol / 6.0f;
+ sp = clamp(sp, vec3(0), vec3(1));
+ bloom = dot(sp, sp) / 4.0;
+ color += sp * spec.rgb;
+ }
+#else // PRODUCTION
+ float sa = dot(refnormpersp, sun_dir.xyz);
+ vec3 dumbshiny = sunlit*shadow*(texture2D(lightFunc, vec2(sa, spec.a)).r);
+
+ // add the two types of shiny together
+ vec3 spec_contrib = dumbshiny * spec.rgb;
+ bloom = dot(spec_contrib, spec_contrib) / 6;
+
+ glare = max(spec_contrib.r, spec_contrib.g);
+ glare = max(glare, spec_contrib.b);
+
+ color += spec_contrib;
+#endif
+ }
+
+ color = mix(color.rgb, diffcol.rgb, diffuse.a);
+
+ if (envIntensity > 0.0)
+ {
+ //add environmentmap
+ vec3 env_vec = env_mat * refnormpersp;
+
+ vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
+
+ color = mix(color, reflected_color, envIntensity);
+
+ float cur_glare = max(reflected_color.r, reflected_color.g);
+ cur_glare = max(cur_glare, reflected_color.b);
+ cur_glare *= envIntensity*4.0;
+ glare += cur_glare;
+ }
+
+ color = atmosFragLighting(color, additive, atten);
+ color = scaleSoftClipFrag(color);
+
+ //convert to linear before adding local lights
+ color = srgb_to_linear(color);
+
+ vec3 npos = normalize(-pos.xyz);
+
+ vec3 light = vec3(0, 0, 0);
+
+#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w );
+
+ LIGHT_LOOP(1)
+ LIGHT_LOOP(2)
+ LIGHT_LOOP(3)
+ LIGHT_LOOP(4)
+ LIGHT_LOOP(5)
+ LIGHT_LOOP(6)
+ LIGHT_LOOP(7)
+
+ color += light;
+
+ glare = min(glare, 1.0);
+ float al = max(diffcol.a, glare)*vertex_color.a;
+
+ //convert to srgb as this color is being written post gamma correction
+ color = linear_to_srgb(color);
+
+#ifdef WATER_FOG
+ vec4 temp = applyWaterFogView(pos, vec4(color, al));
+ color = temp.rgb;
+ al = temp.a;
+#endif
+
+ frag_color = vec4(color, al);
+
+#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer
+
+ // deferred path
+ frag_data[0] = final_color; //gbuffer is sRGB
+ frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
+ frag_data[2] = final_normal; // XY = Normal. Z = Env. intensity.
+#endif
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
index 2cd660ab79..ead754ec76 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
@@ -57,6 +57,10 @@ uniform float sun_moon_glow_factor;
uniform vec4 cloud_color;
+// NOTE: Keep these in sync!
+// indra\newview\app_settings\shaders\class1\deferred\skyV.glsl
+// indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl
+// indra\newview\lllegacyatmospherics.cpp
void main()
{
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index a36e82b155..c8d2524e0e 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -32,6 +32,7 @@
#include "pipeline.h"
#include "llagentaccess.h"
+#include "llagentbenefits.h"
#include "llagentcamera.h"
#include "llagentlistener.h"
#include "llagentwearables.h"
@@ -2997,7 +2998,7 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO
BOOL LLAgent::canJoinGroups() const
{
- return (S32)mGroups.size() < gMaxAgentGroups;
+ return (S32)mGroups.size() < LLAgentBenefitsMgr::current().getGroupMembershipLimit();
}
LLQuaternion LLAgent::getHeadRotation()
diff --git a/indra/newview/llagentbenefits.cpp b/indra/newview/llagentbenefits.cpp
new file mode 100644
index 0000000000..2d219735a0
--- /dev/null
+++ b/indra/newview/llagentbenefits.cpp
@@ -0,0 +1,236 @@
+/**
+* @file llagentbenefits.cpp
+*
+* $LicenseInfo:firstyear=2019&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2019, 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 "llagentbenefits.h"
+
+LLAgentBenefits::LLAgentBenefits():
+ m_initalized(false),
+ m_animated_object_limit(-1),
+ m_animation_upload_cost(-1),
+ m_attachment_limit(-1),
+ m_group_membership_limit(-1),
+ m_picks_limit(-1),
+ m_sound_upload_cost(-1),
+ m_texture_upload_cost(-1)
+{
+}
+
+LLAgentBenefits::~LLAgentBenefits()
+{
+}
+
+// This could be extended to a template scheme or otherwise modified
+// to support other types, if and when needed. Currently all fields
+// the viewer cares about are integer.
+bool get_required_S32(const LLSD& sd, const LLSD::String& key, S32& value)
+{
+ value = -1;
+ if (sd.has(key))
+ {
+ value = sd[key].asInteger();
+ return true;
+ }
+
+ LL_WARNS("Benefits") << "Missing required benefit field " << key << LL_ENDL;
+ return false;
+}
+
+bool LLAgentBenefits::init(const LLSD& benefits_sd)
+{
+ LL_DEBUGS("Benefits") << "initializing benefits from " << benefits_sd << LL_ENDL;
+
+ if (!get_required_S32(benefits_sd, "animated_object_limit", m_animated_object_limit))
+ {
+ return false;
+ }
+ if (!get_required_S32(benefits_sd, "animation_upload_cost", m_animation_upload_cost))
+ {
+ return false;
+ }
+ if (!get_required_S32(benefits_sd, "attachment_limit", m_attachment_limit))
+ {
+ return false;
+ }
+ if (!get_required_S32(benefits_sd, "create_group_cost", m_create_group_cost))
+ {
+ return false;
+ }
+ if (!get_required_S32(benefits_sd, "group_membership_limit", m_group_membership_limit))
+ {
+ return false;
+ }
+ if (!get_required_S32(benefits_sd, "picks_limit", m_picks_limit))
+ {
+ return false;
+ }
+ if (!get_required_S32(benefits_sd, "sound_upload_cost", m_sound_upload_cost))
+ {
+ return false;
+ }
+ if (!get_required_S32(benefits_sd, "texture_upload_cost", m_texture_upload_cost))
+ {
+ return false;
+ }
+
+ // FIXME PREMIUM - either use this field or get rid of it
+ m_initalized = true;
+ return true;
+}
+
+S32 LLAgentBenefits::getAnimatedObjectLimit() const
+{
+ return m_animated_object_limit;
+}
+
+S32 LLAgentBenefits::getAnimationUploadCost() const
+{
+ return m_animation_upload_cost;
+}
+
+S32 LLAgentBenefits::getAttachmentLimit() const
+{
+ return m_attachment_limit;
+}
+
+S32 LLAgentBenefits::getCreateGroupCost() const
+{
+ return m_create_group_cost;
+}
+
+S32 LLAgentBenefits::getGroupMembershipLimit() const
+{
+ return m_group_membership_limit;
+}
+
+S32 LLAgentBenefits::getPicksLimit() const
+{
+ return m_picks_limit;
+}
+
+S32 LLAgentBenefits::getSoundUploadCost() const
+{
+ return m_sound_upload_cost;
+}
+
+S32 LLAgentBenefits::getTextureUploadCost() const
+{
+ return m_texture_upload_cost;
+}
+
+bool LLAgentBenefits::findUploadCost(LLAssetType::EType& asset_type, S32& cost) const
+{
+ bool succ = false;
+ if (asset_type == LLAssetType::AT_TEXTURE)
+ {
+ cost = getTextureUploadCost();
+ succ = true;
+ }
+ else if (asset_type == LLAssetType::AT_SOUND)
+ {
+ cost = getSoundUploadCost();
+ succ = true;
+ }
+ else if (asset_type == LLAssetType::AT_ANIMATION)
+ {
+ cost = getAnimationUploadCost();
+ succ = true;
+ }
+ return succ;
+}
+
+LLAgentBenefitsMgr::LLAgentBenefitsMgr()
+{
+}
+
+LLAgentBenefitsMgr::~LLAgentBenefitsMgr()
+{
+}
+
+// static
+const LLAgentBenefits& LLAgentBenefitsMgr::current()
+{
+ return instance().mCurrent;
+}
+
+// static
+const LLAgentBenefits& LLAgentBenefitsMgr::get(const std::string& package)
+{
+ if (instance().mPackageMap.find(package) != instance().mPackageMap.end())
+ {
+ return instance().mPackageMap[package];
+ }
+ else
+ {
+ return instance().mDefault;
+ }
+}
+
+// static
+bool LLAgentBenefitsMgr::init(const std::string& package, const LLSD& benefits_sd)
+{
+ LLAgentBenefits benefits;
+ if (!benefits.init(benefits_sd))
+ {
+ LL_WARNS("Benefits") << "Unable to initialize package " << package << " from sd " << benefits_sd << LL_ENDL;
+ return false;
+ }
+ else
+ {
+ instance().mPackageMap[package] = benefits;
+ }
+ return true;
+
+}
+
+// static
+bool LLAgentBenefitsMgr::initCurrent(const std::string& package, const LLSD& benefits_sd)
+{
+ LLAgentBenefits benefits;
+ if (!benefits.init(benefits_sd))
+ {
+ LL_WARNS("Benefits") << "Unable to initialize package " << package << " from sd " << benefits_sd << LL_ENDL;
+ return false;
+ }
+ else
+ {
+ instance().mCurrent = benefits;
+ instance().mCurrentName = package;
+ }
+ return true;
+
+}
+
+// static
+bool LLAgentBenefitsMgr::has(const std::string& package)
+{
+ return instance().mPackageMap.find(package) != instance().mPackageMap.end();
+}
+
+//static
+bool LLAgentBenefitsMgr::isCurrent(const std::string& package)
+{
+ return instance().mCurrentName == package;
+}
diff --git a/indra/newview/llagentbenefits.h b/indra/newview/llagentbenefits.h
new file mode 100644
index 0000000000..48aa6bd869
--- /dev/null
+++ b/indra/newview/llagentbenefits.h
@@ -0,0 +1,88 @@
+/**
+* @file llagentbenefits.h
+*
+* $LicenseInfo:firstyear=2019&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2019, 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_AGENTBENEFITS_H
+#define LL_AGENTBENEFITS_H
+
+#include "llsingleton.h"
+#include "llsd.h"
+#include "llassettype.h"
+
+class LLAgentBenefits
+{
+public:
+ LLAgentBenefits();
+ ~LLAgentBenefits();
+ LOG_CLASS(LLAgentBenefits);
+
+ bool init(const LLSD& benefits_sd);
+
+ S32 getAnimatedObjectLimit() const;
+ S32 getAnimationUploadCost() const;
+ S32 getAttachmentLimit() const;
+ S32 getCreateGroupCost() const;
+ S32 getGroupMembershipLimit() const;
+ S32 getPicksLimit() const;
+ S32 getSoundUploadCost() const;
+ S32 getTextureUploadCost() const;
+
+ bool findUploadCost(LLAssetType::EType& asset_type, S32& cost) const;
+
+private:
+ S32 m_animated_object_limit;
+ S32 m_animation_upload_cost;
+ S32 m_attachment_limit;
+ S32 m_create_group_cost;
+ S32 m_group_membership_limit;
+ S32 m_picks_limit;
+ S32 m_sound_upload_cost;
+ S32 m_texture_upload_cost;
+
+ bool m_initalized;
+};
+
+class LLAgentBenefitsMgr: public LLSingleton<LLAgentBenefitsMgr>
+{
+ LLSINGLETON(LLAgentBenefitsMgr);
+ ~LLAgentBenefitsMgr();
+ LOG_CLASS(LLAgentBenefitsMgr);
+
+public:
+ static const LLAgentBenefits& current();
+ static const LLAgentBenefits& get(const std::string& package);
+ static bool init(const std::string& package, const LLSD& benefits_sd);
+ static bool initCurrent(const std::string& package, const LLSD& benefits_sd);
+ static bool has(const std::string& package);
+ static bool isCurrent(const std::string& package);
+
+private:
+ std::string mCurrentName;
+ LLAgentBenefits mCurrent;
+ LLAgentBenefits mDefault;
+ std::map<std::string, LLAgentBenefits> mPackageMap;
+};
+
+
+#endif
diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp
index ee7e6f8562..131d9b077b 100644
--- a/indra/newview/llfloaterbvhpreview.cpp
+++ b/indra/newview/llfloaterbvhpreview.cpp
@@ -31,13 +31,13 @@
#include "llbvhloader.h"
#include "lldatapacker.h"
#include "lldir.h"
-#include "lleconomy.h"
#include "llnotificationsutil.h"
#include "llvfile.h"
#include "llapr.h"
#include "llstring.h"
#include "llagent.h"
+#include "llagentbenefits.h"
#include "llanimationstates.h"
#include "llbbox.h"
#include "llbutton.h"
@@ -68,7 +68,8 @@
const S32 PREVIEW_BORDER_WIDTH = 2;
const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH;
const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
-const S32 PREF_BUTTON_HEIGHT = 16;
+const S32 PREVIEW_VPAD = 35;
+const S32 PREF_BUTTON_HEIGHT = 16 + 35;
const S32 PREVIEW_TEXTURE_HEIGHT = 300;
const F32 PREVIEW_CAMERA_DISTANCE = 4.f;
@@ -203,7 +204,7 @@ BOOL LLFloaterBvhPreview::postBuild()
setDefaultBtn();
mPreviewRect.set(PREVIEW_HPAD,
- PREVIEW_TEXTURE_HEIGHT,
+ PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD,
getRect().getWidth() - PREVIEW_HPAD,
PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f);
@@ -403,13 +404,13 @@ void LLFloaterBvhPreview::draw()
gGL.begin( LLRender::QUADS );
{
gGL.texCoord2f(0.f, 1.f);
- gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT);
+ gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD);
gGL.texCoord2f(0.f, 0.f);
gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
gGL.texCoord2f(1.f, 0.f);
gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
gGL.texCoord2f(1.f, 1.f);
- gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT);
+ gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT + PREVIEW_VPAD);
}
gGL.end();
@@ -1004,16 +1005,18 @@ void LLFloaterBvhPreview::onBtnOK(void* userdata)
{
std::string name = floaterp->getChild<LLUICtrl>("name_form")->getValue().asString();
std::string desc = floaterp->getChild<LLUICtrl>("description_form")->getValue().asString();
- S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
+ S32 expected_upload_cost = LLAgentBenefitsMgr::current().getAnimationUploadCost();
- LLResourceUploadInfo::ptr_t assetUpdloadInfo(new LLResourceUploadInfo(
+ LLResourceUploadInfo::ptr_t assetUploadInfo(new LLResourceUploadInfo(
floaterp->mTransactionID, LLAssetType::AT_ANIMATION,
name, desc, 0,
LLFolderType::FT_NONE, LLInventoryType::IT_ANIMATION,
- LLFloaterPerms::getNextOwnerPerms("Uploads"), LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
+ LLFloaterPerms::getNextOwnerPerms("Uploads"),
+ LLFloaterPerms::getGroupPerms("Uploads"),
+ LLFloaterPerms::getEveryonePerms("Uploads"),
expected_upload_cost));
- upload_new_resource(assetUpdloadInfo);
+ upload_new_resource(assetUploadInfo);
}
else
{
diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp
index dbe7fee108..f341e2ebcb 100644
--- a/indra/newview/llfloatergroups.cpp
+++ b/indra/newview/llfloatergroups.cpp
@@ -38,6 +38,7 @@
#include "roles_constants.h"
#include "llagent.h"
+#include "llagentbenefits.h"
#include "llbutton.h"
#include "llgroupactions.h"
#include "llscrolllistctrl.h"
@@ -172,7 +173,7 @@ void LLPanelGroups::reset()
group_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
}
getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.size()));
- getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",gMaxAgentGroups));
+ getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",LLAgentBenefitsMgr::current().getGroupMembershipLimit()));
init_group_list(getChild<LLScrollListCtrl>("group list"), gAgent.getGroupID());
enableButtons();
@@ -183,7 +184,7 @@ BOOL LLPanelGroups::postBuild()
childSetCommitCallback("group list", onGroupList, this);
getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.size()));
- getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",gMaxAgentGroups));
+ getChild<LLUICtrl>("groupcount")->setTextArg("[MAX]", llformat("%d",LLAgentBenefitsMgr::current().getGroupMembershipLimit()));
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("group list");
if (list)
diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp
index d4b0fa85ab..696f748613 100644
--- a/indra/newview/llfloaterimagepreview.cpp
+++ b/indra/newview/llfloaterimagepreview.cpp
@@ -63,8 +63,8 @@
const S32 PREVIEW_BORDER_WIDTH = 2;
const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH;
const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
-const S32 PREVIEW_VPAD = -24; // yuk, hard coded
-const S32 PREF_BUTTON_HEIGHT = 16 + 7 + 16;
+const S32 PREVIEW_VPAD = -24 + 35; // yuk, hard coded
+const S32 PREF_BUTTON_HEIGHT = 16 + 7 + 16 + 35;
const S32 PREVIEW_TEXTURE_HEIGHT = 320;
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 8a894c4ec8..bc44e37c5a 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -44,7 +44,6 @@
#include "lldrawable.h"
#include "llrender.h"
#include "llface.h"
-#include "lleconomy.h"
#include "llfocusmgr.h"
#include "llfloaterperms.h"
#include "lliconctrl.h"
diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index 7cde061515..1e9549a04e 100644
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -46,12 +46,13 @@
#include "llnotificationsutil.h"
#include "lluictrlfactory.h"
#include "llstring.h"
-#include "lleconomy.h"
#include "llpermissions.h"
+#include "lltrans.h"
// linden includes
#include "llassetstorage.h"
#include "llinventorytype.h"
+#include "llagentbenefits.h"
const S32 PREVIEW_LINE_HEIGHT = 19;
const S32 PREVIEW_BORDER_WIDTH = 2;
@@ -123,13 +124,39 @@ BOOL LLFloaterNameDesc::postBuild()
// Cancel button
getChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnCancel, this));
- getChild<LLUICtrl>("ok_btn")->setLabelArg("[AMOUNT]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload() ));
+ S32 expected_upload_cost = getExpectedUploadCost();
+ getChild<LLUICtrl>("ok_btn")->setLabelArg("[AMOUNT]", llformat("%d", expected_upload_cost));
+
+ LLTextBox* info_text = getChild<LLTextBox>("info_text");
+ if (info_text)
+ {
+ info_text->setValue(LLTrans::getString("UploadFeeInfo"));
+ }
setDefaultBtn("ok_btn");
return TRUE;
}
+S32 LLFloaterNameDesc::getExpectedUploadCost() const
+{
+ std::string exten = gDirUtilp->getExtension(mFilename);
+ LLAssetType::EType asset_type;
+ S32 upload_cost = -1;
+ if (LLResourceUploadInfo::findAssetTypeOfExtension(exten, asset_type))
+ {
+ if (!LLAgentBenefitsMgr::current().findUploadCost(asset_type, upload_cost))
+ {
+ LL_WARNS() << "Unable to find upload cost for asset type " << asset_type << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS() << "Unable to find upload cost for " << mFilename << LL_ENDL;
+ }
+ return upload_cost;
+}
+
//-----------------------------------------------------------------------------
// LLFloaterNameDesc()
//-----------------------------------------------------------------------------
@@ -162,8 +189,7 @@ void LLFloaterNameDesc::onBtnOK( )
getChildView("ok_btn")->setEnabled(FALSE); // don't allow inadvertent extra uploads
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).
-
+ S32 expected_upload_cost = getExpectedUploadCost();
if (can_afford_transaction(expected_upload_cost))
{
void *nruserdata = NULL;
@@ -185,7 +211,7 @@ void LLFloaterNameDesc::onBtnOK( )
{
LLSD args;
args["COST"] = llformat("%d", expected_upload_cost);
- LLNotificationsUtil::add("ErrorTextureCannotAfford", args);
+ LLNotificationsUtil::add("ErrorCannotAffordUpload", args);
}
closeFloater(false);
diff --git a/indra/newview/llfloaternamedesc.h b/indra/newview/llfloaternamedesc.h
index 41643681ac..589f470e82 100644
--- a/indra/newview/llfloaternamedesc.h
+++ b/indra/newview/llfloaternamedesc.h
@@ -30,6 +30,7 @@
#include "llfloater.h"
#include "llresizehandle.h"
#include "llstring.h"
+#include "llassettype.h"
class LLLineEditor;
class LLButton;
@@ -45,6 +46,8 @@ public:
void onBtnOK();
void onBtnCancel();
void doCommit();
+
+ S32 getExpectedUploadCost() const;
protected:
virtual void onCommit();
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 960fd9620d..4cc43254a5 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -102,7 +102,6 @@ public:
virtual LLSD prepareUpload();
virtual LLSD generatePostBody();
- virtual S32 getEconomyUploadCost();
virtual LLUUID finishUpload(LLSD &result);
virtual bool showInventoryPanel() const { return false; }
@@ -129,11 +128,6 @@ LLSD LLARScreenShotUploader::generatePostBody()
return mReport;
}
-S32 LLARScreenShotUploader::getEconomyUploadCost()
-{ // Abuse report screen shots do not cost anything to upload.
- return 0;
-}
-
LLUUID LLARScreenShotUploader::finishUpload(LLSD &result)
{
/* *TODO$: Report success or failure. Carried over from previous todo on responder*/
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index 599790d2bb..d2bd716f55 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -400,10 +400,10 @@ void LLGroupActions::createGroup()
{
LLSD params;
params["group_id"] = LLUUID::null;
- params["open_tab_name"] = "panel_group_info_sidetray";
+ params["open_tab_name"] = "panel_group_creation_sidetray";
params["action"] = "create";
- LLFloaterSidePanelContainer::showPanel("people", "panel_group_info_sidetray", params);
+ LLFloaterSidePanelContainer::showPanel("people", "panel_group_creation_sidetray", params);
}
//static
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index 088d052533..dbf7639539 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -44,9 +44,8 @@
#include "roles_constants.h"
#include "lltransactiontypes.h"
#include "llstatusbar.h"
-#include "lleconomy.h"
#include "llviewerwindow.h"
-#include "llpanelgroup.h"
+#include "llpanelgroupcreate.h"
#include "llgroupactions.h"
#include "llnotificationsutil.h"
#include "lluictrlfactory.h"
@@ -1452,7 +1451,7 @@ void LLGroupMgr::processCreateGroupReply(LLMessageSystem* msg, void ** data)
gAgent.mGroups.push_back(gd);
- LLPanelGroup::refreshCreatedGroup(group_id);
+ LLPanelGroupCreate::refreshCreatedGroup(group_id);
//FIXME
//LLFloaterGroupInfo::closeCreateGroup();
//LLFloaterGroupInfo::showFromUUID(group_id,"roles_tab");
diff --git a/indra/newview/lllegacyatmospherics.cpp b/indra/newview/lllegacyatmospherics.cpp
index e061b3ad17..a2acb3efe2 100644
--- a/indra/newview/lllegacyatmospherics.cpp
+++ b/indra/newview/lllegacyatmospherics.cpp
@@ -254,7 +254,7 @@ LLColor4 LLAtmospherics::calcSkyColorInDir(const LLSettingsSky::ptr_t &psky, Atm
F32 brightness = vars.hazeColor.brightness();
F32 greyscale_sat = brightness * (1.0f - sky_saturation);
LLColor3 sky_color = vars.hazeColor * sky_saturation + smear(greyscale_sat);
- //sky_color *= (0.5f + 0.5f * brightness); // SL-12574 EEP sky was too dark dark grey/blue, lighten it slightly
+ //sky_color *= (0.5f + 0.5f * brightness); // SL-12574 EEP sky is being attenuated too much
return LLColor4(sky_color, 0.0f);
}
@@ -264,6 +264,10 @@ LLColor4 LLAtmospherics::calcSkyColorInDir(const LLSettingsSky::ptr_t &psky, Atm
return LLColor4(sky_color, 0.0f);
}
+// NOTE: Keep these in sync!
+// indra\newview\app_settings\shaders\class1\deferred\skyV.glsl
+// indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl
+// indra\newview\lllegacyatmospherics.cpp
void LLAtmospherics::calcSkyColorWLVert(const LLSettingsSky::ptr_t &psky, LLVector3 & Pn, AtmosphericsVars& vars)
{
LLColor3 blue_density = vars.blue_density;
@@ -365,19 +369,18 @@ void LLAtmospherics::calcSkyColorWLVert(const LLSettingsSky::ptr_t &psky, LLVect
// Haze color below cloud
vars.hazeColorBelowCloud = (blue_factor * (sunlight + tmpAmbient) + componentMult(haze_factor, sunlight * temp2.mV[0] + tmpAmbient));
- LLColor3 final_atten = LLColor3::white - temp1;
- final_atten.mV[0] = llmax(final_atten.mV[0], 0.0f);
- final_atten.mV[1] = llmax(final_atten.mV[1], 0.0f);
- final_atten.mV[2] = llmax(final_atten.mV[2], 0.0f);
-
// Final atmosphere additive
componentMultBy(vars.hazeColor, LLColor3::white - temp1);
+/*
+ // SL-12574
+
// Attenuate cloud color by atmosphere
temp1 = componentSqrt(temp1); //less atmos opacity (more transparency) below clouds
// At horizon, blend high altitude sky color towards the darker color below the clouds
vars.hazeColor += componentMult(vars.hazeColorBelowCloud - vars.hazeColor, LLColor3::white - componentSqrt(temp1));
+*/
}
void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in)
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 95322cce6d..1d76dd7928 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -41,7 +41,6 @@
#include "lldeadmantimer.h"
#include "llfloatermodelpreview.h"
#include "llfloaterperms.h"
-#include "lleconomy.h"
#include "llimagej2c.h"
#include "llhost.h"
#include "llmath.h"
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 278d83bab7..520c9adcd1 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -36,7 +36,7 @@
#include "llaccordionctrltab.h"
#include "llappearancemgr.h"
-#include "lleconomy.h"
+#include "llagentbenefits.h"
#include "llerror.h"
#include "llfilepicker.h"
#include "llfloaterperms.h"
@@ -910,6 +910,7 @@ bool LLOutfitGalleryContextMenu::onEnable(LLSD::String param)
bool LLOutfitGalleryContextMenu::onVisible(LLSD::String param)
{
+ mMenuHandle.get()->getChild<LLUICtrl>("upload_photo")->setLabelArg("[UPLOAD_COST]", std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()));
if ("remove_photo" == param)
{
LLOutfitGallery* gallery = dynamic_cast<LLOutfitGallery*>(mOutfitList);
@@ -1205,7 +1206,7 @@ void LLOutfitGallery::uploadOutfitImage(const std::vector<std::string>& filename
return;
}
- 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).
+ S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
void *nruserdata = NULL;
nruserdata = (void *)&outfit_id;
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index f2a284a561..71ab826e1c 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -35,6 +35,7 @@
#include "llaccordionctrltab.h"
#include "llagentwearables.h"
#include "llappearancemgr.h"
+#include "llagentbenefits.h"
#include "llfloatersidepanelcontainer.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
@@ -1235,6 +1236,7 @@ bool LLOutfitListGearMenuBase::onEnable(LLSD::String param)
bool LLOutfitListGearMenuBase::onVisible(LLSD::String param)
{
+ getMenu()->getChild<LLUICtrl>("upload_photo")->setLabelArg("[UPLOAD_COST]", std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()));
const LLUUID& selected_outfit_id = getSelectedOutfitID();
if (selected_outfit_id.isNull()) // no selection or invalid outfit selected
{
diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp
index 451f41cd3b..3bae0cebfb 100644
--- a/indra/newview/llpanelcontents.cpp
+++ b/indra/newview/llpanelcontents.cpp
@@ -30,7 +30,6 @@
#include "llpanelcontents.h"
// linden library includes
-#include "lleconomy.h"
#include "llerror.h"
#include "llfloaterreg.h"
#include "llfontgl.h"
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index e41211ddbd..ab255d5215 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -128,10 +128,6 @@ void LLPanelGroup::onOpen(const LLSD& key)
{
onBackBtnClick();
}
- else if(str_action == "create")
- {
- setGroupID(LLUUID::null);
- }
else if(str_action == "refresh_notices")
{
LLPanelGroupNotices* panel_notices = findChild<LLPanelGroupNotices>("group_notices_tab_panel");
@@ -162,12 +158,8 @@ BOOL LLPanelGroup::postBuild()
button = getChild<LLButton>("btn_refresh");
button->setClickedCallback(onBtnRefresh, this);
- getChild<LLButton>("btn_create")->setVisible(false);
-
childSetCommitCallback("back",boost::bind(&LLPanelGroup::onBackBtnClick,this),NULL);
- childSetCommitCallback("btn_create",boost::bind(&LLPanelGroup::onBtnCreate,this),NULL);
-
LLPanelGroupTab* panel_general = findChild<LLPanelGroupTab>("group_general_tab_panel");
LLPanelGroupTab* panel_roles = findChild<LLPanelGroupTab>("group_roles_tab_panel");
LLPanelGroupTab* panel_notices = findChild<LLPanelGroupTab>("group_notices_tab_panel");
@@ -223,7 +215,6 @@ void LLPanelGroup::reposButtons()
}
reposButton("btn_apply");
- reposButton("btn_create");
reposButton("btn_refresh");
reposButton("btn_cancel");
reposButton("btn_chat");
@@ -246,23 +237,6 @@ void LLPanelGroup::onBackBtnClick()
}
}
-
-void LLPanelGroup::onBtnCreate()
-{
- LLPanelGroupGeneral* panel_general = findChild<LLPanelGroupGeneral>("group_general_tab_panel");
- if(!panel_general)
- return;
- std::string apply_mesg;
- if(panel_general->apply(apply_mesg))//yes yes you need to call apply to create...
- return;
- if ( !apply_mesg.empty() )
- {
- LLSD args;
- args["MESSAGE"] = apply_mesg;
- LLNotificationsUtil::add("GenericAlert", args);
- }
-}
-
void LLPanelGroup::onBtnRefresh(void* user_data)
{
LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
@@ -378,7 +352,6 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
LLButton* button_apply = findChild<LLButton>("btn_apply");
LLButton* button_refresh = findChild<LLButton>("btn_refresh");
- LLButton* button_create = findChild<LLButton>("btn_create");
LLButton* button_cancel = findChild<LLButton>("btn_cancel");
LLButton* button_call = findChild<LLButton>("btn_call");
@@ -391,8 +364,6 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
if(button_refresh)
button_refresh->setVisible(!is_null_group_id);
- if(button_create)
- button_create->setVisible(is_null_group_id);
if(button_cancel)
button_cancel->setVisible(!is_null_group_id);
@@ -611,18 +582,6 @@ void LLPanelGroup::showNotice(const std::string& subject,
panel_notices->showNotice(subject,message,has_inventory,inventory_name,inventory_offer);
}
-
-
-
-//static
-void LLPanelGroup::refreshCreatedGroup(const LLUUID& group_id)
-{
- LLPanelGroup* panel = LLFloaterSidePanelContainer::getPanel<LLPanelGroup>("people", "panel_group_info_sidetray");
- if(!panel)
- return;
- panel->setGroupID(group_id);
-}
-
//static
void LLPanelGroup::showNotice(const std::string& subject,
diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h
index 0b40c8b5d3..be40b08a6d 100644
--- a/indra/newview/llpanelgroup.h
+++ b/indra/newview/llpanelgroup.h
@@ -79,8 +79,6 @@ public:
virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- static void refreshCreatedGroup(const LLUUID& group_id);
-
static void showNotice(const std::string& subject,
const std::string& message,
const LLUUID& group_id,
@@ -92,7 +90,6 @@ public:
protected:
virtual void update(LLGroupChange gc);
- void onBtnCreate();
void onBackBtnClick();
void onBtnJoin();
diff --git a/indra/newview/llpanelgroupcreate.cpp b/indra/newview/llpanelgroupcreate.cpp
new file mode 100644
index 0000000000..052212dc27
--- /dev/null
+++ b/indra/newview/llpanelgroupcreate.cpp
@@ -0,0 +1,237 @@
+/**
+ * @file llpanelgroupcreate.cpp
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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 "llpanelgroupcreate.h"
+
+// UI includes
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llfloatersidepanelcontainer.h"
+#include "llsidetraypanelcontainer.h"
+#include "llscrolllistctrl.h"
+#include "llspinctrl.h"
+#include "lltextbox.h"
+#include "lltexteditor.h"
+#include "lltexturectrl.h"
+#include "lluictrlfactory.h"
+
+// Viewer includes
+#include "llagentbenefits.h"
+#include "llfloaterreg.h"
+#include "llfloater.h"
+#include "llgroupmgr.h"
+#include "lltrans.h"
+#include "llnotificationsutil.h"
+#include "lluicolortable.h"
+
+
+const S32 MATURE_CONTENT = 1;
+const S32 NON_MATURE_CONTENT = 2;
+const S32 DECLINE_TO_STATE = 0;
+
+static LLPanelInjector<LLPanelGroupCreate> t_panel_group_creation("panel_group_creation_sidetray");
+
+LLPanelGroupCreate::LLPanelGroupCreate()
+: LLPanel()
+{
+}
+
+LLPanelGroupCreate::~LLPanelGroupCreate()
+{
+}
+
+BOOL LLPanelGroupCreate::postBuild()
+{
+ childSetCommitCallback("back", boost::bind(&LLPanelGroupCreate::onBackBtnClick, this), NULL);
+
+ mComboMature = getChild<LLComboBox>("group_mature_check", TRUE);
+ mCtrlOpenEnrollment = getChild<LLCheckBoxCtrl>("open_enrollement", TRUE);
+ mCtrlEnrollmentFee = getChild<LLCheckBoxCtrl>("check_enrollment_fee", TRUE);
+ mEditCharter = getChild<LLTextEditor>("charter", TRUE);
+ mSpinEnrollmentFee = getChild<LLSpinCtrl>("spin_enrollment_fee", TRUE);
+ mMembershipList = getChild<LLScrollListCtrl>("membership_list", TRUE);
+
+ mCreateButton = getChild<LLButton>("btn_create", TRUE);
+ mCreateButton->setCommitCallback(boost::bind(&LLPanelGroupCreate::onBtnCreate, this));
+
+ mGroupNameEditor = getChild<LLLineEditor>("group_name_editor", TRUE);
+ mGroupNameEditor->setPrevalidate(LLTextValidate::validateASCIINoLeadingSpace);
+
+ mInsignia = getChild<LLTextureCtrl>("insignia", TRUE);
+ mInsignia->setAllowLocalTexture(FALSE);
+ mInsignia->setCanApplyImmediately(FALSE);
+
+ return TRUE;
+}
+
+void LLPanelGroupCreate::onOpen(const LLSD& key)
+{
+ mInsignia->setImageAssetID(LLUUID::null);
+ mInsignia->setImageAssetName(mInsignia->getDefaultImageName());
+ mGroupNameEditor->clear();
+ mEditCharter->clear();
+ mSpinEnrollmentFee->set(0.f);
+ mCtrlEnrollmentFee->set(FALSE);
+ mCtrlOpenEnrollment->set(FALSE);
+ mMembershipList->clearRows();
+
+ // populate list
+ addMembershipRow("Base");
+ addMembershipRow("Premium");
+ addMembershipRow("Premium Plus");
+ addMembershipRow("Internal");// Present only if you are already in one, needed for testing
+
+ S32 cost = LLAgentBenefitsMgr::current().getCreateGroupCost();
+ mCreateButton->setLabelArg("[COST]", llformat("%d", cost));
+}
+
+//static
+void LLPanelGroupCreate::refreshCreatedGroup(const LLUUID& group_id)
+{
+ LLSD params;
+ params["group_id"] = group_id;
+ params["open_tab_name"] = "panel_group_info_sidetray";
+ LLFloaterSidePanelContainer::showPanel("people", "panel_group_info_sidetray", params);
+}
+
+void LLPanelGroupCreate::addMembershipRow(const std::string &name)
+{
+ if (LLAgentBenefitsMgr::has(name))
+ {
+ bool is_current = LLAgentBenefitsMgr::isCurrent(name);
+
+ LLScrollListItem::Params item_params;
+ LLScrollListCell::Params cell_params;
+ cell_params.font = LLFontGL::getFontSansSerif();
+ // Start out right justifying numeric displays
+ cell_params.font_halign = LLFontGL::LEFT;
+ if (is_current)
+ {
+ cell_params.color = LLUIColorTable::instance().getColor("DrYellow");
+ }
+
+ cell_params.column = "clmn_name";
+ std::string mem_str = name + "Membership";
+ if (is_current)
+ {
+ cell_params.value = LLTrans::getString(mem_str) + " " + getString("current_membership");
+ }
+ else
+ {
+ cell_params.value = LLTrans::getString(mem_str);
+ }
+ item_params.columns.add(cell_params);
+ cell_params.column = "clmn_price";
+ cell_params.value = llformat("L$ %d",LLAgentBenefitsMgr::get(name).getCreateGroupCost());
+ item_params.columns.add(cell_params);
+ mMembershipList->addRow(item_params);
+ }
+}
+
+void LLPanelGroupCreate::onBackBtnClick()
+{
+ LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent());
+ if(parent)
+ {
+ parent->openPreviousPanel();
+ }
+}
+
+bool LLPanelGroupCreate::confirmMatureApply(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ // 0 == Yes
+ // 1 == No
+ // 2 == Cancel
+ switch (option)
+ {
+ case 0:
+ mComboMature->setCurrentByIndex(MATURE_CONTENT);
+ createGroup();
+ break;
+ case 1:
+ mComboMature->setCurrentByIndex(NON_MATURE_CONTENT);
+ createGroup();
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void LLPanelGroupCreate::onBtnCreate()
+{
+ LL_INFOS() << "Validating group creation" << LL_ENDL;
+
+ // Validate the group name length.
+ std::string gr_name = mGroupNameEditor->getText();
+ LLStringUtil::trim(gr_name);
+ S32 group_name_len = gr_name.size();
+ if (group_name_len < DB_GROUP_NAME_MIN_LEN
+ || group_name_len > DB_GROUP_NAME_STR_LEN)
+ {
+ LLSD args;
+ args["MIN_LEN"] = DB_GROUP_NAME_MIN_LEN;
+ args["MAX_LEN"] = DB_GROUP_NAME_STR_LEN;
+ LLNotificationsUtil::add("GroupNameLengthWarning", args);
+ }
+ else
+ // Check to make sure mature has been set
+ if (mComboMature &&
+ mComboMature->getCurrentIndex() == DECLINE_TO_STATE)
+ {
+ LLNotificationsUtil::add("SetGroupMature", LLSD(), LLSD(),
+ boost::bind(&LLPanelGroupCreate::confirmMatureApply, this, _1, _2));
+ }
+ else
+ {
+ createGroup();
+ }
+}
+
+void LLPanelGroupCreate::createGroup()
+{
+ LL_INFOS() << "Creating group" << LL_ENDL;
+
+ U32 enrollment_fee = (mCtrlEnrollmentFee->get() ?
+ (U32)mSpinEnrollmentFee->get() : 0);
+ LLUUID insignia_id = mInsignia->getImageItemID().isNull() ? LLUUID::null : mInsignia->getImageAssetID();
+
+ std::string gr_name = mGroupNameEditor->getText();
+ LLStringUtil::trim(gr_name);
+ LLGroupMgr::getInstance()->sendCreateGroupRequest(gr_name,
+ mEditCharter->getText(),
+ true,
+ insignia_id,
+ enrollment_fee,
+ mCtrlOpenEnrollment->get(),
+ false,
+ mComboMature->getCurrentIndex() == MATURE_CONTENT);
+}
+
diff --git a/indra/newview/llpanelgroupcreate.h b/indra/newview/llpanelgroupcreate.h
new file mode 100644
index 0000000000..3ae2e7f24a
--- /dev/null
+++ b/indra/newview/llpanelgroupcreate.h
@@ -0,0 +1,73 @@
+/**
+ * @file llpanelgroupcreate.h
+ *
+ * $LicenseInfo:firstyear=2019&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2019, 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_LLPANELGROUPCREATE_H
+#define LL_LLPANELGROUPCREATE_H
+
+#include "llpanel.h"
+
+
+// Forward declares
+class LLButton;
+class LLCheckBoxCtrl;
+class LLComboBox;
+class LLLineEditor;
+class LLTextEditor;
+class LLTextureCtrl;
+class LLScrollListCtrl;
+class LLSpinCtrl;
+
+
+class LLPanelGroupCreate : public LLPanel
+{
+public:
+ LLPanelGroupCreate();
+ virtual ~LLPanelGroupCreate();
+
+ virtual BOOL postBuild();
+
+ void onOpen(const LLSD& key);
+
+ static void refreshCreatedGroup(const LLUUID& group_id);
+
+private:
+ void addMembershipRow(const std::string &name);
+ bool confirmMatureApply(const LLSD& notification, const LLSD& response);
+ void onBtnCreate();
+ void onBackBtnClick();
+ void createGroup();
+
+ LLComboBox *mComboMature;
+ LLButton *mCreateButton;
+ LLCheckBoxCtrl *mCtrlOpenEnrollment;
+ LLCheckBoxCtrl *mCtrlEnrollmentFee;
+ LLTextEditor *mEditCharter;
+ LLTextureCtrl *mInsignia;
+ LLLineEditor *mGroupNameEditor;
+ LLScrollListCtrl *mMembershipList;
+ LLSpinCtrl *mSpinEnrollmentFee;
+};
+
+#endif // LL_LLPANELGROUPCREATE_H
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index b53cd222e7..375daf60f8 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -30,6 +30,7 @@
#include "llavatarnamecache.h"
#include "llagent.h"
+#include "llagentbenefits.h"
#include "llsdparam.h"
#include "lluictrlfactory.h"
#include "roles_constants.h"
@@ -303,6 +304,11 @@ void LLPanelGroupGeneral::draw()
bool LLPanelGroupGeneral::apply(std::string& mesg)
{
+ if (mGroupID.isNull())
+ {
+ return false;
+ }
+
if (!mGroupID.isNull() && mAllowEdit && mComboActiveTitle && mComboActiveTitle->isDirty())
{
LLGroupMgr::getInstance()->sendGroupTitleUpdate(mGroupID,mComboActiveTitle->getCurrentID());
@@ -312,7 +318,7 @@ bool LLPanelGroupGeneral::apply(std::string& mesg)
BOOL has_power_in_group = gAgent.hasPowerInGroup(mGroupID,GP_GROUP_CHANGE_IDENTITY);
- if (has_power_in_group || mGroupID.isNull())
+ if (has_power_in_group)
{
LL_INFOS() << "LLPanelGroupGeneral::apply" << LL_ENDL;
@@ -325,25 +331,6 @@ bool LLPanelGroupGeneral::apply(std::string& mesg)
return false;
}
- if (mGroupID.isNull())
- {
- // Validate the group name length.
- S32 group_name_len = mGroupNameEditor->getText().size();
- if ( group_name_len < DB_GROUP_NAME_MIN_LEN
- || group_name_len > DB_GROUP_NAME_STR_LEN)
- {
- std::ostringstream temp_error;
- temp_error << "A group name must be between " << DB_GROUP_NAME_MIN_LEN
- << " and " << DB_GROUP_NAME_STR_LEN << " characters.";
- mesg = temp_error.str();
- return false;
- }
-
- LLNotificationsUtil::add("CreateGroupCost", LLSD(), LLSD(), boost::bind(&LLPanelGroupGeneral::createGroupCallback, this, _1, _2));
-
- return false;
- }
-
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
if (!gdatap)
{
@@ -450,37 +437,6 @@ bool LLPanelGroupGeneral::confirmMatureApply(const LLSD& notification, const LLS
return ret;
}
-// static
-bool LLPanelGroupGeneral::createGroupCallback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- switch(option)
- {
- case 0:
- {
- // Yay! We are making a new group!
- U32 enrollment_fee = (mCtrlEnrollmentFee->get() ?
- (U32) mSpinEnrollmentFee->get() : 0);
- LLUUID insignia_id = mInsignia->getImageItemID().isNull() ? LLUUID::null : mInsignia->getImageAssetID();
-
- LLGroupMgr::getInstance()->sendCreateGroupRequest(mGroupNameEditor->getText(),
- mEditCharter->getText(),
- mCtrlShowInGroupList->get(),
- insignia_id,
- enrollment_fee,
- mCtrlOpenEnrollment->get(),
- false,
- mComboMature->getCurrentIndex() == MATURE_CONTENT);
-
- }
- break;
- case 1:
- default:
- break;
- }
- return false;
-}
-
// virtual
void LLPanelGroupGeneral::update(LLGroupChange gc)
{
diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h
index 11972bafa9..1d0789521c 100644
--- a/indra/newview/llpanelgroupgeneral.h
+++ b/indra/newview/llpanelgroupgeneral.h
@@ -51,7 +51,6 @@ public:
virtual bool needsApply(std::string& mesg);
virtual bool apply(std::string& mesg);
virtual void cancel();
- bool createGroupCallback(const LLSD& notification, const LLSD& response);
virtual void update(LLGroupChange gc);
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index b40a7ef1f0..02cd22c307 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -28,12 +28,12 @@
#include "llpanelmaininventory.h"
#include "llagent.h"
+#include "llagentbenefits.h"
#include "llagentcamera.h"
#include "llavataractions.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#include "lldndbutton.h"
-#include "lleconomy.h"
#include "llfilepicker.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
@@ -231,16 +231,16 @@ BOOL LLPanelMainInventory::postBuild()
initListCommandsHandlers();
- // *TODO:Get the cost info from the server
- const std::string upload_cost("10");
+ const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost());
+ const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost());
+ const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost());
LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get();
if (menu)
{
- menu->getChild<LLMenuItemGL>("Upload Image")->setLabelArg("[COST]", upload_cost);
- menu->getChild<LLMenuItemGL>("Upload Sound")->setLabelArg("[COST]", upload_cost);
- menu->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", upload_cost);
- menu->getChild<LLMenuItemGL>("Bulk Upload")->setLabelArg("[COST]", upload_cost);
+ menu->getChild<LLMenuItemGL>("Upload Image")->setLabelArg("[COST]", texture_upload_cost_str);
+ menu->getChild<LLMenuItemGL>("Upload Sound")->setLabelArg("[COST]", sound_upload_cost_str);
+ menu->getChild<LLMenuItemGL>("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str);
}
// Trigger callback for focus received so we can deselect items in inbox/outbox
@@ -1517,36 +1517,16 @@ bool LLPanelMainInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType
void LLPanelMainInventory::setUploadCostIfNeeded()
{
- // *NOTE dzaporozhan
- // Upload cost is set in process_economy_data() (llviewermessage.cpp). But since we
- // have two instances of Inventory panel at the moment(and two instances of context menu),
- // call to gMenuHolder->childSetLabelArg() sets upload cost only for one of the instances.
-
LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get();
if(mNeedUploadCost && menu)
{
- LLMenuItemBranchGL* upload_menu = menu->findChild<LLMenuItemBranchGL>("upload");
- if(upload_menu)
- {
- S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
- std::string cost_str;
-
- // getPriceUpload() returns -1 if no data available yet.
- if(upload_cost >= 0)
- {
- mNeedUploadCost = false;
- cost_str = llformat("%d", upload_cost);
- }
- else
- {
- cost_str = llformat("%d", gSavedSettings.getU32("DefaultUploadCost"));
- }
+ const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost());
+ const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost());
+ const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost());
- upload_menu->getChild<LLView>("Upload Image")->setLabelArg("[COST]", cost_str);
- upload_menu->getChild<LLView>("Upload Sound")->setLabelArg("[COST]", cost_str);
- upload_menu->getChild<LLView>("Upload Animation")->setLabelArg("[COST]", cost_str);
- upload_menu->getChild<LLView>("Bulk Upload")->setLabelArg("[COST]", cost_str);
- }
+ menu->getChild<LLView>("Upload Image")->setLabelArg("[COST]", texture_upload_cost_str);
+ menu->getChild<LLView>("Upload Sound")->setLabelArg("[COST]", sound_upload_cost_str);
+ menu->getChild<LLView>("Upload Animation")->setLabelArg("[COST]", animation_upload_cost_str);
}
}
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 3665910c63..6bff95ab36 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -30,7 +30,6 @@
#include "llpanelobject.h"
// linden library includes
-#include "lleconomy.h"
#include "llerror.h"
#include "llfontgl.h"
#include "llpermissionsflags.h"
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index be174475e1..e5142f2b5f 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -47,6 +47,7 @@
#include "llaccordionctrl.h"
#include "llaccordionctrltab.h"
#include "llagent.h"
+#include "llagentbenefits.h"
#include "llavataractions.h"
#include "llavatarlist.h"
#include "llavatarlistitem.h"
@@ -85,11 +86,6 @@ static const std::string RECENT_TAB_NAME = "recent_panel";
static const std::string BLOCKED_TAB_NAME = "blocked_panel"; // blocked avatars
static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
-const S32 BASE_MAX_AGENT_GROUPS = 42;
-const S32 PREMIUM_MAX_AGENT_GROUPS = 60;
-
-extern S32 gMaxAgentGroups;
-
/** Comparator for comparing avatar items by last interaction date */
class LLAvatarItemRecentComparator : public LLAvatarItemComparator
{
@@ -612,26 +608,17 @@ void LLPanelPeople::removePicker()
BOOL LLPanelPeople::postBuild()
{
- S32 max_premium = PREMIUM_MAX_AGENT_GROUPS;
- if (gAgent.getRegion())
- {
- LLSD features;
- gAgent.getRegion()->getSimulatorFeatures(features);
- if (features.has("MaxAgentGroupsPremium"))
- {
- max_premium = features["MaxAgentGroupsPremium"].asInteger();
- }
- }
+ S32 max_premium = LLAgentBenefitsMgr::get("Premium").getGroupMembershipLimit();
getChild<LLFilterEditor>("nearby_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
getChild<LLFilterEditor>("friends_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
getChild<LLFilterEditor>("groups_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
getChild<LLFilterEditor>("recent_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
- if(gMaxAgentGroups < max_premium)
+ if(LLAgentBenefitsMgr::current().getGroupMembershipLimit() < max_premium)
{
- getChild<LLTextBox>("groupcount")->setText(getString("GroupCountWithInfo"));
- getChild<LLTextBox>("groupcount")->setURLClickedCallback(boost::bind(&LLPanelPeople::onGroupLimitInfo, this));
+ getChild<LLTextBox>("groupcount")->setText(getString("GroupCountWithInfo"));
+ getChild<LLTextBox>("groupcount")->setURLClickedCallback(boost::bind(&LLPanelPeople::onGroupLimitInfo, this));
}
mTabContainer = getChild<LLTabContainer>("tabs");
@@ -876,9 +863,10 @@ void LLPanelPeople::updateButtons()
groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected
U32 groups_count = gAgent.mGroups.size();
- U32 groups_ramaining = gMaxAgentGroups > groups_count ? gMaxAgentGroups - groups_count : 0;
+ S32 max_groups = LLAgentBenefitsMgr::current().getGroupMembershipLimit();
+ U32 groups_remaining = max_groups > groups_count ? max_groups - groups_count : 0;
groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d", groups_count));
- groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d", groups_ramaining));
+ groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d", groups_remaining));
}
else
{
@@ -1095,25 +1083,22 @@ void LLPanelPeople::onGroupLimitInfo()
{
LLSD args;
- S32 max_basic = BASE_MAX_AGENT_GROUPS;
- S32 max_premium = PREMIUM_MAX_AGENT_GROUPS;
- if (gAgent.getRegion())
+ S32 max_basic = LLAgentBenefitsMgr::get("Base").getGroupMembershipLimit();
+ S32 max_premium = LLAgentBenefitsMgr::get("Premium").getGroupMembershipLimit();
+
+ args["MAX_BASIC"] = max_basic;
+ args["MAX_PREMIUM"] = max_premium;
+
+ if (LLAgentBenefitsMgr::has("Premium Plus"))
{
- LLSD features;
- gAgent.getRegion()->getSimulatorFeatures(features);
- if (features.has("MaxAgentGroupsBasic"))
- {
- max_basic = features["MaxAgentGroupsBasic"].asInteger();
- }
- if (features.has("MaxAgentGroupsPremium"))
- {
- max_premium = features["MaxAgentGroupsPremium"].asInteger();
- }
+ S32 max_premium_plus = LLAgentBenefitsMgr::get("Premium Plus").getGroupMembershipLimit();
+ args["MAX_PREMIUM_PLUS"] = max_premium_plus;
+ LLNotificationsUtil::add("GroupLimitInfoPlus", args);
}
- args["MAX_BASIC"] = max_basic;
- args["MAX_PREMIUM"] = max_premium;
-
- LLNotificationsUtil::add("GroupLimitInfo", args);
+ else
+ {
+ LLNotificationsUtil::add("GroupLimitInfo", args);
+ }
}
void LLPanelPeople::onTabSelected(const LLSD& param)
diff --git a/indra/newview/llpanelsnapshot.cpp b/indra/newview/llpanelsnapshot.cpp
index a17e3f9e78..c3524a8c87 100644
--- a/indra/newview/llpanelsnapshot.cpp
+++ b/indra/newview/llpanelsnapshot.cpp
@@ -39,6 +39,8 @@
#include "llsidetraypanelcontainer.h"
#include "llviewercontrol.h" // gSavedSettings
+#include "llagentbenefits.h"
+
const S32 MAX_TEXTURE_SIZE = 512 ; //max upload texture size 512 * 512
S32 power_of_two(S32 sz, S32 upper)
@@ -59,6 +61,7 @@ LLPanelSnapshot::LLPanelSnapshot()
// virtual
BOOL LLPanelSnapshot::postBuild()
{
+ getChild<LLUICtrl>("save_btn")->setLabelArg("[UPLOAD_COST]", std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()));
getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshot::onResolutionComboCommit, this, _1));
if (!getWidthSpinnerName().empty())
{
diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp
index 21ac7604ff..9e56a04b3b 100644
--- a/indra/newview/llpanelsnapshotinventory.cpp
+++ b/indra/newview/llpanelsnapshotinventory.cpp
@@ -27,7 +27,6 @@
#include "llviewerprecompiledheaders.h"
#include "llcombobox.h"
-#include "lleconomy.h"
#include "llsidetraypanelcontainer.h"
#include "llspinctrl.h"
@@ -38,6 +37,8 @@
#include "llstatusbar.h" // can_afford_transaction()
#include "llnotificationsutil.h"
+#include "llagentbenefits.h"
+
/**
* The panel provides UI for saving snapshot as an inventory texture.
*/
@@ -135,7 +136,6 @@ BOOL LLPanelSnapshotInventory::postBuild()
// virtual
void LLPanelSnapshotInventory::onOpen(const LLSD& key)
{
- getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload()));
LLPanelSnapshot::onOpen(key);
}
@@ -155,7 +155,7 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl)
void LLPanelSnapshotInventoryBase::onSend()
{
- S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
+ S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
if (can_afford_transaction(expected_upload_cost))
{
if (mSnapshotFloater)
@@ -191,7 +191,7 @@ BOOL LLPanelOutfitSnapshotInventory::postBuild()
// virtual
void LLPanelOutfitSnapshotInventory::onOpen(const LLSD& key)
{
- getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLGlobalEconomy::getInstance()->getPriceUpload()));
+ getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost()));
LLPanelSnapshot::onOpen(key);
}
diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp
index 1a3e946127..8cc2fbc770 100644
--- a/indra/newview/llpanelsnapshotoptions.cpp
+++ b/indra/newview/llpanelsnapshotoptions.cpp
@@ -26,19 +26,20 @@
#include "llviewerprecompiledheaders.h"
-#include "lleconomy.h"
#include "llpanel.h"
#include "llsidetraypanelcontainer.h"
#include "llfloatersnapshot.h" // FIXME: create a snapshot model
#include "llfloaterreg.h"
+#include "llagentbenefits.h"
+
+
/**
* Provides several ways to save a snapshot.
*/
class LLPanelSnapshotOptions
: public LLPanel
-, public LLEconomyObserver
{
LOG_CLASS(LLPanelSnapshotOptions);
@@ -47,7 +48,6 @@ public:
~LLPanelSnapshotOptions();
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
- /*virtual*/ void onEconomyDataChange() { updateUploadCost(); }
private:
void updateUploadCost();
@@ -68,13 +68,10 @@ LLPanelSnapshotOptions::LLPanelSnapshotOptions()
mCommitCallbackRegistrar.add("Snapshot.SaveToEmail", boost::bind(&LLPanelSnapshotOptions::onSaveToEmail, this));
mCommitCallbackRegistrar.add("Snapshot.SaveToInventory", boost::bind(&LLPanelSnapshotOptions::onSaveToInventory, this));
mCommitCallbackRegistrar.add("Snapshot.SaveToComputer", boost::bind(&LLPanelSnapshotOptions::onSaveToComputer, this));
-
- LLGlobalEconomy::getInstance()->addObserver(this);
}
LLPanelSnapshotOptions::~LLPanelSnapshotOptions()
{
- LLGlobalEconomy::getInstance()->removeObserver(this);
}
// virtual
@@ -92,7 +89,7 @@ void LLPanelSnapshotOptions::onOpen(const LLSD& key)
void LLPanelSnapshotOptions::updateUploadCost()
{
- S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
+ S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
getChild<LLUICtrl>("save_to_inventory_btn")->setLabelArg("[AMOUNT]", llformat("%d", upload_cost));
}
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index d50cda2113..2b531b6acc 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -31,7 +31,6 @@
// linden library includes
#include "llclickaction.h"
-#include "lleconomy.h"
#include "llerror.h"
#include "llfontgl.h"
#include "llflexibleobject.h"
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index aee6bcb05e..56068b3bbb 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -35,7 +35,6 @@
#include "llcachename.h"
#include "llavatarnamecache.h"
#include "lldbstrings.h"
-#include "lleconomy.h"
#include "llgl.h"
#include "llmediaentry.h"
#include "llrender.h"
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index b448caeb0b..356f2e81ce 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -28,10 +28,10 @@
#include "llviewerprecompiledheaders.h"
#include "llagent.h"
+#include "llagentbenefits.h"
#include "llagentcamera.h"
#include "llagentui.h"
#include "llcombobox.h"
-#include "lleconomy.h"
#include "llfloaterperms.h"
#include "llfloaterreg.h"
#include "llimagefilter.h"
@@ -1009,7 +1009,7 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
std::string who_took_it;
LLAgentUI::buildFullname(who_took_it);
- S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
+ S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
std::string res_name = outfit_snapshot ? name : "Snapshot : " + pos_string;
std::string res_desc = outfit_snapshot ? "" : "Taken by " + who_took_it + " at " + pos_string;
LLFolderType::EType folder_type = outfit_snapshot ? LLFolderType::FT_NONE : LLFolderType::FT_SNAPSHOT_CATEGORY;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 42cf04fba7..8093a3a589 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -88,6 +88,7 @@
#include "v3math.h"
#include "llagent.h"
+#include "llagentbenefits.h"
#include "llagentcamera.h"
#include "llagentpicksinfo.h"
#include "llagentwearables.h"
@@ -209,7 +210,6 @@
// exported globals
//
bool gAgentMovementCompleted = false;
-S32 gMaxAgentGroups;
const std::string SCREEN_HOME_FILENAME = "screen_home%s.png";
const std::string SCREEN_LAST_FILENAME = "screen_last%s.png";
@@ -246,9 +246,8 @@ static std::string gFirstSimSeedCap;
static LLVector3 gAgentStartLookAt(1.0f, 0.f, 0.f);
static std::string gAgentStartLocation = "safe";
static bool mLoginStatePastUI = false;
+static bool mBenefitsSuccessfullyInit = false;
-const S32 DEFAULT_MAX_AGENT_GROUPS = 42;
-const S32 ALLOWED_MAX_AGENT_GROUPS = 500;
const F32 STATE_AGENT_WAIT_TIMEOUT = 240; //seconds
boost::scoped_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState"));
@@ -279,6 +278,7 @@ void general_cert_done(const LLSD& notification, const LLSD& response);
void trust_cert_done(const LLSD& notification, const LLSD& response);
void apply_udp_blacklist(const std::string& csv);
bool process_login_success_response();
+void on_benefits_failed_callback(const LLSD& notification, const LLSD& response);
void transition_back_to_login_panel(const std::string& emsg);
void callback_cache_name(const LLUUID& id, const std::string& full_name, bool is_group)
@@ -1564,8 +1564,6 @@ bool idle_startup()
send_complete_agent_movement(regionp->getHost());
gAssetStorage->setUpstream(regionp->getHost());
gCacheName->setUpstream(regionp->getHost());
- msg->newMessageFast(_PREHASH_EconomyDataRequest);
- gAgent.sendReliableMessage();
}
display_startup();
@@ -2151,6 +2149,11 @@ bool idle_startup()
set_startup_status(1.0, "", "");
display_startup();
+ if (!mBenefitsSuccessfullyInit)
+ {
+ LLNotificationsUtil::add("FailedToGetBenefits", LLSD(), LLSD(), boost::bind(on_benefits_failed_callback, _1, _2));
+ }
+
// Let the map know about the inventory.
LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
if(floater_world_map)
@@ -3268,10 +3271,70 @@ void apply_udp_blacklist(const std::string& csv)
}
+void on_benefits_failed_callback(const LLSD& notification, const LLSD& response)
+{
+ LL_WARNS("Benefits") << "Failed to load benefits information" << LL_ENDL;
+}
+
+bool init_benefits(LLSD& response)
+{
+ bool succ = true;
+
+ std::string package_name = response["account_type"].asString();
+ const LLSD& benefits_sd = response["account_level_benefits"];
+ if (!LLAgentBenefitsMgr::init(package_name, benefits_sd) ||
+ !LLAgentBenefitsMgr::initCurrent(package_name, benefits_sd))
+ {
+ succ = false;
+ }
+ else
+ {
+ LL_DEBUGS("Benefits") << "Initialized current benefits, level " << package_name << " from " << benefits_sd << LL_ENDL;
+ }
+ const LLSD& packages_sd = response["premium_packages"];
+ for(LLSD::map_const_iterator package_iter = packages_sd.beginMap();
+ package_iter != packages_sd.endMap();
+ ++package_iter)
+ {
+ std::string package_name = package_iter->first;
+ const LLSD& benefits_sd = package_iter->second["benefits"];
+ if (LLAgentBenefitsMgr::init(package_name, benefits_sd))
+ {
+ LL_DEBUGS("Benefits") << "Initialized benefits for package " << package_name << " from " << benefits_sd << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("Benefits") << "Failed init for package " << package_name << " from " << benefits_sd << LL_ENDL;
+ succ = false;
+ }
+ }
+
+ if (!LLAgentBenefitsMgr::has("Base"))
+ {
+ LL_WARNS("Benefits") << "Benefits info did not include required package Base" << LL_ENDL;
+ succ = false;
+ }
+ if (!LLAgentBenefitsMgr::has("Premium"))
+ {
+ LL_WARNS("Benefits") << "Benefits info did not include required package Premium" << LL_ENDL;
+ succ = false;
+ }
+
+ // FIXME PREMIUM - for testing if login does not yet provide Premium Plus. Should be removed thereafter.
+ //if (succ && !LLAgentBenefitsMgr::has("Premium Plus"))
+ //{
+ // LLAgentBenefitsMgr::init("Premium Plus", packages_sd["Premium"]["benefits"]);
+ // llassert(LLAgentBenefitsMgr::has("Premium Plus"));
+ //}
+ return succ;
+}
+
bool process_login_success_response()
{
LLSD response = LLLoginInstance::getInstance()->getResponse();
+ mBenefitsSuccessfullyInit = init_benefits(response);
+
std::string text(response["udp_blacklist"]);
if(!text.empty())
{
@@ -3594,27 +3657,6 @@ bool process_login_success_response()
LLViewerMedia::getInstance()->openIDSetup(openid_url, openid_token);
}
- gMaxAgentGroups = DEFAULT_MAX_AGENT_GROUPS;
- if(response.has("max-agent-groups"))
- {
- S32 agent_groups = atoi(std::string(response["max-agent-groups"]).c_str());
- if (agent_groups > 0 && agent_groups <= ALLOWED_MAX_AGENT_GROUPS)
- {
- gMaxAgentGroups = agent_groups;
- LL_INFOS("LLStartup") << "gMaxAgentGroups read from login.cgi: "
- << gMaxAgentGroups << LL_ENDL;
- }
- else
- {
- LL_INFOS("LLStartup") << "Invalid value received, using defaults for gMaxAgentGroups: "
- << gMaxAgentGroups << LL_ENDL;
- }
- }
- else {
- LL_INFOS("LLStartup") << "Missing max-agent-groups, using default value for gMaxAgentGroups: "
- << gMaxAgentGroups << LL_ENDL;
- }
-
bool success = false;
// JC: gesture loading done below, when we have an asset system
// in place. Don't delete/clear gUserCredentials until then.
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index 5ce74b8fae..d7d294e9f4 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -80,7 +80,6 @@ typedef enum {
// exported symbols
extern bool gAgentMovementCompleted;
-extern S32 gMaxAgentGroups;
extern LLPointer<LLViewerTexture> gStartTexture;
class LLStartUp
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index 6dcd20dc21..6a29be4aa1 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -192,6 +192,11 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
- 3*VPAD - BTN_HEIGHT;
// reshape to calculate real text width and height
msg_box->reshape( MAX_ALLOWED_MSG_WIDTH, max_allowed_msg_height );
+
+ if ("GroupLimitInfo" == mNotification->getName() || "GroupLimitInfoPlus" == mNotification->getName())
+ {
+ msg_box->setSkipLinkUnderline(true);
+ }
msg_box->setValue(msg);
S32 pixel_width = msg_box->getTextPixelWidth();
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 2544f75926..d53cc3f745 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -36,7 +36,6 @@
#include "lluploaddialog.h"
#include "llpreviewscript.h"
#include "llnotificationsutil.h"
-#include "lleconomy.h"
#include "llagent.h"
#include "llfloaterreg.h"
#include "llfloatersnapshot.h"
@@ -171,22 +170,6 @@ void LLResourceUploadInfo::logPreparedUpload()
"Asset Type: " << LLAssetType::lookup(mAssetType) << LL_ENDL;
}
-S32 LLResourceUploadInfo::getEconomyUploadCost()
-{
- // Update L$ and ownership credit information
- // since it probably changed on the server
- if (getAssetType() == LLAssetType::AT_TEXTURE ||
- getAssetType() == LLAssetType::AT_SOUND ||
- getAssetType() == LLAssetType::AT_ANIMATION ||
- getAssetType() == LLAssetType::AT_MESH)
- {
- return LLGlobalEconomy::instance().getPriceUpload();
- }
-
- return 0;
-}
-
-
LLUUID LLResourceUploadInfo::finishUpload(LLSD &result)
{
if (getFolderId().isNull())
@@ -323,6 +306,42 @@ std::string LLResourceUploadInfo::getDisplayName() const
return (mName.empty()) ? mAssetId.asString() : mName;
};
+bool LLResourceUploadInfo::findAssetTypeOfExtension(const std::string& exten, LLAssetType::EType& asset_type)
+{
+ U32 codec;
+ return findAssetTypeAndCodecOfExtension(exten, asset_type, codec, false);
+}
+
+// static
+bool LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(const std::string& exten, LLAssetType::EType& asset_type, U32& codec, bool bulk_upload)
+{
+ bool succ = false;
+
+ codec = LLImageBase::getCodecFromExtension(exten);
+ if (codec != IMG_CODEC_INVALID)
+ {
+ asset_type = LLAssetType::AT_TEXTURE;
+ succ = true;
+ }
+ else if (exten == "wav")
+ {
+ asset_type = LLAssetType::AT_SOUND;
+ succ = true;
+ }
+ else if (exten == "anim")
+ {
+ asset_type = LLAssetType::AT_ANIMATION;
+ succ = true;
+ }
+ else if (!bulk_upload && (exten == "bvh"))
+ {
+ asset_type = LLAssetType::AT_ANIMATION;
+ succ = true;
+ }
+
+ return succ;
+}
+
//=========================================================================
LLNewFileResourceUploadInfo::LLNewFileResourceUploadInfo(
std::string fileName,
@@ -360,9 +379,11 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()
std::string filename = gDirUtilp->getTempFilename();
std::string exten = gDirUtilp->getExtension(getFileName());
- U32 codec = LLImageBase::getCodecFromExtension(exten);
LLAssetType::EType assetType = LLAssetType::AT_NONE;
+ U32 codec = IMG_CODEC_INVALID;
+ bool found_type = findAssetTypeAndCodecOfExtension(exten, assetType, codec);
+
std::string errorMessage;
std::string errorLabel;
@@ -379,10 +400,16 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()
errorLabel = "NoFileExtension";
error = true;
}
- else if (codec != IMG_CODEC_INVALID)
+ else if (!found_type)
+ {
+ // Unknown extension
+ errorMessage = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str());
+ errorLabel = "ErrorMessage";
+ error = TRUE;;
+ }
+ else if (assetType == LLAssetType::AT_TEXTURE)
{
// It's an image file, the upload procedure is the same for all
- assetType = LLAssetType::AT_TEXTURE;
if (!LLViewerTextureList::createUploadFile(getFileName(), filename, codec))
{
errorMessage = llformat("Problem with file %s:\n\n%s\n",
@@ -391,9 +418,8 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()
error = true;
}
}
- else if (exten == "wav")
+ else if (assetType == LLAssetType::AT_SOUND)
{
- assetType = LLAssetType::AT_SOUND; // tag it as audio
S32 encodeResult = 0;
LL_INFOS() << "Attempting to encode wav as an ogg file" << LL_ENDL;
@@ -423,18 +449,10 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile()
errorLabel = "DoNotSupportBulkAnimationUpload";
error = true;
}
- else if (exten == "anim")
+ else if (assetType == LLAssetType::AT_ANIMATION)
{
- assetType = LLAssetType::AT_ANIMATION;
filename = getFileName();
}
- else
- {
- // Unknown extension
- errorMessage = llformat(LLTrans::getString("UnknownFileExtension").c_str(), exten.c_str());
- errorLabel = "ErrorMessage";
- error = TRUE;;
- }
if (error)
{
@@ -744,7 +762,7 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
result["success"] = LLSD::Boolean((ulstate == "complete") && status);
}
- S32 uploadPrice = result["upload_price"].asInteger();//uploadInfo->getEconomyUploadCost();
+ S32 uploadPrice = result["upload_price"].asInteger();
if (uploadPrice > 0)
{
diff --git a/indra/newview/llviewerassetupload.h b/indra/newview/llviewerassetupload.h
index 4241c22c3e..d9eacf3167 100644
--- a/indra/newview/llviewerassetupload.h
+++ b/indra/newview/llviewerassetupload.h
@@ -62,7 +62,6 @@ public:
virtual LLSD prepareUpload();
virtual LLSD generatePostBody();
virtual void logPreparedUpload();
- virtual S32 getEconomyUploadCost();
virtual LLUUID finishUpload(LLSD &result);
LLTransactionID getTransactionId() const { return mTransactionId; }
@@ -88,6 +87,9 @@ public:
LLUUID getItemId() const { return mItemId; }
LLAssetID getAssetId() const { return mAssetId; }
+ static bool findAssetTypeOfExtension(const std::string& exten, LLAssetType::EType& asset_type);
+ static bool findAssetTypeAndCodecOfExtension(const std::string& exten, LLAssetType::EType& asset_type, U32& codec, bool bulk_upload = true);
+
protected:
LLResourceUploadInfo(
std::string name,
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 94ee425405..162acb74f1 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -45,6 +45,7 @@
// newview includes
#include "llagent.h"
#include "llagentaccess.h"
+#include "llagentbenefits.h"
#include "llagentcamera.h"
#include "llagentui.h"
#include "llagentwearables.h"
@@ -123,13 +124,13 @@
#include "lluilistener.h"
#include "llappearancemgr.h"
#include "lltrans.h"
-#include "lleconomy.h"
#include "lltoolgrab.h"
#include "llwindow.h"
#include "llpathfindingmanager.h"
#include "llstartup.h"
#include "boost/unordered_map.hpp"
#include <boost/regex.hpp>
+#include <boost/algorithm/string.hpp>
#include "llcleanup.h"
#include "llviewershadermgr.h"
@@ -502,13 +503,13 @@ void init_menus()
gViewerWindow->setMenuBackgroundColor(false,
LLGridManager::getInstance()->isInProductionGrid());
- // Assume L$10 for now, the server will tell us the real cost at login
// *TODO:Also fix cost in llfolderview.cpp for Inventory menus
- const std::string upload_cost("10");
- gMenuHolder->childSetLabelArg("Upload Image", "[COST]", upload_cost);
- gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", upload_cost);
- gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", upload_cost);
- gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", upload_cost);
+ const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost());
+ const std::string sound_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getSoundUploadCost());
+ const std::string animation_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getAnimationUploadCost());
+ gMenuHolder->childSetLabelArg("Upload Image", "[COST]", texture_upload_cost_str);
+ gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", sound_upload_cost_str);
+ gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", animation_upload_cost_str);
gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE);
gDetachSubMenu = gMenuBarView->findChildMenuByName("Detach Object", TRUE);
@@ -8703,18 +8704,31 @@ class LLUploadCostCalculator : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
- std::string menu_name = userdata.asString();
+ std::vector<std::string> fields;
+ std::string str = userdata.asString();
+ boost::split(fields, str, boost::is_any_of(","));
+ if (fields.size()<1)
+ {
+ return false;
+ }
+ std::string menu_name = fields[0];
+ std::string asset_type_str = "texture";
+ if (fields.size()>1)
+ {
+ asset_type_str = fields[1];
+ }
+ LL_DEBUGS("Benefits") << "userdata " << userdata << " menu_name " << menu_name << " asset_type_str " << asset_type_str << LL_ENDL;
+ calculateCost(asset_type_str);
gMenuHolder->childSetLabelArg(menu_name, "[COST]", mCostStr);
return true;
}
- void calculateCost();
+ void calculateCost(const std::string& asset_type_str);
public:
LLUploadCostCalculator()
{
- calculateCost();
}
};
@@ -8740,19 +8754,27 @@ class LLToggleUIHints : public view_listener_t
}
};
-void LLUploadCostCalculator::calculateCost()
+void LLUploadCostCalculator::calculateCost(const std::string& asset_type_str)
{
- S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
+ S32 upload_cost = -1;
- // getPriceUpload() returns -1 if no data available yet.
- if(upload_cost >= 0)
+ if (asset_type_str == "texture")
{
- mCostStr = llformat("%d", upload_cost);
+ upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
}
- else
+ else if (asset_type_str == "animation")
+ {
+ upload_cost = LLAgentBenefitsMgr::current().getAnimationUploadCost();
+ }
+ else if (asset_type_str == "sound")
+ {
+ upload_cost = LLAgentBenefitsMgr::current().getSoundUploadCost();
+ }
+ if (upload_cost < 0)
{
- mCostStr = llformat("%d", gSavedSettings.getU32("DefaultUploadCost"));
+ LL_WARNS() << "Unable to find upload cost for asset_type_str " << asset_type_str << LL_ENDL;
}
+ mCostStr = std::to_string(upload_cost);
}
void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y)
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 07873f482f..d1d3a7fc12 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -30,6 +30,7 @@
// project includes
#include "llagent.h"
+#include "llagentbenefits.h"
#include "llagentcamera.h"
#include "llfilepicker.h"
#include "llfloaterreg.h"
@@ -67,7 +68,6 @@
#include "llviewerassetupload.h"
// linden libraries
-#include "lleconomy.h"
#include "llnotificationsutil.h"
#include "llsdserialize.h"
#include "llsdutil.h"
@@ -85,8 +85,6 @@ class LLFileEnableUpload : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
return true;
-// bool new_value = gStatusBar && LLGlobalEconomy::getInstance() && (gStatusBar->getBalance() >= LLGlobalEconomy::getInstance()->getPriceUpload());
-// return new_value;
}
};
@@ -406,22 +404,18 @@ const void upload_single_file(const std::vector<std::string>& filenames, LLFileP
return;
}
-
-const void upload_bulk(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter type)
+void do_bulk_upload(std::vector<std::string> filenames, const LLSD& notification, const LLSD& response)
{
- // TODO:
- // Check user balance for entire cost
- // Charge user entire cost
- // Loop, uploading
- // If an upload fails, refund the user for that one
- //
- // Also fix single upload to charge first, then refund
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ if (option != 0)
+ {
+ // Cancel upload
+ return;
+ }
- S32 expected_upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
for (std::vector<std::string>::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter)
{
std::string filename = (*in_iter);
- if (!check_file_extension(filename, type)) continue;
std::string name = gDirUtilp->getBaseFileName(filename, true);
std::string asset_name = name;
@@ -430,6 +424,13 @@ const void upload_bulk(const std::vector<std::string>& filenames, LLFilePicker::
LLStringUtil::stripNonprintable(asset_name);
LLStringUtil::trim(asset_name);
+ std::string ext = gDirUtilp->getExtension(filename);
+ LLAssetType::EType asset_type;
+ U32 codec;
+ S32 expected_upload_cost;
+ if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec) &&
+ LLAgentBenefitsMgr::current().findUploadCost(asset_type, expected_upload_cost))
+ {
LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
filename,
asset_name,
@@ -443,6 +444,93 @@ const void upload_bulk(const std::vector<std::string>& filenames, LLFilePicker::
upload_new_resource(uploadInfo);
}
}
+}
+
+bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S32& total_cost, S32& file_count, S32& bvh_count)
+{
+ total_cost = 0;
+ file_count = 0;
+ bvh_count = 0;
+ for (std::vector<std::string>::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter)
+ {
+ std::string filename = (*in_iter);
+ std::string ext = gDirUtilp->getExtension(filename);
+
+ if (ext == "bvh")
+ {
+ bvh_count++;
+ }
+
+ LLAssetType::EType asset_type;
+ U32 codec;
+ S32 cost;
+
+ if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec) &&
+ LLAgentBenefitsMgr::current().findUploadCost(asset_type, cost))
+ {
+ total_cost += cost;
+ file_count++;
+ }
+ }
+
+ return file_count > 0;
+}
+
+const void upload_bulk(const std::vector<std::string>& filenames, LLFilePicker::ELoadFilter type)
+{
+ // TODO:
+ // Check user balance for entire cost
+ // Charge user entire cost
+ // Loop, uploading
+ // If an upload fails, refund the user for that one
+ //
+ // Also fix single upload to charge first, then refund
+
+ // FIXME PREMIUM what about known types that can't be bulk uploaded
+ // (bvh)? These will fail in the item by item upload but won't be
+ // mentioned in the notification.
+ std::vector<std::string> filtered_filenames;
+ for (std::vector<std::string>::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter)
+ {
+ const std::string& filename = *in_iter;
+ if (check_file_extension(filename, type))
+ {
+ filtered_filenames.push_back(filename);
+ }
+ }
+
+ S32 expected_upload_cost;
+ S32 expected_upload_count;
+ S32 bvh_count;
+ if (get_bulk_upload_expected_cost(filtered_filenames, expected_upload_cost, expected_upload_count, bvh_count))
+ {
+ LLSD args;
+ args["COST"] = expected_upload_cost;
+ args["COUNT"] = expected_upload_count;
+ LLNotificationsUtil::add("BulkUploadCostConfirmation", args, LLSD(), boost::bind(do_bulk_upload, filtered_filenames, _1, _2));
+
+ if (filtered_filenames.size() > expected_upload_count)
+ {
+ if (bvh_count == filtered_filenames.size() - expected_upload_count)
+ {
+ LLNotificationsUtil::add("DoNotSupportBulkAnimationUpload");
+ }
+ else
+ {
+ LLNotificationsUtil::add("BulkUploadIncompatibleFiles");
+ }
+ }
+ }
+ else if (bvh_count == filtered_filenames.size())
+ {
+ LLNotificationsUtil::add("DoNotSupportBulkAnimationUpload");
+ }
+ else
+ {
+ LLNotificationsUtil::add("BulkUploadNoCompatibleFiles");
+ }
+
+}
class LLFileUploadImage : public view_listener_t
{
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 318160dfc7..e077626461 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -32,7 +32,6 @@
#include "llaudioengine.h"
#include "llavataractions.h"
#include "llavatarnamecache.h" // IDEVO HACK
-#include "lleconomy.h"
#include "lleventtimer.h"
#include "llfloaterreg.h"
#include "llfolderview.h"
@@ -51,6 +50,7 @@
#include "mean_collision_data.h"
#include "llagent.h"
+#include "llagentbenefits.h"
#include "llagentcamera.h"
#include "llcallingcard.h"
#include "llbuycurrencyhtml.h"
@@ -908,7 +908,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
if(option == 0 && !group_id.isNull())
{
// check for promotion or demotion.
- S32 max_groups = gMaxAgentGroups;
+ S32 max_groups = LLAgentBenefitsMgr::current().getGroupMembershipLimit();
if(gAgent.isInGroup(group_id)) ++max_groups;
if(gAgent.mGroups.size() < max_groups)
@@ -5444,16 +5444,7 @@ void process_frozen_message(LLMessageSystem *msgsystem, void **user_data)
// do some extra stuff once we get our economy data
void process_economy_data(LLMessageSystem *msg, void** /*user_data*/)
{
- LLGlobalEconomy::processEconomyData(msg, LLGlobalEconomy::getInstance());
-
- S32 upload_cost = LLGlobalEconomy::getInstance()->getPriceUpload();
-
- LL_INFOS_ONCE("Messaging") << "EconomyData message arrived; upload cost is L$" << upload_cost << LL_ENDL;
-
- gMenuHolder->getChild<LLUICtrl>("Upload Image")->setLabelArg("[COST]", llformat("%d", upload_cost));
- gMenuHolder->getChild<LLUICtrl>("Upload Sound")->setLabelArg("[COST]", llformat("%d", upload_cost));
- gMenuHolder->getChild<LLUICtrl>("Upload Animation")->setLabelArg("[COST]", llformat("%d", upload_cost));
- gMenuHolder->getChild<LLUICtrl>("Bulk Upload")->setLabelArg("[COST]", llformat("%d", upload_cost));
+ LL_DEBUGS("Benefits") << "Received economy data, not currently used" << LL_ENDL;
}
void notify_cautioned_script_question(const LLSD& notification, const LLSD& response, S32 orig_questions, BOOL granted)
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 9e5c58572a..e67826454b 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -291,6 +291,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
LL_INFOS("AppInit", "Capabilities") << "Requesting seed from " << url
<< " region name " << regionp->getName()
<< " (attempt #" << mSeedCapAttempts + 1 << ")" << LL_ENDL;
+ LL_DEBUGS("AppInit", "Capabilities") << "Capabilities requested: " << capabilityNames << LL_ENDL;
regionp = NULL;
result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);
@@ -2974,6 +2975,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("UploadBakedTexture");
capabilityNames.append("UserInfo");
capabilityNames.append("ViewerAsset");
+ capabilityNames.append("ViewerBenefits");
capabilityNames.append("ViewerMetrics");
capabilityNames.append("ViewerStartAuction");
capabilityNames.append("ViewerStats");
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index d32881e737..7579eb1a90 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -38,6 +38,7 @@
#include "raytrace.h"
#include "llagent.h" // Get state values from here
+#include "llagentbenefits.h"
#include "llagentcamera.h"
#include "llagentwearables.h"
#include "llanimationstates.h"
@@ -7063,20 +7064,7 @@ U32 LLVOAvatar::getNumAttachments() const
//-----------------------------------------------------------------------------
S32 LLVOAvatar::getMaxAttachments() const
{
- const S32 MAX_AGENT_ATTACHMENTS = 38;
-
- S32 max_attach = MAX_AGENT_ATTACHMENTS;
-
- if (gAgent.getRegion())
- {
- LLSD features;
- gAgent.getRegion()->getSimulatorFeatures(features);
- if (features.has("MaxAgentAttachments"))
- {
- max_attach = features["MaxAgentAttachments"].asInteger();
- }
- }
- return max_attach;
+ return LLAgentBenefitsMgr::current().getAttachmentLimit();
}
//-----------------------------------------------------------------------------
@@ -7110,24 +7098,7 @@ U32 LLVOAvatar::getNumAnimatedObjectAttachments() const
//-----------------------------------------------------------------------------
S32 LLVOAvatar::getMaxAnimatedObjectAttachments() const
{
- S32 max_attach = 0;
- if (gSavedSettings.getBOOL("AnimatedObjectsIgnoreLimits"))
- {
- max_attach = getMaxAttachments();
- }
- else
- {
- if (gAgent.getRegion())
- {
- LLSD features;
- gAgent.getRegion()->getSimulatorFeatures(features);
- if (features.has("AnimatedObjects"))
- {
- max_attach = features["AnimatedObjects"]["MaxAgentAnimatedObjectAttachments"].asInteger();
- }
- }
- }
- return max_attach;
+ return LLAgentBenefitsMgr::current().getAnimatedObjectLimit();
}
//-----------------------------------------------------------------------------
diff --git a/indra/newview/skins/default/xui/de/floater_about_land.xml b/indra/newview/skins/default/xui/de/floater_about_land.xml
index 8fb953d3ab..8f55b3297f 100644
--- a/indra/newview/skins/default/xui/de/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/de/floater_about_land.xml
@@ -370,8 +370,8 @@ Nur große Parzellen können in der Suche aufgeführt werden.
<text name="landing_point">
Landepunkt: [LANDING]
</text>
- <button label="Festlegen" label_selected="Festlegen" left="234" name="Set" right="-88" tool_tip="Legt Ihren Standort als Landepunkt fest, an dem Besucher ankommen. Legt die Position Ihres Avatars innerhalb dieser Parzelle fest." width="70"/>
- <button label="Löschen" label_selected="Löschen" left="312" name="Clear" tool_tip="Landepunkt löschen" width="70"/>
+ <button label="Festlegen" label_selected="Festlegen" name="Set" tool_tip="Legt Ihren Standort als Landepunkt fest, an dem Besucher ankommen. Legt die Position Ihres Avatars innerhalb dieser Parzelle fest." width="70"/>
+ <button label="Löschen" label_selected="Löschen" name="Clear" tool_tip="Landepunkt löschen" width="70"/>
<text name="Teleport Routing: ">
Teleport-Route:
</text>
diff --git a/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml
index b5538a511c..c4ffba33fd 100644
--- a/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
legacy_header_height="18"
- height="190"
+ height="180"
layout="topleft"
name="Anim Preview"
help_topic="animation_anim_preview"
@@ -60,9 +60,9 @@
height="22"
label="Upload (L$[AMOUNT])"
layout="topleft"
- left="45"
+ left="35"
name="ok_btn"
- top_pad="60"
+ top_pad="15"
width="150" />
<button
follows="right|bottom"
@@ -73,4 +73,17 @@
name="cancel_btn"
left_pad="5"
width="90" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="35"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ skip_link_underline="true"
+ name="info_text"
+ word_wrap="true"
+ top_pad="10"
+ width="270"/>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml
index cb6b2f6ebc..0c62bfe304 100644
--- a/indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml
@@ -2,7 +2,7 @@
<floater
legacy_header_height="18"
can_minimize="false"
- height="610"
+ height="645"
layout="topleft"
name="Animation Preview"
help_topic="animation_preview"
@@ -570,4 +570,17 @@ We recommend BVH files exported from Poser 4.
name="cancel_btn"
left="142"
width="128" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="35"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ skip_link_underline="true"
+ name="info_text"
+ word_wrap="true"
+ top_pad="10"
+ width="270"/>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_image_preview.xml b/indra/newview/skins/default/xui/en/floater_image_preview.xml
index 44d2c14cc8..3daff1a132 100644
--- a/indra/newview/skins/default/xui/en/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_image_preview.xml
@@ -2,7 +2,7 @@
<floater
legacy_header_height="18"
can_minimize="false"
- height="460"
+ height="495"
layout="topleft"
name="Image Preview"
help_topic="image_preview"
@@ -148,4 +148,17 @@ Try saving image as 24 bit Targa (.tga).
name="ok_btn"
top_delta="0"
width="125" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="35"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ skip_link_underline="true"
+ name="info_text"
+ word_wrap="true"
+ top_pad="10"
+ width="270"/>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_people.xml b/indra/newview/skins/default/xui/en/floater_people.xml
index 701233ba4a..0cc0ca1ce4 100644
--- a/indra/newview/skins/default/xui/en/floater_people.xml
+++ b/indra/newview/skins/default/xui/en/floater_people.xml
@@ -31,5 +31,11 @@
filename="panel_group_info_sidetray.xml"
label="Group Profile"
font="SansSerifBold"/>
+ <panel
+ class="panel_group_creation_sidetray"
+ name="panel_group_creation_sidetray"
+ filename="panel_group_creation_sidetray.xml"
+ label="Create Group"
+ font="SansSerifBold"/>
</panel_container>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_sound_preview.xml b/indra/newview/skins/default/xui/en/floater_sound_preview.xml
index af791466b6..3889b975a9 100644
--- a/indra/newview/skins/default/xui/en/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_sound_preview.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
legacy_header_height="18"
- height="190"
+ height="180"
layout="topleft"
name="Sound Preview"
help_topic="sound_preview"
@@ -60,9 +60,9 @@
height="22"
label="Upload (L$[AMOUNT])"
layout="topleft"
- left="45"
+ left="35"
name="ok_btn"
- top_pad="60"
+ top_pad="15"
width="150" />
<button
follows="right|bottom"
@@ -73,4 +73,17 @@
name="cancel_btn"
left_pad="5"
width="90" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="35"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ skip_link_underline="true"
+ name="info_text"
+ word_wrap="true"
+ top_pad="10"
+ width="270"/>
</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml
index 1b08767edc..99ca910062 100755
--- a/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml
+++ b/indra/newview/skins/default/xui/en/menu_gallery_outfit_tab.xml
@@ -42,7 +42,7 @@
parameter="take_off" />
</menu_item_call>
<menu_item_call
- label="Upload Photo (L$10)"
+ label="Upload Photo (L$[UPLOAD_COST])"
layout="topleft"
name="upload_photo">
<on_click
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
index 331e64984b..3385a29a6c 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
@@ -56,7 +56,7 @@
function="File.VisibleUploadModel"/>
</menu_item_call>
<menu_item_call
- label="Bulk (L$[COST] per file)..."
+ label="Bulk..."
layout="topleft"
name="Bulk Upload">
<menu_item_call.on_click
@@ -194,7 +194,7 @@
function="Inventory.DoCreate"
parameter="tattoo" />
</menu_item_call>
- <menu_item_call
+ <menu_item_call
label="New Universal"
layout="topleft"
name="New Universal">
diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
index 61cb74f230..32d9d28434 100644
--- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml
@@ -40,7 +40,7 @@
parameter="take_off" />
</menu_item_call>
<menu_item_call
- label="Upload Photo (L$10)"
+ label="Upload Photo (L$[UPLOAD_COST])"
layout="topleft"
name="upload_photo">
<on_click
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 59e098f07e..e228c5bdba 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1286,7 +1286,7 @@ function="World.EnvPreset"
function="File.EnableUpload" />
<menu_item_call.on_visible
function="Upload.CalculateCosts"
- parameter="Upload Image" />
+ parameter="Upload Image,texture" />
</menu_item_call>
<menu_item_call
label="Sound (L$[COST])..."
@@ -1299,7 +1299,7 @@ function="World.EnvPreset"
function="File.EnableUpload" />
<menu_item_call.on_visible
function="Upload.CalculateCosts"
- parameter="Upload Sound" />
+ parameter="Upload Sound,sound" />
</menu_item_call>
<menu_item_call
label="Animation (L$[COST])..."
@@ -1312,7 +1312,7 @@ function="World.EnvPreset"
function="File.EnableUpload" />
<menu_item_call.on_visible
function="Upload.CalculateCosts"
- parameter="Upload Animation" />
+ parameter="Upload Animation,animation" />
</menu_item_call>
<menu_item_call
label="Model..."
@@ -1327,9 +1327,12 @@ function="World.EnvPreset"
function="File.VisibleUploadModel"/>
</menu_item_call>
<menu_item_call
- label="Bulk (L$[COST] per file)..."
+ label="Bulk..."
layout="topleft"
name="Bulk Upload">
+ <menu_item_call.on_visible
+ function="Upload.CalculateCosts"
+ parameter="Bulk Upload,texture" />
<menu_item_call.on_click
function="File.UploadBulk"
parameter="" />
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index a10152d81e..61a23851ed 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -686,6 +686,18 @@ Do you want to revoke modify rights for the selected Residents?
<notification
icon="alertmodal.tga"
+ name="GroupNameLengthWarning"
+ type="alertmodal">
+A group name must be between [MIN_LEN] and [MAX_LEN] characters.
+ <tag>group</tag>
+ <tag>fail</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="UnableToCreateGroup"
type="alertmodal">
Unable to create group.
@@ -920,7 +932,7 @@ You do not have enough L$ to join this group.
icon="alertmodal.tga"
name="CreateGroupCost"
type="alertmodal">
-Creating this group will cost L$100.
+Creating this group will cost L$[COST].
Groups need more than one member, or they are deleted forever.
Please invite members within 48 hours.
<tag>group</tag>
@@ -929,7 +941,7 @@ Please invite members within 48 hours.
canceltext="Cancel"
name="okcancelbuttons"
notext="Cancel"
- yestext="Create group for L$100"/>
+ yestext="Create group for L$[COST]"/>
</notification>
<notification
@@ -1291,6 +1303,14 @@ Error encoding snapshot.
<notification
icon="alertmodal.tga"
+ name="ErrorCannotAffordUpload"
+ type="alertmodal">
+ You need L$[COST] to upload this item.
+ <tag>fail</tag>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="ErrorTextureCannotAfford"
type="alertmodal">
You need L$[COST] to save a texture to your inventory. You may either buy L$ or save the photo to your computer instead.
@@ -4358,11 +4378,21 @@ You have reached your maximum number of groups. Please leave some group before j
icon="alert.tga"
name="GroupLimitInfo"
type="alert">
-The group limit for base accounts is [MAX_BASIC], and for [https://secondlife.com/premium/ premium]
-accounts is [MAX_PREMIUM].
-If you downgraded your account, you will need to get below [MAX_BASIC] group limit before you can join more.
+Residents with Basic memberships may join up to [MAX_BASIC] groups.
+Premium memberships allow up to [MAX_PREMIUM]. [https://secondlife.com/my/account/membership.php? Learn more or upgrade]
+ <tag>group</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="Close"/>
+ </notification>
-[https://secondlife.com/my/account/membership.php Upgrade today!]
+ <notification
+ icon="alert.tga"
+ name="GroupLimitInfoPlus"
+ type="alert">
+Residents with Basic memberships may join up to [MAX_BASIC] groups.
+Premium memberships allow up to [MAX_PREMIUM]. Premium Plus
+memberships allow up to [MAX_PREMIUM_PLUS]. [https://secondlife.com/my/account/membership.php? Learn more or upgrade]
<tag>group</tag>
<usetemplate
name="okbutton"
@@ -8550,9 +8580,50 @@ Your voice has been muted by moderator.
name="okbutton"
yestext="OK"/>
</notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="FailedToGetBenefits"
+ type="alertmodal">
+ Unfortunately, we were unable to get benefits information for this session. This should not happen in a normal production environment. Please contact support. This session will not work normally and we recommend that you restart.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BulkUploadCostConfirmation"
+ type="alertmodal">
+This will upload [COUNT] items at a total cost of L$[COST]. Do you wish to continue with the upload?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Upload"/>
+ </notification>
<notification
icon="alertmodal.tga"
+ name="BulkUploadNoCompatibleFiles"
+ type="alertmodal">
+Selected files can not be bulk-uploaded.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="BulkUploadIncompatibleFiles"
+ type="alertmodal">
+Some of the selected files can not be bulk-uploaded.
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="UploadCostConfirmation"
type="alertmodal">
This upload will cost L$[PRICE], do you wish to continue with the upload?
diff --git a/indra/newview/skins/default/xui/en/panel_group_creation_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_creation_sidetray.xml
new file mode 100644
index 0000000000..c0265c2fa2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_group_creation_sidetray.xml
@@ -0,0 +1,314 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+background_visible="true"
+ follows="all"
+ height="570"
+ label="Group Creation"
+ layout="topleft"
+ min_height="350"
+ left="0"
+ top="20"
+ name="GroupCreation"
+ width="313">
+ <panel.string
+ name="current_membership">
+(your membership)
+ </panel.string>
+ <panel
+ name="group_info_top"
+ follows="top|left"
+ top="0"
+ left="0"
+ height="29"
+ width="313"
+ layout="topleft">
+ <line_editor
+ follows="left|top"
+ font="SansSerif"
+ label="Type your new group name here"
+ layout="topleft"
+ max_length_bytes="35"
+ name="group_name_editor"
+ left="12"
+ top="5"
+ width="270"
+ height="20"
+ visible="true" />
+ </panel>
+ <layout_stack
+ name="layout"
+ orientation="vertical"
+ follows="all"
+ left="8"
+ top_pad="0"
+ height="538"
+ width="300"
+ border_size="0">
+ <layout_panel
+ bg_alpha_color="DkGray2"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true"
+ name="group_info"
+ follows="all"
+ layout="topleft"
+ auto_resize="false"
+ user_resize="false"
+ height="206"
+ width="313">
+ <panel
+ name="group_info_top"
+ follows="top|left|right"
+ top="0"
+ left="0"
+ height="99"
+ width="312"
+ layout="topleft">
+ <texture_picker
+ default_image_name="Generic_Group_Large"
+ follows="left|top"
+ name="insignia"
+ label=""
+ no_commit_on_selection="true"
+ tool_tip="Click to choose a picture"
+ layout="topleft"
+ height="110"
+ left="5"
+ top="5"
+ width="100" />
+ <text_editor
+ follows="left|top|right"
+ layout="topleft"
+ type="string"
+ name="charter"
+ left_pad="3"
+ height="86"
+ max_length="511"
+ top="6"
+ right="-4"
+ bg_readonly_color="DkGray2"
+ text_readonly_color="White"
+ word_wrap="true">
+ Group Charter
+ </text_editor>
+ </panel>
+ <panel
+ layout="topleft"
+ follows="left|top|right"
+ background_visible="false"
+ bevel_style="none"
+ border="false"
+ bg_alpha_color="FloaterUnfocusBorderColor"
+ height="100"
+ width="313"
+ left="0"
+ name="preferences_container"
+ top_pad="5">
+ <check_box
+ follows="right|top|left"
+ layout="topleft"
+ label="Anyone can join"
+ height="16"
+ left="10"
+ name="open_enrollement"
+ tool_tip="Sets whether this group allows new members to join without being invited."
+ width="90" />
+ <check_box
+ label="Cost to join"
+ layout="topleft"
+ name="check_enrollment_fee"
+ tool_tip="Sets whether to require an enrollment fee to join the group"
+ top_pad="5"
+ left_delta="0"
+ height="16"
+ width="300" />
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ halign="left"
+ increment="1"
+ label_width="15"
+ label="L$"
+ layout="topleft"
+ max_val="99999"
+ height="23"
+ left="30"
+ name="spin_enrollment_fee"
+ tool_tip="New members must pay this fee to join the group when Enrollment Fee is checked."
+ width="170" />
+ <combo_box
+ follows="left|top"
+ layout="topleft"
+ name="group_mature_check"
+ tool_tip="Maturity ratings designate the type of content and behavior allowed in a group"
+ height="23"
+ left="10"
+ top_pad="4"
+ width="190">
+ <combo_item name="select_mature" value="Select">
+ - Select maturity rating -
+ </combo_item>
+ <combo_box.item
+ label="Moderate Content"
+ name="mature"
+ value="Mature" />
+ <combo_box.item
+ label="General Content"
+ name="pg"
+ value="Not Mature" />
+ </combo_box>
+ </panel>
+ </layout_panel>
+ <layout_panel
+ background_visible="false"
+ background_opaque="true"
+ name="create_info"
+ follows="all"
+ layout="topleft"
+ auto_resize="false"
+ user_resize="false"
+ height="200"
+ width="313">
+ <text
+ font="SansSerifSmall"
+ follows="top|left|right"
+ layout="topleft"
+ mouse_opaque="false"
+ type="string"
+ name="fee_information"
+ skip_link_underline="true"
+ height="26"
+ left="8"
+ right="-8"
+ top="5"
+ word_wrap="true">
+ The fee to create a group is based on your membership level. [https://secondlife.com/my/account/membership.php More info]
+ </text>
+ <scroll_list
+ draw_border="false"
+ background_visible="false"
+ follows="left|top|bottom|right"
+ layout="topleft"
+ multi_select="true"
+ name="membership_list"
+ row_padding="4"
+ enabled="false"
+ height="150"
+ left="2"
+ top_pad="8"
+ width="290">
+ <scroll_list.columns
+ dynamic_width="false"
+ name="clmn_name"
+ width="220"/>
+ <scroll_list.columns
+ dynamic_width="true"
+ name="clmn_price"/>
+ <scroll_list.rows
+ name="basic"
+ value="Basic (placeholder)"/>
+ <scroll_list.rows
+ name="plc2"
+ value="" />
+ <scroll_list.rows
+ name="premium"
+ value="Premium (placeholder)" />
+ </scroll_list>
+ </layout_panel>
+ <layout_panel
+ background_visible="false"
+ background_opaque="true"
+ name="create_actions"
+ follows="all"
+ layout="topleft"
+ auto_resize="true"
+ user_resize="true"
+ height="200"
+ width="313">
+ </layout_panel>
+ <layout_panel
+ background_visible="false"
+ background_opaque="true"
+ name="create_actions"
+ follows="all"
+ layout="topleft"
+ auto_resize="false"
+ user_resize="false"
+ height="75"
+ width="313">
+
+ <layout_stack
+ follows="bottom|left|right"
+ layout="topleft"
+ name="button_row_ls"
+ left="1"
+ right="-1"
+ orientation="horizontal"
+ height="25"
+ top="1">
+ <layout_panel
+ follows="bottom|left|right"
+ layout="bottomleft"
+ name="layout_crt"
+ auto_resize="true"
+ height="23"
+ width="91">
+ <!-- placeholder to autoadjust buttons (since they are of different sizes)-->
+ </layout_panel>
+ <layout_panel
+ follows="bottom|left|right"
+ layout="bottomleft"
+ name="layout_crt"
+ auto_resize="false"
+ height="23"
+ width="245">
+ <button
+ follows="bottom|left|right"
+ layout="topleft"
+ label="Create group for L$ [COST]"
+ name="btn_create"
+ visible="true"
+ tool_tip="Create a new Group"
+ height="23"
+ left="1"
+ top="0"
+ width="160" />
+ <button
+ follows="bottom|left|right"
+ name="back"
+ label="Cancel"
+ layout="topleft"
+ tool_tip="Return to list of groups"
+ left_pad="13"
+ height="23"
+ top="0"
+ width="70" />
+ </layout_panel>
+ <layout_panel
+ follows="bottom|left|right"
+ layout="bottomleft"
+ name="layout_crt"
+ auto_resize="true"
+ height="23"
+ width="91">
+ <!-- placeholder to autoadjust buttons-->
+ </layout_panel>
+ </layout_stack>
+ <text
+ font="SansSerifSmall"
+ follows="top|left|right"
+ layout="topleft"
+ mouse_opaque="false"
+ type="string"
+ height="26"
+ left="6"
+ right="-6"
+ name="info_deletion"
+ top_pad="8"
+ word_wrap="true"
+ halign="center">
+ Note: After 7 days, a group with no members (other than the creator) is deleted
+ </text>
+ </layout_panel>
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
index 95312edfb9..05de249d22 100644
--- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
@@ -280,17 +280,6 @@ background_visible="true"
left="1"
top="0"
width="90" />
- <button
- follows="bottom|left|right"
- height="23"
- layout="topleft"
- left="1"
- top="0"
- label="Create Group"
- name="btn_create"
- visible="true"
- tool_tip="Create a new Group"
- width="90" />
</layout_panel>
</layout_stack>
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml
index 800faabc2a..441cf97e87 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_snapshot_inventory.xml
@@ -41,7 +41,7 @@
<text
follows="top|left"
font="SansSerif"
- height="56"
+ height="126"
layout="topleft"
left="10"
length="1"
@@ -50,7 +50,9 @@
width="200"
type="string"
word_wrap="true">
- Uploading an image to your inventory costs L$[UPLOAD_COST].
+Uploading an image to your inventory costs L$[UPLOAD_COST].
+
+Fee is based on your subscription level. Higher levels are charged lower fees.
</text>
<button
follows="right|bottom"
@@ -67,7 +69,7 @@
<button
follows="left|bottom"
height="23"
- label="UPLOAD L$10"
+ label="UPLOAD L$[UPLOAD_COST]"
layout="topleft"
left="10"
name="save_btn"
@@ -76,4 +78,4 @@
<button.commit_callback
function="Inventory.SaveOutfitPhoto" />
</button>
-</panel> \ No newline at end of file
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index a47121ae99..c4248d9b92 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -55,7 +55,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
value="[REGION](Double-click to teleport, shift-drag to pan)"/>
<string
name="GroupCountWithInfo"
- value="You belong to [COUNT] groups, and can join [REMAINING] more. [secondlife:/// Want more?]"/>
+ value="You belong to [COUNT] groups, and can join [REMAINING] more. [secondlife:/// Raise your limit]"/>
<tab_container
bottom="-10"
follows="all"
@@ -493,6 +493,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M
top_pad="4"
left="3"
use_ellipses="true"
+ skip_link_underline="true"
name="groupcount">
You belong to [COUNT] groups, and can join [REMAINING] more.
</text>
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
index d019a0a310..8cc27d9eef 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
@@ -118,7 +118,7 @@
width="200"
type="string"
word_wrap="true">
- Saving an image to your inventory costs L$[UPLOAD_COST]. To save your image as a texture select one of the square formats.
+ To save your image as a texture select one of the square formats.
</text>
<button
follows="right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
index 2fe4cf8183..8fc5cd7e63 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
@@ -73,4 +73,18 @@
<button.commit_callback
function="Snapshot.SaveToEmail" />
</button>
+ <text
+ follows="top|left"
+ font="SansSerif"
+ height="56"
+ layout="topleft"
+ left="10"
+ length="1"
+ name="fee_hint_lbl"
+ top_pad="7"
+ width="200"
+ type="string"
+ word_wrap="true">
+ Fee is based on your subscription level. Higher levels are charged lower fees.
+ </text>
</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 463147d80d..1bfac6aeb7 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2369,6 +2369,8 @@ If you continue to receive this message, please contact Second Life support for
<string name="MarketplaceNoStock">out of stock</string>
<string name="MarketplaceUpdating">updating...</string>
+ <string name="UploadFeeInfo">Fee is based on your subscription level. Higher levels are charged lower fees. [https://secondlife.com/my/account/membership.php? Learn more]</string>
+
<string name="Open landmarks">Open landmarks</string>
<string name="Unconstrained">Unconstrained</string>
@@ -3946,6 +3948,12 @@ Please check http://status.secondlifegrid.net to see if there is a known problem
<string name="Accounting">Accounting</string>
<string name="Notices">Notices</string>
<string name="Chat">Chat</string>
+
+ <!-- SL Membership -->
+ <string name="BaseMembership">Base</string>
+ <string name="PremiumMembership">Premium</string>
+ <string name="Premium PlusMembership">Premium Plus</string>
+ <string name="InternalMembership">Internal</string> <!-- No need to translate -->
<!-- Question strings for delete items notifications -->
<string name="DeleteItems">Delete selected items?</string>
diff --git a/indra/newview/skins/default/xui/it/menu_inventory_add.xml b/indra/newview/skins/default/xui/it/menu_inventory_add.xml
index 83ba78294a..6f9212f56b 100644
--- a/indra/newview/skins/default/xui/it/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/it/menu_inventory_add.xml
@@ -5,7 +5,7 @@
<menu_item_call label="Suono ([COST]L$)..." name="Upload Sound"/>
<menu_item_call label="Animazione ([COST]L$)..." name="Upload Animation"/>
<menu_item_call label="Modella..." name="Upload Model"/>
- <menu_item_call label="In blocco ([COST]L$ per file)..." name="Bulk Upload"/>
+ <menu_item_call label="In blocco..." name="Bulk Upload"/>
</menu>
<menu_item_call label="Nuova cartella" name="New Folder"/>
<menu_item_call label="Nuovo script" name="New Script"/>
diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml
index 2c7ecfa6e7..c7a10df910 100644
--- a/indra/newview/skins/default/xui/it/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/it/menu_viewer.xml
@@ -153,7 +153,7 @@
<menu_item_call label="Suono ([COST] L$)..." name="Upload Sound"/>
<menu_item_call label="Animazione ([COST] L$)..." name="Upload Animation"/>
<menu_item_call label="Modella..." name="Upload Model"/>
- <menu_item_call label="In blocco ([COST] L$ per file)..." name="Bulk Upload"/>
+ <menu_item_call label="In blocco..." name="Bulk Upload"/>
</menu>
<menu_item_call label="Annulla" name="Undo"/>
<menu_item_call label="Ripeti" name="Redo"/>
diff --git a/indra/newview/skins/default/xui/pl/menu_viewer.xml b/indra/newview/skins/default/xui/pl/menu_viewer.xml
index 5190723660..4d03e7c780 100644
--- a/indra/newview/skins/default/xui/pl/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pl/menu_viewer.xml
@@ -156,7 +156,7 @@
<menu_item_call label="Dźwięk ([COST]L$)..." name="Upload Sound" />
<menu_item_call label="Animację ([COST]L$)..." name="Upload Animation" />
<menu_item_call label="Model meszowy..." name="Upload Model" />
- <menu_item_call label="Zbiór wielu plików ([COST]L$ per file)..." name="Bulk Upload" />
+ <menu_item_call label="Zbiór wielu plików..." name="Bulk Upload" />
</menu>
<menu_item_call label="Cofnij" name="Undo" />
<menu_item_call label="Ponów" name="Redo" />
diff --git a/indra/newview/skins/default/xui/pt/menu_inventory_add.xml b/indra/newview/skins/default/xui/pt/menu_inventory_add.xml
index d59b109aa8..0eaf3c7c5f 100644
--- a/indra/newview/skins/default/xui/pt/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/pt/menu_inventory_add.xml
@@ -5,7 +5,7 @@
<menu_item_call label="Som (L$[COST])..." name="Upload Sound"/>
<menu_item_call label="Animação (L$[COST])..." name="Upload Animation"/>
<menu_item_call label="Modelar..." name="Upload Model"/>
- <menu_item_call label="Volume (L$[COST] per file)..." name="Bulk Upload"/>
+ <menu_item_call label="Volume..." name="Bulk Upload"/>
</menu>
<menu_item_call label="Nova pasta" name="New Folder"/>
<menu_item_call label="Novo script" name="New Script"/>