diff --git a/autobuild.xml b/autobuild.xml
index bb13eb40bd..2eee366cf7 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -540,9 +540,9 @@
archive
name
darwin64
@@ -564,9 +564,9 @@
archive
name
windows
@@ -576,16 +576,16 @@
archive
name
windows64
version
- 1.4.5.558565
+ 1.4.5.576669
boost
version
- 1.6.8.563850
+ 1.6.38.576621
libuuid
@@ -2728,9 +2728,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 53966a7ba6342395acb7ce15bc3fbe0a
+ 8114c6a7e499ea20d325db0de08ce30a
url
- http://3p.firestormviewer.org/openjpeg-2.3.1.203000304-darwin-203000304.tar.bz2
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105469/923024/openjpeg-2.5.0.575496-darwin64-575496.tar.bz2
name
darwin64
@@ -2752,9 +2752,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- ba2034b4a372fd46c3e09f56bede38a7
+ edc9388870d951632a6d595792293e05
url
- http://3p.firestormviewer.org/openjpeg-2.4.0.211361403-windows-211361403.tar.bz2
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105472/923036/openjpeg-2.5.0.575496-windows-575496.tar.bz2
name
windows
@@ -2764,16 +2764,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- d7ac606703a9330a2d8a3f7276cb6894
+ b95f0732f2388ebb0ddf33d4a30e0ff1
url
- http://3p.firestormviewer.org/openjpeg-2.4.0.211361407-windows64-211361407.tar.bz2
+ https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105471/923037/openjpeg-2.5.0.575496-windows64-575496.tar.bz2
name
windows64
version
- 2.4.0
+ 2.5.0.575496
openssl
diff --git a/doc/contributions.txt b/doc/contributions.txt
index f1eb342f43..872f7e2abb 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -285,6 +285,7 @@ Beq Janus
SL-15709
SL-16021
SL-16027
+ SL-18592
SL-18637
Beth Walcher
Bezilon Kasei
@@ -376,6 +377,7 @@ Charlie Sazaland
Chaser Zaks
BUG-225599
BUG-227485
+ SL-16874
Cherry Cheevers
ChickyBabes Zuzu
Chorazin Allen
@@ -1390,6 +1392,7 @@ Sovereign Engineer
OPEN-343
SL-11625
BUG-229030
+ SL-14696
SL-14705
SL-14706
SL-14707
@@ -1397,6 +1400,12 @@ Sovereign Engineer
SL-14732
SL-15096
SL-16127
+ SL-18249
+ SL-18394
+ SL-18412
+ SL-18497
+ SL-18525
+ SL-18534
SpacedOut Frye
VWR-34
VWR-45
@@ -1659,6 +1668,8 @@ Zi Ree
VWR-25588
STORM-1790
STORM-1842
+ SL-18348
+ SL-18593
Zipherius Turas
VWR-76
VWR-77
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index d0c32504a2..701566b71c 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -253,7 +253,7 @@ elseif(LINUX)
${EXPAT_COPY}
libhunspell-1.3.so.0.0.0
libopenal.so
- #libopenjpeg.so
+ libopenjp2.so
libuuid.so.16
libuuid.so.16.0.22
#libfontconfig.so.1.10.1 # fontconfig and freetype should be taken from the
diff --git a/indra/cmake/FindOpenJPEG.cmake b/indra/cmake/FindOpenJPEG.cmake
index cdbc6c5841..d77e17764d 100644
--- a/indra/cmake/FindOpenJPEG.cmake
+++ b/indra/cmake/FindOpenJPEG.cmake
@@ -16,9 +16,10 @@ FIND_PATH(OPENJPEG_INCLUDE_DIR openjpeg.h
/usr/include/openjpeg-2.1
/usr/include/openjpeg
/usr/include
+include/openjpeg
)
-SET(OPENJPEG_NAMES ${OPENJPEG_NAMES} openjpeg openjp2)
+SET(OPENJPEG_NAMES ${OPENJPEG_NAMES} openjp2)
FIND_LIBRARY(OPENJPEG_LIBRARY
NAMES ${OPENJPEG_NAMES}
PATHS /usr/lib /usr/local/lib
diff --git a/indra/cmake/OpenJPEG.cmake b/indra/cmake/OpenJPEG.cmake
index f254094df6..a078c97cb8 100644
--- a/indra/cmake/OpenJPEG.cmake
+++ b/indra/cmake/OpenJPEG.cmake
@@ -8,8 +8,7 @@ if (USESYSTEMLIBS)
include(FindOpenJPEG)
else (USESYSTEMLIBS)
use_prebuilt_binary(openjpeg)
-
- set(OPENJPEG_LIBRARIES openjp2)
+ set(OPENJPEG_LIBRARIES openjp2)
set(OPENJPEG_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/openjpeg)
endif (USESYSTEMLIBS)
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 44760810dc..7d0c54529b 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -313,7 +313,12 @@ LLAvatarAppearance::~LLAvatarAppearance()
}
}
- if (mRoot) mRoot->removeAllChildren();
+ if (mRoot)
+ {
+ mRoot->removeAllChildren();
+ delete mRoot;
+ mRoot = nullptr;
+ }
mJointMap.clear();
clearSkeleton();
diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp
index 3fc406d51d..0481326e9e 100644
--- a/indra/llappearance/lllocaltextureobject.cpp
+++ b/indra/llappearance/lllocaltextureobject.cpp
@@ -76,7 +76,7 @@ LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject& lto) :
LLLocalTextureObject::~LLLocalTextureObject()
{
- delete_and_clear(mTexLayers); // Mem-leak fix by Drake Arconis
+ delete_and_clear(mTexLayers);
}
LLGLTexture* LLLocalTextureObject::getImage() const
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index cc6e37ebe6..79127d8408 100644
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -1232,7 +1232,7 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, bool allow_invalid_joints)
{
BOOL old_version = FALSE;
- mJointMotionList = new LLKeyframeMotion::JointMotionList;
+ std::unique_ptr joint_motion_list(new LLKeyframeMotion::JointMotionList);
//-------------------------------------------------------------------------
// get base priority
@@ -1244,14 +1244,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
if (!dp.unpackU16(version, "version"))
{
LL_WARNS() << "can't read version number for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
if (!dp.unpackU16(sub_version, "sub_version"))
{
LL_WARNS() << "can't read sub version number for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1264,7 +1262,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
#if LL_RELEASE
LL_WARNS() << "Bad animation version " << version << "." << sub_version
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
#else
LL_ERRS() << "Bad animation version " << version << "." << sub_version
@@ -1276,89 +1273,80 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read animation base_priority"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
- mJointMotionList->mBasePriority = (LLJoint::JointPriority) temp_priority;
+ joint_motion_list->mBasePriority = (LLJoint::JointPriority) temp_priority;
- if (mJointMotionList->mBasePriority >= LLJoint::ADDITIVE_PRIORITY)
+ if (joint_motion_list->mBasePriority >= LLJoint::ADDITIVE_PRIORITY)
{
- mJointMotionList->mBasePriority = (LLJoint::JointPriority)((S32)LLJoint::ADDITIVE_PRIORITY-1);
- mJointMotionList->mMaxPriority = mJointMotionList->mBasePriority;
+ joint_motion_list->mBasePriority = (LLJoint::JointPriority)((S32)LLJoint::ADDITIVE_PRIORITY-1);
+ joint_motion_list->mMaxPriority = joint_motion_list->mBasePriority;
}
- else if (mJointMotionList->mBasePriority < LLJoint::USE_MOTION_PRIORITY)
+ else if (joint_motion_list->mBasePriority < LLJoint::USE_MOTION_PRIORITY)
{
- LL_WARNS() << "bad animation base_priority " << mJointMotionList->mBasePriority
+ LL_WARNS() << "bad animation base_priority " << joint_motion_list->mBasePriority
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
//-------------------------------------------------------------------------
// get duration
//-------------------------------------------------------------------------
- if (!dp.unpackF32(mJointMotionList->mDuration, "duration"))
+ if (!dp.unpackF32(joint_motion_list->mDuration, "duration"))
{
LL_WARNS() << "can't read duration"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
- if (mJointMotionList->mDuration > MAX_ANIM_DURATION ||
- !llfinite(mJointMotionList->mDuration))
+ if (joint_motion_list->mDuration > MAX_ANIM_DURATION ||
+ !llfinite(joint_motion_list->mDuration))
{
LL_WARNS() << "invalid animation duration"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
//-------------------------------------------------------------------------
// get emote (optional)
//-------------------------------------------------------------------------
- if (!dp.unpackString(mJointMotionList->mEmoteName, "emote_name"))
+ if (!dp.unpackString(joint_motion_list->mEmoteName, "emote_name"))
{
LL_WARNS() << "can't read optional_emote_animation"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
- if(mJointMotionList->mEmoteName==mID.asString())
+ if(joint_motion_list->mEmoteName==mID.asString())
{
LL_WARNS() << "Malformed animation mEmoteName==mID"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
//-------------------------------------------------------------------------
// get loop
//-------------------------------------------------------------------------
- if (!dp.unpackF32(mJointMotionList->mLoopInPoint, "loop_in_point") ||
- !llfinite(mJointMotionList->mLoopInPoint))
+ if (!dp.unpackF32(joint_motion_list->mLoopInPoint, "loop_in_point") ||
+ !llfinite(joint_motion_list->mLoopInPoint))
{
LL_WARNS() << "can't read loop point"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
- if (!dp.unpackF32(mJointMotionList->mLoopOutPoint, "loop_out_point") ||
- !llfinite(mJointMotionList->mLoopOutPoint))
+ if (!dp.unpackF32(joint_motion_list->mLoopOutPoint, "loop_out_point") ||
+ !llfinite(joint_motion_list->mLoopOutPoint))
{
LL_WARNS() << "can't read loop point"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
- if (!dp.unpackS32(mJointMotionList->mLoop, "loop"))
+ if (!dp.unpackS32(joint_motion_list->mLoop, "loop"))
{
LL_WARNS() << "can't read loop"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1368,27 +1356,25 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
if (female_land_anim == asset_id || formal_female_land_anim == asset_id)
{
LL_WARNS() << "Animation(" << asset_id << ") won't be looped." << LL_ENDL;
- mJointMotionList->mLoop = FALSE;
+ joint_motion_list->mLoop = FALSE;
}
//-------------------------------------------------------------------------
// get easeIn and easeOut
//-------------------------------------------------------------------------
- if (!dp.unpackF32(mJointMotionList->mEaseInDuration, "ease_in_duration") ||
- !llfinite(mJointMotionList->mEaseInDuration))
+ if (!dp.unpackF32(joint_motion_list->mEaseInDuration, "ease_in_duration") ||
+ !llfinite(joint_motion_list->mEaseInDuration))
{
LL_WARNS() << "can't read easeIn"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
- if (!dp.unpackF32(mJointMotionList->mEaseOutDuration, "ease_out_duration") ||
- !llfinite(mJointMotionList->mEaseOutDuration))
+ if (!dp.unpackF32(joint_motion_list->mEaseOutDuration, "ease_out_duration") ||
+ !llfinite(joint_motion_list->mEaseOutDuration))
{
LL_WARNS() << "can't read easeOut"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1400,7 +1386,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read hand pose"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1408,11 +1393,10 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "invalid LLHandMotion::eHandPose index: " << word
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
- mJointMotionList->mHandPose = (LLHandMotion::eHandPose)word;
+ joint_motion_list->mHandPose = (LLHandMotion::eHandPose)word;
//-------------------------------------------------------------------------
// get number of joint motions
@@ -1422,7 +1406,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read number of joints"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1430,19 +1413,17 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "no joints"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
else if (num_motions > LL_CHARACTER_MAX_ANIMATED_JOINTS)
{
LL_WARNS() << "too many joints"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
- mJointMotionList->mJointMotionArray.clear();
- mJointMotionList->mJointMotionArray.reserve(num_motions);
+ joint_motion_list->mJointMotionArray.clear();
+ joint_motion_list->mJointMotionArray.reserve(num_motions);
mJointStates.clear();
mJointStates.reserve(num_motions);
@@ -1453,14 +1434,13 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
for(U32 i=0; imJointMotionArray.push_back(joint_motion);
+ joint_motion_list->mJointMotionArray.push_back(joint_motion);
std::string joint_name;
if (!dp.unpackString(joint_name, "joint_name"))
{
LL_WARNS() << "can't read joint name"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1468,7 +1448,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "attempted to animate special " << joint_name << " joint"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1515,7 +1494,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read joint priority."
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1523,15 +1501,14 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "joint priority unknown - too low."
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
joint_motion->mPriority = (LLJoint::JointPriority)joint_priority;
if (joint_priority != LLJoint::USE_MOTION_PRIORITY &&
- joint_priority > mJointMotionList->mMaxPriority)
+ joint_priority > joint_motion_list->mMaxPriority)
{
- mJointMotionList->mMaxPriority = (LLJoint::JointPriority)joint_priority;
+ joint_motion_list->mMaxPriority = (LLJoint::JointPriority)joint_priority;
}
joint_state->setPriority((LLJoint::JointPriority)joint_priority);
@@ -1543,7 +1520,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read number of rotation keys"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1570,7 +1546,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read rotation key (" << k << ")"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1581,17 +1556,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read rotation key (" << k << ")"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
- time = U16_to_F32(time_short, 0.f, mJointMotionList->mDuration);
+ time = U16_to_F32(time_short, 0.f, joint_motion_list->mDuration);
- if (time < 0 || time > mJointMotionList->mDuration)
+ if (time < 0 || time > joint_motion_list->mDuration)
{
LL_WARNS() << "invalid frame time"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
}
@@ -1601,40 +1574,58 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
LLVector3 rot_angles;
U16 x, y, z;
- BOOL success = TRUE;
-
if (old_version)
{
- success = dp.unpackVector3(rot_angles, "rot_angles") && rot_angles.isFinite();
+ if (!dp.unpackVector3(rot_angles, "rot_angles"))
+ {
+ LL_WARNS() << "can't read rot_angles in rotation key (" << k << ")" << LL_ENDL;
+ return FALSE;
+ }
+ if (!rot_angles.isFinite())
+ {
+ LL_WARNS() << "non-finite angle in rotation key (" << k << ")" << LL_ENDL;
+ return FALSE;
+ }
LLQuaternion::Order ro = StringToOrder("ZYX");
rot_key.mRotation = mayaQ(rot_angles.mV[VX], rot_angles.mV[VY], rot_angles.mV[VZ], ro);
}
else
{
- success &= dp.unpackU16(x, "rot_angle_x");
- success &= dp.unpackU16(y, "rot_angle_y");
- success &= dp.unpackU16(z, "rot_angle_z");
+ if (!dp.unpackU16(x, "rot_angle_x"))
+ {
+ LL_WARNS() << "can't read rot_angle_x in rotation key (" << k << ")" << LL_ENDL;
+ return FALSE;
+ }
+ if (!dp.unpackU16(y, "rot_angle_y"))
+ {
+ LL_WARNS() << "can't read rot_angle_y in rotation key (" << k << ")" << LL_ENDL;
+ return FALSE;
+ }
+ if (!dp.unpackU16(z, "rot_angle_z"))
+ {
+ LL_WARNS() << "can't read rot_angle_z in rotation key (" << k << ")" << LL_ENDL;
+ return FALSE;
+ }
LLVector3 rot_vec;
rot_vec.mV[VX] = U16_to_F32(x, -1.f, 1.f);
rot_vec.mV[VY] = U16_to_F32(y, -1.f, 1.f);
rot_vec.mV[VZ] = U16_to_F32(z, -1.f, 1.f);
+
+ if(!rot_vec.isFinite())
+ {
+ LL_WARNS() << "non-finite angle in rotation key (" << k << ")"
+ << " for animation " << asset_id << LL_ENDL;
+ return FALSE;
+ }
rot_key.mRotation.unpackFromVector3(rot_vec);
}
- if( !(rot_key.mRotation.isFinite()) )
+ if(!rot_key.mRotation.isFinite())
{
- LL_WARNS() << "non-finite angle in rotation key"
+ LL_WARNS() << "non-finite angle in rotation key (" << k << ")"
<< " for animation " << asset_id << LL_ENDL;
- success = FALSE;
- }
-
- if (!success)
- {
- LL_WARNS() << "can't read rotation key (" << k << ")"
- << " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1648,7 +1639,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read number of position keys"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1675,7 +1665,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read position key (" << k << ")"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
}
@@ -1685,18 +1674,19 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read position key (" << k << ")"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
- pos_key.mTime = U16_to_F32(time_short, 0.f, mJointMotionList->mDuration);
+ pos_key.mTime = U16_to_F32(time_short, 0.f, joint_motion_list->mDuration);
}
- BOOL success = TRUE;
-
if (old_version)
{
- success = dp.unpackVector3(pos_key.mPosition, "pos");
+ if (!dp.unpackVector3(pos_key.mPosition, "pos"))
+ {
+ LL_WARNS() << "can't read pos in position key (" << k << ")" << LL_ENDL;
+ return FALSE;
+ }
//MAINT-6162
pos_key.mPosition.mV[VX] = llclamp( pos_key.mPosition.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
@@ -1708,27 +1698,31 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
U16 x, y, z;
- success &= dp.unpackU16(x, "pos_x");
- success &= dp.unpackU16(y, "pos_y");
- success &= dp.unpackU16(z, "pos_z");
+ if (!dp.unpackU16(x, "pos_x"))
+ {
+ LL_WARNS() << "can't read pos_x in position key (" << k << ")" << LL_ENDL;
+ return FALSE;
+ }
+ if (!dp.unpackU16(y, "pos_y"))
+ {
+ LL_WARNS() << "can't read pos_y in position key (" << k << ")" << LL_ENDL;
+ return FALSE;
+ }
+ if (!dp.unpackU16(z, "pos_z"))
+ {
+ LL_WARNS() << "can't read pos_z in position key (" << k << ")" << LL_ENDL;
+ return FALSE;
+ }
pos_key.mPosition.mV[VX] = U16_to_F32(x, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
pos_key.mPosition.mV[VY] = U16_to_F32(y, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
pos_key.mPosition.mV[VZ] = U16_to_F32(z, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
}
- if( !(pos_key.mPosition.isFinite()) )
+ if(!pos_key.mPosition.isFinite())
{
LL_WARNS() << "non-finite position in key"
<< " for animation " << asset_id << LL_ENDL;
- success = FALSE;
- }
-
- if (!success)
- {
- LL_WARNS() << "can't read position key (" << k << ")"
- << " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1736,7 +1730,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
if (is_pelvis)
{
- mJointMotionList->mPelvisBBox.addPoint(pos_key.mPosition);
+ joint_motion_list->mPelvisBBox.addPoint(pos_key.mPosition);
}
}
@@ -1751,7 +1745,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read number of constraints"
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1769,25 +1762,21 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
for(S32 i = 0; i < num_constraints; ++i)
{
// read in constraint data
- JointConstraintSharedData* constraintp = new JointConstraintSharedData;
+ std::unique_ptr constraintp(new JointConstraintSharedData);
U8 byte = 0;
if (!dp.unpackU8(byte, "chain_length"))
{
LL_WARNS() << "can't read constraint chain length"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
constraintp->mChainLength = (S32) byte;
- if((U32)constraintp->mChainLength > mJointMotionList->getNumJointMotions())
+ if((U32)constraintp->mChainLength > joint_motion_list->getNumJointMotions())
{
LL_WARNS() << "invalid constraint chain length"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1795,8 +1784,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read constraint type"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1804,8 +1791,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "invalid constraint type"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
constraintp->mConstraintType = (EConstraintType)byte;
@@ -1816,8 +1801,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read source volume name"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1828,8 +1811,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "not a valid source constraint volume " << str
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // avoid mem-leak as per others
return FALSE;
}
@@ -1837,8 +1818,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read constraint source offset"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1846,8 +1825,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "non-finite constraint source offset"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1855,8 +1832,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read target volume name"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1875,8 +1850,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "not a valid target constraint volume " << str
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // avoid mem-leak as per others
return FALSE;
}
}
@@ -1885,8 +1858,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read constraint target offset"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1894,8 +1865,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "non-finite constraint target offset"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1903,8 +1872,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read constraint target direction"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1912,8 +1879,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "non-finite constraint target direction"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1927,8 +1892,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read constraint ease in start time"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1936,8 +1899,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read constraint ease in stop time"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1945,8 +1906,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read constraint ease out start time"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -1954,36 +1913,31 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "can't read constraint ease out stop time"
<< " for animation " << asset_id << LL_ENDL;
- delete constraintp;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
- mJointMotionList->mConstraints.push_front(constraintp);
-
- constraintp->mJointStateIndices = new S32[constraintp->mChainLength + 1]; // note: mChainLength is size-limited - comes from a byte
-
LLJoint* joint = mCharacter->findCollisionVolume(constraintp->mSourceConstraintVolume);
// get joint to which this collision volume is attached
if (!joint)
{
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
+
+ constraintp->mJointStateIndices = new S32[constraintp->mChainLength + 1]; // note: mChainLength is size-limited - comes from a byte
+
for (S32 i = 0; i < constraintp->mChainLength + 1; i++)
{
LLJoint* parent = joint->getParent();
if (!parent)
{
LL_WARNS() << "Joint with no parent: " << joint->getName()
- << " Emote: " << mJointMotionList->mEmoteName
+ << " Emote: " << joint_motion_list->mEmoteName
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
joint = parent;
constraintp->mJointStateIndices[i] = -1;
- for (U32 j = 0; j < mJointMotionList->getNumJointMotions(); j++)
+ for (U32 j = 0; j < joint_motion_list->getNumJointMotions(); j++)
{
LLJoint* constraint_joint = getJoint(j);
@@ -1991,7 +1945,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "Invalid joint " << j
<< " for animation " << asset_id << LL_ENDL;
- delete mJointMotionList; // Mem-leak fix by Drake Arconis
return FALSE;
}
@@ -2005,17 +1958,16 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo
{
LL_WARNS() << "No joint index for constraint " << i
<< " for animation " << asset_id << LL_ENDL;
- // Mem-leak fix by Drake Arconis
- //delete constraintp;
- delete mJointMotionList;
- //
return FALSE;
}
}
+
+ joint_motion_list->mConstraints.push_front(constraintp.release());
}
}
// *FIX: support cleanup of old keyframe data
+ mJointMotionList = joint_motion_list.release(); // release from unique_ptr to member;
LLKeyframeDataCache::addKeyframeData(getID(), mJointMotionList);
mAssetStatus = ASSET_LOADED;
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index e313df704e..f91f17c491 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -287,25 +287,15 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl
return name;
}
+namespace
+{
+
#if LL_WINDOWS
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
-U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name)
+U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
{
- // C++ exceptions were logged in toplevelTryWrapper, but not SEH
- // log SEH exceptions here, to make sure it gets into bugsplat's
- // report and because __try won't allow std::string operations
- if (code != STATUS_MSC_EXCEPTION)
- {
- LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL;
- }
- // Handle bugsplat here, since GetExceptionInformation() can only be
- // called from within filter for __except(filter), not from __except's {}
- // Bugsplat should get all exceptions, C++ and SEH
- LLApp::instance()->reportCrashToBugsplat(exception_infop);
-
- // Only convert non C++ exceptions.
if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
@@ -318,28 +308,38 @@ U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop,
}
}
-void LLCoros::sehHandle(const std::string& name, const LLCoros::callable_t& callable)
+void sehandle(const LLCoros::callable_t& callable)
{
__try
{
- LLCoros::toplevelTryWrapper(name, callable);
+ callable();
}
- __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name))
+ __except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
{
- // convert to C++ styled exception for handlers other than bugsplat
+ // convert to C++ styled exception
// Note: it might be better to use _se_set_translator
// if you want exception to inherit full callstack
- //
- // in case of bugsplat this will get to exceptionTerminateHandler and
- // looks like fiber will terminate application after that
char integer_string[512];
- sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode());
+ sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
throw std::exception(integer_string);
}
}
-#endif
-void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable)
+#else // ! LL_WINDOWS
+
+inline void sehandle(const LLCoros::callable_t& callable)
+{
+ callable();
+}
+
+#endif // ! LL_WINDOWS
+
+} // anonymous namespace
+
+// Top-level wrapper around caller's coroutine callable.
+// Normally we like to pass strings and such by const reference -- but in this
+// case, we WANT to copy both the name and the callable to our local stack!
+void LLCoros::toplevel(std::string name, callable_t callable)
{
// keep the CoroData on this top-level function's stack frame
CoroData corodata(name);
@@ -349,12 +349,12 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call
// run the code the caller actually wants in the coroutine
try
{
- callable();
+ sehandle(callable);
}
catch (const Stop& exc)
{
LL_INFOS("LLCoros") << "coroutine " << name << " terminating because "
- << exc.what() << LL_ENDL;
+ << exc.what() << LL_ENDL;
}
catch (const LLContinueError&)
{
@@ -365,36 +365,14 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call
}
catch (...)
{
-#if LL_WINDOWS
- // Any OTHER kind of uncaught exception will cause the viewer to
- // crash, SEH handling should catch it and report to bugsplat.
- LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name));
- // to not modify callstack
- throw;
-#else
// Stash any OTHER kind of uncaught exception in the rethrow() queue
// to be rethrown by the main fiber.
LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine "
<< name << LL_ENDL;
LLCoros::instance().saveException(name, std::current_exception());
-#endif
}
}
-// Top-level wrapper around caller's coroutine callable.
-// Normally we like to pass strings and such by const reference -- but in this
-// case, we WANT to copy both the name and the callable to our local stack!
-void LLCoros::toplevel(std::string name, callable_t callable)
-{
-#if LL_WINDOWS
- // Because SEH can's have unwinding, need to call a wrapper
- // 'try' is inside SEH handling to not catch LLContinue
- sehHandle(name, callable);
-#else
- toplevelTryWrapper(name, callable);
-#endif
-}
-
//static
void LLCoros::checkStop()
{
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index dbff921f16..966ce03296 100644
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -307,11 +307,7 @@ public:
private:
std::string generateDistinctName(const std::string& prefix) const;
- void toplevelTryWrapper(const std::string& name, const callable_t& callable);
-#if LL_WINDOWS
- void sehHandle(const std::string& name, const callable_t& callable); // calls toplevelTryWrapper
-#endif
- void toplevel(std::string name, callable_t callable); // calls sehHandle or toplevelTryWrapper
+ void toplevel(std::string name, callable_t callable);
struct CoroData;
static CoroData& get_CoroData(const std::string& caller);
void saveException(const std::string& name, std::exception_ptr exc);
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 2c03a68245..f2ec442ba9 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -954,7 +954,7 @@ namespace LLError
for (a = sets.beginArray(), end = sets.endArray(); a != end; ++a)
{
const LLSD& entry = *a;
- if (entry.isMap() && !entry.emptyMap())
+ if (entry.isMap() && entry.size() != 0)
{
ELevel level = decodeLevel(entry["level"]);
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 42766396e5..ecd37daa59 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -34,10 +34,9 @@
#include
#include "apr_base64.h"
-// Add non-allocating variants of unzip_llsd
#include
#include
-//
+
#ifdef LL_USESYSTEMLIBS
# include
#else
@@ -2132,8 +2131,8 @@ std::string zip_llsd(LLSD& data)
{ //copy result into output
if (strm.avail_out >= CHUNK)
{
- // free(output);
- if( output )
+ deflateEnd(&strm);
+ if(output)
free(output);
LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
return std::string();
@@ -2157,8 +2156,8 @@ std::string zip_llsd(LLSD& data)
}
else
{
- // free(output);
- if( output )
+ deflateEnd(&strm);
+ if(output)
free(output);
LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
return std::string();
@@ -2170,8 +2169,7 @@ std::string zip_llsd(LLSD& data)
std::string result((char*) output, size);
deflateEnd(&strm);
- // free(output);
- if( output )
+ if(output)
free(output);
return result;
@@ -2182,148 +2180,8 @@ std::string zip_llsd(LLSD& data)
// and deserializes from that copy using LLSDSerialize
LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, S32 size)
{
- // Add non-allocating variants of unzip_llsd
- // U8* result = NULL;
- // U32 cur_size = 0;
- // z_stream strm;
-
- // const U32 CHUNK = 65536;
-
- // U8 *in = new(std::nothrow) U8[size];
- // if (!in)
- // {
- // return ZR_MEM_ERROR;
- // }
- // is.read((char*) in, size);
-
- // U8 out[CHUNK];
-
- // strm.zalloc = Z_NULL;
- // strm.zfree = Z_NULL;
- // strm.opaque = Z_NULL;
- // strm.avail_in = size;
- // strm.next_in = in;
-
- // S32 ret = inflateInit(&strm);
-
- // do
- // {
- // strm.avail_out = CHUNK;
- // strm.next_out = out;
- // ret = inflate(&strm, Z_NO_FLUSH);
- // if (ret == Z_STREAM_ERROR)
- // {
- // LL_DEBUGS() << "Unzip error: Z_STREAM_ERROR" << LL_ENDL; //
- // inflateEnd(&strm);
- // // free(result);
- // if( result )
- // free(result);
- // delete [] in;
- // return ZR_DATA_ERROR;
- // }
-
- // switch (ret)
- // {
- // case Z_NEED_DICT:
- // ret = Z_DATA_ERROR;
- // case Z_DATA_ERROR:
- // case Z_MEM_ERROR:
- // LL_DEBUGS() << "Unzip error: " << ret << LL_ENDL; //
- // inflateEnd(&strm);
- // // free(result);
- // if( result )
- // free(result);
- // delete [] in;
- // return ZR_MEM_ERROR;
- // break;
- // }
-
- // U32 have = CHUNK-strm.avail_out;
-
- // U8* new_result = (U8*)realloc(result, cur_size + have);
- // if (new_result == NULL)
- // {
- // inflateEnd(&strm);
- // if (result)
- // {
- // free(result);
- // }
- // delete[] in;
- // return ZR_MEM_ERROR;
- // }
- // result = new_result;
- // memcpy(result+cur_size, out, have);
- // cur_size += have;
-
- // } while (ret == Z_OK);
-
- // inflateEnd(&strm);
- // delete [] in;
-
- // if (ret != Z_STREAM_END)
- // {
- // LL_DEBUGS() << "Unzip error: !Z_STREAM_END" << LL_ENDL; //
- // // free(result);
- // if( result )
- // free(result);
- // return ZR_DATA_ERROR;
- // }
-
- // //result now points to the decompressed LLSD block
- // {
- // std::istringstream istr;
- // // Since we are using this for meshes, data we are dealing with tend to be large.
- // // So string can potentially fail to allocate, make sure this won't cause problems
- // try
- // {
- // std::string res_str((char*)result, cur_size);
-
- // std::string deprecated_header(" LLSD/Binary ?>");
-
- // if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
- // {
- // res_str = res_str.substr(deprecated_header.size() + 1, cur_size);
- // }
- // cur_size = res_str.size();
-
- // istr.str(res_str);
- // }
- // #ifdef LL_WINDOWS
- // catch (std::length_error)
- // {
- // // free(result);
- // if( result )
- // free(result);
- // return ZR_SIZE_ERROR;
- // }
- // #endif
- // catch (std::bad_alloc&)
- // {
- // // free(result);
- // if( result )
- // free(result);
- // return ZR_MEM_ERROR;
- // }
-
- // if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH))
- // {
- // // free(result);
- // if( result )
- // free(result);
- // return ZR_PARSE_ERROR;
- // }
- // }
-
- // // free(result);
- // if( result )
- // free(result);
- // return ZR_OK;
- std::unique_ptr in;
- try
- {
- in = std::unique_ptr(new U8[size]);
- }
- catch(const std::bad_alloc&)
+ std::unique_ptr in = std::unique_ptr(new(std::nothrow) U8[size]);
+ if (!in)
{
return ZR_MEM_ERROR;
}
@@ -2338,19 +2196,12 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32
U32 cur_size = 0;
z_stream strm;
- constexpr U32 CHUNK = 1024 * 256;
+ constexpr U32 CHUNK = 1024 * 512;
static thread_local std::unique_ptr out;
if (!out)
{
- try
- {
- out = std::unique_ptr(new U8[CHUNK]);
- }
- catch (const std::bad_alloc&)
- {
- return ZR_MEM_ERROR;
- }
+ out = std::unique_ptr(new(std::nothrow) U8[CHUNK]);
}
strm.zalloc = Z_NULL;
@@ -2360,16 +2211,7 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32
strm.next_in = const_cast(in);
S32 ret = inflateInit(&strm);
- switch (ret)
- {
- case Z_STREAM_ERROR:
- return ZR_DATA_ERROR;
- case Z_VERSION_ERROR:
- return ZR_VERSION_ERROR;
- case Z_MEM_ERROR:
- return ZR_MEM_ERROR;
- }
-
+
do
{
strm.avail_out = CHUNK;
@@ -2381,7 +2223,9 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32
case Z_DATA_ERROR:
{
inflateEnd(&strm);
- free(result);
+ // free(result);
+ if( result )
+ free(result);
return ZR_DATA_ERROR;
}
case Z_STREAM_ERROR:
@@ -2395,7 +2239,9 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32
case Z_MEM_ERROR:
{
inflateEnd(&strm);
- free(result);
+ // free(result);
+ if( result )
+ free(result);
return ZR_MEM_ERROR;
}
}
@@ -2422,7 +2268,9 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32
if (ret != Z_STREAM_END)
{
- free(result);
+ // free(result);
+ if( result )
+ free(result);
return ZR_DATA_ERROR;
}
@@ -2434,134 +2282,138 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32
if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH))
{
- free(result);
+ // free(result);
+ if( result )
+ free(result);
return ZR_PARSE_ERROR;
}
}
- free(result);
+ // free(result);
+ if( result )
+ free(result);
return ZR_OK;
}
//
//This unzip function will only work with a gzip header and trailer - while the contents
//of the actual compressed data is the same for either format (gzip vs zlib ), the headers
//and trailers are different for the formats.
-U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size )
+U8* unzip_llsdNavMesh(bool& valid, unsigned int& outsize, std::istream& is, S32 size)
{
-// Add non-allocating variants of unzip_llsd
-// if (size == 0)
-// {
-// LL_WARNS() << "No data to unzip." << LL_ENDL;
-// return NULL;
-// }
+ // Add non-allocating variants of unzip_llsd
+ // if (size == 0)
+ // {
+ // LL_WARNS() << "No data to unzip." << LL_ENDL;
+ // return NULL;
+ // }
-// U8* result = NULL;
-// U32 cur_size = 0;
-// z_stream strm;
-
-// const U32 CHUNK = 0x4000;
+ // U8* result = NULL;
+ // U32 cur_size = 0;
+ // z_stream strm;
-// U8 *in = new(std::nothrow) U8[size];
-// if (in == NULL)
-// {
-// LL_WARNS() << "Memory allocation failure." << LL_ENDL;
-// return NULL;
-// }
-// is.read((char*) in, size);
+ // const U32 CHUNK = 0x4000;
-// U8 out[CHUNK];
-
-// strm.zalloc = Z_NULL;
-// strm.zfree = Z_NULL;
-// strm.opaque = Z_NULL;
-// strm.avail_in = size;
-// strm.next_in = in;
+ // U8 *in = new(std::nothrow) U8[size];
+ // if (in == NULL)
+ // {
+ // LL_WARNS() << "Memory allocation failure." << LL_ENDL;
+ // return NULL;
+ // }
+ // is.read((char*) in, size);
-// valid = true; // Default is all okay.
-// S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP );
-// do
-// {
-// strm.avail_out = CHUNK;
-// strm.next_out = out;
-// ret = inflate(&strm, Z_NO_FLUSH);
-// if (ret == Z_STREAM_ERROR)
-// {
-// inflateEnd(&strm);
-// // free(result);
-// if( result )
-// free(result);
-// delete [] in;
-// in = NULL; result = NULL;// Or we get a double free aftr the while loop ...
-// valid = false;
-// }
-
-// switch (ret)
-// {
-// case Z_NEED_DICT:
-// ret = Z_DATA_ERROR;
-// case Z_DATA_ERROR:
-// case Z_MEM_ERROR:
-// inflateEnd(&strm);
-// // free(result);
-// if( result )
-// free(result);
-// delete [] in;
-// valid = false;
-// in = NULL; result = NULL;// Or we get a double free aftr the while loop ...
-// break;
-// }
+ // U8 out[CHUNK];
-// if( valid ) {// in case this stream is invalid, do not pass the already freed buffer to realloc.
-
-// U32 have = CHUNK-strm.avail_out;
+ // strm.zalloc = Z_NULL;
+ // strm.zfree = Z_NULL;
+ // strm.opaque = Z_NULL;
+ // strm.avail_in = size;
+ // strm.next_in = in;
-// U8* new_result = (U8*) realloc(result, cur_size + have);
-// if (new_result == NULL)
-// {
-// LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size
-// << " bytes; requested " << cur_size + have
-// << " bytes; total syze: ." << size << " bytes."
-// << LL_ENDL;
-// inflateEnd(&strm);
-// if (result)
-// {
-// free(result);
-// }
-// delete[] in;
-// valid = false;
-// return NULL;
-// }
-// result = new_result;
-// memcpy(result+cur_size, out, have);
-// cur_size += have;
+ // valid = true; // Default is all okay.
+ // S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP );
+ // do
+ // {
+ // strm.avail_out = CHUNK;
+ // strm.next_out = out;
+ // ret = inflate(&strm, Z_NO_FLUSH);
+ // if (ret == Z_STREAM_ERROR)
+ // {
+ // inflateEnd(&strm);
+ // // free(result);
+ // if( result )
+ // free(result);
+ // delete [] in;
+ // in = NULL; result = NULL;// Or we get a double free aftr the while loop ...
+ // valid = false;
+ // }
-// } //
+ // switch (ret)
+ // {
+ // case Z_NEED_DICT:
+ // ret = Z_DATA_ERROR;
+ // case Z_DATA_ERROR:
+ // case Z_MEM_ERROR:
+ // inflateEnd(&strm);
+ // // free(result);
+ // if( result )
+ // free(result);
+ // delete [] in;
+ // valid = false;
+ // in = NULL; result = NULL;// Or we get a double free aftr the while loop ...
+ // break;
+ // }
-// } while (ret == Z_OK);
+ // if( valid ) {// in case this stream is invalid, do not pass the already freed buffer to realloc.
-// inflateEnd(&strm);
-// delete [] in;
+ // U32 have = CHUNK-strm.avail_out;
-// if (ret != Z_STREAM_END)
-// {
-// // result might have been freed above. And calling free with a null pointer is not defined.
-// // free(result);
-// if( result )
-// free(result);
-// //
-
-// valid = false;
-// return NULL;
-// }
+ // U8* new_result = (U8*) realloc(result, cur_size + have);
+ // if (new_result == NULL)
+ // {
+ // LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size
+ // << " bytes; requested " << cur_size + have
+ // << " bytes; total syze: ." << size << " bytes."
+ // << LL_ENDL;
+ // inflateEnd(&strm);
+ // if (result)
+ // {
+ // free(result);
+ // }
+ // delete[] in;
+ // valid = false;
+ // return NULL;
+ // }
+ // result = new_result;
+ // memcpy(result+cur_size, out, have);
+ // cur_size += have;
-// //result now points to the decompressed LLSD block
-// {
-// outsize= cur_size;
-// valid = true;
-// }
+ // } //
-// return result;
-// }
+ // } while (ret == Z_OK);
+
+ // inflateEnd(&strm);
+ // delete [] in;
+
+ // if (ret != Z_STREAM_END)
+ // {
+ // // result might have been freed above. And calling free with a null pointer is not defined.
+ // // free(result);
+ // if( result )
+ // free(result);
+ // //
+
+ // valid = false;
+ // return NULL;
+ // }
+
+ // //result now points to the decompressed LLSD block
+ // {
+ // outsize= cur_size;
+ // valid = true;
+ // }
+
+ // return result;
+ // }
if (size == 0)
{
LL_WARNS() << "No data to unzip." << LL_ENDL;
@@ -2578,33 +2430,33 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32
return nullptr;
}
- is.read((char*) in.get(), size);
+ is.read((char*)in.get(), size);
return unzip_llsdNavMesh(valid, outsize, in.get(), size);
}
-U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, const U8* in, S32 size )
+U8* unzip_llsdNavMesh(bool& valid, unsigned int& outsize, const U8* in, S32 size)
{
if (size == 0)
{
LL_WARNS() << "No data to unzip." << LL_ENDL;
return nullptr;
}
- U8* result = NULL;
+ U8* result = nullptr;
U32 cur_size = 0;
z_stream strm;
-
+
const U32 CHUNK = 0x4000;
U8 out[CHUNK];
-
+
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = size;
strm.next_in = const_cast(in);
-
- S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP );
+
+ S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP);
do
{
strm.avail_out = CHUNK;
@@ -2614,26 +2466,26 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, const U8* in, S32 siz
{
inflateEnd(&strm);
free(result);
- return NULL;
+ return nullptr;
}
-
+
switch (ret)
{
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
- // [[fallthrough]]; // TODO when we have C++17 compilation.
+ [[fallthrough]];
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&strm);
free(result);
valid = false;
- return NULL;
+ return nullptr;
}
- U32 have = CHUNK-strm.avail_out;
+ U32 have = CHUNK - strm.avail_out;
- U8* new_result = (U8*) realloc(result, cur_size + have);
- if (new_result == NULL)
+ U8* new_result = (U8*)realloc(result, cur_size + have);
+ if (!new_result)
{
LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size
<< " bytes; requested " << cur_size + have
@@ -2645,10 +2497,10 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, const U8* in, S32 siz
free(result);
}
valid = false;
- return NULL;
+ return nullptr;
}
result = new_result;
- memcpy(result+cur_size, out, have);
+ memcpy(result + cur_size, out, have);
cur_size += have;
} while (ret == Z_OK);
@@ -2659,17 +2511,18 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, const U8* in, S32 siz
{
free(result);
valid = false;
- return NULL;
+ return nullptr;
}
//result now points to the decompressed LLSD block
{
- outsize= cur_size;
- valid = true;
+ outsize = cur_size;
+ valid = true;
}
return result;
}
+//
char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size)
{
@@ -2689,4 +2542,4 @@ char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size)
return in;
}
-//
\ No newline at end of file
+
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index 6df00540bd..8c2005e42b 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -858,14 +858,12 @@ public:
ZR_SIZE_ERROR,
ZR_DATA_ERROR,
ZR_PARSE_ERROR,
-// Add non-allocating variants of unzip_llsd
- ZR_BUFFER_ERROR,
- ZR_VERSION_ERROR
-//
+ ZR_BUFFER_ERROR,
+ ZR_VERSION_ERROR
} EZipRresult;
// return OK or reason for failure
static EZipRresult unzip_llsd(LLSD& data, std::istream& is, S32 size);
- static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size); // Add non-allocating variants of unzip_llsd
+ static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size);
};
//dirty little zip functions -- yell at davep
@@ -878,5 +876,4 @@ LL_COMMON_API U8* unzip_llsdNavMesh(bool& valid, unsigned int& outsize, const U8
// returns a pointer to the array or past the array if the deprecated header exists
LL_COMMON_API char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size = nullptr);
-//
#endif // LL_LLSDSERIALIZE_H
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index 51b324199e..c8d18e32c9 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -1016,44 +1016,6 @@ LLUUID::LLUUID()
//
}
-// Copy constructor
- LLUUID::LLUUID(const LLUUID& rhs)
-{
- LL_PROFILE_ZONE_SCOPED;
- // Fix for misaligned unsigned ints in LLUUID; by Sovereign Engineer / Shyotl Kuhr
- //U32 *tmp = (U32 *)mData;
- //U32 *rhstmp = (U32 *)rhs.mData;
- //tmp[0] = rhstmp[0];
- //tmp[1] = rhstmp[1];
- //tmp[2] = rhstmp[2];
- //tmp[3] = rhstmp[3];
- memcpy(mData, rhs.mData, sizeof(mData));
- //
-}
-
- LLUUID::~LLUUID()
-{
-}
-
-// Assignment
- LLUUID& LLUUID::operator=(const LLUUID& rhs)
-{
- LL_PROFILE_ZONE_SCOPED;
- // Fix for misaligned unsigned ints in LLUUID; by Sovereign Engineer / Shyotl Kuhr
- //// No need to check the case where this==&rhs. The branch is slower than the write.
- //U32 *tmp = (U32 *)mData;
- //U32 *rhstmp = (U32 *)rhs.mData;
- //tmp[0] = rhstmp[0];
- //tmp[1] = rhstmp[1];
- //tmp[2] = rhstmp[2];
- //tmp[3] = rhstmp[3];
-
- memcpy(mData, rhs.mData, sizeof(mData));
- //
- return *this;
-}
-
-
LLUUID::LLUUID(const char *in_string)
{
if (!in_string || in_string[0] == 0)
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index f7215b1dae..5f0d7579f2 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -29,11 +29,10 @@
#include
#include
#include
-#include // for std::memmove
#include "stdtypes.h"
#include "llpreprocessor.h"
#include
-#include "llprofiler.h"
+
class LLMutex;
const S32 UUID_BYTES = 16;
@@ -56,12 +55,7 @@ public:
LLUUID();
explicit LLUUID(const char *in_string); // Convert from string.
explicit LLUUID(const std::string& in_string); // Convert from string.
- LLUUID(const LLUUID &in);
- LLUUID(LLUUID&& rhs) noexcept { LL_PROFILE_ZONE_SCOPED; std::memmove(mData, rhs.mData, sizeof(mData));};
- LLUUID &operator=(const LLUUID &rhs);
- LLUUID &operator=(LLUUID &&rhs) noexcept { LL_PROFILE_ZONE_SCOPED; std::memmove(mData, rhs.mData, sizeof(mData));return *this;};
-
- ~LLUUID();
+ ~LLUUID() = default;
//
// MANIPULATORS
@@ -189,6 +183,9 @@ public:
U8 mData[UUID_BYTES];
};
+static_assert(std::is_trivially_copyable::value, "LLUUID must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLUUID must be trivial move");
+static_assert(std::is_standard_layout::value, "LLUUID must be a standard layout type");
typedef std::vector uuid_vec_t;
typedef std::set uuid_set_t;
diff --git a/indra/llcommon/threadsafeschedule.h b/indra/llcommon/threadsafeschedule.h
index 5ae89375c5..0c3a541196 100644
--- a/indra/llcommon/threadsafeschedule.h
+++ b/indra/llcommon/threadsafeschedule.h
@@ -248,8 +248,6 @@ namespace LL
TimePoint until = TimePoint::clock::now() + std::chrono::hours(24);
pop_result popped = tryPopUntil_(lock, until, tt);
if (popped == POPPED)
- // Prevent RVO elision
- //return std::move(tt);
return tt;
// DONE: throw, just as super::pop() does
diff --git a/indra/llfilesystem/lldir_mac.cpp b/indra/llfilesystem/lldir_mac.cpp
index b8414ff009..437a380c76 100644
--- a/indra/llfilesystem/lldir_mac.cpp
+++ b/indra/llfilesystem/lldir_mac.cpp
@@ -66,16 +66,16 @@ LLDir_Mac::LLDir_Mac()
const std::string secondLifeString = "Firestorm";
- std::string *executablepathstr = getSystemExecutableFolder();
+ std::string executablepathstr = getSystemExecutableFolder();
//NOTE: LLINFOS/LLERRS will not output to log here. The streams are not initialized.
- if (executablepathstr)
+ if (!executablepathstr.empty())
{
// mExecutablePathAndName
- mExecutablePathAndName = *executablepathstr;
+ mExecutablePathAndName = executablepathstr;
- boost::filesystem::path executablepath(*executablepathstr);
+ boost::filesystem::path executablepath(executablepathstr);
# ifndef BOOST_SYSTEM_NO_DEPRECATED
#endif
@@ -83,8 +83,8 @@ LLDir_Mac::LLDir_Mac()
mExecutableDir = executablepath.parent_path().string();
// mAppRODataDir
- std::string *resourcepath = getSystemResourceFolder();
- mAppRODataDir = *resourcepath;
+ std::string resourcepath = getSystemResourceFolder();
+ mAppRODataDir = resourcepath;
// *NOTE: When running in a dev tree, use the copy of
// skins in indra/newview/ rather than in the application bundle. This
@@ -110,11 +110,11 @@ LLDir_Mac::LLDir_Mac()
}
// mOSUserDir
- std::string *appdir = getSystemApplicationSupportFolder();
+ std::string appdir = getSystemApplicationSupportFolder();
std::string rootdir;
//Create root directory
- if (CreateDirectory(*appdir, secondLifeString, &rootdir))
+ if (CreateDirectory(appdir, secondLifeString, &rootdir))
{
// Save the full path to the folder
@@ -128,12 +128,10 @@ LLDir_Mac::LLDir_Mac()
}
//mOSCacheDir
- std::string *cachedir = getSystemCacheFolder();
-
- if (cachedir)
-
+ std::string cachedir = getSystemCacheFolder();
+ if (!cachedir.empty())
{
- mOSCacheDir = *cachedir;
+ mOSCacheDir = cachedir;
//TODO: This changes from ~/Library/Cache/Secondlife to ~/Library/Cache/com.app.secondlife/Secondlife. Last dir level could go away.
// Adjust the cache directory to match what's expected in lldir.
//CreateDirectory(mOSCacheDir, secondLifeString, NULL);
@@ -159,12 +157,10 @@ LLDir_Mac::LLDir_Mac()
// mTempDir
//Aura 120920 boost::filesystem::temp_directory_path() not yet implemented on mac. :(
- std::string *tmpdir = getSystemTempFolder();
- if (tmpdir)
+ std::string tmpdir = getSystemTempFolder();
+ if (!tmpdir.empty())
{
-
- CreateDirectory(*tmpdir, secondLifeString, &mTempDir);
- if (tmpdir) delete tmpdir;
+ CreateDirectory(tmpdir, secondLifeString, &mTempDir);
}
mWorkingDir = getCurPath();
diff --git a/indra/llfilesystem/lldir_utils_objc.h b/indra/llfilesystem/lldir_utils_objc.h
index 12019c4284..59dbeb4aec 100644
--- a/indra/llfilesystem/lldir_utils_objc.h
+++ b/indra/llfilesystem/lldir_utils_objc.h
@@ -33,11 +33,11 @@
#include
-std::string* getSystemTempFolder();
-std::string* getSystemCacheFolder();
-std::string* getSystemApplicationSupportFolder();
-std::string* getSystemResourceFolder();
-std::string* getSystemExecutableFolder();
+std::string getSystemTempFolder();
+std::string getSystemCacheFolder();
+std::string getSystemApplicationSupportFolder();
+std::string getSystemResourceFolder();
+std::string getSystemExecutableFolder();
#endif // LL_LLDIR_UTILS_OBJC_H
diff --git a/indra/llfilesystem/lldir_utils_objc.mm b/indra/llfilesystem/lldir_utils_objc.mm
index da55a2f897..20540fb93c 100644
--- a/indra/llfilesystem/lldir_utils_objc.mm
+++ b/indra/llfilesystem/lldir_utils_objc.mm
@@ -30,75 +30,75 @@
#include "lldir_utils_objc.h"
#import
-std::string* getSystemTempFolder()
+std::string getSystemTempFolder()
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSString * tempDir = NSTemporaryDirectory();
- if (tempDir == nil)
- tempDir = @"/tmp";
- std::string *result = ( new std::string([tempDir UTF8String]) );
- [pool release];
+ std::string result;
+ @autoreleasepool {
+ NSString * tempDir = NSTemporaryDirectory();
+ if (tempDir == nil)
+ tempDir = @"/tmp";
+ result = std::string([tempDir UTF8String]);
+ }
return result;
}
//findSystemDirectory scoped exclusively to this file.
-std::string* findSystemDirectory(NSSearchPathDirectory searchPathDirectory,
+std::string findSystemDirectory(NSSearchPathDirectory searchPathDirectory,
NSSearchPathDomainMask domainMask)
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- std::string *result = nil;
- NSString *path = nil;
-
- // Search for the path
- NSArray* paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory,
- domainMask,
- YES);
- if ([paths count])
- {
- path = [paths objectAtIndex:0];
- //HACK: Always attempt to create directory, ignore errors.
- NSError *error = nil;
-
- [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error];
-
+ std::string result;
+ @autoreleasepool {
+ NSString *path = nil;
- result = new std::string([path UTF8String]);
+ // Search for the path
+ NSArray* paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory,
+ domainMask,
+ YES);
+ if ([paths count])
+ {
+ path = [paths objectAtIndex:0];
+ //HACK: Always attempt to create directory, ignore errors.
+ NSError *error = nil;
+
+ [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error];
+
+
+ result = std::string([path UTF8String]);
+ }
}
- [pool release];
return result;
}
-std::string* getSystemExecutableFolder()
+std::string getSystemExecutableFolder()
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSString *bundlePath = [[NSBundle mainBundle] executablePath];
- std::string *result = (new std::string([bundlePath UTF8String]));
- [pool release];
+ std::string result;
+ @autoreleasepool {
+ NSString *bundlePath = [[NSBundle mainBundle] executablePath];
+ result = std::string([bundlePath UTF8String]);
+ }
return result;
}
-std::string* getSystemResourceFolder()
+std::string getSystemResourceFolder()
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
- std::string *result = (new std::string([bundlePath UTF8String]));
- [pool release];
+ std::string result;
+ @autoreleasepool {
+ NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
+ result = std::string([bundlePath UTF8String]);
+ }
return result;
}
-std::string* getSystemCacheFolder()
+std::string getSystemCacheFolder()
{
return findSystemDirectory (NSCachesDirectory,
NSUserDomainMask);
}
-std::string* getSystemApplicationSupportFolder()
+std::string getSystemApplicationSupportFolder()
{
return findSystemDirectory (NSApplicationSupportDirectory,
NSUserDomainMask);
diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp
index f7dc6272cf..cad7c00042 100644
--- a/indra/llimage/llpngwrapper.cpp
+++ b/indra/llimage/llpngwrapper.cpp
@@ -257,12 +257,7 @@ void LLPngWrapper::normalizeImage()
png_set_strip_16(mReadPngPtr);
}
-#if LL_DARWIN
- const F64 SCREEN_GAMMA = 1.8;
-#else
const F64 SCREEN_GAMMA = 2.2;
-#endif
-
if (png_get_gAMA(mReadPngPtr, mReadInfoPtr, &mGamma))
{
png_set_gamma(mReadPngPtr, SCREEN_GAMMA, mGamma);
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index a671eeca13..41a21c4b68 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -25,184 +25,48 @@
*/
#include "linden_common.h"
-// #include "fstelemetry.h" // instrument image decodes
#include "llimagej2coj.h"
-#define OPENJPEG2
// this is defined so that we get static linking.
#include "openjpeg.h"
-#ifndef OPENJPEG2
-#include "cio.h"
-#endif
#include "event.h"
+#include "cio.h"
-#include "lltimer.h"
-
-// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3
-#ifdef OPENJPEG2
-class LLJp2StreamReader {
-public:
- LLJp2StreamReader(LLImageJ2C* pImage) : m_pImage(pImage), m_Position(0) { }
-
- static OPJ_SIZE_T readStream(void* pBufferOut, OPJ_SIZE_T szBufferOut, void* pUserData)
- {
- LLJp2StreamReader* pStream = (LLJp2StreamReader*)pUserData;
- if ( (!pBufferOut) || (!pStream) || (!pStream->m_pImage) )
- return (OPJ_SIZE_T)-1;
-
- OPJ_SIZE_T szBufferRead = llmin(szBufferOut, pStream->m_pImage->getDataSize() - pStream->m_Position);
- if (!szBufferRead)
- return (OPJ_SIZE_T)-1;
-
- memcpy(pBufferOut, pStream->m_pImage->getData() + pStream->m_Position, szBufferRead);
- pStream->m_Position += szBufferRead;
- return szBufferRead;
- }
-
- static OPJ_OFF_T skipStream(OPJ_OFF_T bufferOffset, void* pUserData)
- {
- LLJp2StreamReader* pStream = (LLJp2StreamReader*)pUserData;
- if ( (!pStream) || (!pStream->m_pImage) )
- return (OPJ_SIZE_T)-1;
-
- if (bufferOffset < 0)
- {
- // Skipping backward
- if (pStream->m_Position == 0)
- return (OPJ_SIZE_T)-1; // Already at the start of the stream
- else if (pStream->m_Position + bufferOffset < 0)
- bufferOffset = -(OPJ_OFF_T)pStream->m_Position; // Don't underflow
- }
- else
- {
- // Skipping forward
- OPJ_SIZE_T szRemaining = pStream->m_pImage->getDataSize() - pStream->m_Position;
- if (!szRemaining)
- return (OPJ_SIZE_T)-1; // Already at the end of the stream
- else if (bufferOffset > szRemaining)
- bufferOffset = szRemaining; // Don't overflow
- }
- pStream->m_Position += bufferOffset;
-
- return bufferOffset;
- }
-
- static OPJ_BOOL seekStream(OPJ_OFF_T bufferOffset, void* pUserData)
- {
- LLJp2StreamReader* pStream = (LLJp2StreamReader*)pUserData;
- if ( (!pStream) || (!pStream->m_pImage) )
- return OPJ_FALSE;
-
- if ( (bufferOffset < 0) || (bufferOffset > pStream->m_pImage->getDataSize()) )
- return OPJ_FALSE;
-
- pStream->m_Position = bufferOffset;
- return OPJ_TRUE;
- }
-protected:
- LLImageJ2C* m_pImage = nullptr;
- OPJ_SIZE_T m_Position = 0;
-};
-
-class LLJp2StreamWriter {
-public:
- LLJp2StreamWriter(LLImageJ2C* pImage) : m_pImage(pImage), m_Position(0) { }
-
- static OPJ_SIZE_T writeStream(void* pBufferIn, OPJ_SIZE_T szBufferIn, void* pUserData)
- {
- LLJp2StreamWriter* pStream = (LLJp2StreamWriter*)pUserData;
- if ( (!pBufferIn) || (!pStream) || (!pStream->m_pImage) )
- return (OPJ_SIZE_T)-1;
-
- if (pStream->m_Position + szBufferIn > pStream->m_pImage->getDataSize())
- pStream->m_pImage->reallocateData(pStream->m_Position + szBufferIn);
-
- memcpy(pStream->m_pImage->getData() + pStream->m_Position, pBufferIn, szBufferIn);
- pStream->m_Position += szBufferIn;
- return szBufferIn;
- }
-
- static OPJ_OFF_T skipStream(OPJ_OFF_T bufferOffset, void* pUserData)
- {
- LLJp2StreamWriter* pStream = (LLJp2StreamWriter*)pUserData;
- if ( (!pStream) || (!pStream->m_pImage) )
- return -1;
-
- if (bufferOffset < 0)
- {
- // Skipping backward
- if (pStream->m_Position == 0)
- return -1; // Already at the start of the stream
- else if (pStream->m_Position + bufferOffset < 0)
- bufferOffset = -pStream->m_Position; // Don't underflow
- }
- else
- {
- // Skipping forward
- if (pStream->m_Position + bufferOffset > pStream->m_pImage->getDataSize())
- return -1; // Don't allow skipping past the end of the stream
- }
-
- pStream->m_Position += bufferOffset;
- return bufferOffset;
- }
-
- static OPJ_BOOL seekStream(OPJ_OFF_T bufferOffset, void* pUserData)
- {
- LLJp2StreamWriter* pStream = (LLJp2StreamWriter*)pUserData;
- if ( (!pStream) || (!pStream->m_pImage) )
- return OPJ_FALSE;
-
- if ( (bufferOffset < 0) || (bufferOffset > pStream->m_pImage->getDataSize()) )
- return OPJ_FALSE;
-
- pStream->m_Position = bufferOffset;
- return OPJ_TRUE;
- }
-
-protected:
- LLImageJ2C* m_pImage = nullptr;
- OPJ_OFF_T m_Position = 0;
-};
-#endif
-// [/SL:KB]
+#define MAX_ENCODED_DISCARD_LEVELS 5
// Factory function: see declaration in llimagej2c.cpp
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
{
- return new LLImageJ2COJ();
+ return new LLImageJ2COJ();
}
std::string LLImageJ2COJ::getEngineInfo() const
{
-#ifdef OPENJPEG_VERSION
- return std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
- + opj_version();
-#elif defined OPJ_PACKAGE_VERSION
- return std::string("OpenJPEG: " OPJ_PACKAGE_VERSION ", Runtime: ") + opj_version();
-#else
-#ifdef OPENJPEG2
- return llformat("OpenJPEG: %i.%i.%i, Runtime: %s", OPJ_VERSION_MAJOR, OPJ_VERSION_MINOR, OPJ_VERSION_BUILD, opj_version());
-#else
- return std::string("OpenJPEG Runtime: ") + opj_version();
-#endif
-#endif
+// OpenJpeg fixes
+//#ifdef OPENJPEG_VERSION
+// return std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
+// + opj_version();
+//#else
+// return std::string("OpenJPEG runtime: ") + opj_version();
+//#endif
+ return llformat("OpenJPEG: %i.%i.%i, Runtime: %s", OPJ_VERSION_MAJOR, OPJ_VERSION_MINOR, OPJ_VERSION_BUILD, opj_version());
+//
}
// Return string from message, eliminating final \n if present
static std::string chomp(const char* msg)
{
- // stomp trailing \n
- std::string message = msg;
- if (!message.empty())
- {
- size_t last = message.size() - 1;
- if (message[last] == '\n')
- {
- message.resize( last );
- }
- }
- return message;
+ // stomp trailing \n
+ std::string message = msg;
+ if (!message.empty())
+ {
+ size_t last = message.size() - 1;
+ if (message[last] == '\n')
+ {
+ message.resize(last);
+ }
+}
+ return message;
}
/**
@@ -210,29 +74,642 @@ sample error callback expecting a LLFILE* client object
*/
void error_callback(const char* msg, void*)
{
- LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+ LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
}
/**
sample warning callback expecting a LLFILE* client object
*/
void warning_callback(const char* msg, void*)
{
- LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+ LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
}
/**
sample debug callback expecting no client object
*/
void info_callback(const char* msg, void*)
{
- LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+ LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
}
// Divide a by 2 to the power of b and round upwards
int ceildivpow2(int a, int b)
{
- return (a + (1 << b) - 1) >> b;
+ return (a + (1 << b) - 1) >> b;
}
+class JPEG2KBase
+{
+public:
+ JPEG2KBase() {}
+
+ U8* buffer = nullptr;
+ OPJ_SIZE_T size = 0;
+ OPJ_OFF_T offset = 0;
+};
+
+#define WANT_VERBOSE_OPJ_SPAM LL_DEBUG
+
+static void opj_info(const char* msg, void* user_data)
+{
+ llassert(user_data);
+#if WANT_VERBOSE_OPJ_SPAM
+ LL_INFOS("OpenJPEG") << msg << LL_ENDL;
+#endif
+}
+
+static void opj_warn(const char* msg, void* user_data)
+{
+ llassert(user_data);
+#if WANT_VERBOSE_OPJ_SPAM
+ LL_WARNS("OpenJPEG") << msg << LL_ENDL;
+#endif
+}
+
+static void opj_error(const char* msg, void* user_data)
+{
+ llassert(user_data);
+#if WANT_VERBOSE_OPJ_SPAM
+ LL_WARNS("OpenJPEG") << msg << LL_ENDL;
+#endif
+}
+
+static OPJ_SIZE_T opj_read(void * buffer, OPJ_SIZE_T bytes, void* user_data)
+{
+ llassert(user_data);
+ JPEG2KBase* jpeg_codec = static_cast(user_data);
+ OPJ_SIZE_T remainder = (jpeg_codec->size - jpeg_codec->offset);
+ if (remainder <= 0)
+ {
+ jpeg_codec->offset = jpeg_codec->size;
+ // Indicate end of stream (hacky?)
+ return (OPJ_OFF_T)-1;
+ }
+ OPJ_SIZE_T to_read = llclamp(U32(bytes), U32(0), U32(remainder));
+ memcpy(buffer, jpeg_codec->buffer + jpeg_codec->offset, to_read);
+ jpeg_codec->offset += to_read;
+ return to_read;
+}
+
+static OPJ_SIZE_T opj_write(void * buffer, OPJ_SIZE_T bytes, void* user_data)
+{
+ llassert(user_data);
+ JPEG2KBase* jpeg_codec = static_cast(user_data);
+ OPJ_SIZE_T remainder = jpeg_codec->size - jpeg_codec->offset;
+ if (remainder < bytes)
+ {
+ OPJ_SIZE_T new_size = jpeg_codec->size + (bytes - remainder);
+ U8* new_buffer = (U8*)ll_aligned_malloc_16(new_size);
+ memcpy(new_buffer, jpeg_codec->buffer, jpeg_codec->offset);
+ U8* old_buffer = jpeg_codec->buffer;
+ jpeg_codec->buffer = new_buffer;
+ ll_aligned_free_16(old_buffer);
+ jpeg_codec->size = new_size;
+ }
+ memcpy(jpeg_codec->buffer + jpeg_codec->offset, buffer, bytes);
+ jpeg_codec->offset += bytes;
+ return bytes;
+}
+
+static OPJ_OFF_T opj_skip(OPJ_OFF_T bytes, void* user_data)
+{
+ JPEG2KBase* jpeg_codec = static_cast(user_data);
+ jpeg_codec->offset += bytes;
+
+ if (jpeg_codec->offset > jpeg_codec->size)
+ {
+ jpeg_codec->offset = jpeg_codec->size;
+ // Indicate end of stream
+ return (OPJ_OFF_T)-1;
+ }
+
+ if (jpeg_codec->offset < 0)
+ {
+ // Shouldn't be possible?
+ jpeg_codec->offset = 0;
+ return (OPJ_OFF_T)-1;
+ }
+
+ return bytes;
+}
+
+static OPJ_BOOL opj_seek(OPJ_OFF_T bytes, void * user_data)
+{
+ JPEG2KBase* jpeg_codec = static_cast(user_data);
+ jpeg_codec->offset = bytes;
+ jpeg_codec->offset = llclamp(U32(jpeg_codec->offset), U32(0), U32(jpeg_codec->size));
+ return OPJ_TRUE;
+}
+
+static void opj_free_user_data(void * user_data)
+{
+ JPEG2KBase* jpeg_codec = static_cast(user_data);
+ // Don't free, data is managed externally
+ jpeg_codec->buffer = nullptr;
+ jpeg_codec->size = 0;
+ jpeg_codec->offset = 0;
+}
+
+static void opj_free_user_data_write(void * user_data)
+{
+ JPEG2KBase* jpeg_codec = static_cast(user_data);
+ // Free, data was allocated here
+ ll_aligned_free_16(jpeg_codec->buffer);
+ jpeg_codec->buffer = nullptr;
+ jpeg_codec->size = 0;
+ jpeg_codec->offset = 0;
+}
+
+class JPEG2KDecode : public JPEG2KBase
+{
+public:
+
+ JPEG2KDecode(S8 discardLevel)
+ {
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ memset(¶meters, 0, sizeof(opj_dparameters_t));
+ event_mgr.error_handler = error_callback;
+ event_mgr.warning_handler = warning_callback;
+ event_mgr.info_handler = info_callback;
+ opj_set_default_decoder_parameters(¶meters);
+ parameters.cp_reduce = discardLevel;
+ }
+
+ ~JPEG2KDecode()
+ {
+ if (decoder)
+ {
+ opj_destroy_codec(decoder);
+ }
+ decoder = nullptr;
+
+ if (image)
+ {
+ opj_image_destroy(image);
+ }
+ image = nullptr;
+
+ if (stream)
+ {
+ opj_stream_destroy(stream);
+ }
+ stream = nullptr;
+
+ if (codestream_info)
+ {
+ opj_destroy_cstr_info(&codestream_info);
+ }
+ codestream_info = nullptr;
+ }
+
+ bool readHeader(
+ U8* data,
+ U32 dataSize,
+ S32& widthOut,
+ S32& heightOut,
+ S32& components,
+ S32& discard_level)
+ {
+ parameters.flags |= OPJ_DPARAMETERS_DUMP_FLAG;
+
+ decoder = opj_create_decompress(OPJ_CODEC_J2K);
+
+ if (!opj_setup_decoder(decoder, ¶meters))
+ {
+ return false;
+ }
+
+ if (stream)
+ {
+ opj_stream_destroy(stream);
+ }
+
+ stream = opj_stream_create(dataSize, true);
+ if (!stream)
+ {
+ return false;
+ }
+
+ opj_stream_set_user_data(stream, this, opj_free_user_data);
+ opj_stream_set_user_data_length(stream, dataSize);
+ opj_stream_set_read_function(stream, opj_read);
+ opj_stream_set_write_function(stream, opj_write);
+ opj_stream_set_skip_function(stream, opj_skip);
+ opj_stream_set_seek_function(stream, opj_seek);
+
+ buffer = data;
+ size = dataSize;
+ offset = 0;
+
+ // enable decoding partially loaded images
+ opj_decoder_set_strict_mode(decoder, OPJ_FALSE);
+
+ /* Read the main header of the codestream and if necessary the JP2 boxes*/
+ if (!opj_read_header((opj_stream_t*)stream, decoder, &image))
+ {
+ return false;
+ }
+
+ codestream_info = opj_get_cstr_info(decoder);
+
+ if (!codestream_info)
+ {
+ return false;
+ }
+
+ U32 tileDimX = codestream_info->tdx;
+ U32 tileDimY = codestream_info->tdy;
+ U32 tilesW = codestream_info->tw;
+ U32 tilesH = codestream_info->th;
+
+ widthOut = S32(tilesW * tileDimX);
+ heightOut = S32(tilesH * tileDimY);
+ components = codestream_info->nbcomps;
+
+ discard_level = 0;
+ while (tilesW > 1 && tilesH > 1 && discard_level < MAX_DISCARD_LEVEL)
+ {
+ discard_level++;
+ tilesW >>= 1;
+ tilesH >>= 1;
+ }
+
+ return true;
+ }
+
+ bool decode(U8* data, U32 dataSize, U32* channels, U8 discard_level)
+ {
+ parameters.flags &= ~OPJ_DPARAMETERS_DUMP_FLAG;
+
+ decoder = opj_create_decompress(OPJ_CODEC_J2K);
+ opj_setup_decoder(decoder, ¶meters);
+
+ opj_set_info_handler(decoder, opj_info, this);
+ opj_set_warning_handler(decoder, opj_warn, this);
+ opj_set_error_handler(decoder, opj_error, this);
+
+ if (stream)
+ {
+ opj_stream_destroy(stream);
+ }
+
+ stream = opj_stream_create(dataSize, true);
+ if (!stream)
+ {
+ return false;
+ }
+
+ opj_stream_set_user_data(stream, this, opj_free_user_data);
+ opj_stream_set_user_data_length(stream, dataSize);
+ opj_stream_set_read_function(stream, opj_read);
+ opj_stream_set_write_function(stream, opj_write);
+ opj_stream_set_skip_function(stream, opj_skip);
+ opj_stream_set_seek_function(stream, opj_seek);
+
+ buffer = data;
+ size = dataSize;
+ offset = 0;
+
+ if (image)
+ {
+ opj_image_destroy(image);
+ image = nullptr;
+ }
+
+ // needs to happen before opj_read_header and opj_decode...
+ opj_set_decoded_resolution_factor(decoder, discard_level);
+
+ // enable decoding partially loaded images
+ opj_decoder_set_strict_mode(decoder, OPJ_FALSE);
+
+ if (!opj_read_header(stream, decoder, &image))
+ {
+ return false;
+ }
+
+ // needs to happen before decode which may fail
+ if (channels)
+ {
+ *channels = image->numcomps;
+ }
+
+ OPJ_BOOL decoded = opj_decode(decoder, stream, image);
+
+ // count was zero. The latter is just a sanity check before we
+ // dereference the array.
+ if (!decoded || !image || !image->numcomps)
+ {
+ opj_end_decompress(decoder, stream);
+ return false;
+ }
+
+ opj_end_decompress(decoder, stream);
+
+ return true;
+ }
+
+ opj_image_t* getImage() { return image; }
+
+private:
+ opj_dparameters_t parameters;
+ opj_event_mgr_t event_mgr;
+ opj_image_t* image = nullptr;
+ opj_codec_t* decoder = nullptr;
+ opj_stream_t* stream = nullptr;
+ opj_codestream_info_v2_t* codestream_info = nullptr;
+};
+
+class JPEG2KEncode : public JPEG2KBase
+{
+public:
+ const OPJ_UINT32 TILE_SIZE = 64 * 64 * 3;
+
+ JPEG2KEncode(const char* comment_text_in, bool reversible)
+ {
+ memset(¶meters, 0, sizeof(opj_cparameters_t));
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = error_callback;
+ event_mgr.warning_handler = warning_callback;
+ event_mgr.info_handler = info_callback;
+
+ opj_set_default_encoder_parameters(¶meters);
+ parameters.cod_format = OPJ_CODEC_J2K;
+ parameters.cp_disto_alloc = 1;
+ parameters.max_cs_size = (1 << 15);
+
+ if (reversible)
+ {
+ parameters.tcp_numlayers = 1;
+ parameters.tcp_rates[0] = 1.0f;
+ }
+ else
+ {
+ parameters.tcp_numlayers = 5;
+ parameters.tcp_rates[0] = 1920.0f;
+ parameters.tcp_rates[1] = 960.0f;
+ parameters.tcp_rates[2] = 480.0f;
+ parameters.tcp_rates[3] = 120.0f;
+ parameters.tcp_rates[4] = 30.0f;
+ parameters.irreversible = 1;
+ parameters.tcp_mct = 1;
+ }
+
+ if (comment_text)
+ {
+ free(comment_text);
+ }
+ comment_text = comment_text_in ? strdup(comment_text_in) : nullptr;
+
+ parameters.cp_comment = comment_text ? comment_text : (char*)"no comment";
+ llassert(parameters.cp_comment);
+ }
+
+ ~JPEG2KEncode()
+ {
+ if (encoder)
+ {
+ opj_destroy_codec(encoder);
+ }
+ encoder = nullptr;
+
+ if (image)
+ {
+ opj_image_destroy(image);
+ }
+ image = nullptr;
+
+ if (stream)
+ {
+ opj_stream_destroy(stream);
+ }
+ stream = nullptr;
+
+ if (comment_text)
+ {
+ free(comment_text);
+ }
+ comment_text = nullptr;
+ }
+
+ bool encode(const LLImageRaw& rawImageIn, LLImageJ2C &compressedImageOut)
+ {
+ setImage(rawImageIn);
+
+ encoder = opj_create_compress(OPJ_CODEC_J2K);
+
+ parameters.tcp_mct = (image->numcomps >= 3) ? 1 : 0;
+ parameters.cod_format = OPJ_CODEC_J2K;
+ parameters.prog_order = OPJ_RLCP;
+ parameters.cp_disto_alloc = 1;
+
+ if (!opj_setup_encoder(encoder, ¶meters, image))
+ {
+ return false;
+ }
+
+ opj_set_info_handler(encoder, opj_info, this);
+ opj_set_warning_handler(encoder, opj_warn, this);
+ opj_set_error_handler(encoder, opj_error, this);
+
+ U32 tile_count = (rawImageIn.getWidth() >> 6) * (rawImageIn.getHeight() >> 6);
+ U32 data_size_guess = tile_count * TILE_SIZE;
+
+ // will be freed in opj_free_user_data_write
+ buffer = (U8*)ll_aligned_malloc_16(data_size_guess);
+ size = data_size_guess;
+ offset = 0;
+
+ memset(buffer, 0, data_size_guess);
+
+ if (stream)
+ {
+ opj_stream_destroy(stream);
+ }
+
+ stream = opj_stream_create(data_size_guess, false);
+ if (!stream)
+ {
+ return false;
+ }
+
+ opj_stream_set_user_data(stream, this, opj_free_user_data_write);
+ opj_stream_set_user_data_length(stream, data_size_guess);
+ opj_stream_set_read_function(stream, opj_read);
+ opj_stream_set_write_function(stream, opj_write);
+ opj_stream_set_skip_function(stream, opj_skip);
+ opj_stream_set_seek_function(stream, opj_seek);
+
+ OPJ_BOOL started = opj_start_compress(encoder, image, stream);
+
+ if (!started)
+ {
+ return false;
+ }
+
+ if (!opj_encode(encoder, stream))
+ {
+ return false;
+ }
+
+ OPJ_BOOL encoded = opj_end_compress(encoder, stream);
+
+ // if we successfully encoded, then stream out the compressed data...
+ if (encoded)
+ {
+ // "append" (set) the data we "streamed" (memcopied) for writing to the formatted image
+ // with side-effect of setting the actually encoded size to same
+ compressedImageOut.allocateData(offset);
+ memcpy(compressedImageOut.getData(), buffer, offset);
+ compressedImageOut.updateData(); // update width, height etc from header
+ }
+ return encoded;
+ }
+
+ void setImage(const LLImageRaw& raw)
+ {
+ opj_image_cmptparm_t cmptparm[MAX_ENCODED_DISCARD_LEVELS];
+ memset(&cmptparm[0], 0, MAX_ENCODED_DISCARD_LEVELS * sizeof(opj_image_cmptparm_t));
+
+ S32 numcomps = raw.getComponents();
+ S32 width = raw.getWidth();
+ S32 height = raw.getHeight();
+
+ for (S32 c = 0; c < numcomps; c++)
+ {
+ cmptparm[c].prec = 8;
+ cmptparm[c].bpp = 8;
+ cmptparm[c].sgnd = 0;
+ cmptparm[c].dx = parameters.subsampling_dx;
+ cmptparm[c].dy = parameters.subsampling_dy;
+ cmptparm[c].w = width;
+ cmptparm[c].h = height;
+ }
+
+ image = opj_image_create(numcomps, &cmptparm[0], OPJ_CLRSPC_SRGB);
+
+ image->x1 = width;
+ image->y1 = height;
+
+ const U8 *src_datap = raw.getData();
+
+ S32 i = 0;
+ for (S32 y = height - 1; y >= 0; y--)
+ {
+ for (S32 x = 0; x < width; x++)
+ {
+ const U8 *pixel = src_datap + (y*width + x) * numcomps;
+ for (S32 c = 0; c < numcomps; c++)
+ {
+ image->comps[c].data[i] = *pixel;
+ pixel++;
+ }
+ i++;
+ }
+ }
+
+ // This likely works, but there seems to be an issue openjpeg side
+ // check over after gixing that.
+
+ // De-interleave to component plane data
+ /*
+ switch (numcomps)
+ {
+ case 0:
+ default:
+ break;
+
+ case 1:
+ {
+ U32 rBitDepth = image->comps[0].bpp;
+ U32 bytesPerPixel = rBitDepth >> 3;
+ memcpy(image->comps[0].data, src, width * height * bytesPerPixel);
+ }
+ break;
+
+ case 2:
+ {
+ U32 rBitDepth = image->comps[0].bpp;
+ U32 gBitDepth = image->comps[1].bpp;
+ U32 totalBitDepth = rBitDepth + gBitDepth;
+ U32 bytesPerPixel = totalBitDepth >> 3;
+ U32 stride = width * bytesPerPixel;
+ U32 offset = 0;
+ for (S32 y = height - 1; y >= 0; y--)
+ {
+ const U8* component = src + (y * stride);
+ for (S32 x = 0; x < width; x++)
+ {
+ image->comps[0].data[offset] = *component++;
+ image->comps[1].data[offset] = *component++;
+ offset++;
+ }
+ }
+ }
+ break;
+
+ case 3:
+ {
+ U32 rBitDepth = image->comps[0].bpp;
+ U32 gBitDepth = image->comps[1].bpp;
+ U32 bBitDepth = image->comps[2].bpp;
+ U32 totalBitDepth = rBitDepth + gBitDepth + bBitDepth;
+ U32 bytesPerPixel = totalBitDepth >> 3;
+ U32 stride = width * bytesPerPixel;
+ U32 offset = 0;
+ for (S32 y = height - 1; y >= 0; y--)
+ {
+ const U8* component = src + (y * stride);
+ for (S32 x = 0; x < width; x++)
+ {
+ image->comps[0].data[offset] = *component++;
+ image->comps[1].data[offset] = *component++;
+ image->comps[2].data[offset] = *component++;
+ offset++;
+ }
+ }
+ }
+ break;
+
+
+ case 4:
+ {
+ U32 rBitDepth = image->comps[0].bpp;
+ U32 gBitDepth = image->comps[1].bpp;
+ U32 bBitDepth = image->comps[2].bpp;
+ U32 aBitDepth = image->comps[3].bpp;
+
+ U32 totalBitDepth = rBitDepth + gBitDepth + bBitDepth + aBitDepth;
+ U32 bytesPerPixel = totalBitDepth >> 3;
+
+ U32 stride = width * bytesPerPixel;
+ U32 offset = 0;
+ for (S32 y = height - 1; y >= 0; y--)
+ {
+ const U8* component = src + (y * stride);
+ for (S32 x = 0; x < width; x++)
+ {
+ image->comps[0].data[offset] = *component++;
+ image->comps[1].data[offset] = *component++;
+ image->comps[2].data[offset] = *component++;
+ image->comps[3].data[offset] = *component++;
+ offset++;
+ }
+ }
+ }
+ break;
+ }*/
+ }
+
+ opj_image_t* getImage() { return image; }
+
+private:
+ opj_cparameters_t parameters;
+ opj_event_mgr_t event_mgr;
+ opj_image_t* image = nullptr;
+ opj_codec_t* encoder = nullptr;
+ opj_stream_t* stream = nullptr;
+ char* comment_text = nullptr;
+};
+
LLImageJ2COJ::LLImageJ2COJ()
: LLImageJ2CImpl()
@@ -246,668 +723,178 @@ LLImageJ2COJ::~LLImageJ2COJ()
bool LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
{
- // No specific implementation for this method in the OpenJpeg case
+ base.mDiscardLevel = discard_level;
return false;
}
bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
// No specific implementation for this method in the OpenJpeg case
return false;
}
bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- // texture comment metadata reader
- U8* c_data = base.getData();
- S32 c_size = base.getDataSize();
- S32 position = 0;
-
- while (position < 1024 && position < (c_size - 7)) // the comment field should be in the first 1024 bytes.
- {
- if (c_data[position] == 0xff && c_data[position + 1] == 0x64)
- {
- U8 high_byte = c_data[position + 2];
- U8 low_byte = c_data[position + 3];
- S32 c_length = (high_byte * 256) + low_byte; // This size also counts the markers, 00 01 and itself
- if (c_length > 200) // sanity check
- {
- // While comments can be very long, anything longer then 200 is suspect.
- break;
- }
+ JPEG2KDecode decoder(0);
- if (position + 2 + c_length > c_size)
- {
- // comment extends past end of data, corruption, or all data not retrived yet.
- break;
- }
+ // texture comment metadata reader
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; // instrument image decodes
+ U8* c_data = base.getData();
+ S32 c_size = base.getDataSize();
+ S32 position = 0;
- // if the comment block does not end at the end of data, check to see if the next
- // block starts with 0xFF
- if (position + 2 + c_length < c_size && c_data[position + 2 + c_length] != 0xff)
- {
- // invalied comment block
- break;
- }
+ while (position < 1024 && position < (c_size - 7)) // the comment field should be in the first 1024 bytes.
+ {
+ if (c_data[position] == 0xff && c_data[position + 1] == 0x64)
+ {
+ U8 high_byte = c_data[position + 2];
+ U8 low_byte = c_data[position + 3];
+ S32 c_length = (high_byte * 256) + low_byte; // This size also counts the markers, 00 01 and itself
+ if (c_length > 200) // sanity check
+ {
+ // While comments can be very long, anything longer then 200 is suspect.
+ break;
+ }
- // extract the comment minus the markers, 00 01
- raw_image.mComment.assign((char*)(c_data + position + 6), c_length - 4);
- break;
- }
- position++;
- }
- //
+ if (position + 2 + c_length > c_size)
+ {
+ // comment extends past end of data, corruption, or all data not retrived yet.
+ break;
+ }
- LLTimer decode_timer;
+ // if the comment block does not end at the end of data, check to see if the next
+ // block starts with 0xFF
+ if (position + 2 + c_length < c_size && c_data[position + 2 + c_length] != 0xff)
+ {
+ // invalied comment block
+ break;
+ }
- opj_dparameters_t parameters; /* decompression parameters */
- opj_event_mgr_t event_mgr; /* event manager */
- opj_image_t *image = NULL;
+ // extract the comment minus the markers, 00 01
+ raw_image.mComment.assign((char*)(c_data + position + 6), c_length - 4);
+ break;
+ }
+ position++;
+ }
+ //
-#ifndef OPENJPEG2
- opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */
- opj_cio_t *cio = NULL;
-#endif
+ U32 image_channels = 0;
+ S32 data_size = base.getDataSize();
+ S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
+ bool decoded = decoder.decode(base.getData(), max_bytes, &image_channels, base.mDiscardLevel);
- /* configure the event callbacks (not required) */
- memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
- event_mgr.error_handler = error_callback;
- event_mgr.warning_handler = warning_callback;
- event_mgr.info_handler = info_callback;
+ // set correct channel count early so failed decodes don't miss it...
+ S32 channels = (S32)image_channels - first_channel;
+ channels = llmin(channels, max_channel_count);
- /* set decoding parameters to default values */
- opj_set_default_decoder_parameters(¶meters);
+ if (!decoded)
+ {
+ // reset the channel count if necessary
+ if (raw_image.getComponents() != channels)
+ {
+ raw_image.resize(raw_image.getWidth(), raw_image.getHeight(), S8(channels));
+ }
- parameters.cp_reduce = base.getRawDiscardLevel();
+ LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL;
+ // [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3
+ base.decodeFailed();
+ // [SL:KB]
+ return true; // done
+ }
- /* decode the code-stream */
- /* ---------------------- */
+ opj_image_t *image = decoder.getImage();
- /* JPEG-2000 codestream */
+ // Component buffers are allocated in an image width by height buffer.
+ // The image placed in that buffer is ceil(width/2^factor) by
+ // ceil(height/2^factor) and if the factor isn't zero it will be at the
+ // top left of the buffer with black filled in the rest of the pixels.
+ // It is integer math so the formula is written in ceildivpo2.
+ // (Assuming all the components have the same width, height and
+ // factor.)
+ U32 comp_width = image->comps[0].w; // leave this unshifted by 'f' discard factor, the strides are always for the full buffer width
+ U32 f = image->comps[0].factor;
-#ifdef OPENJPEG2
-// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3
- /* get a decoder handle */
- opj_codec_t* opj_decoder_p = opj_create_decompress(OPJ_CODEC_J2K);
+ // do size the texture to the mem we'll acrually use...
+ U32 width = image->comps[0].w;
+ U32 height = image->comps[0].h;
- /* catch events using our callbacks and give a local context */
- opj_set_error_handler(opj_decoder_p, error_callback, 0);
- opj_set_warning_handler(opj_decoder_p, warning_callback, 0);
- opj_set_info_handler(opj_decoder_p, info_callback, 0);
+ raw_image.resize(U16(width), U16(height), S8(channels));
- /* setup the decoder decoding parameters using user parameters */
- opj_setup_decoder(opj_decoder_p, ¶meters);
+ U8 *rawp = raw_image.getData();
- /* allow multi-threading */
- if (opj_has_thread_support())
- {
- opj_codec_set_threads(opj_decoder_p, opj_get_num_cpus());
- }
+ // Port fix for MAINT-4327/MAINT-6584 to OpenJPEG decoder
+ if (!rawp)
+ {
+ base.setLastError("Memory error");
+ base.decodeFailed();
+ return true; // done
+ }
+ //
- /* open a byte stream */
- LLJp2StreamReader streamReader(&base);
- opj_stream_t* opj_stream_p = opj_stream_default_create(OPJ_STREAM_READ);
- opj_stream_set_read_function(opj_stream_p, LLJp2StreamReader::readStream);
- opj_stream_set_skip_function(opj_stream_p, LLJp2StreamReader::skipStream);
- opj_stream_set_seek_function(opj_stream_p, LLJp2StreamReader::seekStream);
- opj_stream_set_user_data(opj_stream_p, &streamReader, nullptr);
- opj_stream_set_user_data_length(opj_stream_p, base.getDataSize());
+ // first_channel is what channel to start copying from
+ // dest is what channel to copy to. first_channel comes from the
+ // argument, dest always starts writing at channel zero.
+ for (S32 comp = first_channel, dest = 0; comp < first_channel + channels; comp++, dest++)
+ {
+ llassert(image->comps[comp].data);
+ if (image->comps[comp].data)
+ {
+ S32 offset = dest;
+ for (S32 y = (height - 1); y >= 0; y--)
+ {
+ for (S32 x = 0; x < width; x++)
+ {
+ rawp[offset] = image->comps[comp].data[y*comp_width + x];
+ offset += channels;
+ }
+ }
+ }
+ else // Some rare OpenJPEG versions have this bug.
+ {
+ LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed! (OpenJPEG bug)" << LL_ENDL;
+ // [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3
+ base.decodeFailed();
+ // [SL:KB]
+ }
+ }
- /* decode the stream and fill the image structure */
- bool fSuccess = opj_read_header(opj_stream_p, opj_decoder_p, &image) &&
- opj_decode(opj_decoder_p, opj_stream_p, image) &&
- opj_end_decompress(opj_decoder_p, opj_stream_p);
+ base.setDiscardLevel(f);
- /* close the byte stream */
- opj_stream_destroy(opj_stream_p);
-
- /* free remaining structures */
- opj_destroy_codec(opj_decoder_p);
-#else
- /* get a decoder handle */
- dinfo = opj_create_decompress(CODEC_J2K);
-
- /* catch events using our callbacks and give a local context */
- opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
-
- /* setup the decoder decoding parameters using user parameters */
- opj_setup_decoder(dinfo, ¶meters);
-
- /* open a byte stream */
- cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize());
-
- /* decode the stream and fill the image structure */
- image = opj_decode(dinfo, cio);
-
- /* close the byte stream */
- opj_cio_close(cio);
-
- /* free remaining structures */
- if(dinfo)
- {
- opj_destroy_decompress(dinfo);
- }
-#endif
-// [/SL:KB]
-
- // The image decode failed if the return was NULL or the component
- // count was zero. The latter is just a sanity check before we
- // dereference the array.
-// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3
-#ifdef OPENJPEG2
- if ( (!fSuccess) || (!image) || (!image->numcomps) )
-#else
- if(!image || !image->numcomps)
-#endif
-// [/SL:KB]
- {
- LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL;
- if (image)
- {
- opj_image_destroy(image);
- }
-
-// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3
- base.decodeFailed();
-// [SL:KB]
- return true; // done
- }
-
- // sometimes we get bad data out of the cache - check to see if the decode succeeded
-// for (S32 i = 0; i < image->numcomps; i++)
-// {
-// if (image->comps[i].factor != base.getRawDiscardLevel())
-// {
-// // if we didn't get the discard level we're expecting, fail
-//
-//// [SN:SG] - Patch: Import-MiscOpenJPEG
-// LL_WARNS("Texture") << "Expected discard level not reached!" << LL_ENDL;
-// base.decodeFailed();
-//// [SN:SG]
-//// base.mDecoding = false;
-// return true;
-// }
-// }
-
- if(image->numcomps <= first_channel)
- {
- LL_WARNS() << "trying to decode more channels than are present in image: numcomps: " << image->numcomps << " first_channel: " << first_channel << LL_ENDL;
- if (image)
- {
- opj_image_destroy(image);
- }
-
-// [SN:SG] - Patch: Import-MiscOpenJPEG
- base.decodeFailed();
-// [SN:SG]
-
- return true;
- }
-
- // Copy image data into our raw image format (instead of the separate channel format
-
- S32 img_components = image->numcomps;
- S32 channels = img_components - first_channel;
- if( channels > max_channel_count )
- channels = max_channel_count;
-
- // Component buffers are allocated in an image width by height buffer.
- // The image placed in that buffer is ceil(width/2^factor) by
- // ceil(height/2^factor) and if the factor isn't zero it will be at the
- // top left of the buffer with black filled in the rest of the pixels.
- // It is integer math so the formula is written in ceildivpo2.
- // (Assuming all the components have the same width, height and
- // factor.)
- S32 comp_width = image->comps[0].w;
- S32 f=image->comps[0].factor;
- S32 width = ceildivpow2(image->x1 - image->x0, f);
- S32 height = ceildivpow2(image->y1 - image->y0, f);
- raw_image.resize(width, height, channels);
- U8 *rawp = raw_image.getData();
-
- // Port fix for MAINT-4327/MAINT-6584 to OpenJPEG decoder
- if (!rawp)
- {
- base.setLastError("Memory error");
- base.decodeFailed();
- opj_image_destroy(image);
- return true; // done
- }
- //
-
- // first_channel is what channel to start copying from
- // dest is what channel to copy to. first_channel comes from the
- // argument, dest always starts writing at channel zero.
- for (S32 comp = first_channel, dest=0; comp < first_channel + channels;
- comp++, dest++)
- {
- if (image->comps[comp].data)
- {
- S32 offset = dest;
- for (S32 y = (height - 1); y >= 0; y--)
- {
- for (S32 x = 0; x < width; x++)
- {
- rawp[offset] = image->comps[comp].data[y*comp_width + x];
- offset += channels;
- }
- }
- }
- else // Some rare OpenJPEG versions have this bug.
- {
- LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL;
- opj_image_destroy(image);
-
-// [SN:SG] - Patch: Import-MiscOpenJPEG
- base.decodeFailed();
-// [SN:SG]
- return true; // done
- }
- }
-
- /* free image data structure */
- opj_image_destroy(image);
-
- return true; // done
+ return true; // done
}
bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible)
{
- const S32 MAX_COMPS = 5;
- opj_cparameters_t parameters; /* compression parameters */
- opj_event_mgr_t event_mgr; /* event manager */
-
-
- /*
- configure the event callbacks (not required)
- setting of each callback is optional
- */
- memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
- event_mgr.error_handler = error_callback;
- event_mgr.warning_handler = warning_callback;
- event_mgr.info_handler = info_callback;
-
- /* set encoding parameters to default values */
- opj_set_default_encoder_parameters(¶meters);
- parameters.cod_format = 0;
- parameters.cp_disto_alloc = 1;
-
- if (reversible)
- {
- parameters.tcp_numlayers = 1;
- parameters.tcp_rates[0] = 0.0f;
- }
- else
- {
- parameters.tcp_numlayers = 5;
- parameters.tcp_rates[0] = 1920.0f;
- parameters.tcp_rates[1] = 480.0f;
- parameters.tcp_rates[2] = 120.0f;
- parameters.tcp_rates[3] = 30.0f;
- parameters.tcp_rates[4] = 10.0f;
- parameters.irreversible = 1;
- if (raw_image.getComponents() >= 3)
- {
- parameters.tcp_mct = 1;
- }
- }
-
- if (!comment_text)
- {
- parameters.cp_comment = (char *) "";
- }
- else
- {
- // Awful hacky cast, too lazy to copy right now.
- parameters.cp_comment = (char *) comment_text;
- }
-
- //
- // Fill in the source image from our raw image
- //
-// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3
-#ifdef OPENJPEG2
- OPJ_COLOR_SPACE color_space = OPJ_CLRSPC_SRGB;
-#else
- OPJ_COLOR_SPACE color_space = CLRSPC_SRGB;
-#endif
-// [/SL:KB]
- opj_image_cmptparm_t cmptparm[MAX_COMPS];
- opj_image_t * image = NULL;
- S32 numcomps = raw_image.getComponents();
- S32 width = raw_image.getWidth();
- S32 height = raw_image.getHeight();
-
- memset(&cmptparm[0], 0, MAX_COMPS * sizeof(opj_image_cmptparm_t));
- for(S32 c = 0; c < numcomps; c++) {
- cmptparm[c].prec = 8;
- cmptparm[c].bpp = 8;
- cmptparm[c].sgnd = 0;
- cmptparm[c].dx = parameters.subsampling_dx;
- cmptparm[c].dy = parameters.subsampling_dy;
- cmptparm[c].w = width;
- cmptparm[c].h = height;
- }
-
- /* create the image */
- image = opj_image_create(numcomps, &cmptparm[0], color_space);
-
- image->x1 = width;
- image->y1 = height;
-
- S32 i = 0;
- const U8 *src_datap = raw_image.getData();
- for (S32 y = height - 1; y >= 0; y--)
- {
- for (S32 x = 0; x < width; x++)
- {
- const U8 *pixel = src_datap + (y*width + x) * numcomps;
- for (S32 c = 0; c < numcomps; c++)
- {
- image->comps[c].data[i] = *pixel;
- pixel++;
- }
- i++;
- }
- }
-
-
-
- /* encode the destination image */
- /* ---------------------------- */
-
-// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3
-#ifdef OPENJPEG2
- /* get a J2K compressor handle */
- opj_codec_t* opj_encoder_p = opj_create_compress(OPJ_CODEC_J2K);
-
- /* catch events using our callbacks and give a local context */
- opj_set_error_handler(opj_encoder_p, error_callback, 0);
- opj_set_warning_handler(opj_encoder_p, warning_callback, 0);
- opj_set_info_handler(opj_encoder_p, info_callback, 0);
-
- /* setup the encoder parameters using the current image and using user parameters */
- bool fSuccess = opj_setup_encoder(opj_encoder_p, ¶meters, image);
- if (!fSuccess)
- {
- opj_destroy_codec(opj_encoder_p);
- opj_image_destroy(image);
- LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL;
- return false;
- }
-
- /* open a byte stream for writing */
- /* allocate memory for all tiles */
- LLJp2StreamWriter streamWriter(&base);
- opj_stream_t* opj_stream_p = opj_stream_default_create(OPJ_STREAM_WRITE);
- opj_stream_set_write_function(opj_stream_p, LLJp2StreamWriter::writeStream);
- opj_stream_set_skip_function(opj_stream_p, LLJp2StreamWriter::skipStream);
- opj_stream_set_seek_function(opj_stream_p, LLJp2StreamWriter::seekStream);
- opj_stream_set_user_data(opj_stream_p, &streamWriter, nullptr);
- opj_stream_set_user_data_length(opj_stream_p, raw_image.getDataSize());
-
- /* encode the image */
- fSuccess = opj_start_compress(opj_encoder_p, image, opj_stream_p) &&
- opj_encode(opj_encoder_p, opj_stream_p) &&
- opj_end_compress(opj_encoder_p, opj_stream_p);
- if (!fSuccess)
- {
- opj_stream_destroy(opj_stream_p);
- opj_destroy_codec(opj_encoder_p);
- opj_image_destroy(image);
- LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL;
- return false;
- }
-
- base.updateData(); // set width, height
-
- /* close and free the byte stream */
- opj_stream_destroy(opj_stream_p);
-
- /* free remaining compression structures */
- opj_destroy_codec(opj_encoder_p);
-#else
- int codestream_length;
- opj_cio_t *cio = NULL;
-
- /* get a J2K compressor handle */
- opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
-
- /* catch events using our callbacks and give a local context */
- opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
-
- /* setup the encoder parameters using the current image and using user parameters */
- opj_setup_encoder(cinfo, ¶meters, image);
-
- /* open a byte stream for writing */
- /* allocate memory for all tiles */
- cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
-
- /* encode the image */
- bool bSuccess = opj_encode(cinfo, cio, image, NULL);
- if (!bSuccess)
- {
- opj_cio_close(cio);
- LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL;
- return false;
- }
- codestream_length = cio_tell(cio);
-
- base.copyData(cio->buffer, codestream_length);
- base.updateData(); // set width, height
-
- /* close and free the byte stream */
- opj_cio_close(cio);
-
- /* free remaining compression structures */
- opj_destroy_compress(cinfo);
-
-
- /* free user parameters structure */
- if(parameters.cp_matrice) free(parameters.cp_matrice);
-#endif
- // [/SL:KB]
-
- /* free image data */
- opj_image_destroy(image);
- return true;
-}
-
-inline S32 extractLong4( U8 const *aBuffer, int nOffset )
-{
- S32 ret = aBuffer[ nOffset ] << 24;
- ret += aBuffer[ nOffset + 1 ] << 16;
- ret += aBuffer[ nOffset + 2 ] << 8;
- ret += aBuffer[ nOffset + 3 ];
- return ret;
-}
-
-inline S32 extractShort2( U8 const *aBuffer, int nOffset )
-{
- S32 ret = aBuffer[ nOffset ] << 8;
- ret += aBuffer[ nOffset + 1 ];
-
- return ret;
-}
-
-inline bool isSOC( U8 const *aBuffer )
-{
- return aBuffer[ 0 ] == 0xFF && aBuffer[ 1 ] == 0x4F;
-}
-
-inline bool isSIZ( U8 const *aBuffer )
-{
- return aBuffer[ 0 ] == 0xFF && aBuffer[ 1 ] == 0x51;
-}
-
-bool getMetadataFast( LLImageJ2C &aImage, S32 &aW, S32 &aH, S32 &aComps )
-{
- const int J2K_HDR_LEN( 42 );
- const int J2K_HDR_X1( 8 );
- const int J2K_HDR_Y1( 12 );
- const int J2K_HDR_X0( 16 );
- const int J2K_HDR_Y0( 20 );
- const int J2K_HDR_NUMCOMPS( 40 );
-
- if( aImage.getDataSize() < J2K_HDR_LEN )
- return false;
-
- U8 const* pBuffer = aImage.getData();
-
- if( !isSOC( pBuffer ) || !isSIZ( pBuffer+2 ) )
- return false;
-
- S32 x1 = extractLong4( pBuffer, J2K_HDR_X1 );
- S32 y1 = extractLong4( pBuffer, J2K_HDR_Y1 );
- S32 x0 = extractLong4( pBuffer, J2K_HDR_X0 );
- S32 y0 = extractLong4( pBuffer, J2K_HDR_Y0 );
- S32 numComps = extractShort2( pBuffer, J2K_HDR_NUMCOMPS );
-
- aComps = numComps;
- aW = x1 - x0;
- aH = y1 - y0;
-
- return true;
+ JPEG2KEncode encode(comment_text, reversible);
+ bool encoded = encode.encode(raw_image, base);
+ if (encoded)
+ {
+ LL_WARNS() << "Openjpeg encoding implementation isn't complete, returning false" << LL_ENDL;
+ }
+ return encoded;
+ //return false;
}
bool LLImageJ2COJ::getMetadata(LLImageJ2C &base)
{
- //
- // FIXME: We get metadata by decoding the ENTIRE image.
- //
+ JPEG2KDecode decode(0);
- // Update the raw discard level
- base.updateRawDiscardLevel();
+ S32 width = 0;
+ S32 height = 0;
+ S32 components = 0;
+ S32 discard_level = 0;
- S32 width(0);
- S32 height(0);
- S32 img_components(0);
+ U32 dataSize = base.getDataSize();
+ U8* data = base.getData();
+ bool header_read = decode.readHeader(data, dataSize, width, height, components, discard_level);
+ if (!header_read)
+ {
+ return false;
+ }
- if ( getMetadataFast( base, width, height, img_components ) )
- {
- base.setSize(width, height, img_components);
- return true;
- }
-
- // Do it the old and slow way, decode the image with openjpeg
-
- opj_dparameters_t parameters; /* decompression parameters */
- opj_event_mgr_t event_mgr; /* event manager */
- opj_image_t *image = NULL;
-
-#ifndef OPENJPEG2
- opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */
- opj_cio_t *cio = NULL;
-#endif
-
- /* configure the event callbacks (not required) */
- memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
- event_mgr.error_handler = error_callback;
- event_mgr.warning_handler = warning_callback;
- event_mgr.info_handler = info_callback;
-
- /* set decoding parameters to default values */
- opj_set_default_decoder_parameters(¶meters);
-
- // Only decode what's required to get the size data.
-#ifndef OPENJPEG2
- parameters.cp_limit_decoding=LIMIT_TO_MAIN_HEADER;
-#endif
-
- //parameters.cp_reduce = mRawDiscardLevel;
-
- /* decode the code-stream */
- /* ---------------------- */
-
- /* JPEG-2000 codestream */
-
-// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3
-#ifdef OPENJPEG2
- /* get a decoder handle */
- opj_codec_t* opj_decoder_p = opj_create_decompress(OPJ_CODEC_J2K);
-
- /* catch events using our callbacks and give a local context */
- opj_set_error_handler(opj_decoder_p, error_callback, 0);
- opj_set_warning_handler(opj_decoder_p, warning_callback, 0);
- opj_set_info_handler(opj_decoder_p, info_callback, 0);
-
- /* setup the decoder decoding parameters using user parameters */
- bool fSuccess = opj_setup_decoder(opj_decoder_p, ¶meters);
- if (!fSuccess)
- {
- opj_destroy_codec(opj_decoder_p);
- LL_WARNS() << "ERROR -> getMetadata: failed to decode image!" << LL_ENDL;
- return false;
- }
-
- /* open a byte stream */
- LLJp2StreamReader streamReader(&base);
- opj_stream_t* opj_stream_p = opj_stream_default_create(OPJ_STREAM_READ);
- opj_stream_set_read_function(opj_stream_p, LLJp2StreamReader::readStream);
- opj_stream_set_skip_function(opj_stream_p, LLJp2StreamReader::skipStream);
- opj_stream_set_seek_function(opj_stream_p, LLJp2StreamReader::seekStream);
- opj_stream_set_user_data(opj_stream_p, &streamReader, nullptr);
- opj_stream_set_user_data_length(opj_stream_p, base.getDataSize());
-
- /* decode the stream and fill the image structure */
- fSuccess = opj_read_header(opj_stream_p, opj_decoder_p, &image);
- if (!fSuccess)
- {
- opj_stream_destroy(opj_stream_p);
- opj_destroy_codec(opj_decoder_p);
- LL_WARNS() << "ERROR -> getMetadata: failed to decode image!" << LL_ENDL;
- return false;
- }
-
- /* close the byte stream */
- opj_stream_destroy(opj_stream_p);
-
- /* free remaining structures */
- opj_destroy_codec(opj_decoder_p);
-#else
- /* get a decoder handle */
- dinfo = opj_create_decompress(CODEC_J2K);
-
- /* catch events using our callbacks and give a local context */
- opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
-
- /* setup the decoder decoding parameters using user parameters */
- opj_setup_decoder(dinfo, ¶meters);
-
- /* open a byte stream */
- cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize());
-
- /* decode the stream and fill the image structure */
- image = opj_decode(dinfo, cio);
-
- /* close the byte stream */
- opj_cio_close(cio);
-
- /* free remaining structures */
- if(dinfo)
- {
- opj_destroy_decompress(dinfo);
- }
-#endif
-// [/SL:KB]
-
- if(!image)
- {
- LL_WARNS() << "ERROR -> getMetadata: failed to decode image!" << LL_ENDL;
- return false;
- }
-
- // Copy image data into our raw image format (instead of the separate channel format
-
- img_components = image->numcomps;
- width = image->x1 - image->x0;
- height = image->y1 - image->y0;
-
- base.setSize(width, height, img_components);
-
- /* free image data structure */
- opj_image_destroy(image);
- return true;
+ base.mDiscardLevel = discard_level;
+ base.setSize(width, height, components);
+ return true;
}
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 9e02b7de9c..07ae5a1001 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2414,13 +2414,12 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL;
return false;
}
-// Add non-allocating variants of of unpackVolumeFaces
return unpackVolumeFacesInternal(mdl);
}
bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size)
{
- //input stream is now pointing at a zlib compressed block of LLSD
+ //input data is now pointing at a zlib compressed block of LLSD
//decompress block
LLSD mdl;
U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, in_data, size);
@@ -2434,7 +2433,6 @@ bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size)
bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
{
-//
{
U32 face_count = mdl.size();
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index a49990ff34..e3c8f0eed6 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -1117,14 +1117,12 @@ protected:
BOOL generate();
void createVolumeFaces();
public:
- virtual bool unpackVolumeFaces(std::istream& is, S32 size);
-// Add non-allocating variants of of unpackVolumeFaces
+ bool unpackVolumeFaces(std::istream& is, S32 size);
bool unpackVolumeFaces(U8* in_data, S32 size);
private:
bool unpackVolumeFacesInternal(const LLSD& mdl);
public:
-//
virtual void setMeshAssetLoaded(BOOL loaded);
virtual BOOL isMeshAssetLoaded();
diff --git a/indra/llmessage/lldatapacker.cpp b/indra/llmessage/lldatapacker.cpp
index 64cd1c2ad0..9f7768f78e 100644
--- a/indra/llmessage/lldatapacker.cpp
+++ b/indra/llmessage/lldatapacker.cpp
@@ -754,14 +754,13 @@ BOOL LLDataPackerAsciiBuffer::packString(const std::string& value, const char *n
BOOL LLDataPackerAsciiBuffer::unpackString(std::string& value, const char *name)
{
- BOOL success = TRUE;
char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/
if (!getValueStr(name, valuestr, DP_BUFSIZE)) // NULL terminated
{
return FALSE;
}
value = valuestr;
- return success;
+ return TRUE;
}
diff --git a/indra/llmessage/tests/llcoproceduremanager_test.cpp b/indra/llmessage/tests/llcoproceduremanager_test.cpp
index 78424a28c8..d6481d4eea 100644
--- a/indra/llmessage/tests/llcoproceduremanager_test.cpp
+++ b/indra/llmessage/tests/llcoproceduremanager_test.cpp
@@ -92,7 +92,7 @@ namespace tut
Sync sync;
int foo = 0;
LLCoprocedureManager::instance().initializePool("PoolName");
- LLUUID queueId = LLCoprocedureManager::instance().enqueueCoprocedure("PoolName", "ProcName",
+ LLCoprocedureManager::instance().enqueueCoprocedure("PoolName", "ProcName",
[&foo, &sync] (LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t & ptr, const LLUUID & id) {
sync.bump();
foo = 1;
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 39b81244be..f56d4f18e9 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -1456,6 +1456,16 @@ LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin):
fromLLSD(skin);
}
+LLMeshSkinInfo::LLMeshSkinInfo(const LLUUID& mesh_id, LLSD& skin) :
+ mMeshID(mesh_id),
+ mPelvisOffset(0.0),
+ mLockScaleIfJointPosition(false),
+ mInvalidJointsScrubbed(false),
+ mJointNumsInitialized(false)
+{
+ fromLLSD(skin);
+}
+
void LLMeshSkinInfo::fromLLSD(LLSD& skin)
{
if (skin.has("joint_names"))
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index 7461a38ac9..689172dda3 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -43,12 +43,13 @@ class domMesh;
#define MAX_MODEL_FACES 8
LL_ALIGN_PREFIX(16)
-class LLMeshSkinInfo
+class LLMeshSkinInfo : public LLRefCount
{
LL_ALIGN_NEW
public:
LLMeshSkinInfo();
LLMeshSkinInfo(LLSD& data);
+ LLMeshSkinInfo(const LLUUID& mesh_id, LLSD& data);
void fromLLSD(LLSD& data);
LLSD asLLSD(bool include_joints, bool lock_scale_if_joint_position) const;
void updateHash();
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 15a9c8bb0a..5a68c00c33 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -515,6 +515,17 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
}
};
+LLFlatListView::~LLFlatListView()
+{
+ for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it)
+ {
+ mItemsPanel->removeChild((*it)->first);
+ (*it)->first->die();
+ delete *it;
+ }
+ mItemPairs.clear();
+}
+
// virtual
void LLFlatListView::draw()
{
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index c2ba8f2f02..7fe5d90876 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -307,6 +307,7 @@ public:
virtual S32 notify(const LLSD& info) ;
+ virtual ~LLFlatListView();
protected:
/** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index c7b4d08b3b..a7086e09de 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -163,6 +163,7 @@ LLFolderView::LLFolderView(const Params& p)
: LLFolderViewFolder(p),
mScrollContainer( NULL ),
mPopupMenuHandle(),
+ mMenuFileName(p.options_menu),
mAllowMultiSelect(p.allow_multiselect),
mAllowDrag(p.allow_drag),
mShowEmptyMessage(p.show_empty_message),
@@ -186,6 +187,7 @@ LLFolderView::LLFolderView(const Params& p)
mDragStartY(0),
// [/SL:KB]
mCallbackRegistrar(NULL),
+ mEnableRegistrar(NULL),
mUseEllipses(p.use_ellipses),
mDraggingOverItem(NULL),
mStatusTextBox(NULL),
@@ -248,17 +250,6 @@ LLFolderView::LLFolderView(const Params& p)
mStatusTextBox->setFollowsTop();
addChild(mStatusTextBox);
-
- // make the popup menu available
- llassert(LLMenuGL::sMenuContainer != NULL);
- LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile(p.options_menu, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
- if (!menu)
- {
- menu = LLUICtrlFactory::getDefaultWidget("inventory_menu");
- }
- menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
- mPopupMenuHandle = menu->getHandle();
-
mViewModelItem->openItem();
mAreChildrenInited = true; // root folder is a special case due to not being loaded normally, assume that it's inited.
@@ -280,6 +271,7 @@ LLFolderView::~LLFolderView( void )
mStatusTextBox = NULL;
if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
+ mPopupMenuHandle.markDead();
mAutoOpenItems.removeAllNodes();
clearSelection();
@@ -1534,22 +1526,56 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL;
S32 count = mSelectedItems.size();
- LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
+ LLMenuGL* menu = static_cast(mPopupMenuHandle.get());
+ if (!menu)
+ {
+ if (mCallbackRegistrar)
+ {
+ mCallbackRegistrar->pushScope();
+ }
+ if (mEnableRegistrar)
+ {
+ mEnableRegistrar->pushScope();
+ }
+ llassert(LLMenuGL::sMenuContainer != NULL);
+ menu = LLUICtrlFactory::getInstance()->createFromFile(mMenuFileName, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
+ if (!menu)
+ {
+ menu = LLUICtrlFactory::getDefaultWidget("inventory_menu");
+ }
+ menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor"));
+ mPopupMenuHandle = menu->getHandle();
+ if (mEnableRegistrar)
+ {
+ mEnableRegistrar->popScope();
+ }
+ if (mCallbackRegistrar)
+ {
+ mCallbackRegistrar->popScope();
+ }
+ }
bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected();
- if ((handled
- && ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible
- && menu ) &&
+ if (menu && (handled
+ && ( count > 0 && (hasVisibleChildren()) )) && // show menu only if selected items are visible
!hide_folder_menu)
{
if (mCallbackRegistrar)
{
mCallbackRegistrar->pushScope();
}
+ if (mEnableRegistrar)
+ {
+ mEnableRegistrar->pushScope();
+ }
updateMenuOptions(menu);
menu->updateParent(LLMenuGL::sMenuContainer);
LLMenuGL::showPopup(this, menu, x, y);
+ if (mEnableRegistrar)
+ {
+ mEnableRegistrar->popScope();
+ }
if (mCallbackRegistrar)
{
mCallbackRegistrar->popScope();
@@ -1627,7 +1653,7 @@ void LLFolderView::deleteAllChildren()
{
closeRenamer();
if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die();
- mPopupMenuHandle = LLHandle();
+ mPopupMenuHandle.markDead();
mScrollContainer = NULL;
mRenameItem = NULL;
mRenamer = NULL;
diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index 491028556c..e6d6d76ad9 100644
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -240,6 +240,7 @@ public:
bool showItemLinkOverlays() { return mShowItemLinkOverlays; }
void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; }
+ void setEnableRegistrar(LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* registrar) { mEnableRegistrar = registrar; }
LLPanel* getParentPanel() { return mParentPanel.get(); }
// DEBUG only
@@ -277,6 +278,7 @@ protected:
protected:
LLHandle mPopupMenuHandle;
+ std::string mMenuFileName;
selected_items_t mSelectedItems;
bool mKeyboardSelection,
@@ -336,6 +338,7 @@ protected:
LLFolderViewItem* mDraggingOverItem; // See EXT-719
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar;
public:
static F32 sAutoOpenTime;
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index 4b8a31a07e..31d28a5257 100644
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -432,21 +432,15 @@ public:
mFilter(filter)
{}
- virtual ~LLFolderViewModel()
- {
- delete mSorter;
- mSorter = NULL;
- delete mFilter;
- mFilter = NULL;
- }
+ virtual ~LLFolderViewModel() {}
virtual SortType& getSorter() { return *mSorter; }
virtual const SortType& getSorter() const { return *mSorter; }
- virtual void setSorter(const SortType& sorter) { mSorter = new SortType(sorter); requestSortAll(); }
+ virtual void setSorter(const SortType& sorter) { mSorter.reset(new SortType(sorter)); requestSortAll(); }
virtual FilterType& getFilter() { return *mFilter; }
virtual const FilterType& getFilter() const { return *mFilter; }
- virtual void setFilter(const FilterType& filter) { mFilter = new FilterType(filter); }
+ virtual void setFilter(const FilterType& filter) { mFilter.reset(new FilterType(filter)); }
// By default, we assume the content is available. If a network fetch mechanism is implemented for the model,
// this method needs to be overloaded and return the relevant fetch status.
@@ -484,8 +478,8 @@ public:
}
protected:
- SortType* mSorter;
- FilterType* mFilter;
+ std::unique_ptr mSorter;
+ std::unique_ptr mFilter;
};
#endif // LLFOLDERVIEWMODEL_H
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 63482df996..86a26df6ad 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -164,8 +164,6 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mHighlightColor(p.highlight_color()),
mPreeditBgColor(p.preedit_bg_color()),
mGLFont(p.font),
- // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL
- mDelayedInit(false),
mContextMenuHandle(),
mAutoreplaceCallback()
{
@@ -212,24 +210,6 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
setPrevalidateInput(p.prevalidate_input_callback());
setPrevalidate(p.prevalidate_callback());
-
- // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL
- if (LLMenuGL::sMenuContainer)
- {
- //
- llassert(LLMenuGL::sMenuContainer != NULL);
- LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile
- ("menu_text_editor.xml",
- LLMenuGL::sMenuContainer,
- LLMenuHolderGL::child_registry_t::instance());
- setContextMenu(menu);
- // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL
- }
- else
- {
- mDelayedInit = true;
- }
- //
}
LLLineEditor::~LLLineEditor()
@@ -244,9 +224,6 @@ LLLineEditor::~LLLineEditor()
}
setContextMenu(NULL);
- // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL
- mDelayedInit = false;
-
// calls onCommit() while LLLineEditor still valid
gFocusMgr.releaseFocusIfNeeded( this );
}
@@ -1660,10 +1637,7 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask )
KEY_SHIFT != key &&
KEY_CONTROL != key &&
KEY_ALT != key &&
- // Capslock deselecting text
- //KEY_CAPSLOCK )
KEY_CAPSLOCK != key)
- //
{
deselect();
}
@@ -2759,24 +2733,16 @@ LLWString LLLineEditor::getConvertedText() const
void LLLineEditor::showContextMenu(S32 x, S32 y, bool set_cursor_pos)
//
{
- //LLContextMenu* menu = static_cast(mContextMenuHandle.get());
- // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL
- LLContextMenu* menu = NULL;
- if (mDelayedInit && !mContextMenuHandle.get())
+ LLContextMenu* menu = static_cast(mContextMenuHandle.get());
+ if (!menu)
{
llassert(LLMenuGL::sMenuContainer != NULL);
- menu = LLUICtrlFactory::instance().createFromFile
+ menu = LLUICtrlFactory::createFromFile
("menu_text_editor.xml",
- LLMenuGL::sMenuContainer,
- LLMenuHolderGL::child_registry_t::instance());
+ LLMenuGL::sMenuContainer,
+ LLMenuHolderGL::child_registry_t::instance());
setContextMenu(menu);
}
- else
- {
- menu = static_cast(mContextMenuHandle.get());
- }
- mDelayedInit = false;
- //
if (menu)
{
@@ -2827,8 +2793,6 @@ void LLLineEditor::setContextMenu(LLContextMenu* new_context_menu)
{
menu->die();
mContextMenuHandle.markDead();
- // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL
- mDelayedInit = false;
}
if (new_context_menu)
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index 2387cc1478..a7b4029d32 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -422,9 +422,6 @@ protected:
LLHandle mContextMenuHandle;
- // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL
- bool mDelayedInit;
-
private:
// Instances that by default point to the statics but can be overidden in XML.
LLPointer mBgImage;
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index d0d1db88dd..18b789da24 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -4125,12 +4125,7 @@ void LLTearOffMenu::closeTearOff()
LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p)
: LLMenuItemGL(p)
- //mBranch( p.branch()->getHandle() ) // Context menu memory leak fix by Rye Mutt
{
- // Context menu memory leak fix by Rye Mutt
- //mBranch.get()->hide();
- //mBranch.get()->setParentMenuItem(this);
- //
LLContextMenu* branch = static_cast(p.branch);
if (branch)
{
@@ -4140,7 +4135,6 @@ LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p)
}
}
-// Context menu memory leak fix by Rye Mutt
LLContextMenuBranch::~LLContextMenuBranch()
{
if (mBranch.get())
@@ -4148,30 +4142,21 @@ LLContextMenuBranch::~LLContextMenuBranch()
mBranch.get()->die();
}
}
-//
// called to rebuild the draw label
void LLContextMenuBranch::buildDrawLabel( void )
{
- // Context menu memory leak fix by Rye Mutt
auto menu = getBranch();
if (menu)
- //
{
// default enablement is this -- if any of the subitems are
// enabled, this item is enabled. JC
- // Context menu memory leak fix by Rye Mutt
- //U32 sub_count = mBranch.get()->getItemCount();
U32 sub_count = menu->getItemCount();
- //
U32 i;
BOOL any_enabled = FALSE;
for (i = 0; i < sub_count; i++)
{
- // Context menu memory leak fix by Rye Mutt
- //LLMenuItemGL* item = mBranch.get()->getItem(i);
LLMenuItemGL* item = menu->getItem(i);
- //
item->buildDrawLabel();
if (item->getEnabled() && !item->getDrawTextDisabled() )
{
@@ -4193,28 +4178,18 @@ void LLContextMenuBranch::buildDrawLabel( void )
void LLContextMenuBranch::showSubMenu()
{
- // Context menu memory leak fix by Rye Mutt
- //LLMenuItemGL* menu_item = mBranch.get()->getParentMenuItem();
- //if (menu_item != NULL && menu_item->getVisible())
- //{
- // S32 center_x;
- // S32 center_y;
- // localPointToScreen(getRect().getWidth(), getRect().getHeight() , ¢er_x, ¢er_y);
- // mBranch.get()->show(center_x, center_y);
- //}
auto menu = getBranch();
- if (menu)
+ if(menu)
{
LLMenuItemGL* menu_item = menu->getParentMenuItem();
if (menu_item != NULL && menu_item->getVisible())
{
S32 center_x;
S32 center_y;
- localPointToScreen(getRect().getWidth(), getRect().getHeight() , ¢er_x, ¢er_y);
+ localPointToScreen(getRect().getWidth(), getRect().getHeight(), ¢er_x, ¢er_y);
menu->show(center_x, center_y);
}
}
- //
}
// onCommit() - do the primary funcationality of the menu item.
@@ -4227,15 +4202,6 @@ void LLContextMenuBranch::setHighlight( BOOL highlight )
{
if (highlight == getHighlight()) return;
LLMenuItemGL::setHighlight(highlight);
- // Context menu memory leak fix by Rye Mutt
- //if( highlight )
- //{
- // showSubMenu();
- //}
- //else
- //{
- // mBranch.get()->hide();
- //}
auto menu = getBranch();
if (menu)
{
@@ -4248,7 +4214,6 @@ void LLContextMenuBranch::setHighlight( BOOL highlight )
menu->hide();
}
}
- //
}
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 73600f01f3..760d3eff6c 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -754,11 +754,7 @@ public:
LLContextMenuBranch(const Params&);
- // Context menu memory leak fix by Rye Mutt
- //virtual ~LLContextMenuBranch()
- //{}
virtual ~LLContextMenuBranch();
- //
// called to rebuild the draw label
virtual void buildDrawLabel( void );
diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp
index f89064d59a..604d246f12 100644
--- a/indra/llui/llmultislider.cpp
+++ b/indra/llui/llmultislider.cpp
@@ -92,7 +92,7 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)
mMouseDownSignal(NULL),
mMouseUpSignal(NULL)
{
- mValue.emptyMap();
+ mValue = LLSD::emptyMap();
mCurSlider = LLStringUtil::null;
if (mOrientation == HORIZONTAL)
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index bc1aa24d25..35d5c44f9b 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -201,7 +201,6 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mHighlightedItem(-1),
mBorder(NULL),
mSortCallback(NULL),
- mPopupMenu(NULL),
mCommentTextView(NULL),
mNumDynamicWidthColumns(0),
mTotalStaticColumnWidth(0),
@@ -412,6 +411,13 @@ LLScrollListCtrl::~LLScrollListCtrl()
mItemList.clear();
clearColumns(); //clears columns and deletes headers
delete mIsFriendSignal;
+
+ auto menu = mPopupMenuHandle.get();
+ if (menu)
+ {
+ menu->die();
+ mPopupMenuHandle.markDead();
+ }
}
@@ -1423,20 +1429,20 @@ LLScrollListItem* LLScrollListCtrl::getItemByLabel(const std::string& label, BOO
}
-BOOL LLScrollListCtrl::selectItemByPrefix(const std::string& target, BOOL case_sensitive)
+BOOL LLScrollListCtrl::selectItemByPrefix(const std::string& target, BOOL case_sensitive, S32 column)
{
- return selectItemByPrefix(utf8str_to_wstring(target), case_sensitive);
+ return selectItemByPrefix(utf8str_to_wstring(target), case_sensitive, column);
}
// Selects first enabled item that has a name where the name's first part matched the target string.
// Returns false if item not found.
-BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sensitive)
+BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sensitive, S32 column)
// Allow selection by substring match
{
return selectItemByStringMatch(target, true, case_sensitive);
}
-BOOL LLScrollListCtrl::selectItemByStringMatch(const LLWString& target, bool prefix_match, BOOL case_sensitive)
+BOOL LLScrollListCtrl::selectItemByStringMatch(const LLWString& target, bool prefix_match, BOOL case_sensitive, S32 column)
//
{
BOOL found = FALSE;
@@ -1452,7 +1458,7 @@ BOOL LLScrollListCtrl::selectItemByStringMatch(const LLWString& target, bool pre
{
LLScrollListItem* item = *iter;
// Only select enabled items with matching names
- LLScrollListCell* cellp = item->getColumn(getSearchColumn());
+ LLScrollListCell* cellp = item->getColumn(column == -1 ? getSearchColumn() : column);
BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE;
if (select)
{
@@ -1475,7 +1481,7 @@ BOOL LLScrollListCtrl::selectItemByStringMatch(const LLWString& target, bool pre
LLScrollListItem* item = *iter;
// Only select enabled items with matching names
- LLScrollListCell* cellp = item->getColumn(getSearchColumn());
+ LLScrollListCell* cellp = item->getColumn(column == -1 ? getSearchColumn() : column);
if (!cellp)
{
continue;
@@ -2252,17 +2258,23 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
// create the context menu from the XUI file and display it
std::string menu_name = is_group ? "menu_url_group.xml" : "menu_url_agent.xml";
- delete mPopupMenu;
- llassert(LLMenuGL::sMenuContainer != NULL);
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile(
- menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
- if (mPopupMenu)
+ auto menu = mPopupMenuHandle.get();
+ if (menu)
{
+ menu->die();
+ mPopupMenuHandle.markDead();
+ }
+ llassert(LLMenuGL::sMenuContainer != NULL);
+ menu = LLUICtrlFactory::getInstance()->createFromFile(
+ menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandle = menu->getHandle();
if (mIsFriendSignal)
{
bool isFriend = *(*mIsFriendSignal)(uuid);
- LLView* addFriendButton = mPopupMenu->getChild("add_friend");
- LLView* removeFriendButton = mPopupMenu->getChild("remove_friend");
+ LLView* addFriendButton = menu->getChild("add_friend");
+ LLView* removeFriendButton = menu->getChild("remove_friend");
if (addFriendButton && removeFriendButton)
{
@@ -2271,8 +2283,8 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
}
}
- mPopupMenu->show(x, y);
- LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ menu->show(x, y);
+ LLMenuGL::showPopup(this, menu, x, y);
return TRUE;
}
}
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 55d30ad422..30d7e54f82 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -270,12 +270,12 @@ public:
virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD());
BOOL selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 ); // FALSE if item not found
- BOOL selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE);
- BOOL selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE);
+ BOOL selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE, S32 column = -1);
+ BOOL selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE, S32 column = -1);
// Allow selection by substring match
BOOL selectItemBySubstring(const std::string& target, BOOL case_sensitive = TRUE);
BOOL selectItemBySubstring(const LLWString& target, BOOL case_sensitive = TRUE);
- BOOL selectItemByStringMatch(const LLWString& target, bool prefix_match, BOOL case_sensitive = TRUE);
+ BOOL selectItemByStringMatch(const LLWString& target, bool prefix_match, BOOL case_sensitive = TRUE, S32 column = -1);
//
LLScrollListItem* getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 );
const std::string getSelectedItemLabel(S32 column = 0) const;
@@ -565,7 +565,7 @@ private:
S32 mHighlightedItem;
class LLViewBorder* mBorder;
- LLContextMenu *mPopupMenu;
+ LLHandle mPopupMenuHandle;
LLView *mCommentTextView;
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 0a04ae36ac..ea965c83ee 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1583,12 +1583,10 @@ void LLTabContainer::selectLastTab()
void LLTabContainer::selectNextTab()
{
- // FIRE-15580: Crash fix (division by 0)
- if (mTabList.size() == 0)
- {
- return;
- }
- //
+ if (mTabList.size() == 0)
+ {
+ return;
+ }
BOOL tab_has_focus = FALSE;
if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus())
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 498dbc4a3a..aa8822a00e 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -303,6 +303,12 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
LLTextBase::~LLTextBase()
{
mSegments.clear();
+ LLContextMenu* menu = static_cast(mPopupMenuHandle.get());
+ if (menu)
+ {
+ menu->die();
+ mPopupMenuHandle.markDead();
+ }
delete mURLClickSignal;
delete mIsFriendSignal;
delete mIsObjectBlockedSignal;
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 942af90fd8..c208c0006b 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -258,7 +258,6 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mMouseDownY(0),
mTabsToNextField(p.ignore_tab),
mPrevalidateFunc(p.prevalidate_callback()),
- mContextMenu(NULL),
mShowContextMenu(p.show_context_menu),
mEnableTooltipPaste(p.enable_tooltip_paste),
mPassDelete(FALSE),
@@ -303,8 +302,13 @@ LLTextEditor::~LLTextEditor()
// Scrollbar is deleted by LLView
std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
mUndoStack.clear();
- // context menu is owned by menu holder, not us
- //delete mContextMenu;
+ // Mark the menu as dead or its retained in memory till shutdown.
+ LLContextMenu* menu = static_cast(mContextMenuHandle.get());
+ if(menu)
+ {
+ menu->die();
+ mContextMenuHandle.markDead();
+ }
}
////////////////////////////////////////////////////////////
@@ -2236,19 +2240,19 @@ void LLTextEditor::setEnabled(BOOL enabled)
void LLTextEditor::showContextMenu(S32 x, S32 y, bool set_cursor_pos)
//
{
- if (!mContextMenu)
+ LLContextMenu* menu = static_cast(mContextMenuHandle.get());
+ if (!menu)
{
llassert(LLMenuGL::sMenuContainer != NULL);
- mContextMenu = LLUICtrlFactory::instance().createFromFile("menu_text_editor.xml",
+ menu = LLUICtrlFactory::createFromFile("menu_text_editor.xml",
LLMenuGL::sMenuContainer,
LLMenuHolderGL::child_registry_t::instance());
- // FIRE-31081 defend against null this prt exception in setItemVisible found in BugSplat
- if(!mContextMenu)
- {
- LL_WARNS() << "Failed to create context menu 'menu_text_editor'" << LL_ENDL;
- return;
- }
- //
+ if(!menu)
+ {
+ LL_WARNS() << "Failed to create menu for LLTextEditor: " << getName() << LL_ENDL;
+ return;
+ }
+ mContextMenuHandle = menu->getHandle();
}
// Route menu to this class
@@ -2295,11 +2299,11 @@ void LLTextEditor::showContextMenu(S32 x, S32 y, bool set_cursor_pos)
}
}
- mContextMenu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty()));
- mContextMenu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled));
- mContextMenu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled));
- mContextMenu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled));
- mContextMenu->show(screen_x, screen_y, this);
+ menu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty()));
+ menu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled));
+ menu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled));
+ menu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled));
+ menu->show(screen_x, screen_y, this);
}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 714247c1c6..4fc837c439 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -345,7 +345,7 @@ private:
keystroke_signal_t mKeystrokeSignal;
LLTextValidate::validate_func_t mPrevalidateFunc;
- LLContextMenu* mContextMenu;
+ LLHandle mContextMenuHandle;
}; // end class LLTextEditor
// Build time optimization, generate once in .cpp file
diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp
index dcce2aa1fd..bf8c3f51e5 100644
--- a/indra/llui/lltoolbar.cpp
+++ b/indra/llui/lltoolbar.cpp
@@ -162,7 +162,12 @@ LLToolBar::LLToolBar(const LLToolBar::Params& p)
LLToolBar::~LLToolBar()
{
- delete mPopupMenuHandle.get();
+ auto menu = mPopupMenuHandle.get();
+ if (menu)
+ {
+ menu->die();
+ mPopupMenuHandle.markDead();
+ }
delete mButtonAddSignal;
delete mButtonEnterSignal;
delete mButtonLeaveSignal;
diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp
index e13cfc4aa9..c0614811e7 100644
--- a/indra/llwindow/lldxhardware.cpp
+++ b/indra/llwindow/lldxhardware.cpp
@@ -1108,7 +1108,7 @@ LLSD LLDXHardware::getDisplayInfo()
}
LCleanup:
- if (ret.emptyMap())
+ if (!ret.isMap() || (ret.size() == 0))
{
LL_INFOS() << "Failed to get data, cleaning up" << LL_ENDL;
}
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index a9ebffc09a..0c6da56cd3 100644
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -83,7 +83,7 @@ int createNSApp(int argc, const char **argv);
void setupCocoa();
bool pasteBoardAvailable();
bool copyToPBoard(const unsigned short *str, unsigned int len);
-const unsigned short *copyFromPBoard();
+unsigned short *copyFromPBoard();
CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY);
short releaseImageCursor(CursorRef ref);
short setImageCursor(CursorRef ref);
diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm
index 2a88049c5c..37baad1324 100644
--- a/indra/llwindow/llwindowmacosx-objc.mm
+++ b/indra/llwindow/llwindowmacosx-objc.mm
@@ -49,14 +49,12 @@ void setupCocoa()
if(!inited)
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- // The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents.
- // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr'
- // when init'ing the Cocoa App window.
- [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
-
- [pool release];
+ @autoreleasepool {
+ // The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents.
+ // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr'
+ // when init'ing the Cocoa App window.
+ [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
+ }
inited = true;
}
@@ -64,13 +62,13 @@ void setupCocoa()
bool copyToPBoard(const unsigned short *str, unsigned int len)
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
- NSPasteboard *pboard = [NSPasteboard generalPasteboard];
- [pboard clearContents];
-
- NSArray *contentsToPaste = [[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil];
- [pool release];
- return [pboard writeObjects:contentsToPaste];
+ @autoreleasepool {
+ NSPasteboard *pboard = [NSPasteboard generalPasteboard];
+ [pboard clearContents];
+
+ NSArray *contentsToPaste = [[[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil] autorelease];
+ return [pboard writeObjects:contentsToPaste];
+ }
}
bool pasteBoardAvailable()
@@ -79,45 +77,39 @@ bool pasteBoardAvailable()
return [[NSPasteboard generalPasteboard] canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
}
-const unsigned short *copyFromPBoard()
+unsigned short *copyFromPBoard()
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
- NSPasteboard *pboard = [NSPasteboard generalPasteboard];
- NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
- NSString *str = NULL;
- BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
- if (ok)
- {
- NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]];
- str = [objToPaste objectAtIndex:0];
- }
- NSUInteger len = [str length];
-
- // add+1 for 0-terminator.
- // unichar* temp = (unichar*)calloc([str length]+1, sizeof(unichar));
- unichar* buffer = (unichar*)calloc(len+1, sizeof(unichar));
- //
-
- [str getCharacters:buffer range:NSMakeRange(0, len)];
- [pool release];
- return buffer;
+ @autoreleasepool {
+ NSPasteboard *pboard = [NSPasteboard generalPasteboard];
+ NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
+ NSString *str = NULL;
+ BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
+ if (ok)
+ {
+ NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]];
+ str = [objToPaste objectAtIndex:0];
+ }
+ NSUInteger str_len = [str length];
+ unichar* temp = (unichar*)calloc(str_len+1, sizeof(unichar));
+ [str getCharacters:temp range:NSMakeRange(0, str_len)];
+ return temp;
+ }
}
CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY)
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- // extra retain on the NSCursor since we want it to live for the lifetime of the app.
- NSCursor *cursor =
- [[[NSCursor alloc]
- initWithImage:
- [[[NSImage alloc] initWithContentsOfFile:
- [NSString stringWithUTF8String:fullpath]
- ]autorelease]
- hotSpot:NSMakePoint(hotspotX, hotspotY)
- ]retain];
-
- [pool release];
+ NSCursor *cursor = nil;
+ @autoreleasepool {
+ // extra retain on the NSCursor since we want it to live for the lifetime of the app.
+ cursor =
+ [[[NSCursor alloc]
+ initWithImage:
+ [[[NSImage alloc] initWithContentsOfFile:
+ [NSString stringWithUTF8String:fullpath]
+ ] autorelease]
+ hotSpot:NSMakePoint(hotspotX, hotspotY)
+ ] retain];
+ }
return (CursorRef)cursor;
}
@@ -184,10 +176,10 @@ OSErr releaseImageCursor(CursorRef ref)
{
if( ref != NULL )
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSCursor *cursor = (NSCursor*)ref;
- [cursor release];
- [pool release];
+ @autoreleasepool {
+ NSCursor *cursor = (NSCursor*)ref;
+ [cursor autorelease];
+ }
}
else
{
@@ -201,10 +193,10 @@ OSErr setImageCursor(CursorRef ref)
{
if( ref != NULL )
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSCursor *cursor = (NSCursor*)ref;
- [cursor set];
- [pool release];
+ @autoreleasepool {
+ NSCursor *cursor = (NSCursor*)ref;
+ [cursor set];
+ }
}
else
{
@@ -425,24 +417,26 @@ void requestUserAttention()
long showAlert(std::string text, std::string title, int type)
{
- NSAlert *alert = [[NSAlert alloc] init];
-
- [alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]];
- [alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]];
- if (type == 0)
- {
- [alert addButtonWithTitle:@"Okay"];
- } else if (type == 1)
- {
- [alert addButtonWithTitle:@"Okay"];
- [alert addButtonWithTitle:@"Cancel"];
- } else if (type == 2)
- {
- [alert addButtonWithTitle:@"Yes"];
- [alert addButtonWithTitle:@"No"];
+ long ret = 0;
+ @autoreleasepool {
+ NSAlert *alert = [[[NSAlert alloc] init] autorelease];
+
+ [alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]];
+ [alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]];
+ if (type == 0)
+ {
+ [alert addButtonWithTitle:@"Okay"];
+ } else if (type == 1)
+ {
+ [alert addButtonWithTitle:@"Okay"];
+ [alert addButtonWithTitle:@"Cancel"];
+ } else if (type == 2)
+ {
+ [alert addButtonWithTitle:@"Yes"];
+ [alert addButtonWithTitle:@"No"];
+ }
+ ret = [alert runModal];
}
- long ret = [alert runModal];
- [alert dealloc];
if (ret == NSAlertFirstButtonReturn)
{
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 6df23fcf37..86e0814669 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -678,11 +678,11 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
if (cgl_err != kCGLNoError )
{
- LL_DEBUGS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL;
+ LL_INFOS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL;
}
else
{
- LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL;
+ LL_INFOS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL;
}
}
makeFirstResponder(mWindow, mGLView);
@@ -1266,10 +1266,13 @@ BOOL LLWindowMacOSX::isClipboardTextAvailable()
}
BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst)
-{
- //llutf16string str(copyFromPBoard());
- dst = utf16str_to_wstring(copyFromPBoard());
- LLWStringUtil::removeCRLF(dst); //
+{
+ unsigned short* pboard_data = copyFromPBoard(); // must free returned data
+ llutf16string str(pboard_data);
+ free(pboard_data);
+
+ dst = utf16str_to_wstring(str)
+ LLWStringUtil::removeCRLF(dst); // ;
if (dst != L"")
{
return true;
@@ -1301,7 +1304,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r
{
if (!mSupportedResolutions)
{
- CFArrayRef modes = CGDisplayAvailableModes(mDisplay);
+ CFArrayRef modes = CGDisplayCopyAllDisplayModes(mDisplay, nullptr);
if(modes != NULL)
{
@@ -1340,6 +1343,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r
}
}
}
+ CFRelease(modes);
}
}
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index e414195bda..49ebdd3989 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -235,6 +235,7 @@ protected:
BOOL mLanguageTextInputAllowed;
LLPreeditor* mPreeditor;
+public:
static BOOL sUseMultGL;
friend class LLWindowManager;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 2a3f28b381..b5b7b58b9b 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -2257,9 +2257,9 @@ if (WINDOWS)
set_target_properties(${VIEWER_BINARY_NAME}
PROPERTIES
# *TODO -reenable this once we get server usage sorted out
- LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /LARGEADDRESSAWARE"
- LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO /LARGEADDRESSAWARE"
- LINK_FLAGS_RELEASE "/FORCE:MULTIPLE /MAP\"secondlife-bin.MAP\" /OPT:REF /LARGEADDRESSAWARE"
+ LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /LARGEADDRESSAWARE /LTCG"
+ LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO /LARGEADDRESSAWARE /LTCG"
+ LINK_FLAGS_RELEASE "/FORCE:MULTIPLE /MAP\"secondlife-bin.MAP\" /OPT:REF /LARGEADDRESSAWARE /LTCG"
)
if(USE_PRECOMPILED_HEADERS)
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index e4727764bf..f41620d544 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -23511,6 +23511,17 @@ Change of this parameter will affect the layout of buttons in notification toast
Value
0
+ DebugSettingsHideDefault
+
+ Comment
+ Show non-default settings only in Debug Settings list
+ Persist
+ 0
+ Type
+ Boolean
+ Value
+ 0
+
FSNetMapPhantomOpacity
Comment
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
index adc2db60b6..0c398b263f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
@@ -25,6 +25,17 @@
/*[EXTRA_CODE_HERE]*/
+// Inputs
+VARYING vec3 vary_HazeColor;
+VARYING float vary_LightNormPosDot;
+
+uniform sampler2D rainbow_map;
+uniform sampler2D halo_map;
+
+uniform float moisture_level;
+uniform float droplet_radius;
+uniform float ice_level;
+
#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_data[3];
#else
@@ -35,11 +46,35 @@ out vec4 frag_data[3];
// The fragment shader for the sky
/////////////////////////////////////////////////////////////////////////
-VARYING vec3 vary_HazeColor;
+
+vec3 rainbow(float d)
+{
+ // 'Interesting' values of d are -0.75 .. -0.825, i.e. when view vec nearly opposite of sun vec
+ // Rainbox tex is mapped with REPEAT, so -.75 as tex coord is same as 0.25. -0.825 -> 0.175. etc.
+ // SL-13629
+ // Unfortunately the texture is inverted, so we need to invert the y coord, but keep the 'interesting'
+ // part within the same 0.175..0.250 range, i.e. d = (1 - d) - 1.575
+ d = clamp(-0.575 - d, 0.0, 1.0);
+
+ // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible.
+ // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate
+ // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857
+ float interior_coord = max(0.0, d - 0.25) * 4.2857;
+ d = clamp(d, 0.0, 0.25) + interior_coord;
+
+ float rad = (droplet_radius - 5.0f) / 1024.0f;
+ return pow(texture2D(rainbow_map, vec2(rad+0.5, d)).rgb, vec3(1.8)) * moisture_level;
+}
+
+vec3 halo22(float d)
+{
+ d = clamp(d, 0.1, 1.0);
+ float v = sqrt(clamp(1 - (d * d), 0, 1));
+ return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
+}
/// Soft clips the light with a gamma correction
vec3 scaleSoftClip(vec3 light);
-vec3 srgb_to_linear(vec3 c);
void main()
{
@@ -48,14 +83,18 @@ void main()
// the fragment) if the sky wouldn't show up because the clouds
// are fully opaque.
- vec3 color;
- color = vary_HazeColor;
+ vec3 color = vary_HazeColor;
+ float rel_pos_lightnorm = vary_LightNormPosDot;
+ float optic_d = rel_pos_lightnorm;
+ vec3 halo_22 = halo22(optic_d);
+ color.rgb += rainbow(optic_d);
+ color.rgb += halo_22;
color.rgb *= 2.;
color.rgb = scaleSoftClip(color.rgb);
- /// Gamma correct for WL (soft clip effect).
- frag_data[0] = vec4(color.rgb, 0.0);
+ // Gamma correct for WL (soft clip effect).
+ frag_data[0] = vec4(color.rgb, 1.0);
frag_data[1] = vec4(0.0,0.0,0.0,0.0);
frag_data[2] = vec4(0.0,0.0,0.0,GBUFFER_FLAG_SKIP_ATMOS); //1.0 in norm.w masks off fog
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
index ff53646fd4..1424b57d6f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
@@ -33,6 +33,7 @@ ATTRIBUTE vec3 position;
// Output parameters
VARYING vec3 vary_HazeColor;
+VARYING float vary_LightNormPosDot;
// Inputs
uniform vec3 camPosLocal;
@@ -70,30 +71,32 @@ void main()
vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
// Adj position vector to clamp altitude
- if (rel_pos.y > 0)
+ if (rel_pos.y > 0.)
{
rel_pos *= (max_y / rel_pos.y);
}
- if (rel_pos.y < 0)
+ if (rel_pos.y < 0.)
{
rel_pos *= (-32000. / rel_pos.y);
}
- // Can normalize then
- vec3 rel_pos_norm = normalize(rel_pos);
+ // Normalized
+ vec3 rel_pos_norm = normalize(rel_pos);
+ float rel_pos_len = length(rel_pos);
- float rel_pos_len = length(rel_pos);
+ // Grab this value and pass to frag shader for rainbows
+ float rel_pos_lightnorm_dot = dot(rel_pos_norm, lightnorm.xyz);
+ vary_LightNormPosDot = rel_pos_lightnorm_dot;
// Initialize temp variables
vec3 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
- vec3 light_atten;
// Sunlight attenuation effect (hue and brightness) due to atmosphere
// this is used later for sunlight modulation at various altitudes
- light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
+ vec3 light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
// Calculate relative weights
- vec3 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+ vec3 combined_haze = abs(blue_density) + vec3(abs(haze_density));
vec3 blue_weight = blue_density / combined_haze;
vec3 haze_weight = haze_density / combined_haze;
@@ -110,7 +113,7 @@ void main()
combined_haze = exp(-combined_haze * density_dist);
// Compute haze glow
- float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
+ float haze_glow = 1.0 - rel_pos_lightnorm_dot;
// haze_glow is 0 at the sun and increases away from sun
haze_glow = max(haze_glow, .001);
// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
@@ -121,30 +124,30 @@ void main()
// Add "minimum anti-solar illumination"
// For sun, add to glow. For moon, remove glow entirely. SL-13768
- haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
+ haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25));
- vec3 color =
- (blue_horizon * blue_weight * (sunlight + ambient_color) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
+ // Haze color above cloud
+ vec3 color = (blue_horizon * blue_weight * (sunlight + ambient_color)
+ + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
// Final atmosphere additive
color *= (1. - combined_haze);
// Increase ambient when there are more clouds
- vec3 tmpAmbient = ambient_color;
- tmpAmbient += max(vec3(0), (1. - ambient_color)) * cloud_shadow * 0.5;
+ vec3 ambient = ambient_color + max(vec3(0), (1. - ambient_color)) * cloud_shadow * 0.5;
// Dim sunlight by cloud shadow percentage
sunlight *= max(0.0, (1. - cloud_shadow));
// Haze color below cloud
- vec3 additiveColorBelowCloud =
- (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
+ vec3 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient)
+ + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient));
// Attenuate cloud color by atmosphere
combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
// At horizon, blend high altitude sky color towards the darker color below the clouds
- color += (additiveColorBelowCloud - color) * (1. - sqrt(combined_haze));
+ color += (add_below_cloud - color) * (1. - sqrt(combined_haze));
// Haze color above cloud
vary_HazeColor = color;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
deleted file mode 100644
index 668f70c3ab..0000000000
--- a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
+++ /dev/null
@@ -1,199 +0,0 @@
-/**
- * @file class2/deferred/skyF.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-uniform mat4 modelview_projection_matrix;
-
-// SKY ////////////////////////////////////////////////////////////////////////
-// The vertex shader for creating the atmospheric sky
-///////////////////////////////////////////////////////////////////////////////
-
-// Inputs
-uniform vec3 camPosLocal;
-
-uniform vec3 lightnorm;
-uniform vec3 sunlight_color;
-uniform vec3 moonlight_color;
-uniform int sun_up_factor;
-uniform vec3 ambient_color;
-uniform vec3 blue_horizon;
-uniform vec3 blue_density;
-uniform float haze_horizon;
-uniform float haze_density;
-
-uniform float cloud_shadow;
-uniform float density_multiplier;
-uniform float distance_multiplier;
-uniform float max_y;
-
-uniform vec3 glow;
-uniform float sun_moon_glow_factor;
-
-uniform vec3 cloud_color;
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-
-VARYING vec3 pos;
-
-/////////////////////////////////////////////////////////////////////////
-// The fragment shader for the sky
-/////////////////////////////////////////////////////////////////////////
-
-uniform sampler2D rainbow_map;
-uniform sampler2D halo_map;
-
-uniform float moisture_level;
-uniform float droplet_radius;
-uniform float ice_level;
-
-vec3 rainbow(float d)
-{
- // d is the dot product of view and sun directions, so ranging -1.0..1.0
- // 'interesting' values of d are the range -0.75..-0.825, when view is nearly opposite of sun vec
- // Rainbox texture mode is GL_REPEAT, so tc of -.75 is equiv to 0.25, -0.825 equiv to 0.175.
-
- // SL-13629 Rainbow texture has colors within the correct .175...250 range, but order is inverted.
- // Rather than replace the texture, we mirror and translate the y tc to keep the colors within the
- // interesting range, but in reversed order: i.e. d = (1 - d) - 1.575
- d = clamp(-0.575 - d, 0.0, 1.0);
-
- // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible.
- // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate
- // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857
- float interior_coord = max(0.0, d - 0.25) * 4.2857;
- d = clamp(d, 0.0, 0.25) + interior_coord;
-
- float rad = (droplet_radius - 5.0f) / 1024.0f;
- return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
-}
-
-vec3 halo22(float d)
-{
- d = clamp(d, 0.1, 1.0);
- float v = sqrt(clamp(1 - (d * d), 0, 1));
- return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
-}
-
-/// Soft clips the light with a gamma correction
-vec3 scaleSoftClip(vec3 light);
-
-void main()
-{
- // World / view / projection
- // Get relative position (offset why?)
- vec3 rel_pos = pos.xyz - camPosLocal.xyz + vec3(0, 50, 0);
-
- // Adj position vector to clamp altitude
- if (rel_pos.y > 0.)
- {
- rel_pos *= (max_y / rel_pos.y);
- }
- if (rel_pos.y < 0.)
- {
- rel_pos *= (-32000. / rel_pos.y);
- }
-
- // Normalized
- vec3 rel_pos_norm = normalize(rel_pos);
- float rel_pos_len = length(rel_pos);
-
- // Initialize temp variables
- vec3 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
-
- // Sunlight attenuation effect (hue and brightness) due to atmosphere
- // this is used later for sunlight modulation at various altitudes
- vec3 light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
-
- // Calculate relative weights
- vec3 combined_haze = abs(blue_density) + vec3(abs(haze_density));
- vec3 blue_weight = blue_density / combined_haze;
- vec3 haze_weight = haze_density / combined_haze;
-
- // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
- float off_axis = 1.0 / max(1e-6, max(0, rel_pos_norm.y) + lightnorm.y);
- sunlight *= exp(-light_atten * off_axis);
-
- // Distance
- float density_dist = rel_pos_len * density_multiplier;
-
- // Transparency (-> combined_haze)
- // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
- // compiler gets confused.
- combined_haze = exp(-combined_haze * density_dist);
-
- // Compute haze glow
- float haze_glow = dot(rel_pos_norm, lightnorm.xyz);
- haze_glow = 1. - haze_glow;
- // haze_glow is 0 at the sun and increases away from sun
- haze_glow = max(haze_glow, .001);
- // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
- haze_glow *= glow.x;
- // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
- haze_glow = pow(haze_glow, glow.z);
- // glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
- // Add "minimum anti-solar illumination"
- // For sun, add to glow. For moon, remove glow entirely. SL-13768
- haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25));
-
- // Haze color above cloud
- vec3 color = blue_horizon * blue_weight * (sunlight + ambient_color)
- + haze_horizon * haze_weight * (sunlight * haze_glow + ambient_color);
-
- // Final atmosphere additive
- color *= (1. - combined_haze);
-
- // Increase ambient when there are more clouds
- // TODO 9/20: DJH what does this do? max(0,(1-ambient)) will change the color
- vec3 ambient = ambient_color + max(vec3(0), (1. - ambient_color)) * cloud_shadow * 0.5;
-
- // Dim sunlight by cloud shadow percentage
- sunlight *= max(0.0, (1. - cloud_shadow));
-
- // Haze color below cloud
- vec3 add_below_cloud = blue_horizon * blue_weight * (sunlight + ambient)
- + haze_horizon * haze_weight * (sunlight * haze_glow + ambient);
-
- // Attenuate cloud color by atmosphere
- combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds
-
- // At horizon, blend high altitude sky color towards the darker color below the clouds
- color += (add_below_cloud - color) * (1. - sqrt(combined_haze));
-
- float optic_d = dot(rel_pos_norm, lightnorm.xyz);
- vec3 halo_22 = halo22(optic_d);
- color.rgb += rainbow(optic_d);
- color.rgb += halo_22;
- color.rgb *= 2.;
- color.rgb = scaleSoftClip(color.rgb);
-
- // Gamma correct for WL (soft clip effect).
- frag_data[0] = vec4(color.rgb, 1.0);
- frag_data[1] = vec4(0.0, 0.0, 0.0, 0.0);
- frag_data[2] = vec4(0.0, 0.0, 0.0, GBUFFER_FLAG_SKIP_ATMOS); // 1.0 in norm.w masks off fog
-}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl
deleted file mode 100644
index bcf775577a..0000000000
--- a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * @file WLSkyV.glsl
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-uniform mat4 modelview_projection_matrix;
-
-ATTRIBUTE vec3 position;
-
-// SKY ////////////////////////////////////////////////////////////////////////
-// The vertex shader for creating the atmospheric sky
-///////////////////////////////////////////////////////////////////////////////
-
-VARYING vec3 pos;
-
-void main()
-{
-
- // World / view / projection
- pos = position.xyz;
- gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
-}
diff --git a/indra/newview/fschathistory.cpp b/indra/newview/fschathistory.cpp
index 51d151b5e2..46ed261d15 100644
--- a/indra/newview/fschathistory.cpp
+++ b/indra/newview/fschathistory.cpp
@@ -1263,9 +1263,7 @@ FSChatHistory::FSChatHistory(const FSChatHistory::Params& p)
LLSD FSChatHistory::getValue() const
{
- LLSD* text=new LLSD();
- text->assign(getText());
- return *text;
+ return LLSD(getText());
}
FSChatHistory::~FSChatHistory()
diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp
index e09527a34b..d3f988d715 100644
--- a/indra/newview/llaccountingcostmanager.cpp
+++ b/indra/newview/llaccountingcostmanager.cpp
@@ -96,11 +96,7 @@ void LLAccountingCostManager::accountingCostCoro(std::string url,
LLSD dataToPost = LLSD::emptyMap();
dataToPost[keystr.c_str()] = objectList;
- LLAccountingCostObserver* observer = observerHandle.get();
- LLUUID transactionId = observer->getTransactionID();
- observer = NULL;
-
-
+ LLAccountingCostObserver* observer = NULL;
LLSD results = httpAdapter->postAndSuspend(httpRequest, url, dataToPost);
diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index aa801d6ae6..55e35c8ef7 100644
--- a/indra/newview/llappdelegate-objc.mm
+++ b/indra/newview/llappdelegate-objc.mm
@@ -46,6 +46,7 @@
- (void)dealloc
{
+ [currentInputLanguage release];
[super dealloc];
}
@@ -199,17 +200,17 @@
- (bool) romanScript
{
- // How to add support for new languages with the input window:
- // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.)
- NSArray *nonRomanScript = [[NSArray alloc] initWithObjects:@"ja", @"ko", @"zh-Hant", @"zh-Hans", nil];
- bool ret = true;
- if ([nonRomanScript containsObject:currentInputLanguage])
- {
- ret = false;
+ @autoreleasepool {
+ // How to add support for new languages with the input window:
+ // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.)
+ NSArray* nonRomanScript = @[@"ja", @"ko", @"zh-Hant", @"zh-Hans"];
+ if ([nonRomanScript containsObject:currentInputLanguage])
+ {
+ return false;
+ }
}
- [nonRomanScript release];
- return ret;
+ return true;
}
#if defined(LL_BUGSPLAT)
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 5a77e44399..771d7398da 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -4504,7 +4504,7 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo
// existence of AIS as an indicator the fix is present. Does
// not actually use AIS to create the category.
inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel);
- LLUUID folder_id = gInventory.createNewCategory(
+ gInventory.createNewCategory(
parent_id,
LLFolderType::FT_OUTFIT,
new_folder_name,
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 725670a819..9bb3b22b9a 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -150,6 +150,10 @@
#include "vlc/libvlc_version.h"
#endif // LL_LINUX
+#if LL_DARWIN
+#include "llwindowmacosx.h"
+#endif
+
// Third party library includes
#include
#include
@@ -635,6 +639,7 @@ static void settings_to_globals()
LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale"));
#if LL_DARWIN
+ LLWindowMacOSX::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL");
gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI");
#endif
}
@@ -1994,7 +1999,8 @@ bool LLAppViewer::cleanup()
{
if (!isSecondInstance())
{
- LLSceneMonitor::instance().dumpToFile(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv"));
+ std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv");
+ LLSceneMonitor::instance().dumpToFile(dump_path);
}
LLSceneMonitor::deleteSingleton();
}
diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp
index 275f17b02a..293c9d60a1 100644
--- a/indra/newview/llavatarrenderinfoaccountant.cpp
+++ b/indra/newview/llavatarrenderinfoaccountant.cpp
@@ -364,11 +364,10 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi
}
}
-// static
// Called every frame - send render weight requests to every region
void LLAvatarRenderInfoAccountant::idle()
{
- if (mRenderInfoScanTimer.hasExpired())
+ if (mRenderInfoScanTimer.hasExpired() && !LLApp::isExiting())
{
LL_DEBUGS("AvatarRenderInfo") << "Scanning regions for render info updates"
<< LL_ENDL;
diff --git a/indra/newview/llbuycurrencyhtml.cpp b/indra/newview/llbuycurrencyhtml.cpp
index c1099ffa23..d2f191036a 100644
--- a/indra/newview/llbuycurrencyhtml.cpp
+++ b/indra/newview/llbuycurrencyhtml.cpp
@@ -43,7 +43,7 @@ class LLBuyCurrencyHTMLHandler :
{
public:
// requests will be throttled from a non-trusted browser
- LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_ALLOW ) {}
+ LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_THROTTLE) {}
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
{
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 51d4e94430..ad9ae12ced 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -723,8 +723,7 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
{
if(mBuddyInfo.find(agent_id) != mBuddyInfo.end())
{
- if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
- && !gAgent.isDoNotDisturb())
+ if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS))
{
LLSD args;
// Always show complete name in rights dialogs
@@ -803,19 +802,18 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
// we were tracking someone who went offline
deleteTrackingData();
}
- // } [FIRE-32324] least invasive change move this brace after the if. LL fix should follow sometime soon
- //[FIX FIRE-3522 : SJ] Notify Online/Offline to Nearby Chat even if chat_notify isnt true
-
- // Attempt to speed up things a little
- // if(chat_notify||LGGContactSets::getInstance()->notifyForFriend(agent_id)||gSavedSettings.getBOOL("OnlineOfflinetoNearbyChat"))
- static LLCachedControl OnlineOfflinetoNearbyChat(gSavedSettings, "OnlineOfflinetoNearbyChat");
- if(chat_notify || LGGContactSets::getInstance()->notifyForFriend(agent_id) || OnlineOfflinetoNearbyChat)
- //
- {
- // Look up the name of this agent for the notification
- LLAvatarNameCache::get(agent_id,boost::bind(&on_avatar_name_cache_notify,_1, _2, online, payload));
+
+ //[FIX FIRE-3522 : SJ] Notify Online/Offline to Nearby Chat even if chat_notify isnt true
+ // Attempt to speed up things a little
+ // if(chat_notify||LGGContactSets::getInstance()->notifyForFriend(agent_id)||gSavedSettings.getBOOL("OnlineOfflinetoNearbyChat"))
+ static LLCachedControl OnlineOfflinetoNearbyChat(gSavedSettings, "OnlineOfflinetoNearbyChat");
+ if(chat_notify || LGGContactSets::getInstance()->notifyForFriend(agent_id) || OnlineOfflinetoNearbyChat)
+ //
+ {
+ // Look up the name of this agent for the notification
+ LLAvatarNameCache::get(agent_id,boost::bind(&on_avatar_name_cache_notify,_1, _2, online, payload));
+ }
}
- } // [FIRE-32324] least invasive change move this brace after the if
mModifyMask |= LLFriendObserver::ONLINE;
instance().notifyObservers();
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 293c92cc49..6cd03db6f7 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -155,6 +155,18 @@ public:
{
mAvatarNameCacheConnection.disconnect();
}
+ auto menu = mPopupMenuHandleAvatar.get();
+ if (menu)
+ {
+ menu->die();
+ mPopupMenuHandleAvatar.markDead();
+ }
+ menu = mPopupMenuHandleObject.get();
+ if (menu)
+ {
+ menu->die();
+ mPopupMenuHandleObject.markDead();
+ }
}
BOOL handleMouseUp(S32 x, S32 y, MASK mask)
@@ -587,36 +599,6 @@ public:
BOOL postBuild()
{
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
- LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable;
-
- registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2));
- registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2));
- registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2));
- registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2));
- registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2));
- registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2));
-
- LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- if (menu)
- {
- mPopupMenuHandleAvatar = menu->getHandle();
- }
- else
- {
- LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL;
- }
-
- menu = LLUICtrlFactory::getInstance()->createFromFile("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- if (menu)
- {
- mPopupMenuHandleObject = menu->getHandle();
- }
- else
- {
- LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL;
- }
-
setDoubleClickCallback(boost::bind(&LLChatHistoryHeader::showInspector, this));
setMouseEnterCallback(boost::bind(&LLChatHistoryHeader::showInfoCtrl, this));
@@ -937,13 +919,53 @@ protected:
void showObjectContextMenu(S32 x,S32 y)
{
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleObject.get();
- if(menu)
+ if (!menu)
+ {
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable;
+ registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2));
+ registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2));
+
+ menu = LLUICtrlFactory::getInstance()->createFromFile("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandleObject = menu->getHandle();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(this, menu, x, y);
+ }
+ else
+ {
+ LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL;
+ }
+ }
+ else
+ {
LLMenuGL::showPopup(this, menu, x, y);
+ }
}
void showAvatarContextMenu(S32 x,S32 y)
{
LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleAvatar.get();
+ if (!menu)
+ {
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable;
+ registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2));
+ registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2));
+ registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2));
+ registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2));
+
+ menu = LLUICtrlFactory::getInstance()->createFromFile("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandleAvatar = menu->getHandle();
+ }
+ else
+ {
+ LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL;
+ }
+ }
if(menu)
{
@@ -1142,10 +1164,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
LLSD LLChatHistory::getValue() const
{
- LLSD* text=new LLSD();
- text->assign(mEditor->getText());
- return *text;
-
+ return LLSD(mEditor->getText());
}
LLChatHistory::~LLChatHistory()
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index ae54043cba..9d3ad0effc 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -98,7 +98,6 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p)
, mMaxDisplayedCount(p.max_displayed_count)
, mIsNewMessagesState(false)
, mFlashToLitTimer(NULL)
- , mContextMenu(NULL)
{
LLButton::Params button_params = p.button;
mButton = LLUICtrlFactory::create(button_params);
@@ -110,6 +109,12 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p)
LLSysWellChiclet::~LLSysWellChiclet()
{
mFlashToLitTimer->unset();
+ LLContextMenu* menu = static_cast(mContextMenuHandle.get());
+ if (menu)
+ {
+ menu->die();
+ mContextMenuHandle.markDead();
+ }
}
void LLSysWellChiclet::setCounter(S32 counter)
@@ -176,14 +181,16 @@ void LLSysWellChiclet::updateWidget(bool is_window_empty)
// virtual
BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- if(!mContextMenu)
+ LLContextMenu* menu_avatar = mContextMenuHandle.get();
+ if(!menu_avatar)
{
createMenu();
+ menu_avatar = mContextMenuHandle.get();
}
- if (mContextMenu)
+ if (menu_avatar)
{
- mContextMenu->show(x, y);
- LLMenuGL::showPopup(this, mContextMenu, x, y);
+ menu_avatar->show(x, y);
+ LLMenuGL::showPopup(this, menu_avatar, x, y);
}
return TRUE;
}
@@ -207,6 +214,13 @@ LLIMWellChiclet::LLIMWellChiclet(const Params& p)
LLIMWellChiclet::~LLIMWellChiclet()
{
+ LLContextMenu* menu = static_cast(mContextMenuHandle.get());
+ if (menu)
+ {
+ menu->die();
+ mContextMenuHandle.markDead();
+ }
+
LLIMWellWindow* im_well_window = LLIMWellWindow::findInstance();
if (im_well_window)
{
@@ -237,7 +251,7 @@ bool LLIMWellChiclet::enableMenuItem(const LLSD& user_data)
void LLIMWellChiclet::createMenu()
{
- if(mContextMenu)
+ if(mContextMenuHandle.get())
{
LL_WARNS() << "Menu already exists" << LL_ENDL;
return;
@@ -251,10 +265,14 @@ void LLIMWellChiclet::createMenu()
enable_registrar.add("IMWellChicletMenu.EnableItem",
boost::bind(&LLIMWellChiclet::enableMenuItem, this, _2));
- mContextMenu = LLUICtrlFactory::getInstance()->createFromFile
+ LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile
("menu_fs_im_well_button.xml",
LLMenuGL::sMenuContainer,
LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mContextMenuHandle = menu->getHandle();
+ }
}
void LLIMWellChiclet::messageCountChanged(const LLSD& session_data)
@@ -358,7 +376,7 @@ bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data)
void LLNotificationChiclet::createMenu()
{
- if(mContextMenu)
+ if(mContextMenuHandle.get())
{
LL_WARNS() << "Menu already exists" << LL_ENDL;
return;
@@ -373,10 +391,14 @@ void LLNotificationChiclet::createMenu()
boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2));
llassert(LLMenuGL::sMenuContainer != NULL);
- mContextMenu = LLUICtrlFactory::getInstance()->createFromFile
+ LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile
("menu_notification_well_button.xml",
LLMenuGL::sMenuContainer,
LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mContextMenuHandle = menu->getHandle();
+ }
}
/*virtual*/
@@ -492,12 +514,21 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p)
, mCounterCtrl(NULL)
// [FS communication UI]
, mChicletButton(NULL)
-, mPopupMenu(NULL)
{
// [FS communication UI]
enableCounterControl(p.enable_counter);
}
+LLIMChiclet::~LLIMChiclet()
+{
+ auto menu = mPopupMenuHandle.get();
+ if (menu)
+ {
+ menu->die();
+ mPopupMenuHandle.markDead();
+ }
+}
+
/* virtual*/
BOOL LLIMChiclet::postBuild()
{
@@ -688,16 +719,18 @@ LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id)
BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- if(!mPopupMenu)
+ auto menu = static_cast(mPopupMenuHandle.get());
+ if(!menu)
{
createPopupMenu();
+ menu = static_cast(mPopupMenuHandle.get());
}
- if (mPopupMenu)
+ if (menu)
{
updateMenuItems();
- mPopupMenu->arrangeAndClear();
- LLMenuGL::showPopup(this, mPopupMenu, x, y);
+ menu->arrangeAndClear();
+ LLMenuGL::showPopup(this, menu, x, y);
}
return TRUE;
@@ -705,15 +738,16 @@ BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
void LLIMChiclet::hidePopupMenu()
{
- if (mPopupMenu)
+ auto menu = mPopupMenuHandle.get();
+ if (menu)
{
- mPopupMenu->setVisible(FALSE);
+ menu->setVisible(FALSE);
}
}
bool LLIMChiclet::canCreateMenu()
{
- if(mPopupMenu)
+ if(mPopupMenuHandle.get())
{
LL_WARNS() << "Menu already exists" << LL_ENDL;
return false;
@@ -784,17 +818,17 @@ void LLIMP2PChiclet::setOtherParticipantId(const LLUUID& other_participant_id)
void LLIMP2PChiclet::updateMenuItems()
{
- if(!mPopupMenu)
+ if(!mPopupMenuHandle.get())
return;
if(getSessionId().isNull())
return;
FSFloaterIM* open_im_floater = FSFloaterIM::findInstance(getSessionId());
bool open_window_exists = open_im_floater && open_im_floater->getVisible();
- mPopupMenu->getChild("Send IM")->setEnabled(!open_window_exists);
+ mPopupMenuHandle.get()->getChild("Send IM")->setEnabled(!open_window_exists);
bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId());
- mPopupMenu->getChild("Add Friend")->setEnabled(!is_friend);
+ mPopupMenuHandle.get()->getChild("Add Friend")->setEnabled(!is_friend);
}
void LLIMP2PChiclet::createPopupMenu()
@@ -805,8 +839,12 @@ void LLIMP2PChiclet::createPopupMenu()
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("IMChicletMenu.Action", boost::bind(&LLIMP2PChiclet::onMenuItemClicked, this, _2));
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile
("menu_fs_imchiclet_p2p.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandle = menu->getHandle();
+ }
}
void LLIMP2PChiclet::onMenuItemClicked(const LLSD& user_data)
@@ -925,8 +963,12 @@ void LLAdHocChiclet::createPopupMenu()
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("IMChicletMenu.Action", boost::bind(&LLAdHocChiclet::onMenuItemClicked, this, _2));
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile
+ auto menu = LLUICtrlFactory::getInstance()->createFromFile
("menu_fs_imchiclet_adhoc.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandle = menu->getHandle();
+ }
}
void LLAdHocChiclet::onMenuItemClicked(const LLSD& user_data)
@@ -1060,14 +1102,14 @@ void LLIMGroupChiclet::changed(LLGroupChange gc)
void LLIMGroupChiclet::updateMenuItems()
{
- if(!mPopupMenu)
+ if(!mPopupMenuHandle.get())
return;
if(getSessionId().isNull())
return;
FSFloaterIM* open_im_floater = FSFloaterIM::findInstance(getSessionId());
bool open_window_exists = open_im_floater && open_im_floater->getVisible();
- mPopupMenu->getChild("Chat")->setEnabled(!open_window_exists);
+ mPopupMenuHandle.get()->getChild("Chat")->setEnabled(!open_window_exists);
}
void LLIMGroupChiclet::createPopupMenu()
@@ -1078,8 +1120,12 @@ void LLIMGroupChiclet::createPopupMenu()
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("IMChicletMenu.Action", boost::bind(&LLIMGroupChiclet::onMenuItemClicked, this, _2));
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile
+ auto menu = LLUICtrlFactory::getInstance()->createFromFile
("menu_fs_imchiclet_group.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandle = menu->getHandle();
+ }
}
void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data)
@@ -2010,8 +2056,13 @@ void LLScriptChiclet::createPopupMenu()
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("ScriptChiclet.Action", boost::bind(&LLScriptChiclet::onMenuItemClicked, this, _2));
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile
("menu_script_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandle = menu->getHandle();
+ }
+
}
//////////////////////////////////////////////////////////////////////////
@@ -2095,8 +2146,12 @@ void LLInvOfferChiclet::createPopupMenu()
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("InvOfferChiclet.Action", boost::bind(&LLInvOfferChiclet::onMenuItemClicked, this, _2));
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile
("menu_inv_offer_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mPopupMenuHandle = menu->getHandle();
+ }
}
// EOF
diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h
index 598678f6ea..478e02a1ef 100644
--- a/indra/newview/llchiclet.h
+++ b/indra/newview/llchiclet.h
@@ -325,7 +325,7 @@ public:
{};
- virtual ~LLIMChiclet() {};
+ virtual ~LLIMChiclet();
/**
* It is used for default setting up of chicklet:click handler, etc.
@@ -456,7 +456,7 @@ protected:
bool canCreateMenu();
- LLMenuGL* mPopupMenu;
+ LLHandle mPopupMenuHandle;
bool mShowSpeaker;
bool mCounterEnabled;
@@ -633,6 +633,8 @@ public:
*/
/*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }
+ /*virtual*/ ~LLIMP2PChiclet() {};
+
protected:
LLIMP2PChiclet(const Params& p);
friend class LLUICtrlFactory;
@@ -705,6 +707,8 @@ public:
*/
/*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }
+ /*virtual*/ ~LLAdHocChiclet() {};
+
protected:
LLAdHocChiclet(const Params& p);
friend class LLUICtrlFactory;
@@ -884,7 +888,7 @@ protected:
bool mIsNewMessagesState;
LLFlashTimer* mFlashToLitTimer;
- LLContextMenu* mContextMenu;
+ LLHandle mContextMenuHandle;
};
class LLNotificationChiclet : public LLSysWellChiclet
diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index 23e2271eae..74f37961c7 100644
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
@@ -39,6 +39,7 @@
#define THROTTLE_PERIOD 5 // required seconds between throttled commands
static LLCommandDispatcherListener sCommandDispatcherListener;
+const std::string LLCommandHandler::NAV_TYPE_CLICKED = "clicked";
//---------------------------------------------------------------------------
// Underlying registry for command handlers, not directly accessible.
@@ -64,6 +65,9 @@ public:
bool trusted_browser);
private:
+ void notifySlurlBlocked();
+ void notifySlurlThrottled();
+
friend LLSD LLCommandDispatcher::enumerate();
std::map mMap;
};
@@ -96,8 +100,6 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
const std::string& nav_type,
bool trusted_browser)
{
- static bool slurl_blocked = false;
- static bool slurl_throttled = false;
static F64 last_throttle_time = 0.0;
F64 cur_time = 0.0;
std::map::iterator it = mMap.find(cmd);
@@ -115,44 +117,45 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
// block request from external browser, but report as
// "handled" because it was well formatted.
LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
- if (! slurl_blocked)
- {
- if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
- {
- // Note: commands can arrive before we initialize everything we need for Notification.
- LLNotificationsUtil::add("BlockedSLURL");
- }
- slurl_blocked = true;
- }
+ notifySlurlBlocked();
return true;
+ case LLCommandHandler::UNTRUSTED_CLICK_ONLY:
+ if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED
+ && info.mHandler->canHandleUntrusted(params, query_map, web, nav_type))
+ {
+ break;
+ }
+ LL_WARNS_ONCE("SLURL") << "Blocked SLURL click-only command " << cmd << " from untrusted browser" << LL_ENDL;
+ notifySlurlBlocked();
+ return true;
+
case LLCommandHandler::UNTRUSTED_THROTTLE:
- // if users actually click on a link, we don't need to throttle it
- // (throttling mechanism is used to prevent an avalanche of clicks via
- // javascript
- if ( nav_type == "clicked" )
- {
- break;
- }
//skip initial request from external browser before STATE_BROWSER_INIT
if (LLStartUp::getStartupState() == STATE_FIRST)
{
return true;
}
+ if (!info.mHandler->canHandleUntrusted(params, query_map, web, nav_type))
+ {
+ LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL;
+ notifySlurlBlocked();
+ return true;
+ }
+ // if users actually click on a link, we don't need to throttle it
+ // (throttling mechanism is used to prevent an avalanche of clicks via
+ // javascript
+ if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED)
+ {
+ break;
+ }
cur_time = LLTimer::getElapsedSeconds();
if (cur_time < last_throttle_time + THROTTLE_PERIOD)
{
// block request from external browser if it happened
// within THROTTLE_PERIOD seconds of the last command
LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL;
- if (! slurl_throttled)
- {
- if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
- {
- LLNotificationsUtil::add("ThrottledSLURL");
- }
- slurl_throttled = true;
- }
+ notifySlurlThrottled();
return true;
}
last_throttle_time = cur_time;
@@ -163,6 +166,34 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
return info.mHandler->handle(params, query_map, web);
}
+void LLCommandHandlerRegistry::notifySlurlBlocked()
+{
+ static bool slurl_blocked = false;
+ if (!slurl_blocked)
+ {
+ if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
+ {
+ // Note: commands can arrive before we initialize everything we need for Notification.
+ LLNotificationsUtil::add("BlockedSLURL");
+ }
+ slurl_blocked = true;
+ }
+}
+
+void LLCommandHandlerRegistry::notifySlurlThrottled()
+{
+ static bool slurl_throttled = false;
+ if (!slurl_throttled)
+ {
+ if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT)
+ {
+ // Note: commands can arrive before we initialize everything we need for Notification.
+ LLNotificationsUtil::add("ThrottledSLURL");
+ }
+ slurl_throttled = true;
+ }
+}
+
//---------------------------------------------------------------------------
// Automatic registration of commands, runs before main()
//---------------------------------------------------------------------------
@@ -230,6 +261,7 @@ symbol_info symbols[] =
{
ent(LLCommandHandler::UNTRUSTED_ALLOW), // allow commands from untrusted browsers
ent(LLCommandHandler::UNTRUSTED_BLOCK), // ignore commands from untrusted browsers
+ ent(LLCommandHandler::UNTRUSTED_CLICK_ONLY), // allow untrusted, but only if clicked
ent(LLCommandHandler::UNTRUSTED_THROTTLE) // allow untrusted, but only a few per min.
};
diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h
index 1e0895565a..763e3ee51f 100644
--- a/indra/newview/llcommandhandler.h
+++ b/indra/newview/llcommandhandler.h
@@ -65,9 +65,12 @@ public:
{
UNTRUSTED_ALLOW, // allow commands from untrusted browsers
UNTRUSTED_BLOCK, // ignore commands from untrusted browsers
+ UNTRUSTED_CLICK_ONLY, // allow untrusted, but only if clicked
UNTRUSTED_THROTTLE // allow untrusted, but only a few per min.
};
+ static const std::string NAV_TYPE_CLICKED;
+
LLCommandHandler(const char* command, EUntrustedAccess untrusted_access);
// Automatically registers object to get called when
// command is executed. All commands can be processed
@@ -76,6 +79,13 @@ public:
virtual ~LLCommandHandler();
+ virtual bool canHandleUntrusted(
+ const LLSD& params,
+ const LLSD& query_map,
+ LLMediaCtrl* web,
+ const std::string& nav_type)
+ { return true; }
+
virtual bool handle(const LLSD& params,
const LLSD& query_map,
LLMediaCtrl* web) = 0;
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index dd3ed72fec..a604e6def7 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -691,7 +691,6 @@ namespace
if (!injection->mBlendIn)
mix = 1.0 - mix;
stringset_t dummy;
- LLUUID cloud_noise_id = getCloudNoiseTextureId();
F64 value = this->mSettings[injection->mKeyName].asReal();
if (this->getCloudNoiseTextureId().isNull())
{
@@ -3263,7 +3262,7 @@ bool LLEnvironment::loadFromSettings()
LL_INFOS("ENVIRONMENT") << "Unable to open previous session environment file " << user_filepath << LL_ENDL;
}
- if (!env_data.isMap() || env_data.emptyMap())
+ if (!env_data.isMap() || (env_data.size() == 0))
{
LL_DEBUGS("ENVIRONMENT") << "Empty map loaded from: " << user_filepath << LL_ENDL;
return false;
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 132117943e..c797d20e9e 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -650,9 +650,9 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
#elif LL_DARWIN
-std::vector* LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
+std::unique_ptr> LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)
{
- std::vector *allowedv = new std::vector< std::string >;
+ std::unique_ptr> allowedv(new std::vector< std::string >);
switch(filter)
{
case FFLOAD_ALL:
@@ -738,9 +738,9 @@ bool LLFilePicker::doNavChooseDialog(ELoadFilter filter)
gViewerWindow->getWindow()->beforeDialog();
- std::vector *allowed_types=navOpenFilterProc(filter);
+ std::unique_ptr> allowed_types = navOpenFilterProc(filter);
- std::vector *filev = doLoadDialog(allowed_types,
+ std::unique_ptr> filev = doLoadDialog(allowed_types.get(),
mPickOptions);
gViewerWindow->getWindow()->afterDialog();
@@ -879,7 +879,7 @@ bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena
gViewerWindow->getWindow()->beforeDialog();
// Run the dialog
- std::string* filev = doSaveDialog(&namestring,
+ std::unique_ptr filev = doSaveDialog(&namestring,
&type,
&creator,
&extension,
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 9a79dfeae8..69d54f4f8e 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -180,7 +180,7 @@ private:
bool doNavChooseDialog(ELoadFilter filter);
bool doNavSaveDialog(ESaveFilter filter, const std::string& filename);
- std::vector* navOpenFilterProc(ELoadFilter filter);
+ std::unique_ptr> navOpenFilterProc(ELoadFilter filter);
#endif
#if LL_GTK
diff --git a/indra/newview/llfilepicker_mac.h b/indra/newview/llfilepicker_mac.h
index e0b7e2e8ce..b2fb371afe 100644
--- a/indra/newview/llfilepicker_mac.h
+++ b/indra/newview/llfilepicker_mac.h
@@ -39,9 +39,9 @@
#include
//void modelessPicker();
-std::vector* doLoadDialog(const std::vector* allowed_types,
+std::unique_ptr> doLoadDialog(const std::vector* allowed_types,
unsigned int flags);
-std::string* doSaveDialog(const std::string* file,
+std::unique_ptr doSaveDialog(const std::string* file,
const std::string* type,
const std::string* creator,
const std::string* extension,
diff --git a/indra/newview/llfilepicker_mac.mm b/indra/newview/llfilepicker_mac.mm
index f8475365c2..0ae5fc3f77 100644
--- a/indra/newview/llfilepicker_mac.mm
+++ b/indra/newview/llfilepicker_mac.mm
@@ -29,111 +29,107 @@
#include
#include "llfilepicker_mac.h"
-std::vector* doLoadDialog(const std::vector* allowed_types,
+std::unique_ptr> doLoadDialog(const std::vector* allowed_types,
unsigned int flags)
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Fix mem leak by Cinder Roxley
- int i, result;
-
- //Aura TODO: We could init a small window and release it at the end of this routine
- //for a modeless interface.
-
- NSOpenPanel *panel = [NSOpenPanel openPanel];
- //NSString *fileName = nil;
- NSMutableArray *fileTypes = nil;
-
-
- if ( allowed_types && !allowed_types->empty())
- {
- fileTypes = [[NSMutableArray alloc] init];
+ std::unique_ptr> outfiles;
+
+ @autoreleasepool {
+ int i, result;
+ //Aura TODO: We could init a small window and release it at the end of this routine
+ //for a modeless interface.
- for (i=0;isize();++i)
+ NSOpenPanel *panel = [NSOpenPanel openPanel];
+ //NSString *fileName = nil;
+ NSMutableArray *fileTypes = nil;
+
+ if ( allowed_types && !allowed_types->empty())
{
- [fileTypes addObject:
- [NSString stringWithCString:(*allowed_types)[i].c_str()
- encoding:[NSString defaultCStringEncoding]]];
+ fileTypes = [[[NSMutableArray alloc] init] autorelease];
+
+ for (i=0;isize();++i)
+ {
+ [fileTypes addObject:
+ [NSString stringWithCString:(*allowed_types)[i].c_str()
+ encoding:[NSString defaultCStringEncoding]]];
+ }
}
- }
- //[panel setMessage:@"Import one or more files or directories."];
- [panel setAllowsMultipleSelection: ( (flags & F_MULTIPLE)?true:false ) ];
- [panel setCanChooseDirectories: ( (flags & F_DIRECTORY)?true:false ) ];
- [panel setCanCreateDirectories: true];
- [panel setResolvesAliases: true];
- [panel setCanChooseFiles: ( (flags & F_FILE)?true:false )];
- [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
-
- std::vector* outfiles = NULL;
-
- if (fileTypes)
- {
- [panel setAllowedFileTypes:fileTypes];
- result = [panel runModal];
- }
- else
- {
- // I suggest it's better to open the last path and let this default to home dir as necessary
- // for consistency with other OS X apps
- //
- //[panel setDirectoryURL: fileURLWithPath(NSHomeDirectory()) ];
- result = [panel runModal];
- }
-
- if (result == NSOKButton)
- {
- NSArray *filesToOpen = [panel URLs];
- int i, count = [filesToOpen count];
+ //[panel setMessage:@"Import one or more files or directories."];
+ [panel setAllowsMultipleSelection: ( (flags & F_MULTIPLE)?true:false ) ];
+ [panel setCanChooseDirectories: ( (flags & F_DIRECTORY)?true:false ) ];
+ [panel setCanCreateDirectories: true];
+ [panel setResolvesAliases: true];
+ [panel setCanChooseFiles: ( (flags & F_FILE)?true:false )];
+ [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
- if (count > 0)
+ if (fileTypes)
{
- outfiles = new std::vector;
+ [panel setAllowedFileTypes:fileTypes];
+ result = [panel runModal];
+ }
+ else
+ {
+ // I suggest it's better to open the last path and let this default to home dir as necessary
+ // for consistency with other OS X apps
+ //
+ //[panel setDirectoryURL: fileURLWithPath(NSHomeDirectory()) ];
+ result = [panel runModal];
}
- for (i=0; ipush_back(*afilestr);
+ if (result == NSOKButton)
+ {
+ NSArray *filesToOpen = [panel URLs];
+ int i, count = [filesToOpen count];
+
+ if (count > 0)
+ {
+ outfiles.reset(new std::vector);
+ }
+
+ for (i=0; ipush_back(afilestr);
+ }
}
}
- [pool release]; // Fix mem leak by Cinder Roxley
-
+
return outfiles;
}
-std::string* doSaveDialog(const std::string* file,
+std::unique_ptr doSaveDialog(const std::string* file,
const std::string* type,
const std::string* creator,
const std::string* extension,
unsigned int flags)
{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Fix mem leak by Cinder Roxley
- NSSavePanel *panel = [NSSavePanel savePanel];
-
- NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]];
- NSArray *fileType = [extensionns componentsSeparatedByString:@","];
-
- //[panel setMessage:@"Save Image File"];
- [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
- [panel setCanSelectHiddenExtension:true];
- [panel setAllowedFileTypes:fileType];
- NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]];
-
- std::string *outfile = NULL;
- NSURL* url = [NSURL fileURLWithPath:fileName];
- [panel setNameFieldStringValue: fileName];
- [panel setDirectoryURL: url];
- [panel setNameFieldStringValue: fileName]; // Populate filename in the save panel
- if([panel runModal] ==
- NSFileHandlingPanelOKButton)
- {
- NSURL* url = [panel URL];
- NSString* p = [url path];
- outfile = new std::string( [p UTF8String] );
- // write the file
+ std::unique_ptr outfile;
+ @autoreleasepool {
+ NSSavePanel *panel = [NSSavePanel savePanel];
+
+ NSString *extensionns = [NSString stringWithCString:extension->c_str() encoding:[NSString defaultCStringEncoding]];
+ NSArray *fileType = [extensionns componentsSeparatedByString:@","];
+
+ //[panel setMessage:@"Save Image File"];
+ [panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
+ [panel setCanSelectHiddenExtension:true];
+ [panel setAllowedFileTypes:fileType];
+ NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]];
+
+ NSURL* url = [NSURL fileURLWithPath:fileName];
+ [panel setNameFieldStringValue: fileName];
+ [panel setDirectoryURL: url];
+ if([panel runModal] ==
+ NSFileHandlingPanelOKButton)
+ {
+ NSURL* url = [panel URL];
+ NSString* p = [url path];
+ outfile.reset(new std::string([p UTF8String]));
+ // write the file
+ }
}
- [pool release]; // Fix mem leak by Cinder Roxley
-
return outfile;
}
diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp
index 8c92bc643a..cfa742cd38 100644
--- a/indra/newview/llfloater360capture.cpp
+++ b/indra/newview/llfloater360capture.cpp
@@ -553,7 +553,8 @@ void LLFloater360Capture::capture360Images()
// We need to convert from the angle getYaw() gives us into something
// the XMP data field wants (N=0, E=90, S=180, W= 270 etc.)
mInitialHeadingDeg = (360 + 90 - (int)(camera->getYaw() * RAD_TO_DEG)) % 360;
- LL_INFOS("360Capture") << "Recording a heading of " << (int)(mInitialHeadingDeg) << LL_ENDL;
+ LL_INFOS("360Capture") << "Recording a heading of " << (int)(mInitialHeadingDeg)
+ << " Image size: " << (S32)mSourceImageSize << LL_ENDL;
// camera constants for the square, cube map capture image
camera->setAspect(1.0); // must set aspect ratio first to avoid undesirable clamping of vertical FoV
@@ -603,6 +604,9 @@ void LLFloater360Capture::capture360Images()
// for each of the 6 directions we shoot...
for (int i = 0; i < 6; i++)
{
+ LLAppViewer::instance()->pauseMainloopTimeout();
+ LLViewerStats::instance().getRecording().stop();
+
// these buffers are where the raw, captured pixels are stored and
// the first time we use them, we have to make a new one
if (mRawImages[i] == nullptr)
@@ -640,8 +644,10 @@ void LLFloater360Capture::capture360Images()
auto duration = std::chrono::duration_cast>(t_end - t_start);
encode_time_total += duration.count();
- // ping the main loop in case the snapshot process takes a really long
- // time and we get disconnected
+ LLViewerStats::instance().getRecording().resume();
+ LLAppViewer::instance()->resumeMainloopTimeout();
+
+ // update main loop timeout state
LLAppViewer::instance()->pingMainloopTimeout("LLFloater360Capture::capture360Images");
}
diff --git a/indra/newview/llfloateravatar.cpp b/indra/newview/llfloateravatar.cpp
index d5f341e705..e91371b762 100644
--- a/indra/newview/llfloateravatar.cpp
+++ b/indra/newview/llfloateravatar.cpp
@@ -48,12 +48,11 @@ LLFloaterAvatar::LLFloaterAvatar(const LLSD& key)
LLFloaterAvatar::~LLFloaterAvatar()
{
- LLMediaCtrl* avatar_picker = findChild("avatar_picker_contents");
- if (avatar_picker)
+ if (mAvatarPicker)
{
- avatar_picker->navigateStop();
- avatar_picker->clearCache(); //images are reloading each time already
- avatar_picker->unloadMediaSource();
+ mAvatarPicker->navigateStop();
+ mAvatarPicker->clearCache(); //images are reloading each time already
+ mAvatarPicker->unloadMediaSource();
}
// Avatar chooser does not change between OpenSim grids
@@ -66,6 +65,11 @@ LLFloaterAvatar::~LLFloaterAvatar()
BOOL LLFloaterAvatar::postBuild()
{
+ mAvatarPicker = findChild("avatar_picker_contents");
+ if (mAvatarPicker)
+ {
+ mAvatarPicker->clearCache();
+ }
enableResizeCtrls(true, true, false);
return TRUE;
}
diff --git a/indra/newview/llfloateravatar.h b/indra/newview/llfloateravatar.h
index 331a6b5ade..1f898e08a1 100644
--- a/indra/newview/llfloateravatar.h
+++ b/indra/newview/llfloateravatar.h
@@ -29,6 +29,7 @@
#define LL_FLOATER_AVATAR_H
#include "llfloater.h"
+class LLMediaCtrl;
class LLFloaterAvatar:
public LLFloater
@@ -39,6 +40,8 @@ private:
/*virtual*/ ~LLFloaterAvatar();
/*virtual*/ BOOL postBuild();
+ LLMediaCtrl* mAvatarPicker;
+
// Avatar chooser does not change between OpenSim grids
/*virtual*/ void onOpen(const LLSD& key);
void handleUrlChanged(const std::string& url);
diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp
index 7d15480091..71c0d8d57b 100644
--- a/indra/newview/llfloaterbump.cpp
+++ b/indra/newview/llfloaterbump.cpp
@@ -81,6 +81,14 @@ LLFloaterBump::LLFloaterBump(const LLSD& key)
// Destroys the object
LLFloaterBump::~LLFloaterBump()
{
+ // Improved bump list
+ //auto menu = mPopupMenuHandle.get();
+ //if (menu)
+ //{
+ // menu->die();
+ // mPopupMenuHandle.markDead();
+ //}
+ //
}
BOOL LLFloaterBump::postBuild()
@@ -90,11 +98,15 @@ BOOL LLFloaterBump::postBuild()
//mList->setAllowMultipleSelection(false);
//mList->setRightMouseDownCallback(boost::bind(&LLFloaterBump::onScrollListRightClicked, this, _1, _2, _3));
- //mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_avatar_other.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- //mPopupMenu->setItemVisible(std::string("Normal"), false);
- //mPopupMenu->setItemVisible(std::string("Always use impostor"), false);
- //mPopupMenu->setItemVisible(std::string("Never use impostor"), false);
- //mPopupMenu->setItemVisible(std::string("Impostor seperator"), false);
+ //LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_avatar_other.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ //if (menu)
+ //{
+ // mPopupMenuHandle = menu->getHandle();
+ // menu->setItemVisible(std::string("Normal"), false);
+ // menu->setItemVisible(std::string("Always use impostor"), false);
+ // menu->setItemVisible(std::string("Never use impostor"), false);
+ // menu->setItemVisible(std::string("Impostor seperator"), false);
+ //}
//return TRUE;
mList = getChild("bump_list");
@@ -227,18 +239,19 @@ void LLFloaterBump::onScrollListRightClicked(LLUICtrl* ctrl, S32 x, S32 y)
if (!gMeanCollisionList.empty())
{
LLScrollListItem* item = mList->hitItem(x, y);
- if (item && mPopupMenu)
+ auto menu = mPopupMenuHandle.get();
+ if (item && menu)
{
mItemUUID = item->getUUID();
- mPopupMenu->buildDrawLabels();
- mPopupMenu->updateParent(LLMenuGL::sMenuContainer);
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
std::string mute_msg = (LLMuteList::getInstance()->isMuted(mItemUUID, mNames[mItemUUID])) ? "UnmuteAvatar" : "MuteAvatar";
- mPopupMenu->getChild("Avatar Mute")->setValue(LLTrans::getString(mute_msg));
- mPopupMenu->setItemEnabled(std::string("Zoom In"), bool(gObjectList.findObject(mItemUUID)));
+ menu->getChild("Avatar Mute")->setValue(LLTrans::getString(mute_msg));
+ menu->setItemEnabled(std::string("Zoom In"), bool(gObjectList.findObject(mItemUUID)));
- ((LLContextMenu*)mPopupMenu)->show(x, y);
- LLMenuGL::showPopup(ctrl, mPopupMenu, x, y);
+ menu->show(x, y);
+ LLMenuGL::showPopup(ctrl, menu, x, y);
}
}
}
diff --git a/indra/newview/llfloaterbump.h b/indra/newview/llfloaterbump.h
index a951d53fdc..66414dd7d0 100644
--- a/indra/newview/llfloaterbump.h
+++ b/indra/newview/llfloaterbump.h
@@ -76,7 +76,7 @@ private:
// Improved bump list
//LLScrollListCtrl* mList;
- //LLMenuGL* mPopupMenu;
+ //LLHandle mPopupMenuHandle;
//LLUUID mItemUUID;
//typedef std::map uuid_map_t;
diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp
index da22c5ff6e..6a21486f7f 100644
--- a/indra/newview/llfloatercreatelandmark.cpp
+++ b/indra/newview/llfloatercreatelandmark.cpp
@@ -324,7 +324,6 @@ void LLFloaterCreateLandmark::onSaveClicked()
LLStringUtil::trim(current_title_value);
LLStringUtil::trim(current_notes_value);
- LLUUID item_id = mItem->getUUID();
LLUUID folder_id = mFolderCombo->getValue().asUUID();
bool change_parent = folder_id != mItem->getParentUUID();
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index af96c3ce22..c9d549dc6d 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -215,6 +215,7 @@ BOOL LLFloaterIMContainer::postBuild()
p.options_menu = "menu_conversation.xml";
mConversationsRoot = LLUICtrlFactory::create(p);
mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
+ mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar);
// Add listener to conversation model events
mConversationsEventStream.listen("ConversationsRefresh", boost::bind(&LLFloaterIMContainer::onConversationModelEvent, this, _1));
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 0bda09c1a2..11fb8d5931 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -318,6 +318,7 @@ BOOL LLFloaterIMSessionTab::postBuild()
p.name = "root";
mConversationsRoot = LLUICtrlFactory::create(p);
mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
+ mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar);
// Attach that root to the scroller
mScroller->addChild(mConversationsRoot);
mConversationsRoot->setScrollContainer(mScroller);
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index a822dcb6fc..9afbb35078 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -1938,7 +1938,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible)
childSetTextArg("download_weight", "[ST]", tbd);
childSetTextArg("server_weight", "[SIM]", tbd);
childSetTextArg("physics_weight", "[PH]", tbd);
- if (!mModelPhysicsFee.isMap() || mModelPhysicsFee.emptyMap())
+ if (!mModelPhysicsFee.isMap() || (mModelPhysicsFee.size() == 0))
{
childSetTextArg("upload_fee", "[FEE]", tbd);
}
diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp
index 361f54c2f1..980bdf530e 100644
--- a/indra/newview/llfloateropenobject.cpp
+++ b/indra/newview/llfloateropenobject.cpp
@@ -59,8 +59,6 @@ LLFloaterOpenObject::LLFloaterOpenObject(const LLSD& key)
{
// Cinder's fly-out button
//mCommitCallbackRegistrar.add("OpenObject.MoveToInventory", boost::bind(&LLFloaterOpenObject::onClickMoveToInventory, this));
- //mCommitCallbackRegistrar.add("OpenObject.MoveAndWear", boost::bind(&LLFloaterOpenObject::onClickMoveAndWear, this));
- //mCommitCallbackRegistrar.add("OpenObject.ReplaceOutfit", boost::bind(&LLFloaterOpenObject::onClickReplace, this));
mCommitCallbackRegistrar.add("OpenObject.CopyAction", boost::bind(&LLFloaterOpenObject::onClickCopy, this, _2));
//
mCommitCallbackRegistrar.add("OpenObject.Cancel", boost::bind(&LLFloaterOpenObject::onClickCancel, this));
@@ -260,18 +258,6 @@ void LLFloaterOpenObject::callbackMoveInventory(S32 result, void* data)
// moveToInventory(false);
// closeFloater();
//}
-//
-//void LLFloaterOpenObject::onClickMoveAndWear()
-//{
-// moveToInventory(true, false);
-// closeFloater();
-//}
-//
-//void LLFloaterOpenObject::onClickReplace()
-//{
-// moveToInventory(true, true);
-// closeFloater();
-//}
//
void LLFloaterOpenObject::onClickCancel()
diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h
index 3c0e6c1ddc..7dc4255b5e 100644
--- a/indra/newview/llfloateropenobject.h
+++ b/indra/newview/llfloateropenobject.h
@@ -64,8 +64,6 @@ protected:
// Cinder's fly-out button
//void onClickMoveToInventory();
- //void onClickMoveAndWear();
- //void onClickReplace();
void onClickCopy(const LLSD& value);
//
void onClickCancel();
diff --git a/indra/newview/llfloateroutfitphotopreview.cpp b/indra/newview/llfloateroutfitphotopreview.cpp
index 6c39db730c..ade258aef7 100644
--- a/indra/newview/llfloateroutfitphotopreview.cpp
+++ b/indra/newview/llfloateroutfitphotopreview.cpp
@@ -234,7 +234,6 @@ void LLFloaterOutfitPhotoPreview::updateImageID()
if(item)
{
mImageID = item->getAssetUUID();
- LLPermissions perm(item->getPermissions());
}
else
{
diff --git a/indra/newview/llfloaterpathfindinglinksets.cpp b/indra/newview/llfloaterpathfindinglinksets.cpp
index 1e46d7a402..03aede94c6 100644
--- a/indra/newview/llfloaterpathfindinglinksets.cpp
+++ b/indra/newview/llfloaterpathfindinglinksets.cpp
@@ -44,6 +44,7 @@
#include "llpathfindinglinkset.h"
#include "llpathfindinglinksetlist.h"
#include "llpathfindingmanager.h"
+#include "llsearcheditor.h"
#include "llscrolllistitem.h"
#include "llsd.h"
#include "lltextbase.h"
@@ -114,17 +115,13 @@ BOOL LLFloaterPathfindingLinksets::postBuild()
{
mBeaconColor = LLUIColorTable::getInstance()->getColor("PathfindingLinksetBeaconColor");
- mFilterByName = findChild("filter_by_name");
- llassert(mFilterByName != NULL);
- mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this));
- mFilterByName->setSelectAllonFocusReceived(true);
- mFilterByName->setCommitOnFocusLost(true);
+ mFilterByName = getChild("filter_by_name");
+ mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this));
+ mFilterByName->setCommitOnFocusLost(true);
- mFilterByDescription = findChild("filter_by_description");
- llassert(mFilterByDescription != NULL);
- mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this));
- mFilterByDescription->setSelectAllonFocusReceived(true);
- mFilterByDescription->setCommitOnFocusLost(true);
+ mFilterByDescription = getChild("filter_by_description");
+ mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this));
+ mFilterByDescription->setCommitOnFocusLost(true);
mFilterByLinksetUse = findChild("filter_by_linkset_use");
llassert(mFilterByLinksetUse != NULL);
diff --git a/indra/newview/llfloaterpathfindinglinksets.h b/indra/newview/llfloaterpathfindinglinksets.h
index 7149da9215..a954d8a8ec 100644
--- a/indra/newview/llfloaterpathfindinglinksets.h
+++ b/indra/newview/llfloaterpathfindinglinksets.h
@@ -42,6 +42,7 @@ class LLSD;
class LLTextBase;
class LLUICtrl;
class LLVector3;
+class LLSearchEditor;
class LLFloaterPathfindingLinksets : public LLFloaterPathfindingObjects
{
@@ -105,8 +106,8 @@ private:
LLPathfindingLinkset::ELinksetUse convertToLinksetUse(LLSD pXuiValue) const;
LLSD convertToXuiValue(LLPathfindingLinkset::ELinksetUse pLinksetUse) const;
- LLLineEditor *mFilterByName;
- LLLineEditor *mFilterByDescription;
+ LLSearchEditor *mFilterByName;
+ LLSearchEditor *mFilterByDescription;
LLComboBox *mFilterByLinksetUse;
LLComboBox *mEditLinksetUse;
LLScrollListItem *mEditLinksetUseUnset;
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index 1b97794c5a..db997c4a54 100644
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -421,7 +421,6 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
for(S32 i = 0; i < number_parcels; i++)
{
std::string parcel_name = content["parcels"][i]["name"].asString();
- LLUUID parcel_id = content["parcels"][i]["id"].asUUID();
S32 number_objects = content["parcels"][i]["objects"].size();
S32 local_id = 0;
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
index 77ed07f057..a9b802f5c3 100644
--- a/indra/newview/llfloatersearch.cpp
+++ b/indra/newview/llfloatersearch.cpp
@@ -48,7 +48,7 @@ class LLSearchHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
- LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { }
+ LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_CLICK_ONLY) { }
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
{
if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableSearch"))
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index e44c5b5ad2..dcd67c2fb3 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -130,7 +130,7 @@ class LLWorldMapHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
- LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE ) { }
+ LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_CLICK_ONLY ) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
@@ -174,7 +174,7 @@ class LLMapTrackAvatarHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
- LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_THROTTLE)
+ LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_CLICK_ONLY)
{
}
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index dac8a034e5..2e53c5048e 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -68,7 +68,32 @@ class LLGroupHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
- LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_THROTTLE) { }
+ LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_CLICK_ONLY) { }
+
+ virtual bool canHandleUntrusted(
+ const LLSD& params,
+ const LLSD& query_map,
+ LLMediaCtrl* web,
+ const std::string& nav_type)
+ {
+ if (params.size() < 1)
+ {
+ return true; // don't block, will fail later
+ }
+
+ if (nav_type == NAV_TYPE_CLICKED)
+ {
+ return true;
+ }
+
+ const std::string verb = params[0].asString();
+ if (verb == "create")
+ {
+ return false;
+ }
+ return true;
+ }
+
bool handle(const LLSD& tokens, const LLSD& query_map,
LLMediaCtrl* web)
{
diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp
index bef574e9e5..3b68ee7326 100644
--- a/indra/newview/llimprocessing.cpp
+++ b/indra/newview/llimprocessing.cpp
@@ -2309,7 +2309,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url)
return;
}
- if (messages.emptyArray())
+ if (messages.size() == 0)
{
// Nothing to process
return;
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 4c380d320e..b4c773fbb9 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -2396,8 +2396,6 @@ void LLOutgoingCallDialog::show(const LLSD& key)
std::string callee_name = mPayload["session_name"].asString();
- LLUUID session_id = mPayload["session_id"].asUUID();
-
if (callee_name == "anonymous") // obsolete? Likely was part of avaline support
{
callee_name = getString("anonymous");
@@ -2784,7 +2782,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload
}
}
- LLUUID new_session_id = gIMMgr->addSession(correct_session_name, type, session_id, true);
+ gIMMgr->addSession(correct_session_name, type, session_id, true);
std::string url = gAgent.getRegion()->getCapability(
"ChatSessionRequest");
@@ -2870,7 +2868,7 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
}
else
{
- LLUUID new_session_id = gIMMgr->addSession(
+ gIMMgr->addSession(
payload["session_name"].asString(),
type,
session_id, true);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index cd2bcbecf8..b1ed209835 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -899,6 +899,12 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
{
disabled_items.push_back(std::string("Find Original"));
}
+
+ items.push_back(std::string("Cut"));
+ if (!isItemMovable() || !isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Cut"));
+ }
}
else
{
@@ -2398,6 +2404,7 @@ bool LLItemBridge::isItemCopyable(bool can_copy_as_link) const
// [/SL:KB]
// static LLCachedControl inventory_linking(gSavedSettings, "InventoryLinking", true);
// return (can_copy_as_link && inventory_linking)
+// || (mIsLink && inventory_linking)
// || item->getPermissions().allowCopyBy(gAgent.getID());
}
@@ -2648,6 +2655,12 @@ BOOL LLFolderBridge::isUpToDate() const
bool LLFolderBridge::isItemCopyable(bool can_copy_as_link) const
{
+ if (can_copy_as_link && !LLFolderType::lookupIsProtectedType(getPreferredType()))
+ {
+ // Can copy and paste unprotected folders as links
+ return true;
+ }
+
// Folders are copyable if items in them are, recursively, copyable.
// Get the content of the folder
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 569c5c292c..82b9fa5772 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -497,7 +497,6 @@ bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInvent
bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) const
{
LLInventoryType::EType object_type = item->getInventoryType();
- const LLUUID object_id = item->getUUID();
const U32 filterTypes = mFilterOps.mFilterTypes;
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 9526bb7048..4c0b285193 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -1533,9 +1533,6 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol
LLNotificationsUtil::add("MerchantPasteFailed", subs);
return false;
}
-
- // Get the parent folder of the moved item : we may have to update it
- LLUUID src_folder = viewer_inv_item->getParentUUID();
if (copy)
{
diff --git a/indra/newview/llinventorylistitem.h b/indra/newview/llinventorylistitem.h
index 3d07116651..bb751927c5 100644
--- a/indra/newview/llinventorylistitem.h
+++ b/indra/newview/llinventorylistitem.h
@@ -201,6 +201,7 @@ protected:
virtual const LLPanelInventoryListItemBase::Params& getDefaultParams() const; // Better attachment list
const LLUUID mInventoryItemUUID;
+ bool mHovered;
private:
@@ -225,7 +226,6 @@ private:
LLUIImagePtr mSelectedImage;
LLUIImagePtr mSeparatorImage;
- bool mHovered;
bool mSelected;
bool mSeparatorVisible;
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 3368e29790..2d18101056 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1872,11 +1872,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo
// Can't have links to links, so there's no need for this update
// if the item removed is a link. Can also skip if source of the
// update is getting broken link info separately.
- obj = NULL; // delete obj
if (fix_broken_links && !is_link_type)
{
updateLinkedObjectsFromPurge(id);
}
+ obj = nullptr; // delete obj
if (do_notify_observers)
{
notifyObservers();
@@ -2964,7 +2964,6 @@ void LLInventoryModel::buildParentChildMap()
// some accounts has pbroken inventory root folders
std::string name = "My Inventory";
- LLUUID prev_root_id = mRootFolderID;
for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(),
it_end = mParentChildCategoryTree.end(); it != it_end; ++it)
{
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index b2b4754bb2..0a0b2269aa 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -233,7 +233,11 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
p.item_top_pad = default_params.item_top_pad - (default_params.item_height - fsFolderViewItemHeight) / 2 - 1;
//
- return LLUICtrlFactory::create(p);
+ LLFolderView* fv = LLUICtrlFactory::create(p);
+ fv->setCallbackRegistrar(&mCommitCallbackRegistrar);
+ fv->setEnableRegistrar(&mEnableCallbackRegistrar);
+
+ return fv;
}
void LLInventoryPanel::clearFolderRoot()
@@ -286,6 +290,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
}
mCommitCallbackRegistrar.popScope();
mFolderRoot.get()->setCallbackRegistrar(&mCommitCallbackRegistrar);
+ mFolderRoot.get()->setEnableRegistrar(&mEnableCallbackRegistrar);
// Scroller
LLRect scroller_view_rect = getRect();
diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp
index d3ba18525b..60f8aca94c 100644
--- a/indra/newview/llkeyconflict.cpp
+++ b/indra/newview/llkeyconflict.cpp
@@ -171,8 +171,9 @@ bool LLKeyConflictHandler::isReservedByMenu(const KEY &key, const MASK &mask)
{
return false;
}
- return (gMenuBarView && gMenuBarView->hasAccelerator(key, mask))
- || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(key, mask));
+ // At the moment controls are only applicable inworld,
+ // ignore gLoginMenuBarView
+ return gMenuBarView && gMenuBarView->hasAccelerator(key, mask);
}
// static
@@ -182,8 +183,7 @@ bool LLKeyConflictHandler::isReservedByMenu(const LLKeyData &data)
{
return false;
}
- return (gMenuBarView && gMenuBarView->hasAccelerator(data.mKey, data.mMask))
- || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(data.mKey, data.mMask));
+ return gMenuBarView && gMenuBarView->hasAccelerator(data.mKey, data.mMask);
}
bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask)
diff --git a/indra/newview/lllistcontextmenu.cpp b/indra/newview/lllistcontextmenu.cpp
index 6bda8b1d0d..77185411c5 100644
--- a/indra/newview/lllistcontextmenu.cpp
+++ b/indra/newview/lllistcontextmenu.cpp
@@ -51,6 +51,7 @@ LLListContextMenu::~LLListContextMenu()
if (!mMenuHandle.isDead())
{
mMenuHandle.get()->die();
+ mMenuHandle.markDead();
}
}
@@ -59,13 +60,8 @@ void LLListContextMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32
LLContextMenu* menup = mMenuHandle.get();
if (menup)
{
- //preventing parent (menu holder) from deleting already "dead" context menus on exit
- LLView* parent = menup->getParent();
- if (parent)
- {
- parent->removeChild(menup);
- }
- delete menup;
+ menup->die();
+ mMenuHandle.markDead();
mUUIDs.clear();
}
diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp
index c48923e643..3b59b2f05e 100644
--- a/indra/newview/llmaterialmgr.cpp
+++ b/indra/newview/llmaterialmgr.cpp
@@ -428,12 +428,10 @@ void LLMaterialMgr::onGetResponse(bool success, const LLSD& content, const LLUUI
llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
- LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
- std::string content_string(reinterpret_cast(content_binary.data()), content_binary.size());
- std::istringstream content_stream(content_string);
+ const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
LLSD response_data;
- U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size());
+ U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());
if (uzip_result != LLUZipHelper::ZR_OK)
{
LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL;
@@ -471,15 +469,10 @@ void LLMaterialMgr::onGetAllResponse(bool success, const LLSD& content, const LL
llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
- LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
- std::string content_string(reinterpret_cast(content_binary.data()), content_binary.size());
- std::istringstream content_stream(content_string);
+ const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
LLSD response_data;
- // Use new variant unzip_llsd
- // U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size());
U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());
- //
if (uzip_result != LLUZipHelper::ZR_OK)
{
LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL;
@@ -543,12 +536,10 @@ void LLMaterialMgr::onPutResponse(bool success, const LLSD& content)
llassert(content.has(MATERIALS_CAP_ZIP_FIELD));
llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary());
- LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
- std::string content_string(reinterpret_cast(content_binary.data()), content_binary.size());
- std::istringstream content_stream(content_string);
+ const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();
LLSD response_data;
- U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size());
+ U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());
if (uzip_result != LLUZipHelper::ZR_OK)
{
LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL;
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 5bba2f9e54..6e728b7f6d 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -112,7 +112,6 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
mTrusted(p.trusted_content),
mWindowShade(NULL),
mHoverTextChanged(false),
- mContextMenu(NULL),
mAllowFileDownload(false)
{
{
@@ -157,6 +156,13 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
LLMediaCtrl::~LLMediaCtrl()
{
+ auto menu = mContextMenuHandle.get();
+ if (menu)
+ {
+ menu->die();
+ mContextMenuHandle.markDead();
+ }
+
if (mMediaSource)
{
mMediaSource->remObserver( this );
@@ -342,15 +348,33 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask )
setFocus( TRUE );
}
- if (mContextMenu)
+ auto menu = mContextMenuHandle.get();
+ if (!menu)
+ {
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar;
+ registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this));
+
+ // stinson 05/05/2014 : use this as the parent of the context menu if the static menu
+ // container has yet to be created
+ LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast(LLMenuGL::sMenuContainer) : dynamic_cast(this);
+ llassert(menuParent != NULL);
+ menu = LLUICtrlFactory::getInstance()->createFromFile(
+ "menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance());
+ if (menu)
+ {
+ mContextMenuHandle = menu->getHandle();
+ }
+ }
+
+ if (menu)
{
// hide/show debugging options
bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging");
- mContextMenu->setItemVisible("open_webinspector", media_plugin_debugging_enabled );
- mContextMenu->setItemVisible("debug_separator", media_plugin_debugging_enabled );
+ menu->setItemVisible("open_webinspector", media_plugin_debugging_enabled );
+ menu->setItemVisible("debug_separator", media_plugin_debugging_enabled );
- mContextMenu->show(x, y);
- LLMenuGL::showPopup(this, mContextMenu, x, y);
+ menu->show(x, y);
+ LLMenuGL::showPopup(this, menu, x, y);
}
return TRUE;
@@ -460,15 +484,6 @@ void LLMediaCtrl::setFocus(BOOL b)
//
BOOL LLMediaCtrl::postBuild ()
{
- LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar;
- registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this));
-
- // stinson 05/05/2014 : use this as the parent of the context menu if the static menu
- // container has yet to be created
- LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast(LLMenuGL::sMenuContainer) : dynamic_cast(this);
- llassert(menuParent != NULL);
- mContextMenu = LLUICtrlFactory::getInstance()->createFromFile(
- "menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance());
setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2));
return TRUE;
@@ -1300,11 +1315,6 @@ void LLMediaCtrl::setTrustedContent(bool trusted)
}
}
-void LLMediaCtrl::updateContextMenuParent(LLView* pNewParent)
-{
- mContextMenu->updateParent(pNewParent);
-}
-
bool LLMediaCtrl::wantsKeyUpKeyDown() const
{
return true;
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 2372e3d7b0..0f1bcb6f75 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -175,8 +175,6 @@ public:
LLUUID getTextureID() {return mMediaTextureID;}
- void updateContextMenuParent(LLView* pNewParent);
-
// The Browser windows want keyup and keydown events. Overridden from LLFocusableElement to return true.
virtual bool wantsKeyUpKeyDown() const;
virtual bool wantsReturnKey() const;
@@ -221,7 +219,7 @@ public:
mTextureHeight;
class LLWindowShade* mWindowShade;
- LLContextMenu* mContextMenu;
+ LLHandle mContextMenuHandle;
};
#endif // LL_LLMediaCtrl_H
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 4c6b0ec406..84d85b8ef8 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -77,6 +77,8 @@
#include "lluploaddialog.h"
#include "llfloaterreg.h"
+#include "boost/iostreams/device/array.hpp"
+#include "boost/iostreams/stream.hpp"
#include "boost/lexical_cast.hpp"
// Reduce temporaries and copes in decoding mesh headers
#include
@@ -143,7 +145,7 @@
// data copied
// headerReceived() invoked
// LLSD parsed
-// mMeshHeader, mMeshHeaderSize updated
+// mMeshHeader updated
// scan mPendingLOD for LOD request
// push LODRequest to mLODReqQ
// ...
@@ -251,7 +253,6 @@
// sActiveLODRequests mMutex rw.any.mMutex, ro.repo.none [1]
// sMaxConcurrentRequests mMutex wo.main.none, ro.repo.none, ro.main.mMutex
// mMeshHeader mHeaderMutex rw.repo.mHeaderMutex, ro.main.mHeaderMutex, ro.main.none [0]
-// mMeshHeaderSize mHeaderMutex rw.repo.mHeaderMutex
// mSkinRequests mMutex rw.repo.mMutex, ro.repo.none [5]
// mSkinInfoQ mMutex rw.repo.mMutex, rw.main.mMutex [5] (was: [0])
// mDecompositionRequests mMutex rw.repo.mMutex, ro.repo.none [5]
@@ -887,6 +888,12 @@ LLMeshRepoThread::~LLMeshRepoThread()
mHttpRequestSet.clear();
mHttpHeaders.reset();
+ while (!mSkinInfoQ.empty())
+ {
+ delete mSkinInfoQ.front();
+ mSkinInfoQ.pop_front();
+ }
+
while (!mDecompositionQ.empty())
{
delete mDecompositionQ.front();
@@ -976,7 +983,8 @@ void LLMeshRepoThread::run()
else
{
// too many fails
- mUnavailableQ.push(req);
+ LLMutexLock lock(mMutex);
+ mUnavailableQ.push_back(req);
LL_WARNS() << "Failed to load " << req.mMeshParams << " , skip" << LL_ENDL;
}
}
@@ -1052,37 +1060,42 @@ void LLMeshRepoThread::run()
if (!mSkinRequests.empty())
{
- std::set incomplete;
- while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater)
- {
- mMutex->lock();
- std::set::iterator iter = mSkinRequests.begin();
- UUIDBasedRequest req = *iter;
- mSkinRequests.erase(iter);
- mMutex->unlock();
- if (req.isDelayed())
- {
- incomplete.insert(req);
- }
- else if (!fetchMeshSkinInfo(req.mId))
- {
- if (req.canRetry())
- {
- req.updateTime();
- incomplete.insert(req);
- }
- else
- {
- LL_DEBUGS() << "mSkinRequests failed: " << req.mId << LL_ENDL;
- }
- }
- }
+ std::list incomplete;
+ while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater)
+ {
- if (!incomplete.empty())
- {
- LLMutexLock locker(mMutex);
- mSkinRequests.insert(incomplete.begin(), incomplete.end());
- }
+ mMutex->lock();
+ auto req = mSkinRequests.front();
+ mSkinRequests.pop_front();
+ mMutex->unlock();
+ if (req.isDelayed())
+ {
+ incomplete.emplace_back(req);
+ }
+ else if (!fetchMeshSkinInfo(req.mId, req.canRetry()))
+ {
+ if (req.canRetry())
+ {
+ req.updateTime();
+ incomplete.emplace_back(req);
+ }
+ else
+ {
+ LLMutexLock locker(mMutex);
+ mSkinUnavailableQ.push_back(req);
+ LL_DEBUGS() << "mSkinReqQ failed: " << req.mId << LL_ENDL;
+ }
+ }
+ }
+
+ if (!incomplete.empty())
+ {
+ LLMutexLock locker(mMutex);
+ for (const auto& req : incomplete)
+ {
+ mSkinRequests.push_back(req);
+ }
+ }
}
// holding lock, try next list
@@ -1181,7 +1194,7 @@ void LLMeshRepoThread::run()
// Mutex: LLMeshRepoThread::mMutex must be held on entry
void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id)
{
- mSkinRequests.insert(UUIDBasedRequest(mesh_id));
+ mSkinRequests.push_back(UUIDBasedRequest(mesh_id));
}
// Mutex: LLMeshRepoThread::mMutex must be held on entry
@@ -1207,10 +1220,13 @@ void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32
void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
{ //could be called from any thread
+ const LLUUID& mesh_id = mesh_params.getSculptID();
LLMutexLock lock(mMutex);
- mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID());
+ LLMutexLock header_lock(mHeaderMutex);
+ mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
if (iter != mMeshHeader.end())
{ //if we have the header, request LOD byte range
+
LODRequest req(mesh_params, lod);
{
mLODReqQ.push(req);
@@ -1220,8 +1236,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
else
{
HeaderRequest req(mesh_params);
-
- pending_lod_map::iterator pending = mPendingLOD.find(mesh_params);
+ pending_lod_map::iterator pending = mPendingLOD.find(mesh_id);
if (pending != mPendingLOD.end())
{ //append this lod request to existing header request
@@ -1231,7 +1246,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
else
{ //if no header request is pending, fetch header
mHeaderReqQ.push(req);
- mPendingLOD[mesh_params].push_back(lod);
+ mPendingLOD[mesh_id].push_back(lod);
}
}
}
@@ -1374,7 +1389,7 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int l
}
-bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
+bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)
{
if (!mHeaderMutex)
@@ -1384,7 +1399,8 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
mHeaderMutex->lock();
- if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
+ auto header_it = mMeshHeader.find(mesh_id);
+ if (header_it == mMeshHeader.end())
{ //we have no header info for this mesh, do nothing
mHeaderMutex->unlock();
return false;
@@ -1392,13 +1408,14 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
++LLMeshRepository::sMeshRequestCount;
bool ret = true;
- U32 header_size = mMeshHeaderSize[mesh_id];
+ U32 header_size = header_it->second.first;
if (header_size > 0)
{
- S32 version = mMeshHeader[mesh_id]["version"].asInteger();
- S32 offset = header_size + mMeshHeader[mesh_id]["skin"]["offset"].asInteger();
- S32 size = mMeshHeader[mesh_id]["skin"]["size"].asInteger();
+ const LLSD& header = header_it->second.second;
+ S32 version = header["version"].asInteger();
+ S32 offset = header_size + header["skin"]["offset"].asInteger();
+ S32 size = header["skin"]["size"].asInteger();
mHeaderMutex->unlock();
@@ -1461,12 +1478,27 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
<< LL_ENDL;
ret = false;
}
- else
+ else if(can_retry)
{
handler->mHttpHandle = handle;
mHttpRequestSet.insert(handler);
}
+ else
+ {
+ LLMutexLock locker(mMutex);
+ mSkinUnavailableQ.emplace_back(mesh_id);
+ }
}
+ else
+ {
+ LLMutexLock locker(mMutex);
+ mSkinUnavailableQ.emplace_back(mesh_id);
+ }
+ }
+ else
+ {
+ LLMutexLock locker(mMutex);
+ mSkinUnavailableQ.emplace_back(mesh_id);
}
}
else
@@ -1487,21 +1519,23 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
mHeaderMutex->lock();
- if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
+ auto header_it = mMeshHeader.find(mesh_id);
+ if (header_it == mMeshHeader.end())
{ //we have no header info for this mesh, do nothing
mHeaderMutex->unlock();
return false;
}
++LLMeshRepository::sMeshRequestCount;
- U32 header_size = mMeshHeaderSize[mesh_id];
+ U32 header_size = header_it->second.first;
bool ret = true;
if (header_size > 0)
{
- S32 version = mMeshHeader[mesh_id]["version"].asInteger();
- S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger();
- S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger();
+ const auto& header = header_it->second.second;
+ S32 version = header["version"].asInteger();
+ S32 offset = header_size + header["physics_convex"]["offset"].asInteger();
+ S32 size = header["physics_convex"]["size"].asInteger();
mHeaderMutex->unlock();
@@ -1591,21 +1625,23 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
mHeaderMutex->lock();
- if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
+ auto header_it = mMeshHeader.find(mesh_id);
+ if (header_it == mMeshHeader.end())
{ //we have no header info for this mesh, do nothing
mHeaderMutex->unlock();
return false;
}
++LLMeshRepository::sMeshRequestCount;
- U32 header_size = mMeshHeaderSize[mesh_id];
+ U32 header_size = header_it->second.first;
bool ret = true;
if (header_size > 0)
{
- S32 version = mMeshHeader[mesh_id]["version"].asInteger();
- S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger();
- S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger();
+ const auto& header = header_it->second.second;
+ S32 version = header["version"].asInteger();
+ S32 offset = header_size + header["physics_mesh"]["offset"].asInteger();
+ S32 size = header["physics_mesh"]["size"].asInteger();
mHeaderMutex->unlock();
@@ -1799,20 +1835,25 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
return false;
}
- mHeaderMutex->lock();
+ const LLUUID& mesh_id = mesh_params.getSculptID();
+ mHeaderMutex->lock();
+ auto header_it = mMeshHeader.find(mesh_id);
+ if (header_it == mMeshHeader.end())
+ { //we have no header info for this mesh, do nothing
+ mHeaderMutex->unlock();
+ return false;
+ }
++LLMeshRepository::sMeshRequestCount;
bool retval = true;
-
- LLUUID mesh_id = mesh_params.getSculptID();
- U32 header_size = mMeshHeaderSize[mesh_id];
-
+ U32 header_size = header_it->second.first;
if (header_size > 0)
{
- S32 version = mMeshHeader[mesh_id]["version"].asInteger();
- S32 offset = header_size + mMeshHeader[mesh_id][header_lod[lod]]["offset"].asInteger();
- S32 size = mMeshHeader[mesh_id][header_lod[lod]]["size"].asInteger();
+ const auto& header = header_it->second.second;
+ S32 version = header["version"].asInteger();
+ S32 offset = header_size + header[header_lod[lod]]["offset"].asInteger();
+ S32 size = header[header_lod[lod]]["size"].asInteger();
mHeaderMutex->unlock();
if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)
@@ -1894,17 +1935,20 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
}
else
{
- mUnavailableQ.push(LODRequest(mesh_params, lod));
+ LLMutexLock lock(mMutex);
+ mUnavailableQ.push_back(LODRequest(mesh_params, lod));
}
}
else
{
- mUnavailableQ.push(LODRequest(mesh_params, lod));
+ LLMutexLock lock(mMutex);
+ mUnavailableQ.push_back(LODRequest(mesh_params, lod));
}
}
else
{
- mUnavailableQ.push(LODRequest(mesh_params, lod));
+ LLMutexLock lock(mMutex);
+ mUnavailableQ.push_back(LODRequest(mesh_params, lod));
}
}
else
@@ -1923,35 +1967,12 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
U32 header_size = 0;
if (data_size > 0)
{
- // Reduce temporaries and copes in decoding mesh headers
- // std::istringstream stream;
- // try
- // {
- // std::string res_str((char*)data, data_size);
-
- // std::string deprecated_header(" LLSD/Binary ?>");
-
- // if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
- // {
- // res_str = res_str.substr(deprecated_header.size() + 1, data_size);
- // header_size = deprecated_header.size() + 1;
- // }
- // data_size = res_str.size();
-
- // stream.str(res_str);
- // }
- // catch (std::bad_alloc&)
- // {
- // // out of memory, we won't be able to process this mesh
- // return MESH_OUT_OF_MEMORY;
- // }
U32 dsize = data_size;
char* result_ptr = strip_deprecated_header((char*)data, dsize, &header_size);
data_size = dsize;
boost::iostreams::stream stream(result_ptr, data_size);
- //
if (!LLSDSerialize::fromBinary(header, stream, data_size))
{
@@ -1988,8 +2009,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
{
LLMutexLock lock(mHeaderMutex);
- mMeshHeaderSize[mesh_id] = header_size;
- mMeshHeader[mesh_id] = header;
+ mMeshHeader[mesh_id] = { header_size, header };
LLMeshRepository::sCacheBytesHeaders += header_size;
}
@@ -1997,7 +2017,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time.
//check for pending requests
- pending_lod_map::iterator iter = mPendingLOD.find(mesh_params);
+ pending_lod_map::iterator iter = mPendingLOD.find(mesh_id);
if (iter != mPendingLOD.end())
{
for (U32 i = 0; i < iter->second.size(); ++i)
@@ -2021,29 +2041,14 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p
}
LLPointer volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod));
- // Reduce temporaries and copes in decoding mesh headers
- // std::istringstream stream;
- // try
- // {
- // std::string mesh_string((char*)data, data_size);
- // stream.str(mesh_string);
- // }
- // catch (std::bad_alloc&)
- // {
- // // out of memory, we won't be able to process this mesh
- // return MESH_OUT_OF_MEMORY;
- // }
-
- // if (volume->unpackVolumeFaces(stream, data_size))
if (volume->unpackVolumeFaces(data, data_size))
- //
{
if (volume->getNumFaces() > 0)
{
LoadedMesh mesh(volume, mesh_params, lod);
{
LLMutexLock lock(mMutex);
- mLoadedQ.push(mesh);
+ mLoadedQ.push_back(mesh);
// LLPointer is not thread safe, since we added this pointer into
// threaded list, make sure counter gets decreased inside mutex lock
// and won't affect mLoadedQ processing
@@ -2066,13 +2071,7 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat
{
try
{
- // Reduce temporaries and copes in decoding mesh headers
- // std::string res_str((char*)data, data_size);
- // std::istringstream stream(res_str);
-
- // U32 uzip_result = LLUZipHelper::unzip_llsd(skin, stream, data_size);
U32 uzip_result = LLUZipHelper::unzip_llsd(skin, data, data_size);
- //
if (uzip_result != LLUZipHelper::ZR_OK)
{
LL_WARNS(LOG_MESH) << "Mesh skin info parse error. Not a valid mesh asset! ID: " << mesh_id
@@ -2089,8 +2088,16 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat
}
{
- LLMeshSkinInfo info(skin);
- info.mMeshID = mesh_id;
+ LLMeshSkinInfo* info = nullptr;
+ try
+ {
+ info = new LLMeshSkinInfo(mesh_id, skin);
+ }
+ catch (const std::bad_alloc& ex)
+ {
+ LL_WARNS() << "Failed to allocate skin info with exception: " << ex.what() << LL_ENDL;
+ return false;
+ }
// LL_DEBUGS(LOG_MESH) << "info pelvis offset" << info.mPelvisOffset << LL_ENDL;
{
@@ -2110,13 +2117,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3
{
try
{
- // Reduce temporaries and copes in decoding mesh headers
- // std::string res_str((char*)data, data_size);
- // std::istringstream stream(res_str);
-
- // U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, stream, data_size);
U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, data, data_size);
- //
if (uzip_result != LLUZipHelper::ZR_OK)
{
LL_WARNS(LOG_MESH) << "Mesh decomposition parse error. Not a valid mesh asset! ID: " << mesh_id
@@ -2125,7 +2126,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3
return false;
}
}
- catch (const std::bad_alloc&) // const cos const!
+ catch (const std::bad_alloc&)
{
LL_WARNS(LOG_MESH) << "Out of memory for mesh ID " << mesh_id << " of size: " << data_size << LL_ENDL;
return false;
@@ -2162,21 +2163,6 @@ EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_
volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH);
LLPointer volume = new LLVolume(volume_params,0);
- // Reduce temporaries and copes in decoding mesh headers
- // std::istringstream stream;
- // try
- // {
- // std::string mesh_string((char*)data, data_size);
- // stream.str(mesh_string);
- // }
- // catch (std::bad_alloc&)
- // {
- // // out of memory, we won't be able to process this mesh
- // delete d;
- // return MESH_OUT_OF_MEMORY;
- // }
-
- // if (volume->unpackVolumeFaces(stream, data_size))
if (volume->unpackVolumeFaces(data, data_size))
{
d->mPhysicsShapeMesh.clear();
@@ -2988,58 +2974,72 @@ void LLMeshRepoThread::notifyLoadedMeshes()
return;
}
- while (!mLoadedQ.empty())
+ if (!mLoadedQ.empty())
{
+ std::deque loaded_queue;
+
mMutex->lock();
- if (mLoadedQ.empty())
+ if (!mLoadedQ.empty())
{
+ loaded_queue.swap(mLoadedQ);
mMutex->unlock();
- break;
- }
- LoadedMesh mesh = mLoadedQ.front(); // make sure nothing else owns volume pointer by this point
- mLoadedQ.pop();
- mMutex->unlock();
-
- update_metrics = true;
- if (mesh.mVolume->getNumVolumeFaces() > 0)
- {
- gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume);
- }
- else
- {
- gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams,
- LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail()));
+
+ update_metrics = true;
+
+ // Process the elements free of the lock
+ for (const auto& mesh : loaded_queue)
+ {
+ if (mesh.mVolume->getNumVolumeFaces() > 0)
+ {
+ gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume);
+ }
+ else
+ {
+ gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams,
+ LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail()));
+ }
+ }
}
}
- while (!mUnavailableQ.empty())
+ if (!mUnavailableQ.empty())
{
- mMutex->lock();
- if (mUnavailableQ.empty())
- {
- mMutex->unlock();
- break;
- }
-
- LODRequest req = mUnavailableQ.front();
- mUnavailableQ.pop();
- mMutex->unlock();
+ std::deque unavil_queue;
- update_metrics = true;
- gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD);
+ mMutex->lock();
+ if (!mUnavailableQ.empty())
+ {
+ unavil_queue.swap(mUnavailableQ);
+ mMutex->unlock();
+
+ update_metrics = true;
+
+ // Process the elements free of the lock
+ for (const auto& req : unavil_queue)
+ {
+ gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD);
+ }
+ }
}
- if (! mSkinInfoQ.empty() || ! mDecompositionQ.empty())
+ if (!mSkinInfoQ.empty() || !mSkinUnavailableQ.empty() || ! mDecompositionQ.empty())
{
if (mMutex->trylock())
{
- std::list skin_info_q;
+ std::deque skin_info_q;
+ std::deque skin_info_unavail_q;
std::list decomp_q;
if (! mSkinInfoQ.empty())
{
skin_info_q.swap(mSkinInfoQ);
}
+
+ if (! mSkinUnavailableQ.empty())
+ {
+ skin_info_unavail_q.swap(mSkinUnavailableQ);
+ }
+
if (! mDecompositionQ.empty())
{
decomp_q.swap(mDecompositionQ);
@@ -3053,6 +3053,11 @@ void LLMeshRepoThread::notifyLoadedMeshes()
gMeshRepo.notifySkinInfoReceived(skin_info_q.front());
skin_info_q.pop_front();
}
+ while (! skin_info_unavail_q.empty())
+ {
+ gMeshRepo.notifySkinInfoUnavailable(skin_info_unavail_q.front().mId);
+ skin_info_unavail_q.pop_front();
+ }
while (! decomp_q.empty())
{
@@ -3077,7 +3082,7 @@ S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo
if (iter != mMeshHeader.end())
{
- LLSD& header = iter->second;
+ LLSD& header = iter->second.second;
return LLMeshRepository::getActualMeshLOD(header, lod);
}
@@ -3283,7 +3288,7 @@ void LLMeshHeaderHandler::processFailure(LLCore::HttpStatus status)
LLMutexLock lock(gMeshRepo.mThread->mMutex);
for (int i(0); i < 4; ++i)
{
- gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i));
+ gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i));
}
}
@@ -3312,7 +3317,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
LLMutexLock lock(gMeshRepo.mThread->mMutex);
for (int i(0); i < 4; ++i)
{
- gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i));
+ gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i));
}
}
else if (data && data_size > 0)
@@ -3325,8 +3330,8 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
LLMeshRepoThread::mesh_header_map::iterator iter = gMeshRepo.mThread->mMeshHeader.find(mesh_id);
if (iter != gMeshRepo.mThread->mMeshHeader.end())
{
- header_bytes = (S32)gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
- header = iter->second;
+ header_bytes = (S32)iter->second.first;
+ header = iter->second.second;
}
if (header_bytes > 0
@@ -3394,7 +3399,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b
LLMutexLock lock(gMeshRepo.mThread->mMutex);
for (int i(0); i < 4; ++i)
{
- gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i));
+ gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i));
}
}
}
@@ -3421,7 +3426,7 @@ void LLMeshLODHandler::processFailure(LLCore::HttpStatus status)
<< LL_ENDL;
LLMutexLock lock(gMeshRepo.mThread->mMutex);
- gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
+ gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
}
void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */,
@@ -3458,7 +3463,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
<< " Not retrying."
<< LL_ENDL;
LLMutexLock lock(gMeshRepo.mThread->mMutex);
- gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
+ gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
}
}
else
@@ -3469,7 +3474,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
<< " Data size: " << data_size
<< LL_ENDL;
LLMutexLock lock(gMeshRepo.mThread->mMutex);
- gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
+ gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
}
}
@@ -3487,9 +3492,8 @@ void LLMeshSkinInfoHandler::processFailure(LLCore::HttpStatus status)
<< ", Reason: " << status.toString()
<< " (" << status.toTerseString() << "). Not retrying."
<< LL_ENDL;
-
- // *TODO: Mark mesh unavailable on error. For now, simply leave
- // request unfulfilled rather than retry forever.
+ LLMutexLock lock(gMeshRepo.mThread->mMutex);
+ gMeshRepo.mThread->mSkinUnavailableQ.emplace_back(mMeshID);
}
void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */,
@@ -3520,7 +3524,8 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /*
LL_WARNS(LOG_MESH) << "Error during mesh skin info processing. ID: " << mMeshID
<< ", Unknown reason. Not retrying."
<< LL_ENDL;
- // *TODO: Mark mesh unavailable on error
+ LLMutexLock lock(gMeshRepo.mThread->mMutex);
+ gMeshRepo.mThread->mSkinUnavailableQ.emplace_back(mMeshID);
}
}
@@ -3630,7 +3635,7 @@ LLMeshRepository::LLMeshRepository()
mLegacyGetMeshVersion(0), // [UDP Assets]
mThread(NULL)
{
-
+ mSkinInfoCullTimer.resetWithExpiry(10.f);
}
void LLMeshRepository::init()
@@ -3731,6 +3736,22 @@ S32 LLMeshRepository::update()
return size ;
}
+void LLMeshRepository::unregisterMesh(LLVOVolume* vobj)
+{
+ for (auto& lod : mLoadingMeshes)
+ {
+ for (auto& param : lod)
+ {
+ vector_replace_with_last(param.second, vobj);
+ }
+ }
+
+ for (auto& skin_pair : mLoadingSkins)
+ {
+ vector_replace_with_last(skin_pair.second, vobj);
+ }
+}
+
S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail, S32 last_lod)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; //LL_LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH);
@@ -3746,15 +3767,19 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
{
LLMutexLock lock(mMeshMutex);
//add volume to list of loading meshes
- mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_params);
+ const auto& mesh_id = mesh_params.getSculptID();
+ mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_id);
if (iter != mLoadingMeshes[detail].end())
{ //request pending for this mesh, append volume id to list
- iter->second.insert(vobj->getID());
+ auto it = std::find(iter->second.begin(), iter->second.end(), vobj);
+ if (it == iter->second.end()) {
+ iter->second.push_back(vobj);
+ }
}
else
{
//first request for this mesh
- mLoadingMeshes[detail][mesh_params].insert(vobj->getID());
+ mLoadingMeshes[detail][mesh_id].push_back(vobj);
mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail));
LLMeshRepository::sLODPending++;
}
@@ -3967,6 +3992,28 @@ void LLMeshRepository::notifyLoadedMeshes()
//call completed callbacks on finished decompositions
mDecompThread->notifyCompleted();
+ if (mSkinInfoCullTimer.checkExpirationAndReset(10.f))
+ {
+ //// Clean up dead skin info
+ //U64Bytes skinbytes(0);
+ for (auto iter = mSkinMap.begin(), ender = mSkinMap.end(); iter != ender;)
+ {
+ auto copy_iter = iter++;
+
+ //skinbytes += U64Bytes(sizeof(LLMeshSkinInfo));
+ //skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(std::string));
+ //skinbytes += U64Bytes(copy_iter->second->mJointNums.size() * sizeof(S32));
+ //skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(LLMatrix4a));
+ //skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(LLMatrix4));
+
+ if (copy_iter->second->getNumRefs() == 1)
+ {
+ mSkinMap.erase(copy_iter);
+ }
+ }
+ //LL_INFOS() << "Skin info cache elements:" << mSkinMap.size() << " Memory: " << U64Kilobytes(skinbytes) << LL_ENDL;
+ }
+
// For major operations, attempt to get the required locks
// without blocking and punt if they're not available. The
// longest run of holdoffs is kept in sMaxLockHoldoffs just
@@ -4051,10 +4098,9 @@ void LLMeshRepository::notifyLoadedMeshes()
for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter)
{
F32 max_score = 0.f;
- for (std::set::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
+ for (auto obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
{
- LLViewerObject* object = gObjectList.findObject(*obj_iter);
-
+ LLVOVolume* object = *obj_iter;
if (object)
{
LLDrawable* drawable = object->mDrawable;
@@ -4066,7 +4112,7 @@ void LLMeshRepository::notifyLoadedMeshes()
}
}
- score_map[iter->first.getSculptID()] = max_score;
+ score_map[iter->first] = max_score;
}
}
@@ -4118,24 +4164,39 @@ void LLMeshRepository::notifyLoadedMeshes()
mThread->mSignal->signal();
}
-void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info)
+void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo* info)
{
- mSkinMap[info.mMeshID] = info;
+ mSkinMap[info->mMeshID] = info; // Cache into LLPointer
// Alternative: We can get skin size from header
- sCacheBytesSkins += info.sizeBytes();
+ sCacheBytesSkins += info->sizeBytes();
- skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID);
+ skin_load_map::iterator iter = mLoadingSkins.find(info->mMeshID);
if (iter != mLoadingSkins.end())
{
- for (std::set::iterator obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id)
+ for (LLVOVolume* vobj : iter->second)
{
- LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*obj_id);
if (vobj)
{
- vobj->notifyMeshLoaded();
+ vobj->notifySkinInfoLoaded(info);
}
}
- mLoadingSkins.erase(info.mMeshID);
+ mLoadingSkins.erase(iter);
+ }
+}
+
+void LLMeshRepository::notifySkinInfoUnavailable(const LLUUID& mesh_id)
+{
+ skin_load_map::iterator iter = mLoadingSkins.find(mesh_id);
+ if (iter != mLoadingSkins.end())
+ {
+ for (LLVOVolume* vobj : iter->second)
+ {
+ if (vobj)
+ {
+ vobj->notifySkinInfoUnavailable();
+ }
+ }
+ mLoadingSkins.erase(iter);
}
}
@@ -4164,14 +4225,15 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
S32 detail = LLVolumeLODGroup::getVolumeDetailFromScale(volume->getDetail());
//get list of objects waiting to be notified this mesh is loaded
- mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh_params);
+ const auto& mesh_id = mesh_params.getSculptID();
+ mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh_id);
if (volume && obj_iter != mLoadingMeshes[detail].end())
{
//make sure target volume is still valid
if (volume->getNumVolumeFaces() <= 0)
{
- LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume. ID: " << mesh_params.getSculptID()
+ LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume. ID: " << mesh_id
<< LL_ENDL;
}
@@ -4185,37 +4247,35 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
}
else
{
- LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_params.getSculptID()
+ LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_id
<< LL_ENDL;
}
}
//notify waiting LLVOVolume instances that their requested mesh is available
- for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter)
+ for (LLVOVolume* vobj : obj_iter->second)
{
- LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter);
if (vobj)
{
vobj->notifyMeshLoaded();
}
}
- mLoadingMeshes[detail].erase(mesh_params);
+ mLoadingMeshes[detail].erase(obj_iter);
}
}
void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod)
{ //called from main thread
//get list of objects waiting to be notified this mesh is loaded
- mesh_load_map::iterator obj_iter = mLoadingMeshes[lod].find(mesh_params);
-
- F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod);
-
+ const auto& mesh_id = mesh_params.getSculptID();
+ mesh_load_map::iterator obj_iter = mLoadingMeshes[lod].find(mesh_id);
if (obj_iter != mLoadingMeshes[lod].end())
{
- for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter)
+ F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod);
+
+ for (LLVOVolume* vobj : obj_iter->second)
{
- LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter);
if (vobj)
{
LLVolume* obj_volume = vobj->getVolume();
@@ -4229,7 +4289,7 @@ void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params,
}
}
- mLoadingMeshes[lod].erase(mesh_params);
+ mLoadingMeshes[lod].erase(obj_iter);
}
}
@@ -4238,7 +4298,7 @@ S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo
return mThread->getActualMeshLOD(mesh_params, lod);
}
-const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj)
+const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;
if (mesh_id.notNull())
@@ -4246,7 +4306,7 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const
skin_map::iterator iter = mSkinMap.find(mesh_id);
if (iter != mSkinMap.end())
{
- return &(iter->second);
+ return iter->second;
}
//no skin info known about given mesh, try to fetch it
@@ -4255,14 +4315,22 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const
LLMutexLock lock(mMeshMutex);
//add volume to list of loading meshes
skin_load_map::iterator iter = mLoadingSkins.find(mesh_id);
- if (iter == mLoadingSkins.end())
- { //no request pending for this skin info
+ if (iter != mLoadingSkins.end())
+ { //request pending for this mesh, append volume id to list
+ auto it = std::find(iter->second.begin(), iter->second.end(), requesting_obj);
+ if (it == iter->second.end()) {
+ iter->second.push_back(requesting_obj);
+ }
+ }
+ else
+ {
+ //first request for this mesh
+ mLoadingSkins[mesh_id].push_back(requesting_obj);
mPendingSkinRequests.push(mesh_id);
}
- mLoadingSkins[mesh_id].insert(requesting_obj->getID());
}
}
- return NULL;
+ return nullptr;
}
void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id)
@@ -4365,16 +4433,13 @@ bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id)
bool LLMeshRepoThread::hasPhysicsShapeInHeader(const LLUUID& mesh_id)
{
LLMutexLock lock(mHeaderMutex);
- if (mMeshHeaderSize[mesh_id] > 0)
+ mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
+ if (iter != mMeshHeader.end() && iter->second.first > 0)
{
- mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
- if (iter != mMeshHeader.end())
+ LLSD &mesh = iter->second.second;
+ if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0))
{
- LLSD &mesh = iter->second;
- if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0))
- {
- return true;
- }
+ return true;
}
}
@@ -4395,16 +4460,13 @@ LLUUID LLMeshRepository::getCreatorFromHeader(const LLUUID& mesh_id)
LLUUID LLMeshRepoThread::getCreatorFromHeader(const LLUUID& mesh_id)
{
LLMutexLock lock(mHeaderMutex);
- if (mMeshHeaderSize[mesh_id] > 0)
+ mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
+ if (iter != mMeshHeader.end() && iter->second.first > 0)
{
- mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);
- if (iter != mMeshHeader.end())
+ LLSD& mesh = iter->second.second;
+ if (mesh.has("creator") && mesh["creator"].isUUID())
{
- LLSD& mesh = iter->second;
- if (mesh.has("creator") && mesh["creator"].isUUID())
- {
- return mesh["creator"].asUUID();
- }
+ return mesh["creator"].asUUID();
}
}
@@ -4429,9 +4491,9 @@ S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
{
LLMutexLock lock(mThread->mHeaderMutex);
LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
- if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
+ if (iter != mThread->mMeshHeader.end() && iter->second.first > 0)
{
- LLSD& header = iter->second;
+ const LLSD& header = iter->second.second;
if (header.has("404"))
{
@@ -4535,9 +4597,9 @@ F32 LLMeshRepository::getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* by
{
LLMutexLock lock(mThread->mHeaderMutex);
LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
- if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
+ if (iter != mThread->mMeshHeader.end() && iter->second.first > 0)
{
- result = getStreamingCostLegacy(iter->second, radius, bytes, bytes_visible, lod, unscaled_value);
+ result = getStreamingCostLegacy(iter->second.second, radius, bytes, bytes_visible, lod, unscaled_value);
}
}
if (result > 0.f)
@@ -4859,10 +4921,9 @@ bool LLMeshRepository::getCostData(LLUUID mesh_id, LLMeshCostData& data)
{
LLMutexLock lock(mThread->mHeaderMutex);
LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id);
- if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0)
+ if (iter != mThread->mMeshHeader.end() && iter->second.first > 0)
{
- // TODO - come to this back later. From all known so far it's not a simply race condition but LLSD being not multi thread safe at all. (which in fact it isn't).
- LLSD& header = iter->second;
+ LLSD& header = iter->second.second;
bool header_invalid = (header.has("404")
|| !header.has("lowest_lod")
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index e3a7865b96..4933dfba7a 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -210,10 +210,8 @@ public:
LLCondition* mSignal;
//map of known mesh headers
- typedef std::map mesh_header_map;
+ typedef boost::unordered_map> mesh_header_map; // pair is header_size and data
mesh_header_map mMeshHeader;
-
- std::map mMeshHeaderSize;
class HeaderRequest : public RequestStats
{
@@ -283,10 +281,13 @@ public:
};
//set of requested skin info
- std::set mSkinRequests;
+ std::deque mSkinRequests;
// list of completed skin info requests
- std::list mSkinInfoQ;
+ std::deque mSkinInfoQ;
+
+ // list of skin info requests that have failed or are unavailaibe
+ std::deque mSkinUnavailableQ;
//set of requested decompositions
std::set mDecompositionRequests;
@@ -304,13 +305,13 @@ public:
std::queue mLODReqQ;
//queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD)
- std::queue mUnavailableQ;
+ std::deque mUnavailableQ;
//queue of successfully loaded meshes
- std::queue mLoadedQ;
+ std::deque mLoadedQ;
//map of pending header requests and currently desired LODs
- typedef std::map > pending_lod_map;
+ typedef boost::unordered_map > pending_lod_map;
pending_lod_map mPendingLOD;
// llcorehttp library interface objects.
@@ -359,7 +360,7 @@ public:
//send request for skin info, returns true if header info exists
// (should hold onto mesh_id and try again later if header info does not exist)
- bool fetchMeshSkinInfo(const LLUUID& mesh_id);
+ bool fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry = true);
//send request for decomposition, returns true if header info exists
// (should hold onto mesh_id and try again later if header info does not exist)
@@ -597,18 +598,20 @@ public:
void shutdown();
S32 update();
+ void unregisterMesh(LLVOVolume* volume);
//mesh management functions
S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1);
void notifyLoadedMeshes();
void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume);
void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod);
- void notifySkinInfoReceived(LLMeshSkinInfo& info);
+ void notifySkinInfoReceived(LLMeshSkinInfo* info);
+ void notifySkinInfoUnavailable(const LLUUID& info);
void notifyDecompositionReceived(LLModel::Decomposition* info);
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
static S32 getActualMeshLOD(LLSD& header, S32 lod);
- const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj = nullptr);
+ const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj = nullptr);
LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
void fetchPhysicsShape(const LLUUID& mesh_id);
bool hasPhysicsShape(const LLUUID& mesh_id);
@@ -633,13 +636,13 @@ public:
static void metricsProgress(unsigned int count);
static void metricsUpdate();
- typedef std::map > mesh_load_map;
+ typedef boost::unordered_map > mesh_load_map;
mesh_load_map mLoadingMeshes[4];
// DAE export
LLUUID getCreatorFromHeader(const LLUUID& mesh_id);
- typedef std::unordered_map skin_map;
+ typedef std::unordered_map> skin_map;
skin_map mSkinMap;
typedef std::map decomposition_map;
@@ -650,7 +653,7 @@ public:
std::vector mPendingRequests;
//list of mesh ids awaiting skin info
- typedef std::map > skin_load_map;
+ typedef boost::unordered_map > skin_load_map;
skin_load_map mLoadingSkins;
//list of mesh ids that need to send skin info fetch requests
@@ -675,6 +678,8 @@ public:
std::vector mUploadWaitList;
LLPhysicsDecomp* mDecompThread;
+
+ LLFrameTimer mSkinInfoCullTimer;
class inventory_data
{
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index f742f40e0f..f5991a66c1 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -2778,38 +2778,16 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
if (sloppy_ratio < 0)
{
// Sloppy method didn't work, try with smaller decimation values
- S32 size_vertices = 0;
-
- for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)
- {
- const LLVolumeFace &face = base->getVolumeFace(face_idx);
- size_vertices += face.mNumVertices;
- }
-
- // Complex models aren't supposed to get here, they are supposed
- // to work on a first try of sloppy due to having more viggle room.
- // If they didn't, something is likely wrong, no point locking the
- // thread in a long calculation that will fail.
- const U32 too_many_vertices = 65535;
- if (size_vertices > too_many_vertices)
- {
- // log this properly.
- // LL_WARNS() << "Sloppy optimization method failed for a complex model " << target_model->getName() << LL_ENDL;
- std::ostringstream out;
- out << "Sloppy optimization method failed for a complex model " << target_model->getName();
- LL_WARNS() << out.str() << LL_ENDL;
- LLFloaterModelPreview::addStringToLog(out, true);
- //
- }
- else
{
// Find a decimator that does work
F32 sloppy_decimation_step = sqrt((F32)decimation); // example: 27->15->9->5->3
F32 sloppy_decimator = indices_decimator / sloppy_decimation_step;
+ U64Microseconds end_time = LLTimer::getTotalTime() + U64Seconds(5);
while (sloppy_ratio < 0
&& sloppy_decimator > precise_ratio
- && sloppy_decimator > 1)// precise_ratio isn't supposed to be below 1, but check just in case
+ && sloppy_decimator > 1 // precise_ratio isn't supposed to be below 1, but check just in case
+ && end_time > LLTimer::getTotalTime())
{
sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY);
sloppy_decimator = sloppy_decimator / sloppy_decimation_step;
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index c0d59dbfed..9ef304d08e 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -140,8 +140,7 @@ LLNetMap::LLNetMap (const Params & p)
// [/SL:KB]
mClosestAgentToCursor(),
// mClosestAgentAtLastRightClick(),
- mToolTipMsg(),
- mPopupMenu(NULL)
+ mToolTipMsg()
{
// Fixing borked minimap zoom level persistance
//mScale = gSavedSettings.getF32("MiniMapScale");
@@ -160,6 +159,13 @@ LLNetMap::LLNetMap (const Params & p)
LLNetMap::~LLNetMap()
{
+ auto menu = static_cast(mPopupMenuHandle.get());
+ if (menu)
+ {
+ menu->die();
+ mPopupMenuHandle.markDead();
+ }
+
// Protect avatar name lookup callbacks
for (avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.begin(); it != mAvatarNameCacheConnections.end(); ++it)
{
@@ -252,10 +258,9 @@ BOOL LLNetMap::postBuild()
mParcelOverlayConn = LLViewerParcelOverlay::setUpdateCallback(boost::bind(&LLNetMap::refreshParcelOverlay, this));
// [/SL:KB]
- mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_mini_map.xml", gMenuHolder,
- LLViewerMenuHolderGL::child_registry_t::instance());
- mPopupMenu->setItemEnabled("Re-center map", false);
-
+ LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_mini_map.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mPopupMenuHandle = menu->getHandle();
+ menu->setItemEnabled("Re-center map", false);
return TRUE;
}
@@ -358,8 +363,12 @@ void LLNetMap::draw()
mCentering = false;
}
- bool can_recenter_map = !(centered || mCentering || auto_centering);
- mPopupMenu->setItemEnabled("Re-center map", can_recenter_map);
+ auto menu = static_cast(mPopupMenuHandle.get());
+ if (menu)
+ {
+ bool can_recenter_map = !(centered || mCentering || auto_centering);
+ menu->setItemEnabled("Re-center map", can_recenter_map);
+ }
updateAboutLandPopupButton();
// Prepare a scissor region
@@ -1045,14 +1054,15 @@ void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color,
bool LLNetMap::isMouseOnPopupMenu()
{
- if (!mPopupMenu->isOpen())
+ auto menu = static_cast(mPopupMenuHandle.get());
+ if (!menu || !menu->isOpen())
{
return false;
}
S32 popup_x;
S32 popup_y;
- LLUI::getInstance()->getMousePositionLocal(mPopupMenu, &popup_x, &popup_y);
+ LLUI::getInstance()->getMousePositionLocal(menu, &popup_x, &popup_y);
// *NOTE: Tolerance is larger than it needs to be because the context menu is offset from the mouse when the menu is opened from certain
// directions. This may be a quirk of LLMenuGL::showPopup. -Cosmic,2022-03-22
constexpr S32 tolerance = 10;
@@ -1063,7 +1073,7 @@ bool LLNetMap::isMouseOnPopupMenu()
{
for (S32 sign_y = -1; sign_y <= 1; sign_y += 2)
{
- if (mPopupMenu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance)))
+ if (menu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance)))
{
return true;
}
@@ -1074,7 +1084,8 @@ bool LLNetMap::isMouseOnPopupMenu()
void LLNetMap::updateAboutLandPopupButton()
{
- if (!mPopupMenu->isOpen())
+ auto menu = static_cast(mPopupMenuHandle.get());
+ if (!menu || !menu->isOpen())
{
return;
}
@@ -1082,7 +1093,7 @@ void LLNetMap::updateAboutLandPopupButton()
LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal(mPopupWorldPos);
if (!region)
{
- mPopupMenu->setItemEnabled("About Land", false);
+ menu->setItemEnabled("About Land", false);
}
else
{
@@ -1097,7 +1108,7 @@ void LLNetMap::updateAboutLandPopupButton()
{
valid_parcel = hover_parcel->getOwnerID().notNull();
}
- mPopupMenu->setItemEnabled("About Land", valid_parcel);
+ menu->setItemEnabled("About Land", valid_parcel);
}
}
}
@@ -1744,11 +1755,15 @@ void LLNetMap::setAvatarProfileLabel(const LLUUID& av_id, const LLAvatarName& av
mAvatarNameCacheConnections.erase(it);
}
- LLMenuItemGL* pItem = mPopupMenu->findChild(item_name, TRUE /*recurse*/);
- if (pItem)
+ auto menu = static_cast(mPopupMenuHandle.get());
+ if (menu)
{
- pItem->setLabel(avName.getCompleteName());
- pItem->getMenu()->arrange();
+ LLMenuItemGL* pItem = menu->findChild(item_name, TRUE /*recurse*/);
+ if (pItem)
+ {
+ pItem->setLabel(avName.getCompleteName());
+ pItem->getMenu()->arrange();
+ }
}
}
@@ -1802,23 +1817,24 @@ void LLNetMap::handleTextureType(const LLSD& sdParam) const
BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
- if (mPopupMenu)
+ auto menu = static_cast(mPopupMenuHandle.get());
+ if (menu)
{
mPopupWorldPos = viewPosToGlobal(x, y);
// [SL:KB] - Patch: World-MiniMap | Checked: 2012-07-08 (Catznip-3.3)
mClosestAgentRightClick = mClosestAgentToCursor;
mClosestAgentsRightClick = mClosestAgentsToCursor;
- mPopupMenu->setItemVisible("Add to Set Multiple", mClosestAgentsToCursor.size() > 1);
- mPopupMenu->setItemVisible("More Options", mClosestAgentsToCursor.size() == 1);
- mPopupMenu->setItemVisible("View Profile", mClosestAgentsToCursor.size() == 1);
+ menu->setItemVisible("Add to Set Multiple", mClosestAgentsToCursor.size() > 1);
+ menu->setItemVisible("More Options", mClosestAgentsToCursor.size() == 1);
+ menu->setItemVisible("View Profile", mClosestAgentsToCursor.size() == 1);
bool can_show_names = !RlvActions::hasBehaviour(RLV_BHVR_SHOWNAMES);
- mPopupMenu->setItemEnabled("Add to Set Multiple", can_show_names);
- mPopupMenu->setItemEnabled("More Options", can_show_names);
- mPopupMenu->setItemEnabled("View Profile", can_show_names);
+ menu->setItemEnabled("Add to Set Multiple", can_show_names);
+ menu->setItemEnabled("More Options", can_show_names);
+ menu->setItemEnabled("View Profile", can_show_names);
- LLMenuItemBranchGL* pProfilesMenu = mPopupMenu->getChild("View Profiles");
+ LLMenuItemBranchGL* pProfilesMenu = menu->getChild("View Profiles");
if (pProfilesMenu)
{
pProfilesMenu->setVisible(mClosestAgentsToCursor.size() > 1);
@@ -1857,22 +1873,22 @@ BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask)
pProfilesMenu->getBranch()->addChild(pMenuItem);
}
}
- mPopupMenu->setItemVisible("Cam", LLAvatarActions::canZoomIn(mClosestAgentToCursor));
- mPopupMenu->setItemVisible("MarkAvatar", mClosestAgentToCursor.notNull());
- mPopupMenu->setItemVisible("Start Tracking", mClosestAgentToCursor.notNull());
- mPopupMenu->setItemVisible("Profile Separator", (mClosestAgentsToCursor.size() >= 1 || mClosestAgentToCursor.notNull()));
- mPopupMenu->setItemEnabled("Place Profile", RlvActions::canShowLocation());
- mPopupMenu->setItemEnabled("World Map", !RlvActions::hasBehaviour(RLV_BHVR_SHOWWORLDMAP));
+ menu->setItemVisible("Cam", LLAvatarActions::canZoomIn(mClosestAgentToCursor));
+ menu->setItemVisible("MarkAvatar", mClosestAgentToCursor.notNull());
+ menu->setItemVisible("Start Tracking", mClosestAgentToCursor.notNull());
+ menu->setItemVisible("Profile Separator", (mClosestAgentsToCursor.size() >= 1 || mClosestAgentToCursor.notNull()));
+ menu->setItemEnabled("Place Profile", RlvActions::canShowLocation());
+ menu->setItemEnabled("World Map", !RlvActions::hasBehaviour(RLV_BHVR_SHOWWORLDMAP));
// [/SL:KB]
- mPopupMenu->buildDrawLabels();
- mPopupMenu->updateParent(LLMenuGL::sMenuContainer);
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
// [SL:KB] - Patch: World-MiniMap | Checked: 2012-07-08 (Catznip-3.3)
- mPopupMenu->setItemVisible("Stop Tracking", LLTracker::isTracking(0));
- mPopupMenu->setItemVisible("Stop Tracking Separator", LLTracker::isTracking(0));
+ menu->setItemVisible("Stop Tracking", LLTracker::isTracking(0));
+ menu->setItemVisible("Stop Tracking Separator", LLTracker::isTracking(0));
// [/SL:KB]
-// mPopupMenu->setItemEnabled("Stop Tracking", LLTracker::isTracking(0));
- LLMenuGL::showPopup(this, mPopupMenu, x, y);
+// menu->setItemEnabled("Stop Tracking", LLTracker::isTracking(0));
+ LLMenuGL::showPopup(this, menu, x, y);
}
return TRUE;
}
@@ -2127,11 +2143,12 @@ void LLNetMap::handleStartTracking()
void LLNetMap::handleStopTracking (const LLSD& userdata)
{
- if (mPopupMenu)
+ auto menu = static_cast(mPopupMenuHandle.get());
+ if (menu)
{
// Hide tracking option instead of disabling
- //mPopupMenu->setItemEnabled ("Stop Tracking", false);
- mPopupMenu->setItemVisible ("Stop Tracking", false);
+ //menu->setItemEnabled ("Stop Tracking", false);
+ menu->setItemVisible ("Stop Tracking", false);
//
LLTracker::stopTracking (LLTracker::isTracking(NULL));
}
diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h
index f2de5a91fe..957cd43716 100644
--- a/indra/newview/llnetmap.h
+++ b/indra/newview/llnetmap.h
@@ -266,7 +266,7 @@ private:
void handleEstateBan();
void handleDerender(bool permanent);
- LLMenuGL* mPopupMenu;
+ LLHandle mPopupMenuHandle;
uuid_vec_t gmSelected;
};
diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp
index cbfd3fcc2d..871e8228da 100644
--- a/indra/newview/llnotificationlistitem.cpp
+++ b/indra/newview/llnotificationlistitem.cpp
@@ -556,8 +556,6 @@ void LLGroupNoticeNotificationListItem::close()
void LLGroupNoticeNotificationListItem::onClickAttachment()
{
if (mInventoryOffer != NULL) {
- mInventoryOffer->forceResponse(IOR_ACCEPT);
-
static const LLUIColor textColor = LLUIColorTable::instance().getColor(
"GroupNotifyDimmedTextColor");
mAttachmentTextBox->setColor(textColor);
@@ -567,7 +565,7 @@ void LLGroupNoticeNotificationListItem::onClickAttachment()
if (!isAttachmentOpenable(mInventoryOffer->mType)) {
LLNotifications::instance().add("AttachmentSaved", LLSD(), LLSD());
}
-
+ mInventoryOffer->forceResponse(IOR_ACCEPT);
mInventoryOffer = NULL;
}
}
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 6a929e5dcf..db03df4151 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -1226,7 +1226,7 @@ void LLOutfitGallery::uploadOutfitImage(const std::vector& filename
checkRemovePhoto(outfit_id);
std::string upload_pending_name = outfit_id.asString();
std::string upload_pending_desc = "";
- LLUUID photo_id = upload_new_resource(filename, // file
+ upload_new_resource(filename, // file
upload_pending_name,
upload_pending_desc,
0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index e0c79b58eb..c0074fd2f9 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -894,8 +894,7 @@ void LLOutfitListBase::onOpen(const LLSD& info)
mCategoriesObserver->addCategory(outfits,
boost::bind(&LLOutfitListBase::refreshList, this, outfits));
- const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
-
+ //const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
// Start observing changes in Current Outfit category.
//mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this));
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index 13c100d9b1..ed3ff43f74 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -1891,7 +1891,7 @@ void LLPanelEditWearable::onClickedImportBtnCallback(const std::vectorsetEnabled( can_change_media && allow_resize );
- LLUUID tmp = parcel->getMediaID();
mMediaTextureCtrl->setImageAssetID ( parcel->getMediaID() );
mMediaTextureCtrl->setEnabled( can_change_media );
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 131cef284f..7d076b1ede 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -425,6 +425,13 @@ LLPanelMainInventory::~LLPanelMainInventory( void )
gInventory.removeObserver(this);
delete mSavedFolderState;
+
+ auto menu = mMenuAddHandle.get();
+ if(menu)
+ {
+ menu->die();
+ mMenuAddHandle.markDead();
+ }
}
LLInventoryPanel* LLPanelMainInventory::getAllItemsPanel()
@@ -1639,13 +1646,12 @@ void LLPanelMainInventory::initListCommandsHandlers()
mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2));
mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- mGearMenuButton->setMenu(mMenuGearDefault);
+ mGearMenuButton->setMenu(mMenuGearDefault, LLMenuButton::MP_TOP_LEFT, true);
LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mMenuAddHandle = menu->getHandle();
mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
- mVisibilityMenuButton->setMenu(mMenuVisibility);
- mVisibilityMenuButton->setMenuPosition(LLMenuButton::MP_BOTTOM_LEFT);
+ mVisibilityMenuButton->setMenu(mMenuVisibility, LLMenuButton::MP_BOTTOM_LEFT, true);
// Update the trash button when selected item(s) get worn or taken off.
LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this));
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 566bd9b887..875bade661 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -2781,7 +2781,7 @@ void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata)
// }
// else if (command == "params_paste")
// {
-// return mHasClipboardParams;
+// return mClipboardParams.isMap() && (mClipboardParams.size() != 0);
// }
// // copy options
// else if (command == "psr_copy")
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index 0d83e62f53..ce3be628a4 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -1497,7 +1497,8 @@ LLPanelObjectInventory::LLPanelObjectInventory(const LLPanelObjectInventory::Par
mHaveInventory(FALSE),
mIsInventoryEmpty(TRUE),
mInventoryNeedsUpdate(FALSE),
- mInventoryViewModel(p.name)
+ mInventoryViewModel(p.name),
+ mShowRootFolder(p.show_root_folder)
{
// Setup context menu callbacks
mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelObjectInventory::doToSelected, this, _2));
@@ -1594,6 +1595,7 @@ void LLPanelObjectInventory::reset()
mFolders = LLUICtrlFactory::create(p);
mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);
+ mFolders->setEnableRegistrar(&mEnableCallbackRegistrar);
if (hasFocus())
{
@@ -1769,15 +1771,23 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root
//
LLFolderViewFolder* new_folder = LLUICtrlFactory::create(p);
- new_folder->addToFolder(mFolders);
- new_folder->toggleOpen();
+
+ if (mShowRootFolder)
+ {
+ new_folder->addToFolder(mFolders);
+ new_folder->toggleOpen();
+ }
if (!contents.empty())
{
- createViewsForCategory(&contents, inventory_root, new_folder);
+ createViewsForCategory(&contents, inventory_root, mShowRootFolder ? new_folder : mFolders);
}
- // Refresh for label to add item count
- new_folder->refresh();
+
+ if (mShowRootFolder)
+ {
+ // Refresh for label to add item count
+ new_folder->refresh();
+ }
}
}
diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h
index 22dadeee7c..bcf5c567f9 100644
--- a/indra/newview/llpanelobjectinventory.h
+++ b/indra/newview/llpanelobjectinventory.h
@@ -48,8 +48,14 @@ class LLViewerObject;
class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener
{
public:
- // dummy param block for template registration purposes
- struct Params : public LLPanel::Params {};
+ struct Params : public LLInitParam::Block
+ {
+ Optional show_root_folder;
+
+ Params()
+ : show_root_folder("show_root_folder", true)
+ {}
+ };
LLPanelObjectInventory(const Params&);
virtual ~LLPanelObjectInventory();
@@ -113,6 +119,7 @@ private:
BOOL mIsInventoryEmpty; // 'Empty' label
BOOL mInventoryNeedsUpdate; // for idle, set on changed callback
LLFolderViewModelInventory mInventoryViewModel;
+ bool mShowRootFolder;
};
#endif // LL_LLPANELOBJECTINVENTORY_H
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index ec953552f2..dd33202980 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -853,7 +853,6 @@ void LLPanelPlaces::onSaveButtonClicked()
LLStringUtil::trim(current_title_value);
LLStringUtil::trim(current_notes_value);
- LLUUID item_id = mItem->getUUID();
LLUUID folder_id = mLandmarkInfo->getLandmarkFolder();
bool change_parent = folder_id != mItem->getParentUUID();
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index afa81823c5..2940eb951d 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -497,6 +497,30 @@ public:
// requires trusted browser to trigger
LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { }
+ virtual bool canHandleUntrusted(
+ const LLSD& params,
+ const LLSD& query_map,
+ LLMediaCtrl* web,
+ const std::string& nav_type)
+ {
+ if (params.size() < 2)
+ {
+ return true; // don't block, will fail later
+ }
+
+ if (nav_type == NAV_TYPE_CLICKED)
+ {
+ return true;
+ }
+
+ const std::string verb = params[1].asString();
+ if (verb == "about" || verb == "inspect" || verb == "reportAbuse")
+ {
+ return true;
+ }
+ return false;
+ }
+
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
{
@@ -1238,7 +1262,6 @@ void LLPanelProfileSecondLife::resetData()
void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data)
{
- LLUUID avatar_id = getAvatarId();
const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId());
if ((relationship != NULL || gAgent.isGodlike()) && !getSelfProfile())
{
@@ -1268,7 +1291,7 @@ void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avat
#ifdef OPENSIM
if (LLGridManager::instance().isInOpenSim())
{
- LLFloater* floater_profile = LLFloaterReg::findInstance("profile", LLSD().with("id", avatar_id));
+ LLFloater* floater_profile = LLFloaterReg::findInstance("profile", LLSD().with("id", getAvatarId()));
if (!floater_profile)
{
// floater is dead, so panels are dead as well
@@ -1593,6 +1616,8 @@ void LLPanelProfileSecondLife::fillRightsData()
void LLPanelProfileSecondLife::fillAgeData(const LLDate &born_on)
{
// Fix LL UI/UX design accident
+ //// Date from server comes already converted to stl timezone,
+ //// so display it as an UTC + 0
//std::string name_and_date = getString("date_format");
//LLSD args_name;
//args_name["datetime"] = (S32)born_on.secondsSinceEpoch();
diff --git a/indra/newview/llpanelprofileclassifieds.cpp b/indra/newview/llpanelprofileclassifieds.cpp
index e05bf6993e..2be077de0b 100644
--- a/indra/newview/llpanelprofileclassifieds.cpp
+++ b/indra/newview/llpanelprofileclassifieds.cpp
@@ -83,6 +83,30 @@ public:
std::set mClassifiedIds;
std::string mRequestVerb;
+
+ virtual bool canHandleUntrusted(
+ const LLSD& params,
+ const LLSD& query_map,
+ LLMediaCtrl* web,
+ const std::string& nav_type)
+ {
+ if (params.size() < 1)
+ {
+ return true; // don't block, will fail later
+ }
+
+ if (nav_type == NAV_TYPE_CLICKED)
+ {
+ return true;
+ }
+
+ const std::string verb = params[0].asString();
+ if (verb == "create")
+ {
+ return false;
+ }
+ return true;
+ }
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
{
diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp
index f5ef2ca7a0..386bd5a3e8 100644
--- a/indra/newview/llpanelprofilepicks.cpp
+++ b/indra/newview/llpanelprofilepicks.cpp
@@ -65,6 +65,30 @@ public:
// requires trusted browser to trigger
LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { }
+ virtual bool canHandleUntrusted(
+ const LLSD& params,
+ const LLSD& query_map,
+ LLMediaCtrl* web,
+ const std::string& nav_type)
+ {
+ if (params.size() < 1)
+ {
+ return true; // don't block, will fail later
+ }
+
+ if (nav_type == NAV_TYPE_CLICKED)
+ {
+ return true;
+ }
+
+ const std::string verb = params[0].asString();
+ if (verb == "create")
+ {
+ return false;
+ }
+ return true;
+ }
+
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
{
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 178cdd7737..e3213135b6 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -317,7 +317,7 @@ void LLPreviewNotecard::loadAsset()
else
{
LLHost source_sim = LLHost();
- LLSD* user_data = new LLSD();
+ LLSD* user_data = nullptr;
if (mObjectUUID.notNull())
{
LLViewerObject *objectp = gObjectList.findObject(mObjectUUID);
@@ -336,6 +336,7 @@ void LLPreviewNotecard::loadAsset()
mAssetStatus = PREVIEW_ASSET_LOADED;
return;
}
+ user_data = new LLSD();
user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID);
}
else
diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp
index 2cc2b21c22..7fd89ff4f8 100644
--- a/indra/newview/llscenemonitor.cpp
+++ b/indra/newview/llscenemonitor.cpp
@@ -515,7 +515,7 @@ void LLSceneMonitor::fetchQueryResult()
}
//dump results to a file _scene_xmonitor_results.csv
-void LLSceneMonitor::dumpToFile(std::string file_name)
+void LLSceneMonitor::dumpToFile(const std::string &file_name)
{
if (!hasResults()) return;
diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h
index fcfd5ccc64..82db9dc552 100644
--- a/indra/newview/llscenemonitor.h
+++ b/indra/newview/llscenemonitor.h
@@ -61,7 +61,7 @@ public:
bool needsUpdate() const;
const LLTrace::ExtendablePeriodicRecording* getRecording() const {return &mSceneLoadRecording;}
- void dumpToFile(std::string file_name);
+ void dumpToFile(const std::string &file_name);
bool hasResults() const { return mSceneLoadRecording.getResults().getDuration() != S32Seconds(0);}
void reset();
diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp
index 16b52a2d0b..812ec015f5 100644
--- a/indra/newview/llscriptfloater.cpp
+++ b/indra/newview/llscriptfloater.cpp
@@ -559,11 +559,11 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)
if(it != mNotifications.end())
{
- auto old_id = it->first; // store UUID to prevent use after free - Rye
+ LLUUID old_id = it->first; // copy LLUUID to prevent use after free when it is erased below
LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel();
if (NULL != chiclet_panelp)
{
- LLIMChiclet * chicletp = chiclet_panelp->findChiclet(old_id); // avoid use after free - Rye
+ LLIMChiclet * chicletp = chiclet_panelp->findChiclet(old_id);
if (NULL != chicletp)
{
// Pass the new_message icon state further.
@@ -572,7 +572,7 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)
}
}
- LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", old_id); // avoid use after free - Rye
+ LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", old_id);
if (floater)
{
// Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142.
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 3daabfe0c7..935afbf86b 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -995,7 +995,6 @@ void LLActiveSpeakerMgr::updateSpeakerList()
// clean up text only speakers
for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it)
{
- LLUUID speaker_id = speaker_it->first;
LLSpeaker* speakerp = speaker_it->second;
if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY)
{
diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp
index 5ca1d4b4a5..0111d8869c 100644
--- a/indra/newview/llspeakingindicatormanager.cpp
+++ b/indra/newview/llspeakingindicatormanager.cpp
@@ -51,6 +51,10 @@ class SpeakingIndicatorManager : public LLSingleton, L
LLSINGLETON(SpeakingIndicatorManager);
~SpeakingIndicatorManager();
LOG_CLASS(SpeakingIndicatorManager);
+
+protected:
+ void cleanupSingleton();
+
public:
/**
@@ -183,12 +187,16 @@ SpeakingIndicatorManager::SpeakingIndicatorManager()
SpeakingIndicatorManager::~SpeakingIndicatorManager()
{
- // Don't use LLVoiceClient::getInstance() here without check
- // singleton MAY have already been destroyed.
- if(LLVoiceClient::instanceExists())
- {
- LLVoiceClient::getInstance()->removeObserver(this);
- }
+}
+
+void SpeakingIndicatorManager::cleanupSingleton()
+{
+ // Don't use LLVoiceClient::getInstance() here without a check,
+ // singleton MAY have already been destroyed.
+ if (LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->removeObserver(this);
+ }
}
void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_id*/)
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 03f24f74ca..927b5779b6 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -320,12 +320,10 @@ void show_release_notes_if_required();
bool first_run_dialog_callback(const LLSD& notification, const LLSD& response);
void set_startup_status(const F32 frac, const std::string& string, const std::string& msg);
bool login_alert_status(const LLSD& notification, const LLSD& response);
-void login_packet_failed(void**, S32 result);
void use_circuit_callback(void**, S32 result);
void register_viewer_callbacks(LLMessageSystem* msg);
void asset_callback_nothing(const LLUUID&, LLAssetType::EType, void*, S32);
bool callback_choose_gender(const LLSD& notification, const LLSD& response);
-void init_start_screen(S32 location_id);
void release_start_screen();
void reset_login();
LLSD transform_cert_args(LLPointer cert);
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index e509b94c71..be1bcb3e43 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -93,6 +93,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt
const LLFontGL* font = make_small_btn ? sFontSmall: sFont; // for block and ignore buttons in script dialog
p.name = form_element["name"].asString();
p.label = form_element["text"].asString();
+ p.tool_tip = form_element["text"].asString();
p.font = font;
p.rect.height = BTN_HEIGHT;
p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata));
diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp
index 010b9d128a..3c73ed7857 100644
--- a/indra/newview/lltoolbarview.cpp
+++ b/indra/newview/lltoolbarview.cpp
@@ -44,7 +44,6 @@
#include "llagent.h" // HACK for destinations guide on startup
#include "llfloaterreg.h" // HACK for destinations guide on startup
#include "llviewercontrol.h" // HACK for destinations guide on startup
-#include "llinventorymodel.h" // HACK to disable starter avatars button for NUX
#include
@@ -383,22 +382,6 @@ bool LLToolBarView::loadToolbars(bool force_default)
}
}
}
-
- // SL-18581: Don't show the starter avatar toolbar button for NUX users
- LLViewerInventoryCategory* my_outfits_cat = gInventory.getCategory(gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS));
- if (gAgent.isFirstLogin()
- && my_outfits_cat != NULL
- && my_outfits_cat->getDescendentCount() > 0)
- {
- for (S32 i = LLToolBarEnums::TOOLBAR_FIRST; i <= LLToolBarEnums::TOOLBAR_LAST; i++)
- {
- if (mToolbars[i])
- {
- mToolbars[i]->removeCommand(LLCommandId("avatar"));
- }
- }
- }
-
mToolbarsLoaded = true;
return true;
}
diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp
index 2930c46bcc..5e231a8698 100644
--- a/indra/newview/llurldispatcher.cpp
+++ b/indra/newview/llurldispatcher.cpp
@@ -328,7 +328,7 @@ public:
// inside the app, otherwise a malicious web page could
// cause a constant teleport loop. JC
LLTeleportHandler() :
- LLCommandHandler("teleport", UNTRUSTED_THROTTLE),
+ LLCommandHandler("teleport", UNTRUSTED_CLICK_ONLY),
LLEventAPI("LLTeleportHandler", "Low-level teleport API")
{
LLEventAPI::add("teleport",
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index abc921124a..bafd6babd2 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -230,11 +230,103 @@ const std::string FLOATER_PROFILE("profile");
class LLFloaterOpenHandler : public LLCommandHandler
{
public:
- // requires trusted browser to trigger
+ // requires trusted browser to trigger or an explicit click
LLFloaterOpenHandler() : LLCommandHandler("openfloater", UNTRUSTED_THROTTLE) { }
- bool handle(const LLSD& params, const LLSD& query_map,
- LLMediaCtrl* web)
+ bool canHandleUntrusted(
+ const LLSD& params,
+ const LLSD& query_map,
+ LLMediaCtrl* web,
+ const std::string& nav_type) override
+ {
+ if (params.size() != 1)
+ {
+ return true; // will fail silently
+ }
+
+ std::string fl_name = params[0].asString();
+
+ if (nav_type == NAV_TYPE_CLICKED)
+ {
+ const std::list blacklist_clicked = {
+ "camera_presets",
+ "delete_pref_preset",
+ "forget_username",
+ "god_tools",
+ "group_picker",
+ "hud",
+ "incoming_call",
+ "linkreplace",
+ "message_critical", // Modal!!! Login specific.
+ "message_tos", // Modal!!! Login specific.
+ "save_pref_preset",
+ "save_camera_preset",
+ "region_restarting",
+ "outfit_snapshot",
+ "upload_anim_bvh",
+ "upload_anim_anim",
+ "upload_image",
+ "upload_model",
+ "upload_script",
+ "upload_sound"
+ };
+ return std::find(blacklist_clicked.begin(), blacklist_clicked.end(), fl_name) == blacklist_clicked.end();
+ }
+ else
+ {
+ const std::list blacklist_untrusted = {
+ "360capture",
+ "block_timers",
+ "add_payment_method",
+ "appearance",
+ "associate_listing",
+ "avatar_picker",
+ "camera",
+ "camera_presets",
+ "classified",
+ "add_landmark",
+ "delete_pref_preset",
+ "env_fixed_environmentent_water",
+ "env_fixed_environmentent_sky",
+ "env_edit_extdaycycle",
+ "font_test",
+ "forget_username",
+ "god_tools",
+ "group_picker",
+ "hud",
+ "incoming_call",
+ "linkreplace",
+ "mem_leaking",
+ "marketplace_validation",
+ "message_critical", // Modal!!! Login specific. If this is in use elsewhere, better to create a non modal variant
+ "message_tos", // Modal!!! Login specific.
+ "mute_object_by_name",
+ "publish_classified",
+ "save_pref_preset",
+ "save_camera_preset",
+ "region_restarting",
+ "script_debug",
+ "script_debug_output",
+ "sell_land",
+ "outfit_snapshot",
+ "upload_anim_bvh",
+ "upload_anim_anim",
+ "upload_image",
+ "upload_model",
+ "upload_script",
+ "upload_sound"
+ };
+ return std::find(blacklist_untrusted.begin(), blacklist_untrusted.end(), fl_name) == blacklist_untrusted.end();
+ }
+
+
+ return true;
+ }
+
+ bool handle(
+ const LLSD& params,
+ const LLSD& query_map,
+ LLMediaCtrl* web) override
{
if (params.size() != 1)
{
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index 881a7df71a..df68909ffc 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -1707,12 +1707,22 @@ BOOL LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask,
clicktype = CLICK_DOUBLELEFT;
}
+ // If the first LMB click is handled by the menu, skip the following double click
+ static bool skip_double_click = false;
+ if (clicktype == CLICK_LEFT && down )
+ {
+ skip_double_click = handled;
+ }
if (double_click_sp && down)
{
// Consume click.
// Due to handling, double click that is not handled will be immediately followed by LMB click
}
+ else if (clicktype == CLICK_DOUBLELEFT && skip_double_click)
+ {
+ handled = true;
+ }
// If UI handled 'down', it should handle 'up' as well
// If we handle 'down' not by UI, then we should handle 'up'/'level' regardless of UI
else if (handled)
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 0e87aa96a9..7f6deb6938 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -236,7 +236,7 @@ class LLInventoryHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
- LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { }
+ LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_CLICK_ONLY) { }
bool handle(const LLSD& params, const LLSD& query_map,
LLMediaCtrl* web)
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 9bb8d12c39..86f6d19832 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3368,14 +3368,15 @@ bool enable_object_show_original()
}
//
-static void init_default_item_label(const std::string& item_name)
+static void init_default_item_label(LLUICtrl* ctrl)
{
+ const std::string& item_name = ctrl->getName();
boost::unordered_map::iterator it = sDefaultItemLabels.find(item_name);
if (it == sDefaultItemLabels.end())
{
// *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value
// (doesn't seem to matter much ATM).
- LLStringExplicit default_label = gMenuHolder->childGetValue(item_name).asString();
+ LLStringExplicit default_label = ctrl->getValue().asString();
if (!default_label.empty())
{
sDefaultItemLabels.insert(std::pair(item_name, default_label));
@@ -3414,18 +3415,17 @@ bool enable_object_touch(LLUICtrl* ctrl)
}
// [/RLVa:KB]
- std::string item_name = ctrl->getName();
- init_default_item_label(item_name);
+ init_default_item_label(ctrl);
// Update label based on the node touch name if available.
LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
if (node && node->mValid && !node->mTouchName.empty())
{
- gMenuHolder->childSetValue(item_name, node->mTouchName);
+ ctrl->setValue(node->mTouchName);
}
else
{
- gMenuHolder->childSetValue(item_name, get_default_item_label(item_name));
+ ctrl->setValue(get_default_item_label(ctrl->getName()));
}
return new_value;
@@ -6895,9 +6895,6 @@ class LLToolsSelectNextPartFace : public view_listener_t
}
}
LLSelectMgr::getInstance()->selectObjectOnly(to_select, new_te);
-
- // Add this back in additionally to selectObjectOnly() to get the lastOperadedTE()
- // function back working to properly shift+cycle through faces
LLSelectMgr::getInstance()->addAsIndividual(to_select, new_te, false);
}
else
@@ -8135,20 +8132,18 @@ bool enable_object_sit(LLUICtrl* ctrl)
bool sitting_on_sel = sitting_on_selection();
if (!sitting_on_sel)
{
- std::string item_name = ctrl->getName();
-
// init default labels
- init_default_item_label(item_name);
+ init_default_item_label(ctrl);
// Update label
LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode();
if (node && node->mValid && !node->mSitName.empty())
{
- gMenuHolder->childSetValue(item_name, node->mSitName);
+ ctrl->setValue(node->mSitName);
}
else
{
- gMenuHolder->childSetValue(item_name, get_default_item_label(item_name));
+ ctrl->setValue(get_default_item_label(ctrl->getName()));
}
}
@@ -9511,7 +9506,6 @@ void handle_selected_texture_info(void*)
map_t::iterator it;
for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it)
{
- LLUUID image_id = it->first;
U8 te = it->second[0];
LLViewerTexture* img = node->getObject()->getTEImage(te);
S32 height = img->getHeight();
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 805f03f49d..076778c1e1 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -3380,36 +3380,39 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
return;
}
- LLFilenameAndTask* ft = new LLFilenameAndTask;
- ft->mTaskID = task_id;
// we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
- msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
+ S16 serial = 0;
+ msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, serial);
- if (ft->mSerial == object->mInventorySerialNum
- && ft->mSerial < object->mExpectedInventorySerialNum)
+ if (serial == object->mInventorySerialNum
+ && serial < object->mExpectedInventorySerialNum)
{
// Loop Protection.
// We received same serial twice.
// Viewer did some changes to inventory that couldn't be saved server side
// or something went wrong to cause serial to be out of sync.
// Drop xfer and restart after some time, assign server's value as expected
- LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL;
- object->mExpectedInventorySerialNum = ft->mSerial;
+ LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << serial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL;
+ object->mExpectedInventorySerialNum = serial;
object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_DESYNC);
}
- else if (ft->mSerial < object->mExpectedInventorySerialNum)
+ else if (serial < object->mExpectedInventorySerialNum)
{
// Out of date message, record to current serial for loop protection, but do not load it
// Drop xfer and restart after some time
- if (ft->mSerial < object->mInventorySerialNum)
+ if (serial < object->mInventorySerialNum)
{
LL_WARNS() << "Task serial decreased. Potentially out of order packet or desync." << LL_ENDL;
}
- object->mInventorySerialNum = ft->mSerial;
+ object->mInventorySerialNum = serial;
object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_OUTDATED);
}
- else if (ft->mSerial >= object->mExpectedInventorySerialNum)
+ else if (serial >= object->mExpectedInventorySerialNum)
{
+ LLFilenameAndTask* ft = new LLFilenameAndTask;
+ ft->mTaskID = task_id;
+ ft->mSerial = serial;
+
// We received version we expected or newer. Load it.
object->mInventorySerialNum = ft->mSerial;
object->mExpectedInventorySerialNum = ft->mSerial;
@@ -3444,7 +3447,7 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
object->mRegionp->getHost(),
TRUE,
&LLViewerObject::processTaskInvFile,
- (void**)ft,
+ (void**)ft, // This takes ownership of ft
LLXferManager::HIGH_PRIORITY);
if (object->mInvRequestState == INVENTORY_XFER)
{
diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp
index f042040e98..1751ee1ebb 100644
--- a/indra/newview/llviewerpartsource.cpp
+++ b/indra/newview/llviewerpartsource.cpp
@@ -793,7 +793,7 @@ void LLViewerPartSourceBeam::update(const F32 dt)
}
LLViewerPart* part = new LLViewerPart();
- part->init(this, mImagep, NULL);
+ part->init(this, mImagep, updatePart);
part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK |
LLPartData::LL_PART_INTERP_SCALE_MASK |
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 0105965e3c..63dd5d09d6 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -1367,7 +1367,6 @@ bool LLViewerTextEditor::onCopyToInvDialog(const LLSD& notification, const LLSD&
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if( 0 == option )
{
- LLUUID item_id = notification["payload"]["item_id"].asUUID();
llwchar wc = llwchar(notification["payload"]["item_wc"].asInteger());
LLInventoryItem* itemp = LLEmbeddedItems::getEmbeddedItemPtr(wc);
if (itemp)
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 6558d88cb4..19155c1fde 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1358,7 +1358,6 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
TRUE /* pick_transparent */,
FALSE /* pick_rigged */);
- LLUUID object_id = pick_info.getObjectID();
S32 object_face = pick_info.mObjectFace;
std::string url = data;
@@ -3873,6 +3872,59 @@ void LLViewerWindow::updateUI()
root_view = mRootView;
}
+ static LLCachedControl dump_menu_holder(gSavedSettings, "DumpMenuHolderSize", false);
+ if (dump_menu_holder)
+ {
+ static bool init = false;
+ static LLFrameTimer child_count_timer;
+ static std::vector child_vec;
+ if (!init)
+ {
+ child_count_timer.resetWithExpiry(5.f);
+ init = true;
+ }
+ if (child_count_timer.hasExpired())
+ {
+ LL_INFOS() << "gMenuHolder child count: " << gMenuHolder->getChildCount() << LL_ENDL;
+ std::vector local_child_vec;
+ LLView::child_list_t child_list = *gMenuHolder->getChildList();
+ for (auto child : child_list)
+ {
+ local_child_vec.emplace_back(child->getName());
+ }
+ if (!local_child_vec.empty() && local_child_vec != child_vec)
+ {
+ std::vector out_vec;
+ std::sort(local_child_vec.begin(), local_child_vec.end());
+ std::sort(child_vec.begin(), child_vec.end());
+ std::set_difference(child_vec.begin(), child_vec.end(), local_child_vec.begin(), local_child_vec.end(), std::inserter(out_vec, out_vec.begin()));
+ if (!out_vec.empty())
+ {
+ LL_INFOS() << "gMenuHolder removal diff size: '"<singletoneInstanceExists()) mVoiceModule->removeObserver(observer);
+ if (mVoiceModule)
+ {
+ mVoiceModule->removeObserver(observer);
+ }
}
void LLVoiceClient::addObserver(LLFriendObserver* observer)
@@ -865,7 +868,10 @@ void LLVoiceClient::addObserver(LLFriendObserver* observer)
void LLVoiceClient::removeObserver(LLFriendObserver* observer)
{
- if (mVoiceModule && mVoiceModule->singletoneInstanceExists()) mVoiceModule->removeObserver(observer);
+ if (mVoiceModule)
+ {
+ mVoiceModule->removeObserver(observer);
+ }
}
void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
@@ -875,7 +881,10 @@ void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer)
void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer)
{
- if (mVoiceModule && mVoiceModule->singletoneInstanceExists()) mVoiceModule->removeObserver(observer);
+ if (mVoiceModule)
+ {
+ mVoiceModule->removeObserver(observer);
+ }
}
std::string LLVoiceClient::sipURIFromID(const LLUUID &id)
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 50fc6d1da5..b4896aba8b 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -125,8 +125,6 @@ public:
virtual const LLVoiceVersionInfo& getVersion()=0;
- virtual bool singletoneInstanceExists()=0;
-
/////////////////////
/// @name Tuning
//@{
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 384c416c0f..a86ec254c4 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -5377,11 +5377,6 @@ void LLVivoxVoiceClient::declineInvite(std::string &sessionHandle)
}
}
-bool LLVivoxVoiceClient::singletoneInstanceExists()
-{
- return LLVivoxVoiceClient::instanceExists();
-}
-
void LLVivoxVoiceClient::leaveNonSpatialChannel()
{
LL_DEBUGS("Voice") << "Request to leave spacial channel." << LL_ENDL;
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 343bd2f8c8..2097b71192 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -73,8 +73,6 @@ public:
// Returns true if vivox has successfully logged in and is not in error state
virtual bool isVoiceWorking() const;
-
- virtual bool singletoneInstanceExists();
/////////////////////
/// @name Tuning
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 28e9835ffa..7477254159 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -100,12 +100,8 @@ LLSkyTex::LLSkyTex() :
void LLSkyTex::init(bool isShiny)
{
mIsShiny = isShiny;
- // Compiler fix - make sure the array size is an integer value
- // mSkyData = new LLColor4[SKYTEX_RESOLUTION * SKYTEX_RESOLUTION];
- // mSkyDirs = new LLVector3[SKYTEX_RESOLUTION * SKYTEX_RESOLUTION];
mSkyData = new LLColor4[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)];
mSkyDirs = new LLVector3[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)];
- //
for (S32 i = 0; i < 2; ++i)
{
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index cf898cff0c..6a24c1783a 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -247,6 +247,9 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
mColorChanged = FALSE;
mSpotLightPriority = 0.f;
+ mSkinInfoFailed = false;
+ mSkinInfo = NULL;
+
mMediaImplList.resize(getNumTEs());
mLastFetchedMediaVersion = -1;
mServerDrawableUpdateCount = 0;
@@ -265,6 +268,8 @@ LLVOVolume::~LLVOVolume()
delete mVolumeImpl;
mVolumeImpl = NULL;
+ gMeshRepo.unregisterMesh(this);
+
if(!mMediaImplList.empty())
{
for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
@@ -999,10 +1004,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
if (isSculpted())
{
- LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- LLUUID id = sculpt_params->getSculptTexture();
-
- updateSculptTexture();
+ updateSculptTexture();
@@ -1275,10 +1277,15 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo
// if it's a mesh
if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
{
+ if (mSkinInfo && mSkinInfo->mMeshID != volume_params.getSculptID())
+ {
+ mSkinInfo = NULL;
+ mSkinInfoFailed = false;
+ }
+
if (!getVolume()->isMeshAssetLoaded())
{
//load request not yet issued, request pipeline load this mesh
- LLUUID asset_id = volume_params.getSculptID();
S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod);
if (available_lod != lod)
{
@@ -1286,6 +1293,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo
}
}
+ if (!mSkinInfo && !mSkinInfoFailed)
+ {
+ const LLMeshSkinInfo* skin_info = gMeshRepo.getSkinInfo(volume_params.getSculptID(), this);
+ if (skin_info)
+ {
+ notifySkinInfoLoaded(skin_info);
+ }
+ }
}
else // otherwise is sculptie
{
@@ -1318,6 +1333,9 @@ void LLVOVolume::updateSculptTexture()
{
mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
}
+
+ mSkinInfoFailed = false;
+ mSkinInfo = NULL;
}
else
{
@@ -1372,6 +1390,20 @@ void LLVOVolume::notifyMeshLoaded()
updateVisualComplexity();
}
+void LLVOVolume::notifySkinInfoLoaded(const LLMeshSkinInfo* skin)
+{
+ mSkinInfoFailed = false;
+ mSkinInfo = skin;
+
+ notifyMeshLoaded();
+}
+
+void LLVOVolume::notifySkinInfoUnavailable()
+{
+ mSkinInfoFailed = true;
+ mSkinInfo = nullptr;
+}
+
// sculpt replaces generate() for sculpted surfaces
void LLVOVolume::sculpt()
{
@@ -3788,7 +3820,7 @@ const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const
{
if (getVolume())
{
- return gMeshRepo.getSkinInfo(getMeshID(), this);
+ return mSkinInfo;
}
else
{
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 235706eefd..271374a7ab 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -383,6 +383,8 @@ public:
void updateVisualComplexity();
void notifyMeshLoaded();
+ void notifySkinInfoLoaded(const LLMeshSkinInfo* skin);
+ void notifySkinInfoUnavailable();
// Returns 'true' iff the media data for this object is in flight
bool isMediaDataBeingFetched() const;
@@ -475,6 +477,8 @@ private:
LLPointer mRiggedVolume;
+ bool mSkinInfoFailed;
+ LLConstPointer mSkinInfo;
// statics
public:
static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index 26c071b66e..4b8a8a690f 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -98,17 +98,82 @@ LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item, co
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelWearableOutfitItem(&typeid(LLPanelWearableOutfitItem::Params), "wearable_outfit_list_item");
+
+LLPanelWearableOutfitItem::Params::Params()
+: add_btn("add_btn"),
+ remove_btn("remove_btn")
+{
+}
+
+BOOL LLPanelWearableOutfitItem::postBuild()
+{
+ LLPanelWearableListItem::postBuild();
+
+ LLViewerInventoryItem* inv_item = getItem();
+ mShowWidgets &= (inv_item->getType() != LLAssetType::AT_BODYPART);
+ //if(mShowWidgets) // Make Add/Remove buttons work
+ {
+ // Make Add/Remove buttons work
+ //addWidgetToRightSide("add_wearable");
+ //addWidgetToRightSide("remove_wearable");
+ addWidgetToRightSide("add_wearable", mShowWidgets);
+ addWidgetToRightSide("remove_wearable", mShowWidgets);
+ //
+
+ childSetAction("add_wearable", boost::bind(&LLPanelWearableOutfitItem::onAddWearable, this));
+ childSetAction("remove_wearable", boost::bind(&LLPanelWearableOutfitItem::onRemoveWearable, this));
+
+ setWidgetsVisible(false);
+ reshapeWidgets();
+ }
+
+ return TRUE;
+}
+
+BOOL LLPanelWearableOutfitItem::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+ if(!mShowWidgets)
+ {
+ return LLPanelWearableListItem::handleDoubleClick(x, y, mask);
+ }
+
+ if(LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID))
+ {
+ onRemoveWearable();
+ }
+ else
+ {
+ onAddWearable();
+ }
+ return TRUE;
+}
+
+void LLPanelWearableOutfitItem::onAddWearable()
+{
+ setWidgetsVisible(false);
+ reshapeWidgets();
+ LLAppearanceMgr::instance().wearItemOnAvatar(mInventoryItemUUID, true, false);
+}
+
+void LLPanelWearableOutfitItem::onRemoveWearable()
+{
+ setWidgetsVisible(false);
+ reshapeWidgets();
+ LLAppearanceMgr::instance().removeItemFromAvatar(mInventoryItemUUID);
+}
// static
LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryItem* item,
- bool worn_indication_enabled)
+ bool worn_indication_enabled,
+ bool show_widgets)
{
LLPanelWearableOutfitItem* list_item = NULL;
if (item)
{
- const LLPanelInventoryListItemBase::Params& params = LLUICtrlFactory::getDefaultParams();
+ const LLPanelWearableOutfitItem::Params& params = LLUICtrlFactory::getDefaultParams();
- list_item = new LLPanelWearableOutfitItem(item, worn_indication_enabled, params);
+ list_item = new LLPanelWearableOutfitItem(item, worn_indication_enabled, params, show_widgets);
list_item->initFromParams(params);
list_item->postBuild();
}
@@ -116,11 +181,24 @@ LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryIt
}
LLPanelWearableOutfitItem::LLPanelWearableOutfitItem(LLViewerInventoryItem* item,
- bool worn_indication_enabled,
- const LLPanelWearableOutfitItem::Params& params)
-: LLPanelInventoryListItemBase(item, params)
+ bool worn_indication_enabled,
+ const LLPanelWearableOutfitItem::Params& params,
+ bool show_widgets)
+: LLPanelWearableListItem(item, params)
, mWornIndicationEnabled(worn_indication_enabled)
+, mShowWidgets(show_widgets)
+, mIsWorn(false) // Make Add/Remove buttons work
{
+ if(mShowWidgets)
+ {
+ LLButton::Params button_params = params.add_btn;
+ applyXUILayout(button_params, this);
+ addChild(LLUICtrlFactory::create(button_params));
+
+ button_params = params.remove_btn;
+ applyXUILayout(button_params, this);
+ addChild(LLUICtrlFactory::create(button_params));
+ }
}
// virtual
@@ -133,8 +211,11 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name,
// We don't use get_is_item_worn() here because this update is triggered by
// an inventory observer upon link in COF beind added or removed so actual
// worn status of a linked item may still remain unchanged.
+ bool is_worn = LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID);
+ // Make Add/Remove buttons work
+ mIsWorn = is_worn;
// Better attachment list
- //if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID))
+ //if (mWornIndicationEnabled && is_worn)
//{
// search_label += LLTrans::getString("worn");
// item_state = IS_WORN;
@@ -161,9 +242,9 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name,
search_label += LLTrans::getString("AttachmentErrorMessage", args);
}
- item_state = LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID) ? IS_WORN : IS_MISMATCH;
+ item_state = is_worn ? IS_WORN : IS_MISMATCH;
}
- else if (getType() != LLAssetType::AT_OBJECT && LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID))
+ else if (getType() != LLAssetType::AT_OBJECT && is_worn)
{
search_label += LLTrans::getString("worn");
item_state = IS_WORN;
@@ -171,6 +252,17 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name,
}
//
+ if(mShowWidgets)
+ {
+ setShowWidget("add_wearable", !is_worn);
+ setShowWidget("remove_wearable", is_worn);
+ if(mHovered)
+ {
+ setWidgetsVisible(true);
+ reshapeWidgets();
+ }
+ }
+
LLPanelInventoryListItemBase::updateItem(search_label, item_state);
}
@@ -430,13 +522,13 @@ FSPanelCOFWearableOutfitListItem::Params::Params()
// static
FSPanelCOFWearableOutfitListItem* FSPanelCOFWearableOutfitListItem::create(LLViewerInventoryItem* item,
- bool worn_indication_enabled, U32 weight)
+ bool worn_indication_enabled, bool show_widgets, U32 weight)
{
FSPanelCOFWearableOutfitListItem* list_item = NULL;
if(item)
{
const Params& params = LLUICtrlFactory::getDefaultParams();
- list_item = new FSPanelCOFWearableOutfitListItem(item, worn_indication_enabled, params);
+ list_item = new FSPanelCOFWearableOutfitListItem(item, worn_indication_enabled, show_widgets, params);
list_item->initFromParams(params);
list_item->postBuild();
list_item->updateItemWeight(weight);
@@ -447,8 +539,9 @@ FSPanelCOFWearableOutfitListItem* FSPanelCOFWearableOutfitListItem::create(LLVie
FSPanelCOFWearableOutfitListItem::FSPanelCOFWearableOutfitListItem(LLViewerInventoryItem* item,
bool worn_indication_enabled,
+ bool show_widgets,
const FSPanelCOFWearableOutfitListItem::Params& params)
-: LLPanelWearableOutfitItem(item, worn_indication_enabled, params)
+: LLPanelWearableOutfitItem(item, worn_indication_enabled, params, show_widgets)
, mWeightCtrl(NULL)
{
LLTextBox::Params weight_params = params.item_weight;
@@ -460,13 +553,17 @@ BOOL FSPanelCOFWearableOutfitListItem::postBuild()
{
mWeightCtrl = getChild("item_weight");
- LLPanelWearableOutfitItem::postBuild();
+ if (!LLPanelWearableOutfitItem::postBuild())
+ {
+ return FALSE;
+ }
- addWidgetToRightSide("item_weight");
+ addWidgetToRightSide(mWeightCtrl);
// Reserve space for 'delete' button event if it is invisible.
setRightWidgetsWidth(mWeightCtrl->getRect().getWidth() + 5);
+ setWidgetsVisible(true);
reshapeWidgets();
return TRUE;
@@ -483,6 +580,35 @@ void FSPanelCOFWearableOutfitListItem::updateItemWeight(U32 item_weight)
mWeightCtrl->setText(complexity_string);
}
+//virtual
+void FSPanelCOFWearableOutfitListItem::updateItem(const std::string& name, EItemState item_state)
+{
+ LLPanelWearableOutfitItem::updateItem(name, item_state);
+
+ setShowWidget("add_wearable", false);
+ setShowWidget("remove_wearable", mShowWidgets && mIsWorn && mHovered);
+ setWidgetsVisible(true);
+ reshapeWidgets();
+}
+
+//virtual
+void FSPanelCOFWearableOutfitListItem::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ LLPanelInventoryListItemBase::onMouseEnter(x, y, mask);
+ setShowWidget("remove_wearable", mShowWidgets && mIsWorn);
+ setWidgetsVisible(true);
+ reshapeWidgets();
+}
+
+//virtual
+void FSPanelCOFWearableOutfitListItem::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ LLPanelInventoryListItemBase::onMouseLeave(x, y, mask);
+ setShowWidget("remove_wearable", false);
+ setWidgetsVisible(true);
+ reshapeWidgets();
+}
+
//virtual
const LLPanelInventoryListItemBase::Params& FSPanelCOFWearableOutfitListItem::getDefaultParams() const
{
@@ -745,6 +871,7 @@ static const LLDefaultChildRegistry::Register r("wearable_i
LLWearableItemsList::Params::Params()
: standalone("standalone", true)
, worn_indication_enabled("worn_indication_enabled", true)
+, show_item_widgets("show_item_widgets", false)
, show_create_new("show_create_new", true) // Optional "Create new" menu item
, show_complexity("show_complexity", false) // Show per-item complexity in COF
{}
@@ -763,6 +890,7 @@ LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p)
}
mWornIndicationEnabled = p.worn_indication_enabled;
setNoItemsCommentText(LLTrans::getString("LoadingData"));
+ mShowItemWidgets = p.show_item_widgets;
mShowCreateNew = p.show_create_new; // Optional "Create new" menu item
// Show per-item complexity in COF
mShowComplexity = p.show_complexity;
@@ -795,10 +923,10 @@ LLPanel* LLWearableItemsList::createNewItem(LLViewerInventoryItem* item)
}
// Show per-item complexity in COF
- //return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled);
+ //return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled, mShowItemWidgets);
if (!mShowComplexity)
{
- return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled);
+ return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled, mShowItemWidgets);
}
else
{
@@ -813,7 +941,7 @@ LLPanel* LLWearableItemsList::createNewItem(LLViewerInventoryItem* item)
mLinkedItemsMap[linked_item_id] = item->getUUID();
weight = mItemComplexityMap[linked_item_id];
}
- return FSPanelCOFWearableOutfitListItem::create(item, mWornIndicationEnabled, weight);
+ return FSPanelCOFWearableOutfitListItem::create(item, mWornIndicationEnabled, mShowItemWidgets, weight);
}
//
}
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index 4b0a70f252..3a27f23519 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -72,12 +72,23 @@ protected:
* Extends LLPanelInventoryListItemBase with handling
* double click to wear the item.
*/
-class LLPanelWearableOutfitItem : public LLPanelInventoryListItemBase
+class LLPanelWearableOutfitItem : public LLPanelWearableListItem
{
LOG_CLASS(LLPanelWearableOutfitItem);
public:
+ struct Params : public LLInitParam::Block
+ {
+ Optional add_btn, remove_btn;
+
+ Params();
+ };
+
+ BOOL postBuild();
+ BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
+
static LLPanelWearableOutfitItem* create(LLViewerInventoryItem* item,
- bool worn_indication_enabled);
+ bool worn_indication_enabled,
+ bool show_widgets);
/**
* Updates item name and (worn) suffix.
@@ -85,12 +96,20 @@ public:
/*virtual*/ void updateItem(const std::string& name,
EItemState item_state = IS_DEFAULT);
+ void onAddWearable();
+ void onRemoveWearable();
+
protected:
LLPanelWearableOutfitItem(LLViewerInventoryItem* item,
- bool worn_indication_enabled, const Params& params);
+ bool worn_indication_enabled, const Params& params, bool show_widgets = false);
private:
bool mWornIndicationEnabled;
+ // Make Add/Remove buttons work
+protected:
+ bool mShowWidgets;
+ bool mIsWorn;
+ //
};
class LLPanelDeletableWearableListItem : public LLPanelWearableListItem
@@ -222,7 +241,7 @@ class FSPanelCOFWearableOutfitListItem : public LLPanelWearableOutfitItem
{
LOG_CLASS(FSPanelCOFWearableOutfitListItem);
public:
- struct Params : public LLInitParam::Block
+ struct Params : public LLInitParam::Block
{
Optional item_weight;
@@ -230,15 +249,20 @@ public:
};
static FSPanelCOFWearableOutfitListItem* create(LLViewerInventoryItem* item,
- bool worn_indication_enabled, U32 weight);
+ bool worn_indication_enabled, bool show_widgets, U32 weight);
/*virtual*/ BOOL postBuild();
void updateItemWeight(U32 item_weight);
+ /*virtual*/ void updateItem(const std::string& name, EItemState item_state = IS_DEFAULT);
+
+ /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask);
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
+
protected:
FSPanelCOFWearableOutfitListItem(LLViewerInventoryItem* item,
- bool worn_indication_enabled, const Params& params);
+ bool worn_indication_enabled, bool show_widgets, const Params& params);
virtual const LLPanelInventoryListItemBase::Params& getDefaultParams() const;
private:
@@ -479,6 +503,7 @@ public:
{
Optional standalone;
Optional worn_indication_enabled;
+ Optional show_item_widgets;
Optional show_create_new; // Optional "Create new" menu item
Optional show_complexity; // Show per-item complexity in COF
@@ -528,6 +553,7 @@ protected:
bool mIsStandalone;
bool mWornIndicationEnabled;
+ bool mShowItemWidgets;
bool mShowCreateNew; // Optional "Create new" menu item
bool mShowComplexity; // Show per-item complexity in COF
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 26b6e9858e..c57cb63ccd 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -721,13 +721,13 @@ void LLWorld::removeRegion(const LLHost &host)
mRegionRemovedSignal(regionp);
- delete regionp;
-
updateWaterObjects();
//double check all objects of this region are removed.
gObjectList.clearAllMapObjectsInRegion(regionp) ;
//llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ;
+
+ delete regionp; // Delete last to prevent use after free
}
diff --git a/indra/newview/skins/ansastorm/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/ansastorm/xui/en/panel_outfits_wearing.xml
index f87e6f4d30..c32ae40a0a 100644
--- a/indra/newview/skins/ansastorm/xui/en/panel_outfits_wearing.xml
+++ b/indra/newview/skins/ansastorm/xui/en/panel_outfits_wearing.xml
@@ -32,6 +32,7 @@
left="3"
multi_select="true"
name="cof_items_list"
+ show_item_widgets="true"
standalone="false"
top="0"
width="309"
diff --git a/indra/newview/skins/ansastorm/xui/en/widgets/filter_editor.xml b/indra/newview/skins/ansastorm/xui/en/widgets/filter_editor.xml
index 5b8a659f95..895226ef00 100644
--- a/indra/newview/skins/ansastorm/xui/en/widgets/filter_editor.xml
+++ b/indra/newview/skins/ansastorm/xui/en/widgets/filter_editor.xml
@@ -6,7 +6,7 @@
text_pad_left="4"
select_on_focus="true"
text_tentative_color="TextFgTentativeColor"
- highlight_text_field="false"
+ highlight_text_field="true"
background_image="TextField_Off"
background_image_disabled="TextField_Disabled"
background_image_focused="TextField_Active"
diff --git a/indra/newview/skins/ansastorm/xui/en/widgets/search_editor.xml b/indra/newview/skins/ansastorm/xui/en/widgets/search_editor.xml
index 4c582f29ef..97848020dc 100644
--- a/indra/newview/skins/ansastorm/xui/en/widgets/search_editor.xml
+++ b/indra/newview/skins/ansastorm/xui/en/widgets/search_editor.xml
@@ -7,7 +7,7 @@
text_pad_right="2"
select_on_focus="true"
text_tentative_color="TextFgTentativeColor"
- highlight_text_field="false"
+ highlight_text_field="true"
background_image="TextField_Off"
background_image_disabled="TextField_Disabled"
background_image_focused="TextField_Active"
diff --git a/indra/newview/skins/default/textures/icons/add_icon.png b/indra/newview/skins/default/textures/icons/add_icon.png
new file mode 100644
index 0000000000..cb68ee8e16
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/add_icon.png differ
diff --git a/indra/newview/skins/default/textures/icons/remove_icon.png b/indra/newview/skins/default/textures/icons/remove_icon.png
new file mode 100644
index 0000000000..6e62ee33f4
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/remove_icon.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 27f2a30a98..0077d7ad33 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -918,6 +918,9 @@ with the same filename but different name
+
+
+
diff --git a/indra/newview/skins/default/xui/de/floater_pathfinding_linksets.xml b/indra/newview/skins/default/xui/de/floater_pathfinding_linksets.xml
index 61ce6185dc..c777dfeef0 100644
--- a/indra/newview/skins/default/xui/de/floater_pathfinding_linksets.xml
+++ b/indra/newview/skins/default/xui/de/floater_pathfinding_linksets.xml
@@ -97,9 +97,11 @@
Name
+
Beschreibung
+
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml
index 30d996468d..a7fc26560c 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml
@@ -15,7 +15,7 @@
Anmelden, um Änderungen vorzunehmen
-
+
(Standorte, Bilder, Web, Suchverlauf)
diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index c48c3899a4..d6f1881e78 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -5475,7 +5475,7 @@ Falls der Fehler weiterhin auftritt, überprüfen Sie bitte Ihre Netzwerk- und F
Premium Plus
- Upgrade auf Premium
+ Mitgliedschaft ändern...
Meine Premium-Mitgliedschaft
diff --git a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml
index 1cd2f38f0c..8f1ea2c664 100644
--- a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml
+++ b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml
@@ -82,17 +82,20 @@
width="62">
Name
-
+
+
+
Description
-
+
+
Premium Plus
Internal
- Upgrade to Premium
+ Change membership plan...
My Premium membership
diff --git a/indra/newview/skins/default/xui/en/widgets/cof_wearable_list_item.xml b/indra/newview/skins/default/xui/en/widgets/cof_wearable_list_item.xml
index 6fadd96cdd..c8bcdced25 100644
--- a/indra/newview/skins/default/xui/en/widgets/cof_wearable_list_item.xml
+++ b/indra/newview/skins/default/xui/en/widgets/cof_wearable_list_item.xml
@@ -57,4 +57,26 @@
top="4"
value="..."
width="70" />
+
+
diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
index b523b26a14..b455ffb0bd 100644
--- a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml
@@ -6,7 +6,7 @@
text_pad_left="10"
select_on_focus="true"
text_tentative_color="TextFgTentativeColor"
- highlight_text_field="false"
+ highlight_text_field="true"
background_image="TextField_Search_Off"
background_image_disabled="TextField_Search_Disabled"
background_image_focused="TextField_Search_Active"
diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
index dc5a07bf4f..18d99f1ed1 100644
--- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
@@ -7,7 +7,7 @@
text_pad_right="6"
select_on_focus="true"
text_tentative_color="TextFgTentativeColor"
- highlight_text_field="false"
+ highlight_text_field="true"
background_image="TextField_Search_Off"
background_image_disabled="TextField_Search_Disabled"
background_image_focused="TextField_Search_Active"
diff --git a/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml b/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml
new file mode 100644
index 0000000000..830eef0abb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/indra/newview/skins/firestorm/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/firestorm/xui/en/panel_outfits_wearing.xml
index 8fa509aede..9c327d64a7 100644
--- a/indra/newview/skins/firestorm/xui/en/panel_outfits_wearing.xml
+++ b/indra/newview/skins/firestorm/xui/en/panel_outfits_wearing.xml
@@ -34,6 +34,7 @@
left="3"
multi_select="true"
name="cof_items_list"
+ show_item_widgets="true"
standalone="false"
top="0"
width="309"
diff --git a/indra/newview/skins/vintage/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/vintage/xui/en/panel_outfits_wearing.xml
index 1fd2b41ac1..f421265c79 100644
--- a/indra/newview/skins/vintage/xui/en/panel_outfits_wearing.xml
+++ b/indra/newview/skins/vintage/xui/en/panel_outfits_wearing.xml
@@ -34,6 +34,7 @@
left="3"
multi_select="true"
name="cof_items_list"
+ show_item_widgets="true"
standalone="false"
top="0"
width="309"
diff --git a/indra/newview/skins/vintage/xui/en/widgets/filter_editor.xml b/indra/newview/skins/vintage/xui/en/widgets/filter_editor.xml
index fade91903f..6bbc236d4d 100644
--- a/indra/newview/skins/vintage/xui/en/widgets/filter_editor.xml
+++ b/indra/newview/skins/vintage/xui/en/widgets/filter_editor.xml
@@ -6,7 +6,7 @@
text_pad_left="7"
select_on_focus="true"
text_tentative_color="TextFgTentativeColor"
- highlight_text_field="false"
+ highlight_text_field="true"
background_image="TextField_Off"
background_image_disabled="TextField_Disabled"
background_image_focused="TextField_Active"
diff --git a/indra/newview/skins/vintage/xui/en/widgets/search_editor.xml b/indra/newview/skins/vintage/xui/en/widgets/search_editor.xml
index 5e6fabfcbe..007a6d1a2e 100644
--- a/indra/newview/skins/vintage/xui/en/widgets/search_editor.xml
+++ b/indra/newview/skins/vintage/xui/en/widgets/search_editor.xml
@@ -7,7 +7,7 @@
text_pad_right="6"
select_on_focus="true"
text_tentative_color="TextFgTentativeColor"
- highlight_text_field="false"
+ highlight_text_field="true"
background_image="TextField_Off"
background_image_disabled="TextField_Disabled"
background_image_focused="TextField_Active"
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 2c8829d306..063064119f 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -2174,7 +2174,7 @@ class Linux_i686_Manifest(LinuxManifest):
self.path("libdirectfb-1.*.so.*")
self.path("libfusion-1.*.so.*")
self.path("libdirect-1.*.so.*")
- self.path("libopenjpeg.so*")
+ self.path("libopenjp2.so*")
self.path("libdirectfb-1.4.so.5")
self.path("libfusion-1.4.so.5")
self.path("libdirect-1.4.so.5*")
diff --git a/indra/newview/vjlocalmesh.cpp b/indra/newview/vjlocalmesh.cpp
index 55b102e8e3..98f5ac3b32 100644
--- a/indra/newview/vjlocalmesh.cpp
+++ b/indra/newview/vjlocalmesh.cpp
@@ -308,12 +308,12 @@ void LLLocalMeshObject::attachSkinInfo()
auto skinmap_seeker = gMeshRepo.mSkinMap.find(mSculptID);
if (skinmap_seeker == gMeshRepo.mSkinMap.end())
{
- gMeshRepo.mSkinMap[mSculptID] = mMeshSkinInfo;
+ gMeshRepo.mSkinMap[mSculptID] = &mMeshSkinInfo;
}
else
{
// NOTE: seems necessary, not tested without.
- skinmap_seeker->second = mMeshSkinInfo;
+ skinmap_seeker->second = &mMeshSkinInfo;
}
}