diff options
Diffstat (limited to 'indra/newview')
67 files changed, 1438 insertions, 955 deletions
| diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7d78ec9e3c..4fe83f0c45 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -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/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6861153d43..e9444efd43 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -16876,5 +16876,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/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/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/llchathistory.cpp b/indra/newview/llchathistory.cpp index 7ff24f64ac..42283f0238 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)); @@ -883,13 +865,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)  		{ @@ -1081,10 +1103,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() 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/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp index c075f7e8bd..8ad0bb3995 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 (gSavedSettings.getBOOL("360CaptureUseInterestListCap") && !LLApp::isExiting())      {          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/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/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/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 93a0b39e02..f973ae43cc 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -317,6 +317,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); 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/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/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..25cf8b2bf7 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,21 +194,19 @@ 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);  		mComment->setText(controlp->getComment());  		spinner1->setMaxValue(F32_MAX); @@ -479,3 +464,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/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..815840f990 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)  	{ diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index fab7ae8f1a..06351dc540 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(); 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/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/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/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/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/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index cfaa9456be..445bed673b 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -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/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index f4eaa78f11..deebf0cd1b 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)  	{ @@ -1280,6 +1304,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/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/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/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 06a6c5e373..b4382a4646 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -173,11 +173,103 @@  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)  		{ 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/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 3573af40cb..3bff01625b 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -5628,6 +5628,7 @@ class LLToolsSelectNextPartFace : public view_listener_t                      }                  }                  LLSelectMgr::getInstance()->selectObjectOnly(to_select, new_te); +                LLSelectMgr::getInstance()->addAsIndividual(to_select, new_te, false);              }              else              { diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index aad6c14b4d..b2e2f23ca7 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -3233,36 +3233,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 +3300,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/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/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 8a7d5f12d0..588fb4eb1b 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -3421,6 +3421,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))  	{ diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index a4e0d367c8..d98a40d188 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++) @@ -1095,6 +1100,12 @@ 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 @@ -1106,6 +1117,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 +1177,9 @@ void LLVOVolume::updateSculptTexture()  		{  			mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);  		} + +		mSkinInfoFailed = false; +		mSkinInfo = NULL;  	}  	else  	{ @@ -1212,6 +1234,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 +3681,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/llworld.cpp b/indra/newview/llworld.cpp index aa32ef04b2..fb9f5f41e6 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -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  } 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_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/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_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..b88a01f035 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 --> 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/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*") | 
