summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x.hgtags1
-rw-r--r--autobuild.xml188
-rw-r--r--indra/llappearance/llavatarappearance.cpp3
-rw-r--r--indra/llappearance/llwearabletype.cpp2
-rw-r--r--indra/llaudio/llaudiodecodemgr.cpp16
-rw-r--r--indra/llcharacter/llkeyframemotion.cpp11
-rw-r--r--indra/llcommon/llassettype.cpp3
-rw-r--r--indra/llcommon/llassettype.h2
-rw-r--r--indra/llcommon/llerror.cpp109
-rw-r--r--indra/llcommon/llerror.h17
-rw-r--r--indra/llcommon/llprocessor.cpp2
-rw-r--r--indra/llcommon/llthread.cpp5
-rw-r--r--indra/llcommon/tests/llerror_test.cpp291
-rw-r--r--indra/llcorehttp/httpstats.cpp2
-rw-r--r--indra/llcorehttp/tests/test_refcounted.hpp3
-rw-r--r--indra/llimage/llimage.cpp4
-rw-r--r--indra/llimage/llimagebmp.cpp8
-rw-r--r--indra/llimage/llimagedxt.cpp6
-rw-r--r--indra/llimage/llimagejpeg.cpp27
-rw-r--r--indra/llimage/llimagepng.cpp7
-rw-r--r--indra/llimage/llimagetga.cpp37
-rw-r--r--indra/llimage/llpngwrapper.cpp13
-rw-r--r--indra/llinventory/llinventorytype.cpp2
-rw-r--r--indra/llinventory/llinventorytype.h2
-rw-r--r--indra/llmessage/lliosocket.cpp4
-rw-r--r--indra/llmessage/lliosocket.h4
-rw-r--r--indra/llmessage/lltransfermanager.cpp4
-rw-r--r--indra/llrender/llimagegl.cpp14
-rw-r--r--indra/llui/llscrolllistctrl.cpp25
-rw-r--r--indra/llui/llscrolllistctrl.h5
-rw-r--r--indra/llwindow/llwindowwin32.cpp31
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/app_settings/logcontrol.xml1
-rw-r--r--indra/newview/llagent.cpp1
-rw-r--r--indra/newview/llagent.h1
-rw-r--r--indra/newview/llappviewer.cpp2
-rw-r--r--indra/newview/llappviewerwin32.cpp2
-rw-r--r--indra/newview/llchicletbar.cpp2
-rw-r--r--indra/newview/llestateinfomodel.cpp6
-rw-r--r--indra/newview/llfeaturemanager.cpp50
-rw-r--r--indra/newview/llfloaternotificationstabbed.cpp3
-rw-r--r--indra/newview/llfloaterpreference.cpp10
-rw-r--r--indra/newview/llfloaterregioninfo.cpp4
-rw-r--r--indra/newview/llfloatersaveprefpreset.cpp11
-rw-r--r--indra/newview/llfloatertools.cpp6
-rw-r--r--indra/newview/llimprocessing.cpp11
-rw-r--r--indra/newview/llinventorybridge.cpp34
-rw-r--r--indra/newview/llinventorybridge.h12
-rw-r--r--indra/newview/llinventoryfilter.cpp2
-rw-r--r--indra/newview/llinventoryicon.cpp3
-rw-r--r--indra/newview/llinventorymodel.cpp53
-rw-r--r--indra/newview/llinventorymodel.h5
-rw-r--r--indra/newview/llinventorypanel.cpp36
-rw-r--r--indra/newview/llnotificationlistitem.cpp31
-rw-r--r--indra/newview/llnotificationlistitem.h1
-rw-r--r--indra/newview/lloutfitgallery.cpp7
-rw-r--r--indra/newview/llpanelface.cpp2
-rw-r--r--indra/newview/llpanelgroupnotices.cpp19
-rw-r--r--indra/newview/llpanelgroupnotices.h4
-rw-r--r--indra/newview/llpanelgrouproles.cpp1
-rw-r--r--indra/newview/llpanelobject.cpp18
-rw-r--r--indra/newview/llpanelpeople.cpp51
-rw-r--r--indra/newview/llpanelpeople.h3
-rw-r--r--indra/newview/llpresetsmanager.cpp5
-rw-r--r--indra/newview/llrecentpeople.cpp30
-rw-r--r--indra/newview/llrecentpeople.h5
-rw-r--r--indra/newview/llregioninfomodel.cpp2
-rw-r--r--indra/newview/llselectmgr.cpp33
-rw-r--r--indra/newview/llselectmgr.h5
-rw-r--r--indra/newview/llsidepaneliteminfo.cpp2
-rw-r--r--indra/newview/llsnapshotlivepreview.cpp2
-rw-r--r--indra/newview/llstartup.cpp8
-rw-r--r--indra/newview/llteleporthistory.cpp2
-rw-r--r--indra/newview/lltoolpie.cpp4
-rw-r--r--indra/newview/llviewerassettype.cpp2
-rw-r--r--indra/newview/llviewerassetupload.cpp12
-rw-r--r--indra/newview/llviewerassetupload.h12
-rw-r--r--indra/newview/llviewerkeyboard.cpp2
-rw-r--r--indra/newview/llviewermenu.cpp8
-rw-r--r--indra/newview/llviewermenufile.cpp5
-rw-r--r--indra/newview/llviewermenufile.h3
-rw-r--r--indra/newview/llviewermessage.cpp220
-rw-r--r--indra/newview/llviewermessage.h6
-rw-r--r--indra/newview/llviewernetwork.cpp2
-rw-r--r--indra/newview/llviewerregion.cpp8
-rw-r--r--indra/newview/llviewertexture.cpp26
-rw-r--r--indra/newview/llviewerwindow.cpp33
-rw-r--r--indra/newview/llvoicechannel.cpp14
-rw-r--r--indra/newview/llvoicevivox.cpp12
-rw-r--r--indra/newview/llweb.cpp6
-rw-r--r--indra/newview/llworldmap.cpp18
-rw-r--r--indra/newview/llworldmapmessage.cpp14
-rw-r--r--indra/newview/llworldmapview.cpp10
-rw-r--r--indra/newview/llworldmipmap.cpp4
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_UnknownObject.pngbin0 -> 1048 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml1
-rw-r--r--indra/newview/skins/default/xui/de/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_outgoing_call.xml18
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby_view.xml10
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml7
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_notify.xml1
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/es/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/it/strings.xml4
-rw-r--r--indra/newview/skins/default/xui/ja/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/ru/floater_tos.xml2
-rw-r--r--indra/newview/skins/default/xui/ru/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/tr/strings.xml2
-rw-r--r--indra/newview/skins/default/xui/zh/strings.xml2
-rw-r--r--indra/newview/tests/llviewernetwork_test.cpp4
-rw-r--r--indra/test/io.cpp3
-rw-r--r--scripts/content_tools/anim_tool.py654
114 files changed, 1763 insertions, 716 deletions
diff --git a/.hgtags b/.hgtags
index 9dd6783e6b..06d289325d 100755
--- a/.hgtags
+++ b/.hgtags
@@ -540,3 +540,4 @@ ad0e15543836d64d6399d28b32852510435e344a 5.1.0-release
04538b8157c1f5cdacd9403f0a395452d4a93689 5.1.6-release
ac3b1332ad4f55b7182a8cbcc1254535a0069f75 5.1.7-release
23ea0fe36fadf009a60c080392ce80e4bf8af8d9 5.1.8-release
+52422540bfe54b71155aa455360bee6e3ef1fd96 5.1.9-release
diff --git a/autobuild.xml b/autobuild.xml
index 7f18ab9abf..3107d77548 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -225,6 +225,36 @@
<key>version</key>
<string>1.57</string>
</map>
+ <key>chardet</key>
+ <map>
+ <key>copyright</key>
+ <string>Contributors to charset (see https://github.com/chardet/chardet)</string>
+ <key>description</key>
+ <string>Python Character Encoding Library</string>
+ <key>license</key>
+ <string>LGPL</string>
+ <key>license_file</key>
+ <string>LICENSES/chardet.txt</string>
+ <key>name</key>
+ <string>chardet</string>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>0124862b6a1b88455c78a68f8b823d21</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6662/23578/chardet-3.0.4-darwin64-506651.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ </map>
+ <key>version</key>
+ <string>3.0.4</string>
+ </map>
<key>colladadom</key>
<map>
<key>copyright</key>
@@ -1435,6 +1465,36 @@
<key>version</key>
<string>2012.1-2</string>
</map>
+ <key>idna</key>
+ <map>
+ <key>copyright</key>
+ <string>Copyright (c) 2013-2017, Kim Davies. All rights reserved.</string>
+ <key>description</key>
+ <string>Python Internationalized Domain Names in Applications (IDNA) Library</string>
+ <key>license</key>
+ <string>see idna.rst</string>
+ <key>license_file</key>
+ <string>LICENSES/idna.rst</string>
+ <key>name</key>
+ <string>idna</string>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>7dfe9fc4023d7d4f511dd9fac7258266</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6663/23584/idna-2.5-darwin64-506652.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ </map>
+ <key>version</key>
+ <string>2.5</string>
+ </map>
<key>jpeglib</key>
<map>
<key>copyright</key>
@@ -2113,6 +2173,46 @@
<key>version</key>
<string>0.0.1</string>
</map>
+ <key>llbase</key>
+ <map>
+ <key>copyright</key>
+ <string>Copyright (c) 2010, Linden Research, Inc.</string>
+ <key>license</key>
+ <string>mit</string>
+ <key>license_file</key>
+ <string>LICENSES/llbase-license.txt</string>
+ <key>name</key>
+ <string>llbase</string>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>e18eeb0691af053b83bd46b76c6ee86a</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6299/21982/llbase-0.9.3.506286-darwin64-506286.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ <key>windows</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>e6865670f9bca1c82fb8b91db3ea515c</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6301/21994/llbase-0.9.3.506286-windows-506286.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>windows</string>
+ </map>
+ </map>
+ <key>version</key>
+ <string>0.9.3.506286</string>
+ </map>
<key>llca</key>
<map>
<key>copyright</key>
@@ -2855,6 +2955,52 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>version</key>
<string>8.35.500898</string>
</map>
+ <key>requests</key>
+ <map>
+ <key>copyright</key>
+ <string>Copyright 2016 Kenneth Reitz</string>
+ <key>description</key>
+ <string>Python HTTP Library</string>
+ <key>license</key>
+ <string>Apache</string>
+ <key>license_file</key>
+ <string>LICENSES/requests.txt</string>
+ <key>name</key>
+ <string>requests</string>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>b8d134a970261b445a3f376ba4e05ff7</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6693/23788/requests-2.18.1-darwin64-506681.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ <key>linux64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>a92f2235991871c3d601a73cfef9b2af</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/4105/11530/requests-1.0-linux64-504094.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>linux64</string>
+ </map>
+ </map>
+ <key>source</key>
+ <string>https://bitbucket.org/lindenlab/p64_python-requests</string>
+ <key>source_type</key>
+ <string>hg</string>
+ <key>version</key>
+ <string>2.18.1</string>
+ </map>
<key>slvoice</key>
<map>
<key>copyright</key>
@@ -3065,6 +3211,36 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>version</key>
<string>0.8.0.1</string>
</map>
+ <key>urllib3</key>
+ <map>
+ <key>copyright</key>
+ <string>Copyright 2008-2016 Andrey Petrov and contributors (see CONTRIBUTORS.txt)</string>
+ <key>description</key>
+ <string>Python HTTP Library</string>
+ <key>license</key>
+ <string>MIT</string>
+ <key>license_file</key>
+ <string>LICENSES/urllib3.txt</string>
+ <key>name</key>
+ <string>urllib3</string>
+ <key>platforms</key>
+ <map>
+ <key>darwin64</key>
+ <map>
+ <key>archive</key>
+ <map>
+ <key>hash</key>
+ <string>22f64c7fbb6704d2e9519fd1cca8e49b</string>
+ <key>url</key>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/6659/23560/urllib3-1.21.1-darwin64-506648.tar.bz2</string>
+ </map>
+ <key>name</key>
+ <string>darwin64</string>
+ </map>
+ </map>
+ <key>version</key>
+ <string>1.21.1</string>
+ </map>
<key>viewer-manager</key>
<map>
<key>copyright</key>
@@ -3072,7 +3248,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>description</key>
<string>Linden Lab Viewer Management Process suite.</string>
<key>license</key>
- <string>viewerlgpl</string>
+ <string>Proprietary</string>
<key>license_file</key>
<string>LICENSE</string>
<key>name</key>
@@ -3084,9 +3260,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
- <string>904caf508ec1718e1fc9cd321ad95715</string>
+ <string>ce95944fb842849108102263a25fc794</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24994/196128/viewer_manager-2.0.519951-darwin64-519951.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/23237/178332/viewer_manager-1.0.518840-darwin64-518840.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@@ -3108,9 +3284,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key>
<map>
<key>hash</key>
- <string>e7f7ed2d40c1e554d038276fef690639</string>
+ <string>642f847a9ac45551af65a55826974334</string>
<key>url</key>
- <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/24996/196136/viewer_manager-2.0.519951-windows-519951.tar.bz2</string>
+ <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/23236/178338/viewer_manager-1.0.518840-windows-518840.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@@ -3121,7 +3297,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>source_type</key>
<string>hg</string>
<key>version</key>
- <string>2.0.519951</string>
+ <string>1.0.518840</string>
</map>
<key>vlc-bin</key>
<map>
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index e5089f028f..60359ca304 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -1566,9 +1566,10 @@ BOOL LLAvatarAppearance::allocateCollisionVolumes( U32 num )
delete_and_clear_array(mCollisionVolumes);
mNumCollisionVolumes = 0;
- mCollisionVolumes = new LLAvatarJointCollisionVolume[num];
+ mCollisionVolumes = new(std::nothrow) LLAvatarJointCollisionVolume[num];
if (!mCollisionVolumes)
{
+ LL_WARNS() << "Failed to allocate collision volumes" << LL_ENDL;
return FALSE;
}
diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp
index 207e0c4011..cd602b43b4 100644
--- a/indra/llappearance/llwearabletype.cpp
+++ b/indra/llappearance/llwearabletype.cpp
@@ -94,7 +94,7 @@ LLWearableDictionary::LLWearableDictionary()
addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE));
- addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE));
+ addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_UNKNOWN, FALSE, FALSE));
addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE));
}
diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index 77e57b14f5..6ab61689fd 100644
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -265,9 +265,19 @@ BOOL LLVorbisDecodeState::initDecode()
mInFilep = NULL;
return FALSE;
}
-
- mWAVBuffer.reserve(size_guess);
- mWAVBuffer.resize(WAV_HEADER_SIZE);
+
+ try
+ {
+ mWAVBuffer.reserve(size_guess);
+ mWAVBuffer.resize(WAV_HEADER_SIZE);
+ }
+ catch (std::bad_alloc)
+ {
+ LL_WARNS("AudioEngine") << "Out of memory when trying to alloc buffer: " << size_guess << LL_ENDL;
+ delete mInFilep;
+ mInFilep = NULL;
+ return FALSE;
+ }
{
// write the .wav format header
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index f12c64023a..330d812985 100644
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -579,8 +579,15 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
else
{
anim_file_size = anim_file->getSize();
- anim_data = new U8[anim_file_size];
- success = anim_file->read(anim_data, anim_file_size); /*Flawfinder: ignore*/
+ anim_data = new(std::nothrow) U8[anim_file_size];
+ if (anim_data)
+ {
+ success = anim_file->read(anim_data, anim_file_size); /*Flawfinder: ignore*/
+ }
+ else
+ {
+ LL_WARNS() << "Failed to allocate buffer: " << anim_file_size << mID << LL_ENDL;
+ }
delete anim_file;
anim_file = NULL;
}
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index 4304db36be..7e5a157cdf 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -95,6 +95,7 @@ LLAssetDictionary::LLAssetDictionary()
addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false));
addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false));
addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false));
+ addEntry(LLAssetType::AT_UNKNOWN, new AssetEntry("UNKNOWN", "invalid", NULL, false, false, false));
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE));
};
@@ -156,7 +157,7 @@ LLAssetType::EType LLAssetType::lookup(const std::string& type_name)
return iter->first;
}
}
- return AT_NONE;
+ return AT_UNKNOWN;
}
// static
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index b849be9f16..79ab3d7efe 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -130,7 +130,7 @@ public:
// | 4. ADD TO LLViewerAssetType.cpp |
// | 5. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp |
// +*********************************************************+
-
+ AT_UNKNOWN = 255,
AT_NONE = -1
};
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 29de79dc64..06c7aef8ab 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -40,6 +40,7 @@
# include <unistd.h>
#endif // !LL_WINDOWS
#include <vector>
+#include "string.h"
#include "llapp.h"
#include "llapr.h"
@@ -530,21 +531,16 @@ namespace LLError
mTags(new const char* [tag_count]),
mTagCount(tag_count)
{
- for (int i = 0; i < tag_count; i++)
- {
- mTags[i] = tags[i];
- }
-
switch (mLevel)
{
- case LEVEL_DEBUG: mLevelString = "DEBUG:"; break;
- case LEVEL_INFO: mLevelString = "INFO:"; break;
- case LEVEL_WARN: mLevelString = "WARNING:"; break;
- case LEVEL_ERROR: mLevelString = "ERROR:"; break;
- default: mLevelString = "XXX:"; break;
+ case LEVEL_DEBUG: mLevelString = "DEBUG"; break;
+ case LEVEL_INFO: mLevelString = "INFO"; break;
+ case LEVEL_WARN: mLevelString = "WARNING"; break;
+ case LEVEL_ERROR: mLevelString = "ERROR"; break;
+ default: mLevelString = "XXX"; break;
};
- mLocationString = llformat("%s(%d) :", abbreviateFile(mFile).c_str(), mLine);
+ mLocationString = llformat("%s(%d)", abbreviateFile(mFile).c_str(), mLine);
#if LL_WINDOWS
// DevStudio: __FUNCTION__ already includes the full class name
#else
@@ -558,13 +554,23 @@ namespace LLError
mFunctionString = className(mClassInfo) + "::";
}
#endif
- mFunctionString += std::string(mFunction) + ":";
- const std::string tag_hash("#");
+ mFunctionString += std::string(mFunction);
+
+ for (int i = 0; i < tag_count; i++)
+ {
+ if (strchr(tags[i], ' '))
+ {
+ LL_ERRS() << "Space is not allowed in a log tag at " << mLocationString << LL_ENDL;
+ }
+ mTags[i] = tags[i];
+ }
+
+ mTagString.append("#");
+ // always construct a tag sequence; will be just a single # if no tag
for (size_t i = 0; i < mTagCount; i++)
{
- mTagString.append(tag_hash);
mTagString.append(mTags[i]);
- mTagString.append((i == mTagCount - 1) ? ";" : ",");
+ mTagString.append("#");
}
}
@@ -899,7 +905,46 @@ namespace LLError
namespace
{
- void writeToRecorders(const LLError::CallSite& site, const std::string& message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true)
+ void addEscapedMessage(std::ostream& out, const std::string& message)
+ {
+ size_t written_out = 0;
+ size_t all_content = message.length();
+ size_t escape_char_index; // always relative to start of message
+ // Use find_first_of to find the next character in message that needs escaping
+ for ( escape_char_index = message.find_first_of("\\\n\r");
+ escape_char_index != std::string::npos && written_out < all_content;
+ // record what we've written this iteration, scan for next char that needs escaping
+ written_out = escape_char_index + 1, escape_char_index = message.find_first_of("\\\n\r", written_out)
+ )
+ {
+ // found a character that needs escaping, so write up to that with the escape prefix
+ // note that escape_char_index is relative to the start, not to the written_out offset
+ out << message.substr(written_out, escape_char_index - written_out) << '\\';
+
+ // write out the appropriate second character in the escape sequence
+ char found = message[escape_char_index];
+ switch ( found )
+ {
+ case '\\':
+ out << '\\';
+ break;
+ case '\n':
+ out << 'n';
+ break;
+ case '\r':
+ out << 'r';
+ break;
+ }
+ }
+
+ if ( written_out < all_content ) // if the loop above didn't write everything
+ {
+ // write whatever was left
+ out << message.substr(written_out, std::string::npos);
+ }
+ }
+
+ void writeToRecorders(const LLError::CallSite& site, const std::string& escaped_message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true)
{
LLError::ELevel level = site.mLevel;
LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig();
@@ -912,32 +957,37 @@ namespace
std::ostringstream message_stream;
- if (show_time && r->wantsTime() && s->mTimeFunction != NULL)
+ if (r->wantsTime() && s->mTimeFunction != NULL)
{
- message_stream << s->mTimeFunction() << " ";
+ message_stream << s->mTimeFunction();
}
-
+ message_stream << " ";
+
if (show_level && r->wantsLevel())
{
- message_stream << site.mLevelString << " ";
+ message_stream << site.mLevelString;
}
+ message_stream << " ";
- if (show_tags && r->wantsTags())
+ if (r->wantsTags())
{
message_stream << site.mTagString;
}
+ message_stream << " ";
- if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation))
+ if (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation)
{
- message_stream << site.mLocationString << " ";
+ message_stream << site.mLocationString;
}
+ message_stream << " ";
if (show_function && r->wantsFunctionName())
{
- message_stream << site.mFunctionString << " ";
+ message_stream << site.mFunctionString;
}
+ message_stream << " : ";
- message_stream << message;
+ message_stream << escaped_message;
r->recordMessage(level, message_stream.str());
}
@@ -1180,11 +1230,6 @@ namespace LLError
delete out;
}
- if (site.mLevel == LEVEL_ERROR)
- {
- writeToRecorders(site, "error", true, true, true, false, false);
- }
-
std::ostringstream message_stream;
if (site.mPrintOnce)
@@ -1210,8 +1255,8 @@ namespace LLError
}
}
- message_stream << message;
-
+ addEscapedMessage(message_stream, message);
+
writeToRecorders(site, message_stream.str());
if (site.mLevel == LEVEL_ERROR && s->mCrashFunction)
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index ceb1fd2c5f..0a78229555 100644
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -146,11 +146,22 @@ const int LL_ERR_NOERR = 0;
will result in messages like:
- WARN: LLFoo::doSomething: called with a big value for i: 283
+ WARN #FooBarTag# llcommon/llfoo(100) LLFoo::doSomething : called with a big value for i: 283
+ the syntax is:
+ <timestamp> SPACE <level> SPACE <tags> SPACE <location> SPACE <function> SPACE COLON SPACE <message>
+
+ where each SPACE is a single space character; note that if a field is empty (such as when no
+ tags are specified), all the SPACEs are still present.
+
+ The tags must be a single word (may not contain a space); if more than one tag is specified,
+ they are all surrounded by '#' ( #FooTag#BarTag# ).
+
Which messages are logged and which are suppressed can be controlled at run
- time from the live file logcontrol.xml based on function, class and/or
- source file. See etc/logcontrol-dev.xml for details.
+ time from the configuration file. The default configuration is in newview/app_settings/logcontrol.xml
+ A copy of that file named logcontrol-dev.xml can be made in the users personal settings
+ directory; that will override the installed default file. See the logcontrol.xml
+ file or http://wiki.secondlife.com/wiki/Logging_System_Overview for configuration details.
Lastly, logging is now very efficient in both compiled code and execution
when skipped. There is no need to wrap messages, even debugging ones, in
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 446c312ca9..a618a1cc70 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -610,7 +610,7 @@ private:
value = (uint64_t)(( uint8_t *)&value);
else
{
- LL_WARNS("Unknown type returned from sysctl!") << LL_ENDL;
+ LL_WARNS() << "Unknown type returned from sysctl" << LL_ENDL;
}
}
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 1f4aa9b3a6..f066e9a4cd 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -249,9 +249,10 @@ void LLThread::shutdown()
// This thread just wouldn't stop, even though we gave it time
//LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
// Put a stake in its heart.
- delete mRecorder;
-
apr_thread_exit(mAPRThreadp, -1);
+ delete mRecorder;
+ mRecorder = NULL;
+ mStatus = STOPPED;
return;
}
mAPRThreadp = NULL;
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 20de205454..ce0dbce075 100644
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -36,6 +36,26 @@
#include "../test/lltut.h"
+enum LogFieldIndex
+{
+ TIME_FIELD,
+ LEVEL_FIELD,
+ TAGS_FIELD,
+ LOCATION_FIELD,
+ FUNCTION_FIELD,
+ MSG_FIELD
+};
+
+static const char* FieldName[] =
+{
+ "TIME",
+ "LEVEL",
+ "TAGS",
+ "LOCATION",
+ "FUNCTION",
+ "MSG"
+};
+
namespace
{
#ifdef __clang__
@@ -58,7 +78,7 @@ namespace tut
class TestRecorder : public LLError::Recorder
{
public:
- TestRecorder() { mWantsTime = false; }
+ TestRecorder() { mWantsTime = false; mWantsTags = true; }
virtual ~TestRecorder() { }
virtual void recordMessage(LLError::ELevel level,
@@ -133,13 +153,64 @@ namespace tut
ensure_equals("message count", countMessages(), expectedCount);
}
- void ensure_message_contains(int n, const std::string& expectedText)
- {
- std::ostringstream test_name;
- test_name << "testing message " << n;
-
- ensure_contains(test_name.str(), message(n), expectedText);
- }
+ std::string message_field(int msgnum, LogFieldIndex fieldnum)
+ {
+ std::ostringstream test_name;
+ test_name << "testing message " << msgnum << ", not enough messages";
+ tut::ensure(test_name.str(), msgnum < countMessages());
+
+ std::string msg(message(msgnum));
+
+ std::string field_value;
+
+ // find the start of the field; fields are separated by a single space
+ size_t scan = 0;
+ int on_field = 0;
+ while ( scan < msg.length() && on_field < fieldnum )
+ {
+ // fields are delimited by one space
+ if ( ' ' == msg[scan] )
+ {
+ if ( on_field < FUNCTION_FIELD )
+ {
+ on_field++;
+ }
+ // except function, which may have embedded spaces so ends with " : "
+ else if ( ( on_field == FUNCTION_FIELD )
+ && ( ':' == msg[scan+1] && ' ' == msg[scan+2] )
+ )
+ {
+ on_field++;
+ scan +=2;
+ }
+ }
+ scan++;
+ }
+ size_t start_field = scan;
+ size_t fieldlen = 0;
+ if ( fieldnum < FUNCTION_FIELD )
+ {
+ fieldlen = msg.find(' ', start_field) - start_field;
+ }
+ else if ( fieldnum == FUNCTION_FIELD )
+ {
+ fieldlen = msg.find(" : ", start_field) - start_field;
+ }
+ else if ( MSG_FIELD == fieldnum ) // no delimiter, just everything to the end
+ {
+ fieldlen = msg.length() - start_field;
+ }
+
+ return msg.substr(start_field, fieldlen);
+ }
+
+ void ensure_message_field_equals(int msgnum, LogFieldIndex fieldnum, const std::string& expectedText)
+ {
+ std::ostringstream test_name;
+ test_name << "testing message " << msgnum << " field " << FieldName[fieldnum] << "\n message: \"" << message(msgnum) << "\"\n ";
+
+ ensure_equals(test_name.str(), message_field(msgnum, fieldnum), expectedText);
+ }
void ensure_message_does_not_contain(int n, const std::string& expectedText)
{
@@ -162,8 +233,8 @@ namespace tut
LL_INFOS() << "test" << LL_ENDL;
LL_INFOS() << "bob" << LL_ENDL;
- ensure_message_contains(0, "test");
- ensure_message_contains(1, "bob");
+ ensure_message_field_equals(0, MSG_FIELD, "test");
+ ensure_message_field_equals(1, MSG_FIELD, "bob");
}
}
@@ -171,11 +242,10 @@ namespace
{
void writeSome()
{
- LL_DEBUGS() << "one" << LL_ENDL;
- LL_INFOS() << "two" << LL_ENDL;
- LL_WARNS() << "three" << LL_ENDL;
- // fatal messages write out an additional "error" message
- LL_ERRS() << "four" << LL_ENDL;
+ LL_DEBUGS("WriteTag","AnotherTag") << "one" << LL_ENDL;
+ LL_INFOS("WriteTag") << "two" << LL_ENDL;
+ LL_WARNS("WriteTag") << "three" << LL_ENDL;
+ LL_ERRS("WriteTag") << "four" << LL_ENDL;
}
};
@@ -187,37 +257,41 @@ namespace tut
{
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
writeSome();
- ensure_message_contains(0, "one");
- ensure_message_contains(1, "two");
- ensure_message_contains(2, "three");
- ensure_message_contains(3, "error");
- ensure_message_contains(4, "four");
- ensure_message_count(5);
+ ensure_message_field_equals(0, MSG_FIELD, "one");
+ ensure_message_field_equals(0, LEVEL_FIELD, "DEBUG");
+ ensure_message_field_equals(0, TAGS_FIELD, "#WriteTag#AnotherTag#");
+ ensure_message_field_equals(1, MSG_FIELD, "two");
+ ensure_message_field_equals(1, LEVEL_FIELD, "INFO");
+ ensure_message_field_equals(1, TAGS_FIELD, "#WriteTag#");
+ ensure_message_field_equals(2, MSG_FIELD, "three");
+ ensure_message_field_equals(2, LEVEL_FIELD, "WARNING");
+ ensure_message_field_equals(2, TAGS_FIELD, "#WriteTag#");
+ ensure_message_field_equals(3, MSG_FIELD, "four");
+ ensure_message_field_equals(3, LEVEL_FIELD, "ERROR");
+ ensure_message_field_equals(3, TAGS_FIELD, "#WriteTag#");
+ ensure_message_count(4);
LLError::setDefaultLevel(LLError::LEVEL_INFO);
writeSome();
- ensure_message_contains(5, "two");
- ensure_message_contains(6, "three");
- ensure_message_contains(7, "error");
- ensure_message_contains(8, "four");
- ensure_message_count(9);
+ ensure_message_field_equals(4, MSG_FIELD, "two");
+ ensure_message_field_equals(5, MSG_FIELD, "three");
+ ensure_message_field_equals(6, MSG_FIELD, "four");
+ ensure_message_count(7);
LLError::setDefaultLevel(LLError::LEVEL_WARN);
writeSome();
- ensure_message_contains(9, "three");
- ensure_message_contains(10, "error");
- ensure_message_contains(11, "four");
- ensure_message_count(12);
+ ensure_message_field_equals(7, MSG_FIELD, "three");
+ ensure_message_field_equals(8, MSG_FIELD, "four");
+ ensure_message_count(9);
LLError::setDefaultLevel(LLError::LEVEL_ERROR);
writeSome();
- ensure_message_contains(12, "error");
- ensure_message_contains(13, "four");
- ensure_message_count(14);
+ ensure_message_field_equals(9, MSG_FIELD, "four");
+ ensure_message_count(10);
LLError::setDefaultLevel(LLError::LEVEL_NONE);
writeSome();
- ensure_message_count(14);
+ ensure_message_count(10);
}
template<> template<>
@@ -225,12 +299,11 @@ namespace tut
// error type string in output
{
writeSome();
- ensure_message_contains(0, "DEBUG: ");
- ensure_message_contains(1, "INFO: ");
- ensure_message_contains(2, "WARNING: ");
- ensure_message_does_not_contain(3, "ERROR");
- ensure_message_contains(4, "ERROR: ");
- ensure_message_count(5);
+ ensure_message_field_equals(0, LEVEL_FIELD, "DEBUG");
+ ensure_message_field_equals(1, LEVEL_FIELD, "INFO");
+ ensure_message_field_equals(2, LEVEL_FIELD, "WARNING");
+ ensure_message_field_equals(3, LEVEL_FIELD, "ERROR");
+ ensure_message_count(4);
}
template<> template<>
@@ -280,7 +353,7 @@ namespace
{
std::ostringstream location;
location << LLError::abbreviateFile(__FILE__)
- << "(" << line << ") : ";
+ << "(" << line << ")";
return location.str();
}
@@ -321,7 +394,7 @@ namespace tut
writeReturningLocation();
ensure_message_does_not_contain(0, location);
- ensure_message_contains(1, location);
+ ensure_message_field_equals(1, LOCATION_FIELD, location);
ensure_message_does_not_contain(2, location);
}
}
@@ -496,13 +569,13 @@ namespace tut
void ErrorTestObject::test<7>()
{
outerLogger();
- ensure_message_contains(0, "inside");
- ensure_message_contains(1, "outside(moo)");
+ ensure_message_field_equals(0, MSG_FIELD, "inside");
+ ensure_message_field_equals(1, MSG_FIELD, "outside(moo)");
ensure_message_count(2);
metaLogger();
- ensure_message_contains(2, "logging");
- ensure_message_contains(3, "meta(baz)");
+ ensure_message_field_equals(2, MSG_FIELD, "logging");
+ ensure_message_field_equals(3, MSG_FIELD, "meta(baz)");
ensure_message_count(4);
}
@@ -513,9 +586,9 @@ namespace tut
LLError::setPrintLocation(false);
std::string location = errorReturningLocation();
- ensure_message_contains(0, location + "error");
- ensure_message_contains(1, "die");
- ensure_message_count(2);
+ ensure_message_field_equals(0, LOCATION_FIELD, location);
+ ensure_message_field_equals(0, MSG_FIELD, "die");
+ ensure_message_count(1);
ensure("fatal callback called", fatalWasCalled);
}
@@ -544,13 +617,13 @@ namespace tut
setWantsTime(false);
ufoSighting();
- ensure_message_contains(0, "ufo");
+ ensure_message_field_equals(0, MSG_FIELD, "ufo");
ensure_message_does_not_contain(0, roswell());
setWantsTime(true);
ufoSighting();
- ensure_message_contains(1, "ufo");
- ensure_message_contains(1, roswell());
+ ensure_message_field_equals(1, MSG_FIELD, "ufo");
+ ensure_message_field_equals(1, TIME_FIELD, roswell());
}
template<> template<>
@@ -564,9 +637,9 @@ namespace tut
function;
writeReturningLocationAndFunction(location, function);
- ensure_equals("order is time location type function message",
+ ensure_equals("order is time level tags location function message",
message(0),
- roswell() + " INFO: " + location + function + ": apple");
+ roswell() + " INFO " + "# " /* no tag */ + location + " " + function + " : " + "apple");
}
template<> template<>
@@ -578,7 +651,7 @@ namespace tut
LL_INFOS() << "boo" << LL_ENDL;
- ensure_message_contains(0, "boo");
+ ensure_message_field_equals(0, MSG_FIELD, "boo");
ensure_equals("alt recorder count", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 1);
ensure_contains("alt recorder message 0", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(0), "boo");
@@ -637,14 +710,12 @@ namespace tut
TestAlpha::doAll();
TestBeta::doAll();
- ensure_message_contains(0, "aim west");
- ensure_message_contains(1, "error");
- ensure_message_contains(2, "ate eels");
- ensure_message_contains(3, "buy iron");
- ensure_message_contains(4, "bad word");
- ensure_message_contains(5, "error");
- ensure_message_contains(6, "big easy");
- ensure_message_count(7);
+ ensure_message_field_equals(0, MSG_FIELD, "aim west");
+ ensure_message_field_equals(1, MSG_FIELD, "ate eels");
+ ensure_message_field_equals(2, MSG_FIELD, "buy iron");
+ ensure_message_field_equals(3, MSG_FIELD, "bad word");
+ ensure_message_field_equals(4, MSG_FIELD, "big easy");
+ ensure_message_count(5);
}
template<> template<>
@@ -657,8 +728,8 @@ namespace tut
LLError::setFunctionLevel("TestBeta::doError", LLError::LEVEL_NONE);
TestBeta::doAll();
- ensure_message_contains(0, "buy iron");
- ensure_message_contains(1, "bad word");
+ ensure_message_field_equals(0, MSG_FIELD, "buy iron");
+ ensure_message_field_equals(1, MSG_FIELD, "bad word");
ensure_message_count(2);
}
@@ -678,9 +749,9 @@ namespace tut
TestAlpha::doAll();
TestBeta::doAll();
- ensure_message_contains(0, "any idea");
- ensure_message_contains(1, "aim west");
- ensure_message_contains(2, "bad word");
+ ensure_message_field_equals(0, MSG_FIELD, "any idea");
+ ensure_message_field_equals(1, MSG_FIELD, "aim west");
+ ensure_message_field_equals(2, MSG_FIELD, "bad word");
ensure_message_count(3);
}
@@ -718,14 +789,13 @@ namespace tut
// configuration from LLSD
void ErrorTestObject::test<16>()
{
- std::string this_file = LLError::abbreviateFile(__FILE__);
LLSD config;
config["print-location"] = true;
config["default-level"] = "DEBUG";
LLSD set1;
set1["level"] = "WARN";
- set1["files"][0] = this_file;
+ set1["files"][0] = LLError::abbreviateFile(__FILE__);
LLSD set2;
set2["level"] = "INFO";
@@ -744,10 +814,9 @@ namespace tut
TestAlpha::doAll();
TestBeta::doAll();
- ensure_message_contains(0, "any idea");
- ensure_message_contains(0, this_file);
- ensure_message_contains(1, "aim west");
- ensure_message_contains(2, "bad word");
+ ensure_message_field_equals(0, MSG_FIELD, "any idea");
+ ensure_message_field_equals(1, MSG_FIELD, "aim west");
+ ensure_message_field_equals(2, MSG_FIELD, "bad word");
ensure_message_count(3);
// make sure reconfiguring works
@@ -758,15 +827,73 @@ namespace tut
TestAlpha::doAll();
TestBeta::doAll();
- ensure_message_contains(3, "aim west");
- ensure_message_does_not_contain(3, this_file);
- ensure_message_contains(4, "error");
- ensure_message_contains(5, "ate eels");
- ensure_message_contains(6, "bad word");
- ensure_message_contains(7, "error");
- ensure_message_contains(8, "big easy");
- ensure_message_count(9);
+ ensure_message_field_equals(3, MSG_FIELD, "aim west");
+ ensure_message_field_equals(4, MSG_FIELD, "ate eels");
+ ensure_message_field_equals(5, MSG_FIELD, "bad word");
+ ensure_message_field_equals(6, MSG_FIELD, "big easy");
+ ensure_message_count(7);
+ }
+}
+
+namespace
+{
+ void writeMsgNeedsEscaping()
+ {
+ LL_DEBUGS("WriteTag") << "backslash\\" << LL_ENDL;
+ LL_INFOS("WriteTag") << "newline\nafternewline" << LL_ENDL;
+ LL_WARNS("WriteTag") << "return\rafterreturn" << LL_ENDL;
+
+ LL_DEBUGS("WriteTag") << "backslash\\backslash\\" << LL_ENDL;
+ LL_INFOS("WriteTag") << "backslash\\newline\nanothernewline\nafternewline" << LL_ENDL;
+ LL_WARNS("WriteTag") << "backslash\\returnnewline\r\n\\afterbackslash" << LL_ENDL;
+ }
+};
+
+namespace tut
+{
+ template<> template<>
+ void ErrorTestObject::test<17>()
+ // backslash, return, and newline are escaped with backslashes
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ writeMsgNeedsEscaping();
+ ensure_message_field_equals(0, MSG_FIELD, "backslash\\\\");
+ ensure_message_field_equals(1, MSG_FIELD, "newline\\nafternewline");
+ ensure_message_field_equals(2, MSG_FIELD, "return\\rafterreturn");
+ ensure_message_field_equals(3, MSG_FIELD, "backslash\\\\backslash\\\\");
+ ensure_message_field_equals(4, MSG_FIELD, "backslash\\\\newline\\nanothernewline\\nafternewline");
+ ensure_message_field_equals(5, MSG_FIELD, "backslash\\\\returnnewline\\r\\n\\\\afterbackslash");
+ ensure_message_count(6);
+ }
+}
+
+namespace
+{
+ std::string writeTagWithSpaceReturningLocation()
+ {
+ LL_DEBUGS("Write Tag") << "not allowed" << LL_ENDL; int this_line = __LINE__;
+
+ std::ostringstream location;
+ location << LLError::abbreviateFile(__FILE__).c_str() << "(" << this_line << ")";
+ return location.str();
}
+};
+
+namespace tut
+{
+ template<> template<>
+ void ErrorTestObject::test<18>()
+ // space character is not allowed in a tag
+ {
+ LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
+ fatalWasCalled = false;
+
+ std::string location = writeTagWithSpaceReturningLocation();
+ std::string expected = "Space is not allowed in a log tag at " + location;
+ ensure_message_field_equals(0, LEVEL_FIELD, "ERROR");
+ ensure_message_field_equals(0, MSG_FIELD, expected);
+ ensure("fatal callback called", fatalWasCalled);
+ }
}
/* Tests left:
diff --git a/indra/llcorehttp/httpstats.cpp b/indra/llcorehttp/httpstats.cpp
index b2de7f51ff..19eceae5ef 100644
--- a/indra/llcorehttp/httpstats.cpp
+++ b/indra/llcorehttp/httpstats.cpp
@@ -101,7 +101,7 @@ void HTTPStats::dumpStats()
out << (*it).first << " " << (*it).second << std::endl;
}
- LL_WARNS("HTTP Core") << out.str() << LL_ENDL;
+ LL_WARNS("HTTPCore") << out.str() << LL_ENDL;
}
diff --git a/indra/llcorehttp/tests/test_refcounted.hpp b/indra/llcorehttp/tests/test_refcounted.hpp
index cb4b50287a..5dff143e5d 100644
--- a/indra/llcorehttp/tests/test_refcounted.hpp
+++ b/indra/llcorehttp/tests/test_refcounted.hpp
@@ -30,6 +30,7 @@
#include "test_allocator.h"
+#if 0 // disable all of this because it's hanging win64 builds?
using namespace LLCoreInt;
namespace tut
@@ -152,5 +153,5 @@ namespace tut
ensure(mMemTotal == (GetMemTotal() - sizeof(RefCounted)));
}
}
-
+#endif // if 0
#endif // TEST_LLCOREINT_REF_COUNTED_H_
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index dca03cfe04..1a4dd2ca99 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -889,7 +889,7 @@ void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components)
bool LLImageRaw::resize(U16 width, U16 height, S8 components)
{
- if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
+ if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components) && !isBufferInvalid())
{
return true;
}
@@ -898,7 +898,7 @@ bool LLImageRaw::resize(U16 width, U16 height, S8 components)
allocateDataSize(width,height,components);
- return true;
+ return !isBufferInvalid();
}
bool LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp
index 2cdd26c22b..867b2bb47b 100644
--- a/indra/llimage/llimagebmp.cpp
+++ b/indra/llimage/llimagebmp.cpp
@@ -318,7 +318,7 @@ bool LLImageBMP::updateData()
if( 0 != mColorPaletteColors )
{
- mColorPalette = new U8[color_palette_size];
+ mColorPalette = new(std::nothrow) U8[color_palette_size];
if (!mColorPalette)
{
LL_ERRS() << "Out of memory in LLImageBMP::updateData()" << LL_ENDL;
@@ -344,7 +344,11 @@ bool LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
return false;
}
- raw_image->resize(getWidth(), getHeight(), 3);
+ if (!raw_image->resize(getWidth(), getHeight(), 3))
+ {
+ setLastError("llimagebmp failed to resize image!");
+ return false;
+ }
U8* src = mdata + mBitmapOffset;
U8* dst = raw_image->getData();
diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp
index 3a7319d765..36317a5ba8 100644
--- a/indra/llimage/llimagedxt.cpp
+++ b/indra/llimage/llimagedxt.cpp
@@ -289,7 +289,11 @@ bool LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
return false;
}
- raw_image->resize(width, height, ncomponents);
+ if (!raw_image->resize(width, height, ncomponents))
+ {
+ setLastError("llImageDXT failed to resize image!");
+ return false;
+ }
memcpy(raw_image->getData(), data, image_size); /* Flawfinder: ignore */
return true;
diff --git a/indra/llimage/llimagejpeg.cpp b/indra/llimage/llimagejpeg.cpp
index 60b2d0faa5..3b1b060c02 100644
--- a/indra/llimage/llimagejpeg.cpp
+++ b/indra/llimage/llimagejpeg.cpp
@@ -29,6 +29,7 @@
#include "llimagejpeg.h"
#include "llerror.h"
+#include "llexception.h"
jmp_buf LLImageJPEG::sSetjmpBuffer ;
LLImageJPEG::LLImageJPEG(S32 quality)
@@ -256,7 +257,10 @@ bool LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
- raw_image->resize(getWidth(), getHeight(), getComponents());
+ if (!raw_image->resize(getWidth(), getHeight(), getComponents()))
+ {
+ throw std::bad_alloc();
+ }
raw_image_data = raw_image->getData();
@@ -311,6 +315,13 @@ bool LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
jpeg_destroy_decompress(&cinfo);
}
+ catch (std::bad_alloc)
+ {
+ setLastError( "Out of memory");
+ jpeg_destroy_decompress(&cinfo);
+ return true; // done
+ }
+
catch (int)
{
jpeg_destroy_decompress(&cinfo);
@@ -370,10 +381,11 @@ boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )
// Double the buffer size;
S32 new_buffer_size = self->mOutputBufferSize * 2;
- U8* new_buffer = new U8[ new_buffer_size ];
+ U8* new_buffer = new(std::nothrow) U8[ new_buffer_size ];
if (!new_buffer)
{
- LL_ERRS() << "Out of memory in LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )" << LL_ENDL;
+ self->setLastError("Out of memory in LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )");
+ LLTHROW(LLContinueError("Out of memory in LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )"));
return false;
}
memcpy( new_buffer, self->mOutputBuffer, self->mOutputBufferSize ); /* Flawfinder: ignore */
@@ -493,7 +505,14 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
disclaimMem(mOutputBufferSize);
mOutputBufferSize = getWidth() * getHeight() * getComponents() + 1024;
claimMem(mOutputBufferSize);
- mOutputBuffer = new U8[ mOutputBufferSize ];
+ mOutputBuffer = new(std::nothrow) U8[ mOutputBufferSize ];
+ if (mOutputBuffer == NULL)
+ {
+ disclaimMem(mOutputBufferSize);
+ mOutputBufferSize = 0;
+ setLastError("Failed to allocate output buffer");
+ return false;
+ }
const U8* raw_image_data = NULL;
S32 row_stride = 0;
diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp
index a4823ed859..c4b98d8260 100644
--- a/indra/llimage/llimagepng.cpp
+++ b/indra/llimage/llimagepng.cpp
@@ -125,7 +125,12 @@ bool LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
// Temporary buffer to hold the encoded image. Note: the final image
// size should be much smaller due to compression.
U32 bufferSize = getWidth() * getHeight() * getComponents() + 8192;
- U8* tmpWriteBuffer = new U8[ bufferSize ];
+ U8* tmpWriteBuffer = new(std::nothrow) U8[ bufferSize ];
+ if (!tmpWriteBuffer)
+ {
+ setLastError("LLImagePNG::out of memory");
+ return false;
+ }
// Delegate actual encoding work to wrapper
LLPngWrapper pngWrapper;
diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp
index 7c75aa1e2a..88bdae9b80 100644
--- a/indra/llimage/llimagetga.cpp
+++ b/indra/llimage/llimagetga.cpp
@@ -263,7 +263,7 @@ bool LLImageTGA::updateData()
// only allocate memory for one if _we_ intend to use it.
if ( (1 == mImageType) || (9 == mImageType) )
{
- mColorMap = new U8[ color_map_bytes ];
+ mColorMap = new(std::nothrow) U8[ color_map_bytes ];
if (!mColorMap)
{
LL_ERRS() << "Out of Memory in bool LLImageTGA::updateData()" << LL_ENDL;
@@ -336,7 +336,11 @@ bool LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
// Copy everything after the header.
- raw_image->resize(getWidth(), getHeight(), getComponents());
+ if( !raw_image->resize(getWidth(), getHeight(), getComponents()))
+ {
+ setLastError("LLImageTGA::out of memory");
+ return false;
+ }
if( (getComponents() != 1) &&
(getComponents() != 3) &&
@@ -346,6 +350,11 @@ bool LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
return false;
}
+ if( raw_image->isBufferInvalid())
+ {
+ setLastError("LLImageTGA::out of memory");
+ return false;
+ }
if( mOriginRightBit )
{
@@ -395,6 +404,11 @@ bool LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, bool rle, bool flipped
// alpha was entirely opaque
// convert to 24 bit image
LLPointer<LLImageRaw> compacted_image = new LLImageRaw(raw_image->getWidth(), raw_image->getHeight(), 3);
+ if (compacted_image->isBufferInvalid())
+ {
+ success = false;
+ break;
+ }
compacted_image->copy(raw_image);
raw_image->resize(raw_image->getWidth(), raw_image->getHeight(), 3);
raw_image->copy(compacted_image);
@@ -411,9 +425,16 @@ bool LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, bool rle, bool flipped
// alpha was entirely opaque
// convert to 24 bit image
LLPointer<LLImageRaw> compacted_image = new LLImageRaw(raw_image->getWidth(), raw_image->getHeight(), 3);
- compacted_image->copy(raw_image);
- raw_image->resize(raw_image->getWidth(), raw_image->getHeight(), 3);
- raw_image->copy(compacted_image);
+ if (compacted_image->isBufferInvalid())
+ {
+ success = false;
+ }
+ else
+ {
+ compacted_image->copy(raw_image);
+ raw_image->resize(raw_image->getWidth(), raw_image->getHeight(), 3);
+ raw_image->copy(compacted_image);
+ }
}
}
@@ -1053,7 +1074,11 @@ bool LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight
return false;
}
- raw_image->resize(getWidth(), getHeight(), getComponents());
+ if( !raw_image->resize(getWidth(), getHeight(), getComponents()) )
+ {
+ LL_ERRS() << "LLImageTGA: Failed to resize image" << LL_ENDL;
+ return false;
+ }
U8* dst = raw_image->getData();
U8* src = getData() + mDataOffset;
diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index eb70b78a36..f298764cc0 100644
--- a/indra/llimage/llpngwrapper.cpp
+++ b/indra/llimage/llpngwrapper.cpp
@@ -173,8 +173,11 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
// data space
if (rawImage != NULL)
{
- rawImage->resize(static_cast<U16>(mWidth),
- static_cast<U16>(mHeight), mChannels);
+ if (!rawImage->resize(static_cast<U16>(mWidth),
+ static_cast<U16>(mHeight), mChannels))
+ {
+ LLTHROW(PngError("Failed to resize image"));
+ }
U8 *dest = rawImage->getData();
int offset = mWidth * mChannels;
@@ -207,6 +210,12 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
releaseResources();
return (FALSE);
}
+ catch (std::bad_alloc)
+ {
+ mErrorMessage = "LLPngWrapper";
+ releaseResources();
+ return (FALSE);
+ }
// Clean up and return
releaseResources();
diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp
index d1e6807f52..7399e1bca4 100644
--- a/indra/llinventory/llinventorytype.cpp
+++ b/indra/llinventory/llinventorytype.cpp
@@ -181,7 +181,7 @@ LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType a
}
else
{
- return IT_NONE;
+ return IT_UNKNOWN;
}
}
diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h
index fc3c78cf50..891ab217fd 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -66,6 +66,7 @@ public:
IT_PERSON = 24,
IT_COUNT = 25,
+ IT_UNKNOWN = 255,
IT_NONE = -1
};
@@ -111,6 +112,7 @@ public:
ICONNAME_MESH,
ICONNAME_INVALID,
+ ICONNAME_UNKNOWN,
ICONNAME_COUNT,
ICONNAME_NONE = -1
};
diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp
index b7460df508..b15b98db80 100644
--- a/indra/llmessage/lliosocket.cpp
+++ b/indra/llmessage/lliosocket.cpp
@@ -101,7 +101,7 @@ void ll_debug_socket(const char* msg, apr_socket_t* apr_sock)
///
// static
-LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
+LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port, const char *hostname)
{
LLSocket::ptr_t rv;
apr_socket_t* socket = NULL;
@@ -150,7 +150,7 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
apr_sockaddr_t* sa = NULL;
status = apr_sockaddr_info_get(
&sa,
- APR_ANYADDR,
+ hostname,
APR_UNSPEC,
port,
0,
diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h
index f840f0275c..303d80eb14 100644
--- a/indra/llmessage/lliosocket.h
+++ b/indra/llmessage/lliosocket.h
@@ -96,12 +96,14 @@ public:
* and associated with the socket.
* @param type The type of socket to create
* @param port The port for the socket
+ * @param hostname e.g. APR_ANYADDR to listen openly, or "127.0.0.1"
* @return A valid socket shared pointer if the call worked.
*/
static ptr_t create(
apr_pool_t* pool,
EType type,
- U16 port = PORT_EPHEMERAL);
+ U16 port = PORT_EPHEMERAL,
+ const char *hostname = APR_ANYADDR);
/**
* @brief Create a LLSocket when you already have an apr socket.
diff --git a/indra/llmessage/lltransfermanager.cpp b/indra/llmessage/lltransfermanager.cpp
index ec7b21d8b6..452b77fb6d 100644
--- a/indra/llmessage/lltransfermanager.cpp
+++ b/indra/llmessage/lltransfermanager.cpp
@@ -62,9 +62,11 @@ LLTransferManager::LLTransferManager() :
LLTransferManager::~LLTransferManager()
{
+ // LLTransferManager should have been cleaned up by message system shutdown process
+ llassert(!mValid);
if (mValid)
{
- LL_WARNS() << "LLTransferManager::~LLTransferManager - Should have been cleaned up by message system shutdown process" << LL_ENDL;
+ // Usually happens if OS tries to kill viewer
cleanup();
}
}
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 89500dcc04..40217b2e80 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1262,7 +1262,8 @@ BOOL LLImageGL::createGLTexture()
stop_glerror();
if (!mTexName)
{
- LL_ERRS() << "LLImageGL::createGLTexture failed to make an empty texture" << LL_ENDL;
+ LL_WARNS() << "LLImageGL::createGLTexture failed to make an empty texture" << LL_ENDL;
+ return FALSE;
}
return TRUE ;
@@ -1395,7 +1396,16 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
}
if (!mTexName)
{
- LL_ERRS() << "LLImageGL::createGLTexture failed to make texture" << LL_ENDL;
+ if (old_name)
+ {
+ sGlobalTextureMemory -= mTextureMemory;
+ LLImageGL::deleteTextures(1, &old_name);
+ disclaimMem(mTextureMemory);
+ stop_glerror();
+ }
+
+ LL_WARNS() << "LLImageGL::createGLTexture failed to make texture" << LL_ENDL;
+ return FALSE;
}
if (mUseMipMaps)
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index ed65b1e45f..f4028057e8 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -199,7 +199,8 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mHoveredColor(p.hovered_color()),
mSearchColumn(p.search_column),
mColumnPadding(p.column_padding),
- mContextMenuType(MENU_NONE)
+ mContextMenuType(MENU_NONE),
+ mIsFriendSignal(NULL)
{
mItemListRect.setOriginAndSize(
mBorderThickness,
@@ -323,6 +324,7 @@ LLScrollListCtrl::~LLScrollListCtrl()
mItemList.clear();
std::for_each(mColumns.begin(), mColumns.end(), DeletePairedPointer());
mColumns.clear();
+ delete mIsFriendSignal;
}
@@ -1836,6 +1838,19 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
if (mPopupMenu)
{
+ if (mIsFriendSignal)
+ {
+ bool isFriend = *(*mIsFriendSignal)(uuid);
+ LLView* addFriendButton = mPopupMenu->getChild<LLView>("add_friend");
+ LLView* removeFriendButton = mPopupMenu->getChild<LLView>("remove_friend");
+
+ if (addFriendButton && removeFriendButton)
+ {
+ addFriendButton->setEnabled(!isFriend);
+ removeFriendButton->setEnabled(isFriend);
+ }
+ }
+
mPopupMenu->show(x, y);
LLMenuGL::showPopup(this, mPopupMenu, x, y);
return TRUE;
@@ -3110,3 +3125,11 @@ void LLScrollListCtrl::onFocusLost()
LLUICtrl::onFocusLost();
}
+boost::signals2::connection LLScrollListCtrl::setIsFriendCallback(const is_friend_signal_t::slot_type& cb)
+{
+ if (!mIsFriendSignal)
+ {
+ mIsFriendSignal = new is_friend_signal_t();
+ }
+ return mIsFriendSignal->connect(cb);
+}
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 699a8744e1..b35a8608e7 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -90,6 +90,7 @@ public:
typedef boost::signals2::signal<S32 (S32,const LLScrollListItem*,const LLScrollListItem*),maximum<S32> > sort_signal_t;
+ typedef boost::signals2::signal<bool(const LLUUID& user_id)> is_friend_signal_t;
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
@@ -393,6 +394,8 @@ public:
return mSortCallback->connect(cb);
}
+ boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb);
+
protected:
// "Full" interface: use this when you're creating a list that has one or more of the following:
@@ -515,6 +518,8 @@ private:
std::vector<sort_column_t> mSortColumns;
sort_signal_t* mSortCallback;
+
+ is_friend_signal_t* mIsFriendSignal;
}; // end class LLScrollListCtrl
#endif // LL_SCROLLLISTCTRL_H
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index f98c2423e5..4ee4a5357c 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -752,9 +752,6 @@ void LLWindowWin32::close()
mDragDrop->reset();
- // Make sure cursor is visible and we haven't mangled the clipping state.
- setMouseClipping(FALSE);
- showCursor();
// Go back to screen mode written in the registry.
if (mFullscreen)
@@ -762,9 +759,23 @@ void LLWindowWin32::close()
resetDisplayResolution();
}
+ // Don't process events in our mainWindowProc any longer.
+ SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, NULL);
+
+ // Make sure cursor is visible and we haven't mangled the clipping state.
+ showCursor();
+ setMouseClipping(FALSE);
+ if (gKeyboard)
+ {
+ gKeyboard->resetKeys();
+ }
+
// Clean up remaining GL state
- LL_DEBUGS("Window") << "Shutting down GL" << LL_ENDL;
- gGLManager.shutdownGL();
+ if (gGLManager.mInited)
+ {
+ LL_INFOS("Window") << "Cleaning up GL" << LL_ENDL;
+ gGLManager.shutdownGL();
+ }
LL_DEBUGS("Window") << "Releasing Context" << LL_ENDL;
if (mhRC)
@@ -785,16 +796,16 @@ void LLWindowWin32::close()
// Restore gamma to the system values.
restoreGamma();
- if (mhDC && !ReleaseDC(mWindowHandle, mhDC))
+ if (mhDC)
{
- LL_WARNS("Window") << "Release of ghDC failed" << LL_ENDL;
+ if (!ReleaseDC(mWindowHandle, mhDC))
+ {
+ LL_WARNS("Window") << "Release of ghDC failed" << LL_ENDL;
+ }
mhDC = NULL;
}
LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
-
- // Don't process events in our mainWindowProc any longer.
- SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, NULL);
// Make sure we don't leave a blank toolbar button.
ShowWindow(mWindowHandle, SW_HIDE);
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index fc3aa7739a..48ea19be07 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-5.1.9
+5.1.10
diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml
index ecd7c4bc36..8ced81fdb3 100644
--- a/indra/newview/app_settings/logcontrol.xml
+++ b/indra/newview/app_settings/logcontrol.xml
@@ -2,7 +2,6 @@
<map>
<!-- default-level can be ALL, DEBUG, INFO, WARN, ERROR, or NONE -->
<key>default-level</key> <string>INFO</string>
- <key>print-location</key> <boolean>false</boolean>
<key>settings</key>
<array>
<!-- Suppress anything but ERROR for some very verbose components -->
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 901294d6b4..9b8cc62aa8 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -4150,6 +4150,7 @@ void LLAgent::setTeleportState(ETeleportState state)
" for previously failed teleport. Ignore!" << LL_ENDL;
return;
}
+ LL_DEBUGS("Teleport") << "Setting teleport state to " << state << " Previous state: " << mTeleportState << LL_ENDL;
mTeleportState = state;
if (mTeleportState > TELEPORT_NONE && gSavedSettings.getBOOL("FreezeTime"))
{
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 4bb4d317e8..b1b39b637e 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -629,6 +629,7 @@ public:
void teleportViaLocationLookAt(const LLVector3d& pos_global);// To a global location, preserving camera rotation
void teleportCancel(); // May or may not be allowed by server
void restoreCanceledTeleportRequest();
+ bool canRestoreCanceledTeleport() { return mTeleportCanceled != NULL; }
bool getTeleportKeepsLookAt() { return mbTeleportKeepsLookAt; } // Whether look-at reset after teleport
protected:
bool teleportCore(bool is_local = false); // Stuff for all teleports; returns true if the teleport can proceed
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index c0fcdd7c79..5a374755f7 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -3115,7 +3115,7 @@ LLSD LLAppViewer::getViewerInfo() const
}
else
{
- LL_WARNS("Driver version")<< "Cannot get driver version from getDriverVersionWMI" << LL_ENDL;
+ LL_WARNS("DriverVersion")<< "Cannot get driver version from getDriverVersionWMI" << LL_ENDL;
LLSD driver_info = gDXHardware.getDisplayInfo();
if (driver_info.has("DriverVersion"))
{
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 48b3a1c485..f0a4a54fbf 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -698,7 +698,7 @@ void LLAppViewerWin32::initCrashReporting(bool reportFreeze)
&processInfo) == FALSE)
// Could not start application -> call 'GetLastError()'
{
- LL_WARNS("CrashReport Launch") << "CreateProcess failed " << GetLastError() << LL_ENDL;
+ LL_WARNS("CrashReport") << "CreateProcess failed " << GetLastError() << LL_ENDL;
return;
}
}
diff --git a/indra/newview/llchicletbar.cpp b/indra/newview/llchicletbar.cpp
index c4f959bfa9..91b9d68fd2 100644
--- a/indra/newview/llchicletbar.cpp
+++ b/indra/newview/llchicletbar.cpp
@@ -70,7 +70,7 @@ void LLChicletBar::log(LLView* panel, const std::string& descr)
{
if (NULL == panel) return;
LLView* layout = panel->getParent();
- LL_DEBUGS("Chiclet Bar Rects") << descr << ": "
+ LL_DEBUGS("ChicletBarRects") << descr << ": "
<< "panel: " << panel->getName()
<< ", rect: " << panel->getRect()
<< " layout: " << layout->getName()
diff --git a/indra/newview/llestateinfomodel.cpp b/indra/newview/llestateinfomodel.cpp
index e56a67f8d1..95d40be913 100644
--- a/indra/newview/llestateinfomodel.cpp
+++ b/indra/newview/llestateinfomodel.cpp
@@ -93,7 +93,7 @@ void LLEstateInfoModel::update(const strings_t& strings)
mFlags = strtoul(strings[3].c_str(), NULL, 10);
mSunHour = ((F32)(strtod(strings[4].c_str(), NULL)))/1024.0f;
- LL_DEBUGS("Windlight Sync") << "Received estate info: "
+ LL_DEBUGS("WindlightSync") << "Received estate info: "
<< "is_sun_fixed = " << getUseFixedSun()
<< ", sun_hour = " << getSunHour() << LL_ENDL;
LL_DEBUGS() << getInfoDump() << LL_ENDL;
@@ -151,7 +151,7 @@ void LLEstateInfoModel::commitEstateInfoCapsCoro(std::string url)
body["invoice"] = LLFloaterRegionInfo::getLastInvoice();
- LL_DEBUGS("Windlight Sync") << "Sending estate caps: "
+ LL_DEBUGS("WindlightSync") << "Sending estate caps: "
<< "is_sun_fixed = " << getUseFixedSun()
<< ", sun_hour = " << getSunHour() << LL_ENDL;
LL_DEBUGS() << body << LL_ENDL;
@@ -181,7 +181,7 @@ void LLEstateInfoModel::commitEstateInfoCapsCoro(std::string url)
// strings[3] = str((S32)(sun_hour * 1024.f))
void LLEstateInfoModel::commitEstateInfoDataserver()
{
- LL_DEBUGS("Windlight Sync") << "Sending estate info: "
+ LL_DEBUGS("WindlightSync") << "Sending estate info: "
<< "is_sun_fixed = " << getUseFixedSun()
<< ", sun_hour = " << getSunHour() << LL_ENDL;
LL_DEBUGS() << getInfoDump() << LL_ENDL;
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 487496df9a..8d07035b97 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -377,6 +377,43 @@ bool LLFeatureManager::parseFeatureTable(std::string filename)
F32 gpu_benchmark();
+#if LL_WINDOWS
+
+static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
+
+U32 exception_benchmark_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
+{
+ if (code == STATUS_MSC_EXCEPTION)
+ {
+ // C++ exception, go on
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else
+ {
+ // handle it
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+}
+
+F32 logExceptionBenchmark()
+{
+ // Todo: make a wrapper/class for SEH exceptions
+ F32 gbps = -1;
+ __try
+ {
+ gbps = gpu_benchmark();
+ }
+ __except (exception_benchmark_filter(GetExceptionCode(), GetExceptionInformation()))
+ {
+ // convert to C++ styled exception
+ char integer_string[32];
+ sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
+ throw std::exception(integer_string);
+ }
+ return gbps;
+}
+#endif
+
bool LLFeatureManager::loadGPUClass()
{
if (!gSavedSettings.getBOOL("SkipBenchmark"))
@@ -385,7 +422,11 @@ bool LLFeatureManager::loadGPUClass()
F32 gbps;
try
{
+#if LL_WINDOWS
+ gbps = logExceptionBenchmark();
+#else
gbps = gpu_benchmark();
+#endif
}
catch (const std::exception& e)
{
@@ -400,11 +441,11 @@ bool LLFeatureManager::loadGPUClass()
LL_WARNS("RenderInit") << "Unable to get an accurate benchmark; defaulting to class 3" << LL_ENDL;
mGPUClass = GPU_CLASS_3;
#else
- if (gGLManager.mGLVersion < 2.f)
+ if (gGLManager.mGLVersion <= 2.f)
{
mGPUClass = GPU_CLASS_0;
}
- else if (gGLManager.mGLVersion < 3.f)
+ else if (gGLManager.mGLVersion <= 3.f)
{
mGPUClass = GPU_CLASS_1;
}
@@ -420,6 +461,11 @@ bool LLFeatureManager::loadGPUClass()
{
mGPUClass = GPU_CLASS_4;
}
+ if (gGLManager.mIsIntel && mGPUClass > GPU_CLASS_1)
+ {
+ // Intels are generally weaker then other GPUs despite having advanced features
+ mGPUClass = (EGPUClass)(mGPUClass - 1);
+ }
#endif
}
else if (gGLManager.mGLVersion <= 2.f)
diff --git a/indra/newview/llfloaternotificationstabbed.cpp b/indra/newview/llfloaternotificationstabbed.cpp
index 4b5fe4989a..d1679fd936 100644
--- a/indra/newview/llfloaternotificationstabbed.cpp
+++ b/indra/newview/llfloaternotificationstabbed.cpp
@@ -387,7 +387,8 @@ void LLFloaterNotificationsTabbed::onStoreToast(LLPanel* info_panel, LLUUID id)
p.notification_name = notify->getName();
p.transaction_id = payload["transaction_id"];
p.group_id = payload["group_id"];
- p.fee = payload["fee"];
+ p.fee = payload["fee"];
+ p.use_offline_cap = payload["use_offline_cap"].asInteger();
p.subject = payload["subject"].asString();
p.message = payload["message"].asString();
p.sender = payload["sender_name"].asString();
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 4ce35643b1..7aff9fb586 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -2704,6 +2704,16 @@ void LLPanelPreferenceGraphics::cancel()
void LLPanelPreferenceGraphics::saveSettings()
{
resetDirtyChilds();
+ std::string preset_graphic_active = gSavedSettings.getString("PresetGraphicActive");
+ if (preset_graphic_active.empty())
+ {
+ LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
+ if (instance)
+ {
+ //don't restore previous preset after closing Preferences
+ instance->saveGraphicsPreset(preset_graphic_active);
+ }
+ }
LLPanelPreference::saveSettings();
}
void LLPanelPreferenceGraphics::setHardwareDefaults()
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index af68a2aae1..a0522c99c2 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -3248,14 +3248,14 @@ void LLPanelEnvironmentInfo::sendRegionSunUpdate()
param_set.setAll(sky_map.beginMap()->second);
F32 sun_angle = param_set.getSunAngle();
- LL_DEBUGS("Windlight Sync") << "Old sun hour: " << region_info.mSunHour << LL_ENDL;
+ LL_DEBUGS("WindlightSync") << "Old sun hour: " << region_info.mSunHour << LL_ENDL;
// convert value range from 0..2pi to 6..30
region_info.mSunHour = fmodf((sun_angle / F_TWO_PI) * 24.f, 24.f) + 6.f;
}
region_info.setUseFixedSun(region_use_fixed_sky);
region_info.mUseEstateSun = !region_use_fixed_sky;
- LL_DEBUGS("Windlight Sync") << "Sun hour: " << region_info.mSunHour << LL_ENDL;
+ LL_DEBUGS("WindlightSync") << "Sun hour: " << region_info.mSunHour << LL_ENDL;
region_info.sendRegionTerrain(LLFloaterRegionInfo::getLastInvoice());
}
diff --git a/indra/newview/llfloatersaveprefpreset.cpp b/indra/newview/llfloatersaveprefpreset.cpp
index bdef718d0e..684778c93a 100644
--- a/indra/newview/llfloatersaveprefpreset.cpp
+++ b/indra/newview/llfloatersaveprefpreset.cpp
@@ -34,6 +34,7 @@
#include "llfloaterreg.h"
#include "llnotificationsutil.h"
#include "llpresetsmanager.h"
+#include "lltrans.h"
LLFloaterSavePrefPreset::LLFloaterSavePrefPreset(const LLSD &key)
: LLFloater(key)
@@ -76,7 +77,7 @@ void LLFloaterSavePrefPreset::onOpen(const LLSD& key)
setTitle(floater_title);
- EDefaultOptions option = DEFAULT_TOP;
+ EDefaultOptions option = DEFAULT_HIDE;
LLPresetsManager::getInstance()->setPresetNamesInComboBox(mSubdirectory, mPresetCombo, option);
onPresetNameEdited();
@@ -86,7 +87,11 @@ void LLFloaterSavePrefPreset::onBtnSave()
{
std::string name = mPresetCombo->getSimple();
- if (!LLPresetsManager::getInstance()->savePreset(mSubdirectory, name))
+ if ((name == LLTrans::getString(PRESETS_DEFAULT)) || (name == PRESETS_DEFAULT))
+ {
+ LLNotificationsUtil::add("DefaultPresetNotSaved");
+ }
+ else if (!LLPresetsManager::getInstance()->savePreset(mSubdirectory, name))
{
LLSD args;
args["NAME"] = name;
@@ -98,7 +103,7 @@ void LLFloaterSavePrefPreset::onBtnSave()
void LLFloaterSavePrefPreset::onPresetsListChange()
{
- EDefaultOptions option = DEFAULT_TOP;
+ EDefaultOptions option = DEFAULT_HIDE;
LLPresetsManager::getInstance()->setPresetNamesInComboBox(mSubdirectory, mPresetCombo, option);
}
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 7fc60ddaac..ee4fdbe9a5 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -1225,7 +1225,7 @@ void LLFloaterTools::getMediaState()
if(!has_media_capability)
{
getChildView("add_media")->setEnabled(FALSE);
- LL_WARNS("LLFloaterTools: media") << "Media not enabled (no capability) in this region!" << LL_ENDL;
+ LL_WARNS("LLFloaterToolsMedia") << "Media not enabled (no capability) in this region!" << LL_ENDL;
clearMediaSettings();
return;
}
@@ -1249,7 +1249,7 @@ void LLFloaterTools::getMediaState()
{
if (!object->permModify())
{
- LL_INFOS("LLFloaterTools: media")
+ LL_INFOS("LLFloaterToolsMedia")
<< "Selection not editable due to lack of modify permissions on object id "
<< object->getID() << LL_ENDL;
@@ -1262,7 +1262,7 @@ void LLFloaterTools::getMediaState()
// contention as to whether this is a sufficient solution.
// if (object->isMediaDataBeingFetched())
// {
-// LL_INFOS("LLFloaterTools: media")
+// LL_INFOS("LLFloaterToolsMedia")
// << "Selection not editable due to media data being fetched for object id "
// << object->getID() << LL_ENDL;
//
diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp
index 491671c46f..e76b3d118e 100644
--- a/indra/newview/llimprocessing.cpp
+++ b/indra/newview/llimprocessing.cpp
@@ -814,10 +814,11 @@ void LLIMProcessing::processNewMessage(LLUUID from_id,
LLSD payload;
payload["transaction_id"] = session_id;
- payload["group_id"] = from_id;
+ payload["group_id"] = from_group ? from_id : aux_id;
payload["name"] = name;
payload["message"] = message;
payload["fee"] = membership_fee;
+ payload["use_offline_cap"] = session_id.isNull() && (offline == IM_OFFLINE);
LLSD args;
args["MESSAGE"] = message;
@@ -1459,8 +1460,12 @@ void LLIMProcessing::requestOfflineMessages()
// Auto-accepted inventory items may require the avatar object
// to build a correct name. Likewise, inventory offers from
// muted avatars require the mute list to properly mute.
- if (cap_url.empty())
+ if (cap_url.empty()
+ || gAgent.getRegionCapability("AcceptFriendship").empty()
+ || gAgent.getRegionCapability("AcceptGroupInvite").empty())
{
+ // Offline messages capability provides no session/transaction ids for message AcceptFriendship and IM_GROUP_INVITATION to work
+ // So make sure we have the caps before using it.
requestOfflineMessagesLegacy();
}
else
@@ -1561,7 +1566,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url)
message_data["to_agent_id"].asUUID(),
IM_OFFLINE,
(EInstantMessage)message_data["dialog"].asInteger(),
- LLUUID::null, // session id, fix this for friendship offers to work
+ LLUUID::null, // session id, since there is none we can only use frienship/group invite caps
message_data["timestamp"].asInteger(),
message_data["from_agent_name"].asString(),
message_data["message"].asString(),
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 90a000c196..e4b6c3b554 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1406,7 +1406,9 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
}
new_listener = new LLMeshBridge(inventory, root, uuid);
break;
-
+ case LLAssetType::AT_UNKNOWN:
+ new_listener = new LLUnknownItemBridge(inventory, root, uuid);
+ break;
case LLAssetType::AT_IMAGE_TGA:
case LLAssetType::AT_IMAGE_JPEG:
//LL_WARNS() << LLAssetType::lookup(asset_type) << " asset type is unhandled for uuid " << uuid << LL_ENDL;
@@ -6949,6 +6951,21 @@ const LLUUID &LLLinkFolderBridge::getFolderID() const
return LLUUID::null;
}
+void LLUnknownItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ menuentry_vec_t items;
+ menuentry_vec_t disabled_items;
+ items.push_back(std::string("Properties"));
+ items.push_back(std::string("Rename"));
+ hide_context_entries(menu, items, disabled_items);
+}
+
+LLUIImagePtr LLUnknownItemBridge::getIcon() const
+{
+ return LLInventoryIcon::getIcon(LLAssetType::AT_UNKNOWN, mInvType);
+}
+
+
/********************************************************************************
**
** BRIDGE ACTIONS
@@ -7310,7 +7327,7 @@ void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_dequ
menuentry_vec_t disabled_items;
if (get_selection_item_uuids(selected_items, ids))
{
- if (!LLAppearanceMgr::instance().canAddWearables(ids))
+ if (!LLAppearanceMgr::instance().canAddWearables(ids) && canWearSelected(ids))
{
disabled_items.push_back(std::string("Wearable Add"));
}
@@ -7318,4 +7335,17 @@ void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_dequ
disable_context_entries_if_present(menu, disabled_items);
}
+bool LLFolderViewGroupedItemBridge::canWearSelected(uuid_vec_t item_ids)
+{
+ for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ LLAssetType::EType asset_type = item->getType();
+ if (!item || (asset_type >= LLAssetType::AT_COUNT) || (asset_type <= LLAssetType::AT_NONE))
+ {
+ return false;
+ }
+ }
+ return true;
+}
// EOF
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index fd5c0433b1..ce06e8fffc 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -575,6 +575,17 @@ protected:
static std::string sPrefix;
};
+class LLUnknownItemBridge : public LLItemBridge
+{
+public:
+ LLUnknownItemBridge(LLInventoryPanel* inventory,
+ LLFolderView* root,
+ const LLUUID& uuid) :
+ LLItemBridge(inventory, root, uuid) {}
+ virtual LLUIImagePtr getIcon() const;
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+};
+
class LLLinkFolderBridge : public LLItemBridge
{
public:
@@ -747,6 +758,7 @@ class LLFolderViewGroupedItemBridge: public LLFolderViewGroupedItemModel
public:
LLFolderViewGroupedItemBridge();
virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu);
+ bool canWearSelected(uuid_vec_t item_ids);
};
#endif // LL_LLINVENTORYBRIDGE_H
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index f64c39c3ad..9193613e9f 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -153,7 +153,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
// we're showing all folders, overriding filter
if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
{
- return !gInventory.isCategoryHidden(folder_id);
+ return true;
}
// when applying a filter, matching folders get their contents downloaded first
diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp
index 495180f087..d0df1c94d5 100644
--- a/indra/newview/llinventoryicon.cpp
+++ b/indra/newview/llinventoryicon.cpp
@@ -93,6 +93,7 @@ LLIconDictionary::LLIconDictionary()
addEntry(LLInventoryType::ICONNAME_MESH, new IconEntry("Inv_Mesh"));
addEntry(LLInventoryType::ICONNAME_INVALID, new IconEntry("Inv_Invalid"));
+ addEntry(LLInventoryType::ICONNAME_UNKNOWN, new IconEntry("Inv_Unknown"));
addEntry(LLInventoryType::ICONNAME_NONE, new IconEntry("NONE"));
}
@@ -166,6 +167,8 @@ const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type,
break;
case LLAssetType::AT_MESH:
idx = LLInventoryType::ICONNAME_MESH;
+ case LLAssetType::AT_UNKNOWN:
+ idx = LLInventoryType::ICONNAME_UNKNOWN;
default:
break;
}
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 76bf87cfe5..2b9607f7a2 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -342,27 +342,6 @@ LLViewerInventoryCategory* LLInventoryModel::getCategory(const LLUUID& id) const
return category;
}
-bool LLInventoryModel::isCategoryHidden(const LLUUID& id) const
-{
- bool res = false;
- const LLViewerInventoryCategory* category = getCategory(id);
- if (category)
- {
- LLFolderType::EType cat_type = category->getPreferredType();
- switch (cat_type)
- {
- case LLFolderType::FT_INBOX:
- case LLFolderType::FT_OUTBOX:
- case LLFolderType::FT_MARKETPLACE_LISTINGS:
- res = true;
- break;
- default:
- break;
- }
- }
- return res;
-}
-
S32 LLInventoryModel::getItemCount() const
{
return mItemMap.size();
@@ -1831,11 +1810,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
llassert(item);
if(item)
{
- // This can happen if assettype enums from llassettype.h ever change.
- // For example, there is a known backwards compatibility issue in some viewer prototypes prior to when
- // the AT_LINK enum changed from 23 to 24.
- if ((item->getType() == LLAssetType::AT_NONE)
- || LLAssetType::lookup(item->getType()) == LLAssetType::badLookup())
+ if (item->getType() <= LLAssetType::AT_NONE)
{
LL_WARNS(LOG_INV) << "Got bad asset type for item [ name: " << item->getName()
<< " type: " << item->getType()
@@ -1843,6 +1818,13 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
return;
}
+ if (LLAssetType::lookup(item->getType()) == LLAssetType::badLookup())
+ {
+ LL_WARNS(LOG_INV) << "Got unknown asset type for item [ name: " << item->getName()
+ << " type: " << item->getType()
+ << " inv-type: " << item->getInventoryType() << " ]." << LL_ENDL;
+ }
+
// This condition means that we tried to add a link without the baseobj being in memory.
// The item will show up as a broken link.
if (item->getIsBrokenLink())
@@ -2051,6 +2033,7 @@ bool LLInventoryModel::loadSkeleton(
update_map_t child_counts;
cat_array_t categories;
item_array_t items;
+ changed_items_t categories_to_update;
item_array_t possible_broken_links;
cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
std::string inventory_filename = getInvCacheAddres(owner_id);
@@ -2076,7 +2059,7 @@ bool LLInventoryModel::loadSkeleton(
}
}
bool is_cache_obsolete = false;
- if(loadFromFile(inventory_filename, categories, items, is_cache_obsolete))
+ if (loadFromFile(inventory_filename, categories, items, categories_to_update, is_cache_obsolete))
{
// We were able to find a cache of files. So, use what we
// found to generate a set of categories we should add. We
@@ -2094,6 +2077,12 @@ bool LLInventoryModel::loadSkeleton(
continue; // cache corruption?? not sure why this happens -SJB
}
LLViewerInventoryCategory* tcat = *cit;
+
+ if (categories_to_update.find(tcat->getUUID()) != categories_to_update.end())
+ {
+ tcat->setVersion(NO_VERSION);
+ LL_WARNS() << "folder to update: " << tcat->getName() << LL_ENDL;
+ }
// we can safely ignore anything loaded from file, but
// not sent down in the skeleton. Must have been removed from inventory.
@@ -2642,6 +2631,7 @@ bool LLUUIDAndName::operator>(const LLUUIDAndName& rhs) const
bool LLInventoryModel::loadFromFile(const std::string& filename,
LLInventoryModel::cat_array_t& categories,
LLInventoryModel::item_array_t& items,
+ LLInventoryModel::changed_items_t& cats_to_update,
bool &is_cache_obsolete)
{
if(filename.empty())
@@ -2716,7 +2706,14 @@ bool LLInventoryModel::loadFromFile(const std::string& filename,
}
else
{
- items.push_back(inv_item);
+ if (inv_item->getType() == LLAssetType::AT_UNKNOWN)
+ {
+ cats_to_update.insert(inv_item->getParentUUID());
+ }
+ else
+ {
+ items.push_back(inv_item);
+ }
}
}
else
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 576c5e9e20..a4326aaeed 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -316,9 +316,7 @@ public:
// Copy content of all folders of type "type" into folder "id" and delete/purge the empty folders
// Note : This method has been designed for FT_OUTBOX (aka Merchant Outbox) but can be used for other categories
void consolidateForType(const LLUUID& id, LLFolderType::EType type);
-
- bool isCategoryHidden(const LLUUID& id) const;
-
+
private:
mutable LLPointer<LLViewerInventoryItem> mLastItem; // cache recent lookups
@@ -615,6 +613,7 @@ protected:
static bool loadFromFile(const std::string& filename,
cat_array_t& categories,
item_array_t& items,
+ changed_items_t& cats_to_update,
bool& is_cache_obsolete);
static bool saveToFile(const std::string& filename,
const cat_array_t& categories,
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 702675ad49..1481992f43 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -861,13 +861,37 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)
if (!folder_view_item && parent_folder)
{
- if (objectp->getType() <= LLAssetType::AT_NONE ||
- objectp->getType() >= LLAssetType::AT_COUNT)
+ if (objectp->getType() <= LLAssetType::AT_NONE)
+ {
+ LL_WARNS() << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : "
+ << ((S32)objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID()
+ << LL_ENDL;
+ return NULL;
+ }
+
+ if (objectp->getType() >= LLAssetType::AT_COUNT)
{
- LL_WARNS() << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : "
- << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID()
- << LL_ENDL;
- return NULL;
+ LL_WARNS() << "LLInventoryPanel::buildNewViews called with unknown objectp->mType : "
+ << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID()
+ << LL_ENDL;
+
+ LLInventoryItem* item = (LLInventoryItem*)objectp;
+ if (item)
+ {
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_UNKNOWN,
+ LLAssetType::AT_UNKNOWN,
+ LLInventoryType::IT_UNKNOWN,
+ this,
+ &mInventoryViewModel,
+ mFolderRoot.get(),
+ item->getUUID(),
+ item->getFlags());
+
+ if (new_listener)
+ {
+ folder_view_item = createFolderViewItem(new_listener);
+ }
+ }
}
if ((objectp->getType() == LLAssetType::AT_CATEGORY) &&
diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp
index f2de8e54a0..a5bc75e6bd 100644
--- a/indra/newview/llnotificationlistitem.cpp
+++ b/indra/newview/llnotificationlistitem.cpp
@@ -312,38 +312,15 @@ void LLGroupInviteNotificationListItem::onClickJoinBtn()
return;
}
- if(mParams.fee > 0)
- {
- LLSD args;
- args["COST"] = llformat("%d", mParams.fee);
- // Set the fee for next time to 0, so that we don't keep
- // asking about a fee.
- LLSD next_payload;
- next_payload["group_id"]= mParams.group_id;
- next_payload["transaction_id"]= mParams.transaction_id;
- next_payload["fee"] = 0;
- LLNotificationsUtil::add("JoinGroupCanAfford", args, next_payload);
- }
- else
- {
- send_improved_im(mParams.group_id,
- std::string("name"),
- std::string("message"),
- IM_ONLINE,
- IM_GROUP_INVITATION_ACCEPT,
- mParams.transaction_id);
- }
+ send_join_group_response(mParams.group_id, mParams.transaction_id, true, mParams.fee, mParams.use_offline_cap);
+
LLNotificationListItem::onClickCloseBtn();
}
void LLGroupInviteNotificationListItem::onClickDeclineBtn()
{
- send_improved_im(mParams.group_id,
- std::string("name"),
- std::string("message"),
- IM_ONLINE,
- IM_GROUP_INVITATION_DECLINE,
- mParams.transaction_id);
+ send_join_group_response(mParams.group_id, mParams.transaction_id, false, mParams.fee, mParams.use_offline_cap);
+
LLNotificationListItem::onClickCloseBtn();
}
diff --git a/indra/newview/llnotificationlistitem.h b/indra/newview/llnotificationlistitem.h
index 3dd52986b0..3d564fed0e 100644
--- a/indra/newview/llnotificationlistitem.h
+++ b/indra/newview/llnotificationlistitem.h
@@ -56,6 +56,7 @@ public:
std::string message;
std::string sender;
S32 fee;
+ U8 use_offline_cap;
LLDate time_stamp;
LLDate received_time;
LLSD inventory_offer;
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index a90a29a731..b2b6de94b3 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -1090,11 +1090,6 @@ void LLOutfitGallery::refreshOutfit(const LLUUID& category_id)
updates["name"] = new_name;
update_inventory_item(inv_id, updates, NULL);
mOutfitRenamePending.setNull();
- LLFloater* inv_floater = LLFloaterReg::getInstance("inventory");
- if (inv_floater)
- {
- inv_floater->closeFloater();
- }
LLFloater* appearance_floater = LLFloaterReg::getInstance("appearance");
if (appearance_floater)
{
@@ -1228,7 +1223,7 @@ void LLOutfitGallery::uploadOutfitImage(const std::vector<std::string>& filename
LLFloaterPerms::getNextOwnerPerms("Uploads"),
LLFloaterPerms::getGroupPerms("Uploads"),
LLFloaterPerms::getEveryonePerms("Uploads"),
- upload_pending_name, callback, expected_upload_cost, nruserdata);
+ upload_pending_name, callback, expected_upload_cost, nruserdata, false);
mOutfitLinkPending = outfit_id;
}
delete unit;
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 01ce4470f0..13ee7bb003 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -1255,7 +1255,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
if (material && editable)
{
- LL_DEBUGS("Materials: OnMatererialsLoaded:") << material->asLLSD() << LL_ENDL;
+ LL_DEBUGS("Materials") << material->asLLSD() << LL_ENDL;
// Alpha
LLCtrlSelectionInterface* combobox_alphamode =
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index 178b5db6c2..ce6834b4b3 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -303,6 +303,8 @@ void LLPanelGroupNotices::activate()
{
if(mNoticesList)
mNoticesList->deleteAllItems();
+
+ mPrevSelectedNotice = LLUUID();
BOOL can_send = gAgent.hasPowerInGroup(mGroupID,GP_NOTICES_SEND);
BOOL can_receive = gAgent.hasPowerInGroup(mGroupID,GP_NOTICES_RECEIVE);
@@ -454,12 +456,18 @@ void LLPanelGroupNotices::refreshNotices()
}
+void LLPanelGroupNotices::clearNoticeList()
+{
+ mPrevSelectedNotice = mNoticesList->getStringUUIDSelectedItem();
+ mNoticesList->deleteAllItems();
+}
+
void LLPanelGroupNotices::onClickRefreshNotices(void* data)
{
LL_DEBUGS() << "LLPanelGroupNotices::onClickGetPastNotices" << LL_ENDL;
LLPanelGroupNotices* self = (LLPanelGroupNotices*)data;
- self->mNoticesList->deleteAllItems();
+ self->clearNoticeList();
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("GroupNoticesListRequest");
@@ -547,7 +555,6 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg)
LLSD row;
row["id"] = id;
-
row["columns"][0]["column"] = "icon";
if (has_attachment)
{
@@ -575,7 +582,13 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg)
mNoticesList->setNeedsSort(save_sort);
mNoticesList->updateSort();
- mNoticesList->selectFirstItem();
+ if (mPanelViewNotice->getVisible())
+ {
+ if (!mNoticesList->selectByID(mPrevSelectedNotice))
+ {
+ mNoticesList->selectFirstItem();
+ }
+ }
}
void LLPanelGroupNotices::onSelectNotice(LLUICtrl* ctrl, void* data)
diff --git a/indra/newview/llpanelgroupnotices.h b/indra/newview/llpanelgroupnotices.h
index 04629b5f6b..46c8c241c6 100644
--- a/indra/newview/llpanelgroupnotices.h
+++ b/indra/newview/llpanelgroupnotices.h
@@ -65,6 +65,8 @@ public:
void refreshNotices();
+ void clearNoticeList();
+
virtual void setGroupID(const LLUUID& id);
private:
@@ -113,6 +115,8 @@ private:
LLOfferInfo* mInventoryOffer;
+ LLUUID mPrevSelectedNotice;
+
static std::map<LLUUID,LLPanelGroupNotices*> sInstances;
};
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 087e0a0759..52a13304df 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -834,6 +834,7 @@ BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)
// Show the member's profile on double click.
mMembersList->setDoubleClickCallback(onMemberDoubleClick, this);
mMembersList->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
+ mMembersList->setIsFriendCallback(LLAvatarActions::isFriend);
LLSD row;
row["columns"][0]["column"] = "name";
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 25cfb598e7..3665910c63 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -341,21 +341,17 @@ void LLPanelObject::getState( )
return;
}
- // can move or rotate only linked group with move permissions, or sub-object with move and modify perms
- BOOL enable_move = objectp->permMove() && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()) && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts"));
- BOOL enable_scale = objectp->permMove() && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()) && objectp->permModify();
- BOOL enable_rotate = objectp->permMove() && !objectp->isPermanentEnforced() && ((root_objectp == NULL) || !root_objectp->isPermanentEnforced()) && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts"));
-
S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ))
&& (selected_count == 1);
- if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 1)
- {
- enable_move = FALSE;
- enable_scale = FALSE;
- enable_rotate = FALSE;
- }
+ bool enable_move;
+ bool enable_modify;
+
+ LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify);
+
+ BOOL enable_scale = enable_modify;
+ BOOL enable_rotate = enable_move; // already accounts for a case of children, which needs permModify() as well
LLVector3 vec;
if (enable_move)
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 30fef9f5f0..1cbff37287 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -213,10 +213,39 @@ protected:
}
};
+class LLAvatarItemRecentArrivalComparator : public LLAvatarItemNameComparator
+{
+public:
+ LLAvatarItemRecentArrivalComparator() {};
+ virtual ~LLAvatarItemRecentArrivalComparator() {};
+
+protected:
+ virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const
+ {
+
+ F32 arr_time1 = LLRecentPeople::instance().getArrivalTimeByID(item1->getAvatarId());
+ F32 arr_time2 = LLRecentPeople::instance().getArrivalTimeByID(item2->getAvatarId());
+
+ if (arr_time1 == arr_time2)
+ {
+ std::string name1 = item1->getAvatarName();
+ std::string name2 = item2->getAvatarName();
+
+ LLStringUtil::toUpper(name1);
+ LLStringUtil::toUpper(name2);
+
+ return name1 < name2;
+ }
+
+ return arr_time1 > arr_time2;
+ }
+};
+
static const LLAvatarItemRecentComparator RECENT_COMPARATOR;
static const LLAvatarItemStatusComparator STATUS_COMPARATOR;
static LLAvatarItemDistanceComparator DISTANCE_COMPARATOR;
static const LLAvatarItemRecentSpeakerComparator RECENT_SPEAKER_COMPARATOR;
+static LLAvatarItemRecentArrivalComparator RECENT_ARRIVAL_COMPARATOR;
static LLPanelInjector<LLPanelPeople> t_people("panel_people");
@@ -539,6 +568,8 @@ LLPanelPeople::LLPanelPeople()
mEnableCallbackRegistrar.add("People.Nearby.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck, this, _2));
mEnableCallbackRegistrar.add("People.Group.Plus.Validate", boost::bind(&LLPanelPeople::onGroupPlusButtonValidate, this));
+
+ doPeriodically(boost::bind(&LLPanelPeople::updateNearbyArrivalTime, this), 2.0);
}
LLPanelPeople::~LLPanelPeople()
@@ -1049,6 +1080,10 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save
list->setComparator(&DISTANCE_COMPARATOR);
list->sort();
break;
+ case E_SORT_BY_RECENT_ARRIVAL:
+ list->setComparator(&RECENT_ARRIVAL_COMPARATOR);
+ list->sort();
+ break;
default:
LL_WARNS() << "Unrecognized people sort order for " << list->getName() << LL_ENDL;
return;
@@ -1386,6 +1421,10 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)
{
setSortOrder(mNearbyList, E_SORT_BY_DISTANCE);
}
+ else if (chosen_item == "sort_arrival")
+ {
+ setSortOrder(mNearbyList, E_SORT_BY_RECENT_ARRIVAL);
+ }
else if (chosen_item == "view_usernames")
{
bool hide_usernames = !gSavedSettings.getBOOL("NearbyListHideUsernames");
@@ -1407,6 +1446,8 @@ bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata)
return sort_order == E_SORT_BY_NAME;
if (item == "sort_distance")
return sort_order == E_SORT_BY_DISTANCE;
+ if (item == "sort_arrival")
+ return sort_order == E_SORT_BY_RECENT_ARRIVAL;
return false;
}
@@ -1594,5 +1635,15 @@ bool LLPanelPeople::isAccordionCollapsedByUser(const std::string& name)
return isAccordionCollapsedByUser(getChild<LLUICtrl>(name));
}
+bool LLPanelPeople::updateNearbyArrivalTime()
+{
+ std::vector<LLVector3d> positions;
+ std::vector<LLUUID> uuids;
+ static LLCachedControl<F32> range(gSavedSettings, "NearMeRange");
+ LLWorld::getInstance()->getAvatars(&uuids, &positions, gAgent.getPositionGlobal(), range);
+ LLRecentPeople::instance().updateAvatarsArrivalTime(uuids);
+ return LLApp::isExiting();
+}
+
// EOF
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index eb7e76a772..c72c4fc08a 100644
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -62,6 +62,8 @@ public:
// internals
class Updater;
+ bool updateNearbyArrivalTime();
+
private:
typedef enum e_sort_oder {
@@ -70,6 +72,7 @@ private:
E_SORT_BY_MOST_RECENT = 2,
E_SORT_BY_DISTANCE = 3,
E_SORT_BY_RECENT_SPEAKERS = 4,
+ E_SORT_BY_RECENT_ARRIVAL = 5
} ESortOrder;
void removePicker();
diff --git a/indra/newview/llpresetsmanager.cpp b/indra/newview/llpresetsmanager.cpp
index 96818d5a21..df93572508 100644
--- a/indra/newview/llpresetsmanager.cpp
+++ b/indra/newview/llpresetsmanager.cpp
@@ -138,6 +138,11 @@ bool LLPresetsManager::savePreset(const std::string& subdirectory, std::string n
{
name = PRESETS_DEFAULT;
}
+ if (!createDefault && name == PRESETS_DEFAULT)
+ {
+ LL_WARNS() << "Should not overwrite default" << LL_ENDL;
+ return false;
+ }
bool saved = false;
std::vector<std::string> name_list;
diff --git a/indra/newview/llrecentpeople.cpp b/indra/newview/llrecentpeople.cpp
index 7689cd1a52..83b0c4f1bf 100644
--- a/indra/newview/llrecentpeople.cpp
+++ b/indra/newview/llrecentpeople.cpp
@@ -126,3 +126,33 @@ bool LLRecentPeople::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
add(event->getValue().asUUID());
return true;
}
+
+void LLRecentPeople::updateAvatarsArrivalTime(uuid_vec_t& uuids)
+{
+ id_to_time_map_t buf = mAvatarsArrivalTime;
+ mAvatarsArrivalTime.clear();
+
+ for (uuid_vec_t::const_iterator id_it = uuids.begin(); id_it != uuids.end(); ++id_it)
+ {
+ if (buf.find(*id_it) != buf.end())
+ {
+ mAvatarsArrivalTime[*id_it] = buf[*id_it];
+ }
+ else
+ {
+ mAvatarsArrivalTime[*id_it] = LLDate::now().secondsSinceEpoch();
+ }
+ }
+}
+
+F32 LLRecentPeople::getArrivalTimeByID(const LLUUID& id)
+{
+ id_to_time_map_t::const_iterator it = mAvatarsArrivalTime.find(id);
+
+ if (it != mAvatarsArrivalTime.end())
+ {
+ return it->second;
+ }
+ return LLDate::now().secondsSinceEpoch();
+}
+
diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h
index c7aaf604f5..1b4295ddad 100644
--- a/indra/newview/llrecentpeople.h
+++ b/indra/newview/llrecentpeople.h
@@ -53,6 +53,7 @@ class LLRecentPeople: public LLSingleton<LLRecentPeople>, public LLOldEvents::LL
LLSINGLETON_EMPTY_CTOR(LLRecentPeople);
LOG_CLASS(LLRecentPeople);
public:
+ typedef std::map <LLUUID, F32> id_to_time_map_t;
typedef boost::signals2::signal<void ()> signal_t;
/**
@@ -116,6 +117,9 @@ public:
*/
/*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata);
+ void updateAvatarsArrivalTime(uuid_vec_t& uuids);
+ F32 getArrivalTimeByID(const LLUUID& id);
+
private:
const LLUUID& getIDByPhoneNumber(const LLSD& userdata);
@@ -123,6 +127,7 @@ private:
typedef std::map<LLUUID, LLSD> recent_people_t;
recent_people_t mPeople;
signal_t mChangedSignal;
+ id_to_time_map_t mAvatarsArrivalTime;
};
#endif // LL_LLRECENTPEOPLE_H
diff --git a/indra/newview/llregioninfomodel.cpp b/indra/newview/llregioninfomodel.cpp
index 25d7be831f..7daaa7ef8e 100644
--- a/indra/newview/llregioninfomodel.cpp
+++ b/indra/newview/llregioninfomodel.cpp
@@ -158,7 +158,7 @@ void LLRegionInfoModel::update(LLMessageSystem* msg)
// actually the "last set" sun hour, not the current sun hour. JC
msg->getF32(_PREHASH_RegionInfo, _PREHASH_SunHour, mSunHour);
- LL_DEBUGS("Windlight Sync") << "Got region sun hour: " << mSunHour << LL_ENDL;
+ LL_DEBUGS("WindlightSync") << "Got region sun hour: " << mSunHour << LL_ENDL;
msg->getS32Fast(_PREHASH_RegionInfo2, _PREHASH_HardMaxAgents, mHardAgentLimit);
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index ddae109030..fce21fa30a 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -3676,6 +3676,39 @@ void LLSelectMgr::selectForceDelete()
SEND_ONLY_ROOTS);
}
+BOOL LLSelectMgr::selectGetEditMoveLinksetPermissions(bool &move, bool &modify)
+{
+ move = true;
+ modify = true;
+ bool selecting_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
+
+ for (LLObjectSelection::iterator iter = getSelection()->begin();
+ iter != getSelection()->end(); iter++)
+ {
+ LLSelectNode* nodep = *iter;
+ LLViewerObject* object = nodep->getObject();
+ if (!object || !nodep->mValid)
+ {
+ move = false;
+ modify = false;
+ return FALSE;
+ }
+
+ LLViewerObject *root_object = object->getRootEdit();
+ bool this_object_movable = false;
+ if (object->permMove() && !object->isPermanentEnforced() &&
+ ((root_object == NULL) || !root_object->isPermanentEnforced()) &&
+ (object->permModify() || selecting_linked_set))
+ {
+ this_object_movable = true;
+ }
+ move = move && this_object_movable;
+ modify = modify && object->permModify();
+ }
+
+ return TRUE;
+}
+
void LLSelectMgr::selectGetAggregateSaleInfo(U32 &num_for_sale,
BOOL &is_for_sale_mixed,
BOOL &is_sale_price_mixed,
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index e965dd80d5..87ac899325 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -675,6 +675,11 @@ public:
// returns TRUE if all the nodes are valid. Accumulates
// permissions in the parameter.
BOOL selectGetPermissions(LLPermissions& perm);
+
+ // returns TRUE if all the nodes are valid. Depends onto "edit linked" state
+ // Children in linksets are a bit special - they require not only move permission
+ // but also modify if "edit linked" is set, since you move them relative to parent
+ BOOL selectGetEditMoveLinksetPermissions(bool &move, bool &modify);
// Get a bunch of useful sale information for the object(s) selected.
// "_mixed" is true if not all objects have the same setting.
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index a486a29aa2..2503e2a5e2 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -613,7 +613,7 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
if(ctl)
{
- ctl->setTentative(TRUE);
+ ctl->setTentative(!ctl->getEnabled());
ctl->set(TRUE);
}
}
diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp
index d0cff1464b..5a40af14a3 100644
--- a/indra/newview/llsnapshotlivepreview.cpp
+++ b/indra/newview/llsnapshotlivepreview.cpp
@@ -1050,7 +1050,7 @@ void LLSnapshotLivePreview::saveTexture(BOOL outfit_snapshot, std::string name)
tid, LLAssetType::AT_TEXTURE, res_name, res_desc, 0,
folder_type, inv_type,
PERM_ALL, LLFloaterPerms::getGroupPerms("Uploads"), LLFloaterPerms::getEveryonePerms("Uploads"),
- expected_upload_cost));
+ expected_upload_cost, !outfit_snapshot));
upload_new_resource(assetUploadInfo);
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 4c51873715..b44d996558 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -246,6 +246,7 @@ static bool mLoginStatePastUI = false;
const S32 DEFAULT_MAX_AGENT_GROUPS = 42;
const S32 ALLOWED_MAX_AGENT_GROUPS = 500;
+const F32 STATE_AGENT_WAIT_TIMEOUT = 240; //seconds
boost::scoped_ptr<LLEventPump> LLStartUp::sStateWatcher(new LLEventStream("StartupState"));
boost::scoped_ptr<LLStartupListener> LLStartUp::sListener(new LLStartupListener());
@@ -1614,6 +1615,13 @@ bool idle_startup()
LLStartUp::setStartupState( STATE_INVENTORY_SEND );
}
display_startup();
+
+ if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT)
+ {
+ LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
+ LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
+ reset_login();
+ }
return FALSE;
}
diff --git a/indra/newview/llteleporthistory.cpp b/indra/newview/llteleporthistory.cpp
index a20d69dd41..3c3c1c96ef 100644
--- a/indra/newview/llteleporthistory.cpp
+++ b/indra/newview/llteleporthistory.cpp
@@ -116,6 +116,8 @@ void LLTeleportHistory::handleLoginComplete()
void LLTeleportHistory::updateCurrentLocation(const LLVector3d& new_pos)
{
+ if (!gAgent.getRegion()) return;
+
if (!mTeleportHistoryStorage)
{
mTeleportHistoryStorage = LLTeleportHistoryStorage::getInstance();
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 6a8843cb44..5082e16685 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -609,8 +609,8 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
LL_DEBUGS("UserInput") << "hover handled by LLToolPie (inactive)" << LL_ENDL;
}
- else if ( (object && object->flagHandleTouch())
- || (parent && parent->flagHandleTouch()))
+ else if ((!object || !object->isAttachment() || object->getClickAction() != CLICK_ACTION_DISABLED)
+ && ((object && object->flagHandleTouch()) || (parent && parent->flagHandleTouch())))
{
show_highlight = true;
gViewerWindow->setCursor(UI_CURSOR_HAND);
diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp
index ad0c1734f9..f07c14d01f 100644
--- a/indra/newview/llviewerassettype.cpp
+++ b/indra/newview/llviewerassettype.cpp
@@ -84,6 +84,8 @@ LLViewerAssetDictionary::LLViewerAssetDictionary()
addEntry(LLViewerAssetType::AT_PERSON, new ViewerAssetEntry(DAD_PERSON));
+ addEntry(LLViewerAssetType::AT_UNKNOWN, new ViewerAssetEntry(DAD_NONE));
+
addEntry(LLViewerAssetType::AT_NONE, new ViewerAssetEntry(DAD_NONE));
};
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 4e13eceb55..97fbb8c601 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -60,7 +60,7 @@ LLResourceUploadInfo::LLResourceUploadInfo(LLTransactionID transactId,
LLAssetType::EType assetType, std::string name, std::string description,
S32 compressionInfo, LLFolderType::EType destinationType,
LLInventoryType::EType inventoryType, U32 nextOWnerPerms,
- U32 groupPerms, U32 everyonePerms, S32 expectedCost) :
+ U32 groupPerms, U32 everyonePerms, S32 expectedCost, bool showInventory) :
mTransactionId(transactId),
mAssetType(assetType),
mName(name),
@@ -72,6 +72,7 @@ LLResourceUploadInfo::LLResourceUploadInfo(LLTransactionID transactId,
mGroupPerms(groupPerms),
mEveryonePerms(everyonePerms),
mExpectedUploadCost(expectedCost),
+ mShowInventory(showInventory),
mFolderId(LLUUID::null),
mItemId(LLUUID::null),
mAssetId(LLAssetID::null)
@@ -81,7 +82,7 @@ LLResourceUploadInfo::LLResourceUploadInfo(LLTransactionID transactId,
LLResourceUploadInfo::LLResourceUploadInfo(std::string name,
std::string description, S32 compressionInfo,
LLFolderType::EType destinationType, LLInventoryType::EType inventoryType,
- U32 nextOWnerPerms, U32 groupPerms, U32 everyonePerms, S32 expectedCost):
+ U32 nextOWnerPerms, U32 groupPerms, U32 everyonePerms, S32 expectedCost, bool showInventory) :
mName(name),
mDescription(description),
mCompressionInfo(compressionInfo),
@@ -91,6 +92,7 @@ LLResourceUploadInfo::LLResourceUploadInfo(std::string name,
mGroupPerms(groupPerms),
mEveryonePerms(everyonePerms),
mExpectedUploadCost(expectedCost),
+ mShowInventory(showInventory),
mTransactionId(),
mAssetType(LLAssetType::AT_NONE),
mFolderId(LLUUID::null),
@@ -112,6 +114,7 @@ LLResourceUploadInfo::LLResourceUploadInfo(LLAssetID assetId, LLAssetType::EType
mGroupPerms(0),
mEveryonePerms(0),
mExpectedUploadCost(0),
+ mShowInventory(true),
mTransactionId(),
mFolderId(LLUUID::null),
mItemId(LLUUID::null)
@@ -331,10 +334,11 @@ LLNewFileResourceUploadInfo::LLNewFileResourceUploadInfo(
U32 nextOWnerPerms,
U32 groupPerms,
U32 everyonePerms,
- S32 expectedCost) :
+ S32 expectedCost,
+ bool show_inventory) :
LLResourceUploadInfo(name, description, compressionInfo,
destinationType, inventoryType,
- nextOWnerPerms, groupPerms, everyonePerms, expectedCost),
+ nextOWnerPerms, groupPerms, everyonePerms, expectedCost, show_inventory),
mFileName(fileName)
{
}
diff --git a/indra/newview/llviewerassetupload.h b/indra/newview/llviewerassetupload.h
index 43e23a0d42..ee1806b782 100644
--- a/indra/newview/llviewerassetupload.h
+++ b/indra/newview/llviewerassetupload.h
@@ -53,7 +53,8 @@ public:
U32 nextOWnerPerms,
U32 groupPerms,
U32 everyonePerms,
- S32 expectedCost);
+ S32 expectedCost,
+ bool showInventory = true);
virtual ~LLResourceUploadInfo()
{ }
@@ -79,7 +80,7 @@ public:
S32 getExpectedUploadCost() const { return mExpectedUploadCost; };
virtual bool showUploadDialog() const { return true; }
- virtual bool showInventoryPanel() const { return true; }
+ virtual bool showInventoryPanel() const { return mShowInventory; }
virtual std::string getDisplayName() const;
@@ -97,7 +98,8 @@ protected:
U32 nextOWnerPerms,
U32 groupPerms,
U32 everyonePerms,
- S32 expectedCost);
+ S32 expectedCost,
+ bool showInventory = true);
LLResourceUploadInfo(
LLAssetID assetId,
@@ -130,6 +132,7 @@ private:
LLUUID mFolderId;
LLUUID mItemId;
LLAssetID mAssetId;
+ bool mShowInventory;
};
//-------------------------------------------------------------------------
@@ -146,7 +149,8 @@ public:
U32 nextOWnerPerms,
U32 groupPerms,
U32 everyonePerms,
- S32 expectedCost);
+ S32 expectedCost,
+ bool show_inventory = true);
virtual LLSD prepareUpload();
diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp
index fd4315a319..b89e1497a1 100644
--- a/indra/newview/llviewerkeyboard.cpp
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -716,7 +716,7 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL
if(mKeysSkippedByUI.find(translated_key) != mKeysSkippedByUI.end())
{
mKeyHandledByUI[translated_key] = FALSE;
- LL_INFOS("Keyboard Handling") << "Key wasn't handled by UI!" << LL_ENDL;
+ LL_INFOS("KeyboardHandling") << "Key wasn't handled by UI!" << LL_ENDL;
}
else
{
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index f7250ffb66..ec851ddaf9 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -134,6 +134,7 @@
#include "llpathfindingmanager.h"
#include "llstartup.h"
#include "boost/unordered_map.hpp"
+#include <boost/regex.hpp>
#include "llcleanup.h"
using namespace LLAvatarAppearanceDefines;
@@ -8025,7 +8026,12 @@ void handle_report_bug(const LLSD& param)
LLUIString url(param.asString());
LLStringUtil::format_map_t replace;
- replace["[ENVIRONMENT]"] = LLURI::escape(LLAppViewer::instance()->getViewerInfoString(true));
+ std::string environment = LLAppViewer::instance()->getViewerInfoString(true);
+ boost::regex regex;
+ regex.assign("</?nolink>");
+ std::string stripped_env = boost::regex_replace(environment, regex, "");
+
+ replace["[ENVIRONMENT]"] = LLURI::escape(stripped_env);
LLSLURL location_url;
LLAgentUI::buildSLURL(location_url);
replace["[LOCATION]"] = LLURI::escape(location_url.getSLURLString());
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index cf1c442ce9..d2a5578568 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -689,7 +689,8 @@ LLUUID upload_new_resource(
const std::string& display_name,
LLAssetStorage::LLStoreAssetCallback callback,
S32 expected_upload_cost,
- void *userdata)
+ void *userdata,
+ bool show_inventory)
{
LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
@@ -697,7 +698,7 @@ LLUUID upload_new_resource(
name, desc, compression_info,
destination_folder_type, inv_type,
next_owner_perms, group_perms, everyone_perms,
- expected_upload_cost));
+ expected_upload_cost, show_inventory));
upload_new_resource(uploadInfo, callback, userdata);
return LLUUID::null;
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index 35f86f606b..4e8348b5e5 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -55,7 +55,8 @@ LLUUID upload_new_resource(
const std::string& display_name,
LLAssetStorage::LLStoreAssetCallback callback,
S32 expected_upload_cost,
- void *userdata);
+ void *userdata,
+ bool show_inventory = true);
void upload_new_resource(
LLResourceUploadInfo::ptr_t &uploadInfo,
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 850d455c36..0c5bd9ad1d 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -169,7 +169,8 @@ void accept_friendship_coro(std::string url, LLSD notification)
url += "?from=" + payload["from_id"].asString();
url += "&agent_name=\"" + LLURI::escape(gAgentAvatarp->getFullname()) + "\"";
- LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+ LLSD data;
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, data);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -199,20 +200,20 @@ void accept_friendship_coro(std::string url, LLSD notification)
void decline_friendship_coro(std::string url, LLSD notification, S32 option)
{
- LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
- LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
- httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("friendshipResponceErrorProcessing", httpPolicy));
- LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
if (url.empty())
{
LL_WARNS("Friendship") << "Empty capability!" << LL_ENDL;
return;
}
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("friendshipResponceErrorProcessing", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLSD payload = notification["payload"];
url += "?from=" + payload["from_id"].asString();
- LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+ LLSD result = httpAdapter->deleteAndSuspend(httpRequest, url);
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -732,6 +733,122 @@ void send_sound_trigger(const LLUUID& sound_id, F32 gain)
static LLSD sSavedGroupInvite;
static LLSD sSavedResponse;
+void response_group_invitation_coro(std::string url, LLUUID group_id, bool notify_and_update)
+{
+ if (url.empty())
+ {
+ LL_WARNS("GroupInvite") << "Empty capability!" << LL_ENDL;
+ return;
+ }
+
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+ httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("responseGroupInvitation", httpPolicy));
+ LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+ LLSD payload;
+ payload["group"] = group_id;
+
+ LLSD result = httpAdapter->postAndSuspend(httpRequest, url, payload);
+
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ if (!status)
+ {
+ LL_WARNS("GroupInvite") << "HTTP status, " << status.toTerseString() <<
+ ". Group " << group_id << " invitation response processing failed." << LL_ENDL;
+ }
+ else
+ {
+ if (!result.has("success") || result["success"].asBoolean() == false)
+ {
+ LL_WARNS("GroupInvite") << "Server failed to process group " << group_id << " invitation response. " << httpResults << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("GroupInvite") << "Successfully sent response to group " << group_id << " invitation" << LL_ENDL;
+ if (notify_and_update)
+ {
+ LLNotificationsUtil::add("JoinGroupSuccess");
+ gAgent.sendAgentDataUpdateRequest();
+
+ LLGroupMgr::getInstance()->clearGroupData(group_id);
+ // refresh the floater for this group, if any.
+ LLGroupActions::refresh(group_id);
+ }
+ }
+ }
+}
+
+void send_join_group_response(LLUUID group_id, LLUUID transaction_id, bool accept_invite, S32 fee, bool use_offline_cap, LLSD &payload)
+{
+ if (accept_invite && fee > 0)
+ {
+ // If there is a fee to join this group, make
+ // sure the user is sure they want to join.
+ LLSD args;
+ args["COST"] = llformat("%d", fee);
+ // Set the fee for next time to 0, so that we don't keep
+ // asking about a fee.
+ LLSD next_payload = payload;
+ next_payload["fee"] = 0;
+ LLNotificationsUtil::add("JoinGroupCanAfford",
+ args,
+ next_payload);
+ }
+ else if (use_offline_cap)
+ {
+ std::string url;
+ if (accept_invite)
+ {
+ url = gAgent.getRegionCapability("AcceptGroupInvite");
+ }
+ else
+ {
+ url = gAgent.getRegionCapability("DeclineGroupInvite");
+ }
+
+ if (!url.empty())
+ {
+ LL_DEBUGS("GroupInvite") << "Capability url: " << url << LL_ENDL;
+ LLCoros::instance().launch("LLMessageSystem::acceptGroupInvitation",
+ boost::bind(response_group_invitation_coro, url, group_id, accept_invite));
+ }
+ else
+ {
+ // if sim has no this cap, we can do nothing - regular request will fail
+ LL_WARNS("GroupInvite") << "No capability, can't reply to offline invitation!" << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_DEBUGS("GroupInvite") << "Replying to group invite via IM message" << LL_ENDL;
+
+ EInstantMessage type = accept_invite ? IM_GROUP_INVITATION_ACCEPT : IM_GROUP_INVITATION_DECLINE;
+
+ send_improved_im(group_id,
+ std::string("name"),
+ std::string("message"),
+ IM_ONLINE,
+ type,
+ transaction_id);
+ }
+}
+
+void send_join_group_response(LLUUID group_id, LLUUID transaction_id, bool accept_invite, S32 fee, bool use_offline_cap)
+{
+ LLSD payload;
+ if (accept_invite)
+ {
+ payload["group_id"] = group_id;
+ payload["transaction_id"] = transaction_id;
+ payload["fee"] = fee;
+ payload["use_offline_cap"] = use_offline_cap;
+ }
+ send_join_group_response(group_id, transaction_id, accept_invite, fee, use_offline_cap, payload);
+}
+
bool join_group_response(const LLSD& notification, const LLSD& response)
{
// A bit of variable saving and restoring is used to deal with the case where your group list is full and you
@@ -770,6 +887,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
std::string name = notification_adjusted["payload"]["name"].asString();
std::string message = notification_adjusted["payload"]["message"].asString();
S32 fee = notification_adjusted["payload"]["fee"].asInteger();
+ U8 use_offline_cap = notification_adjusted["payload"]["use_offline_cap"].asInteger();
if (option == 2 && !group_id.isNull())
{
@@ -798,42 +916,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response)
return false;
}
}
-
- if (accept_invite)
- {
- // If there is a fee to join this group, make
- // sure the user is sure they want to join.
- if (fee > 0)
- {
- LLSD args;
- args["COST"] = llformat("%d", fee);
- // Set the fee for next time to 0, so that we don't keep
- // asking about a fee.
- LLSD next_payload = notification_adjusted["payload"];
- next_payload["fee"] = 0;
- LLNotificationsUtil::add("JoinGroupCanAfford",
- args,
- next_payload);
- }
- else
- {
- send_improved_im(group_id,
- std::string("name"),
- std::string("message"),
- IM_ONLINE,
- IM_GROUP_INVITATION_ACCEPT,
- transaction_id);
- }
- }
- else
- {
- send_improved_im(group_id,
- std::string("name"),
- std::string("message"),
- IM_ONLINE,
- IM_GROUP_INVITATION_DECLINE,
- transaction_id);
- }
+ send_join_group_response(group_id, transaction_id, accept_invite, fee, use_offline_cap, notification_adjusted["payload"]);
sSavedGroupInvite[id] = LLSD::emptyMap();
sSavedResponse[id] = LLSD::emptyMap();
@@ -1740,7 +1823,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
//don't spam them if they are getting flooded
if (check_offer_throttle(mFromName, true))
{
- log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString(".");
+ log_message = "<nolink>" + chatHistory_string + "</nolink> " + LLTrans::getString("InvOfferGaveYou") + " " + getSanitizedDescription() + LLTrans::getString(".");
LLSD args;
args["MESSAGE"] = log_message;
LLNotificationsUtil::add("SystemMessageTip", args);
@@ -1925,7 +2008,7 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
//don't spam them if they are getting flooded
if (check_offer_throttle(mFromName, true))
{
- log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString(".");
+ log_message = "<nolink>" + chatHistory_string + "</nolink> " + LLTrans::getString("InvOfferGaveYou") + " " + getSanitizedDescription() + LLTrans::getString(".");
LLSD args;
args["MESSAGE"] = log_message;
LLNotificationsUtil::add("SystemMessageTip", args);
@@ -1998,6 +2081,23 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
return false;
}
+std::string LLOfferInfo::getSanitizedDescription()
+{
+ // currently we get description from server as: 'Object' ( Location )
+ // object name shouldn't be shown as a hyperlink
+ std::string description = mDesc;
+
+ std::size_t start = mDesc.find_first_of("'");
+ std::size_t end = mDesc.find_last_of("'");
+ if ((start != std::string::npos) && (end != std::string::npos))
+ {
+ description.insert(start, "<nolink>");
+ description.insert(end + 8, "</nolink>");
+ }
+ return description;
+}
+
+
void LLOfferInfo::initRespondFunctionMap()
{
if(mRespondFunctions.empty())
@@ -2609,6 +2709,12 @@ void process_teleport_start(LLMessageSystem *msg, void**)
U32 teleport_flags = 0x0;
msg->getU32("Info", "TeleportFlags", teleport_flags);
+ if (gAgent.getTeleportState() == LLAgent::TELEPORT_MOVING)
+ {
+ // Race condition?
+ LL_WARNS("Messaging") << "Got TeleportStart, but teleport already in progress. TeleportFlags=" << teleport_flags << LL_ENDL;
+ }
+
LL_DEBUGS("Messaging") << "Got TeleportStart with TeleportFlags=" << teleport_flags << ". gTeleportDisplay: " << gTeleportDisplay << ", gAgent.mTeleportState: " << gAgent.getTeleportState() << LL_ENDL;
// *NOTE: The server sends two StartTeleport packets when you are teleporting to a LM
@@ -2666,7 +2772,7 @@ void process_teleport_progress(LLMessageSystem* msg, void**)
}
std::string buffer;
msg->getString("Info", "Message", buffer);
- LL_DEBUGS("Messaging") << "teleport progress: " << buffer << LL_ENDL;
+ LL_DEBUGS("Messaging") << "teleport progress: " << buffer << " flags: " << teleport_flags << LL_ENDL;
//Sorta hacky...default to using simulator raw messages
//if we don't find the coresponding mapping in our progress mappings
@@ -2789,9 +2895,25 @@ void process_teleport_finish(LLMessageSystem* msg, void**)
if (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE)
{
- // Server either ignored teleport cancel message or did not receive it in time.
- // This message can't be ignored since teleport is complete at server side
- gAgent.restoreCanceledTeleportRequest();
+ if (gAgent.canRestoreCanceledTeleport())
+ {
+ // Server either ignored teleport cancel message or did not receive it in time.
+ // This message can't be ignored since teleport is complete at server side
+ gAgent.restoreCanceledTeleportRequest();
+ }
+ else
+ {
+ // Race condition? Make sure all variables are set correctly for teleport to work
+ LL_WARNS("Messaging") << "Teleport 'finish' message without 'start'" << LL_ENDL;
+ gTeleportDisplay = TRUE;
+ LLViewerMessage::getInstance()->mTeleportStartedSignal();
+ gAgent.setTeleportState(LLAgent::TELEPORT_REQUESTED);
+ make_ui_sound("UISndTeleportOut");
+ }
+ }
+ else if (gAgent.getTeleportState() == LLAgent::TELEPORT_MOVING)
+ {
+ LL_WARNS("Messaging") << "Teleport message in the middle of other teleport" << LL_ENDL;
}
// Teleport is finished; it can't be cancelled now.
@@ -3655,7 +3777,7 @@ void process_time_synch(LLMessageSystem *mesgsys, void **user_data)
LLWorld::getInstance()->setSpaceTimeUSec(space_time_usec);
- LL_DEBUGS("Windlight Sync") << "Sun phase: " << phase << " rad = " << fmodf(phase / F_TWO_PI + 0.25, 1.f) * 24.f << " h" << LL_ENDL;
+ LL_DEBUGS("WindlightSync") << "Sun phase: " << phase << " rad = " << fmodf(phase / F_TWO_PI + 0.25, 1.f) * 24.f << " h" << LL_ENDL;
gSky.setSunPhase(phase);
gSky.setSunTargetDirection(sun_direction, sun_ang_velocity);
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index b0eaa37541..913abef2be 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -66,6 +66,11 @@ enum InventoryOfferResponse
BOOL can_afford_transaction(S32 cost);
void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_group = FALSE,
S32 trx_type = TRANS_GIFT, const std::string& desc = LLStringUtil::null);
+void send_join_group_response(LLUUID group_id,
+ LLUUID transaction_id,
+ bool accept_invite,
+ S32 fee,
+ bool use_offline_cap);
void process_logout_reply(LLMessageSystem* msg, void**);
void process_layer_data(LLMessageSystem *mesgsys, void **user_data);
@@ -257,6 +262,7 @@ public:
private:
void initRespondFunctionMap();
+ std::string getSanitizedDescription();
typedef boost::function<bool (const LLSD&, const LLSD&)> respond_function_t;
typedef std::map<std::string, respond_function_t> respond_function_map_t;
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index 9f6d606a22..46b3c8f315 100644
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -127,7 +127,7 @@ void LLGridManager::initialize(const std::string& grid_file)
addSystemGrid(LLTrans::getString("AditiGridLabel"),
"util.aditi.lindenlab.com",
"https://login.aditi.lindenlab.com/cgi-bin/login.cgi",
- "http://aditi-secondlife.webdev.lindenlab.com/helpers/",
+ "https://secondlife.aditi.lindenlab.com/helpers/",
DEFAULT_LOGIN_PAGE,
SL_UPDATE_QUERY_URL,
"https://my.aditi.lindenlab.com/",
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index b759c2a3ab..4f0460da29 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -2817,7 +2817,8 @@ void LLViewerRegion::unpackRegionHandshake()
void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
{
capabilityNames.append("AbuseCategories");
- //capabilityNames.append("AcceptFriendship");
+ capabilityNames.append("AcceptFriendship");
+ capabilityNames.append("AcceptGroupInvite"); // ReadOfflineMsgs recieved messages only!!!
capabilityNames.append("AgentPreferences");
capabilityNames.append("AgentState");
capabilityNames.append("AttachmentResources");
@@ -2827,7 +2828,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("ChatSessionRequest");
capabilityNames.append("CopyInventoryFromNotecard");
capabilityNames.append("CreateInventoryCategory");
- //capabilityNames.append("DeclineFriendship");
+ capabilityNames.append("DeclineFriendship");
+ capabilityNames.append("DeclineGroupInvite"); // ReadOfflineMsgs recieved messages only!!!
capabilityNames.append("DispatchRegionInfo");
capabilityNames.append("DirectDelivery");
capabilityNames.append("EnvironmentSettings");
@@ -2878,7 +2880,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("ParcelVoiceInfoRequest");
capabilityNames.append("ProductInfoRequest");
capabilityNames.append("ProvisionVoiceAccountRequest");
- //capabilityNames.append("ReadOfflineMsgs");
+ capabilityNames.append("ReadOfflineMsgs"); // Requires to respond reliably: AcceptFriendship, AcceptGroupInvite, DeclineFriendship, DeclineGroupInvite
capabilityNames.append("RemoteParcelRequest");
capabilityNames.append("RenderMaterials");
capabilityNames.append("RequestTextureDownload");
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 39ffbfc989..2e366835d9 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -110,6 +110,12 @@ const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve
const F32 desired_discard_bias_max = (F32)MAX_DISCARD_LEVEL; // max number of levels to reduce image quality by
const F64 log_2 = log(2.0);
+#if ADDRESS_SIZE == 32
+const U32 DESIRED_NORMAL_FETCHED_TEXTURE_SIZE = (U32)LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT / 2;
+#else
+const U32 DESIRED_NORMAL_FETCHED_TEXTURE_SIZE = (U32)LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT;
+#endif
+
//----------------------------------------------------------------------------------------------
//namespace: LLViewerTextureAccess
//----------------------------------------------------------------------------------------------
@@ -1578,12 +1584,17 @@ void LLViewerFetchedTexture::processTextureStats()
mDesiredDiscardLevel = llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel);
}
else
- {
+ {
+ U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+ if (mBoostLevel <= LLGLTexture::BOOST_SCULPTED)
+ {
+ desired_size = DESIRED_NORMAL_FETCHED_TEXTURE_SIZE;
+ }
if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight)
{
- if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
+ if (mFullWidth > desired_size || mFullHeight > desired_size)
{
- mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+ mDesiredDiscardLevel = 1;
}
else
{
@@ -3197,8 +3208,13 @@ void LLViewerLODTexture::processTextureStats()
discard_level = floorf(discard_level);
F32 min_discard = 0.f;
- if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
- min_discard = 1.f; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+ U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+ if (mBoostLevel <= LLGLTexture::BOOST_SCULPTED)
+ {
+ desired_size = DESIRED_NORMAL_FETCHED_TEXTURE_SIZE;
+ }
+ if (mFullWidth > desired_size || mFullHeight > desired_size)
+ min_discard = 1.f;
discard_level = llclamp(discard_level, min_discard, (F32)MAX_DISCARD_LEVEL);
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index cef19c9c2d..01ec703fe6 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -3826,37 +3826,22 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
{
if( !LLSelectMgr::getInstance()->getSelection()->isEmpty() )
{
- BOOL moveable_object_selected = FALSE;
- BOOL all_selected_objects_move = TRUE;
- BOOL all_selected_objects_modify = TRUE;
- BOOL selecting_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
-
- for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
- iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++)
- {
- LLSelectNode* nodep = *iter;
- LLViewerObject* object = nodep->getObject();
- LLViewerObject *root_object = (object == NULL) ? NULL : object->getRootEdit();
- BOOL this_object_movable = FALSE;
- if (object->permMove() && !object->isPermanentEnforced() &&
- ((root_object == NULL) || !root_object->isPermanentEnforced()) &&
- (object->permModify() || selecting_linked_set))
- {
- moveable_object_selected = TRUE;
- this_object_movable = TRUE;
- }
- all_selected_objects_move = all_selected_objects_move && this_object_movable;
- all_selected_objects_modify = all_selected_objects_modify && object->permModify();
- }
+ bool all_selected_objects_move;
+ bool all_selected_objects_modify;
+ // Note: This might be costly to do on each frame and when a lot of objects are selected
+ // we might be better off with some kind of memory for selection and/or states, consider
+ // optimizing, perhaps even some kind of selection generation at level of LLSelectMgr to
+ // make whole viewer benefit.
+ LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(all_selected_objects_move, all_selected_objects_modify);
BOOL draw_handles = TRUE;
- if (tool == LLToolCompTranslate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
+ if (tool == LLToolCompTranslate::getInstance() && !all_selected_objects_move)
{
draw_handles = FALSE;
}
- if (tool == LLToolCompRotate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
+ if (tool == LLToolCompRotate::getInstance() && !all_selected_objects_move)
{
draw_handles = FALSE;
}
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index c58e98b3fb..f971554c9d 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -74,10 +74,18 @@ LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& sess
LLVoiceChannel::~LLVoiceChannel()
{
- // Must check instance exists here, the singleton MAY have already been destroyed.
- if(LLVoiceClient::instanceExists())
+ if (sSuspendedVoiceChannel == this)
{
- LLVoiceClient::getInstance()->removeObserver(this);
+ sSuspendedVoiceChannel = NULL;
+ }
+ if (sCurrentVoiceChannel == this)
+ {
+ sCurrentVoiceChannel = NULL;
+ // Must check instance exists here, the singleton MAY have already been destroyed.
+ if(LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->removeObserver(this);
+ }
}
sVoiceChannelMap.erase(mSessionID);
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 88d17a31a4..dd35ed4c71 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -456,7 +456,7 @@ void LLVivoxVoiceClient::updateSettings()
bool LLVivoxVoiceClient::writeString(const std::string &str)
{
bool result = false;
- LL_DEBUGS("LOW Voice") << "sending:\n" << str << LL_ENDL;
+ LL_DEBUGS("LowVoice") << "sending:\n" << str << LL_ENDL;
if(mConnected)
{
@@ -7269,12 +7269,12 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
if (isEvent)
{
const char *eventTypeCstr = eventTypeString.c_str();
- LL_DEBUGS("LOW Voice") << eventTypeCstr << LL_ENDL;
+ LL_DEBUGS("LowVoice") << eventTypeCstr << LL_ENDL;
if (!stricmp(eventTypeCstr, "ParticipantUpdatedEvent"))
{
// These happen so often that logging them is pretty useless.
- LL_DEBUGS("LOW Voice") << "Updated Params: " << sessionHandle << ", " << sessionGroupHandle << ", " << uriString << ", " << alias << ", " << isModeratorMuted << ", " << isSpeaking << ", " << volume << ", " << energy << LL_ENDL;
+ LL_DEBUGS("LowVoice") << "Updated Params: " << sessionHandle << ", " << sessionGroupHandle << ", " << uriString << ", " << alias << ", " << isModeratorMuted << ", " << isSpeaking << ", " << volume << ", " << energy << LL_ENDL;
LLVivoxVoiceClient::getInstance()->participantUpdatedEvent(sessionHandle, sessionGroupHandle, uriString, alias, isModeratorMuted, isSpeaking, volume, energy);
}
else if (!stricmp(eventTypeCstr, "AccountLoginStateChangeEvent"))
@@ -7343,7 +7343,7 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
<ParticipantType>0</ParticipantType>
</Event>
*/
- LL_DEBUGS("LOW Voice") << "Added Params: " << sessionHandle << ", " << sessionGroupHandle << ", " << uriString << ", " << alias << ", " << nameString << ", " << displayNameString << ", " << participantType << LL_ENDL;
+ LL_DEBUGS("LowVoice") << "Added Params: " << sessionHandle << ", " << sessionGroupHandle << ", " << uriString << ", " << alias << ", " << nameString << ", " << displayNameString << ", " << participantType << LL_ENDL;
LLVivoxVoiceClient::getInstance()->participantAddedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString, displayNameString, participantType);
}
else if (!stricmp(eventTypeCstr, "ParticipantRemovedEvent"))
@@ -7356,7 +7356,7 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
<AccountName>xtx7YNV-3SGiG7rA1fo5Ndw==</AccountName>
</Event>
*/
- LL_DEBUGS("LOW Voice") << "Removed params:" << sessionHandle << ", " << sessionGroupHandle << ", " << uriString << ", " << alias << ", " << nameString << LL_ENDL;
+ LL_DEBUGS("LowVoice") << "Removed params:" << sessionHandle << ", " << sessionGroupHandle << ", " << uriString << ", " << alias << ", " << nameString << LL_ENDL;
LLVivoxVoiceClient::getInstance()->participantRemovedEvent(sessionHandle, sessionGroupHandle, uriString, alias, nameString);
}
@@ -7423,7 +7423,7 @@ void LLVivoxProtocolParser::processResponse(std::string tag)
else
{
const char *actionCstr = actionString.c_str();
- LL_DEBUGS("LOW Voice") << actionCstr << LL_ENDL;
+ LL_DEBUGS("LowVoice") << actionCstr << LL_ENDL;
if (!stricmp(actionCstr, "Session.Set3DPosition.1"))
{
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index b816225b07..768db047a4 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -268,6 +268,12 @@ bool LLWeb::useExternalBrowser(const std::string &url)
boost::match_results<std::string::const_iterator> matches;
return !(boost::regex_search(uri_string, matches, pattern));
}
+ else
+ {
+ boost::regex pattern = boost::regex("^mailto:", boost::regex::perl | boost::regex::icase);
+ boost::match_results<std::string::const_iterator> matches;
+ return boost::regex_search(url, matches, pattern);
+ }
return false;
#endif
}
diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp
index 837b30586b..cbb6e85b96 100644
--- a/indra/newview/llworldmap.cpp
+++ b/indra/newview/llworldmap.cpp
@@ -172,7 +172,7 @@ void LLSimInfo::dump() const
U32 x_pos, y_pos;
from_region_handle(mHandle, &x_pos, &y_pos);
- LL_INFOS("World Map") << x_pos << "," << y_pos
+ LL_INFOS("WorldMap") << x_pos << "," << y_pos
<< " " << mName
<< " " << (S32)mAccess
<< " " << std::hex << mRegionFlags << std::dec
@@ -229,7 +229,7 @@ LLWorldMap::LLWorldMap() :
mTrackingLocation( 0, 0, 0 ),
mFirstRequest(true)
{
- //LL_INFOS("World Map") << "Creating the World Map -> LLWorldMap::LLWorldMap()" << LL_ENDL;
+ //LL_INFOS("WorldMap") << "Creating the World Map -> LLWorldMap::LLWorldMap()" << LL_ENDL;
mMapBlockLoaded = new bool[MAP_BLOCK_RES*MAP_BLOCK_RES];
clearSimFlags();
}
@@ -237,7 +237,7 @@ LLWorldMap::LLWorldMap() :
LLWorldMap::~LLWorldMap()
{
- //LL_INFOS("World Map") << "Destroying the World Map -> LLWorldMap::~LLWorldMap()" << LL_ENDL;
+ //LL_INFOS("WorldMap") << "Destroying the World Map -> LLWorldMap::~LLWorldMap()" << LL_ENDL;
reset();
delete[] mMapBlockLoaded;
}
@@ -375,7 +375,7 @@ bool LLWorldMap::simNameFromPosGlobal(const LLVector3d& pos_global, std::string
void LLWorldMap::reloadItems(bool force)
{
- //LL_INFOS("World Map") << "LLWorldMap::reloadItems()" << LL_ENDL;
+ //LL_INFOS("WorldMap") << "LLWorldMap::reloadItems()" << LL_ENDL;
if (clearItems(force))
{
LLWorldMapMessage::getInstance()->sendItemRequest(MAP_ITEM_TELEHUB);
@@ -407,7 +407,7 @@ bool LLWorldMap::insertRegion(U32 x_world, U32 y_world, std::string& name, LLUUI
else
{
U64 handle = to_region_handle(x_world, y_world);
- //LL_INFOS("World Map") << "Map sim : " << name << ", ID : " << image_id.getString() << LL_ENDL;
+ //LL_INFOS("WorldMap") << "Map sim : " << name << ", ID : " << image_id.getString() << LL_ENDL;
// Insert the region in the region map of the world map
// Loading the LLSimInfo object with what we got and insert it in the map
LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromHandle(handle);
@@ -459,7 +459,7 @@ bool LLWorldMap::insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID&
siminfo = LLWorldMap::getInstance()->createSimInfoFromHandle(handle);
}
- //LL_INFOS("World Map") << "Process item : type = " << type << LL_ENDL;
+ //LL_INFOS("WorldMap") << "Process item : type = " << type << LL_ENDL;
switch (type)
{
case MAP_ITEM_TELEHUB: // telehubs
@@ -553,7 +553,7 @@ bool LLWorldMap::insertItem(U32 x_world, U32 y_world, std::string& name, LLUUID&
}
case MAP_ITEM_AGENT_LOCATIONS: // agent locations
{
-// LL_INFOS("World Map") << "New Location " << new_item.mName << LL_ENDL;
+// LL_INFOS("WorldMap") << "New Location " << new_item.mName << LL_ENDL;
if (extra > 0)
{
new_item.setCount(extra);
@@ -604,7 +604,7 @@ void LLWorldMap::updateRegions(S32 x0, S32 y0, S32 x1, S32 y1)
S32 offset = block_x | (block_y * MAP_BLOCK_RES);
if (!mMapBlockLoaded[offset])
{
- //LL_INFOS("World Map") << "Loading Block (" << block_x << "," << block_y << ")" << LL_ENDL;
+ //LL_INFOS("WorldMap") << "Loading Block (" << block_x << "," << block_y << ")" << LL_ENDL;
LLWorldMapMessage::getInstance()->sendMapBlockRequest(block_x * MAP_BLOCK_SIZE, block_y * MAP_BLOCK_SIZE, (block_x * MAP_BLOCK_SIZE) + MAP_BLOCK_SIZE - 1, (block_y * MAP_BLOCK_SIZE) + MAP_BLOCK_SIZE - 1);
mMapBlockLoaded[offset] = true;
}
@@ -614,7 +614,7 @@ void LLWorldMap::updateRegions(S32 x0, S32 y0, S32 x1, S32 y1)
void LLWorldMap::dump()
{
- LL_INFOS("World Map") << "LLWorldMap::dump()" << LL_ENDL;
+ LL_INFOS("WorldMap") << "LLWorldMap::dump()" << LL_ENDL;
for (sim_info_map_t::iterator it = mSimInfoMap.begin(); it != mSimInfoMap.end(); ++it)
{
LLSimInfo* info = it->second;
diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp
index 865292fa90..8be340de4c 100644
--- a/indra/newview/llworldmapmessage.cpp
+++ b/indra/newview/llworldmapmessage.cpp
@@ -54,7 +54,7 @@ LLWorldMapMessage::~LLWorldMapMessage()
void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle)
{
- //LL_INFOS("World Map") << "Send item request : type = " << type << LL_ENDL;
+ //LL_INFOS("WorldMap") << "Send item request : type = " << type << LL_ENDL;
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_MapItemRequest);
@@ -74,7 +74,7 @@ void LLWorldMapMessage::sendItemRequest(U32 type, U64 handle)
void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name)
{
- //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL;
+ //LL_INFOS("WorldMap") << LL_ENDL;
LLMessageSystem* msg = gMessageSystem;
// Request for region data
@@ -95,7 +95,7 @@ void LLWorldMapMessage::sendNamedRegionRequest(std::string region_name,
const std::string& callback_url,
bool teleport) // immediately teleport when result returned
{
- //LL_INFOS("World Map") << "LLWorldMap::sendNamedRegionRequest()" << LL_ENDL;
+ //LL_INFOS("WorldMap") << LL_ENDL;
mSLURLRegionName = region_name;
mSLURLRegionHandle = 0;
mSLURL = callback_url;
@@ -110,7 +110,7 @@ void LLWorldMapMessage::sendHandleRegionRequest(U64 region_handle,
const std::string& callback_url,
bool teleport) // immediately teleport when result returned
{
- //LL_INFOS("World Map") << "LLWorldMap::sendHandleRegionRequest()" << LL_ENDL;
+ //LL_INFOS("WorldMap") << LL_ENDL;
mSLURLRegionName.clear();
mSLURLRegionHandle = region_handle;
mSLURL = callback_url;
@@ -128,7 +128,7 @@ void LLWorldMapMessage::sendHandleRegionRequest(U64 region_handle,
void LLWorldMapMessage::sendMapBlockRequest(U16 min_x, U16 min_y, U16 max_x, U16 max_y, bool return_nonexistent)
{
- //LL_INFOS("World Map") << "LLWorldMap::sendMapBlockRequest()" << ", min = (" << min_x << ", " << min_y << "), max = (" << max_x << ", " << max_y << "), nonexistent = " << return_nonexistent << LL_ENDL;
+ //LL_INFOS("WorldMap" << " min = (" << min_x << ", " << min_y << "), max = (" << max_x << ", " << max_y << ", nonexistent = " << return_nonexistent << LL_ENDL;
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_MapBlockRequest);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -161,7 +161,7 @@ void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**)
}
S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_Data);
- //LL_INFOS("World Map") << "LLWorldMap::processMapBlockReply(), num_blocks = " << num_blocks << LL_ENDL;
+ //LL_INFOS("WorldMap") << "num_blocks = " << num_blocks << LL_ENDL;
bool found_null_sim = false;
@@ -233,7 +233,7 @@ void LLWorldMapMessage::processMapBlockReply(LLMessageSystem* msg, void**)
// public static
void LLWorldMapMessage::processMapItemReply(LLMessageSystem* msg, void**)
{
- //LL_INFOS("World Map") << "LLWorldMap::processMapItemReply()" << LL_ENDL;
+ //LL_INFOS("WorldMap") << LL_ENDL;
U32 type;
msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ItemType, type);
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 9ae788a409..707fe76cef 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -177,7 +177,7 @@ LLWorldMapView::LLWorldMapView()
mMouseDownY( 0 ),
mSelectIDStart(0)
{
- //LL_INFOS("World Map") << "Creating the Map -> LLWorldMapView::LLWorldMapView()" << LL_ENDL;
+ //LL_INFOS("WorldMap") << "Creating the Map -> LLWorldMapView::LLWorldMapView()" << LL_ENDL;
clearLastClick();
}
@@ -217,7 +217,7 @@ BOOL LLWorldMapView::postBuild()
LLWorldMapView::~LLWorldMapView()
{
- //LL_INFOS("World Map") << "Destroying the map -> LLWorldMapView::~LLWorldMapView()" << LL_ENDL;
+ //LL_INFOS("WorldMap") << "Destroying the map -> LLWorldMapView::~LLWorldMapView()" << LL_ENDL;
cleanupTextures();
}
@@ -616,7 +616,7 @@ void LLWorldMapView::drawMipmap(S32 width, S32 height)
}
else
{
- //LL_INFOS("World Map") << "Render complete, don't draw background..." << LL_ENDL;
+ //LL_INFOS("WorldMap") << "Render complete, don't draw background..." << LL_ENDL;
}
// Render the current level
@@ -705,7 +705,7 @@ bool LLWorldMapView::drawMipmapLevel(S32 width, S32 height, S32 level, bool load
//else
//{
// Waiting for a tile -> the level is not complete
- // LL_INFOS("World Map") << "Unfetched tile. level = " << level << LL_ENDL;
+ // LL_INFOS("WorldMap") << "Unfetched tile. level = " << level << LL_ENDL;
//}
}
else
@@ -1668,7 +1668,7 @@ void LLWorldMapView::updateVisibleBlocks()
S32 world_bottom = world_center_y - S32(half_height / sMapScale) - 1;
S32 world_top = world_center_y + S32(half_height / sMapScale) + 1;
- //LL_INFOS("World Map") << "LLWorldMapView::updateVisibleBlocks() : sMapScale = " << sMapScale << ", left = " << world_left << ", right = " << world_right << ", bottom = " << world_bottom << ", top = " << world_top << LL_ENDL;
+ //LL_INFOS("WorldMap") << "LLWorldMapView::updateVisibleBlocks() : sMapScale = " << sMapScale << ", left = " << world_left << ", right = " << world_right << ", bottom = " << world_bottom << ", top = " << world_top << LL_ENDL;
LLWorldMap::getInstance()->updateRegions(world_left, world_bottom, world_right, world_top);
}
diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp
index 895ccaef5a..a2e519a61a 100644
--- a/indra/newview/llworldmipmap.cpp
+++ b/indra/newview/llworldmipmap.cpp
@@ -100,7 +100,7 @@ void LLWorldMipmap::equalizeBoostLevels()
}
}
#if DEBUG_TILES_STAT
- LL_INFOS("World Map") << "LLWorldMipmap tile stats : total requested = " << nb_tiles << ", visible = " << nb_visible << ", missing = " << nb_missing << LL_ENDL;
+ LL_INFOS("WorldMap") << "LLWorldMipmap tile stats : total requested = " << nb_tiles << ", visible = " << nb_visible << ", missing = " << nb_missing << LL_ENDL;
#endif // DEBUG_TILES_STAT
}
@@ -187,7 +187,7 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32
// Use a local jpeg for every tile to test map speed without S3 access
//imageurl = "file://C:\\Develop\\mapserver-distribute-3\\indra\\build-vc80\\mapserver\\relwithdebinfo\\regions\\00995\\01001\\region-995-1001-prims.jpg";
// END DEBUG
- //LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL;
+ //LL_INFOS("WorldMap") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL;
LLPointer<LLViewerFetchedTexture> img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
img->setBoostLevel(LLGLTexture::BOOST_MAP);
diff --git a/indra/newview/skins/default/textures/icons/Inv_UnknownObject.png b/indra/newview/skins/default/textures/icons/Inv_UnknownObject.png
new file mode 100644
index 0000000000..10f2b31cb5
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/Inv_UnknownObject.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index d757e39366..2540ee148d 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -324,6 +324,7 @@ with the same filename but different name
<texture name="Inv_Undershirt" file_name="icons/Inv_Undershirt.png" preload="false" />
<texture name="Inv_Link" file_name="icons/Inv_Link.png" preload="false" />
<texture name="Inv_Invalid" file_name="icons/Inv_Invalid.png" preload="false" />
+ <texture name="Inv_Unknown" file_name="icons/Inv_UnknownObject.png" preload="false" />
<texture name="Inv_VersionFolderClosed" file_name="icons/Inv_VersionFolderClosed.png" preload="false" />
<texture name="Inv_VersionFolderOpen" file_name="icons/Inv_VersionFolderOpen.png" preload="false" />
diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index 3e66007627..45f14a1192 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -70,7 +70,7 @@ UI-Skalierung: [UI_SCALE]
Sichtweite: [DRAW_DISTANCE] m
Bandbreite: [NET_BANDWITH] kbit/s
LOD-Faktor: [LOD_FACTOR]
-Darstellungsqualität: [RENDER_QUALITY] / 7
+Darstellungsqualität: [RENDER_QUALITY]
Erweitertes Beleuchtungsmodell: [GPU_SHADERS]
Texturspeicher: [TEXTURE_MEMORY] MB
Erstellungszeit VFS (Cache): [VFS_TIME]
diff --git a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
index d714cc613e..ae1fb4cccd 100644
--- a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
+++ b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
@@ -57,7 +57,8 @@
top="27"
visible="false"
width="315"
- word_wrap="true">
+ word_wrap="true"
+ parse_urls="false">
Connecting to [CALLEE_NAME]
</text>
<text
@@ -68,7 +69,8 @@ Connecting to [CALLEE_NAME]
name="calling"
top="27"
width="315"
- word_wrap="true">
+ word_wrap="true"
+ parse_urls="false">
Calling [CALLEE_NAME]
</text>
<text
@@ -90,7 +92,8 @@ No Answer. Please try again later.
name="nearby"
top="27"
width="315"
- word_wrap="true">
+ word_wrap="true"
+ parse_urls="false">
You have been disconnected from [VOICE_CHANNEL_NAME]. [RECONNECT_NEARBY]
</text>
<text
@@ -101,7 +104,8 @@ No Answer. Please try again later.
name="nearby_P2P_by_other"
top="27"
width="315"
- word_wrap="true">
+ word_wrap="true"
+ parse_urls="false">
Your call has ended. [RECONNECT_NEARBY]
</text>
<text
@@ -112,7 +116,8 @@ No Answer. Please try again later.
name="nearby_P2P_by_agent"
top="27"
width="315"
- word_wrap="true">
+ word_wrap="true"
+ parse_urls="false">
You have ended the call. [RECONNECT_NEARBY]
</text>
<text
@@ -123,7 +128,8 @@ No Answer. Please try again later.
name="leaving"
top="62"
width="315"
- word_wrap="true">
+ word_wrap="true"
+ parse_urls="false">
Leaving [CURRENT_CHAT].
</text>
<button
diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml
index a9f6b8045d..0f7c6a2aa5 100644
--- a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml
@@ -33,6 +33,16 @@
function="People.Nearby.ViewSort.CheckItem"
parameter="sort_distance"/>
</menu_item_check>
+ <menu_item_check
+ label="Sort by Recent arrival"
+ name="sort_arrival">
+ <menu_item_check.on_click
+ function="People.Nearby.ViewSort.Action"
+ parameter="sort_arrival"/>
+ <menu_item_check.on_check
+ function="People.Nearby.ViewSort.CheckItem"
+ parameter="sort_arrival"/>
+ </menu_item_check>
<menu_item_separator layout="topleft" />
<menu_item_check name="view_icons" label="View People Icons">
<menu_item_check.on_click
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 6b164c660a..9eaa5330c3 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -8277,6 +8277,13 @@ Failed to save snapshot to [PATH]: Directory does not exist.
type="notifytip">
Error saving preset [NAME].
</notification>
+
+ <notification
+ icon="notifytip.tga"
+ name="DefaultPresetNotSaved"
+ type="notifytip">
+Can not overwrite default preset.
+ </notification>
<notification
icon="notifytip.tga"
diff --git a/indra/newview/skins/default/xui/en/panel_group_notify.xml b/indra/newview/skins/default/xui/en/panel_group_notify.xml
index 4121acdfb0..60e5a03d51 100644
--- a/indra/newview/skins/default/xui/en/panel_group_notify.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_notify.xml
@@ -43,6 +43,7 @@
layout="topleft"
left_pad="10"
name="title"
+ parse_urls="false"
text_color="GroupNotifyTextColor"
top="5"
use_ellipses="true"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 882fbaf634..f5f4b4acab 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -53,7 +53,7 @@ UI Scaling: [UI_SCALE]
Draw distance: [DRAW_DISTANCE]m
Bandwidth: [NET_BANDWITH]kbit/s
LOD factor: [LOD_FACTOR]
-Render quality: [RENDER_QUALITY] / 7
+Render quality: [RENDER_QUALITY]
Advanced Lighting Model: [GPU_SHADERS]
Texture memory: [TEXTURE_MEMORY]MB
VFS (cache) creation time: [VFS_TIME]
diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index 341c6d2fe8..8e795de2d6 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -62,7 +62,7 @@ Ajuste de escala de IU: [UI_SCALE]
Distancia de dibujo: [DRAW_DISTANCE]m
Ancho de banda: [NET_BANDWITH]kbit/s
Factor de LOD: [LOD_FACTOR]
-Calidad de renderizado: [RENDER_QUALITY] / 7
+Calidad de renderizado: [RENDER_QUALITY]
Modelo de iluminación avanzado: [GPU_SHADERS]
Memoria de textura: [TEXTURE_MEMORY]MB
Tiempo de creación de VFS (caché): [VFS_TIME]
diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index d76beee93d..23d93e57bf 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -71,7 +71,7 @@ Ajustement de la taille de la police : [FONT_SIZE_ADJUSTMENT] pts
Limite d’affichage : [DRAW_DISTANCE] m
Bande passante : [NET_BANDWITH] kbit/s
Facteur LOD (niveau de détail) : [LOD_FACTOR]
-Qualité de rendu : [RENDER_QUALITY] / 7
+Qualité de rendu : [RENDER_QUALITY]
Modèle d’éclairage avancé : [GPU_SHADERS]
Mémoire textures : [TEXTURE_MEMORY] Mo
Durée de création VFS (cache) : [VFS_TIME]
diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index ad74e16170..e2610ef057 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -68,7 +68,7 @@ Scala UI: [UI_SCALE]
Distanza visualizzazione: [DRAW_DISTANCE] m
Larghezza banda: [NET_BANDWITH] kbit/s
Fattore livello di dettaglio: [LOD_FACTOR]
-Qualità di rendering: [RENDER_QUALITY] / 7
+Qualità di rendering: [RENDER_QUALITY]
Modello illuminazione avanzato: [GPU_SHADERS]
Memoria texture: [TEXTURE_MEMORY] MB
Data/ora creazione VFS (cache): [VFS_TIME]
@@ -1505,7 +1505,7 @@ Se continui a ricevere questo messaggio, contatta l&apos;assistenza Second Life
Trascina le cartelle in questa area per metterle in vendita su [[MARKETPLACE_DASHBOARD_URL] Marketplace].
</string>
<string name="InventoryItemsCount">
- ( [ITEM_COUNT] oggetti )
+ ( [ITEMS_COUNT] oggetti )
</string>
<string name="Marketplace Validation Warning Stock">
la cartella di magazzino deve essere inclusa in una cartella di versione
diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index 5ca7ddd92c..7faf463fd4 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -71,7 +71,7 @@ UI スケーリング: [UI_SCALE]
描画距離:[DRAW_DISTANCE]m
帯域幅:[NET_BANDWITH]kbit/s
LOD 係数: [LOD_FACTOR]
-表示品質: [RENDER_QUALITY] / 7
+表示品質: [RENDER_QUALITY]
高度なライティングモデル: [GPU_SHADERS]
テクスチャメモリ: [TEXTURE_MEMORY]MB
VFS(キャッシュ)作成時間: [VFS_TIME]
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index ee048e28e3..046e7db47c 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -62,7 +62,7 @@ Escala de interface: [UI_SCALE]
Dist. máxima: [DRAW_DISTANCE]m
Largura de banda: [NET_BANDWITH]kbit/s
Fator LOD: [LOD_FACTOR]
-Qualidade de renderização: [RENDER_QUALITY] / 7
+Qualidade de renderização: [RENDER_QUALITY]
Modelo de iluminação avançado: [GPU_SHADERS]
Memória de textura: [TEXTURE_MEMORY]MB
Tempo de criação de VFS (cache): [VFS_TIME]
diff --git a/indra/newview/skins/default/xui/ru/floater_tos.xml b/indra/newview/skins/default/xui/ru/floater_tos.xml
index 3f2b5747d5..7196a04de1 100644
--- a/indra/newview/skins/default/xui/ru/floater_tos.xml
+++ b/indra/newview/skins/default/xui/ru/floater_tos.xml
@@ -16,6 +16,6 @@
<text name="agree_list">
Я прочитал и согласен с Условиями и положениями по конфиденциальности Пользовательского соглашения, включая требования по разрешению разногласий Second Life.
</text>
- <button label="Продолжить" label_selected="Продолжить" name="Continue"/>
+ <button label="Продолжить" label_selected="Продолжить" name="Continue" top_delta="45"/>
<button label="Отмена" label_selected="Отмена" name="Cancel"/>
</floater>
diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml
index 95225da7d0..267c717189 100644
--- a/indra/newview/skins/default/xui/ru/strings.xml
+++ b/indra/newview/skins/default/xui/ru/strings.xml
@@ -71,7 +71,7 @@ SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
Дальность отрисовки: [DRAW_DISTANCE] м
Ширина канала: [NET_BANDWITH] кбит/с
Коэффициент детализации: [LOD_FACTOR]
-Качество визуализации: [RENDER_QUALITY] / 7
+Качество визуализации: [RENDER_QUALITY]
Расширенная модель освещения: [GPU_SHADERS]
Память текстур: [TEXTURE_MEMORY] МБ
Время создания VFS (кэш): [VFS_TIME]
diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml
index 6850c67df3..6542e61475 100644
--- a/indra/newview/skins/default/xui/tr/strings.xml
+++ b/indra/newview/skins/default/xui/tr/strings.xml
@@ -71,7 +71,7 @@ Kullanıcı Arayüzü Ölçekleme: [UI_SCALE]
Çizme mesafesi: [DRAW_DISTANCE] m
Bant genişliği: [NET_BANDWITH] kbit/sn
Ayrıntı seviyesi faktörü: [LOD_FACTOR]
-İşleme kalitesi: [RENDER_QUALITY] / 7
+İşleme kalitesi: [RENDER_QUALITY]
Gelişmiş Aydınlatma Modeli: [GPU_SHADERS]
Doku belleği: [TEXTURE_MEMORY]MB
VFS (önbellek) oluşturma zamanı: [VFS_TIME]
diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml
index e4f9c5d433..24d8dc60cb 100644
--- a/indra/newview/skins/default/xui/zh/strings.xml
+++ b/indra/newview/skins/default/xui/zh/strings.xml
@@ -71,7 +71,7 @@
描繪距離:[DRAW_DISTANCE]公尺
頻寬:[NET_BANDWITH]千位元/秒
細節層次率:[LOD_FACTOR]
-呈像品質:[RENDER_QUALITY] / 7
+呈像品質:[RENDER_QUALITY]
進階照明模型:[GPU_SHADERS]
材質記憶體:[TEXTURE_MEMORY]MB
VFS(快取)建立時間:[VFS_TIME]
diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp
index d1dddf8e7e..bb28abead3 100644
--- a/indra/newview/tests/llviewernetwork_test.cpp
+++ b/indra/newview/tests/llviewernetwork_test.cpp
@@ -258,7 +258,7 @@ namespace tut
std::string("https://login.aditi.lindenlab.com/cgi-bin/login.cgi"));
ensure_equals("Aditi helper uri",
LLGridManager::getInstance()->getHelperURI("util.aditi.lindenlab.com"),
- std::string("http://aditi-secondlife.webdev.lindenlab.com/helpers/"));
+ std::string("https://secondlife.aditi.lindenlab.com/helpers/"));
ensure_equals("Aditi login page",
LLGridManager::getInstance()->getLoginPage("util.aditi.lindenlab.com"),
std::string("https://viewer-splash.secondlife.com/"));
@@ -330,7 +330,7 @@ namespace tut
std::string("https://login.aditi.lindenlab.com/cgi-bin/login.cgi"));
ensure_equals("Aditi helper uri",
LLGridManager::getInstance()->getHelperURI("util.aditi.lindenlab.com"),
- std::string("http://aditi-secondlife.webdev.lindenlab.com/helpers/"));
+ std::string("https://secondlife.aditi.lindenlab.com/helpers/"));
ensure_equals("Aditi login page",
LLGridManager::getInstance()->getLoginPage("util.aditi.lindenlab.com"),
std::string("https://viewer-splash.secondlife.com/"));
diff --git a/indra/test/io.cpp b/indra/test/io.cpp
index ff900ab96b..40243a8ad6 100644
--- a/indra/test/io.cpp
+++ b/indra/test/io.cpp
@@ -914,7 +914,8 @@ namespace tut
mSocket = LLSocket::create(
mPool,
LLSocket::STREAM_TCP,
- SERVER_LISTEN_PORT);
+ SERVER_LISTEN_PORT,
+ "127.0.0.1");
}
~pipe_and_pump_fitness()
diff --git a/scripts/content_tools/anim_tool.py b/scripts/content_tools/anim_tool.py
index 77bf731ae6..3496617b21 100644
--- a/scripts/content_tools/anim_tool.py
+++ b/scripts/content_tools/anim_tool.py
@@ -1,14 +1,22 @@
-#!runpy.sh
-
+#!/usr/bin/python
"""\
-
-This module contains tools for manipulating the .anim files supported
-for Second Life animation upload. Note that this format is unrelated
-to any non-Second Life formats of the same name.
-
-$LicenseInfo:firstyear=2016&license=viewerlgpl$
+@file anim_tool.py
+@author Brad Payne, Nat Goodspeed
+@date 2015-09-15
+@brief This module contains tools for manipulating the .anim files supported
+ for Second Life animation upload. Note that this format is unrelated
+ to any non-Second Life formats of the same name.
+
+ This code is a Python translation of the logic in
+ LLKeyframeMotion::serialize() and deserialize():
+ https://bitbucket.org/lindenlab/viewer-release/src/827a910542a9af0a39b0ca03663c02e5c83869ea/indra/llcharacter/llkeyframemotion.cpp?at=default&fileviewer=file-view-default#llkeyframemotion.cpp-1864
+ https://bitbucket.org/lindenlab/viewer-release/src/827a910542a9af0a39b0ca03663c02e5c83869ea/indra/llcharacter/llkeyframemotion.cpp?at=default&fileviewer=file-view-default#llkeyframemotion.cpp-1220
+ save that there is no support for old-style .anim files, permitting
+ simpler code.
+
+$LicenseInfo:firstyear=2015&license=viewerlgpl$
Second Life Viewer Source Code
-Copyright (C) 2016, Linden Research, Inc.
+Copyright (C) 2015, 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
@@ -28,63 +36,85 @@ Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
$/LicenseInfo$
"""
-import sys
-import os
-import struct
-import StringIO
import math
-import argparse
+import os
import random
-from lxml import etree
+from cStringIO import StringIO
+import struct
+import sys
+from xml.etree import ElementTree
+
+class Error(Exception):
+ pass
+
+class BadFormat(Error):
+ """
+ Something went wrong trying to read the specified .anim file.
+ """
+ pass
+
+class ExtraneousData(BadFormat):
+ """
+ Specifically, the .anim file in question contains more data than needed.
+ This could happen if the file isn't a .anim at all, and it 'just happens'
+ to read properly otherwise -- e.g. a block of all zero bytes could look
+ like empty name strings, empty arrays etc. That could be a legitimate
+ error -- or it could be due to a sloppy tool. Break this exception out
+ separately so caller can distinguish if desired.
+ """
+ pass
U16MAX = 65535
-OOU16MAX = 1.0/(float)(U16MAX)
+# One Over U16MAX, for scaling
+OOU16MAX = 1.0/float(U16MAX)
LL_MAX_PELVIS_OFFSET = 5.0
class FilePacker(object):
def __init__(self):
- self.data = StringIO.StringIO()
- self.offset = 0
+ self.buffer = StringIO()
def write(self,filename):
- f = open(filename,"wb")
- f.write(self.data.getvalue())
- f.close()
+ with open(filename,"wb") as f:
+ f.write(self.buffer.getvalue())
def pack(self,fmt,*args):
buf = struct.pack(fmt, *args)
- self.offset += struct.calcsize(fmt)
- self.data.write(buf)
+ self.buffer.write(buf)
def pack_string(self,str,size=0):
- buf = str + "\000"
- if size and (len(buf) < size):
- buf += "\000" * (size-len(buf))
- self.data.write(buf)
+ # If size == 0, caller doesn't care, just wants a terminating nul byte
+ size = size or (len(str) + 1)
+ # Nonzero size means a fixed-length field. If the passed string (plus
+ # its terminating nul) exceeds that fixed length, we'll have to
+ # truncate. But make sure we still leave room for the final nul byte!
+ str = str[:size-1]
+ # Now pad what's left of str out to 'size' with nul bytes.
+ buf = str + ("\000" * (size-len(str)))
+ self.buffer.write(buf)
class FileUnpacker(object):
def __init__(self, filename):
- f = open(filename,"rb")
- self.data = f.read()
+ with open(filename,"rb") as f:
+ self.buffer = f.read()
self.offset = 0
def unpack(self,fmt):
- result = struct.unpack_from(fmt, self.data, self.offset)
+ result = struct.unpack_from(fmt, self.buffer, self.offset)
self.offset += struct.calcsize(fmt)
return result
def unpack_string(self, size=0):
- result = ""
- i = 0
- while (self.data[self.offset+i] != "\000"):
- result += self.data[self.offset+i]
- i += 1
- i += 1
+ # Nonzero size means we must consider exactly the next 'size'
+ # characters in self.buffer.
if size:
- # fixed-size field for the string
- i = size
- self.offset += i
+ self.offset += size
+ # but stop at the first nul byte
+ return self.buffer[self.offset-size:self.offset].split("\000", 1)[0]
+ # Zero size means consider everything until the next nul character.
+ result = self.buffer[self.offset:].split("\000", 1)[0]
+ # don't forget to skip the nul byte too
+ self.offset += len(result) + 1
return result
# translated from the C++ version in lldefs.h
@@ -108,7 +138,7 @@ def F32_to_U16(val, lower, upper):
# translated from the C++ version in llquantize.h
def U16_to_F32(ival, lower, upper):
if ival < 0 or ival > U16MAX:
- raise Exception("U16 out of range: "+ival)
+ raise ValueError("U16 out of range: %s" % ival)
val = ival*OOU16MAX
delta = (upper - lower)
val *= delta
@@ -121,71 +151,100 @@ def U16_to_F32(ival, lower, upper):
val = 0.0
return val;
-class BadFormat(Exception):
- pass
-
class RotKey(object):
- def __init__(self):
- pass
-
- def unpack(self, anim, fup):
- (self.time_short, ) = fup.unpack("<H")
- self.time = U16_to_F32(self.time_short, 0.0, anim.duration)
+ def __init__(self, time, duration, rot):
+ """
+ This constructor instantiates a RotKey object from scratch, as it
+ were, converting from float time to time_short.
+ """
+ self.time = time
+ self.time_short = F32_to_U16(time, 0.0, duration) \
+ if time is not None else None
+ self.rotation = rot
+
+ @staticmethod
+ def unpack(duration, fup):
+ """
+ This staticmethod constructs a RotKey by loadingfrom a FileUnpacker.
+ """
+ # cheat the other constructor
+ this = RotKey(None, None, None)
+ # load time_short directly from the file
+ (this.time_short, ) = fup.unpack("<H")
+ # then convert to float time
+ this.time = U16_to_F32(this.time_short, 0.0, duration)
+ # convert each coordinate of the rotation from short to float
(x,y,z) = fup.unpack("<HHH")
- self.rotation = [U16_to_F32(i, -1.0, 1.0) for i in (x,y,z)]
+ this.rotation = [U16_to_F32(i, -1.0, 1.0) for i in (x,y,z)]
+ return this
def dump(self, f):
- print >>f, " rot_key: t",self.time,"st",self.time_short,"rot",",".join([str(f) for f in self.rotation])
+ print >>f, " rot_key: t %.3f" % self.time,"st",self.time_short,"rot",",".join("%.3f" % f for f in self.rotation)
- def pack(self, anim, fp):
- if not hasattr(self,"time_short"):
- self.time_short = F32_to_U16(self.time, 0.0, anim.duration)
+ def pack(self, fp):
fp.pack("<H",self.time_short)
(x,y,z) = [F32_to_U16(v, -1.0, 1.0) for v in self.rotation]
fp.pack("<HHH",x,y,z)
class PosKey(object):
- def __init__(self):
- pass
-
- def unpack(self, anim, fup):
- (self.time_short, ) = fup.unpack("<H")
- self.time = U16_to_F32(self.time_short, 0.0, anim.duration)
+ def __init__(self, time, duration, pos):
+ """
+ This constructor instantiates a PosKey object from scratch, as it
+ were, converting from float time to time_short.
+ """
+ self.time = time
+ self.time_short = F32_to_U16(time, 0.0, duration) \
+ if time is not None else None
+ self.position = pos
+
+ @staticmethod
+ def unpack(duration, fup):
+ """
+ This staticmethod constructs a PosKey by loadingfrom a FileUnpacker.
+ """
+ # cheat the other constructor
+ this = PosKey(None, None, None)
+ # load time_short directly from the file
+ (this.time_short, ) = fup.unpack("<H")
+ # then convert to float time
+ this.time = U16_to_F32(this.time_short, 0.0, duration)
+ # convert each coordinate of the rotation from short to float
(x,y,z) = fup.unpack("<HHH")
- self.position = [U16_to_F32(i, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET) for i in (x,y,z)]
+ this.position = [U16_to_F32(i, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET)
+ for i in (x,y,z)]
+ return this
def dump(self, f):
- print >>f, " pos_key: t",self.time,"pos ",",".join([str(f) for f in self.position])
+ print >>f, " pos_key: t %.3f" % self.time,"pos ",",".join("%.3f" % f for f in self.position)
- def pack(self, anim, fp):
- if not hasattr(self,"time_short"):
- self.time_short = F32_to_U16(self.time, 0.0, anim.duration)
+ def pack(self, fp):
fp.pack("<H",self.time_short)
(x,y,z) = [F32_to_U16(v, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET) for v in self.position]
fp.pack("<HHH",x,y,z)
class Constraint(object):
- def __init__(self):
- pass
-
- def unpack(self, anim, fup):
- (self.chain_length, self.constraint_type) = fup.unpack("<BB")
- self.source_volume = fup.unpack_string(16)
- self.source_offset = fup.unpack("<fff")
- self.target_volume = fup.unpack_string(16)
- self.target_offset = fup.unpack("<fff")
- self.target_dir = fup.unpack("<fff")
- fmt = "<ffff"
- (self.ease_in_start, self.ease_in_stop, self.ease_out_start, self.ease_out_stop) = fup.unpack("<ffff")
-
- def pack(self, anim, fp):
+ @staticmethod
+ def unpack(duration, fup):
+ this = Constraint()
+ (this.chain_length, this.constraint_type) = fup.unpack("<BB")
+ this.source_volume = fup.unpack_string(16)
+ this.source_offset = fup.unpack("<fff")
+ this.target_volume = fup.unpack_string(16)
+ this.target_offset = fup.unpack("<fff")
+ this.target_dir = fup.unpack("<fff")
+ (this.ease_in_start, this.ease_in_stop, this.ease_out_start, this.ease_out_stop) = \
+ fup.unpack("<ffff")
+ return this
+
+ def pack(self, fp):
fp.pack("<BB", self.chain_length, self.constraint_type)
fp.pack_string(self.source_volume, 16)
fp.pack("<fff", *self.source_offset)
fp.pack_string(self.target_volume, 16)
fp.pack("<fff", *self.target_offset)
fp.pack("<fff", *self.target_dir)
- fp.pack("<ffff", self.ease_in_start, self.ease_in_stop, self.ease_out_start, self.ease_out_stop)
+ fp.pack("<ffff", self.ease_in_start, self.ease_in_stop,
+ self.ease_out_start, self.ease_out_stop)
def dump(self, f):
print >>f, " constraint:"
@@ -202,30 +261,26 @@ class Constraint(object):
print >>f, " ease_out_stop",self.ease_out_stop
class Constraints(object):
- def __init__(self):
- pass
-
- def unpack(self, anim, fup):
- (self.num_constraints, ) = fup.unpack("<i")
- self.constraints = []
- for i in xrange(self.num_constraints):
- constraint = Constraint()
- constraint.unpack(anim, fup)
- self.constraints.append(constraint)
-
- def pack(self, anim, fp):
- fp.pack("<i",self.num_constraints)
+ @staticmethod
+ def unpack(duration, fup):
+ this = Constraints()
+ (num_constraints, ) = fup.unpack("<i")
+ this.constraints = [Constraint.unpack(duration, fup)
+ for i in xrange(num_constraints)]
+ return this
+
+ def pack(self, fp):
+ fp.pack("<i",len(self.constraints))
for c in self.constraints:
- c.pack(anim,fp)
+ c.pack(fp)
def dump(self, f):
- print >>f, "constraints:",self.num_constraints
+ print >>f, "constraints:",len(self.constraints)
for c in self.constraints:
c.dump(f)
class PositionCurve(object):
def __init__(self):
- self.num_pos_keys = 0
self.keys = []
def is_static(self):
@@ -236,28 +291,27 @@ class PositionCurve(object):
return False
return True
- def unpack(self, anim, fup):
- (self.num_pos_keys, ) = fup.unpack("<i")
- self.keys = []
- for k in xrange(0,self.num_pos_keys):
- pos_key = PosKey()
- pos_key.unpack(anim, fup)
- self.keys.append(pos_key)
+ @staticmethod
+ def unpack(duration, fup):
+ this = PositionCurve()
+ (num_pos_keys, ) = fup.unpack("<i")
+ this.keys = [PosKey.unpack(duration, fup)
+ for k in xrange(num_pos_keys)]
+ return this
- def pack(self, anim, fp):
- fp.pack("<i",self.num_pos_keys)
+ def pack(self, fp):
+ fp.pack("<i",len(self.keys))
for k in self.keys:
- k.pack(anim, fp)
+ k.pack(fp)
def dump(self, f):
print >>f, " position_curve:"
- print >>f, " num_pos_keys", self.num_pos_keys
- for k in xrange(0,self.num_pos_keys):
- self.keys[k].dump(f)
+ print >>f, " num_pos_keys", len(self.keys)
+ for k in self.keys:
+ k.dump(f)
class RotationCurve(object):
def __init__(self):
- self.num_rot_keys = 0
self.keys = []
def is_static(self):
@@ -268,42 +322,46 @@ class RotationCurve(object):
return False
return True
- def unpack(self, anim, fup):
- (self.num_rot_keys, ) = fup.unpack("<i")
- self.keys = []
- for k in xrange(0,self.num_rot_keys):
- rot_key = RotKey()
- rot_key.unpack(anim, fup)
- self.keys.append(rot_key)
+ @staticmethod
+ def unpack(duration, fup):
+ this = RotationCurve()
+ (num_rot_keys, ) = fup.unpack("<i")
+ this.keys = [RotKey.unpack(duration, fup)
+ for k in xrange(num_rot_keys)]
+ return this
- def pack(self, anim, fp):
- fp.pack("<i",self.num_rot_keys)
+ def pack(self, fp):
+ fp.pack("<i",len(self.keys))
for k in self.keys:
- k.pack(anim, fp)
+ k.pack(fp)
def dump(self, f):
print >>f, " rotation_curve:"
- print >>f, " num_rot_keys", self.num_rot_keys
- for k in xrange(0,self.num_rot_keys):
- self.keys[k].dump(f)
+ print >>f, " num_rot_keys", len(self.keys)
+ for k in self.keys:
+ k.dump(f)
class JointInfo(object):
- def __init__(self):
- pass
-
- def unpack(self, anim, fup):
- self.joint_name = fup.unpack_string()
- (self.joint_priority, ) = fup.unpack("<i")
+ def __init__(self, name, priority):
+ self.joint_name = name
+ self.joint_priority = priority
self.rotation_curve = RotationCurve()
- self.rotation_curve.unpack(anim, fup)
self.position_curve = PositionCurve()
- self.position_curve.unpack(anim, fup)
- def pack(self, anim, fp):
+ @staticmethod
+ def unpack(duration, fup):
+ this = JointInfo(None, None)
+ this.joint_name = fup.unpack_string()
+ (this.joint_priority, ) = fup.unpack("<i")
+ this.rotation_curve = RotationCurve.unpack(duration, fup)
+ this.position_curve = PositionCurve.unpack(duration, fup)
+ return this
+
+ def pack(self, fp):
fp.pack_string(self.joint_name)
fp.pack("<i", self.joint_priority)
- self.rotation_curve.pack(anim, fp)
- self.position_curve.pack(anim, fp)
+ self.rotation_curve.pack(fp)
+ self.position_curve.pack(fp)
def dump(self, f):
print >>f, "joint:"
@@ -313,13 +371,26 @@ class JointInfo(object):
self.position_curve.dump(f)
class Anim(object):
- def __init__(self, filename=None):
+ def __init__(self, filename=None, verbose=False):
+ # set this FIRST as it's consulted by read() and unpack()
+ self.verbose = verbose
if filename:
self.read(filename)
def read(self, filename):
fup = FileUnpacker(filename)
- self.unpack(fup)
+ try:
+ self.unpack(fup)
+ except struct.error as err:
+ raise BadFormat("error reading %s: %s" % (filename, err))
+ # By the end of streaming data in from our FileUnpacker, we should
+ # have consumed the entire thing. If there's excess data, it's
+ # entirely possible that this is a garbage file that happens to
+ # resemble a valid degenerate .anim file, e.g. with zero counts of
+ # things.
+ if fup.offset != len(fup.buffer):
+ raise ExtraneousData("extraneous data in %s; is it really a Linden .anim file?" %
+ filename)
# various validity checks could be added - see LLKeyframeMotion::deserialize()
def unpack(self,fup):
@@ -333,27 +404,57 @@ class Anim(object):
else:
raise BadFormat("Bad combination of version, sub_version: %d %d" % (self.version, self.sub_version))
+ # Also consult BVH conversion code for stricter checks
+
+ # C++ deserialize() checks self.base_priority against
+ # LLJoint::ADDITIVE_PRIORITY and LLJoint::USE_MOTION_PRIORITY,
+ # possibly sets self.max_priority
+ # checks self.duration against MAX_ANIM_DURATION !!
+ # checks self.emote_name != str(self.ID)
+ # checks self.hand_pose against LLHandMotion::NUM_HAND_POSES !!
+ # checks 0 < num_joints <= LL_CHARACTER_MAX_JOINTS (no need --
+ # validate names)
+ # checks each joint_name neither "mScreen" nor "mRoot" ("attempted to
+ # animate special joint") !!
+ # checks each joint_name can be found in mCharacter
+ # checks each joint_priority >= LLJoint::USE_MOTION_PRIORITY
+ # tracks max observed joint_priority, excluding USE_MOTION_PRIORITY
+ # checks each 0 <= RotKey.time <= self.duration !!
+ # checks each RotKey.rotation.isFinite() !!
+ # checks each PosKey.position.isFinite() !!
+ # checks 0 <= num_constraints <= MAX_CONSTRAINTS !!
+ # checks each Constraint.chain_length <= num_joints
+ # checks each Constraint.constraint_type < NUM_CONSTRAINT_TYPES !!
+ # checks each Constraint.source_offset.isFinite() !!
+ # checks each Constraint.target_offset.isFinite() !!
+ # checks each Constraint.target_dir.isFinite() !!
+ # from https://bitbucket.org/lindenlab/viewer-release/src/827a910542a9af0a39b0ca03663c02e5c83869ea/indra/llcharacter/llkeyframemotion.cpp?at=default&fileviewer=file-view-default#llkeyframemotion.cpp-1812 :
+ # find joint to which each Constraint's collision volume is attached;
+ # for each link in Constraint.chain_length, walk to joint's parent,
+ # find that parent in list of joints, set its index in index list
+
self.emote_name = fup.unpack_string()
- (self.loop_in_point, self.loop_out_point, self.loop, self.ease_in_duration, self.ease_out_duration, self.hand_pose, self.num_joints) = fup.unpack("@ffiffII")
+ (self.loop_in_point, self.loop_out_point, self.loop,
+ self.ease_in_duration, self.ease_out_duration, self.hand_pose, num_joints) = \
+ fup.unpack("@ffiffII")
- self.joints = []
- for j in xrange(0,self.num_joints):
- joint_info = JointInfo()
- joint_info.unpack(self, fup)
- self.joints.append(joint_info)
- print "unpacked joint",joint_info.joint_name
- self.constraints = Constraints()
- self.constraints.unpack(self, fup)
- self.data = fup.data
+ self.joints = [JointInfo.unpack(self.duration, fup)
+ for j in xrange(num_joints)]
+ if self.verbose:
+ for joint_info in self.joints:
+ print "unpacked joint",joint_info.joint_name
+ self.constraints = Constraints.unpack(self.duration, fup)
+ self.buffer = fup.buffer
def pack(self, fp):
fp.pack("@HHhf", self.version, self.sub_version, self.base_priority, self.duration)
fp.pack_string(self.emote_name, 0)
- fp.pack("@ffiffII", self.loop_in_point, self.loop_out_point, self.loop, self.ease_in_duration, self.ease_out_duration, self.hand_pose, self.num_joints)
+ fp.pack("@ffiffII", self.loop_in_point, self.loop_out_point, self.loop,
+ self.ease_in_duration, self.ease_out_duration, self.hand_pose, len(self.joints))
for j in self.joints:
- j.pack(anim, fp)
- self.constraints.pack(anim, fp)
+ j.pack(fp)
+ self.constraints.pack(fp)
def dump(self, filename="-"):
if filename=="-":
@@ -370,7 +471,7 @@ class Anim(object):
print >>f, "ease_in_duration: ", self.ease_in_duration
print >>f, "ease_out_duration: ", self.ease_out_duration
print >>f, "hand_pose", self.hand_pose
- print >>f, "num_joints", self.num_joints
+ print >>f, "num_joints", len(self.joints)
for j in self.joints:
j.dump(f)
self.constraints.dump(f)
@@ -382,10 +483,9 @@ class Anim(object):
def write_src_data(self, filename):
print "write file",filename
- f = open(filename,"wb")
- f.write(self.data)
- f.close()
-
+ with open(filename,"wb") as f:
+ f.write(self.buffer)
+
def find_joint(self, name):
joints = [j for j in self.joints if j.joint_name == name]
if joints:
@@ -395,91 +495,71 @@ class Anim(object):
def add_joint(self, name, priority):
if not self.find_joint(name):
- j = JointInfo()
- j.joint_name = name
- j.joint_priority = priority
- j.rotation_curve = RotationCurve()
- j.position_curve = PositionCurve()
- self.joints.append(j)
- self.num_joints = len(self.joints)
+ self.joints.append(JointInfo(name, priority))
def delete_joint(self, name):
j = self.find_joint(name)
if j:
- if args.verbose:
+ if self.verbose:
print "removing joint", name
- anim.joints.remove(j)
- anim.num_joints = len(self.joints)
+ self.joints.remove(j)
else:
- if args.verbose:
+ if self.verbose:
print "joint not found to remove", name
def summary(self):
nj = len(self.joints)
nz = len([j for j in self.joints if j.joint_priority > 0])
- nstatic = len([j for j in self.joints if j.rotation_curve.is_static() and j.position_curve.is_static()])
+ nstatic = len([j for j in self.joints
+ if j.rotation_curve.is_static()
+ and j.position_curve.is_static()])
print "summary: %d joints, non-zero priority %d, static %d" % (nj, nz, nstatic)
def add_pos(self, joint_names, positions):
js = [joint for joint in self.joints if joint.joint_name in joint_names]
for j in js:
- if args.verbose:
+ if self.verbose:
print "adding positions",j.joint_name,positions
j.joint_priority = 4
- j.position_curve.num_pos_keys = len(positions)
- j.position_curve.keys = []
- for i,pos in enumerate(positions):
- key = PosKey()
- key.time = self.duration * i / (len(positions) - 1)
- key.time_short = F32_to_U16(key.time, 0.0, self.duration)
- key.position = pos
- j.position_curve.keys.append(key)
+ j.position_curve.keys = [PosKey(self.duration * i / (len(positions) - 1),
+ self.duration,
+ pos)
+ for i,pos in enumerate(positions)]
def add_rot(self, joint_names, rotations):
js = [joint for joint in self.joints if joint.joint_name in joint_names]
for j in js:
print "adding rotations",j.joint_name
j.joint_priority = 4
- j.rotation_curve.num_rot_keys = len(rotations)
- j.rotation_curve.keys = []
- for i,pos in enumerate(rotations):
- key = RotKey()
- key.time = self.duration * i / (len(rotations) - 1)
- key.time_short = F32_to_U16(key.time, 0.0, self.duration)
- key.rotation = pos
- j.rotation_curve.keys.append(key)
+ j.rotation_curve.keys = [RotKey(self.duration * i / (len(rotations) - 1),
+ self.duration,
+ rot)
+ for i,rot in enumerate(rotations)]
def twistify(anim, joint_names, rot1, rot2):
js = [joint for joint in anim.joints if joint.joint_name in joint_names]
for j in js:
print "twisting",j.joint_name
- print j.rotation_curve.num_rot_keys
+ print len(j.rotation_curve.keys)
j.joint_priority = 4
- j.rotation_curve.num_rot_keys = 2
- j.rotation_curve.keys = []
- key1 = RotKey()
- key1.time_short = 0
- key1.time = U16_to_F32(key1.time_short, 0.0, anim.duration)
- key1.rotation = rot1
- key2 = RotKey()
- key2.time_short = U16MAX
- key2.time = U16_to_F32(key2.time_short, 0.0, anim.duration)
- key2.rotation = rot2
- j.rotation_curve.keys.append(key1)
- j.rotation_curve.keys.append(key2)
+ # Set the joint(s) to rot1 at time 0, rot2 at the full duration.
+ j.rotation_curve.keys = [
+ RotKey(0.0, anim.duration, rot1),
+ RotKey(anim.duration, anim.duration, rot2)]
def float_triple(arg):
vals = arg.split()
if len(vals)==3:
return [float(x) for x in vals]
else:
- raise Exception("arg %s does not resolve to a float triple" % arg)
+ raise ValueError("arg %s does not resolve to a float triple" % arg)
def get_joint_by_name(tree,name):
if tree is None:
return None
- matches = [elt for elt in tree.getroot().iter() if \
- elt.get("name")==name and elt.tag in ["bone", "collision_volume", "attachment_point"]]
+ matches = [elt for elt in tree.getroot().iter()
+ if elt.get("name")==name
+ and elt.tag in ["bone", "collision_volume", "attachment_point"]]
if len(matches)==1:
return matches[0]
elif len(matches)>1:
@@ -496,121 +576,135 @@ def get_elt_pos(elt):
else:
return (0.0, 0.0, 0.0)
-def resolve_joints(names, skel_tree, lad_tree):
- print "resolve joints, no_hud is",args.no_hud
+def resolve_joints(names, skel_tree, lad_tree, no_hud=False):
+ print "resolve joints, no_hud is",no_hud
if skel_tree and lad_tree:
all_elts = [elt for elt in skel_tree.getroot().iter()]
all_elts.extend([elt for elt in lad_tree.getroot().iter()])
- matches = []
+ matches = set()
for elt in all_elts:
if elt.get("name") is None:
continue
#print elt.get("name"),"hud",elt.get("hud")
- if args.no_hud and elt.get("hud"):
+ if no_hud and elt.get("hud"):
#print "skipping hud joint", elt.get("name")
continue
if elt.get("name") in names or elt.tag in names:
- matches.append(elt.get("name"))
- return list(set(matches))
+ matches.add(elt.get("name"))
+ return list(matches)
else:
return names
-if __name__ == "__main__":
+def main(*argv):
+ import argparse
# default search location for config files is defined relative to
# the script location; assuming they live in the same viewer repo
+ # Use sys.argv[0] because (a) this script lives where it lives regardless
+ # of what our caller passes and (b) we don't expect our caller to pass the
+ # script name anyway.
pathname = os.path.dirname(sys.argv[0])
- path_to_skel = os.path.join(os.path.abspath(pathname),"..","..","indra","newview","character")
+ # we're in scripts/content_tools; hop back to base of repository clone
+ path_to_skel = os.path.join(os.path.abspath(pathname),os.pardir,os.pardir,
+ "indra","newview","character")
parser = argparse.ArgumentParser(description="process SL animations")
parser.add_argument("--verbose", help="verbose flag", action="store_true")
- parser.add_argument("--dump", help="dump to specified file")
+ parser.add_argument("--dump", metavar="FILEPATH", help="dump to specified file")
parser.add_argument("--rot", help="specify sequence of rotations", type=float_triple, nargs="+")
- parser.add_argument("--rand_pos", help="request random positions", action="store_true")
+ parser.add_argument("--rand_pos", help="request NUM random positions (default %(default)s)",
+ metavar="NUM", type=int, default=2)
parser.add_argument("--reset_pos", help="request original positions", action="store_true")
parser.add_argument("--pos", help="specify sequence of positions", type=float_triple, nargs="+")
- parser.add_argument("--num_pos", help="number of positions to create", type=int, default=2)
- parser.add_argument("--delete_joints", help="specify joints to be deleted", nargs="+")
- parser.add_argument("--joints", help="specify joints to be added or modified", nargs="+")
+ parser.add_argument("--delete_joints", help="specify joints to be deleted", nargs="+",
+ metavar="JOINT")
+ parser.add_argument("--joints", help="specify joints to be added or modified", nargs="+",
+ metavar="JOINT")
parser.add_argument("--summary", help="print summary of the output animation", action="store_true")
- parser.add_argument("--skel", help="name of the avatar_skeleton file", default= os.path.join(path_to_skel,"avatar_skeleton.xml"))
- parser.add_argument("--lad", help="name of the avatar_lad file", default= os.path.join(path_to_skel,"avatar_lad.xml"))
- parser.add_argument("--set_version", nargs=2, type=int, help="set version and sub-version to specified values")
+ parser.add_argument("--skel", help="name of the avatar_skeleton file (default %(default)s)",
+ default=os.path.join(path_to_skel,"avatar_skeleton.xml"),
+ metavar="FILEPATH")
+ parser.add_argument("--lad", help="name of the avatar_lad file (default %(default)s)",
+ default=os.path.join(path_to_skel,"avatar_lad.xml"),
+ metavar="FILEPATH")
+ parser.add_argument("--set_version", nargs=2, type=int,
+ help="set version and sub-version to specified values",
+ metavar=("VERSION", "SUB-VERSION"))
parser.add_argument("--no_hud", help="omit hud joints from list of attachments", action="store_true")
parser.add_argument("--base_priority", help="set base priority", type=int)
parser.add_argument("--joint_priority", help="set joint priority for all joints", type=int)
parser.add_argument("infilename", help="name of a .anim file to input")
parser.add_argument("outfilename", nargs="?", help="name of a .anim file to output")
- args = parser.parse_args()
+ args = parser.parse_args(argv)
- print "anim_tool.py: " + " ".join(sys.argv)
+ print "anim_tool.py: " + " ".join(argv)
print "dump is", args.dump
print "infilename",args.infilename,"outfilename",args.outfilename
print "rot",args.rot
print "pos",args.pos
print "joints",args.joints
- try:
- anim = Anim(args.infilename)
- skel_tree = None
- lad_tree = None
- joints = []
- if args.skel:
- skel_tree = etree.parse(args.skel)
- if skel_tree is None:
- print "failed to parse",args.skel
- exit(1)
- if args.lad:
- lad_tree = etree.parse(args.lad)
- if lad_tree is None:
- print "failed to parse",args.lad
- exit(1)
- if args.joints:
- joints = resolve_joints(args.joints, skel_tree, lad_tree)
- if args.verbose:
- print "joints resolved to",joints
- for name in joints:
- anim.add_joint(name,0)
- if args.delete_joints:
- for name in args.delete_joints:
- anim.delete_joint(name)
- if joints and args.rot:
- anim.add_rot(joints, args.rot)
- if joints and args.pos:
- anim.add_pos(joints, args.pos)
- if joints and args.rand_pos:
- for joint in joints:
- pos_array = list(tuple(random.uniform(-1,1) for i in xrange(3)) for j in xrange(args.num_pos))
- pos_array.append(pos_array[0])
- anim.add_pos([joint], pos_array)
- if joints and args.reset_pos:
- for joint in joints:
- elt = get_joint_by_name(skel_tree,joint)
- if elt is None:
- elt = get_joint_by_name(lad_tree,joint)
- if elt is not None:
- pos_array = []
- pos_array.append(get_elt_pos(elt))
- pos_array.append(pos_array[0])
- anim.add_pos([joint], pos_array)
- else:
- print "no elt or no pos data for",joint
- if args.set_version:
- anim.version = args.set_version[0]
- anim.sub_version = args.set_version[1]
- if args.base_priority is not None:
- print "set base priority",args.base_priority
- anim.base_priority = args.base_priority
- if args.joint_priority is not None:
- print "set joint priority",args.joint_priority
- for joint in anim.joints:
- joint.joint_priority = args.joint_priority
- if args.dump:
- anim.dump(args.dump)
- if args.summary:
- anim.summary()
- if args.outfilename:
- anim.write(args.outfilename)
- except:
- raise
+ anim = Anim(args.infilename, args.verbose)
+ skel_tree = None
+ lad_tree = None
+ joints = []
+ if args.skel:
+ skel_tree = ElementTree.parse(args.skel)
+ if skel_tree is None:
+ raise Error("failed to parse " + args.skel)
+ if args.lad:
+ lad_tree = ElementTree.parse(args.lad)
+ if lad_tree is None:
+ raise Error("failed to parse " + args.lad)
+ if args.joints:
+ joints = resolve_joints(args.joints, skel_tree, lad_tree, args.no_hud)
+ if args.verbose:
+ print "joints resolved to",joints
+ for name in joints:
+ anim.add_joint(name,0)
+ if args.delete_joints:
+ for name in args.delete_joints:
+ anim.delete_joint(name)
+ if joints and args.rot:
+ anim.add_rot(joints, args.rot)
+ if joints and args.pos:
+ anim.add_pos(joints, args.pos)
+ if joints and args.rand_pos:
+ # pick a random sequence of positions for each joint specified
+ for joint in joints:
+ # generate a list of rand_pos triples
+ pos_array = [tuple(random.uniform(-1,1) for i in xrange(3))
+ for j in xrange(args.rand_pos)]
+ # close the loop by cycling back to the first entry
+ pos_array.append(pos_array[0])
+ anim.add_pos([joint], pos_array)
+ if joints and args.reset_pos:
+ for joint in joints:
+ elt = get_joint_by_name(skel_tree,joint) or get_joint_by_name(lad_tree,joint)
+ if elt is not None:
+ anim.add_pos([joint], 2*[get_elt_pos(elt)])
+ else:
+ print "no elt or no pos data for",joint
+ if args.set_version:
+ anim.version, anim.sub_version = args.set_version
+ if args.base_priority is not None:
+ print "set base priority",args.base_priority
+ anim.base_priority = args.base_priority
+ # --joint_priority sets priority for ALL joints, not just the explicitly-
+ # specified ones
+ if args.joint_priority is not None:
+ print "set joint priority",args.joint_priority
+ for joint in anim.joints:
+ joint.joint_priority = args.joint_priority
+ if args.dump:
+ anim.dump(args.dump)
+ if args.summary:
+ anim.summary()
+ if args.outfilename:
+ anim.write(args.outfilename)
+if __name__ == "__main__":
+ try:
+ sys.exit(main(*sys.argv[1:]))
+ except Error as err:
+ sys.exit("%s: %s" % (err.__class__.__name__, err))