summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/settings.xml22
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl37
-rw-r--r--indra/newview/groupchatlistener.cpp84
-rw-r--r--indra/newview/groupchatlistener.h15
-rw-r--r--indra/newview/llagentlistener.cpp387
-rw-r--r--indra/newview/llagentlistener.h16
-rw-r--r--indra/newview/llappearancelistener.cpp158
-rw-r--r--indra/newview/llappearancelistener.h46
-rw-r--r--indra/newview/llappearancemgr.cpp8
-rw-r--r--indra/newview/llappearancemgr.h1
-rw-r--r--indra/newview/llappviewer.cpp3
-rw-r--r--indra/newview/llappviewerwin32.cpp60
-rw-r--r--indra/newview/lldrawpoolavatar.cpp2
-rw-r--r--indra/newview/lldrawpoolterrain.h1
-rw-r--r--indra/newview/llenvironment.cpp1
-rw-r--r--indra/newview/llfloatereditextdaycycle.cpp2
-rw-r--r--indra/newview/llfloaterenvironmentadjust.cpp29
-rw-r--r--indra/newview/llfloaterimnearbychat.cpp3
-rw-r--r--indra/newview/llfloaterimnearbychatlistener.cpp34
-rw-r--r--indra/newview/llfloaterimnearbychatlistener.h6
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp42
-rw-r--r--indra/newview/llfloaterimsessiontab.h5
-rw-r--r--indra/newview/llfloatersnapshot.cpp44
-rw-r--r--indra/newview/llfloatersnapshot.h3
-rwxr-xr-xindra/newview/llfloaterworldmap.cpp7
-rw-r--r--indra/newview/llgroupactions.cpp2
-rw-r--r--indra/newview/llimprocessing.cpp49
-rw-r--r--indra/newview/llimprocessing.h1
-rw-r--r--indra/newview/llimview.cpp13
-rw-r--r--indra/newview/llimview.h4
-rw-r--r--indra/newview/llinventorybridge.cpp267
-rw-r--r--indra/newview/llinventorybridge.h1
-rw-r--r--indra/newview/llinventoryfunctions.cpp39
-rw-r--r--indra/newview/llinventoryfunctions.h30
-rw-r--r--indra/newview/llinventorygallery.cpp116
-rw-r--r--indra/newview/llinventorygallerymenu.cpp25
-rw-r--r--indra/newview/llinventorymodel.cpp5
-rw-r--r--indra/newview/lllocalbitmaps.cpp20
-rw-r--r--indra/newview/lllocalbitmaps.h1
-rw-r--r--indra/newview/llmeshrepository.cpp29
-rw-r--r--indra/newview/llmeshrepository.h3
-rw-r--r--indra/newview/llmodelpreview.cpp36
-rw-r--r--indra/newview/lloutfitslist.cpp48
-rw-r--r--indra/newview/llpanelface.cpp4
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp2
-rw-r--r--indra/newview/llpanelprofileclassifieds.h16
-rw-r--r--indra/newview/llpanelsnapshot.cpp12
-rw-r--r--indra/newview/llpanelsnapshotinventory.cpp128
-rw-r--r--indra/newview/llpanelsnapshotlocal.cpp20
-rw-r--r--indra/newview/llpanelsnapshotoptions.cpp37
-rw-r--r--indra/newview/llpanelsnapshotpostcard.cpp20
-rw-r--r--indra/newview/llpanelsnapshotprofile.cpp18
-rw-r--r--indra/newview/llpanelvolume.cpp44
-rw-r--r--indra/newview/llphysicsmotion.cpp21
-rw-r--r--indra/newview/llpreviewscript.cpp5
-rw-r--r--indra/newview/llpreviewscript.h5
-rw-r--r--indra/newview/llselectmgr.cpp27
-rw-r--r--indra/newview/llselectmgr.h2
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp2
-rw-r--r--indra/newview/llstatusbar.cpp4
-rw-r--r--indra/newview/llstatusbar.h2
-rw-r--r--indra/newview/llsurfacepatch.cpp9
-rw-r--r--indra/newview/llsurfacepatch.h2
-rw-r--r--indra/newview/llterrainpaintmap.cpp3
-rw-r--r--indra/newview/lltexturecache.cpp44
-rw-r--r--indra/newview/llvieweraudio.cpp4
-rw-r--r--indra/newview/llviewerdisplay.cpp6
-rw-r--r--indra/newview/llviewermenufile.cpp2
-rw-r--r--indra/newview/llviewermessage.cpp34
-rw-r--r--indra/newview/llviewerobject.cpp6
-rw-r--r--indra/newview/llviewerparcelmgr.cpp36
-rw-r--r--indra/newview/llviewerparcelmgr.h6
-rw-r--r--indra/newview/llviewertexturelist.cpp9
-rw-r--r--indra/newview/llviewerwindow.cpp21
-rw-r--r--indra/newview/llviewerwindow.h10
-rw-r--r--indra/newview/llviewerwindowlistener.cpp2
-rw-r--r--indra/newview/llvoavatar.cpp10
-rw-r--r--indra/newview/llvosurfacepatch.cpp51
-rw-r--r--indra/newview/llvosurfacepatch.h4
-rw-r--r--indra/newview/llwearableitemslist.cpp10
-rw-r--r--indra/newview/llwearableitemslist.h9
-rw-r--r--indra/newview/llworld.cpp4
-rw-r--r--indra/newview/pipeline.cpp10
-rw-r--r--indra/newview/skins/default/xui/da/floater_about.xml2
-rw-r--r--indra/newview/skins/default/xui/da/strings.xml4
-rw-r--r--indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/de/panel_snapshot_options.xml2
-rw-r--r--indra/newview/skins/default/xui/de/strings.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_snapshot.xml14
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml8
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_settings_water.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_snapshot_options.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_tools_texture.xml24
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml50
-rw-r--r--indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml1
-rw-r--r--indra/newview/skins/default/xui/en/widgets/xy_vector.xml4
-rw-r--r--indra/newview/skins/default/xui/es/panel_snapshot_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/es/panel_snapshot_options.xml2
-rw-r--r--indra/newview/skins/default/xui/es/strings.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/panel_snapshot_options.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/strings.xml6
-rw-r--r--indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/it/panel_snapshot_options.xml2
-rw-r--r--indra/newview/skins/default/xui/it/strings.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/panel_settings_water.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/panel_snapshot_options.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/strings.xml6
-rw-r--r--indra/newview/skins/default/xui/pl/panel_snapshot_options.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/strings.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/panel_snapshot_options.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/strings.xml6
-rw-r--r--indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/ru/panel_snapshot_options.xml2
-rw-r--r--indra/newview/skins/default/xui/ru/strings.xml6
-rw-r--r--indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/tr/panel_snapshot_options.xml2
-rw-r--r--indra/newview/skins/default/xui/tr/strings.xml6
-rw-r--r--indra/newview/skins/default/xui/zh/panel_snapshot_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/zh/panel_snapshot_options.xml2
-rw-r--r--indra/newview/skins/default/xui/zh/strings.xml6
127 files changed, 1907 insertions, 686 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 8d7f37142f..0f81c2b8ef 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -103,6 +103,7 @@ set(viewer_SOURCE_FILES
llagentwearables.cpp
llanimstatelabels.cpp
llappcorehttp.cpp
+ llappearancelistener.cpp
llappearancemgr.cpp
llappviewer.cpp
llappviewerlistener.cpp
@@ -778,6 +779,7 @@ set(viewer_HEADER_FILES
llanimstatelabels.h
llappcorehttp.h
llappearance.h
+ llappearancelistener.h
llappearancemgr.h
llappviewer.h
llappviewerlistener.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index f8487c020e..561957477e 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -368,6 +368,17 @@
<key>Value</key>
<real>0.5</real>
</map>
+ <key>AudioLevelWind</key>
+ <map>
+ <key>Comment</key>
+ <string>Audio level of wind noise when standing still</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
+ </map>
<key>AudioStreamingMedia</key>
<map>
<key>Comment</key>
@@ -9628,6 +9639,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>RenderBalanceInSnapshot</key>
+ <map>
+ <key>Comment</key>
+ <string>Display L$ balance in snapshot</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>RenderUIBuffer</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl
index a63b8d7c2b..774ccb6baf 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl
@@ -117,27 +117,34 @@ uniform float exposure;
uniform float tonemap_mix;
uniform int tonemap_type;
+
vec3 toneMap(vec3 color)
{
#ifndef NO_POST
- float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
-
- color *= exposure * exp_scale;
+ vec3 linear_input_color = color;
- vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0));
+ float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
+ float final_exposure = exposure * exp_scale;
+ vec3 exposed_color = color * final_exposure;
+ vec3 tonemapped_color = exposed_color;
switch(tonemap_type)
{
case 0:
- color = PBRNeutralToneMapping(color);
+ tonemapped_color = PBRNeutralToneMapping(exposed_color);
break;
case 1:
- color = toneMapACES_Hill(color);
+ tonemapped_color = toneMapACES_Hill(exposed_color);
break;
}
- // mix tonemapped and linear here to provide adjustment
- color = mix(clamped_color, color, tonemap_mix);
+ vec3 exposed_linear_input = linear_input_color * final_exposure;
+ color = mix(exposed_linear_input, tonemapped_color, tonemap_mix);
+
+ color = clamp(color, 0.0, 1.0);
+#else
+ color *= exposure * texture(exposureMap, vec2(0.5,0.5)).r;
+ color = clamp(color, 0.0, 1.0);
#endif
return color;
@@ -147,20 +154,24 @@ vec3 toneMap(vec3 color)
vec3 toneMapNoExposure(vec3 color)
{
#ifndef NO_POST
- vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0));
+ vec3 linear_input_color = color;
+ vec3 tonemapped_color = color;
switch(tonemap_type)
{
case 0:
- color = PBRNeutralToneMapping(color);
+ tonemapped_color = PBRNeutralToneMapping(color);
break;
case 1:
- color = toneMapACES_Hill(color);
+ tonemapped_color = toneMapACES_Hill(color);
break;
}
- // mix tonemapped and linear here to provide adjustment
- color = mix(clamped_color, color, tonemap_mix);
+ color = mix(linear_input_color, tonemapped_color, tonemap_mix);
+
+ color = clamp(color, 0.0, 1.0);
+#else
+ color = clamp(color, 0.0, 1.0);
#endif
return color;
diff --git a/indra/newview/groupchatlistener.cpp b/indra/newview/groupchatlistener.cpp
index 43507f13e9..ed9e34d1bf 100644
--- a/indra/newview/groupchatlistener.cpp
+++ b/indra/newview/groupchatlistener.cpp
@@ -2,11 +2,11 @@
* @file groupchatlistener.cpp
* @author Nat Goodspeed
* @date 2011-04-11
- * @brief Implementation for groupchatlistener.
+ * @brief Implementation for LLGroupChatListener.
*
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
+ * Copyright (C) 2024, 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
@@ -34,43 +34,69 @@
// std headers
// external library headers
// other Linden headers
+#include "llchat.h"
#include "llgroupactions.h"
#include "llimview.h"
+LLGroupChatListener::LLGroupChatListener():
+ LLEventAPI("GroupChat",
+ "API to enter, leave, send and intercept group chat messages")
+{
+ add("startGroupChat",
+ "Enter a group chat in group with UUID [\"group_id\"]\n"
+ "Assumes the logged-in agent is already a member of this group.",
+ &LLGroupChatListener::startGroupChat,
+ llsd::map("group_id", LLSD()));
+ add("leaveGroupChat",
+ "Leave a group chat in group with UUID [\"group_id\"]\n"
+ "Assumes a prior successful startIM request.",
+ &LLGroupChatListener::leaveGroupChat,
+ llsd::map("group_id", LLSD()));
+ add("sendGroupIM",
+ "send a [\"message\"] to group with UUID [\"group_id\"]",
+ &LLGroupChatListener::sendGroupIM,
+ llsd::map("message", LLSD(), "group_id", LLSD()));
+}
-namespace {
- void startIm_wrapper(LLSD const & event)
+bool is_in_group(LLEventAPI::Response &response, const LLSD &data)
+{
+ if (!LLGroupActions::isInGroup(data["group_id"]))
{
- LLUUID session_id = LLGroupActions::startIM(event["id"].asUUID());
- sendReply(LLSDMap("session_id", LLSD(session_id)), event);
+ response.error(stringize("You are not the member of the group:", std::quoted(data["group_id"].asString())));
+ return false;
}
+ return true;
+}
- void send_message_wrapper(const std::string& text, const LLUUID& session_id, const LLUUID& group_id)
+void LLGroupChatListener::startGroupChat(LLSD const &data)
+{
+ Response response(LLSD(), data);
+ if (!is_in_group(response, data))
+ {
+ return;
+ }
+ if (LLGroupActions::startIM(data["group_id"]).isNull())
{
- LLIMModel::sendMessage(text, session_id, group_id, IM_SESSION_GROUP_START);
+ return response.error(stringize("Failed to start group chat session ", std::quoted(data["group_id"].asString())));
}
}
+void LLGroupChatListener::leaveGroupChat(LLSD const &data)
+{
+ Response response(LLSD(), data);
+ if (is_in_group(response, data))
+ {
+ LLGroupActions::endIM(data["group_id"].asUUID());
+ }
+}
-GroupChatListener::GroupChatListener():
- LLEventAPI("GroupChat",
- "API to enter, leave, send and intercept group chat messages")
+void LLGroupChatListener::sendGroupIM(LLSD const &data)
{
- add("startIM",
- "Enter a group chat in group with UUID [\"id\"]\n"
- "Assumes the logged-in agent is already a member of this group.",
- &startIm_wrapper);
- add("endIM",
- "Leave a group chat in group with UUID [\"id\"]\n"
- "Assumes a prior successful startIM request.",
- &LLGroupActions::endIM,
- llsd::array("id"));
- add("sendIM",
- "send a groupchat IM",
- &send_message_wrapper,
- llsd::array("text", "session_id", "group_id"));
+ Response response(LLSD(), data);
+ if (!is_in_group(response, data))
+ {
+ return;
+ }
+ LLUUID group_id(data["group_id"]);
+ LLIMModel::sendMessage(data["message"], gIMMgr->computeSessionID(IM_SESSION_GROUP_START, group_id), group_id, IM_SESSION_SEND);
}
-/*
- static void sendMessage(const std::string& utf8_text, const LLUUID& im_session_id,
- const LLUUID& other_participant_id, EInstantMessage dialog);
-*/
diff --git a/indra/newview/groupchatlistener.h b/indra/newview/groupchatlistener.h
index 3819ac59b7..14cd7266a3 100644
--- a/indra/newview/groupchatlistener.h
+++ b/indra/newview/groupchatlistener.h
@@ -26,15 +26,20 @@
* $/LicenseInfo$
*/
-#if ! defined(LL_GROUPCHATLISTENER_H)
-#define LL_GROUPCHATLISTENER_H
+#if ! defined(LL_LLGROUPCHATLISTENER_H)
+#define LL_LLGROUPCHATLISTENER_H
#include "lleventapi.h"
-class GroupChatListener: public LLEventAPI
+class LLGroupChatListener: public LLEventAPI
{
public:
- GroupChatListener();
+ LLGroupChatListener();
+
+private:
+ void startGroupChat(LLSD const &data);
+ void leaveGroupChat(LLSD const &data);
+ void sendGroupIM(LLSD const &data);
};
-#endif /* ! defined(LL_GROUPCHATLISTENER_H) */
+#endif /* ! defined(LL_LLGROUPCHATLISTENER_H) */
diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp
index 0c120ae01d..5ddb87558a 100644
--- a/indra/newview/llagentlistener.cpp
+++ b/indra/newview/llagentlistener.cpp
@@ -31,19 +31,25 @@
#include "llagentlistener.h"
#include "llagent.h"
+#include "llagentcamera.h"
+#include "llavatarname.h"
+#include "llavatarnamecache.h"
#include "llvoavatar.h"
#include "llcommandhandler.h"
+#include "llinventorymodel.h"
#include "llslurl.h"
#include "llurldispatcher.h"
+#include "llviewercontrol.h"
#include "llviewernetwork.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
+#include "llvoavatarself.h"
#include "llsdutil.h"
#include "llsdutil_math.h"
#include "lltoolgrab.h"
#include "llhudeffectlookat.h"
-#include "llagentcamera.h"
+#include "llviewercamera.h"
LLAgentListener::LLAgentListener(LLAgent &agent)
: LLEventAPI("LLAgent",
@@ -69,13 +75,6 @@ LLAgentListener::LLAgentListener(LLAgent &agent)
add("resetAxes",
"Set the agent to a fixed orientation (optionally specify [\"lookat\"] = array of [x, y, z])",
&LLAgentListener::resetAxes);
- add("getAxes",
- "Obsolete - use getPosition instead\n"
- "Send information about the agent's orientation on [\"reply\"]:\n"
- "[\"euler\"]: map of {roll, pitch, yaw}\n"
- "[\"quat\"]: array of [x, y, z, w] quaternion values",
- &LLAgentListener::getAxes,
- LLSDMap("reply", LLSD()));
add("getPosition",
"Send information about the agent's position and orientation on [\"reply\"]:\n"
"[\"region\"]: array of region {x, y, z} position\n"
@@ -87,33 +86,34 @@ LLAgentListener::LLAgentListener(LLAgent &agent)
add("startAutoPilot",
"Start the autopilot system using the following parameters:\n"
"[\"target_global\"]: array of target global {x, y, z} position\n"
- "[\"stop_distance\"]: target maxiumum distance from target [default: autopilot guess]\n"
+ "[\"stop_distance\"]: maximum stop distance from target [default: autopilot guess]\n"
"[\"target_rotation\"]: array of [x, y, z, w] quaternion values [default: no target]\n"
"[\"rotation_threshold\"]: target maximum angle from target facing rotation [default: 0.03 radians]\n"
- "[\"behavior_name\"]: name of the autopilot behavior [default: \"\"]"
- "[\"allow_flying\"]: allow flying during autopilot [default: True]",
- //"[\"callback_pump\"]: pump to send success/failure and callback data to [default: none]\n"
- //"[\"callback_data\"]: data to send back during a callback [default: none]",
- &LLAgentListener::startAutoPilot);
+ "[\"behavior_name\"]: name of the autopilot behavior [default: \"\"]\n"
+ "[\"allow_flying\"]: allow flying during autopilot [default: True]\n"
+ "event with [\"success\"] flag is sent to 'LLAutopilot' event pump, when auto pilot is terminated",
+ &LLAgentListener::startAutoPilot,
+ llsd::map("target_global", LLSD()));
add("getAutoPilot",
"Send information about current state of the autopilot system to [\"reply\"]:\n"
"[\"enabled\"]: boolean indicating whether or not autopilot is enabled\n"
"[\"target_global\"]: array of target global {x, y, z} position\n"
"[\"leader_id\"]: uuid of target autopilot is following\n"
- "[\"stop_distance\"]: target maximum distance from target\n"
+ "[\"stop_distance\"]: maximum stop distance from target\n"
"[\"target_distance\"]: last known distance from target\n"
"[\"use_rotation\"]: boolean indicating if autopilot has a target facing rotation\n"
"[\"target_facing\"]: array of {x, y} target direction to face\n"
"[\"rotation_threshold\"]: target maximum angle from target facing rotation\n"
"[\"behavior_name\"]: name of the autopilot behavior",
&LLAgentListener::getAutoPilot,
- LLSDMap("reply", LLSD()));
+ llsd::map("reply", LLSD()));
add("startFollowPilot",
"[\"leader_id\"]: uuid of target to follow using the autopilot system (optional with avatar_name)\n"
"[\"avatar_name\"]: avatar name to follow using the autopilot system (optional with leader_id)\n"
"[\"allow_flying\"]: allow flying during autopilot [default: True]\n"
- "[\"stop_distance\"]: target maxiumum distance from target [default: autopilot guess]",
- &LLAgentListener::startFollowPilot);
+ "[\"stop_distance\"]: maximum stop distance from target [default: autopilot guess]",
+ &LLAgentListener::startFollowPilot,
+ llsd::map("reply", LLSD()));
add("setAutoPilotTarget",
"Update target for currently running autopilot:\n"
"[\"target_global\"]: array of target global {x, y, z} position",
@@ -138,6 +138,69 @@ LLAgentListener::LLAgentListener(LLAgent &agent)
"[\"contrib\"]: user's land contribution to this group\n",
&LLAgentListener::getGroups,
LLSDMap("reply", LLSD()));
+ //camera params are similar to LSL, see https://wiki.secondlife.com/wiki/LlSetCameraParams
+ add("setCameraParams",
+ "Set Follow camera params, and then activate it:\n"
+ "[\"camera_pos\"]: vector3, camera position in region coordinates\n"
+ "[\"focus_pos\"]: vector3, what the camera is aimed at (in region coordinates)\n"
+ "[\"focus_offset\"]: vector3, adjusts the camera focus position relative to the target, default is (1, 0, 0)\n"
+ "[\"distance\"]: float (meters), distance the camera wants to be from its target, default is 3\n"
+ "[\"focus_threshold\"]: float (meters), sets the radius of a sphere around the camera's target position within which its focus is not affected by target motion, default is 1\n"
+ "[\"camera_threshold\"]: float (meters), sets the radius of a sphere around the camera's ideal position within which it is not affected by target motion, default is 1\n"
+ "[\"focus_lag\"]: float (seconds), how much the camera lags as it tries to aim towards the target, default is 0.1\n"
+ "[\"camera_lag\"]: float (seconds), how much the camera lags as it tries to move towards its 'ideal' position, default is 0.1\n"
+ "[\"camera_pitch\"]: float (degrees), adjusts the angular amount that the camera aims straight ahead vs. straight down, maintaining the same distance, default is 0\n"
+ "[\"behindness_angle\"]: float (degrees), sets the angle in degrees within which the camera is not constrained by changes in target rotation, default is 10\n"
+ "[\"behindness_lag\"]: float (seconds), sets how strongly the camera is forced to stay behind the target if outside of behindness angle, default is 0\n"
+ "[\"camera_locked\"]: bool, locks the camera position so it will not move\n"
+ "[\"focus_locked\"]: bool, locks the camera focus so it will not move",
+ &LLAgentListener::setFollowCamParams);
+ add("setFollowCamActive",
+ "Turns on or off scripted control of the camera using boolean [\"active\"]",
+ &LLAgentListener::setFollowCamActive,
+ llsd::map("active", LLSD()));
+ add("removeCameraParams",
+ "Reset Follow camera params",
+ &LLAgentListener::removeFollowCamParams);
+
+ add("playAnimation",
+ "Play [\"item_id\"] animation locally (by default) or [\"inworld\"] (when set to true)",
+ &LLAgentListener::playAnimation,
+ llsd::map("item_id", LLSD(), "reply", LLSD()));
+ add("stopAnimation",
+ "Stop playing [\"item_id\"] animation",
+ &LLAgentListener::stopAnimation,
+ llsd::map("item_id", LLSD(), "reply", LLSD()));
+ add("getAnimationInfo",
+ "Return information about [\"item_id\"] animation",
+ &LLAgentListener::getAnimationInfo,
+ llsd::map("item_id", LLSD(), "reply", LLSD()));
+
+ add("getID",
+ "Return your own avatar ID",
+ &LLAgentListener::getID,
+ llsd::map("reply", LLSD()));
+
+ add("getNearbyAvatarsList",
+ "Return result set key [\"result\"] for nearby avatars in a range of [\"dist\"]\n"
+ "if [\"dist\"] is not specified, 'RenderFarClip' setting is used\n"
+ "reply contains \"result\" table with \"id\", \"name\", \"global_pos\", \"region_pos\", \"region_id\" fields",
+ &LLAgentListener::getNearbyAvatarsList,
+ llsd::map("reply", LLSD()));
+
+ add("getNearbyObjectsList",
+ "Return result set key [\"result\"] for nearby objects in a range of [\"dist\"]\n"
+ "if [\"dist\"] is not specified, 'RenderFarClip' setting is used\n"
+ "reply contains \"result\" table with \"id\", \"global_pos\", \"region_pos\", \"region_id\" fields",
+ &LLAgentListener::getNearbyObjectsList,
+ llsd::map("reply", LLSD()));
+
+ add("getAgentScreenPos",
+ "Return screen position of the [\"avatar_id\"] avatar or own avatar if not specified\n"
+ "reply contains \"x\", \"y\" coordinates and \"onscreen\" flag to indicate if it's actually in within the current window\n"
+ "avatar render position is used as the point",
+ &LLAgentListener::getAgentScreenPos,
+ llsd::map("reply", LLSD()));
}
void LLAgentListener::requestTeleport(LLSD const & event_data) const
@@ -168,7 +231,7 @@ void LLAgentListener::requestSit(LLSD const & event_data) const
//mAgent.getAvatarObject()->sitOnObject();
// shamelessly ripped from llviewermenu.cpp:handle_sit_or_stand()
// *TODO - find a permanent place to share this code properly.
-
+ Response response(LLSD(), event_data);
LLViewerObject *object = NULL;
if (event_data.has("obj_uuid"))
{
@@ -177,7 +240,13 @@ void LLAgentListener::requestSit(LLSD const & event_data) const
else if (event_data.has("position"))
{
LLVector3 target_position = ll_vector3_from_sd(event_data["position"]);
- object = findObjectClosestTo(target_position);
+ object = findObjectClosestTo(target_position, true);
+ }
+ else
+ {
+ //just sit on the ground
+ mAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND);
+ return;
}
if (object && object->getPCode() == LL_PCODE_VOLUME)
@@ -194,8 +263,7 @@ void LLAgentListener::requestSit(LLSD const & event_data) const
}
else
{
- LL_WARNS() << "LLAgent requestSit could not find the sit target: "
- << event_data << LL_ENDL;
+ response.error("requestSit could not find the sit target");
}
}
@@ -205,7 +273,7 @@ void LLAgentListener::requestStand(LLSD const & event_data) const
}
-LLViewerObject * LLAgentListener::findObjectClosestTo( const LLVector3 & position ) const
+LLViewerObject * LLAgentListener::findObjectClosestTo(const LLVector3 & position, bool sit_target) const
{
LLViewerObject *object = NULL;
@@ -216,8 +284,13 @@ LLViewerObject * LLAgentListener::findObjectClosestTo( const LLVector3 & positio
while (cur_index < num_objects)
{
LLViewerObject * cur_object = gObjectList.getObject(cur_index++);
- if (cur_object)
- { // Calculate distance from the target position
+ if (cur_object && !cur_object->isAttachment())
+ {
+ if(sit_target && (cur_object->getPCode() != LL_PCODE_VOLUME))
+ {
+ continue;
+ }
+ // Calculate distance from the target position
LLVector3 target_diff = cur_object->getPositionRegion() - position;
F32 distance_to_target = target_diff.length();
if (distance_to_target < min_distance)
@@ -296,22 +369,6 @@ void LLAgentListener::resetAxes(const LLSD& event_data) const
}
}
-void LLAgentListener::getAxes(const LLSD& event_data) const
-{
- LLQuaternion quat(mAgent.getQuat());
- F32 roll, pitch, yaw;
- quat.getEulerAngles(&roll, &pitch, &yaw);
- // The official query API for LLQuaternion's [x, y, z, w] values is its
- // public member mQ...
- LLSD reply = LLSD::emptyMap();
- reply["quat"] = llsd_copy_array(boost::begin(quat.mQ), boost::end(quat.mQ));
- reply["euler"] = LLSD::emptyMap();
- reply["euler"]["roll"] = roll;
- reply["euler"]["pitch"] = pitch;
- reply["euler"]["yaw"] = yaw;
- sendReply(reply, event_data);
-}
-
void LLAgentListener::getPosition(const LLSD& event_data) const
{
F32 roll, pitch, yaw;
@@ -333,14 +390,13 @@ void LLAgentListener::getPosition(const LLSD& event_data) const
void LLAgentListener::startAutoPilot(LLSD const & event_data)
{
- LLQuaternion target_rotation_value;
LLQuaternion* target_rotation = NULL;
if (event_data.has("target_rotation"))
{
- target_rotation_value = ll_quaternion_from_sd(event_data["target_rotation"]);
+ LLQuaternion target_rotation_value = ll_quaternion_from_sd(event_data["target_rotation"]);
target_rotation = &target_rotation_value;
}
- // *TODO: Use callback_pump and callback_data
+
F32 rotation_threshold = 0.03f;
if (event_data.has("rotation_threshold"))
{
@@ -360,13 +416,24 @@ void LLAgentListener::startAutoPilot(LLSD const & event_data)
stop_distance = (F32)event_data["stop_distance"].asReal();
}
+ std::string behavior_name = LLCoros::getName();
+ if (event_data.has("behavior_name"))
+ {
+ behavior_name = event_data["behavior_name"].asString();
+ }
+
// Clear follow target, this is doing a path
mFollowTarget.setNull();
+ auto finish_cb = [](bool success, void*)
+ {
+ LLEventPumps::instance().obtain("LLAutopilot").post(llsd::map("success", success));
+ };
+
mAgent.startAutoPilotGlobal(ll_vector3d_from_sd(event_data["target_global"]),
- event_data["behavior_name"],
+ behavior_name,
target_rotation,
- NULL, NULL,
+ finish_cb, NULL,
stop_distance,
rotation_threshold,
allow_flying);
@@ -374,7 +441,7 @@ void LLAgentListener::startAutoPilot(LLSD const & event_data)
void LLAgentListener::getAutoPilot(const LLSD& event_data) const
{
- LLSD reply = LLSD::emptyMap();
+ Response reply(LLSD(), event_data);
LLSD::Boolean enabled = mAgent.getAutoPilot();
reply["enabled"] = enabled;
@@ -403,12 +470,11 @@ void LLAgentListener::getAutoPilot(const LLSD& event_data) const
reply["rotation_threshold"] = mAgent.getAutoPilotRotationThreshold();
reply["behavior_name"] = mAgent.getAutoPilotBehaviorName();
reply["fly"] = (LLSD::Boolean) mAgent.getFlying();
-
- sendReply(reply, event_data);
}
void LLAgentListener::startFollowPilot(LLSD const & event_data)
{
+ Response response(LLSD(), event_data);
LLUUID target_id;
bool allow_flying = true;
@@ -442,6 +508,10 @@ void LLAgentListener::startFollowPilot(LLSD const & event_data)
}
}
}
+ else
+ {
+ return response.error("'leader_id' or 'avatar_name' should be specified");
+ }
F32 stop_distance = 0.f;
if (event_data.has("stop_distance"))
@@ -449,13 +519,16 @@ void LLAgentListener::startFollowPilot(LLSD const & event_data)
stop_distance = (F32)event_data["stop_distance"].asReal();
}
- if (target_id.notNull())
+ if (!gObjectList.findObject(target_id))
{
- mAgent.setFlying(allow_flying);
- mFollowTarget = target_id; // Save follow target so we can report distance later
-
- mAgent.startFollowPilot(target_id, allow_flying, stop_distance);
+ std::string target_info = event_data.has("leader_id") ? event_data["leader_id"] : event_data["avatar_name"];
+ return response.error(stringize("Target ", std::quoted(target_info), " was not found"));
}
+
+ mAgent.setFlying(allow_flying);
+ mFollowTarget = target_id; // Save follow target so we can report distance later
+
+ mAgent.startFollowPilot(target_id, allow_flying, stop_distance);
}
void LLAgentListener::setAutoPilotTarget(LLSD const & event_data) const
@@ -519,3 +592,209 @@ void LLAgentListener::getGroups(const LLSD& event) const
}
sendReply(LLSDMap("groups", reply), event);
}
+
+/*----------------------------- camera control -----------------------------*/
+// specialize LLSDParam to support (const LLVector3&) arguments -- this
+// wouldn't even be necessary except that the relevant LLVector3 constructor
+// is explicitly explicit
+template <>
+class LLSDParam<const LLVector3&>: public LLSDParamBase
+{
+public:
+ LLSDParam(const LLSD& value): value(LLVector3(value)) {}
+
+ operator const LLVector3&() const { return value; }
+
+private:
+ LLVector3 value;
+};
+
+// accept any of a number of similar LLFollowCamMgr methods with different
+// argument types, and return a wrapper lambda that accepts LLSD and converts
+// to the target argument type
+template <typename T>
+auto wrap(void (LLFollowCamMgr::*method)(const LLUUID& source, T arg))
+{
+ return [method](LLFollowCamMgr& followcam, const LLUUID& source, const LLSD& arg)
+ { (followcam.*method)(source, LLSDParam<T>(arg)); };
+}
+
+// table of supported LLFollowCamMgr methods,
+// with the corresponding setFollowCamParams() argument keys
+static std::pair<std::string, std::function<void(LLFollowCamMgr&, const LLUUID&, const LLSD&)>>
+cam_params[] =
+{
+ { "camera_pos", wrap(&LLFollowCamMgr::setPosition) },
+ { "focus_pos", wrap(&LLFollowCamMgr::setFocus) },
+ { "focus_offset", wrap(&LLFollowCamMgr::setFocusOffset) },
+ { "camera_locked", wrap(&LLFollowCamMgr::setPositionLocked) },
+ { "focus_locked", wrap(&LLFollowCamMgr::setFocusLocked) },
+ { "distance", wrap(&LLFollowCamMgr::setDistance) },
+ { "focus_threshold", wrap(&LLFollowCamMgr::setFocusThreshold) },
+ { "camera_threshold", wrap(&LLFollowCamMgr::setPositionThreshold) },
+ { "focus_lag", wrap(&LLFollowCamMgr::setFocusLag) },
+ { "camera_lag", wrap(&LLFollowCamMgr::setPositionLag) },
+ { "camera_pitch", wrap(&LLFollowCamMgr::setPitch) },
+ { "behindness_lag", wrap(&LLFollowCamMgr::setBehindnessLag) },
+ { "behindness_angle", wrap(&LLFollowCamMgr::setBehindnessAngle) },
+};
+
+void LLAgentListener::setFollowCamParams(const LLSD& event) const
+{
+ auto& followcam{ LLFollowCamMgr::instance() };
+ for (const auto& pair : cam_params)
+ {
+ if (event.has(pair.first))
+ {
+ pair.second(followcam, gAgentID, event[pair.first]);
+ }
+ }
+ followcam.setCameraActive(gAgentID, true);
+}
+
+void LLAgentListener::setFollowCamActive(LLSD const & event) const
+{
+ LLFollowCamMgr::getInstance()->setCameraActive(gAgentID, event["active"]);
+}
+
+void LLAgentListener::removeFollowCamParams(LLSD const & event) const
+{
+ LLFollowCamMgr::getInstance()->removeFollowCamParams(gAgentID);
+}
+
+LLViewerInventoryItem* get_anim_item(LLEventAPI::Response &response, const LLSD &event_data)
+{
+ LLViewerInventoryItem* item = gInventory.getItem(event_data["item_id"].asUUID());
+ if (!item || (item->getInventoryType() != LLInventoryType::IT_ANIMATION))
+ {
+ response.error(stringize("Animation item ", std::quoted(event_data["item_id"].asString()), " was not found"));
+ return NULL;
+ }
+ return item;
+}
+
+void LLAgentListener::playAnimation(LLSD const &event_data)
+{
+ Response response(LLSD(), event_data);
+ if (LLViewerInventoryItem* item = get_anim_item(response, event_data))
+ {
+ if (event_data["inworld"].asBoolean())
+ {
+ mAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_START);
+ }
+ else
+ {
+ gAgentAvatarp->startMotion(item->getAssetUUID());
+ }
+ }
+}
+
+void LLAgentListener::stopAnimation(LLSD const &event_data)
+{
+ Response response(LLSD(), event_data);
+ if (LLViewerInventoryItem* item = get_anim_item(response, event_data))
+ {
+ gAgentAvatarp->stopMotion(item->getAssetUUID());
+ mAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_STOP);
+ }
+}
+
+void LLAgentListener::getAnimationInfo(LLSD const &event_data)
+{
+ Response response(LLSD(), event_data);
+ if (LLViewerInventoryItem* item = get_anim_item(response, event_data))
+ {
+ // if motion exists, will return existing one
+ LLMotion* motion = gAgentAvatarp->createMotion(item->getAssetUUID());
+ response["anim_info"] = llsd::map("duration", motion->getDuration(),
+ "is_loop", motion->getLoop(),
+ "num_joints", motion->getNumJointMotions(),
+ "asset_id", item->getAssetUUID(),
+ "priority", motion->getPriority());
+ }
+}
+
+void LLAgentListener::getID(LLSD const& event_data)
+{
+ Response response(llsd::map("id", gAgentID), event_data);
+}
+
+F32 get_search_radius(LLSD const& event_data)
+{
+ static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
+ F32 dist = render_far_clip;
+ if (event_data.has("dist"))
+ {
+ dist = llclamp((F32)event_data["dist"].asReal(), 1, 512);
+ }
+ return dist * dist;
+}
+
+void LLAgentListener::getNearbyAvatarsList(LLSD const& event_data)
+{
+ Response response(LLSD(), event_data);
+ F32 radius = get_search_radius(event_data);
+ LLVector3d agent_pos = gAgent.getPositionGlobal();
+ for (LLCharacter* character : LLCharacter::sInstances)
+ {
+ LLVOAvatar* avatar = (LLVOAvatar*)character;
+ if (avatar && !avatar->isDead() && !avatar->isControlAvatar() && !avatar->isSelf())
+ {
+ if ((dist_vec_squared(avatar->getPositionGlobal(), agent_pos) <= radius))
+ {
+ LLAvatarName av_name;
+ LLAvatarNameCache::get(avatar->getID(), &av_name);
+ LLVector3 region_pos = avatar->getCharacterPosition();
+ response["result"].append(llsd::map("id", avatar->getID(), "global_pos", ll_sd_from_vector3d(avatar->getPosGlobalFromAgent(region_pos)),
+ "region_pos", ll_sd_from_vector3(region_pos), "name", av_name.getUserName(), "region_id", avatar->getRegion()->getRegionID()));
+ }
+ }
+ }
+}
+
+void LLAgentListener::getNearbyObjectsList(LLSD const& event_data)
+{
+ Response response(LLSD(), event_data);
+ F32 radius = get_search_radius(event_data);
+ S32 num_objects = gObjectList.getNumObjects();
+ LLVector3d agent_pos = gAgent.getPositionGlobal();
+ for (S32 i = 0; i < num_objects; ++i)
+ {
+ LLViewerObject* object = gObjectList.getObject(i);
+ if (object && object->getVolume() && !object->isAttachment())
+ {
+ if ((dist_vec_squared(object->getPositionGlobal(), agent_pos) <= radius))
+ {
+ response["result"].append(llsd::map("id", object->getID(), "global_pos", ll_sd_from_vector3d(object->getPositionGlobal()), "region_pos",
+ ll_sd_from_vector3(object->getPositionRegion()), "region_id", object->getRegion()->getRegionID()));
+ }
+ }
+ }
+}
+
+void LLAgentListener::getAgentScreenPos(LLSD const& event_data)
+{
+ Response response(LLSD(), event_data);
+ LLVector3 render_pos;
+ if (event_data.has("avatar_id") && (event_data["avatar_id"].asUUID() != gAgentID))
+ {
+ LLUUID avatar_id(event_data["avatar_id"]);
+ for (LLCharacter* character : LLCharacter::sInstances)
+ {
+ LLVOAvatar* avatar = (LLVOAvatar*)character;
+ if (!avatar->isDead() && (avatar->getID() == avatar_id))
+ {
+ render_pos = avatar->getRenderPosition();
+ break;
+ }
+ }
+ }
+ else if (gAgentAvatarp.notNull() && gAgentAvatarp->isValid())
+ {
+ render_pos = gAgentAvatarp->getRenderPosition();
+ }
+ LLCoordGL screen_pos;
+ response["onscreen"] = LLViewerCamera::getInstance()->projectPosAgentToScreen(render_pos, screen_pos, false);
+ response["x"] = screen_pos.mX;
+ response["y"] = screen_pos.mY;
+}
diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h
index c544d089ce..b5bea8c0bd 100644
--- a/indra/newview/llagentlistener.h
+++ b/indra/newview/llagentlistener.h
@@ -48,7 +48,6 @@ private:
void requestStand(LLSD const & event_data) const;
void requestTouch(LLSD const & event_data) const;
void resetAxes(const LLSD& event_data) const;
- void getAxes(const LLSD& event_data) const;
void getGroups(const LLSD& event) const;
void getPosition(const LLSD& event_data) const;
void startAutoPilot(const LLSD& event_data);
@@ -58,7 +57,20 @@ private:
void stopAutoPilot(const LLSD& event_data) const;
void lookAt(LLSD const & event_data) const;
- LLViewerObject * findObjectClosestTo( const LLVector3 & position ) const;
+ void setFollowCamParams(LLSD const & event_data) const;
+ void setFollowCamActive(LLSD const & event_data) const;
+ void removeFollowCamParams(LLSD const & event_data) const;
+
+ void playAnimation(LLSD const &event_data);
+ void stopAnimation(LLSD const &event_data);
+ void getAnimationInfo(LLSD const &event_data);
+
+ void getID(LLSD const& event_data);
+ void getNearbyAvatarsList(LLSD const& event_data);
+ void getNearbyObjectsList(LLSD const& event_data);
+ void getAgentScreenPos(LLSD const& event_data);
+
+ LLViewerObject * findObjectClosestTo( const LLVector3 & position, bool sit_target = false ) const;
private:
LLAgent & mAgent;
diff --git a/indra/newview/llappearancelistener.cpp b/indra/newview/llappearancelistener.cpp
new file mode 100644
index 0000000000..dc7bbc3236
--- /dev/null
+++ b/indra/newview/llappearancelistener.cpp
@@ -0,0 +1,158 @@
+/**
+ * @file llappearancelistener.cpp
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llappearancelistener.h"
+
+#include "llappearancemgr.h"
+#include "llinventoryfunctions.h"
+#include "lltransutil.h"
+#include "llwearableitemslist.h"
+#include "stringize.h"
+
+LLAppearanceListener::LLAppearanceListener()
+ : LLEventAPI("LLAppearance",
+ "API to wear a specified outfit and wear/remove individual items")
+{
+ add("wearOutfit",
+ "Wear outfit by folder id: [\"folder_id\"] OR by folder name: [\"folder_name\"]\n"
+ "When [\"append\"] is true, outfit will be added to COF\n"
+ "otherwise it will replace current oufit",
+ &LLAppearanceListener::wearOutfit);
+
+ add("wearItems",
+ "Wear items by id: [items_id]",
+ &LLAppearanceListener::wearItems,
+ llsd::map("items_id", LLSD(), "replace", LLSD()));
+
+ add("detachItems",
+ "Detach items by id: [items_id]",
+ &LLAppearanceListener::detachItems,
+ llsd::map("items_id", LLSD()));
+
+ add("getOutfitsList",
+ "Return the table with Outfits info(id and name)",
+ &LLAppearanceListener::getOutfitsList);
+
+ add("getOutfitItems",
+ "Return the table of items with info(id : name, wearable_type, is_worn) inside specified outfit folder",
+ &LLAppearanceListener::getOutfitItems);
+}
+
+
+void LLAppearanceListener::wearOutfit(LLSD const &data)
+{
+ Response response(LLSD(), data);
+ if (!data.has("folder_id") && !data.has("folder_name"))
+ {
+ return response.error("Either [folder_id] or [folder_name] is required");
+ }
+
+ bool append = data.has("append") ? data["append"].asBoolean() : false;
+ if (!LLAppearanceMgr::instance().wearOutfit(data, append))
+ {
+ response.error("Failed to wear outfit");
+ }
+}
+
+void LLAppearanceListener::wearItems(LLSD const &data)
+{
+ const LLSD& items_id{ data["items_id"] };
+ uuid_vec_t ids;
+ if (!items_id.isArray())
+ {
+ ids.push_back(items_id.asUUID());
+ }
+ else // array
+ {
+ for (const auto& id : llsd::inArray(items_id))
+ {
+ ids.push_back(id);
+ }
+ }
+ LLAppearanceMgr::instance().wearItemsOnAvatar(ids, true, data["replace"].asBoolean());
+}
+
+void LLAppearanceListener::detachItems(LLSD const &data)
+{
+ const LLSD& items_id{ data["items_id"] };
+ uuid_vec_t ids;
+ if (!items_id.isArray())
+ {
+ ids.push_back(items_id.asUUID());
+ }
+ else // array
+ {
+ for (const auto& id : llsd::inArray(items_id))
+ {
+ ids.push_back(id);
+ }
+ }
+ LLAppearanceMgr::instance().removeItemsFromAvatar(ids);
+}
+
+void LLAppearanceListener::getOutfitsList(LLSD const &data)
+{
+ Response response(LLSD(), data);
+ const LLUUID outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+
+ LLIsFolderType is_category(LLFolderType::FT_OUTFIT);
+ gInventory.collectDescendentsIf(outfits_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, is_category);
+
+ response["outfits"] = llsd::toMap(cat_array,
+ [](const LLPointer<LLViewerInventoryCategory> &cat)
+ { return std::make_pair(cat->getUUID().asString(), cat->getName()); });
+}
+
+void LLAppearanceListener::getOutfitItems(LLSD const &data)
+{
+ Response response(LLSD(), data);
+ LLUUID outfit_id(data["outfit_id"].asUUID());
+ LLViewerInventoryCategory *cat = gInventory.getCategory(outfit_id);
+ if (!cat || cat->getPreferredType() != LLFolderType::FT_OUTFIT)
+ {
+ return response.error(stringize("Couldn't find outfit ", outfit_id.asString()));
+ }
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+
+ LLFindOutfitItems collector = LLFindOutfitItems();
+ gInventory.collectDescendentsIf(outfit_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, collector);
+
+ response["items"] = llsd::toMap(item_array,
+ [](const LLPointer<LLViewerInventoryItem> &it)
+ {
+ return std::make_pair(
+ it->getUUID().asString(),
+ llsd::map(
+ "name", it->getName(),
+ "wearable_type", LLWearableType::getInstance()->getTypeName(it->isWearableType() ? it->getWearableType() : LLWearableType::WT_NONE),
+ "is_worn", get_is_item_worn(it)));
+ });
+}
diff --git a/indra/newview/llappearancelistener.h b/indra/newview/llappearancelistener.h
new file mode 100644
index 0000000000..04c5eac2eb
--- /dev/null
+++ b/indra/newview/llappearancelistener.h
@@ -0,0 +1,46 @@
+/**
+ * @file llappearancelistener.h
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+
+#ifndef LL_LLAPPEARANCELISTENER_H
+#define LL_LLAPPEARANCELISTENER_H
+
+#include "lleventapi.h"
+
+class LLAppearanceListener : public LLEventAPI
+{
+public:
+ LLAppearanceListener();
+
+private:
+ void wearOutfit(LLSD const &data);
+ void wearItems(LLSD const &data);
+ void detachItems(LLSD const &data);
+ void getOutfitsList(LLSD const &data);
+ void getOutfitItems(LLSD const &data);
+};
+
+#endif // LL_LLAPPEARANCELISTENER_H
+
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 101aca3823..e9d455ae53 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -31,6 +31,7 @@
#include "llagent.h"
#include "llagentcamera.h"
#include "llagentwearables.h"
+#include "llappearancelistener.h"
#include "llappearancemgr.h"
#include "llattachmentsmgr.h"
#include "llcommandhandler.h"
@@ -66,6 +67,8 @@
#include "llavatarpropertiesprocessor.h"
+LLAppearanceListener sAppearanceListener;
+
namespace
{
const S32 BAKE_RETRY_MAX_COUNT = 5;
@@ -4762,6 +4765,11 @@ bool wear_category(const LLSD& query_map, bool append)
return false;
}
+bool LLAppearanceMgr::wearOutfit(const LLSD& query_map, bool append)
+{
+ return wear_category(query_map, append);
+}
+
class LLWearFolderHandler : public LLCommandHandler
{
public:
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 6c45a32856..bc7dc9506b 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -60,6 +60,7 @@ public:
void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append);
void wearCategoryFinal(const LLUUID& cat_id, bool copy_items, bool append);
void wearOutfitByName(const std::string& name);
+ bool wearOutfit(const LLSD& query_map, bool append = false);
void changeOutfit(bool proceed, const LLUUID& category, bool append);
void replaceCurrentOutfit(const LLUUID& new_outfit);
void renameOutfit(const LLUUID& outfit_id);
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index c5190fe486..87b165b739 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -4585,6 +4585,7 @@ void LLAppViewer::saveFinalSnapshot()
false,
gSavedSettings.getBOOL("RenderHUDInSnapshot"),
true,
+ false,
LLSnapshotModel::SNAPSHOT_TYPE_COLOR,
LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
mSavedFinalSnapshot = true;
@@ -5299,6 +5300,8 @@ void LLAppViewer::sendLogoutRequest()
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
gAgent.sendReliableMessage();
+ LL_INFOS("Agent") << "Logging out as agent: " << gAgent.getID() << " Session: " << gAgent.getSessionID() << LL_ENDL;
+
gLogoutTimer.reset();
gLogoutMaxTime = LOGOUT_REQUEST_TIME;
mLogoutRequestSent = true;
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 169fea320a..ef609026ad 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -814,69 +814,11 @@ void write_debug_dx(const std::string& str)
bool LLAppViewerWin32::initHardwareTest()
{
- //
- // Do driver verification and initialization based on DirectX
- // hardware polling and driver versions
- //
- if (true == gSavedSettings.getBOOL("ProbeHardwareOnStartup") && false == gSavedSettings.getBOOL("NoHardwareProbe"))
- {
- // per DEV-11631 - disable hardware probing for everything
- // but vram.
- bool vram_only = true;
-
- LLSplashScreen::update(LLTrans::getString("StartupDetectingHardware"));
-
- LL_DEBUGS("AppInit") << "Attempting to poll DirectX for hardware info" << LL_ENDL;
- gDXHardware.setWriteDebugFunc(write_debug_dx);
- bool probe_ok = gDXHardware.getInfo(vram_only);
-
- if (!probe_ok
- && gWarningSettings.getBOOL("AboutDirectX9"))
- {
- LL_WARNS("AppInit") << "DirectX probe failed, alerting user." << LL_ENDL;
-
- // Warn them that runnin without DirectX 9 will
- // not allow us to tell them about driver issues
- std::ostringstream msg;
- msg << LLTrans::getString ("MBNoDirectX");
- S32 button = OSMessageBox(
- msg.str(),
- LLTrans::getString("MBWarning"),
- OSMB_YESNO);
- if (OSBTN_NO== button)
- {
- LL_INFOS("AppInit") << "User quitting after failed DirectX 9 detection" << LL_ENDL;
- LLWeb::loadURLExternal("http://secondlife.com/support/", false);
- return false;
- }
- gWarningSettings.setBOOL("AboutDirectX9", false);
- }
- LL_DEBUGS("AppInit") << "Done polling DirectX for hardware info" << LL_ENDL;
-
- // Only probe once after installation
- gSavedSettings.setBOOL("ProbeHardwareOnStartup", false);
-
- // Disable so debugger can work
- std::string splash_msg;
- LLStringUtil::format_map_t args;
- args["[APP_NAME]"] = LLAppViewer::instance()->getSecondLifeTitle();
- splash_msg = LLTrans::getString("StartupLoading", args);
-
- LLSplashScreen::update(splash_msg);
- }
-
if (!restoreErrorTrap())
{
- LL_WARNS("AppInit") << " Someone took over my exception handler (post hardware probe)!" << LL_ENDL;
+ LL_WARNS("AppInit") << " Someone took over my exception handler!" << LL_ENDL;
}
- if (gGLManager.mVRAM == 0)
- {
- gGLManager.mVRAM = gDXHardware.getVRAM();
- }
-
- LL_INFOS("AppInit") << "Detected VRAM: " << gGLManager.mVRAM << LL_ENDL;
-
return true;
}
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 95f96e85d6..90ee95d424 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -491,7 +491,6 @@ void LLDrawPoolAvatar::beginImpostor()
if (!LLPipeline::sReflectionRender)
{
- LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f);
LLVOAvatar::sNumVisibleAvatars = 0;
}
@@ -547,7 +546,6 @@ void LLDrawPoolAvatar::beginDeferredImpostor()
if (!LLPipeline::sReflectionRender)
{
- LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f);
LLVOAvatar::sNumVisibleAvatars = 0;
}
diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h
index 5380463d01..23cf253b6a 100644
--- a/indra/newview/lldrawpoolterrain.h
+++ b/indra/newview/lldrawpoolterrain.h
@@ -38,6 +38,7 @@ public:
VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX |
LLVertexBuffer::MAP_NORMAL |
LLVertexBuffer::MAP_TANGENT | // Only PBR terrain uses this currently
+ LLVertexBuffer::MAP_TEXCOORD0 | // Ownership overlay
LLVertexBuffer::MAP_TEXCOORD1
};
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 0017a724ea..875dac103c 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -2563,7 +2563,6 @@ void LLEnvironment::setSharedEnvironment()
{
clearEnvironment(LLEnvironment::ENV_LOCAL);
setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
- updateEnvironment();
}
void LLEnvironment::setExperienceEnvironment(LLUUID experience_id, LLUUID asset_id, F32 transition_time)
diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp
index 42307dd3f8..0a8b8d321d 100644
--- a/indra/newview/llfloatereditextdaycycle.cpp
+++ b/indra/newview/llfloatereditextdaycycle.cpp
@@ -495,7 +495,6 @@ void LLFloaterEditExtDayCycle::setEditDayCycle(const LLSettingsDay::ptr_t &pday)
updateEditEnvironment();
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_INSTANT);
- LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
synchronizeTabs();
updateTabs();
refresh();
@@ -824,7 +823,6 @@ void LLFloaterEditExtDayCycle::onClearTrack()
updateEditEnvironment();
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_INSTANT);
- LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
synchronizeTabs();
updateTabs();
refresh();
diff --git a/indra/newview/llfloaterenvironmentadjust.cpp b/indra/newview/llfloaterenvironmentadjust.cpp
index 35f8340997..4825cbf7fb 100644
--- a/indra/newview/llfloaterenvironmentadjust.cpp
+++ b/indra/newview/llfloaterenvironmentadjust.cpp
@@ -242,9 +242,7 @@ void LLFloaterEnvironmentAdjust::captureCurrentEnvironment()
environment.setEnvironment(LLEnvironment::ENV_LOCAL, mLiveSky, FLOATER_ENVIRONMENT_UPDATE);
environment.setEnvironment(LLEnvironment::ENV_LOCAL, mLiveWater, FLOATER_ENVIRONMENT_UPDATE);
}
- environment.setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
- environment.updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
-
+ environment.setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT);
}
void LLFloaterEnvironmentAdjust::onButtonReset()
@@ -258,7 +256,6 @@ void LLFloaterEnvironmentAdjust::onButtonReset()
this->closeFloater();
LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL);
LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
- LLEnvironment::instance().updateEnvironment();
}
});
@@ -455,9 +452,29 @@ void LLFloaterEnvironmentAdjust::onMoonAzimElevChanged()
void LLFloaterEnvironmentAdjust::onCloudMapChanged()
{
if (!mLiveSky)
+ {
return;
- mLiveSky->setCloudNoiseTextureId(getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->getValue().asUUID());
- mLiveSky->update();
+ }
+
+ LLTextureCtrl* picker_ctrl = getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP);
+
+ LLUUID new_texture_id = picker_ctrl->getValue().asUUID();
+
+ LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+
+ LLSettingsSky::ptr_t sky_to_set = mLiveSky->buildClone();
+ if (!sky_to_set)
+ {
+ return;
+ }
+
+ sky_to_set->setCloudNoiseTextureId(new_texture_id);
+
+ LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, sky_to_set);
+
+ LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT, true);
+
+ picker_ctrl->setValue(new_texture_id);
}
void LLFloaterEnvironmentAdjust::onWaterMapChanged()
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index 28c651f0cd..db6f9ac22a 100644
--- a/indra/newview/llfloaterimnearbychat.cpp
+++ b/indra/newview/llfloaterimnearbychat.cpp
@@ -52,6 +52,7 @@
#include "llfirstuse.h"
#include "llfloaterimnearbychat.h"
+#include "llfloaterimnearbychatlistener.h"
#include "llagent.h" // gAgent
#include "llgesturemgr.h"
#include "llmultigesture.h"
@@ -71,6 +72,8 @@
S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0;
+static LLFloaterIMNearbyChatListener sChatListener;
+
constexpr S32 EXPANDED_HEIGHT = 266;
constexpr S32 COLLAPSED_HEIGHT = 60;
constexpr S32 EXPANDED_MIN_HEIGHT = 150;
diff --git a/indra/newview/llfloaterimnearbychatlistener.cpp b/indra/newview/llfloaterimnearbychatlistener.cpp
index 43173d3680..b15a32ce40 100644
--- a/indra/newview/llfloaterimnearbychatlistener.cpp
+++ b/indra/newview/llfloaterimnearbychatlistener.cpp
@@ -34,12 +34,12 @@
#include "llagent.h"
#include "llchat.h"
#include "llviewercontrol.h"
+#include "stringize.h"
+static const F32 CHAT_THROTTLE_PERIOD = 1.f;
-LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar)
- : LLEventAPI("LLChatBar",
- "LLChatBar listener to (e.g.) sendChat, etc."),
- mChatbar(chatbar)
+LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener() :
+ LLEventAPI("LLChatBar", "LLChatBar listener to (e.g.) sendChat, etc.")
{
add("sendChat",
"Send chat to the simulator:\n"
@@ -49,10 +49,18 @@ LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyCh
&LLFloaterIMNearbyChatListener::sendChat);
}
-
// "sendChat" command
-void LLFloaterIMNearbyChatListener::sendChat(LLSD const & chat_data) const
+void LLFloaterIMNearbyChatListener::sendChat(LLSD const& chat_data)
{
+ F64 cur_time = LLTimer::getElapsedSeconds();
+
+ if (cur_time < mLastThrottleTime + CHAT_THROTTLE_PERIOD)
+ {
+ LL_WARNS("LLFloaterIMNearbyChatListener") << "'sendChat' was throttled" << LL_ENDL;
+ return;
+ }
+ mLastThrottleTime = cur_time;
+
// Extract the data
std::string chat_text = chat_data["message"].asString();
@@ -81,20 +89,12 @@ void LLFloaterIMNearbyChatListener::sendChat(LLSD const & chat_data) const
}
// Have to prepend /42 style channel numbers
- std::string chat_to_send;
- if (channel == 0)
- {
- chat_to_send = chat_text;
- }
- else
+ if (channel)
{
- chat_to_send += "/";
- chat_to_send += chat_data["channel"].asString();
- chat_to_send += " ";
- chat_to_send += chat_text;
+ chat_text = stringize("/", chat_data["channel"].asString(), " ", chat_text);
}
// Send it as if it was typed in
- mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, ((bool)(channel == 0)) && gSavedSettings.getBOOL("PlayChatAnim"));
+ LLFloaterIMNearbyChat::sendChatFromViewer(chat_text, type_o_chat, (channel == 0) && gSavedSettings.getBOOL("PlayChatAnim"));
}
diff --git a/indra/newview/llfloaterimnearbychatlistener.h b/indra/newview/llfloaterimnearbychatlistener.h
index 96184d95b3..71eba53a9a 100644
--- a/indra/newview/llfloaterimnearbychatlistener.h
+++ b/indra/newview/llfloaterimnearbychatlistener.h
@@ -38,12 +38,12 @@ class LLFloaterIMNearbyChat;
class LLFloaterIMNearbyChatListener : public LLEventAPI
{
public:
- LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar);
+ LLFloaterIMNearbyChatListener();
private:
- void sendChat(LLSD const & chat_data) const;
+ void sendChat(LLSD const & chat_data);
- LLFloaterIMNearbyChat & mChatbar;
+ F64 mLastThrottleTime{0};
};
#endif // LL_LLFLOATERIMNEARBYCHATLISTENER_H
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 335aba2cc9..553aa1ff4b 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -39,6 +39,7 @@
#include "llchicletbar.h"
#include "lldraghandle.h"
#include "llemojidictionary.h"
+#include "llemojihelper.h"
#include "llfloaterreg.h"
#include "llfloateremojipicker.h"
#include "llfloaterimsession.h"
@@ -300,6 +301,8 @@ bool LLFloaterIMSessionTab::postBuild()
mEmojiPickerShowBtn = getChild<LLButton>("emoji_picker_show_btn");
mEmojiPickerShowBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerShowBtnClicked(); });
+ mEmojiPickerShowBtn->setMouseDownCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerShowBtnDown(); });
+ mEmojiCloseConn = LLEmojiHelper::instance().setCloseCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerClosed(); });
mGearBtn = getChild<LLButton>("gear_btn");
mAddBtn = getChild<LLButton>("add_btn");
@@ -532,8 +535,43 @@ void LLFloaterIMSessionTab::onEmojiRecentPanelToggleBtnClicked()
void LLFloaterIMSessionTab::onEmojiPickerShowBtnClicked()
{
- mInputEditor->setFocus(true);
- mInputEditor->showEmojiHelper();
+ if (!mEmojiPickerShowBtn->getToggleState())
+ {
+ mInputEditor->hideEmojiHelper();
+ mInputEditor->setFocus(true);
+ mInputEditor->showEmojiHelper();
+ mEmojiPickerShowBtn->setToggleState(true); // in case hideEmojiHelper closed a visible instance
+ }
+ else
+ {
+ mInputEditor->hideEmojiHelper();
+ mEmojiPickerShowBtn->setToggleState(false);
+ }
+}
+
+void LLFloaterIMSessionTab::onEmojiPickerShowBtnDown()
+{
+ if (mEmojiHelperLastCallbackFrame == LLFrameTimer::getFrameCount())
+ {
+ // Helper gets closed by focus lost event on Down before before onEmojiPickerShowBtnDown
+ // triggers.
+ // If this condition is true, user pressed button and it was 'toggled' during press,
+ // restore 'toggled' state so that button will not reopen helper.
+ mEmojiPickerShowBtn->setToggleState(true);
+ }
+}
+
+void LLFloaterIMSessionTab::onEmojiPickerClosed()
+{
+ if (mEmojiPickerShowBtn->getToggleState())
+ {
+ mEmojiPickerShowBtn->setToggleState(false);
+ // Helper gets closed by focus lost event on Down before onEmojiPickerShowBtnDown
+ // triggers. If mEmojiHelperLastCallbackFrame is set and matches Down, means close
+ // was triggered by user's press.
+ // A bit hacky, but I can't think of a better way to handle this without rewriting helper.
+ mEmojiHelperLastCallbackFrame = LLFrameTimer::getFrameCount();
+ }
}
void LLFloaterIMSessionTab::initEmojiRecentPanel()
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index 367d988f26..6d04d622e1 100644
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -235,6 +235,8 @@ private:
void onEmojiRecentPanelToggleBtnClicked();
void onEmojiPickerShowBtnClicked();
+ void onEmojiPickerShowBtnDown();
+ void onEmojiPickerClosed();
void initEmojiRecentPanel();
void onEmojiRecentPanelFocusReceived();
void onEmojiRecentPanelFocusLost();
@@ -249,6 +251,9 @@ private:
S32 mInputEditorPad;
S32 mChatLayoutPanelHeight;
S32 mFloaterHeight;
+
+ boost::signals2::connection mEmojiCloseConn;
+ U32 mEmojiHelperLastCallbackFrame = { 0 };
};
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 68b9e758a1..faf7ed0d8c 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -60,12 +60,13 @@ LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase*
{
LLSideTrayPanelContainer* panel_container = floater->getChild<LLSideTrayPanelContainer>("panel_container");
LLPanelSnapshot* active_panel = dynamic_cast<LLPanelSnapshot*>(panel_container->getCurrentPanel());
- if (!active_panel)
- {
- LL_WARNS() << "No snapshot active panel, current panel index: " << panel_container->getCurrentPanelIndex() << LL_ENDL;
- }
+
if (!ok_if_not_found)
{
+ if (!active_panel)
+ {
+ LL_WARNS() << "No snapshot active panel, current panel index: " << panel_container->getCurrentPanelIndex() << LL_ENDL;
+ }
llassert_always(active_panel != NULL);
}
return active_panel;
@@ -516,34 +517,13 @@ void LLFloaterSnapshotBase::ImplBase::onClickFilter(LLUICtrl *ctrl, void* data)
}
// static
-void LLFloaterSnapshotBase::ImplBase::onClickUICheck(LLUICtrl *ctrl, void* data)
+void LLFloaterSnapshotBase::ImplBase::onClickDisplaySetting(LLUICtrl* ctrl, void* data)
{
- LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
- gSavedSettings.setBOOL( "RenderUIInSnapshot", check->get() );
-
- LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
+ LLFloaterSnapshot* view = (LLFloaterSnapshot*)data;
if (view)
{
LLSnapshotLivePreview* previewp = view->getPreviewView();
- if(previewp)
- {
- previewp->updateSnapshot(true, true);
- }
- view->impl->updateControls(view);
- }
-}
-
-// static
-void LLFloaterSnapshotBase::ImplBase::onClickHUDCheck(LLUICtrl *ctrl, void* data)
-{
- LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl;
- gSavedSettings.setBOOL( "RenderHUDInSnapshot", check->get() );
-
- LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
- if (view)
- {
- LLSnapshotLivePreview* previewp = view->getPreviewView();
- if(previewp)
+ if (previewp)
{
previewp->updateSnapshot(true, true);
}
@@ -1002,11 +982,9 @@ bool LLFloaterSnapshot::postBuild()
mSucceessLblPanel = getChild<LLUICtrl>("succeeded_panel");
mFailureLblPanel = getChild<LLUICtrl>("failed_panel");
- childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this);
- getChild<LLUICtrl>("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot"));
-
- childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this);
- getChild<LLUICtrl>("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot"));
+ childSetCommitCallback("ui_check", ImplBase::onClickDisplaySetting, this);
+ childSetCommitCallback("balance_check", ImplBase::onClickDisplaySetting, this);
+ childSetCommitCallback("hud_check", ImplBase::onClickDisplaySetting, this);
((Impl*)impl)->setAspectRatioCheckboxValue(this, gSavedSettings.getBOOL("KeepAspectForSnapshot"));
diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h
index 6df851b839..186d9c41cf 100644
--- a/indra/newview/llfloatersnapshot.h
+++ b/indra/newview/llfloatersnapshot.h
@@ -103,8 +103,7 @@ public:
static void onClickAutoSnap(LLUICtrl *ctrl, void* data);
static void onClickNoPost(LLUICtrl *ctrl, void* data);
static void onClickFilter(LLUICtrl *ctrl, void* data);
- static void onClickUICheck(LLUICtrl *ctrl, void* data);
- static void onClickHUDCheck(LLUICtrl *ctrl, void* data);
+ static void onClickDisplaySetting(LLUICtrl *ctrl, void* data);
static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data);
virtual LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true) = 0;
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 30ed723db6..a798ba31ee 100755
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -486,8 +486,11 @@ void LLFloaterWorldMap::onOpen(const LLSD& key)
const LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
LLInventoryModelBackgroundFetch::instance().start(landmark_folder_id);
- mLocationEditor->setFocus( true);
- gFocusMgr.triggerFocusFlash();
+ if (hasFocus())
+ {
+ mLocationEditor->setFocus( true);
+ gFocusMgr.triggerFocusFlash();
+ }
buildAvatarIDList();
buildLandmarkIDLists();
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index ba9c9fa13f..34d96aa024 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -46,7 +46,7 @@
//
// Globals
//
-static GroupChatListener sGroupChatListener;
+static LLGroupChatListener sGroupChatListener;
class LLGroupHandler : public LLCommandHandler
{
diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp
index 4e8bcc4f7a..4c02511268 100644
--- a/indra/newview/llimprocessing.cpp
+++ b/indra/newview/llimprocessing.cpp
@@ -422,6 +422,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
U8 *binary_bucket,
S32 binary_bucket_size,
LLHost &sender,
+ LLSD metadata,
LLUUID aux_id)
{
LLChat chat;
@@ -451,6 +452,28 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
bool is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT &&
LLMuteList::isLinden(name);
+ /***
+ * The simulator may have flagged this sender as a bot, if the viewer would like to display
+ * the chat text in a different color or font, the below code is how the viewer can
+ * tell if the sender is a bot.
+ *-----------------------------------------------------
+ bool is_bot = false;
+ if (metadata.has("sender"))
+ { // The server has identified this sender as a bot.
+ is_bot = metadata["sender"]["bot"].asBoolean();
+ }
+ *-----------------------------------------------------
+ */
+
+ std::string notice_name;
+ LLSD notice_args;
+ if (metadata.has("notice"))
+ { // The server has injected a notice into the IM conversation.
+ // These will be things like bot notifications, etc.
+ notice_name = metadata["notice"]["id"].asString();
+ notice_args = metadata["notice"]["data"];
+ }
+
chat.mMuted = is_muted;
chat.mFromID = from_id;
chat.mFromName = name;
@@ -544,7 +567,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
}
else
{
- // standard message, not from system
+ // standard message, server may have injected a notice into the conversation.
std::string saved;
if (offline == IM_OFFLINE)
{
@@ -579,8 +602,17 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
region_message = true;
}
}
- gIMMgr->addMessage(
- session_id,
+
+ std::string real_name;
+
+ if (!notice_name.empty())
+ { // The simulator has injected some sort of notice into the conversation.
+ // findString will only replace the contents of buffer if the notice_id is found.
+ LLTrans::findString(buffer, notice_name, notice_args);
+ real_name = SYSTEM_FROM;
+ }
+
+ gIMMgr->addMessage(session_id,
from_id,
name,
buffer,
@@ -591,7 +623,9 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
region_id,
position,
region_message,
- timestamp);
+ timestamp,
+ LLUUID::null,
+ real_name);
}
else
{
@@ -1619,6 +1653,12 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url)
from_group = message_data["from_group"].asString() == "Y";
}
+ LLSD metadata;
+ if (message_data.has("metadata"))
+ {
+ metadata = message_data["metadata"];
+ }
+
EInstantMessage dialog = static_cast<EInstantMessage>(message_data["dialog"].asInteger());
LLUUID session_id = message_data["transaction-id"].asUUID();
if (session_id.isNull() && dialog == IM_FROM_TASK)
@@ -1646,6 +1686,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url)
local_bin_bucket.data(),
S32(local_bin_bucket.size()),
local_sender,
+ metadata,
message_data["asset_id"].asUUID());
});
diff --git a/indra/newview/llimprocessing.h b/indra/newview/llimprocessing.h
index 030d28b198..66ffc59ae0 100644
--- a/indra/newview/llimprocessing.h
+++ b/indra/newview/llimprocessing.h
@@ -48,6 +48,7 @@ public:
U8 *binary_bucket,
S32 binary_bucket_size,
LLHost &sender,
+ LLSD metadata,
LLUUID aux_id = LLUUID::null);
// Either receives list of offline messages from 'ReadOfflineMsgs' capability
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 756f3b33ed..77451a6248 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -3144,9 +3144,16 @@ void LLIMMgr::addMessage(
const LLUUID& region_id,
const LLVector3& position,
bool is_region_msg,
- U32 timestamp) // May be zero
+ U32 timestamp, // May be zero
+ LLUUID display_id,
+ std::string_view display_name)
{
LLUUID other_participant_id = target_id;
+ std::string message_display_name = (display_name.empty()) ? from : std::string(display_name);
+ if (display_id.isNull() && (display_name.empty()))
+ {
+ display_id = other_participant_id;
+ }
LLUUID new_session_id = session_id;
if (new_session_id.isNull())
@@ -3243,7 +3250,7 @@ void LLIMMgr::addMessage(
}
//Play sound for new conversations
- if (!skip_message & !gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation")))
+ if (!skip_message && !gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation")))
{
make_ui_sound("UISndNewIncomingIMSession");
}
@@ -3257,7 +3264,7 @@ void LLIMMgr::addMessage(
if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message)
{
- LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg, true, is_region_msg, timestamp);
+ LLIMModel::instance().addMessage(new_session_id, message_display_name, display_id, msg, true, is_region_msg, timestamp);
}
// Open conversation floater if offline messages are present
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 61776860e3..23f90ca795 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -368,7 +368,9 @@ public:
const LLUUID& region_id = LLUUID::null,
const LLVector3& position = LLVector3::zero,
bool is_region_msg = false,
- U32 timestamp = 0);
+ U32 timestamp = 0,
+ LLUUID display_id = LLUUID::null,
+ std::string_view display_name = "");
void addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 15190854a2..ee530c163b 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -104,7 +104,6 @@ static bool check_item(const LLUUID& item_id,
LLInventoryFilter* filter);
// Helper functions
-
bool isAddAction(const std::string& action)
{
return ("wear" == action || "attach" == action || "activate" == action);
@@ -2697,7 +2696,12 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit");
if (is_movable && move_is_into_outfit)
{
- if (mUUID == my_outifts_id)
+ if ((inv_cat->getPreferredType() != LLFolderType::FT_NONE) && (inv_cat->getPreferredType() != LLFolderType::FT_OUTFIT))
+ {
+ tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
+ is_movable = false;
+ }
+ else if (mUUID == my_outifts_id)
{
if (source != LLToolDragAndDrop::SOURCE_AGENT || move_is_from_marketplacelistings)
{
@@ -2714,13 +2718,39 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
is_movable = false;
}
}
- else if(getCategory() && getCategory()->getPreferredType() == LLFolderType::FT_NONE)
+ else if (!getCategory())
{
- is_movable = ((inv_cat->getPreferredType() == LLFolderType::FT_NONE) || (inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT));
+ is_movable = false;
+ tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
}
else
{
- is_movable = false;
+ EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id);
+ EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
+ if ((dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) && inv_res == MY_OUTFITS_OUTFIT)
+ {
+ is_movable = false;
+ tooltip_msg = LLTrans::getString("TooltipCantMoveOutfitIntoOutfit");
+ }
+ else if (dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT)
+ {
+ is_movable = false;
+ tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
+ }
+ else if (dest_res == MY_OUTFITS_SUBFOLDER && inv_res == MY_OUTFITS_SUBOUTFIT)
+ {
+ is_movable = false;
+ tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
+ }
+ else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear))
+ {
+ is_movable = true;
+ }
+ else
+ {
+ is_movable = false;
+ tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
+ }
}
}
if (is_movable && move_is_into_current_outfit && is_link)
@@ -2912,9 +2942,77 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
if (mUUID == my_outifts_id)
{
- // Category can contains objects,
- // create a new folder and populate it with links to original objects
- dropToMyOutfits(inv_cat, cb);
+ EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
+ if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT)
+ {
+ LLInvFVBridge::changeCategoryParent(
+ model,
+ (LLViewerInventoryCategory*)inv_cat,
+ mUUID,
+ false);
+ if (cb) cb->fire(inv_cat->getUUID());
+ }
+ else
+ {
+ // Moving from inventory
+ // create a new folder and populate it with links to original objects
+ dropToMyOutfits(inv_cat, cb);
+ }
+ }
+ else if (move_is_into_my_outfits)
+ {
+ EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id);
+ EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
+ switch (inv_res)
+ {
+ case MY_OUTFITS_NO:
+ // Moning from outside outfits into outfits
+ if (dest_res == MY_OUTFITS_SUBFOLDER)
+ {
+ // turn it into outfit
+ dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_OUTFIT, cb);
+ }
+ else
+ {
+ // or link it?
+ dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_NONE, cb);
+ }
+ break;
+ case MY_OUTFITS_SUBFOLDER:
+ case MY_OUTFITS_OUTFIT:
+ // only permit moving subfodlers and outfits into other subfolders
+ if (dest_res == MY_OUTFITS_SUBFOLDER)
+ {
+ LLInvFVBridge::changeCategoryParent(
+ model,
+ (LLViewerInventoryCategory*)inv_cat,
+ mUUID,
+ false);
+ if (cb) cb->fire(inv_cat->getUUID());
+ }
+ else
+ {
+ assert(false); // mot permitted, shouldn't have accepted
+ }
+ break;
+ case MY_OUTFITS_SUBOUTFIT:
+ if (dest_res == MY_OUTFITS_SUBOUTFIT || dest_res == MY_OUTFITS_OUTFIT)
+ {
+ LLInvFVBridge::changeCategoryParent(
+ model,
+ (LLViewerInventoryCategory*)inv_cat,
+ mUUID,
+ false);
+ if (cb) cb->fire(inv_cat->getUUID());
+ }
+ else
+ {
+ assert(false); // mot permitted, shouldn't have accepted
+ }
+ break;
+ default:
+ break;
+ }
}
// if target is current outfit folder we use link
else if (move_is_into_current_outfit &&
@@ -4008,6 +4106,7 @@ void LLFolderBridge::perform_pasteFromClipboard()
{
if (!move_is_into_my_outfits && item && can_move_to_outfit(item, move_is_into_current_outfit))
{
+ // todo: this is going to create dupplicate folders?
dropToOutfit(item, move_is_into_current_outfit, cb);
}
else if (move_is_into_my_outfits && LLAssetType::AT_CATEGORY == obj->getType())
@@ -4016,7 +4115,23 @@ void LLFolderBridge::perform_pasteFromClipboard()
U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit");
if (cat && can_move_to_my_outfits(model, cat, max_items_to_wear))
{
- dropToMyOutfits(cat, cb);
+ if (mUUID == my_outifts_id)
+ {
+ dropToMyOutfits(cat, cb);
+ }
+ else if (move_is_into_my_outfits)
+ {
+ EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id);
+ if (res == MY_OUTFITS_SUBFOLDER)
+ {
+ // turn it into outfit
+ dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_OUTFIT, cb);
+ }
+ else
+ {
+ dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_NONE, cb);
+ }
+ }
}
else
{
@@ -4256,6 +4371,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
if (outfits_id == mUUID)
{
+ items.push_back(std::string("New Outfit Folder"));
items.push_back(std::string("New Outfit"));
}
@@ -4349,63 +4465,83 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
else if(isAgentInventory()) // do not allow creating in library
{
LLViewerInventoryCategory *cat = getCategory();
- // BAP removed protected check to re-enable standard ops in untyped folders.
- // Not sure what the right thing is to do here.
- if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
- {
- if (!isInboxFolder() // don't allow creation in inbox
- && outfits_id != mUUID)
- {
- bool menu_items_added = false;
- // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
- if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
- {
- items.push_back(std::string("New Folder"));
- menu_items_added = true;
- }
- if (!isMarketplaceListingsFolder())
- {
- items.push_back(std::string("upload_def"));
- items.push_back(std::string("create_new"));
- items.push_back(std::string("New Script"));
- items.push_back(std::string("New Note"));
- items.push_back(std::string("New Gesture"));
- items.push_back(std::string("New Material"));
- items.push_back(std::string("New Clothes"));
- items.push_back(std::string("New Body Parts"));
- items.push_back(std::string("New Settings"));
- if (!LLEnvironment::instance().isInventoryEnabled())
- {
- disabled_items.push_back("New Settings");
- }
- }
- else
- {
- items.push_back(std::string("New Listing Folder"));
- }
- if (menu_items_added)
- {
- items.push_back(std::string("Create Separator"));
- }
- }
- getClipboardEntries(false, items, disabled_items, flags);
- }
- else
+
+ if (cat)
{
- // Want some but not all of the items from getClipboardEntries for outfits.
- if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT))
+ if (cat->getPreferredType() == LLFolderType::FT_OUTFIT)
{
+ // Want some but not all of the items from getClipboardEntries for outfits.
items.push_back(std::string("Rename"));
items.push_back(std::string("thumbnail"));
addDeleteContextMenuOptions(items, disabled_items);
// EXT-4030: disallow deletion of currently worn outfit
- const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
+ const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();
if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory()))
{
disabled_items.push_back(std::string("Delete"));
}
}
+ else if (outfits_id == mUUID)
+ {
+ getClipboardEntries(false, items, disabled_items, flags);
+ }
+ else if (!isCOFFolder())
+ {
+ EMyOutfitsSubfolderType in_my_outfits = myoutfit_object_subfolder_type(model, mUUID, outfits_id);
+ if (in_my_outfits != MY_OUTFITS_NO)
+ {
+ if (in_my_outfits == MY_OUTFITS_SUBFOLDER)
+ {
+ // Not inside an outfit, but inside 'my outfits'
+ items.push_back(std::string("New Outfit"));
+ items.push_back(std::string("New Outfit Folder"));
+ }
+ items.push_back(std::string("Rename"));
+ items.push_back(std::string("thumbnail"));
+
+ addDeleteContextMenuOptions(items, disabled_items);
+ }
+ else
+ {
+ if (!isInboxFolder() // don't allow creation in inbox
+ && outfits_id != mUUID)
+ {
+ bool menu_items_added = false;
+ // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
+ if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
+ {
+ items.push_back(std::string("New Folder"));
+ menu_items_added = true;
+ }
+ if (!isMarketplaceListingsFolder())
+ {
+ items.push_back(std::string("upload_def"));
+ items.push_back(std::string("create_new"));
+ items.push_back(std::string("New Script"));
+ items.push_back(std::string("New Note"));
+ items.push_back(std::string("New Gesture"));
+ items.push_back(std::string("New Material"));
+ items.push_back(std::string("New Clothes"));
+ items.push_back(std::string("New Body Parts"));
+ items.push_back(std::string("New Settings"));
+ if (!LLEnvironment::instance().isInventoryEnabled())
+ {
+ disabled_items.push_back("New Settings");
+ }
+ }
+ else
+ {
+ items.push_back(std::string("New Listing Folder"));
+ }
+ if (menu_items_added)
+ {
+ items.push_back(std::string("Create Separator"));
+ }
+ }
+ getClipboardEntries(false, items, disabled_items, flags);
+ }
+ }
}
if (model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT) == mUUID)
@@ -4560,7 +4696,11 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t&
if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren() && (type != LLFolderType::FT_OUTFIT))
{
- items.push_back(std::string("Ungroup folder items"));
+ const LLUUID my_outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+ if (!gInventory.isObjectDescendentOf(mUUID, my_outfits))
+ {
+ items.push_back(std::string("Ungroup folder items"));
+ }
}
}
else
@@ -5333,13 +5473,24 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLI
// Note: creation will take time, so passing folder id to callback is slightly unreliable,
// but so is collecting and passing descendants' ids
inventory_func_type func = boost::bind(outfitFolderCreatedCallback, inv_cat->getUUID(), _1, cb, mInventoryPanel);
- gInventory.createNewCategory(dest_id,
+ getInventoryModel()->createNewCategory(dest_id,
LLFolderType::FT_OUTFIT,
inv_cat->getName(),
func,
inv_cat->getThumbnailUUID());
}
+void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLFolderType::EType preferred_type, LLPointer<LLInventoryCallback> cb)
+{
+ const LLUUID outfits_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+ inventory_func_type func = boost::bind(outfitFolderCreatedCallback, inv_cat->getUUID(), _1, cb, mInventoryPanel);
+ getInventoryModel()->createNewCategory(dest_id,
+ preferred_type,
+ inv_cat->getName(),
+ func,
+ inv_cat->getThumbnailUUID());
+}
+
void LLFolderBridge::outfitFolderCreatedCallback(LLUUID cat_source_id,
LLUUID cat_dest_id,
LLPointer<LLInventoryCallback> cb,
@@ -5513,7 +5664,9 @@ bool LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
else if (user_confirm && (move_is_into_current_outfit || move_is_into_outfit))
{
- accept = can_move_to_outfit(inv_item, move_is_into_current_outfit);
+ EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id);
+ // don't allow items in my outfits' subfodlers, only in outfits and outfit's subfolders
+ accept = res != MY_OUTFITS_SUBFOLDER && can_move_to_outfit(inv_item, move_is_into_current_outfit);
}
else if (user_confirm && (move_is_into_favorites || move_is_into_landmarks))
{
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 3e7f74384b..a101c7368a 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -369,6 +369,7 @@ protected:
void dropToFavorites(LLInventoryItem* inv_item, LLPointer<LLInventoryCallback> cb = NULL);
void dropToOutfit(LLInventoryItem* inv_item, bool move_is_into_current_outfit, LLPointer<LLInventoryCallback> cb = NULL);
void dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLInventoryCallback> cb = NULL);
+ void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest, LLFolderType::EType preferred_type, LLPointer<LLInventoryCallback> cb = NULL);
//--------------------------------------------------------------------
// Messy hacks for handling folder options
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 1ccefa3212..7fff88fba7 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -2493,6 +2493,40 @@ bool can_share_item(const LLUUID& item_id)
return can_share;
}
+
+EMyOutfitsSubfolderType myoutfit_object_subfolder_type(
+ LLInventoryModel* model,
+ const LLUUID& obj_id,
+ const LLUUID& my_outfits_id)
+{
+ if (obj_id == my_outfits_id) return MY_OUTFITS_NO;
+
+ const LLViewerInventoryCategory* test_cat = model->getCategory(obj_id);
+ if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT)
+ {
+ return MY_OUTFITS_OUTFIT;
+ }
+ while (test_cat)
+ {
+ if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT)
+ {
+ return MY_OUTFITS_SUBOUTFIT;
+ }
+
+ const LLUUID& parent_id = test_cat->getParentUUID();
+ if (parent_id.isNull())
+ {
+ return MY_OUTFITS_NO;
+ }
+ if (parent_id == my_outfits_id)
+ {
+ return MY_OUTFITS_SUBFOLDER;
+ }
+ test_cat = model->getCategory(parent_id);
+ }
+
+ return MY_OUTFITS_NO;
+}
///----------------------------------------------------------------------------
/// LLMarketplaceValidator implementations
///----------------------------------------------------------------------------
@@ -2621,6 +2655,11 @@ bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(const LLInventoryIte
return false;
}
+bool LLIsFolderType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
+{
+ return cat && cat->getPreferredType() == mType;
+}
+
bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
{
if(mType == LLAssetType::AT_CATEGORY)
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 13a64f21dc..0ab045f2a0 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -121,6 +121,18 @@ std::string get_searchable_creator_name(LLInventoryModel* model, const LLUUID& i
std::string get_searchable_UUID(LLInventoryModel* model, const LLUUID& item_id);
bool can_share_item(const LLUUID& item_id);
+enum EMyOutfitsSubfolderType
+{
+ MY_OUTFITS_NO,
+ MY_OUTFITS_SUBFOLDER,
+ MY_OUTFITS_OUTFIT,
+ MY_OUTFITS_SUBOUTFIT,
+};
+EMyOutfitsSubfolderType myoutfit_object_subfolder_type(
+ LLInventoryModel* model,
+ const LLUUID& obj_id,
+ const LLUUID& my_outfits_id);
+
/** Miscellaneous global functions
** **
*******************************************************************************/
@@ -234,6 +246,24 @@ protected:
// the type is the type passed in during construction.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLIsFolderType : public LLInventoryCollectFunctor
+{
+public:
+ LLIsFolderType(LLFolderType::EType type) : mType(type) {}
+ virtual ~LLIsFolderType() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item);
+protected:
+ LLFolderType::EType mType;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLIsType
+//
+// Implementation of a LLInventoryCollectFunctor which returns true if
+// the type is the type passed in during construction.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
class LLIsType : public LLInventoryCollectFunctor
{
public:
diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp
index c4f93cee98..eb47af85fd 100644
--- a/indra/newview/llinventorygallery.cpp
+++ b/indra/newview/llinventorygallery.cpp
@@ -60,10 +60,12 @@ static LLPanelInjector<LLInventoryGallery> t_inventory_gallery("inventory_galler
const S32 GALLERY_ITEMS_PER_ROW_MIN = 2;
const S32 FAST_LOAD_THUMBNAIL_TRSHOLD = 50; // load folders below this value immediately
+
// Helper dnd functions
bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, bool drop, std::string& tooltip_msg, bool is_link);
bool dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, bool drop, std::string& tooltip_msg, bool user_confirm);
void dropToMyOutfits(LLInventoryCategory* inv_cat);
+void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLFolderType::EType preferred_type);
class LLGalleryPanel: public LLPanel
{
@@ -3745,7 +3747,12 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit");
if (is_movable && move_is_into_outfit)
{
- if (dest_id == my_outifts_id)
+ if ((inv_cat->getPreferredType() != LLFolderType::FT_NONE) && (inv_cat->getPreferredType() != LLFolderType::FT_OUTFIT))
+ {
+ tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
+ is_movable = false;
+ }
+ else if (dest_id == my_outifts_id)
{
if (source != LLToolDragAndDrop::SOURCE_AGENT || move_is_from_marketplacelistings)
{
@@ -3762,13 +3769,39 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
is_movable = false;
}
}
- else if (dest_cat && dest_cat->getPreferredType() == LLFolderType::FT_NONE)
+ else if (!dest_cat)
{
- is_movable = ((inv_cat->getPreferredType() == LLFolderType::FT_NONE) || (inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT));
+ is_movable = false;
+ tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
}
else
{
- is_movable = false;
+ EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, dest_id, my_outifts_id);
+ EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
+ if ((dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) && inv_res == MY_OUTFITS_OUTFIT)
+ {
+ is_movable = false;
+ tooltip_msg = LLTrans::getString("TooltipCantMoveOutfitIntoOutfit");
+ }
+ else if (dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT)
+ {
+ is_movable = false;
+ tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
+ }
+ else if (dest_res == MY_OUTFITS_SUBFOLDER && inv_res == MY_OUTFITS_SUBOUTFIT)
+ {
+ is_movable = false;
+ tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
+ }
+ else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear))
+ {
+ is_movable = true;
+ }
+ else
+ {
+ is_movable = false;
+ tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit");
+ }
}
}
if (is_movable && move_is_into_current_outfit && is_link)
@@ -3894,9 +3927,70 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,
if (dest_id == my_outifts_id)
{
- // Category can contains objects,
- // create a new folder and populate it with links to original objects
- dropToMyOutfits(inv_cat);
+ EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
+ if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT)
+ {
+ gInventory.changeCategoryParent(
+ (LLViewerInventoryCategory*)inv_cat,
+ dest_id,
+ move_is_into_trash);
+ }
+ else
+ {
+ // Category can contains objects,
+ // create a new folder and populate it with links to original objects
+ dropToMyOutfits(inv_cat);
+ }
+ }
+ else if (move_is_into_my_outfits)
+ {
+ EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, dest_id, my_outifts_id);
+ EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id);
+ switch (inv_res)
+ {
+ case MY_OUTFITS_NO:
+ // Moning from outside outfits into outfits
+ if (dest_res == MY_OUTFITS_SUBFOLDER)
+ {
+ // turn it into outfit
+ dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_OUTFIT);
+ }
+ else
+ {
+ dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_NONE);
+ }
+ break;
+ case MY_OUTFITS_SUBFOLDER:
+ case MY_OUTFITS_OUTFIT:
+ // only permit moving subfodlers and outfits into other subfolders
+ if (dest_res == MY_OUTFITS_SUBFOLDER)
+ {
+ gInventory.changeCategoryParent(
+ (LLViewerInventoryCategory*)inv_cat,
+ dest_id,
+ move_is_into_trash);
+ }
+ else
+ {
+ assert(false); // mot permitted, shouldn't have accepted
+ }
+ break;
+ case MY_OUTFITS_SUBOUTFIT:
+ if (dest_res == MY_OUTFITS_SUBOUTFIT || dest_res == MY_OUTFITS_OUTFIT)
+ {
+ gInventory.changeCategoryParent(
+ (LLViewerInventoryCategory*)inv_cat,
+ dest_id,
+ move_is_into_trash);
+ }
+ else
+ {
+ assert(false); // mot permitted, shouldn't have accepted
+ }
+ break;
+ default:
+ break;
+ }
}
// if target is current outfit folder we use link
else if (move_is_into_current_outfit &&
@@ -4041,3 +4135,11 @@ void dropToMyOutfits(LLInventoryCategory* inv_cat)
inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1);
gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID());
}
+
+void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID &dest_id, LLFolderType::EType preferred_type)
+{
+ // Note: creation will take time, so passing folder id to callback is slightly unreliable,
+ // but so is collecting and passing descendants' ids
+ inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1);
+ gInventory.createNewCategory(dest_id, preferred_type, inv_cat->getName(), func, inv_cat->getThumbnailUUID());
+}
diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp
index 0c35a7f695..3fede1a001 100644
--- a/indra/newview/llinventorygallerymenu.cpp
+++ b/indra/newview/llinventorygallerymenu.cpp
@@ -607,7 +607,9 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
bool is_trash = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH));
bool is_in_trash = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH));
bool is_lost_and_found = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND));
- bool is_outfits= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS));
+ const LLUUID my_outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+ bool is_outfits= (selected_id == my_outfits);
+ bool is_in_outfits = is_outfits || gInventory.isObjectDescendentOf(selected_id, my_outfits);
bool is_in_favorites = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
//bool is_favorites= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE));
@@ -746,7 +748,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
}
else
{
- if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits)
+ if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits && !is_in_outfits)
{
LLViewerInventoryCategory* category = gInventory.getCategory(selected_id);
if (!category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(category))
@@ -792,15 +794,26 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men
items.push_back(std::string("Set favorite folder"));
- if(is_outfits && !isRootFolder())
+ if(is_outfits)
{
- items.push_back(std::string("New Outfit"));
+ EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(&gInventory, selected_id, my_outfits);
+ if (res != MY_OUTFITS_OUTFIT && res != MY_OUTFITS_SUBOUTFIT)
+ {
+ items.push_back(std::string("New Outfit"));
+ items.push_back(std::string("New Outfit Folder"));
+ }
+ items.push_back(std::string("Delete"));
+ items.push_back(std::string("Rename"));
+ if (!get_is_category_and_children_removable(&gInventory, selected_id, false))
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
}
items.push_back(std::string("Subfolder Separator"));
- if (!is_system_folder && !isRootFolder())
+ if (!is_system_folder && !isRootFolder() && !is_outfits)
{
- if(has_children && (folder_type != LLFolderType::FT_OUTFIT))
+ if(has_children && (folder_type != LLFolderType::FT_OUTFIT) && !is_in_outfits)
{
items.push_back(std::string("Ungroup folder items"));
}
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index b6ff31a7ed..de1c7a7ed8 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1007,7 +1007,8 @@ void LLInventoryModel::createNewCategory(const LLUUID& parent_id,
return;
}
- if (preferred_type != LLFolderType::FT_NONE)
+ if (preferred_type != LLFolderType::FT_NONE
+ && preferred_type != LLFolderType::FT_OUTFIT)
{
// Ultimately this should only be done for non-singleton
// types. Requires back-end changes to guarantee that others
@@ -3525,7 +3526,7 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
fileXML.close();
- LL_INFOS(LOG_INV) << "Inventory saved: " << cat_count << " categories, " << it_count << " items." << LL_ENDL;
+ LL_INFOS(LOG_INV) << "Inventory saved: " << (S32)cat_count << " categories, " << (S32)it_count << " items." << LL_ENDL;
}
catch (...)
{
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 101ee215cb..e31fbb188a 100644
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -38,6 +38,7 @@
/* image compression headers. */
#include "llimagebmp.h"
#include "llimagetga.h"
+#include "llimagej2c.h"
#include "llimagejpeg.h"
#include "llimagepng.h"
@@ -106,6 +107,10 @@ LLLocalBitmap::LLLocalBitmap(std::string filename)
{
mExtension = ET_IMG_JPG;
}
+ else if (temp_exten == "j2c" || temp_exten == "jp2")
+ {
+ mExtension = ET_IMG_J2C;
+ }
else if (temp_exten == "png")
{
mExtension = ET_IMG_PNG;
@@ -354,6 +359,21 @@ bool LLLocalBitmap::decodeBitmap(LLPointer<LLImageRaw> rawimg)
break;
}
+ case ET_IMG_J2C:
+ {
+ LLPointer<LLImageJ2C> jpeg_image = new LLImageJ2C;
+ if (jpeg_image->load(mFilename))
+ {
+ jpeg_image->setDiscardLevel(0);
+ if (jpeg_image->decode(rawimg, 0.0f))
+ {
+ rawimg->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT);
+ decode_successful = true;
+ }
+ }
+ break;
+ }
+
case ET_IMG_PNG:
{
LLPointer<LLImagePNG> png_image = new LLImagePNG;
diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h
index de2dcb3467..6c9d65e3b6 100644
--- a/indra/newview/lllocalbitmaps.h
+++ b/indra/newview/lllocalbitmaps.h
@@ -89,6 +89,7 @@ class LLLocalBitmap
ET_IMG_BMP,
ET_IMG_TGA,
ET_IMG_JPG,
+ ET_IMG_J2C,
ET_IMG_PNG
};
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index a8c6f69425..48c80842b9 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1210,6 +1210,12 @@ void LLMeshRepoThread::run()
LL_WARNS(LOG_MESH) << "Convex decomposition unable to be quit." << LL_ENDL;
}
}
+void LLMeshRepoThread::cleanup()
+{
+ mShuttingDown = true;
+ mSignal->broadcast();
+ mMeshThreadPool->close();
+}
// Mutex: LLMeshRepoThread::mMutex must be held on entry
void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id)
@@ -1493,6 +1499,11 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
[mesh_id, buffer, size]
()
{
+ if (gMeshRepo.mThread->isShuttingDown())
+ {
+ delete[] buffer;
+ return;
+ }
if (!gMeshRepo.mThread->skinInfoReceived(mesh_id, buffer, size))
{
// either header is faulty or something else overwrote the cache
@@ -1993,6 +2004,11 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
[params, mesh_id, lod, buffer, size]
()
{
+ if (gMeshRepo.mThread->isShuttingDown())
+ {
+ delete[] buffer;
+ return;
+ }
if (gMeshRepo.mThread->lodReceived(params, lod, buffer, size) == MESH_OK)
{
LL_DEBUGS(LOG_MESH) << "Mesh/Cache: Mesh body for ID " << mesh_id << " - was retrieved from the cache." << LL_ENDL;
@@ -3792,6 +3808,11 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
[shrd_handler, data, data_size]
()
{
+ if (gMeshRepo.mThread->isShuttingDown())
+ {
+ delete[] data;
+ return;
+ }
LLMeshLODHandler* handler = (LLMeshLODHandler * )shrd_handler.get();
handler->processLod(data, data_size);
delete[] data;
@@ -3905,6 +3926,11 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /*
[shrd_handler, data, data_size]
()
{
+ if (gMeshRepo.mThread->isShuttingDown())
+ {
+ delete[] data;
+ return;
+ }
LLMeshSkinInfoHandler* handler = (LLMeshSkinInfoHandler*)shrd_handler.get();
handler->processSkin(data, data_size);
delete[] data;
@@ -4127,8 +4153,7 @@ void LLMeshRepository::shutdown()
mUploads[i]->discard() ; //discard the uploading requests.
}
- mThread->mSignal->broadcast();
- mThread->mMeshThreadPool->close();
+ mThread->cleanup();
while (!mThread->isStopped())
{
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 0d9da32e27..b9acb3573f 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -515,6 +515,8 @@ public:
~LLMeshRepoThread();
virtual void run();
+ void cleanup();
+ bool isShuttingDown() { return mShuttingDown; }
void lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
@@ -583,6 +585,7 @@ private:
U8* getDiskCacheBuffer(S32 size);
S32 mDiskCacheBufferSize = 0;
U8* mDiskCacheBuffer = nullptr;
+ bool mShuttingDown = false;
};
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index 64ea1710f5..d8e05e1d01 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -132,20 +132,21 @@ std::string getLodSuffix(S32 lod)
return suffix;
}
-void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut)
+static bool FindModel(const LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut)
{
- for (auto scene_iter = scene.begin(); scene_iter != scene.end(); scene_iter++)
+ for (const auto& scene_pair : scene)
{
- for (auto model_iter = scene_iter->second.begin(); model_iter != scene_iter->second.end(); model_iter++)
+ for (const auto& model_iter : scene_pair.second)
{
- if (model_iter->mModel && (model_iter->mModel->mLabel == name_to_match))
+ if (model_iter.mModel && (model_iter.mModel->mLabel == name_to_match))
{
- baseModelOut = model_iter->mModel;
- matOut = scene_iter->first;
- return;
+ baseModelOut = model_iter.mModel;
+ matOut = scene_pair.first;
+ return true;
}
}
}
+ return false;
}
//-----------------------------------------------------------------------------
@@ -319,10 +320,8 @@ void LLModelPreview::rebuildUploadData()
mat *= scale_mat;
- for (auto model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
- { // for each instance with said transform applied
- LLModelInstance instance = *model_iter;
-
+ for (LLModelInstance& instance : iter->second)
+ { //for each instance with said transform applied
LLModel* base_model = instance.mModel;
if (base_model && !requested_name.empty())
@@ -354,7 +353,7 @@ void LLModelPreview::rebuildUploadData()
}
else
{
- //Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for
+ // Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for
extensionLOD = mPhysicsSearchLOD;
}
@@ -365,9 +364,9 @@ void LLModelPreview::rebuildUploadData()
name_to_match += toAdd;
}
- FindModel(mScene[i], name_to_match, lod_model, transform);
+ bool found = FindModel(mScene[i], name_to_match, lod_model, transform);
- if (!lod_model && i != LLModel::LOD_PHYSICS)
+ if (!found && i != LLModel::LOD_PHYSICS)
{
if (mImporterDebug)
{
@@ -380,7 +379,7 @@ void LLModelPreview::rebuildUploadData()
}
int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i;
- while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model)
+ for (; searchLOD <= LLModel::LOD_HIGH; ++searchLOD)
{
std::string name_to_match = instance.mLabel;
llassert(!name_to_match.empty());
@@ -394,8 +393,8 @@ void LLModelPreview::rebuildUploadData()
// See if we can find an appropriately named model in LOD 'searchLOD'
//
- FindModel(mScene[searchLOD], name_to_match, lod_model, transform);
- searchLOD++;
+ if (FindModel(mScene[searchLOD], name_to_match, lod_model, transform))
+ break;
}
}
}
@@ -1174,8 +1173,7 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)
LLModel* found_model = NULL;
LLMatrix4 transform;
- FindModel(mBaseScene, loaded_name, found_model, transform);
- if (found_model)
+ if (FindModel(mBaseScene, loaded_name, found_model, transform))
{ // don't rename correctly named models (even if they are placed in a wrong order)
name_based = true;
}
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 6e666b8a4b..9d8493549d 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -819,6 +819,50 @@ void LLOutfitListBase::observerCallback(const LLUUID& category_id)
refreshList(category_id);
}
+class LLIsOutfitListFolder : public LLInventoryCollectFunctor
+{
+public:
+ LLIsOutfitListFolder()
+ {
+ mOutfitsId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
+ }
+ virtual ~LLIsOutfitListFolder() {}
+
+ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override
+ {
+ if (cat)
+ {
+ if (cat->getPreferredType() == LLFolderType::FT_OUTFIT)
+ {
+ return true;
+ }
+ if (cat->getPreferredType() == LLFolderType::FT_NONE
+ && cat->getParentUUID() == mOutfitsId)
+ {
+ LLViewerInventoryCategory* inv_cat = dynamic_cast<LLViewerInventoryCategory*>(cat);
+ if (inv_cat && inv_cat->getDescendentCount() > 3)
+ {
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+ gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items);
+ if (cats->empty() // protection against outfits inside
+ && items->size() > 3) // eyes, skin, hair and shape are required
+ {
+ // For now assume this to be an old style outfit, not a subfolder
+ // but ideally no such 'outfits' should be left in My Outfits
+ // Todo: stop counting FT_NONE as outfits,
+ // convert obvious outfits into FT_OUTFIT
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+protected:
+ LLUUID mOutfitsId;
+};
+
void LLOutfitListBase::refreshList(const LLUUID& category_id)
{
bool wasNull = mRefreshListState.CategoryUUID.isNull();
@@ -828,13 +872,13 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id)
LLInventoryModel::item_array_t item_array;
// Collect all sub-categories of a given category.
- LLIsType is_category(LLAssetType::AT_CATEGORY);
+ LLIsOutfitListFolder is_outfit;
gInventory.collectDescendentsIf(
category_id,
cat_array,
item_array,
LLInventoryModel::EXCLUDE_TRASH,
- is_category);
+ is_outfit);
// Memorize item names for each UUID
std::map<LLUUID, std::string> names;
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 4ada9c445c..3a164ec94b 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -3644,7 +3644,7 @@ void LLPanelFace::onCommitRepeatsPerMeter()
bool identical_scale_t = false;
LLSelectedTE::getObjectScaleS(obj_scale_s, identical_scale_s);
- LLSelectedTE::getObjectScaleS(obj_scale_t, identical_scale_t);
+ LLSelectedTE::getObjectScaleT(obj_scale_t, identical_scale_t);
if (gSavedSettings.getBOOL("SyncMaterialSettings"))
{
@@ -5151,6 +5151,7 @@ void LLPanelFace::LLSelectedTEMaterial::getMaxSpecularRepeats(F32& repeats, bool
LLMaterial* mat = object->getTE(face)->getMaterialParams().get();
U32 s_axis = VX;
U32 t_axis = VY;
+ LLPrimitive::getTESTAxes(face, &s_axis, &t_axis);
F32 repeats_s = 1.0f;
F32 repeats_t = 1.0f;
if (mat)
@@ -5175,6 +5176,7 @@ void LLPanelFace::LLSelectedTEMaterial::getMaxNormalRepeats(F32& repeats, bool&
LLMaterial* mat = object->getTE(face)->getMaterialParams().get();
U32 s_axis = VX;
U32 t_axis = VY;
+ LLPrimitive::getTESTAxes(face, &s_axis, &t_axis);
F32 repeats_s = 1.0f;
F32 repeats_t = 1.0f;
if (mat)
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 7b562337a3..b1c8b5f36a 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -777,7 +777,7 @@ void LLPanelPrimMediaControls::draw()
else if(mFadeTimer.getStarted())
{
F32 time = mFadeTimer.getElapsedTimeF32();
- alpha *= llmax(lerp(1.0f, 0.0f, time / mControlFadeTime), 0.0f);
+ alpha *= llmax(lerp(1.f, 0.f, time / mControlFadeTime), 0.0f);
if(time >= mControlFadeTime)
{
diff --git a/indra/newview/llpanelprofileclassifieds.h b/indra/newview/llpanelprofileclassifieds.h
index 42cd5f8975..2e6b7c4428 100644
--- a/indra/newview/llpanelprofileclassifieds.h
+++ b/indra/newview/llpanelprofileclassifieds.h
@@ -157,17 +157,17 @@ public:
void setParcelId(const LLUUID& id) { mParcelId = id; }
- LLUUID getParcelId() { return mParcelId; }
+ LLUUID getParcelId() const { return mParcelId; }
void setSimName(const std::string& sim_name) { mSimName = sim_name; }
- std::string getSimName() { return mSimName; }
+ std::string getSimName() const { return mSimName; }
void setFromSearch(bool val) { mFromSearch = val; }
- bool fromSearch() { return mFromSearch; }
+ bool fromSearch() const { return mFromSearch; }
- bool getInfoLoaded() { return mInfoLoaded; }
+ bool getInfoLoaded() const { return mInfoLoaded; }
void setInfoLoaded(bool loaded) { mInfoLoaded = loaded; }
@@ -175,9 +175,9 @@ public:
void resetDirty() override;
- bool isNew() { return mIsNew; }
+ bool isNew() const { return mIsNew; }
- bool isNewWithErrors() { return mIsNewWithErrors; }
+ bool isNewWithErrors() const { return mIsNewWithErrors; }
bool canClose();
@@ -191,10 +191,10 @@ public:
bool getAutoRenew();
- S32 getPriceForListing() { return mPriceForListing; }
+ S32 getPriceForListing() const { return mPriceForListing; }
void setEditMode(bool edit_mode);
- bool getEditMode() {return mEditMode;}
+ bool getEditMode() const { return mEditMode; }
static void setClickThrough(
const LLUUID& classified_id,
diff --git a/indra/newview/llpanelsnapshot.cpp b/indra/newview/llpanelsnapshot.cpp
index 32c9f6f402..56c0294dbe 100644
--- a/indra/newview/llpanelsnapshot.cpp
+++ b/indra/newview/llpanelsnapshot.cpp
@@ -37,6 +37,7 @@
// newview
#include "llsidetraypanelcontainer.h"
+#include "llsnapshotlivepreview.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llagentbenefits.h"
@@ -99,6 +100,17 @@ void LLPanelSnapshot::onOpen(const LLSD& key)
{
getParentByType<LLFloater>()->notify(LLSD().with("image-format-change", true));
}
+
+ // If resolution is set to "Current Window", force a snapshot update
+ // each time a snapshot panel is opened to determine the correct
+ // image size (and upload fee) depending on the snapshot type.
+ if (mSnapshotFloater && getChild<LLUICtrl>(getImageSizeComboName())->getValue().asString() == "[i0,i0]")
+ {
+ if (LLSnapshotLivePreview* preview = mSnapshotFloater->getPreviewView())
+ {
+ preview->mForceUpdateSnapshot = true;
+ }
+ }
}
LLSnapshotModel::ESnapshotFormat LLPanelSnapshot::getImageFormat() const
diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp
index 96b17acc40..b81b891685 100644
--- a/indra/newview/llpanelsnapshotinventory.cpp
+++ b/indra/newview/llpanelsnapshotinventory.cpp
@@ -42,77 +42,35 @@
/**
* The panel provides UI for saving snapshot as an inventory texture.
*/
-class LLPanelSnapshotInventoryBase
- : public LLPanelSnapshot
-{
- LOG_CLASS(LLPanelSnapshotInventoryBase);
-
-public:
- LLPanelSnapshotInventoryBase();
-
- /*virtual*/ bool postBuild();
-protected:
- void onSend();
- /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType();
-};
-
class LLPanelSnapshotInventory
- : public LLPanelSnapshotInventoryBase
+ : public LLPanelSnapshot
{
LOG_CLASS(LLPanelSnapshotInventory);
public:
LLPanelSnapshotInventory();
- /*virtual*/ bool postBuild();
- /*virtual*/ void onOpen(const LLSD& key);
+ bool postBuild() override;
+ void onOpen(const LLSD& key) override;
void onResolutionCommit(LLUICtrl* ctrl);
private:
- /*virtual*/ std::string getWidthSpinnerName() const { return "inventory_snapshot_width"; }
- /*virtual*/ std::string getHeightSpinnerName() const { return "inventory_snapshot_height"; }
- /*virtual*/ std::string getAspectRatioCBName() const { return "inventory_keep_aspect_check"; }
- /*virtual*/ std::string getImageSizeComboName() const { return "texture_size_combo"; }
- /*virtual*/ std::string getImageSizePanelName() const { return LLStringUtil::null; }
- /*virtual*/ void updateControls(const LLSD& info);
-
-};
-
-class LLPanelOutfitSnapshotInventory
- : public LLPanelSnapshotInventoryBase
-{
- LOG_CLASS(LLPanelOutfitSnapshotInventory);
-
-public:
- LLPanelOutfitSnapshotInventory();
- /*virtual*/ bool postBuild();
- /*virtual*/ void onOpen(const LLSD& key);
+ std::string getWidthSpinnerName() const override { return "inventory_snapshot_width"; }
+ std::string getHeightSpinnerName() const override { return "inventory_snapshot_height"; }
+ std::string getAspectRatioCBName() const override { return "inventory_keep_aspect_check"; }
+ std::string getImageSizeComboName() const override { return "texture_size_combo"; }
+ std::string getImageSizePanelName() const override { return LLStringUtil::null; }
+ LLSnapshotModel::ESnapshotType getSnapshotType() override;
+ void updateControls(const LLSD& info) override;
-private:
- /*virtual*/ std::string getWidthSpinnerName() const { return ""; }
- /*virtual*/ std::string getHeightSpinnerName() const { return ""; }
- /*virtual*/ std::string getAspectRatioCBName() const { return ""; }
- /*virtual*/ std::string getImageSizeComboName() const { return "texture_size_combo"; }
- /*virtual*/ std::string getImageSizePanelName() const { return LLStringUtil::null; }
- /*virtual*/ void updateControls(const LLSD& info);
-
- /*virtual*/ void cancel();
+ void onSend();
+ void updateUploadCost();
+ S32 calculateUploadCost();
};
static LLPanelInjector<LLPanelSnapshotInventory> panel_class1("llpanelsnapshotinventory");
-static LLPanelInjector<LLPanelOutfitSnapshotInventory> panel_class2("llpaneloutfitsnapshotinventory");
-
-LLPanelSnapshotInventoryBase::LLPanelSnapshotInventoryBase()
-{
-}
-
-bool LLPanelSnapshotInventoryBase::postBuild()
-{
- return LLPanelSnapshot::postBuild();
-}
-
-LLSnapshotModel::ESnapshotType LLPanelSnapshotInventoryBase::getSnapshotType()
+LLSnapshotModel::ESnapshotType LLPanelSnapshotInventory::getSnapshotType()
{
return LLSnapshotModel::SNAPSHOT_TEXTURE;
}
@@ -130,12 +88,14 @@ bool LLPanelSnapshotInventory::postBuild()
getChild<LLSpinCtrl>(getHeightSpinnerName())->setAllowEdit(false);
getChild<LLUICtrl>(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshotInventory::onResolutionCommit, this, _1));
- return LLPanelSnapshotInventoryBase::postBuild();
+ return LLPanelSnapshot::postBuild();
}
// virtual
void LLPanelSnapshotInventory::onOpen(const LLSD& key)
{
+ updateUploadCost();
+
LLPanelSnapshot::onOpen(key);
}
@@ -144,6 +104,8 @@ void LLPanelSnapshotInventory::updateControls(const LLSD& info)
{
const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true;
getChild<LLUICtrl>("save_btn")->setEnabled(have_snapshot);
+
+ updateUploadCost();
}
void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl)
@@ -153,21 +115,9 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl)
getChild<LLSpinCtrl>(getHeightSpinnerName())->setVisible(!current_window_selected);
}
-void LLPanelSnapshotInventoryBase::onSend()
+void LLPanelSnapshotInventory::onSend()
{
- S32 w = 0;
- S32 h = 0;
-
- if( mSnapshotFloater )
- {
- LLSnapshotLivePreview* preview = mSnapshotFloater->getPreviewView();
- if( preview )
- {
- preview->getSize(w, h);
- }
- }
-
- S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(w, h);
+ S32 expected_upload_cost = calculateUploadCost();
if (can_afford_transaction(expected_upload_cost))
{
if (mSnapshotFloater)
@@ -188,36 +138,24 @@ void LLPanelSnapshotInventoryBase::onSend()
}
}
-LLPanelOutfitSnapshotInventory::LLPanelOutfitSnapshotInventory()
+void LLPanelSnapshotInventory::updateUploadCost()
{
- mCommitCallbackRegistrar.add("Inventory.SaveOutfitPhoto", boost::bind(&LLPanelOutfitSnapshotInventory::onSend, this));
- mCommitCallbackRegistrar.add("Inventory.SaveOutfitCancel", boost::bind(&LLPanelOutfitSnapshotInventory::cancel, this));
+ getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", calculateUploadCost()));
}
-// virtual
-bool LLPanelOutfitSnapshotInventory::postBuild()
+S32 LLPanelSnapshotInventory::calculateUploadCost()
{
- return LLPanelSnapshotInventoryBase::postBuild();
-}
-
-// virtual
-void LLPanelOutfitSnapshotInventory::onOpen(const LLSD& key)
-{
- getChild<LLUICtrl>("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost()));
- LLPanelSnapshot::onOpen(key);
-}
-
-// virtual
-void LLPanelOutfitSnapshotInventory::updateControls(const LLSD& info)
-{
- const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true;
- getChild<LLUICtrl>("save_btn")->setEnabled(have_snapshot);
-}
+ S32 w = 0;
+ S32 h = 0;
-void LLPanelOutfitSnapshotInventory::cancel()
-{
if (mSnapshotFloater)
{
- mSnapshotFloater->closeFloater();
+ if (LLSnapshotLivePreview* preview = mSnapshotFloater->getPreviewView())
+ {
+ w = preview->getEncodedImageWidth();
+ h = preview->getEncodedImageHeight();
+ }
}
+
+ return LLAgentBenefitsMgr::current().getTextureUploadCost(w, h);
}
diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp
index 366030c0fa..57759fbcaa 100644
--- a/indra/newview/llpanelsnapshotlocal.cpp
+++ b/indra/newview/llpanelsnapshotlocal.cpp
@@ -47,18 +47,18 @@ class LLPanelSnapshotLocal
public:
LLPanelSnapshotLocal();
- /*virtual*/ bool postBuild();
- /*virtual*/ void onOpen(const LLSD& key);
+ bool postBuild() override;
+ void onOpen(const LLSD& key) override;
private:
- /*virtual*/ std::string getWidthSpinnerName() const { return "local_snapshot_width"; }
- /*virtual*/ std::string getHeightSpinnerName() const { return "local_snapshot_height"; }
- /*virtual*/ std::string getAspectRatioCBName() const { return "local_keep_aspect_check"; }
- /*virtual*/ std::string getImageSizeComboName() const { return "local_size_combo"; }
- /*virtual*/ std::string getImageSizePanelName() const { return "local_image_size_lp"; }
- /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const;
- /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType();
- /*virtual*/ void updateControls(const LLSD& info);
+ std::string getWidthSpinnerName() const override { return "local_snapshot_width"; }
+ std::string getHeightSpinnerName() const override { return "local_snapshot_height"; }
+ std::string getAspectRatioCBName() const override { return "local_keep_aspect_check"; }
+ std::string getImageSizeComboName() const override { return "local_size_combo"; }
+ std::string getImageSizePanelName() const override { return "local_image_size_lp"; }
+ LLSnapshotModel::ESnapshotFormat getImageFormat() const override;
+ LLSnapshotModel::ESnapshotType getSnapshotType() override;
+ void updateControls(const LLSD& info) override;
S32 mLocalFormat;
diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp
index 962d3bba16..05cd9e7b3a 100644
--- a/indra/newview/llpanelsnapshotoptions.cpp
+++ b/indra/newview/llpanelsnapshotoptions.cpp
@@ -30,12 +30,8 @@
#include "llsidetraypanelcontainer.h"
#include "llfloatersnapshot.h" // FIXME: create a snapshot model
-#include "llsnapshotlivepreview.h"
#include "llfloaterreg.h"
-#include "llagentbenefits.h"
-
-
/**
* Provides several ways to save a snapshot.
*/
@@ -46,12 +42,9 @@ class LLPanelSnapshotOptions
public:
LLPanelSnapshotOptions();
- ~LLPanelSnapshotOptions();
- /*virtual*/ bool postBuild();
- /*virtual*/ void onOpen(const LLSD& key);
+ bool postBuild() override;
private:
- void updateUploadCost();
void openPanel(const std::string& panel_name);
void onSaveToProfile();
void onSaveToEmail();
@@ -71,10 +64,6 @@ LLPanelSnapshotOptions::LLPanelSnapshotOptions()
mCommitCallbackRegistrar.add("Snapshot.SaveToComputer", boost::bind(&LLPanelSnapshotOptions::onSaveToComputer, this));
}
-LLPanelSnapshotOptions::~LLPanelSnapshotOptions()
-{
-}
-
// virtual
bool LLPanelSnapshotOptions::postBuild()
{
@@ -82,30 +71,6 @@ bool LLPanelSnapshotOptions::postBuild()
return LLPanel::postBuild();
}
-// virtual
-void LLPanelSnapshotOptions::onOpen(const LLSD& key)
-{
- updateUploadCost();
-}
-
-void LLPanelSnapshotOptions::updateUploadCost()
-{
- S32 w = 0;
- S32 h = 0;
-
- if( mSnapshotFloater )
- {
- LLSnapshotLivePreview* preview = mSnapshotFloater->getPreviewView();
- if( preview )
- {
- preview->getSize(w, h);
- }
- }
-
- S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(w, h);
- getChild<LLUICtrl>("save_to_inventory_btn")->setLabelArg("[AMOUNT]", llformat("%d", upload_cost));
-}
-
void LLPanelSnapshotOptions::openPanel(const std::string& panel_name)
{
LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent());
diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp
index 23e8789e3f..f3dfdc9250 100644
--- a/indra/newview/llpanelsnapshotpostcard.cpp
+++ b/indra/newview/llpanelsnapshotpostcard.cpp
@@ -56,18 +56,18 @@ class LLPanelSnapshotPostcard
public:
LLPanelSnapshotPostcard();
- /*virtual*/ bool postBuild();
- /*virtual*/ void onOpen(const LLSD& key);
+ bool postBuild() override;
+ void onOpen(const LLSD& key) override;
private:
- /*virtual*/ std::string getWidthSpinnerName() const { return "postcard_snapshot_width"; }
- /*virtual*/ std::string getHeightSpinnerName() const { return "postcard_snapshot_height"; }
- /*virtual*/ std::string getAspectRatioCBName() const { return "postcard_keep_aspect_check"; }
- /*virtual*/ std::string getImageSizeComboName() const { return "postcard_size_combo"; }
- /*virtual*/ std::string getImageSizePanelName() const { return "postcard_image_size_lp"; }
- /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG; }
- /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType();
- /*virtual*/ void updateControls(const LLSD& info);
+ std::string getWidthSpinnerName() const override { return "postcard_snapshot_width"; }
+ std::string getHeightSpinnerName() const override { return "postcard_snapshot_height"; }
+ std::string getAspectRatioCBName() const override { return "postcard_keep_aspect_check"; }
+ std::string getImageSizeComboName() const override { return "postcard_size_combo"; }
+ std::string getImageSizePanelName() const override { return "postcard_image_size_lp"; }
+ LLSnapshotModel::ESnapshotFormat getImageFormat() const override { return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG; }
+ LLSnapshotModel::ESnapshotType getSnapshotType() override;
+ void updateControls(const LLSD& info) override;
bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response);
static void sendPostcardFinished(LLSD result);
diff --git a/indra/newview/llpanelsnapshotprofile.cpp b/indra/newview/llpanelsnapshotprofile.cpp
index aa257dea9e..b533d7bbbc 100644
--- a/indra/newview/llpanelsnapshotprofile.cpp
+++ b/indra/newview/llpanelsnapshotprofile.cpp
@@ -49,17 +49,17 @@ class LLPanelSnapshotProfile
public:
LLPanelSnapshotProfile();
- /*virtual*/ bool postBuild();
- /*virtual*/ void onOpen(const LLSD& key);
+ bool postBuild() override;
+ void onOpen(const LLSD& key) override;
private:
- /*virtual*/ std::string getWidthSpinnerName() const { return "profile_snapshot_width"; }
- /*virtual*/ std::string getHeightSpinnerName() const { return "profile_snapshot_height"; }
- /*virtual*/ std::string getAspectRatioCBName() const { return "profile_keep_aspect_check"; }
- /*virtual*/ std::string getImageSizeComboName() const { return "profile_size_combo"; }
- /*virtual*/ std::string getImageSizePanelName() const { return "profile_image_size_lp"; }
- /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; }
- /*virtual*/ void updateControls(const LLSD& info);
+ std::string getWidthSpinnerName() const override { return "profile_snapshot_width"; }
+ std::string getHeightSpinnerName() const override { return "profile_snapshot_height"; }
+ std::string getAspectRatioCBName() const override { return "profile_keep_aspect_check"; }
+ std::string getImageSizeComboName() const override { return "profile_size_combo"; }
+ std::string getImageSizePanelName() const override { return "profile_image_size_lp"; }
+ LLSnapshotModel::ESnapshotFormat getImageFormat() const override { return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; }
+ void updateControls(const LLSD& info) override;
void onSend();
};
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 951dc45a78..2fbdbeaf59 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -576,32 +576,48 @@ void LLPanelVolume::getState( )
return object->getMaterial();
}
} func;
- bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_code );
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ bool material_same = selection->getSelectedTEValue( &func, material_code );
std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright");
- if (editable && single_volume && material_same)
+
+ bool enable_material = editable && single_volume && material_same;
+ LLCachedControl<bool> edit_linked(gSavedSettings, "EditLinkedParts", false);
+ if (!enable_material && !edit_linked())
{
- mComboMaterial->setEnabled( true );
- if (material_code == LL_MCODE_LIGHT)
+ LLViewerObject* root = selection->getPrimaryObject();
+ while (root && !root->isAvatar() && root->getParent())
{
- if (mComboMaterial->getItemCount() == mComboMaterialItemCount)
+ LLViewerObject* parent = (LLViewerObject*)root->getParent();
+ if (parent->isAvatar())
{
- mComboMaterial->add(LEGACY_FULLBRIGHT_DESC);
+ break;
}
- mComboMaterial->setSimple(LEGACY_FULLBRIGHT_DESC);
+ root = parent;
}
- else
+ if (root)
{
- if (mComboMaterial->getItemCount() != mComboMaterialItemCount)
- {
- mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC);
- }
+ material_code = root->getMaterial();
+ }
+ }
- mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code)));
+ mComboMaterial->setEnabled(enable_material);
+
+ if (material_code == LL_MCODE_LIGHT)
+ {
+ if (mComboMaterial->getItemCount() == mComboMaterialItemCount)
+ {
+ mComboMaterial->add(LEGACY_FULLBRIGHT_DESC);
}
+ mComboMaterial->setSimple(LEGACY_FULLBRIGHT_DESC);
}
else
{
- mComboMaterial->setEnabled( false );
+ if (mComboMaterial->getItemCount() != mComboMaterialItemCount)
+ {
+ mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC);
+ }
+
+ mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code)));
}
// Physics properties
diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp
index 86291708b0..e5c84728fe 100644
--- a/indra/newview/llphysicsmotion.cpp
+++ b/indra/newview/llphysicsmotion.cpp
@@ -646,18 +646,17 @@ bool LLPhysicsMotion::onUpdate(F32 time)
velocity_new_local = 0;
}
- // Check for NaN values. A NaN value is detected if the variables doesn't equal itself.
- // If NaN, then reset everything.
- if ((mPosition_local != mPosition_local) ||
- (mVelocity_local != mVelocity_local) ||
- (position_new_local != position_new_local))
+ // Check for NaN values. If NaN, then reset everything.
+ if (llisnan(mPosition_local) ||
+ llisnan(mVelocity_local) ||
+ llisnan(position_new_local))
{
- position_new_local = 0;
- mVelocity_local = 0;
- mVelocityJoint_local = 0;
- mAccelerationJoint_local = 0;
- mPosition_local = 0;
- mPosition_world = LLVector3(0,0,0);
+ position_new_local = 0.f;
+ mVelocity_local = 0.f;
+ mVelocityJoint_local = 0.f;
+ mAccelerationJoint_local = 0.f;
+ mPosition_local = 0.f;
+ mPosition_world = LLVector3(0.f,0.f,0.f);
}
const F32 position_new_local_clamped = llclamp(position_new_local,
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 02a4c7fb26..c2aa4925bd 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -703,9 +703,10 @@ void LLScriptEdCore::sync()
}
}
-bool LLScriptEdCore::hasChanged()
+bool LLScriptEdCore::hasChanged() const
{
- if (!mEditor) return false;
+ if (!mEditor)
+ return false;
return ((!mEditor->isPristine() || mEnableSave) && mHasScriptData);
}
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index 70ee1a4274..0bbe540207 100644
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -143,7 +143,7 @@ public:
void setItemRemoved(bool script_removed){mScriptRemoved = script_removed;};
void setAssetID( const LLUUID& asset_id){ mAssetID = asset_id; };
- LLUUID getAssetID() { return mAssetID; }
+ LLUUID getAssetID() const { return mAssetID; }
bool isFontSizeChecked(const LLSD &userdata);
void onChangeFontSize(const LLSD &size_name);
@@ -155,7 +155,7 @@ public:
void onBtnDynamicHelp();
void onBtnUndoChanges();
- bool hasChanged();
+ bool hasChanged() const;
void selectFirstError();
@@ -211,7 +211,6 @@ class LLScriptEdContainer : public LLPreview
public:
LLScriptEdContainer(const LLSD& key);
- LLScriptEdContainer(const LLSD& key, const bool live);
bool handleKeyHere(KEY key, MASK mask);
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 1876cd3086..41895d7d6a 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -3139,6 +3139,8 @@ void LLSelectMgr::adjustTexturesByScale(bool send_to_sim, bool stretch)
F32 scale_x = 1;
F32 scale_y = 1;
+ F32 offset_x = 0;
+ F32 offset_y = 0;
for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
{
@@ -3155,6 +3157,21 @@ void LLSelectMgr::adjustTexturesByScale(bool send_to_sim, bool stretch)
scale_y = scale_ratio.mV[t_axis] * object_scale.mV[t_axis];
}
material->mTextureTransform[i].mScale.set(scale_x, scale_y);
+
+ LLVector2 scales = selectNode->mGLTFScales[te_num][i];
+ LLVector2 offsets = selectNode->mGLTFOffsets[te_num][i];
+ F64 int_part = 0;
+ offset_x = (F32)modf((offsets[VX] + (scales[VX] - scale_x)) / 2, &int_part);
+ if (offset_x < 0)
+ {
+ offset_x++;
+ }
+ offset_y = (F32)modf((offsets[VY] + (scales[VY] - scale_y)) / 2, &int_part);
+ if (offset_y < 0)
+ {
+ offset_y++;
+ }
+ material->mTextureTransform[i].mOffset.set(offset_x, offset_y);
}
const LLGLTFMaterial* base_material = tep->getGLTFMaterial();
@@ -6909,6 +6926,8 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query)
{
mTextureScaleRatios.clear();
mGLTFScaleRatios.clear();
+ mGLTFScales.clear();
+ mGLTFOffsets.clear();
if (mObject.notNull())
{
@@ -6949,6 +6968,8 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query)
F32 scale_x = 1;
F32 scale_y = 1;
std::vector<LLVector3> material_v_vec;
+ std::vector<LLVector2> material_scales_vec;
+ std::vector<LLVector2> material_offset_vec;
for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
{
if (material)
@@ -6956,12 +6977,16 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query)
LLGLTFMaterial::TextureTransform& transform = material->mTextureTransform[i];
scale_x = transform.mScale[VX];
scale_y = transform.mScale[VY];
+ material_scales_vec.push_back(transform.mScale);
+ material_offset_vec.push_back(transform.mOffset);
}
else
{
// Not having an override doesn't mean that there is no material
scale_x = 1;
scale_y = 1;
+ material_scales_vec.emplace_back(scale_x, scale_y);
+ material_offset_vec.emplace_back(0.f, 0.f);
}
if (tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR)
@@ -6977,6 +7002,8 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query)
material_v_vec.push_back(material_v);
}
mGLTFScaleRatios.push_back(material_v_vec);
+ mGLTFScales.push_back(material_scales_vec);
+ mGLTFOffsets.push_back(material_offset_vec);
}
}
}
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 0dbdc133e3..792a37297f 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -242,6 +242,8 @@ public:
gltf_materials_vec_t mSavedGLTFOverrideMaterials;
std::vector<LLVector3> mTextureScaleRatios;
std::vector< std::vector<LLVector3> > mGLTFScaleRatios;
+ std::vector< std::vector<LLVector2> > mGLTFScales;
+ std::vector< std::vector<LLVector2> > mGLTFOffsets;
std::vector<LLVector3> mSilhouetteVertices; // array of vertices to render silhouette of object
std::vector<LLVector3> mSilhouetteNormals; // array of normals to render silhouette of object
bool mSilhouetteExists; // need to generate silhouette?
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index ea95d71b27..68b4ab381a 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -694,6 +694,7 @@ bool LLSnapshotLivePreview::onIdle( void* snapshot_preview )
static LLCachedControl<bool> freeze_time(gSavedSettings, "FreezeTime", false);
static LLCachedControl<bool> use_freeze_frame(gSavedSettings, "UseFreezeFrame", false);
static LLCachedControl<bool> render_ui(gSavedSettings, "RenderUIInSnapshot", false);
+ static LLCachedControl<bool> render_balance(gSavedSettings, "RenderBalanceInSnapshot", false);
static LLCachedControl<bool> render_hud(gSavedSettings, "RenderHUDInSnapshot", false);
static LLCachedControl<bool> render_no_post(gSavedSettings, "RenderSnapshotNoPost", false);
@@ -750,6 +751,7 @@ bool LLSnapshotLivePreview::onIdle( void* snapshot_preview )
render_hud,
false,
render_no_post,
+ render_balance,
previewp->mSnapshotBufferType,
previewp->getMaxImageSize()))
{
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index 1bab602364..bda75c16e7 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -759,6 +759,10 @@ void LLStatusBar::updateBalancePanelPosition()
balance_bg_view->setShape(balance_bg_rect);
}
+void LLStatusBar::setBalanceVisible(bool visible)
+{
+ mBoxBalance->setVisible(visible);
+}
// Implements secondlife:///app/balance/request to request a L$ balance
// update via UDP message system. JC
diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h
index 7e1ecf08ca..86c1ccd051 100644
--- a/indra/newview/llstatusbar.h
+++ b/indra/newview/llstatusbar.h
@@ -93,6 +93,8 @@ public:
S32 getSquareMetersCommitted() const;
S32 getSquareMetersLeft() const;
+ void setBalanceVisible(bool visible);
+
LLPanelNearByMedia* getNearbyMediaPanel() { return mPanelNearByMedia; }
private:
diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp
index 4315c4c6b0..6f99da5957 100644
--- a/indra/newview/llsurfacepatch.cpp
+++ b/indra/newview/llsurfacepatch.cpp
@@ -201,7 +201,7 @@ LLVector2 LLSurfacePatch::getTexCoords(const U32 x, const U32 y) const
void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 *vertex, LLVector3 *normal,
- LLVector2 *tex1) const
+ LLVector2* tex0, LLVector2 *tex1) const
{
if (!mSurfacep || !mSurfacep->getRegion() || !mSurfacep->getGridsPerEdge() || !mVObjp)
{
@@ -210,6 +210,7 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3
llassert_always(vertex && normal && tex1);
U32 surface_stride = mSurfacep->getGridsPerEdge();
+ U32 texture_stride = mSurfacep->getGridsPerEdge() - 1;
U32 point_offset = x + y*surface_stride;
*normal = getNormal(x, y);
@@ -220,6 +221,12 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3
pos_agent.mV[VZ] = *(mDataZ + point_offset);
*vertex = pos_agent-mVObjp->getRegion()->getOriginAgent();
+ // tex0 is used for ownership overlay
+ LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent();
+ LLVector3 tex_pos = rel_pos * (1.f / (texture_stride * mSurfacep->getMetersPerGrid()));
+ tex0->mV[0] = tex_pos.mV[0];
+ tex0->mV[1] = tex_pos.mV[1];
+
tex1->mV[0] = mSurfacep->getRegion()->getCompositionXY(llfloor(mOriginRegion.mV[0])+x, llfloor(mOriginRegion.mV[1])+y);
const F32 xyScale = 4.9215f*7.f; //0.93284f;
diff --git a/indra/newview/llsurfacepatch.h b/indra/newview/llsurfacepatch.h
index f4831487c1..505fc8c24c 100644
--- a/indra/newview/llsurfacepatch.h
+++ b/indra/newview/llsurfacepatch.h
@@ -116,7 +116,7 @@ public:
void calcNormalFlat(LLVector3& normal_out, const U32 x, const U32 y, const U32 index /* 0 or 1 */);
void eval(const U32 x, const U32 y, const U32 stride,
- LLVector3 *vertex, LLVector3 *normal, LLVector2 *tex1) const;
+ LLVector3 *vertex, LLVector3 *normal, LLVector2* tex0, LLVector2 *tex1) const;
diff --git a/indra/newview/llterrainpaintmap.cpp b/indra/newview/llterrainpaintmap.cpp
index 8ccde74c93..c7a82013e4 100644
--- a/indra/newview/llterrainpaintmap.cpp
+++ b/indra/newview/llterrainpaintmap.cpp
@@ -204,8 +204,9 @@ bool LLTerrainPaintMap::bakeHeightNoiseIntoPBRPaintMapRGB(const LLViewerRegion&
{
LLVector3 scratch3;
LLVector3 pos3;
+ LLVector2 tex0_temp;
LLVector2 tex1_temp;
- patch->eval(i, j, stride, &pos3, &scratch3, &tex1_temp);
+ patch->eval(i, j, stride, &pos3, &scratch3, &tex0_temp, &tex1_temp);
(*pos++).set(pos3.mV[VX], pos3.mV[VY], pos3.mV[VZ]);
*tex1++ = tex1_temp;
vertex_total++;
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index be7653c011..442c627d07 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -1347,27 +1347,39 @@ U32 LLTextureCache::openAndReadEntries(std::vector<Entry>& entries)
}
for (U32 idx=0; idx<num_entries; idx++)
{
- Entry entry;
- S32 bytes_read = aprfile->read((void*)(&entry), (S32)sizeof(Entry));
- if (bytes_read < sizeof(Entry))
+ try
+ {
+ Entry entry;
+ S32 bytes_read = aprfile->read((void*)(&entry), (S32)sizeof(Entry));
+ if (bytes_read < sizeof(Entry))
+ {
+ LL_WARNS() << "Corrupted header entries, failed at " << idx << " / " << num_entries << LL_ENDL;
+ return 0;
+ }
+ entries.push_back(entry);
+ // LL_INFOS() << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << LL_ENDL;
+ if (entry.mImageSize > entry.mBodySize)
+ {
+ mHeaderIDMap[entry.mID] = idx;
+ mTexturesSizeMap[entry.mID] = entry.mBodySize;
+ mTexturesSizeTotal += entry.mBodySize;
+ }
+ else
+ {
+ mFreeList.insert(idx);
+ }
+ }
+ catch (std::bad_alloc&)
{
- LL_WARNS() << "Corrupted header entries, failed at " << idx << " / " << num_entries << LL_ENDL;
+ // Too little ram yet very large cache?
+ // Should this actually crash viewer?
+ entries.clear();
+ LL_WARNS() << "Bad alloc trying to read texture entries from cache, mFreeList: " << (S32)mFreeList.size()
+ << ", added entries: " << idx << ", total entries: " << num_entries << LL_ENDL;
closeHeaderEntriesFile();
purgeAllTextures(false);
return 0;
}
- entries.push_back(entry);
-// LL_INFOS() << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << LL_ENDL;
- if(entry.mImageSize > entry.mBodySize)
- {
- mHeaderIDMap[entry.mID] = idx;
- mTexturesSizeMap[entry.mID] = entry.mBodySize;
- mTexturesSizeTotal += entry.mBodySize;
- }
- else
- {
- mFreeList.insert(idx);
- }
}
closeHeaderEntriesFile();
return num_entries;
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index b3b4f43e57..404297c58f 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -541,8 +541,8 @@ void audio_update_wind(bool force_update)
// whereas steady-state avatar walk velocity is only 3.2 m/s.
// Without this the world feels desolate on first login when you are
// standing still.
- const F32 WIND_LEVEL = 0.5f;
- LLVector3 scaled_wind_vec = gWindVec * WIND_LEVEL;
+ static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f);
+ LLVector3 scaled_wind_vec = gWindVec * wind_level;
// Mix in the avatar's motion, subtract because when you walk north,
// the apparent wind moves south.
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 24f1be3d1c..10fa0fd3cd 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -215,11 +215,15 @@ void display_update_camera()
final_far = gSavedSettings.getF32("RenderReflectionProbeDrawDistance");
}
else if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
-
{
final_far *= 0.5f;
}
+ else if (LLViewerTexture::sDesiredDiscardBias > 2.f)
+ {
+ final_far = llmax(32.f, final_far / (LLViewerTexture::sDesiredDiscardBias - 1.f));
+ }
LLViewerCamera::getInstance()->setFar(final_far);
+ LLVOAvatar::sRenderDistance = llclamp(final_far, 16.f, 256.f);
gViewerWindow->setup3DRender();
if (!gCubeSnapshot)
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index ce66dbc03f..9743ec0c59 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -932,6 +932,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
bool render_ui = gSavedSettings.getBOOL("RenderUIInSnapshot");
bool render_hud = gSavedSettings.getBOOL("RenderHUDInSnapshot");
bool render_no_post = gSavedSettings.getBOOL("RenderSnapshotNoPost");
+ bool render_balance = gSavedSettings.getBOOL("RenderBalanceInSnapshot");
bool high_res = gSavedSettings.getBOOL("HighResSnapshot");
if (high_res)
@@ -952,6 +953,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t
render_hud,
false,
render_no_post,
+ render_balance,
LLSnapshotModel::SNAPSHOT_TYPE_COLOR,
high_res ? S32_MAX : MAX_SNAPSHOT_IMAGE_SIZE)) //per side
{
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 5fd820f91d..bdcfec34f6 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2137,6 +2137,21 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
EInstantMessage dialog = (EInstantMessage)d;
LLHost sender = msg->getSender();
+ LLSD metadata;
+ if (msg->getNumberOfBlocksFast(_PREHASH_MetaData) > 0)
+ {
+ S32 metadata_size = msg->getSizeFast(_PREHASH_MetaData, 0, _PREHASH_Data);
+ std::string metadata_buffer;
+ metadata_buffer.resize(metadata_size, 0);
+
+ msg->getBinaryDataFast(_PREHASH_MetaData, _PREHASH_Data, &metadata_buffer[0], metadata_size, 0, metadata_size );
+ std::stringstream metadata_stream(metadata_buffer);
+ if (LLSDSerialize::fromBinary(metadata, metadata_stream, metadata_size) == LLSDParser::PARSE_FAILURE)
+ {
+ metadata.clear();
+ }
+ }
+
LLIMProcessing::processNewMessage(from_id,
from_group,
to_id,
@@ -2151,7 +2166,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
position,
binary_bucket,
binary_bucket_size,
- sender);
+ sender,
+ metadata);
}
void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id)
@@ -5039,6 +5055,7 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem)
false, //UI
gSavedSettings.getBOOL("RenderHUDInSnapshot"),
false,
+ false,
LLSnapshotModel::SNAPSHOT_TYPE_COLOR,
LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
}
@@ -5144,6 +5161,7 @@ static void process_special_alert_messages(const std::string & message)
false,
gSavedSettings.getBOOL("RenderHUDInSnapshot"),
false,
+ false,
LLSnapshotModel::SNAPSHOT_TYPE_COLOR,
LLSnapshotModel::SNAPSHOT_FORMAT_PNG);
}
@@ -6641,7 +6659,6 @@ void process_initiate_download(LLMessageSystem* msg, void**)
(void**)new std::string(viewer_filename));
}
-
void process_script_teleport_request(LLMessageSystem* msg, void**)
{
if (!gSavedSettings.getBOOL("ScriptsCanShowUI")) return;
@@ -6655,6 +6672,11 @@ void process_script_teleport_request(LLMessageSystem* msg, void**)
msg->getString("Data", "SimName", sim_name);
msg->getVector3("Data", "SimPosition", pos);
msg->getVector3("Data", "LookAt", look_at);
+ U32 flags = (BEACON_SHOW_MAP | BEACON_FOCUS_MAP);
+ if (msg->has("Options"))
+ {
+ msg->getU32("Options", "Flags", flags);
+ }
LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance();
if(instance)
@@ -6665,7 +6687,13 @@ void process_script_teleport_request(LLMessageSystem* msg, void**)
<< LL_ENDL;
instance->trackURL(sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]);
- LLFloaterReg::showInstance("world_map", "center");
+ if (flags & BEACON_SHOW_MAP)
+ {
+ bool old_auto_focus = instance->getAutoFocus();
+ instance->setAutoFocus(flags & BEACON_FOCUS_MAP);
+ instance->openFloater("center");
+ instance->setAutoFocus(old_auto_focus);
+ }
}
// remove above two lines and replace with below line
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index c5e81dd179..8d90187e91 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -2325,6 +2325,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
// Set the rotation of the object followed by adjusting for the accumulated angular velocity (llSetTargetOmega)
setRotation(new_rot * mAngularVelocityRot);
+ if ((mFlags & FLAGS_SERVER_AUTOPILOT) && asAvatar() && asAvatar()->isSelf())
+ {
+ gAgent.resetAxes();
+ gAgent.rotate(new_rot);
+ gAgentCamera.resetView();
+ }
setChanged(ROTATED | SILHOUETTE);
}
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 8e6657b4b9..432da2e990 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -42,6 +42,7 @@
// Viewer includes
#include "llagent.h"
#include "llagentaccess.h"
+#include "llcallbacklist.h"
#include "llviewerparcelaskplay.h"
#include "llviewerwindow.h"
#include "llviewercontrol.h"
@@ -1327,12 +1328,12 @@ const S32 LLViewerParcelMgr::getAgentParcelId() const
return INVALID_PARCEL_ID;
}
-void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_agent_region)
+void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel)
{
if(!parcel)
return;
- LLViewerRegion *region = use_agent_region ? gAgent.getRegion() : LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
+ LLViewerRegion *region = LLWorld::getInstance()->getRegionFromID(parcel->getRegionID());
if (!region)
return;
@@ -1676,10 +1677,16 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
// Actually extract the data.
if (parcel)
{
+ // store region_id in the parcel so we can find it again later
+ LLViewerRegion* parcel_region = LLWorld::getInstance()->getRegion(msg->getSender());
+ if (parcel_region)
+ {
+ parcel->setRegionID(parcel_region->getRegionID());
+ }
+
if (local_id == parcel_mgr.mAgentParcel->getLocalID())
{
// Parcels in different regions can have same ids.
- LLViewerRegion* parcel_region = LLWorld::getInstance()->getRegion(msg->getSender());
LLViewerRegion* agent_region = gAgent.getRegion();
if (parcel_region && agent_region && parcel_region->getRegionID() == agent_region->getRegionID())
{
@@ -1750,6 +1757,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
{
instance->mTeleportFinishedSignal(instance->mTeleportInProgressPosition, false);
}
+ instance->postTeleportFinished(instance->mTeleportWithinRegion);
+ instance->mTeleportWithinRegion = false;
}
parcel->setParcelEnvironmentVersion(parcel_environment_version);
LL_DEBUGS("ENVIRONMENT") << "Parcel environment version is " << parcel->getParcelEnvironmentVersion() << LL_ENDL;
@@ -2719,6 +2728,8 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos
// Local teleport. We already have the agent parcel data.
// Emit the signal immediately.
getInstance()->mTeleportFinishedSignal(new_pos, local);
+
+ postTeleportFinished(true);
}
else
{
@@ -2727,12 +2738,14 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos
// Let's wait for the update and then emit the signal.
mTeleportInProgressPosition = new_pos;
mTeleportInProgress = true;
+ mTeleportWithinRegion = local;
}
}
void LLViewerParcelMgr::onTeleportFailed()
{
mTeleportFailedSignal();
+ LLEventPumps::instance().obtain("LLTeleport").post(llsd::map("success", false));
}
bool LLViewerParcelMgr::getTeleportInProgress()
@@ -2740,3 +2753,20 @@ bool LLViewerParcelMgr::getTeleportInProgress()
return mTeleportInProgress // case where parcel data arrives after teleport
|| gAgent.getTeleportState() > LLAgent::TELEPORT_NONE; // For LOCAL, no mTeleportInProgress
}
+
+void LLViewerParcelMgr::postTeleportFinished(bool local)
+{
+ auto post = []()
+ {
+ LLEventPumps::instance().obtain("LLTeleport").post(llsd::map("success", true));
+ };
+ if (local)
+ {
+ static LLCachedControl<F32> teleport_local_delay(gSavedSettings, "TeleportLocalDelay");
+ doAfterInterval(post, teleport_local_delay + 0.5f);
+ }
+ else
+ {
+ post();
+ }
+}
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 974ea39359..1925cd23ed 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -219,7 +219,7 @@ public:
// containing the southwest corner of the selection.
// If want_reply_to_update, simulator will send back a ParcelProperties
// message.
- void sendParcelPropertiesUpdate(LLParcel* parcel, bool use_agent_region = false);
+ void sendParcelPropertiesUpdate(LLParcel* parcel);
// Takes an Access List flag, like AL_ACCESS or AL_BAN
void sendParcelAccessListUpdate(U32 which);
@@ -295,6 +295,8 @@ public:
void onTeleportFailed();
bool getTeleportInProgress();
+ void postTeleportFinished(bool local);
+
static bool isParcelOwnedByAgent(const LLParcel* parcelp, U64 group_proxy_power);
static bool isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power);
@@ -344,7 +346,9 @@ private:
std::vector<LLParcelObserver*> mObservers;
+ // Used to communicate between onTeleportFinished() and processParcelProperties()
bool mTeleportInProgress;
+ bool mTeleportWithinRegion{ false };
LLVector3d mTeleportInProgressPosition;
teleport_finished_signal_t mTeleportFinishedSignal;
teleport_failed_signal_t mTeleportFailedSignal;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 40daac887d..f174e16624 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -1447,6 +1447,15 @@ bool LLViewerTextureList::createUploadFile(const std::string& filename,
image->setLastError("Couldn't load the image to be uploaded.");
return false;
}
+
+ // calcDataSizeJ2C assumes maximum size is 2048 and for bigger images can
+ // assign discard to bring imige to needed size, but upload does the scaling
+ // as needed, so just reset discard.
+ // Assume file is full and has 'discard' 0 data.
+ // Todo: probably a better idea to have some setMaxDimentions in J2C
+ // called when loading from a local file
+ image->setDiscardLevel(0);
+
// Decompress or expand it in a raw image structure
LLPointer<LLImageRaw> raw_image = new LLImageRaw;
if (!image->decode(raw_image, 0.0f))
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ef6409c23b..d32e3f4cbd 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -4862,12 +4862,12 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
}
}
-bool LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, bool show_ui, bool show_hud, bool do_rebuild, LLSnapshotModel::ESnapshotLayerType type, LLSnapshotModel::ESnapshotFormat format)
+bool LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, bool show_ui, bool show_hud, bool do_rebuild, bool show_balance, LLSnapshotModel::ESnapshotLayerType type, LLSnapshotModel::ESnapshotFormat format)
{
LL_INFOS() << "Saving snapshot to: " << filepath << LL_ENDL;
LLPointer<LLImageRaw> raw = new LLImageRaw;
- bool success = rawSnapshot(raw, image_width, image_height, true, false, show_ui, show_hud, do_rebuild);
+ bool success = rawSnapshot(raw, image_width, image_height, true, false, show_ui, show_hud, do_rebuild, show_balance);
if (success)
{
@@ -4928,14 +4928,14 @@ void LLViewerWindow::resetSnapshotLoc() const
bool LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, bool show_ui, bool show_hud, bool do_rebuild, bool no_post, LLSnapshotModel::ESnapshotLayerType type)
{
- return rawSnapshot(raw, preview_width, preview_height, false, false, show_ui, show_hud, do_rebuild, no_post, type);
+ return rawSnapshot(raw, preview_width, preview_height, false, false, show_ui, show_hud, do_rebuild, no_post, gSavedSettings.getBOOL("RenderBalanceInSnapshot"), type);
}
// Saves the image from the screen to a raw image
// Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy
// the results over to the final raw image.
bool LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height,
- bool keep_window_aspect, bool is_texture, bool show_ui, bool show_hud, bool do_rebuild, bool no_post, LLSnapshotModel::ESnapshotLayerType type, S32 max_size)
+ bool keep_window_aspect, bool is_texture, bool show_ui, bool show_hud, bool do_rebuild, bool no_post, bool show_balance, LLSnapshotModel::ESnapshotLayerType type, S32 max_size)
{
if (!raw)
{
@@ -4993,6 +4993,8 @@ bool LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
// If the user wants the UI, limit the output size to the available screen size
image_width = llmin(image_width, window_width);
image_height = llmin(image_height, window_height);
+
+ setBalanceVisible(show_balance);
}
S32 original_width = 0;
@@ -5070,11 +5072,13 @@ bool LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
}
else
{
+ setBalanceVisible(true);
return false;
}
if (raw->isBufferInvalid())
{
+ setBalanceVisible(true);
return false;
}
@@ -5250,6 +5254,7 @@ bool LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
{
send_agent_resume();
}
+ setBalanceVisible(true);
return ret;
}
@@ -5715,6 +5720,14 @@ void LLViewerWindow::setProgressCancelButtonVisible( bool b, const std::string&
}
}
+void LLViewerWindow::setBalanceVisible(bool visible)
+{
+ if (gStatusBar)
+ {
+ gStatusBar->setBalanceVisible(visible);
+ }
+}
+
LLProgressView *LLViewerWindow::getProgressView() const
{
return mProgressView;
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index ac0dfa3fe4..d55c2d3817 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -364,9 +364,11 @@ public:
// snapshot functionality.
// perhaps some of this should move to llfloatershapshot? -MG
- bool saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, bool show_ui = true, bool show_hud = true, bool do_rebuild = false, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::ESnapshotFormat format = LLSnapshotModel::SNAPSHOT_FORMAT_BMP);
- bool rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, bool keep_window_aspect = true, bool is_texture = false,
- bool show_ui = true, bool show_hud = true, bool do_rebuild = false, bool no_post = false, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE);
+ bool saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, bool show_ui = true, bool show_hud = true, bool do_rebuild = false, bool show_balance = true,
+ LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::ESnapshotFormat format = LLSnapshotModel::SNAPSHOT_FORMAT_BMP);
+ bool rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, bool keep_window_aspect = true, bool is_texture = false,
+ bool show_ui = true, bool show_hud = true, bool do_rebuild = false, bool no_post = false, bool show_balance = true,
+ LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE);
bool simpleSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, const int num_render_passes);
@@ -462,6 +464,8 @@ public:
void calcDisplayScale();
static LLRect calcScaledRect(const LLRect & rect, const LLVector2& display_scale);
+ void setBalanceVisible(bool visible);
+
static std::string getLastSnapshotDir();
LLView* getFloaterSnapRegion() { return mFloaterSnapRegion; }
diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp
index da7e18af5c..3119c31613 100644
--- a/indra/newview/llviewerwindowlistener.cpp
+++ b/indra/newview/llviewerwindowlistener.cpp
@@ -100,7 +100,7 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const
}
type = found->second;
}
- bool ok = mViewerWindow->saveSnapshot(event["filename"], width, height, showui, showhud, rebuild, type);
+ bool ok = mViewerWindow->saveSnapshot(event["filename"], width, height, showui, showhud, rebuild, true /*L$ Balance*/, type);
sendReply(LLSDMap("ok", ok), event);
}
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 1cca2161fe..3a52908b8a 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -123,8 +123,8 @@ extern F32 ANIM_SPEED_MAX;
extern F32 ANIM_SPEED_MIN;
extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG;
-const F32 MAX_HOVER_Z = 2.0;
-const F32 MIN_HOVER_Z = -2.0;
+const F32 MAX_HOVER_Z = 3.0;
+const F32 MIN_HOVER_Z = -3.0;
const F32 MIN_ATTACHMENT_COMPLEXITY = 0.f;
const F32 DEFAULT_MAX_ATTACHMENT_COMPLEXITY = 1.0e6f;
@@ -11006,8 +11006,7 @@ void LLVOAvatar::idleUpdateRenderComplexity()
bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf();
if (autotune && !isDead())
{
- static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
- F32 radius = render_far_clip * render_far_clip;
+ F32 radius = sRenderDistance * sRenderDistance;
bool is_nearby = true;
if ((dist_vec_squared(getPositionGlobal(), gAgent.getPositionGlobal()) > radius) &&
@@ -11039,8 +11038,7 @@ void LLVOAvatar::updateNearbyAvatarCount()
if (agent_update_timer.getElapsedTimeF32() > 1.0f)
{
S32 avs_nearby = 0;
- static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
- F32 radius = render_far_clip * render_far_clip;
+ F32 radius = sRenderDistance * sRenderDistance;
for (LLCharacter* character : LLCharacter::sInstances)
{
LLVOAvatar* avatar = (LLVOAvatar*)character;
diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp
index 294d36b0a9..bc326a74a8 100644
--- a/indra/newview/llvosurfacepatch.cpp
+++ b/indra/newview/llvosurfacepatch.cpp
@@ -245,6 +245,7 @@ bool LLVOSurfacePatch::updateLOD()
void LLVOSurfacePatch::getTerrainGeometry(LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
+ LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp)
{
@@ -259,18 +260,21 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider<LLVector3> &verticesp,
updateMainGeometry(facep,
verticesp,
normalsp,
+ texCoords0p,
texCoords1p,
indicesp,
index_offset);
updateNorthGeometry(facep,
verticesp,
normalsp,
+ texCoords0p,
texCoords1p,
indicesp,
index_offset);
updateEastGeometry(facep,
verticesp,
normalsp,
+ texCoords0p,
texCoords1p,
indicesp,
index_offset);
@@ -279,6 +283,7 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider<LLVector3> &verticesp,
void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
+ LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset)
@@ -317,9 +322,10 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
{
x = i * render_stride;
y = j * render_stride;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
}
@@ -381,6 +387,7 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep,
void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
+ LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset)
@@ -414,9 +421,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
x = i * render_stride;
y = 16 - render_stride;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
@@ -425,9 +433,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
{
x = i * render_stride;
y = 16;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
@@ -460,9 +469,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
x = i * render_stride;
y = 16 - render_stride;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
@@ -472,9 +482,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
x = i * render_stride;
y = 16;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
@@ -514,9 +525,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
x = i * north_stride;
y = 16 - render_stride;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
@@ -526,9 +538,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
x = i * north_stride;
y = 16;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
@@ -564,6 +577,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep,
void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
+ LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset)
@@ -592,9 +606,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
x = 16 - render_stride;
y = i * render_stride;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
@@ -603,9 +618,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
{
x = 16;
y = i * render_stride;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
@@ -638,9 +654,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
x = 16 - render_stride;
y = i * render_stride;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
// Iterate through the east patch's points
@@ -649,9 +666,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
x = 16;
y = i * render_stride;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
@@ -690,9 +708,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
x = 16 - render_stride;
y = i * east_stride;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
// Iterate through the east patch's points
@@ -701,9 +720,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep,
x = 16;
y = i * east_stride;
- mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get());
+ mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get());
verticesp++;
normalsp++;
+ texCoords0p++;
texCoords1p++;
}
@@ -1022,12 +1042,14 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
LLStrider<LLVector3> vertices_start;
LLStrider<LLVector3> normals_start;
LLStrider<LLVector4a> tangents_start;
+ LLStrider<LLVector2> texcoords0_start; // ownership overlay
LLStrider<LLVector2> texcoords2_start;
LLStrider<U16> indices_start;
llassert_always(buffer->getVertexStrider(vertices_start));
llassert_always(buffer->getNormalStrider(normals_start));
llassert_always(buffer->getTangentStrider(tangents_start));
+ llassert_always(buffer->getTexCoord0Strider(texcoords0_start));
llassert_always(buffer->getTexCoord1Strider(texcoords2_start));
llassert_always(buffer->getIndexStrider(indices_start));
@@ -1037,6 +1059,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
{
LLStrider<LLVector3> vertices = vertices_start;
LLStrider<LLVector3> normals = normals_start;
+ LLStrider<LLVector2> texcoords0 = texcoords0_start;
LLStrider<LLVector2> texcoords2 = texcoords2_start;
LLStrider<U16> indices = indices_start;
@@ -1049,7 +1072,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group)
facep->setVertexBuffer(buffer);
LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject();
- patchp->getTerrainGeometry(vertices, normals, texcoords2, indices);
+ patchp->getTerrainGeometry(vertices, normals, texcoords0, texcoords2, indices);
indices_index += facep->getIndicesCount();
index_offset += facep->getGeomCount();
diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h
index af5f05774b..c93a58d2d9 100644
--- a/indra/newview/llvosurfacepatch.h
+++ b/indra/newview/llvosurfacepatch.h
@@ -57,6 +57,7 @@ public:
/*virtual*/ void updateFaceSize(S32 idx);
void getTerrainGeometry(LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
+ LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp);
@@ -109,18 +110,21 @@ protected:
void updateMainGeometry(LLFace *facep,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
+ LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset);
void updateNorthGeometry(LLFace *facep,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
+ LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset);
void updateEastGeometry(LLFace *facep,
LLStrider<LLVector3> &verticesp,
LLStrider<LLVector3> &normalsp,
+ LLStrider<LLVector2> &texCoords0p,
LLStrider<LLVector2> &texCoords1p,
LLStrider<U16> &indicesp,
U32 &index_offset);
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index 8ce1a745c3..c708e804b2 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -33,7 +33,6 @@
#include "llagentwearables.h"
#include "llappearancemgr.h"
-#include "llinventoryfunctions.h"
#include "llinventoryicon.h"
#include "llgesturemgr.h"
#include "lltransutil.h"
@@ -41,15 +40,6 @@
#include "llviewermenu.h"
#include "llvoavatarself.h"
-class LLFindOutfitItems : public LLInventoryCollectFunctor
-{
-public:
- LLFindOutfitItems() {}
- virtual ~LLFindOutfitItems() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item);
-};
-
bool LLFindOutfitItems::operator()(LLInventoryCategory* cat,
LLInventoryItem* item)
{
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index 3fe1059176..7a5f29020e 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -32,6 +32,7 @@
#include "llsingleton.h"
// newview
+#include "llinventoryfunctions.h"
#include "llinventoryitemslist.h"
#include "llinventorylistitem.h"
#include "lllistcontextmenu.h"
@@ -507,4 +508,12 @@ protected:
LLWearableType::EType mMenuWearableType;
};
+class LLFindOutfitItems : public LLInventoryCollectFunctor
+{
+public:
+ LLFindOutfitItems() {}
+ virtual ~LLFindOutfitItems() {}
+ virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item);
+};
+
#endif //LL_LLWEARABLEITEMSLIST_H
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 899733ccc3..47e1815bc2 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -1372,10 +1372,8 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positi
F32 LLWorld::getNearbyAvatarsAndMaxGPUTime(std::vector<LLVOAvatar*> &valid_nearby_avs)
{
- static LLCachedControl<F32> render_far_clip(gSavedSettings, "RenderFarClip", 64);
-
F32 nearby_max_complexity = 0;
- F32 radius = render_far_clip * render_far_clip;
+ F32 radius = LLVOAvatar::sRenderDistance * LLVOAvatar::sRenderDistance;
for (LLCharacter* character : LLCharacter::sInstances)
{
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 076459a7b2..6b3a5b1892 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -121,7 +121,7 @@
#include "SMAAAreaTex.h"
#include "SMAASearchTex.h"
-
+#include "llerror.h"
#ifndef LL_WINDOWS
#define A_GCC 1
#pragma GCC diagnostic ignored "-Wunused-function"
@@ -601,7 +601,6 @@ void LLPipeline::init()
connectRefreshCachedSettingsSafe("RenderMirrors");
connectRefreshCachedSettingsSafe("RenderHeroProbeUpdateRate");
connectRefreshCachedSettingsSafe("RenderHeroProbeConservativeUpdateMultiplier");
- connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit");
LLPointer<LLControlVariable> cntrl_ptr = gSavedSettings.getControl("CollectFontVertexBuffers");
if (cntrl_ptr.notNull())
@@ -1291,8 +1290,11 @@ void LLPipeline::createGLBuffers()
}
allocateScreenBuffer(resX, resY);
- mRT->width = 0;
- mRT->height = 0;
+ // Do not zero out mRT dimensions here. allocateScreenBuffer() above
+ // already sets the correct dimensions. Zeroing them caused resizeShadowTexture()
+ // to fail if called immediately after createGLBuffers (e.g., post graphics change).
+ // mRT->width = 0;
+ // mRT->height = 0;
if (!mNoiseMap)
diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml
index 604eb7c58f..4ea34975e1 100644
--- a/indra/newview/skins/default/xui/da/floater_about.xml
+++ b/indra/newview/skins/default/xui/da/floater_about.xml
@@ -5,7 +5,7 @@
[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]
</floater.string>
<floater.string name="AboutPosition">
- Du er ved [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] i regionen [REGION] lokaliseret ved &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Du er ved [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] i regionen [REGION] lokaliseret ved &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt;
[SERVER_VERSION]
[SERVER_RELEASE_NOTES_URL]
</floater.string>
diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml
index a7dff91311..038a2e0fcd 100644
--- a/indra/newview/skins/default/xui/da/strings.xml
+++ b/indra/newview/skins/default/xui/da/strings.xml
@@ -3723,6 +3723,10 @@ Hvis du bliver ved med at modtage denne besked, kontakt venligst [SUPPORT_SITE].
<string name="conference-title-incoming">
Konference med [AGENT_NAME]
</string>
+ <string name="bot_warning">
+Du chatter med en bot, [NAME]. Del ikke personlige oplysninger.
+Læs mere på https://second.life/scripted-agents.
+ </string>
<string name="no_session_message">
(IM session eksisterer ikke)
</string>
diff --git a/indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml
index 602424821f..09447cbbaf 100644
--- a/indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml
@@ -7,7 +7,7 @@
<combo_box.item label="Klein (128x128)" name="Small(128x128)"/>
<combo_box.item label="Mittel (256x256)" name="Medium(256x256)"/>
<combo_box.item label="Groß (512x512)" name="Large(512x512)"/>
- <combo_box.item label="Aktuelles Fenster (512x512)" name="CurrentWindow"/>
+ <combo_box.item label="Aktuelles Fenster" name="CurrentWindow"/>
<combo_box.item label="Benutzerdefiniert" name="Custom"/>
</combo_box>
<spinner label="Breite x Höhe" name="inventory_snapshot_width"/>
diff --git a/indra/newview/skins/default/xui/de/panel_snapshot_options.xml b/indra/newview/skins/default/xui/de/panel_snapshot_options.xml
index dab20d63eb..2a51f10894 100644
--- a/indra/newview/skins/default/xui/de/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/de/panel_snapshot_options.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_snapshot_options">
<button label="Auf Datenträger speichern" name="save_to_computer_btn"/>
- <button label="In Inventar speichern ([AMOUNT] L$)" name="save_to_inventory_btn"/>
+ <button label="In Inventar speichern" name="save_to_inventory_btn"/>
<button label="Im Profil-Feed teilen" name="save_to_profile_btn"/>
<button label="Auf Facebook teilen" name="send_to_facebook_btn"/>
<button label="Auf Twitter teilen" name="send_to_twitter_btn"/>
diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index 4bed43dd1d..9057821414 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -12,7 +12,7 @@
<string name="StartupRequireDriverUpdate">Grafikinitialisierung fehlgeschlagen. Bitte aktualisieren Sie Ihren Grafiktreiber.</string>
<string name="AboutHeader">[CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([ADDRESS_SIZE]Bit) [[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]</string>
<string name="BuildConfig">Build-Konfiguration [BUILD_CONFIG]</string>
- <string name="AboutPosition">Sie befinden sich an [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] auf &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ <string name="AboutPosition">Sie befinden sich an [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] auf &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt;
SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
(globale Koordinaten [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])
[SERVER_VERSION]
@@ -1613,6 +1613,10 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_
<string name="conference-title-incoming">Konferenz mit [AGENT_NAME]</string>
<string name="inventory_item_offered-im">Inventarobjekt „[ITEM_NAME]“ angeboten</string>
<string name="inventory_folder_offered-im">Inventarordner „[ITEM_NAME]“ angeboten</string>
+ <string name="bot_warning">
+ Sie chatten mit einem Bot, [NAME]. Geben Sie keine persönlichen Informationen weiter.
+Erfahren Sie mehr unter https://second.life/scripted-agents.
+ </string>
<string name="share_alert">Objekte aus dem Inventar hier her ziehen</string>
<string name="facebook_post_success">Sie haben auf Facebook gepostet.</string>
<string name="flickr_post_success">Sie haben auf Flickr gepostet.</string>
diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
index e6b780728c..acdccdc03a 100644
--- a/indra/newview/skins/default/xui/en/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -167,8 +167,19 @@
left="30"
height="16"
top_pad="8"
- width="180"
+ width="80"
+ control_name="RenderUIInSnapshot"
name="ui_check" />
+ <check_box
+ label="L$ Balance"
+ layout="topleft"
+ left_pad="16"
+ height="16"
+ top_delta="0"
+ width="80"
+ control_name="RenderBalanceInSnapshot"
+ enabled_control="RenderUIInSnapshot"
+ name="balance_check" />
<check_box
label="HUDs"
layout="topleft"
@@ -176,6 +187,7 @@
left="30"
top_pad="1"
width="180"
+ control_name="RenderHUDInSnapshot"
name="hud_check" />
<check_box
label="Freeze frame (fullscreen)"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index e0f380e074..d672ffbc94 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -152,6 +152,14 @@
parameter="category" />
</menu_item_call>
<menu_item_call
+ label="New Folder"
+ layout="topleft"
+ name="New Outfit Folder">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_call
label="New Outfit"
layout="topleft"
name="New Outfit">
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 4245b22e88..bcca3ce495 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -10336,6 +10336,14 @@ You are now the owner of object [OBJECT_NAME]
<notification
icon="alertmodal.tga"
+ name="NowOwnObjectInv"
+ type="notify">
+ <tag>fail</tag>
+You are now the owner of object [OBJECT_NAME] and it has been placed in your inventory.
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
name="CantRezOnLand"
type="notify">
<tag>fail</tag>
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml
index 7687f7cd96..23bbf45e88 100644
--- a/indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml
@@ -139,7 +139,7 @@
max_val_x="30"
min_val_y="-30"
max_val_y="30"
- logarithmic="1"/>
+ logarithmic="true"/>
<text
name="cloud_image_label"
diff --git a/indra/newview/skins/default/xui/en/panel_settings_water.xml b/indra/newview/skins/default/xui/en/panel_settings_water.xml
index 5e65b0e8a2..e062f1710b 100644
--- a/indra/newview/skins/default/xui/en/panel_settings_water.xml
+++ b/indra/newview/skins/default/xui/en/panel_settings_water.xml
@@ -378,7 +378,7 @@
initial_value="0"
layout="topleft"
left_delta="5"
- min_val="-0.5"
+ min_val="0"
max_val="0.5"
name="water_blur_multip"
top_pad="5"
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
index f8040b9a65..0cac1b410f 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml
@@ -60,7 +60,7 @@
name="Large(512x512)"
value="[i512,i512]" />
<combo_box.item
- label="Current Window(512x512)"
+ label="Current Window"
name="CurrentWindow"
value="[i0,i0]" />
<combo_box.item
@@ -119,6 +119,8 @@
type="string"
word_wrap="true">
To save your image as a texture select one of the square formats.
+
+Upload cost: L$[UPLOAD_COST]
</text>
<button
follows="right|bottom"
diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
index 3a7731d235..2fb02af61c 100644
--- a/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/en/panel_snapshot_options.xml
@@ -31,7 +31,7 @@
image_overlay_alignment="left"
image_top_pad="-1"
imgoverlay_label_space="10"
- label="Save to Inventory (L$[AMOUNT])"
+ label="Save to Inventory"
layout="topleft"
left_delta="0"
name="save_to_inventory_btn"
diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
index 9a19d06432..af6a9b94d9 100644
--- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
@@ -729,8 +729,8 @@
label_width="205"
layout="topleft"
left="10"
- min_val="-100"
- max_val="100"
+ min_val="-10000"
+ max_val="10000"
name="TexScaleU"
top_pad="5"
width="265" />
@@ -742,8 +742,8 @@
label_width="205"
layout="topleft"
left="10"
- min_val="-100"
- max_val="100"
+ min_val="-10000"
+ max_val="10000"
name="TexScaleV"
width="265" />
<spinner
@@ -805,8 +805,8 @@
label_width="205"
layout="topleft"
left="10"
- min_val="-100"
- max_val="100"
+ min_val="-10000"
+ max_val="10000"
name="bumpyScaleU"
top_delta="-115"
width="265" />
@@ -818,8 +818,8 @@
label_width="205"
layout="topleft"
left="10"
- min_val="-100"
- max_val="100"
+ min_val="-10000"
+ max_val="10000"
name="bumpyScaleV"
width="265" />
<spinner
@@ -869,8 +869,8 @@
label_width="205"
layout="topleft"
left="10"
- min_val="-100"
- max_val="100"
+ min_val="-10000"
+ max_val="10000"
name="shinyScaleU"
top_delta="-115"
width="265" />
@@ -882,8 +882,8 @@
label_width="205"
layout="topleft"
left="10"
- min_val="-100"
- max_val="100"
+ min_val="-10000"
+ max_val="10000"
name="shinyScaleV"
width="265" />
<spinner
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 44da9a8dac..14123de82c 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -13,7 +13,6 @@
<string name="SUPPORT_SITE">Second Life Support Portal</string>
<!-- starting up -->
- <string name="StartupDetectingHardware">Detecting hardware...</string>
<string name="StartupLoading">Loading [APP_NAME]...</string>
<string name="StartupClearingCache">Clearing cache...</string>
<string name="StartupInitializingTextureCache">Initializing texture cache...</string>
@@ -71,7 +70,7 @@ Voice Server Version: [VOICE_VERSION]
<string name="LocalTime">[month, datetime, local] [day, datetime, local] [year, datetime, local] [hour, datetime, local]:[min, datetime, local]:[second,datetime, local]</string>
<string name="ErrorFetchingServerReleaseNotesURL">Error fetching server release notes URL.</string>
<string name="BuildConfiguration">Build Configuration</string>
-
+
<!-- progress -->
<string name="ProgressRestoring">Restoring...</string>
<string name="ProgressChangingResolution">Changing resolution...</string>
@@ -114,10 +113,10 @@ Voice Server Version: [VOICE_VERSION]
<string name="LoginFailedHeader">Login failed.</string>
<string name="Quit">Quit</string>
<string name="create_account_url">http://join.secondlife.com/?sourceid=[sourceid]</string>
-
+
<string name="AgniGridLabel">Second Life Main Grid (Agni)</string>
<string name="AditiGridLabel">Second Life Beta Test Grid (Aditi)</string>
-
+
<string name="ViewerDownloadURL">http://secondlife.com/download</string>
<string name="LoginFailedViewerNotPermitted">
The viewer you are using can no longer access Second Life. Please visit the following page to download a new viewer:
@@ -209,7 +208,7 @@ If you feel this is an error, please contact support@secondlife.com</string>
<string name="YouHaveBeenDisconnected">You have been disconnected from the region you were in.</string>
<string name="SentToInvalidRegion">You were sent to an invalid region.</string>
<string name="TestingDisconnect">Testing viewer disconnect</string>
-
+
<!-- SLShare: User Friendly Filter Names Translation -->
<string name="BlackAndWhite">Black &amp; White</string>
<string name="Colors1970">1970&apos;s Colors</string>
@@ -222,7 +221,7 @@ If you feel this is an error, please contact support@secondlife.com</string>
<string name="LensFlare">Lens Flare</string>
<string name="Miniature">Miniature</string>
<string name="Toycamera">Toy Camera</string>
-
+
<!-- Tooltip -->
<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->
<string name="TooltipNoName">(no name)</string> <!-- No name on an object -->
@@ -259,10 +258,11 @@ If you feel this is an error, please contact support@secondlife.com</string>
<string name="TooltipOutboxMixedStock">All items in a stock folder must have the same type and permission</string>
<string name="TooltipOutfitNotInInventory">You can only put items or outfits from your personal inventory into "My outfits"</string>
<string name="TooltipCantCreateOutfit">One or more items can't be used inside "My outfits"</string>
-
+ <string name="TooltipCantMoveOutfitIntoOutfit">Can not move an outfit into another outfit</string>
+
<string name="TooltipDragOntoOwnChild">You can't move a folder into its child</string>
<string name="TooltipDragOntoSelf">You can't move a folder into itself</string>
-
+
<!-- tooltips for Urls -->
<string name="TooltipHttpUrl">Click to view this web page</string>
<string name="TooltipSLURL">Click to view this location's information</string>
@@ -370,7 +370,7 @@ are allowed.
<string name="AssetUploadServerDifficulties">The server is experiencing unexpected difficulties.</string>
<string name="AssetUploadServerUnavaliable">Service not available or upload timeout was reached.</string>
<string name="AssetUploadRequestInvalid">
-Error in upload request. Please visit
+Error in upload request. Please visit
http://secondlife.com/support for help fixing this problem.
</string>
@@ -534,7 +534,7 @@ http://secondlife.com/support for help fixing this problem.
<string name="ChangeYourDefaultAnimations">Change your default animations</string>
<string name="ForceSitAvatar">Force your avatar to sit</string>
<string name="ChangeEnvSettings">Change your environment settings</string>
-
+
<string name="NotConnected">Not Connected</string>
<string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name -->
<string name="JoinAnExperience"/><!-- intentionally blank -->
@@ -2320,7 +2320,7 @@ For AI Character: Get the closest navigable point to the point provided.
<!-- inventory -->
<string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].</string>
- <string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>
+ <string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>
<string name="PlacesNoMatchingItems">To add a place to your landmarks, click the star to the right of the location name.</string>
<string name="FavoritesNoMatchingItems">To add a place to your favorites, click the star to the right of the location name, then save the landmark to "Favorites bar".</string>
<string name="MarketplaceNoListing">You have no listings yet.</string>
@@ -2503,7 +2503,7 @@ If you continue to receive this message, please contact Second Life support for
<string name="InvFolder Materials">Materials</string>
<!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694-->
- <string name="InvFolder Friends">Friends</string>
+ <string name="InvFolder Friends">Friends</string>
<string name="InvFolder All">All</string>
<string name="no_attachments">No attachments worn</string>
@@ -2672,7 +2672,7 @@ If you continue to receive this message, please contact Second Life support for
<string name="UploadFailed">File upload failed: </string>
<string name="ObjectOutOfRange">Script (object out of range)</string>
<string name="ScriptWasDeleted">Script (deleted from inventory)</string>
-
+
<!-- god tools -->
<string name="GodToolsObjectOwnedBy">Object [OBJECT] owned by [OWNER]</string>
@@ -2942,14 +2942,12 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .anim
<string name="Linden Location">Linden Location</string>
<string name="Adult">Adult</string>
<string name="Arts&amp;Culture">Arts &amp; Culture</string>
- <string name="Arts and Culture">Arts &amp; Culture</string>
<string name="Business">Business</string>
<string name="Educational">Educational</string>
<string name="Gaming">Gaming</string>
<string name="Hangout">Hangout</string>
<string name="Newcomer Friendly">Newcomer Friendly</string>
<string name="Parks&amp;Nature">Parks &amp; Nature</string>
- <string name="Parks and Nature">Parks &amp; Nature</string>
<string name="Residential">Residential</string>
<!--<string name="Shopping">Shopping</string> -->
<string name="Stage">Stage</string>
@@ -3719,6 +3717,10 @@ Please reinstall viewer from https://secondlife.com/support/downloads/ and cont
<string name="inventory_folder_offered-im">
Inventory folder '[ITEM_NAME]' offered
</string>
+ <string name="bot_warning">
+ You are chatting with a bot, [NAME]. Do not share any personal information.
+Learn more at https://second.life/scripted-agents.
+ </string>
<string name="share_alert">
Drag items from inventory here
</string>
@@ -3851,7 +3853,7 @@ Please reinstall viewer from https://secondlife.com/support/downloads/ and cont
<string name="uploading_costs">Uploading costs L$ [AMOUNT]</string>
<string name="this_costs">This costs L$ [AMOUNT]</string>
-
+
<string name="buying_selected_land">This land costs</string>
<string name="this_object_costs">This item costs</string>
<string name="giving">You want to give</string>
@@ -3932,7 +3934,7 @@ Abuse Report</string>
<string name="New Daycycle">New Daycycle</string>
<string name="New Water">New Water</string>
<string name="New Sky">New Sky</string>
-
+
<string name="/bow">/bow</string>
<string name="/clap">/clap</string>
@@ -4014,7 +4016,7 @@ Please check http://status.secondlifegrid.net to see if there is a known problem
<string name="Accounting">Accounting</string>
<string name="Notices">Notices</string>
<string name="Chat">Chat</string>
-
+
<!-- SL Membership -->
<string name="BaseMembership">Base</string>
<string name="PremiumMembership">Premium</string>
@@ -4180,7 +4182,7 @@ Try enclosing path to the editor with double quotes.
<!-- commands -->
- <string
+ <string
name="Command_360_Capture_Label">360 snapshot</string>
<string name="Command_AboutLand_Label">About land</string>
<string name="Command_Appearance_Label">Outfits</string>
@@ -4213,9 +4215,9 @@ name="Command_360_Capture_Label">360 snapshot</string>
<string name="Command_View_Label">Camera controls</string>
<string name="Command_Voice_Label">Voice settings</string>
<string name="Command_FavoriteFolder_Label">Favorite folder</string>
- <string name="Command_ResyncAnimations_Label">Resync animations</string>
+ <string name="Command_ResyncAnimations_Label">Resync animations</string>
- <string
+ <string
name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<string name="Command_AboutLand_Tooltip">Information about the land you're visiting</string>
<string name="Command_Appearance_Tooltip">Change your avatar</string>
@@ -4248,7 +4250,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<string name="Command_View_Tooltip">Changing camera angle</string>
<string name="Command_Voice_Tooltip">Volume controls for calls and people near you in world</string>
<string name="Command_FavoriteFolder_Tooltip">Open your favorite inventory folder</string>
- <string name="Command_ResyncAnimations_Tooltip">Synchronizes avatar animations</string>
+ <string name="Command_ResyncAnimations_Tooltip">Synchronizes avatar animations</string>
<string name="Toolbar_Bottom_Tooltip">currently in your bottom toolbar</string>
<string name="Toolbar_Left_Tooltip" >currently in your left toolbar</string>
@@ -4282,7 +4284,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<!-- Spell check settings floater -->
<string name="UserDictionary">[User]</string>
-
+
<!-- Experience Tools strings -->
<string name="experience_tools_experience">Experience</string>
<string name="ExperienceNameNull">(no experience)</string>
@@ -4344,7 +4346,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<string name="Default">Default</string>
<string name="none_paren_cap">(None)</string>
<string name="no_limit">No limit</string>
-
+
<string name="Mav_Details_MAV_FOUND_DEGENERATE_TRIANGLES">
The physics shape contains triangles which are too small. Try simplifying the physics model.
</string>
diff --git a/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml b/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml
index cdeff6ab05..f246ff764a 100644
--- a/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml
+++ b/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml
@@ -3,7 +3,6 @@
name="virtualtrackball"
width="150"
height="150"
- user_resize="false"
increment_angle_mouse="1.5f"
increment_angle_btn="1.0f"
image_sphere="VirtualTrackball_Sphere"
diff --git a/indra/newview/skins/default/xui/en/widgets/xy_vector.xml b/indra/newview/skins/default/xui/en/widgets/xy_vector.xml
index 23cde55f30..923895be5e 100644
--- a/indra/newview/skins/default/xui/en/widgets/xy_vector.xml
+++ b/indra/newview/skins/default/xui/en/widgets/xy_vector.xml
@@ -3,11 +3,9 @@
name="xyvector"
width="120"
height="140"
- decimal_digits="1"
label_width="16"
padding="4"
- edit_bar_height="18"
- user_resize="false">
+ edit_bar_height="18">
<xy_vector.border
visible="true"/>
diff --git a/indra/newview/skins/default/xui/es/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/es/panel_snapshot_inventory.xml
index b5cf57ade7..c9eea9a58e 100644
--- a/indra/newview/skins/default/xui/es/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/es/panel_snapshot_inventory.xml
@@ -7,7 +7,7 @@
Guardar una imagen en el inventario cuesta [UPLOAD_COST] L$. Para guardar una imagen como una textura, selecciona uno de los formatos cuadrados.
</text>
<combo_box label="Resolución" name="texture_size_combo">
- <combo_box.item label="Ventana actual (512 × 512)" name="CurrentWindow"/>
+ <combo_box.item label="Ventana actual" name="CurrentWindow"/>
<combo_box.item label="Pequeña (128x128)" name="Small(128x128)"/>
<combo_box.item label="Mediana (256x256)" name="Medium(256x256)"/>
<combo_box.item label="Grande (512x512)" name="Large(512x512)"/>
diff --git a/indra/newview/skins/default/xui/es/panel_snapshot_options.xml b/indra/newview/skins/default/xui/es/panel_snapshot_options.xml
index 4eb9ecf28f..f3119c739e 100644
--- a/indra/newview/skins/default/xui/es/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/es/panel_snapshot_options.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_snapshot_options">
<button label="Guardar en disco" name="save_to_computer_btn"/>
- <button label="Guardar en inventario (L$[AMOUNT])" name="save_to_inventory_btn"/>
+ <button label="Guardar en inventario" name="save_to_inventory_btn"/>
<button label="Compartir en los comentarios de Mi perfil" name="save_to_profile_btn"/>
<button label="Compartir en Facebook" name="send_to_facebook_btn"/>
<button label="Compartir en Twitter" name="send_to_twitter_btn"/>
diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index cf86427477..4ec72d0409 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -10,7 +10,7 @@
<string name="AboutHeader">[CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([ADDRESS_SIZE]bit)
[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]</string>
<string name="BuildConfig">Configuración de constitución [BUILD_CONFIG]</string>
- <string name="AboutPosition">Estás en la posición [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1], de [REGION], alojada en &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ <string name="AboutPosition">Estás en la posición [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1], de [REGION], alojada en &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt;
SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
(coordenadas globales [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])
[SERVER_VERSION]
@@ -1584,6 +1584,10 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE].</string>
<string name="conference-title-incoming">Conferencia con [AGENT_NAME]</string>
<string name="inventory_item_offered-im">Ítem del inventario '[ITEM_NAME]' ofrecido</string>
<string name="inventory_folder_offered-im">Carpeta del inventario '[ITEM_NAME]' ofrecida</string>
+ <string name="bot_warning">
+Estás conversando con un bot, [NAME]. No compartas información personal.
+Más información en https://second.life/scripted-agents.
+ </string>
<string name="share_alert">Arrastra los ítems desde el invenbtario hasta aquí</string>
<string name="facebook_post_success">Has publicado en Facebook.</string>
<string name="flickr_post_success">Has publicado en Flickr.</string>
diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml
index 3cf64583d2..a560ff8d5e 100644
--- a/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml
@@ -7,7 +7,7 @@
L&apos;enregistrement d&apos;une image dans l&apos;inventaire coûte [UPLOAD_COST] L$. Pour enregistrer votre image sous forme de texture, sélectionnez un format carré.
</text>
<combo_box label="Résolution" name="texture_size_combo">
- <combo_box.item label="Fenêtre actuelle (512x512)" name="CurrentWindow"/>
+ <combo_box.item label="Fenêtre actuelle" name="CurrentWindow"/>
<combo_box.item label="Petite (128 x 128)" name="Small(128x128)"/>
<combo_box.item label="Moyenne (256 x 256)" name="Medium(256x256)"/>
<combo_box.item label="Grande (512 x 512)" name="Large(512x512)"/>
diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_options.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_options.xml
index bdedb9162f..52fa318f8e 100644
--- a/indra/newview/skins/default/xui/fr/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/fr/panel_snapshot_options.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_snapshot_options">
<button label="Enreg. sur le disque" name="save_to_computer_btn"/>
- <button label="Enreg. dans l&apos;inventaire ([AMOUNT] L$)" name="save_to_inventory_btn"/>
+ <button label="Enreg. dans l&apos;inventaire" name="save_to_inventory_btn"/>
<button label="Partager sur le flux de profil" name="save_to_profile_btn"/>
<button label="Partager sur Facebook" name="send_to_facebook_btn"/>
<button label="Partager sur Twitter" name="send_to_twitter_btn"/>
diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index 3889e26aee..5ea33591fc 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -13,7 +13,7 @@
<string name="AboutHeader">[CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([ADDRESS_SIZE]bit)
[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]</string>
<string name="BuildConfig">Configuration de la construction [BUILD_CONFIG]</string>
- <string name="AboutPosition">Vous êtes à [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] dans [REGION], se trouvant à &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ <string name="AboutPosition">Vous êtes à [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] dans [REGION], se trouvant à &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt;
SLURL : &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
(coordonnées globales [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])
[SERVER_VERSION]
@@ -1614,6 +1614,10 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE].</string>
<string name="conference-title-incoming">Conférence avec [AGENT_NAME]</string>
<string name="inventory_item_offered-im">Objet de l’inventaire [ITEM_NAME] offert</string>
<string name="inventory_folder_offered-im">Dossier de l’inventaire [ITEM_NAME] offert</string>
+ <string name="bot_warning">
+Vous discutez avec un bot, [NAME]. Ne partagez pas d’informations personnelles.
+En savoir plus sur https://second.life/scripted-agents.
+ </string>
<string name="share_alert">Faire glisser les objets de l'inventaire ici</string>
<string name="facebook_post_success">Vous avez publié sur Facebook.</string>
<string name="flickr_post_success">Vous avez publié sur Flickr.</string>
diff --git a/indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml
index 75b5d64660..21b65e8e69 100644
--- a/indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml
@@ -7,7 +7,7 @@
Salvare un&apos;immagine nell&apos;inventario costa L$[UPLOAD_COST]. Per salvare l&apos;immagine come texture, selezionare uno dei formati quadrati.
</text>
<combo_box label="Risoluzione" name="texture_size_combo">
- <combo_box.item label="Finestra corrente (512x512)" name="CurrentWindow"/>
+ <combo_box.item label="Finestra corrente" name="CurrentWindow"/>
<combo_box.item label="Piccola (128x128)" name="Small(128x128)"/>
<combo_box.item label="Media (256x256)" name="Medium(256x256)"/>
<combo_box.item label="Grande (512x512)" name="Large(512x512)"/>
diff --git a/indra/newview/skins/default/xui/it/panel_snapshot_options.xml b/indra/newview/skins/default/xui/it/panel_snapshot_options.xml
index 50fb3d39fa..7fce171326 100644
--- a/indra/newview/skins/default/xui/it/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/it/panel_snapshot_options.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_snapshot_options">
<button label="Salva sul disco" name="save_to_computer_btn"/>
- <button label="Salva nell&apos;inventario (L$[AMOUNT])" name="save_to_inventory_btn"/>
+ <button label="Salva nell&apos;inventario" name="save_to_inventory_btn"/>
<button label="Condividi sul feed del profilo" name="save_to_profile_btn"/>
<button label="Condividi su Facebook" name="send_to_facebook_btn"/>
<button label="Condividi su Twitter" name="send_to_twitter_btn"/>
diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index 270e7ac3a1..61377a7d9d 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -12,7 +12,7 @@
<string name="AboutHeader">[CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([ADDRESS_SIZE]bit)
[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]</string>
<string name="BuildConfig">Configurazione struttura [BUILD_CONFIG]</string>
- <string name="AboutPosition">Tu sei a [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] che si trova a &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ <string name="AboutPosition">Tu sei a [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] che si trova a &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt;
SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
(coordinate globali [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])
[SERVER_VERSION]
@@ -1586,6 +1586,10 @@ Se il messaggio persiste, contatta [SUPPORT_SITE].</string>
<string name="conference-title-incoming">Chiamata in conferenza con [AGENT_NAME]</string>
<string name="inventory_item_offered-im">Offerto oggetto di inventario &quot;[ITEM_NAME]&quot;</string>
<string name="inventory_folder_offered-im">Offerta cartella di inventario &quot;[ITEM_NAME]&quot;</string>
+ <string name="bot_warning">
+Stai parlando con un bot, [NAME]. Non condividere informazioni personali.
+Scopri di più su https://second.life/scripted-agents.
+ </string>
<string name="facebook_post_success">Hai pubblicato su Facebook.</string>
<string name="flickr_post_success">Hai pubblicato su Flickr.</string>
<string name="twitter_post_success">Hai pubblicato su Twitter.</string>
diff --git a/indra/newview/skins/default/xui/ja/panel_settings_water.xml b/indra/newview/skins/default/xui/ja/panel_settings_water.xml
index ead1ca9b2f..2510523897 100644
--- a/indra/newview/skins/default/xui/ja/panel_settings_water.xml
+++ b/indra/newview/skins/default/xui/ja/panel_settings_water.xml
@@ -63,7 +63,7 @@
<text follows="left|top|right" font="SansSerif" height="16" layout="topleft" left_delta="-5" top_pad="5" width="215">
ブラー乗数
</text>
- <slider control_name="water_blur_multip" follows="left|top" height="16" increment="0.001" initial_value="0" layout="topleft" left_delta="5" min_val="-0.5" max_val="0.5" name="water_blur_multip" top_pad="5" width="200" can_edit_text="true"/>
+ <slider control_name="water_blur_multip" follows="left|top" height="16" increment="0.001" initial_value="0" layout="topleft" left_delta="5" min_val="0" max_val="0.5" name="water_blur_multip" top_pad="5" width="200" can_edit_text="true"/>
</layout_panel>
</layout_stack>
</layout_panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml
index c55c11e928..04ecba4264 100644
--- a/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml
@@ -6,7 +6,7 @@
</text>
<view_border name="hr"/>
<combo_box label="解像度" name="texture_size_combo">
- <combo_box.item label="現在のウィンドウ (512✕512)" name="CurrentWindow"/>
+ <combo_box.item label="現在のウィンドウ" name="CurrentWindow"/>
<combo_box.item label="小(128✕128)" name="Small(128x128)"/>
<combo_box.item label="中(256✕256)" name="Medium(256x256)"/>
<combo_box.item label="大(512✕512)" name="Large(512x512)"/>
@@ -16,7 +16,7 @@
<spinner label="" name="inventory_snapshot_height"/>
<check_box label="縦横比の固定" name="inventory_keep_aspect_check"/>
<text name="hint_lbl">
- 画像をテクスチャとして保存する場合は、いずれかの正方形を選択してください。
+ 画像をインベントリに保存するには L$[UPLOAD_COST] の費用がかかります。画像をテクスチャとして保存するには平方形式の 1 つを選択してください。
</text>
<button label="キャンセル" name="cancel_btn"/>
<button label="保存" name="save_btn"/>
diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml
index 7a1aa280ec..a979e31c9a 100644
--- a/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/ja/panel_snapshot_options.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_snapshot_options">
<button label="ディスクに保存" name="save_to_computer_btn"/>
- <button label="インベントリに保存(L$ [AMOUNT])" name="save_to_inventory_btn"/>
+ <button label="インベントリに保存" name="save_to_inventory_btn"/>
<button label="プロフィールフィードで共有する" name="save_to_profile_btn"/>
<button label="メールで送信" name="save_to_email_btn"/>
<text name="fee_hint_lbl">
diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index 106bf91d0c..4f7e34774f 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -39,7 +39,7 @@
</string>
<string name="AboutPosition">
あなたは、現在[REGION]の[POSITION_LOCAL_0,number,1],[POSITION_LOCAL_1,number,1],[POSITION_LOCAL_2,number,1]にいます。
-位置は、&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt;です。([HOSTIP])
+位置は、&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt;です。
SLURL:&lt;nolink&gt;[SLURL]&lt;/nolink&gt;
(グローバル座標は、[POSITION_0,number,1],[POSITION_1,number,1],[POSITION_2,number,1]です。)
[SERVER_VERSION]
@@ -6149,6 +6149,10 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
<string name="inventory_folder_offered-im">
フォルダ「[ITEM_NAME]」がインベントリに送られてきました。
</string>
+ <string name="bot_warning">
+[NAME]とチャットしています。個人情報を共有しないでください。
+詳細は https://second.life/scripted-agents をご覧ください。
+ </string>
<string name="share_alert">
インベントリからここにアイテムをドラッグします。
</string>
diff --git a/indra/newview/skins/default/xui/pl/panel_snapshot_options.xml b/indra/newview/skins/default/xui/pl/panel_snapshot_options.xml
index 016b9ca197..04c01940e1 100644
--- a/indra/newview/skins/default/xui/pl/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/pl/panel_snapshot_options.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="panel_snapshot_options">
<button label="Zapisz na dysku twardym" name="save_to_computer_btn" />
- <button label="Zapisz do Szafy ([AMOUNT]L$)" name="save_to_inventory_btn" />
+ <button label="Zapisz do Szafy" name="save_to_inventory_btn" />
<button label="Wyślij na mój Kanał" name="save_to_profile_btn" />
<button label="Załaduj na Facebook" name="send_to_facebook_btn" />
<button label="Załaduj na Twitter" name="send_to_twitter_btn" />
diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml
index 8032443020..65b487e1b3 100644
--- a/indra/newview/skins/default/xui/pl/strings.xml
+++ b/indra/newview/skins/default/xui/pl/strings.xml
@@ -4412,6 +4412,10 @@ Jeżeli nadal otrzymujesz ten komunikat, skontaktuj się z [SUPPORT_SITE].
<string name="inventory_folder_offered-im">
Zaoferowano folder: '[ITEM_NAME]'
</string>
+ <string name="bot_warning">
+Rozmawiasz z botem [NAME]. Nie udostępniaj żadnych danych osobowych.
+Dowiedz się więcej na https://second.life/scripted-agents.
+ </string>
<string name="share_alert">
Przeciągaj tutaj rzeczy z Szafy
</string>
diff --git a/indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml
index f3357026d5..28a5142baa 100644
--- a/indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml
@@ -7,7 +7,7 @@
Salvar uma imagem em seu inventário custa L$[UPLOAD_COST]. Para salvar sua imagem como uma textura, selecione um dos formatos quadrados.
</text>
<combo_box label="Resolução" name="texture_size_combo">
- <combo_box.item label="Janela ativa (512x512)" name="CurrentWindow"/>
+ <combo_box.item label="Janela ativa" name="CurrentWindow"/>
<combo_box.item label="Pequeno (128x128)" name="Small(128x128)"/>
<combo_box.item label="Médio (256x256)" name="Medium(256x256)"/>
<combo_box.item label="Grande (512x512)" name="Large(512x512)"/>
diff --git a/indra/newview/skins/default/xui/pt/panel_snapshot_options.xml b/indra/newview/skins/default/xui/pt/panel_snapshot_options.xml
index 067e5dbd76..f71bc7cd12 100644
--- a/indra/newview/skins/default/xui/pt/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/pt/panel_snapshot_options.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_snapshot_options">
<button label="Salvar no disco" name="save_to_computer_btn"/>
- <button label="Salvar em inventário (L$[AMOUNT])" name="save_to_inventory_btn"/>
+ <button label="Salvar em inventário" name="save_to_inventory_btn"/>
<button label="Compartilhar no feed do perfil" name="save_to_profile_btn"/>
<button label="Compartilhar no Facebook" name="send_to_facebook_btn"/>
<button label="Compartilhar no Twitter" name="send_to_twitter_btn"/>
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index 3e33744b85..3798431d90 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -10,7 +10,7 @@
<string name="AboutHeader">[CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([ADDRESS_SIZE]bit)
[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]</string>
<string name="BuildConfig">Configuração do corpo [BUILD_CONFIG]</string>
- <string name="AboutPosition">Você está em [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] em [REGION] localizado em &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ <string name="AboutPosition">Você está em [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] em [REGION] localizado em &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt;
SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
(coordenadas globais [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])
[SERVER_VERSION]
@@ -1549,6 +1549,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE].</string>
<string name="conference-title-incoming">Conversa com [AGENT_NAME]</string>
<string name="inventory_item_offered-im">Item do inventário '[ITEM_NAME]' oferecido</string>
<string name="inventory_folder_offered-im">Pasta do inventário '[ITEM_NAME]' oferecida</string>
+ <string name="bot_warning">
+Você está conversando com um bot, [NAME]. Não compartilhe informações pessoais.
+Saiba mais em https://second.life/scripted-agents.
+ </string>
<string name="facebook_post_success">Você publicou no Facebook.</string>
<string name="flickr_post_success">Você publicou no Flickr.</string>
<string name="twitter_post_success">Você publicou no Twitter.</string>
diff --git a/indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml
index f07e12e0ed..adc612dfd8 100644
--- a/indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml
@@ -7,7 +7,7 @@
Сохранение изображения в инвентаре стоит L$[UPLOAD_COST]. Чтобы сохранить его как текстуру, выберите один из квадратных форматов.
</text>
<combo_box label="Размер" name="texture_size_combo">
- <combo_box.item label="Текущее окно (512x512)" name="CurrentWindow"/>
+ <combo_box.item label="Текущее окно" name="CurrentWindow"/>
<combo_box.item label="Маленький (128x128)" name="Small(128x128)"/>
<combo_box.item label="Средний (256x256)" name="Medium(256x256)"/>
<combo_box.item label="Большой (512x512)" name="Large(512x512)"/>
diff --git a/indra/newview/skins/default/xui/ru/panel_snapshot_options.xml b/indra/newview/skins/default/xui/ru/panel_snapshot_options.xml
index 7ba03ee0c9..f7fda0b1dc 100644
--- a/indra/newview/skins/default/xui/ru/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/ru/panel_snapshot_options.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_snapshot_options">
<button label="Сохранить на диске" name="save_to_computer_btn"/>
- <button label="Сохранить в инвентаре (L$[AMOUNT])" name="save_to_inventory_btn"/>
+ <button label="Сохранить в инвентаре" name="save_to_inventory_btn"/>
<button label="Поделиться в профиле" name="save_to_profile_btn"/>
<button label="Поделиться в Facebook" name="send_to_facebook_btn"/>
<button label="Поделиться в Twitter" name="send_to_twitter_btn"/>
diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml
index 10b0d3578f..0e6ddb0e34 100644
--- a/indra/newview/skins/default/xui/ru/strings.xml
+++ b/indra/newview/skins/default/xui/ru/strings.xml
@@ -42,7 +42,7 @@
Конфигурация построения [BUILD_CONFIG]
</string>
<string name="AboutPosition">
- Вы в точке [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] в регионе «[REGION]», расположенном на &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Вы в точке [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] в регионе «[REGION]», расположенном на &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt;
SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
(глобальные координаты [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])
[SERVER_VERSION]
@@ -4576,6 +4576,10 @@ support@secondlife.com.
<string name="inventory_folder_offered-im">
Предложена папка инвентаря «[ITEM_NAME]»
</string>
+ <string name="bot_warning">
+Вы общаетесь с ботом [NAME]. Не передавайте личные данные.
+Подробнее на https://second.life/scripted-agents.
+ </string>
<string name="share_alert">
Перетаскивайте вещи из инвентаря сюда
</string>
diff --git a/indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml
index be5940c4b9..160cba8700 100644
--- a/indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml
@@ -7,7 +7,7 @@
Bir görüntüyü envanterinize kaydetmenin maliyeti L$[UPLOAD_COST] olur. Görüntünüzü bir doku olarak kaydetmek için kare formatlardan birini seçin.
</text>
<combo_box label="Çözünürlük" name="texture_size_combo">
- <combo_box.item label="Mevcut Pencere(512x512)" name="CurrentWindow"/>
+ <combo_box.item label="Mevcut Pencere" name="CurrentWindow"/>
<combo_box.item label="Küçük (128x128)" name="Small(128x128)"/>
<combo_box.item label="Orta (256x256)" name="Medium(256x256)"/>
<combo_box.item label="Büyük (512x512)" name="Large(512x512)"/>
diff --git a/indra/newview/skins/default/xui/tr/panel_snapshot_options.xml b/indra/newview/skins/default/xui/tr/panel_snapshot_options.xml
index 1b48bbeec2..a028710b98 100644
--- a/indra/newview/skins/default/xui/tr/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/tr/panel_snapshot_options.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_snapshot_options">
<button label="Diske Kaydet" name="save_to_computer_btn"/>
- <button label="Envantere Kaydet (L$[AMOUNT])" name="save_to_inventory_btn"/>
+ <button label="Envantere Kaydet" name="save_to_inventory_btn"/>
<button label="Profil Akışında Paylaş" name="save_to_profile_btn"/>
<button label="Facebook&apos;ta Paylaş" name="send_to_facebook_btn"/>
<button label="Twitter&apos;da Paylaş" name="send_to_twitter_btn"/>
diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml
index d992788e13..32cf1e14ff 100644
--- a/indra/newview/skins/default/xui/tr/strings.xml
+++ b/indra/newview/skins/default/xui/tr/strings.xml
@@ -42,7 +42,7 @@
Yapı Konfigürasyonu [BUILD_CONFIG]
</string>
<string name="AboutPosition">
- &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] konumundasınız
+ &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; üzerinde bulunan [REGION] içerisinde [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] konumundasınız
SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
(küresel koordinatlar [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])
[SERVER_VERSION]
@@ -4579,6 +4579,10 @@ Bu iletiyi almaya devam ederseniz, lütfen [SUPPORT_SITE] bölümüne başvurun.
<string name="inventory_folder_offered-im">
&quot;[ITEM_NAME]&quot; envanter klasörü sunuldu
</string>
+ <string name="bot_warning">
+Bir bot ile sohbet ediyorsunuz, [NAME]. Kişisel bilgilerinizi paylaşmayın.
+Daha fazla bilgi için: https://second.life/scripted-agents.
+ </string>
<string name="share_alert">
Envanterinizden buraya öğeler sürükleyin
</string>
diff --git a/indra/newview/skins/default/xui/zh/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/zh/panel_snapshot_inventory.xml
index 094bf019b4..9c45c54a5e 100644
--- a/indra/newview/skins/default/xui/zh/panel_snapshot_inventory.xml
+++ b/indra/newview/skins/default/xui/zh/panel_snapshot_inventory.xml
@@ -7,7 +7,7 @@
將圖像儲存到收納區的費用為 L$[UPLOAD_COST]。 若要將圖像存為材質,請選擇一個正方格式。
</text>
<combo_box label="解析度" name="texture_size_combo">
- <combo_box.item label="目前視窗(512x512)" name="CurrentWindow"/>
+ <combo_box.item label="目前視窗" name="CurrentWindow"/>
<combo_box.item label="小(128x128)" name="Small(128x128)"/>
<combo_box.item label="中(256x256)" name="Medium(256x256)"/>
<combo_box.item label="大(512x512)" name="Large(512x512)"/>
diff --git a/indra/newview/skins/default/xui/zh/panel_snapshot_options.xml b/indra/newview/skins/default/xui/zh/panel_snapshot_options.xml
index d7c65bb25e..d9536882ac 100644
--- a/indra/newview/skins/default/xui/zh/panel_snapshot_options.xml
+++ b/indra/newview/skins/default/xui/zh/panel_snapshot_options.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<panel name="panel_snapshot_options">
<button label="儲存到硬碟" name="save_to_computer_btn"/>
- <button label="儲存到收納區(L$[AMOUNT])" name="save_to_inventory_btn"/>
+ <button label="儲存到收納區" name="save_to_inventory_btn"/>
<button label="分享至檔案訊息發佈" name="save_to_profile_btn"/>
<button label="分享到臉書" name="send_to_facebook_btn"/>
<button label="分享到推特" name="send_to_twitter_btn"/>
diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml
index d053d2b30d..dee48b3d58 100644
--- a/indra/newview/skins/default/xui/zh/strings.xml
+++ b/indra/newview/skins/default/xui/zh/strings.xml
@@ -42,7 +42,7 @@
建製設置 [BUILD_CONFIG]
</string>
<string name="AboutPosition">
- 你的方位是 [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1],地區名:[REGION],主機:&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ 你的方位是 [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1],地區名:[REGION],主機:&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt;
第二人生URL:&lt;nolink&gt;[SLURL]&lt;/nolink&gt;
(全域坐標:[POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1])
[SERVER_VERSION]
@@ -4572,6 +4572,10 @@ http://secondlife.com/support 求助解決問題。
<string name="inventory_folder_offered-im">
收納區資料夾&apos;[ITEM_NAME]&apos;已向人提供
</string>
+ <string name="bot_warning">
+您正在与人工智能机器人 [NAME] 聊天。请勿分享任何个人信息。
+了解更多:https://second.life/scripted-agents。
+ </string>
<string name="share_alert">
將收納區物品拖曳到這裡
</string>