summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorMnikolenko Productengine <mnikolenko@productengine.com>2022-04-26 16:03:03 +0300
committerMnikolenko Productengine <mnikolenko@productengine.com>2022-04-26 16:03:03 +0300
commit79c9a8a4b79124baa06cb6630be3113906f1e342 (patch)
tree84e73c23280a42f5fff630a05e23cf914ae289bf /indra/newview
parente5e710a1e6e0f74cd60647e3dae7d037076351ff (diff)
parentbafa869c21cb8b329f94be6fa930a43d11699082 (diff)
Merge branch 'DRTVWR-546' into DRTVWR-539
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt8
-rw-r--r--indra/newview/app_settings/cmd_line.xml8
-rw-r--r--indra/newview/app_settings/key_bindings.xml88
-rw-r--r--indra/newview/app_settings/settings.xml39
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl37
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl14
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/previewPhysicsF.glsl42
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/previewPhysicsV.glsl42
-rw-r--r--indra/newview/llagent.cpp10
-rw-r--r--indra/newview/llappviewer.cpp62
-rw-r--r--indra/newview/llappviewer.h15
-rw-r--r--indra/newview/llappviewerwin32.h4
-rw-r--r--indra/newview/llavatarrenderinfoaccountant.cpp33
-rw-r--r--indra/newview/llcallingcard.cpp3
-rw-r--r--indra/newview/llchathistory.cpp2
-rw-r--r--indra/newview/llconversationview.cpp19
-rw-r--r--indra/newview/lldrawpool.cpp6
-rw-r--r--indra/newview/lldrawpoolalpha.cpp39
-rw-r--r--indra/newview/lldrawpoolbump.cpp181
-rw-r--r--indra/newview/lldrawpoolbump.h1
-rw-r--r--indra/newview/lldrawpoolmaterials.cpp2
-rw-r--r--indra/newview/lldrawpoolwater.cpp14
-rw-r--r--indra/newview/llenvironment.cpp22
-rw-r--r--indra/newview/llenvironment.h2
-rw-r--r--indra/newview/llface.cpp36
-rw-r--r--indra/newview/llface.h9
-rw-r--r--indra/newview/llfeaturemanager.cpp8
-rw-r--r--indra/newview/llfloatercamera.cpp4
-rw-r--r--indra/newview/llfloaterfixedenvironment.cpp1
-rw-r--r--indra/newview/llfloatergesture.cpp3
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp2
-rw-r--r--indra/newview/llfloaterpreference.cpp11
-rw-r--r--indra/newview/llfloatersearch.cpp9
-rw-r--r--indra/newview/llfloaterworldmap.cpp120
-rw-r--r--indra/newview/llfloaterworldmap.h28
-rw-r--r--indra/newview/llgesturemgr.cpp79
-rw-r--r--indra/newview/llgroupactions.cpp2
-rw-r--r--indra/newview/llinventorymodel.cpp192
-rw-r--r--indra/newview/llinventorymodel.h11
-rw-r--r--indra/newview/llkeyconflict.cpp78
-rw-r--r--indra/newview/llkeyconflict.h12
-rw-r--r--indra/newview/lllogininstance.cpp11
-rw-r--r--indra/newview/llmediactrl.cpp5
-rw-r--r--indra/newview/llmodelpreview.cpp115
-rw-r--r--indra/newview/llmodelpreview.h4
-rw-r--r--indra/newview/llpathfindingmanager.cpp2
-rw-r--r--indra/newview/llpreviewgesture.cpp1
-rw-r--r--indra/newview/llsearchableui.cpp7
-rw-r--r--indra/newview/llstartup.cpp68
-rw-r--r--indra/newview/lltextureview.cpp4
-rw-r--r--indra/newview/lltoolcomp.cpp10
-rw-r--r--indra/newview/lltoolgrab.cpp26
-rw-r--r--indra/newview/lltoolmorph.cpp10
-rw-r--r--indra/newview/lltoolpie.cpp13
-rw-r--r--indra/newview/llviewerassetstorage.cpp7
-rw-r--r--indra/newview/llviewerinput.cpp171
-rw-r--r--indra/newview/llviewerinput.h8
-rw-r--r--indra/newview/llviewermedia.cpp4
-rw-r--r--indra/newview/llviewerobject.cpp5
-rw-r--r--indra/newview/llviewerregion.cpp68
-rw-r--r--indra/newview/llviewershadermgr.cpp23
-rw-r--r--indra/newview/llviewershadermgr.h1
-rw-r--r--indra/newview/llviewerstats.cpp8
-rw-r--r--indra/newview/llviewertexturelist.cpp21
-rw-r--r--indra/newview/llviewerwindow.cpp3
-rw-r--r--indra/newview/llvoavatar.cpp89
-rw-r--r--indra/newview/llvoavatar.h6
-rw-r--r--indra/newview/llvovolume.cpp73
-rw-r--r--indra/newview/llweb.cpp21
-rw-r--r--indra/newview/llworld.cpp24
-rw-r--r--indra/newview/llworld.h4
-rw-r--r--indra/newview/pipeline.cpp220
-rw-r--r--indra/newview/pipeline.h3
-rw-r--r--indra/newview/skins/default/xui/en/control_table_contents_media.xml10
-rw-r--r--indra/newview/skins/default/xui/en/floater_associate_listing.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_model_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_hide_beacon.xml20
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_toolbar_view.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_volume_pulldown.xml2
82 files changed, 1551 insertions, 829 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index e7f0af84ef..539b4f7b34 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1917,9 +1917,7 @@ if (WINDOWS)
add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
endif (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
- add_dependencies(${VIEWER_BINARY_NAME}
- SLPlugin
- )
+ add_dependencies(${VIEWER_BINARY_NAME} SLPlugin)
# sets the 'working directory' for debugging from visual studio.
# Condition for version can be moved to requirements once build agents will be updated (see TOOL-3865)
@@ -2270,7 +2268,7 @@ endif (INSTALL)
# Note that the conventional VIEWER_SYMBOL_FILE is set by ../../build.sh
if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIEWER_SYMBOL_FILE)
- if (BUGSPLAT_DB)
+ if (USE_BUGSPLAT)
# BugSplat symbol-file generation
if (WINDOWS)
# Just pack up a tarball containing only the .pdb file for the
@@ -2354,7 +2352,7 @@ if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIE
if (LINUX)
# TBD
endif (LINUX)
- endif (BUGSPLAT_DB)
+ endif (USE_BUGSPLAT)
# for both Bugsplat and Breakpad
add_dependencies(llpackage generate_symbols)
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index 7514913d13..dd2b656ce3 100644
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -207,14 +207,6 @@
<map>
<key>map-to</key>
<string>NoAudio</string>
- </map>
-
- <key>noinvlib</key>
- <map>
- <key>desc</key>
- <string>Do not request the inventory library.</string>
- <key>map-to</key>
- <string>NoInventoryLibrary</string>
</map>
<key>noninteractive</key>
diff --git a/indra/newview/app_settings/key_bindings.xml b/indra/newview/app_settings/key_bindings.xml
index 1a5157838c..55babc88bc 100644
--- a/indra/newview/app_settings/key_bindings.xml
+++ b/indra/newview/app_settings/key_bindings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<keys>
+<keys xml_version="1">
<first_person>
<binding key="A" mask="NONE" command="slide_left"/>
<binding key="D" mask="NONE" command="slide_right"/>
@@ -17,22 +17,13 @@
<binding key="PGDN" mask="NONE" command="push_down"/>
<binding key="HOME" mask="NONE" command="toggle_fly"/>
- <binding key="PAD_LEFT" mask="NONE" command="slide_left"/>
- <binding key="PAD_RIGHT" mask="NONE" command="slide_right"/>
- <binding key="PAD_UP" mask="NONE" command="push_forward"/>
- <binding key="PAD_DOWN" mask="NONE" command="push_backward"/>
- <binding key="PAD_PGUP" mask="NONE" command="jump"/>
- <binding key="PAD_PGDN" mask="NONE" command="push_down"/>
- <binding key="PAD_HOME" mask="NONE" command="toggle_fly"/>
- <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
- <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
- <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
-
<binding key="SPACE" mask="NONE" command="stop_moving"/>
<binding key="ENTER" mask="NONE" command="start_chat"/>
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
</first_person>
<third_person>
<binding key="A" mask="NONE" command="turn_left"/>
@@ -60,19 +51,6 @@
<binding key="PGDN" mask="NONE" command="push_down"/>
<binding key="HOME" mask="NONE" command="toggle_fly"/>
- <binding key="PAD_LEFT" mask="NONE" command="turn_left"/>
- <binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
- <binding key="PAD_RIGHT" mask="NONE" command="turn_right"/>
- <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
- <binding key="PAD_UP" mask="NONE" command="push_forward"/>
- <binding key="PAD_DOWN" mask="NONE" command="push_backward"/>
- <binding key="PAD_PGUP" mask="NONE" command="jump"/>
- <binding key="PAD_PGDN" mask="NONE" command="push_down"/>
- <binding key="PAD_HOME" mask="NONE" command="toggle_fly"/>
- <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
- <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
- <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
-
<!--Camera controls in third person on Alt-->
<binding key="LEFT" mask="ALT" command="spin_around_cw"/>
<binding key="RIGHT" mask="ALT" command="spin_around_ccw"/>
@@ -88,15 +66,6 @@
<binding key="E" mask="ALT" command="spin_over"/>
<binding key="C" mask="ALT" command="spin_under"/>
- <binding key="PAD_LEFT" mask="ALT" command="spin_around_cw"/>
- <binding key="PAD_RIGHT" mask="ALT" command="spin_around_ccw"/>
- <binding key="PAD_UP" mask="ALT" command="move_forward"/>
- <binding key="PAD_DOWN" mask="ALT" command="move_backward"/>
- <binding key="PAD_PGUP" mask="ALT" command="spin_over"/>
- <binding key="PAD_PGDN" mask="ALT" command="spin_under"/>
- <binding key="PAD_ENTER" mask="ALT" command="start_chat"/>
- <binding key="PAD_DIVIDE" mask="ALT" command="start_gesture"/>
-
<!--mimic alt zoom behavior with keyboard only-->
<binding key="W" mask="CTL_ALT" command="spin_over"/>
<binding key="S" mask="CTL_ALT" command="spin_under"/>
@@ -104,9 +73,6 @@
<binding key="UP" mask="CTL_ALT" command="spin_over"/>
<binding key="DOWN" mask="CTL_ALT" command="spin_under"/>
- <binding key="PAD_UP" mask="CTL_ALT" command="spin_over"/>
- <binding key="PAD_DOWN" mask="CTL_ALT" command="spin_under"/>
-
<!--Therefore pan on Alt-Shift-->
<binding key="A" mask="CTL_ALT_SHIFT" command="pan_left"/>
<binding key="D" mask="CTL_ALT_SHIFT" command="pan_right"/>
@@ -118,14 +84,10 @@
<binding key="UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
<binding key="DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
- <binding key="PAD_LEFT" mask="CTL_ALT_SHIFT" command="pan_left"/>
- <binding key="PAD_RIGHT" mask="CTL_ALT_SHIFT" command="pan_right"/>
- <binding key="PAD_UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
- <binding key="PAD_DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
- <binding key="PAD_ENTER" mask="CTL_ALT_SHIFT" command="start_chat"/>
- <binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
-
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+ <binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
</third_person>
<sitting>
<binding key="A" mask="ALT" command="spin_around_cw"/>
@@ -167,16 +129,6 @@
<binding key="PGUP" mask="NONE" command="spin_over_sitting"/>
<binding key="PGDN" mask="NONE" command="spin_under_sitting"/>
- <binding key="PAD_LEFT" mask="NONE" command="spin_around_cw_sitting"/>
- <binding key="PAD_RIGHT" mask="NONE" command="spin_around_ccw_sitting"/>
- <binding key="PAD_UP" mask="NONE" command="move_forward_sitting"/>
- <binding key="PAD_DOWN" mask="NONE" command="move_backward_sitting"/>
- <binding key="PAD_PGUP" mask="NONE" command="spin_over_sitting"/>
- <binding key="PAD_PGDN" mask="NONE" command="spin_under_sitting"/>
- <binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
- <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
- <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
-
<!--these are for passing controls when sitting on vehicles-->
<binding key="A" mask="SHIFT" command="slide_left"/>
<binding key="D" mask="SHIFT" command="slide_right"/>
@@ -192,15 +144,6 @@
<binding key="PGUP" mask="SHIFT" command="spin_over_sitting"/>
<binding key="PGDN" mask="SHIFT" command="spin_under_sitting"/>
- <binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
- <binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
- <binding key="PAD_UP" mask="SHIFT" command="move_forward_sitting"/>
- <binding key="PAD_DOWN" mask="SHIFT" command="move_backward_sitting"/>
- <binding key="PAD_PGUP" mask="SHIFT" command="spin_over_sitting"/>
- <binding key="PAD_PGDN" mask="SHIFT" command="spin_under_sitting"/>
- <binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
- <binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
-
<!--pan on Alt-Shift-->
<binding key="A" mask="CTL_ALT_SHIFT" command="pan_left"/>
<binding key="D" mask="CTL_ALT_SHIFT" command="pan_right"/>
@@ -212,17 +155,12 @@
<binding key="UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
<binding key="DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
- <binding key="PAD_LEFT" mask="CTL_ALT_SHIFT" command="pan_left"/>
- <binding key="PAD_RIGHT" mask="CTL_ALT_SHIFT" command="pan_right"/>
- <binding key="PAD_UP" mask="CTL_ALT_SHIFT" command="pan_up"/>
- <binding key="PAD_DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
- <binding key="PAD_ENTER" mask="CTL_ALT_SHIFT" command="start_chat"/>
- <binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
-
<binding key="ENTER" mask="NONE" command="start_chat"/>
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
</sitting>
<edit_avatar>
<!--Avatar editing camera controls-->
@@ -240,15 +178,9 @@
<binding key="PGDN" mask="NONE" command="edit_avatar_spin_under"/>
<binding key="ENTER" mask="NONE" command="start_chat"/>
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
- <binding key="PAD_LEFT" mask="NONE" command="edit_avatar_spin_cw"/>
- <binding key="PAD_RIGHT" mask="NONE" command="edit_avatar_spin_ccw"/>
- <binding key="PAD_UP" mask="NONE" command="edit_avatar_move_forward"/>
- <binding key="PAD_DOWN" mask="NONE" command="edit_avatar_move_backward"/>
- <binding key="PAD_PGUP" mask="NONE" command="edit_avatar_spin_over"/>
- <binding key="PAD_PGDN" mask="NONE" command="edit_avatar_spin_under"/>
- <binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
- <binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
+
+ <binding key="" mask="NONE" mouse="LMB" command="script_trigger_lbutton"/>
</edit_avatar>
</keys>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index bfc47d2c65..5d775622a0 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4758,7 +4758,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
- <string>https://search.[GRID]/viewer/[CATEGORY]/?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]&amp;patch=[VERSION_PATCH]&amp;build=[VERSION_BUILD]</string>
+ <string>https://search.[GRID]/viewer/[CATEGORY]/?q=[QUERY]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]&amp;channel=[CHANNEL]&amp;version=[VERSION]&amp;major=[VERSION_MAJOR]&amp;minor=[VERSION_MINOR]&amp;patch=[VERSION_PATCH]&amp;build=[VERSION_BUILD]</string>
</map>
<key>GuidebookURL</key>
<map>
@@ -5895,17 +5895,6 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>LoginAsGod</key>
- <map>
- <key>Comment</key>
- <string>Attempt to login with god powers (Linden accounts only)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
<key>LoginLocation</key>
<map>
<key>Comment</key>
@@ -6481,7 +6470,7 @@
<key>MaxHeapSize</key>
<map>
<key>Comment</key>
- <string>Maximum heap size (GB)</string>
+ <string>Maximum heap size on 32-bit builds (GB)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6489,6 +6478,17 @@
<key>Value</key>
<real>1.6</real>
</map>
+ <key>MaxHeapSize64</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum heap size on 64-bit builds (GB)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>16.0</real>
+ </map>
<key>MaxPersistentNotifications</key>
<map>
<key>Comment</key>
@@ -6964,6 +6964,17 @@
<key>Value</key>
<integer>1000</integer>
</map>
+ <key>FakeInitialOutfitName</key>
+ <map>
+ <key>Comment</key>
+ <string>Pretend that this is first time login and specified name was chosen</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string />
+ </map>
<key>MyOutfitsAutofill</key>
<map>
<key>Comment</key>
@@ -7066,7 +7077,7 @@
<key>NoInventoryLibrary</key>
<map>
<key>Comment</key>
- <string>Do not request inventory library.</string>
+ <string>(Deprecated) Do not request inventory library.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index d3a05c34c0..02b2daf0ac 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -56,6 +56,10 @@ VARYING vec3 vary_norm;
VARYING vec4 vertex_color; //vertex color should be treated as sRGB
#endif
+#ifdef HAS_ALPHA_MASK
+uniform float minimum_alpha;
+#endif
+
uniform mat4 proj_mat;
uniform mat4 inv_proj;
uniform vec2 screen_res;
@@ -191,7 +195,6 @@ void main()
#endif
vec4 diffuse_srgb = diffuse_tap;
- vec4 diffuse_linear = vec4(srgb_to_linear(diffuse_srgb.rgb), diffuse_srgb.a);
#ifdef FOR_IMPOSTOR
vec4 color;
@@ -200,25 +203,37 @@ void main()
float final_alpha = diffuse_srgb.a * vertex_color.a;
diffuse_srgb.rgb *= vertex_color.rgb;
- diffuse_linear.rgb = srgb_to_linear(diffuse_srgb.rgb);
// Insure we don't pollute depth with invis pixels in impostor rendering
//
- if (final_alpha < 0.01)
+ if (final_alpha < minimum_alpha)
{
discard;
}
-#else
-
+
+ color.rgb = diffuse_srgb.rgb;
+ color.a = final_alpha;
+
+#else // FOR_IMPOSTOR
+
+ vec4 diffuse_linear = vec4(srgb_to_linear(diffuse_srgb.rgb), diffuse_srgb.a);
+
vec3 light_dir = (sun_up_factor == 1) ? sun_dir: moon_dir;
float final_alpha = diffuse_linear.a;
#ifdef USE_VERTEX_COLOR
final_alpha *= vertex_color.a;
+
+ if (final_alpha < minimum_alpha)
+ { // TODO: figure out how to get invisible faces out of
+ // render batches without breaking glow
+ discard;
+ }
+
diffuse_srgb.rgb *= vertex_color.rgb;
diffuse_linear.rgb = srgb_to_linear(diffuse_srgb.rgb);
-#endif
+#endif // USE_VERTEX_COLOR
vec3 sunlit;
vec3 amblit;
@@ -250,13 +265,13 @@ void main()
#if !defined(AMBIENT_KILL)
color.rgb = amblit;
color.rgb *= ambient;
-#endif
+#endif // !defined(AMBIENT_KILL)
vec3 post_ambient = color.rgb;
#if !defined(SUNLIGHT_KILL)
color.rgb += sun_contrib;
-#endif
+#endif // !defined(SUNLIGHT_KILL)
vec3 post_sunlight = color.rgb;
@@ -288,7 +303,7 @@ vec3 post_atmo = color.rgb;
// sum local light contrib in linear colorspace
#if !defined(LOCAL_LIGHT_KILL)
color.rgb += light.rgb;
-#endif
+#endif // !defined(LOCAL_LIGHT_KILL)
// back to sRGB as we're going directly to the final RT post-deferred gamma correction
color.rgb = linear_to_srgb(color.rgb);
@@ -307,8 +322,8 @@ vec3 post_atmo = color.rgb;
color = applyWaterFogView(pos.xyz, color);
#endif // WATER_FOG
-#endif
-
+#endif // #else // FOR_IMPOSTOR
+
frag_color = color;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
index eb6e56e718..a58cc3d12d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
@@ -54,8 +54,7 @@ void main()
vec4 norm = texture2D(normalMap, vary_texcoord0.xy);
vec4 spec = texture2D(specularMap, vary_texcoord0.xy);
- col.rgb = linear_to_srgb(col.rgb);
frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = spec;
- frag_data[2] = vec4(norm.xy,0,0);
+ frag_data[2] = norm;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl b/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl
index d0c06cd51f..7a941674b8 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl
@@ -43,18 +43,18 @@ uniform float norm_scale;
void main()
{
- float alpha = texture2D(alphaMap, vary_texcoord0).a;
+ float c = texture2D(alphaMap, vary_texcoord0).r;
- vec3 right = vec3(norm_scale, 0, (texture2D(alphaMap, vary_texcoord0+vec2(stepX, 0)).a-alpha)*255);
- vec3 left = vec3(-norm_scale, 0, (texture2D(alphaMap, vary_texcoord0-vec2(stepX, 0)).a-alpha)*255);
- vec3 up = vec3(0, -norm_scale, (texture2D(alphaMap, vary_texcoord0-vec2(0, stepY)).a-alpha)*255);
- vec3 down = vec3(0, norm_scale, (texture2D(alphaMap, vary_texcoord0+vec2(0, stepY)).a-alpha)*255);
+ vec3 right = vec3(norm_scale, 0, (texture2D(alphaMap, vary_texcoord0+vec2(stepX, 0)).r-c)*255);
+ vec3 left = vec3(-norm_scale, 0, (texture2D(alphaMap, vary_texcoord0-vec2(stepX, 0)).r-c)*255);
+ vec3 up = vec3(0, -norm_scale, (texture2D(alphaMap, vary_texcoord0-vec2(0, stepY)).r-c)*255);
+ vec3 down = vec3(0, norm_scale, (texture2D(alphaMap, vary_texcoord0+vec2(0, stepY)).r-c)*255);
vec3 norm = cross(right, down) + cross(down, left) + cross(left,up) + cross(up, right);
norm = normalize(norm);
norm *= 0.5;
norm += 0.5;
-
- frag_color = vec4(norm, alpha);
+
+ frag_color = vec4(norm, c);
}
diff --git a/indra/newview/app_settings/shaders/class1/objects/previewPhysicsF.glsl b/indra/newview/app_settings/shaders/class1/objects/previewPhysicsF.glsl
new file mode 100644
index 0000000000..3a5e6fdf7c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/objects/previewPhysicsF.glsl
@@ -0,0 +1,42 @@
+/**
+ * @file previewPhysicsF.glsl
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D diffuseMap;
+uniform vec4 color;
+
+VARYING vec2 vary_texcoord0;
+
+//====================================================================================================
+
+void main()
+{
+ frag_color = texture2D(diffuseMap,vary_texcoord0.xy) * color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/objects/previewPhysicsV.glsl b/indra/newview/app_settings/shaders/class1/objects/previewPhysicsV.glsl
new file mode 100644
index 0000000000..913dec83bd
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/objects/previewPhysicsV.glsl
@@ -0,0 +1,42 @@
+/**
+ * @file previewPhysicsV.glsl
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+uniform mat4 texture_matrix0;
+uniform mat4 modelview_matrix;
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec2 texcoord0;
+
+VARYING vec2 vary_texcoord0;
+
+//====================================================================================================
+
+void main()
+{
+ //transform vertex
+ gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+}
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index d3a490f51f..d9c7d8b42e 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -1988,7 +1988,8 @@ void LLAgent::propagate(const F32 dt)
//-----------------------------------------------------------------------------
void LLAgent::updateAgentPosition(const F32 dt, const F32 yaw_radians, const S32 mouse_x, const S32 mouse_y)
{
- if (mMoveTimer.getStarted() && mMoveTimer.getElapsedTimeF32() > gSavedSettings.getF32("NotMovingHintTimeout"))
+ static LLCachedControl<F32> hint_timeout(gSavedSettings, "NotMovingHintTimeout");
+ if (mMoveTimer.getStarted() && mMoveTimer.getElapsedTimeF32() > hint_timeout)
{
LLFirstUse::notMoving();
}
@@ -2159,7 +2160,8 @@ void LLAgent::endAnimationUpdateUI()
LLNavigationBar::getInstance()->setVisible(TRUE && gSavedSettings.getBOOL("ShowNavbarNavigationPanel"));
gStatusBar->setVisibleForMouselook(true);
- if (gSavedSettings.getBOOL("ShowMiniLocationPanel"))
+ static LLCachedControl<bool> show_mini_location_panel(gSavedSettings, "ShowMiniLocationPanel");
+ if (show_mini_location_panel)
{
LLPanelTopInfoBar::getInstance()->setVisible(TRUE);
}
@@ -3901,10 +3903,6 @@ bool LLAgent::teleportCore(bool is_local)
// yet if the teleport will succeed. Look in
// process_teleport_location_reply
- // close the map panel so we can see our destination.
- // we don't close search floater, see EXT-5840.
- LLFloaterReg::hideInstance("world_map");
-
// hide land floater too - it'll be out of date
LLFloaterReg::hideInstance("about_land");
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 66c44ef6a6..a63203f3cb 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -637,6 +637,7 @@ LLAppViewer::LLAppViewer()
mLogoutMarkerFile(),
mReportedCrash(false),
mNumSessions(0),
+ mGeneralThreadPool(nullptr),
mPurgeCache(false),
mPurgeCacheOnExit(false),
mPurgeUserDataOnExit(false),
@@ -1309,10 +1310,13 @@ void LLAppViewer::initMaxHeapSize()
//------------------------------------------------------------------------------------------
//currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB.
- //F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ;
- F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ;
+ #ifndef LL_X86_64
+ F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ;
+#else
+ F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize64");
+#endif
- LLMemory::initMaxHeapSizeGB(max_heap_size_gb);
+ LLMemory::initMaxHeapSizeGB(max_heap_size_gb);
}
static LLTrace::BlockTimerStatHandle FTM_MESSAGES("System Messages");
@@ -1709,11 +1713,6 @@ void LLAppViewer::flushLFSIO()
bool LLAppViewer::cleanup()
{
- // Since we don't know what functions are going to be queued by
- // onCleanup(), we have to assume they might rely on some of the things
- // we're about to destroy below. Run them first.
- mOnCleanup();
-
LLAtmosphere::cleanupClass();
//ditch LLVOAvatarSelf instance
@@ -2067,6 +2066,10 @@ bool LLAppViewer::cleanup()
sTextureCache->shutdown();
sImageDecodeThread->shutdown();
sPurgeDiskCacheThread->shutdown();
+ if (mGeneralThreadPool)
+ {
+ mGeneralThreadPool->close();
+ }
sTextureFetch->shutDownTextureCacheThread() ;
sTextureFetch->shutDownImageDecodeThread() ;
@@ -2091,6 +2094,8 @@ bool LLAppViewer::cleanup()
mFastTimerLogThread = NULL;
delete sPurgeDiskCacheThread;
sPurgeDiskCacheThread = NULL;
+ delete mGeneralThreadPool;
+ mGeneralThreadPool = NULL;
if (LLFastTimerView::sAnalyzePerformance)
{
@@ -2156,6 +2161,7 @@ bool LLAppViewer::cleanup()
LLEnvironment::deleteSingleton();
LLSelectMgr::deleteSingleton();
LLViewerEventRecorder::deleteSingleton();
+ LLWorld::deleteSingleton();
// It's not at first obvious where, in this long sequence, a generic cleanup
// call OUGHT to go. So let's say this: as we migrate cleanup from
@@ -2176,6 +2182,24 @@ bool LLAppViewer::cleanup()
return true;
}
+void LLAppViewer::initGeneralThread()
+{
+ if (mGeneralThreadPool)
+ {
+ return;
+ }
+
+ LLSD poolSizes{ gSavedSettings.getLLSD("ThreadPoolSizes") };
+ LLSD sizeSpec{ poolSizes["General"] };
+ LLSD::Integer poolSize{ sizeSpec.isInteger() ? sizeSpec.asInteger() : 3 };
+ LL_DEBUGS("ThreadPool") << "Instantiating General pool with "
+ << poolSize << " threads" << LL_ENDL;
+ // We don't want anyone, especially the main thread, to have to block
+ // due to this ThreadPool being full.
+ mGeneralThreadPool = new LL::ThreadPool("General", poolSize, 1024 * 1024);
+ mGeneralThreadPool->start();
+}
+
bool LLAppViewer::initThreads()
{
static const bool enable_threads = true;
@@ -5365,14 +5389,18 @@ void LLAppViewer::disconnectViewer()
}
// save inventory if appropriate
- gInventory.cache(gInventory.getRootFolderID(), gAgent.getID());
- if (gInventory.getLibraryRootFolderID().notNull()
- && gInventory.getLibraryOwnerID().notNull())
- {
- gInventory.cache(
- gInventory.getLibraryRootFolderID(),
- gInventory.getLibraryOwnerID());
- }
+ if (gInventory.isInventoryUsable()
+ && gAgent.getID().notNull()) // Shouldn't be null at this stage
+ {
+ gInventory.cache(gInventory.getRootFolderID(), gAgent.getID());
+ if (gInventory.getLibraryRootFolderID().notNull()
+ && gInventory.getLibraryOwnerID().notNull())
+ {
+ gInventory.cache(
+ gInventory.getLibraryRootFolderID(),
+ gInventory.getLibraryOwnerID());
+ }
+ }
saveNameCache();
if (LLExperienceCache::instanceExists())
@@ -5394,7 +5422,7 @@ void LLAppViewer::disconnectViewer()
// Now we just ask the LLWorld singleton to cleanly shut down.
if(LLWorld::instanceExists())
{
- LLWorld::getInstance()->destroyClass();
+ LLWorld::getInstance()->resetClass();
}
LLVOCache::deleteSingleton();
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index d807cf9765..a86fa7d873 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -63,6 +63,11 @@ class LLViewerJoystick;
class LLPurgeDiskCacheThread;
class LLViewerRegion;
+namespace LL
+{
+ class ThreadPool;
+}
+
extern LLTrace::BlockTimerStatHandle FTM_FRAME;
class LLAppViewer : public LLApp
@@ -201,13 +206,7 @@ public:
void addOnIdleCallback(const boost::function<void()>& cb); // add a callback to fire (once) when idle
- typedef boost::signals2::signal<void()> cleanup_signal_t;
- cleanup_signal_t mOnCleanup;
- boost::signals2::connection onCleanup(const cleanup_signal_t::slot_type& cb)
- {
- return mOnCleanup.connect(cb);
- }
-
+ void initGeneralThread();
void purgeUserDataOnExit() { mPurgeUserDataOnExit = true; }
void purgeCache(); // Clear the local cache.
void purgeCacheImmediate(); //clear local cache immediately.
@@ -269,7 +268,6 @@ private:
void idle();
void idleShutdown();
// update avatar SLID and display name caches
- void idleExperienceCache();
void idleNameCache();
void idleNetwork();
@@ -298,6 +296,7 @@ private:
static LLImageDecodeThread* sImageDecodeThread;
static LLTextureFetch* sTextureFetch;
static LLPurgeDiskCacheThread* sPurgeDiskCacheThread;
+ LL::ThreadPool* mGeneralThreadPool;
S32 mNumSessions;
diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h
index 82b6b0c77c..ab52bf15f9 100644
--- a/indra/newview/llappviewerwin32.h
+++ b/indra/newview/llappviewerwin32.h
@@ -51,8 +51,8 @@ protected:
bool initHardwareTest() override; // Win32 uses DX9 to test hardware.
bool initParseCommandLine(LLCommandLineParser& clp) override;
- virtual bool beingDebugged();
- virtual bool restoreErrorTrap();
+ bool beingDebugged() override;
+ bool restoreErrorTrap() override;
bool sendURLToOtherInstance(const std::string& url) override;
diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp
index ca83afb5ab..fe94cd27b6 100644
--- a/indra/newview/llavatarrenderinfoaccountant.cpp
+++ b/indra/newview/llavatarrenderinfoaccountant.cpp
@@ -82,7 +82,15 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro(std::string url, U64
LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
- LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ LLWorld *world_inst = LLWorld::getInstance();
+ if (!world_inst)
+ {
+ LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight info received but world no longer exists "
+ << regionHandle << LL_ENDL;
+ return;
+ }
+
+ LLViewerRegion * regionp = world_inst->getRegionFromHandle(regionHandle);
if (!regionp)
{
LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight info received but region not found for "
@@ -183,7 +191,15 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro(std::string url, U
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AvatarRenderInfoAccountant", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
- LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ LLWorld *world_inst = LLWorld::getInstance();
+ if (!world_inst)
+ {
+ LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight calculation but world no longer exists "
+ << regionHandle << LL_ENDL;
+ return;
+ }
+
+ LLViewerRegion * regionp = world_inst->getRegionFromHandle(regionHandle);
if (!regionp)
{
LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight calculation but region not found for "
@@ -239,9 +255,18 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro(std::string url, U
report[KEY_AGENTS] = agents;
regionp = NULL;
+ world_inst = NULL;
LLSD result = httpAdapter->postAndSuspend(httpRequest, url, report);
- regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ world_inst = LLWorld::getInstance();
+ if (!world_inst)
+ {
+ LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight POST result but world no longer exists "
+ << regionHandle << LL_ENDL;
+ return;
+ }
+
+ regionp = world_inst->getRegionFromHandle(regionHandle);
if (!regionp)
{
LL_INFOS("AvatarRenderInfoAccountant") << "Avatar render weight POST result received but region not found for "
@@ -345,6 +370,8 @@ void LLAvatarRenderInfoAccountant::idle()
&& regionp->capabilitiesReceived())
{
// each of these is further governed by and resets its own timer
+ // Note: We can have multiple regions, each launches up to two coroutines,
+ // it likely is expensive
sendRenderInfoToRegion(regionp);
getRenderInfoFromRegion(regionp);
}
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 9ee9900eba..bddbc79df4 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -645,7 +645,8 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
{
if(mBuddyInfo.find(agent_id) != mBuddyInfo.end())
{
- if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
+ if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
+ && !gAgent.isDoNotDisturb())
{
LLSD args;
args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString();
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index c110e0d815..cdf82c77c1 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -752,7 +752,7 @@ public:
if ( chat.mSourceType == CHAT_SOURCE_OBJECT)
{
std::string slurl = args["slurl"].asString();
- if (slurl.empty())
+ if (slurl.empty() && LLWorld::instanceExists())
{
LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosAgent(chat.mPosAgent);
if(region)
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index fee85d50bd..20fa6d490b 100644
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -96,10 +96,14 @@ LLConversationViewSession::~LLConversationViewSession()
{
mActiveVoiceChannelConnection.disconnect();
- if(LLVoiceClient::instanceExists() && mVoiceClientObserver)
- {
- LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver);
- }
+ if (mVoiceClientObserver)
+ {
+ if (LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver);
+ }
+ delete mVoiceClientObserver;
+ }
mFlashTimer->unset();
}
@@ -255,7 +259,12 @@ BOOL LLConversationViewSession::postBuild()
mIsInActiveVoiceChannel = true;
if(LLVoiceClient::instanceExists())
{
- LLNearbyVoiceClientStatusObserver* mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this);
+ if (mVoiceClientObserver)
+ {
+ LLVoiceClient::getInstance()->removeObserver(mVoiceClientObserver);
+ delete mVoiceClientObserver;
+ }
+ mVoiceClientObserver = new LLNearbyVoiceClientStatusObserver(this);
LLVoiceClient::getInstance()->addObserver(mVoiceClientObserver);
}
break;
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index faa5f71da4..a3837fe10c 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -451,7 +451,7 @@ void LLRenderPass::pushRiggedBatches(U32 type, U32 mask, BOOL texture, BOOL batc
LLDrawInfo* pparams = *i;
if (pparams)
{
- if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
+ if (pparams->mAvatar.notNull() && (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash))
{
uploadMatrixPalette(*pparams);
lastAvatar = pparams->mAvatar;
@@ -596,6 +596,10 @@ bool LLRenderPass::uploadMatrixPalette(LLDrawInfo& params)
//static
bool LLRenderPass::uploadMatrixPalette(LLVOAvatar* avatar, LLMeshSkinInfo* skinInfo)
{
+ if (!avatar)
+ {
+ return false;
+ }
const LLVOAvatar::MatrixPaletteCache& mpc = avatar->updateSkinInfoMatrixPalette(skinInfo);
U32 count = mpc.mMatrixPalette.size();
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 2bf8e9b911..eebd89f77f 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -56,6 +56,11 @@ BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
static BOOL deferred_render = FALSE;
+// minimum alpha before discarding a fragment
+static const F32 MINIMUM_ALPHA = 0.004f; // ~ 1/255
+// minimum alpha before discarding a fragment when rendering impostors
+static const F32 MINIMUM_IMPOSTOR_ALPHA = 0.1f;
+
LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) :
LLRenderPass(type), target_shader(NULL),
mColorSFactor(LLRender::BF_UNDEF), mColorDFactor(LLRender::BF_UNDEF),
@@ -106,11 +111,11 @@ static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma, bool d
if (LLPipeline::sImpostorRender)
{
- shader->setMinimumAlpha(0.5f);
+ shader->setMinimumAlpha(MINIMUM_IMPOSTOR_ALPHA);
}
else
{
- shader->setMinimumAlpha(0.f);
+ shader->setMinimumAlpha(MINIMUM_ALPHA);
}
if (textureGamma)
{
@@ -130,14 +135,15 @@ void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
deferred_render = TRUE;
// prepare shaders
- emissive_shader = (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
+ emissive_shader = (LLPipeline::sRenderDeferred) ? &gDeferredEmissiveProgram :
+ (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
prepare_alpha_shader(emissive_shader, true, false);
- fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram :
- (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram;
+ fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightAlphaMaskProgram :
+ (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightAlphaMaskProgram;
prepare_alpha_shader(fullbright_shader, true, false);
- simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram :
+ simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram :
(LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram;
prepare_alpha_shader(simple_shader, false, true); //prime simple shader (loads shadow relevant uniforms)
@@ -196,18 +202,18 @@ void LLDrawPoolAlpha::render(S32 pass)
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
simple_shader = (LLPipeline::sImpostorRender) ? &gObjectSimpleImpostorProgram :
- (LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram : &gObjectSimpleProgram;
+ (LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram : &gObjectSimpleAlphaMaskProgram;
- fullbright_shader = (LLPipeline::sImpostorRender) ? &gObjectFullbrightProgram :
- (LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightProgram;
+ fullbright_shader = (LLPipeline::sImpostorRender) ? &gObjectFullbrightAlphaMaskProgram :
+ (LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightAlphaMaskProgram;
emissive_shader = (LLPipeline::sImpostorRender) ? &gObjectEmissiveProgram :
(LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
- F32 minimum_alpha = 0.f;
+ F32 minimum_alpha = MINIMUM_ALPHA;
if (LLPipeline::sImpostorRender)
{
- minimum_alpha = 0.5f;
+ minimum_alpha = MINIMUM_IMPOSTOR_ALPHA;
}
prepare_forward_shader(fullbright_shader, minimum_alpha);
prepare_forward_shader(simple_shader, minimum_alpha);
@@ -228,8 +234,8 @@ void LLDrawPoolAlpha::forwardRender(bool rigged)
//enable writing to alpha for emissive effects
gGL.setColorMask(true, true);
- bool write_depth = rigged
- || LLDrawPoolWater::sSkipScreenCopy
+ bool write_depth = rigged ||
+ LLDrawPoolWater::sSkipScreenCopy
// we want depth written so that rendered alpha will
// contribute to the alpha mask used for impostors
|| LLPipeline::sImpostorRenderAlphaDepthPass;
@@ -484,6 +490,7 @@ void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissi
void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives)
{
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE); //disable depth writes since "emissive" is additive so sorting doesn't matter
LLGLSLShader* shader = emissive_shader->mRiggedVariant;
shader->bind();
shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
@@ -587,7 +594,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
const LLTextureEntry* tep = face->getTextureEntry();
if(tep)
{ // don't render faces that are more than 90% transparent
- if(tep->getColor().mV[3] < 0.1f)
+ if(tep->getColor().mV[3] < MINIMUM_IMPOSTOR_ALPHA)
continue;
}
}
@@ -795,6 +802,10 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged)
bool LLDrawPoolAlpha::uploadMatrixPalette(const LLDrawInfo& params)
{
+ if (params.mAvatar.isNull())
+ {
+ return false;
+ }
const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar.get()->updateSkinInfoMatrixPalette(params.mSkinInfo);
U32 count = mpc.mMatrixPalette.size();
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 1d5419b515..2892fc6f9f 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -56,6 +56,7 @@
LLStandardBumpmap gStandardBumpmapList[TEM_BUMPMAP_COUNT];
LL::WorkQueue::weak_t LLBumpImageList::sMainQueue;
LL::WorkQueue::weak_t LLBumpImageList::sTexUpdateQueue;
+LLRenderTarget LLBumpImageList::sRenderTarget;
// static
U32 LLStandardBumpmap::sStandardBumpmapCount = 0;
@@ -76,7 +77,7 @@ static S32 cube_channel = -1;
static S32 diffuse_channel = -1;
static S32 bump_channel = -1;
-#define LL_BUMPLIST_MULTITHREADED 0
+#define LL_BUMPLIST_MULTITHREADED 0 // TODO -- figure out why this doesn't work
// static
void LLStandardBumpmap::init()
@@ -776,6 +777,8 @@ void LLBumpImageList::clear()
mBrightnessEntries.clear();
mDarknessEntries.clear();
+ sRenderTarget.release();
+
LLStandardBumpmap::clear();
}
@@ -1032,6 +1035,8 @@ void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nr
// static
void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
{
+ LL_PROFILE_ZONE_SCOPED;
+
if( success )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
@@ -1201,145 +1206,111 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI
}
else
{ //convert to normal map
-
- //disable compression on normal maps to prevent errors below
- bump->getGLTexture()->setAllowCompression(false);
- bump->getGLTexture()->setUseMipMaps(TRUE);
-
- auto* bump_ptr = bump.get();
- auto* dst_ptr = dst_image.get();
+ LL_PROFILE_ZONE_NAMED("bil - create normal map");
+ LLImageGL* img = bump->getGLTexture();
+ LLImageRaw* dst_ptr = dst_image.get();
+ LLGLTexture* bump_ptr = bump.get();
-#if LL_BUMPLIST_MULTITHREADED
- bump_ptr->ref();
dst_ptr->ref();
-#endif
-
- bump_ptr->setExplicitFormat(GL_RGBA8, GL_ALPHA);
-
- auto create_texture = [=]()
+ img->ref();
+ bump_ptr->ref();
+ auto create_func = [=]()
{
-#if LL_IMAGEGL_THREAD_CHECK
- bump_ptr->getGLTexture()->mActiveThread = LLThread::currentID();
-#endif
- LL_PROFILE_ZONE_NAMED("bil - create texture deferred");
+ img->setUseMipMaps(TRUE);
+ // upload dst_image to GPU (greyscale in red channel)
+ img->setExplicitFormat(GL_RED, GL_RED);
+
bump_ptr->createGLTexture(0, dst_ptr);
+ dst_ptr->unref();
};
- auto gen_normal_map = [=]()
+ auto generate_func = [=]()
{
-#if LL_IMAGEGL_THREAD_CHECK
- bump_ptr->getGLTexture()->mActiveThread = LLThread::currentID();
-#endif
- LL_PROFILE_ZONE_NAMED("bil - generate normal map");
- if (gNormalMapGenProgram.mProgramObject == 0)
- {
-#if LL_BUMPLIST_MULTITHREADED
- bump_ptr->unref();
- dst_ptr->unref();
-#endif
- return;
- }
- gPipeline.mScreen.bindTarget();
-
- LLGLDepthTest depth(GL_FALSE);
- LLGLDisable cull(GL_CULL_FACE);
- LLGLDisable blend(GL_BLEND);
- gGL.setColorMask(TRUE, TRUE);
- gNormalMapGenProgram.bind();
-
- static LLStaticHashedString sNormScale("norm_scale");
- static LLStaticHashedString sStepX("stepX");
- static LLStaticHashedString sStepY("stepY");
-
- gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale"));
- gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump_ptr->getWidth());
- gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump_ptr->getHeight());
+ // Allocate an empty RGBA texture at "tex_name" the same size as bump
+ // Note: bump will still point at GPU copy of dst_image
+ bump_ptr->setExplicitFormat(GL_RGBA, GL_RGBA);
+ LLGLuint tex_name;
+ img->createGLTexture(0, nullptr, 0, 0, true, &tex_name);
- LLVector2 v((F32)bump_ptr->getWidth() / gPipeline.mScreen.getWidth(),
- (F32)bump_ptr->getHeight() / gPipeline.mScreen.getHeight());
+ // point render target at empty buffer
+ sRenderTarget.setColorAttachment(img, tex_name);
- gGL.getTexUnit(0)->bind(bump_ptr);
-
- S32 width = bump_ptr->getWidth();
- S32 height = bump_ptr->getHeight();
-
- S32 screen_width = gPipeline.mScreen.getWidth();
- S32 screen_height = gPipeline.mScreen.getHeight();
-
- glViewport(0, 0, screen_width, screen_height);
-
- for (S32 left = 0; left < width; left += screen_width)
+ // generate normal map in empty texture
{
- S32 right = left + screen_width;
- right = llmin(right, width);
+ sRenderTarget.bindTarget();
- F32 left_tc = (F32)left / width;
- F32 right_tc = (F32)right / width;
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+ gGL.setColorMask(TRUE, TRUE);
- for (S32 bottom = 0; bottom < height; bottom += screen_height)
- {
- S32 top = bottom + screen_height;
- top = llmin(top, height);
+ gNormalMapGenProgram.bind();
- F32 bottom_tc = (F32)bottom / height;
- F32 top_tc = (F32)(bottom + screen_height) / height;
- top_tc = llmin(top_tc, 1.f);
+ static LLStaticHashedString sNormScale("norm_scale");
+ static LLStaticHashedString sStepX("stepX");
+ static LLStaticHashedString sStepY("stepY");
- F32 screen_right = (F32)(right - left) / screen_width;
- F32 screen_top = (F32)(top - bottom) / screen_height;
+ gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale"));
+ gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump_ptr->getWidth());
+ gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump_ptr->getHeight());
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(left_tc, bottom_tc);
- gGL.vertex2f(0, 0);
+ gGL.getTexUnit(0)->bind(bump_ptr);
- gGL.texCoord2f(left_tc, top_tc);
- gGL.vertex2f(0, screen_top);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(0, 0);
+ gGL.vertex2f(0, 0);
- gGL.texCoord2f(right_tc, bottom_tc);
- gGL.vertex2f(screen_right, 0);
+ gGL.texCoord2f(0, 1);
+ gGL.vertex2f(0, 1);
- gGL.texCoord2f(right_tc, top_tc);
- gGL.vertex2f(screen_right, screen_top);
+ gGL.texCoord2f(1, 0);
+ gGL.vertex2f(1, 0);
- gGL.end();
+ gGL.texCoord2f(1, 1);
+ gGL.vertex2f(1, 1);
- gGL.flush();
+ gGL.end();
- S32 w = right - left;
- S32 h = top - bottom;
+ gGL.flush();
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, left, bottom, 0, 0, w, h);
- }
- }
+ gNormalMapGenProgram.unbind();
- glGenerateMipmap(GL_TEXTURE_2D);
+ sRenderTarget.flush();
+ sRenderTarget.releaseColorAttachment();
+ }
- gPipeline.mScreen.flush();
+ // point bump at normal map and free gpu copy of dst_image
+ img->syncTexName(tex_name);
- gNormalMapGenProgram.unbind();
+ // generate mipmap
+ gGL.getTexUnit(0)->bind(img);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ gGL.getTexUnit(0)->disable();
- //generateNormalMapFromAlpha(dst_image, nrm_image);
-#if LL_BUMPLIST_MULTITHREADED
bump_ptr->unref();
- dst_ptr->unref();
-#endif
+ img->unref();
};
#if LL_BUMPLIST_MULTITHREADED
- auto main_queue = sMainQueue.lock();
-
- if (LLImageGLThread::sEnabled)
- { //dispatch creation to background thread
- main_queue->postTo(sTexUpdateQueue, create_texture, gen_normal_map);
+ auto main_queue = LLImageGLThread::sEnabled ? sMainQueue.lock() : nullptr;
+
+ if (main_queue)
+ { //dispatch texture upload to background thread, issue GPU commands to generate normal map on main thread
+ main_queue->postTo(
+ sTexUpdateQueue,
+ create_func,
+ generate_func);
}
else
#endif
- {
- create_texture();
- gen_normal_map();
+ { // immediate upload texture and generate normal map
+ create_func();
+ generate_func();
}
+
+
}
-
+
iter->second = bump; // derefs (and deletes) old image
//---------------------------------------------------
}
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index 6e21859738..e8a027967b 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -163,6 +163,7 @@ private:
bump_image_map_t mDarknessEntries;
static LL::WorkQueue::weak_t sMainQueue;
static LL::WorkQueue::weak_t sTexUpdateQueue;
+ static LLRenderTarget sRenderTarget;
};
extern LLBumpImageList gBumpImageList;
diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp
index 135770c99c..2b05f4c453 100644
--- a/indra/newview/lldrawpoolmaterials.cpp
+++ b/indra/newview/lldrawpoolmaterials.cpp
@@ -243,7 +243,7 @@ void LLDrawPoolMaterials::pushMaterialsBatch(LLDrawInfo& params, U32 mask, bool
}
// upload matrix palette to shader
- if (rigged)
+ if (rigged && params.mAvatar.notNull())
{
const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar->updateSkinInfoMatrixPalette(params.mSkinInfo);
U32 count = mpc.mMatrixPalette.size();
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 6762b38c39..a84f62036e 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -624,18 +624,10 @@ void LLDrawPoolWater::renderWater()
shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp);
- if (LLEnvironment::instance().isCloudScrollPaused())
- {
- static const std::array<F32, 2> zerowave {{0.0f, 0.0f}};
- shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, zerowave.data());
- shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, zerowave.data());
- }
- else
- {
- shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV);
- shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV);
- }
+ shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV);
+ shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV);
+
shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV);
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 42f3d15a1c..b76dc6a961 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -1155,6 +1155,10 @@ void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSe
mSignalEnvChanged(env, env_version);
}
+void LLEnvironment::setCurrentEnvironmentSelection(LLEnvironment::EnvSelection_t env)
+{
+ mCurrentEnvironment->setEnvironmentSelection(env);
+}
void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironment::fixedEnvironment_t fixed, S32 env_version)
{
@@ -1761,8 +1765,22 @@ void LLEnvironment::updateShaderUniforms(LLGLSLShader* shader)
void LLEnvironment::updateSettingsUniforms()
{
- updateGLVariablesForSettings(mWaterUniforms, mCurrentEnvironment->getWater());
- updateGLVariablesForSettings(mSkyUniforms, mCurrentEnvironment->getSky());
+ if (mCurrentEnvironment->getWater())
+ {
+ updateGLVariablesForSettings(mWaterUniforms, mCurrentEnvironment->getWater());
+ }
+ else
+ {
+ LL_WARNS("ENVIRONMENT") << "Failed to update GL variable for water settings, environment is not properly set" << LL_ENDL;
+ }
+ if (mCurrentEnvironment->getSky())
+ {
+ updateGLVariablesForSettings(mSkyUniforms, mCurrentEnvironment->getSky());
+ }
+ else
+ {
+ LL_WARNS("ENVIRONMENT") << "Failed to update GL variable for sky settings, environment is not properly set" << LL_ENDL;
+ }
}
void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envinfo, LLSettingsBase::Seconds transition)
diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h
index 0ec06402f8..330de2bea8 100644
--- a/indra/newview/llenvironment.h
+++ b/indra/newview/llenvironment.h
@@ -158,6 +158,8 @@ public:
static void logEnvironment(EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version = NO_VERSION);
+ void setCurrentEnvironmentSelection(LLEnvironment::EnvSelection_t env);
+
LLSettingsDay::ptr_t getEnvironmentDay(EnvSelection_t env);
LLSettingsDay::Seconds getEnvironmentDayLength(EnvSelection_t env);
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index b328dd2962..d1e2b8b93d 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1172,6 +1172,11 @@ bool LLFace::canRenderAsMask()
return true;
}
+ if (isState(LLFace::RIGGED))
+ { // never auto alpha-mask rigged faces
+ return false;
+ }
+
const LLTextureEntry* te = getTextureEntry();
if( !te || !getViewerObject() || !getTexture() )
{
@@ -2359,14 +2364,35 @@ F32 LLFace::getTextureVirtualSize()
BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE;
//VECTORIZE THIS
//get area of circle around face
- LLVector4a center;
- center.load3(getPositionAgent().mV);
- LLVector4a size;
- size.setSub(mExtents[1], mExtents[0]);
+
+ LLVector4a center;
+ LLVector4a size;
+
+
+ if (isState(LLFace::RIGGED))
+ {
+ //override with avatar bounding box
+ LLVOAvatar* avatar = mVObjp->getAvatar();
+ if (avatar)
+ {
+ center.load3(avatar->getPositionAgent().mV);
+ const LLVector4a* exts = avatar->mDrawable->getSpatialExtents();
+ size.setSub(exts[1], exts[0]);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ center.load3(getPositionAgent().mV);
+ size.setSub(mExtents[1], mExtents[0]);
+ }
size.mul(0.5f);
LLViewerCamera* camera = LLViewerCamera::getInstance();
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 79f50f2273..aa00c9d052 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -143,7 +143,7 @@ public:
LLViewerObject* getViewerObject() const { return mVObjp; }
S32 getLOD() const { return mVObjp.notNull() ? mVObjp->getLOD() : 0; }
void setPoolType(U32 type) { mPoolType = type; }
- S32 getTEOffset() { return mTEOffset; }
+ S32 getTEOffset() const { return mTEOffset; }
LLViewerTexture* getTexture(U32 ch = LLRender::DIFFUSE_MAP) const;
void setViewerObject(LLViewerObject* object);
@@ -233,6 +233,12 @@ public:
void notifyAboutCreatingTexture(LLViewerTexture *texture);
void notifyAboutMissingAsset(LLViewerTexture *texture);
+ // used to preserve draw order of faces that are batched together.
+ // Allows content creators to manipulate linked sets and face ordering
+ // for consistent alpha sorting results, particularly for rigged attachments
+ void setDrawOrderIndex(U32 index) { mDrawOrderIndex = index; }
+ U32 getDrawOrderIndex() const { return mDrawOrderIndex; }
+
public: //aligned members
LLVector4a mExtents[2];
@@ -305,6 +311,7 @@ private:
bool mHasMedia ;
bool mIsMediaAllowed;
+ U32 mDrawOrderIndex = 0; // see setDrawOrderIndex
protected:
static BOOL sSafeRenderSelect;
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 0813057714..329af264eb 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -381,7 +381,10 @@ F32 gpu_benchmark();
F32 logExceptionBenchmark()
{
- // Todo: make a wrapper/class for SEH exceptions
+ // FIXME: gpu_benchmark uses many C++ classes on the stack to control state.
+ // SEH exceptions with our current exception handling options do not call
+ // destructors for these classes, resulting in an undefined state should
+ // this handler be invoked.
F32 gbps = -1;
__try
{
@@ -389,6 +392,9 @@ F32 logExceptionBenchmark()
}
__except (msc_exception_filter(GetExceptionCode(), GetExceptionInformation()))
{
+ // HACK - ensure that profiling is disabled
+ LLGLSLShader::finishProfile(false);
+
// convert to C++ styled exception
char integer_string[32];
sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp
index 3b192ff81b..1c69b9d60b 100644
--- a/indra/newview/llfloatercamera.cpp
+++ b/indra/newview/llfloatercamera.cpp
@@ -453,18 +453,18 @@ void LLFloaterCamera::setMode(ECameraControlMode mode)
void LLFloaterCamera::switchMode(ECameraControlMode mode)
{
- setMode(mode);
-
switch (mode)
{
case CAMERA_CTRL_MODE_PRESETS:
case CAMERA_CTRL_MODE_PAN:
sFreeCamera = false;
+ setMode(mode); // depends onto sFreeCamera
clear_camera_tool();
break;
case CAMERA_CTRL_MODE_FREE_CAMERA:
sFreeCamera = true;
+ setMode(mode);
activate_camera_tool();
break;
diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
index 4f2c36f45b..fec218ca3b 100644
--- a/indra/newview/llfloaterfixedenvironment.cpp
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -137,6 +137,7 @@ void LLFloaterFixedEnvironment::onClose(bool app_quitting)
doCloseInventoryFloater(app_quitting);
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+ LLEnvironment::instance().setCurrentEnvironmentSelection(LLEnvironment::ENV_LOCAL);
LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_EDIT);
mSettings.reset();
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index c4e0dd483f..6e326ff3cf 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -582,8 +582,7 @@ void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
LLInventoryItem* item = gInventory.getItem(*it);
if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
{
- LLWString item_name = utf8str_to_wstring(item->getName());
- LLClipboard::instance().addToClipboard(item_name, 0, item_name.size());
+ LLClipboard::instance().addToClipboard(*it);
}
}
}
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 43dc304c10..34499ac170 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -384,7 +384,7 @@ void LLFloaterIMSessionTab::draw()
void LLFloaterIMSessionTab::enableDisableCallBtn()
{
- if (LLVoiceClient::instanceExists())
+ if (LLVoiceClient::instanceExists() && mVoiceButton)
{
mVoiceButton->setEnabled(
mSessionID.notNull()
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index a57705fe50..0e94d31d90 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -2056,7 +2056,16 @@ void LLPanelPreference::saveSettings()
{
view_stack.push_back(*iter);
}
- }
+ }
+
+ if (LLStartUp::getStartupState() == STATE_STARTED)
+ {
+ LLControlVariable* control = gSavedPerAccountSettings.getControl("VoiceCallsFriendsOnly");
+ if (control)
+ {
+ mSavedValues[control] = control->getValue();
+ }
+ }
}
void LLPanelPreference::showMultipleViewersWarning(LLUICtrl* checkbox, const LLSD& value)
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index 779542cfcc..2e1fbb09e0 100644
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -169,15 +169,6 @@ void LLFloaterSearch::search(const SearchQuery &p)
// add the search query string
subs["QUERY"] = LLURI::escape(p.query);
- // add the permissions token that login.cgi gave us
- // We use "search_token", and fallback to "auth_token" if not present.
- LLSD search_token = LLLoginInstance::getInstance()->getResponse("search_token");
- if (search_token.asString().empty())
- {
- search_token = LLLoginInstance::getInstance()->getResponse("auth_token");
- }
- subs["AUTH_TOKEN"] = search_token.asString();
-
// add the user's preferred maturity (can be changed via prefs)
std::string maturity;
if (gAgent.prefersAdult())
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 27197f0b06..2c84cd1f93 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -56,10 +56,12 @@
#include "llscrolllistctrl.h"
#include "llslurl.h"
#include "lltextbox.h"
+#include "lltoolbarview.h"
#include "lltracker.h"
#include "lltrans.h"
#include "llviewerinventory.h" // LLViewerInventoryItem
#include "llviewermenu.h"
+#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include "llviewerstats.h"
#include "llviewertexture.h"
@@ -87,6 +89,9 @@ static const F32 MAP_ZOOM_TIME = 0.2f;
// Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window.
static const S32 MAX_VISIBLE_REGIONS = 512;
+
+const S32 HIDE_BEACON_PAD = 133;
+
// It would be more logical to have this inside the method where it is used but to compile under gcc this
// struct has to be here.
struct SortRegionNames
@@ -326,6 +331,8 @@ LLFloaterWorldMap::~LLFloaterWorldMap()
mFriendObserver = NULL;
gFloaterWorldMap = NULL;
+
+ mTeleportFinishConnection.disconnect();
}
//static
@@ -339,12 +346,16 @@ void LLFloaterWorldMap::onClose(bool app_quitting)
{
// While we're not visible, discard the overlay images we're using
LLWorldMap::getInstance()->clearImageRefs();
+ mTeleportFinishConnection.disconnect();
}
// virtual
void LLFloaterWorldMap::onOpen(const LLSD& key)
{
- bool center_on_target = (key.asString() == "center");
+ mTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
+ setTeleportFinishedCallback(boost::bind(&LLFloaterWorldMap::onTeleportFinished, this));
+
+ bool center_on_target = (key.asString() == "center");
mIsClosing = FALSE;
@@ -1566,6 +1577,13 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
}
}
+void LLFloaterWorldMap::onTeleportFinished()
+{
+ if(isInVisibleChain())
+ {
+ LLWorldMapView::setPan(0, 0, TRUE);
+ }
+}
void LLFloaterWorldMap::onCommitSearchResult()
{
@@ -1642,3 +1660,103 @@ void LLFloaterWorldMap::onFocusLost()
LLWorldMapView* map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel;
map_panel->mPanning = FALSE;
}
+
+LLPanelHideBeacon::LLPanelHideBeacon() :
+ mHideButton(NULL)
+{
+}
+
+// static
+LLPanelHideBeacon* LLPanelHideBeacon::getInstance()
+{
+ static LLPanelHideBeacon* panel = getPanelHideBeacon();
+ return panel;
+}
+
+
+BOOL LLPanelHideBeacon::postBuild()
+{
+ mHideButton = getChild<LLButton>("hide_beacon_btn");
+ mHideButton->setCommitCallback(boost::bind(&LLPanelHideBeacon::onHideButtonClick, this));
+
+ gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLPanelHideBeacon::updatePosition, this));
+
+ return TRUE;
+}
+
+//virtual
+void LLPanelHideBeacon::draw()
+{
+ if (!LLTracker::isTracking(NULL))
+ {
+ mHideButton->setVisible(false);
+ return;
+ }
+ mHideButton->setVisible(true);
+ updatePosition();
+ LLPanel::draw();
+}
+
+//virtual
+void LLPanelHideBeacon::setVisible(BOOL visible)
+{
+ if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) visible = false;
+
+ if (visible)
+ {
+ updatePosition();
+ }
+
+ LLPanel::setVisible(visible);
+}
+
+
+//static
+LLPanelHideBeacon* LLPanelHideBeacon::getPanelHideBeacon()
+{
+ LLPanelHideBeacon* panel = new LLPanelHideBeacon();
+ panel->buildFromFile("panel_hide_beacon.xml");
+
+ LL_INFOS() << "Build LLPanelHideBeacon panel" << LL_ENDL;
+
+ panel->updatePosition();
+ return panel;
+}
+
+void LLPanelHideBeacon::onHideButtonClick()
+{
+ LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance();
+ if (instance)
+ {
+ instance->onClearBtn();
+ }
+}
+
+/**
+* Updates position of the panel (similar to Stand & Stop Flying panel).
+*/
+void LLPanelHideBeacon::updatePosition()
+{
+ S32 bottom_tb_center = 0;
+ if (LLToolBar* toolbar_bottom = gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_BOTTOM))
+ {
+ bottom_tb_center = toolbar_bottom->getRect().getCenterX();
+ }
+
+ S32 left_tb_width = 0;
+ if (LLToolBar* toolbar_left = gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_LEFT))
+ {
+ left_tb_width = toolbar_left->getRect().getWidth();
+ }
+
+ if (gToolBarView != NULL && gToolBarView->getToolbar(LLToolBarEnums::TOOLBAR_LEFT)->hasButtons())
+ {
+ S32 x_pos = bottom_tb_center - getRect().getWidth() / 2 - left_tb_width;
+ setOrigin( x_pos + HIDE_BEACON_PAD, 0);
+ }
+ else
+ {
+ S32 x_pos = bottom_tb_center - getRect().getWidth() / 2;
+ setOrigin( x_pos + HIDE_BEACON_PAD, 0);
+ }
+}
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index 97e99297cf..14a9c26fb9 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -107,7 +107,8 @@ public:
// teleport to the tracked item, if there is one
void teleport();
void onChangeMaturity();
-
+
+ void onClearBtn();
//Slapp instigated avatar tracking
void avatarTrackFromSlapp( const LLUUID& id );
@@ -124,7 +125,6 @@ protected:
void onComboTextEntry( );
void onSearchTextEntry( );
- void onClearBtn();
void onClickTeleportBtn();
void onShowTargetBtn();
void onShowAgentBtn();
@@ -151,7 +151,7 @@ protected:
void onCoordinatesCommit();
void onCommitSearchResult();
- void cacheLandmarkPosition();
+ void onTeleportFinished();
private:
LLPanel* mPanel; // Panel displaying the map
@@ -195,9 +195,31 @@ private:
LLCtrlListInterface * mListFriendCombo;
LLCtrlListInterface * mListLandmarkCombo;
LLCtrlListInterface * mListSearchResults;
+
+ boost::signals2::connection mTeleportFinishConnection;
};
extern LLFloaterWorldMap* gFloaterWorldMap;
+
+class LLPanelHideBeacon : public LLPanel
+{
+public:
+ static LLPanelHideBeacon* getInstance();
+
+ LLPanelHideBeacon();
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void setVisible(BOOL visible);
+ /*virtual*/ void draw();
+
+private:
+ static LLPanelHideBeacon* getPanelHideBeacon();
+ void onHideButtonClick();
+ void updatePosition();
+
+ LLButton* mHideButton;
+
+};
+
#endif
diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp
index 9f2119281d..489d34edca 100644
--- a/indra/newview/llgesturemgr.cpp
+++ b/indra/newview/llgesturemgr.cpp
@@ -483,8 +483,13 @@ void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_ges
mActive[base_item_id] = new_gesture;
- delete old_gesture;
- old_gesture = NULL;
+ // replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id)
+ // replaces ids without repalcing gesture
+ if (old_gesture != new_gesture)
+ {
+ delete old_gesture;
+ old_gesture = NULL;
+ }
if (asset_id.notNull())
{
@@ -910,7 +915,7 @@ void LLGestureMgr::stepGesture(LLMultiGesture* gesture)
else if (gesture->mWaitTimer.getElapsedTimeF32() > MAX_WAIT_ANIM_SECS)
{
// we've waited too long for an animation
- LL_INFOS() << "Waited too long for animations to stop, continuing gesture."
+ LL_INFOS("GestureMgr") << "Waited too long for animations to stop, continuing gesture."
<< LL_ENDL;
gesture->mWaitingAnimations = FALSE;
gesture->mCurrentStep++;
@@ -1097,6 +1102,34 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid,
self.setFetchID(item_id);
self.startFetch();
}
+
+ item_map_t::iterator it = self.mActive.find(item_id);
+ if (it == self.mActive.end())
+ {
+ // Gesture is supposed to be present, active, but NULL
+ LL_DEBUGS("GestureMgr") << "Gesture " << item_id << " not found in active list" << LL_ENDL;
+ }
+ else
+ {
+ LLMultiGesture* old_gesture = (*it).second;
+ if (old_gesture && old_gesture != gesture)
+ {
+ LL_DEBUGS("GestureMgr") << "Received dupplicate " << item_id << " callback" << LL_ENDL;
+ // In case somebody managest to activate, deactivate and
+ // then activate gesture again, before asset finishes loading.
+ // LLLoadInfo will have a different pointer, asset storage will
+ // see it as a different request, resulting in two callbacks.
+
+ // deactivateSimilarGestures() did not turn this one off
+ // because of matching item_id
+ self.stopGesture(old_gesture);
+
+ self.mActive.erase(item_id);
+ delete old_gesture;
+ old_gesture = NULL;
+ }
+ }
+
self.mActive[item_id] = gesture;
// Everything has been successful. Add to the active list.
@@ -1131,9 +1164,23 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid,
}
else
{
- LL_WARNS() << "Unable to load gesture" << LL_ENDL;
-
- self.mActive.erase(item_id);
+ LL_WARNS("GestureMgr") << "Unable to load gesture" << LL_ENDL;
+
+ item_map_t::iterator it = self.mActive.find(item_id);
+ if (it != self.mActive.end())
+ {
+ LLMultiGesture* old_gesture = (*it).second;
+ if (old_gesture)
+ {
+ // Shouldn't happen, just in case
+ LL_WARNS("GestureMgr") << "Gesture " << item_id << " existed when it shouldn't" << LL_ENDL;
+
+ self.stopGesture(old_gesture);
+ delete old_gesture;
+ old_gesture = NULL;
+ }
+ self.mActive.erase(item_id);
+ }
delete gesture;
gesture = NULL;
@@ -1151,9 +1198,23 @@ void LLGestureMgr::onLoadComplete(const LLUUID& asset_uuid,
LLDelayedGestureError::gestureFailedToLoad( item_id );
}
- LL_WARNS() << "Problem loading gesture: " << status << LL_ENDL;
-
- LLGestureMgr::instance().mActive.erase(item_id);
+ LL_WARNS("GestureMgr") << "Problem loading gesture: " << status << LL_ENDL;
+
+ item_map_t::iterator it = self.mActive.find(item_id);
+ if (it != self.mActive.end())
+ {
+ LLMultiGesture* old_gesture = (*it).second;
+ if (old_gesture)
+ {
+ // Shouldn't happen, just in case
+ LL_WARNS("GestureMgr") << "Gesture " << item_id << " existed when it shouldn't" << LL_ENDL;
+
+ self.stopGesture(old_gesture);
+ delete old_gesture;
+ old_gesture = NULL;
+ }
+ self.mActive.erase(item_id);
+ }
}
}
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index 9dca509262..e7bc2a9268 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -196,7 +196,7 @@ LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL;
// static
void LLGroupActions::search()
{
- LLFloaterReg::showInstance("search", LLSD().with("category", "groups"));
+ LLFloaterReg::showInstance("search");
}
// static
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index b4fc832596..37500176ea 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -138,6 +138,8 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
LLInventoryValidationInfo::LLInventoryValidationInfo():
mFatalErrorCount(0),
mWarningCount(0),
+ mLoopCount(0),
+ mOrphanedCount(0),
mInitialized(false),
mFatalNoRootFolder(false),
mFatalNoLibraryRootFolder(false),
@@ -147,7 +149,10 @@ LLInventoryValidationInfo::LLInventoryValidationInfo():
void LLInventoryValidationInfo::toOstream(std::ostream& os) const
{
- os << "mFatalErrorCount " << mFatalErrorCount << " mWarningCount " << mWarningCount;
+ os << "mFatalErrorCount " << mFatalErrorCount
+ << " mWarningCount " << mWarningCount
+ << " mLoopCount " << mLoopCount
+ << " mOrphanedCount " << mOrphanedCount;
}
@@ -161,6 +166,8 @@ void LLInventoryValidationInfo::asLLSD(LLSD& sd) const
{
sd["fatal_error_count"] = mFatalErrorCount;
sd["warning_count"] = mWarningCount;
+ sd["loop_count"] = mLoopCount;
+ sd["orphaned_count"] = mOrphanedCount;
sd["initialized"] = mInitialized;
sd["missing_system_folders_count"] = LLSD::Integer(mMissingRequiredSystemFolders.size());
sd["fatal_no_root_folder"] = mFatalNoRootFolder;
@@ -337,21 +344,35 @@ const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LL
return NULL;
}
-bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const
+LLInventoryModel::EAnscestorResult LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const
{
LLInventoryObject *object = getObject(object_id);
- while (object && object->getParentUUID().notNull())
- {
- LLInventoryObject *parent_object = getObject(object->getParentUUID());
+ if (!object)
+ {
+ LL_WARNS(LOG_INV) << "Unable to trace topmost ancestor, initial object " << object_id << " does not exist" << LL_ENDL;
+ return ANSCESTOR_MISSING;
+ }
+
+ std::set<LLUUID> object_ids{ object_id }; // loop protection
+ while (object->getParentUUID().notNull())
+ {
+ LLUUID parent_id = object->getParentUUID();
+ if (object_ids.find(parent_id) != object_ids.end())
+ {
+ LL_WARNS(LOG_INV) << "Detected a loop on an object " << parent_id << " when searching for ancestor of " << object_id << LL_ENDL;
+ return ANSCESTOR_LOOP;
+ }
+ object_ids.insert(parent_id);
+ LLInventoryObject *parent_object = getObject(parent_id);
if (!parent_object)
{
- LL_WARNS(LOG_INV) << "unable to trace topmost ancestor, missing item for uuid " << object->getParentUUID() << LL_ENDL;
- return false;
+ LL_WARNS(LOG_INV) << "unable to trace topmost ancestor of " << object_id << ", missing item for uuid " << parent_id << LL_ENDL;
+ return ANSCESTOR_MISSING;
}
object = parent_object;
}
result = object->getUUID();
- return true;
+ return ANSCESTOR_OK;
}
// Get the object by id. Returns NULL if not found.
@@ -2947,42 +2968,69 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
LL_INFOS(LOG_INV) << "saving inventory to: (" << filename << ")" << LL_ENDL;
- llofstream fileXML(filename.c_str());
- if (!fileXML.is_open())
- {
- LL_WARNS(LOG_INV) << "unable to save inventory to: " << filename << LL_ENDL;
- return false;
- }
+ try
+ {
+ llofstream fileXML(filename.c_str());
+ if (!fileXML.is_open())
+ {
+ LL_WARNS(LOG_INV) << "Failed to open file. Unable to save inventory to: " << filename << LL_ENDL;
+ return false;
+ }
- LLSD cache_ver;
- cache_ver["inv_cache_version"] = sCurrentInvCacheVersion;
+ LLSD cache_ver;
+ cache_ver["inv_cache_version"] = sCurrentInvCacheVersion;
- fileXML << LLSDOStreamer<LLSDNotationFormatter>(cache_ver) << std::endl;
+ if (fileXML.fail())
+ {
+ LL_WARNS(LOG_INV) << "Failed to write cache version to file. Unable to save inventory to: " << filename << LL_ENDL;
+ return false;
+ }
- S32 count = categories.size();
- S32 cat_count = 0;
- S32 i;
- for(i = 0; i < count; ++i)
- {
- LLViewerInventoryCategory* cat = categories[i];
- if(cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
- {
- fileXML << LLSDOStreamer<LLSDNotationFormatter>(cat->exportLLSD()) << std::endl;
- cat_count++;
- }
- }
+ fileXML << LLSDOStreamer<LLSDNotationFormatter>(cache_ver) << std::endl;
- S32 it_count = items.size();
- for(i = 0; i < it_count; ++i)
- {
- fileXML << LLSDOStreamer<LLSDNotationFormatter>(items[i]->asLLSD()) << std::endl;
- }
+ S32 count = categories.size();
+ S32 cat_count = 0;
+ S32 i;
+ for (i = 0; i < count; ++i)
+ {
+ LLViewerInventoryCategory* cat = categories[i];
+ if (cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
+ {
+ fileXML << LLSDOStreamer<LLSDNotationFormatter>(cat->exportLLSD()) << std::endl;
+ cat_count++;
+ }
- fileXML.close();
+ if (fileXML.fail())
+ {
+ LL_WARNS(LOG_INV) << "Failed to write a folder to file. Unable to save inventory to: " << filename << LL_ENDL;
+ return false;
+ }
+ }
- LL_INFOS(LOG_INV) << "Inventory saved: " << cat_count << " categories, " << it_count << " items." << LL_ENDL;
+ S32 it_count = items.size();
+ for (i = 0; i < it_count; ++i)
+ {
+ fileXML << LLSDOStreamer<LLSDNotationFormatter>(items[i]->asLLSD()) << std::endl;
- return true;
+ if (fileXML.fail())
+ {
+ LL_WARNS(LOG_INV) << "Failed to write an item to file. Unable to save inventory to: " << filename << LL_ENDL;
+ return false;
+ }
+ }
+
+ fileXML.close();
+
+ LL_INFOS(LOG_INV) << "Inventory saved: " << cat_count << " categories, " << it_count << " items." << LL_ENDL;
+ }
+ catch (...)
+ {
+ LOG_UNHANDLED_EXCEPTION("");
+ LL_INFOS(LOG_INV) << "Failed to save inventory to: (" << filename << ")" << LL_ENDL;
+ return false;
+ }
+
+ return true;
}
// message handling functionality
@@ -3850,20 +3898,23 @@ void LLInventoryModel::dumpInventory() const
LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LLPointer<LLInventoryValidationInfo> validation_info = new LLInventoryValidationInfo;
- S32 fatalities = 0;
+ S32 fatal_errs = 0;
S32 warnings = 0;
+ S32 loops = 0;
+ S32 orphaned = 0;
if (getRootFolderID().isNull())
{
LL_WARNS("Inventory") << "Fatal inventory corruption: no root folder id" << LL_ENDL;
validation_info->mFatalNoRootFolder = true;
- fatalities++;
+ fatal_errs++;
}
if (getLibraryRootFolderID().isNull())
{
+ // Probably shouldn't be a fatality, inventory can function without a library
LL_WARNS("Inventory") << "Fatal inventory corruption: no library root folder id" << LL_ENDL;
validation_info->mFatalNoLibraryRootFolder = true;
- fatalities++;
+ fatal_errs++;
}
if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size())
@@ -3895,7 +3946,23 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
}
LLUUID topmost_ancestor_id;
// Will leave as null uuid on failure
- getObjectTopmostAncestor(cat_id, topmost_ancestor_id);
+ EAnscestorResult res = getObjectTopmostAncestor(cat_id, topmost_ancestor_id);
+ switch (res)
+ {
+ case ANSCESTOR_MISSING:
+ orphaned++;
+ break;
+ case ANSCESTOR_LOOP:
+ loops++;
+ break;
+ case ANSCESTOR_OK:
+ break;
+ default:
+ LL_WARNS("Inventory") << "Unknown ancestor error for " << cat_id << LL_ENDL;
+ warnings++;
+ break;
+ }
+
if (cat_id != cat->getUUID())
{
LL_WARNS("Inventory") << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL;
@@ -3995,8 +4062,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
// Topmost ancestor should be root or library.
LLUUID topmost_ancestor_id;
- bool found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
- if (!found)
+ EAnscestorResult found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
+ if (found != ANSCESTOR_OK)
{
LL_WARNS("Inventory") << "unable to find topmost ancestor for " << item_id << LL_ENDL;
warnings++;
@@ -4026,7 +4093,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName()
<< "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL;
- warnings++;
+ orphaned++;
}
else
{
@@ -4044,6 +4111,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName()
<< "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL;
+ orphaned++;
}
}
}
@@ -4052,7 +4120,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
LLFolderType::EType folder_type = cat->getPreferredType();
bool cat_is_in_library = false;
LLUUID topmost_id;
- if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) && topmost_id == getLibraryRootFolderID())
+ if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) == ANSCESTOR_OK && topmost_id == getLibraryRootFolderID())
{
cat_is_in_library = true;
}
@@ -4092,6 +4160,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
if (parent_id.isNull())
{
LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL;
+ orphaned++;
}
else
{
@@ -4102,6 +4171,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName()
<< "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL;
+ orphaned++;
}
else
{
@@ -4118,6 +4188,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName()
<< "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL;
+ orphaned++;
}
}
@@ -4135,15 +4206,18 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
LL_WARNS("Inventory") << "link " << item->getUUID() << " type " << item->getActualType()
<< " missing backlink info at target_id " << target_id
<< LL_ENDL;
+ orphaned++;
}
// Links should have referents.
if (item->getActualType() == LLAssetType::AT_LINK && !target_item)
{
LL_WARNS("Inventory") << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+ orphaned++;
}
else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat)
{
LL_WARNS("Inventory") << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+ orphaned++;
}
if (target_item && target_item->getIsLinkType())
{
@@ -4215,8 +4289,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
if (is_automatic)
{
LL_WARNS("Inventory") << "Fatal inventory corruption: cannot create system folder of type " << ft << LL_ENDL;
- fatalities++;
- validation_info->mMissingRequiredSystemFolders.insert(LLFolderType::EType(ft));
+ fatal_errs++;
+ validation_info->mMissingRequiredSystemFolders.insert(folder_type);
}
else
{
@@ -4227,8 +4301,20 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
else if (count_under_root > 1)
{
LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL;
- validation_info->mDuplicateRequiredSystemFolders.insert(LLFolderType::EType(ft));
- fatalities++;
+ validation_info->mDuplicateRequiredSystemFolders.insert(folder_type);
+ if (!is_automatic && folder_type != LLFolderType::FT_SETTINGS)
+ {
+ // It is a fatal problem or can lead to fatal problems for COF,
+ // outfits, trash and other non-automatic folders.
+ fatal_errs++;
+ }
+ else
+ {
+ // For automatic folders it's not a fatal issue and shouldn't
+ // break inventory or other functionality further
+ // Exception: FT_SETTINGS is not automatic, but only deserves a warning.
+ warnings++;
+ }
}
if (count_elsewhere > 0)
{
@@ -4254,11 +4340,13 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
}
// FIXME need to fail login and tell user to retry, contact support if problem persists.
- bool valid = (fatalities == 0);
- LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatalities << ", warnings: " << warnings << ", valid: " << valid << LL_ENDL;
+ bool valid = (fatal_errs == 0);
+ LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatal_errs << ", warnings: " << warnings << ", valid: " << valid << LL_ENDL;
- validation_info->mFatalErrorCount = fatalities;
+ validation_info->mFatalErrorCount = fatal_errs;
validation_info->mWarningCount = warnings;
+ validation_info->mLoopCount = loops;
+ validation_info->mOrphanedCount = orphaned;
return validation_info;
}
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index e81652820f..eeec89bfb0 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -68,6 +68,8 @@ public:
S32 mFatalErrorCount;
S32 mWarningCount;
+ S32 mLoopCount; // Presence of folders whose ansestors loop onto themselves
+ S32 mOrphanedCount; // Missing or orphaned items, links and folders
bool mInitialized;
bool mFatalNoRootFolder;
bool mFatalNoLibraryRootFolder;
@@ -283,9 +285,14 @@ public:
// Check if one object has a parent chain up to the category specified by UUID.
BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const;
-
+
+ enum EAnscestorResult{
+ ANSCESTOR_OK = 0,
+ ANSCESTOR_MISSING = 1,
+ ANSCESTOR_LOOP = 2,
+ };
// Follow parent chain to the top.
- bool getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
+ EAnscestorResult getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
//--------------------------------------------------------------------
// Find
diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp
index c1e5e5faed..d3ba18525b 100644
--- a/indra/newview/llkeyconflict.cpp
+++ b/indra/newview/llkeyconflict.cpp
@@ -411,8 +411,16 @@ void LLKeyConflictHandler::loadFromSettings(ESourceMode load_mode)
filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename_default);
if (!gDirUtilp->fileExists(filename) || !loadFromSettings(load_mode, filename, &mControlsMap))
{
- // mind placeholders
- mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end());
+ // Mind placeholders
+ // Do not use mControlsMap.insert(mDefaultsMap) since mControlsMap has
+ // placeholders that won't be added over(to) by insert.
+ // Or instead move generatePlaceholders call to be after copying
+ control_map_t::iterator iter = mDefaultsMap.begin();
+ while (iter != mDefaultsMap.end())
+ {
+ mControlsMap[iter->first].mKeyBind = iter->second.mKeyBind;
+ iter++;
+ }
}
}
mLoadMode = load_mode;
@@ -575,6 +583,8 @@ void LLKeyConflictHandler::saveToSettings(bool temporary)
break;
}
+ keys.xml_version.set(keybindings_xml_version, true);
+
if (temporary)
{
// write to temporary xml and use it for gViewerInput
@@ -736,9 +746,9 @@ void LLKeyConflictHandler::resetToDefault(const std::string &control_name)
resetToDefaultAndResolve(control_name, false);
}
-void LLKeyConflictHandler::resetToDefaults(ESourceMode mode)
+void LLKeyConflictHandler::resetToDefaultsAndResolve()
{
- if (mode == MODE_SAVED_SETTINGS)
+ if (mLoadMode == MODE_SAVED_SETTINGS)
{
control_map_t::iterator iter = mControlsMap.begin();
control_map_t::iterator end = mControlsMap.end();
@@ -751,8 +761,16 @@ void LLKeyConflictHandler::resetToDefaults(ESourceMode mode)
else
{
mControlsMap.clear();
- generatePlaceholders(mode);
+
+ // Set key combinations.
+ // Copy from mDefaultsMap before doing generatePlaceholders, otherwise
+ // insert() will fail to add some keys into pre-existing values from
+ // generatePlaceholders()
mControlsMap.insert(mDefaultsMap.begin(), mDefaultsMap.end());
+
+ // Set conflict masks and mark functions (un)assignable
+ generatePlaceholders(mLoadMode);
+
}
mHasUnsavedChanges = true;
@@ -762,7 +780,7 @@ void LLKeyConflictHandler::resetToDefaults()
{
if (!empty())
{
- resetToDefaults(mLoadMode);
+ resetToDefaultsAndResolve();
}
else
{
@@ -772,7 +790,7 @@ void LLKeyConflictHandler::resetToDefaults()
// 3. We are loading 'current' only to replace it
// but it is reliable and works Todo: consider optimizing.
loadFromSettings(mLoadMode);
- resetToDefaults(mLoadMode);
+ resetToDefaultsAndResolve();
}
}
@@ -805,7 +823,7 @@ void LLKeyConflictHandler::resetKeyboardBindings()
void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode)
{
- // These controls are meant to cause conflicts when user tries to assign same control somewhere else
+ // These placeholders are meant to cause conflict resolution when user tries to assign same control somewhere else
// also this can be used to pre-record controls that should not conflict or to assign conflict groups/masks
if (load_mode == MODE_FIRST_PERSON)
@@ -865,24 +883,60 @@ void LLKeyConflictHandler::generatePlaceholders(ESourceMode load_mode)
registerTemporaryControl("spin_around_ccw_sitting");
registerTemporaryControl("spin_around_cw_sitting");
}
+
+
+ // Special case, mouse clicks passed to scripts have 'lowest' piority
+ // thus do not conflict, everything else has a chance before them
+ // also in ML they have highest priority, but only when script-grabbed,
+ // thus do not conflict
+ // (see AGENT_CONTROL_ML_LBUTTON_DOWN and CONTROL_LBUTTON_DOWN_INDEX)
+ LLKeyConflict *type_data = &mControlsMap[script_mouse_handler_name];
+ type_data->mAssignable = true;
+ type_data->mConflictMask = U32_MAX - CONFLICT_LMOUSE;
}
-bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, const U32 &conlict_mask)
+bool LLKeyConflictHandler::removeConflicts(const LLKeyData &data, U32 conlict_mask)
{
if (conlict_mask == CONFLICT_NOTHING)
{
// Can't conflict
return true;
}
+
+ if (data.mMouse == CLICK_LEFT
+ && data.mMask == MASK_NONE
+ && data.mKey == KEY_NONE)
+ {
+ if ((conlict_mask & CONFLICT_LMOUSE) == 0)
+ {
+ // Can't conflict
+ return true;
+ }
+ else
+ {
+ // simplify conflict mask
+ conlict_mask = CONFLICT_LMOUSE;
+ }
+ }
+ else
+ {
+ // simplify conflict mask
+ conlict_mask &= ~CONFLICT_LMOUSE;
+ }
+
std::map<std::string, S32> conflict_list;
control_map_t::iterator cntrl_iter = mControlsMap.begin();
control_map_t::iterator cntrl_end = mControlsMap.end();
for (; cntrl_iter != cntrl_end; ++cntrl_iter)
{
+ const U32 cmp_mask = cntrl_iter->second.mConflictMask;
+ if ((cmp_mask & conlict_mask) == 0)
+ {
+ // can't conflict
+ continue;
+ }
S32 index = cntrl_iter->second.mKeyBind.findKeyData(data);
- if (index >= 0
- && cntrl_iter->second.mConflictMask != CONFLICT_NOTHING
- && (cntrl_iter->second.mConflictMask & conlict_mask) != 0)
+ if (index >= 0)
{
if (cntrl_iter->second.mAssignable)
{
diff --git a/indra/newview/llkeyconflict.h b/indra/newview/llkeyconflict.h
index 2926ca3aeb..23c1adf1e4 100644
--- a/indra/newview/llkeyconflict.h
+++ b/indra/newview/llkeyconflict.h
@@ -66,6 +66,7 @@ public:
};
const U32 CONFLICT_NOTHING = 0;
+ const U32 CONFLICT_LMOUSE = 0x1 << 1;
// at the moment this just means that key will conflict with everything that is identical
const U32 CONFLICT_ANY = U32_MAX;
@@ -128,23 +129,24 @@ public:
// resets current mode to defaults
void resetToDefaults();
- bool empty() { return mControlsMap.empty(); }
+ bool empty() const { return mControlsMap.empty(); }
void clear();
// reloads bindings from last valid user's xml or from default xml
// to keyboard's handler
static void resetKeyboardBindings();
- bool hasUnsavedChanges() { return mHasUnsavedChanges; }
+ bool hasUnsavedChanges() const { return mHasUnsavedChanges; }
void setLoadMode(ESourceMode mode) { mLoadMode = mode; }
- ESourceMode getLoadMode() { return mLoadMode; }
+ ESourceMode getLoadMode() const { return mLoadMode; }
private:
void resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts);
- void resetToDefaults(ESourceMode mode);
+ void resetToDefaultsAndResolve();
// at the moment these kind of control is not savable, but takes part in conflict resolution
void registerTemporaryControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask);
+ // conflict mask 0 means that any conflicts will be ignored
void registerTemporaryControl(const std::string &control_name, U32 conflict_mask = 0);
typedef std::map<std::string, LLKeyConflict> control_map_t;
@@ -152,7 +154,7 @@ private:
bool loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination);
void generatePlaceholders(ESourceMode load_mode); //E.x. non-assignable values
// returns false in case user is trying to reuse control that can't be reassigned
- bool removeConflicts(const LLKeyData &data, const U32 &conlict_mask);
+ bool removeConflicts(const LLKeyData &data, U32 conlict_mask);
// removes flags and removes temporary file, returns 'true' if file was removed
bool clearUnsavedChanges();
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index e81d2cc082..531f0b172d 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -165,13 +165,12 @@ void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credentia
//requested_options.append("inventory-meat");
//requested_options.append("inventory-skel-targets");
#if (!defined LL_MINIMIAL_REQUESTED_OPTIONS)
- if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary"))
- {
- requested_options.append("inventory-lib-root");
- requested_options.append("inventory-lib-owner");
- requested_options.append("inventory-skel-lib");
+
+ // Not requesting library will trigger mFatalNoLibraryRootFolder
+ requested_options.append("inventory-lib-root");
+ requested_options.append("inventory-lib-owner");
+ requested_options.append("inventory-skel-lib");
// requested_options.append("inventory-meat-lib");
- }
requested_options.append("initial-outfit");
requested_options.append("gestures");
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 5393d0b0b7..9142aadab9 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -1146,6 +1146,11 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
}
else
{
+ // Media might be blocked, waiting for a file,
+ // send an empty response to unblock it
+ const std::vector<std::string> empty_response;
+ self->sendPickFileResponse(empty_response);
+
LLNotificationsUtil::add("MediaFileDownloadUnsupported");
}
};
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index d3eb2dd4d4..859d987fc3 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -180,7 +180,6 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
mPreviewLOD = 0;
mModelLoader = NULL;
mMaxTriangleLimit = 0;
- mMinTriangleLimit = 0;
mDirty = false;
mGenLOD = false;
mLoading = false;
@@ -1287,7 +1286,14 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
F32 result_error = 0; // how far from original the model is, 1 == 100%
S32 new_indices = 0;
- target_indices = llclamp(llfloor(size_indices / indices_decimator), 3, (S32)size_indices); // leave at least one triangle
+ if (indices_decimator > 0)
+ {
+ target_indices = llclamp(llfloor(size_indices / indices_decimator), 3, (S32)size_indices); // leave at least one triangle
+ }
+ else // indices_decimator can be zero for error_threshold based calculations
+ {
+ target_indices = 3;
+ }
new_indices = LLMeshOptimizer::simplifyU32(
output_indices,
combined_indices,
@@ -1377,7 +1383,28 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
<< " original count: " << size_indices
<< " error treshold: " << error_threshold
<< LL_ENDL;
- return -1;
+
+ // U16 vertices overflow shouldn't happen, but just in case
+ new_indices = 0;
+ valid_faces = 0;
+ for (U32 face_idx = 0; face_idx < base_model->getNumVolumeFaces(); ++face_idx)
+ {
+ genMeshOptimizerPerFace(base_model, target_model, face_idx, indices_decimator, error_threshold, false);
+ const LLVolumeFace &face = target_model->getVolumeFace(face_idx);
+ new_indices += face.mNumIndices;
+ if (face.mNumIndices >= 3)
+ {
+ valid_faces++;
+ }
+ }
+ if (valid_faces)
+ {
+ return (F32)size_indices / (F32)new_indices;
+ }
+ else
+ {
+ return -1;
+ }
}
// Copy vertice, normals, tcs
@@ -1447,20 +1474,6 @@ F32 LLModelPreview::genMeshOptimizerPerModel(LLModel *base_model, LLModel *targe
if (new_indices < 3 || valid_faces == 0)
{
// Model should have at least one visible triangle
-
- if (!sloppy)
- {
- // Should only happen with sloppy
- // non sloppy shouldn't be capable of optimizing mesh away
- LL_WARNS() << "Failed to generate triangles"
- << " model " << target_model->mLabel
- << " target Indices: " << target_indices
- << " new Indices: " << new_indices
- << " original count: " << size_indices
- << " error treshold: " << error_threshold
- << LL_ENDL;
- }
-
return -1;
}
@@ -1484,7 +1497,14 @@ F32 LLModelPreview::genMeshOptimizerPerFace(LLModel *base_model, LLModel *target
F32 result_error = 0; // how far from original the model is, 1 == 100%
S32 new_indices = 0;
- target_indices = llclamp(llfloor(size_indices / indices_decimator), 3, (S32)size_indices); // leave at least one triangle
+ if (indices_decimator > 0)
+ {
+ target_indices = llclamp(llfloor(size_indices / indices_decimator), 3, (S32)size_indices); // leave at least one triangle
+ }
+ else
+ {
+ target_indices = 3;
+ }
new_indices = LLMeshOptimizer::simplify(
output,
face.mIndices,
@@ -1621,11 +1641,13 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
}
// meshoptimizer doesn't use triangle limit, it uses indices limit, so convert it to aproximate ratio
- indices_decimator = (F32)base_triangle_count / triangle_limit;
+ // triangle_limit can be 0.
+ indices_decimator = (F32)base_triangle_count / llmax(triangle_limit, 1.f);
}
else
{
- lod_error_threshold = mFMP->childGetValue("lod_error_threshold_" + lod_name[which_lod]).asReal();
+ // UI shows 0 to 100%, but meshoptimizer works with 0 to 1
+ lod_error_threshold = mFMP->childGetValue("lod_error_threshold_" + lod_name[which_lod]).asReal() / 100.f;
}
}
else
@@ -1636,7 +1658,6 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
}
mMaxTriangleLimit = base_triangle_count;
- mMinTriangleLimit = mBaseModel.size();
// Build models
@@ -1661,8 +1682,8 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
}
}
- mRequestedTriangleCount[lod] = llmax(mMinTriangleLimit, (S32)triangle_limit);
- mRequestedErrorThreshold[lod] = lod_error_threshold;
+ mRequestedTriangleCount[lod] = triangle_limit;
+ mRequestedErrorThreshold[lod] = lod_error_threshold * 100;
mRequestedLoDMode[lod] = lod_mode;
mModel[lod].clear();
@@ -1699,11 +1720,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
F32 res = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false);
if (res < 0)
{
- // U16 vertices overflow, shouldn't happen, but just in case
- for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)
- {
- genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false);
- }
+ target_model->copyVolumeFaces(base);
}
}
@@ -1726,15 +1743,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
F32 allowed_ratio_drift = 2.f;
F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false);
- if (precise_ratio < 0)
- {
- // U16 vertices overflow, shouldn't happen, but just in case
- for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)
- {
- genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false);
- }
- }
- else if (precise_ratio * allowed_ratio_drift < indices_decimator)
+ if (precise_ratio < 0 || (precise_ratio * allowed_ratio_drift < indices_decimator))
{
// Try sloppy variant if normal one failed to simplify model enough.
// Sloppy variant can fail entirely and has issues with precision,
@@ -1815,9 +1824,18 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
{
// Sloppy variant failed to generate triangles or is worse.
// Can happen with models that are too simple as is.
- // Fallback to normal method
- precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false);
+ if (precise_ratio < 0)
+ {
+ // Precise method failed as well, just copy face over
+ target_model->copyVolumeFaces(base);
+ precise_ratio = 1.f;
+ }
+ else
+ {
+ // Fallback to normal method
+ precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false);
+ }
LL_INFOS() << "Model " << target_model->getName()
<< " lod " << which_lod
@@ -1999,7 +2017,6 @@ void LLModelPreview::updateStatusMessages()
if (mMaxTriangleLimit == 0)
{
mMaxTriangleLimit = total_tris[LLModel::LOD_HIGH];
- mMinTriangleLimit = mUploadData.size();
}
mHasDegenerate = false;
@@ -2502,7 +2519,6 @@ void LLModelPreview::updateLodControls(S32 lod)
LLSpinCtrl* limit = mFMP->getChild<LLSpinCtrl>("lod_triangle_limit_" + lod_name[lod]);
limit->setMaxValue(mMaxTriangleLimit);
- limit->setMinValue(mMinTriangleLimit);
limit->forceSetValue(mRequestedTriangleCount[lod]);
threshold->forceSetValue(mRequestedErrorThreshold[lod]);
@@ -2515,7 +2531,6 @@ void LLModelPreview::updateLodControls(S32 lod)
threshold->setVisible(false);
limit->setMaxValue(mMaxTriangleLimit);
- limit->setMinValue(mMinTriangleLimit);
limit->setIncrement(llmax((U32)1, mMaxTriangleLimit / 32));
}
else
@@ -2798,7 +2813,9 @@ void LLModelPreview::lookupLODModelFiles(S32 lod)
std::string lod_filename = mLODFile[LLModel::LOD_HIGH];
std::string ext = ".dae";
- std::string::size_type i = lod_filename.rfind(ext);
+ std::string lod_filename_lower(lod_filename);
+ LLStringUtil::toLower(lod_filename_lower);
+ std::string::size_type i = lod_filename_lower.rfind(ext);
if (i != std::string::npos)
{
lod_filename.replace(i, lod_filename.size() - ext.size(), getLodSuffix(next_lod) + ext);
@@ -3281,6 +3298,14 @@ BOOL LLModelPreview::render()
if (!physics.mMesh.empty())
{ //render hull instead of mesh
+ // SL-16993 physics.mMesh[i].mNormals were being used to light the exploded
+ // analyzed physics shape but the drawArrays() interface changed
+ // causing normal data <0,0,0> to be passed to the shader.
+ // The Phyics Preview shader uses plain vertex coloring so the physics hull is full lit.
+ // We could also use interface/ui shaders.
+ gObjectPreviewProgram.unbind();
+ gPhysicsPreviewProgram.bind();
+
for (U32 i = 0; i < physics.mMesh.size(); ++i)
{
if (explode > 0.f)
@@ -3308,6 +3333,9 @@ BOOL LLModelPreview::render()
gGL.popMatrix();
}
}
+
+ gPhysicsPreviewProgram.unbind();
+ gObjectPreviewProgram.bind();
}
}
}
@@ -3730,6 +3758,7 @@ void LLModelPreview::onLODMeshOptimizerParamCommit(S32 requested_lod, bool enfor
{
genMeshOptimizerLODs(requested_lod, mode, 3, enforce_tri_limit);
refresh();
+ mDirty = true;
}
}
diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h
index f78f476810..9e32215e6a 100644
--- a/indra/newview/llmodelpreview.h
+++ b/indra/newview/llmodelpreview.h
@@ -290,10 +290,6 @@ protected:
// Amount of triangles in original(base) model
U32 mMaxTriangleLimit;
- // Minimum amount of allowed triangles in lod for spin cntrl.
- // Leave at least one triangle per model.
- S32 mMinTriangleLimit;
-
LLMeshUploadThread::instance_list mUploadData;
std::set<LLViewerFetchedTexture * > mTextureSet;
diff --git a/indra/newview/llpathfindingmanager.cpp b/indra/newview/llpathfindingmanager.cpp
index cb4c07a417..852b39f442 100644
--- a/indra/newview/llpathfindingmanager.cpp
+++ b/indra/newview/llpathfindingmanager.cpp
@@ -61,7 +61,7 @@
#define CAP_SERVICE_NAVMESH_STATUS "NavMeshGenerationStatus"
-#define CAP_SERVICE_OBJECT_LINKSETS "ObjectNavMeshProperties"
+#define CAP_SERVICE_OBJECT_LINKSETS "RegionObjects"
#define CAP_SERVICE_TERRAIN_LINKSETS "TerrainNavMeshProperties"
#define CAP_SERVICE_CHARACTERS "CharacterProperties"
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 061ecad099..39cdb6fb04 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -1029,7 +1029,6 @@ void LLPreviewGesture::finishInventoryUpload(LLUUID itemId, LLUUID newAssetId)
// active map with the new pointer.
if (LLGestureMgr::instance().isGestureActive(itemId))
{
- //*TODO: This is crashing for some reason. Fix it.
// Active gesture edited from menu.
LLGestureMgr::instance().replaceGesture(itemId, newAssetId);
gInventory.notifyObservers();
diff --git a/indra/newview/llsearchableui.cpp b/indra/newview/llsearchableui.cpp
index 1119e80005..620bbdfcdf 100644
--- a/indra/newview/llsearchableui.cpp
+++ b/indra/newview/llsearchableui.cpp
@@ -132,8 +132,11 @@ void ll::statusbar::SearchableItem::setNotHighlighted( )
{
mCtrl->setHighlighted( false );
- if( mWasHiddenBySearch )
- mMenu->setVisible( TRUE );
+ if (mWasHiddenBySearch)
+ {
+ mMenu->setVisible(TRUE);
+ mWasHiddenBySearch = false;
+ }
}
}
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 537b431ea2..a42b6562b8 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -310,6 +310,12 @@ void update_texture_fetch()
LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
gTextureList.updateImages(0.10f);
+
+ if (LLImageGLThread::sEnabled)
+ {
+ std::shared_ptr<LL::WorkQueue> main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->runFor(std::chrono::milliseconds(1));
+ }
}
void set_flags_and_update_appearance()
@@ -1490,19 +1496,7 @@ bool idle_startup()
display_startup();
// start up the ThreadPool we'll use for textures et al.
- {
- LLSD poolSizes{ gSavedSettings.getLLSD("ThreadPoolSizes") };
- LLSD sizeSpec{ poolSizes["General"] };
- LLSD::Integer poolSize{ sizeSpec.isInteger()? sizeSpec.asInteger() : 3 };
- LL_DEBUGS("ThreadPool") << "Instantiating General pool with "
- << poolSize << " threads" << LL_ENDL;
- // We don't want anyone, especially the main thread, to have to block
- // due to this ThreadPool being full.
- auto pool = new LL::ThreadPool("General", poolSize, 1024*1024);
- pool->start();
- // Once we start shutting down, destroy this ThreadPool.
- LLAppViewer::instance()->onCleanup([pool](){ delete pool; });
- }
+ LLAppViewer::instance()->initGeneralThread();
// Initialize global class data needed for surfaces (i.e. textures)
LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL;
@@ -1518,7 +1512,11 @@ bool idle_startup()
display_startup();
LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL;
- // For all images pre-loaded into viewer cache, decode them.
+ // For all images pre-loaded into viewer cache, init
+ // priorities and fetching using decodeAllImages.
+ // Most of the fetching and decoding likely to be done
+ // by update_texture_fetch() later, while viewer waits.
+ //
// Need to do this AFTER we init the sky
const S32 DECODE_TIME_SEC = 2;
for (int i = 0; i < DECODE_TIME_SEC; i++)
@@ -2242,10 +2240,6 @@ bool idle_startup()
// Have the agent start watching the friends list so we can update proxies
gAgent.observeFriends();
- if (gSavedSettings.getBOOL("LoginAsGod"))
- {
- gAgent.requestEnterGodMode();
- }
// Start automatic replay if the flag is set.
if (gSavedSettings.getBOOL("StatsAutoRun") || gAgentPilot.getReplaySession())
@@ -2726,19 +2720,34 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
gAgentAvatarp->setSex(gender);
- // try to find the outfit - if not there, create some default
- // wearables.
+ // try to find the requested outfit or folder
+
+ // -- check for existing outfit in My Outfits
+ bool do_copy = false;
LLUUID cat_id = findDescendentCategoryIDByName(
- gInventory.getLibraryRootFolderID(),
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS),
outfit_folder_name);
+
+ // -- check for existing folder in Library
if (cat_id.isNull())
{
+ cat_id = findDescendentCategoryIDByName(
+ gInventory.getLibraryRootFolderID(),
+ outfit_folder_name);
+ if (!cat_id.isNull())
+ {
+ do_copy = true;
+ }
+ }
+
+ if (cat_id.isNull())
+ {
+ // -- final fallback: create standard wearables
LL_DEBUGS() << "standard wearables" << LL_ENDL;
gAgentWearables.createStandardWearables();
}
else
{
- bool do_copy = true;
bool do_append = false;
LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
// Need to fetch cof contents before we can wear.
@@ -2836,7 +2845,7 @@ void reset_login()
gAgentWearables.cleanup();
gAgentCamera.cleanup();
gAgent.cleanup();
- LLWorld::getInstance()->destroyClass();
+ LLWorld::getInstance()->resetClass();
if ( gViewerWindow )
{ // Hide menus and normal buttons
@@ -3613,6 +3622,19 @@ bool process_login_success_response()
}
}
+ std::string fake_initial_outfit_name = gSavedSettings.getString("FakeInitialOutfitName");
+ if (!fake_initial_outfit_name.empty())
+ {
+ gAgent.setFirstLogin(TRUE);
+ sInitialOutfit = fake_initial_outfit_name;
+ if (sInitialOutfitGender.empty())
+ {
+ sInitialOutfitGender = "female"; // just guess, will get overridden when outfit is worn anyway.
+ }
+
+ LL_WARNS() << "Faking first-time login with initial outfit " << sInitialOutfit << LL_ENDL;
+ }
+
// set the location of the Agent Appearance service, from which we can request
// avatar baked textures if they are supported by the current region
std::string agent_appearance_url = response["agent_appearance_service"];
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 7a0f69fed5..b74577315e 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -549,9 +549,11 @@ void LLGLTexMemBar::draw()
U32 texFetchLatMed = U32(recording.getMean(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
U32 texFetchLatMax = U32(recording.getMax(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
- text = llformat("GL Tot: %d/%d MB Bound: %4d/%4d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
+ text = llformat("GL Tot: %d/%d MB GL Free: %d Sys Free: %d MB Bound: %4d/%4d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
total_mem.value(),
max_total_mem.value(),
+ LLImageGLThread::getFreeVRAMMegabytes(),
+ LLMemory::getAvailableMemKB()/1024,
bound_mem.value(),
max_bound_mem.value(),
LLRenderTarget::sBytesAllocated/(1024*1024),
diff --git a/indra/newview/lltoolcomp.cpp b/indra/newview/lltoolcomp.cpp
index ba328f27c4..6d54a3770c 100644
--- a/indra/newview/lltoolcomp.cpp
+++ b/indra/newview/lltoolcomp.cpp
@@ -44,6 +44,7 @@
#include "lltoolmgr.h"
#include "lltoolselectrect.h"
#include "lltoolplacer.h"
+#include "llviewerinput.h"
#include "llviewermenu.h"
#include "llviewerobject.h"
#include "llviewerwindow.h"
@@ -745,7 +746,7 @@ BOOL LLToolCompGun::handleHover(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
{
// if the left button is grabbed, don't put up the pie menu
- if (gAgent.leftButtonGrabbed())
+ if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
{
gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
return FALSE;
@@ -762,7 +763,7 @@ BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask)
{
// if the left button is grabbed, don't put up the pie menu
- if (gAgent.leftButtonGrabbed())
+ if (gAgent.leftButtonGrabbed() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
{
gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
return FALSE;
@@ -796,7 +797,10 @@ BOOL LLToolCompGun::handleRightMouseDown(S32 x, S32 y, MASK mask)
BOOL LLToolCompGun::handleMouseUp(S32 x, S32 y, MASK mask)
{
- gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+ if (gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+ }
setCurrentTool( (LLTool*) mGun );
return TRUE;
}
diff --git a/indra/newview/lltoolgrab.cpp b/indra/newview/lltoolgrab.cpp
index 6216899dc6..897f8c1e5f 100644
--- a/indra/newview/lltoolgrab.cpp
+++ b/indra/newview/lltoolgrab.cpp
@@ -51,6 +51,7 @@
#include "lltoolmgr.h"
#include "lltoolpie.h"
#include "llviewercamera.h"
+#include "llviewerinput.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
@@ -140,7 +141,6 @@ BOOL LLToolGrabBase::handleMouseDown(S32 x, S32 y, MASK mask)
LL_INFOS() << "LLToolGrab handleMouseDown" << LL_ENDL;
}
- // call the base class to propogate info to sim
LLTool::handleMouseDown(x, y, mask);
// leftButtonGrabbed() checks if controls are reserved by scripts, but does not take masks into account
@@ -150,6 +150,19 @@ BOOL LLToolGrabBase::handleMouseDown(S32 x, S32 y, MASK mask)
gViewerWindow->pickAsync(x, y, mask, pickCallback, /*BOOL pick_transparent*/ TRUE);
}
mClickedInMouselook = gAgentCamera.cameraMouselook();
+
+ if (mClickedInMouselook && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
+ {
+ // LLToolCompGun::handleMouseDown handles the event if ML controls are grabed,
+ // but LLToolGrabBase is often the end point for mouselook clicks if ML controls
+ // are not grabbed and LLToolGrabBase::handleMouseDown consumes the event,
+ // so send clicks from here.
+ // We are sending specifically CONTROL_LBUTTON_DOWN instead of _ML_ version.
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
+
+ // Todo: LLToolGrabBase probably shouldn't consume the event if there is nothing
+ // to grab in Mouselook, it intercepts handling in scanMouse
+ }
return TRUE;
}
@@ -953,9 +966,18 @@ void LLToolGrabBase::handleHoverFailed(S32 x, S32 y, MASK mask)
BOOL LLToolGrabBase::handleMouseUp(S32 x, S32 y, MASK mask)
{
- // call the base class to propogate info to sim
LLTool::handleMouseUp(x, y, mask);
+ if (gAgentCamera.cameraMouselook() && gViewerInput.isLMouseHandlingDefault(MODE_FIRST_PERSON))
+ {
+ // LLToolCompGun::handleMouseUp handles the event if ML controls are grabed,
+ // but LLToolGrabBase is often the end point for mouselook clicks if ML controls
+ // are not grabbed and LToolGrabBase::handleMouseUp consumes the event,
+ // so send clicks from here.
+ // We are sending specifically CONTROL_LBUTTON_UP instead of _ML_ version.
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
+ }
+
if( hasMouseCapture() )
{
setMouseCapture( FALSE );
diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp
index b5eb2880ae..d99c0ba2a6 100644
--- a/indra/newview/lltoolmorph.cpp
+++ b/indra/newview/lltoolmorph.cpp
@@ -239,7 +239,15 @@ BOOL LLVisualParamHint::render()
LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
- gPipeline.previewAvatar(gAgentAvatarp);
+ if (gAgentAvatarp->mDrawable.notNull())
+ {
+ LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
+ gGL.flush();
+ gGL.setSceneBlendType(LLRender::BT_REPLACE);
+ gPipeline.generateImpostor(gAgentAvatarp, true);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ gGL.flush();
+ }
gAgentAvatarp->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
mWearablePtr->setVisualParamWeight(mVisualParam->getID(), mLastParamWeight);
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index b4736841d6..43deac60d9 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -394,8 +394,9 @@ BOOL LLToolPie::handleLeftClickPick()
gFocusMgr.setKeyboardFocus(NULL);
}
- BOOL touchable = (object && object->flagHandleTouch())
- || (parent && parent->flagHandleTouch());
+ bool touchable = object
+ && (object->getClickAction() != CLICK_ACTION_DISABLED)
+ && (object->flagHandleTouch() || (parent && parent->flagHandleTouch()));
// Switch to grab tool if physical or triggerable
if (object &&
@@ -656,6 +657,12 @@ bool LLToolPie::teleportToClickedLocation()
LLViewerObject* objp = mHoverPick.getObject();
LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL;
+ if (objp && (objp->getAvatar() == gAgentAvatarp || objp == gAgentAvatarp)) // ex: nametag
+ {
+ // Don't teleport to self, teleporting to other avatars is fine
+ return false;
+ }
+
bool is_in_world = mHoverPick.mObjectID.notNull() && objp && !objp->isHUDAttachment();
bool is_land = mHoverPick.mPickType == LLPickInfo::PICK_LAND;
bool pos_non_zero = !mHoverPick.mPosGlobal.isExactlyZero();
@@ -750,7 +757,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
else if (!mMouseOutsideSlop
&& mMouseButtonDown
// disable camera steering if click on land is not used for moving
- && gViewerInput.isMouseBindUsed(CLICK_LEFT))
+ && gViewerInput.isMouseBindUsed(CLICK_LEFT, MASK_NONE, MODE_THIRD_PERSON))
{
S32 delta_x = x - mMouseDownX;
S32 delta_y = y - mMouseDownY;
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index 6aa1273174..70065cb5a0 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -353,7 +353,7 @@ void LLViewerAssetStorage::checkForTimeouts()
// Restore requests
LLCoprocedureManager* manager = LLCoprocedureManager::getInstance();
while (mCoroWaitList.size() > 0
- && manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < LLCoprocedureManager::DEFAULT_QUEUE_SIZE)
+ && manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < (LLCoprocedureManager::DEFAULT_QUEUE_SIZE - 1))
{
CoroWaitList &request = mCoroWaitList.front();
@@ -425,13 +425,14 @@ void LLViewerAssetStorage::queueRequestHttp(
if (!duplicate)
{
// Coroutine buffer has fixed size (synchronization buffer, so we have no alternatives), so buffer any request above limit
- if (LLCoprocedureManager::instance().count(VIEWER_ASSET_STORAGE_CORO_POOL) < LLCoprocedureManager::DEFAULT_QUEUE_SIZE)
+ LLCoprocedureManager* manager = LLCoprocedureManager::getInstance();
+ if (manager->count(VIEWER_ASSET_STORAGE_CORO_POOL) < (LLCoprocedureManager::DEFAULT_QUEUE_SIZE - 1))
{
bool with_http = true;
bool is_temp = false;
LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
- LLCoprocedureManager::instance().enqueueCoprocedure(VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro",
+ manager->enqueueCoprocedure(VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro",
boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, req, uuid, atype, callback, user_data));
}
else
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index 94ec534732..43b9cd90bd 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -816,13 +816,20 @@ bool toggle_enable_media(EKeystate s)
bool walk_to(EKeystate s)
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s)
+ {
+ // teleport/walk is usually on mouseclick, mouseclick needs
+ // to let AGENT_CONTROL_LBUTTON_UP happen if teleport didn't,
+ // so return false, but if it causes issues, do some kind of
+ // "return !has_teleported"
+ return false;
+ }
return LLToolPie::getInstance()->walkToClickedLocation();
}
bool teleport_to(EKeystate s)
{
- if (KEYSTATE_DOWN != s) return true;
+ if (KEYSTATE_DOWN != s) return false;
return LLToolPie::getInstance()->teleportToClickedLocation();
}
@@ -850,7 +857,47 @@ bool voice_follow_key(EKeystate s)
return false;
}
-bool agen_control_lbutton_handle(EKeystate s)
+bool script_trigger_lbutton(EKeystate s)
+{
+ // Check for script overriding/expecting left mouse button.
+ // Note that this does not pass event further and depends onto mouselook.
+ // Checks CONTROL_ML_LBUTTON_DOWN_INDEX for mouselook,
+ // CONTROL_LBUTTON_DOWN_INDEX for normal camera
+ if (gAgent.leftButtonGrabbed())
+ {
+ bool mouselook = gAgentCamera.cameraMouselook();
+ switch (s)
+ {
+ case KEYSTATE_DOWN:
+ if (mouselook)
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_DOWN);
+ }
+ else
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
+ }
+ return true;
+ case KEYSTATE_UP:
+ if (mouselook)
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_ML_LBUTTON_UP);
+ }
+ else
+ {
+ gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
+ }
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+// Used by scripts, for overriding/handling left mouse button
+// see mControlsTakenCount
+bool agent_control_lbutton_handle(EKeystate s)
{
switch (s)
{
@@ -922,6 +969,7 @@ REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to);
REGISTER_KEYBOARD_ACTION("walk_to", walk_to);
REGISTER_KEYBOARD_GLOBAL_ACTION("toggle_voice", toggle_voice);
REGISTER_KEYBOARD_GLOBAL_ACTION("voice_follow_key", voice_follow_key);
+REGISTER_KEYBOARD_ACTION(script_mouse_handler_name, script_trigger_lbutton);
#undef REGISTER_KEYBOARD_ACTION
LLViewerInput::LLViewerInput()
@@ -1193,6 +1241,20 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const
typedef boost::function<bool(EKeystate)> function_t;
function_t function = NULL;
+ if (mouse == CLICK_LEFT
+ && mask == MASK_NONE
+ && function_name == script_mouse_handler_name)
+ {
+ // Special case
+ // Left click has script overrides and by default
+ // is handled via agent_control_lbutton as last option
+ // In case of mouselook and present overrides it has highest
+ // priority even over UI and is handled in LLToolCompGun::handleMouseDown
+ // so just mark it as having default handler
+ mLMouseDefaultHandling[mode] = true;
+ return TRUE;
+ }
+
LLKeybindFunctionData* result = LLKeyboardActionRegistry::getValue(function_name);
if (result)
{
@@ -1269,7 +1331,8 @@ LLViewerInput::Keys::Keys()
: first_person("first_person"),
third_person("third_person"),
sitting("sitting"),
- edit_avatar("edit_avatar")
+ edit_avatar("edit_avatar"),
+ xml_version("xml_version", 0)
{}
void LLViewerInput::resetBindings()
@@ -1280,6 +1343,7 @@ void LLViewerInput::resetBindings()
mGlobalMouseBindings[i].clear();
mKeyBindings[i].clear();
mMouseBindings[i].clear();
+ mLMouseDefaultHandling[i] = false;
}
}
@@ -1298,6 +1362,65 @@ S32 LLViewerInput::loadBindingsXML(const std::string& filename)
binding_count += loadBindingMode(keys.third_person, MODE_THIRD_PERSON);
binding_count += loadBindingMode(keys.sitting, MODE_SITTING);
binding_count += loadBindingMode(keys.edit_avatar, MODE_EDIT_AVATAR);
+
+ // verify version
+ if (keys.xml_version < 1)
+ {
+ // updating from a version that was not aware of LMouse bindings
+ for (S32 i = 0; i < MODE_COUNT; i++)
+ {
+ mLMouseDefaultHandling[i] = true;
+ }
+
+ // fix missing values
+ KeyBinding mouse_binding;
+ mouse_binding.key = "";
+ mouse_binding.mask = "NONE";
+ mouse_binding.mouse = "LMB";
+ mouse_binding.command = script_mouse_handler_name;
+
+ if (keys.third_person.isProvided())
+ {
+ keys.third_person.bindings.add(mouse_binding);
+ }
+
+ if (keys.first_person.isProvided())
+ {
+ keys.first_person.bindings.add(mouse_binding);
+ }
+
+ if (keys.sitting.isProvided())
+ {
+ keys.sitting.bindings.add(mouse_binding);
+ }
+
+ if (keys.edit_avatar.isProvided())
+ {
+ keys.edit_avatar.bindings.add(mouse_binding);
+ }
+
+ // fix version
+ keys.xml_version.set(keybindings_xml_version, true);
+
+ // Write the resulting XML to file
+ LLXMLNodePtr output_node = new LLXMLNode("keys", false);
+ LLXUIParser write_parser;
+ write_parser.writeXUI(output_node, keys);
+
+ if (!output_node->isNull())
+ {
+ // file in app_settings is supposed to be up to date
+ // this is only for the file from user_settings
+ LL_INFOS("ViewerInput") << "Updating file " << filename << " to a newer version" << LL_ENDL;
+ LLFILE *fp = LLFile::fopen(filename, "w");
+ if (fp != NULL)
+ {
+ LLXMLNode::writeHeaderToFile(fp);
+ output_node->writeToFile(fp);
+ fclose(fp);
+ }
+ }
+ }
}
return binding_count;
}
@@ -1469,17 +1592,6 @@ bool LLViewerInput::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
bool res = scanKey(mKeyBindings[mode], mKeyBindings[mode].size(), key, mask, key_down, key_up, key_level, repeat);
- if (!res && agent_control_lbutton.canHandle(CLICK_NONE, key, mask))
- {
- if (key_down && !repeat)
- {
- res = agen_control_lbutton_handle(KEYSTATE_DOWN);
- }
- if (key_up)
- {
- res = agen_control_lbutton_handle(KEYSTATE_UP);
- }
- }
return res;
}
@@ -1603,29 +1715,36 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
bool res = false;
S32 mode = getMode();
MASK mask = gKeyboard->currentMask(TRUE);
-
- // By default mouse clicks require exact mask
- // Todo: support for mIgnoreMasks because some functions like teleports
- // expect to be canceled, but for voice it's prefered to ignore mask.
res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state, false);
- // no user defined actions found or those actions can't handle the key/button, handle control if nessesary
- if (!res && agent_control_lbutton.canHandle(click, KEY_NONE, mask))
+
+ // No user defined actions found or those actions can't handle the key/button,
+ // so handle CONTROL_LBUTTON if nessesary.
+ //
+ // Default handling for MODE_FIRST_PERSON is in LLToolCompGun::handleMouseDown,
+ // and sends AGENT_CONTROL_ML_LBUTTON_DOWN, but it only applies if ML controls
+ // are leftButtonGrabbed(), send a normal click otherwise.
+
+ if (!res
+ && mLMouseDefaultHandling[mode]
+ && (mode != MODE_FIRST_PERSON || !gAgent.leftButtonGrabbed())
+ && (click == CLICK_LEFT || click == CLICK_DOUBLELEFT)
+ )
{
switch (state)
{
case MOUSE_STATE_DOWN:
- agen_control_lbutton_handle(KEYSTATE_DOWN);
+ agent_control_lbutton_handle(KEYSTATE_DOWN);
res = true;
break;
case MOUSE_STATE_CLICK:
// might not work best with some functions,
// but some function need specific states too specifically
- agen_control_lbutton_handle(KEYSTATE_DOWN);
- agen_control_lbutton_handle(KEYSTATE_UP);
+ agent_control_lbutton_handle(KEYSTATE_DOWN);
+ agent_control_lbutton_handle(KEYSTATE_UP);
res = true;
break;
case MOUSE_STATE_UP:
- agen_control_lbutton_handle(KEYSTATE_UP);
+ agent_control_lbutton_handle(KEYSTATE_UP);
res = true;
break;
default:
@@ -1655,7 +1774,7 @@ void LLViewerInput::scanMouse()
}
}
-bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode)
+bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const
{
S32 size = mMouseBindings[mode].size();
for (S32 index = 0; index < size; index++)
diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h
index ca70ac76bf..52e95e2168 100644
--- a/indra/newview/llviewerinput.h
+++ b/indra/newview/llviewerinput.h
@@ -31,6 +31,8 @@
#include "llinitparam.h"
const S32 MAX_KEY_BINDINGS = 128; // was 60
+const S32 keybindings_xml_version = 1;
+const std::string script_mouse_handler_name = "script_trigger_lbutton";
class LLNamedFunction
{
@@ -100,7 +102,7 @@ public:
third_person,
sitting,
edit_avatar;
-
+ Optional<S32> xml_version; // 'xml', because 'version' appears to be reserved
Keys();
};
@@ -131,7 +133,8 @@ public:
BOOL handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
void scanMouse();
- bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask = MASK_NONE, const S32 mode = MODE_THIRD_PERSON);
+ bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask, const S32 mode) const;
+ bool isLMouseHandlingDefault(const S32 mode) const { return mLMouseDefaultHandling[mode]; }
private:
bool scanKey(const std::vector<LLKeyboardBinding> &binding,
@@ -171,6 +174,7 @@ private:
// to send what we think function wants based on collection of bools (mKeyRepeated, mKeyLevel, mKeyDown)
std::vector<LLKeyboardBinding> mKeyBindings[MODE_COUNT];
std::vector<LLMouseBinding> mMouseBindings[MODE_COUNT];
+ bool mLMouseDefaultHandling[MODE_COUNT]; // Due to having special priority
// keybindings that do not consume event and are handled earlier, before floaters
std::vector<LLKeyboardBinding> mGlobalKeyBindings[MODE_COUNT];
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 27d8df28c3..812f804ea9 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -3289,10 +3289,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD:
{
LL_DEBUGS("Media") << "Media event - file download requested - filename is " << plugin->getFileDownloadFilename() << LL_ENDL;
-
- //unblock media plugin
- const std::vector<std::string> empty_response;
- plugin->sendPickFileResponse(empty_response);
}
break;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index a2d3f2c0cf..a95636ff23 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -1278,6 +1278,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num, MAX_OBJECT_BINARY_DATA_SIZE);
mTotalCRC = crc;
+ // Might need to update mSourceMuted here to properly pick up new radius
mSoundCutOffRadius = cutoff;
// Owner ID used for sound muting or particle system muting
@@ -5884,7 +5885,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow
else if (flags & LL_SOUND_FLAG_STOP)
{
// Just shut off the sound
- mAudioSourcep->play(LLUUID::null);
+ mAudioSourcep->stop();
}
return;
}
@@ -5923,7 +5924,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow
mAudioSourcep->setQueueSounds(queue);
if(!queue) // stop any current sound first to avoid "farts of doom" (SL-1541) -MG
{
- mAudioSourcep->play(LLUUID::null);
+ mAudioSourcep->stop();
}
// Play this sound if region maturity permits
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 27fbf39673..67ad72e997 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -266,7 +266,14 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
return;
}
- regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ LLWorld *world_inst = LLWorld::getInstance(); // Not a singleton!
+ if (!world_inst)
+ {
+ LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities, but world no longer exists!" << LL_ENDL;
+ return;
+ }
+
+ regionp = world_inst->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
{
LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities for region that no longer exists!" << LL_ENDL;
@@ -314,6 +321,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
regionp = NULL;
impl = NULL;
+ world_inst = NULL;
result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);
if (STATE_WORLD_INIT > LLStartUp::getStartupState())
@@ -327,7 +335,14 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
return;
}
- regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ world_inst = LLWorld::getInstance();
+ if (!world_inst)
+ {
+ LL_WARNS("AppInit", "Capabilities") << "Received capabilities, but world no longer exists!" << LL_ENDL;
+ return;
+ }
+
+ regionp = world_inst->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
{
LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL;
@@ -411,7 +426,14 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)
// This loop is used for retrying a capabilities request.
do
{
- regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ LLWorld *world_inst = LLWorld::getInstance(); // Not a singleton!
+ if (!world_inst)
+ {
+ LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities, but world no longer exists!" << LL_ENDL;
+ return;
+ }
+
+ regionp = world_inst->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
{
LL_WARNS("AppInit", "Capabilities") << "Attempting to get capabilities for region that no longer exists!" << LL_ENDL;
@@ -434,6 +456,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)
LL_INFOS("AppInit", "Capabilities") << "Requesting second Seed from " << url << " for region " << regionp->getRegionID() << LL_ENDL;
regionp = NULL;
+ world_inst = NULL;
result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);
LLSD httpResults = result["http_result"];
@@ -449,7 +472,14 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)
break;
}
- regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ world_inst = LLWorld::getInstance();
+ if (!world_inst)
+ {
+ LL_WARNS("AppInit", "Capabilities") << "Received capabilities, but world no longer exists!" << LL_ENDL;
+ return;
+ }
+
+ regionp = world_inst->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
{
LL_WARNS("AppInit", "Capabilities") << "Received capabilities for region that no longer exists!" << LL_ENDL;
@@ -533,7 +563,14 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region
break;
}
- regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ LLWorld *world_inst = LLWorld::getInstance(); // Not a singleton!
+ if (!world_inst)
+ {
+ LL_WARNS("AppInit", "Capabilities") << "Attempting to request Sim Feature, but world no longer exists!" << LL_ENDL;
+ return;
+ }
+
+ regionp = world_inst->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
{
LL_WARNS("AppInit", "SimulatorFeatures") << "Attempting to request Sim Feature for region that no longer exists!" << LL_ENDL;
@@ -541,6 +578,7 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region
}
regionp = NULL;
+ world_inst = NULL;
LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
LLSD httpResults = result["http_result"];
@@ -559,7 +597,14 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region
// remove the http_result from the llsd
result.erase("http_result");
- regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
+ world_inst = LLWorld::getInstance();
+ if (!world_inst)
+ {
+ LL_WARNS("AppInit", "Capabilities") << "Attempting to request Sim Feature, but world no longer exists!" << LL_ENDL;
+ return;
+ }
+
+ regionp = world_inst->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
{
LL_WARNS("AppInit", "SimulatorFeatures") << "Attempting to set Sim Feature for region that no longer exists!" << LL_ENDL;
@@ -2092,7 +2137,14 @@ public:
const LLSD& input) const
{
LLHost host(input["sender"].asString());
- LLViewerRegion* region = LLWorld::getInstance()->getRegion(host);
+
+ LLWorld *world_inst = LLWorld::getInstance(); // Not a singleton!
+ if (!world_inst)
+ {
+ return;
+ }
+
+ LLViewerRegion* region = world_inst->getRegion(host);
if( !region )
{
return;
@@ -3008,12 +3060,12 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("ObjectAnimation");
capabilityNames.append("ObjectMedia");
capabilityNames.append("ObjectMediaNavigate");
- capabilityNames.append("ObjectNavMeshProperties");
capabilityNames.append("ParcelPropertiesUpdate");
capabilityNames.append("ParcelVoiceInfoRequest");
capabilityNames.append("ProductInfoRequest");
capabilityNames.append("ProvisionVoiceAccountRequest");
capabilityNames.append("ReadOfflineMsgs"); // Requires to respond reliably: AcceptFriendship, AcceptGroupInvite, DeclineFriendship, DeclineGroupInvite
+ capabilityNames.append("RegionObjects");
capabilityNames.append("RemoteParcelRequest");
capabilityNames.append("RenderMaterials");
capabilityNames.append("RequestTextureDownload");
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index c97b1d914b..1cb2c6b9ee 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -102,6 +102,7 @@ LLGLSLShader gSkinnedObjectSimpleProgram;
LLGLSLShader gObjectSimpleImpostorProgram;
LLGLSLShader gSkinnedObjectSimpleImpostorProgram;
LLGLSLShader gObjectPreviewProgram;
+LLGLSLShader gPhysicsPreviewProgram;
LLGLSLShader gObjectSimpleWaterProgram;
LLGLSLShader gSkinnedObjectSimpleWaterProgram;
LLGLSLShader gObjectSimpleAlphaMaskProgram;
@@ -758,6 +759,7 @@ void LLViewerShaderMgr::unloadShaders()
gObjectSimpleImpostorProgram.unload();
gSkinnedObjectSimpleImpostorProgram.unload();
gObjectPreviewProgram.unload();
+ gPhysicsPreviewProgram.unload();
gImpostorProgram.unload();
gObjectSimpleAlphaMaskProgram.unload();
gSkinnedObjectSimpleAlphaMaskProgram.unload();
@@ -1874,6 +1876,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
shader->clearPermutations();
shader->addPermutation("USE_VERTEX_COLOR", "1");
+ shader->addPermutation("HAS_ALPHA_MASK", "1");
shader->addPermutation("USE_INDEXED_TEX", "1");
if (use_sun_shadow)
{
@@ -1950,6 +1953,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
shader->clearPermutations();
shader->addPermutation("USE_INDEXED_TEX", "1");
shader->addPermutation("FOR_IMPOSTOR", "1");
+ shader->addPermutation("HAS_ALPHA_MASK", "1");
shader->addPermutation("USE_VERTEX_COLOR", "1");
if (rigged)
{
@@ -2021,6 +2025,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
shader[i]->addPermutation("USE_INDEXED_TEX", "1");
shader[i]->addPermutation("WATER_FOG", "1");
shader[i]->addPermutation("USE_VERTEX_COLOR", "1");
+ shader[i]->addPermutation("HAS_ALPHA_MASK", "1");
if (use_sun_shadow)
{
shader[i]->addPermutation("HAS_SHADOW", "1");
@@ -3023,6 +3028,24 @@ BOOL LLViewerShaderMgr::loadShadersObject()
if (success)
{
+ gPhysicsPreviewProgram.mName = "Preview Physics Shader";
+ gPhysicsPreviewProgram.mFeatures.calculatesLighting = false;
+ gPhysicsPreviewProgram.mFeatures.calculatesAtmospherics = false;
+ gPhysicsPreviewProgram.mFeatures.hasGamma = false;
+ gPhysicsPreviewProgram.mFeatures.hasAtmospherics = false;
+ gPhysicsPreviewProgram.mFeatures.hasLighting = false;
+ gPhysicsPreviewProgram.mFeatures.mIndexedTextureChannels = 0;
+ gPhysicsPreviewProgram.mFeatures.disableTextureIndex = true;
+ gPhysicsPreviewProgram.mShaderFiles.clear();
+ gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsV.glsl", GL_VERTEX_SHADER_ARB));
+ gPhysicsPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewPhysicsF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gPhysicsPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
+ success = gPhysicsPreviewProgram.createShader(NULL, NULL);
+ gPhysicsPreviewProgram.mFeatures.hasLighting = false;
+ }
+
+ if (success)
+ {
gObjectSimpleProgram.mName = "Simple Shader";
gObjectSimpleProgram.mFeatures.calculatesLighting = true;
gObjectSimpleProgram.mFeatures.calculatesAtmospherics = true;
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 297cfb6e68..93bb29a355 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -181,6 +181,7 @@ extern LLGLSLShader gOneTextureNoColorProgram;
extern LLGLSLShader gObjectSimpleProgram;
extern LLGLSLShader gObjectSimpleImpostorProgram;
extern LLGLSLShader gObjectPreviewProgram;
+extern LLGLSLShader gPhysicsPreviewProgram;
extern LLGLSLShader gObjectSimpleAlphaMaskProgram;
extern LLGLSLShader gObjectSimpleWaterProgram;
extern LLGLSLShader gObjectSimpleWaterAlphaMaskProgram;
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 5484d43b8d..3befac73b3 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -392,8 +392,12 @@ void update_statistics()
gTransferManager.resetTransferBitsIn(LLTCT_ASSET);
sample(LLStatViewer::VISIBLE_AVATARS, LLVOAvatar::sNumVisibleAvatars);
- LLWorld::getInstance()->updateNetStats();
- LLWorld::getInstance()->requestCacheMisses();
+ LLWorld *world = LLWorld::getInstance(); // not LLSingleton
+ if (world)
+ {
+ world->updateNetStats();
+ world->requestCacheMisses();
+ }
// Reset all of these values.
gVLManager.resetBitCounts();
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index f9fd0f85e3..19797a2f54 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1222,6 +1222,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
LLViewerFetchedTexture* imagep = *iter++;
imagep->updateFetch();
}
+ std::shared_ptr<LL::WorkQueue> main_queue = LLImageGLThread::sEnabled ? LL::WorkQueue::getInstance("mainloop") : NULL;
// Run threads
S32 fetch_pending = 0;
while (1)
@@ -1229,6 +1230,13 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
LLAppViewer::instance()->getTextureCache()->update(1); // unpauses the texture cache thread
LLAppViewer::instance()->getImageDecodeThread()->update(1); // unpauses the image thread
fetch_pending = LLAppViewer::instance()->getTextureFetch()->update(1); // unpauses the texture fetch thread
+
+ if (LLImageGLThread::sEnabled)
+ {
+ main_queue->runFor(std::chrono::milliseconds(1));
+ fetch_pending += main_queue->size();
+ }
+
if (fetch_pending == 0 || timer.getElapsedTimeF32() > max_time)
{
break;
@@ -1968,9 +1976,18 @@ bool LLUIImageList::initFromFile()
preloadUIImage(image.name, file_name, image.use_mips, image.scale, image.clip, image.scale_type);
}
- if (cur_pass == PASS_DECODE_NOW && !gSavedSettings.getBOOL("NoPreload"))
+ if (!gSavedSettings.getBOOL("NoPreload"))
{
- gTextureList.decodeAllImages(10.f); // decode preloaded images
+ if (cur_pass == PASS_DECODE_NOW)
+ {
+ // init fetching and decoding of preloaded images
+ gTextureList.decodeAllImages(9.f);
+ }
+ else
+ {
+ // decodeAllImages needs two passes to refresh stats and priorities on second pass
+ gTextureList.decodeAllImages(1.f);
+ }
}
}
return true;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index a54c29a404..42e21f7130 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2282,6 +2282,9 @@ void LLViewerWindow::initWorldUI()
LLPanelStandStopFlying* panel_stand_stop_flying = LLPanelStandStopFlying::getInstance();
panel_ssf_container->addChild(panel_stand_stop_flying);
+ LLPanelHideBeacon* panel_hide_beacon = LLPanelHideBeacon::getInstance();
+ panel_ssf_container->addChild(panel_hide_beacon);
+
panel_ssf_container->setVisible(TRUE);
LLMenuOptionPathfindingRebakeNavmesh::getInstance()->initialize();
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 6a5cd6eabc..87aff6ca98 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1334,7 +1334,8 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
- S32 box_detail = gSavedSettings.getS32("AvatarBoundingBoxComplexity");
+ static LLCachedControl<S32> box_detail_cache(gSavedSettings, "AvatarBoundingBoxComplexity");
+ S32 box_detail = box_detail_cache;
if (getOverallAppearance() != AOA_NORMAL)
{
if (isControlAvatar())
@@ -2539,16 +2540,13 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
{
LL_INFOS() << "Warning! Idle on dead avatar" << LL_ENDL;
return;
- }
+ }
+ static LLCachedControl<bool> disable_all_render_types(gSavedSettings, "DisableAllRenderTypes");
if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR))
- && !(gSavedSettings.getBOOL("DisableAllRenderTypes")) && !isSelf())
+ && !disable_all_render_types && !isSelf())
{
- if (!mIsControlAvatar)
- {
- idleUpdateNameTag( mLastRootPos );
- }
- return;
+ return;
}
// Update should be happening max once per frame.
@@ -2684,7 +2682,8 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
// Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled.
if(isSelf())
{
- if(gAgentCamera.cameraMouselook() || gSavedSettings.getBOOL("VoiceDisableMic"))
+ static LLCachedControl<bool> voice_disable_mic(gSavedSettings, "VoiceDisableMic");
+ if(gAgentCamera.cameraMouselook() || voice_disable_mic)
{
render_visualizer = false;
}
@@ -2821,11 +2820,15 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
++attachment_iter)
{
LLViewerObject* attached_object = attachment_iter->get();
- BOOL visibleAttachment = visible || (attached_object &&
+ BOOL visibleAttachment = visible || (attached_object && attached_object->mDrawable.notNull() &&
!(attached_object->mDrawable->getSpatialBridge() &&
attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0));
- if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid())
+ if (visibleAttachment
+ && attached_object
+ && !attached_object->isDead()
+ && attachment->getValid()
+ && attached_object->mDrawable.notNull())
{
//override rigged attachments' octree spatial extents with this avatar's bounding box
@@ -3181,20 +3184,26 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
}
const F32 time_visible = mTimeVisible.getElapsedTimeF32();
- const F32 NAME_SHOW_TIME = gSavedSettings.getF32("RenderNameShowTime"); // seconds
- const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds
- BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping);
- BOOL render_name = visible_chat ||
- (((sRenderName == RENDER_NAME_ALWAYS) ||
+
+ static LLCachedControl<F32> NAME_SHOW_TIME(gSavedSettings, "RenderNameShowTime"); // seconds
+ static LLCachedControl<F32> FADE_DURATION(gSavedSettings, "RenderNameFadeDuration"); // seconds
+ static LLCachedControl<bool> use_chat_bubbles(gSavedSettings, "UseChatBubbles");
+
+ bool visible_avatar = isVisible() || mNeedsAnimUpdate;
+ bool visible_chat = use_chat_bubbles && (mChats.size() || mTyping);
+ bool render_name = visible_chat ||
+ (visible_avatar &&
+ ((sRenderName == RENDER_NAME_ALWAYS) ||
(sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)));
// If it's your own avatar, don't draw in mouselook, and don't
// draw if we're specifically hiding our own name.
if (isSelf())
{
+ static LLCachedControl<bool> render_name_show_self(gSavedSettings, "RenderNameShowSelf");
+ static LLCachedControl<S32> name_tag_mode(gSavedSettings, "AvatarNameTagMode");
render_name = render_name
&& !gAgentCamera.cameraMouselook()
- && (visible_chat || (gSavedSettings.getBOOL("RenderNameShowSelf")
- && gSavedSettings.getS32("AvatarNameTagMode") ));
+ && (visible_chat || (render_name_show_self && name_tag_mode));
}
if ( !render_name )
@@ -3209,7 +3218,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
return;
}
- BOOL new_name = FALSE;
+ bool new_name = FALSE;
if (visible_chat != mVisibleChat)
{
mVisibleChat = visible_chat;
@@ -3274,7 +3283,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
idleUpdateNameTagAlpha(new_name, alpha);
}
-void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
+void LLVOAvatar::idleUpdateNameTagText(bool new_name)
{
LLNameValue *title = getNVPair("Title");
LLNameValue* firstname = getNVPair("FirstName");
@@ -3584,7 +3593,7 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)
mNameText->setPositionAgent(name_position);
}
-void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha)
+void LLVOAvatar::idleUpdateNameTagAlpha(bool new_name, F32 alpha)
{
llassert(mNameText);
@@ -3727,7 +3736,8 @@ void LLVOAvatar::updateAppearanceMessageDebugText()
{
debug_line += llformat(" - cof: %d req: %d rcv:%d",
curr_cof_version, last_request_cof_version, last_received_cof_version);
- if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure"))
+ static LLCachedControl<bool> debug_force_failure(gSavedSettings, "DebugForceAppearanceRequestFailure");
+ if (debug_force_failure)
{
debug_line += " FORCING ERRS";
}
@@ -5943,7 +5953,8 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
//}
//else
{
- LLUUID sound_id = LLUUID(gSavedSettings.getString("UISndTyping"));
+ static LLCachedControl<std::string> ui_snd_string(gSavedSettings, "UISndTyping");
+ LLUUID sound_id = LLUUID(ui_snd_string);
gAudiop->triggerSound(sound_id, getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_SFX, char_pos_global);
}
}
@@ -6011,7 +6022,7 @@ void LLVOAvatar::resetAnimations()
// animations.
LLUUID LLVOAvatar::remapMotionID(const LLUUID& id)
{
- BOOL use_new_walk_run = gSavedSettings.getBOOL("UseNewWalkRun");
+ static LLCachedControl<bool> use_new_walk_run(gSavedSettings, "UseNewWalkRun");
LLUUID result = id;
// start special case female walk for female avatars
@@ -8232,7 +8243,8 @@ BOOL LLVOAvatar::isFullyLoaded() const
bool LLVOAvatar::isTooComplex() const
{
bool too_complex;
- bool render_friend = (LLAvatarTracker::instance().isBuddy(getID()) && gSavedSettings.getBOOL("AlwaysRenderFriends"));
+ static LLCachedControl<bool> always_render_friends(gSavedSettings, "AlwaysRenderFriends");
+ bool render_friend = (LLAvatarTracker::instance().isBuddy(getID()) && always_render_friends);
if (isSelf() || render_friend || mVisuallyMuteSetting == AV_ALWAYS_RENDER)
{
@@ -9089,7 +9101,8 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe
// Parse visual params, if any.
S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
- bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing
+ static LLCachedControl<bool> block_some_avatars(gSavedSettings, "BlockSomeAvatarAppearanceVisualParams");
+ bool drop_visual_params_debug = block_some_avatars && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing
if( num_blocks > 1 && !drop_visual_params_debug)
{
//LL_DEBUGS("Avatar") << avString() << " handle visual params, num_blocks " << num_blocks << LL_ENDL;
@@ -9194,10 +9207,12 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32
void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
{
LL_DEBUGS("Avatar") << "starts" << LL_ENDL;
-
- bool enable_verbose_dumps = gSavedSettings.getBOOL("DebugAvatarAppearanceMessage");
+
+ static LLCachedControl<bool> enable_verbose_dumps(gSavedSettings, "DebugAvatarAppearanceMessage");
+ static LLCachedControl<bool> block_avatar_appearance_messages(gSavedSettings, "BlockAvatarAppearanceMessages");
+
std::string dump_prefix = getFullname() + "_" + (isSelf()?"s":"o") + "_";
- if (gSavedSettings.getBOOL("BlockAvatarAppearanceMessages"))
+ if (block_avatar_appearance_messages)
{
LL_WARNS() << "Blocking AvatarAppearance message" << LL_ENDL;
return;
@@ -10648,12 +10663,12 @@ void LLVOAvatar::accountRenderComplexityForObject(
F32 attachment_volume_cost = 0;
F32 attachment_texture_cost = 0;
F32 attachment_children_cost = 0;
- const F32 animated_object_attachment_surcharge = 1000;
+ const F32 animated_object_attachment_surcharge = 1000;
- if (attached_object->isAnimatedObject())
- {
- attachment_volume_cost += animated_object_attachment_surcharge;
- }
+ if (attached_object->isAnimatedObject())
+ {
+ attachment_volume_cost += animated_object_attachment_surcharge;
+ }
attachment_volume_cost += volume->getRenderCost(textures);
const_child_list_t children = volume->getChildren();
@@ -10901,13 +10916,13 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
mVisualComplexity = cost;
mVisualComplexityStale = false;
- if (isSelf())
+ static LLCachedControl<U32> show_my_complexity_changes(gSavedSettings, "ShowMyComplexityChanges", 20);
+
+ if (isSelf() && show_my_complexity_changes)
{
// Avatar complexity
LLAvatarRenderNotifier::getInstance()->updateNotificationAgent(mVisualComplexity);
-
LLAvatarRenderNotifier::getInstance()->setObjectComplexityList(object_complexity_list);
-
// HUD complexity
LLHUDRenderNotifier::getInstance()->updateNotificationHUD(hud_complexity_list);
}
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index acebbc1074..8a47895cf7 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -282,9 +282,9 @@ public:
void idleUpdateLoadingEffect();
void idleUpdateWindEffect();
void idleUpdateNameTag(const LLVector3& root_pos_last);
- void idleUpdateNameTagText(BOOL new_name);
+ void idleUpdateNameTagText(bool new_name);
void idleUpdateNameTagPosition(const LLVector3& root_pos_last);
- void idleUpdateNameTagAlpha(BOOL new_name, F32 alpha);
+ void idleUpdateNameTagAlpha(bool new_name, F32 alpha);
LLColor4 getNameTagColor(bool is_friend);
void clearNameTag();
static void invalidateNameTag(const LLUUID& agent_id);
@@ -939,7 +939,7 @@ public:
void startTyping() { mTyping = TRUE; mTypingTimer.reset(); }
void stopTyping() { mTyping = FALSE; }
private:
- BOOL mVisibleChat;
+ bool mVisibleChat;
//--------------------------------------------------------------------
// Lip synch morphs
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 1625dd5276..126a25115d 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -71,6 +71,8 @@
#include "llmediaentry.h"
#include "llmediadataclient.h"
#include "llmeshrepository.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
#include "llagent.h"
#include "llviewermediafocus.h"
#include "lldatapacker.h"
@@ -2993,6 +2995,17 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
}
}
break;
+
+ case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD:
+ {
+ // Media might be blocked, waiting for a file,
+ // send an empty response to unblock it
+ const std::vector<std::string> empty_response;
+ plugin->sendPickFileResponse(empty_response);
+
+ LLNotificationsUtil::add("MediaFileDownloadUnsupported");
+ }
+ break;
default:
break;
@@ -5467,6 +5480,7 @@ static inline void add_face(T*** list, U32* count, T* face)
{
if (count[1] < MAX_FACE_COUNT)
{
+ face->setDrawOrderIndex(count[1]);
list[1][count[1]++] = face;
}
}
@@ -5474,6 +5488,7 @@ static inline void add_face(T*** list, U32* count, T* face)
{
if (count[0] < MAX_FACE_COUNT)
{
+ face->setDrawOrderIndex(count[0]);
list[0][count[0]++] = face;
}
}
@@ -5689,6 +5704,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
pool->removeFace(facep);
}
facep->clearState(LLFace::RIGGED);
+ facep->mAvatar = NULL;
+ facep->mSkinInfo = NULL;
}
}
@@ -5926,7 +5943,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
// for rigged set, add weights and disable alpha sorting (rigged items use depth buffer)
extra_mask |= LLVertexBuffer::MAP_WEIGHT4;
- alpha_sort = FALSE;
rigged = TRUE;
}
@@ -6086,7 +6102,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
}
}
-struct CompareBatchBreakerModified
+struct CompareBatchBreaker
{
bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
{
@@ -6101,18 +6117,23 @@ struct CompareBatchBreakerModified
{
return lte->getFullbright() < rte->getFullbright();
}
- else if (LLPipeline::sRenderDeferred && lte->getMaterialParams() != rte->getMaterialParams())
- {
- return lte->getMaterialParams() < rte->getMaterialParams();
- }
- else if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny()))
+ else if (LLPipeline::sRenderDeferred && lte->getMaterialID() != rte->getMaterialID())
+ {
+ return lte->getMaterialID() < rte->getMaterialID();
+ }
+ else if (lte->getShiny() != rte->getShiny())
{
return lte->getShiny() < rte->getShiny();
}
- else
+ else if (lhs->getTexture() != rhs->getTexture())
{
return lhs->getTexture() < rhs->getTexture();
}
+ else
+ {
+ // all else being equal, maintain consistent draw order
+ return lhs->getDrawOrderIndex() < rhs->getDrawOrderIndex();
+ }
}
};
@@ -6120,9 +6141,6 @@ struct CompareBatchBreakerRigged
{
bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
{
- const LLTextureEntry* lte = lhs->getTextureEntry();
- const LLTextureEntry* rte = rhs->getTextureEntry();
-
if (lhs->mAvatar != rhs->mAvatar)
{
return lhs->mAvatar < rhs->mAvatar;
@@ -6131,23 +6149,12 @@ struct CompareBatchBreakerRigged
{
return lhs->mSkinInfo->mHash < rhs->mSkinInfo->mHash;
}
- else if (lhs->getTexture() != rhs->getTexture())
- {
- return lhs->getTexture() < rhs->getTexture();
- }
- else if (lte->getBumpmap() != rte->getBumpmap())
- {
- return lte->getBumpmap() < rte->getBumpmap();
- }
- else if (LLPipeline::sRenderDeferred && lte->getMaterialID() != rte->getMaterialID())
- {
- return lte->getMaterialID() < rte->getMaterialID();
- }
- else // if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny()))
+ else
{
- return lte->getShiny() < rte->getShiny();
+ // "inherit" non-rigged behavior
+ CompareBatchBreaker comp;
+ return comp(lhs, rhs);
}
-
}
};
@@ -6190,13 +6197,16 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
if (rigged)
{
- //sort faces by things that break batches, including avatar and mesh id
- std::sort(faces, faces + face_count, CompareBatchBreakerRigged());
+ if (!distance_sort) // <--- alpha "sort" rigged faces by maintaining original draw order
+ {
+ //sort faces by things that break batches, including avatar and mesh id
+ std::sort(faces, faces + face_count, CompareBatchBreakerRigged());
+ }
}
else if (!distance_sort)
{
//sort faces by things that break batches, not including avatar and mesh id
- std::sort(faces, faces + face_count, CompareBatchBreakerModified());
+ std::sort(faces, faces + face_count, CompareBatchBreaker());
}
else
{
@@ -6226,11 +6236,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels;
}
- if (rigged)
- { //don't attempt distance sorting on rigged meshes, not likely to succeed and breaks batches
- distance_sort = FALSE;
- }
-
if (distance_sort)
{
buffer_index = -1;
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index b8f1ec35f6..c4d873dd22 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -199,19 +199,16 @@ std::string LLWeb::expandURLSubstitutions(const std::string &url,
// find the grid
std::string current_grid = LLGridManager::getInstance()->getGridId();
std::transform(current_grid.begin(), current_grid.end(), current_grid.begin(), ::tolower);
- if (current_grid == "agni")
+ if (current_grid == "damballah")
{
- substitution["GRID"] = "secondlife.com";
- }
- else if (current_grid == "damballah")
- {
- // Staging grid has its own naming scheme.
- substitution["GRID"] = "secondlife-staging.com";
- }
- else
- {
- substitution["GRID"] = llformat("%s.lindenlab.com", current_grid.c_str());
- }
+ // Staging grid has its own naming scheme.
+ substitution["GRID"] = "secondlife-staging.com";
+ }
+ else
+ {
+ substitution["GRID"] = "secondlife.com";
+ }
+
// expand all of the substitution strings and escape the url
std::string expanded_url = url;
LLStringUtil::format(expanded_url, substitution);
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 0a2ad82354..d79a25c1ad 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -114,7 +114,7 @@ LLWorld::LLWorld() :
}
-void LLWorld::destroyClass()
+void LLWorld::resetClass()
{
mHoleWaterObjects.clear();
gObjectList.destroy();
@@ -136,7 +136,6 @@ void LLWorld::destroyClass()
LLDrawable::incrementVisible();
LLSceneMonitor::deleteSingleton();
- LLWorld::deleteSingleton();
}
@@ -1201,6 +1200,16 @@ public:
return;
}
+ if (gDisconnected)
+ {
+ return;
+ }
+
+ if (!LLWorld::instanceExists())
+ {
+ return;
+ }
+
if (!input["body"].has("agent-id") ||
!input["body"].has("sim-ip-and-port") ||
!input["body"].has("seed-capability"))
@@ -1209,8 +1218,13 @@ public:
return;
}
- LLHost sim(input["body"]["sim-ip-and-port"].asString());
-
+ LLHost sim(input["body"]["sim-ip-and-port"].asString());
+ if (sim.isInvalid())
+ {
+ LL_WARNS() << "Got EstablishAgentCommunication with invalid host" << LL_ENDL;
+ return;
+ }
+
LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(sim);
if (!regionp)
{
@@ -1219,7 +1233,7 @@ public:
return;
}
LL_DEBUGS("CrossingCaps") << "Calling setSeedCapability from LLEstablishAgentCommunication::post. Seed cap == "
- << input["body"]["seed-capability"] << LL_ENDL;
+ << input["body"]["seed-capability"] << " for region " << regionp->getRegionID() << LL_ENDL;
regionp->setSeedCapability(input["body"]["seed-capability"]);
}
};
diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h
index 1c12ad0e2c..68db2b8ccf 100644
--- a/indra/newview/llworld.h
+++ b/indra/newview/llworld.h
@@ -65,7 +65,9 @@ class LLWorld : public LLSimpleton<LLWorld>
public:
LLWorld();
- void destroyClass();
+ // Clear any objects, regions
+ // Prepares class to be reused or destroyed
+ void resetClass();
LLViewerRegion* addRegion(const U64 &region_handle, const LLHost &host);
// safe to call if already present, does the "right thing" if
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index a3c971153c..545fe9642a 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -363,10 +363,12 @@ static LLCullResult* sCull = NULL;
void validate_framebuffer_object();
-
-bool addDeferredAttachments(LLRenderTarget& target)
+// Add color attachments for deferred rendering
+// target -- RenderTarget to add attachments to
+// for_impostor -- whether or not these render targets are for an impostor (if true, avoids implicit sRGB conversions)
+bool addDeferredAttachments(LLRenderTarget& target, bool for_impostor = false)
{
- return target.addColorAttachment(GL_SRGB8_ALPHA8) && //specular
+ return target.addColorAttachment(for_impostor ? GL_RGBA : GL_SRGB8_ALPHA8) && //specular
target.addColorAttachment(GL_RGB10_A2); //normal+z
}
@@ -10818,7 +10820,7 @@ void LLPipeline::renderRiggedGroups(LLRenderPass* pass, U32 type, U32 mask, bool
static LLTrace::BlockTimerStatHandle FTM_GENERATE_IMPOSTOR("Generate Impostor");
-void LLPipeline::generateImpostor(LLVOAvatar* avatar)
+void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
{
LL_RECORD_BLOCK_TIME(FTM_GENERATE_IMPOSTOR);
LLGLState::checkStates();
@@ -10837,11 +10839,12 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
assertInitialized();
- bool visually_muted = avatar->isVisuallyMuted();
+ // previews can't be muted or impostered
+ bool visually_muted = !preview_avatar && avatar->isVisuallyMuted();
LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID()
<< " is " << ( visually_muted ? "" : "not ") << "visually muted"
<< LL_ENDL;
- bool too_complex = avatar->isTooComplex();
+ bool too_complex = !preview_avatar && avatar->isTooComplex();
LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID()
<< " is " << ( too_complex ? "" : "not ") << "too complex"
<< LL_ENDL;
@@ -10915,6 +10918,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
U32 resY = 0;
U32 resX = 0;
+ if (!preview_avatar)
{
const LLVector4a* ext = avatar->mDrawable->getSpatialExtents();
LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset());
@@ -10972,14 +10976,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
if (!avatar->mImpostor.isComplete())
{
+ avatar->mImpostor.allocate(resX, resY, GL_RGBA, TRUE, FALSE);
+
if (LLPipeline::sRenderDeferred)
{
- avatar->mImpostor.allocate(resX,resY,GL_SRGB8_ALPHA8,TRUE,FALSE);
- addDeferredAttachments(avatar->mImpostor);
- }
- else
- {
- avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,FALSE);
+ addDeferredAttachments(avatar->mImpostor, true);
}
gGL.getTexUnit(0)->bind(&avatar->mImpostor);
@@ -11001,7 +11002,20 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
LLDrawPoolAvatar::sMinimumAlpha = 0.f;
}
- if (LLPipeline::sRenderDeferred)
+ if (preview_avatar)
+ {
+ // previews don't care about imposters
+ if (LLPipeline::sRenderDeferred)
+ {
+ renderGeomDeferred(camera);
+ renderGeomPostDeferred(camera);
+ }
+ else
+ {
+ renderGeom(camera);
+ }
+ }
+ else if (LLPipeline::sRenderDeferred)
{
avatar->mImpostor.clear();
renderGeomDeferred(camera);
@@ -11089,7 +11103,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " MUTED set solid color " << muted_color << LL_ENDL;
gGL.diffuseColor4fv( muted_color.mV );
}
- else
+ else if (!preview_avatar)
{ //grey muted avatar
LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " MUTED set grey" << LL_ENDL;
gGL.diffuseColor4fv(LLColor4::pink.mV );
@@ -11110,9 +11124,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
gGL.popMatrix();
}
- avatar->mImpostor.flush();
-
- avatar->setImpostorDim(tdim);
+ if (!preview_avatar)
+ {
+ avatar->mImpostor.flush();
+ avatar->setImpostorDim(tdim);
+ }
sUseOcclusion = occlusion;
sReflectionRender = false;
@@ -11125,176 +11141,18 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
gGL.matrixMode(LLRender::MM_MODELVIEW);
gGL.popMatrix();
- avatar->mNeedsImpostorUpdate = FALSE;
- avatar->cacheImpostorValues();
- avatar->mLastImpostorUpdateFrameTime = gFrameTimeSeconds;
+ if (!preview_avatar)
+ {
+ avatar->mNeedsImpostorUpdate = FALSE;
+ avatar->cacheImpostorValues();
+ avatar->mLastImpostorUpdateFrameTime = gFrameTimeSeconds;
+ }
LLVertexBuffer::unbind();
LLGLState::checkStates();
LLGLState::checkTextureChannels();
}
-static LLTrace::BlockTimerStatHandle FTM_PREVIEW_AVATAR("Preview Avatar");
-
-void LLPipeline::previewAvatar(LLVOAvatar* avatar)
-{
- LL_RECORD_BLOCK_TIME(FTM_PREVIEW_AVATAR);
-
- LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE);
- gGL.flush();
- gGL.setSceneBlendType(LLRender::BT_REPLACE);
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
-
- static LLCullResult result;
- result.clear();
- grabReferences(result);
-
- if (!avatar || !avatar->mDrawable)
- {
- LL_WARNS_ONCE("AvatarRenderPipeline") << "Avatar is " << (avatar ? "not drawable" : "null") << LL_ENDL;
- return;
- }
- LL_DEBUGS_ONCE("AvatarRenderPipeline") << "Avatar " << avatar->getID() << " is drawable" << LL_ENDL;
-
- assertInitialized();
-
- pushRenderTypeMask();
-
- {
- //hide world geometry
- clearRenderTypeMask(
- RENDER_TYPE_SKY,
- RENDER_TYPE_WL_SKY,
- RENDER_TYPE_GROUND,
- RENDER_TYPE_TERRAIN,
- RENDER_TYPE_GRASS,
- RENDER_TYPE_CONTROL_AV, // Animesh
- RENDER_TYPE_TREE,
- RENDER_TYPE_VOIDWATER,
- RENDER_TYPE_WATER,
- RENDER_TYPE_PASS_GRASS,
- RENDER_TYPE_HUD,
- RENDER_TYPE_PARTICLES,
- RENDER_TYPE_CLOUDS,
- RENDER_TYPE_HUD_PARTICLES,
- END_RENDER_TYPES
- );
- }
-
- S32 occlusion = sUseOcclusion;
- sUseOcclusion = 0;
-
- sReflectionRender = !sRenderDeferred;
-
- sShadowRender = true;
- sImpostorRender = true; // Likely not needed for previews
-
- LLViewerCamera* viewer_camera = LLViewerCamera::getInstance();
-
- {
- markVisible(avatar->mDrawable, *viewer_camera);
-
- LLVOAvatar::attachment_map_t::iterator iter;
- for (iter = avatar->mAttachmentPoints.begin();
- iter != avatar->mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment *attachment = iter->second;
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- if (LLViewerObject* attached_object = attachment_iter->get())
- {
- markVisible(attached_object->mDrawable->getSpatialBridge(), *viewer_camera);
- }
- }
- }
- }
-
- stateSort(*LLViewerCamera::getInstance(), result);
-
- LLCamera camera = *viewer_camera;
-
- F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha;
-
- if (LLPipeline::sRenderDeferred)
- {
- renderGeomDeferred(camera);
-
- renderGeomPostDeferred(camera);
- }
- else
- {
- renderGeom(camera);
- }
-
- LLDrawPoolAvatar::sMinimumAlpha = old_alpha;
-
- { //create alpha mask based on depth buffer
- if (LLPipeline::sRenderDeferred)
- {
- GLuint buff = GL_COLOR_ATTACHMENT0;
- LL_PROFILER_GPU_ZONEC("gl.DrawBuffersARB", 0x8000FF);
- glDrawBuffersARB(1, &buff);
- }
-
- LLGLDisable blend(GL_BLEND);
-
- gGL.setColorMask(false, true);
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER);
-
- gGL.flush();
-
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
-
- static const F32 clip_plane = 0.99999f;
-
- gDebugProgram.bind();
-
- gGL.begin(LLRender::QUADS);
- gGL.vertex3f(-1, -1, clip_plane);
- gGL.vertex3f(1, -1, clip_plane);
- gGL.vertex3f(1, 1, clip_plane);
- gGL.vertex3f(-1, 1, clip_plane);
- gGL.end();
- gGL.flush();
-
- gDebugProgram.unbind();
-
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
- }
-
- sUseOcclusion = occlusion;
- sReflectionRender = false;
- sImpostorRender = false;
- sShadowRender = false;
- popRenderTypeMask();
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
-
- LLVertexBuffer::unbind();
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
-
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- gGL.flush();
-}
-
bool LLPipeline::hasRenderBatches(const U32 type) const
{
return sCull->getRenderMapSize(type) > 0;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 4946bac701..bdd498abff 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -134,8 +134,7 @@ public:
void allocatePhysicsBuffer();
void resetVertexBuffers(LLDrawable* drawable);
- void generateImpostor(LLVOAvatar* avatar);
- void previewAvatar(LLVOAvatar* avatar);
+ void generateImpostor(LLVOAvatar* avatar, bool preview_avatar = false);
void bindScreenToTexture();
void renderFinalize();
diff --git a/indra/newview/skins/default/xui/en/control_table_contents_media.xml b/indra/newview/skins/default/xui/en/control_table_contents_media.xml
index ce5d3556b6..43e8d730cd 100644
--- a/indra/newview/skins/default/xui/en/control_table_contents_media.xml
+++ b/indra/newview/skins/default/xui/en/control_table_contents_media.xml
@@ -73,4 +73,14 @@
name="lst_action"
value="Start Gesture" />
</rows>
+ <rows
+ name="script_trigger_lbutton"
+ value="script_trigger_lbutton">
+ <columns
+ column="lst_action"
+ font="SansSerif"
+ halign="left"
+ name="lst_action"
+ value="Interact (Script LMB)" />
+ </rows>
</contents>
diff --git a/indra/newview/skins/default/xui/en/floater_associate_listing.xml b/indra/newview/skins/default/xui/en/floater_associate_listing.xml
index e019ed58dd..0f7ed24103 100644
--- a/indra/newview/skins/default/xui/en/floater_associate_listing.xml
+++ b/indra/newview/skins/default/xui/en/floater_associate_listing.xml
@@ -20,9 +20,10 @@
name="message">
Listing ID:
</text>
+ <!--listing_id is a positive S32-->
<line_editor
type="string"
- length="1"
+ max_length_bytes="10"
follows="top|right"
font="SansSerif"
height="20"
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index ca3e40465c..e499ddbc2f 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -34,7 +34,7 @@
<string name="mesh_status_missing_lod">Missing required level of detail.</string>
<string name="mesh_status_invalid_material_list">LOD materials are not a subset of reference model.</string>
<string name="phys_status_vertex_limit_exceeded">Some physical hulls exceed vertex limitations.</string>
- <string name="phys_status_degenerate_triangles">The physics mesh too dense remove the small thin triangles (see preview)</string>
+ <string name="phys_status_degenerate_triangles">The physics mesh is too dense or contains degenerate triangles. Use Analyze/Simplify to resolve.</string>
<string name="layer_all">All</string> <!-- Text to display in physics layer combo box for "all layers" -->
<string name="decomposing">Analyzing...</string>
<string name="simplifying">Simplifying...</string>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 1b9df53ad2..ed6683ce2a 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2344,6 +2344,7 @@ Please try again later.
<notification
icon="notifytip.tga"
name="LandmarkCreated"
+ log_to_chat="false"
type="notifytip">
You have added "[LANDMARK_NAME]" to your [FOLDER_NAME] folder.
</notification>
diff --git a/indra/newview/skins/default/xui/en/panel_hide_beacon.xml b/indra/newview/skins/default/xui/en/panel_hide_beacon.xml
new file mode 100644
index 0000000000..7cab285f77
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_hide_beacon.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ height="25"
+ layout="topleft"
+ name="panel_hide_beacon"
+ mouse_opaque="false"
+ visible="true"
+ width="133">
+ <button
+ follows="left|bottom"
+ height="19"
+ label="Hide beacon"
+ layout="topleft"
+ left="10"
+ name="hide_beacon_btn"
+ tool_tip="Stop tracking and hide beacon"
+ top="2"
+ visible="false"
+ width="113" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index 2ea20570b1..42a34d171a 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -28,7 +28,7 @@
height="15"
increment="0.025"
initial_value="0.5"
- label="Master volume"
+ label="All volume"
label_width="120"
layout="topleft"
left="0"
@@ -386,7 +386,7 @@
left="25"
name="voice_chat_settings"
width="200"
- top_pad="7">
+ top_pad="16">
Voice Chat Settings
</text>
<text
diff --git a/indra/newview/skins/default/xui/en/panel_toolbar_view.xml b/indra/newview/skins/default/xui/en/panel_toolbar_view.xml
index f5c559fe1d..a3348f28c7 100644
--- a/indra/newview/skins/default/xui/en/panel_toolbar_view.xml
+++ b/indra/newview/skins/default/xui/en/panel_toolbar_view.xml
@@ -95,7 +95,7 @@
tab_stop="false"
name="state_management_buttons_container"
visible="false"
- width="200"/>
+ width="350"/>
</layout_panel>
<layout_panel name="right_toolbar_panel"
auto_resize="false"
diff --git a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
index 2034409111..b4eb1ade94 100644
--- a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
+++ b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml
@@ -19,7 +19,7 @@
height="15"
increment="0.025"
initial_value="0.5"
- label="Master"
+ label="All"
label_width="60"
left="10"
width="160"