diff options
Diffstat (limited to 'indra/newview')
189 files changed, 3267 insertions, 3319 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7d78ec9e3c..837efee7b1 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -287,9 +287,9 @@ set(viewer_SOURCE_FILES llfloaternotificationsconsole.cpp llfloaternotificationstabbed.cpp llfloateroutfitphotopreview.cpp - llfloateroutfitsnapshot.cpp llfloaterobjectweights.cpp llfloateropenobject.cpp + llfloatersimpleoutfitsnapshot.cpp llfloaterpathfindingcharacters.cpp llfloaterpathfindingconsole.cpp llfloaterpathfindinglinksets.cpp @@ -929,9 +929,9 @@ set(viewer_HEADER_FILES llfloaternotificationsconsole.h llfloaternotificationstabbed.h llfloateroutfitphotopreview.h - llfloateroutfitsnapshot.h llfloaterobjectweights.h llfloateropenobject.h + llfloatersimpleoutfitsnapshot.h llfloaterpathfindingcharacters.h llfloaterpathfindingconsole.h llfloaterpathfindinglinksets.h @@ -1825,9 +1825,9 @@ if (WINDOWS) ${SHARED_LIB_STAGING_DIR}/Release/libcollada14dom22.dll ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libcollada14dom22.dll ${SHARED_LIB_STAGING_DIR}/Debug/libcollada14dom22-d.dll - ${SHARED_LIB_STAGING_DIR}/Release/openjpeg.dll - ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/openjpeg.dll - ${SHARED_LIB_STAGING_DIR}/Debug/openjpegd.dll + ${SHARED_LIB_STAGING_DIR}/Release/openjp2.dll + ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/openjp2.dll + ${SHARED_LIB_STAGING_DIR}/Debug/openjp2.dll ${SHARED_LIB_STAGING_DIR}/Release/libhunspell.dll ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libhunspell.dll ${SHARED_LIB_STAGING_DIR}/Debug/libhunspell.dll diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 4aa5a3a58e..0673dfa857 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.6.8 +6.6.10 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6861153d43..411f77e6a7 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4747,7 +4747,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>https://search.[GRID]/?query_term=[QUERY]&search_type=[TYPE][COLLECTION]&maturity=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]&channel=[CHANNEL]&version=[VERSION]&major=[VERSION_MAJOR]&minor=[VERSION_MINOR]&patch=[VERSION_PATCH]&build=[VERSION_BUILD]</string> + <string>https://search.[GRID]/viewer/?query_term=[QUERY]&search_type=[TYPE][COLLECTION]&maturity=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]&channel=[CHANNEL]&version=[VERSION]&major=[VERSION_MAJOR]&minor=[VERSION_MINOR]&patch=[VERSION_PATCH]&build=[VERSION_BUILD]</string> </map> <key>GuidebookURL</key> <map> @@ -14634,6 +14634,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>MediaSoundsEarLocation</key> + <map> + <key>Comment</key> + <string>Location of the virtual ear for media and sounds</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>0</integer> + </map> <key>VoiceHost</key> <map> <key>Comment</key> @@ -16876,5 +16887,16 @@ <key>Value</key> <string></string> </map> + <key>DebugSettingsHideDefault</key> + <map> + <key>Comment</key> + <string>Show non-default settings only in Debug Settings list</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> </map> </llsd> diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl index b26194f278..b30d7655db 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl @@ -202,7 +202,7 @@ VARYING vec2 vary_texcoord2; uniform float env_intensity; uniform vec4 specular_color; // specular color RGB and specular exponent (glossiness) in alpha -#ifdef HAS_ALPHA_MASK +#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK) uniform float minimum_alpha; #endif @@ -227,12 +227,11 @@ void main() vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy); diffcol.rgb *= vertex_color.rgb; -#ifdef HAS_ALPHA_MASK -#if DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND - if (diffcol.a*vertex_color.a < minimum_alpha) -#else - if (diffcol.a < minimum_alpha) -#endif +#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 (SL-18637) + if (diffcol.a < minimum_alpha-bias) { discard; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl index 331249dc33..de22312d3c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -25,6 +25,17 @@ /*[EXTRA_CODE_HERE]*/ +// Inputs +VARYING vec4 vary_HazeColor; +VARYING float vary_LightNormPosDot; + +uniform sampler2D rainbow_map; +uniform sampler2D halo_map; + +uniform float moisture_level; +uniform float droplet_radius; +uniform float ice_level; + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_data[3]; #else @@ -35,11 +46,34 @@ out vec4 frag_data[3]; // The fragment shader for the sky ///////////////////////////////////////////////////////////////////////// -VARYING vec4 vary_HazeColor; +vec3 rainbow(float d) +{ + // 'Interesting' values of d are -0.75 .. -0.825, i.e. when view vec nearly opposite of sun vec + // Rainbox tex is mapped with REPEAT, so -.75 as tex coord is same as 0.25. -0.825 -> 0.175. etc. + // SL-13629 + // Unfortunately the texture is inverted, so we need to invert the y coord, but keep the 'interesting' + // part within the same 0.175..0.250 range, i.e. d = (1 - d) - 1.575 + d = clamp(-0.575 - d, 0.0, 1.0); + + // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible. + // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate + // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857 + float interior_coord = max(0.0, d - 0.25) * 4.2857; + d = clamp(d, 0.0, 0.25) + interior_coord; + + float rad = (droplet_radius - 5.0f) / 1024.0f; + return pow(texture2D(rainbow_map, vec2(rad+0.5, d)).rgb, vec3(1.8)) * moisture_level; +} + +vec3 halo22(float d) +{ + d = clamp(d, 0.1, 1.0); + float v = sqrt(clamp(1 - (d * d), 0, 1)); + return texture2D(halo_map, vec2(0, v)).rgb * ice_level; +} /// Soft clips the light with a gamma correction vec3 scaleSoftClip(vec3 light); -vec3 srgb_to_linear(vec3 c); void main() { @@ -48,14 +82,18 @@ void main() // the fragment) if the sky wouldn't show up because the clouds // are fully opaque. - vec4 color; - color = vary_HazeColor; + vec4 color = vary_HazeColor; + float rel_pos_lightnorm = vary_LightNormPosDot; + float optic_d = rel_pos_lightnorm; + vec3 halo_22 = halo22(optic_d); + color.rgb += rainbow(optic_d); + color.rgb += halo_22; color.rgb *= 2.; color.rgb = scaleSoftClip(color.rgb); - /// Gamma correct for WL (soft clip effect). - frag_data[0] = vec4(color.rgb, 0.0); + // Gamma correct for WL (soft clip effect). + frag_data[0] = vec4(color.rgb, 1.0); frag_data[1] = vec4(0.0,0.0,0.0,0.0); frag_data[2] = vec4(0.0,0.0,0.0,1.0); //1.0 in norm.w masks off fog diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl index 28a1faf24f..6db4690bff 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -33,6 +33,7 @@ ATTRIBUTE vec3 position; // Output parameters VARYING vec4 vary_HazeColor; +VARYING float vary_LightNormPosDot; // Inputs uniform vec3 camPosLocal; @@ -72,27 +73,29 @@ void main() vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0); // Adj position vector to clamp altitude - if (rel_pos.y > 0) + if (rel_pos.y > 0.) { rel_pos *= (max_y / rel_pos.y); } - if (rel_pos.y < 0) + if (rel_pos.y < 0.) { rel_pos *= (-32000. / rel_pos.y); } - // Can normalize then - vec3 rel_pos_norm = normalize(rel_pos); + // Normalized + vec3 rel_pos_norm = normalize(rel_pos); + float rel_pos_len = length(rel_pos); - float rel_pos_len = length(rel_pos); + // Grab this value and pass to frag shader for rainbows + float rel_pos_lightnorm_dot = dot(rel_pos_norm, lightnorm.xyz); + vary_LightNormPosDot = rel_pos_lightnorm_dot; // Initialize temp variables vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color; - vec4 light_atten; // Sunlight attenuation effect (hue and brightness) due to atmosphere // this is used later for sunlight modulation at various altitudes - light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); + vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); // Calculate relative weights vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density)); @@ -112,7 +115,7 @@ void main() combined_haze = exp(-combined_haze * density_dist); // Compute haze glow - float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz); + float haze_glow = 1.0 - rel_pos_lightnorm_dot; // haze_glow is 0 at the sun and increases away from sun haze_glow = max(haze_glow, .001); // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) @@ -123,30 +126,30 @@ void main() // Add "minimum anti-solar illumination" // For sun, add to glow. For moon, remove glow entirely. SL-13768 - haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25); + haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25)); - vec4 color = - (blue_horizon * blue_weight * (sunlight + ambient_color) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color)); + // Haze color above cloud + vec4 color = (blue_horizon * blue_weight * (sunlight + ambient_color) + + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color)); // Final atmosphere additive color *= (1. - combined_haze); // Increase ambient when there are more clouds - vec4 tmpAmbient = ambient_color; - tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; + vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; // Dim sunlight by cloud shadow percentage sunlight *= max(0.0, (1. - cloud_shadow)); // Haze color below cloud - vec4 additiveColorBelowCloud = - (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient)); + vec4 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient) + + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient)); // Attenuate cloud color by atmosphere combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds // At horizon, blend high altitude sky color towards the darker color below the clouds - color += (additiveColorBelowCloud - color) * (1. - sqrt(combined_haze)); + color += (add_below_cloud - color) * (1. - sqrt(combined_haze)); // Haze color above cloud vary_HazeColor = color; diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl deleted file mode 100644 index 6841a8194f..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl +++ /dev/null @@ -1,199 +0,0 @@ -/** - * @file class2/deferred/skyF.glsl - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2005, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 modelview_projection_matrix; - -// SKY //////////////////////////////////////////////////////////////////////// -// The vertex shader for creating the atmospheric sky -/////////////////////////////////////////////////////////////////////////////// - -// Inputs -uniform vec3 camPosLocal; - -uniform vec4 lightnorm; -uniform vec4 sunlight_color; -uniform vec4 moonlight_color; -uniform int sun_up_factor; -uniform vec4 ambient_color; -uniform vec4 blue_horizon; -uniform vec4 blue_density; -uniform float haze_horizon; -uniform float haze_density; - -uniform float cloud_shadow; -uniform float density_multiplier; -uniform float distance_multiplier; -uniform float max_y; - -uniform vec4 glow; -uniform float sun_moon_glow_factor; - -uniform vec4 cloud_color; - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_data[3]; -#else -#define frag_data gl_FragData -#endif - -VARYING vec3 pos; - -///////////////////////////////////////////////////////////////////////// -// The fragment shader for the sky -///////////////////////////////////////////////////////////////////////// - -uniform sampler2D rainbow_map; -uniform sampler2D halo_map; - -uniform float moisture_level; -uniform float droplet_radius; -uniform float ice_level; - -vec3 rainbow(float d) -{ - // d is the dot product of view and sun directions, so ranging -1.0..1.0 - // 'interesting' values of d are the range -0.75..-0.825, when view is nearly opposite of sun vec - // Rainbox texture mode is GL_REPEAT, so tc of -.75 is equiv to 0.25, -0.825 equiv to 0.175. - - // SL-13629 Rainbow texture has colors within the correct .175...250 range, but order is inverted. - // Rather than replace the texture, we mirror and translate the y tc to keep the colors within the - // interesting range, but in reversed order: i.e. d = (1 - d) - 1.575 - d = clamp(-0.575 - d, 0.0, 1.0); - - // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible. - // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate - // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857 - float interior_coord = max(0.0, d - 0.25) * 4.2857; - d = clamp(d, 0.0, 0.25) + interior_coord; - - float rad = (droplet_radius - 5.0f) / 1024.0f; - return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level; -} - -vec3 halo22(float d) -{ - d = clamp(d, 0.1, 1.0); - float v = sqrt(clamp(1 - (d * d), 0, 1)); - return texture2D(halo_map, vec2(0, v)).rgb * ice_level; -} - -/// Soft clips the light with a gamma correction -vec3 scaleSoftClip(vec3 light); - -void main() -{ - // World / view / projection - // Get relative position (offset why?) - vec3 rel_pos = pos.xyz - camPosLocal.xyz + vec3(0, 50, 0); - - // Adj position vector to clamp altitude - if (rel_pos.y > 0.) - { - rel_pos *= (max_y / rel_pos.y); - } - if (rel_pos.y < 0.) - { - rel_pos *= (-32000. / rel_pos.y); - } - - // Normalized - vec3 rel_pos_norm = normalize(rel_pos); - float rel_pos_len = length(rel_pos); - - // Initialize temp variables - vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color; - - // Sunlight attenuation effect (hue and brightness) due to atmosphere - // this is used later for sunlight modulation at various altitudes - vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); - - // Calculate relative weights - vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density)); - vec4 blue_weight = blue_density / combined_haze; - vec4 haze_weight = haze_density / combined_haze; - - // Compute sunlight from rel_pos & lightnorm (for long rays like sky) - float off_axis = 1.0 / max(1e-6, max(0, rel_pos_norm.y) + lightnorm.y); - sunlight *= exp(-light_atten * off_axis); - - // Distance - float density_dist = rel_pos_len * density_multiplier; - - // Transparency (-> combined_haze) - // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati - // compiler gets confused. - combined_haze = exp(-combined_haze * density_dist); - - // Compute haze glow - float haze_glow = dot(rel_pos_norm, lightnorm.xyz); - haze_glow = 1. - haze_glow; - // haze_glow is 0 at the sun and increases away from sun - haze_glow = max(haze_glow, .001); - // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) - haze_glow *= glow.x; - // Higher glow.x gives dimmer glow (because next step is 1 / "angle") - haze_glow = pow(haze_glow, glow.z); - // glow.z should be negative, so we're doing a sort of (1 / "angle") function - - // Add "minimum anti-solar illumination" - // For sun, add to glow. For moon, remove glow entirely. SL-13768 - haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25)); - - // Haze color above cloud - vec4 color = blue_horizon * blue_weight * (sunlight + ambient_color) - + haze_horizon * haze_weight * (sunlight * haze_glow + ambient_color); - - // Final atmosphere additive - color *= (1. - combined_haze); - - // Increase ambient when there are more clouds - // TODO 9/20: DJH what does this do? max(0,(1-ambient)) will change the color - vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; - - // Dim sunlight by cloud shadow percentage - sunlight *= max(0.0, (1. - cloud_shadow)); - - // Haze color below cloud - vec4 add_below_cloud = blue_horizon * blue_weight * (sunlight + ambient) - + haze_horizon * haze_weight * (sunlight * haze_glow + ambient); - - // Attenuate cloud color by atmosphere - combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds - - // At horizon, blend high altitude sky color towards the darker color below the clouds - color += (add_below_cloud - color) * (1. - sqrt(combined_haze)); - - float optic_d = dot(rel_pos_norm, lightnorm.xyz); - vec3 halo_22 = halo22(optic_d); - color.rgb += rainbow(optic_d); - color.rgb += halo_22; - color.rgb *= 2.; - color.rgb = scaleSoftClip(color.rgb); - - // Gamma correct for WL (soft clip effect). - frag_data[0] = vec4(color.rgb, 1.0); - frag_data[1] = vec4(0.0, 0.0, 0.0, 0.0); - frag_data[2] = vec4(0.0, 0.0, 0.0, 1.0); // 1.0 in norm.w masks off fog -} diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl deleted file mode 100644 index bcf775577a..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file WLSkyV.glsl - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2005, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; - -// SKY //////////////////////////////////////////////////////////////////////// -// The vertex shader for creating the atmospheric sky -/////////////////////////////////////////////////////////////////////////////// - -VARYING vec3 pos; - -void main() -{ - - // World / view / projection - pos = position.xyz; - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); -} diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 1ccde98283..93dd5e7e70 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -33,7 +33,6 @@ RenderAvatarLODFactor 1 1.0 RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarMaxNonImpostors 1 16 RenderAvatarMaxComplexity 1 350000 -RenderAvatarVP 1 1 RenderAutoMuteSurfaceAreaLimit 1 1000.0 RenderCubeMap 1 1 RenderDelayVBUpdate 1 0 diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index 5542eee6ca..66197e6484 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -33,7 +33,6 @@ RenderAvatarLODFactor 1 1.0 RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarMaxNonImpostors 1 16 RenderAvatarMaxComplexity 1 350000 -RenderAvatarVP 1 1 RenderAutoMuteSurfaceAreaLimit 1 1000.0 RenderCubeMap 1 1 RenderDelayVBUpdate 1 0 @@ -80,7 +79,6 @@ RenderAvatarLODFactor 1 0 RenderAvatarPhysicsLODFactor 1 0 RenderAvatarMaxNonImpostors 1 3 RenderAvatarMaxComplexity 1 25000 -RenderAvatarVP 1 0 RenderFarClip 1 64 RenderFlexTimeFactor 1 0 RenderGlowResolutionPow 1 8 @@ -111,7 +109,6 @@ RenderAvatarLODFactor 1 0 RenderAvatarPhysicsLODFactor 1 0 RenderAvatarMaxNonImpostors 1 3 RenderAvatarMaxComplexity 1 35000 -RenderAvatarVP 1 0 RenderFarClip 1 64 RenderFlexTimeFactor 1 0 RenderGlowResolutionPow 1 8 @@ -141,7 +138,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0.5 RenderAvatarMaxComplexity 1 100000 RenderAvatarPhysicsLODFactor 1 0.75 -RenderAvatarVP 1 1 RenderFarClip 1 96 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 8 @@ -171,7 +167,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 200000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -201,7 +196,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 250000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -231,7 +225,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 300000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -261,7 +254,6 @@ RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 RenderAvatarMaxComplexity 1 350000 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -290,7 +282,6 @@ RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 RenderAvatarPhysicsLODFactor 1 1.0 -RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 @@ -367,7 +358,6 @@ RenderCompressTextures 1 0 // No Pixel Shaders available // list NoPixelShaders -RenderAvatarVP 0 0 RenderAvatarCloth 0 0 RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 @@ -380,7 +370,6 @@ RenderShadowDetail 0 0 // No Vertex Shaders available // list NoVertexShaders -RenderAvatarVP 0 0 RenderAvatarCloth 0 0 RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 @@ -402,7 +391,6 @@ RenderVBOMappingDisable 1 1 list safe RenderAnisotropic 1 0 RenderAvatarCloth 0 0 -RenderAvatarVP 0 0 RenderAvatarMaxNonImpostors 1 16 RenderAvatarMaxComplexity 1 80000 RenderObjectBump 0 0 @@ -597,7 +585,6 @@ Disregard128DefaultDrawDistance 1 0 // on various ATI chipsets on drivers before 8.2 list ATIOldDriver -RenderAvatarVP 0 0 RenderAvatarCloth 0 0 // Avoid driver crashes with some features on Linux with old ATI drivers UseOcclusion 0 0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index c9efd89cc8..fed035c7fa 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -33,7 +33,6 @@ RenderAvatarLODFactor 1 1.0 RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarMaxNonImpostors 1 16 RenderAvatarMaxComplexity 1 350000 -RenderAvatarVP 1 1 RenderAutoMuteSurfaceAreaLimit 1 1000.0 RenderCubeMap 1 1 RenderDelayVBUpdate 1 0 diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp index e09527a34b..d3f988d715 100644 --- a/indra/newview/llaccountingcostmanager.cpp +++ b/indra/newview/llaccountingcostmanager.cpp @@ -96,11 +96,7 @@ void LLAccountingCostManager::accountingCostCoro(std::string url, LLSD dataToPost = LLSD::emptyMap(); dataToPost[keystr.c_str()] = objectList; - LLAccountingCostObserver* observer = observerHandle.get(); - LLUUID transactionId = observer->getTransactionID(); - observer = NULL; - - + LLAccountingCostObserver* observer = NULL; LLSD results = httpAdapter->postAndSuspend(httpRequest, url, dataToPost); diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 5250369813..9018a5f168 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2912,9 +2912,11 @@ void LLAgent::processMaturityPreferenceFromServer(const LLSD &result, U8 perferr bool LLAgent::requestPostCapability(const std::string &capName, LLSD &postData, httpCallback_t cbSuccess, httpCallback_t cbFailure) { - std::string url; - - url = getRegion()->getCapability(capName); + if (!getRegion()) + { + return false; + } + std::string url = getRegion()->getCapability(capName); if (url.empty()) { diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 5214f4b838..1090888c1c 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -46,6 +46,7 @@ - (void)dealloc { + [currentInputLanguage release]; [super dealloc]; } @@ -199,12 +200,14 @@ - (bool) romanScript { - // How to add support for new languages with the input window: - // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.) - NSArray *nonRomanScript = [[NSArray alloc] initWithObjects:@"ja", @"ko", @"zh-Hant", @"zh-Hans", nil]; - if ([nonRomanScript containsObject:currentInputLanguage]) - { - return false; + @autoreleasepool { + // How to add support for new languages with the input window: + // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.) + NSArray* nonRomanScript = @[@"ja", @"ko", @"zh-Hant", @"zh-Hans"]; + if ([nonRomanScript containsObject:currentInputLanguage]) + { + return false; + } } return true; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 909f32cd21..3c93a9df7e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3987,7 +3987,7 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo // existence of AIS as an indicator the fix is present. Does // not actually use AIS to create the category. inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel); - LLUUID folder_id = gInventory.createNewCategory( + gInventory.createNewCategory( parent_id, LLFolderType::FT_OUTFIT, new_folder_name, diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b31447a72b..dc9f7bb403 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -135,6 +135,10 @@ #include "vlc/libvlc_version.h" #endif // LL_LINUX +#if LL_DARWIN +#include "llwindowmacosx.h" +#endif + // Third party library includes #include <boost/bind.hpp> #include <boost/foreach.hpp> @@ -209,7 +213,7 @@ #include "llcommandlineparser.h" #include "llfloatermemleak.h" #include "llfloaterreg.h" -#include "llfloateroutfitsnapshot.h" +#include "llfloatersimpleoutfitsnapshot.h" #include "llfloatersnapshot.h" #include "llsidepanelinventory.h" #include "llatmosphere.h" @@ -560,6 +564,7 @@ static void settings_to_globals() LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale")); #if LL_DARWIN + LLWindowMacOSX::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL"); gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI"); #endif } @@ -1275,7 +1280,6 @@ bool LLAppViewer::init() //LLSimpleton creations LLEnvironment::createInstance(); - LLEnvironment::getInstance()->initSingleton(); LLWorld::createInstance(); LLSelectMgr::createInstance(); LLViewerCamera::createInstance(); @@ -1521,7 +1525,7 @@ bool LLAppViewer::doFrame() LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df Snapshot" ) pingMainloopTimeout("Main:Snapshot"); LLFloaterSnapshot::update(); // take snapshots - LLFloaterOutfitSnapshot::update(); + LLFloaterSimpleOutfitSnapshot::update(); gGLActive = FALSE; } } @@ -1725,7 +1729,8 @@ bool LLAppViewer::cleanup() { if (!isSecondInstance()) { - LLSceneMonitor::instance().dumpToFile(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv")); + std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv"); + LLSceneMonitor::instance().dumpToFile(dump_path); } LLSceneMonitor::deleteSingleton(); } diff --git a/indra/newview/llaudiosourcevo.cpp b/indra/newview/llaudiosourcevo.cpp index 1846238d93..43abbb57ee 100644 --- a/indra/newview/llaudiosourcevo.cpp +++ b/indra/newview/llaudiosourcevo.cpp @@ -102,7 +102,7 @@ LLVector3d LLAudioSourceVO::getPosGlobal() const bool LLAudioSourceVO::isInCutOffRadius(const LLVector3d pos_global, const F32 cutoff) const { - static LLCachedControl<S32> ear_mode(gSavedSettings, "VoiceEarLocation", 0); + static LLCachedControl<S32> ear_mode(gSavedSettings, "MediaSoundsEarLocation", 0); LLVector3d pos_ear; @@ -113,9 +113,6 @@ bool LLAudioSourceVO::isInCutOffRadius(const LLVector3d pos_global, const F32 cu break; case 1: // avatar - case 2: - // voice support 'mixed' in '2' case with agent's position and camera's rotations - // but it is not defined in settings and uses camera as default pos_ear = gAgent.getPositionGlobal(); break; diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index 275f17b02a..293c9d60a1 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -364,11 +364,10 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi } } -// static // Called every frame - send render weight requests to every region void LLAvatarRenderInfoAccountant::idle() { - if (mRenderInfoScanTimer.hasExpired()) + if (mRenderInfoScanTimer.hasExpired() && !LLApp::isExiting()) { LL_DEBUGS("AvatarRenderInfo") << "Scanning regions for render info updates" << LL_ENDL; diff --git a/indra/newview/llbuycurrencyhtml.cpp b/indra/newview/llbuycurrencyhtml.cpp index 1c69dadb12..7ad06f8eaa 100644 --- a/indra/newview/llbuycurrencyhtml.cpp +++ b/indra/newview/llbuycurrencyhtml.cpp @@ -41,7 +41,7 @@ class LLBuyCurrencyHTMLHandler : { public: // requests will be throttled from a non-trusted browser - LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_ALLOW ) {} + LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_THROTTLE) {} bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 1ad2157df0..df79043b00 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -650,8 +650,7 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg) { if(mBuddyInfo.find(agent_id) != mBuddyInfo.end()) { - if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS) - && !gAgent.isDoNotDisturb()) + if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)) { LLSD args; args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString(); @@ -719,11 +718,12 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online) // we were tracking someone who went offline deleteTrackingData(); } - } - if(chat_notify) - { - // Look up the name of this agent for the notification - LLAvatarNameCache::get(agent_id,boost::bind(&on_avatar_name_cache_notify,_1, _2, online, payload)); + + if(chat_notify) + { + // Look up the name of this agent for the notification + LLAvatarNameCache::get(agent_id,boost::bind(&on_avatar_name_cache_notify,_1, _2, online, payload)); + } } mModifyMask |= LLFriendObserver::ONLINE; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 7ff24f64ac..9a608fba8e 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -141,6 +141,18 @@ public: { mAvatarNameCacheConnection.disconnect(); } + auto menu = mPopupMenuHandleAvatar.get(); + if (menu) + { + menu->die(); + mPopupMenuHandleAvatar.markDead(); + } + menu = mPopupMenuHandleObject.get(); + if (menu) + { + menu->die(); + mPopupMenuHandleObject.markDead(); + } } BOOL handleMouseUp(S32 x, S32 y, MASK mask) @@ -567,36 +579,6 @@ public: BOOL postBuild() { - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable; - - registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2)); - registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2)); - registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2)); - registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2)); - registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2)); - registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2)); - - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if (menu) - { - mPopupMenuHandleAvatar = menu->getHandle(); - } - else - { - LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL; - } - - menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if (menu) - { - mPopupMenuHandleObject = menu->getHandle(); - } - else - { - LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL; - } - setDoubleClickCallback(boost::bind(&LLChatHistoryHeader::showInspector, this)); setMouseEnterCallback(boost::bind(&LLChatHistoryHeader::showInfoCtrl, this)); @@ -650,7 +632,7 @@ public: void showInspector() { - if (mAvatarID.isNull() && CHAT_SOURCE_SYSTEM != mSourceType) return; + if (mAvatarID.isNull() && CHAT_SOURCE_SYSTEM != mSourceType && CHAT_SOURCE_REGION != mSourceType) return; if (mSourceType == CHAT_SOURCE_OBJECT) { @@ -798,6 +780,7 @@ public: icon->setValue(LLSD("OBJECT_Icon")); break; case CHAT_SOURCE_SYSTEM: + case CHAT_SOURCE_REGION: icon->setValue(LLSD("SL_Logo")); break; case CHAT_SOURCE_TELEPORT: @@ -883,13 +866,53 @@ protected: void showObjectContextMenu(S32 x,S32 y) { LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleObject.get(); - if(menu) + if (!menu) + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable; + registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2)); + registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2)); + + menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandleObject = menu->getHandle(); + menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, menu, x, y); + } + else + { + LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL; + } + } + else + { LLMenuGL::showPopup(this, menu, x, y); + } } void showAvatarContextMenu(S32 x,S32 y) { LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleAvatar.get(); + if (!menu) + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable; + registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2)); + registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2)); + registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2)); + registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2)); + + menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandleAvatar = menu->getHandle(); + } + else + { + LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL; + } + } if(menu) { @@ -947,7 +970,7 @@ protected: void showInfoCtrl() { - const bool isVisible = !mAvatarID.isNull() && !mFrom.empty() && CHAT_SOURCE_SYSTEM != mSourceType; + const bool isVisible = !mAvatarID.isNull() && !mFrom.empty() && CHAT_SOURCE_SYSTEM != mSourceType && CHAT_SOURCE_REGION != mSourceType; if (isVisible) { const LLRect sticky_rect = mUserNameTextBox->getRect(); @@ -1081,10 +1104,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) LLSD LLChatHistory::getValue() const { - LLSD* text=new LLSD(); - text->assign(mEditor->getText()); - return *text; - + return LLSD(mEditor->getText()); } LLChatHistory::~LLChatHistory() @@ -1343,7 +1363,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL mEditor->appendText(chat.mFromName + delimiter, prependNewLineState, link_params); prependNewLineState = false; } - else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log) + else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log && chat.mSourceType != CHAT_SOURCE_REGION) { LLStyle::Params link_params(body_message_params); link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 0f187b0ecf..cc4f4536a4 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -67,7 +67,6 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p) , mMaxDisplayedCount(p.max_displayed_count) , mIsNewMessagesState(false) , mFlashToLitTimer(NULL) - , mContextMenu(NULL) { LLButton::Params button_params = p.button; mButton = LLUICtrlFactory::create<LLButton>(button_params); @@ -79,6 +78,12 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p) LLSysWellChiclet::~LLSysWellChiclet() { mFlashToLitTimer->unset(); + LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get()); + if (menu) + { + menu->die(); + mContextMenuHandle.markDead(); + } } void LLSysWellChiclet::setCounter(S32 counter) @@ -145,14 +150,16 @@ void LLSysWellChiclet::updateWidget(bool is_window_empty) // virtual BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if(!mContextMenu) + LLContextMenu* menu_avatar = mContextMenuHandle.get(); + if(!menu_avatar) { createMenu(); + menu_avatar = mContextMenuHandle.get(); } - if (mContextMenu) + if (menu_avatar) { - mContextMenu->show(x, y); - LLMenuGL::showPopup(this, mContextMenu, x, y); + menu_avatar->show(x, y); + LLMenuGL::showPopup(this, menu_avatar, x, y); } return TRUE; } @@ -192,7 +199,7 @@ bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data) void LLNotificationChiclet::createMenu() { - if(mContextMenu) + if(mContextMenuHandle.get()) { LL_WARNS() << "Menu already exists" << LL_ENDL; return; @@ -207,10 +214,14 @@ void LLNotificationChiclet::createMenu() boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2)); llassert(LLMenuGL::sMenuContainer != NULL); - mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu> + LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu> ("menu_notification_well_button.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mContextMenuHandle = menu->getHandle(); + } } /*virtual*/ @@ -309,10 +320,19 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) , mDefaultWidth(p.rect().getWidth()) , mNewMessagesIcon(NULL) , mChicletButton(NULL) -, mPopupMenu(NULL) { } +LLIMChiclet::~LLIMChiclet() +{ + auto menu = mPopupMenuHandle.get(); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } +} + /* virtual*/ BOOL LLIMChiclet::postBuild() { @@ -364,16 +384,18 @@ void LLIMChiclet::setToggleState(bool toggle) BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if(!mPopupMenu) + auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); + if(!menu) { createPopupMenu(); + menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); } - if (mPopupMenu) + if (menu) { updateMenuItems(); - mPopupMenu->arrangeAndClear(); - LLMenuGL::showPopup(this, mPopupMenu, x, y); + menu->arrangeAndClear(); + LLMenuGL::showPopup(this, menu, x, y); } return TRUE; @@ -381,15 +403,16 @@ BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) void LLIMChiclet::hidePopupMenu() { - if (mPopupMenu) + auto menu = mPopupMenuHandle.get(); + if (menu) { - mPopupMenu->setVisible(FALSE); + menu->setVisible(FALSE); } } bool LLIMChiclet::canCreateMenu() { - if(mPopupMenu) + if(mPopupMenuHandle.get()) { LL_WARNS() << "Menu already exists" << LL_ENDL; return false; @@ -1107,8 +1130,13 @@ void LLScriptChiclet::createPopupMenu() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("ScriptChiclet.Action", boost::bind(&LLScriptChiclet::onMenuItemClicked, this, _2)); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> ("menu_script_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandle = menu->getHandle(); + } + } ////////////////////////////////////////////////////////////////////////// @@ -1185,8 +1213,12 @@ void LLInvOfferChiclet::createPopupMenu() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("InvOfferChiclet.Action", boost::bind(&LLInvOfferChiclet::onMenuItemClicked, this, _2)); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> ("menu_inv_offer_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandle = menu->getHandle(); + } } // EOF diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index aceedda07e..58a797218f 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -252,7 +252,7 @@ public: {}; - virtual ~LLIMChiclet() {}; + virtual ~LLIMChiclet(); /** * It is used for default setting up of chicklet:click handler, etc. @@ -325,7 +325,7 @@ protected: bool canCreateMenu(); - LLMenuGL* mPopupMenu; + LLHandle<LLUICtrl> mPopupMenuHandle; bool mShowSpeaker; bool mCounterEnabled; @@ -519,7 +519,7 @@ protected: bool mIsNewMessagesState; LLFlashTimer* mFlashToLitTimer; - LLContextMenu* mContextMenu; + LLHandle<LLContextMenu> mContextMenuHandle; }; class LLNotificationChiclet : public LLSysWellChiclet diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index 23e2271eae..74f37961c7 100644 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -39,6 +39,7 @@ #define THROTTLE_PERIOD 5 // required seconds between throttled commands static LLCommandDispatcherListener sCommandDispatcherListener; +const std::string LLCommandHandler::NAV_TYPE_CLICKED = "clicked"; //--------------------------------------------------------------------------- // Underlying registry for command handlers, not directly accessible. @@ -64,6 +65,9 @@ public: bool trusted_browser); private: + void notifySlurlBlocked(); + void notifySlurlThrottled(); + friend LLSD LLCommandDispatcher::enumerate(); std::map<std::string, LLCommandHandlerInfo> mMap; }; @@ -96,8 +100,6 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, const std::string& nav_type, bool trusted_browser) { - static bool slurl_blocked = false; - static bool slurl_throttled = false; static F64 last_throttle_time = 0.0; F64 cur_time = 0.0; std::map<std::string, LLCommandHandlerInfo>::iterator it = mMap.find(cmd); @@ -115,44 +117,45 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, // block request from external browser, but report as // "handled" because it was well formatted. LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL; - if (! slurl_blocked) - { - if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) - { - // Note: commands can arrive before we initialize everything we need for Notification. - LLNotificationsUtil::add("BlockedSLURL"); - } - slurl_blocked = true; - } + notifySlurlBlocked(); return true; + case LLCommandHandler::UNTRUSTED_CLICK_ONLY: + if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED + && info.mHandler->canHandleUntrusted(params, query_map, web, nav_type)) + { + break; + } + LL_WARNS_ONCE("SLURL") << "Blocked SLURL click-only command " << cmd << " from untrusted browser" << LL_ENDL; + notifySlurlBlocked(); + return true; + case LLCommandHandler::UNTRUSTED_THROTTLE: + //skip initial request from external browser before STATE_BROWSER_INIT + if (LLStartUp::getStartupState() == STATE_FIRST) + { + return true; + } + if (!info.mHandler->canHandleUntrusted(params, query_map, web, nav_type)) + { + LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL; + notifySlurlBlocked(); + return true; + } // if users actually click on a link, we don't need to throttle it // (throttling mechanism is used to prevent an avalanche of clicks via // javascript - if ( nav_type == "clicked" ) + if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED) { break; } - //skip initial request from external browser before STATE_BROWSER_INIT - if (LLStartUp::getStartupState() == STATE_FIRST) - { - return true; - } cur_time = LLTimer::getElapsedSeconds(); if (cur_time < last_throttle_time + THROTTLE_PERIOD) { // block request from external browser if it happened // within THROTTLE_PERIOD seconds of the last command LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL; - if (! slurl_throttled) - { - if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) - { - LLNotificationsUtil::add("ThrottledSLURL"); - } - slurl_throttled = true; - } + notifySlurlThrottled(); return true; } last_throttle_time = cur_time; @@ -163,6 +166,34 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, return info.mHandler->handle(params, query_map, web); } +void LLCommandHandlerRegistry::notifySlurlBlocked() +{ + static bool slurl_blocked = false; + if (!slurl_blocked) + { + if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) + { + // Note: commands can arrive before we initialize everything we need for Notification. + LLNotificationsUtil::add("BlockedSLURL"); + } + slurl_blocked = true; + } +} + +void LLCommandHandlerRegistry::notifySlurlThrottled() +{ + static bool slurl_throttled = false; + if (!slurl_throttled) + { + if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) + { + // Note: commands can arrive before we initialize everything we need for Notification. + LLNotificationsUtil::add("ThrottledSLURL"); + } + slurl_throttled = true; + } +} + //--------------------------------------------------------------------------- // Automatic registration of commands, runs before main() //--------------------------------------------------------------------------- @@ -230,6 +261,7 @@ symbol_info symbols[] = { ent(LLCommandHandler::UNTRUSTED_ALLOW), // allow commands from untrusted browsers ent(LLCommandHandler::UNTRUSTED_BLOCK), // ignore commands from untrusted browsers + ent(LLCommandHandler::UNTRUSTED_CLICK_ONLY), // allow untrusted, but only if clicked ent(LLCommandHandler::UNTRUSTED_THROTTLE) // allow untrusted, but only a few per min. }; diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h index 1e0895565a..763e3ee51f 100644 --- a/indra/newview/llcommandhandler.h +++ b/indra/newview/llcommandhandler.h @@ -65,9 +65,12 @@ public: { UNTRUSTED_ALLOW, // allow commands from untrusted browsers UNTRUSTED_BLOCK, // ignore commands from untrusted browsers + UNTRUSTED_CLICK_ONLY, // allow untrusted, but only if clicked UNTRUSTED_THROTTLE // allow untrusted, but only a few per min. }; + static const std::string NAV_TYPE_CLICKED; + LLCommandHandler(const char* command, EUntrustedAccess untrusted_access); // Automatically registers object to get called when // command is executed. All commands can be processed @@ -76,6 +79,13 @@ public: virtual ~LLCommandHandler(); + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { return true; } + virtual bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) = 0; diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 787deeb594..7c6980a7e6 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -87,7 +87,7 @@ public: virtual BOOL removeItem() { return FALSE; } virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) { } virtual void move( LLFolderViewModelItem* parent_listener ) { } - virtual BOOL isItemCopyable() const { return FALSE; } + virtual bool isItemCopyable(bool can_copy_as_link = true) const { return false; } virtual BOOL copyToClipboard() const { return FALSE; } virtual BOOL cutToClipboard() { return FALSE; } virtual BOOL isClipboardPasteable() const { return FALSE; } diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 8db6a10e26..c4c88d304c 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -41,6 +41,7 @@ #include "lldrawable.h" #include "llface.h" #include "llsky.h" +#include "llstartup.h" #include "lltextureentry.h" #include "llviewercamera.h" #include "llviewertexturelist.h" @@ -79,11 +80,6 @@ static S32 bump_channel = -1; #define LL_BUMPLIST_MULTITHREADED 0 // TODO -- figure out why this doesn't work -// static -void LLStandardBumpmap::init() -{ - LLStandardBumpmap::restoreGL(); -} // static void LLStandardBumpmap::shutdown() @@ -94,7 +90,7 @@ void LLStandardBumpmap::shutdown() // static void LLStandardBumpmap::restoreGL() { - addstandard(); + addstandard(); } // static @@ -107,6 +103,12 @@ void LLStandardBumpmap::addstandard() return ; } + if (LLStartUp::getStartupState() < STATE_SEED_CAP_GRANTED) + { + // Not ready, need caps for images + return; + } + // can't assert; we destroyGL and restoreGL a lot during *first* startup, which populates this list already, THEN we explicitly init the list as part of *normal* startup. Sigh. So clear the list every time before we (re-)add the standard bumpmaps. //llassert( LLStandardBumpmap::sStandardBumpmapCount == 0 ); clear(); @@ -769,8 +771,6 @@ void LLBumpImageList::init() llassert( mBrightnessEntries.size() == 0 ); llassert( mDarknessEntries.size() == 0 ); - LLStandardBumpmap::init(); - LLStandardBumpmap::restoreGL(); sMainQueue = LL::WorkQueue::getInstance("mainloop"); sTexUpdateQueue = LL::WorkQueue::getInstance("LLImageGL"); // Share work queue with tex loader. diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index e8a027967b..cf463f4458 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -118,7 +118,6 @@ public: static void clear(); static void addstandard(); - static void init(); static void shutdown(); static void restoreGL(); static void destroyGL(); diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 1300cf3658..05c7decfbd 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -684,7 +684,6 @@ namespace if (!injection->mBlendIn) mix = 1.0 - mix; stringset_t dummy; - LLUUID cloud_noise_id = getCloudNoiseTextureId(); F64 value = this->mSettings[injection->mKeyName].asReal(); if (this->getCloudNoiseTextureId().isNull()) { @@ -874,26 +873,37 @@ void LLEnvironment::initSingleton() requestRegion(); - gAgent.addParcelChangedCallback([this]() { onParcelChange(); }); + if (!mParcelCallbackConnection.connected()) + { + mParcelCallbackConnection = gAgent.addParcelChangedCallback([this]() { onParcelChange(); }); - //TODO: This frequently results in one more request than we need. It isn't breaking, but should be nicer. - // We need to know new env version to fix this, without it we can only do full re-request - // Happens: on updates, on opening LLFloaterRegionInfo, on region crossing if info floater is open - LLRegionInfoModel::instance().setUpdateCallback([this]() { requestRegion(); }); - gAgent.addRegionChangedCallback([this]() { onRegionChange(); }); + //TODO: This frequently results in one more request than we need. It isn't breaking, but should be nicer. + // We need to know new env version to fix this, without it we can only do full re-request + // Happens: on updates, on opening LLFloaterRegionInfo, on region crossing if info floater is open + mRegionUpdateCallbackConnection = LLRegionInfoModel::instance().setUpdateCallback([this]() { requestRegion(); }); + mRegionChangeCallbackConnection = gAgent.addRegionChangedCallback([this]() { onRegionChange(); }); - gAgent.whenPositionChanged([this](const LLVector3 &localpos, const LLVector3d &) { onAgentPositionHasChanged(localpos); }); + mPositionCallbackConnection = gAgent.whenPositionChanged([this](const LLVector3 &localpos, const LLVector3d &) { onAgentPositionHasChanged(localpos); }); + } if (!gGenericDispatcher.isHandlerPresent(MESSAGE_PUSHENVIRONMENT)) { gGenericDispatcher.addHandler(MESSAGE_PUSHENVIRONMENT, &environment_push_dispatch_handler); } + LLEventPumps::instance().obtain(PUMP_EXPERIENCE).stopListening(LISTENER_NAME); LLEventPumps::instance().obtain(PUMP_EXPERIENCE).listen(LISTENER_NAME, [this](LLSD message) { listenExperiencePump(message); return false; }); } void LLEnvironment::cleanupSingleton() { + if (mParcelCallbackConnection.connected()) + { + mParcelCallbackConnection.disconnect(); + mRegionUpdateCallbackConnection.disconnect(); + mRegionChangeCallbackConnection.disconnect(); + mPositionCallbackConnection.disconnect(); + } LLEventPumps::instance().obtain(PUMP_EXPERIENCE).stopListening(LISTENER_NAME); } @@ -3086,7 +3096,7 @@ bool LLEnvironment::loadFromSettings() LL_INFOS("ENVIRONMENT") << "Unable to open previous session environment file " << user_filepath << LL_ENDL; } - if (!env_data.isMap() || env_data.emptyMap()) + if (!env_data.isMap() || (env_data.size() == 0)) { LL_DEBUGS("ENVIRONMENT") << "Empty map loaded from: " << user_filepath << LL_ENDL; return false; diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h index 330de2bea8..64fd170e43 100644 --- a/indra/newview/llenvironment.h +++ b/indra/newview/llenvironment.h @@ -402,6 +402,11 @@ private: bool mShowMoonBeacon; S32 mEditorCounter; + connection_t mParcelCallbackConnection; + connection_t mRegionUpdateCallbackConnection; + connection_t mRegionChangeCallbackConnection; + connection_t mPositionCallbackConnection; + struct UpdateInfo { typedef std::shared_ptr<UpdateInfo> ptr_t; diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 3669fb1eeb..e3a695fc79 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -586,9 +586,9 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, #elif LL_DARWIN -std::vector<std::string>* LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode) +std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode) { - std::vector<std::string> *allowedv = new std::vector< std::string >; + std::unique_ptr<std::vector<std::string>> allowedv(new std::vector< std::string >); switch(filter) { case FFLOAD_ALL: @@ -661,9 +661,9 @@ bool LLFilePicker::doNavChooseDialog(ELoadFilter filter) gViewerWindow->getWindow()->beforeDialog(); - std::vector<std::string> *allowed_types=navOpenFilterProc(filter); + std::unique_ptr<std::vector<std::string>> allowed_types = navOpenFilterProc(filter); - std::vector<std::string> *filev = doLoadDialog(allowed_types, + std::unique_ptr<std::vector<std::string>> filev = doLoadDialog(allowed_types.get(), mPickOptions); gViewerWindow->getWindow()->afterDialog(); @@ -780,7 +780,7 @@ bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena gViewerWindow->getWindow()->beforeDialog(); // Run the dialog - std::string* filev = doSaveDialog(&namestring, + std::unique_ptr<std::string> filev = doSaveDialog(&namestring, &type, &creator, &extension, diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 04ba4416d7..73baeca1c0 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -167,7 +167,7 @@ private: bool doNavChooseDialog(ELoadFilter filter); bool doNavSaveDialog(ESaveFilter filter, const std::string& filename); - std::vector<std::string>* navOpenFilterProc(ELoadFilter filter); + std::unique_ptr<std::vector<std::string>> navOpenFilterProc(ELoadFilter filter); #endif #if LL_GTK diff --git a/indra/newview/llfilepicker_mac.h b/indra/newview/llfilepicker_mac.h index e0b7e2e8ce..b2fb371afe 100644 --- a/indra/newview/llfilepicker_mac.h +++ b/indra/newview/llfilepicker_mac.h @@ -39,9 +39,9 @@ #include <vector> //void modelessPicker(); -std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types, +std::unique_ptr<std::vector<std::string>> doLoadDialog(const std::vector<std::string>* allowed_types, unsigned int flags); -std::string* doSaveDialog(const std::string* file, +std::unique_ptr<std::string> doSaveDialog(const std::string* file, const std::string* type, const std::string* creator, const std::string* extension, diff --git a/indra/newview/llfilepicker_mac.mm b/indra/newview/llfilepicker_mac.mm index 1438e4dc0a..0ae5fc3f77 100644 --- a/indra/newview/llfilepicker_mac.mm +++ b/indra/newview/llfilepicker_mac.mm @@ -29,104 +29,107 @@ #include <iostream> #include "llfilepicker_mac.h" -std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types, +std::unique_ptr<std::vector<std::string>> doLoadDialog(const std::vector<std::string>* allowed_types, unsigned int flags) { - int i, result; - - //Aura TODO: We could init a small window and release it at the end of this routine - //for a modeless interface. - - NSOpenPanel *panel = [NSOpenPanel openPanel]; - //NSString *fileName = nil; - NSMutableArray *fileTypes = nil; - - - if ( allowed_types && !allowed_types->empty()) - { - fileTypes = [[NSMutableArray alloc] init]; + std::unique_ptr<std::vector<std::string>> outfiles; + + @autoreleasepool { + int i, result; + //Aura TODO: We could init a small window and release it at the end of this routine + //for a modeless interface. + + NSOpenPanel *panel = [NSOpenPanel openPanel]; + //NSString *fileName = nil; + NSMutableArray *fileTypes = nil; - for (i=0;i<allowed_types->size();++i) + if ( allowed_types && !allowed_types->empty()) { - [fileTypes addObject: - [NSString stringWithCString:(*allowed_types)[i].c_str() - encoding:[NSString defaultCStringEncoding]]]; + fileTypes = [[[NSMutableArray alloc] init] autorelease]; + + for (i=0;i<allowed_types->size();++i) + { + [fileTypes addObject: + [NSString stringWithCString:(*allowed_types)[i].c_str() + encoding:[NSString defaultCStringEncoding]]]; + } } - } - //[panel setMessage:@"Import one or more files or directories."]; - [panel setAllowsMultipleSelection: ( (flags & F_MULTIPLE)?true:false ) ]; - [panel setCanChooseDirectories: ( (flags & F_DIRECTORY)?true:false ) ]; - [panel setCanCreateDirectories: true]; - [panel setResolvesAliases: true]; - [panel setCanChooseFiles: ( (flags & F_FILE)?true:false )]; - [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ]; - - std::vector<std::string>* outfiles = NULL; - - if (fileTypes) - { - [panel setAllowedFileTypes:fileTypes]; - result = [panel runModal]; - } - else - { - // I suggest it's better to open the last path and let this default to home dir as necessary - // for consistency with other OS X apps - // - //[panel setDirectoryURL: fileURLWithPath(NSHomeDirectory()) ]; - result = [panel runModal]; - } - - if (result == NSOKButton) - { - NSArray *filesToOpen = [panel URLs]; - int i, count = [filesToOpen count]; + //[panel setMessage:@"Import one or more files or directories."]; + [panel setAllowsMultipleSelection: ( (flags & F_MULTIPLE)?true:false ) ]; + [panel setCanChooseDirectories: ( (flags & F_DIRECTORY)?true:false ) ]; + [panel setCanCreateDirectories: true]; + [panel setResolvesAliases: true]; + [panel setCanChooseFiles: ( (flags & F_FILE)?true:false )]; + [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ]; - if (count > 0) + if (fileTypes) + { + [panel setAllowedFileTypes:fileTypes]; + result = [panel runModal]; + } + else { - outfiles = new std::vector<std::string>; + // I suggest it's better to open the last path and let this default to home dir as necessary + // for consistency with other OS X apps + // + //[panel setDirectoryURL: fileURLWithPath(NSHomeDirectory()) ]; + result = [panel runModal]; } - for (i=0; i<count; i++) { - NSString *aFile = [[filesToOpen objectAtIndex:i] path]; - std::string *afilestr = new std::string([aFile UTF8String]); - outfiles->push_back(*afilestr); + if (result == NSOKButton) + { + NSArray *filesToOpen = [panel URLs]; + int i, count = [filesToOpen count]; + + if (count > 0) + { + outfiles.reset(new std::vector<std::string>); + } + + for (i=0; i<count; i++) { + NSString *aFile = [[filesToOpen objectAtIndex:i] path]; + std::string afilestr = std::string([aFile UTF8String]); + outfiles->push_back(afilestr); + } } } + return outfiles; } -std::string* doSaveDialog(const std::string* file, +std::unique_ptr<std::string> doSaveDialog(const std::string* file, const std::string* type, const std::string* creator, const std::string* extension, unsigned int flags) { - NSSavePanel *panel = [NSSavePanel savePanel]; - - NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]]; - NSArray *fileType = [extensionns componentsSeparatedByString:@","]; - - //[panel setMessage:@"Save Image File"]; - [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ]; - [panel setCanSelectHiddenExtension:true]; - [panel setAllowedFileTypes:fileType]; - NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]]; - - std::string *outfile = NULL; - NSURL* url = [NSURL fileURLWithPath:fileName]; - [panel setNameFieldStringValue: fileName]; - [panel setDirectoryURL: url]; - if([panel runModal] == - NSFileHandlingPanelOKButton) - { - NSURL* url = [panel URL]; - NSString* p = [url path]; - outfile = new std::string( [p UTF8String] ); - // write the file - } + std::unique_ptr<std::string> outfile; + @autoreleasepool { + NSSavePanel *panel = [NSSavePanel savePanel]; + + NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]]; + NSArray *fileType = [extensionns componentsSeparatedByString:@","]; + + //[panel setMessage:@"Save Image File"]; + [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ]; + [panel setCanSelectHiddenExtension:true]; + [panel setAllowedFileTypes:fileType]; + NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]]; + + NSURL* url = [NSURL fileURLWithPath:fileName]; + [panel setNameFieldStringValue: fileName]; + [panel setDirectoryURL: url]; + if([panel runModal] == + NSFileHandlingPanelOKButton) + { + NSURL* url = [panel URL]; + NSString* p = [url path]; + outfile.reset(new std::string([p UTF8String])); + // write the file + } + } return outfile; } diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp index c075f7e8bd..eff94bd195 100644 --- a/indra/newview/llfloater360capture.cpp +++ b/indra/newview/llfloater360capture.cpp @@ -84,7 +84,7 @@ LLFloater360Capture::~LLFloater360Capture() // Tell the Simulator not to send us everything anymore // and revert to the regular "keyhole" frustum of interest // list updates. - if (gSavedSettings.getBOOL("360CaptureUseInterestListCap")) + if (!LLApp::isExiting() && gSavedSettings.getBOOL("360CaptureUseInterestListCap")) { const bool send_everything = false; changeInterestListMode(send_everything); @@ -537,7 +537,8 @@ void LLFloater360Capture::capture360Images() // We need to convert from the angle getYaw() gives us into something // the XMP data field wants (N=0, E=90, S=180, W= 270 etc.) mInitialHeadingDeg = (360 + 90 - (int)(camera->getYaw() * RAD_TO_DEG)) % 360; - LL_INFOS("360Capture") << "Recording a heading of " << (int)(mInitialHeadingDeg) << LL_ENDL; + LL_INFOS("360Capture") << "Recording a heading of " << (int)(mInitialHeadingDeg) + << " Image size: " << (S32)mSourceImageSize << LL_ENDL; // camera constants for the square, cube map capture image camera->setAspect(1.0); // must set aspect ratio first to avoid undesirable clamping of vertical FoV @@ -587,6 +588,9 @@ void LLFloater360Capture::capture360Images() // for each of the 6 directions we shoot... for (int i = 0; i < 6; i++) { + LLAppViewer::instance()->pauseMainloopTimeout(); + LLViewerStats::instance().getRecording().stop(); + // these buffers are where the raw, captured pixels are stored and // the first time we use them, we have to make a new one if (mRawImages[i] == nullptr) @@ -624,8 +628,10 @@ void LLFloater360Capture::capture360Images() auto duration = std::chrono::duration_cast<std::chrono::duration<double>>(t_end - t_start); encode_time_total += duration.count(); - // ping the main loop in case the snapshot process takes a really long - // time and we get disconnected + LLViewerStats::instance().getRecording().resume(); + LLAppViewer::instance()->resumeMainloopTimeout(); + + // update main loop timeout state LLAppViewer::instance()->pingMainloopTimeout("LLFloater360Capture::capture360Images"); } diff --git a/indra/newview/llfloateravatar.cpp b/indra/newview/llfloateravatar.cpp index 31adf5b61e..f888d032ae 100644 --- a/indra/newview/llfloateravatar.cpp +++ b/indra/newview/llfloateravatar.cpp @@ -44,17 +44,21 @@ LLFloaterAvatar::LLFloaterAvatar(const LLSD& key) LLFloaterAvatar::~LLFloaterAvatar() { - LLMediaCtrl* avatar_picker = findChild<LLMediaCtrl>("avatar_picker_contents"); - if (avatar_picker) + if (mAvatarPicker) { - avatar_picker->navigateStop(); - avatar_picker->clearCache(); //images are reloading each time already - avatar_picker->unloadMediaSource(); + mAvatarPicker->navigateStop(); + mAvatarPicker->clearCache(); //images are reloading each time already + mAvatarPicker->unloadMediaSource(); } } BOOL LLFloaterAvatar::postBuild() { + mAvatarPicker = findChild<LLMediaCtrl>("avatar_picker_contents"); + if (mAvatarPicker) + { + mAvatarPicker->clearCache(); + } enableResizeCtrls(true, true, false); return TRUE; } diff --git a/indra/newview/llfloateravatar.h b/indra/newview/llfloateravatar.h index cadc5e4028..76e9372709 100644 --- a/indra/newview/llfloateravatar.h +++ b/indra/newview/llfloateravatar.h @@ -29,6 +29,7 @@ #define LL_FLOATER_AVATAR_H #include "llfloater.h" +class LLMediaCtrl; class LLFloaterAvatar: public LLFloater @@ -38,6 +39,8 @@ private: LLFloaterAvatar(const LLSD& key); /*virtual*/ ~LLFloaterAvatar(); /*virtual*/ BOOL postBuild(); + + LLMediaCtrl* mAvatarPicker; }; #endif diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp index 33e4c7cd5f..307ab8c4d1 100644 --- a/indra/newview/llfloaterbump.cpp +++ b/indra/newview/llfloaterbump.cpp @@ -69,6 +69,12 @@ LLFloaterBump::LLFloaterBump(const LLSD& key) // Destroys the object LLFloaterBump::~LLFloaterBump() { + auto menu = mPopupMenuHandle.get(); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } } BOOL LLFloaterBump::postBuild() @@ -77,11 +83,15 @@ BOOL LLFloaterBump::postBuild() mList->setAllowMultipleSelection(false); mList->setRightMouseDownCallback(boost::bind(&LLFloaterBump::onScrollListRightClicked, this, _1, _2, _3)); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_avatar_other.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mPopupMenu->setItemVisible(std::string("Normal"), false); - mPopupMenu->setItemVisible(std::string("Always use impostor"), false); - mPopupMenu->setItemVisible(std::string("Never use impostor"), false); - mPopupMenu->setItemVisible(std::string("Impostor seperator"), false); + LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_avatar_other.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandle = menu->getHandle(); + menu->setItemVisible(std::string("Normal"), false); + menu->setItemVisible(std::string("Always use impostor"), false); + menu->setItemVisible(std::string("Never use impostor"), false); + menu->setItemVisible(std::string("Impostor seperator"), false); + } return TRUE; } @@ -176,18 +186,19 @@ void LLFloaterBump::onScrollListRightClicked(LLUICtrl* ctrl, S32 x, S32 y) if (!gMeanCollisionList.empty()) { LLScrollListItem* item = mList->hitItem(x, y); - if (item && mPopupMenu) + auto menu = mPopupMenuHandle.get(); + if (item && menu) { mItemUUID = item->getUUID(); - mPopupMenu->buildDrawLabels(); - mPopupMenu->updateParent(LLMenuGL::sMenuContainer); + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); std::string mute_msg = (LLMuteList::getInstance()->isMuted(mItemUUID, mNames[mItemUUID])) ? "UnmuteAvatar" : "MuteAvatar"; - mPopupMenu->getChild<LLUICtrl>("Avatar Mute")->setValue(LLTrans::getString(mute_msg)); - mPopupMenu->setItemEnabled(std::string("Zoom In"), bool(gObjectList.findObject(mItemUUID))); + menu->getChild<LLUICtrl>("Avatar Mute")->setValue(LLTrans::getString(mute_msg)); + menu->setItemEnabled(std::string("Zoom In"), bool(gObjectList.findObject(mItemUUID))); - ((LLContextMenu*)mPopupMenu)->show(x, y); - LLMenuGL::showPopup(ctrl, mPopupMenu, x, y); + menu->show(x, y); + LLMenuGL::showPopup(ctrl, menu, x, y); } } } diff --git a/indra/newview/llfloaterbump.h b/indra/newview/llfloaterbump.h index ce52c75255..d2f9fabdd3 100644 --- a/indra/newview/llfloaterbump.h +++ b/indra/newview/llfloaterbump.h @@ -68,7 +68,7 @@ private: virtual ~LLFloaterBump(); LLScrollListCtrl* mList; - LLMenuGL* mPopupMenu; + LLHandle<LLContextMenu> mPopupMenuHandle; LLUUID mItemUUID; typedef std::map<LLUUID, std::string> uuid_map_t; diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp index 7def855d83..b82d8a29ba 100644 --- a/indra/newview/llfloatercreatelandmark.cpp +++ b/indra/newview/llfloatercreatelandmark.cpp @@ -316,7 +316,6 @@ void LLFloaterCreateLandmark::onSaveClicked() LLStringUtil::trim(current_title_value); LLStringUtil::trim(current_notes_value); - LLUUID item_id = mItem->getUUID(); LLUUID folder_id = mFolderCombo->getValue().asUUID(); bool change_parent = folder_id != mItem->getParentUUID(); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 703b5d0011..2720b7fcf7 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -211,6 +211,7 @@ BOOL LLFloaterIMContainer::postBuild() p.options_menu = "menu_conversation.xml"; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar); // Add listener to conversation model events mConversationsEventStream.listen("ConversationsRefresh", boost::bind(&LLFloaterIMContainer::onConversationModelEvent, this, _1)); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 4cceddeefb..f1807f1c5b 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -307,7 +307,6 @@ void LLFloaterIMNearbyChat::onOpen(const LLSD& key) restoreFloater(); onCollapseToLine(this); } - showTranslationCheckbox(LLTranslate::isTranslationConfigured()); } // virtual diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 48e2b8dc14..ee9dc35283 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -842,6 +842,7 @@ void LLFloaterIMSession::updateMessages() std::string from = msg["from"].asString(); std::string message = msg["message"].asString(); bool is_history = msg["is_history"].asBoolean(); + bool is_region_msg = msg["is_region_msg"].asBoolean(); LLChat chat; chat.mFromID = from_id; @@ -849,6 +850,10 @@ void LLFloaterIMSession::updateMessages() chat.mFromName = from; chat.mTimeStr = time; chat.mChatStyle = is_history ? CHAT_STYLE_HISTORY : chat.mChatStyle; + if (is_region_msg) + { + chat.mSourceType = CHAT_SOURCE_REGION; + } // process offer notification if (msg.has("notification_id")) diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 93a0b39e02..78271369d2 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -253,7 +253,6 @@ BOOL LLFloaterIMSessionTab::postBuild() mGearBtn = getChild<LLButton>("gear_btn"); mAddBtn = getChild<LLButton>("add_btn"); mVoiceButton = getChild<LLButton>("voice_call_btn"); - mTranslationCheckBox = getChild<LLUICtrl>("translate_chat_checkbox_lp"); mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder"); @@ -317,6 +316,7 @@ BOOL LLFloaterIMSessionTab::postBuild() p.name = "root"; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar); // Attach that root to the scroller mScroller->addChild(mConversationsRoot); mConversationsRoot->setScrollContainer(mScroller); @@ -811,8 +811,6 @@ void LLFloaterIMSessionTab::updateHeaderAndToolbar() mCloseBtn->setVisible(is_not_torn_off && !mIsNearbyChat); enableDisableCallBtn(); - - showTranslationCheckbox(); } void LLFloaterIMSessionTab::forceReshape() @@ -829,11 +827,6 @@ void LLFloaterIMSessionTab::reshapeChatLayoutPanel() mChatLayoutPanel->reshape(mChatLayoutPanel->getRect().getWidth(), mInputEditor->getRect().getHeight() + mInputEditorPad, FALSE); } -void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show) -{ - mTranslationCheckBox->setVisible(mIsNearbyChat && show); -} - // static void LLFloaterIMSessionTab::processChatHistoryStyleUpdate(bool clean_messages/* = false*/) { diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 375461cfc1..9f00917647 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -71,8 +71,6 @@ public: static LLFloaterIMSessionTab* findConversation(const LLUUID& uuid); static LLFloaterIMSessionTab* getConversation(const LLUUID& uuid); - // show/hide the translation check box - void showTranslationCheckbox(const BOOL visible = FALSE); bool isNearbyChat() {return mIsNearbyChat;} @@ -187,7 +185,6 @@ protected: LLButton* mGearBtn; LLButton* mAddBtn; LLButton* mVoiceButton; - LLUICtrl* mTranslationCheckBox; private: // Handling selection and contextual menu diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 66a245b779..6f8f73bca0 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1740,7 +1740,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible) childSetTextArg("download_weight", "[ST]", tbd); childSetTextArg("server_weight", "[SIM]", tbd); childSetTextArg("physics_weight", "[PH]", tbd); - if (!mModelPhysicsFee.isMap() || mModelPhysicsFee.emptyMap()) + if (!mModelPhysicsFee.isMap() || (mModelPhysicsFee.size() == 0)) { childSetTextArg("upload_fee", "[FEE]", tbd); } diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 2a1749bd42..a682064dad 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -56,8 +56,6 @@ LLFloaterOpenObject::LLFloaterOpenObject(const LLSD& key) mDirty(TRUE) { mCommitCallbackRegistrar.add("OpenObject.MoveToInventory", boost::bind(&LLFloaterOpenObject::onClickMoveToInventory, this)); - mCommitCallbackRegistrar.add("OpenObject.MoveAndWear", boost::bind(&LLFloaterOpenObject::onClickMoveAndWear, this)); - mCommitCallbackRegistrar.add("OpenObject.ReplaceOutfit", boost::bind(&LLFloaterOpenObject::onClickReplace, this)); mCommitCallbackRegistrar.add("OpenObject.Cancel", boost::bind(&LLFloaterOpenObject::onClickCancel, this)); } @@ -243,18 +241,6 @@ void LLFloaterOpenObject::onClickMoveToInventory() closeFloater(); } -void LLFloaterOpenObject::onClickMoveAndWear() -{ - moveToInventory(true, false); - closeFloater(); -} - -void LLFloaterOpenObject::onClickReplace() -{ - moveToInventory(true, true); - closeFloater(); -} - void LLFloaterOpenObject::onClickCancel() { closeFloater(); diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h index 2e761f99bf..745753316b 100644 --- a/indra/newview/llfloateropenobject.h +++ b/indra/newview/llfloateropenobject.h @@ -63,8 +63,6 @@ protected: void moveToInventory(bool wear, bool replace = false); void onClickMoveToInventory(); - void onClickMoveAndWear(); - void onClickReplace(); void onClickCancel(); static void callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear, bool replace = false); static void callbackMoveInventory(S32 result, void* data); diff --git a/indra/newview/llfloateroutfitphotopreview.cpp b/indra/newview/llfloateroutfitphotopreview.cpp index 6c39db730c..ade258aef7 100644 --- a/indra/newview/llfloateroutfitphotopreview.cpp +++ b/indra/newview/llfloateroutfitphotopreview.cpp @@ -234,7 +234,6 @@ void LLFloaterOutfitPhotoPreview::updateImageID() if(item) { mImageID = item->getAssetUUID(); - LLPermissions perm(item->getPermissions()); } else { diff --git a/indra/newview/llfloateroutfitsnapshot.cpp b/indra/newview/llfloateroutfitsnapshot.cpp deleted file mode 100644 index ad5e97e067..0000000000 --- a/indra/newview/llfloateroutfitsnapshot.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/** - * @file llfloateroutfitsnapshot.cpp - * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2016, 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 "llfloatersnapshot.h" -#include "llfloateroutfitsnapshot.h" - -#include "llagent.h" -#include "llfloaterreg.h" -#include "llimagefiltersmanager.h" -#include "llcheckboxctrl.h" -#include "llcombobox.h" -#include "llpostcard.h" -#include "llresmgr.h" // LLLocale -#include "llsdserialize.h" -#include "llsidetraypanelcontainer.h" -#include "llspinctrl.h" -#include "llviewercontrol.h" -#include "lltoolfocus.h" -#include "lltoolmgr.h" - -///---------------------------------------------------------------------------- -/// Local function declarations, constants, enums, and typedefs -///---------------------------------------------------------------------------- -LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView = NULL; - -const S32 OUTFIT_SNAPSHOT_WIDTH = 256; -const S32 OUTFIT_SNAPSHOT_HEIGHT = 256; - -static LLDefaultChildRegistry::Register<LLOutfitSnapshotFloaterView> r("snapshot_outfit_floater_view"); - -///---------------------------------------------------------------------------- -/// Class LLFloaterOutfitSnapshot::Impl -///---------------------------------------------------------------------------- - -// virtual -LLPanelSnapshot* LLFloaterOutfitSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found) -{ - LLPanel* panel = floater->getChild<LLPanel>("panel_outfit_snapshot_inventory"); - LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel); - if (!ok_if_not_found) - { - llassert_always(active_panel != NULL); - } - return active_panel; -} - -// virtual -LLSnapshotModel::ESnapshotFormat LLFloaterOutfitSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater) -{ - return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; -} - -// virtual -LLSnapshotModel::ESnapshotLayerType LLFloaterOutfitSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater) -{ - return LLSnapshotModel::SNAPSHOT_TYPE_COLOR; -} - -// This is the main function that keeps all the GUI controls in sync with the saved settings. -// It should be called anytime a setting is changed that could affect the controls. -// No other methods should be changing any of the controls directly except for helpers called by this method. -// The basic pattern for programmatically changing the GUI settings is to first set the -// appropriate saved settings and then call this method to sync the GUI with them. -// FIXME: The above comment seems obsolete now. -// virtual -void LLFloaterOutfitSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater) -{ - LLSnapshotModel::ESnapshotType shot_type = getActiveSnapshotType(floater); - LLSnapshotModel::ESnapshotFormat shot_format = (LLSnapshotModel::ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); - LLSnapshotModel::ESnapshotLayerType layer_type = getLayerType(floater); - - LLSnapshotLivePreview* previewp = getPreviewView(); - BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); - - // *TODO: Separate maximum size for Web images from postcards - LL_DEBUGS() << "Is snapshot up-to-date? " << got_snap << LL_ENDL; - - LLLocale locale(LLLocale::USER_LOCALE); - std::string bytes_string; - if (got_snap) - { - LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10); - } - - // Update displayed image resolution. - LLTextBox* image_res_tb = floater->getChild<LLTextBox>("image_res_text"); - image_res_tb->setVisible(got_snap); - if (got_snap) - { - image_res_tb->setTextArg("[WIDTH]", llformat("%d", previewp->getEncodedImageWidth())); - image_res_tb->setTextArg("[HEIGHT]", llformat("%d", previewp->getEncodedImageHeight())); - } - - floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown")); - floater->getChild<LLUICtrl>("file_size_label")->setColor(LLUIColorTable::instance().getColor("LabelTextColor")); - - updateResolution(floater); - - if (previewp) - { - previewp->setSnapshotType(shot_type); - previewp->setSnapshotFormat(shot_format); - previewp->setSnapshotBufferType(layer_type); - } - - LLPanelSnapshot* current_panel = Impl::getActivePanel(floater); - if (current_panel) - { - LLSD info; - info["have-snapshot"] = got_snap; - current_panel->updateControls(info); - } - LL_DEBUGS() << "finished updating controls" << LL_ENDL; -} - -// virtual -std::string LLFloaterOutfitSnapshot::Impl::getSnapshotPanelPrefix() -{ - return "panel_outfit_snapshot_"; -} - -// Show/hide upload status message. -// virtual -void LLFloaterOutfitSnapshot::Impl::setFinished(bool finished, bool ok, const std::string& msg) -{ - mFloater->setSuccessLabelPanelVisible(finished && ok); - mFloater->setFailureLabelPanelVisible(finished && !ok); - - if (finished) - { - LLUICtrl* finished_lbl = mFloater->getChild<LLUICtrl>(ok ? "succeeded_lbl" : "failed_lbl"); - std::string result_text = mFloater->getString(msg + "_" + (ok ? "succeeded_str" : "failed_str")); - finished_lbl->setValue(result_text); - - LLPanel* snapshot_panel = mFloater->getChild<LLPanel>("panel_outfit_snapshot_inventory"); - snapshot_panel->onOpen(LLSD()); - } -} - -void LLFloaterOutfitSnapshot::Impl::updateResolution(void* data) -{ - LLFloaterOutfitSnapshot *view = (LLFloaterOutfitSnapshot *)data; - - if (!view) - { - llassert(view); - return; - } - - S32 width = OUTFIT_SNAPSHOT_WIDTH; - S32 height = OUTFIT_SNAPSHOT_HEIGHT; - - LLSnapshotLivePreview* previewp = getPreviewView(); - if (previewp) - { - S32 original_width = 0, original_height = 0; - previewp->getSize(original_width, original_height); - - if (gSavedSettings.getBOOL("RenderUIInSnapshot") || gSavedSettings.getBOOL("RenderHUDInSnapshot")) - { //clamp snapshot resolution to window size when showing UI or HUD in snapshot - width = llmin(width, gViewerWindow->getWindowWidthRaw()); - height = llmin(height, gViewerWindow->getWindowHeightRaw()); - } - - - llassert(width > 0 && height > 0); - - // use the resolution from the selected pre-canned drop-down choice - LL_DEBUGS() << "Setting preview res selected from combo: " << width << "x" << height << LL_ENDL; - previewp->setSize(width, height); - - if (original_width != width || original_height != height) - { - // hide old preview as the aspect ratio could be wrong - checkAutoSnapshot(previewp, FALSE); - LL_DEBUGS() << "updating thumbnail" << LL_ENDL; - previewp->updateSnapshot(TRUE); - } - } -} - -///---------------------------------------------------------------------------- -/// Class LLFloaterOutfitSnapshot -///---------------------------------------------------------------------------- - -// Default constructor -LLFloaterOutfitSnapshot::LLFloaterOutfitSnapshot(const LLSD& key) -: LLFloaterSnapshotBase(key), -mOutfitGallery(NULL) -{ - impl = new Impl(this); -} - -LLFloaterOutfitSnapshot::~LLFloaterOutfitSnapshot() -{ -} - -// virtual -BOOL LLFloaterOutfitSnapshot::postBuild() -{ - mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn"); - childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this); - mRefreshLabel = getChild<LLUICtrl>("refresh_lbl"); - mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel"); - mFailureLblPanel = getChild<LLUICtrl>("failed_panel"); - - childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this); - getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot")); - - childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this); - getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot")); - - getChild<LLUICtrl>("freeze_frame_check")->setValue(gSavedSettings.getBOOL("UseFreezeFrame")); - childSetCommitCallback("freeze_frame_check", ImplBase::onCommitFreezeFrame, this); - - getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot")); - childSetCommitCallback("auto_snapshot_check", ImplBase::onClickAutoSnap, this); - - getChild<LLButton>("retract_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, this)); - getChild<LLButton>("extend_btn")->setCommitCallback(boost::bind(&LLFloaterOutfitSnapshot::onExtendFloater, this)); - - // Filters - LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox"); - std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); - for (U32 i = 0; i < filter_list.size(); i++) - { - filterbox->add(filter_list[i]); - } - childSetCommitCallback("filters_combobox", ImplBase::onClickFilter, this); - - mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); - - // create preview window - LLRect full_screen_rect = getRootView()->getRect(); - LLSnapshotLivePreview::Params p; - p.rect(full_screen_rect); - LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); - LLView* parent_view = gSnapshotFloaterView->getParent(); - - parent_view->removeChild(gSnapshotFloaterView); - // make sure preview is below snapshot floater - parent_view->addChild(previewp); - parent_view->addChild(gSnapshotFloaterView); - - //move snapshot floater to special purpose snapshotfloaterview - gFloaterView->removeChild(this); - gSnapshotFloaterView->addChild(this); - - impl->mPreviewHandle = previewp->getHandle(); - previewp->setContainer(this); - impl->updateControls(this); - impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot")); - impl->updateLayout(this); - - previewp->mKeepAspectRatio = FALSE; - previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect()); - - return TRUE; -} - -// virtual -void LLFloaterOutfitSnapshot::onOpen(const LLSD& key) -{ - LLSnapshotLivePreview* preview = getPreviewView(); - if (preview) - { - LL_DEBUGS() << "opened, updating snapshot" << LL_ENDL; - preview->updateSnapshot(TRUE); - } - focusFirstItem(FALSE); - gSnapshotFloaterView->setEnabled(TRUE); - gSnapshotFloaterView->setVisible(TRUE); - gSnapshotFloaterView->adjustToFitScreen(this, FALSE); - - impl->updateControls(this); - impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot")); - impl->updateLayout(this); - - LLPanel* snapshot_panel = getChild<LLPanel>("panel_outfit_snapshot_inventory"); - snapshot_panel->onOpen(LLSD()); - postPanelSwitch(); - -} - -void LLFloaterOutfitSnapshot::onExtendFloater() -{ - impl->setAdvanced(gSavedSettings.getBOOL("AdvanceOutfitSnapshot")); -} - -// static -void LLFloaterOutfitSnapshot::update() -{ - LLFloaterOutfitSnapshot* inst = findInstance(); - if (inst != NULL) - { - inst->impl->updateLivePreview(); - } -} - - -// static -LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::findInstance() -{ - return LLFloaterReg::findTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot"); -} - -// static -LLFloaterOutfitSnapshot* LLFloaterOutfitSnapshot::getInstance() -{ - return LLFloaterReg::getTypedInstance<LLFloaterOutfitSnapshot>("outfit_snapshot"); -} - -// virtual -void LLFloaterOutfitSnapshot::saveTexture() -{ - LL_DEBUGS() << "saveTexture" << LL_ENDL; - - LLSnapshotLivePreview* previewp = getPreviewView(); - if (!previewp) - { - llassert(previewp != NULL); - return; - } - - if (mOutfitGallery) - { - mOutfitGallery->onBeforeOutfitSnapshotSave(); - } - previewp->saveTexture(TRUE, getOutfitID().asString()); - if (mOutfitGallery) - { - mOutfitGallery->onAfterOutfitSnapshotSave(); - } - closeFloater(); -} - -///---------------------------------------------------------------------------- -/// Class LLOutfitSnapshotFloaterView -///---------------------------------------------------------------------------- - -LLOutfitSnapshotFloaterView::LLOutfitSnapshotFloaterView(const Params& p) : LLFloaterView(p) -{ -} - -LLOutfitSnapshotFloaterView::~LLOutfitSnapshotFloaterView() -{ -} diff --git a/indra/newview/llfloateroutfitsnapshot.h b/indra/newview/llfloateroutfitsnapshot.h deleted file mode 100644 index bee386ec63..0000000000 --- a/indra/newview/llfloateroutfitsnapshot.h +++ /dev/null @@ -1,123 +0,0 @@ -/** - * @file llfloateroutfitsnapshot.h - * @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2016, 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_LLFLOATEROUTFITSNAPSHOT_H -#define LL_LLFLOATEROUTFITSNAPSHOT_H - -#include "llfloater.h" -#include "llfloatersnapshot.h" -#include "lloutfitgallery.h" -#include "llsnapshotlivepreview.h" - -///---------------------------------------------------------------------------- -/// Class LLFloaterOutfitSnapshot -///---------------------------------------------------------------------------- - -class LLFloaterOutfitSnapshot : public LLFloaterSnapshotBase -{ - LOG_CLASS(LLFloaterOutfitSnapshot); - -public: - - LLFloaterOutfitSnapshot(const LLSD& key); - /*virtual*/ ~LLFloaterOutfitSnapshot(); - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); - - static void update(); - - void onExtendFloater(); - - static LLFloaterOutfitSnapshot* getInstance(); - static LLFloaterOutfitSnapshot* findInstance(); - /*virtual*/ void saveTexture(); - - const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); } - - void setOutfitID(LLUUID id) { mOutfitID = id; } - LLUUID getOutfitID() { return mOutfitID; } - void setGallery(LLOutfitGallery* gallery) { mOutfitGallery = gallery; } - - class Impl; - friend class Impl; -private: - - LLUUID mOutfitID; - LLOutfitGallery* mOutfitGallery; -}; - -///---------------------------------------------------------------------------- -/// Class LLFloaterOutfitSnapshot::Impl -///---------------------------------------------------------------------------- - -class LLFloaterOutfitSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase -{ - LOG_CLASS(LLFloaterOutfitSnapshot::Impl); -public: - Impl(LLFloaterSnapshotBase* floater) - : LLFloaterSnapshotBase::ImplBase(floater) - {} - ~Impl() - {} - void updateResolution(void* data); - - static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status); - - /*virtual*/ LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true); - /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater); - /*virtual*/ std::string getSnapshotPanelPrefix(); - - /*virtual*/ void updateControls(LLFloaterSnapshotBase* floater); - -private: - /*virtual*/ LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater); - /*virtual*/ void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null); -}; - -///---------------------------------------------------------------------------- -/// Class LLOutfitSnapshotFloaterView -///---------------------------------------------------------------------------- - -class LLOutfitSnapshotFloaterView : public LLFloaterView -{ -public: - struct Params - : public LLInitParam::Block<Params, LLFloaterView::Params> - { - }; - -protected: - LLOutfitSnapshotFloaterView(const Params& p); - friend class LLUICtrlFactory; - -public: - virtual ~LLOutfitSnapshotFloaterView(); -}; - -extern LLOutfitSnapshotFloaterView* gOutfitSnapshotFloaterView; - -#endif // LL_LLFLOATEROUTFITSNAPSHOT_H diff --git a/indra/newview/llfloaterpathfindinglinksets.cpp b/indra/newview/llfloaterpathfindinglinksets.cpp index 1e46d7a402..03aede94c6 100644 --- a/indra/newview/llfloaterpathfindinglinksets.cpp +++ b/indra/newview/llfloaterpathfindinglinksets.cpp @@ -44,6 +44,7 @@ #include "llpathfindinglinkset.h" #include "llpathfindinglinksetlist.h" #include "llpathfindingmanager.h" +#include "llsearcheditor.h" #include "llscrolllistitem.h" #include "llsd.h" #include "lltextbase.h" @@ -114,17 +115,13 @@ BOOL LLFloaterPathfindingLinksets::postBuild() { mBeaconColor = LLUIColorTable::getInstance()->getColor("PathfindingLinksetBeaconColor"); - mFilterByName = findChild<LLLineEditor>("filter_by_name"); - llassert(mFilterByName != NULL); - mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); - mFilterByName->setSelectAllonFocusReceived(true); - mFilterByName->setCommitOnFocusLost(true); - - mFilterByDescription = findChild<LLLineEditor>("filter_by_description"); - llassert(mFilterByDescription != NULL); - mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); - mFilterByDescription->setSelectAllonFocusReceived(true); - mFilterByDescription->setCommitOnFocusLost(true); + mFilterByName = getChild<LLSearchEditor>("filter_by_name"); + mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); + mFilterByName->setCommitOnFocusLost(true); + + mFilterByDescription = getChild<LLSearchEditor>("filter_by_description"); + mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); + mFilterByDescription->setCommitOnFocusLost(true); mFilterByLinksetUse = findChild<LLComboBox>("filter_by_linkset_use"); llassert(mFilterByLinksetUse != NULL); diff --git a/indra/newview/llfloaterpathfindinglinksets.h b/indra/newview/llfloaterpathfindinglinksets.h index 7149da9215..a954d8a8ec 100644 --- a/indra/newview/llfloaterpathfindinglinksets.h +++ b/indra/newview/llfloaterpathfindinglinksets.h @@ -42,6 +42,7 @@ class LLSD; class LLTextBase; class LLUICtrl; class LLVector3; +class LLSearchEditor; class LLFloaterPathfindingLinksets : public LLFloaterPathfindingObjects { @@ -105,8 +106,8 @@ private: LLPathfindingLinkset::ELinksetUse convertToLinksetUse(LLSD pXuiValue) const; LLSD convertToXuiValue(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; - LLLineEditor *mFilterByName; - LLLineEditor *mFilterByDescription; + LLSearchEditor *mFilterByName; + LLSearchEditor *mFilterByDescription; LLComboBox *mFilterByLinksetUse; LLComboBox *mEditLinksetUse; LLScrollListItem *mEditLinksetUseUnset; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 273810e8d4..6909ad513d 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -512,6 +512,7 @@ void LLFloaterPreference::saveSettings() if (panel) panel->saveSettings(); } + saveIgnoredNotifications(); } void LLFloaterPreference::apply() @@ -628,6 +629,8 @@ void LLFloaterPreference::cancel() gSavedSettings.setString("PresetGraphicActive", mSavedGraphicsPreset); LLPresetsManager::getInstance()->triggerChangeSignal(); } + + restoreIgnoredNotifications(); } void LLFloaterPreference::onOpen(const LLSD& key) @@ -1505,6 +1508,10 @@ void LLFloaterPreference::onClickEnablePopup() } buildPopupLists(); + if (!mFilterEdit->getText().empty()) + { + filterIgnorableNotifications(); + } } void LLFloaterPreference::onClickDisablePopup() @@ -1520,6 +1527,10 @@ void LLFloaterPreference::onClickDisablePopup() } buildPopupLists(); + if (!mFilterEdit->getText().empty()) + { + filterIgnorableNotifications(); + } } void LLFloaterPreference::resetAllIgnored() @@ -3545,11 +3556,24 @@ void LLFloaterPreference::onUpdateFilterTerm(bool force) return; mSearchData->mRootTab->hightlightAndHide( seachValue ); + filterIgnorableNotifications(); + LLTabContainer *pRoot = getChild< LLTabContainer >( "pref core" ); if( pRoot ) pRoot->selectFirstTab(); } +void LLFloaterPreference::filterIgnorableNotifications() +{ + bool visible = getChildRef<LLScrollListCtrl>("enabled_popups").highlightMatchingItems(mFilterEdit->getValue()); + visible |= getChildRef<LLScrollListCtrl>("disabled_popups").highlightMatchingItems(mFilterEdit->getValue()); + + if (visible) + { + getChildRef<LLTabContainer>("pref core").setTabVisibility( getChild<LLPanel>("msgs"), true ); + } +} + void collectChildren( LLView const *aView, ll::prefs::PanelDataPtr aParentPanel, ll::prefs::TabContainerDataPtr aParentTabContainer ) { if( !aView ) @@ -3638,3 +3662,28 @@ void LLFloaterPreference::collectSearchableItems() } mSearchDataDirty = false; } + +void LLFloaterPreference::saveIgnoredNotifications() +{ + for (LLNotifications::TemplateMap::const_iterator iter = LLNotifications::instance().templatesBegin(); + iter != LLNotifications::instance().templatesEnd(); + ++iter) + { + LLNotificationTemplatePtr templatep = iter->second; + LLNotificationFormPtr formp = templatep->mForm; + + LLNotificationForm::EIgnoreType ignore = formp->getIgnoreType(); + if (ignore <= LLNotificationForm::IGNORE_NO) + continue; + + mIgnorableNotifs[templatep->mName] = !formp->getIgnored(); + } +} + +void LLFloaterPreference::restoreIgnoredNotifications() +{ + for (std::map<std::string, bool>::iterator it = mIgnorableNotifs.begin(); it != mIgnorableNotifs.end(); ++it) + { + LLUI::getInstance()->mSettingGroups["ignores"]->setBOOL(it->first, it->second); + } +} diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 542df18ddb..e312c35135 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -143,6 +143,9 @@ public: // cancel() can restore them. void saveSettings(); + void saveIgnoredNotifications(); + void restoreIgnoredNotifications(); + void setCacheLocation(const LLStringExplicit& location); void onClickSetCache(); @@ -223,6 +226,9 @@ private: void onUpdateFilterTerm( bool force = false ); void collectSearchableItems(); + void filterIgnorableNotifications(); + + std::map<std::string, bool> mIgnorableNotifs; }; class LLPanelPreference : public LLPanel diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 3746b9b6c2..40fe11b309 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -421,7 +421,6 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) for(S32 i = 0; i < number_parcels; i++) { std::string parcel_name = content["parcels"][i]["name"].asString(); - LLUUID parcel_id = content["parcels"][i]["id"].asUUID(); S32 number_objects = content["parcels"][i]["objects"].size(); S32 local_id = 0; diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index bb3ed77772..7e6af45515 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -45,7 +45,7 @@ class LLSearchHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { } + LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_CLICK_ONLY) { } bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableSearch")) diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp index 186994c857..3c7f341613 100644 --- a/indra/newview/llfloatersettingsdebug.cpp +++ b/indra/newview/llfloatersettingsdebug.cpp @@ -2,9 +2,9 @@ * @file llfloatersettingsdebug.cpp * @brief floater for debugging internal viewer settings * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2022, 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 @@ -27,8 +27,8 @@ #include "llviewerprecompiledheaders.h" #include "llfloatersettingsdebug.h" #include "llfloater.h" +#include "llfiltereditor.h" #include "lluictrlfactory.h" -//#include "llfirstuse.h" #include "llcombobox.h" #include "llspinctrl.h" #include "llcolorswatch.h" @@ -37,12 +37,11 @@ LLFloaterSettingsDebug::LLFloaterSettingsDebug(const LLSD& key) -: LLFloater(key) +: LLFloater(key), + mSettingList(NULL) { - mCommitCallbackRegistrar.add("SettingSelect", boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this,_1)); mCommitCallbackRegistrar.add("CommitSettings", boost::bind(&LLFloaterSettingsDebug::onCommitSettings, this)); mCommitCallbackRegistrar.add("ClickDefault", boost::bind(&LLFloaterSettingsDebug::onClickDefault, this)); - } LLFloaterSettingsDebug::~LLFloaterSettingsDebug() @@ -50,59 +49,43 @@ LLFloaterSettingsDebug::~LLFloaterSettingsDebug() BOOL LLFloaterSettingsDebug::postBuild() { - LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo"); + enableResizeCtrls(true, false, true); - struct f : public LLControlGroup::ApplyFunctor - { - LLComboBox* combo; - f(LLComboBox* c) : combo(c) {} - virtual void apply(const std::string& name, LLControlVariable* control) - { - if (!control->isHiddenFromSettingsEditor()) - { - combo->add(name, (void*)control); - } - } - } func(settings_combo); + mComment = getChild<LLTextEditor>("comment_text"); - std::string key = getKey().asString(); - if (key == "all" || key == "base") - { - gSavedSettings.applyToAll(&func); - } - if (key == "all" || key == "account") - { - gSavedPerAccountSettings.applyToAll(&func); - } + getChild<LLFilterEditor>("filter_input")->setCommitCallback(boost::bind(&LLFloaterSettingsDebug::setSearchFilter, this, _2)); + + mSettingList = getChild<LLScrollListCtrl>("setting_list"); + mSettingList->setCommitOnSelectionChange(TRUE); + mSettingList->setCommitCallback(boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this)); + + updateList(); + + gSavedSettings.getControl("DebugSettingsHideDefault")->getCommitSignal()->connect(boost::bind(&LLFloaterSettingsDebug::updateList, this, false)); - settings_combo->sortByName(); - settings_combo->updateSelection(); - mComment = getChild<LLTextEditor>("comment_text"); return TRUE; } void LLFloaterSettingsDebug::draw() { - LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo"); - LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata(); - updateControl(controlp); + LLScrollListItem* first_selected = mSettingList->getFirstSelected(); + if (first_selected) + { + LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata(); + updateControl(controlp); + } LLFloater::draw(); } -//static -void LLFloaterSettingsDebug::onSettingSelect(LLUICtrl* ctrl) -{ - LLComboBox* combo_box = (LLComboBox*)ctrl; - LLControlVariable* controlp = (LLControlVariable*)combo_box->getCurrentUserdata(); - - updateControl(controlp); -} - void LLFloaterSettingsDebug::onCommitSettings() { - LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo"); - LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata(); + LLScrollListItem* first_selected = mSettingList->getFirstSelected(); + if (!first_selected) + { + return; + } + LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata(); if (!controlp) { @@ -176,19 +159,23 @@ void LLFloaterSettingsDebug::onCommitSettings() default: break; } + updateDefaultColumn(controlp); } // static void LLFloaterSettingsDebug::onClickDefault() { - LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo"); - LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata(); - - if (controlp) - { - controlp->resetToDefault(true); - updateControl(controlp); - } + LLScrollListItem* first_selected = mSettingList->getFirstSelected(); + if (first_selected) + { + LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata(); + if (controlp) + { + controlp->resetToDefault(true); + updateDefaultColumn(controlp); + updateControl(controlp); + } + } } // we've switched controls, or doing per-frame update, so update spinners, etc. @@ -207,23 +194,30 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp) return; } - spinner1->setVisible(FALSE); - spinner2->setVisible(FALSE); - spinner3->setVisible(FALSE); - spinner4->setVisible(FALSE); - color_swatch->setVisible(FALSE); - getChildView("val_text")->setVisible( FALSE); - mComment->setText(LLStringUtil::null); + hideUIControls(); - if (controlp) + if (controlp && !isSettingHidden(controlp)) { eControlType type = controlp->type(); //hide combo box only for non booleans, otherwise this will result in the combo box closing every frame getChildView("boolean_combo")->setVisible( type == TYPE_BOOLEAN); - + getChildView("default_btn")->setVisible(true); + getChildView("setting_name_txt")->setVisible(true); + getChild<LLTextBox>("setting_name_txt")->setText(controlp->getName()); + getChild<LLTextBox>("setting_name_txt")->setToolTip(controlp->getName()); + mComment->setVisible(true); + + std::string old_text = mComment->getText(); + std::string new_text = controlp->getComment(); + // Don't setText if not nessesary, it will reset scroll + // This is a debug UI that reads from xml, there might + // be use cases where comment changes, but not the name + if (old_text != new_text) + { + mComment->setText(controlp->getComment()); + } - mComment->setText(controlp->getComment()); spinner1->setMaxValue(F32_MAX); spinner2->setMaxValue(F32_MAX); spinner3->setMaxValue(F32_MAX); @@ -479,3 +473,166 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp) } } + +void LLFloaterSettingsDebug::updateList(bool skip_selection) +{ + std::string last_selected; + LLScrollListItem* item = mSettingList->getFirstSelected(); + if (item) + { + LLScrollListCell* cell = item->getColumn(1); + if (cell) + { + last_selected = cell->getValue().asString(); + } + } + + mSettingList->deleteAllItems(); + struct f : public LLControlGroup::ApplyFunctor + { + LLScrollListCtrl* setting_list; + LLFloaterSettingsDebug* floater; + std::string selected_setting; + bool skip_selection; + f(LLScrollListCtrl* list, LLFloaterSettingsDebug* floater, std::string setting, bool skip_selection) + : setting_list(list), floater(floater), selected_setting(setting), skip_selection(skip_selection) {} + virtual void apply(const std::string& name, LLControlVariable* control) + { + if (!control->isHiddenFromSettingsEditor() && floater->matchesSearchFilter(name) && !floater->isSettingHidden(control)) + { + LLSD row; + + row["columns"][0]["column"] = "changed_setting"; + row["columns"][0]["value"] = control->isDefault() ? "" : "*"; + + row["columns"][1]["column"] = "setting"; + row["columns"][1]["value"] = name; + + LLScrollListItem* item = setting_list->addElement(row, ADD_BOTTOM, (void*)control); + if (!floater->mSearchFilter.empty() && (selected_setting == name) && !skip_selection) + { + std::string lower_name(name); + LLStringUtil::toLower(lower_name); + if (LLStringUtil::startsWith(lower_name, floater->mSearchFilter)) + { + item->setSelected(true); + } + } + } + } + } func(mSettingList, this, last_selected, skip_selection); + + std::string key = getKey().asString(); + if (key == "all" || key == "base") + { + gSavedSettings.applyToAll(&func); + } + if (key == "all" || key == "account") + { + gSavedPerAccountSettings.applyToAll(&func); + } + + + if (!mSettingList->isEmpty()) + { + if (mSettingList->hasSelectedItem()) + { + mSettingList->scrollToShowSelected(); + } + else if (!mSettingList->hasSelectedItem() && !mSearchFilter.empty() && !skip_selection) + { + if (!mSettingList->selectItemByPrefix(mSearchFilter, false, 1)) + { + mSettingList->selectFirstItem(); + } + mSettingList->scrollToShowSelected(); + } + } + else + { + LLSD row; + + row["columns"][0]["column"] = "changed_setting"; + row["columns"][0]["value"] = ""; + row["columns"][1]["column"] = "setting"; + row["columns"][1]["value"] = "No matching settings."; + + mSettingList->addElement(row); + hideUIControls(); + } +} + +void LLFloaterSettingsDebug::onSettingSelect() +{ + LLScrollListItem* first_selected = mSettingList->getFirstSelected(); + if (first_selected) + { + LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata(); + if (controlp) + { + updateControl(controlp); + } + } +} + +void LLFloaterSettingsDebug::setSearchFilter(const std::string& filter) +{ + if(mSearchFilter == filter) + return; + mSearchFilter = filter; + LLStringUtil::toLower(mSearchFilter); + updateList(); +} + +bool LLFloaterSettingsDebug::matchesSearchFilter(std::string setting_name) +{ + // If the search filter is empty, everything passes. + if (mSearchFilter.empty()) return true; + + LLStringUtil::toLower(setting_name); + std::string::size_type match_name = setting_name.find(mSearchFilter); + + return (std::string::npos != match_name); +} + +bool LLFloaterSettingsDebug::isSettingHidden(LLControlVariable* control) +{ + static LLCachedControl<bool> hide_default(gSavedSettings, "DebugSettingsHideDefault", false); + return hide_default && control->isDefault(); +} + +void LLFloaterSettingsDebug::updateDefaultColumn(LLControlVariable* control) +{ + if (isSettingHidden(control)) + { + hideUIControls(); + updateList(true); + return; + } + + LLScrollListItem* item = mSettingList->getFirstSelected(); + if (item) + { + LLScrollListCell* cell = item->getColumn(0); + if (cell) + { + std::string is_default = control->isDefault() ? "" : "*"; + cell->setValue(is_default); + } + } +} + +void LLFloaterSettingsDebug::hideUIControls() +{ + getChildView("val_spinner_1")->setVisible(false); + getChildView("val_spinner_2")->setVisible(false); + getChildView("val_spinner_3")->setVisible(false); + getChildView("val_spinner_4")->setVisible(false); + getChildView("val_color_swatch")->setVisible(false); + getChildView("val_text")->setVisible(false); + getChildView("default_btn")->setVisible(false); + getChildView("boolean_combo")->setVisible(false); + getChildView("setting_name_txt")->setVisible(false); + mComment->setVisible(false); +} + diff --git a/indra/newview/llfloatersettingsdebug.h b/indra/newview/llfloatersettingsdebug.h index f07e0557e3..888eaadcbd 100644 --- a/indra/newview/llfloatersettingsdebug.h +++ b/indra/newview/llfloatersettingsdebug.h @@ -2,9 +2,9 @@ * @file llfloatersettingsdebug.h * @brief floater for debugging internal viewer settings * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * $LicenseInfo:firstyear=2022&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2022, 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 @@ -30,6 +30,8 @@ #include "llcontrol.h" #include "llfloater.h" +class LLScrollListCtrl; + class LLFloaterSettingsDebug : public LLFloater { @@ -42,18 +44,31 @@ public: void updateControl(LLControlVariable* control); - void onSettingSelect(LLUICtrl* ctrl); void onCommitSettings(); void onClickDefault(); + bool matchesSearchFilter(std::string setting_name); + bool isSettingHidden(LLControlVariable* control); + private: // key - selects which settings to show, one of: // "all", "base", "account", "skin" LLFloaterSettingsDebug(const LLSD& key); virtual ~LLFloaterSettingsDebug(); + + void updateList(bool skip_selection = false); + void onSettingSelect(); + void setSearchFilter(const std::string& filter); + + void updateDefaultColumn(LLControlVariable* control); + void hideUIControls(); + + LLScrollListCtrl* mSettingList; protected: class LLTextEditor* mComment; + + std::string mSearchFilter; }; #endif //LLFLOATERDEBUGSETTINGS_H diff --git a/indra/newview/llfloatersimpleoutfitsnapshot.cpp b/indra/newview/llfloatersimpleoutfitsnapshot.cpp new file mode 100644 index 0000000000..bab2efbbd5 --- /dev/null +++ b/indra/newview/llfloatersimpleoutfitsnapshot.cpp @@ -0,0 +1,333 @@ +/** +* @file llfloatersimpleoutfitsnapshot.cpp +* @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery +* +* $LicenseInfo:firstyear=2022&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2022, 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 "llfloatersimpleoutfitsnapshot.h" + +#include "llfloaterreg.h" +#include "llimagefiltersmanager.h" +#include "llstatusbar.h" // can_afford_transaction() +#include "llnotificationsutil.h" +#include "llagentbenefits.h" +#include "llviewercontrol.h" + +LLSimpleOutfitSnapshotFloaterView* gSimpleOutfitSnapshotFloaterView = NULL; + +const S32 OUTFIT_SNAPSHOT_WIDTH = 256; +const S32 OUTFIT_SNAPSHOT_HEIGHT = 256; + +static LLDefaultChildRegistry::Register<LLSimpleOutfitSnapshotFloaterView> r("simple_snapshot_outfit_floater_view"); + +///---------------------------------------------------------------------------- +/// Class LLFloaterSimpleOutfitSnapshot::Impl +///---------------------------------------------------------------------------- + +LLSnapshotModel::ESnapshotFormat LLFloaterSimpleOutfitSnapshot::Impl::getImageFormat(LLFloaterSnapshotBase* floater) +{ + return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; +} + +LLSnapshotModel::ESnapshotLayerType LLFloaterSimpleOutfitSnapshot::Impl::getLayerType(LLFloaterSnapshotBase* floater) +{ + return LLSnapshotModel::SNAPSHOT_TYPE_COLOR; +} + +void LLFloaterSimpleOutfitSnapshot::Impl::updateControls(LLFloaterSnapshotBase* floater) +{ + LLSnapshotLivePreview* previewp = getPreviewView(); + updateResolution(floater); + if (previewp) + { + previewp->setSnapshotType(LLSnapshotModel::ESnapshotType::SNAPSHOT_TEXTURE); + previewp->setSnapshotFormat(LLSnapshotModel::ESnapshotFormat::SNAPSHOT_FORMAT_PNG); + previewp->setSnapshotBufferType(LLSnapshotModel::ESnapshotLayerType::SNAPSHOT_TYPE_COLOR); + } +} + +std::string LLFloaterSimpleOutfitSnapshot::Impl::getSnapshotPanelPrefix() +{ + return "panel_outfit_snapshot_"; +} + +void LLFloaterSimpleOutfitSnapshot::Impl::updateResolution(void* data) +{ + LLFloaterSimpleOutfitSnapshot *view = (LLFloaterSimpleOutfitSnapshot *)data; + + if (!view) + { + llassert(view); + return; + } + + S32 width = OUTFIT_SNAPSHOT_WIDTH; + S32 height = OUTFIT_SNAPSHOT_HEIGHT; + + LLSnapshotLivePreview* previewp = getPreviewView(); + if (previewp) + { + S32 original_width = 0, original_height = 0; + previewp->getSize(original_width, original_height); + + if (gSavedSettings.getBOOL("RenderHUDInSnapshot")) + { //clamp snapshot resolution to window size when showing UI HUD in snapshot + width = llmin(width, gViewerWindow->getWindowWidthRaw()); + height = llmin(height, gViewerWindow->getWindowHeightRaw()); + } + + llassert(width > 0 && height > 0); + + previewp->setSize(width, height); + + if (original_width != width || original_height != height) + { + // hide old preview as the aspect ratio could be wrong + checkAutoSnapshot(previewp, FALSE); + previewp->updateSnapshot(TRUE); + } + } +} + +void LLFloaterSimpleOutfitSnapshot::Impl::setStatus(EStatus status, bool ok, const std::string& msg) +{ + switch (status) + { + case STATUS_READY: + mFloater->setCtrlsEnabled(true); + break; + case STATUS_WORKING: + mFloater->setCtrlsEnabled(false); + break; + case STATUS_FINISHED: + mFloater->setCtrlsEnabled(true); + break; + } + + mStatus = status; +} + +///----------------------------------------------------------------re------------ +/// Class LLFloaterSimpleOutfitSnapshot +///---------------------------------------------------------------------------- + +LLFloaterSimpleOutfitSnapshot::LLFloaterSimpleOutfitSnapshot(const LLSD& key) + : LLFloaterSnapshotBase(key), + mOutfitGallery(NULL) +{ + impl = new Impl(this); +} + +LLFloaterSimpleOutfitSnapshot::~LLFloaterSimpleOutfitSnapshot() +{ +} + +BOOL LLFloaterSimpleOutfitSnapshot::postBuild() +{ + getChild<LLUICtrl>("save_btn")->setLabelArg("[UPLOAD_COST]", std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost())); + + childSetAction("new_snapshot_btn", ImplBase::onClickNewSnapshot, this); + childSetAction("save_btn", boost::bind(&LLFloaterSimpleOutfitSnapshot::onSend, this)); + childSetAction("cancel_btn", boost::bind(&LLFloaterSimpleOutfitSnapshot::onCancel, this)); + + mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder"); + + // create preview window + LLRect full_screen_rect = getRootView()->getRect(); + LLSnapshotLivePreview::Params p; + p.rect(full_screen_rect); + LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p); + LLView* parent_view = gSnapshotFloaterView->getParent(); + + parent_view->removeChild(gSnapshotFloaterView); + // make sure preview is below snapshot floater + parent_view->addChild(previewp); + parent_view->addChild(gSnapshotFloaterView); + + //move snapshot floater to special purpose snapshotfloaterview + gFloaterView->removeChild(this); + gSnapshotFloaterView->addChild(this); + + impl->mPreviewHandle = previewp->getHandle(); + previewp->setContainer(this); + impl->updateControls(this); + impl->setAdvanced(true); + impl->setSkipReshaping(true); + + previewp->mKeepAspectRatio = FALSE; + previewp->setThumbnailPlaceholderRect(getThumbnailPlaceholderRect()); + previewp->setAllowRenderUI(false); + + return TRUE; +} +const S32 PREVIEW_OFFSET_X = 12; +const S32 PREVIEW_OFFSET_Y = 70; + +void LLFloaterSimpleOutfitSnapshot::draw() +{ + LLSnapshotLivePreview* previewp = getPreviewView(); + + if (previewp && (previewp->isSnapshotActive() || previewp->getThumbnailLock())) + { + // don't render snapshot window in snapshot, even if "show ui" is turned on + return; + } + + LLFloater::draw(); + + if (previewp && !isMinimized() && mThumbnailPlaceholder->getVisible()) + { + if(previewp->getThumbnailImage()) + { + bool working = impl->getStatus() == ImplBase::STATUS_WORKING; + const LLRect& thumbnail_rect = getThumbnailPlaceholderRect(); + const S32 thumbnail_w = previewp->getThumbnailWidth(); + const S32 thumbnail_h = previewp->getThumbnailHeight(); + + S32 offset_x = PREVIEW_OFFSET_X; + S32 offset_y = PREVIEW_OFFSET_Y; + + gGL.matrixMode(LLRender::MM_MODELVIEW); + // Apply floater transparency to the texture unless the floater is focused. + F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency(); + LLColor4 color = working ? LLColor4::grey4 : LLColor4::white; + gl_draw_scaled_image(offset_x, offset_y, + thumbnail_w, thumbnail_h, + previewp->getThumbnailImage(), color % alpha); +#if LL_DARWIN + std::string alpha_color = getTransparencyType() == TT_ACTIVE ? "OutfitSnapshotMacMask" : "OutfitSnapshotMacMask2"; +#else + std::string alpha_color = getTransparencyType() == TT_ACTIVE ? "FloaterFocusBackgroundColor" : "DkGray"; +#endif + + previewp->drawPreviewRect(offset_x, offset_y, LLUIColorTable::instance().getColor(alpha_color)); + + gGL.pushUIMatrix(); + LLUI::translate((F32) thumbnail_rect.mLeft, (F32) thumbnail_rect.mBottom); + mThumbnailPlaceholder->draw(); + gGL.popUIMatrix(); + } + } + impl->updateLayout(this); +} + +void LLFloaterSimpleOutfitSnapshot::onOpen(const LLSD& key) +{ + LLSnapshotLivePreview* preview = getPreviewView(); + if (preview) + { + preview->updateSnapshot(TRUE); + } + focusFirstItem(FALSE); + gSnapshotFloaterView->setEnabled(TRUE); + gSnapshotFloaterView->setVisible(TRUE); + gSnapshotFloaterView->adjustToFitScreen(this, FALSE); + + impl->updateControls(this); + impl->setStatus(ImplBase::STATUS_READY); +} + +void LLFloaterSimpleOutfitSnapshot::onCancel() +{ + closeFloater(); +} + +void LLFloaterSimpleOutfitSnapshot::onSend() +{ + S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(); + if (can_afford_transaction(expected_upload_cost)) + { + saveTexture(); + postSave(); + } + else + { + LLSD args; + args["COST"] = llformat("%d", expected_upload_cost); + LLNotificationsUtil::add("ErrorPhotoCannotAfford", args); + inventorySaveFailed(); + } +} + +void LLFloaterSimpleOutfitSnapshot::postSave() +{ + impl->setStatus(ImplBase::STATUS_WORKING); +} + +// static +void LLFloaterSimpleOutfitSnapshot::update() +{ + LLFloaterSimpleOutfitSnapshot* inst = findInstance(); + if (inst != NULL) + { + inst->impl->updateLivePreview(); + } +} + + +// static +LLFloaterSimpleOutfitSnapshot* LLFloaterSimpleOutfitSnapshot::findInstance() +{ + return LLFloaterReg::findTypedInstance<LLFloaterSimpleOutfitSnapshot>("simple_outfit_snapshot"); +} + +// static +LLFloaterSimpleOutfitSnapshot* LLFloaterSimpleOutfitSnapshot::getInstance() +{ + return LLFloaterReg::getTypedInstance<LLFloaterSimpleOutfitSnapshot>("simple_outfit_snapshot"); +} + +void LLFloaterSimpleOutfitSnapshot::saveTexture() +{ + LLSnapshotLivePreview* previewp = getPreviewView(); + if (!previewp) + { + llassert(previewp != NULL); + return; + } + + if (mOutfitGallery) + { + mOutfitGallery->onBeforeOutfitSnapshotSave(); + } + previewp->saveTexture(TRUE, getOutfitID().asString()); + if (mOutfitGallery) + { + mOutfitGallery->onAfterOutfitSnapshotSave(); + } + closeFloater(); +} + +///---------------------------------------------------------------------------- +/// Class LLSimpleOutfitSnapshotFloaterView +///---------------------------------------------------------------------------- + +LLSimpleOutfitSnapshotFloaterView::LLSimpleOutfitSnapshotFloaterView(const Params& p) : LLFloaterView(p) +{ +} + +LLSimpleOutfitSnapshotFloaterView::~LLSimpleOutfitSnapshotFloaterView() +{ +} diff --git a/indra/newview/llfloatersimpleoutfitsnapshot.h b/indra/newview/llfloatersimpleoutfitsnapshot.h new file mode 100644 index 0000000000..cc9a6c5d1e --- /dev/null +++ b/indra/newview/llfloatersimpleoutfitsnapshot.h @@ -0,0 +1,129 @@ +/** +* @file llfloatersimpleoutfitsnapshot.h +* @brief Snapshot preview window for saving as an outfit thumbnail in visual outfit gallery +* +* $LicenseInfo:firstyear=2022&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2022, 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_LLFLOATERSIMPLEOUTFITSNAPSHOT_H +#define LL_LLFLOATERSIMPLEOUTFITSNAPSHOT_H + +#include "llfloater.h" +#include "llfloatersnapshot.h" +#include "lloutfitgallery.h" +#include "llsnapshotlivepreview.h" + +///---------------------------------------------------------------------------- +/// Class LLFloaterSimpleOutfitSnapshot +///---------------------------------------------------------------------------- + +class LLFloaterSimpleOutfitSnapshot : public LLFloaterSnapshotBase +{ + LOG_CLASS(LLFloaterSimpleOutfitSnapshot); + +public: + + LLFloaterSimpleOutfitSnapshot(const LLSD& key); + ~LLFloaterSimpleOutfitSnapshot(); + + BOOL postBuild(); + void onOpen(const LLSD& key); + void draw(); + + static void update(); + + static LLFloaterSimpleOutfitSnapshot* getInstance(); + static LLFloaterSimpleOutfitSnapshot* findInstance(); + void saveTexture(); + + const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); } + + void setOutfitID(LLUUID id) { mOutfitID = id; } + LLUUID getOutfitID() { return mOutfitID; } + void setGallery(LLOutfitGallery* gallery) { mOutfitGallery = gallery; } + + void postSave(); + + class Impl; + friend class Impl; + +private: + void onSend(); + void onCancel(); + + LLUUID mOutfitID; + LLOutfitGallery* mOutfitGallery; +}; + +///---------------------------------------------------------------------------- +/// Class LLFloaterSimpleOutfitSnapshot::Impl +///---------------------------------------------------------------------------- + +class LLFloaterSimpleOutfitSnapshot::Impl : public LLFloaterSnapshotBase::ImplBase +{ + LOG_CLASS(LLFloaterSimpleOutfitSnapshot::Impl); +public: + Impl(LLFloaterSnapshotBase* floater) + : LLFloaterSnapshotBase::ImplBase(floater) + {} + ~Impl() + {} + void updateResolution(void* data); + + static void onSnapshotUploadFinished(LLFloaterSnapshotBase* floater, bool status); + + LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true) { return NULL; } + LLSnapshotModel::ESnapshotFormat getImageFormat(LLFloaterSnapshotBase* floater); + std::string getSnapshotPanelPrefix(); + + void updateControls(LLFloaterSnapshotBase* floater); + + void setStatus(EStatus status, bool ok = true, const std::string& msg = LLStringUtil::null); + +private: + LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater); + void setFinished(bool finished, bool ok = true, const std::string& msg = LLStringUtil::null) {}; +}; + +///---------------------------------------------------------------------------- +/// Class LLSimpleOutfitSnapshotFloaterView +///---------------------------------------------------------------------------- + +class LLSimpleOutfitSnapshotFloaterView : public LLFloaterView +{ +public: + struct Params + : public LLInitParam::Block<Params, LLFloaterView::Params> + { + }; + +protected: + LLSimpleOutfitSnapshotFloaterView(const Params& p); + friend class LLUICtrlFactory; + +public: + virtual ~LLSimpleOutfitSnapshotFloaterView(); +}; + +extern LLSimpleOutfitSnapshotFloaterView* gSimpleOutfitSnapshotFloaterView; + +#endif // LL_LLFLOATERSIMPLEOUTFITSNAPSHOT_H diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 83212230e5..6b9d4580dc 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -176,16 +176,20 @@ void LLFloaterSnapshotBase::ImplBase::updateLayout(LLFloaterSnapshotBase* floate LLUICtrl* thumbnail_placeholder = floaterp->getChild<LLUICtrl>("thumbnail_placeholder"); thumbnail_placeholder->setVisible(mAdvanced); - thumbnail_placeholder->reshape(panel_width, thumbnail_placeholder->getRect().getHeight()); + floaterp->getChild<LLUICtrl>("image_res_text")->setVisible(mAdvanced); floaterp->getChild<LLUICtrl>("file_size_label")->setVisible(mAdvanced); if (floaterp->hasChild("360_label", TRUE)) { floaterp->getChild<LLUICtrl>("360_label")->setVisible(mAdvanced); } - if(!floaterp->isMinimized()) + if (!mSkipReshaping) { - floaterp->reshape(floater_width, floaterp->getRect().getHeight()); + thumbnail_placeholder->reshape(panel_width, thumbnail_placeholder->getRect().getHeight()); + if (!floaterp->isMinimized()) + { + floaterp->reshape(floater_width, floaterp->getRect().getHeight()); + } } bool use_freeze_frame = floaterp->getChild<LLUICtrl>("freeze_frame_check")->getValue().asBoolean(); @@ -1193,7 +1197,7 @@ S32 LLFloaterSnapshotBase::notify(const LLSD& info) // The refresh button is initially hidden. We show it after the first update, // i.e. when preview appears. - if (!mRefreshBtn->getVisible()) + if (mRefreshBtn && !mRefreshBtn->getVisible()) { mRefreshBtn->setVisible(true); } diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index 7ec133ff45..7fc62a2746 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -59,9 +59,9 @@ public: const LLRect& getThumbnailPlaceholderRect() { return mThumbnailPlaceholder->getRect(); } - void setRefreshLabelVisible(bool value) { mRefreshLabel->setVisible(value); } - void setSuccessLabelPanelVisible(bool value) { mSucceessLblPanel->setVisible(value); } - void setFailureLabelPanelVisible(bool value) { mFailureLblPanel->setVisible(value); } + void setRefreshLabelVisible(bool value) { if (mRefreshLabel) mRefreshLabel->setVisible(value); } + void setSuccessLabelPanelVisible(bool value) { if (mSucceessLblPanel) mSucceessLblPanel->setVisible(value); } + void setFailureLabelPanelVisible(bool value) { if (mFailureLblPanel) mFailureLblPanel->setVisible(value); } void inventorySaveFailed(); class ImplBase; @@ -88,6 +88,7 @@ public: mLastToolset(NULL), mAspectRatioCheckOff(false), mNeedRefresh(false), + mSkipReshaping(false), mStatus(STATUS_READY), mFloater(floater) {} @@ -120,6 +121,7 @@ public: static BOOL updatePreviewList(bool initialized); void setAdvanced(bool advanced) { mAdvanced = advanced; } + void setSkipReshaping(bool skip) { mSkipReshaping = skip; } virtual LLSnapshotModel::ESnapshotLayerType getLayerType(LLFloaterSnapshotBase* floater) = 0; virtual void checkAutoSnapshot(LLSnapshotLivePreview* floater, BOOL update_thumbnail = FALSE); @@ -135,6 +137,7 @@ public: bool mAspectRatioCheckOff; bool mNeedRefresh; bool mAdvanced; + bool mSkipReshaping; EStatus mStatus; }; diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index b1316e386d..082bb888b1 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -289,7 +289,6 @@ void LLFloaterTranslationSettings::onBtnOK() gSavedSettings.setString("TranslationService", getSelectedService()); gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey()); gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); - (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))-> - showTranslationCheckbox(LLTranslate::isTranslationConfigured()); + closeFloater(false); } diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 01bfae8934..704abd269f 100755 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -122,7 +122,7 @@ class LLWorldMapHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE ) { } + LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_CLICK_ONLY ) { } bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) @@ -159,7 +159,7 @@ class LLMapTrackAvatarHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_THROTTLE) + LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_CLICK_ONLY) { } diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index 84a1278767..be52e280e1 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -52,7 +52,32 @@ class LLGroupHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_THROTTLE) { } + LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_CLICK_ONLY) { } + + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { + if (params.size() < 1) + { + return true; // don't block, will fail later + } + + if (nav_type == NAV_TYPE_CLICKED) + { + return true; + } + + const std::string verb = params[0].asString(); + if (verb == "create") + { + return false; + } + return true; + } + bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { @@ -175,8 +200,7 @@ public: virtual void processGroupData() = 0; protected: LLUUID mGroupId; -private: - bool mRequestProcessed; + bool mRequestProcessed; }; class LLFetchLeaveGroupData: public LLFetchGroupMemberData @@ -189,6 +213,22 @@ public: { LLGroupActions::processLeaveGroupDataResponse(mGroupId); } + void changed(LLGroupChange gc) + { + if (gc == GC_PROPERTIES && !mRequestProcessed) + { + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupId); + if (!gdatap) + { + LL_WARNS() << "GroupData was NULL" << LL_ENDL; + } + else + { + processGroupData(); + mRequestProcessed = true; + } + } + } }; LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL; diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index 0524313a5c..af2d168aef 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -55,6 +55,7 @@ #include "llviewerwindow.h" #include "llviewerregion.h" #include "llvoavatarself.h" +#include "llworld.h" #include "boost/lexical_cast.hpp" #if LL_MSVC @@ -520,8 +521,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, dialog, parent_estate_id, region_id, - position, - true); + position); if (!gIMMgr->isDNDMessageSend(session_id)) { @@ -572,6 +572,15 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, } if (!mute_im) { + bool region_message = false; + if (region_id.isNull()) + { + LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(from_id); + if (regionp) + { + region_message = true; + } + } gIMMgr->addMessage( session_id, from_id, @@ -583,7 +592,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, parent_estate_id, region_id, position, - true); + region_message); } else { @@ -1102,8 +1111,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, IM_SESSION_INVITE, parent_estate_id, region_id, - position, - true); + position); } else { @@ -1128,8 +1136,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, IM_SESSION_INVITE, parent_estate_id, region_id, - position, - true); + position); } break; @@ -1561,7 +1568,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url) return; } - if (messages.emptyArray()) + if (messages.size() == 0) { // Nothing to process return; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4d6ebf9cbb..3607e49b4a 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -760,7 +760,7 @@ void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_ } } -void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history) +void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history, bool is_region_msg) { LLSD message; message["from"] = from; @@ -769,6 +769,7 @@ void LLIMModel::LLIMSession::addMessage(const std::string& from, const LLUUID& f message["time"] = time; message["index"] = (LLSD::Integer)mMsgs.size(); message["is_history"] = is_history; + message["is_region_msg"] = is_region_msg; LL_DEBUGS("UIUsage") << "addMessage " << " from " << from << " from_id " << from_id << " utf8_text " << utf8_text << " time " << time << " is_history " << is_history << " session mType " << mType << LL_ENDL; if (from_id == gAgent.getID()) @@ -1149,7 +1150,7 @@ void LLIMModel::sendNoUnreadMessages(const LLUUID& session_id) mNoUnreadMsgsSignal(arg); } -bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) { +bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text, bool is_region_msg) { LLIMSession* session = findIMSession(session_id); @@ -1159,7 +1160,7 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, return false; } - session->addMessage(from, from_id, utf8_text, LLLogChat::timestamp(false)); //might want to add date separately + session->addMessage(from, from_id, utf8_text, LLLogChat::timestamp(false), false, is_region_msg); //might want to add date separately return true; } @@ -1197,9 +1198,9 @@ bool LLIMModel::proccessOnlineOfflineNotification( } bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, - const std::string& utf8_text, bool log2file /* = true */) { + const std::string& utf8_text, bool log2file, bool is_region_msg) { - LLIMSession* session = addMessageSilently(session_id, from, from_id, utf8_text, log2file); + LLIMSession* session = addMessageSilently(session_id, from, from_id, utf8_text, log2file, is_region_msg); if (!session) return false; //good place to add some1 to recent list @@ -1224,7 +1225,7 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co } LLIMModel::LLIMSession* LLIMModel::addMessageSilently(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, - const std::string& utf8_text, bool log2file /* = true */) + const std::string& utf8_text, bool log2file, bool is_region_msg) { LLIMSession* session = findIMSession(session_id); @@ -1240,7 +1241,7 @@ LLIMModel::LLIMSession* LLIMModel::addMessageSilently(const LLUUID& session_id, from_name = SYSTEM_FROM; } - addToHistory(session_id, from_name, from_id, utf8_text); + addToHistory(session_id, from_name, from_id, utf8_text, is_region_msg); if (log2file) { logToFile(getHistoryFileName(session_id), from_name, from_id, utf8_text); @@ -2114,8 +2115,6 @@ void LLOutgoingCallDialog::show(const LLSD& key) std::string callee_name = mPayload["session_name"].asString(); - LLUUID session_id = mPayload["session_id"].asUUID(); - if (callee_name == "anonymous") // obsolete? Likely was part of avaline support { callee_name = getString("anonymous"); @@ -2499,7 +2498,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload } } - LLUUID new_session_id = gIMMgr->addSession(correct_session_name, type, session_id, true); + gIMMgr->addSession(correct_session_name, type, session_id, true); std::string url = gAgent.getRegion()->getCapability( "ChatSessionRequest"); @@ -2585,7 +2584,7 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) } else { - LLUUID new_session_id = gIMMgr->addSession( + gIMMgr->addSession( payload["session_name"].asString(), type, session_id, true); @@ -2663,7 +2662,7 @@ void LLIMMgr::addMessage( U32 parent_estate_id, const LLUUID& region_id, const LLVector3& position, - bool link_name) // If this is true, then we insert the name and link it to a profile + bool is_region_msg) { LLUUID other_participant_id = target_id; @@ -2735,7 +2734,7 @@ void LLIMMgr::addMessage( //<< "*** region_id: " << region_id << std::endl //<< "*** position: " << position << std::endl; - LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str()); + LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, bonus_info.str(), true, is_region_msg); } // Logically it would make more sense to reject the session sooner, in another area of the @@ -2765,7 +2764,7 @@ void LLIMMgr::addMessage( if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message) { - LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg); + LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg, true, is_region_msg); } // Open conversation floater if offline messages are present @@ -3692,8 +3691,7 @@ public: IM_SESSION_INVITE, message_params["parent_estate_id"].asInteger(), message_params["region_id"].asUUID(), - ll_vector3_from_sd(message_params["position"]), - true); + ll_vector3_from_sd(message_params["position"])); if (LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat)) { diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index fdf9806e2e..326e8f22e3 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -81,7 +81,7 @@ public: void sessionInitReplyReceived(const LLUUID& new_session_id); void addMessagesFromHistory(const std::list<LLSD>& history); - void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history = false); + void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time, const bool is_history = false, bool is_region_msg = false); void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction); /** @deprecated */ @@ -208,13 +208,13 @@ public: * and also saved into a file if log2file is specified. * It sends new message signal for each added message. */ - bool addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true); + bool addMessage(const LLUUID& session_id, const std::string& from, const LLUUID& other_participant_id, const std::string& utf8_text, bool log2file = true, bool is_region_msg = false); /** * Similar to addMessage(...) above but won't send a signal about a new message added */ LLIMModel::LLIMSession* addMessageSilently(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, - const std::string& utf8_text, bool log2file = true); + const std::string& utf8_text, bool log2file = true, bool is_region_msg = false); /** * Add a system message to an IM Model @@ -292,7 +292,7 @@ private: /** * Add message to a list of message associated with session specified by session_id */ - bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text); + bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text, bool is_region_msg = false); }; @@ -334,7 +334,7 @@ public: U32 parent_estate_id = 0, const LLUUID& region_id = LLUUID::null, const LLVector3& position = LLVector3::zero, - bool link_name = false); + bool is_region_msg = false); void addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a0bc1035bf..db347f7096 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -614,7 +614,7 @@ BOOL LLInvFVBridge::isClipboardPasteable() const if (cat) { LLFolderBridge cat_br(mInventoryPanel.get(), mRoot, item_id); - if (!cat_br.isItemCopyable()) + if (!cat_br.isItemCopyable(false)) return FALSE; // Skip to the next item in the clipboard continue; @@ -622,7 +622,7 @@ BOOL LLInvFVBridge::isClipboardPasteable() const // Each item must be copyable to be pastable LLItemBridge item_br(mInventoryPanel.get(), mRoot, item_id); - if (!item_br.isItemCopyable()) + if (!item_br.isItemCopyable(false)) { return FALSE; } @@ -654,6 +654,11 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const { return FALSE; } + + if (gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getLibraryRootFolderID())) + { + return FALSE; + } } const LLViewerInventoryCategory *cat = model->getCategory(objects.at(i)); if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) @@ -729,15 +734,15 @@ void hide_context_entries(LLMenuGL& menu, } bool found = false; - menuentry_vec_t::const_iterator itor2; - for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2) - { - if (*itor2 == name) - { - found = true; - break; - } - } + + std::string myinput; + std::vector<std::string> mylist{ "a", "b", "c" }; + + menuentry_vec_t::const_iterator itor2 = std::find(entries_to_show.begin(), entries_to_show.end(), name); + if (itor2 != entries_to_show.end()) + { + found = true; + } // Don't allow multiple separators in a row (e.g. such as if there are no items // between two separators). @@ -755,7 +760,21 @@ void hide_context_entries(LLMenuGL& menu, menu_item->setVisible(FALSE); } - menu_item->setEnabled(FALSE); + if (menu_item->getEnabled()) + { + // These should stay enabled unless specifically disabled + const menuentry_vec_t exceptions = { + "Detach From Yourself", + "Wearable And Object Wear", + "Wearable Add", + }; + + menuentry_vec_t::const_iterator itor2 = std::find(exceptions.begin(), exceptions.end(), name); + if (itor2 == exceptions.end()) + { + menu_item->setEnabled(FALSE); + } + } } else { @@ -812,6 +831,12 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, { disabled_items.push_back(std::string("Find Original")); } + + items.push_back(std::string("Cut")); + if (!isItemMovable() || !isItemRemovable()) + { + disabled_items.push_back(std::string("Cut")); + } } else { @@ -882,7 +907,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Paste")); } - if (gSavedSettings.getBOOL("InventoryLinking")) + static LLCachedControl<bool> inventory_linking(gSavedSettings, "InventoryLinking", true); + if (inventory_linking) { items.push_back(std::string("Paste As Link")); if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) @@ -2059,7 +2085,8 @@ BOOL LLItemBridge::removeItem() // we can't do this check because we may have items in a folder somewhere that is // not yet in memory, so we don't want false negatives. (If disabled, then we // know we only have links in the Outfits folder which we explicitly fetch.) - if (!gSavedSettings.getBOOL("InventoryLinking")) + static LLCachedControl<bool> inventory_linking(gSavedSettings, "InventoryLinking", true); + if (!inventory_linking) { if (!item->getIsLinkType()) { @@ -2102,22 +2129,25 @@ BOOL LLItemBridge::confirmRemoveItem(const LLSD& notification, const LLSD& respo return FALSE; } -BOOL LLItemBridge::isItemCopyable() const +bool LLItemBridge::isItemCopyable(bool can_copy_as_link) const { - LLViewerInventoryItem* item = getItem(); - if (item) - { - // Can't copy worn objects. - // Worn objects are tied to their inworld conterparts - // Copy of modified worn object will return object with obsolete asset and inventory - if(get_is_item_worn(mUUID)) - { - return FALSE; - } + LLViewerInventoryItem* item = getItem(); + if (!item) + { + return false; + } + // Can't copy worn objects. + // Worn objects are tied to their inworld conterparts + // Copy of modified worn object will return object with obsolete asset and inventory + if (get_is_item_worn(mUUID)) + { + return false; + } - return item->getPermissions().allowCopyBy(gAgent.getID()) || gSavedSettings.getBOOL("InventoryLinking"); - } - return FALSE; + static LLCachedControl<bool> inventory_linking(gSavedSettings, "InventoryLinking", true); + return (can_copy_as_link && inventory_linking) + || (mIsLink && inventory_linking) + || item->getPermissions().allowCopyBy(gAgent.getID()); } LLViewerInventoryItem* LLItemBridge::getItem() const @@ -2321,8 +2351,14 @@ BOOL LLFolderBridge::isUpToDate() const return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN; } -BOOL LLFolderBridge::isItemCopyable() const +bool LLFolderBridge::isItemCopyable(bool can_copy_as_link) const { + if (can_copy_as_link && !LLFolderType::lookupIsProtectedType(getPreferredType())) + { + // Can copy and paste unprotected folders as links + return true; + } + // Folders are copyable if items in them are, recursively, copyable. // Get the content of the folder @@ -2336,22 +2372,26 @@ BOOL LLFolderBridge::isItemCopyable() const { LLInventoryItem* item = *iter; LLItemBridge item_br(mInventoryPanel.get(), mRoot, item->getUUID()); - if (!item_br.isItemCopyable()) - return FALSE; -} + if (!item_br.isItemCopyable(false)) + { + return false; + } + } // Check the folders LLInventoryModel::cat_array_t cat_array_copy = *cat_array; for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) -{ + { LLViewerInventoryCategory* category = *iter; LLFolderBridge cat_br(mInventoryPanel.get(), mRoot, category->getUUID()); - if (!cat_br.isItemCopyable()) - return FALSE; - } - - return TRUE; - } + if (!cat_br.isItemCopyable(false)) + { + return false; + } + } + + return true; +} BOOL LLFolderBridge::isClipboardPasteable() const { @@ -3768,6 +3808,7 @@ void LLFolderBridge::perform_pasteFromClipboard() LLInventoryObject *obj = model->getObject(item_id); if (obj) { + if (move_is_into_lost_and_found) { if (LLAssetType::AT_CATEGORY == obj->getType()) @@ -4296,7 +4337,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items.push_back(std::string("IM All Contacts In Folder")); } - if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren()) + if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren() && (type != LLFolderType::FT_OUTFIT)) { items.push_back(std::string("Ungroup folder items")); } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 0b0ef273e1..bdffecf1c6 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -119,7 +119,7 @@ public: //virtual BOOL removeItem() = 0; virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); virtual void move(LLFolderViewModelItem* new_parent_bridge) {} - virtual BOOL isItemCopyable() const { return FALSE; } + virtual bool isItemCopyable(bool can_copy_as_link = true) const { return false; } virtual BOOL copyToClipboard() const; virtual BOOL cutToClipboard(); virtual bool isCutToClipboard(); @@ -245,7 +245,7 @@ public: virtual BOOL isItemRenameable() const; virtual BOOL renameItem(const std::string& new_name); virtual BOOL removeItem(); - virtual BOOL isItemCopyable() const; + virtual bool isItemCopyable(bool can_copy_as_link = true) const; virtual bool hasChildren() const { return FALSE; } virtual BOOL isUpToDate() const { return TRUE; } virtual LLUIImagePtr getIconOverlay() const; @@ -318,7 +318,7 @@ public: virtual BOOL isItemRemovable() const; virtual BOOL isItemMovable() const ; virtual BOOL isUpToDate() const; - virtual BOOL isItemCopyable() const; + virtual bool isItemCopyable(bool can_copy_as_link = true) const; virtual BOOL isClipboardPasteable() const; virtual BOOL isClipboardPasteableAsLink() const; diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 707ff2b7b6..e3a6b2dc85 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -437,7 +437,6 @@ bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInvent bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) const { LLInventoryType::EType object_type = item->getInventoryType(); - const LLUUID object_id = item->getUUID(); const U32 filterTypes = mFilterOps.mFilterTypes; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 27edc8148e..af1c93f383 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -862,6 +862,9 @@ LLUUID create_folder_for_item(LLInventoryItem* item, const LLUUID& destFolderId) S32 depth_nesting_in_marketplace(LLUUID cur_uuid) { // Get the marketplace listings root, exit with -1 (i.e. not under the marketplace listings root) if none + // Todo: findCategoryUUIDForType is somewhat expensive with large + // flat root folders yet we use depth_nesting_in_marketplace at + // every turn, find a way to correctly cache this id. const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); if (marketplace_listings_uuid.isNull()) { @@ -1403,9 +1406,6 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol LLNotificationsUtil::add("MerchantPasteFailed", subs); return false; } - - // Get the parent folder of the moved item : we may have to update it - LLUUID src_folder = viewer_inv_item->getParentUUID(); if (copy) { @@ -1504,7 +1504,12 @@ void dump_trace(std::string& message, S32 depth, LLError::ELevel log_level) // This function does no deletion of listings but a mere audit and raises issues to the user (through the // optional callback cb). It also returns a boolean, true if things validate, false if issues are raised. // The only inventory changes that are done is to move and sort folders containing no-copy items to stock folders. -bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_t cb, bool fix_hierarchy, S32 depth) +bool validate_marketplacelistings( + LLInventoryCategory* cat, + validation_callback_t cb, + bool fix_hierarchy, + S32 depth, + bool notify_observers) { #if 0 // Used only for debug @@ -1570,7 +1575,7 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_ LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, LLFolderType::FT_NONE, cat->getName()); LLInventoryCategory* new_cat = gInventory.getCategory(folder_uuid); gInventory.changeCategoryParent(viewer_cat, folder_uuid, false); - result &= validate_marketplacelistings(new_cat, cb, fix_hierarchy, depth + 1); + result &= validate_marketplacelistings(new_cat, cb, fix_hierarchy, depth + 1, notify_observers); return result; } else @@ -1740,7 +1745,10 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_ // Next type update_marketplace_category(parent_uuid); update_marketplace_category(folder_uuid); - gInventory.notifyObservers(); + if (notify_observers) + { + gInventory.notifyObservers(); + } items_vector_it++; } } @@ -1754,7 +1762,7 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_ { LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (*iter); gInventory.changeCategoryParent(viewer_cat, parent_uuid, false); - result &= validate_marketplacelistings(viewer_cat, cb, fix_hierarchy, depth); + result &= validate_marketplacelistings(viewer_cat, cb, fix_hierarchy, depth, false); } } } @@ -1826,7 +1834,10 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_ cb(message,depth,LLError::LEVEL_WARN); } gInventory.removeCategory(cat->getUUID()); - gInventory.notifyObservers(); + if (notify_observers) + { + gInventory.notifyObservers(); + } return result && !has_bad_items; } } @@ -1840,11 +1851,14 @@ bool validate_marketplacelistings(LLInventoryCategory* cat, validation_callback_ for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) { LLInventoryCategory* category = *iter; - result &= validate_marketplacelistings(category, cb, fix_hierarchy, depth + 1); + result &= validate_marketplacelistings(category, cb, fix_hierarchy, depth + 1, false); } update_marketplace_category(cat->getUUID(), true, true); - gInventory.notifyObservers(); + if (notify_observers) + { + gInventory.notifyObservers(); + } return result && !has_bad_items; } @@ -2583,8 +2597,62 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root } std::set<LLUUID> selected_uuid_set = LLAvatarActions::getInventorySelectedUUIDs(); + + // copy list of applicable items into a vector for bulk handling uuid_vec_t ids; - std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids)); + if (action == "wear" || action == "wear_add") + { + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + std::copy_if(selected_uuid_set.begin(), + selected_uuid_set.end(), + std::back_inserter(ids), + [trash_id, mp_id](LLUUID id) + { + if (get_is_item_worn(id) + || LLAppearanceMgr::instance().getIsInCOF(id) + || gInventory.isObjectDescendentOf(id, trash_id)) + { + return false; + } + if (mp_id.notNull() && gInventory.isObjectDescendentOf(id, mp_id)) + { + return false; + } + LLInventoryObject* obj = (LLInventoryObject*)gInventory.getObject(id); + if (!obj) + { + return false; + } + if (obj->getIsLinkType() && gInventory.isObjectDescendentOf(obj->getLinkedUUID(), trash_id)) + { + return false; + } + if (obj->getIsLinkType() && LLAssetType::lookupIsLinkType(obj->getType())) + { + // missing + return false; + } + return true; + } + ); + } + else if (isRemoveAction(action)) + { + std::copy_if(selected_uuid_set.begin(), + selected_uuid_set.end(), + std::back_inserter(ids), + [](LLUUID id) + { + return get_is_item_worn(id); + } + ); + } + else + { + std::copy(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids)); + } + // Check for actions that get handled in bulk if (action == "wear") { diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index ba9f157e47..56ad6f6496 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -87,7 +87,7 @@ bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInve bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryCategory* inv_cat, std::string& tooltip_msg, S32 bundle_size = 1, bool check_items = true, bool from_paste = false); bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy = false); bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy = false, bool move_no_copy_items = false); -bool validate_marketplacelistings(LLInventoryCategory* inv_cat, validation_callback_t cb = NULL, bool fix_hierarchy = true, S32 depth = -1); +bool validate_marketplacelistings(LLInventoryCategory* inv_cat, validation_callback_t cb = NULL, bool fix_hierarchy = true, S32 depth = -1, bool notify_observers = true); S32 depth_nesting_in_marketplace(LLUUID cur_uuid); LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth); S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false); diff --git a/indra/newview/llinventorylistitem.h b/indra/newview/llinventorylistitem.h index d4dd212cc3..cf713a6930 100644 --- a/indra/newview/llinventorylistitem.h +++ b/indra/newview/llinventorylistitem.h @@ -197,6 +197,7 @@ protected: virtual BOOL handleToolTip( S32 x, S32 y, MASK mask); const LLUUID mInventoryItemUUID; + bool mHovered; private: @@ -221,7 +222,6 @@ private: LLUIImagePtr mSelectedImage; LLUIImagePtr mSeparatorImage; - bool mHovered; bool mSelected; bool mSeparatorVisible; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index fab7ae8f1a..b0d6f9d9c3 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1691,11 +1691,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo // Can't have links to links, so there's no need for this update // if the item removed is a link. Can also skip if source of the // update is getting broken link info separately. - obj = NULL; // delete obj if (fix_broken_links && !is_link_type) { updateLinkedObjectsFromPurge(id); } + obj = nullptr; // delete obj if (do_notify_observers) { notifyObservers(); @@ -1851,9 +1851,13 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent) mChangedItemIDs.insert(referent); } - // Fix me: From DD-81, probably shouldn't be here, instead - // should be somewhere in an observer - update_marketplace_category(referent, false); + if (mask != LLInventoryObserver::LABEL) + { + // Fix me: From DD-81, probably shouldn't be here, instead + // should be somewhere in an observer or in + // LLMarketplaceInventoryObserver::onIdleProcessQueue + update_marketplace_category(referent, false); + } if (mask & LLInventoryObserver::ADD) { @@ -2711,7 +2715,6 @@ void LLInventoryModel::buildParentChildMap() // some accounts has pbroken inventory root folders std::string name = "My Inventory"; - LLUUID prev_root_id = mRootFolderID; for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(), it_end = mParentChildCategoryTree.end(); it != it_end; ++it) { diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 6b102c7500..c065c76dca 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -211,7 +211,11 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) p.allow_drop = mParams.allow_drop_on_root; p.options_menu = "menu_inventory.xml"; - return LLUICtrlFactory::create<LLFolderView>(p); + LLFolderView* fv = LLUICtrlFactory::create<LLFolderView>(p); + fv->setCallbackRegistrar(&mCommitCallbackRegistrar); + fv->setEnableRegistrar(&mEnableCallbackRegistrar); + + return fv; } void LLInventoryPanel::clearFolderRoot() @@ -264,6 +268,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) } mCommitCallbackRegistrar.popScope(); mFolderRoot.get()->setCallbackRegistrar(&mCommitCallbackRegistrar); + mFolderRoot.get()->setEnableRegistrar(&mEnableCallbackRegistrar); // Scroller LLRect scroller_view_rect = getRect(); diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index d3ba18525b..60f8aca94c 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -171,8 +171,9 @@ bool LLKeyConflictHandler::isReservedByMenu(const KEY &key, const MASK &mask) { return false; } - return (gMenuBarView && gMenuBarView->hasAccelerator(key, mask)) - || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(key, mask)); + // At the moment controls are only applicable inworld, + // ignore gLoginMenuBarView + return gMenuBarView && gMenuBarView->hasAccelerator(key, mask); } // static @@ -182,8 +183,7 @@ bool LLKeyConflictHandler::isReservedByMenu(const LLKeyData &data) { return false; } - return (gMenuBarView && gMenuBarView->hasAccelerator(data.mKey, data.mMask)) - || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(data.mKey, data.mMask)); + return gMenuBarView && gMenuBarView->hasAccelerator(data.mKey, data.mMask); } bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) diff --git a/indra/newview/lllistcontextmenu.cpp b/indra/newview/lllistcontextmenu.cpp index 6bda8b1d0d..77185411c5 100644 --- a/indra/newview/lllistcontextmenu.cpp +++ b/indra/newview/lllistcontextmenu.cpp @@ -51,6 +51,7 @@ LLListContextMenu::~LLListContextMenu() if (!mMenuHandle.isDead()) { mMenuHandle.get()->die(); + mMenuHandle.markDead(); } } @@ -59,13 +60,8 @@ void LLListContextMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 LLContextMenu* menup = mMenuHandle.get(); if (menup) { - //preventing parent (menu holder) from deleting already "dead" context menus on exit - LLView* parent = menup->getParent(); - if (parent) - { - parent->removeChild(menup); - } - delete menup; + menup->die(); + mMenuHandle.markDead(); mUUIDs.clear(); } diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index dd4ae4d201..2d726409c6 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -30,6 +30,7 @@ #include "llagent.h" #include "llbufferstream.h" +#include "llcallbacklist.h" #include "llinventoryfunctions.h" #include "llinventoryobserver.h" #include "llnotificationsutil.h" @@ -605,20 +606,67 @@ public: LLMarketplaceInventoryObserver() {} virtual ~LLMarketplaceInventoryObserver() {} virtual void changed(U32 mask); + +private: + static void onIdleProcessQueue(void *userdata); + + // doesn't hold just marketplace related ids + static std::set<LLUUID> sAddQueue; + static std::set<LLUUID> sStructureQueue; + static bool sProcessingQueue; }; +std::set<LLUUID> LLMarketplaceInventoryObserver::sAddQueue; +std::set<LLUUID> LLMarketplaceInventoryObserver::sStructureQueue; +bool LLMarketplaceInventoryObserver::sProcessingQueue = false; + void LLMarketplaceInventoryObserver::changed(U32 mask) { - // When things are added to the marketplace, we might need to re-validate and fix the containing listings - if (mask & LLInventoryObserver::ADD) + if (mask & LLInventoryObserver::ADD && LLMarketplaceData::instance().hasValidationWaiting()) { + // When things are added to the marketplace, we might need to re-validate and fix the containing listings + // just add whole list even if it contains items and non-marketplace folders const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); - - std::set<LLUUID>::const_iterator id_it = changed_items.begin(); - std::set<LLUUID>::const_iterator id_end = changed_items.end(); + sAddQueue.insert(changed_items.begin(), changed_items.end()); + } + + if (mask & (LLInventoryObserver::INTERNAL | LLInventoryObserver::STRUCTURE)) + { + // When things are changed in the inventory, this can trigger a host of changes in the marketplace listings folder: + // * stock counts changing : no copy items coming in and out will change the stock count on folders + // * version and listing folders : moving those might invalidate the marketplace data itself + // Since we should cannot raise inventory change while the observer is called (the list will be cleared + // once observers are called) we need to raise a flag in the inventory to signal that things have been dirtied. + const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); + sStructureQueue.insert(changed_items.begin(), changed_items.end()); + } + + if (!sProcessingQueue && (!sAddQueue.empty() || !sStructureQueue.empty())) + { + gIdleCallbacks.addFunction(onIdleProcessQueue, NULL); + // can do without sProcessingQueue, but it's usufull for simplicity and reliability + sProcessingQueue = true; + } +} + +void LLMarketplaceInventoryObserver::onIdleProcessQueue(void *userdata) +{ + U64 start_time = LLTimer::getTotalTime(); // microseconds + const U64 MAX_PROCESSING_TIME = 1000; + U64 stop_time = start_time + MAX_PROCESSING_TIME; + + if (!sAddQueue.empty()) + { + // Make a copy of sAddQueue since decrementValidationWaiting + // can theoretically add more items + std::set<LLUUID> add_queue(sAddQueue); + sAddQueue.clear(); + + std::set<LLUUID>::const_iterator id_it = add_queue.begin(); + std::set<LLUUID>::const_iterator id_end = add_queue.end(); // First, count the number of items in this list... S32 count = 0; - for (;id_it != id_end; ++id_it) + for (; id_it != id_end; ++id_it) { LLInventoryObject* obj = gInventory.getObject(*id_it); if (obj && (LLAssetType::AT_CATEGORY != obj->getType())) @@ -629,56 +677,58 @@ void LLMarketplaceInventoryObserver::changed(U32 mask) // Then, decrement the folders of that amount // Note that of all of those, only one folder will be a listing folder (if at all). // The other will be ignored by the decrement method. - id_it = changed_items.begin(); - for (;id_it != id_end; ++id_it) + id_it = add_queue.begin(); + for (; id_it != id_end; ++id_it) { LLInventoryObject* obj = gInventory.getObject(*id_it); if (obj && (LLAssetType::AT_CATEGORY == obj->getType())) { - LLMarketplaceData::instance().decrementValidationWaiting(obj->getUUID(),count); + // can trigger notifyObservers + LLMarketplaceData::instance().decrementValidationWaiting(obj->getUUID(), count); } } - } - - // When things are changed in the inventory, this can trigger a host of changes in the marketplace listings folder: - // * stock counts changing : no copy items coming in and out will change the stock count on folders - // * version and listing folders : moving those might invalidate the marketplace data itself - // Since we should cannot raise inventory change while the observer is called (the list will be cleared - // once observers are called) we need to raise a flag in the inventory to signal that things have been dirtied. - - if (mask & (LLInventoryObserver::INTERNAL | LLInventoryObserver::STRUCTURE)) - { - const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); - - std::set<LLUUID>::const_iterator id_it = changed_items.begin(); - std::set<LLUUID>::const_iterator id_end = changed_items.end(); - for (;id_it != id_end; ++id_it) + } + + while (!sStructureQueue.empty() && LLTimer::getTotalTime() < stop_time) + { + std::set<LLUUID>::const_iterator id_it = sStructureQueue.begin(); + LLInventoryObject* obj = gInventory.getObject(*id_it); + if (obj) { - LLInventoryObject* obj = gInventory.getObject(*id_it); - if (obj) + if (LLAssetType::AT_CATEGORY == obj->getType()) { - if (LLAssetType::AT_CATEGORY == obj->getType()) + // If it's a folder known to the marketplace, let's check it's in proper shape + if (LLMarketplaceData::instance().isListed(*id_it) || LLMarketplaceData::instance().isVersionFolder(*id_it)) { - // If it's a folder known to the marketplace, let's check it's in proper shape - if (LLMarketplaceData::instance().isListed(*id_it) || LLMarketplaceData::instance().isVersionFolder(*id_it)) - { - LLInventoryCategory* cat = (LLInventoryCategory*)(obj); - validate_marketplacelistings(cat); - } + LLInventoryCategory* cat = (LLInventoryCategory*)(obj); + // can trigger notifyObservers + // can cause more structural changes + validate_marketplacelistings(cat); } - else + } + else + { + // If it's not a category, it's an item... + LLInventoryItem* item = (LLInventoryItem*)(obj); + // If it's a no copy item, we may need to update the label count of marketplace listings + if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) { - // If it's not a category, it's an item... - LLInventoryItem* item = (LLInventoryItem*)(obj); - // If it's a no copy item, we may need to update the label count of marketplace listings - if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) - { - LLMarketplaceData::instance().setDirtyCount(); - } + LLMarketplaceData::instance().setDirtyCount(); } } } - } + + // sStructureQueue could have been modified in validate_marketplacelistings + // adding items does not invalidate existing iterator + sStructureQueue.erase(id_it); + } + + if (LLApp::isExiting() || (sAddQueue.empty() && sStructureQueue.empty())) + { + // Nothing to do anymore + gIdleCallbacks.deleteFunction(onIdleProcessQueue, NULL); + sProcessingQueue = false; + } } // Tuple == Item diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h index 088507d850..24fdc5e0ad 100644 --- a/indra/newview/llmarketplacefunctions.h +++ b/indra/newview/llmarketplacefunctions.h @@ -242,6 +242,7 @@ public: void setUpdating(const LLUUID& folder_id, bool isUpdating); // Used to decide when to run a validation on listing folders + bool hasValidationWaiting() { return mValidationWaitingList.size() > 0; } void setValidationWaiting(const LLUUID& folder_id, S32 count); void decrementValidationWaiting(const LLUUID& folder_id, S32 count = 1); diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index 11aa607393..a52f7244f3 100644 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -429,12 +429,10 @@ void LLMaterialMgr::onGetResponse(bool success, const LLSD& content, const LLUUI llassert(content.has(MATERIALS_CAP_ZIP_FIELD)); llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary()); - LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); - std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size()); - std::istringstream content_stream(content_string); + const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); LLSD response_data; - U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size()); + U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size()); if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL; @@ -472,12 +470,10 @@ void LLMaterialMgr::onGetAllResponse(bool success, const LLSD& content, const LL llassert(content.has(MATERIALS_CAP_ZIP_FIELD)); llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary()); - LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); - std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size()); - std::istringstream content_stream(content_string); + const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); LLSD response_data; - U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size()); + U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size()); if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL; @@ -541,12 +537,10 @@ void LLMaterialMgr::onPutResponse(bool success, const LLSD& content) llassert(content.has(MATERIALS_CAP_ZIP_FIELD)); llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary()); - LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); - std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size()); - std::istringstream content_stream(content_string); + const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); LLSD response_data; - U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size()); + U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size()); if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL; @@ -666,8 +660,8 @@ void LLMaterialMgr::processGetQueue() { material_queue_t::iterator itMaterial = loopMaterial++; materialsData.append((*itMaterial).asLLSD()); - materials.erase(itMaterial); markGetPending(region_id, *itMaterial); + materials.erase(itMaterial); } if (materials.empty()) { diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 9142aadab9..36ac1bdf97 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -106,7 +106,6 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : mTrusted(p.trusted_content), mWindowShade(NULL), mHoverTextChanged(false), - mContextMenu(NULL), mAllowFileDownload(false) { { @@ -151,6 +150,13 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : LLMediaCtrl::~LLMediaCtrl() { + auto menu = mContextMenuHandle.get(); + if (menu) + { + menu->die(); + mContextMenuHandle.markDead(); + } + if (mMediaSource) { mMediaSource->remObserver( this ); @@ -336,15 +342,33 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask ) setFocus( TRUE ); } - if (mContextMenu) + auto menu = mContextMenuHandle.get(); + if (!menu) + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; + registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this)); + + // stinson 05/05/2014 : use this as the parent of the context menu if the static menu + // container has yet to be created + LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast<LLPanel*>(LLMenuGL::sMenuContainer) : dynamic_cast<LLPanel*>(this); + llassert(menuParent != NULL); + menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( + "menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mContextMenuHandle = menu->getHandle(); + } + } + + if (menu) { // hide/show debugging options bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); - mContextMenu->setItemVisible("open_webinspector", media_plugin_debugging_enabled ); - mContextMenu->setItemVisible("debug_separator", media_plugin_debugging_enabled ); + menu->setItemVisible("open_webinspector", media_plugin_debugging_enabled ); + menu->setItemVisible("debug_separator", media_plugin_debugging_enabled ); - mContextMenu->show(x, y); - LLMenuGL::showPopup(this, mContextMenu, x, y); + menu->show(x, y); + LLMenuGL::showPopup(this, menu, x, y); } return TRUE; @@ -409,15 +433,6 @@ void LLMediaCtrl::onFocusLost() // BOOL LLMediaCtrl::postBuild () { - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; - registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this)); - - // stinson 05/05/2014 : use this as the parent of the context menu if the static menu - // container has yet to be created - LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast<LLPanel*>(LLMenuGL::sMenuContainer) : dynamic_cast<LLPanel*>(this); - llassert(menuParent != NULL); - mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( - "menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance()); setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2)); return TRUE; @@ -1230,11 +1245,6 @@ void LLMediaCtrl::setTrustedContent(bool trusted) } } -void LLMediaCtrl::updateContextMenuParent(LLView* pNewParent) -{ - mContextMenu->updateParent(pNewParent); -} - bool LLMediaCtrl::wantsKeyUpKeyDown() const { return true; diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index bc4cbaae68..487c654adc 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -174,8 +174,6 @@ public: LLUUID getTextureID() {return mMediaTextureID;} - void updateContextMenuParent(LLView* pNewParent); - // The Browser windows want keyup and keydown events. Overridden from LLFocusableElement to return true. virtual bool wantsKeyUpKeyDown() const; virtual bool wantsReturnKey() const; @@ -220,7 +218,7 @@ public: mTextureHeight; class LLWindowShade* mWindowShade; - LLContextMenu* mContextMenu; + LLHandle<LLContextMenu> mContextMenuHandle; }; #endif // LL_LLMediaCtrl_H diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index a15a61429b..f937754368 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -77,6 +77,8 @@ #include "lluploaddialog.h" #include "llfloaterreg.h" +#include "boost/iostreams/device/array.hpp" +#include "boost/iostreams/stream.hpp" #include "boost/lexical_cast.hpp" #ifndef LL_WINDOWS @@ -138,7 +140,7 @@ // data copied // headerReceived() invoked // LLSD parsed -// mMeshHeader, mMeshHeaderSize updated +// mMeshHeader updated // scan mPendingLOD for LOD request // push LODRequest to mLODReqQ // ... @@ -246,7 +248,6 @@ // sActiveLODRequests mMutex rw.any.mMutex, ro.repo.none [1] // sMaxConcurrentRequests mMutex wo.main.none, ro.repo.none, ro.main.mMutex // mMeshHeader mHeaderMutex rw.repo.mHeaderMutex, ro.main.mHeaderMutex, ro.main.none [0] -// mMeshHeaderSize mHeaderMutex rw.repo.mHeaderMutex // mSkinRequests mMutex rw.repo.mMutex, ro.repo.none [5] // mSkinInfoQ mMutex rw.repo.mMutex, rw.main.mMutex [5] (was: [0]) // mDecompositionRequests mMutex rw.repo.mMutex, ro.repo.none [5] @@ -858,6 +859,12 @@ LLMeshRepoThread::~LLMeshRepoThread() mHttpRequestSet.clear(); mHttpHeaders.reset(); + while (!mSkinInfoQ.empty()) + { + delete mSkinInfoQ.front(); + mSkinInfoQ.pop_front(); + } + while (!mDecompositionQ.empty()) { delete mDecompositionQ.front(); @@ -947,7 +954,8 @@ void LLMeshRepoThread::run() else { // too many fails - mUnavailableQ.push(req); + LLMutexLock lock(mMutex); + mUnavailableQ.push_back(req); LL_WARNS() << "Failed to load " << req.mMeshParams << " , skip" << LL_ENDL; } } @@ -1023,37 +1031,42 @@ void LLMeshRepoThread::run() if (!mSkinRequests.empty()) { - std::set<UUIDBasedRequest> incomplete; - while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater) - { - mMutex->lock(); - std::set<UUIDBasedRequest>::iterator iter = mSkinRequests.begin(); - UUIDBasedRequest req = *iter; - mSkinRequests.erase(iter); - mMutex->unlock(); - if (req.isDelayed()) - { - incomplete.insert(req); - } - else if (!fetchMeshSkinInfo(req.mId)) - { - if (req.canRetry()) - { - req.updateTime(); - incomplete.insert(req); - } - else - { - LL_DEBUGS() << "mSkinRequests failed: " << req.mId << LL_ENDL; - } - } - } + std::list<UUIDBasedRequest> incomplete; + while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater) + { - if (!incomplete.empty()) - { - LLMutexLock locker(mMutex); - mSkinRequests.insert(incomplete.begin(), incomplete.end()); - } + mMutex->lock(); + auto req = mSkinRequests.front(); + mSkinRequests.pop_front(); + mMutex->unlock(); + if (req.isDelayed()) + { + incomplete.emplace_back(req); + } + else if (!fetchMeshSkinInfo(req.mId, req.canRetry())) + { + if (req.canRetry()) + { + req.updateTime(); + incomplete.emplace_back(req); + } + else + { + LLMutexLock locker(mMutex); + mSkinUnavailableQ.push_back(req); + LL_DEBUGS() << "mSkinReqQ failed: " << req.mId << LL_ENDL; + } + } + } + + if (!incomplete.empty()) + { + LLMutexLock locker(mMutex); + for (const auto& req : incomplete) + { + mSkinRequests.push_back(req); + } + } } // holding lock, try next list @@ -1152,7 +1165,7 @@ void LLMeshRepoThread::run() // Mutex: LLMeshRepoThread::mMutex must be held on entry void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id) { - mSkinRequests.insert(UUIDBasedRequest(mesh_id)); + mSkinRequests.push_back(UUIDBasedRequest(mesh_id)); } // Mutex: LLMeshRepoThread::mMutex must be held on entry @@ -1178,10 +1191,13 @@ void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) { //could be called from any thread + const LLUUID& mesh_id = mesh_params.getSculptID(); LLMutexLock lock(mMutex); - mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID()); + LLMutexLock header_lock(mHeaderMutex); + mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); if (iter != mMeshHeader.end()) { //if we have the header, request LOD byte range + LODRequest req(mesh_params, lod); { mLODReqQ.push(req); @@ -1191,8 +1207,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) else { HeaderRequest req(mesh_params); - - pending_lod_map::iterator pending = mPendingLOD.find(mesh_params); + pending_lod_map::iterator pending = mPendingLOD.find(mesh_id); if (pending != mPendingLOD.end()) { //append this lod request to existing header request @@ -1202,7 +1217,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) else { //if no header request is pending, fetch header mHeaderReqQ.push(req); - mPendingLOD[mesh_params].push_back(lod); + mPendingLOD[mesh_id].push_back(lod); } } } @@ -1307,7 +1322,7 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, } -bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) +bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry) { if (!mHeaderMutex) @@ -1317,7 +1332,8 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) mHeaderMutex->lock(); - if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) + auto header_it = mMeshHeader.find(mesh_id); + if (header_it == mMeshHeader.end()) { //we have no header info for this mesh, do nothing mHeaderMutex->unlock(); return false; @@ -1325,13 +1341,14 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) ++LLMeshRepository::sMeshRequestCount; bool ret = true; - U32 header_size = mMeshHeaderSize[mesh_id]; + U32 header_size = header_it->second.first; if (header_size > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id]["skin"]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id]["skin"]["size"].asInteger(); + const LLSD& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header["skin"]["offset"].asInteger(); + S32 size = header["skin"]["size"].asInteger(); mHeaderMutex->unlock(); @@ -1387,12 +1404,27 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) << LL_ENDL; ret = false; } - else + else if(can_retry) { handler->mHttpHandle = handle; mHttpRequestSet.insert(handler); } + else + { + LLMutexLock locker(mMutex); + mSkinUnavailableQ.emplace_back(mesh_id); + } } + else + { + LLMutexLock locker(mMutex); + mSkinUnavailableQ.emplace_back(mesh_id); + } + } + else + { + LLMutexLock locker(mMutex); + mSkinUnavailableQ.emplace_back(mesh_id); } } else @@ -1413,21 +1445,23 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) mHeaderMutex->lock(); - if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) + auto header_it = mMeshHeader.find(mesh_id); + if (header_it == mMeshHeader.end()) { //we have no header info for this mesh, do nothing mHeaderMutex->unlock(); return false; } ++LLMeshRepository::sMeshRequestCount; - U32 header_size = mMeshHeaderSize[mesh_id]; + U32 header_size = header_it->second.first; bool ret = true; if (header_size > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger(); + const auto& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header["physics_convex"]["offset"].asInteger(); + S32 size = header["physics_convex"]["size"].asInteger(); mHeaderMutex->unlock(); @@ -1510,21 +1544,23 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) mHeaderMutex->lock(); - if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) + auto header_it = mMeshHeader.find(mesh_id); + if (header_it == mMeshHeader.end()) { //we have no header info for this mesh, do nothing mHeaderMutex->unlock(); return false; } ++LLMeshRepository::sMeshRequestCount; - U32 header_size = mMeshHeaderSize[mesh_id]; + U32 header_size = header_it->second.first; bool ret = true; if (header_size > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger(); + const auto& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header["physics_mesh"]["offset"].asInteger(); + S32 size = header["physics_mesh"]["size"].asInteger(); mHeaderMutex->unlock(); @@ -1704,20 +1740,25 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, return false; } - mHeaderMutex->lock(); + const LLUUID& mesh_id = mesh_params.getSculptID(); + mHeaderMutex->lock(); + auto header_it = mMeshHeader.find(mesh_id); + if (header_it == mMeshHeader.end()) + { //we have no header info for this mesh, do nothing + mHeaderMutex->unlock(); + return false; + } ++LLMeshRepository::sMeshRequestCount; bool retval = true; - - LLUUID mesh_id = mesh_params.getSculptID(); - U32 header_size = mMeshHeaderSize[mesh_id]; - + U32 header_size = header_it->second.first; if (header_size > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id][header_lod[lod]]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id][header_lod[lod]]["size"].asInteger(); + const auto& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header[header_lod[lod]]["offset"].asInteger(); + S32 size = header[header_lod[lod]]["size"].asInteger(); mHeaderMutex->unlock(); if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) @@ -1792,17 +1833,20 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, } else { - mUnavailableQ.push(LODRequest(mesh_params, lod)); + LLMutexLock lock(mMutex); + mUnavailableQ.push_back(LODRequest(mesh_params, lod)); } } else { - mUnavailableQ.push(LODRequest(mesh_params, lod)); + LLMutexLock lock(mMutex); + mUnavailableQ.push_back(LODRequest(mesh_params, lod)); } } else { - mUnavailableQ.push(LODRequest(mesh_params, lod)); + LLMutexLock lock(mMutex); + mUnavailableQ.push_back(LODRequest(mesh_params, lod)); } } else @@ -1821,27 +1865,12 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes U32 header_size = 0; if (data_size > 0) { - std::istringstream stream; - try - { - std::string res_str((char*)data, data_size); + U32 dsize = data_size; + char* result_ptr = strip_deprecated_header((char*)data, dsize, &header_size); - std::string deprecated_header("<? LLSD/Binary ?>"); + data_size = dsize; - if (res_str.substr(0, deprecated_header.size()) == deprecated_header) - { - res_str = res_str.substr(deprecated_header.size() + 1, data_size); - header_size = deprecated_header.size() + 1; - } - data_size = res_str.size(); - - stream.str(res_str); - } - catch (std::bad_alloc&) - { - // out of memory, we won't be able to process this mesh - return MESH_OUT_OF_MEMORY; - } + boost::iostreams::stream<boost::iostreams::array_source> stream(result_ptr, data_size); if (!LLSDSerialize::fromBinary(header, stream, data_size)) { @@ -1878,8 +1907,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes { LLMutexLock lock(mHeaderMutex); - mMeshHeaderSize[mesh_id] = header_size; - mMeshHeader[mesh_id] = header; + mMeshHeader[mesh_id] = { header_size, header }; LLMeshRepository::sCacheBytesHeaders += header_size; } @@ -1887,7 +1915,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time. //check for pending requests - pending_lod_map::iterator iter = mPendingLOD.find(mesh_params); + pending_lod_map::iterator iter = mPendingLOD.find(mesh_id); if (iter != mPendingLOD.end()) { for (U32 i = 0; i < iter->second.size(); ++i) @@ -1911,26 +1939,14 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p } LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); - std::istringstream stream; - try - { - std::string mesh_string((char*)data, data_size); - stream.str(mesh_string); - } - catch (std::bad_alloc&) - { - // out of memory, we won't be able to process this mesh - return MESH_OUT_OF_MEMORY; - } - - if (volume->unpackVolumeFaces(stream, data_size)) + if (volume->unpackVolumeFaces(data, data_size)) { if (volume->getNumFaces() > 0) { LoadedMesh mesh(volume, mesh_params, lod); { LLMutexLock lock(mMutex); - mLoadedQ.push(mesh); + mLoadedQ.push_back(mesh); // LLPointer is not thread safe, since we added this pointer into // threaded list, make sure counter gets decreased inside mutex lock // and won't affect mLoadedQ processing @@ -1953,10 +1969,7 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat { try { - std::string res_str((char*)data, data_size); - std::istringstream stream(res_str); - - U32 uzip_result = LLUZipHelper::unzip_llsd(skin, stream, data_size); + U32 uzip_result = LLUZipHelper::unzip_llsd(skin, data, data_size); if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS(LOG_MESH) << "Mesh skin info parse error. Not a valid mesh asset! ID: " << mesh_id @@ -1973,8 +1986,16 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat } { - LLMeshSkinInfo info(skin); - info.mMeshID = mesh_id; + LLMeshSkinInfo* info = nullptr; + try + { + info = new LLMeshSkinInfo(mesh_id, skin); + } + catch (const std::bad_alloc& ex) + { + LL_WARNS() << "Failed to allocate skin info with exception: " << ex.what() << LL_ENDL; + return false; + } // LL_DEBUGS(LOG_MESH) << "info pelvis offset" << info.mPelvisOffset << LL_ENDL; { @@ -1994,10 +2015,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3 { try { - std::string res_str((char*)data, data_size); - std::istringstream stream(res_str); - - U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, stream, data_size); + U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, data, data_size); if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS(LOG_MESH) << "Mesh decomposition parse error. Not a valid mesh asset! ID: " << mesh_id @@ -2006,7 +2024,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3 return false; } } - catch (std::bad_alloc&) + catch (const std::bad_alloc&) { LL_WARNS(LOG_MESH) << "Out of memory for mesh ID " << mesh_id << " of size: " << data_size << LL_ENDL; return false; @@ -2043,20 +2061,7 @@ EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_ volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH); LLPointer<LLVolume> volume = new LLVolume(volume_params,0); - std::istringstream stream; - try - { - std::string mesh_string((char*)data, data_size); - stream.str(mesh_string); - } - catch (std::bad_alloc&) - { - // out of memory, we won't be able to process this mesh - delete d; - return MESH_OUT_OF_MEMORY; - } - - if (volume->unpackVolumeFaces(stream, data_size)) + if (volume->unpackVolumeFaces(data, data_size)) { d->mPhysicsShapeMesh.clear(); @@ -2870,58 +2875,72 @@ void LLMeshRepoThread::notifyLoadedMeshes() return; } - while (!mLoadedQ.empty()) + if (!mLoadedQ.empty()) { + std::deque<LoadedMesh> loaded_queue; + mMutex->lock(); - if (mLoadedQ.empty()) + if (!mLoadedQ.empty()) { + loaded_queue.swap(mLoadedQ); mMutex->unlock(); - break; - } - LoadedMesh mesh = mLoadedQ.front(); // make sure nothing else owns volume pointer by this point - mLoadedQ.pop(); - mMutex->unlock(); - - update_metrics = true; - if (mesh.mVolume->getNumVolumeFaces() > 0) - { - gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume); - } - else - { - gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams, - LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail())); + + update_metrics = true; + + // Process the elements free of the lock + for (const auto& mesh : loaded_queue) + { + if (mesh.mVolume->getNumVolumeFaces() > 0) + { + gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume); + } + else + { + gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams, + LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail())); + } + } } } - while (!mUnavailableQ.empty()) + if (!mUnavailableQ.empty()) { + std::deque<LODRequest> unavil_queue; + mMutex->lock(); - if (mUnavailableQ.empty()) + if (!mUnavailableQ.empty()) { + unavil_queue.swap(mUnavailableQ); mMutex->unlock(); - break; - } - - LODRequest req = mUnavailableQ.front(); - mUnavailableQ.pop(); - mMutex->unlock(); - update_metrics = true; - gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD); + update_metrics = true; + + // Process the elements free of the lock + for (const auto& req : unavil_queue) + { + gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD); + } + } } - if (! mSkinInfoQ.empty() || ! mDecompositionQ.empty()) + if (!mSkinInfoQ.empty() || !mSkinUnavailableQ.empty() || ! mDecompositionQ.empty()) { if (mMutex->trylock()) { - std::list<LLMeshSkinInfo> skin_info_q; + std::deque<LLMeshSkinInfo*> skin_info_q; + std::deque<UUIDBasedRequest> skin_info_unavail_q; std::list<LLModel::Decomposition*> decomp_q; if (! mSkinInfoQ.empty()) { skin_info_q.swap(mSkinInfoQ); } + + if (! mSkinUnavailableQ.empty()) + { + skin_info_unavail_q.swap(mSkinUnavailableQ); + } + if (! mDecompositionQ.empty()) { decomp_q.swap(mDecompositionQ); @@ -2935,6 +2954,11 @@ void LLMeshRepoThread::notifyLoadedMeshes() gMeshRepo.notifySkinInfoReceived(skin_info_q.front()); skin_info_q.pop_front(); } + while (! skin_info_unavail_q.empty()) + { + gMeshRepo.notifySkinInfoUnavailable(skin_info_unavail_q.front().mId); + skin_info_unavail_q.pop_front(); + } while (! decomp_q.empty()) { @@ -2959,7 +2983,7 @@ S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo if (iter != mMeshHeader.end()) { - LLSD& header = iter->second; + LLSD& header = iter->second.second; return LLMeshRepository::getActualMeshLOD(header, lod); } @@ -3162,7 +3186,7 @@ void LLMeshHeaderHandler::processFailure(LLCore::HttpStatus status) LLMutexLock lock(gMeshRepo.mThread->mMutex); for (int i(0); i < 4; ++i) { - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i)); } } @@ -3191,7 +3215,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b LLMutexLock lock(gMeshRepo.mThread->mMutex); for (int i(0); i < 4; ++i) { - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i)); } } else if (data && data_size > 0) @@ -3204,8 +3228,8 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b LLMeshRepoThread::mesh_header_map::iterator iter = gMeshRepo.mThread->mMeshHeader.find(mesh_id); if (iter != gMeshRepo.mThread->mMeshHeader.end()) { - header_bytes = (S32)gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; - header = iter->second; + header_bytes = (S32)iter->second.first; + header = iter->second.second; } if (header_bytes > 0 @@ -3273,7 +3297,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b LLMutexLock lock(gMeshRepo.mThread->mMutex); for (int i(0); i < 4; ++i) { - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i)); } } } @@ -3300,7 +3324,7 @@ void LLMeshLODHandler::processFailure(LLCore::HttpStatus status) << LL_ENDL; LLMutexLock lock(gMeshRepo.mThread->mMutex); - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); } void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */, @@ -3337,7 +3361,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body << " Not retrying." << LL_ENDL; LLMutexLock lock(gMeshRepo.mThread->mMutex); - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); } } else @@ -3348,7 +3372,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body << " Data size: " << data_size << LL_ENDL; LLMutexLock lock(gMeshRepo.mThread->mMutex); - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); } } @@ -3366,9 +3390,8 @@ void LLMeshSkinInfoHandler::processFailure(LLCore::HttpStatus status) << ", Reason: " << status.toString() << " (" << status.toTerseString() << "). Not retrying." << LL_ENDL; - - // *TODO: Mark mesh unavailable on error. For now, simply leave - // request unfulfilled rather than retry forever. + LLMutexLock lock(gMeshRepo.mThread->mMutex); + gMeshRepo.mThread->mSkinUnavailableQ.emplace_back(mMeshID); } void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */, @@ -3399,7 +3422,8 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* LL_WARNS(LOG_MESH) << "Error during mesh skin info processing. ID: " << mMeshID << ", Unknown reason. Not retrying." << LL_ENDL; - // *TODO: Mark mesh unavailable on error + LLMutexLock lock(gMeshRepo.mThread->mMutex); + gMeshRepo.mThread->mSkinUnavailableQ.emplace_back(mMeshID); } } @@ -3508,7 +3532,7 @@ LLMeshRepository::LLMeshRepository() mMeshThreadCount(0), mThread(NULL) { - + mSkinInfoCullTimer.resetWithExpiry(10.f); } void LLMeshRepository::init() @@ -3609,6 +3633,22 @@ S32 LLMeshRepository::update() return size ; } +void LLMeshRepository::unregisterMesh(LLVOVolume* vobj) +{ + for (auto& lod : mLoadingMeshes) + { + for (auto& param : lod) + { + vector_replace_with_last(param.second, vobj); + } + } + + for (auto& skin_pair : mLoadingSkins) + { + vector_replace_with_last(skin_pair.second, vobj); + } +} + S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail, S32 last_lod) { LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; //LL_LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH); @@ -3624,15 +3664,19 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes - mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_params); + const auto& mesh_id = mesh_params.getSculptID(); + mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_id); if (iter != mLoadingMeshes[detail].end()) { //request pending for this mesh, append volume id to list - iter->second.insert(vobj->getID()); + auto it = std::find(iter->second.begin(), iter->second.end(), vobj); + if (it == iter->second.end()) { + iter->second.push_back(vobj); + } } else { //first request for this mesh - mLoadingMeshes[detail][mesh_params].insert(vobj->getID()); + mLoadingMeshes[detail][mesh_id].push_back(vobj); mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail)); LLMeshRepository::sLODPending++; } @@ -3789,6 +3833,28 @@ void LLMeshRepository::notifyLoadedMeshes() //call completed callbacks on finished decompositions mDecompThread->notifyCompleted(); + if (mSkinInfoCullTimer.checkExpirationAndReset(10.f)) + { + //// Clean up dead skin info + //U64Bytes skinbytes(0); + for (auto iter = mSkinMap.begin(), ender = mSkinMap.end(); iter != ender;) + { + auto copy_iter = iter++; + + //skinbytes += U64Bytes(sizeof(LLMeshSkinInfo)); + //skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(std::string)); + //skinbytes += U64Bytes(copy_iter->second->mJointNums.size() * sizeof(S32)); + //skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(LLMatrix4a)); + //skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(LLMatrix4)); + + if (copy_iter->second->getNumRefs() == 1) + { + mSkinMap.erase(copy_iter); + } + } + //LL_INFOS() << "Skin info cache elements:" << mSkinMap.size() << " Memory: " << U64Kilobytes(skinbytes) << LL_ENDL; + } + // For major operations, attempt to get the required locks // without blocking and punt if they're not available. The // longest run of holdoffs is kept in sMaxLockHoldoffs just @@ -3859,10 +3925,9 @@ void LLMeshRepository::notifyLoadedMeshes() for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter) { F32 max_score = 0.f; - for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) + for (auto obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) { - LLViewerObject* object = gObjectList.findObject(*obj_iter); - + LLVOVolume* object = *obj_iter; if (object) { LLDrawable* drawable = object->mDrawable; @@ -3874,7 +3939,7 @@ void LLMeshRepository::notifyLoadedMeshes() } } - score_map[iter->first.getSculptID()] = max_score; + score_map[iter->first] = max_score; } } @@ -3926,24 +3991,39 @@ void LLMeshRepository::notifyLoadedMeshes() mThread->mSignal->signal(); } -void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info) +void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo* info) { - mSkinMap[info.mMeshID] = info; + mSkinMap[info->mMeshID] = info; // Cache into LLPointer // Alternative: We can get skin size from header - sCacheBytesSkins += info.sizeBytes(); + sCacheBytesSkins += info->sizeBytes(); - skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID); + skin_load_map::iterator iter = mLoadingSkins.find(info->mMeshID); if (iter != mLoadingSkins.end()) { - for (std::set<LLUUID>::iterator obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id) + for (LLVOVolume* vobj : iter->second) { - LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*obj_id); if (vobj) { - vobj->notifyMeshLoaded(); + vobj->notifySkinInfoLoaded(info); } } - mLoadingSkins.erase(info.mMeshID); + mLoadingSkins.erase(iter); + } +} + +void LLMeshRepository::notifySkinInfoUnavailable(const LLUUID& mesh_id) +{ + skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); + if (iter != mLoadingSkins.end()) + { + for (LLVOVolume* vobj : iter->second) + { + if (vobj) + { + vobj->notifySkinInfoUnavailable(); + } + } + mLoadingSkins.erase(iter); } } @@ -3972,14 +4052,15 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol S32 detail = LLVolumeLODGroup::getVolumeDetailFromScale(volume->getDetail()); //get list of objects waiting to be notified this mesh is loaded - mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh_params); + const auto& mesh_id = mesh_params.getSculptID(); + mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh_id); if (volume && obj_iter != mLoadingMeshes[detail].end()) { //make sure target volume is still valid if (volume->getNumVolumeFaces() <= 0) { - LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume. ID: " << mesh_params.getSculptID() + LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume. ID: " << mesh_id << LL_ENDL; } @@ -3993,37 +4074,35 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol } else { - LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_params.getSculptID() + LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_id << LL_ENDL; } } //notify waiting LLVOVolume instances that their requested mesh is available - for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + for (LLVOVolume* vobj : obj_iter->second) { - LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); if (vobj) { vobj->notifyMeshLoaded(); } } - mLoadingMeshes[detail].erase(mesh_params); + mLoadingMeshes[detail].erase(obj_iter); } } void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod) { //called from main thread //get list of objects waiting to be notified this mesh is loaded - mesh_load_map::iterator obj_iter = mLoadingMeshes[lod].find(mesh_params); - - F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod); - + const auto& mesh_id = mesh_params.getSculptID(); + mesh_load_map::iterator obj_iter = mLoadingMeshes[lod].find(mesh_id); if (obj_iter != mLoadingMeshes[lod].end()) { - for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod); + + for (LLVOVolume* vobj : obj_iter->second) { - LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); if (vobj) { LLVolume* obj_volume = vobj->getVolume(); @@ -4037,7 +4116,7 @@ void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params, } } - mLoadingMeshes[lod].erase(mesh_params); + mLoadingMeshes[lod].erase(obj_iter); } } @@ -4046,7 +4125,7 @@ S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo return mThread->getActualMeshLOD(mesh_params, lod); } -const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj) +const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj) { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; if (mesh_id.notNull()) @@ -4054,7 +4133,7 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const skin_map::iterator iter = mSkinMap.find(mesh_id); if (iter != mSkinMap.end()) { - return &(iter->second); + return iter->second; } //no skin info known about given mesh, try to fetch it @@ -4063,14 +4142,22 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); - if (iter == mLoadingSkins.end()) - { //no request pending for this skin info + if (iter != mLoadingSkins.end()) + { //request pending for this mesh, append volume id to list + auto it = std::find(iter->second.begin(), iter->second.end(), requesting_obj); + if (it == iter->second.end()) { + iter->second.push_back(requesting_obj); + } + } + else + { + //first request for this mesh + mLoadingSkins[mesh_id].push_back(requesting_obj); mPendingSkinRequests.push(mesh_id); } - mLoadingSkins[mesh_id].insert(requesting_obj->getID()); } } - return NULL; + return nullptr; } void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id) @@ -4173,16 +4260,13 @@ bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id) bool LLMeshRepoThread::hasPhysicsShapeInHeader(const LLUUID& mesh_id) { LLMutexLock lock(mHeaderMutex); - if (mMeshHeaderSize[mesh_id] > 0) + mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); + if (iter != mMeshHeader.end() && iter->second.first > 0) { - mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); - if (iter != mMeshHeader.end()) + LLSD &mesh = iter->second.second; + if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) { - LLSD &mesh = iter->second; - if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) - { - return true; - } + return true; } } @@ -4207,9 +4291,9 @@ S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod) { LLMutexLock lock(mThread->mHeaderMutex); LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); - if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) + if (iter != mThread->mMeshHeader.end() && iter->second.first > 0) { - LLSD& header = iter->second; + const LLSD& header = iter->second.second; if (header.has("404")) { @@ -4313,9 +4397,9 @@ F32 LLMeshRepository::getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* by { LLMutexLock lock(mThread->mHeaderMutex); LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); - if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) + if (iter != mThread->mMeshHeader.end() && iter->second.first > 0) { - result = getStreamingCostLegacy(iter->second, radius, bytes, bytes_visible, lod, unscaled_value); + result = getStreamingCostLegacy(iter->second.second, radius, bytes, bytes_visible, lod, unscaled_value); } } if (result > 0.f) @@ -4628,9 +4712,9 @@ bool LLMeshRepository::getCostData(LLUUID mesh_id, LLMeshCostData& data) { LLMutexLock lock(mThread->mHeaderMutex); LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); - if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) + if (iter != mThread->mMeshHeader.end() && iter->second.first > 0) { - LLSD& header = iter->second; + LLSD& header = iter->second.second; bool header_invalid = (header.has("404") || !header.has("lowest_lod") diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index f61da3e571..e3688ff243 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -210,10 +210,8 @@ public: LLCondition* mSignal; //map of known mesh headers - typedef std::map<LLUUID, LLSD> mesh_header_map; + typedef boost::unordered_map<LLUUID, std::pair<U32, LLSD>> mesh_header_map; // pair is header_size and data mesh_header_map mMeshHeader; - - std::map<LLUUID, U32> mMeshHeaderSize; class HeaderRequest : public RequestStats { @@ -283,10 +281,13 @@ public: }; //set of requested skin info - std::set<UUIDBasedRequest> mSkinRequests; + std::deque<UUIDBasedRequest> mSkinRequests; // list of completed skin info requests - std::list<LLMeshSkinInfo> mSkinInfoQ; + std::deque<LLMeshSkinInfo*> mSkinInfoQ; + + // list of skin info requests that have failed or are unavailaibe + std::deque<UUIDBasedRequest> mSkinUnavailableQ; //set of requested decompositions std::set<UUIDBasedRequest> mDecompositionRequests; @@ -304,13 +305,13 @@ public: std::queue<LODRequest> mLODReqQ; //queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD) - std::queue<LODRequest> mUnavailableQ; + std::deque<LODRequest> mUnavailableQ; //queue of successfully loaded meshes - std::queue<LoadedMesh> mLoadedQ; + std::deque<LoadedMesh> mLoadedQ; //map of pending header requests and currently desired LODs - typedef std::map<LLVolumeParams, std::vector<S32> > pending_lod_map; + typedef boost::unordered_map<LLUUID, std::vector<S32> > pending_lod_map; pending_lod_map mPendingLOD; // llcorehttp library interface objects. @@ -354,7 +355,7 @@ public: //send request for skin info, returns true if header info exists // (should hold onto mesh_id and try again later if header info does not exist) - bool fetchMeshSkinInfo(const LLUUID& mesh_id); + bool fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry = true); //send request for decomposition, returns true if header info exists // (should hold onto mesh_id and try again later if header info does not exist) @@ -577,18 +578,20 @@ public: void shutdown(); S32 update(); + void unregisterMesh(LLVOVolume* volume); //mesh management functions S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1); void notifyLoadedMeshes(); void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume); void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod); - void notifySkinInfoReceived(LLMeshSkinInfo& info); + void notifySkinInfoReceived(LLMeshSkinInfo* info); + void notifySkinInfoUnavailable(const LLUUID& info); void notifyDecompositionReceived(LLModel::Decomposition* info); S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); static S32 getActualMeshLOD(LLSD& header, S32 lod); - const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj = nullptr); + const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj = nullptr); LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id); void fetchPhysicsShape(const LLUUID& mesh_id); bool hasPhysicsShape(const LLUUID& mesh_id); @@ -613,10 +616,10 @@ public: static void metricsProgress(unsigned int count); static void metricsUpdate(); - typedef std::map<LLVolumeParams, std::set<LLUUID> > mesh_load_map; + typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > mesh_load_map; mesh_load_map mLoadingMeshes[4]; - typedef std::unordered_map<LLUUID, LLMeshSkinInfo> skin_map; + typedef std::unordered_map<LLUUID, LLPointer<LLMeshSkinInfo>> skin_map; skin_map mSkinMap; typedef std::map<LLUUID, LLModel::Decomposition*> decomposition_map; @@ -627,7 +630,7 @@ public: std::vector<LLMeshRepoThread::LODRequest> mPendingRequests; //list of mesh ids awaiting skin info - typedef std::map<LLUUID, std::set<LLUUID> > skin_load_map; + typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > skin_load_map; skin_load_map mLoadingSkins; //list of mesh ids that need to send skin info fetch requests @@ -652,6 +655,8 @@ public: std::vector<LLMeshUploadThread*> mUploadWaitList; LLPhysicsDecomp* mDecompThread; + + LLFrameTimer mSkinInfoCullTimer; class inventory_data { diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 642df7f931..e1a5b22490 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -1926,32 +1926,16 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d if (sloppy_ratio < 0) { // Sloppy method didn't work, try with smaller decimation values - S32 size_vertices = 0; - - for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx) - { - const LLVolumeFace &face = base->getVolumeFace(face_idx); - size_vertices += face.mNumVertices; - } - - // Complex models aren't supposed to get here, they are supposed - // to work on a first try of sloppy due to having more viggle room. - // If they didn't, something is likely wrong, no point locking the - // thread in a long calculation that will fail. - const U32 too_many_vertices = 27000; - if (size_vertices > too_many_vertices) - { - LL_WARNS() << "Sloppy optimization method failed for a complex model " << target_model->getName() << LL_ENDL; - } - else { // Find a decimator that does work F32 sloppy_decimation_step = sqrt((F32)decimation); // example: 27->15->9->5->3 F32 sloppy_decimator = indices_decimator / sloppy_decimation_step; + U64Microseconds end_time = LLTimer::getTotalTime() + U64Seconds(5); while (sloppy_ratio < 0 && sloppy_decimator > precise_ratio - && sloppy_decimator > 1)// precise_ratio isn't supposed to be below 1, but check just in case + && sloppy_decimator > 1 // precise_ratio isn't supposed to be below 1, but check just in case + && end_time > LLTimer::getTotalTime()) { sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY); sloppy_decimator = sloppy_decimator / sloppy_decimation_step; diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index b34be80b07..0ba3c3d691 100755..100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -102,8 +102,7 @@ LLNetMap::LLNetMap (const Params & p) mObjectImagep(), mClosestAgentToCursor(), mClosestAgentAtLastRightClick(), - mToolTipMsg(), - mPopupMenu(NULL) + mToolTipMsg() { mScale = gSavedSettings.getF32("MiniMapScale"); if (gAgent.isFirstLogin()) @@ -119,6 +118,12 @@ LLNetMap::LLNetMap (const Params & p) LLNetMap::~LLNetMap() { + auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } } BOOL LLNetMap::postBuild() @@ -134,11 +139,10 @@ BOOL LLNetMap::postBuild() commitRegistrar.add("Minimap.MapOrientation.Set", boost::bind(&LLNetMap::setMapOrientation, this, _2)); commitRegistrar.add("Minimap.AboutLand", boost::bind(&LLNetMap::popupShowAboutLand, this, _2)); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, - LLViewerMenuHolderGL::child_registry_t::instance()); - mPopupMenu->setItemEnabled("Re-center map", false); - - return true; + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mPopupMenuHandle = menu->getHandle(); + menu->setItemEnabled("Re-center map", false); + return TRUE; } void LLNetMap::setScale( F32 scale ) @@ -206,8 +210,12 @@ void LLNetMap::draw() mCentering = false; } - bool can_recenter_map = !(centered || mCentering || auto_centering); - mPopupMenu->setItemEnabled("Re-center map", can_recenter_map); + auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); + if (menu) + { + bool can_recenter_map = !(centered || mCentering || auto_centering); + menu->setItemEnabled("Re-center map", can_recenter_map); + } updateAboutLandPopupButton(); // Prepare a scissor region @@ -595,14 +603,15 @@ void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color, bool LLNetMap::isMouseOnPopupMenu() { - if (!mPopupMenu->isOpen()) + auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); + if (!menu || !menu->isOpen()) { return false; } S32 popup_x; S32 popup_y; - LLUI::getInstance()->getMousePositionLocal(mPopupMenu, &popup_x, &popup_y); + LLUI::getInstance()->getMousePositionLocal(menu, &popup_x, &popup_y); // *NOTE: Tolerance is larger than it needs to be because the context menu is offset from the mouse when the menu is opened from certain // directions. This may be a quirk of LLMenuGL::showPopup. -Cosmic,2022-03-22 constexpr S32 tolerance = 10; @@ -613,7 +622,7 @@ bool LLNetMap::isMouseOnPopupMenu() { for (S32 sign_y = -1; sign_y <= 1; sign_y += 2) { - if (mPopupMenu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance))) + if (menu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance))) { return true; } @@ -624,7 +633,8 @@ bool LLNetMap::isMouseOnPopupMenu() void LLNetMap::updateAboutLandPopupButton() { - if (!mPopupMenu->isOpen()) + auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); + if (!menu || !menu->isOpen()) { return; } @@ -632,7 +642,7 @@ void LLNetMap::updateAboutLandPopupButton() LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal(mPopupWorldPos); if (!region) { - mPopupMenu->setItemEnabled("About Land", false); + menu->setItemEnabled("About Land", false); } else { @@ -647,7 +657,7 @@ void LLNetMap::updateAboutLandPopupButton() { valid_parcel = hover_parcel->getOwnerID().notNull(); } - mPopupMenu->setItemEnabled("About Land", valid_parcel); + menu->setItemEnabled("About Land", valid_parcel); } } } @@ -1043,13 +1053,14 @@ BOOL LLNetMap::handleMouseUp(S32 x, S32 y, MASK mask) BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if (mPopupMenu) + auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); + if (menu) { - mPopupWorldPos = viewPosToGlobal(x, y); - mPopupMenu->buildDrawLabels(); - mPopupMenu->updateParent(LLMenuGL::sMenuContainer); - mPopupMenu->setItemEnabled("Stop tracking", LLTracker::isTracking(0)); - LLMenuGL::showPopup(this, mPopupMenu, x, y); + mPopupWorldPos = viewPosToGlobal(x, y); + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); + menu->setItemEnabled("Stop Tracking", LLTracker::isTracking(0)); + LLMenuGL::showPopup(this, menu, x, y); } return TRUE; } @@ -1182,9 +1193,10 @@ void LLNetMap::setZoom(const LLSD &userdata) void LLNetMap::handleStopTracking (const LLSD& userdata) { - if (mPopupMenu) + auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); + if (menu) { - mPopupMenu->setItemEnabled ("Stop tracking", false); + menu->setItemEnabled ("Stop Tracking", false); LLTracker::stopTracking (LLTracker::isTracking(NULL)); } } diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index fe1aca65a9..75c1abc4ed 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -162,7 +162,7 @@ private: void setMapOrientation(const LLSD& userdata); void popupShowAboutLand(const LLSD& userdata); - LLMenuGL* mPopupMenu; + LLHandle<LLView> mPopupMenuHandle; uuid_vec_t gmSelected; }; diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp index 6a79a0c68c..f86edfd0cf 100644 --- a/indra/newview/llnotificationlistitem.cpp +++ b/indra/newview/llnotificationlistitem.cpp @@ -521,8 +521,6 @@ void LLGroupNoticeNotificationListItem::close() void LLGroupNoticeNotificationListItem::onClickAttachment() { if (mInventoryOffer != NULL) { - mInventoryOffer->forceResponse(IOR_ACCEPT); - static const LLUIColor textColor = LLUIColorTable::instance().getColor( "GroupNotifyDimmedTextColor"); mAttachmentTextBox->setColor(textColor); @@ -532,7 +530,7 @@ void LLGroupNoticeNotificationListItem::onClickAttachment() if (!isAttachmentOpenable(mInventoryOffer->mType)) { LLNotifications::instance().add("AttachmentSaved", LLSD(), LLSD()); } - + mInventoryOffer->forceResponse(IOR_ACCEPT); mInventoryOffer = NULL; } } diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index f419e2e06d..602b7412a4 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -41,7 +41,7 @@ #include "llfilepicker.h" #include "llfloaterperms.h" #include "llfloaterreg.h" -#include "llfloateroutfitsnapshot.h" +#include "llfloatersimpleoutfitsnapshot.h" #include "llimagedimensionsinfo.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" @@ -1226,7 +1226,7 @@ void LLOutfitGallery::uploadOutfitImage(const std::vector<std::string>& filename checkRemovePhoto(outfit_id); std::string upload_pending_name = outfit_id.asString(); std::string upload_pending_desc = ""; - LLUUID photo_id = upload_new_resource(filename, // file + upload_new_resource(filename, // file upload_pending_name, upload_pending_desc, 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, @@ -1386,8 +1386,8 @@ void LLOutfitGallery::onSelectPhoto(LLUUID selected_outfit_id) void LLOutfitGallery::onTakeSnapshot(LLUUID selected_outfit_id) { - LLFloaterReg::toggleInstanceOrBringToFront("outfit_snapshot"); - LLFloaterOutfitSnapshot* snapshot_floater = LLFloaterOutfitSnapshot::getInstance(); + LLFloaterReg::toggleInstanceOrBringToFront("simple_outfit_snapshot"); + LLFloaterSimpleOutfitSnapshot* snapshot_floater = LLFloaterSimpleOutfitSnapshot::getInstance(); if (snapshot_floater) { snapshot_floater->setOutfitID(selected_outfit_id); diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 7270580032..4171fd8822 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -823,8 +823,7 @@ void LLOutfitListBase::onOpen(const LLSD& info) mCategoriesObserver->addCategory(outfits, boost::bind(&LLOutfitListBase::refreshList, this, outfits)); - const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - + //const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); // Start observing changes in Current Outfit category. //mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this)); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index ea10aa75ae..0103bf628a 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1663,7 +1663,7 @@ void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLAvatarAppearanceDefine class LLMetricSystemHandler : public LLCommandHandler { public: - LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_THROTTLE) { } + LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_CLICK_ONLY) { } bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp index 44b4728df7..e5c637938f 100644 --- a/indra/newview/llpanelexperiencelog.cpp +++ b/indra/newview/llpanelexperiencelog.cpp @@ -112,7 +112,7 @@ void LLPanelExperienceLog::refresh() int items = 0; bool moreItems = false; LLSD events_to_save = events; - if (!events.emptyMap()) + if (events.isMap() && events.size() != 0) { LLSD::map_const_iterator day = events.endMap(); do diff --git a/indra/newview/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp index 26cd3ff1c1..e379d67e37 100644 --- a/indra/newview/llpanellandmedia.cpp +++ b/indra/newview/llpanellandmedia.cpp @@ -179,7 +179,6 @@ void LLPanelLandMedia::refresh() // enable/disable for text label for completeness mMediaSizeCtrlLabel->setEnabled( can_change_media && allow_resize ); - LLUUID tmp = parcel->getMediaID(); mMediaTextureCtrl->setImageAssetID ( parcel->getMediaID() ); mMediaTextureCtrl->setEnabled( can_change_media ); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 89256b40c4..81acb1c8b4 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -307,6 +307,13 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) gInventory.removeObserver(this); delete mSavedFolderState; + + auto menu = mMenuAddHandle.get(); + if(menu) + { + menu->die(); + mMenuAddHandle.markDead(); + } } LLInventoryPanel* LLPanelMainInventory::getAllItemsPanel() @@ -1177,13 +1184,12 @@ void LLPanelMainInventory::initListCommandsHandlers() mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2)); mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2)); mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mGearMenuButton->setMenu(mMenuGearDefault); + mGearMenuButton->setMenu(mMenuGearDefault, LLMenuButton::MP_TOP_LEFT, true); LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mMenuAddHandle = menu->getHandle(); mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mVisibilityMenuButton->setMenu(mMenuVisibility); - mVisibilityMenuButton->setMenuPosition(LLMenuButton::MP_BOTTOM_LEFT); + mVisibilityMenuButton->setMenu(mMenuVisibility, LLMenuButton::MP_BOTTOM_LEFT, true); // Update the trash button when selected item(s) get worn or taken off. LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this)); diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp index e1818cc68b..416857bd30 100644 --- a/indra/newview/llpanelmediasettingsgeneral.cpp +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -454,7 +454,8 @@ bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace(bool only_if_current_ LLViewerMedia::getInstance()->getMediaImplFromTextureID(object->getTE(face)->getMediaData()->getMediaID()); if(media_impl) { - media_impl->navigateHome(); + media_impl->setPriority(LLPluginClassMedia::PRIORITY_NORMAL); + media_impl->navigateHome(); return true; } } diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 0bfc1297d3..2da431955f 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -93,6 +93,8 @@ enum { MI_HOLE_COUNT }; +const F32 MAX_ATTACHMENT_DIST = 3.5f; // meters + //static const std::string LEGACY_FULLBRIGHT_DESC =LLTrans::getString("Fullbright"); BOOL LLPanelObject::postBuild() @@ -1685,6 +1687,16 @@ void LLPanelObject::sendPosition(BOOL btn_down) mCtrlPosZ->set(LLWorld::getInstance()->resolveLandHeightAgent(newpos) + 1.f); } } + else + { + if (newpos.length() > MAX_ATTACHMENT_DIST) + { + newpos.clampLength(MAX_ATTACHMENT_DIST); + mCtrlPosX->set(newpos.mV[VX]); + mCtrlPosY->set(newpos.mV[VY]); + mCtrlPosZ->set(newpos.mV[VZ]); + } + } // Make sure new position is in a valid region, so the object // won't get dumped by the simulator. @@ -2119,7 +2131,7 @@ bool LLPanelObject::menuEnableItem(const LLSD& userdata) } else if (command == "params_paste") { - return mClipboardParams.isMap() && !mClipboardParams.emptyMap(); + return mClipboardParams.isMap() && (mClipboardParams.size() != 0); } // copy options else if (command == "psr_copy") @@ -2191,6 +2203,10 @@ void LLPanelObject::onPastePos() mClipboardPos.mV[VY] = llclamp(mClipboardPos.mV[VY], 0.f, max_width); //height will get properly clamped by sendPosition } + else + { + mClipboardPos.clampLength(MAX_ATTACHMENT_DIST); + } mCtrlPosX->set( mClipboardPos.mV[VX] ); mCtrlPosY->set( mClipboardPos.mV[VY] ); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index cfaa9456be..bd40c9dd2b 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -131,7 +131,7 @@ public: virtual BOOL removeItem(); virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); virtual void move(LLFolderViewModelItem* parent_listener); - virtual BOOL isItemCopyable() const; + virtual bool isItemCopyable(bool can_copy_as_link = true) const; virtual BOOL copyToClipboard() const; virtual BOOL cutToClipboard(); virtual BOOL isClipboardPasteable() const; @@ -439,10 +439,10 @@ void LLTaskInvFVBridge::move(LLFolderViewModelItem* parent_listener) { } -BOOL LLTaskInvFVBridge::isItemCopyable() const +bool LLTaskInvFVBridge::isItemCopyable(bool can_link) const { LLInventoryItem* item = findItem(); - if(!item) return FALSE; + if(!item) return false; return gAgent.allowOperation(PERM_COPY, item->getPermissions(), GP_OBJECT_MANIPULATE); } @@ -1275,7 +1275,8 @@ LLPanelObjectInventory::LLPanelObjectInventory(const LLPanelObjectInventory::Par mHaveInventory(FALSE), mIsInventoryEmpty(TRUE), mInventoryNeedsUpdate(FALSE), - mInventoryViewModel(p.name) + mInventoryViewModel(p.name), + mShowRootFolder(p.show_root_folder) { // Setup context menu callbacks mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelObjectInventory::doToSelected, this, _2)); @@ -1360,6 +1361,7 @@ void LLPanelObjectInventory::reset() mFolders = LLUICtrlFactory::create<LLFolderView>(p); mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); + mFolders->setEnableRegistrar(&mEnableCallbackRegistrar); if (hasFocus()) { @@ -1526,15 +1528,23 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root p.font_highlight_color = item_color; LLFolderViewFolder* new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); - new_folder->addToFolder(mFolders); - new_folder->toggleOpen(); + + if (mShowRootFolder) + { + new_folder->addToFolder(mFolders); + new_folder->toggleOpen(); + } if (!contents.empty()) { - createViewsForCategory(&contents, inventory_root, new_folder); + createViewsForCategory(&contents, inventory_root, mShowRootFolder ? new_folder : mFolders); } - // Refresh for label to add item count - new_folder->refresh(); + + if (mShowRootFolder) + { + // Refresh for label to add item count + new_folder->refresh(); + } } } diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 7b9ecfb8f3..0e450d8ce9 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -48,8 +48,14 @@ class LLViewerObject; class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener { public: - // dummy param block for template registration purposes - struct Params : public LLPanel::Params {}; + struct Params : public LLInitParam::Block<Params, LLPanel::Params> + { + Optional<bool> show_root_folder; + + Params() + : show_root_folder("show_root_folder", true) + {} + }; LLPanelObjectInventory(const Params&); virtual ~LLPanelObjectInventory(); @@ -110,6 +116,7 @@ private: BOOL mIsInventoryEmpty; // 'Empty' label BOOL mInventoryNeedsUpdate; // for idle, set on changed callback LLFolderViewModelInventory mInventoryViewModel; + bool mShowRootFolder; }; #endif // LL_LLPANELOBJECTINVENTORY_H diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 74ec576554..0f00231643 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -800,7 +800,6 @@ void LLPanelPlaces::onSaveButtonClicked() LLStringUtil::trim(current_title_value); LLStringUtil::trim(current_notes_value); - LLUUID item_id = mItem->getUUID(); LLUUID folder_id = mLandmarkInfo->getLandmarkFolder(); bool change_parent = folder_id != mItem->getParentUUID(); diff --git a/indra/newview/llpanelpresetscamerapulldown.cpp b/indra/newview/llpanelpresetscamerapulldown.cpp index 183123e534..4c9c30160c 100644 --- a/indra/newview/llpanelpresetscamerapulldown.cpp +++ b/indra/newview/llpanelpresetscamerapulldown.cpp @@ -127,7 +127,10 @@ void LLPanelPresetsCameraPulldown::onRowClick(const LLSD& user_data) LL_DEBUGS() << "selected '" << name << "'" << LL_ENDL; LLFloaterCamera::switchToPreset(name); - setVisible(FALSE); + // Scroll grabbed focus, drop it to prevent selection of parent menu + setFocus(FALSE); + + setVisible(FALSE); } else { diff --git a/indra/newview/llpanelpresetspulldown.cpp b/indra/newview/llpanelpresetspulldown.cpp index d52ad8056f..23e4fa8887 100644 --- a/indra/newview/llpanelpresetspulldown.cpp +++ b/indra/newview/llpanelpresetspulldown.cpp @@ -122,6 +122,9 @@ void LLPanelPresetsPulldown::onRowClick(const LLSD& user_data) LL_DEBUGS() << "selected '" << name << "'" << LL_ENDL; LLPresetsManager::getInstance()->loadPreset(PRESETS_GRAPHIC, name); + // Scroll grabbed focus, drop it to prevent selection of parent menu + setFocus(FALSE); + setVisible(FALSE); } else diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index f4eaa78f11..708ff26ced 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -484,6 +484,30 @@ public: // requires trusted browser to trigger LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { } + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { + if (params.size() < 2) + { + return true; // don't block, will fail later + } + + if (nav_type == NAV_TYPE_CLICKED) + { + return true; + } + + const std::string verb = params[1].asString(); + if (verb == "about" || verb == "inspect" || verb == "reportAbuse") + { + return true; + } + return false; + } + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { @@ -1031,7 +1055,6 @@ void LLPanelProfileSecondLife::resetData() void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) { - LLUUID avatar_id = getAvatarId(); const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); if ((relationship != NULL || gAgent.isGodlike()) && !getSelfProfile()) { @@ -1280,6 +1303,8 @@ void LLPanelProfileSecondLife::fillRightsData() void LLPanelProfileSecondLife::fillAgeData(const LLDate &born_on) { + // Date from server comes already converted to stl timezone, + // so display it as an UTC + 0 std::string name_and_date = getString("date_format"); LLSD args_name; args_name["datetime"] = (S32)born_on.secondsSinceEpoch(); diff --git a/indra/newview/llpanelprofileclassifieds.cpp b/indra/newview/llpanelprofileclassifieds.cpp index a3913ddc49..1ff12b4f37 100644 --- a/indra/newview/llpanelprofileclassifieds.cpp +++ b/indra/newview/llpanelprofileclassifieds.cpp @@ -81,6 +81,30 @@ public: std::set<LLUUID> mClassifiedIds; std::string mRequestVerb; + + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { + if (params.size() < 1) + { + return true; // don't block, will fail later + } + + if (nav_type == NAV_TYPE_CLICKED) + { + return true; + } + + const std::string verb = params[0].asString(); + if (verb == "create") + { + return false; + } + return true; + } bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp index 774119f169..45d0252e4f 100644 --- a/indra/newview/llpanelprofilepicks.cpp +++ b/indra/newview/llpanelprofilepicks.cpp @@ -63,6 +63,30 @@ public: // requires trusted browser to trigger LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { } + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { + if (params.size() < 1) + { + return true; // don't block, will fail later + } + + if (nav_type == NAV_TYPE_CLICKED) + { + return true; + } + + const std::string verb = params[0].asString(); + if (verb == "create") + { + return false; + } + return true; + } + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { diff --git a/indra/newview/llpanelpulldown.cpp b/indra/newview/llpanelpulldown.cpp index 4de6ee8182..075278f44c 100644 --- a/indra/newview/llpanelpulldown.cpp +++ b/indra/newview/llpanelpulldown.cpp @@ -51,6 +51,7 @@ void LLPanelPulldown::onMouseEnter(S32 x, S32 y, MASK mask) /*virtual*/ void LLPanelPulldown::onTopLost() { + setFocus(FALSE); // drop focus to prevent transfer to parent setVisible(FALSE); } @@ -113,6 +114,7 @@ void LLPanelPulldown::draw() if (alpha == 0.f) { + setFocus(FALSE); // drop focus to prevent transfer to parent setVisible(FALSE); } } diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 3fd4f51559..33656566d1 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -255,7 +255,7 @@ void LLPreviewNotecard::loadAsset() else { LLHost source_sim = LLHost(); - LLSD* user_data = new LLSD(); + LLSD* user_data = nullptr; if (mObjectUUID.notNull()) { LLViewerObject *objectp = gObjectList.findObject(mObjectUUID); @@ -274,6 +274,7 @@ void LLPreviewNotecard::loadAsset() mAssetStatus = PREVIEW_ASSET_LOADED; return; } + user_data = new LLSD(); user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID); } else diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 2e44dc1459..7089df677e 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -515,7 +515,7 @@ void LLSceneMonitor::fetchQueryResult() } //dump results to a file _scene_xmonitor_results.csv -void LLSceneMonitor::dumpToFile(std::string file_name) +void LLSceneMonitor::dumpToFile(const std::string &file_name) { if (!hasResults()) return; diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h index 7cd531bd34..f2e1ef69b9 100644 --- a/indra/newview/llscenemonitor.h +++ b/indra/newview/llscenemonitor.h @@ -61,7 +61,7 @@ public: bool needsUpdate() const; const LLTrace::ExtendablePeriodicRecording* getRecording() const {return &mSceneLoadRecording;} - void dumpToFile(std::string file_name); + void dumpToFile(const std::string &file_name); bool hasResults() const { return mSceneLoadRecording.getResults().getDuration() != S32Seconds(0);} void reset(); diff --git a/indra/newview/llscripteditor.cpp b/indra/newview/llscripteditor.cpp index c6bb2f19dd..140cbbedbe 100644 --- a/indra/newview/llscripteditor.cpp +++ b/indra/newview/llscripteditor.cpp @@ -187,82 +187,8 @@ void LLScriptEditor::drawSelectionBackground() // Draw selection even if we don't have keyboard focus for search/replace if( hasSelection() && !mLineInfoList.empty()) { - std::vector<LLRect> selection_rects; - - S32 selection_left = llmin( mSelectionStart, mSelectionEnd ); - S32 selection_right = llmax( mSelectionStart, mSelectionEnd ); - - // Skip through the lines we aren't drawing. - LLRect content_display_rect = getVisibleDocumentRect(); - - // binary search for line that starts before top of visible buffer - line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, LLTextBase::compare_bottom()); - line_list_t::const_iterator end_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, LLTextBase::compare_top()); - - bool done = false; - - // Find the coordinates of the selected area - for (;line_iter != end_iter && !done; ++line_iter) - { - // is selection visible on this line? - if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right) - { - segment_set_t::iterator segment_iter; - S32 segment_offset; - getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset); - - LLRect selection_rect; - selection_rect.mLeft = line_iter->mRect.mLeft; - selection_rect.mRight = line_iter->mRect.mLeft; - selection_rect.mBottom = line_iter->mRect.mBottom; - selection_rect.mTop = line_iter->mRect.mTop; - - for(;segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0) - { - LLTextSegmentPtr segmentp = *segment_iter; - - S32 segment_line_start = segmentp->getStart() + segment_offset; - S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd); - - if (segment_line_start > segment_line_end) break; - - S32 segment_width = 0; - S32 segment_height = 0; - - // if selection after beginning of segment - if(selection_left >= segment_line_start) - { - S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start; - segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); - selection_rect.mLeft += segment_width; - } - - // if selection_right == segment_line_end then that means we are the first character of the next segment - // or first character of the next line, in either case we want to add the length of the current segment - // to the selection rectangle and continue. - // if selection right > segment_line_end then selection spans end of current segment... - if (selection_right >= segment_line_end) - { - // extend selection slightly beyond end of line - // to indicate selection of newline character (use "n" character to determine width) - S32 num_chars = segment_line_end - segment_line_start; - segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); - selection_rect.mRight += segment_width; - } - // else if selection ends on current segment... - else - { - S32 num_chars = selection_right - segment_line_start; - segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); - selection_rect.mRight += segment_width; - - break; - } - } - selection_rects.push_back(selection_rect); - } - } - + std::vector<LLRect> selection_rects = getSelctionRects(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); const LLColor4& color = mReadOnly ? mReadOnlyFgColor : mFgColor; F32 alpha = hasFocus() ? 0.7f : 0.3f; @@ -272,6 +198,7 @@ void LLScriptEditor::drawSelectionBackground() (1.f + color.mV[VGREEN]) * 0.5f, (1.f + color.mV[VBLUE]) * 0.5f, alpha); + LLRect content_display_rect = getVisibleDocumentRect(); for (std::vector<LLRect>::iterator rect_it = selection_rects.begin(); rect_it != selection_rects.end(); diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index da912ef3d4..6a27ff3047 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -460,10 +460,11 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) if(it != mNotifications.end()) { + LLUUID old_id = it->first; // copy LLUUID to prevent use after free when it is erased below LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); if (NULL != chiclet_panelp) { - LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(it->first); + LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(old_id); if (NULL != chicletp) { // Pass the new_message icon state further. @@ -472,14 +473,14 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) } } - LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", it->first); + LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", old_id); if (floater) { // Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142. set_new_message |= !floater->hasFocus(); } - removeNotification(it->first); + removeNotification(old_id); } } diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 1930faa1a0..b1eed81476 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -694,8 +694,8 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - LLVector4 sunDiffuse = LLVector4(psky->getSunlightColor().mV); - LLVector4 moonDiffuse = LLVector4(psky->getMoonlightColor().mV); + LLVector4 sunDiffuse = LLVector4(LLVector3(psky->getSunlightColor().mV)); + LLVector4 moonDiffuse = LLVector4(LLVector3(psky->getMoonlightColor().mV)); shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, sunDiffuse); shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, moonDiffuse); diff --git a/indra/newview/llsky.h b/indra/newview/llsky.h index 8c0d70c16c..ec0de1fbfd 100644 --- a/indra/newview/llsky.h +++ b/indra/newview/llsky.h @@ -39,7 +39,6 @@ class LLViewerCamera; class LLVOWLSky; -class LLVOWLClouds; class LLSky diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 8134187c21..ed7e18fadc 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -233,7 +233,7 @@ bool LLSnapshotLivePreview::setSnapshotQuality(S32 quality, bool set_by_user) return false; } -void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y) +void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y, LLColor4 alpha_color) { F32 line_width ; glGetFloatv(GL_LINE_WIDTH, &line_width) ; @@ -246,7 +246,6 @@ void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y) //draw four alpha rectangles to cover areas outside of the snapshot image if(!mKeepAspectRatio) { - LLColor4 alpha_color(0.5f, 0.5f, 0.5f, 0.8f) ; S32 dwl = 0, dwr = 0 ; if(mThumbnailWidth > mPreviewRect.getWidth()) { diff --git a/indra/newview/llsnapshotlivepreview.h b/indra/newview/llsnapshotlivepreview.h index 683cd016d8..1f81307976 100644 --- a/indra/newview/llsnapshotlivepreview.h +++ b/indra/newview/llsnapshotlivepreview.h @@ -112,7 +112,7 @@ public: BOOL setThumbnailImageSize() ; void generateThumbnailImage(BOOL force_update = FALSE) ; void resetThumbnailImage() { mThumbnailImage = NULL ; } - void drawPreviewRect(S32 offset_x, S32 offset_y) ; + void drawPreviewRect(S32 offset_x, S32 offset_y, LLColor4 alpha_color = LLColor4(0.5f, 0.5f, 0.5f, 0.8f)); void prepareFreezeFrame(); LLViewerTexture* getBigThumbnailImage(); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index ea671a130e..60bada8f58 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -982,7 +982,6 @@ void LLActiveSpeakerMgr::updateSpeakerList() // clean up text only speakers for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it) { - LLUUID speaker_id = speaker_it->first; LLSpeaker* speakerp = speaker_it->second; if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) { diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 5ca1d4b4a5..0111d8869c 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -51,6 +51,10 @@ class SpeakingIndicatorManager : public LLSingleton<SpeakingIndicatorManager>, L LLSINGLETON(SpeakingIndicatorManager); ~SpeakingIndicatorManager(); LOG_CLASS(SpeakingIndicatorManager); + +protected: + void cleanupSingleton(); + public: /** @@ -183,12 +187,16 @@ SpeakingIndicatorManager::SpeakingIndicatorManager() SpeakingIndicatorManager::~SpeakingIndicatorManager() { - // Don't use LLVoiceClient::getInstance() here without check - // singleton MAY have already been destroyed. - if(LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver(this); - } +} + +void SpeakingIndicatorManager::cleanupSingleton() +{ + // Don't use LLVoiceClient::getInstance() here without a check, + // singleton MAY have already been destroyed. + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver(this); + } } void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_id*/) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 054e9530d4..6883ead5ee 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -272,12 +272,10 @@ void show_first_run_dialog(); bool first_run_dialog_callback(const LLSD& notification, const LLSD& response); void set_startup_status(const F32 frac, const std::string& string, const std::string& msg); bool login_alert_status(const LLSD& notification, const LLSD& response); -void login_packet_failed(void**, S32 result); void use_circuit_callback(void**, S32 result); void register_viewer_callbacks(LLMessageSystem* msg); void asset_callback_nothing(const LLUUID&, LLAssetType::EType, void*, S32); bool callback_choose_gender(const LLSD& notification, const LLSD& response); -void init_start_screen(S32 location_id); void release_start_screen(); void reset_login(); LLSD transform_cert_args(LLPointer<LLCertificate> cert); @@ -1285,9 +1283,6 @@ bool idle_startup() // Initialize classes w/graphics stuff. // LLViewerStatsRecorder::instance(); // Since textures work in threads - gTextureList.doPrefetchImages(); - display_startup(); - LLSurface::initClasses(); display_startup(); @@ -1432,6 +1427,15 @@ bool idle_startup() if (STATE_SEED_CAP_GRANTED == LLStartUp::getStartupState()) { display_startup(); + + // These textures are not warrantied to be cached, so needs + // to hapen with caps granted + gTextureList.doPrefetchImages(); + + // will init images, should be done with caps, but before gSky.init() + LLEnvironment::getInstance()->initSingleton(); + + display_startup(); update_texture_fetch(); display_startup(); @@ -2526,8 +2530,6 @@ void use_circuit_callback(void**, S32 result) void register_viewer_callbacks(LLMessageSystem* msg) { msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data ); - msg->setHandlerFuncFast(_PREHASH_ImageData, LLViewerTextureList::receiveImageHeader ); - msg->setHandlerFuncFast(_PREHASH_ImagePacket, LLViewerTextureList::receiveImagePacket ); msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update ); msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update ); msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update ); @@ -2913,6 +2915,7 @@ void reset_login() gAgentWearables.cleanup(); gAgentCamera.cleanup(); gAgent.cleanup(); + gSky.cleanup(); // mVOSkyp is an inworld object. LLWorld::getInstance()->resetClass(); if ( gViewerWindow ) diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index aeefcd6fb8..449d3d95c8 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -714,7 +714,7 @@ BOOL LLSurfacePatch::updateTexture() { mVObjp->dirtyGeom(); gPipeline.markGLRebuild(mVObjp); - return TRUE; + return !mSTexUpdate; } } } diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 67da311493..5c6f7254f2 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1646,6 +1646,12 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) { gDirUtilp->deleteFilesInDir(dirname, mask); } +#if LL_WINDOWS + // Texture cache can be large and can take a while to remove + // assure OS that processes is alive and not hanging + MSG msg; + PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE | PM_NOYIELD); +#endif } gDirUtilp->deleteFilesInDir(mTexturesDirName, mask); // headers, fast cache if (purge_directories) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 8923f53cf5..6f6ca2be9b 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -282,7 +282,6 @@ static const char* e_state_name[] = "LOAD_FROM_TEXTURE_CACHE", "CACHE_POST", "LOAD_FROM_NETWORK", - "LOAD_FROM_SIMULATOR", "WAIT_HTTP_RESOURCE", "WAIT_HTTP_RESOURCE2", "SEND_HTTP_REQ", @@ -456,7 +455,6 @@ public: LOAD_FROM_TEXTURE_CACHE, CACHE_POST, LOAD_FROM_NETWORK, - LOAD_FROM_SIMULATOR, WAIT_HTTP_RESOURCE, // Waiting for HTTP resources WAIT_HTTP_RESOURCE2, // Waiting for HTTP resources SEND_HTTP_REQ, // Commit to sending as HTTP @@ -497,8 +495,6 @@ private: // Locks: Mw void clearPackets(); - // Locks: Mw - void setupPacketData(); // Locks: Mw (ctor invokes without lock) U32 calcWorkPriority(); @@ -507,10 +503,6 @@ private: void removeFromCache(); // Threads: Ttf - // Locks: Mw - bool processSimulatorPackets(); - - // Threads: Ttf bool writeToCacheComplete(); // Threads: Ttf @@ -612,8 +604,7 @@ private: BOOL mHaveAllData; BOOL mInLocalCache; BOOL mInCache; - bool mCanUseHTTP, - mCanUseNET ; //can get from asset server. + bool mCanUseHTTP; S32 mRetryAttempt; S32 mActiveCount; LLCore::HttpStatus mGetStatus; @@ -885,7 +876,6 @@ const char* sStateDescs[] = { "LOAD_FROM_TEXTURE_CACHE", "CACHE_POST", "LOAD_FROM_NETWORK", - "LOAD_FROM_SIMULATOR", "WAIT_HTTP_RESOURCE", "WAIT_HTTP_RESOURCE2", "SEND_HTTP_REQ", @@ -897,7 +887,7 @@ const char* sStateDescs[] = { "DONE" }; -const std::set<S32> LOGGED_STATES = { LLTextureFetchWorker::LOAD_FROM_TEXTURE_CACHE, LLTextureFetchWorker::LOAD_FROM_NETWORK, LLTextureFetchWorker::LOAD_FROM_SIMULATOR, +const std::set<S32> LOGGED_STATES = { LLTextureFetchWorker::LOAD_FROM_TEXTURE_CACHE, LLTextureFetchWorker::LOAD_FROM_NETWORK, LLTextureFetchWorker::WAIT_HTTP_REQ, LLTextureFetchWorker::DECODE_IMAGE_UPDATE, LLTextureFetchWorker::WAIT_ON_WRITE }; // static @@ -972,8 +962,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mResourceWaitCount(0U), mFetchRetryPolicy(10.0,3600.0,2.0,10) { - mCanUseNET = mUrl.empty() ; - calcWorkPriority(); mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL; // LL_INFOS(LOG_TXT) << "Create: " << mID << " mHost:" << host << " Discard=" << discard << LL_ENDL; @@ -1037,39 +1025,6 @@ void LLTextureFetchWorker::clearPackets() mFirstPacket = 0; } -// Locks: Mw -void LLTextureFetchWorker::setupPacketData() -{ - S32 data_size = 0; - if (mFormattedImage.notNull()) - { - data_size = mFormattedImage->getDataSize(); - } - if (data_size > 0) - { - // Only used for simulator requests - mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1; - if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size) - { - LL_WARNS(LOG_TXT) << "Bad CACHED TEXTURE size: " << data_size << " removing." << LL_ENDL; - removeFromCache(); - resetFormattedData(); - clearPackets(); - } - else if (mFileSize > 0) - { - mLastPacket = mFirstPacket-1; - mTotalPackets = (mFileSize - FIRST_PACKET_SIZE + MAX_IMG_PACKET_SIZE-1) / MAX_IMG_PACKET_SIZE + 1; - } - else - { - // This file was cached using HTTP so we have to refetch the first packet - resetFormattedData(); - clearPackets(); - } - } -} - // Locks: Mw (ctor invokes without lock) U32 LLTextureFetchWorker::calcWorkPriority() { @@ -1177,13 +1132,13 @@ bool LLTextureFetchWorker::doWork(S32 param) if(mImagePriority < F_ALMOST_ZERO) { - if (mState == INIT || mState == LOAD_FROM_NETWORK || mState == LOAD_FROM_SIMULATOR) + if (mState == INIT || mState == LOAD_FROM_NETWORK) { LL_DEBUGS(LOG_TXT) << mID << " abort: mImagePriority < F_ALMOST_ZERO" << LL_ENDL; return true; // abort } } - if(mState > CACHE_POST && !mCanUseNET && !mCanUseHTTP) + if(mState > CACHE_POST && !mCanUseHTTP) { //nowhere to get data, abort. LL_WARNS(LOG_TXT) << mID << " abort, nowhere to get data" << LL_ENDL; @@ -1387,10 +1342,14 @@ bool LLTextureFetchWorker::doWork(S32 param) if ( use_http && mCanUseHTTP && mUrl.empty())//get http url. { LLViewerRegion* region = NULL; - if (mHost.isInvalid()) - region = gAgent.getRegion(); - else - region = LLWorld::getInstance()->getRegion(mHost); + if (mHost.isInvalid()) + { + region = gAgent.getRegion(); + } + else if (LLWorld::instanceExists()) + { + region = LLWorld::getInstance()->getRegion(mHost); + } if (region) { @@ -1408,14 +1367,14 @@ bool LLTextureFetchWorker::doWork(S32 param) else { mCanUseHTTP = false ; - LL_DEBUGS(LOG_TXT) << "Texture not available via HTTP: empty URL." << LL_ENDL; + LL_WARNS(LOG_TXT) << "Texture not available via HTTP: empty URL." << LL_ENDL; } } else { // This will happen if not logged in or if a region deoes not have HTTP Texture enabled //LL_WARNS(LOG_TXT) << "Region not found for host: " << mHost << LL_ENDL; - LL_DEBUGS(LOG_TXT) << "Texture not available via HTTP: no region " << mUrl << LL_ENDL; + LL_WARNS(LOG_TXT) << "Texture not available via HTTP: no region " << mUrl << LL_ENDL; mCanUseHTTP = false; } } @@ -1434,84 +1393,12 @@ bool LLTextureFetchWorker::doWork(S32 param) } // don't return, fall through to next state } - else if (mSentRequest == UNSENT && mCanUseNET) - { - // Add this to the network queue and sit here. - // LLTextureFetch::update() will send off a request which will change our state - mWriteToCacheState = CAN_WRITE ; - mRequestedSize = mDesiredSize; - mRequestedDiscard = mDesiredDiscard; - mSentRequest = QUEUED; - mFetcher->addToNetworkQueue(this); - recordTextureStart(false); - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); - - return false; - } else { - // Shouldn't need to do anything here - //llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end()); - // Make certain this is in the network queue - //mFetcher->addToNetworkQueue(this); - //recordTextureStart(false); - //setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); - return false; } } - if (mState == LOAD_FROM_SIMULATOR) - { - if (mFormattedImage.isNull()) - { - mFormattedImage = new LLImageJ2C; - } - if (processSimulatorPackets()) - { - // Capture some measure of total size for metrics - F64 byte_count = 0; - if (mLastPacket >= mFirstPacket) - { - for (S32 i=mFirstPacket; i<=mLastPacket; i++) - { - llassert_always((i>=0) && (i<mPackets.size())); - if (mPackets[i]) - { - byte_count += mPackets[i]->mSize; - } - } - } - - LL_DEBUGS(LOG_TXT) << mID << ": Loaded from Sim. Bytes: " << mFormattedImage->getDataSize() << LL_ENDL; - mFetcher->removeFromNetworkQueue(this, false); - if (mFormattedImage.isNull() || !mFormattedImage->getDataSize()) - { - // processSimulatorPackets() failed -// LL_WARNS(LOG_TXT) << "processSimulatorPackets() failed to load buffer" << LL_ENDL; - LL_WARNS(LOG_TXT) << mID << " processSimulatorPackets() failed to load buffer" << LL_ENDL; - return true; // failed - } - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); - if (mLoadedDiscard < 0) - { - LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard - << ", should be >=0" << LL_ENDL; - } - setState(DECODE_IMAGE); - mWriteToCacheState = SHOULD_WRITE; - - recordTextureDone(false, byte_count); - } - else - { - mFetcher->addToNetworkQueue(this); // failsafe - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); - recordTextureStart(false); - } - return false; - } - if (mState == WAIT_HTTP_RESOURCE) { // NOTE: @@ -1553,8 +1440,6 @@ bool LLTextureFetchWorker::doWork(S32 param) LL_WARNS(LOG_TXT) << mID << " abort: SEND_HTTP_REQ but !mCanUseHTTP" << LL_ENDL; return true; // abort } - - mFetcher->removeFromNetworkQueue(this, false); S32 cur_size = 0; if (mFormattedImage.notNull()) @@ -1701,17 +1586,6 @@ bool LLTextureFetchWorker::doWork(S32 param) } return true; } - - // roll back to try UDP - if (mCanUseNET) - { - setState(INIT); - mCanUseHTTP = false; - mUrl.clear(); - setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); - releaseHttpSemaphore(); - return false; - } } else if (http_service_unavail == mGetStatus) { @@ -2284,69 +2158,6 @@ void LLTextureFetchWorker::removeFromCache() // Threads: Ttf // Locks: Mw -bool LLTextureFetchWorker::processSimulatorPackets() -{ - if (mFormattedImage.isNull() || mRequestedSize < 0) - { - // not sure how we got here, but not a valid state, abort! - llassert_always(mDecodeHandle == 0); - mFormattedImage = NULL; - return true; - } - - if (mLastPacket >= mFirstPacket) - { - S32 buffer_size = mFormattedImage->getDataSize(); - for (S32 i = mFirstPacket; i<=mLastPacket; i++) - { - llassert_always((i>=0) && (i<mPackets.size())); - llassert_always(mPackets[i]); - buffer_size += mPackets[i]->mSize; - } - bool have_all_data = mLastPacket >= mTotalPackets-1; - if (mRequestedSize <= 0) - { - // We received a packed but haven't requested anything yet (edge case) - // Return true (we're "done") since we didn't request anything - return true; - } - if (buffer_size >= mRequestedSize || have_all_data) - { - /// We have enough (or all) data - if (have_all_data) - { - mHaveAllData = TRUE; - } - S32 cur_size = mFormattedImage->getDataSize(); - if (buffer_size > cur_size) - { - /// We have new data - U8* buffer = (U8*)ll_aligned_malloc_16(buffer_size); - S32 offset = 0; - if (cur_size > 0 && mFirstPacket > 0) - { - memcpy(buffer, mFormattedImage->getData(), cur_size); - offset = cur_size; - } - for (S32 i=mFirstPacket; i<=mLastPacket; i++) - { - memcpy(buffer + offset, mPackets[i]->mData, mPackets[i]->mSize); - offset += mPackets[i]->mSize; - } - // NOTE: setData releases current data - mFormattedImage->setData(buffer, buffer_size); - } - mLoadedDiscard = mRequestedDiscard; - return true; - } - } - return false; -} - -////////////////////////////////////////////////////////////////////////////// - -// Threads: Ttf -// Locks: Mw S32 LLTextureFetchWorker::callbackHttpGet(LLCore::HttpResponse * response, bool partial, bool success) { @@ -2813,40 +2624,6 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const } -// Threads: T* (but Ttf in practice) - -// protected -void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker) -{ - lockQueue(); // +Mfq - bool in_request_map = (mRequestMap.find(worker->mID) != mRequestMap.end()) ; - unlockQueue(); // -Mfq - - LLMutexLock lock(&mNetworkQueueMutex); // +Mfnq - if (in_request_map) - { - // only add to the queue if in the request map - // i.e. a delete has not been requested - mNetworkQueue.insert(worker->mID); - } - for (cancel_queue_t::iterator iter1 = mCancelQueue.begin(); - iter1 != mCancelQueue.end(); ++iter1) - { - iter1->second.erase(worker->mID); - } -} // -Mfnq - -// Threads: T* -void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel) -{ - LLMutexLock lock(&mNetworkQueueMutex); // +Mfnq - size_t erased = mNetworkQueue.erase(worker->mID); - if (cancel && erased > 0) - { - mCancelQueue[worker->mHost].insert(worker->mID); - } -} // -Mfnq - // Threads: T* // // protected @@ -2880,7 +2657,6 @@ void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel) unlockQueue(); // -Mfq llassert_always(erased_1 > 0) ; - removeFromNetworkQueue(worker, cancel); llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ; worker->scheduleDelete(); @@ -2908,7 +2684,6 @@ void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel) unlockQueue(); // -Mfq llassert_always(erased_1 > 0) ; - removeFromNetworkQueue(worker, cancel); llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ; worker->scheduleDelete(); @@ -3197,17 +2972,6 @@ size_t LLTextureFetch::update(F32 max_time_ms) size_t res = LLWorkerThread::update(max_time_ms); - if (!mDebugPause) - { - // this is the startup state when send_complete_agent_movement() message is sent. - // Before this, the RequestImages message sent by sendRequestListToSimulators - // won't work so don't bother trying - if (LLStartUp::getStartupState() > STATE_AGENT_SEND) - { - sendRequestListToSimulators(); - } - } - if (!mThreaded) { commonUpdate(); @@ -3298,202 +3062,6 @@ void LLTextureFetch::threadedUpdate() ////////////////////////////////////////////////////////////////////////////// -// Threads: Tmain -void LLTextureFetch::sendRequestListToSimulators() -{ - // All requests - const F32 REQUEST_DELTA_TIME = 0.10f; // 10 fps - - // Sim requests - const S32 IMAGES_PER_REQUEST = 50; - const F32 SIM_LAZY_FLUSH_TIMEOUT = 10.0f; // temp - const F32 MIN_REQUEST_TIME = 1.0f; - const F32 MIN_DELTA_PRIORITY = 1000.f; - - // Periodically, gather the list of textures that need data from the network - // And send the requests out to the simulators - static LLFrameTimer timer; - if (timer.getElapsedTimeF32() < REQUEST_DELTA_TIME) - { - return; - } - timer.reset(); - - // Send requests - typedef std::set<LLTextureFetchWorker*,LLTextureFetchWorker::Compare> request_list_t; - typedef std::map< LLHost, request_list_t > work_request_map_t; - work_request_map_t requests; - { - LLMutexLock lock2(&mNetworkQueueMutex); // +Mfnq - for (queue_t::iterator iter = mNetworkQueue.begin(); iter != mNetworkQueue.end(); ) - { - queue_t::iterator curiter = iter++; - LLTextureFetchWorker* req = getWorker(*curiter); - if (!req) - { - mNetworkQueue.erase(curiter); - continue; // paranoia - } - if ((req->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK) && - (req->mState != LLTextureFetchWorker::LOAD_FROM_SIMULATOR)) - { - // We already received our URL, remove from the queue - LL_WARNS(LOG_TXT) << "Worker: " << req->mID << " in mNetworkQueue but in wrong state: " << req->mState << LL_ENDL; - mNetworkQueue.erase(curiter); - continue; - } - if (req->mID == mDebugID) - { - mDebugCount++; // for setting breakpoints - } - if (req->mSentRequest == LLTextureFetchWorker::SENT_SIM && - req->mTotalPackets > 0 && - req->mLastPacket >= req->mTotalPackets-1) - { - // We have all the packets... make sure this is high priority -// req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority); - continue; - } - F32 elapsed = req->mRequestedDeltaTimer.getElapsedTimeF32(); - { - F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority); - if ((req->mSimRequestedDiscard != req->mDesiredDiscard) || - (delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) || - (elapsed >= SIM_LAZY_FLUSH_TIMEOUT)) - { - requests[req->mHost].insert(req); - } - } - } - } // -Mfnq - - for (work_request_map_t::iterator iter1 = requests.begin(); - iter1 != requests.end(); ++iter1) - { - LLHost host = iter1->first; - // invalid host = use agent host - if (host.isInvalid()) - { - host = gAgent.getRegionHost(); - } - - S32 sim_request_count = 0; - - for (request_list_t::iterator iter2 = iter1->second.begin(); - iter2 != iter1->second.end(); ++iter2) - { - LLTextureFetchWorker* req = *iter2; - if (gMessageSystem) - { - if (req->mSentRequest != LLTextureFetchWorker::SENT_SIM) - { - // Initialize packet data based on data read from cache - req->lockWorkMutex(); // +Mw - req->setupPacketData(); - req->unlockWorkMutex(); // -Mw - } - if (0 == sim_request_count) - { - gMessageSystem->newMessageFast(_PREHASH_RequestImage); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - } - S32 packet = req->mLastPacket + 1; - gMessageSystem->nextBlockFast(_PREHASH_RequestImage); - gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID); - gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mDesiredDiscard); - gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, req->mImagePriority); - gMessageSystem->addU32Fast(_PREHASH_Packet, packet); - gMessageSystem->addU8Fast(_PREHASH_Type, req->mType); -// LL_INFOS(LOG_TXT) << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard -// << " Packet: " << packet << " Priority: " << req->mImagePriority << LL_ENDL; - - static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog", false); - static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator", false); - if (log_to_viewer_log || log_to_sim) - { - mTextureInfo.setRequestStartTime(req->mID, LLTimer::getTotalTime()); - mTextureInfo.setRequestOffset(req->mID, 0); - mTextureInfo.setRequestSize(req->mID, 0); - mTextureInfo.setRequestType(req->mID, LLTextureInfoDetails::REQUEST_TYPE_UDP); - } - - req->lockWorkMutex(); // +Mw - req->mSentRequest = LLTextureFetchWorker::SENT_SIM; - req->mSimRequestedDiscard = req->mDesiredDiscard; - req->mRequestedPriority = req->mImagePriority; - req->mRequestedDeltaTimer.reset(); - req->unlockWorkMutex(); // -Mw - sim_request_count++; - if (sim_request_count >= IMAGES_PER_REQUEST) - { -// LL_INFOS(LOG_TXT) << "REQUESTING " << sim_request_count << " IMAGES FROM HOST: " << host.getIPString() << LL_ENDL; - - gMessageSystem->sendSemiReliable(host, NULL, NULL); - sim_request_count = 0; - } - } - } - if (gMessageSystem && sim_request_count > 0 && sim_request_count < IMAGES_PER_REQUEST) - { -// LL_INFOS(LOG_TXT) << "REQUESTING " << sim_request_count << " IMAGES FROM HOST: " << host.getIPString() << LL_ENDL; - gMessageSystem->sendSemiReliable(host, NULL, NULL); - sim_request_count = 0; - } - } - - // Send cancelations - { - LLMutexLock lock2(&mNetworkQueueMutex); // +Mfnq - if (gMessageSystem && !mCancelQueue.empty()) - { - for (cancel_queue_t::iterator iter1 = mCancelQueue.begin(); - iter1 != mCancelQueue.end(); ++iter1) - { - LLHost host = iter1->first; - if (host.isInvalid()) - { - host = gAgent.getRegionHost(); - } - S32 request_count = 0; - for (queue_t::iterator iter2 = iter1->second.begin(); - iter2 != iter1->second.end(); ++iter2) - { - if (0 == request_count) - { - gMessageSystem->newMessageFast(_PREHASH_RequestImage); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - } - gMessageSystem->nextBlockFast(_PREHASH_RequestImage); - gMessageSystem->addUUIDFast(_PREHASH_Image, *iter2); - gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, -1); - gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, 0); - gMessageSystem->addU32Fast(_PREHASH_Packet, 0); - gMessageSystem->addU8Fast(_PREHASH_Type, 0); -// LL_INFOS(LOG_TXT) << "CANCELING IMAGE REQUEST: " << (*iter2) << LL_ENDL; - - request_count++; - if (request_count >= IMAGES_PER_REQUEST) - { - gMessageSystem->sendSemiReliable(host, NULL, NULL); - request_count = 0; - } - } - if (request_count > 0 && request_count < IMAGES_PER_REQUEST) - { - gMessageSystem->sendSemiReliable(host, NULL, NULL); - } - } - mCancelQueue.clear(); - } - } // -Mfnq -} - -////////////////////////////////////////////////////////////////////////////// - // Threads: T* // Locks: Mw bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size) @@ -3556,138 +3124,6 @@ void LLTextureFetchWorker::setState(e_state new_state) mState = new_state; } -// Threads: T* -bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, - U16 data_size, U8* data) -{ - LLTextureFetchWorker* worker = getWorker(id); - bool res = true; - - ++mPacketCount; - - if (!worker) - { -// LL_WARNS(LOG_TXT) << "Received header for non active worker: " << id << LL_ENDL; - res = false; - } - else if (worker->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK || - worker->mSentRequest != LLTextureFetchWorker::SENT_SIM) - { -// LL_WARNS(LOG_TXT) << "receiveImageHeader for worker: " << id -// << " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] -// << " sent: " << worker->mSentRequest << LL_ENDL; - res = false; - } - else if (worker->mLastPacket != -1) - { - // check to see if we've gotten this packet before -// LL_WARNS(LOG_TXT) << "Received duplicate header for: " << id << LL_ENDL; - res = false; - } - else if (!data_size) - { -// LL_WARNS(LOG_TXT) << "Img: " << id << ":" << " Empty Image Header" << LL_ENDL; - res = false; - } - if (!res) - { - mNetworkQueueMutex.lock(); // +Mfnq - ++mBadPacketCount; - mCancelQueue[host].insert(id); - mNetworkQueueMutex.unlock(); // -Mfnq - return false; - } - - LLViewerStatsRecorder::instance().textureFetch(data_size); - LLViewerStatsRecorder::instance().log(0.1f); - - worker->lockWorkMutex(); - - - // Copy header data into image object - worker->mImageCodec = codec; - worker->mTotalPackets = packets; - worker->mFileSize = (S32)totalbytes; - llassert_always(totalbytes > 0); - llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize); - res = worker->insertPacket(0, data, data_size); - worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); - worker->setState(LLTextureFetchWorker::LOAD_FROM_SIMULATOR); - worker->unlockWorkMutex(); // -Mw - return res; -} - - -// Threads: T* -bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data) -{ - LLTextureFetchWorker* worker = getWorker(id); - bool res = true; - - ++mPacketCount; - - if (!worker) - { -// LL_WARNS(LOG_TXT) << "Received packet " << packet_num << " for non active worker: " << id << LL_ENDL; - res = false; - } - else if (worker->mLastPacket == -1) - { -// LL_WARNS(LOG_TXT) << "Received packet " << packet_num << " before header for: " << id << LL_ENDL; - res = false; - } - else if (!data_size) - { -// LL_WARNS(LOG_TXT) << "Img: " << id << ":" << " Empty Image Header" << LL_ENDL; - res = false; - } - if (!res) - { - mNetworkQueueMutex.lock(); // +Mfnq - ++mBadPacketCount; - mCancelQueue[host].insert(id); - mNetworkQueueMutex.unlock(); // -Mfnq - return false; - } - - LLViewerStatsRecorder::instance().textureFetch(data_size); - LLViewerStatsRecorder::instance().log(0.1f); - - worker->lockWorkMutex(); - - - res = worker->insertPacket(packet_num, data, data_size); - - if ((worker->mState == LLTextureFetchWorker::LOAD_FROM_SIMULATOR) || - (worker->mState == LLTextureFetchWorker::LOAD_FROM_NETWORK)) - { - worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); - worker->setState(LLTextureFetchWorker::LOAD_FROM_SIMULATOR); - } - else - { -// LL_WARNS(LOG_TXT) << "receiveImagePacket " << packet_num << "/" << worker->mLastPacket << " for worker: " << id -// << " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] << LL_ENDL; - removeFromNetworkQueue(worker, true); // failsafe - } - - if (packet_num >= (worker->mTotalPackets - 1)) - { - static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog", false); - static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator", false); - - if (log_to_viewer_log || log_to_sim) - { - U64Microseconds timeNow = LLTimer::getTotalTime(); - mTextureInfoMainThread.setRequestSize(id, worker->mFileSize); - mTextureInfoMainThread.setRequestCompleteTimeAndLog(id, timeNow); - } - } - worker->unlockWorkMutex(); // -Mw - - return res; -} - ////////////////////////////////////////////////////////////////////////////// // Threads: T* @@ -3726,13 +3162,7 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r request_dtime = worker->mRequestedDeltaTimer.getElapsedTimeF32(); if (worker->mFileSize > 0) { - if (state == LLTextureFetchWorker::LOAD_FROM_SIMULATOR) - { - S32 data_size = FIRST_PACKET_SIZE + (worker->mLastPacket-1) * MAX_IMG_PACKET_SIZE; - data_size = llmax(data_size, 0); - data_progress = (F32)data_size / (F32)worker->mFileSize; - } - else if (worker->mFormattedImage.notNull()) + if (worker->mFormattedImage.notNull()) { data_progress = (F32)worker->mFormattedImage->getDataSize() / (F32)worker->mFileSize; } diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index e2d2aa365c..611a7d6419 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -101,12 +101,6 @@ public: // Threads: T* bool updateRequestPriority(const LLUUID& id, F32 priority); - // Threads: T* - bool receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data); - - // Threads: T* - bool receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data); - // Threads: T* (but not safe) void setTextureBandwidth(F32 bandwidth) { mTextureBandwidth = bandwidth; } @@ -227,12 +221,6 @@ public: // ---------------------------------- protected: - // Threads: T* (but Ttf in practice) - void addToNetworkQueue(LLTextureFetchWorker* worker); - - // Threads: T* - void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel); - // Threads: T* void addToHTTPQueue(const LLUUID& id); @@ -251,9 +239,6 @@ protected: bool runCondition(); private: - // Threads: Tmain - void sendRequestListToSimulators(); - // Threads: Ttf /*virtual*/ void startThread(void); @@ -319,7 +304,7 @@ public: private: LLMutex mQueueMutex; //to protect mRequestMap and mCommands only - LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue. + LLMutex mNetworkQueueMutex; //to protect mHTTPTextureQueue LLTextureCache* mTextureCache; LLImageDecodeThread* mImageDecodeThread; @@ -330,10 +315,8 @@ private: // Set of requests that require network data typedef std::set<LLUUID> queue_t; - queue_t mNetworkQueue; // Mfnq queue_t mHTTPTextureQueue; // Mfnq typedef std::map<LLHost,std::set<LLUUID> > cancel_queue_t; - cancel_queue_t mCancelQueue; // Mfnq F32 mTextureBandwidth; // <none> F32 mMaxBandwidth; // Mfnq LLTextureInfo mTextureInfo; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index b74577315e..cf9211767e 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -234,7 +234,6 @@ void LLTextureBar::draw() { "DSK", LLColor4::cyan }, // LOAD_FROM_TEXTURE_CACHE { "DSK", LLColor4::blue }, // CACHE_POST { "NET", LLColor4::green }, // LOAD_FROM_NETWORK - { "SIM", LLColor4::green }, // LOAD_FROM_SIMULATOR { "HTW", LLColor4::green }, // WAIT_HTTP_RESOURCE { "HTW", LLColor4::green }, // WAIT_HTTP_RESOURCE2 { "REQ", LLColor4::yellow },// SEND_HTTP_REQ diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 024f25bc98..bf3f4c1e88 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -89,6 +89,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt const LLFontGL* font = make_small_btn ? sFontSmall: sFont; // for block and ignore buttons in script dialog p.name = form_element["name"].asString(); p.label = form_element["text"].asString(); + p.tool_tip = form_element["text"].asString(); p.font = font; p.rect.height = BTN_HEIGHT; p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata)); diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index a1670351f4..7c92e7ef98 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -263,7 +263,7 @@ public: // inside the app, otherwise a malicious web page could // cause a constant teleport loop. JC LLTeleportHandler() : - LLCommandHandler("teleport", UNTRUSTED_THROTTLE), + LLCommandHandler("teleport", UNTRUSTED_CLICK_ONLY), LLEventAPI("LLTeleportHandler", "Low-level teleport API") { LLEventAPI::add("teleport", diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index 14fae8d035..232b52a3f9 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -868,11 +868,6 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti { floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory"))); } - LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot"); - if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown()) - { - floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory"))); - } } //========================================================================= @@ -951,11 +946,5 @@ void LLViewerAssetUpload::HandleUploadError(LLCore::HttpStatus status, LLSD &res floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory"))); } } - - LLFloater* floater_outfit_snapshot = LLFloaterReg::findInstance("outfit_snapshot"); - if (uploadInfo->getAssetType() == LLAssetType::AT_TEXTURE && floater_outfit_snapshot && floater_outfit_snapshot->isShown()) - { - floater_outfit_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory"))); - } } diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index f810e5f4ef..cc73f7ca80 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -496,7 +496,20 @@ void audio_update_listener() if (gAudiop) { // update listener position because agent has moved - LLVector3d lpos_global = gAgentCamera.getCameraPositionGlobal(); + static LLUICachedControl<S32> mEarLocation("MediaSoundsEarLocation", 0); + LLVector3d ear_position; + switch(mEarLocation) + { + case 0: + default: + ear_position = gAgentCamera.getCameraPositionGlobal(); + break; + + case 1: + ear_position = gAgent.getPositionGlobal(); + break; + } + LLVector3d lpos_global = ear_position; LLVector3 lpos_global_f; lpos_global_f.setVec(lpos_global); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index bc46a61fb0..34c9dae4bb 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -616,7 +616,7 @@ bool toggle_show_navigation_panel(const LLSD& newvalue) LLNavigationBar::getInstance()->setVisible(value); gSavedSettings.setBOOL("ShowMiniLocationPanel", !value); - + gViewerWindow->reshapeStatusBarContainer(); return true; } diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 06a6c5e373..c0398372b4 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -103,7 +103,7 @@ #include "llfloaterobjectweights.h" #include "llfloateropenobject.h" #include "llfloateroutfitphotopreview.h" -#include "llfloateroutfitsnapshot.h" +#include "llfloatersimpleoutfitsnapshot.h" #include "llfloaterpathfindingcharacters.h" #include "llfloaterpathfindingconsole.h" #include "llfloaterpathfindinglinksets.h" @@ -170,14 +170,107 @@ // *NOTE: Please add files in alphabetical order to keep merges easy. // handle secondlife:///app/openfloater/{NAME} URLs +const std::string FLOATER_PROFILE("profile"); class LLFloaterOpenHandler : public LLCommandHandler { public: - // requires trusted browser to trigger + // requires trusted browser to trigger or an explicit click LLFloaterOpenHandler() : LLCommandHandler("openfloater", UNTRUSTED_THROTTLE) { } - bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) override + { + if (params.size() != 1) + { + return true; // will fail silently + } + + std::string fl_name = params[0].asString(); + + if (nav_type == NAV_TYPE_CLICKED) + { + const std::list<std::string> blacklist_clicked = { + "camera_presets", + "delete_pref_preset", + "forget_username", + "god_tools", + "group_picker", + "hud", + "incoming_call", + "linkreplace", + "message_critical", // Modal!!! Login specific. + "message_tos", // Modal!!! Login specific. + "save_pref_preset", + "save_camera_preset", + "region_restarting", + "outfit_snapshot", + "upload_anim_bvh", + "upload_anim_anim", + "upload_image", + "upload_model", + "upload_script", + "upload_sound" + }; + return std::find(blacklist_clicked.begin(), blacklist_clicked.end(), fl_name) == blacklist_clicked.end(); + } + else + { + const std::list<std::string> blacklist_untrusted = { + "360capture", + "block_timers", + "add_payment_method", + "appearance", + "associate_listing", + "avatar_picker", + "camera", + "camera_presets", + "classified", + "add_landmark", + "delete_pref_preset", + "env_fixed_environmentent_water", + "env_fixed_environmentent_sky", + "env_edit_extdaycycle", + "font_test", + "forget_username", + "god_tools", + "group_picker", + "hud", + "incoming_call", + "linkreplace", + "mem_leaking", + "marketplace_validation", + "message_critical", // Modal!!! Login specific. If this is in use elsewhere, better to create a non modal variant + "message_tos", // Modal!!! Login specific. + "mute_object_by_name", + "publish_classified", + "save_pref_preset", + "save_camera_preset", + "region_restarting", + "script_debug", + "script_debug_output", + "sell_land", + "outfit_snapshot", + "upload_anim_bvh", + "upload_anim_anim", + "upload_image", + "upload_model", + "upload_script", + "upload_sound" + }; + return std::find(blacklist_untrusted.begin(), blacklist_untrusted.end(), fl_name) == blacklist_untrusted.end(); + } + + + return true; + } + + bool handle( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web) override { if (params.size() != 1) { @@ -185,7 +278,12 @@ public: } const std::string floater_name = LLURI::unescape(params[0].asString()); - LLFloaterReg::showInstance(floater_name); + LLSD key; + if (floater_name == FLOATER_PROFILE) + { + key["id"] = gAgentID; + } + LLFloaterReg::showInstance(floater_name, key); return true; } @@ -368,7 +466,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>); LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>); LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>); - LLFloaterReg::add("outfit_snapshot", "floater_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutfitSnapshot>); + LLFloaterReg::add("simple_outfit_snapshot", "floater_simple_outfit_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSimpleOutfitSnapshot>); LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>); LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>); LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>); diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 43b9cd90bd..6bab2c2100 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1614,12 +1614,22 @@ BOOL LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, clicktype = CLICK_DOUBLELEFT; } + // If the first LMB click is handled by the menu, skip the following double click + static bool skip_double_click = false; + if (clicktype == CLICK_LEFT && down ) + { + skip_double_click = handled; + } if (double_click_sp && down) { // Consume click. // Due to handling, double click that is not handled will be immediately followed by LMB click } + else if (clicktype == CLICK_DOUBLELEFT && skip_double_click) + { + handled = true; + } // If UI handled 'down', it should handle 'up' as well // If we handle 'down' not by UI, then we should handle 'up'/'level' regardless of UI else if (handled) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 55ac817479..50252556de 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -232,7 +232,7 @@ class LLInventoryHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { } + LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_CLICK_ONLY) { } bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index fd314ed3dc..b3bfb86b99 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -45,7 +45,7 @@ #include "llglheaders.h" extern LLPipeline gPipeline; -const F32 MAX_ATTACHMENT_DIST = 3.5f; // meters? +const F32 MAX_ATTACHMENT_DIST = 3.5f; // meters //----------------------------------------------------------------------------- // LLViewerJointAttachment() diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index a1cb152e1e..8570c0cd5d 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -3581,7 +3581,20 @@ void LLViewerMediaImpl::calculateInterest() LLVector3d global_delta = agent_global - obj_global ; mProximityDistance = global_delta.magVecSquared(); // use distance-squared because it's cheaper and sorts the same. - LLVector3d camera_delta = gAgentCamera.getCameraPositionGlobal() - obj_global; + static LLUICachedControl<S32> mEarLocation("MediaSoundsEarLocation", 0); + LLVector3d ear_position; + switch(mEarLocation) + { + case 0: + default: + ear_position = gAgentCamera.getCameraPositionGlobal(); + break; + + case 1: + ear_position = agent_global; + break; + } + LLVector3d camera_delta = ear_position - obj_global; mProximityCamera = camera_delta.magVec(); } } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 3573af40cb..a0223a5dbb 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2803,14 +2803,15 @@ void handle_object_show_original() } -static void init_default_item_label(const std::string& item_name) +static void init_default_item_label(LLUICtrl* ctrl) { + const std::string& item_name = ctrl->getName(); boost::unordered_map<std::string, LLStringExplicit>::iterator it = sDefaultItemLabels.find(item_name); if (it == sDefaultItemLabels.end()) { // *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value // (doesn't seem to matter much ATM). - LLStringExplicit default_label = gMenuHolder->childGetValue(item_name).asString(); + LLStringExplicit default_label = ctrl->getValue().asString(); if (!default_label.empty()) { sDefaultItemLabels.insert(std::pair<std::string, LLStringExplicit>(item_name, default_label)); @@ -2841,18 +2842,17 @@ bool enable_object_touch(LLUICtrl* ctrl) new_value = obj->flagHandleTouch() || (parent && parent->flagHandleTouch()); } - std::string item_name = ctrl->getName(); - init_default_item_label(item_name); + init_default_item_label(ctrl); // Update label based on the node touch name if available. LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if (node && node->mValid && !node->mTouchName.empty()) { - gMenuHolder->childSetValue(item_name, node->mTouchName); + ctrl->setValue(node->mTouchName); } else { - gMenuHolder->childSetValue(item_name, get_default_item_label(item_name)); + ctrl->setValue(get_default_item_label(ctrl->getName())); } return new_value; @@ -4334,6 +4334,10 @@ class LLLandSit : public view_listener_t { bool handleEvent(const LLSD& userdata) { + if (gAgent.isSitting()) + { + gAgent.standUp(); + } LLVector3d posGlobal = LLToolPie::getInstance()->getPick().mPosGlobal; LLQuaternion target_rot; @@ -5628,6 +5632,7 @@ class LLToolsSelectNextPartFace : public view_listener_t } } LLSelectMgr::getInstance()->selectObjectOnly(to_select, new_te); + LLSelectMgr::getInstance()->addAsIndividual(to_select, new_te, false); } else { @@ -6591,20 +6596,18 @@ bool enable_object_sit(LLUICtrl* ctrl) bool sitting_on_sel = sitting_on_selection(); if (!sitting_on_sel) { - std::string item_name = ctrl->getName(); - // init default labels - init_default_item_label(item_name); + init_default_item_label(ctrl); // Update label LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if (node && node->mValid && !node->mSitName.empty()) { - gMenuHolder->childSetValue(item_name, node->mSitName); + ctrl->setValue(node->mSitName); } else { - gMenuHolder->childSetValue(item_name, get_default_item_label(item_name)); + ctrl->setValue(get_default_item_label(ctrl->getName())); } } return !sitting_on_sel && is_object_sittable(); @@ -7650,7 +7653,6 @@ void handle_selected_texture_info(void*) map_t::iterator it; for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it) { - LLUUID image_id = it->first; U8 te = it->second[0]; LLViewerTexture* img = node->getObject()->getTEImage(te); S32 height = img->getHeight(); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index f1e2c06e0c..fdf1d04c09 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -38,7 +38,7 @@ #include "llfloatermap.h" #include "llfloatermodelpreview.h" #include "llfloatersnapshot.h" -#include "llfloateroutfitsnapshot.h" +#include "llfloatersimpleoutfitsnapshot.h" #include "llimage.h" #include "llimagebmp.h" #include "llimagepng.h" @@ -664,7 +664,7 @@ class LLFileEnableCloseAllWindows : public view_listener_t bool handleEvent(const LLSD& userdata) { LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance(); - LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::findInstance(); + LLFloaterSimpleOutfitSnapshot* floater_outfit_snapshot = LLFloaterSimpleOutfitSnapshot::findInstance(); bool is_floaters_snapshot_opened = (floater_snapshot && floater_snapshot->isInVisibleChain()) || (floater_outfit_snapshot && floater_outfit_snapshot->isInVisibleChain()); bool open_children = gFloaterView->allChildrenClosed() && !is_floaters_snapshot_opened; @@ -681,7 +681,7 @@ class LLFileCloseAllWindows : public view_listener_t LLFloaterSnapshot* floater_snapshot = LLFloaterSnapshot::findInstance(); if (floater_snapshot) floater_snapshot->closeFloater(app_quitting); - LLFloaterOutfitSnapshot* floater_outfit_snapshot = LLFloaterOutfitSnapshot::findInstance(); + LLFloaterSimpleOutfitSnapshot* floater_outfit_snapshot = LLFloaterSimpleOutfitSnapshot::findInstance(); if (floater_outfit_snapshot) floater_outfit_snapshot->closeFloater(app_quitting); if (gMenuHolder) gMenuHolder->hideMenus(); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index aad6c14b4d..f47f0b4572 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -316,7 +316,8 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mLastUpdateType(OUT_UNKNOWN), mLastUpdateCached(FALSE), mCachedMuteListUpdateTime(0), - mCachedOwnerInMuteList(false) + mCachedOwnerInMuteList(false), + mRiggedAttachedWarned(false) { if (!is_global) { @@ -3233,36 +3234,39 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) return; } - LLFilenameAndTask* ft = new LLFilenameAndTask; - ft->mTaskID = task_id; // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update - msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial); + S16 serial = 0; + msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, serial); - if (ft->mSerial == object->mInventorySerialNum - && ft->mSerial < object->mExpectedInventorySerialNum) + if (serial == object->mInventorySerialNum + && serial < object->mExpectedInventorySerialNum) { // Loop Protection. // We received same serial twice. // Viewer did some changes to inventory that couldn't be saved server side // or something went wrong to cause serial to be out of sync. // Drop xfer and restart after some time, assign server's value as expected - LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL; - object->mExpectedInventorySerialNum = ft->mSerial; + LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << serial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL; + object->mExpectedInventorySerialNum = serial; object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_DESYNC); } - else if (ft->mSerial < object->mExpectedInventorySerialNum) + else if (serial < object->mExpectedInventorySerialNum) { // Out of date message, record to current serial for loop protection, but do not load it // Drop xfer and restart after some time - if (ft->mSerial < object->mInventorySerialNum) + if (serial < object->mInventorySerialNum) { LL_WARNS() << "Task serial decreased. Potentially out of order packet or desync." << LL_ENDL; } - object->mInventorySerialNum = ft->mSerial; + object->mInventorySerialNum = serial; object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_OUTDATED); } - else if (ft->mSerial >= object->mExpectedInventorySerialNum) + else if (serial >= object->mExpectedInventorySerialNum) { + LLFilenameAndTask* ft = new LLFilenameAndTask; + ft->mTaskID = task_id; + ft->mSerial = serial; + // We received version we expected or newer. Load it. object->mInventorySerialNum = ft->mSerial; object->mExpectedInventorySerialNum = ft->mSerial; @@ -3297,7 +3301,7 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) object->mRegionp->getHost(), TRUE, &LLViewerObject::processTaskInvFile, - (void**)ft, + (void**)ft, // This takes ownership of ft LLXferManager::HIGH_PRIORITY); if (object->mInvRequestState == INVENTORY_XFER) { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index bef8e3e7e3..0005cdf14e 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -702,6 +702,8 @@ public: // Replace textures with web pages on this object while drawing BOOL mRenderMedia; + bool mRiggedAttachedWarned; + // In bits S32 mBestUpdatePrecision; diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 75eb16c085..97dc916bfe 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1974,7 +1974,7 @@ void LLViewerParcelMgr::optionallyStartMusic(const std::string &music_url, const static LLCachedControl<bool> tentative_autoplay(gSavedSettings, "MediaTentativeAutoPlay", true); // only play music when you enter a new parcel if the UI control for this // was not *explicitly* stopped by the user. (part of SL-4878) - LLPanelNearByMedia* nearby_media_panel = gStatusBar->getNearbyMediaPanel(); + LLPanelNearByMedia* nearby_media_panel = gStatusBar ? gStatusBar->getNearbyMediaPanel() : NULL; LLViewerAudio* viewer_audio = LLViewerAudio::getInstance(); // ask mode //todo constants diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp index f042040e98..1751ee1ebb 100644 --- a/indra/newview/llviewerpartsource.cpp +++ b/indra/newview/llviewerpartsource.cpp @@ -793,7 +793,7 @@ void LLViewerPartSourceBeam::update(const F32 dt) } LLViewerPart* part = new LLViewerPart(); - part->init(this, mImagep, NULL); + part->init(this, mImagep, updatePart); part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index e2de7ac825..7abb42dd8a 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -1252,7 +1252,6 @@ bool LLViewerTextEditor::onCopyToInvDialog(const LLSD& notification, const LLSD& S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if( 0 == option ) { - LLUUID item_id = notification["payload"]["item_id"].asUUID(); llwchar wc = llwchar(notification["payload"]["item_wc"].asInteger()); LLInventoryItem* itemp = LLEmbeddedItems::getEmbeddedItemPtr(wc); if (itemp) diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index da3c860ddb..93ae1670c8 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -45,11 +45,13 @@ #include "llxmltree.h" #include "message.h" +#include "lldrawpoolbump.h" // to init bumpmap images #include "lltexturecache.h" #include "lltexturefetch.h" #include "llviewercontrol.h" #include "llviewertexture.h" #include "llviewermedia.h" +#include "llviewernetwork.h" #include "llviewerregion.h" #include "llviewerstats.h" #include "pipeline.h" @@ -139,9 +141,6 @@ void LLViewerTextureList::doPreloadImages() //uv_test->setClamp(FALSE, FALSE); //uv_test->setMipFilterNearest(TRUE, TRUE); - // prefetch specific UUIDs - LLViewerTextureManager::getFetchedTexture(IMG_SHOT); - LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF); LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { @@ -160,12 +159,6 @@ void LLViewerTextureList::doPreloadImages() image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, FTT_DEFAULT, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); - if (image) - { - image->setAddressMode(LLTexUnit::TAM_WRAP); - mImagePreloads.insert(image); - } image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, 0, 0, IMG_TRANSPARENT); if (image) @@ -198,7 +191,18 @@ void LLViewerTextureList::doPreloadImages() static std::string get_texture_list_name() { - return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "texture_list_" + gSavedSettings.getString("LoginLocation") + "." + gDirUtilp->getUserName() + ".xml"); + if (LLGridManager::getInstance()->isInProductionGrid()) + { + return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, + "texture_list_" + gSavedSettings.getString("LoginLocation") + "." + gDirUtilp->getUserName() + ".xml"); + } + else + { + const std::string& grid_id_str = LLGridManager::getInstance()->getGridId(); + const std::string& grid_id_lower = utf8str_tolower(grid_id_str); + return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, + "texture_list_" + gSavedSettings.getString("LoginLocation") + "." + gDirUtilp->getUserName() + "." + grid_id_lower + ".xml"); + } } void LLViewerTextureList::doPrefetchImages() @@ -207,6 +211,26 @@ void LLViewerTextureList::doPrefetchImages() gTextureTimer.start(); gTextureTimer.pause(); + // todo: do not load without getViewerAssetUrl() + // either fail login without caps or provide this + // in some other way, textures won't load otherwise + LLViewerFetchedTexture *imagep = findImage(DEFAULT_WATER_NORMAL, TEX_LIST_STANDARD); + if (!imagep) + { + // add it to mImagePreloads only once + imagep = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, FTT_DEFAULT, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + if (imagep) + { + imagep->setAddressMode(LLTexUnit::TAM_WRAP); + mImagePreloads.insert(imagep); + } + } + + LLViewerTextureManager::getFetchedTexture(IMG_SHOT); + LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF); + + LLStandardBumpmap::addstandard(); + if (LLAppViewer::instance()->getPurgeCache()) { // cache was purged, no point @@ -1501,152 +1525,6 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem) /////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_data) -{ - static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ; - - LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - - // Receive image header, copy into image object and decompresses - // if this is a one-packet image. - - LLUUID id; - - char ip_string[256]; - u32_to_ip_string(msg->getSenderIP(),ip_string); - - U32Bytes received_size ; - if (msg->getReceiveCompressedSize()) - { - received_size = (U32Bytes)msg->getReceiveCompressedSize() ; - } - else - { - received_size = (U32Bytes)msg->getReceiveSize() ; - } - add(LLStatViewer::TEXTURE_NETWORK_DATA_RECEIVED, received_size); - add(LLStatViewer::TEXTURE_PACKETS, 1); - - U8 codec; - U16 packets; - U32 totalbytes; - msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); - msg->getU8Fast(_PREHASH_ImageID, _PREHASH_Codec, codec); - msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packets, packets); - msg->getU32Fast(_PREHASH_ImageID, _PREHASH_Size, totalbytes); - - S32 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); - if (!data_size) - { - return; - } - if (data_size < 0) - { - // msg->getSizeFast() is probably trying to tell us there - // was an error. - LL_ERRS() << "image header chunk size was negative: " - << data_size << LL_ENDL; - return; - } - - // this buffer gets saved off in the packet list - U8 *data = new U8[data_size]; - msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - if (!image) - { - delete [] data; - return; - } - if(log_texture_traffic) - { - gTotalTextureBytesPerBoostLevel[image->getBoostLevel()] += received_size ; - } - - //image->getLastPacketTimer()->reset(); - bool res = LLAppViewer::getTextureFetch()->receiveImageHeader(msg->getSender(), id, codec, packets, totalbytes, data_size, data); - if (!res) - { - delete[] data; - } -} - -// static -void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_data) -{ - static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ; - - LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - - // Receives image packet, copy into image object, - // checks if all packets received, decompresses if so. - - LLUUID id; - U16 packet_num; - - char ip_string[256]; - u32_to_ip_string(msg->getSenderIP(),ip_string); - - U32Bytes received_size ; - if (msg->getReceiveCompressedSize()) - { - received_size = (U32Bytes)msg->getReceiveCompressedSize() ; - } - else - { - received_size = (U32Bytes)msg->getReceiveSize() ; - } - - add(LLStatViewer::TEXTURE_NETWORK_DATA_RECEIVED, F64Bytes(received_size)); - add(LLStatViewer::TEXTURE_PACKETS, 1); - - //llprintline("Start decode, image header..."); - msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); - msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packet, packet_num); - S32 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); - - if (!data_size) - { - return; - } - if (data_size < 0) - { - // msg->getSizeFast() is probably trying to tell us there - // was an error. - LL_ERRS() << "image data chunk size was negative: " - << data_size << LL_ENDL; - return; - } - if (data_size > MTUBYTES) - { - LL_ERRS() << "image data chunk too large: " << data_size << " bytes" << LL_ENDL; - return; - } - U8 *data = new U8[data_size]; - msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); - if (!image) - { - delete [] data; - return; - } - if(log_texture_traffic) - { - gTotalTextureBytesPerBoostLevel[image->getBoostLevel()] += received_size ; - } - - //image->getLastPacketTimer()->reset(); - bool res = LLAppViewer::getTextureFetch()->receiveImagePacket(msg->getSender(), id, packet_num, data_size, data); - if (!res) - { - delete[] data; - } -} - - // We've been that the asset server does not contain the requested image id. // static void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem *msg,void **user_data) diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 6fb0d3552e..0018e78d45 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -98,8 +98,6 @@ public: const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); static LLPointer<LLImageJ2C> convertToUploadFile(LLPointer<LLImageRaw> raw_image, const S32 max_image_dimentions = LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); static void processImageNotInDatabase( LLMessageSystem *msg, void **user_data ); - static void receiveImageHeader(LLMessageSystem *msg, void **user_data); - static void receiveImagePacket(LLMessageSystem *msg, void **user_data); public: LLViewerTextureList(); @@ -133,7 +131,9 @@ public: void updateMaxResidentTexMem(S32Megabytes mem); + // Local UI images void doPreloadImages(); + // Network images. Needs caps and cache to work void doPrefetchImages(); void clearFetchingRequests(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 8a7d5f12d0..ddc11ac0bd 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -262,6 +262,8 @@ static const F32 MIN_UI_SCALE = 0.75f; static const F32 MAX_UI_SCALE = 7.0f; static const F32 MIN_DISPLAY_SCALE = 0.75f; +static const char KEY_MOUSELOOK = 'M'; + static LLCachedControl<std::string> sSnapshotBaseName(LLCachedControl<std::string>(gSavedPerAccountSettings, "SnapshotBaseName", "Snapshot")); static LLCachedControl<std::string> sSnapshotDir(LLCachedControl<std::string>(gSavedPerAccountSettings, "SnapshotBaseDir", "")); @@ -1307,7 +1309,6 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi TRUE /* pick_transparent */, FALSE /* pick_rigged */); - LLUUID object_id = pick_info.getObjectID(); S32 object_face = pick_info.mObjectFace; std::string url = data; @@ -2232,31 +2233,36 @@ void LLViewerWindow::initWorldUI() // Force gFloaterTools to initialize LLFloaterReg::getInstance("build"); - // Status bar LLPanel* status_bar_container = getRootView()->getChild<LLPanel>("status_bar_container"); gStatusBar = new LLStatusBar(status_bar_container->getLocalRect()); - gStatusBar->setFollowsAll(); + gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_RIGHT); gStatusBar->setShape(status_bar_container->getLocalRect()); // sync bg color with menu bar gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() ); // add InBack so that gStatusBar won't be drawn over menu - status_bar_container->addChildInBack(gStatusBar); - status_bar_container->setVisible(TRUE); + status_bar_container->addChildInBack(gStatusBar, 2/*tab order, after menu*/); + status_bar_container->setVisible(TRUE); // Navigation bar - LLPanel* nav_bar_container = getRootView()->getChild<LLPanel>("nav_bar_container"); + LLView* nav_bar_container = getRootView()->getChild<LLView>("nav_bar_container"); LLNavigationBar* navbar = LLNavigationBar::getInstance(); navbar->setShape(nav_bar_container->getLocalRect()); navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get()); nav_bar_container->addChild(navbar); nav_bar_container->setVisible(TRUE); - + + if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel")) { navbar->setVisible(FALSE); } + else + { + reshapeStatusBarContainer(); + } + // Top Info bar LLPanel* topinfo_bar_container = getRootView()->getChild<LLPanel>("topinfo_bar_container"); @@ -2883,6 +2889,13 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if (keyboard_focus && !gFocusMgr.getKeystrokesOnly()) { + //Most things should fall through, but mouselook is an exception, + //don't switch to mouselook if any floater has focus + if ((key == KEY_MOUSELOOK) && !(mask & (MASK_CONTROL | MASK_ALT))) + { + return TRUE; + } + LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(keyboard_focus); if (cur_focus && cur_focus->acceptsTextInput()) { @@ -3421,6 +3434,59 @@ void LLViewerWindow::updateUI() root_view = mRootView; } + static LLCachedControl<bool> dump_menu_holder(gSavedSettings, "DumpMenuHolderSize", false); + if (dump_menu_holder) + { + static bool init = false; + static LLFrameTimer child_count_timer; + static std::vector <std::string> child_vec; + if (!init) + { + child_count_timer.resetWithExpiry(5.f); + init = true; + } + if (child_count_timer.hasExpired()) + { + LL_INFOS() << "gMenuHolder child count: " << gMenuHolder->getChildCount() << LL_ENDL; + std::vector<std::string> local_child_vec; + LLView::child_list_t child_list = *gMenuHolder->getChildList(); + for (auto child : child_list) + { + local_child_vec.emplace_back(child->getName()); + } + if (!local_child_vec.empty() && local_child_vec != child_vec) + { + std::vector<std::string> out_vec; + std::sort(local_child_vec.begin(), local_child_vec.end()); + std::sort(child_vec.begin(), child_vec.end()); + std::set_difference(child_vec.begin(), child_vec.end(), local_child_vec.begin(), local_child_vec.end(), std::inserter(out_vec, out_vec.begin())); + if (!out_vec.empty()) + { + LL_INFOS() << "gMenuHolder removal diff size: '"<<out_vec.size() <<"' begin_child_diff"; + for (auto str : out_vec) + { + LL_CONT << " : " << str; + } + LL_CONT << " : end_child_diff" << LL_ENDL; + } + + out_vec.clear(); + std::set_difference(local_child_vec.begin(), local_child_vec.end(), child_vec.begin(), child_vec.end(), std::inserter(out_vec, out_vec.begin())); + if (!out_vec.empty()) + { + LL_INFOS() << "gMenuHolder addition diff size: '" << out_vec.size() << "' begin_child_diff"; + for (auto str : out_vec) + { + LL_CONT << " : " << str; + } + LL_CONT << " : end_child_diff" << LL_ENDL; + } + child_vec.swap(local_child_vec); + } + child_count_timer.resetWithExpiry(5.f); + } + } + // only update mouse hover set when UI is visible (since we shouldn't send hover events to invisible UI if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { @@ -5842,6 +5908,27 @@ LLRect LLViewerWindow::getChatConsoleRect() return console_rect; } + +void LLViewerWindow::reshapeStatusBarContainer() +{ + LLPanel* status_bar_container = getRootView()->getChild<LLPanel>("status_bar_container"); + LLView* nav_bar_container = getRootView()->getChild<LLView>("nav_bar_container"); + + S32 new_height = status_bar_container->getRect().getHeight(); + S32 new_width = status_bar_container->getRect().getWidth(); + + if (gSavedSettings.getBOOL("ShowNavbarNavigationPanel")) + { + // Navigation bar is outside visible area, expand status_bar_container to show it + new_height += nav_bar_container->getRect().getHeight(); + } + else + { + // collapse status_bar_container + new_height -= nav_bar_container->getRect().getHeight(); + } + status_bar_container->reshape(new_width, new_height, TRUE); +} //---------------------------------------------------------------------------- diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 979a560508..1927e01ddb 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -177,6 +177,8 @@ public: bool getUIVisibility(); void handlePieMenu(S32 x, S32 y, MASK mask); + void reshapeStatusBarContainer(); + BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down); // diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index 46beac8255..0e6734f6e0 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -287,6 +287,12 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, BOOL delete_raw = (mDetailTextures[i]->reloadRawImage(ddiscard) != NULL) ; if(mDetailTextures[i]->getRawImageLevel() != ddiscard)//raw iamge is not ready, will enter here again later. { + if (mDetailTextures[i]->getDecodePriority() <= 0.0f && !mDetailTextures[i]->hasSavedRawImage()) + { + mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_MAP); + mDetailTextures[i]->forceToRefetchTexture(ddiscard); + } + if(delete_raw) { mDetailTextures[i]->destroyRawImage() ; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 42550ed48d..176528cb56 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -10636,7 +10636,7 @@ void LLVOAvatar::updateVisualComplexity() // with an avatar. This will be either an attached object or an animated // object. void LLVOAvatar::accountRenderComplexityForObject( - const LLViewerObject *attached_object, + LLViewerObject *attached_object, const F32 max_attachment_complexity, LLVOVolume::texture_cost_t& textures, U32& cost, @@ -10708,7 +10708,7 @@ void LLVOAvatar::accountRenderComplexityForObject( && attached_object->mDrawable) { textures.clear(); - + BOOL is_rigged_mesh = attached_object->isRiggedMesh(); mAttachmentSurfaceArea += attached_object->recursiveGetScaledSurfaceArea(); const LLVOVolume* volume = attached_object->mDrawable->getVOVolume(); @@ -10729,6 +10729,7 @@ void LLVOAvatar::accountRenderComplexityForObject( iter != child_list.end(); ++iter) { LLViewerObject* childp = *iter; + is_rigged_mesh |= childp->isRiggedMesh(); const LLVOVolume* chld_volume = dynamic_cast<LLVOVolume*>(childp); if (chld_volume) { @@ -10737,6 +10738,16 @@ void LLVOAvatar::accountRenderComplexityForObject( hud_object_complexity.objectsCount++; } } + if (is_rigged_mesh && !attached_object->mRiggedAttachedWarned) + { + LLSD args; + LLViewerInventoryItem* itemp = gInventory.getItem(attached_object->getAttachmentItemID()); + args["NAME"] = itemp ? itemp->getName() : LLTrans::getString("Unknown"); + args["POINT"] = LLTrans::getString(getTargetAttachmentPoint(attached_object)->getName()); + LLNotificationsUtil::add("RiggedMeshAttachedToHUD", args); + + attached_object->mRiggedAttachedWarned = true; + } hud_object_complexity.texturesCount += textures.size(); @@ -10841,7 +10852,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() attachment_iter != attachment->mAttachedObjects.end(); ++attachment_iter) { - const LLViewerObject* attached_object = attachment_iter->get(); + LLViewerObject* attached_object = attachment_iter->get(); accountRenderComplexityForObject(attached_object, max_attachment_complexity, textures, cost, hud_complexity_list); } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 8d1dcbcda2..56f2b73bef 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -293,7 +293,7 @@ public: void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font, const bool use_ellipses = false); void idleUpdateRenderComplexity(); void idleUpdateDebugInfo(); - void accountRenderComplexityForObject(const LLViewerObject *attached_object, + void accountRenderComplexityForObject(LLViewerObject *attached_object, const F32 max_attachment_complexity, LLVOVolume::texture_cost_t& textures, U32& cost, diff --git a/indra/newview/llvoground.h b/indra/newview/llvoground.h index a53f309e46..e7033290c7 100644 --- a/indra/newview/llvoground.h +++ b/indra/newview/llvoground.h @@ -49,7 +49,6 @@ public: /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - void cleanupGL(); }; #endif // LL_LLVOGROUND_H diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 2ef2d66f18..6bb987ede4 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -797,7 +797,10 @@ void LLVoiceClient::addObserver(LLVoiceClientStatusObserver* observer) void LLVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer) { - if (mVoiceModule && mVoiceModule->singletoneInstanceExists()) mVoiceModule->removeObserver(observer); + if (mVoiceModule) + { + mVoiceModule->removeObserver(observer); + } } void LLVoiceClient::addObserver(LLFriendObserver* observer) @@ -807,7 +810,10 @@ void LLVoiceClient::addObserver(LLFriendObserver* observer) void LLVoiceClient::removeObserver(LLFriendObserver* observer) { - if (mVoiceModule && mVoiceModule->singletoneInstanceExists()) mVoiceModule->removeObserver(observer); + if (mVoiceModule) + { + mVoiceModule->removeObserver(observer); + } } void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer) @@ -817,7 +823,10 @@ void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer) void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer) { - if (mVoiceModule && mVoiceModule->singletoneInstanceExists()) mVoiceModule->removeObserver(observer); + if (mVoiceModule) + { + mVoiceModule->removeObserver(observer); + } } std::string LLVoiceClient::sipURIFromID(const LLUUID &id) diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 246883b611..aa67502908 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -122,8 +122,6 @@ public: virtual const LLVoiceVersionInfo& getVersion()=0; - virtual bool singletoneInstanceExists()=0; - ///////////////////// /// @name Tuning //@{ diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index ac6369e4e2..8f0938d01e 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -1247,8 +1247,8 @@ bool LLVivoxVoiceClient::establishVoiceConnection() if (result.has("connector")) { - LLVoiceVivoxStats::getInstance()->establishAttemptEnd(connected); connected = LLSD::Boolean(result["connector"]); + LLVoiceVivoxStats::getInstance()->establishAttemptEnd(connected); if (!connected) { if (result.has("retry") && ++retries <= CONNECT_RETRY_MAX && !sShuttingDown) @@ -4551,9 +4551,7 @@ void LLVivoxVoiceClient::messageEvent( IM_NOTHING_SPECIAL, // default arg 0, // default arg LLUUID::null, // default arg - LLVector3::zero, // default arg - true); // prepend name and make it a link to the user's profile - + LLVector3::zero); // default arg } } } @@ -5217,11 +5215,6 @@ void LLVivoxVoiceClient::declineInvite(std::string &sessionHandle) } } -bool LLVivoxVoiceClient::singletoneInstanceExists() -{ - return LLVivoxVoiceClient::instanceExists(); -} - void LLVivoxVoiceClient::leaveNonSpatialChannel() { LL_DEBUGS("Voice") << "Request to leave spacial channel." << LL_ENDL; @@ -6229,7 +6222,7 @@ void LLVivoxVoiceClient::clearSessionHandle(const sessionStatePtr_t &session) { if (session) { - if (session->mHandle.empty()) + if (!session->mHandle.empty()) { sessionMap::iterator iter = mSessionsByHandle.find(session->mHandle); if (iter != mSessionsByHandle.end()) diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index ebc3a62c35..0a785401c1 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -73,8 +73,6 @@ public: // Returns true if vivox has successfully logged in and is not in error state virtual bool isVoiceWorking() const; - - virtual bool singletoneInstanceExists(); ///////////////////// /// @name Tuning diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 1aa00bc894..909588367b 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -100,8 +100,8 @@ LLSkyTex::LLSkyTex() : void LLSkyTex::init(bool isShiny) { mIsShiny = isShiny; - mSkyData = new LLColor4[SKYTEX_RESOLUTION * SKYTEX_RESOLUTION]; - mSkyDirs = new LLVector3[SKYTEX_RESOLUTION * SKYTEX_RESOLUTION]; + mSkyData = new LLColor4[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)]; + mSkyDirs = new LLVector3[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)]; for (S32 i = 0; i < 2; ++i) { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index a4e0d367c8..2e7ccc8334 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -228,6 +228,9 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mColorChanged = FALSE; mSpotLightPriority = 0.f; + mSkinInfoFailed = false; + mSkinInfo = NULL; + mMediaImplList.resize(getNumTEs()); mLastFetchedMediaVersion = -1; mServerDrawableUpdateCount = 0; @@ -244,6 +247,8 @@ LLVOVolume::~LLVOVolume() delete mVolumeImpl; mVolumeImpl = NULL; + gMeshRepo.unregisterMesh(this); + if(!mMediaImplList.empty()) { for(U32 i = 0 ; i < mMediaImplList.size() ; i++) @@ -851,10 +856,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) if (isSculpted()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - - updateSculptTexture(); + updateSculptTexture(); @@ -1095,10 +1097,15 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo // if it's a mesh if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { + if (mSkinInfo && mSkinInfo->mMeshID != volume_params.getSculptID()) + { + mSkinInfo = NULL; + mSkinInfoFailed = false; + } + if (!getVolume()->isMeshAssetLoaded()) { //load request not yet issued, request pipeline load this mesh - LLUUID asset_id = volume_params.getSculptID(); S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod); if (available_lod != lod) { @@ -1106,6 +1113,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo } } + if (!mSkinInfo && !mSkinInfoFailed) + { + const LLMeshSkinInfo* skin_info = gMeshRepo.getSkinInfo(volume_params.getSculptID(), this); + if (skin_info) + { + notifySkinInfoLoaded(skin_info); + } + } } else // otherwise is sculptie { @@ -1158,6 +1173,9 @@ void LLVOVolume::updateSculptTexture() { mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); } + + mSkinInfoFailed = false; + mSkinInfo = NULL; } else { @@ -1212,6 +1230,20 @@ void LLVOVolume::notifyMeshLoaded() updateVisualComplexity(); } +void LLVOVolume::notifySkinInfoLoaded(const LLMeshSkinInfo* skin) +{ + mSkinInfoFailed = false; + mSkinInfo = skin; + + notifyMeshLoaded(); +} + +void LLVOVolume::notifySkinInfoUnavailable() +{ + mSkinInfoFailed = true; + mSkinInfo = nullptr; +} + // sculpt replaces generate() for sculpted surfaces void LLVOVolume::sculpt() { @@ -3645,7 +3677,7 @@ const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const { if (getVolume()) { - return gMeshRepo.getSkinInfo(getMeshID(), this); + return mSkinInfo; } else { diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 01ad40274b..59599ddc0c 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -353,6 +353,8 @@ public: void updateVisualComplexity(); void notifyMeshLoaded(); + void notifySkinInfoLoaded(const LLMeshSkinInfo* skin); + void notifySkinInfoUnavailable(); // Returns 'true' iff the media data for this object is in flight bool isMediaDataBeingFetched() const; @@ -437,6 +439,8 @@ private: LLPointer<LLRiggedVolume> mRiggedVolume; + bool mSkinInfoFailed; + LLConstPointer<LLMeshSkinInfo> mSkinInfo; // statics public: static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index bf4db81475..89b74ae962 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -92,17 +92,77 @@ LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item, co ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelWearableOutfitItem(&typeid(LLPanelWearableOutfitItem::Params), "wearable_outfit_list_item"); + +LLPanelWearableOutfitItem::Params::Params() +: add_btn("add_btn"), + remove_btn("remove_btn") +{ +} + +BOOL LLPanelWearableOutfitItem::postBuild() +{ + LLPanelWearableListItem::postBuild(); + + LLViewerInventoryItem* inv_item = getItem(); + mShowWidgets &= (inv_item->getType() != LLAssetType::AT_BODYPART); + if(mShowWidgets) + { + addWidgetToRightSide("add_wearable"); + addWidgetToRightSide("remove_wearable"); + + childSetAction("add_wearable", boost::bind(&LLPanelWearableOutfitItem::onAddWearable, this)); + childSetAction("remove_wearable", boost::bind(&LLPanelWearableOutfitItem::onRemoveWearable, this)); + + setWidgetsVisible(false); + reshapeWidgets(); + } + return TRUE; +} + +BOOL LLPanelWearableOutfitItem::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + if(!mShowWidgets) + { + return LLPanelWearableListItem::handleDoubleClick(x, y, mask); + } + + if(LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID)) + { + onRemoveWearable(); + } + else + { + onAddWearable(); + } + return TRUE; +} + +void LLPanelWearableOutfitItem::onAddWearable() +{ + setWidgetsVisible(false); + reshapeWidgets(); + LLAppearanceMgr::instance().wearItemOnAvatar(mInventoryItemUUID, true, false); +} + +void LLPanelWearableOutfitItem::onRemoveWearable() +{ + setWidgetsVisible(false); + reshapeWidgets(); + LLAppearanceMgr::instance().removeItemFromAvatar(mInventoryItemUUID); +} // static LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryItem* item, - bool worn_indication_enabled) + bool worn_indication_enabled, + bool show_widgets) { LLPanelWearableOutfitItem* list_item = NULL; if (item) { - const LLPanelInventoryListItemBase::Params& params = LLUICtrlFactory::getDefaultParams<LLPanelInventoryListItemBase>(); + const LLPanelWearableOutfitItem::Params& params = LLUICtrlFactory::getDefaultParams<LLPanelWearableOutfitItem>(); - list_item = new LLPanelWearableOutfitItem(item, worn_indication_enabled, params); + list_item = new LLPanelWearableOutfitItem(item, worn_indication_enabled, params, show_widgets); list_item->initFromParams(params); list_item->postBuild(); } @@ -110,11 +170,23 @@ LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryIt } LLPanelWearableOutfitItem::LLPanelWearableOutfitItem(LLViewerInventoryItem* item, - bool worn_indication_enabled, - const LLPanelWearableOutfitItem::Params& params) -: LLPanelInventoryListItemBase(item, params) + bool worn_indication_enabled, + const LLPanelWearableOutfitItem::Params& params, + bool show_widgets) +: LLPanelWearableListItem(item, params) , mWornIndicationEnabled(worn_indication_enabled) +, mShowWidgets(show_widgets) { + if(mShowWidgets) + { + LLButton::Params button_params = params.add_btn; + applyXUILayout(button_params, this); + addChild(LLUICtrlFactory::create<LLButton>(button_params)); + + button_params = params.remove_btn; + applyXUILayout(button_params, this); + addChild(LLUICtrlFactory::create<LLButton>(button_params)); + } } // virtual @@ -127,11 +199,22 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name, // We don't use get_is_item_worn() here because this update is triggered by // an inventory observer upon link in COF beind added or removed so actual // worn status of a linked item may still remain unchanged. - if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID)) + bool is_worn = LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID); + if (mWornIndicationEnabled && is_worn) { search_label += LLTrans::getString("worn"); item_state = IS_WORN; } + if(mShowWidgets) + { + setShowWidget("add_wearable", !is_worn); + setShowWidget("remove_wearable", is_worn); + if(mHovered) + { + setWidgetsVisible(true); + reshapeWidgets(); + } + } LLPanelInventoryListItemBase::updateItem(search_label, item_state); } @@ -634,6 +717,7 @@ static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_i LLWearableItemsList::Params::Params() : standalone("standalone", true) , worn_indication_enabled("worn_indication_enabled", true) +, show_item_widgets("show_item_widgets", false) {} LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) @@ -649,6 +733,7 @@ LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) } mWornIndicationEnabled = p.worn_indication_enabled; setNoItemsCommentText(LLTrans::getString("LoadingData")); + mShowItemWidgets = p.show_item_widgets; } // virtual @@ -665,7 +750,7 @@ LLPanel* LLWearableItemsList::createNewItem(LLViewerInventoryItem* item) return NULL; } - return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled); + return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled, mShowItemWidgets); } void LLWearableItemsList::updateList(const LLUUID& category_id) diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index ba8488b237..f7774a7086 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -72,12 +72,23 @@ protected: * Extends LLPanelInventoryListItemBase with handling * double click to wear the item. */ -class LLPanelWearableOutfitItem : public LLPanelInventoryListItemBase +class LLPanelWearableOutfitItem : public LLPanelWearableListItem { LOG_CLASS(LLPanelWearableOutfitItem); public: + struct Params : public LLInitParam::Block<Params, LLPanelWearableListItem::Params> + { + Optional<LLButton::Params> add_btn, remove_btn; + + Params(); + }; + + BOOL postBuild(); + BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + static LLPanelWearableOutfitItem* create(LLViewerInventoryItem* item, - bool worn_indication_enabled); + bool worn_indication_enabled, + bool show_widgets); /** * Updates item name and (worn) suffix. @@ -85,12 +96,16 @@ public: /*virtual*/ void updateItem(const std::string& name, EItemState item_state = IS_DEFAULT); + void onAddWearable(); + void onRemoveWearable(); + protected: LLPanelWearableOutfitItem(LLViewerInventoryItem* item, - bool worn_indication_enabled, const Params& params); + bool worn_indication_enabled, const Params& params, bool show_widgets = false); private: bool mWornIndicationEnabled; + bool mShowWidgets; }; class LLPanelDeletableWearableListItem : public LLPanelWearableListItem @@ -442,6 +457,7 @@ public: { Optional<bool> standalone; Optional<bool> worn_indication_enabled; + Optional<bool> show_item_widgets; Params(); }; @@ -482,6 +498,7 @@ protected: bool mIsStandalone; bool mWornIndicationEnabled; + bool mShowItemWidgets; ESortOrder mSortOrder; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index aa32ef04b2..871583e071 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -93,7 +93,7 @@ LLWorld::LLWorld() : mLastPacketsLost(0), mSpaceTimeUSec(0) { - for (S32 i = 0; i < 8; i++) + for (S32 i = 0; i < EDGE_WATER_OBJECTS_COUNT; i++) { mEdgeWaterObjects[i] = NULL; } @@ -126,7 +126,7 @@ void LLWorld::resetClass() LLViewerPartSim::getInstance()->destroyClass(); mDefaultWaterTexturep = NULL ; - for (S32 i = 0; i < 8; i++) + for (S32 i = 0; i < EDGE_WATER_OBJECTS_COUNT; i++) { mEdgeWaterObjects[i] = NULL; } @@ -293,13 +293,13 @@ void LLWorld::removeRegion(const LLHost &host) mRegionRemovedSignal(regionp); - delete regionp; - updateWaterObjects(); //double check all objects of this region are removed. gObjectList.clearAllMapObjectsInRegion(regionp) ; //llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ; + + delete regionp; // Delete last to prevent use after free } @@ -753,6 +753,8 @@ void LLWorld::clearAllVisibleObjects() //clear all cached visible objects. (*iter)->clearCachedVisibleObjects(); } + clearHoleWaterObjects(); + clearEdgeWaterObjects(); } void LLWorld::updateParticles() @@ -920,7 +922,7 @@ void LLWorld::precullWaterObjects(LLCamera& camera, LLCullResult* cull, bool inc } S32 dir; - for (dir = 0; dir < 8; dir++) + for (dir = 0; dir < EDGE_WATER_OBJECTS_COUNT; dir++) { LLVOWater* waterp = mEdgeWaterObjects[dir]; if (waterp && waterp->mDrawable) @@ -931,6 +933,26 @@ void LLWorld::precullWaterObjects(LLCamera& camera, LLCullResult* cull, bool inc } } +void LLWorld::clearHoleWaterObjects() +{ + for (std::list<LLPointer<LLVOWater> >::iterator iter = mHoleWaterObjects.begin(); + iter != mHoleWaterObjects.end(); ++iter) + { + LLVOWater* waterp = (*iter).get(); + gObjectList.killObject(waterp); + } + mHoleWaterObjects.clear(); +} + +void LLWorld::clearEdgeWaterObjects() +{ + for (S32 i = 0; i < EDGE_WATER_OBJECTS_COUNT; i++) + { + gObjectList.killObject(mEdgeWaterObjects[i]); + mEdgeWaterObjects[i] = NULL; + } +} + void LLWorld::updateWaterObjects() { if (!gAgent.getRegion()) @@ -974,13 +996,7 @@ void LLWorld::updateWaterObjects() } } - for (std::list<LLPointer<LLVOWater> >::iterator iter = mHoleWaterObjects.begin(); - iter != mHoleWaterObjects.end(); ++ iter) - { - LLVOWater* waterp = (*iter).get(); - gObjectList.killObject(waterp); - } - mHoleWaterObjects.clear(); + clearHoleWaterObjects(); // Use the water height of the region we're on for areas where there is no region F32 water_height = gAgent.getRegion()->getWaterHeight(); @@ -1021,7 +1037,7 @@ void LLWorld::updateWaterObjects() (S32)(512 - (region_y - min_y)) }; S32 dir; - for (dir = 0; dir < 8; dir++) + for (dir = 0; dir < EDGE_WATER_OBJECTS_COUNT; dir++) { S32 dim[2] = { 0 }; switch (gDirAxes[dir][0]) diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index 5c43cdf4e2..5dee8eea0f 100644 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -122,12 +122,9 @@ public: void updateRegions(F32 max_update_time); void updateVisibilities(); void updateParticles(); - void updateClouds(const F32 dt); - LLCloudGroup * findCloudGroup(const LLCloudPuff &puff); void renderPropertyLines(); - void resetStats(); void updateNetStats(); // Update network statistics for all the regions... void printPacketsLost(); @@ -140,7 +137,7 @@ public: void setLandFarClip(const F32 far_clip); LLViewerTexture *getDefaultWaterTexture(); - void updateWaterObjects(); + void updateWaterObjects(); void precullWaterObjects(LLCamera& camera, LLCullResult* cull, bool include_void_water); @@ -175,6 +172,9 @@ public: bool isRegionListed(const LLViewerRegion* region) const; private: + void clearHoleWaterObjects(); + void clearEdgeWaterObjects(); + region_list_t mActiveRegionList; region_list_t mRegionList; region_list_t mVisibleRegionList; @@ -198,15 +198,14 @@ private: U32 mNumOfActiveCachedObjects; U64MicrosecondsImplicit mSpaceTimeUSec; - BOOL mClassicCloudsEnabled; - //////////////////////////// // // Data for "Fake" objects // std::list<LLPointer<LLVOWater> > mHoleWaterObjects; - LLPointer<LLVOWater> mEdgeWaterObjects[8]; + static const S32 EDGE_WATER_OBJECTS_COUNT = 8; + LLPointer<LLVOWater> mEdgeWaterObjects[EDGE_WATER_OBJECTS_COUNT]; LLPointer<LLViewerTexture> mDefaultWaterTexturep; }; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 96ba80dacc..13d6966723 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -685,7 +685,9 @@ void LLPipeline::cleanup() mFaceSelectImagep = NULL; - mMovedBridge.clear(); + mMovedList.clear(); + mMovedBridge.clear(); + mShiftList.clear(); mInitialized = false; @@ -1773,15 +1775,20 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) void LLPipeline::removeMutedAVsLights(LLVOAvatar* muted_avatar) { LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; - for (light_set_t::iterator iter = gPipeline.mNearbyLights.begin(); - iter != gPipeline.mNearbyLights.end(); iter++) - { - if (iter->drawable->getVObj()->isAttachment() && iter->drawable->getVObj()->getAvatar() == muted_avatar) - { - gPipeline.mLights.erase(iter->drawable); - gPipeline.mNearbyLights.erase(iter); - } - } + light_set_t::iterator iter = gPipeline.mNearbyLights.begin(); + + while (iter != gPipeline.mNearbyLights.end()) + { + if (iter->drawable->getVObj()->isAttachment() && iter->drawable->getVObj()->getAvatar() == muted_avatar) + { + gPipeline.mLights.erase(iter->drawable); + iter = gPipeline.mNearbyLights.erase(iter); + } + else + { + iter++; + } + } } U32 LLPipeline::addObject(LLViewerObject *vobj) @@ -2817,6 +2824,14 @@ void LLPipeline::clearRebuildDrawables() drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD); } mMovedList.clear(); + + for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); + iter != mShiftList.end(); ++iter) + { + LLDrawable *drawablep = *iter; + drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED | LLDrawable::ON_MOVE_LIST | LLDrawable::ANIMATED_CHILD | LLDrawable::ON_SHIFT_LIST); + } + mShiftList.clear(); } void LLPipeline::rebuildPriorityGroups() @@ -10906,6 +10921,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar) if (preview_avatar) { // Only show rigged attachments for preview + // For the sake of performance and so that static + // objects won't obstruct previewing changes LLVOAvatar::attachment_map_t::iterator iter; for (iter = avatar->mAttachmentPoints.begin(); iter != avatar->mAttachmentPoints.end(); @@ -10917,9 +10934,27 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar) ++attachment_iter) { LLViewerObject* attached_object = attachment_iter->get(); - if (attached_object && attached_object->isRiggedMesh()) + if (attached_object) { - markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); + if (attached_object->isRiggedMesh()) + { + markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); + } + else + { + // sometimes object is a linkset and rigged mesh is a child + LLViewerObject::const_child_list_t& child_list = attached_object->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + if (child->isRiggedMesh()) + { + markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera); + break; + } + } + } } } } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 62d3ae7a39..0830d4a2ea 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -465,7 +465,7 @@ public: RENDER_TYPE_PASS_SIMPLE_RIGGED = LLRenderPass::PASS_SIMPLE_RIGGED, RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS, RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT, - RENDER_TYPE_PASS_FULLBRIGHT_RIGGED = LLRenderPass::PASS_FULLBRIGHT, + RENDER_TYPE_PASS_FULLBRIGHT_RIGGED = LLRenderPass::PASS_FULLBRIGHT_RIGGED, RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE, RENDER_TYPE_PASS_INVISIBLE_RIGGED = LLRenderPass::PASS_INVISIBLE_RIGGED, RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY, diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index c3ce83e834..8bb3feaeb0 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -985,4 +985,10 @@ <color name="AddPaymentPanel" value="0.27 0.27 0.27 1" /> + <color + name="OutfitSnapshotMacMask" + value="0.115 0.115 0.115 1"/> + <color + name="OutfitSnapshotMacMask2" + value="0.1 0.1 0.1 1"/> </colors> diff --git a/indra/newview/skins/default/textures/icons/add_icon.png b/indra/newview/skins/default/textures/icons/add_icon.png Binary files differnew file mode 100644 index 0000000000..cb68ee8e16 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/add_icon.png diff --git a/indra/newview/skins/default/textures/icons/remove_icon.png b/indra/newview/skins/default/textures/icons/remove_icon.png Binary files differnew file mode 100644 index 0000000000..6e62ee33f4 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/remove_icon.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 4429a1677e..1f2c0867c4 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -743,6 +743,9 @@ with the same filename but different name <texture name="Wearables_Divider" file_name="windows/Wearables_Divider.png" preload="false" /> + <texture name="Add_Icon" file_name="icons/add_icon.png" preload="false" /> + <texture name="Remove_Icon" file_name="icons/remove_icon.png" preload="false" /> + <texture name="Web_Profile_Off" file_name="icons/Web_Profile_Off.png" preload="false" /> <texture name="WellButton_Lit" file_name="bottomtray/WellButton_Lit.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" /> diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 4678d65b85..c6776ad039 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1908,7 +1908,7 @@ Only large parcels can be listed in search. </text> <check_box height="16" - label="Obscure MOAP" + label="Restrict MOAP to this parcel" layout="topleft" left="110" left_pad="0" diff --git a/indra/newview/skins/default/xui/en/floater_how_to.xml b/indra/newview/skins/default/xui/en/floater_how_to.xml index baff8e1bc0..19e42798af 100644 --- a/indra/newview/skins/default/xui/en/floater_how_to.xml +++ b/indra/newview/skins/default/xui/en/floater_how_to.xml @@ -3,7 +3,6 @@ legacy_header_height="18" can_resize="false" can_minimize="false" - can_close="false" height="525" layout="topleft" name="floater_how_to" diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 15f02ab9c3..da84fbeea6 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -221,20 +221,6 @@ right="-1" bottom="-1"> <layout_panel - auto_resize="false" - height="26" - name="translate_chat_checkbox_lp"> - <check_box - top="10" - control_name="TranslateChat" - enabled="true" - height="16" - label="Translate chat" - left="5" - name="translate_chat_checkbox" - width="230" /> - </layout_panel> - <layout_panel name="chat_holder"> <chat_history font="SansSerifSmall" diff --git a/indra/newview/skins/default/xui/en/floater_object_weights.xml b/indra/newview/skins/default/xui/en/floater_object_weights.xml index eb283a1043..889efa061c 100644 --- a/indra/newview/skins/default/xui/en/floater_object_weights.xml +++ b/indra/newview/skins/default/xui/en/floater_object_weights.xml @@ -2,7 +2,7 @@ <floater can_close="true" can_tear_off="false" - height="315" + height="289" help_topic="object_weights" layout="topleft" name="object_weights" @@ -320,23 +320,4 @@ top_delta="0" value="Total capacity" width="130" /> - <view_border - bevel_style="none" - follows="top|left" - height="0" - layout="topleft" - left="10" - name="land_impacts_text_border" - top_pad="5" - width="180"/> - - <text - follows="left|top" - height="16" - layout="topleft" - left="10" - name="help_SLURL" - top_pad="10" - value="[secondlife:///app/help/object_weights What is all this?...]" - width="180" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_openobject.xml b/indra/newview/skins/default/xui/en/floater_openobject.xml index 912db80bcc..ec03d7d32c 100644 --- a/indra/newview/skins/default/xui/en/floater_openobject.xml +++ b/indra/newview/skins/default/xui/en/floater_openobject.xml @@ -3,7 +3,7 @@ legacy_header_height="18" can_resize="true" default_tab_group="1" - height="370" + height="350" layout="topleft" min_height="190" min_width="285" @@ -31,62 +31,18 @@ background_visible="false" draw_border="false" follows="all" - height="240" + height="265" layout="topleft" + show_root_folder="false" left="10" name="object_contents" top_pad="0" width="284" /> - <view_border - bevel_style="none" - follows="bottom|left" - height="50" - highlight_light_color="0.6 0.6 0.6" - layout="topleft" - left="10" - name="border" - top_pad="5" - width="270"/> - <text - follows="bottom|left" - height="15" - layout="topleft" - left="15" - name="border_note" - text_color="White" - top_delta="5"> - Copy to inventory and wear - </text> - <button - follows="bottom|left" - height="23" - label="Add to outfit" - label_selected="Add to outfit" - layout="topleft" - left="15" - name="copy_and_wear_button" - top_pad="3" - width="135"> - <button.commit_callback - function="OpenObject.MoveAndWear" /> - </button> - <button - follows="bottom|left" - height="23" - label="Replace outfit" - label_selected="Replace outfit" - layout="topleft" - left_pad="5" - name="copy_and_replace_button" - width="120"> - <button.commit_callback - function="OpenObject.ReplaceOutfit" /> - </button> <button follows="bottom|left" height="23" label="Only copy to inventory" - label_selected="Only copy to inventory" + label_selected="Copy to inventory" layout="topleft" left="15" name="copy_to_inventory_button" diff --git a/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml b/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml deleted file mode 100644 index 15c480f144..0000000000 --- a/indra/newview/skins/default/xui/en/floater_outfit_snapshot.xml +++ /dev/null @@ -1,351 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - positioning="cascading" - legacy_header_height="18" - can_minimize="true" - can_resize="false" - can_close="true" - height="455" - layout="topleft" - name="outfit_snapshot" - single_instance="true" - help_topic="snapshot" - save_rect="true" - save_visibility="false" - title="OUTFIT SNAPSHOT" - width="624" - min_height="455"> - <floater.string - name="unknown"> - unknown - </floater.string> - <string - name="inventory_progress_str"> - Saving to Inventory - </string> - <string - name="inventory_succeeded_str"> - Saved to Inventory! - </string> - <string - name="inventory_failed_str"> - Failed to save to inventory. - </string> - <button - follows="left|top" - height="25" - image_overlay="Refresh_Off" - image_hover_unselected="Toolbar_Middle_Over" - image_selected="Toolbar_Middle_Selected" - image_unselected="Toolbar_Middle_Off" - image_overlay_alignment="left" - imgoverlay_label_space="5" - pad_bottom="0" - halign="left" - layout="topleft" - left="10" - label="REFRESH" - name="new_snapshot_btn" - top_pad="26" - width="167" /> - <button - follows="left|top" - control_name="AdvanceOutfitSnapshot" - invisibility_control="AdvanceOutfitSnapshot" - height="25" - is_toggle="true" - layout="topleft" - image_hover_unselected="Toolbar_Middle_Over" - image_selected="Toolbar_Middle_Off" - image_unselected="Toolbar_Middle_Off" - image_overlay="Conv_toolbar_expand" - name="retract_btn" - left_pad="1" - top_delta="0" - width="31" /> - <button - follows="left|top" - control_name="AdvanceOutfitSnapshot" - visibility_control="AdvanceOutfitSnapshot" - height="25" - is_toggle="true" - layout="topleft" - image_overlay="Conv_toolbar_collapse" - image_hover_unselected="Toolbar_Middle_Over" - image_selected="Toolbar_Middle_Off" - image_unselected="Toolbar_Middle_Off" - name="extend_btn" - left_delta="0" - top_delta="0" - width="31" /> - <panel - height="154" - layout="topleft" - follows="top|left" - left="0" - name="advanced_options_panel" - top_pad="-6" - width="210"> - <view_border - bevel_style="in" - follows="left|top|right" - height="1" - left="10" - layout="topleft" - name="advanced_options_hr" - right="-1" - top_pad="5" - /> - <text - type="string" - length="1" - follows="left|top" - height="13" - layout="topleft" - left="10" - name="layer_type_label" - top_pad="10" - width="100"> - Capture: - </text> - <check_box - label="Interface" - layout="topleft" - left="30" - height="16" - top_pad="8" - width="180" - name="ui_check" /> - <check_box - label="HUDs" - layout="topleft" - height="16" - left="30" - top_pad="1" - width="180" - name="hud_check" /> - <check_box - label="Freeze frame (fullscreen)" - layout="topleft" - height="16" - left="10" - top_pad="1" - width="180" - name="freeze_frame_check" /> - <check_box - label="Auto-refresh" - layout="topleft" - height="16" - left="10" - top_pad="1" - width="180" - name="auto_snapshot_check" /> - <text - type="string" - length="1" - follows="left|top" - height="13" - layout="topleft" - left="10" - name="filter_list_label" - top_pad="10" - width="50"> - Filter: - </text> - <combo_box - control_name="PhotoFilters" - follows="left|right|top" - name="filters_combobox" - tool_tip="Image filters" - top_delta="-3" - left="50" - right="-1" - height="21" - width="135"> - <combo_box.item - label="No Filter" - name="NoFilter" - value="NoFilter" /> - </combo_box> - <view_border - bevel_style="in" - follows="left|top|right" - height="1" - left="10" - layout="topleft" - name="advanced_options_hr" - right="-1" - top_pad="7" - /> - </panel> - <panel - class="llpaneloutfitsnapshotinventory" - follows="left|top" - height="230" - layout="topleft" - left="0" - name="panel_outfit_snapshot_inventory" - filename="panel_outfit_snapshot_inventory.xml" - top_pad="10" - width="215" - /> - <view_border - bevel_style="in" - follows="left|top" - height="1" - left="10" - layout="topleft" - name="status_hr" - width="199" - top_pad="-16"/> - <panel - background_visible="false" - follows="left|top" - font="SansSerifLarge" - halign="center" - height="20" - layout="topleft" - left="10" - length="1" - name="succeeded_panel" - width="198" - top_pad="1" - type="string" - visible="false"> - <text - follows="all" - font="SansSerif" - halign="center" - height="18" - layout="topleft" - left="1" - length="1" - name="succeeded_lbl" - right="-1" - text_color="0.2 0.85 0.2 1" - top="4" - translate="false" - type="string"> - Succeeded - </text> - </panel> - <panel - background_visible="false" - follows="left|top" - font="SansSerifLarge" - halign="center" - height="20" - layout="topleft" - left="10" - length="1" - name="failed_panel" - width="198" - top_delta="0" - type="string" - visible="false"> - <text - follows="all" - font="SansSerif" - halign="center" - height="18" - layout="topleft" - left="1" - length="1" - name="failed_lbl" - right="-1" - text_color="0.95 0.4 0.4 1" - top="4" - translate="false" - type="string"> - Failed - </text> - </panel> - <loading_indicator - follows="left|top" - height="24" - layout="topleft" - name="working_indicator" - left="10" - top_delta="0" - visible="false" - width="24" /> - <text - follows="left|top" - font="SansSerifBold" - height="14" - layout="topleft" - left_pad="3" - length="1" - halign="left" - name="working_lbl" - top_delta="5" - translate="false" - type="string" - visible="false" - width="162"> - Working - </text> - <text - follows="left|top" - font="SansSerifBold" - halign="left" - height="18" - layout="topleft" - left="10" - length="1" - name="refresh_lbl" - text_color="0.95 0.4 0.4 1" - top_delta="0" - translate="false" - type="string" - visible="false" - width="130"> - Refresh to save. - </text> - <ui_ctrl - layout="topleft" - name="thumbnail_placeholder" - top="23" - left="215" - width="400" - height="400" - follows="top|left"/> - <view_border - bevel_style="in" - height="21" - layout="topleft" - name="img_info_border" - top_pad="0" - right="-10" - follows="left|top|right" - left_delta="0"/> - <text - type="string" - font="SansSerifSmall" - length="1" - follows="left|top|right" - height="14" - layout="topleft" - left="220" - right="-20" - halign="left" - name="image_res_text" - top_delta="5" - width="200"> - [WIDTH]px (width) x [HEIGHT]px (height) - </text> - <text - follows="right|top" - font="SansSerifSmall" - height="14" - layout="topleft" - left="-65" - length="1" - halign="right" - name="file_size_label" - top_delta="0" - type="string" - width="50"> - [SIZE] KB - </text> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml index 41384a77b8..59117c0178 100644 --- a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml +++ b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml @@ -82,17 +82,20 @@ width="62"> Name </text> - <line_editor - border_style="line" - border_thickness="1" - follows="left|top" - height="20" - layout="topleft" - left_pad="0" - top_pad="-18" - max_length_chars="255" - name="filter_by_name" - width="161" /> + + <search_editor + follows="left|top" + search_button_visible="false" + height="20" + text_readonly_color="DkGray" + label="Objects by Name" + layout="topleft" + left_pad="0" + top_pad="-18" + name="filter_by_name" + select_on_focus="true" + width="161"> + </search_editor> <text name="linksets_desc_label" height="13" @@ -108,17 +111,19 @@ width="88"> Description </text> - <line_editor - border_style="line" - border_thickness="1" - follows="left|top" - height="20" - layout="topleft" - left_pad="0" - top_pad="-17" - max_length_chars="255" - name="filter_by_description" - width="162" /> + <search_editor + follows="left|top" + search_button_visible="false" + height="20" + text_readonly_color="DkGray" + label="Objects by Description" + layout="topleft" + left_pad="0" + top_pad="-17" + name="filter_by_description" + select_on_focus="true" + width="162"> + </search_editor> <combo_box height="20" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_settings_debug.xml b/indra/newview/skins/default/xui/en/floater_settings_debug.xml index 3ed2bd7206..e4fda5cd10 100644 --- a/indra/newview/skins/default/xui/en/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/en/floater_settings_debug.xml @@ -2,41 +2,79 @@ <floater legacy_header_height="18" can_minimize="false" - height="215" + height="360" + min_height="367" layout="topleft" name="settings_debug" help_topic="settings_debug" title="DEBUG SETTINGS" - width="350"> - <combo_box - allow_text_entry="true" - follows="top|left" - height="22" - layout="topleft" - left="15" - max_chars="255" - name="settings_combo" - top="30" - width="320"> - <combo_box.commit_callback - function="SettingSelect" /> - </combo_box> - <text_editor - enabled="false" - height="60" - layout="topleft" - left_delta="0" - name="comment_text" - top_pad="10" - width="320" - word_wrap="true" /> + reuse_instance="true" + can_resize="true" + min_width="550" + width="570"> + <filter_editor + follows="left|top|right" + height="23" + layout="topleft" + left="10" + right="-10" + label="Enter search text" + max_length_chars="300" + name="filter_input" + text_pad_left="10" + top="30" /> + <scroll_list + column_padding="0" + draw_heading="true" + draw_stripes="false" + heading_height="23" + height="266" + layout="topleft" + search_column="1" + left="10" + follows="left|top|bottom" + name="setting_list" + top_pad="2" + width="300"> + <scroll_list.columns + name="changed_setting" + relative_width="0.05" /> + <scroll_list.columns + label="Setting" + name="setting" /> + </scroll_list> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + name="setting_name_txt" + font="SansSerifSmallBold" + top_delta="8" + left_pad="10" + visible="false" + use_ellipses="true" + text_color="White" + width="240"> + Debug setting name + </text> + <text_editor + enabled="false" + height="75" + layout="topleft" + visible="false" + name="comment_text" + follows="left|top" + width="240" + top_delta="20" + word_wrap="true" /> <radio_group follows="top|left" height="30" layout="topleft" - left_delta="0" name="boolean_combo" - top_pad="10" + top_pad="15" visible="false" tab_stop="true" width="100"> @@ -55,21 +93,25 @@ </radio_group> <line_editor height="20" + follows="top|left" layout="topleft" left_delta="0" name="val_text" top_delta="0" visible="false" - width="300" > + width="220" > <line_editor.commit_callback function="CommitSettings" /> </line_editor> <color_swatch - bottom="185" + top_delta="0" + left_delta="0" + follows="top|left" can_apply_immediately="true" height="55" name="val_color_swatch" label="Color" + visible="false" layout="topleft" width="37" > <color_swatch.commit_callback @@ -79,10 +121,11 @@ height="20" label="x" layout="topleft" + follows="top|left" left_delta="0" max_val="1e+007" name="val_spinner_1" - top_delta="10" + top_delta="5" visible="false" width="120" > <spinner.commit_callback @@ -92,10 +135,11 @@ height="20" label="x" layout="topleft" - left_pad="15" + follows="top|left" + left_delta="0" max_val="1e+007" name="val_spinner_2" - top_delta="0" + top_pad="10" visible="false" width="120"> <spinner.commit_callback @@ -105,10 +149,11 @@ height="20" label="x" layout="topleft" - left="15" + follows="top|left" + left_delta="0" max_val="1e+007" name="val_spinner_3" - top="160" + top_pad="10" visible="false" width="120"> <spinner.commit_callback @@ -118,10 +163,11 @@ height="20" label="x" layout="topleft" - left_pad="15" + follows="top|left" + left_delta="0" max_val="1e+007" name="val_spinner_4" - top_delta="0" + top_pad="10" visible="false" width="120" > <spinner.commit_callback @@ -130,12 +176,26 @@ <button height="22" label="Reset to default" + follows="left|top" layout="topleft" - left="15" + left_delta="0" name="default_btn" - top="186" + visible="false" + top_pad="10" width="150" > <button.commit_callback function="ClickDefault" /> </button> + <check_box + control_name="DebugSettingsHideDefault" + height="16" + initial_value="true" + label="Show changed settings only" + layout="topleft" + top_pad="10" + left="10" + follows="left|bottom" + name="hide_default" + width="330"> + </check_box> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_simple_outfit_snapshot.xml b/indra/newview/skins/default/xui/en/floater_simple_outfit_snapshot.xml new file mode 100644 index 0000000000..5ece7b85d5 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_simple_outfit_snapshot.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + positioning="cascading" + legacy_header_height="18" + can_minimize="true" + can_resize="false" + can_close="true" + height="305" + layout="topleft" + name="simple_outfit_snapshot" + single_instance="true" + help_topic="snapshot" + save_rect="true" + save_visibility="false" + title="OUTFIT SNAPSHOT" + width="351"> + <ui_ctrl + layout="topleft" + name="thumbnail_placeholder" + top="18" + left="22" + width="335" + height="200" + follows="top|left"/> + <button + follows="left|bottom" + height="22" + layout="topleft" + left="29" + label="Take photo" + name="new_snapshot_btn" + bottom="-15" + width="90" /> + <button + follows="left|bottom" + height="22" + layout="topleft" + left_pad="10" + label="Save (L$[UPLOAD_COST])" + name="save_btn" + width="90" /> + <button + follows="left|bottom" + height="22" + layout="topleft" + left_pad="10" + label="Cancel" + name="cancel_btn" + width="90" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_tos.xml b/indra/newview/skins/default/xui/en/floater_tos.xml index a8db0aca4e..7e172e138a 100644 --- a/indra/newview/skins/default/xui/en/floater_tos.xml +++ b/indra/newview/skins/default/xui/en/floater_tos.xml @@ -76,7 +76,7 @@ word_wrap="true" text_readonly_color="LabelDisabledColor" width="552"> - I have read and agree to the Second Life Terms and Conditions, Privacy Policy, and Terms of Service, including the dispute resolution requirements. + I consent to the Linden Lab Terms of Service, Second Life Terms and Conditions, and acknowledge receipt of the Privacy Policy. </text> <button enabled="false" diff --git a/indra/newview/skins/default/xui/en/main_view.xml b/indra/newview/skins/default/xui/en/main_view.xml index 842184de88..bab37c6258 100644 --- a/indra/newview/skins/default/xui/en/main_view.xml +++ b/indra/newview/skins/default/xui/en/main_view.xml @@ -8,16 +8,6 @@ tab_stop="false" name="main_view" width="1024"> - - <!-- At the moment layout_stack is not an LLUICtrl, - but Tab requires focus_root to function and focus_root - functionality is implemented in LLUICtrl --> - <panel follows="all" - height="768" - name="menu_tab_wrapper" - mouse_opaque="false" - focus_root="true" - top="0"> <layout_stack border_size="0" follows="all" mouse_opaque="false" @@ -25,31 +15,35 @@ name="menu_stack" orientation="vertical" top="0"> + <!-- Menu, nav bar and status bar need common focus_root--> <layout_panel mouse_opaque="true" follows="left|right|top" name="status_bar_container" + focus_root="true" height="19" left="0" top="0" width="1024" auto_resize="false" - default_tab_group="1" visible="true"> <view mouse_opaque="false" - follows="all" + follows="top|left|right" name="menu_bar_holder" + tab_group="1" left="0" top="0" width="1024" - tab_group="1" height="19"/> + <view mouse_opaque="false" + follows="top|left|right" + name="nav_bar_container" + tab_group="3" + left="0" + top="19" + width="1024" + height="34" + visible="false"/> </layout_panel> - <layout_panel auto_resize="false" - height="34" - mouse_opaque="false" - name="nav_bar_container" - width="1024" - visible="false"/> <layout_panel auto_resize="true" follows="all" height="500" @@ -109,7 +103,6 @@ tab_stop="false"/> </layout_panel> </layout_stack> - </panel> <!--menu_tab_wrapper--> <panel top="0" follows="all" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 1ddec93668..d1a99133f0 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -9689,7 +9689,7 @@ Do you wish to continue? The selected object affects the navmesh. Changing it to a Flexible Path will remove it from the navmesh. <tag>confirm</tag> <usetemplate - ignoretext="The selected object affects the navmesh. Changing it to a Flexible Path will remove it from the navmesh." + ignoretext="The selected object affects the navmesh. Changing it to a Flexible Path will remove it from the navmesh." name="okcancelignore" notext="Cancel" yestext="OK"/> @@ -11914,4 +11914,20 @@ Unpacking: [UNPACK_TIME]s [USIZE]KB yestext="OK"/> </notification> + <notification + icon="alertmodal.tga" + name="RiggedMeshAttachedToHUD" + type="alertmodal"> + An object "[NAME]" attached to HUD point "[POINT]" contains rigged mesh. + +Rigged mesh objects are designed for attachment to the avatar. You will see this object but no one else will. + +If you want others to see this object, remove it and re-attach it to an avatar attachment point. + <tag>confirm</tag> + <usetemplate + ignoretext="Warn me when rigged mesh is attached to HUD point." + name="okignore" + yestext="OK"/> + </notification> + </notifications> diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml index 2a24c74feb..d74dca8b95 100644 --- a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml @@ -18,6 +18,7 @@ follows="all" keep_one_selected="true" multi_select="true" + show_item_widgets="true" name="wearable_items_list" translate="false" standalone="false" diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml index 4de56b424e..edc1fb21e7 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml @@ -18,26 +18,6 @@ orientation="vertical" width="242"> <layout_panel - auto_resize="false" - height="26" - layout="topleft" - left_delta="0" - name="translate_chat_checkbox_lp" - top_delta="0" - visible="true" - width="230"> - <check_box - top="10" - control_name="TranslateChat" - enabled="true" - height="16" - label="Translate chat" - layout="topleft" - left="5" - name="translate_chat_checkbox" - width="230" /> - </layout_panel> - <layout_panel auto_resize="true" height="138" left_delta="0" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml index 42a7974316..b2dc975c6e 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml @@ -36,6 +36,7 @@ left="3" multi_select="true" name="cof_items_list" + show_item_widgets="true" standalone="false" top="0" width="309" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 2ec5cef640..ef08fdf7c4 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -19,7 +19,7 @@ follows="left|top" height="23" label="Clear History" - tool_tip="Clear login image, last location, teleport history, web and texture cache" + tool_tip="Clear search and teleport history, web and texture cache" layout="topleft" left="30" name="clear_cache" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml index 42a34d171a..ab2e9c72f3 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml @@ -322,154 +322,161 @@ name="enable_voice_check" width="110"/> <!-- --> - <text - follows="left|top" - layout="topleft" - height="15" - left="0" - top_pad="3" - width="120" - halign="right" - name="media_autoplay_label"> - Media auto-play - </text> - <combo_box + <text + type="string" + length="1" + follows="left|top" + layout="topleft" + left="23" + top_delta="22" + name="Listen media from" + height="15" + word_wrap="true" + width="112"> + Hear media and sounds from: + </text> + <radio_group + control_name="MediaSoundsEarLocation" + follows="left|top" + top_delta="-6" + layout="topleft" + left_pad="20" + width="360" + height="40" + name="media_ear_location"> + <radio_item + height="19" + label="Camera position" + follows="left|top" + layout="topleft" + name="0" + width="200"/> + <radio_item + height="19" + follows="left|top" + label="Avatar position" + layout="topleft" + left_delta="0" + name="1" + top_delta ="18" + width="200" /> + </radio_group> + <check_box + name="media_show_on_others_btn" + control_name="MediaShowOnOthers" + value="true" + follows="left|top" + layout="topleft" + height="15" + top_pad="8" + tool_tip="Uncheck this to hide media attached to other avatars nearby" + label="Play media attached to other avatars" + left="20" + width="230"/> + <text + follows="left|top" + layout="topleft" + height="15" + left="23" + top_pad="8" + width="120" + name="media_autoplay_label"> + Auto-play media + </text> + <combo_box control_name="ParcelMediaAutoPlayEnable" enabled_control="AudioStreamingMedia" follows="left|top" layout="topleft" height="23" - left_pad="7" + left_pad="-15" top_delta="-4" name="media_auto_play_combo" - width="100"> - <item - label="No" - name="autoplay_disabled" - value="0"/> - <item - label="Yes" - name="autoplay_enabled" - value="1"/> - <item - label="Ask" - name="autoplay_ask" - value="2"/> - </combo_box> - <check_box - name="media_show_on_others_btn" - control_name="MediaShowOnOthers" - value="true" - follows="left|bottom|right" - height="15" - tool_tip="Uncheck this to hide media attached to other avatars nearby" - label="Play media attached to other avatars" - left="25" - width="230"/> - <check_box - name="gesture_audio_play_btn" - control_name="EnableGestureSounds" - disabled_control="MuteAudio" - value="true" - follows="left|bottom|right" - height="15" - tool_tip="Check this to hear sounds from gestures" - label="Play sounds from gestures" - top_pad="1" - left="25"/> - <text - type="string" - length="1" - follows="left|top" - height="20" - layout="topleft" - left="25" - name="voice_chat_settings" - width="200" - top_pad="16"> - Voice Chat Settings - </text> - <text - type="string" - length="1" - follows="left|top" - layout="topleft" - left="46" - top_delta="16" - name="Listen from" - width="112"> - Listen from: - </text> - <icon - follows="left|top" - height="18" - image_name="Cam_FreeCam_Off" - layout="topleft" - name="camera_icon" - mouse_opaque="false" - visible="true" - width="18" - left_pad="-4" - top_delta="-5"/> - <icon - follows="left|top" - height="18" - image_name="Move_Walk_Off" - layout="topleft" - left_pad="170" - name="avatar_icon" - mouse_opaque="false" - visible="true" - width="18" - top_delta="0" /> - <radio_group - enabled_control="EnableVoiceChat" - control_name="VoiceEarLocation" - follows="left|top" - layout="topleft" - left_delta="-168" - width="360" - height="20" - name="ear_location"> - <radio_item - height="19" - label="Camera position" - follows="left|top" - layout="topleft" - name="0" - width="200"/> - <radio_item - height="19" - follows="left|top" - label="Avatar position" - layout="topleft" - left_pad="-16" - name="1" - top_delta ="0" - width="200" /> - </radio_group> + width="115"> + <item + label="Never" + name="autoplay_disabled" + value="0"/> + <item + label="Always" + name="autoplay_enabled" + value="1"/> + <item + label="Ask" + name="autoplay_ask" + value="2"/> + </combo_box> + <text + type="string" + length="1" + follows="left|top" + layout="topleft" + left="23" + top_delta="30" + name="Listen from" + width="112"> + Hear voice from: + </text> + <radio_group + enabled_control="EnableVoiceChat" + control_name="VoiceEarLocation" + follows="left|top" + layout="topleft" + left_pad="20" + top_delta="-6" + width="360" + height="40" + name="ear_location"> + <radio_item + height="19" + label="Camera position" + follows="left|top" + layout="topleft" + name="0" + width="200"/> + <radio_item + height="19" + follows="left|top" + label="Avatar position" + layout="topleft" + left_delta="0" + name="1" + top_delta ="18" + width="200" /> + </radio_group> <check_box control_name="LipSyncEnabled" follows="left|top" height="15" label="Move avatar lips when speaking" layout="topleft" - left="44" + left="20" name="enable_lip_sync" - top_pad="5" + top_pad="10" width="237"/> - <check_box - follows="top|left" - enabled_control="EnableVoiceChat" - control_name="PushToTalkToggle" - height="15" - label="Toggle speak on/off when I press button in toolbar" - layout="topleft" - left="44" - name="push_to_talk_toggle_check" - width="237" - tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down." - top_pad="3"/> + <check_box + follows="top|left" + enabled_control="EnableVoiceChat" + control_name="PushToTalkToggle" + height="15" + label="Toggle speak on/off when I press button in toolbar" + layout="topleft" + left="20" + name="push_to_talk_toggle_check" + width="237" + tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down." + top_pad="5"/> + <check_box + name="gesture_audio_play_btn" + control_name="EnableGestureSounds" + disabled_control="MuteAudio" + value="true" + follows="left|bottom|right" + height="15" + tool_tip="Check this to hear sounds from gestures" + label="Play sounds from gestures" + top_pad="5" + left="20"/> <button control_name="ShowDeviceSettings" follows="left|top" @@ -478,7 +485,7 @@ label="Voice Input/Output devices" layout="topleft" left="20" - top_pad="6" + top_pad="9" name="device_settings_btn" width="230"> </button> diff --git a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml index 551b477876..777b37d666 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml @@ -9,9 +9,13 @@ follows="all" layout="topleft" > + <!-- + Date from server comes already converted to stl timezone, + so display it as an UTC+0 + --> <string name="date_format" - value="SL birthdate: [mth,datetime,slt] [day,datetime,slt], [year,datetime,slt]" /> + value="SL birthdate: [mth,datetime,utc] [day,datetime,utc], [year,datetime,utc]" /> <string name="age_format" value="[AGE]" /> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 6f95e282ca..42a10e8c56 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3983,7 +3983,7 @@ Please check http://status.secondlifegrid.net to see if there is a known problem <string name="Premium_PlusMembership">Premium Plus</string> <string name="InternalMembership">Internal</string> <!-- No need to translate --> - <string name="MembershipUpgradeText">Upgrade to Premium</string> + <string name="MembershipUpgradeText">Change membership plan...</string> <string name="MembershipPremiumText">My Premium membership</string> <!-- Question strings for delete items notifications --> @@ -4300,6 +4300,10 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string> <string name="Mav_Details_MAV_CONFIRMATION_DATA_MISMATCH"> The physics shape contains bad confirmation data. Try to correct the physics model. </string> + <!-- MAV_BLOCK_MISSING means server didn't get and couldn't substitute physics_convex, high_lod or BoundingVerts--> + <string name="Mav_Details_MAV_BLOCK_MISSING"> + Missing data. Make sure high lod is present and valid. Set the physics model if not set. + </string> <string name="Mav_Details_MAV_UNKNOWN_VERSION"> The physics shape does not have correct version. Set the correct version for the physics model. </string> diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml index 1c4822b8d5..9c80deeafc 100644 --- a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml @@ -6,7 +6,7 @@ text_pad_left="7" select_on_focus="true" text_tentative_color="TextFgTentativeColor" - highlight_text_field="false" + highlight_text_field="true" background_image="TextField_Search_Off" background_image_disabled="TextField_Search_Disabled" background_image_focused="TextField_Search_Active" diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml index dc5a07bf4f..18d99f1ed1 100644 --- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml @@ -7,7 +7,7 @@ text_pad_right="6" select_on_focus="true" text_tentative_color="TextFgTentativeColor" - highlight_text_field="false" + highlight_text_field="true" background_image="TextField_Search_Off" background_image_disabled="TextField_Search_Disabled" background_image_focused="TextField_Search_Active" diff --git a/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml b/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml new file mode 100644 index 0000000000..cd84b91b1f --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<inventory_list_item + follows="top|right|left" + height="20" + name="inventory_item" + tab_stop="false" + hover_image="ListItem_Over" + selected_image="ListItem_Select" + separator_image="Wearables_Divider" + width="380"> + <!-- DEFAULT style for inventory list item --> + <default_style + font="SansSerifSmall" + font.style="NORMAL" /> + + <!-- style for inventory list item WORN on avatar --> + <worn_style + font="SansSerifSmall" + font.style="BOLD" + color="EmphasisColor" /> + <item_icon + height="16" + follows="top|left" + image_name="Inv_Object" + layout="topleft" + left="0" + name="item_icon" + top="0" + width="16" /> + <item_name + follows="left|right" + height="20" + layout="topleft" + left="21" + parse_urls="false" + use_ellipses="true" + name="item_name" + text_color="white" + top="4" + value="..." + width="359" /> + <add_btn + name="add_wearable" + layout="topleft" + follows="top|right" + image_unselected="Add_Icon" + image_selected="Add_Icon" + top="1" + left="0" + height="16" + width="16" + tab_stop="false" /> + <remove_btn + name="remove_wearable" + layout="topleft" + follows="top|right" + image_unselected="Remove_Icon" + image_selected="Remove_Icon" + top="1" + left="26" + height="16" + width="16" + tab_stop="false" /> +</inventory_list_item> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 59eb18b734..6d68fd5453 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -518,7 +518,7 @@ class WindowsManifest(ViewerManifest): self.path("alut.dll") # For textures - self.path("openjpeg.dll") + self.path("openjp2.dll") # Uriparser self.path("uriparser.dll") @@ -1501,7 +1501,7 @@ class Linux_i686_Manifest(LinuxManifest): self.path("libdirectfb-1.*.so.*") self.path("libfusion-1.*.so.*") self.path("libdirect-1.*.so.*") - self.path("libopenjpeg.so*") + self.path("libopenjp2.so*") self.path("libdirectfb-1.4.so.5") self.path("libfusion-1.4.so.5") self.path("libdirect-1.4.so.5*") |