diff options
Diffstat (limited to 'indra')
169 files changed, 3291 insertions, 2131 deletions
| diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index ff705101de..04b4202ca3 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -52,7 +52,7 @@ if(WINDOWS)      set(release_src_dir "${ARCH_PREBUILT_DIRS_RELEASE}")      set(release_files -        openjpeg.dll +        openjp2.dll          libapr-1.dll          libaprutil-1.dll          libapriconv-1.dll @@ -220,7 +220,7 @@ elseif(LINUX)          libgobject-2.0.so          libhunspell-1.3.so.0.0.0          libopenal.so -        libopenjpeg.so +        libopenjp2.so          libuuid.so.16          libuuid.so.16.0.22          libfontconfig.so.1.8.0 diff --git a/indra/cmake/FindOpenJPEG.cmake b/indra/cmake/FindOpenJPEG.cmake index 949384eec4..2d4353b54f 100644 --- a/indra/cmake/FindOpenJPEG.cmake +++ b/indra/cmake/FindOpenJPEG.cmake @@ -14,9 +14,10 @@ FIND_PATH(OPENJPEG_INCLUDE_DIR openjpeg.h  /usr/local/include  /usr/include/openjpeg  /usr/include +include/openjpeg  ) -SET(OPENJPEG_NAMES ${OPENJPEG_NAMES} openjpeg) +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 bf0bde2ba7..a078c97cb8 100644 --- a/indra/cmake/OpenJPEG.cmake +++ b/indra/cmake/OpenJPEG.cmake @@ -8,15 +8,7 @@ if (USESYSTEMLIBS)    include(FindOpenJPEG)  else (USESYSTEMLIBS)    use_prebuilt_binary(openjpeg) -   -  if(WINDOWS) -    # Windows has differently named release and debug openjpeg(d) libs. -    set(OPENJPEG_LIBRARIES  -        debug openjpegd -        optimized openjpeg) -  else(WINDOWS) -    set(OPENJPEG_LIBRARIES openjpeg) -  endif(WINDOWS) -   -    set(OPENJPEG_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/openjpeg) + +  set(OPENJPEG_LIBRARIES openjp2) +  set(OPENJPEG_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/openjpeg)  endif (USESYSTEMLIBS) diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt index d7706e73b2..3957ede77f 100644 --- a/indra/integration_tests/llui_libtest/CMakeLists.txt +++ b/indra/integration_tests/llui_libtest/CMakeLists.txt @@ -99,14 +99,14 @@ if (WINDOWS)      # Copy over OpenJPEG.dll      # *NOTE: On Windows with VS2005, only the first comment prints      set(OPENJPEG_RELEASE -        "${ARCH_PREBUILT_DIRS_RELEASE}/openjpeg.dll") +        "${ARCH_PREBUILT_DIRS_RELEASE}/openjp2.dll")      add_custom_command( TARGET llui_libtest POST_BUILD          COMMAND ${CMAKE_COMMAND} -E copy_if_different               ${OPENJPEG_RELEASE} ${CMAKE_CURRENT_BINARY_DIR}          COMMENT "Copying OpenJPEG DLLs to binary directory"          )      set(OPENJPEG_DEBUG -        "${ARCH_PREBUILT_DIRS_DEBUG}/openjpegd.dll") +        "${ARCH_PREBUILT_DIRS_DEBUG}/openjp2.dll")      add_custom_command( TARGET llui_libtest POST_BUILD          COMMAND ${CMAKE_COMMAND} -E copy_if_different               ${OPENJPEG_DEBUG} ${CMAKE_CURRENT_BINARY_DIR} diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index f0df3e1474..c1336fd612 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -305,7 +305,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 3f564ec3de..0481326e9e 100644 --- a/indra/llappearance/lllocaltextureobject.cpp +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -76,6 +76,7 @@ LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject& lto) :  LLLocalTextureObject::~LLLocalTextureObject()  { +	delete_and_clear(mTexLayers);  }  LLGLTexture* LLLocalTextureObject::getImage() const diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index ebf7454a61..403d5bcf49 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -1229,7 +1229,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<LLKeyframeMotion::JointMotionList> joint_motion_list(new LLKeyframeMotion::JointMotionList);  	//-------------------------------------------------------------------------  	// get base priority @@ -1272,16 +1272,16 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo                     << " for animation " << asset_id << LL_ENDL;  		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;  		return FALSE;  	} @@ -1289,15 +1289,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo  	//-------------------------------------------------------------------------  	// 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;  		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; @@ -1307,14 +1307,14 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo  	//-------------------------------------------------------------------------  	// 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;  		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; @@ -1324,23 +1324,23 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo  	//-------------------------------------------------------------------------  	// 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;  		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;  		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; @@ -1353,22 +1353,22 @@ 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;  		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; @@ -1393,7 +1393,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo  		return FALSE;  	} -	mJointMotionList->mHandPose = (LLHandMotion::eHandPose)word; +	joint_motion_list->mHandPose = (LLHandMotion::eHandPose)word;  	//-------------------------------------------------------------------------  	// get number of joint motions @@ -1419,8 +1419,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo  		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); @@ -1431,7 +1431,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo  	for(U32 i=0; i<num_motions; ++i)  	{  		JointMotion* joint_motion = new JointMotion;		 -		mJointMotionList->mJointMotionArray.push_back(joint_motion); +		joint_motion_list->mJointMotionArray.push_back(joint_motion);  		std::string joint_name;  		if (!dp.unpackString(joint_name, "joint_name")) @@ -1503,9 +1503,9 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo  		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); @@ -1556,9 +1556,9 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo  					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; @@ -1571,38 +1571,57 @@ 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()) ) -			{ -				LL_WARNS() << "non-finite angle in rotation key" -                           << " for animation " << asset_id << LL_ENDL; -				success = FALSE; -			} -			 -			if (!success) +			if(!rot_key.mRotation.isFinite())  			{ -				LL_WARNS() << "can't read rotation key (" << k << ")" +				LL_WARNS() << "non-finite angle in rotation key (" << k << ")"                             << " for animation " << asset_id << LL_ENDL;  				return FALSE;  			} @@ -1655,14 +1674,16 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo  					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); @@ -1674,26 +1695,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;  				return FALSE;  			} @@ -1701,7 +1727,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);  			}  		} @@ -1733,23 +1759,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<JointConstraintSharedData> 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;  				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;  				return FALSE;  			} @@ -1757,7 +1781,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;  				return FALSE;  			} @@ -1765,7 +1788,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo  			{  				LL_WARNS() << "invalid constraint type"                             << " for animation " << asset_id << LL_ENDL; -				delete constraintp;  				return FALSE;  			}  			constraintp->mConstraintType = (EConstraintType)byte; @@ -1776,7 +1798,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;  				return FALSE;  			} @@ -1787,7 +1808,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;  				return FALSE;  			} @@ -1795,7 +1815,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;  				return FALSE;  			} @@ -1803,7 +1822,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;  				return FALSE;  			} @@ -1811,7 +1829,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;  				return FALSE;  			} @@ -1830,7 +1847,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;  					return FALSE;  				}  			} @@ -1839,7 +1855,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;  				return FALSE;  			} @@ -1847,7 +1862,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;  				return FALSE;  			} @@ -1855,7 +1869,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;  				return FALSE;  			} @@ -1863,7 +1876,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;  				return FALSE;  			} @@ -1877,7 +1889,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;  				return FALSE;  			} @@ -1885,7 +1896,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;  				return FALSE;  			} @@ -1893,7 +1903,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;  				return FALSE;  			} @@ -1901,33 +1910,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;  				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)  			{  				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;  					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); @@ -1948,14 +1955,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; -					delete constraintp;  					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 14bfb98629..70d8dfc8b9 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -288,25 +288,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 @@ -319,28 +309,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); @@ -350,12 +350,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&)      { @@ -366,36 +366,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 919d2dabc4..56fb7c21ca 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -943,7 +943,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 8b4a0ee6d8..a510b73096 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -34,6 +34,9 @@  #include <iostream>  #include "apr_base64.h" +#include <boost/iostreams/device/array.hpp> +#include <boost/iostreams/stream.hpp> +  #ifdef LL_USESYSTEMLIBS  # include <zlib.h>  #else @@ -2128,7 +2131,9 @@ std::string zip_llsd(LLSD& data)  		{ //copy result into output  			if (strm.avail_out >= CHUNK)  			{ -				free(output); +				deflateEnd(&strm); +				if(output) +					free(output);  				LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;  				return std::string();  			} @@ -2151,7 +2156,9 @@ std::string zip_llsd(LLSD& data)  		}  		else   		{ -			free(output); +			deflateEnd(&strm); +			if(output) +				free(output);  			LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;  			return std::string();  		} @@ -2162,7 +2169,8 @@ std::string zip_llsd(LLSD& data)  	std::string result((char*) output, size);  	deflateEnd(&strm); -	free(output); +	if(output) +		free(output);  	return result;  } @@ -2172,53 +2180,66 @@ 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)  { +	std::unique_ptr<U8[]> in = std::unique_ptr<U8[]>(new(std::nothrow) U8[size]); +	if (!in) +	{ +		return ZR_MEM_ERROR; +	} +	is.read((char*) in.get(), size);  + +	return unzip_llsd(data, in.get(), size); +} + +LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 size) +{  	U8* result = NULL;  	U32 cur_size = 0;  	z_stream strm; -	const U32 CHUNK = 65536; +	constexpr U32 CHUNK = 1024 * 512; -	U8 *in = new(std::nothrow) U8[size]; -	if (!in) +	static thread_local std::unique_ptr<U8[]> out; +	if (!out)  	{ -		return ZR_MEM_ERROR; +		out = std::unique_ptr<U8[]>(new(std::nothrow) U8[CHUNK]);  	} -	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; +	strm.next_in = const_cast<U8*>(in);  	S32 ret = inflateInit(&strm);  	do  	{  		strm.avail_out = CHUNK; -		strm.next_out = out; +		strm.next_out = out.get();  		ret = inflate(&strm, Z_NO_FLUSH); -		if (ret == Z_STREAM_ERROR) +		switch (ret) +		{ +		case Z_NEED_DICT: +		case Z_DATA_ERROR:  		{  			inflateEnd(&strm);  			free(result); -			delete [] in;  			return ZR_DATA_ERROR;  		} -		 -		switch (ret) +		case Z_STREAM_ERROR: +		case Z_BUF_ERROR:  		{ -		case Z_NEED_DICT: -			ret = Z_DATA_ERROR; -		case Z_DATA_ERROR: +			inflateEnd(&strm); +			free(result); +			return ZR_BUFFER_ERROR; +		} +  		case Z_MEM_ERROR: +		{  			inflateEnd(&strm);  			free(result); -			delete [] in;  			return ZR_MEM_ERROR; -			break; +		}  		}  		U32 have = CHUNK-strm.avail_out; @@ -2231,17 +2252,15 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,  			{  				free(result);  			} -			delete[] in;  			return ZR_MEM_ERROR;  		}  		result = new_result; -		memcpy(result+cur_size, out, have); +		memcpy(result+cur_size, out.get(), have);  		cur_size += have; -	} while (ret == Z_OK); +	} while (ret == Z_OK && ret != Z_STREAM_END);  	inflateEnd(&strm); -	delete [] in;  	if (ret != Z_STREAM_END)  	{ @@ -2251,37 +2270,11 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is,  	//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); -			return ZR_SIZE_ERROR; -		} -#endif -		catch (std::bad_alloc&) -		{ -			free(result); -			return ZR_MEM_ERROR; -		} +		char* result_ptr = strip_deprecated_header((char*)result, cur_size); -		if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH)) +		boost::iostreams::stream<boost::iostreams::array_source> istrm(result_ptr, cur_size); +		 +		if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH))  		{  			free(result);  			return ZR_PARSE_ERROR; @@ -2395,4 +2388,22 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32  	return result;  } +char* strip_deprecated_header(char* in, U32& cur_size, U32* header_size) +{ +	const char* deprecated_header = "<? LLSD/Binary ?>"; +	constexpr size_t deprecated_header_size = 17; + +	if (cur_size > deprecated_header_size +		&& memcmp(in, deprecated_header, deprecated_header_size) == 0) +	{ +		in = in + deprecated_header_size; +		cur_size = cur_size - deprecated_header_size; +		if (header_size) +		{ +			*header_size = deprecated_header_size + 1; +		} +	} + +	return in; +} diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index d6079fd9fa..d33d2b6f34 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -858,9 +858,12 @@ public:          ZR_SIZE_ERROR,          ZR_DATA_ERROR,          ZR_PARSE_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);  };  //dirty little zip functions -- yell at davep @@ -868,4 +871,7 @@ LL_COMMON_API std::string zip_llsd(LLSD& data);  LL_COMMON_API U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize,std::istream& is, S32 size); + +// 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 acce8366ea..6f9e09a587 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -1009,36 +1009,6 @@ LLUUID::LLUUID()  	return !(word[0] | word[1] | word[2] | word[3]);  } -// Copy constructor - LLUUID::LLUUID(const LLUUID& rhs) -{ -	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]; -} - - LLUUID::~LLUUID() -{ -} - -// Assignment - LLUUID& LLUUID::operator=(const LLUUID& rhs) -{ -	// 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]; -	 -	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 86a396ab06..c139c4eb4e 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -55,10 +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 &operator=(const LLUUID &rhs); - -	~LLUUID(); +	~LLUUID() = default;  	//  	// MANIPULATORS @@ -131,6 +128,9 @@ public:  	U8 mData[UUID_BYTES];  }; +static_assert(std::is_trivially_copyable<LLUUID>::value, "LLUUID must be trivial copy"); +static_assert(std::is_trivially_move_assignable<LLUUID>::value, "LLUUID must be trivial move"); +static_assert(std::is_standard_layout<LLUUID>::value, "LLUUID must be a standard layout type");  typedef std::vector<LLUUID> uuid_vec_t;  typedef std::set<LLUUID> uuid_set_t; diff --git a/indra/llcommon/threadsafeschedule.h b/indra/llcommon/threadsafeschedule.h index 3e0da94c02..0c3a541196 100644 --- a/indra/llcommon/threadsafeschedule.h +++ b/indra/llcommon/threadsafeschedule.h @@ -248,7 +248,7 @@ namespace LL                  TimePoint until = TimePoint::clock::now() + std::chrono::hours(24);                  pop_result popped = tryPopUntil_(lock, until, tt);                  if (popped == POPPED) -                    return std::move(tt); +                    return tt;                  // DONE: throw, just as super::pop() does                  if (popped == DONE) diff --git a/indra/llfilesystem/lldir_mac.cpp b/indra/llfilesystem/lldir_mac.cpp index 3bc4ee844e..9ad8e274b6 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 = "SecondLife"; -    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.              CreateDirectory(mOSCacheDir, secondLifeString, NULL);  		} @@ -143,12 +141,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 <iostream> -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 <Cocoa/Cocoa.h> -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 925da5674b..12985c3c7f 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -29,40 +29,41 @@  // this is defined so that we get static linking.  #include "openjpeg.h" +#include "event.h" +#include "cio.h" -#include "lltimer.h" -//#include "llmemory.h" +#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(); +    return std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ") +        + opj_version();  #else -	return std::string("OpenJPEG runtime: ") + opj_version(); +    return std::string("OpenJPEG runtime: ") + opj_version();  #endif  }  // 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;  }  /** @@ -70,419 +71,770 @@ 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;  } - -LLImageJ2COJ::LLImageJ2COJ() -	: LLImageJ2CImpl() +class JPEG2KBase  { -} +public: +    JPEG2KBase() {} +    U8*        buffer = nullptr; +    OPJ_SIZE_T size = 0; +    OPJ_OFF_T  offset = 0; +}; -LLImageJ2COJ::~LLImageJ2COJ() +#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  } -bool LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region) +static void opj_warn(const char* msg, void* user_data)  { -	// No specific implementation for this method in the OpenJpeg case -	return false; +    llassert(user_data); +#if WANT_VERBOSE_OPJ_SPAM +    LL_WARNS("OpenJPEG") << msg << LL_ENDL; +#endif  } -bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels) +static void opj_error(const char* msg, void* user_data)  { -	// No specific implementation for this method in the OpenJpeg case -	return false; +    llassert(user_data); +#if WANT_VERBOSE_OPJ_SPAM +    LL_WARNS("OpenJPEG") << msg << LL_ENDL; +#endif  } -bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) +static OPJ_SIZE_T opj_read(void * buffer, OPJ_SIZE_T bytes, void* user_data)  { -	// -	// FIXME: Get the comment field out of the texture -	// - -	LLTimer decode_timer; - -	opj_dparameters_t parameters;	/* decompression parameters */ -	opj_event_mgr_t event_mgr;		/* event manager */ -	opj_image_t *image = NULL; - -	opj_dinfo_t* dinfo = NULL;	/* handle to a decompressor */ -	opj_cio_t *cio = NULL; - - -	/* 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); - -	parameters.cp_reduce = base.getRawDiscardLevel(); - -	/* decode the code-stream */ -	/* ---------------------- */ - -	/* JPEG-2000 codestream */ - -	/* 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); -	} - -	// 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. -	if(!image || !image->numcomps) -	{ -		LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL; -		if (image) -		{ -			opj_image_destroy(image); -		} - -		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 -			opj_image_destroy(image); -			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); -		} -			 -		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(); - -	// 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); - -			return true; // done -		} -	} - -	/* free image data structure */ -	opj_image_destroy(image); - -	return true; // done +    llassert(user_data); +    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(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;  } - -bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible) +static OPJ_SIZE_T opj_write(void * buffer, OPJ_SIZE_T bytes, void* user_data)  { -	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 -	// -	OPJ_COLOR_SPACE color_space = CLRSPC_SRGB; -	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 */ -	/* ---------------------------- */ - -	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); - -	/* free image data */ -	opj_image_destroy(image); -	return true; +    llassert(user_data); +    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(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;  } -bool LLImageJ2COJ::getMetadata(LLImageJ2C &base) +static OPJ_OFF_T opj_skip(OPJ_OFF_T bytes, void* user_data)  { -	// -	// FIXME: We get metadata by decoding the ENTIRE image. -	// - -	// Update the raw discard level -	base.updateRawDiscardLevel(); - -	opj_dparameters_t parameters;	/* decompression parameters */ -	opj_event_mgr_t event_mgr;		/* event manager */ -	opj_image_t *image = NULL; - -	opj_dinfo_t* dinfo = NULL;	/* handle to a decompressor */ -	opj_cio_t *cio = NULL; - - -	/* 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. -	parameters.cp_limit_decoding=LIMIT_TO_MAIN_HEADER; +    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(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; +} -	//parameters.cp_reduce = mRawDiscardLevel; +static OPJ_BOOL opj_seek(OPJ_OFF_T bytes, void * user_data) +{ +    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data); +    jpeg_codec->offset = bytes; +    jpeg_codec->offset = llclamp(U32(jpeg_codec->offset), U32(0), U32(jpeg_codec->size)); +    return OPJ_TRUE; +} -	/* decode the code-stream */ -	/* ---------------------- */ +static void opj_free_user_data(void * user_data) +{ +    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data); +    // Don't free, data is managed externally +    jpeg_codec->buffer = nullptr; +    jpeg_codec->size = 0; +    jpeg_codec->offset = 0; +} -	/* JPEG-2000 codestream */ +static void opj_free_user_data_write(void * user_data) +{ +    JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(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; +} -	/* get a decoder handle */ -	dinfo = opj_create_decompress(CODEC_J2K); +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; +}; -	/* 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); +LLImageJ2COJ::LLImageJ2COJ() +	: LLImageJ2CImpl() +{ +} -	/* 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); +LLImageJ2COJ::~LLImageJ2COJ() +{ +} -	/* close the byte stream */ -	opj_cio_close(cio); +bool LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region) +{ +    base.mDiscardLevel = discard_level; +	return false; +} -	/* free remaining structures */ -	if(dinfo) -	{ -		opj_destroy_decompress(dinfo); -	} +bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels) +{ +	// No specific implementation for this method in the OpenJpeg case +	return false; +} -	if(!image) -	{ -		LL_WARNS() << "ERROR -> getMetadata: failed to decode image!" << LL_ENDL; -		return false; -	} +bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) +{ +    JPEG2KDecode decoder(0); + +    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); + +    // 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); + +    if (!decoded) +    { +        // reset the channel count if necessary +        if (raw_image.getComponents() != channels) +        { +            raw_image.resize(raw_image.getWidth(), raw_image.getHeight(), S8(channels)); +        } + +        LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL; +        return true; // done +    } + +    opj_image_t *image = decoder.getImage(); + +    // 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; + +    // do size the texture to the mem we'll acrually use... +    U32 width = image->comps[0].w; +    U32 height = image->comps[0].h; + +    raw_image.resize(U16(width), U16(height), S8(channels)); + +    U8 *rawp = raw_image.getData(); + +    // 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; +        } +    } + +    base.setDiscardLevel(f); + +    return true; // done +} -	// Copy image data into our raw image format (instead of the separate channel format -	S32 width = 0; -	S32 height = 0; -	S32 img_components = image->numcomps; -	width = image->x1 - image->x0; -	height = image->y1 - image->y0; -	base.setSize(width, height, img_components); +bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible) +{ +    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; +} -	/* free image data structure */ -	opj_image_destroy(image); -	return true; +bool LLImageJ2COJ::getMetadata(LLImageJ2C &base) +{ +    JPEG2KDecode decode(0); + +    S32 width = 0; +    S32 height = 0; +    S32 components = 0; +    S32 discard_level = 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; +    } + +    base.mDiscardLevel = discard_level; +    base.setSize(width, height, components); +    return true;  } diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index be25592d54..281f1bd87a 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2386,7 +2386,25 @@ 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;  	} -	 +	return unpackVolumeFacesInternal(mdl); +} + +bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size) +{ +	//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); +	if (uzip_result != LLUZipHelper::ZR_OK) +	{ +		LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; +		return false; +	} +	return unpackVolumeFacesInternal(mdl); +} + +bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) +{  	{  		U32 face_count = mdl.size(); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 3ccaed47f1..1509241623 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -1101,8 +1101,12 @@ protected:  	BOOL generate();  	void createVolumeFaces();  public: -	virtual bool unpackVolumeFaces(std::istream& is, S32 size); +	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 b6adc102d2..9f7768f78e 100644 --- a/indra/llmessage/lldatapacker.cpp +++ b/indra/llmessage/lldatapacker.cpp @@ -116,9 +116,8 @@ BOOL LLDataPacker::packFixed(const F32 value, const char *name,  BOOL LLDataPacker::unpackFixed(F32 &value, const char *name,  							   const BOOL is_signed, const U32 int_bits, const U32 frac_bits)  { -	//BOOL success = TRUE; +	BOOL success = TRUE;  	//LL_INFOS() << "unpackFixed:" << name << " int:" << int_bits << " frac:" << frac_bits << LL_ENDL; -	BOOL ok = FALSE;  	S32 unsigned_bits = int_bits + frac_bits;  	S32 total_bits = unsigned_bits; @@ -134,19 +133,19 @@ BOOL LLDataPacker::unpackFixed(F32 &value, const char *name,  	if (total_bits <= 8)  	{  		U8 fixed_8; -		ok = unpackU8(fixed_8, name); +		success = unpackU8(fixed_8, name);  		fixed_val = (F32)fixed_8;  	}  	else if (total_bits <= 16)  	{  		U16 fixed_16; -		ok = unpackU16(fixed_16, name); +		success = unpackU16(fixed_16, name);  		fixed_val = (F32)fixed_16;  	}  	else if (total_bits <= 31)  	{  		U32 fixed_32; -		ok = unpackU32(fixed_32, name); +		success = unpackU32(fixed_32, name);  		fixed_val = (F32)fixed_32;  	}  	else @@ -164,7 +163,7 @@ BOOL LLDataPacker::unpackFixed(F32 &value, const char *name,  	}  	value = fixed_val;  	//LL_INFOS() << "Value: " << value << LL_ENDL; -	return ok; +	return success;  }  BOOL LLDataPacker::unpackU16s(U16 *values, S32 count, const char *name) @@ -238,37 +237,43 @@ BOOL LLDataPacker::unpackUUIDs(LLUUID *values, S32 count, const char *name)  BOOL LLDataPackerBinaryBuffer::packString(const std::string& value, const char *name)  { -	BOOL success = TRUE;  	S32 length = value.length()+1; -	success &= verifyLength(length, name); +	if (!verifyLength(length, name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{  		htolememcpy(mCurBufferp, value.c_str(), MVT_VARIABLE, length);    	}  	mCurBufferp += length; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackString(std::string& value, const char *name)  { -	BOOL success = TRUE;  	S32 length = (S32)strlen((char *)mCurBufferp) + 1; /*Flawfinder: ignore*/ -	success &= verifyLength(length, name); +	if (!verifyLength(length, name)) +	{ +		return FALSE; +	}  	value = std::string((char*)mCurBufferp); // We already assume NULL termination calling strlen()  	mCurBufferp += length; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packBinaryData(const U8 *value, S32 size, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(size + 4, name); +	if (!verifyLength(size + 4, name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{  @@ -280,102 +285,117 @@ BOOL LLDataPackerBinaryBuffer::packBinaryData(const U8 *value, S32 size, const c  		htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);    	}  	mCurBufferp += size; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackBinaryData(U8 *value, S32 &size, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(4, name); -	htolememcpy(&size, mCurBufferp, MVT_S32, 4); -	mCurBufferp += 4; -	success &= verifyLength(size, name); -	if (success) +	if (!verifyLength(4, name))  	{ -		htolememcpy(value, mCurBufferp, MVT_VARIABLE, size); -		mCurBufferp += size; +		LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData would unpack invalid data, aborting!" << LL_ENDL; +		return FALSE;  	} -	else + +	htolememcpy(&size, mCurBufferp, MVT_S32, 4); +	mCurBufferp += 4; + +	if (!verifyLength(size, name))  	{  		LL_WARNS() << "LLDataPackerBinaryBuffer::unpackBinaryData would unpack invalid data, aborting!" << LL_ENDL; -		success = FALSE; +		return FALSE;  	} -	return success; + +	htolememcpy(value, mCurBufferp, MVT_VARIABLE, size); +	mCurBufferp += size; + +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packBinaryDataFixed(const U8 *value, S32 size, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(size, name); +	if (!verifyLength(size, name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{   		htolememcpy(mCurBufferp, value, MVT_VARIABLE, size);    	}  	mCurBufferp += size; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackBinaryDataFixed(U8 *value, S32 size, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(size, name); +	if (!verifyLength(size, name)) +	{ +		return FALSE; +	}  	htolememcpy(value, mCurBufferp, MVT_VARIABLE, size);  	mCurBufferp += size; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packU8(const U8 value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(sizeof(U8), name); +	if (!verifyLength(sizeof(U8), name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{  		*mCurBufferp = value;  	}  	mCurBufferp++; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackU8(U8 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(sizeof(U8), name); +	if (!verifyLength(sizeof(U8), name)) +	{ +		return FALSE; +	}  	value = *mCurBufferp;  	mCurBufferp++; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packU16(const U16 value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(sizeof(U16), name); +	if (!verifyLength(sizeof(U16), name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{   		htolememcpy(mCurBufferp, &value, MVT_U16, 2);    	}  	mCurBufferp += 2; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackU16(U16 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(sizeof(U16), name); +	if (!verifyLength(sizeof(U16), name)) +	{ +		return FALSE; +	}  	htolememcpy(&value, mCurBufferp, MVT_U16, 2);  	mCurBufferp += 2; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packS16(const S16 value, const char *name) @@ -404,134 +424,156 @@ BOOL LLDataPackerBinaryBuffer::unpackS16(S16 &value, const char *name)  BOOL LLDataPackerBinaryBuffer::packU32(const U32 value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(sizeof(U32), name); +	if (!verifyLength(sizeof(U32), name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{   		htolememcpy(mCurBufferp, &value, MVT_U32, 4);    	}  	mCurBufferp += 4; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackU32(U32 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(sizeof(U32), name); +	if (!verifyLength(sizeof(U32), name)) +	{ +		return FALSE; +	}  	htolememcpy(&value, mCurBufferp, MVT_U32, 4);  	mCurBufferp += 4; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packS32(const S32 value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(sizeof(S32), name); +	if (!verifyLength(sizeof(S32), name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{   		htolememcpy(mCurBufferp, &value, MVT_S32, 4);   	}  	mCurBufferp += 4; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackS32(S32 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(sizeof(S32), name); +	if(!verifyLength(sizeof(S32), name)) +	{ +		return FALSE; +	}  	htolememcpy(&value, mCurBufferp, MVT_S32, 4);  	mCurBufferp += 4; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packF32(const F32 value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(sizeof(F32), name); +	if (!verifyLength(sizeof(F32), name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{   		htolememcpy(mCurBufferp, &value, MVT_F32, 4);   	}  	mCurBufferp += 4; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackF32(F32 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(sizeof(F32), name); +	if (!verifyLength(sizeof(F32), name)) +	{ +		return FALSE; +	}  	htolememcpy(&value, mCurBufferp, MVT_F32, 4);  	mCurBufferp += 4; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packColor4(const LLColor4 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(16, name); +	if (!verifyLength(16, name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{   		htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);   	}  	mCurBufferp += 16; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackColor4(LLColor4 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(16, name); +	if (!verifyLength(16, name)) +	{ +		return FALSE; +	}  	htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);  	mCurBufferp += 16; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packColor4U(const LLColor4U &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(4, name); +	if (!verifyLength(4, name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{   		htolememcpy(mCurBufferp, value.mV, MVT_VARIABLE, 4);    	}  	mCurBufferp += 4; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackColor4U(LLColor4U &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(4, name); +	if (!verifyLength(4, name)) +	{ +		return FALSE; +	}  	htolememcpy(value.mV, mCurBufferp, MVT_VARIABLE, 4);  	mCurBufferp += 4; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packVector2(const LLVector2 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(8, name); +	if (!verifyLength(8, name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{  @@ -539,92 +581,106 @@ BOOL LLDataPackerBinaryBuffer::packVector2(const LLVector2 &value, const char *n  		htolememcpy(mCurBufferp+4, &value.mV[1], MVT_F32, 4);    	}  	mCurBufferp += 8; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackVector2(LLVector2 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(8, name); +	if (!verifyLength(8, name)) +	{ +		return FALSE; +	}  	htolememcpy(&value.mV[0], mCurBufferp, MVT_F32, 4);  	htolememcpy(&value.mV[1], mCurBufferp+4, MVT_F32, 4);  	mCurBufferp += 8; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packVector3(const LLVector3 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(12, name); +	if (!verifyLength(12, name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{   		htolememcpy(mCurBufferp, value.mV, MVT_LLVector3, 12);    	}  	mCurBufferp += 12; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackVector3(LLVector3 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(12, name); +	if (!verifyLength(12, name)) +	{ +		return FALSE; +	}  	htolememcpy(value.mV, mCurBufferp, MVT_LLVector3, 12);  	mCurBufferp += 12; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packVector4(const LLVector4 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(16, name); +	if (!verifyLength(16, name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{   		htolememcpy(mCurBufferp, value.mV, MVT_LLVector4, 16);    	}  	mCurBufferp += 16; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackVector4(LLVector4 &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(16, name); +	if (!verifyLength(16, name)) +	{ +		return FALSE; +	}  	htolememcpy(value.mV, mCurBufferp, MVT_LLVector4, 16);  	mCurBufferp += 16; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::packUUID(const LLUUID &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(16, name); +	if (!verifyLength(16, name)) +	{ +		return FALSE; +	}  	if (mWriteEnabled)   	{   		htolememcpy(mCurBufferp, value.mData, MVT_LLUUID, 16);    	}  	mCurBufferp += 16; -	return success; +	return TRUE;  }  BOOL LLDataPackerBinaryBuffer::unpackUUID(LLUUID &value, const char *name)  { -	BOOL success = TRUE; -	success &= verifyLength(16, name); +	if (!verifyLength(16, name)) +	{ +		return FALSE; +	}  	htolememcpy(value.mData, mCurBufferp, MVT_LLUUID, 16);  	mCurBufferp += 16; -	return success; +	return TRUE;  }  const LLDataPackerBinaryBuffer&	LLDataPackerBinaryBuffer::operator=(const LLDataPackerBinaryBuffer &a) @@ -698,15 +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*/ -	BOOL res = getValueStr(name, valuestr, DP_BUFSIZE); // NULL terminated -	if (!res) //  +	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 6424117ef3..a1a4ce0520 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 805af55299..765a8cda22 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1386,6 +1386,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 2aaaa4e8c1..4505d6b3b9 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -41,12 +41,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 5e00bf7f45..b13e7389cc 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -505,6 +505,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 230ea200d8..d47c1cf333 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -299,6 +299,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 ea2ca68e47..e1869e8125 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), @@ -182,6 +183,7 @@ LLFolderView::LLFolderView(const Params& p)  	mMinWidth(0),  	mDragAndDropThisFrame(FALSE),  	mCallbackRegistrar(NULL), +	mEnableRegistrar(NULL),  	mUseEllipses(p.use_ellipses),  	mDraggingOverItem(NULL),  	mStatusTextBox(NULL), @@ -244,17 +246,6 @@ LLFolderView::LLFolderView(const Params& p)  	mStatusTextBox->setFollowsTop();  	addChild(mStatusTextBox); - -	// make the popup menu available -	llassert(LLMenuGL::sMenuContainer != NULL); -	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(p.options_menu, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); -	if (!menu) -	{ -		menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("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. @@ -276,6 +267,7 @@ LLFolderView::~LLFolderView( void )  	mStatusTextBox = NULL;  	if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); +	mPopupMenuHandle.markDead();  	mAutoOpenItems.removeAllNodes();  	clearSelection(); @@ -1438,22 +1430,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<LLMenuGL*>(mPopupMenuHandle.get()); +	if (!menu) +	{ +		if (mCallbackRegistrar) +		{ +			mCallbackRegistrar->pushScope(); +		} +		if (mEnableRegistrar) +		{ +			mEnableRegistrar->pushScope(); +		} +		llassert(LLMenuGL::sMenuContainer != NULL); +		menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>(mMenuFileName, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); +		if (!menu) +		{ +			menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("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(); @@ -1531,7 +1557,7 @@ void LLFolderView::deleteAllChildren()  {  	closeRenamer();  	if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); -	mPopupMenuHandle = LLHandle<LLView>(); +	mPopupMenuHandle.markDead();  	mScrollContainer = NULL;  	mRenameItem = NULL;  	mRenamer = NULL; diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 6bb5e6c02e..7dfa04828a 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -235,6 +235,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 @@ -272,6 +273,7 @@ protected:  protected:  	LLHandle<LLView>					mPopupMenuHandle; +	std::string						mMenuFileName;  	selected_items_t				mSelectedItems;  	bool							mKeyboardSelection, @@ -327,6 +329,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 618169a8fe..c5e027d314 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -419,21 +419,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. @@ -471,8 +465,8 @@ public:  	}  protected: -	SortType*		mSorter; -	FilterType*		mFilter; +	std::unique_ptr<SortType>		mSorter; +	std::unique_ptr<FilterType>		mFilter;  };  #endif // LLFOLDERVIEWMODEL_H diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 33037b5001..940cf398c0 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -209,13 +209,6 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)  	setPrevalidateInput(p.prevalidate_input_callback());  	setPrevalidate(p.prevalidate_callback()); - -	llassert(LLMenuGL::sMenuContainer != NULL); -	LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu> -		("menu_text_editor.xml", -		 LLMenuGL::sMenuContainer, -		 LLMenuHolderGL::child_registry_t::instance()); -	setContextMenu(menu);  }  LLLineEditor::~LLLineEditor() @@ -1567,7 +1560,7 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask )  				KEY_SHIFT != key &&  				KEY_CONTROL != key &&  				KEY_ALT != key && -				KEY_CAPSLOCK ) +				KEY_CAPSLOCK != key)  			{  				deselect();  			} @@ -2637,6 +2630,15 @@ LLWString LLLineEditor::getConvertedText() const  void LLLineEditor::showContextMenu(S32 x, S32 y)  {  	LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get()); +	if (!menu) +	{ +		llassert(LLMenuGL::sMenuContainer != NULL); +		menu = LLUICtrlFactory::createFromFile<LLContextMenu> +			("menu_text_editor.xml", +				LLMenuGL::sMenuContainer, +				LLMenuHolderGL::child_registry_t::instance()); +		setContextMenu(menu); +	}  	if (menu)  	{ diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 4264028338..5cb840fd61 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -4087,25 +4087,39 @@ void LLTearOffMenu::closeTearOff()  }  LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p)  -:	LLMenuItemGL(p), -	mBranch( p.branch()->getHandle() ) +:	LLMenuItemGL(p)  { -	mBranch.get()->hide(); -	mBranch.get()->setParentMenuItem(this); +	LLContextMenu* branch = static_cast<LLContextMenu*>(p.branch); +	if (branch) +	{ +		mBranch = branch->getHandle(); +		branch->hide(); +		branch->setParentMenuItem(this); +	} +} + +LLContextMenuBranch::~LLContextMenuBranch() +{ +	if (mBranch.get()) +	{ +		mBranch.get()->die(); +	}  }  // called to rebuild the draw label  void LLContextMenuBranch::buildDrawLabel( void )  { +	auto menu = getBranch(); +	if (menu)  	{  		// default enablement is this -- if any of the subitems are  		// enabled, this item is enabled. JC -		U32 sub_count = mBranch.get()->getItemCount(); +		U32 sub_count = menu->getItemCount();  		U32 i;  		BOOL any_enabled = FALSE;  		for (i = 0; i < sub_count; i++)  		{ -			LLMenuItemGL* item = mBranch.get()->getItem(i); +			LLMenuItemGL* item = menu->getItem(i);  			item->buildDrawLabel();  			if (item->getEnabled() && !item->getDrawTextDisabled() )  			{ @@ -4127,13 +4141,17 @@ void LLContextMenuBranch::buildDrawLabel( void )  void	LLContextMenuBranch::showSubMenu()  { -	LLMenuItemGL* menu_item = mBranch.get()->getParentMenuItem(); -	if (menu_item != NULL && menu_item->getVisible()) +	auto menu = getBranch(); +	if(menu)  	{ -		S32 center_x; -		S32 center_y; -		localPointToScreen(getRect().getWidth(), getRect().getHeight() , ¢er_x, ¢er_y); -		mBranch.get()->show(center_x, center_y); +		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); +			menu->show(center_x, center_y); +		}  	}  } @@ -4147,13 +4165,17 @@ void LLContextMenuBranch::setHighlight( BOOL highlight )  {  	if (highlight == getHighlight()) return;  	LLMenuItemGL::setHighlight(highlight); -	if( highlight ) -	{ -		showSubMenu(); -	} -	else +	auto menu = getBranch(); +	if (menu)  	{ -		mBranch.get()->hide(); +		if (highlight) +		{ +			showSubMenu(); +		} +		else +		{ +			menu->hide(); +		}  	}  } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index abbfd9a24a..f84c4d41eb 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -745,8 +745,7 @@ public:  	LLContextMenuBranch(const Params&); -	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 88c1bdc0d5..219667f766 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -196,7 +196,6 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)  	mHighlightedItem(-1),  	mBorder(NULL),  	mSortCallback(NULL), -	mPopupMenu(NULL),  	mCommentTextView(NULL),  	mNumDynamicWidthColumns(0),  	mTotalStaticColumnWidth(0), @@ -348,6 +347,13 @@ LLScrollListCtrl::~LLScrollListCtrl()  	mItemList.clear();      clearColumns(); //clears columns and deletes headers  	delete mIsFriendSignal; + +	auto menu = mPopupMenuHandle.get(); +	if (menu) +	{ +		menu->die(); +		mPopupMenuHandle.markDead(); +	}  } @@ -1307,14 +1313,14 @@ 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)  {  	BOOL found = FALSE; @@ -1329,7 +1335,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen  		{  			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)  			{ @@ -1352,7 +1358,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen  			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; @@ -1997,17 +2003,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; +			auto menu = mPopupMenuHandle.get(); +			if (menu) +			{ +				menu->die(); +				mPopupMenuHandle.markDead(); +			}  			llassert(LLMenuGL::sMenuContainer != NULL); -			mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( +			menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(  				menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); -			if (mPopupMenu) +			if (menu)  			{ +				mPopupMenuHandle = menu->getHandle();  				if (mIsFriendSignal)  				{  					bool isFriend = *(*mIsFriendSignal)(uuid); -					LLView* addFriendButton = mPopupMenu->getChild<LLView>("add_friend"); -					LLView* removeFriendButton = mPopupMenu->getChild<LLView>("remove_friend"); +					LLView* addFriendButton = menu->getChild<LLView>("add_friend"); +					LLView* removeFriendButton = menu->getChild<LLView>("remove_friend");  					if (addFriendButton && removeFriendButton)  					{ @@ -2016,8 +2028,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 11ee012185..73b4fb036a 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -261,8 +261,8 @@ 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);  	LLScrollListItem*  getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 );  	const std::string	getSelectedItemLabel(S32 column = 0) const;  	LLSD			getSelectedValue(); @@ -528,7 +528,7 @@ private:  	S32				mHighlightedItem;  	class LLViewBorder*	mBorder; -	LLContextMenu	*mPopupMenu; +	LLHandle<LLContextMenu>	mPopupMenuHandle;  	LLView			*mCommentTextView; diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 0aa7a2d217..8c841540a5 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1442,6 +1442,11 @@ void LLTabContainer::selectLastTab()  void LLTabContainer::selectNextTab()  { +    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 8effd866e0..82a3c01c6d 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -273,6 +273,12 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)  LLTextBase::~LLTextBase()  {  	mSegments.clear(); +	LLContextMenu* menu = static_cast<LLContextMenu*>(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 b1f8b00cab..3d2a426913 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -257,7 +257,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), @@ -301,8 +300,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<LLContextMenu*>(mContextMenuHandle.get()); +	if(menu) +	{ +		menu->die(); +		mContextMenuHandle.markDead(); +	}  }  //////////////////////////////////////////////////////////// @@ -2051,12 +2055,19 @@ void LLTextEditor::setEnabled(BOOL enabled)  void LLTextEditor::showContextMenu(S32 x, S32 y)  { -	if (!mContextMenu) +	LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get()); +	if (!menu)  	{  		llassert(LLMenuGL::sMenuContainer != NULL); -		mContextMenu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_text_editor.xml",  +		menu = LLUICtrlFactory::createFromFile<LLContextMenu>("menu_text_editor.xml",   																				LLMenuGL::sMenuContainer,   																				LLMenuHolderGL::child_registry_t::instance()); +        if(!menu) +        { +            LL_WARNS() << "Failed to create menu for LLTextEditor: " << getName() << LL_ENDL; +            return; +        } +		mContextMenuHandle = menu->getHandle();  	}  	// Route menu to this class @@ -2102,11 +2113,11 @@ void LLTextEditor::showContextMenu(S32 x, S32 y)  		}  	} -	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 1a10d2fd1e..f3939248c2 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -329,7 +329,7 @@ private:  	keystroke_signal_t mKeystrokeSignal;  	LLTextValidate::validate_func_t mPrevalidateFunc; -	LLContextMenu* mContextMenu; +	LLHandle<LLContextMenu> 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 5150df25f2..2707f7a15c 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -127,7 +127,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 81e938edbe..391a377280 100644 --- a/indra/llwindow/lldxhardware.cpp +++ b/indra/llwindow/lldxhardware.cpp @@ -1098,7 +1098,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/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 049226db65..7936245744 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -495,7 +495,12 @@ attributedStringInfo getSegments(NSAttributedString *str)      // e.g. OS Window for upload something or Input Window...      // mModifiers instance variable is for insertText: or insertText:replacementRange:  (by Pell Smit)  	mModifiers = [theEvent modifierFlags]; -    unichar ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; +    NSString *str_no_modifiers = [theEvent charactersIgnoringModifiers]; +    unichar ch = 0; +    if (str_no_modifiers.length) +    { +        ch = [str_no_modifiers characterAtIndex:0]; +    }      bool acceptsText = mHasMarkedText ? false : callKeyDown(&eventData, keycode, mModifiers, ch);      if (acceptsText && diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 43edc0110d..77024d3a9c 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 3693042eef..690fe058db 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,39 +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]; -	} -	unichar* temp = (unichar*)calloc([str length]+1, sizeof(unichar)); -	[str getCharacters:temp]; -	[pool release]; -	return temp; +    @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;  } @@ -178,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  	{ @@ -195,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  	{ @@ -420,24 +418,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 c29131d60b..f924b17090 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -668,11 +668,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); @@ -1246,8 +1246,11 @@ BOOL LLWindowMacOSX::isClipboardTextAvailable()  }  BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst) -{	 -	llutf16string str(copyFromPBoard()); +{ +    unsigned short* pboard_data = copyFromPBoard(); // must free returned data +	llutf16string str(pboard_data); +    free(pboard_data); +  	dst = utf16str_to_wstring(str);  	if (dst != L"")  	{ @@ -1280,7 +1283,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r  {  	if (!mSupportedResolutions)  	{ -		CFArrayRef modes = CGDisplayAvailableModes(mDisplay); +		CFArrayRef modes = CGDisplayCopyAllDisplayModes(mDisplay, nullptr);  		if(modes != NULL)  		{ @@ -1319,6 +1322,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r  					}  				}  			} +            CFRelease(modes);  		}  	} diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index b0f339e1db..851c860017 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -228,6 +228,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 9eee5338ec..837efee7b1 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1825,9 +1825,9 @@ if (WINDOWS)        ${SHARED_LIB_STAGING_DIR}/Release/libcollada14dom22.dll        ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libcollada14dom22.dll        ${SHARED_LIB_STAGING_DIR}/Debug/libcollada14dom22-d.dll -      ${SHARED_LIB_STAGING_DIR}/Release/openjpeg.dll -      ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/openjpeg.dll -      ${SHARED_LIB_STAGING_DIR}/Debug/openjpegd.dll +      ${SHARED_LIB_STAGING_DIR}/Release/openjp2.dll +      ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/openjp2.dll +      ${SHARED_LIB_STAGING_DIR}/Debug/openjp2.dll        ${SHARED_LIB_STAGING_DIR}/Release/libhunspell.dll        ${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libhunspell.dll        ${SHARED_LIB_STAGING_DIR}/Debug/libhunspell.dll diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index f5199477c5..0673dfa857 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.6.9 +6.6.10 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6789e71e41..411f77e6a7 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -16887,5 +16887,16 @@      <key>Value</key>      <string></string>    </map> +  <key>DebugSettingsHideDefault</key> +  <map> +    <key>Comment</key> +    <string>Show non-default settings only in Debug Settings list</string> +    <key>Persist</key> +    <integer>0</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>0</integer> +  </map>  </map>  </llsd> diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl index 331249dc33..de22312d3c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -25,6 +25,17 @@  /*[EXTRA_CODE_HERE]*/ +// Inputs +VARYING vec4 vary_HazeColor; +VARYING float vary_LightNormPosDot; + +uniform sampler2D rainbow_map; +uniform sampler2D halo_map; + +uniform float moisture_level; +uniform float droplet_radius; +uniform float ice_level; +  #ifdef DEFINE_GL_FRAGCOLOR  out vec4 frag_data[3];  #else @@ -35,11 +46,34 @@ out vec4 frag_data[3];  // The fragment shader for the sky  ///////////////////////////////////////////////////////////////////////// -VARYING vec4 vary_HazeColor; +vec3 rainbow(float d) +{ +    // 'Interesting' values of d are -0.75 .. -0.825, i.e. when view vec nearly opposite of sun vec +    // Rainbox tex is mapped with REPEAT, so -.75 as tex coord is same as 0.25.  -0.825 -> 0.175. etc. +    // SL-13629 +    // Unfortunately the texture is inverted, so we need to invert the y coord, but keep the 'interesting' +    // part within the same 0.175..0.250 range, i.e. d = (1 - d) - 1.575 +    d         = clamp(-0.575 - d, 0.0, 1.0); + +    // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible. +    // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate +    // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857 +    float interior_coord = max(0.0, d - 0.25) * 4.2857; +    d = clamp(d, 0.0, 0.25) + interior_coord; + +    float rad = (droplet_radius - 5.0f) / 1024.0f; +    return pow(texture2D(rainbow_map, vec2(rad+0.5, d)).rgb, vec3(1.8)) * moisture_level; +} + +vec3 halo22(float d) +{ +    d       = clamp(d, 0.1, 1.0); +    float v = sqrt(clamp(1 - (d * d), 0, 1)); +    return texture2D(halo_map, vec2(0, v)).rgb * ice_level; +}  /// Soft clips the light with a gamma correction  vec3 scaleSoftClip(vec3 light); -vec3 srgb_to_linear(vec3 c);  void main()  { @@ -48,14 +82,18 @@ void main()      // the fragment) if the sky wouldn't show up because the clouds       // are fully opaque. -    vec4 color; -    color = vary_HazeColor; +    vec4 color = vary_HazeColor; +    float  rel_pos_lightnorm = vary_LightNormPosDot; +    float optic_d = rel_pos_lightnorm; +    vec3  halo_22 = halo22(optic_d); +    color.rgb += rainbow(optic_d); +    color.rgb += halo_22;      color.rgb *= 2.;      color.rgb = scaleSoftClip(color.rgb); -    /// Gamma correct for WL (soft clip effect). -    frag_data[0] = vec4(color.rgb, 0.0); +    // Gamma correct for WL (soft clip effect). +    frag_data[0] = vec4(color.rgb, 1.0);      frag_data[1] = vec4(0.0,0.0,0.0,0.0);      frag_data[2] = vec4(0.0,0.0,0.0,1.0); //1.0 in norm.w masks off fog diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl index 28a1faf24f..6db4690bff 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -33,6 +33,7 @@ ATTRIBUTE vec3 position;  // Output parameters  VARYING vec4 vary_HazeColor; +VARYING float vary_LightNormPosDot;  // Inputs  uniform vec3 camPosLocal; @@ -72,27 +73,29 @@ void main()      vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);      // Adj position vector to clamp altitude -    if (rel_pos.y > 0) +    if (rel_pos.y > 0.)      {          rel_pos *= (max_y / rel_pos.y);      } -    if (rel_pos.y < 0) +    if (rel_pos.y < 0.)      {          rel_pos *= (-32000. / rel_pos.y);      } -    // Can normalize then -    vec3 rel_pos_norm = normalize(rel_pos); +    // Normalized +    vec3  rel_pos_norm = normalize(rel_pos); +    float rel_pos_len  = length(rel_pos); -    float rel_pos_len = length(rel_pos); +    // Grab this value and pass to frag shader for rainbows +    float rel_pos_lightnorm_dot = dot(rel_pos_norm, lightnorm.xyz); +    vary_LightNormPosDot = rel_pos_lightnorm_dot;      // Initialize temp variables      vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color; -    vec4 light_atten;      // Sunlight attenuation effect (hue and brightness) due to atmosphere      // this is used later for sunlight modulation at various altitudes -    light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); +    vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);      // Calculate relative weights      vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density)); @@ -112,7 +115,7 @@ void main()      combined_haze = exp(-combined_haze * density_dist);      // Compute haze glow -    float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz); +    float haze_glow = 1.0 - rel_pos_lightnorm_dot;      // haze_glow is 0 at the sun and increases away from sun      haze_glow = max(haze_glow, .001);      // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) @@ -123,30 +126,30 @@ void main()      // Add "minimum anti-solar illumination"      // For sun, add to glow.  For moon, remove glow entirely. SL-13768 -    haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25); +    haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25)); -    vec4 color = -        (blue_horizon * blue_weight * (sunlight + ambient_color) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color)); +    // Haze color above cloud +    vec4 color = (blue_horizon * blue_weight * (sunlight + ambient_color) +               + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));      // Final atmosphere additive      color *= (1. - combined_haze);      // Increase ambient when there are more clouds -    vec4 tmpAmbient = ambient_color; -    tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; +    vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;      // Dim sunlight by cloud shadow percentage      sunlight *= max(0.0, (1. - cloud_shadow));      // Haze color below cloud -    vec4 additiveColorBelowCloud = -        (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient)); +    vec4 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient)  +                         + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient));      // Attenuate cloud color by atmosphere      combined_haze = sqrt(combined_haze);  // less atmos opacity (more transparency) below clouds      // At horizon, blend high altitude sky color towards the darker color below the clouds -    color += (additiveColorBelowCloud - color) * (1. - sqrt(combined_haze)); +    color += (add_below_cloud - color) * (1. - sqrt(combined_haze));      // Haze color above cloud      vary_HazeColor = color; diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl deleted file mode 100644 index 6841a8194f..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl +++ /dev/null @@ -1,199 +0,0 @@ -/** - * @file class2/deferred/skyF.glsl - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2005, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -uniform mat4 modelview_projection_matrix; - -// SKY //////////////////////////////////////////////////////////////////////// -// The vertex shader for creating the atmospheric sky -/////////////////////////////////////////////////////////////////////////////// - -// Inputs -uniform vec3 camPosLocal; - -uniform vec4  lightnorm; -uniform vec4  sunlight_color; -uniform vec4  moonlight_color; -uniform int   sun_up_factor; -uniform vec4  ambient_color; -uniform vec4  blue_horizon; -uniform vec4  blue_density; -uniform float haze_horizon; -uniform float haze_density; - -uniform float cloud_shadow; -uniform float density_multiplier; -uniform float distance_multiplier; -uniform float max_y; - -uniform vec4  glow; -uniform float sun_moon_glow_factor; - -uniform vec4 cloud_color; - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_data[3]; -#else -#define frag_data gl_FragData -#endif - -VARYING vec3 pos; - -///////////////////////////////////////////////////////////////////////// -// The fragment shader for the sky -///////////////////////////////////////////////////////////////////////// - -uniform sampler2D rainbow_map; -uniform sampler2D halo_map; - -uniform float moisture_level; -uniform float droplet_radius; -uniform float ice_level; - -vec3 rainbow(float d) -{ -    // d is the dot product of view and sun directions, so ranging -1.0..1.0 -    // 'interesting' values of d are the range -0.75..-0.825, when view is nearly opposite of sun vec -    // Rainbox texture mode is GL_REPEAT, so tc of -.75 is equiv to 0.25, -0.825 equiv to 0.175. - -    // SL-13629 Rainbow texture has colors within the correct .175...250 range, but order is inverted. -    // Rather than replace the texture, we mirror and translate the y tc to keep the colors within the -    // interesting range, but in reversed order:  i.e. d = (1 - d) - 1.575 -    d = clamp(-0.575 - d, 0.0, 1.0); - -    // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible. -    // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate -    // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857 -    float interior_coord = max(0.0, d - 0.25) * 4.2857; -    d = clamp(d, 0.0, 0.25) + interior_coord; - -    float rad = (droplet_radius - 5.0f) / 1024.0f; -    return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level; -} - -vec3 halo22(float d) -{ -    d       = clamp(d, 0.1, 1.0); -    float v = sqrt(clamp(1 - (d * d), 0, 1)); -    return texture2D(halo_map, vec2(0, v)).rgb * ice_level; -} - -/// Soft clips the light with a gamma correction -vec3 scaleSoftClip(vec3 light); - -void main() -{ -    // World / view / projection -    // Get relative position (offset why?) -    vec3 rel_pos = pos.xyz - camPosLocal.xyz + vec3(0, 50, 0); - -    // Adj position vector to clamp altitude -    if (rel_pos.y > 0.) -    { -        rel_pos *= (max_y / rel_pos.y); -    } -    if (rel_pos.y < 0.) -    { -        rel_pos *= (-32000. / rel_pos.y); -    } - -    // Normalized -    vec3  rel_pos_norm = normalize(rel_pos); -    float rel_pos_len  = length(rel_pos); - -    // Initialize temp variables -    vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color; - -    // Sunlight attenuation effect (hue and brightness) due to atmosphere -    // this is used later for sunlight modulation at various altitudes -    vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); - -    // Calculate relative weights -    vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density)); -    vec4 blue_weight   = blue_density / combined_haze; -    vec4 haze_weight   = haze_density / combined_haze; - -    // Compute sunlight from rel_pos & lightnorm (for long rays like sky) -    float off_axis = 1.0 / max(1e-6, max(0, rel_pos_norm.y) + lightnorm.y); -    sunlight *= exp(-light_atten * off_axis); - -    // Distance -    float density_dist = rel_pos_len * density_multiplier; - -    // Transparency (-> combined_haze) -    // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati -    // compiler gets confused. -    combined_haze = exp(-combined_haze * density_dist); - -    // Compute haze glow -    float haze_glow = dot(rel_pos_norm, lightnorm.xyz); -    haze_glow       = 1. - haze_glow; -    // haze_glow is 0 at the sun and increases away from sun -    haze_glow = max(haze_glow, .001); -    // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) -    haze_glow *= glow.x; -    // Higher glow.x gives dimmer glow (because next step is 1 / "angle") -    haze_glow = pow(haze_glow, glow.z); -    // glow.z should be negative, so we're doing a sort of (1 / "angle") function - -    // Add "minimum anti-solar illumination" -    // For sun, add to glow.  For moon, remove glow entirely. SL-13768 -    haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25)); - -    // Haze color above cloud -    vec4 color = blue_horizon * blue_weight * (sunlight + ambient_color)  -               + haze_horizon * haze_weight * (sunlight * haze_glow + ambient_color); - -    // Final atmosphere additive -    color *= (1. - combined_haze); - -    // Increase ambient when there are more clouds -    // TODO 9/20: DJH what does this do?  max(0,(1-ambient)) will change the color -    vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; - -    // Dim sunlight by cloud shadow percentage -    sunlight *= max(0.0, (1. - cloud_shadow)); - -    // Haze color below cloud -    vec4 add_below_cloud = blue_horizon * blue_weight * (sunlight + ambient)  -                         + haze_horizon * haze_weight * (sunlight * haze_glow + ambient); - -    // Attenuate cloud color by atmosphere -    combined_haze = sqrt(combined_haze);  // less atmos opacity (more transparency) below clouds - -    // At horizon, blend high altitude sky color towards the darker color below the clouds -    color += (add_below_cloud - color) * (1. - sqrt(combined_haze)); - -    float optic_d = dot(rel_pos_norm, lightnorm.xyz); -    vec3  halo_22 = halo22(optic_d); -    color.rgb += rainbow(optic_d); -    color.rgb += halo_22; -    color.rgb *= 2.; -    color.rgb = scaleSoftClip(color.rgb); - -    // Gamma correct for WL (soft clip effect). -    frag_data[0] = vec4(color.rgb, 1.0); -    frag_data[1] = vec4(0.0, 0.0, 0.0, 0.0); -    frag_data[2] = vec4(0.0, 0.0, 0.0, 1.0);  // 1.0 in norm.w masks off fog -} diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl deleted file mode 100644 index bcf775577a..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl +++ /dev/null @@ -1,42 +0,0 @@ -/**  - * @file WLSkyV.glsl - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2005, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -uniform mat4 modelview_projection_matrix; - -ATTRIBUTE vec3 position; - -// SKY //////////////////////////////////////////////////////////////////////// -// The vertex shader for creating the atmospheric sky -/////////////////////////////////////////////////////////////////////////////// - -VARYING vec3 pos; - -void main() -{ - -	// World / view / projection -    pos = position.xyz; -	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); -} diff --git a/indra/newview/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 5214f4b838..1090888c1c 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -46,6 +46,7 @@  - (void)dealloc  { +    [currentInputLanguage release];      [super dealloc];  } @@ -199,12 +200,14 @@  - (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]; -	if ([nonRomanScript containsObject:currentInputLanguage]) -    { -        return 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; +        }      }      return true; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 909f32cd21..3c93a9df7e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3987,7 +3987,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 d9d89efee7..283794209f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -135,6 +135,10 @@  #include "vlc/libvlc_version.h"  #endif // LL_LINUX +#if LL_DARWIN +#include "llwindowmacosx.h" +#endif +  // Third party library includes  #include <boost/bind.hpp>  #include <boost/foreach.hpp> @@ -560,6 +564,7 @@ static void settings_to_globals()      LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale"));  #if LL_DARWIN +    LLWindowMacOSX::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL");  	gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI");  #endif  } @@ -1724,7 +1729,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 1c69dadb12..7ad06f8eaa 100644 --- a/indra/newview/llbuycurrencyhtml.cpp +++ b/indra/newview/llbuycurrencyhtml.cpp @@ -41,7 +41,7 @@ class LLBuyCurrencyHTMLHandler :  {  public:  	// requests will be throttled from a non-trusted browser -	LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_ALLOW ) {} +	LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_THROTTLE) {}  	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)  	{ diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 193d368b83..df79043b00 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -650,8 +650,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;  					args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString(); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 7188b9136c..9a608fba8e 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -141,6 +141,18 @@ public:  		{  			mAvatarNameCacheConnection.disconnect();  		} +		auto menu = mPopupMenuHandleAvatar.get(); +		if (menu) +		{ +			menu->die(); +			mPopupMenuHandleAvatar.markDead(); +		} +		menu = mPopupMenuHandleObject.get(); +		if (menu) +		{ +			menu->die(); +			mPopupMenuHandleObject.markDead(); +		}  	}  	BOOL handleMouseUp(S32 x, S32 y, MASK mask) @@ -567,36 +579,6 @@ public:  	BOOL postBuild()  	{ -		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -		LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable; - -		registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2)); -		registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2)); -		registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2)); -		registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2)); -		registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2)); -		registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2)); - -		LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -		if (menu) -		{ -			mPopupMenuHandleAvatar = menu->getHandle(); -		} -		else -		{ -			LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL; -		} - -		menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -		if (menu) -		{ -			mPopupMenuHandleObject = menu->getHandle(); -		} -		else -		{ -			LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL; -		} -  		setDoubleClickCallback(boost::bind(&LLChatHistoryHeader::showInspector, this));  		setMouseEnterCallback(boost::bind(&LLChatHistoryHeader::showInfoCtrl, this)); @@ -884,13 +866,53 @@ protected:  	void showObjectContextMenu(S32 x,S32 y)  	{  		LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleObject.get(); -		if(menu) +		if (!menu) +		{ +			LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +			LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable; +			registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2)); +			registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2)); + +			menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +			if (menu) +			{ +				mPopupMenuHandleObject = menu->getHandle(); +				menu->updateParent(LLMenuGL::sMenuContainer); +				LLMenuGL::showPopup(this, menu, x, y); +			} +			else +			{ +				LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL; +			} +		} +		else +		{  			LLMenuGL::showPopup(this, menu, x, y); +		}  	}  	void showAvatarContextMenu(S32 x,S32 y)  	{  		LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleAvatar.get(); +		if (!menu) +		{ +			LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +			LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable; +			registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2)); +			registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2)); +			registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2)); +			registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2)); + +			menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +			if (menu) +			{ +				mPopupMenuHandleAvatar = menu->getHandle(); +			} +			else +			{ +				LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL; +			} +		}  		if(menu)  		{ @@ -1082,10 +1104,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)  LLSD LLChatHistory::getValue() const  { -  LLSD* text=new LLSD();  -  text->assign(mEditor->getText()); -  return *text; -     +	return LLSD(mEditor->getText());  }  LLChatHistory::~LLChatHistory() diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 0f187b0ecf..cc4f4536a4 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -67,7 +67,6 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p)  	, mMaxDisplayedCount(p.max_displayed_count)  	, mIsNewMessagesState(false)  	, mFlashToLitTimer(NULL) -	, mContextMenu(NULL)  {  	LLButton::Params button_params = p.button;  	mButton = LLUICtrlFactory::create<LLButton>(button_params); @@ -79,6 +78,12 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p)  LLSysWellChiclet::~LLSysWellChiclet()  {  	mFlashToLitTimer->unset(); +	LLContextMenu* menu = static_cast<LLContextMenu*>(mContextMenuHandle.get()); +	if (menu) +	{ +		menu->die(); +		mContextMenuHandle.markDead(); +	}  }  void LLSysWellChiclet::setCounter(S32 counter) @@ -145,14 +150,16 @@ void LLSysWellChiclet::updateWidget(bool is_window_empty)  // virtual  BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)  { -	if(!mContextMenu) +	LLContextMenu* menu_avatar = mContextMenuHandle.get(); +	if(!menu_avatar)  	{  		createMenu(); +		menu_avatar = mContextMenuHandle.get();  	} -	if (mContextMenu) +	if (menu_avatar)  	{ -		mContextMenu->show(x, y); -		LLMenuGL::showPopup(this, mContextMenu, x, y); +		menu_avatar->show(x, y); +		LLMenuGL::showPopup(this, menu_avatar, x, y);  	}  	return TRUE;  } @@ -192,7 +199,7 @@ bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data)  void LLNotificationChiclet::createMenu()  { -	if(mContextMenu) +	if(mContextMenuHandle.get())  	{  		LL_WARNS() << "Menu already exists" << LL_ENDL;  		return; @@ -207,10 +214,14 @@ void LLNotificationChiclet::createMenu()  		boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2));  	llassert(LLMenuGL::sMenuContainer != NULL); -	mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu> +	LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>  		("menu_notification_well_button.xml",  		 LLMenuGL::sMenuContainer,  		 LLViewerMenuHolderGL::child_registry_t::instance()); +	if (menu) +	{ +		mContextMenuHandle = menu->getHandle(); +	}  }  /*virtual*/ @@ -309,10 +320,19 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p)  , mDefaultWidth(p.rect().getWidth())  , mNewMessagesIcon(NULL)  , mChicletButton(NULL) -, mPopupMenu(NULL)  {  } +LLIMChiclet::~LLIMChiclet() +{ +	auto menu = mPopupMenuHandle.get(); +	if (menu) +	{ +		menu->die(); +		mPopupMenuHandle.markDead(); +	} +} +  /* virtual*/  BOOL LLIMChiclet::postBuild()  { @@ -364,16 +384,18 @@ void LLIMChiclet::setToggleState(bool toggle)  BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)  { -	if(!mPopupMenu) +	auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); +	if(!menu)  	{  		createPopupMenu(); +		menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get());  	} -	if (mPopupMenu) +	if (menu)  	{  		updateMenuItems(); -		mPopupMenu->arrangeAndClear(); -		LLMenuGL::showPopup(this, mPopupMenu, x, y); +		menu->arrangeAndClear(); +		LLMenuGL::showPopup(this, menu, x, y);  	}  	return TRUE; @@ -381,15 +403,16 @@ BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)  void LLIMChiclet::hidePopupMenu()  { -	if (mPopupMenu) +	auto menu = mPopupMenuHandle.get(); +	if (menu)  	{ -		mPopupMenu->setVisible(FALSE); +		menu->setVisible(FALSE);  	}  }  bool LLIMChiclet::canCreateMenu()  { -	if(mPopupMenu) +	if(mPopupMenuHandle.get())  	{  		LL_WARNS() << "Menu already exists" << LL_ENDL;  		return false; @@ -1107,8 +1130,13 @@ void LLScriptChiclet::createPopupMenu()  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;  	registrar.add("ScriptChiclet.Action", boost::bind(&LLScriptChiclet::onMenuItemClicked, this, _2)); -	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> +	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>  		("menu_script_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +	if (menu) +	{ +		mPopupMenuHandle = menu->getHandle(); +	} +  }  ////////////////////////////////////////////////////////////////////////// @@ -1185,8 +1213,12 @@ void LLInvOfferChiclet::createPopupMenu()  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;  	registrar.add("InvOfferChiclet.Action", boost::bind(&LLInvOfferChiclet::onMenuItemClicked, this, _2)); -	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL> +	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>  		("menu_inv_offer_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +	if (menu) +	{ +		mPopupMenuHandle = menu->getHandle(); +	}  }  // EOF diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index aceedda07e..58a797218f 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -252,7 +252,7 @@ public:  	{}; -	virtual ~LLIMChiclet() {}; +	virtual ~LLIMChiclet();  	/**  	 * It is used for default setting up of chicklet:click handler, etc.   @@ -325,7 +325,7 @@ protected:  	bool canCreateMenu(); -	LLMenuGL* mPopupMenu; +	LLHandle<LLUICtrl> mPopupMenuHandle;  	bool mShowSpeaker;  	bool mCounterEnabled; @@ -519,7 +519,7 @@ protected:  	bool mIsNewMessagesState;  	LLFlashTimer* mFlashToLitTimer; -	LLContextMenu* mContextMenu; +	LLHandle<LLContextMenu> mContextMenuHandle;  };  class LLNotificationChiclet : public LLSysWellChiclet diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index 23e2271eae..74f37961c7 100644 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -39,6 +39,7 @@  #define THROTTLE_PERIOD    5    // required seconds between throttled commands  static LLCommandDispatcherListener sCommandDispatcherListener; +const std::string LLCommandHandler::NAV_TYPE_CLICKED = "clicked";  //---------------------------------------------------------------------------  // Underlying registry for command handlers, not directly accessible. @@ -64,6 +65,9 @@ public:  				  bool trusted_browser);  private: +    void notifySlurlBlocked(); +    void notifySlurlThrottled(); +  	friend LLSD LLCommandDispatcher::enumerate();  	std::map<std::string, LLCommandHandlerInfo> mMap;  }; @@ -96,8 +100,6 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,  										const std::string& nav_type,  										bool trusted_browser)  { -	static bool slurl_blocked = false; -	static bool slurl_throttled = false;  	static F64 last_throttle_time = 0.0;  	F64 cur_time = 0.0;  	std::map<std::string, LLCommandHandlerInfo>::iterator it = mMap.find(cmd); @@ -115,44 +117,45 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,  			// block request from external browser, but report as  			// "handled" because it was well formatted.  			LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL; -			if (! slurl_blocked) -			{ -				if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) -				{ -					// Note: commands can arrive before we initialize everything we need for Notification. -					LLNotificationsUtil::add("BlockedSLURL"); -				} -				slurl_blocked = true; -			} +            notifySlurlBlocked();  			return true; +        case LLCommandHandler::UNTRUSTED_CLICK_ONLY: +            if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED +                && info.mHandler->canHandleUntrusted(params, query_map, web, nav_type)) +            { +                break; +            } +            LL_WARNS_ONCE("SLURL") << "Blocked SLURL click-only command " << cmd << " from untrusted browser" << LL_ENDL; +            notifySlurlBlocked(); +            return true; +  		case LLCommandHandler::UNTRUSTED_THROTTLE: +			//skip initial request from external browser before STATE_BROWSER_INIT +			if (LLStartUp::getStartupState() == STATE_FIRST) +			{ +				return true; +			} +            if (!info.mHandler->canHandleUntrusted(params, query_map, web, nav_type)) +            { +                LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL; +                notifySlurlBlocked(); +                return true; +            }  			// if users actually click on a link, we don't need to throttle it  			// (throttling mechanism is used to prevent an avalanche of clicks via  			// javascript -			if ( nav_type == "clicked" ) +			if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED)  			{  				break;  			} -			//skip initial request from external browser before STATE_BROWSER_INIT -			if (LLStartUp::getStartupState() == STATE_FIRST) -			{ -				return true; -			}  			cur_time = LLTimer::getElapsedSeconds();  			if (cur_time < last_throttle_time + THROTTLE_PERIOD)  			{  				// block request from external browser if it happened  				// within THROTTLE_PERIOD seconds of the last command  				LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL; -				if (! slurl_throttled) -				{ -					if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) -					{ -						LLNotificationsUtil::add("ThrottledSLURL"); -					} -					slurl_throttled = true; -				} +                notifySlurlThrottled();  				return true;  			}  			last_throttle_time = cur_time; @@ -163,6 +166,34 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,  	return info.mHandler->handle(params, query_map, web);  } +void LLCommandHandlerRegistry::notifySlurlBlocked() +{ +    static bool slurl_blocked = false; +    if (!slurl_blocked) +    { +        if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) +        { +            // Note: commands can arrive before we initialize everything we need for Notification. +            LLNotificationsUtil::add("BlockedSLURL"); +        } +        slurl_blocked = true; +    } +} + +void LLCommandHandlerRegistry::notifySlurlThrottled() +{ +    static bool slurl_throttled = false; +    if (!slurl_throttled) +    { +        if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) +        { +            // Note: commands can arrive before we initialize everything we need for Notification. +            LLNotificationsUtil::add("ThrottledSLURL"); +        } +        slurl_throttled = true; +    } +} +  //---------------------------------------------------------------------------  // Automatic registration of commands, runs before main()  //--------------------------------------------------------------------------- @@ -230,6 +261,7 @@ symbol_info symbols[] =  {  	ent(LLCommandHandler::UNTRUSTED_ALLOW),		  // allow commands from untrusted browsers  	ent(LLCommandHandler::UNTRUSTED_BLOCK),		  // ignore commands from untrusted browsers +    ent(LLCommandHandler::UNTRUSTED_CLICK_ONLY),  // allow untrusted, but only if clicked  	ent(LLCommandHandler::UNTRUSTED_THROTTLE)	  // allow untrusted, but only a few per min.  }; diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h index 1e0895565a..763e3ee51f 100644 --- a/indra/newview/llcommandhandler.h +++ b/indra/newview/llcommandhandler.h @@ -65,9 +65,12 @@ public:  	{  		UNTRUSTED_ALLOW,       // allow commands from untrusted browsers  		UNTRUSTED_BLOCK,       // ignore commands from untrusted browsers +        UNTRUSTED_CLICK_ONLY,  // allow untrusted, but only if clicked  		UNTRUSTED_THROTTLE     // allow untrusted, but only a few per min.  	}; +    static const std::string NAV_TYPE_CLICKED; +  	LLCommandHandler(const char* command, EUntrustedAccess untrusted_access);  		// Automatically registers object to get called when   		// command is executed.  All commands can be processed @@ -76,6 +79,13 @@ public:  	virtual ~LLCommandHandler(); +    virtual bool canHandleUntrusted( +        const LLSD& params, +        const LLSD& query_map, +        LLMediaCtrl* web, +        const std::string& nav_type) +    { return true; } +  	virtual bool handle(const LLSD& params,  						const LLSD& query_map,  						LLMediaCtrl* web) = 0; diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 4ef14c20f7..05c7decfbd 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -684,7 +684,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())              { @@ -3097,7 +3096,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 3669fb1eeb..e3a695fc79 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -586,9 +586,9 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,  #elif LL_DARWIN -std::vector<std::string>* LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode) +std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode)  { -    std::vector<std::string> *allowedv = new std::vector< std::string >; +    std::unique_ptr<std::vector<std::string>> allowedv(new std::vector< std::string >);      switch(filter)      {          case FFLOAD_ALL: @@ -661,9 +661,9 @@ bool	LLFilePicker::doNavChooseDialog(ELoadFilter filter)  	gViewerWindow->getWindow()->beforeDialog(); -    std::vector<std::string> *allowed_types=navOpenFilterProc(filter); +    std::unique_ptr<std::vector<std::string>> allowed_types = navOpenFilterProc(filter); -    std::vector<std::string> *filev  = doLoadDialog(allowed_types,  +    std::unique_ptr<std::vector<std::string>> filev  = doLoadDialog(allowed_types.get(),                                                      mPickOptions);  	gViewerWindow->getWindow()->afterDialog(); @@ -780,7 +780,7 @@ bool	LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena  	gViewerWindow->getWindow()->beforeDialog();  	// Run the dialog -    std::string* filev = doSaveDialog(&namestring,  +    std::unique_ptr<std::string> filev = doSaveDialog(&namestring,                    &type,                   &creator,                   &extension, diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 04ba4416d7..73baeca1c0 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -167,7 +167,7 @@ private:  	bool doNavChooseDialog(ELoadFilter filter);  	bool doNavSaveDialog(ESaveFilter filter, const std::string& filename); -    std::vector<std::string>* navOpenFilterProc(ELoadFilter filter); +    std::unique_ptr<std::vector<std::string>> 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 <vector>  //void modelessPicker(); -std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types,  +std::unique_ptr<std::vector<std::string>> doLoadDialog(const std::vector<std::string>* allowed_types,                   unsigned int flags); -std::string* doSaveDialog(const std::string* file,  +std::unique_ptr<std::string> 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 1438e4dc0a..0ae5fc3f77 100644 --- a/indra/newview/llfilepicker_mac.mm +++ b/indra/newview/llfilepicker_mac.mm @@ -29,104 +29,107 @@  #include <iostream>  #include "llfilepicker_mac.h" -std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types,  +std::unique_ptr<std::vector<std::string>> doLoadDialog(const std::vector<std::string>* allowed_types,                   unsigned int flags)  { -    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<std::vector<std::string>> 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. +         +        NSOpenPanel *panel = [NSOpenPanel openPanel]; +        //NSString *fileName = nil; +        NSMutableArray *fileTypes = nil; -        for (i=0;i<allowed_types->size();++i) +        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;i<allowed_types->size();++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<std::string>* 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) +        { +            [panel setAllowedFileTypes:fileTypes]; +            result = [panel runModal]; +        } +        else          { -            outfiles = new std::vector<std::string>; +            // 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; i<count; i++) { -            NSString *aFile = [[filesToOpen objectAtIndex:i] path]; -            std::string *afilestr = new std::string([aFile UTF8String]); -            outfiles->push_back(*afilestr); +        if (result == NSOKButton) +        { +            NSArray *filesToOpen = [panel URLs]; +            int i, count = [filesToOpen count]; +             +            if (count > 0) +            { +                outfiles.reset(new std::vector<std::string>); +            } +             +            for (i=0; i<count; i++) { +                NSString *aFile = [[filesToOpen objectAtIndex:i] path]; +                std::string afilestr = std::string([aFile UTF8String]); +                outfiles->push_back(afilestr); +            }          }      } +      return outfiles;  } -std::string* doSaveDialog(const std::string* file,  +std::unique_ptr<std::string> doSaveDialog(const std::string* file,                    const std::string* type,                    const std::string* creator,                    const std::string* extension,                    unsigned int flags)  { -    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]; -    if([panel runModal] ==  -       NSFileHandlingPanelOKButton)  -    { -        NSURL* url = [panel URL]; -        NSString* p = [url path]; -        outfile = new std::string( [p UTF8String] ); -        // write the file  -    }  +    std::unique_ptr<std::string> 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 +        } +    }      return outfile;  } diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp index 62a1e0af94..eff94bd195 100644 --- a/indra/newview/llfloater360capture.cpp +++ b/indra/newview/llfloater360capture.cpp @@ -537,7 +537,8 @@ void LLFloater360Capture::capture360Images()      // We need to convert from the angle getYaw() gives us into something      // the XMP data field wants (N=0, E=90, S=180, W= 270 etc.)      mInitialHeadingDeg  = (360 + 90 - (int)(camera->getYaw() * RAD_TO_DEG)) % 360; -    LL_INFOS("360Capture") << "Recording a heading of " << (int)(mInitialHeadingDeg) << LL_ENDL; +    LL_INFOS("360Capture") << "Recording a heading of " << (int)(mInitialHeadingDeg) +        << " Image size: " << (S32)mSourceImageSize << LL_ENDL;      // camera constants for the square, cube map capture image      camera->setAspect(1.0); // must set aspect ratio first to avoid undesirable clamping of vertical FoV @@ -587,6 +588,9 @@ void LLFloater360Capture::capture360Images()      // for each of the 6 directions we shoot...      for (int i = 0; i < 6; i++)      { +        LLAppViewer::instance()->pauseMainloopTimeout(); +        LLViewerStats::instance().getRecording().stop(); +          // these buffers are where the raw, captured pixels are stored and          // the first time we use them, we have to make a new one          if (mRawImages[i] == nullptr) @@ -624,8 +628,10 @@ void LLFloater360Capture::capture360Images()          auto duration = std::chrono::duration_cast<std::chrono::duration<double>>(t_end - t_start);          encode_time_total += duration.count(); -        // ping the main loop in case the snapshot process takes a really long -        // time and we get disconnected +        LLViewerStats::instance().getRecording().resume(); +        LLAppViewer::instance()->resumeMainloopTimeout(); +         +        // update main loop timeout state          LLAppViewer::instance()->pingMainloopTimeout("LLFloater360Capture::capture360Images");      } diff --git a/indra/newview/llfloateravatar.cpp b/indra/newview/llfloateravatar.cpp index 31adf5b61e..f888d032ae 100644 --- a/indra/newview/llfloateravatar.cpp +++ b/indra/newview/llfloateravatar.cpp @@ -44,17 +44,21 @@ LLFloaterAvatar::LLFloaterAvatar(const LLSD& key)  LLFloaterAvatar::~LLFloaterAvatar()  { -	LLMediaCtrl* avatar_picker = findChild<LLMediaCtrl>("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();  	}  }  BOOL LLFloaterAvatar::postBuild()  { +    mAvatarPicker = findChild<LLMediaCtrl>("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 cadc5e4028..76e9372709 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 @@ -38,6 +39,8 @@ private:  	LLFloaterAvatar(const LLSD& key);  	/*virtual*/	~LLFloaterAvatar();  	/*virtual*/	BOOL postBuild(); + +    LLMediaCtrl* mAvatarPicker;  };  #endif diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp index 33e4c7cd5f..307ab8c4d1 100644 --- a/indra/newview/llfloaterbump.cpp +++ b/indra/newview/llfloaterbump.cpp @@ -69,6 +69,12 @@ LLFloaterBump::LLFloaterBump(const LLSD& key)  // Destroys the object  LLFloaterBump::~LLFloaterBump()  { +	auto menu = mPopupMenuHandle.get(); +	if (menu) +	{ +		menu->die(); +		mPopupMenuHandle.markDead(); +	}  }  BOOL LLFloaterBump::postBuild() @@ -77,11 +83,15 @@ BOOL LLFloaterBump::postBuild()  	mList->setAllowMultipleSelection(false);  	mList->setRightMouseDownCallback(boost::bind(&LLFloaterBump::onScrollListRightClicked, this, _1, _2, _3)); -	mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_avatar_other.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	mPopupMenu->setItemVisible(std::string("Normal"), false); -	mPopupMenu->setItemVisible(std::string("Always use impostor"), false); -	mPopupMenu->setItemVisible(std::string("Never use impostor"), false); -	mPopupMenu->setItemVisible(std::string("Impostor seperator"), false); +	LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>("menu_avatar_other.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +	if (menu) +	{ +		mPopupMenuHandle = menu->getHandle(); +		menu->setItemVisible(std::string("Normal"), false); +		menu->setItemVisible(std::string("Always use impostor"), false); +		menu->setItemVisible(std::string("Never use impostor"), false); +		menu->setItemVisible(std::string("Impostor seperator"), false); +	}  	return TRUE;  } @@ -176,18 +186,19 @@ void LLFloaterBump::onScrollListRightClicked(LLUICtrl* ctrl, S32 x, S32 y)  	if (!gMeanCollisionList.empty())  	{  		LLScrollListItem* item = mList->hitItem(x, y); -		if (item && mPopupMenu) +		auto menu = mPopupMenuHandle.get(); +		if (item && menu)  		{  			mItemUUID = item->getUUID(); -			mPopupMenu->buildDrawLabels(); -			mPopupMenu->updateParent(LLMenuGL::sMenuContainer); +			menu->buildDrawLabels(); +			menu->updateParent(LLMenuGL::sMenuContainer);  			std::string mute_msg = (LLMuteList::getInstance()->isMuted(mItemUUID, mNames[mItemUUID])) ? "UnmuteAvatar" : "MuteAvatar"; -			mPopupMenu->getChild<LLUICtrl>("Avatar Mute")->setValue(LLTrans::getString(mute_msg)); -			mPopupMenu->setItemEnabled(std::string("Zoom In"), bool(gObjectList.findObject(mItemUUID))); +			menu->getChild<LLUICtrl>("Avatar Mute")->setValue(LLTrans::getString(mute_msg)); +			menu->setItemEnabled(std::string("Zoom In"), bool(gObjectList.findObject(mItemUUID))); -			((LLContextMenu*)mPopupMenu)->show(x, y); -			LLMenuGL::showPopup(ctrl, mPopupMenu, x, y); +			menu->show(x, y); +			LLMenuGL::showPopup(ctrl, menu, x, y);  		}  	}  } diff --git a/indra/newview/llfloaterbump.h b/indra/newview/llfloaterbump.h index ce52c75255..d2f9fabdd3 100644 --- a/indra/newview/llfloaterbump.h +++ b/indra/newview/llfloaterbump.h @@ -68,7 +68,7 @@ private:  	virtual ~LLFloaterBump();  	LLScrollListCtrl* mList; -	LLMenuGL* mPopupMenu; +	LLHandle<LLContextMenu> mPopupMenuHandle;  	LLUUID mItemUUID;  	typedef std::map<LLUUID, std::string> uuid_map_t; diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp index 7def855d83..b82d8a29ba 100644 --- a/indra/newview/llfloatercreatelandmark.cpp +++ b/indra/newview/llfloatercreatelandmark.cpp @@ -316,7 +316,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 703b5d0011..2720b7fcf7 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -211,6 +211,7 @@ BOOL LLFloaterIMContainer::postBuild()      p.options_menu = "menu_conversation.xml";  	mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);      mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); +	mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar);  	// Add listener to conversation model events  	mConversationsEventStream.listen("ConversationsRefresh", boost::bind(&LLFloaterIMContainer::onConversationModelEvent, this, _1)); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 204cd03b09..78271369d2 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -316,6 +316,7 @@ BOOL LLFloaterIMSessionTab::postBuild()      p.name = "root";  	mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p);      mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); +	mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar);  	// Attach that root to the scroller  	mScroller->addChild(mConversationsRoot);  	mConversationsRoot->setScrollContainer(mScroller); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 66a245b779..6f8f73bca0 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1740,7 +1740,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 2a1749bd42..a682064dad 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -56,8 +56,6 @@ LLFloaterOpenObject::LLFloaterOpenObject(const LLSD& key)  	mDirty(TRUE)  {  	mCommitCallbackRegistrar.add("OpenObject.MoveToInventory",	boost::bind(&LLFloaterOpenObject::onClickMoveToInventory, this)); -	mCommitCallbackRegistrar.add("OpenObject.MoveAndWear",		boost::bind(&LLFloaterOpenObject::onClickMoveAndWear, this)); -	mCommitCallbackRegistrar.add("OpenObject.ReplaceOutfit",	boost::bind(&LLFloaterOpenObject::onClickReplace, this));  	mCommitCallbackRegistrar.add("OpenObject.Cancel",			boost::bind(&LLFloaterOpenObject::onClickCancel, this));  } @@ -243,18 +241,6 @@ void LLFloaterOpenObject::onClickMoveToInventory()  	closeFloater();  } -void LLFloaterOpenObject::onClickMoveAndWear() -{ -	moveToInventory(true, false); -	closeFloater(); -} - -void LLFloaterOpenObject::onClickReplace() -{ -	moveToInventory(true, true); -	closeFloater(); -} -  void LLFloaterOpenObject::onClickCancel()  {  	closeFloater(); diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h index 2e761f99bf..745753316b 100644 --- a/indra/newview/llfloateropenobject.h +++ b/indra/newview/llfloateropenobject.h @@ -63,8 +63,6 @@ protected:  	void moveToInventory(bool wear, bool replace = false);  	void onClickMoveToInventory(); -	void onClickMoveAndWear(); -	void onClickReplace();  	void onClickCancel();  	static void callbackCreateInventoryCategory(const LLUUID& category_id, LLUUID object_id, bool wear, bool replace = false);  	static void callbackMoveInventory(S32 result, void* data); diff --git a/indra/newview/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<LLLineEditor>("filter_by_name"); -	llassert(mFilterByName != NULL); -	mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); -	mFilterByName->setSelectAllonFocusReceived(true); -	mFilterByName->setCommitOnFocusLost(true); - -	mFilterByDescription = findChild<LLLineEditor>("filter_by_description"); -	llassert(mFilterByDescription != NULL); -	mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); -	mFilterByDescription->setSelectAllonFocusReceived(true); -	mFilterByDescription->setCommitOnFocusLost(true); +    mFilterByName = getChild<LLSearchEditor>("filter_by_name"); +    mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); +    mFilterByName->setCommitOnFocusLost(true); + +    mFilterByDescription = getChild<LLSearchEditor>("filter_by_description"); +    mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); +    mFilterByDescription->setCommitOnFocusLost(true);  	mFilterByLinksetUse = findChild<LLComboBox>("filter_by_linkset_use");  	llassert(mFilterByLinksetUse != NULL); diff --git a/indra/newview/llfloaterpathfindinglinksets.h b/indra/newview/llfloaterpathfindinglinksets.h index 7149da9215..a954d8a8ec 100644 --- a/indra/newview/llfloaterpathfindinglinksets.h +++ b/indra/newview/llfloaterpathfindinglinksets.h @@ -42,6 +42,7 @@ class LLSD;  class LLTextBase;  class LLUICtrl;  class LLVector3; +class LLSearchEditor;  class LLFloaterPathfindingLinksets : public LLFloaterPathfindingObjects  { @@ -105,8 +106,8 @@ private:  	LLPathfindingLinkset::ELinksetUse convertToLinksetUse(LLSD pXuiValue) const;  	LLSD                              convertToXuiValue(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; -	LLLineEditor     *mFilterByName; -	LLLineEditor     *mFilterByDescription; +    LLSearchEditor   *mFilterByName; +    LLSearchEditor   *mFilterByDescription;  	LLComboBox       *mFilterByLinksetUse;  	LLComboBox       *mEditLinksetUse;  	LLScrollListItem *mEditLinksetUseUnset; diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 3746b9b6c2..40fe11b309 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 bb3ed77772..7e6af45515 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -45,7 +45,7 @@ class LLSearchHandler : public LLCommandHandler  {  public:  	// requires trusted browser to trigger -	LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { } +	LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_CLICK_ONLY) { }  	bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)  	{  		if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableSearch")) diff --git a/indra/newview/llfloatersettingsdebug.cpp b/indra/newview/llfloatersettingsdebug.cpp index 186994c857..3c7f341613 100644 --- a/indra/newview/llfloatersettingsdebug.cpp +++ b/indra/newview/llfloatersettingsdebug.cpp @@ -2,9 +2,9 @@   * @file llfloatersettingsdebug.cpp   * @brief floater for debugging internal viewer settings   * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * $LicenseInfo:firstyear=2022&license=viewerlgpl$   * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2022, Linden Research, Inc.   *    * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -27,8 +27,8 @@  #include "llviewerprecompiledheaders.h"  #include "llfloatersettingsdebug.h"  #include "llfloater.h" +#include "llfiltereditor.h"  #include "lluictrlfactory.h" -//#include "llfirstuse.h"  #include "llcombobox.h"  #include "llspinctrl.h"  #include "llcolorswatch.h" @@ -37,12 +37,11 @@  LLFloaterSettingsDebug::LLFloaterSettingsDebug(const LLSD& key)  -:	LLFloater(key) +:   LLFloater(key), +    mSettingList(NULL)  { -	mCommitCallbackRegistrar.add("SettingSelect",	boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this,_1));  	mCommitCallbackRegistrar.add("CommitSettings",	boost::bind(&LLFloaterSettingsDebug::onCommitSettings, this));  	mCommitCallbackRegistrar.add("ClickDefault",	boost::bind(&LLFloaterSettingsDebug::onClickDefault, this)); -  }  LLFloaterSettingsDebug::~LLFloaterSettingsDebug() @@ -50,59 +49,43 @@ LLFloaterSettingsDebug::~LLFloaterSettingsDebug()  BOOL LLFloaterSettingsDebug::postBuild()  { -	LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo"); +    enableResizeCtrls(true, false, true); -	struct f : public LLControlGroup::ApplyFunctor -	{ -		LLComboBox* combo; -		f(LLComboBox* c) : combo(c) {} -		virtual void apply(const std::string& name, LLControlVariable* control) -		{ -			if (!control->isHiddenFromSettingsEditor()) -			{ -				combo->add(name, (void*)control); -			} -		} -	} func(settings_combo); +    mComment = getChild<LLTextEditor>("comment_text"); -	std::string key = getKey().asString(); -	if (key == "all" || key == "base") -	{ -		gSavedSettings.applyToAll(&func); -	} -	if (key == "all" || key == "account") -	{ -		gSavedPerAccountSettings.applyToAll(&func); -	} +    getChild<LLFilterEditor>("filter_input")->setCommitCallback(boost::bind(&LLFloaterSettingsDebug::setSearchFilter, this, _2)); + +    mSettingList = getChild<LLScrollListCtrl>("setting_list"); +    mSettingList->setCommitOnSelectionChange(TRUE); +    mSettingList->setCommitCallback(boost::bind(&LLFloaterSettingsDebug::onSettingSelect, this)); + +    updateList(); + +    gSavedSettings.getControl("DebugSettingsHideDefault")->getCommitSignal()->connect(boost::bind(&LLFloaterSettingsDebug::updateList, this, false)); -	settings_combo->sortByName(); -	settings_combo->updateSelection(); -	mComment = getChild<LLTextEditor>("comment_text");  	return TRUE;  }  void LLFloaterSettingsDebug::draw()  { -	LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo"); -	LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata(); -	updateControl(controlp); +    LLScrollListItem* first_selected = mSettingList->getFirstSelected(); +    if (first_selected) +    { +        LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata(); +        updateControl(controlp); +    }  	LLFloater::draw();  } -//static  -void LLFloaterSettingsDebug::onSettingSelect(LLUICtrl* ctrl) -{ -	LLComboBox* combo_box = (LLComboBox*)ctrl; -	LLControlVariable* controlp = (LLControlVariable*)combo_box->getCurrentUserdata(); - -	updateControl(controlp); -} -  void LLFloaterSettingsDebug::onCommitSettings()  { -	LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo"); -	LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata(); +    LLScrollListItem* first_selected = mSettingList->getFirstSelected(); +    if (!first_selected) +    { +        return; +    } +    LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata();  	if (!controlp)  	{ @@ -176,19 +159,23 @@ void LLFloaterSettingsDebug::onCommitSettings()  	  default:  		break;  	} +    updateDefaultColumn(controlp);  }  // static  void LLFloaterSettingsDebug::onClickDefault()  { -	LLComboBox* settings_combo = getChild<LLComboBox>("settings_combo"); -	LLControlVariable* controlp = (LLControlVariable*)settings_combo->getCurrentUserdata(); - -	if (controlp) -	{ -		controlp->resetToDefault(true); -		updateControl(controlp); -	} +    LLScrollListItem* first_selected = mSettingList->getFirstSelected(); +    if (first_selected) +    { +        LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata(); +        if (controlp) +        { +            controlp->resetToDefault(true); +            updateDefaultColumn(controlp); +            updateControl(controlp); +        } +    }  }  // we've switched controls, or doing per-frame update, so update spinners, etc. @@ -207,23 +194,30 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp)  		return;  	} -	spinner1->setVisible(FALSE); -	spinner2->setVisible(FALSE); -	spinner3->setVisible(FALSE); -	spinner4->setVisible(FALSE); -	color_swatch->setVisible(FALSE); -	getChildView("val_text")->setVisible( FALSE); -	mComment->setText(LLStringUtil::null); +    hideUIControls(); -	if (controlp) +	if (controlp && !isSettingHidden(controlp))  	{  		eControlType type = controlp->type();  		//hide combo box only for non booleans, otherwise this will result in the combo box closing every frame  		getChildView("boolean_combo")->setVisible( type == TYPE_BOOLEAN); -		 +        getChildView("default_btn")->setVisible(true); +        getChildView("setting_name_txt")->setVisible(true); +        getChild<LLTextBox>("setting_name_txt")->setText(controlp->getName()); +        getChild<LLTextBox>("setting_name_txt")->setToolTip(controlp->getName()); +        mComment->setVisible(true); + +        std::string old_text = mComment->getText(); +        std::string new_text = controlp->getComment(); +        // Don't setText if not nessesary, it will reset scroll +        // This is a debug UI that reads from xml, there might +        // be use cases where comment changes, but not the name +        if (old_text != new_text) +        { +            mComment->setText(controlp->getComment()); +        } -		mComment->setText(controlp->getComment());  		spinner1->setMaxValue(F32_MAX);  		spinner2->setMaxValue(F32_MAX);  		spinner3->setMaxValue(F32_MAX); @@ -479,3 +473,166 @@ void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp)  	}  } + +void LLFloaterSettingsDebug::updateList(bool skip_selection) +{ +    std::string last_selected; +    LLScrollListItem* item = mSettingList->getFirstSelected(); +    if (item) +    { +        LLScrollListCell* cell = item->getColumn(1); +        if (cell) +        { +            last_selected = cell->getValue().asString(); +         } +    } + +    mSettingList->deleteAllItems(); +    struct f : public LLControlGroup::ApplyFunctor +    { +        LLScrollListCtrl* setting_list; +        LLFloaterSettingsDebug* floater; +        std::string selected_setting; +        bool skip_selection; +        f(LLScrollListCtrl* list, LLFloaterSettingsDebug* floater, std::string setting, bool skip_selection)  +            : setting_list(list), floater(floater), selected_setting(setting), skip_selection(skip_selection) {} +        virtual void apply(const std::string& name, LLControlVariable* control) +        { +            if (!control->isHiddenFromSettingsEditor() && floater->matchesSearchFilter(name) && !floater->isSettingHidden(control)) +            { +                LLSD row; + +                row["columns"][0]["column"] = "changed_setting"; +                row["columns"][0]["value"] = control->isDefault() ? "" : "*"; + +                row["columns"][1]["column"] = "setting"; +                row["columns"][1]["value"] = name; + +                LLScrollListItem* item = setting_list->addElement(row, ADD_BOTTOM, (void*)control); +                if (!floater->mSearchFilter.empty() && (selected_setting == name) && !skip_selection) +                { +                    std::string lower_name(name); +                    LLStringUtil::toLower(lower_name); +                    if (LLStringUtil::startsWith(lower_name, floater->mSearchFilter)) +                    { +                        item->setSelected(true); +                    } +                } +            } +        } +    } func(mSettingList, this, last_selected, skip_selection); + +    std::string key = getKey().asString(); +    if (key == "all" || key == "base") +    { +        gSavedSettings.applyToAll(&func); +    } +    if (key == "all" || key == "account") +    { +        gSavedPerAccountSettings.applyToAll(&func); +    } + + +    if (!mSettingList->isEmpty()) +    { +        if (mSettingList->hasSelectedItem()) +        { +            mSettingList->scrollToShowSelected(); +        } +        else if (!mSettingList->hasSelectedItem() && !mSearchFilter.empty() && !skip_selection) +        { +            if (!mSettingList->selectItemByPrefix(mSearchFilter, false, 1)) +            { +                mSettingList->selectFirstItem(); +            } +            mSettingList->scrollToShowSelected(); +        } +    } +    else +    { +        LLSD row; + +        row["columns"][0]["column"] = "changed_setting"; +        row["columns"][0]["value"] = ""; +        row["columns"][1]["column"] = "setting"; +        row["columns"][1]["value"] = "No matching settings."; + +        mSettingList->addElement(row); +        hideUIControls(); +    } +} + +void LLFloaterSettingsDebug::onSettingSelect() +{ +    LLScrollListItem* first_selected = mSettingList->getFirstSelected(); +    if (first_selected) +    { +        LLControlVariable* controlp = (LLControlVariable*)first_selected->getUserdata(); +        if (controlp) +        { +            updateControl(controlp); +        } +    } +} + +void LLFloaterSettingsDebug::setSearchFilter(const std::string& filter) +{ +    if(mSearchFilter == filter) +        return; +    mSearchFilter = filter; +    LLStringUtil::toLower(mSearchFilter); +    updateList(); +} + +bool LLFloaterSettingsDebug::matchesSearchFilter(std::string setting_name) +{ +    // If the search filter is empty, everything passes. +    if (mSearchFilter.empty()) return true; + +    LLStringUtil::toLower(setting_name); +    std::string::size_type match_name = setting_name.find(mSearchFilter); + +    return (std::string::npos != match_name); +} + +bool LLFloaterSettingsDebug::isSettingHidden(LLControlVariable* control) +{ +    static LLCachedControl<bool> hide_default(gSavedSettings, "DebugSettingsHideDefault", false); +    return hide_default && control->isDefault(); +} + +void LLFloaterSettingsDebug::updateDefaultColumn(LLControlVariable* control) +{ +    if (isSettingHidden(control)) +    { +        hideUIControls(); +        updateList(true); +        return; +    } + +    LLScrollListItem* item = mSettingList->getFirstSelected(); +    if (item) +    { +        LLScrollListCell* cell = item->getColumn(0); +        if (cell) +        { +            std::string is_default = control->isDefault() ? "" : "*"; +            cell->setValue(is_default); +        } +    } +} + +void LLFloaterSettingsDebug::hideUIControls() +{ +    getChildView("val_spinner_1")->setVisible(false); +    getChildView("val_spinner_2")->setVisible(false); +    getChildView("val_spinner_3")->setVisible(false); +    getChildView("val_spinner_4")->setVisible(false); +    getChildView("val_color_swatch")->setVisible(false); +    getChildView("val_text")->setVisible(false); +    getChildView("default_btn")->setVisible(false); +    getChildView("boolean_combo")->setVisible(false); +    getChildView("setting_name_txt")->setVisible(false); +    mComment->setVisible(false); +} + diff --git a/indra/newview/llfloatersettingsdebug.h b/indra/newview/llfloatersettingsdebug.h index f07e0557e3..888eaadcbd 100644 --- a/indra/newview/llfloatersettingsdebug.h +++ b/indra/newview/llfloatersettingsdebug.h @@ -2,9 +2,9 @@   * @file llfloatersettingsdebug.h   * @brief floater for debugging internal viewer settings   * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * $LicenseInfo:firstyear=2022&license=viewerlgpl$   * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2022, Linden Research, Inc.   *    * This library is free software; you can redistribute it and/or   * modify it under the terms of the GNU Lesser General Public @@ -30,6 +30,8 @@  #include "llcontrol.h"  #include "llfloater.h" +class LLScrollListCtrl; +  class LLFloaterSettingsDebug   :	public LLFloater  { @@ -42,18 +44,31 @@ public:  	void updateControl(LLControlVariable* control); -	void onSettingSelect(LLUICtrl* ctrl);  	void onCommitSettings();  	void onClickDefault(); +    bool matchesSearchFilter(std::string setting_name); +    bool isSettingHidden(LLControlVariable* control); +  private:  	// key - selects which settings to show, one of:  	// "all", "base", "account", "skin"  	LLFloaterSettingsDebug(const LLSD& key);  	virtual ~LLFloaterSettingsDebug(); + +    void updateList(bool skip_selection = false); +    void onSettingSelect(); +    void setSearchFilter(const std::string& filter); + +    void updateDefaultColumn(LLControlVariable* control); +    void hideUIControls(); + +    LLScrollListCtrl* mSettingList;  protected:  	class LLTextEditor* mComment; + +    std::string mSearchFilter;  };  #endif //LLFLOATERDEBUGSETTINGS_H diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 01bfae8934..704abd269f 100755 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -122,7 +122,7 @@ class LLWorldMapHandler : public LLCommandHandler  {  public:  	// requires trusted browser to trigger -	LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE ) { } +	LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_CLICK_ONLY ) { }  	bool handle(const LLSD& params, const LLSD& query_map,  				LLMediaCtrl* web) @@ -159,7 +159,7 @@ class LLMapTrackAvatarHandler : public LLCommandHandler  {  public:  	// requires trusted browser to trigger -	LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_THROTTLE)  +	LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_CLICK_ONLY)   	{   	} diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index dbeb157323..be52e280e1 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -52,7 +52,32 @@ class LLGroupHandler : public LLCommandHandler  {  public:  	// requires trusted browser to trigger -	LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_THROTTLE) { } +	LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_CLICK_ONLY) { } + +    virtual bool canHandleUntrusted( +        const LLSD& params, +        const LLSD& query_map, +        LLMediaCtrl* web, +        const std::string& nav_type) +    { +        if (params.size() < 1) +        { +            return true; // don't block, will fail later +        } + +        if (nav_type == NAV_TYPE_CLICKED) +        { +            return true; +        } + +        const std::string verb = params[0].asString(); +        if (verb == "create") +        { +            return false; +        } +        return true; +    } +  	bool handle(const LLSD& tokens, const LLSD& query_map,  				LLMediaCtrl* web)  	{ diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index e6845127e3..af2d168aef 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -1568,7 +1568,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 f2c2f82cdb..5039e15047 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2159,8 +2159,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"); @@ -2544,7 +2542,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"); @@ -2630,7 +2628,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 7793b71f56..db347f7096 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -831,6 +831,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  		{ @@ -2140,6 +2146,7 @@ bool LLItemBridge::isItemCopyable(bool can_copy_as_link) const      static LLCachedControl<bool> inventory_linking(gSavedSettings, "InventoryLinking", true);      return (can_copy_as_link && inventory_linking) +        || (mIsLink && inventory_linking)          || item->getPermissions().allowCopyBy(gAgent.getID());  } @@ -2346,6 +2353,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 707ff2b7b6..e3a6b2dc85 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -437,7 +437,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 ffeaa15cff..67240ac7e7 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1411,9 +1411,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 d4dd212cc3..cf713a6930 100644 --- a/indra/newview/llinventorylistitem.h +++ b/indra/newview/llinventorylistitem.h @@ -197,6 +197,7 @@ protected:  	virtual BOOL handleToolTip( S32 x, S32 y, MASK mask);  	const LLUUID mInventoryItemUUID; +    bool mHovered;  private: @@ -221,7 +222,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 1ebb18be1b..0784a010bf 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1694,11 +1694,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)  	{          rebuildLinkItems(links);  	} +	obj = nullptr; // delete obj  	if (do_notify_observers)  	{  		notifyObservers(); @@ -2719,7 +2719,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 0e3db51d2a..8029486d6f 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -211,7 +211,11 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )      p.allow_drop = mParams.allow_drop_on_root;      p.options_menu = "menu_inventory.xml"; -    return LLUICtrlFactory::create<LLFolderView>(p); +	LLFolderView* fv = LLUICtrlFactory::create<LLFolderView>(p); +	fv->setCallbackRegistrar(&mCommitCallbackRegistrar); +	fv->setEnableRegistrar(&mEnableCallbackRegistrar); + +	return fv;  }  void LLInventoryPanel::clearFolderRoot() @@ -264,6 +268,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)  	}  	mCommitCallbackRegistrar.popScope();  	mFolderRoot.get()->setCallbackRegistrar(&mCommitCallbackRegistrar); +	mFolderRoot.get()->setEnableRegistrar(&mEnableCallbackRegistrar);  	// Scroller  		LLRect scroller_view_rect = getRect(); diff --git a/indra/newview/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 11aa607393..a52f7244f3 100644 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -429,12 +429,10 @@ void LLMaterialMgr::onGetResponse(bool success, const LLSD& content, const LLUUI  	llassert(content.has(MATERIALS_CAP_ZIP_FIELD));  	llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary()); -	LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); -	std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size()); -	std::istringstream content_stream(content_string); +	const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();  	LLSD response_data; -	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size()); +	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());  	if (uzip_result != LLUZipHelper::ZR_OK)  	{  		LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL; @@ -472,12 +470,10 @@ void LLMaterialMgr::onGetAllResponse(bool success, const LLSD& content, const LL  	llassert(content.has(MATERIALS_CAP_ZIP_FIELD));  	llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary()); -	LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); -	std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size()); -	std::istringstream content_stream(content_string); +	const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();  	LLSD response_data; -	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size()); +	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());  	if (uzip_result != LLUZipHelper::ZR_OK)  	{  		LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL; @@ -541,12 +537,10 @@ void LLMaterialMgr::onPutResponse(bool success, const LLSD& content)  	llassert(content.has(MATERIALS_CAP_ZIP_FIELD));  	llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary()); -	LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); -	std::string content_string(reinterpret_cast<const char*>(content_binary.data()), content_binary.size()); -	std::istringstream content_stream(content_string); +	const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary();  	LLSD response_data; -	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size()); +	U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size());  	if (uzip_result != LLUZipHelper::ZR_OK)  	{  		LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL; @@ -666,8 +660,8 @@ void LLMaterialMgr::processGetQueue()  		{  			material_queue_t::iterator itMaterial = loopMaterial++;  			materialsData.append((*itMaterial).asLLSD()); -			materials.erase(itMaterial);  			markGetPending(region_id, *itMaterial); +			materials.erase(itMaterial);  		}  		if (materials.empty())  		{ diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 9142aadab9..36ac1bdf97 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -106,7 +106,6 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :  	mTrusted(p.trusted_content),  	mWindowShade(NULL),  	mHoverTextChanged(false), -	mContextMenu(NULL),      mAllowFileDownload(false)  {  	{ @@ -151,6 +150,13 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :  LLMediaCtrl::~LLMediaCtrl()  { +	auto menu = mContextMenuHandle.get(); +	if (menu) +	{ +		menu->die(); +		mContextMenuHandle.markDead(); +	} +  	if (mMediaSource)  	{  		mMediaSource->remObserver( this ); @@ -336,15 +342,33 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask )  		setFocus( TRUE );  	} -	if (mContextMenu) +	auto menu = mContextMenuHandle.get(); +	if (!menu) +	{ +		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; +		registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this)); + +		// stinson 05/05/2014 : use this as the parent of the context menu if the static menu +		// container has yet to be created +		LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast<LLPanel*>(LLMenuGL::sMenuContainer) : dynamic_cast<LLPanel*>(this); +		llassert(menuParent != NULL); +		menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( +			"menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance()); +		if (menu) +		{ +			mContextMenuHandle = menu->getHandle(); +		} +	} + +	if (menu)  	{  		// hide/show debugging options  		bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); -		mContextMenu->setItemVisible("open_webinspector", media_plugin_debugging_enabled ); -		mContextMenu->setItemVisible("debug_separator", media_plugin_debugging_enabled ); +		menu->setItemVisible("open_webinspector", media_plugin_debugging_enabled ); +		menu->setItemVisible("debug_separator", media_plugin_debugging_enabled ); -		mContextMenu->show(x, y); -		LLMenuGL::showPopup(this, mContextMenu, x, y); +		menu->show(x, y); +		LLMenuGL::showPopup(this, menu, x, y);  	}  	return TRUE; @@ -409,15 +433,6 @@ void LLMediaCtrl::onFocusLost()  //  BOOL LLMediaCtrl::postBuild ()  { -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; -	registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this)); - -	// stinson 05/05/2014 : use this as the parent of the context menu if the static menu -	// container has yet to be created -	LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast<LLPanel*>(LLMenuGL::sMenuContainer) : dynamic_cast<LLPanel*>(this); -	llassert(menuParent != NULL); -	mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( -		"menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance());  	setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2));  	return TRUE; @@ -1230,11 +1245,6 @@ void LLMediaCtrl::setTrustedContent(bool trusted)  	}  } -void LLMediaCtrl::updateContextMenuParent(LLView* pNewParent) -{ -	mContextMenu->updateParent(pNewParent); -} -  bool LLMediaCtrl::wantsKeyUpKeyDown() const  {      return true; diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index bc4cbaae68..487c654adc 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -174,8 +174,6 @@ public:  		LLUUID getTextureID() {return mMediaTextureID;} -		void updateContextMenuParent(LLView* pNewParent); -          // The Browser windows want keyup and keydown events. Overridden from LLFocusableElement to return true.          virtual bool    wantsKeyUpKeyDown() const;          virtual bool    wantsReturnKey() const; @@ -220,7 +218,7 @@ public:  			mTextureHeight;  		class LLWindowShade* mWindowShade; -		LLContextMenu* mContextMenu; +		LLHandle<LLContextMenu> mContextMenuHandle;  };  #endif // LL_LLMediaCtrl_H diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index a15a61429b..f937754368 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -77,6 +77,8 @@  #include "lluploaddialog.h"  #include "llfloaterreg.h" +#include "boost/iostreams/device/array.hpp" +#include "boost/iostreams/stream.hpp"  #include "boost/lexical_cast.hpp"  #ifndef LL_WINDOWS @@ -138,7 +140,7 @@  //                               data copied  //                               headerReceived() invoked  //                                 LLSD parsed -//                                 mMeshHeader, mMeshHeaderSize updated +//                                 mMeshHeader updated  //                                 scan mPendingLOD for LOD request  //                                 push LODRequest to mLODReqQ  //                             ... @@ -246,7 +248,6 @@  //     sActiveLODRequests       mMutex        rw.any.mMutex, ro.repo.none [1]  //     sMaxConcurrentRequests   mMutex        wo.main.none, ro.repo.none, ro.main.mMutex  //     mMeshHeader              mHeaderMutex  rw.repo.mHeaderMutex, ro.main.mHeaderMutex, ro.main.none [0] -//     mMeshHeaderSize          mHeaderMutex  rw.repo.mHeaderMutex  //     mSkinRequests            mMutex        rw.repo.mMutex, ro.repo.none [5]  //     mSkinInfoQ               mMutex        rw.repo.mMutex, rw.main.mMutex [5] (was:  [0])  //     mDecompositionRequests   mMutex        rw.repo.mMutex, ro.repo.none [5] @@ -858,6 +859,12 @@ LLMeshRepoThread::~LLMeshRepoThread()  	mHttpRequestSet.clear();      mHttpHeaders.reset(); +	while (!mSkinInfoQ.empty()) +    { +        delete mSkinInfoQ.front(); +        mSkinInfoQ.pop_front(); +    } +      while (!mDecompositionQ.empty())      {          delete mDecompositionQ.front(); @@ -947,7 +954,8 @@ void LLMeshRepoThread::run()                      else                      {                          // too many fails -                        mUnavailableQ.push(req); +						LLMutexLock lock(mMutex); +                        mUnavailableQ.push_back(req);                          LL_WARNS() << "Failed to load " << req.mMeshParams << " , skip" << LL_ENDL;                      }                  } @@ -1023,37 +1031,42 @@ void LLMeshRepoThread::run()              if (!mSkinRequests.empty())              { -                std::set<UUIDBasedRequest> incomplete; -                while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater) -                { -                    mMutex->lock(); -                    std::set<UUIDBasedRequest>::iterator iter = mSkinRequests.begin(); -                    UUIDBasedRequest req = *iter; -                    mSkinRequests.erase(iter); -                    mMutex->unlock(); -                    if (req.isDelayed()) -                    { -                        incomplete.insert(req); -                    } -                    else if (!fetchMeshSkinInfo(req.mId)) -                    { -                        if (req.canRetry()) -                        { -                            req.updateTime(); -                            incomplete.insert(req); -                        } -                        else -                        { -                            LL_DEBUGS() << "mSkinRequests failed: " << req.mId << LL_ENDL; -                        } -                    } -                } +				std::list<UUIDBasedRequest> incomplete; +				while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater) +				{ -                if (!incomplete.empty()) -                { -                    LLMutexLock locker(mMutex); -                    mSkinRequests.insert(incomplete.begin(), incomplete.end()); -                } +					mMutex->lock(); +					auto req = mSkinRequests.front(); +					mSkinRequests.pop_front(); +					mMutex->unlock(); +					if (req.isDelayed()) +					{ +						incomplete.emplace_back(req); +					} +					else if (!fetchMeshSkinInfo(req.mId, req.canRetry())) +					{ +						if (req.canRetry()) +						{ +							req.updateTime(); +							incomplete.emplace_back(req); +						} +						else +						{ +							LLMutexLock locker(mMutex); +							mSkinUnavailableQ.push_back(req); +							LL_DEBUGS() << "mSkinReqQ failed: " << req.mId << LL_ENDL; +						} +					} +				} + +				if (!incomplete.empty()) +				{ +					LLMutexLock locker(mMutex); +					for (const auto& req : incomplete) +					{ +						mSkinRequests.push_back(req); +					} +				}              }              // holding lock, try next list @@ -1152,7 +1165,7 @@ void LLMeshRepoThread::run()  // Mutex:  LLMeshRepoThread::mMutex must be held on entry  void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id)  { -	mSkinRequests.insert(UUIDBasedRequest(mesh_id)); +	mSkinRequests.push_back(UUIDBasedRequest(mesh_id));  }  // Mutex:  LLMeshRepoThread::mMutex must be held on entry @@ -1178,10 +1191,13 @@ void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32  void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  { //could be called from any thread +	const LLUUID& mesh_id = mesh_params.getSculptID();  	LLMutexLock lock(mMutex); -	mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID()); +	LLMutexLock header_lock(mHeaderMutex); +	mesh_header_map::iterator iter = mMeshHeader.find(mesh_id);  	if (iter != mMeshHeader.end())  	{ //if we have the header, request LOD byte range +  		LODRequest req(mesh_params, lod);  		{  			mLODReqQ.push(req); @@ -1191,8 +1207,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  	else  	{   		HeaderRequest req(mesh_params); -		 -		pending_lod_map::iterator pending = mPendingLOD.find(mesh_params); +		pending_lod_map::iterator pending = mPendingLOD.find(mesh_id);  		if (pending != mPendingLOD.end())  		{ //append this lod request to existing header request @@ -1202,7 +1217,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  		else  		{ //if no header request is pending, fetch header  			mHeaderReqQ.push(req); -			mPendingLOD[mesh_params].push_back(lod); +			mPendingLOD[mesh_id].push_back(lod);  		}  	}  } @@ -1307,7 +1322,7 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url,  } -bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) +bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)  {  	if (!mHeaderMutex) @@ -1317,7 +1332,8 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  	mHeaderMutex->lock(); -	if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) +	auto header_it = mMeshHeader.find(mesh_id); +	if (header_it == mMeshHeader.end())  	{ //we have no header info for this mesh, do nothing  		mHeaderMutex->unlock();  		return false; @@ -1325,13 +1341,14 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  	++LLMeshRepository::sMeshRequestCount;  	bool ret = true; -	U32 header_size = mMeshHeaderSize[mesh_id]; +	U32 header_size = header_it->second.first;  	if (header_size > 0)  	{ -		S32 version = mMeshHeader[mesh_id]["version"].asInteger(); -		S32 offset = header_size + mMeshHeader[mesh_id]["skin"]["offset"].asInteger(); -		S32 size = mMeshHeader[mesh_id]["skin"]["size"].asInteger(); +		const LLSD& header = header_it->second.second; +		S32 version = header["version"].asInteger(); +		S32 offset = header_size + header["skin"]["offset"].asInteger(); +		S32 size = header["skin"]["size"].asInteger();  		mHeaderMutex->unlock(); @@ -1387,12 +1404,27 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  									   << LL_ENDL;  					ret = false;  				} -				else +				else if(can_retry)  				{  					handler->mHttpHandle = handle;  					mHttpRequestSet.insert(handler);  				} +				else +				{ +					LLMutexLock locker(mMutex); +					mSkinUnavailableQ.emplace_back(mesh_id); +				}  			} +			else +			{ +				LLMutexLock locker(mMutex); +				mSkinUnavailableQ.emplace_back(mesh_id); +			} +		} +		else +		{ +			LLMutexLock locker(mMutex); +			mSkinUnavailableQ.emplace_back(mesh_id);  		}  	}  	else @@ -1413,21 +1445,23 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  	mHeaderMutex->lock(); -	if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) +	auto header_it = mMeshHeader.find(mesh_id); +	if (header_it == mMeshHeader.end())  	{ //we have no header info for this mesh, do nothing  		mHeaderMutex->unlock();  		return false;  	}  	++LLMeshRepository::sMeshRequestCount; -	U32 header_size = mMeshHeaderSize[mesh_id]; +	U32 header_size = header_it->second.first;  	bool ret = true;  	if (header_size > 0)  	{ -		S32 version = mMeshHeader[mesh_id]["version"].asInteger(); -		S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger(); -		S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger(); +		const auto& header = header_it->second.second; +		S32 version = header["version"].asInteger(); +		S32 offset = header_size + header["physics_convex"]["offset"].asInteger(); +		S32 size = header["physics_convex"]["size"].asInteger();  		mHeaderMutex->unlock(); @@ -1510,21 +1544,23 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  	mHeaderMutex->lock(); -	if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) +	auto header_it = mMeshHeader.find(mesh_id); +	if (header_it == mMeshHeader.end())  	{ //we have no header info for this mesh, do nothing  		mHeaderMutex->unlock();  		return false;  	}  	++LLMeshRepository::sMeshRequestCount; -	U32 header_size = mMeshHeaderSize[mesh_id]; +	U32 header_size = header_it->second.first;  	bool ret = true;  	if (header_size > 0)  	{ -		S32 version = mMeshHeader[mesh_id]["version"].asInteger(); -		S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger(); -		S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger(); +		const auto& header = header_it->second.second; +		S32 version = header["version"].asInteger(); +		S32 offset = header_size + header["physics_mesh"]["offset"].asInteger(); +		S32 size = header["physics_mesh"]["size"].asInteger();  		mHeaderMutex->unlock(); @@ -1704,20 +1740,25 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,  		return false;  	} -	mHeaderMutex->lock(); +	const LLUUID& mesh_id = mesh_params.getSculptID(); +	mHeaderMutex->lock(); +	auto header_it = mMeshHeader.find(mesh_id); +	if (header_it == mMeshHeader.end()) +	{ //we have no header info for this mesh, do nothing +		mHeaderMutex->unlock(); +		return false; +	}  	++LLMeshRepository::sMeshRequestCount;  	bool retval = true; - -	LLUUID mesh_id = mesh_params.getSculptID(); -	U32 header_size = mMeshHeaderSize[mesh_id]; - +	U32 header_size = header_it->second.first;  	if (header_size > 0)  	{ -		S32 version = mMeshHeader[mesh_id]["version"].asInteger(); -		S32 offset = header_size + mMeshHeader[mesh_id][header_lod[lod]]["offset"].asInteger(); -		S32 size = mMeshHeader[mesh_id][header_lod[lod]]["size"].asInteger(); +		const auto& header = header_it->second.second; +		S32 version = header["version"].asInteger(); +		S32 offset = header_size + header[header_lod[lod]]["offset"].asInteger(); +		S32 size = header[header_lod[lod]]["size"].asInteger();  		mHeaderMutex->unlock();  		if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) @@ -1792,17 +1833,20 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,  				}  				else  				{ -					mUnavailableQ.push(LODRequest(mesh_params, lod)); +					LLMutexLock lock(mMutex); +					mUnavailableQ.push_back(LODRequest(mesh_params, lod));  				}  			}  			else  			{ -				mUnavailableQ.push(LODRequest(mesh_params, lod)); +				LLMutexLock lock(mMutex); +				mUnavailableQ.push_back(LODRequest(mesh_params, lod));  			}  		}  		else  		{ -			mUnavailableQ.push(LODRequest(mesh_params, lod)); +			LLMutexLock lock(mMutex); +			mUnavailableQ.push_back(LODRequest(mesh_params, lod));  		}  	}  	else @@ -1821,27 +1865,12 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes  	U32 header_size = 0;  	if (data_size > 0)  	{ -        std::istringstream stream; -        try -        { -            std::string res_str((char*)data, data_size); +		U32 dsize = data_size; +		char* result_ptr = strip_deprecated_header((char*)data, dsize, &header_size); -            std::string deprecated_header("<? LLSD/Binary ?>"); +		data_size = dsize; -            if (res_str.substr(0, deprecated_header.size()) == deprecated_header) -            { -                res_str = res_str.substr(deprecated_header.size() + 1, data_size); -                header_size = deprecated_header.size() + 1; -            } -            data_size = res_str.size(); - -            stream.str(res_str); -        } -        catch (std::bad_alloc&) -        { -            // out of memory, we won't be able to process this mesh -            return MESH_OUT_OF_MEMORY; -        } +		boost::iostreams::stream<boost::iostreams::array_source> stream(result_ptr, data_size);  		if (!LLSDSerialize::fromBinary(header, stream, data_size))  		{ @@ -1878,8 +1907,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes  		{  			LLMutexLock lock(mHeaderMutex); -			mMeshHeaderSize[mesh_id] = header_size; -			mMeshHeader[mesh_id] = header; +			mMeshHeader[mesh_id] = { header_size, header };              LLMeshRepository::sCacheBytesHeaders += header_size;  		} @@ -1887,7 +1915,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes  		LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time.  		//check for pending requests -		pending_lod_map::iterator iter = mPendingLOD.find(mesh_params); +		pending_lod_map::iterator iter = mPendingLOD.find(mesh_id);  		if (iter != mPendingLOD.end())  		{  			for (U32 i = 0; i < iter->second.size(); ++i) @@ -1911,26 +1939,14 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p  	}  	LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); -	std::istringstream stream; -	try -	{ -		std::string mesh_string((char*)data, data_size); -		stream.str(mesh_string); -	} -	catch (std::bad_alloc&) -	{ -		// out of memory, we won't be able to process this mesh -		return MESH_OUT_OF_MEMORY; -	} - -	if (volume->unpackVolumeFaces(stream, data_size)) +	if (volume->unpackVolumeFaces(data, data_size))  	{  		if (volume->getNumFaces() > 0)  		{  			LoadedMesh mesh(volume, mesh_params, lod);  			{  				LLMutexLock lock(mMutex); -				mLoadedQ.push(mesh); +				mLoadedQ.push_back(mesh);  				// LLPointer is not thread safe, since we added this pointer into  				// threaded list, make sure counter gets decreased inside mutex lock  				// and won't affect mLoadedQ processing @@ -1953,10 +1969,7 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat  	{          try          { -            std::string res_str((char*)data, data_size); -            std::istringstream stream(res_str); - -            U32 uzip_result = LLUZipHelper::unzip_llsd(skin, stream, data_size); +            U32 uzip_result = LLUZipHelper::unzip_llsd(skin, data, data_size);              if (uzip_result != LLUZipHelper::ZR_OK)              {                  LL_WARNS(LOG_MESH) << "Mesh skin info parse error.  Not a valid mesh asset!  ID:  " << mesh_id @@ -1973,8 +1986,16 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat  	}  	{ -		LLMeshSkinInfo info(skin); -		info.mMeshID = mesh_id; +		LLMeshSkinInfo* info = nullptr; +		try +		{ +			info = new LLMeshSkinInfo(mesh_id, skin); +		} +		catch (const std::bad_alloc& ex) +		{ +			LL_WARNS() << "Failed to allocate skin info with exception: " << ex.what()  << LL_ENDL; +			return false; +		}          // LL_DEBUGS(LOG_MESH) << "info pelvis offset" << info.mPelvisOffset << LL_ENDL;  		{ @@ -1994,10 +2015,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3      {          try          { -            std::string res_str((char*)data, data_size); -            std::istringstream stream(res_str); - -            U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, stream, data_size); +            U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, data, data_size);              if (uzip_result != LLUZipHelper::ZR_OK)              {                  LL_WARNS(LOG_MESH) << "Mesh decomposition parse error.  Not a valid mesh asset!  ID:  " << mesh_id @@ -2006,7 +2024,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3                  return false;              }          } -        catch (std::bad_alloc&) +        catch (const std::bad_alloc&)          {              LL_WARNS(LOG_MESH) << "Out of memory for mesh ID " << mesh_id << " of size: " << data_size << LL_ENDL;              return false; @@ -2043,20 +2061,7 @@ EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_  		volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH);  		LLPointer<LLVolume> volume = new LLVolume(volume_params,0); -        std::istringstream stream; -        try -        { -            std::string mesh_string((char*)data, data_size); -            stream.str(mesh_string); -        } -        catch (std::bad_alloc&) -        { -            // out of memory, we won't be able to process this mesh -            delete d; -            return MESH_OUT_OF_MEMORY; -        } - -		if (volume->unpackVolumeFaces(stream, data_size)) +		if (volume->unpackVolumeFaces(data, data_size))  		{  			d->mPhysicsShapeMesh.clear(); @@ -2870,58 +2875,72 @@ void LLMeshRepoThread::notifyLoadedMeshes()  		return;  	} -	while (!mLoadedQ.empty()) +	if (!mLoadedQ.empty())  	{ +		std::deque<LoadedMesh> loaded_queue; +  		mMutex->lock(); -		if (mLoadedQ.empty()) +		if (!mLoadedQ.empty())  		{ +			loaded_queue.swap(mLoadedQ);  			mMutex->unlock(); -			break; -		} -		LoadedMesh mesh = mLoadedQ.front(); // make sure nothing else owns volume pointer by this point -		mLoadedQ.pop(); -		mMutex->unlock(); -		 -		update_metrics = true; -		if (mesh.mVolume->getNumVolumeFaces() > 0) -		{ -			gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume); -		} -		else -		{ -			gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams,  -				LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail())); + +			update_metrics = true; + +			// Process the elements free of the lock +			for (const auto& mesh : loaded_queue) +			{ +				if (mesh.mVolume->getNumVolumeFaces() > 0) +				{ +					gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume); +				} +				else +				{ +					gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams, +						LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail())); +				} +			}  		}  	} -	while (!mUnavailableQ.empty()) +	if (!mUnavailableQ.empty())  	{ +		std::deque<LODRequest> unavil_queue; +  		mMutex->lock(); -		if (mUnavailableQ.empty()) +		if (!mUnavailableQ.empty())  		{ +			unavil_queue.swap(mUnavailableQ);  			mMutex->unlock(); -			break; -		} -		 -		LODRequest req = mUnavailableQ.front(); -		mUnavailableQ.pop(); -		mMutex->unlock(); -		update_metrics = true; -		gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD); +			update_metrics = true; + +			// Process the elements free of the lock +			for (const auto& req : unavil_queue) +			{ +				gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD); +			} +		}  	} -	if (! mSkinInfoQ.empty() || ! mDecompositionQ.empty()) +	if (!mSkinInfoQ.empty() || !mSkinUnavailableQ.empty() || ! mDecompositionQ.empty())  	{  		if (mMutex->trylock())  		{ -			std::list<LLMeshSkinInfo> skin_info_q; +			std::deque<LLMeshSkinInfo*> skin_info_q; +			std::deque<UUIDBasedRequest> skin_info_unavail_q;  			std::list<LLModel::Decomposition*> decomp_q;  			if (! mSkinInfoQ.empty())  			{  				skin_info_q.swap(mSkinInfoQ);  			} + +			if (! mSkinUnavailableQ.empty()) +			{ +				skin_info_unavail_q.swap(mSkinUnavailableQ); +			} +  			if (! mDecompositionQ.empty())  			{  				decomp_q.swap(mDecompositionQ); @@ -2935,6 +2954,11 @@ void LLMeshRepoThread::notifyLoadedMeshes()  				gMeshRepo.notifySkinInfoReceived(skin_info_q.front());  				skin_info_q.pop_front();  			} +			while (! skin_info_unavail_q.empty()) +			{ +				gMeshRepo.notifySkinInfoUnavailable(skin_info_unavail_q.front().mId); +				skin_info_unavail_q.pop_front(); +			}  			while (! decomp_q.empty())  			{ @@ -2959,7 +2983,7 @@ S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo  	if (iter != mMeshHeader.end())  	{ -		LLSD& header = iter->second; +		LLSD& header = iter->second.second;  		return LLMeshRepository::getActualMeshLOD(header, lod);  	} @@ -3162,7 +3186,7 @@ void LLMeshHeaderHandler::processFailure(LLCore::HttpStatus status)  	LLMutexLock lock(gMeshRepo.mThread->mMutex);  	for (int i(0); i < 4; ++i)  	{ -		gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); +		gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i));  	}  } @@ -3191,7 +3215,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b  		LLMutexLock lock(gMeshRepo.mThread->mMutex);  		for (int i(0); i < 4; ++i)  		{ -			gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); +			gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i));  		}  	}  	else if (data && data_size > 0) @@ -3204,8 +3228,8 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b  		LLMeshRepoThread::mesh_header_map::iterator iter = gMeshRepo.mThread->mMeshHeader.find(mesh_id);  		if (iter != gMeshRepo.mThread->mMeshHeader.end())  		{ -			header_bytes = (S32)gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; -			header = iter->second; +			header_bytes = (S32)iter->second.first; +			header = iter->second.second;  		}  		if (header_bytes > 0 @@ -3273,7 +3297,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b  			LLMutexLock lock(gMeshRepo.mThread->mMutex);  			for (int i(0); i < 4; ++i)  			{ -				gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); +				gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i));  			}  		}  	} @@ -3300,7 +3324,7 @@ void LLMeshLODHandler::processFailure(LLCore::HttpStatus status)  					   << LL_ENDL;  	LLMutexLock lock(gMeshRepo.mThread->mMutex); -	gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); +	gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));  }  void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */, @@ -3337,7 +3361,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body  							   << " Not retrying."  							   << LL_ENDL;  			LLMutexLock lock(gMeshRepo.mThread->mMutex); -			gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); +			gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));  		}  	}  	else @@ -3348,7 +3372,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body  						   << " Data size: " << data_size  						   << LL_ENDL;  		LLMutexLock lock(gMeshRepo.mThread->mMutex); -		gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); +		gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));  	}  } @@ -3366,9 +3390,8 @@ void LLMeshSkinInfoHandler::processFailure(LLCore::HttpStatus status)  					   << ", Reason:  " << status.toString()  					   << " (" << status.toTerseString() << ").  Not retrying."  					   << LL_ENDL; - -	// *TODO:  Mark mesh unavailable on error.  For now, simply leave -	// request unfulfilled rather than retry forever. +		LLMutexLock lock(gMeshRepo.mThread->mMutex); +		gMeshRepo.mThread->mSkinUnavailableQ.emplace_back(mMeshID);  }  void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */, @@ -3399,7 +3422,8 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /*  		LL_WARNS(LOG_MESH) << "Error during mesh skin info processing.  ID:  " << mMeshID  						   << ", Unknown reason.  Not retrying."  						   << LL_ENDL; -		// *TODO:  Mark mesh unavailable on error +		LLMutexLock lock(gMeshRepo.mThread->mMutex); +		gMeshRepo.mThread->mSkinUnavailableQ.emplace_back(mMeshID);  	}  } @@ -3508,7 +3532,7 @@ LLMeshRepository::LLMeshRepository()    mMeshThreadCount(0),    mThread(NULL)  { - +	mSkinInfoCullTimer.resetWithExpiry(10.f);  }  void LLMeshRepository::init() @@ -3609,6 +3633,22 @@ S32 LLMeshRepository::update()  	return size ;  } +void LLMeshRepository::unregisterMesh(LLVOVolume* vobj) +{ +	for (auto& lod : mLoadingMeshes) +	{ +		for (auto& param : lod) +		{ +			vector_replace_with_last(param.second, vobj); +		} +	} + +	for (auto& skin_pair : mLoadingSkins) +	{ +		vector_replace_with_last(skin_pair.second, vobj); +	} +} +  S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail, S32 last_lod)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; //LL_LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH); @@ -3624,15 +3664,19 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para  	{  		LLMutexLock lock(mMeshMutex);  		//add volume to list of loading meshes -		mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_params); +		const auto& mesh_id = mesh_params.getSculptID(); +		mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_id);  		if (iter != mLoadingMeshes[detail].end())  		{ //request pending for this mesh, append volume id to list -			iter->second.insert(vobj->getID()); +			auto it = std::find(iter->second.begin(), iter->second.end(), vobj); +			if (it == iter->second.end()) { +				iter->second.push_back(vobj); +			}  		}  		else  		{  			//first request for this mesh -			mLoadingMeshes[detail][mesh_params].insert(vobj->getID()); +			mLoadingMeshes[detail][mesh_id].push_back(vobj);  			mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail));  			LLMeshRepository::sLODPending++;  		} @@ -3789,6 +3833,28 @@ void LLMeshRepository::notifyLoadedMeshes()  	//call completed callbacks on finished decompositions  	mDecompThread->notifyCompleted(); +	if (mSkinInfoCullTimer.checkExpirationAndReset(10.f))  +	{ +		//// Clean up dead skin info +		//U64Bytes skinbytes(0); +		for (auto iter = mSkinMap.begin(), ender = mSkinMap.end(); iter != ender;) +		{ +			auto copy_iter = iter++; + +			//skinbytes += U64Bytes(sizeof(LLMeshSkinInfo)); +			//skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(std::string)); +			//skinbytes += U64Bytes(copy_iter->second->mJointNums.size() * sizeof(S32)); +			//skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(LLMatrix4a)); +			//skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(LLMatrix4)); + +			if (copy_iter->second->getNumRefs() == 1) +			{ +				mSkinMap.erase(copy_iter); +			} +		} +		//LL_INFOS() << "Skin info cache elements:" << mSkinMap.size() << " Memory: " << U64Kilobytes(skinbytes) << LL_ENDL; +	} +  	// For major operations, attempt to get the required locks  	// without blocking and punt if they're not available.  The  	// longest run of holdoffs is kept in sMaxLockHoldoffs just @@ -3859,10 +3925,9 @@ void LLMeshRepository::notifyLoadedMeshes()  					for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin();  iter != mLoadingMeshes[i].end(); ++iter)  					{  						F32 max_score = 0.f; -						for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) +						for (auto obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)  						{ -							LLViewerObject* object = gObjectList.findObject(*obj_iter); -							 +							LLVOVolume* object = *obj_iter;						  							if (object)  							{  								LLDrawable* drawable = object->mDrawable; @@ -3874,7 +3939,7 @@ void LLMeshRepository::notifyLoadedMeshes()  							}  						} -						score_map[iter->first.getSculptID()] = max_score; +						score_map[iter->first] = max_score;  					}  				} @@ -3926,24 +3991,39 @@ void LLMeshRepository::notifyLoadedMeshes()  	mThread->mSignal->signal();  } -void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info) +void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo* info)  { -	mSkinMap[info.mMeshID] = info; +	mSkinMap[info->mMeshID] = info; // Cache into LLPointer      // Alternative: We can get skin size from header -    sCacheBytesSkins += info.sizeBytes(); +    sCacheBytesSkins += info->sizeBytes(); -	skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID); +	skin_load_map::iterator iter = mLoadingSkins.find(info->mMeshID);  	if (iter != mLoadingSkins.end())  	{ -		for (std::set<LLUUID>::iterator obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id) +		for (LLVOVolume* vobj : iter->second)  		{ -			LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*obj_id);  			if (vobj)  			{ -				vobj->notifyMeshLoaded(); +				vobj->notifySkinInfoLoaded(info);  			}  		} -		mLoadingSkins.erase(info.mMeshID); +		mLoadingSkins.erase(iter); +	} +} + +void LLMeshRepository::notifySkinInfoUnavailable(const LLUUID& mesh_id) +{ +	skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); +	if (iter != mLoadingSkins.end()) +	{ +		for (LLVOVolume* vobj : iter->second) +		{ +			if (vobj) +			{ +				vobj->notifySkinInfoUnavailable(); +			} +		} +		mLoadingSkins.erase(iter);  	}  } @@ -3972,14 +4052,15 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol  	S32 detail = LLVolumeLODGroup::getVolumeDetailFromScale(volume->getDetail());  	//get list of objects waiting to be notified this mesh is loaded -	mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh_params); +	const auto& mesh_id = mesh_params.getSculptID(); +	mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh_id);  	if (volume && obj_iter != mLoadingMeshes[detail].end())  	{  		//make sure target volume is still valid  		if (volume->getNumVolumeFaces() <= 0)  		{ -			LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume.  ID:  " << mesh_params.getSculptID() +			LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume.  ID:  " << mesh_id  							   << LL_ENDL;  		} @@ -3993,37 +4074,35 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol  			}  			else  			{ -				LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_params.getSculptID() +				LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_id  								   << LL_ENDL;  			}  		}  		//notify waiting LLVOVolume instances that their requested mesh is available -		for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) +		for (LLVOVolume* vobj : obj_iter->second)  		{ -			LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter);  			if (vobj)  			{  				vobj->notifyMeshLoaded();  			}  		} -		mLoadingMeshes[detail].erase(mesh_params); +		mLoadingMeshes[detail].erase(obj_iter);  	}  }  void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod)  { //called from main thread  	//get list of objects waiting to be notified this mesh is loaded -	mesh_load_map::iterator obj_iter = mLoadingMeshes[lod].find(mesh_params); - -	F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod); - +	const auto& mesh_id = mesh_params.getSculptID(); +	mesh_load_map::iterator obj_iter = mLoadingMeshes[lod].find(mesh_id);  	if (obj_iter != mLoadingMeshes[lod].end())  	{ -		for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) +		F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod); + +		for (LLVOVolume* vobj : obj_iter->second)  		{ -			LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter);  			if (vobj)  			{  				LLVolume* obj_volume = vobj->getVolume(); @@ -4037,7 +4116,7 @@ void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params,  			}  		} -		mLoadingMeshes[lod].erase(mesh_params); +		mLoadingMeshes[lod].erase(obj_iter);  	}  } @@ -4046,7 +4125,7 @@ S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo  	return mThread->getActualMeshLOD(mesh_params, lod);  } -const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj) +const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR;      if (mesh_id.notNull()) @@ -4054,7 +4133,7 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const          skin_map::iterator iter = mSkinMap.find(mesh_id);          if (iter != mSkinMap.end())          { -            return &(iter->second); +            return iter->second;          }          //no skin info known about given mesh, try to fetch it @@ -4063,14 +4142,22 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const              LLMutexLock lock(mMeshMutex);              //add volume to list of loading meshes              skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); -            if (iter == mLoadingSkins.end()) -            { //no request pending for this skin info +			if (iter != mLoadingSkins.end()) +			{ //request pending for this mesh, append volume id to list +				auto it = std::find(iter->second.begin(), iter->second.end(), requesting_obj); +				if (it == iter->second.end()) { +					iter->second.push_back(requesting_obj); +				} +			} +			else +			{ +				//first request for this mesh +				mLoadingSkins[mesh_id].push_back(requesting_obj);                  mPendingSkinRequests.push(mesh_id);              } -            mLoadingSkins[mesh_id].insert(requesting_obj->getID());          }      } -	return NULL; +	return nullptr;  }  void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id) @@ -4173,16 +4260,13 @@ bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id)  bool LLMeshRepoThread::hasPhysicsShapeInHeader(const LLUUID& mesh_id)  {      LLMutexLock lock(mHeaderMutex); -    if (mMeshHeaderSize[mesh_id] > 0) +    mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); +    if (iter != mMeshHeader.end() && iter->second.first > 0)      { -        mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); -        if (iter != mMeshHeader.end()) +        LLSD &mesh = iter->second.second; +        if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0))          { -            LLSD &mesh = iter->second; -            if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) -            { -                return true; -            } +            return true;          }      } @@ -4207,9 +4291,9 @@ S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)  	{  		LLMutexLock lock(mThread->mHeaderMutex);  		LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); -		if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) +		if (iter != mThread->mMeshHeader.end() && iter->second.first > 0)  		{ -			LLSD& header = iter->second; +			const LLSD& header = iter->second.second;  			if (header.has("404"))  			{ @@ -4313,9 +4397,9 @@ F32 LLMeshRepository::getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* by      {          LLMutexLock lock(mThread->mHeaderMutex);          LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); -        if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) +        if (iter != mThread->mMeshHeader.end() && iter->second.first > 0)          { -            result  = getStreamingCostLegacy(iter->second, radius, bytes, bytes_visible, lod, unscaled_value); +            result  = getStreamingCostLegacy(iter->second.second, radius, bytes, bytes_visible, lod, unscaled_value);          }      }      if (result > 0.f) @@ -4628,9 +4712,9 @@ bool LLMeshRepository::getCostData(LLUUID mesh_id, LLMeshCostData& data)      {          LLMutexLock lock(mThread->mHeaderMutex);          LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); -        if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) +        if (iter != mThread->mMeshHeader.end() && iter->second.first > 0)          { -            LLSD& header = iter->second; +            LLSD& header = iter->second.second;              bool header_invalid = (header.has("404")                                     || !header.has("lowest_lod") diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index f61da3e571..e3688ff243 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -210,10 +210,8 @@ public:  	LLCondition* mSignal;  	//map of known mesh headers -	typedef std::map<LLUUID, LLSD> mesh_header_map; +	typedef boost::unordered_map<LLUUID, std::pair<U32, LLSD>> mesh_header_map; // pair is header_size and data  	mesh_header_map mMeshHeader; -	 -	std::map<LLUUID, U32> mMeshHeaderSize;  	class HeaderRequest : public RequestStats  	{  @@ -283,10 +281,13 @@ public:  	};  	//set of requested skin info -	std::set<UUIDBasedRequest> mSkinRequests; +	std::deque<UUIDBasedRequest> mSkinRequests;  	// list of completed skin info requests -	std::list<LLMeshSkinInfo> mSkinInfoQ; +	std::deque<LLMeshSkinInfo*> mSkinInfoQ; + +	// list of skin info requests that have failed or are unavailaibe +	std::deque<UUIDBasedRequest> mSkinUnavailableQ;  	//set of requested decompositions  	std::set<UUIDBasedRequest> mDecompositionRequests; @@ -304,13 +305,13 @@ public:  	std::queue<LODRequest> mLODReqQ;  	//queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD) -	std::queue<LODRequest> mUnavailableQ; +	std::deque<LODRequest> mUnavailableQ;  	//queue of successfully loaded meshes -	std::queue<LoadedMesh> mLoadedQ; +	std::deque<LoadedMesh> mLoadedQ;  	//map of pending header requests and currently desired LODs -	typedef std::map<LLVolumeParams, std::vector<S32> > pending_lod_map; +	typedef boost::unordered_map<LLUUID, std::vector<S32> > pending_lod_map;  	pending_lod_map mPendingLOD;  	// llcorehttp library interface objects. @@ -354,7 +355,7 @@ public:  	//send request for skin info, returns true if header info exists   	//  (should hold onto mesh_id and try again later if header info does not exist) -	bool fetchMeshSkinInfo(const LLUUID& mesh_id); +	bool fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry = true);  	//send request for decomposition, returns true if header info exists   	//  (should hold onto mesh_id and try again later if header info does not exist) @@ -577,18 +578,20 @@ public:  	void shutdown();  	S32 update(); +	void unregisterMesh(LLVOVolume* volume);  	//mesh management functions  	S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1);  	void notifyLoadedMeshes();  	void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume);  	void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod); -	void notifySkinInfoReceived(LLMeshSkinInfo& info); +	void notifySkinInfoReceived(LLMeshSkinInfo* info); +	void notifySkinInfoUnavailable(const LLUUID& info);  	void notifyDecompositionReceived(LLModel::Decomposition* info);  	S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);  	static S32 getActualMeshLOD(LLSD& header, S32 lod); -	const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj = nullptr); +	const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj = nullptr);  	LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);  	void fetchPhysicsShape(const LLUUID& mesh_id);  	bool hasPhysicsShape(const LLUUID& mesh_id); @@ -613,10 +616,10 @@ public:  	static void metricsProgress(unsigned int count);  	static void metricsUpdate(); -	typedef std::map<LLVolumeParams, std::set<LLUUID> > mesh_load_map; +	typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > mesh_load_map;  	mesh_load_map mLoadingMeshes[4]; -	typedef std::unordered_map<LLUUID, LLMeshSkinInfo> skin_map; +	typedef std::unordered_map<LLUUID, LLPointer<LLMeshSkinInfo>> skin_map;  	skin_map mSkinMap;  	typedef std::map<LLUUID, LLModel::Decomposition*> decomposition_map; @@ -627,7 +630,7 @@ public:  	std::vector<LLMeshRepoThread::LODRequest> mPendingRequests;  	//list of mesh ids awaiting skin info -	typedef std::map<LLUUID, std::set<LLUUID> > skin_load_map; +	typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > skin_load_map;  	skin_load_map mLoadingSkins;  	//list of mesh ids that need to send skin info fetch requests @@ -652,6 +655,8 @@ public:  	std::vector<LLMeshUploadThread*> mUploadWaitList;  	LLPhysicsDecomp* mDecompThread; + +	LLFrameTimer     mSkinInfoCullTimer;  	class inventory_data  	{ diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 642df7f931..e1a5b22490 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -1926,32 +1926,16 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d                      if (sloppy_ratio < 0)                      {                          // Sloppy method didn't work, try with smaller decimation values -                        S32 size_vertices = 0; - -                        for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx) -                        { -                            const LLVolumeFace &face = base->getVolumeFace(face_idx); -                            size_vertices += face.mNumVertices; -                        } - -                        // Complex models aren't supposed to get here, they are supposed -                        // to work on a first try of sloppy due to having more viggle room. -                        // If they didn't, something is likely wrong, no point locking the -                        // thread in a long calculation that will fail. -                        const U32 too_many_vertices = 27000; -                        if (size_vertices > too_many_vertices) -                        { -                            LL_WARNS() << "Sloppy optimization method failed for a complex model " << target_model->getName() << LL_ENDL; -                        } -                        else                          {                              // Find a decimator that does work                              F32 sloppy_decimation_step = sqrt((F32)decimation); // example: 27->15->9->5->3                              F32 sloppy_decimator = indices_decimator / sloppy_decimation_step; +                            U64Microseconds end_time = LLTimer::getTotalTime() + U64Seconds(5);                              while (sloppy_ratio < 0                                  && sloppy_decimator > precise_ratio -                                && sloppy_decimator > 1)// precise_ratio isn't supposed to be below 1, but check just in case +                                && sloppy_decimator > 1 // precise_ratio isn't supposed to be below 1, but check just in case +                                && end_time > LLTimer::getTotalTime())                              {                                  sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY);                                  sloppy_decimator = sloppy_decimator / sloppy_decimation_step; diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index b34be80b07..0ba3c3d691 100755..100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -102,8 +102,7 @@ LLNetMap::LLNetMap (const Params & p)  	mObjectImagep(),  	mClosestAgentToCursor(),  	mClosestAgentAtLastRightClick(), -	mToolTipMsg(), -	mPopupMenu(NULL) +	mToolTipMsg()  {  	mScale = gSavedSettings.getF32("MiniMapScale");      if (gAgent.isFirstLogin()) @@ -119,6 +118,12 @@ LLNetMap::LLNetMap (const Params & p)  LLNetMap::~LLNetMap()  { +    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); +    if (menu) +    { +        menu->die(); +        mPopupMenuHandle.markDead(); +    }  }  BOOL LLNetMap::postBuild() @@ -134,11 +139,10 @@ BOOL LLNetMap::postBuild()      commitRegistrar.add("Minimap.MapOrientation.Set", boost::bind(&LLNetMap::setMapOrientation, this, _2));      commitRegistrar.add("Minimap.AboutLand", boost::bind(&LLNetMap::popupShowAboutLand, this, _2)); -    mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, -                                                                          LLViewerMenuHolderGL::child_registry_t::instance()); -    mPopupMenu->setItemEnabled("Re-center map", false); - -    return true; +    LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_mini_map.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +    mPopupMenuHandle = menu->getHandle(); +    menu->setItemEnabled("Re-center map", false); +	return TRUE;  }  void LLNetMap::setScale( F32 scale ) @@ -206,8 +210,12 @@ void LLNetMap::draw()          mCentering = false;      } -    bool can_recenter_map = !(centered || mCentering || auto_centering); -    mPopupMenu->setItemEnabled("Re-center map", can_recenter_map); +    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); +    if (menu) +    { +        bool can_recenter_map = !(centered || mCentering || auto_centering); +        menu->setItemEnabled("Re-center map", can_recenter_map); +    }      updateAboutLandPopupButton();  	// Prepare a scissor region @@ -595,14 +603,15 @@ void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color,  bool LLNetMap::isMouseOnPopupMenu()  { -    if (!mPopupMenu->isOpen()) +    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); +    if (!menu || !menu->isOpen())      {          return false;      }      S32 popup_x;      S32 popup_y; -    LLUI::getInstance()->getMousePositionLocal(mPopupMenu, &popup_x, &popup_y); +    LLUI::getInstance()->getMousePositionLocal(menu, &popup_x, &popup_y);      // *NOTE: Tolerance is larger than it needs to be because the context menu is offset from the mouse when the menu is opened from certain      // directions. This may be a quirk of LLMenuGL::showPopup. -Cosmic,2022-03-22      constexpr S32 tolerance = 10; @@ -613,7 +622,7 @@ bool LLNetMap::isMouseOnPopupMenu()      {          for (S32 sign_y = -1; sign_y <= 1; sign_y += 2)          { -            if (mPopupMenu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance))) +            if (menu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance)))              {                  return true;              } @@ -624,7 +633,8 @@ bool LLNetMap::isMouseOnPopupMenu()  void LLNetMap::updateAboutLandPopupButton()  { -    if (!mPopupMenu->isOpen()) +    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); +    if (!menu || !menu->isOpen())      {          return;      } @@ -632,7 +642,7 @@ void LLNetMap::updateAboutLandPopupButton()      LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal(mPopupWorldPos);      if (!region)      { -        mPopupMenu->setItemEnabled("About Land", false); +        menu->setItemEnabled("About Land", false);      }      else      { @@ -647,7 +657,7 @@ void LLNetMap::updateAboutLandPopupButton()              {                  valid_parcel = hover_parcel->getOwnerID().notNull();              } -            mPopupMenu->setItemEnabled("About Land", valid_parcel); +            menu->setItemEnabled("About Land", valid_parcel);          }      }  } @@ -1043,13 +1053,14 @@ BOOL LLNetMap::handleMouseUp(S32 x, S32 y, MASK mask)  BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask)  { -	if (mPopupMenu) +    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); +    if (menu)  	{ -        mPopupWorldPos = viewPosToGlobal(x, y); -		mPopupMenu->buildDrawLabels(); -		mPopupMenu->updateParent(LLMenuGL::sMenuContainer); -		mPopupMenu->setItemEnabled("Stop tracking", LLTracker::isTracking(0)); -		LLMenuGL::showPopup(this, mPopupMenu, x, y); +		mPopupWorldPos = viewPosToGlobal(x, y); +        menu->buildDrawLabels(); +        menu->updateParent(LLMenuGL::sMenuContainer); +        menu->setItemEnabled("Stop Tracking", LLTracker::isTracking(0)); +		LLMenuGL::showPopup(this, menu, x, y);  	}  	return TRUE;  } @@ -1182,9 +1193,10 @@ void LLNetMap::setZoom(const LLSD &userdata)  void LLNetMap::handleStopTracking (const LLSD& userdata)  { -	if (mPopupMenu) +    auto menu = static_cast<LLMenuGL*>(mPopupMenuHandle.get()); +    if (menu)  	{ -		mPopupMenu->setItemEnabled ("Stop tracking", false); +        menu->setItemEnabled ("Stop Tracking", false);  		LLTracker::stopTracking (LLTracker::isTracking(NULL));  	}  } diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index fe1aca65a9..75c1abc4ed 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -162,7 +162,7 @@ private:      void setMapOrientation(const LLSD& userdata);      void popupShowAboutLand(const LLSD& userdata); -	LLMenuGL*		mPopupMenu; +    LLHandle<LLView> mPopupMenuHandle;  	uuid_vec_t		gmSelected;  }; diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp index 6a79a0c68c..f86edfd0cf 100644 --- a/indra/newview/llnotificationlistitem.cpp +++ b/indra/newview/llnotificationlistitem.cpp @@ -521,8 +521,6 @@ void LLGroupNoticeNotificationListItem::close()  void LLGroupNoticeNotificationListItem::onClickAttachment()  {      if (mInventoryOffer != NULL) { -        mInventoryOffer->forceResponse(IOR_ACCEPT); -          static const LLUIColor textColor = LLUIColorTable::instance().getColor(              "GroupNotifyDimmedTextColor");          mAttachmentTextBox->setColor(textColor); @@ -532,7 +530,7 @@ void LLGroupNoticeNotificationListItem::onClickAttachment()          if (!isAttachmentOpenable(mInventoryOffer->mType)) {              LLNotifications::instance().add("AttachmentSaved", LLSD(), LLSD());          } - +        mInventoryOffer->forceResponse(IOR_ACCEPT);          mInventoryOffer = NULL;      }  } diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 1facbbf37c..602b7412a4 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -1226,7 +1226,7 @@ void LLOutfitGallery::uploadOutfitImage(const std::vector<std::string>& 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 7270580032..4171fd8822 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -823,8 +823,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 ea10aa75ae..0103bf628a 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1663,7 +1663,7 @@ void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLAvatarAppearanceDefine  class LLMetricSystemHandler : public LLCommandHandler  {  public: -        LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_THROTTLE) { } +        LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_CLICK_ONLY) { }          bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)          { diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp index 44b4728df7..e5c637938f 100644 --- a/indra/newview/llpanelexperiencelog.cpp +++ b/indra/newview/llpanelexperiencelog.cpp @@ -112,7 +112,7 @@ void LLPanelExperienceLog::refresh()  	int items = 0;  	bool moreItems = false;  	LLSD events_to_save = events; -	if (!events.emptyMap()) +	if (events.isMap() && events.size() != 0)  	{  		LLSD::map_const_iterator day = events.endMap();  		do diff --git a/indra/newview/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp index 26cd3ff1c1..e379d67e37 100644 --- a/indra/newview/llpanellandmedia.cpp +++ b/indra/newview/llpanellandmedia.cpp @@ -179,7 +179,6 @@ void LLPanelLandMedia::refresh()  		// enable/disable for text label for completeness  		mMediaSizeCtrlLabel->setEnabled( 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 ccda9c2399..744d49ff57 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -307,6 +307,13 @@ LLPanelMainInventory::~LLPanelMainInventory( void )  	gInventory.removeObserver(this);  	delete mSavedFolderState; + +	auto menu = mMenuAddHandle.get(); +	if(menu) +	{ +		menu->die(); +		mMenuAddHandle.markDead(); +	}  }  LLInventoryPanel* LLPanelMainInventory::getAllItemsPanel() @@ -1189,13 +1196,12 @@ void LLPanelMainInventory::initListCommandsHandlers()  	mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2));  	mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));  	mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	mGearMenuButton->setMenu(mMenuGearDefault); +	mGearMenuButton->setMenu(mMenuGearDefault, LLMenuButton::MP_TOP_LEFT, true);  	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());  	mMenuAddHandle = menu->getHandle();  	mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	mVisibilityMenuButton->setMenu(mMenuVisibility); -	mVisibilityMenuButton->setMenuPosition(LLMenuButton::MP_BOTTOM_LEFT); +	mVisibilityMenuButton->setMenu(mMenuVisibility, LLMenuButton::MP_BOTTOM_LEFT, true);  	// Update the trash button when selected item(s) get worn or taken off.  	LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this)); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index bc7933d84b..2da431955f 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -2131,7 +2131,7 @@ bool LLPanelObject::menuEnableItem(const LLSD& userdata)      }      else if (command == "params_paste")      { -        return mClipboardParams.isMap() && !mClipboardParams.emptyMap(); +        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 fff25c6c61..bd40c9dd2b 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1275,7 +1275,8 @@ LLPanelObjectInventory::LLPanelObjectInventory(const LLPanelObjectInventory::Par  	mHaveInventory(FALSE),  	mIsInventoryEmpty(TRUE),  	mInventoryNeedsUpdate(FALSE), -	mInventoryViewModel(p.name) +	mInventoryViewModel(p.name), +    mShowRootFolder(p.show_root_folder)  {  	// Setup context menu callbacks  	mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelObjectInventory::doToSelected, this, _2)); @@ -1360,6 +1361,7 @@ void LLPanelObjectInventory::reset()  	mFolders = LLUICtrlFactory::create<LLFolderView>(p);  	mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); +	mFolders->setEnableRegistrar(&mEnableCallbackRegistrar);  	if (hasFocus())  	{ @@ -1526,15 +1528,23 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root  		p.font_highlight_color = item_color;  		LLFolderViewFolder* new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); -		new_folder->addToFolder(mFolders); -		new_folder->toggleOpen(); + +        if (mShowRootFolder) +        { +            new_folder->addToFolder(mFolders); +            new_folder->toggleOpen(); +        }  		if (!contents.empty())  		{ -			createViewsForCategory(&contents, inventory_root, new_folder); +			createViewsForCategory(&contents, inventory_root, mShowRootFolder ? new_folder : mFolders);  		} -        // Refresh for label to add item count -        new_folder->refresh(); + +        if (mShowRootFolder) +        { +            // Refresh for label to add item count +            new_folder->refresh(); +        }  	}  } diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 7b9ecfb8f3..0e450d8ce9 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -48,8 +48,14 @@ class LLViewerObject;  class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener  {  public: -	// dummy param block for template registration purposes -	struct Params : public LLPanel::Params {}; +    struct Params : public LLInitParam::Block<Params, LLPanel::Params> +    { +        Optional<bool> show_root_folder; + +        Params() +            : show_root_folder("show_root_folder", true) +        {} +    };  	LLPanelObjectInventory(const Params&);  	virtual ~LLPanelObjectInventory(); @@ -110,6 +116,7 @@ private:  	BOOL mIsInventoryEmpty; // 'Empty' label  	BOOL mInventoryNeedsUpdate; // for idle, set on changed callback  	LLFolderViewModelInventory	mInventoryViewModel;	 +    bool mShowRootFolder;  };  #endif // LL_LLPANELOBJECTINVENTORY_H diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 74ec576554..0f00231643 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -800,7 +800,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 f4eaa78f11..708ff26ced 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -484,6 +484,30 @@ public:  	// requires trusted browser to trigger  	LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { } +    virtual bool canHandleUntrusted( +        const LLSD& params, +        const LLSD& query_map, +        LLMediaCtrl* web, +        const std::string& nav_type) +    { +        if (params.size() < 2) +        { +            return true; // don't block, will fail later +        } + +        if (nav_type == NAV_TYPE_CLICKED) +        { +            return true; +        } + +        const std::string verb = params[1].asString(); +        if (verb == "about" || verb == "inspect" || verb == "reportAbuse") +        { +            return true; +        } +        return false; +    } +  	bool handle(const LLSD& params, const LLSD& query_map,  		LLMediaCtrl* web)  	{ @@ -1031,7 +1055,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())      { @@ -1280,6 +1303,8 @@ void LLPanelProfileSecondLife::fillRightsData()  void LLPanelProfileSecondLife::fillAgeData(const LLDate &born_on)  { +    // Date from server comes already converted to stl timezone, +    // so display it as an UTC + 0      std::string name_and_date = getString("date_format");      LLSD args_name;      args_name["datetime"] = (S32)born_on.secondsSinceEpoch(); diff --git a/indra/newview/llpanelprofileclassifieds.cpp b/indra/newview/llpanelprofileclassifieds.cpp index a3913ddc49..1ff12b4f37 100644 --- a/indra/newview/llpanelprofileclassifieds.cpp +++ b/indra/newview/llpanelprofileclassifieds.cpp @@ -81,6 +81,30 @@ public:  	std::set<LLUUID> mClassifiedIds;  	std::string mRequestVerb; + +    virtual bool canHandleUntrusted( +        const LLSD& params, +        const LLSD& query_map, +        LLMediaCtrl* web, +        const std::string& nav_type) +    { +        if (params.size() < 1) +        { +            return true; // don't block, will fail later +        } + +        if (nav_type == NAV_TYPE_CLICKED) +        { +            return true; +        } + +        const std::string verb = params[0].asString(); +        if (verb == "create") +        { +            return false; +        } +        return true; +    }  	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)      { diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp index 774119f169..45d0252e4f 100644 --- a/indra/newview/llpanelprofilepicks.cpp +++ b/indra/newview/llpanelprofilepicks.cpp @@ -63,6 +63,30 @@ public:      // requires trusted browser to trigger      LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { } +    virtual bool canHandleUntrusted( +        const LLSD& params, +        const LLSD& query_map, +        LLMediaCtrl* web, +        const std::string& nav_type) +    { +        if (params.size() < 1) +        { +            return true; // don't block, will fail later +        } + +        if (nav_type == NAV_TYPE_CLICKED) +        { +            return true; +        } + +        const std::string verb = params[0].asString(); +        if (verb == "create") +        { +            return false; +        } +        return true; +    } +      bool handle(const LLSD& params, const LLSD& query_map,          LLMediaCtrl* web)      { diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 3fd4f51559..33656566d1 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -255,7 +255,7 @@ void LLPreviewNotecard::loadAsset()  			else  			{  				LLHost source_sim = LLHost(); -				LLSD* user_data = new LLSD(); +				LLSD* user_data = nullptr;  				if (mObjectUUID.notNull())  				{  					LLViewerObject *objectp = gObjectList.findObject(mObjectUUID); @@ -274,6 +274,7 @@ void LLPreviewNotecard::loadAsset()  						mAssetStatus = PREVIEW_ASSET_LOADED;  						return;  					} +					user_data = new LLSD();  					user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID);  				}  				else diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 2e44dc1459..7089df677e 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 7cd531bd34..f2e1ef69b9 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 da912ef3d4..6a27ff3047 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -460,10 +460,11 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)  		if(it != mNotifications.end())  		{ +			LLUUID old_id = it->first; // copy LLUUID to prevent use after free when it is erased below  			LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel();  			if (NULL != chiclet_panelp)  			{ -				LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(it->first); +				LLIMChiclet * chicletp = chiclet_panelp->findChiclet<LLIMChiclet>(old_id);  				if (NULL != chicletp)  				{  					// Pass the new_message icon state further. @@ -472,14 +473,14 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id)  				}  			} -			LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", it->first); +			LLScriptFloater* floater = LLFloaterReg::findTypedInstance<LLScriptFloater>("script_floater", old_id);  			if (floater)  			{  				// Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142.  				set_new_message |= !floater->hasFocus();  			} -			removeNotification(it->first); +			removeNotification(old_id);  		}  	} diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 7c762170a7..707b602fc6 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -694,8 +694,8 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)          LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); -        LLVector4 sunDiffuse = LLVector4(psky->getSunlightColor().mV); -        LLVector4 moonDiffuse = LLVector4(psky->getMoonlightColor().mV); +        LLVector4 sunDiffuse = LLVector4(LLVector3(psky->getSunlightColor().mV)); +        LLVector4 moonDiffuse = LLVector4(LLVector3(psky->getMoonlightColor().mV));          shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, sunDiffuse);          shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, moonDiffuse); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index ea671a130e..60bada8f58 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -982,7 +982,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<SpeakingIndicatorManager>, 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 1dd5c5cbe5..6883ead5ee 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -272,12 +272,10 @@ void show_first_run_dialog();  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<LLCertificate> cert); diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 024f25bc98..bf3f4c1e88 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -89,6 +89,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 752fc6f3f3..01d799dcd5 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 <boost/foreach.hpp> @@ -320,22 +319,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 a1670351f4..7c92e7ef98 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -263,7 +263,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 59654350e4..c0398372b4 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -174,11 +174,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<std::string> blacklist_clicked = { +                "camera_presets", +                "delete_pref_preset", +                "forget_username", +                "god_tools", +                "group_picker", +                "hud", +                "incoming_call", +                "linkreplace", +                "message_critical", // Modal!!! Login specific. +                "message_tos", // Modal!!! Login specific. +                "save_pref_preset", +                "save_camera_preset", +                "region_restarting", +                "outfit_snapshot", +                "upload_anim_bvh", +                "upload_anim_anim", +                "upload_image", +                "upload_model", +                "upload_script", +                "upload_sound" +            }; +            return std::find(blacklist_clicked.begin(), blacklist_clicked.end(), fl_name) == blacklist_clicked.end(); +        } +        else +        { +            const std::list<std::string> blacklist_untrusted = { +                "360capture", +                "block_timers", +                "add_payment_method", +                "appearance", +                "associate_listing", +                "avatar_picker", +                "camera", +                "camera_presets", +                "classified", +                "add_landmark", +                "delete_pref_preset", +                "env_fixed_environmentent_water", +                "env_fixed_environmentent_sky", +                "env_edit_extdaycycle", +                "font_test", +                "forget_username", +                "god_tools", +                "group_picker", +                "hud", +                "incoming_call", +                "linkreplace", +                "mem_leaking", +                "marketplace_validation", +                "message_critical", // Modal!!! Login specific. If this is in use elsewhere, better to create a non modal variant +                "message_tos", // Modal!!! Login specific. +                "mute_object_by_name", +                "publish_classified", +                "save_pref_preset", +                "save_camera_preset", +                "region_restarting", +                "script_debug", +                "script_debug_output", +                "sell_land", +                "outfit_snapshot", +                "upload_anim_bvh", +                "upload_anim_anim", +                "upload_image", +                "upload_model", +                "upload_script", +                "upload_sound" +            }; +            return std::find(blacklist_untrusted.begin(), blacklist_untrusted.end(), fl_name) == blacklist_untrusted.end(); +        } + + +        return true; +    } + +	bool handle( +        const LLSD& params, +        const LLSD& query_map, +        LLMediaCtrl* web) override  	{  		if (params.size() != 1)  		{ diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 43b9cd90bd..6bab2c2100 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1614,12 +1614,22 @@ BOOL LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask,              clicktype = CLICK_DOUBLELEFT;          } +        // If the first LMB click is handled by the menu, skip the following double click +        static bool skip_double_click = false; +        if (clicktype == CLICK_LEFT && down ) +        { +            skip_double_click = handled; +        }          if (double_click_sp && down)          {              // Consume click.              // Due to handling, double click that is not handled will be immediately followed by LMB click          } +        else if (clicktype == CLICK_DOUBLELEFT && skip_double_click) +        { +            handled = true; +        }          // If UI handled 'down', it should handle 'up' as well          // If we handle 'down' not by UI, then we should handle 'up'/'level' regardless of UI          else if (handled) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 55ac817479..50252556de 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -232,7 +232,7 @@ class LLInventoryHandler : public LLCommandHandler  {  public:  	// requires trusted browser to trigger -	LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { } +	LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_CLICK_ONLY) { }  	bool handle(const LLSD& params, const LLSD& query_map,  				LLMediaCtrl* web) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c796ed30f7..a0223a5dbb 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2803,14 +2803,15 @@ void handle_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<std::string, LLStringExplicit>::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<std::string, LLStringExplicit>(item_name, default_label)); @@ -2841,18 +2842,17 @@ bool enable_object_touch(LLUICtrl* ctrl)  		new_value = obj->flagHandleTouch() || (parent && parent->flagHandleTouch());  	} -	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; @@ -5632,6 +5632,7 @@ class LLToolsSelectNextPartFace : public view_listener_t                      }                  }                  LLSelectMgr::getInstance()->selectObjectOnly(to_select, new_te); +                LLSelectMgr::getInstance()->addAsIndividual(to_select, new_te, false);              }              else              { @@ -6595,20 +6596,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()));  		}  	}  	return !sitting_on_sel && is_object_sittable(); @@ -7654,7 +7653,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 7ac1df8e31..f47f0b4572 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -3234,36 +3234,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; @@ -3298,7 +3301,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 e2de7ac825..7abb42dd8a 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -1252,7 +1252,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 3b391e311a..ddc11ac0bd 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1309,7 +1309,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; @@ -3435,6 +3434,59 @@ void LLViewerWindow::updateUI()  		root_view = mRootView;  	} +	static LLCachedControl<bool> dump_menu_holder(gSavedSettings, "DumpMenuHolderSize", false); +	if (dump_menu_holder) +	{ +		static bool init = false; +		static LLFrameTimer child_count_timer; +		static std::vector <std::string> child_vec; +		if (!init) +		{ +			child_count_timer.resetWithExpiry(5.f); +			init = true; +		} +		if (child_count_timer.hasExpired()) +		{ +			LL_INFOS() << "gMenuHolder child count: " << gMenuHolder->getChildCount() << LL_ENDL; +			std::vector<std::string> local_child_vec; +			LLView::child_list_t child_list = *gMenuHolder->getChildList(); +			for (auto child : child_list) +			{ +				local_child_vec.emplace_back(child->getName()); +			} +			if (!local_child_vec.empty() && local_child_vec != child_vec) +			{ +				std::vector<std::string> out_vec; +				std::sort(local_child_vec.begin(), local_child_vec.end()); +				std::sort(child_vec.begin(), child_vec.end()); +				std::set_difference(child_vec.begin(), child_vec.end(), local_child_vec.begin(), local_child_vec.end(), std::inserter(out_vec, out_vec.begin())); +				if (!out_vec.empty()) +				{ +					LL_INFOS() << "gMenuHolder removal diff size: '"<<out_vec.size() <<"' begin_child_diff"; +					for (auto str : out_vec) +					{ +						LL_CONT << " : " << str; +					} +					LL_CONT << " : end_child_diff" << LL_ENDL; +				} + +				out_vec.clear(); +				std::set_difference(local_child_vec.begin(), local_child_vec.end(), child_vec.begin(), child_vec.end(), std::inserter(out_vec, out_vec.begin())); +				if (!out_vec.empty()) +				{ +					LL_INFOS() << "gMenuHolder addition diff size: '" << out_vec.size() << "' begin_child_diff"; +					for (auto str : out_vec) +					{ +						LL_CONT << " : " << str; +					} +					LL_CONT << " : end_child_diff" << LL_ENDL; +				} +				child_vec.swap(local_child_vec); +			} +			child_count_timer.resetWithExpiry(5.f); +		} +	} +  	// only update mouse hover set when UI is visible (since we shouldn't send hover events to invisible UI  	if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))  	{ diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 2ef2d66f18..6bb987ede4 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -797,7 +797,10 @@ void LLVoiceClient::addObserver(LLVoiceClientStatusObserver* observer)  void LLVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer)  { -	if (mVoiceModule && mVoiceModule->singletoneInstanceExists()) mVoiceModule->removeObserver(observer); +    if (mVoiceModule) +    { +        mVoiceModule->removeObserver(observer); +    }  }  void LLVoiceClient::addObserver(LLFriendObserver* observer) @@ -807,7 +810,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) @@ -817,7 +823,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 246883b611..aa67502908 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -122,8 +122,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 ab90f2e482..8f0938d01e 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -5215,11 +5215,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 ebc3a62c35..0a785401c1 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 1aa00bc894..909588367b 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -100,8 +100,8 @@ LLSkyTex::LLSkyTex() :  void LLSkyTex::init(bool isShiny)  {      mIsShiny = isShiny; -	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 a4e0d367c8..2e7ccc8334 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -228,6 +228,9 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re      mColorChanged = FALSE;  	mSpotLightPriority = 0.f; +	mSkinInfoFailed = false; +	mSkinInfo = NULL; +  	mMediaImplList.resize(getNumTEs());  	mLastFetchedMediaVersion = -1;      mServerDrawableUpdateCount = 0; @@ -244,6 +247,8 @@ LLVOVolume::~LLVOVolume()  	delete mVolumeImpl;  	mVolumeImpl = NULL; +	gMeshRepo.unregisterMesh(this); +  	if(!mMediaImplList.empty())  	{  		for(U32 i = 0 ; i < mMediaImplList.size() ; i++) @@ -851,10 +856,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)  	if (isSculpted())  	{ -		LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); -		LLUUID id =  sculpt_params->getSculptTexture(); -		 -		updateSculptTexture(); +        updateSculptTexture(); @@ -1095,10 +1097,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)  					{ @@ -1106,6 +1113,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo  					}  				} +				if (!mSkinInfo && !mSkinInfoFailed) +				{ +					const LLMeshSkinInfo* skin_info = gMeshRepo.getSkinInfo(volume_params.getSculptID(), this); +					if (skin_info) +					{ +						notifySkinInfoLoaded(skin_info); +					} +				}  			}  			else // otherwise is sculptie  			{ @@ -1158,6 +1173,9 @@ void LLVOVolume::updateSculptTexture()  		{  			mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);  		} + +		mSkinInfoFailed = false; +		mSkinInfo = NULL;  	}  	else  	{ @@ -1212,6 +1230,20 @@ void LLVOVolume::notifyMeshLoaded()      updateVisualComplexity();  } +void LLVOVolume::notifySkinInfoLoaded(const LLMeshSkinInfo* skin) +{ +	mSkinInfoFailed = false; +	mSkinInfo = skin; + +	notifyMeshLoaded(); +} + +void LLVOVolume::notifySkinInfoUnavailable() +{ +	mSkinInfoFailed = true; +	mSkinInfo = nullptr; +} +  // sculpt replaces generate() for sculpted surfaces  void LLVOVolume::sculpt()  {	 @@ -3645,7 +3677,7 @@ const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const  {      if (getVolume())      { -        return gMeshRepo.getSkinInfo(getMeshID(), this); +         return mSkinInfo;      }      else      { diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 01ad40274b..59599ddc0c 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -353,6 +353,8 @@ public:      void updateVisualComplexity();  	void notifyMeshLoaded(); +	void notifySkinInfoLoaded(const LLMeshSkinInfo* skin); +	void notifySkinInfoUnavailable();  	// Returns 'true' iff the media data for this object is in flight  	bool isMediaDataBeingFetched() const; @@ -437,6 +439,8 @@ private:  	LLPointer<LLRiggedVolume> mRiggedVolume; +	bool mSkinInfoFailed; +	LLConstPointer<LLMeshSkinInfo> mSkinInfo;  	// statics  public:  	static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index bf4db81475..89b74ae962 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -92,17 +92,77 @@ 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) +    { +        addWidgetToRightSide("add_wearable"); +        addWidgetToRightSide("remove_wearable"); + +        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<LLPanelInventoryListItemBase>(); +		const LLPanelWearableOutfitItem::Params& params = LLUICtrlFactory::getDefaultParams<LLPanelWearableOutfitItem>(); -		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();  	} @@ -110,11 +170,23 @@ 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)  { +    if(mShowWidgets) +    { +        LLButton::Params button_params = params.add_btn; +        applyXUILayout(button_params, this); +        addChild(LLUICtrlFactory::create<LLButton>(button_params)); + +        button_params = params.remove_btn; +        applyXUILayout(button_params, this); +        addChild(LLUICtrlFactory::create<LLButton>(button_params)); +    }  }  // virtual @@ -127,11 +199,22 @@ 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. -	if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID)) +    bool is_worn = LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID); +	if (mWornIndicationEnabled && is_worn)  	{  		search_label += LLTrans::getString("worn");  		item_state = IS_WORN;  	} +    if(mShowWidgets) +    { +        setShowWidget("add_wearable", !is_worn); +        setShowWidget("remove_wearable", is_worn); +        if(mHovered) +        { +            setWidgetsVisible(true); +            reshapeWidgets(); +        } +    }  	LLPanelInventoryListItemBase::updateItem(search_label, item_state);  } @@ -634,6 +717,7 @@ static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_i  LLWearableItemsList::Params::Params()  :	standalone("standalone", true)  ,	worn_indication_enabled("worn_indication_enabled", true) +,   show_item_widgets("show_item_widgets", false)  {}  LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) @@ -649,6 +733,7 @@ LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p)  	}  	mWornIndicationEnabled = p.worn_indication_enabled;  	setNoItemsCommentText(LLTrans::getString("LoadingData")); +    mShowItemWidgets = p.show_item_widgets;  }  // virtual @@ -665,7 +750,7 @@ LLPanel* LLWearableItemsList::createNewItem(LLViewerInventoryItem* item)          return NULL;      } -    return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled); +    return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled, mShowItemWidgets);  }  void LLWearableItemsList::updateList(const LLUUID& category_id) diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index ba8488b237..f7774a7086 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<Params, LLPanelWearableListItem::Params> +    { +        Optional<LLButton::Params>   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,16 @@ 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; +    bool mShowWidgets;  };  class LLPanelDeletableWearableListItem : public LLPanelWearableListItem @@ -442,6 +457,7 @@ public:  	{  		Optional<bool> standalone;  		Optional<bool> worn_indication_enabled; +        Optional<bool> show_item_widgets;  		Params();  	}; @@ -482,6 +498,7 @@ protected:  	bool mIsStandalone;  	bool mWornIndicationEnabled; +    bool mShowItemWidgets;  	ESortOrder		mSortOrder; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 55bcbf8aa5..871583e071 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -293,13 +293,13 @@ void LLWorld::removeRegion(const LLHost &host)  	mRegionRemovedSignal(regionp); -	delete regionp; -  	updateWaterObjects();  	//double check all objects of this region are removed.  	gObjectList.clearAllMapObjectsInRegion(regionp) ;  	//llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ; + +	delete regionp; // Delete last to prevent use after free  } diff --git a/indra/newview/skins/default/textures/icons/add_icon.png b/indra/newview/skins/default/textures/icons/add_icon.pngBinary files differ new file mode 100644 index 0000000000..cb68ee8e16 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/add_icon.png diff --git a/indra/newview/skins/default/textures/icons/remove_icon.png b/indra/newview/skins/default/textures/icons/remove_icon.pngBinary files differ new file mode 100644 index 0000000000..6e62ee33f4 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/remove_icon.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 4429a1677e..1f2c0867c4 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -743,6 +743,9 @@ with the same filename but different name    <texture name="Wearables_Divider" file_name="windows/Wearables_Divider.png" preload="false" /> +  <texture name="Add_Icon" file_name="icons/add_icon.png" preload="false" /> +  <texture name="Remove_Icon" file_name="icons/remove_icon.png" preload="false" /> +    <texture name="Web_Profile_Off" file_name="icons/Web_Profile_Off.png" preload="false" />    <texture name="WellButton_Lit" file_name="bottomtray/WellButton_Lit.png"  preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" /> diff --git a/indra/newview/skins/default/xui/en/floater_object_weights.xml b/indra/newview/skins/default/xui/en/floater_object_weights.xml index eb283a1043..889efa061c 100644 --- a/indra/newview/skins/default/xui/en/floater_object_weights.xml +++ b/indra/newview/skins/default/xui/en/floater_object_weights.xml @@ -2,7 +2,7 @@  <floater   can_close="true"   can_tear_off="false" - height="315" + height="289"   help_topic="object_weights"   layout="topleft"   name="object_weights" @@ -320,23 +320,4 @@       top_delta="0"       value="Total capacity"       width="130" /> -    <view_border -     bevel_style="none" -     follows="top|left" -     height="0" -     layout="topleft" -     left="10" -     name="land_impacts_text_border" -     top_pad="5" -     width="180"/> - -    <text -     follows="left|top" -     height="16" -     layout="topleft" -     left="10" -     name="help_SLURL" -     top_pad="10" -     value="[secondlife:///app/help/object_weights What is all this?...]" -     width="180" />  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_openobject.xml b/indra/newview/skins/default/xui/en/floater_openobject.xml index 912db80bcc..ec03d7d32c 100644 --- a/indra/newview/skins/default/xui/en/floater_openobject.xml +++ b/indra/newview/skins/default/xui/en/floater_openobject.xml @@ -3,7 +3,7 @@   legacy_header_height="18"   can_resize="true"   default_tab_group="1" - height="370" + height="350"   layout="topleft"   min_height="190"   min_width="285" @@ -31,62 +31,18 @@       background_visible="false"       draw_border="false"       follows="all" -     height="240" +     height="265"       layout="topleft" +     show_root_folder="false"       left="10"       name="object_contents"       top_pad="0"       width="284" /> -  	<view_border -     bevel_style="none" -     follows="bottom|left" -     height="50" -     highlight_light_color="0.6 0.6 0.6" -     layout="topleft" -     left="10" -     name="border" -     top_pad="5" -     width="270"/>  -  	<text -  	 follows="bottom|left" -  	 height="15" -  	 layout="topleft" -  	 left="15" -  	 name="border_note" -  	 text_color="White" -  	 top_delta="5"> -  	 	Copy to inventory and wear -    </text>   - 	<button -     follows="bottom|left" -     height="23" -     label="Add to outfit" -     label_selected="Add to outfit" -     layout="topleft" - 	 left="15"     -     name="copy_and_wear_button" 	 - 	 top_pad="3"	 -     width="135"> -        <button.commit_callback -         function="OpenObject.MoveAndWear" /> -    </button> -	<button -     follows="bottom|left" -     height="23" -     label="Replace outfit" -     label_selected="Replace outfit" -     layout="topleft" -     left_pad="5" -     name="copy_and_replace_button" -     width="120"> -        <button.commit_callback -         function="OpenObject.ReplaceOutfit" /> -    </button>        <button       follows="bottom|left"       height="23"       label="Only copy to inventory" -     label_selected="Only copy to inventory" +     label_selected="Copy to inventory"       layout="topleft"       left="15"       name="copy_to_inventory_button" diff --git a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml index 41384a77b8..59117c0178 100644 --- a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml +++ b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml @@ -82,17 +82,20 @@          width="62">        Name      </text> -    <line_editor -        border_style="line" -        border_thickness="1" -        follows="left|top" -        height="20" -        layout="topleft" -        left_pad="0" -        top_pad="-18" -        max_length_chars="255" -        name="filter_by_name" -        width="161" /> + +    <search_editor +       follows="left|top" +       search_button_visible="false" +       height="20" +       text_readonly_color="DkGray" +       label="Objects by Name" +       layout="topleft" +       left_pad="0" +       top_pad="-18" +       name="filter_by_name" +       select_on_focus="true" +       width="161"> +    </search_editor>      <text          name="linksets_desc_label"          height="13" @@ -108,17 +111,19 @@          width="88">        Description      </text> -    <line_editor -        border_style="line" -        border_thickness="1" -        follows="left|top" -        height="20" -        layout="topleft" -        left_pad="0" -        top_pad="-17" -        max_length_chars="255" -        name="filter_by_description" -        width="162" /> +    <search_editor +       follows="left|top" +       search_button_visible="false" +       height="20" +       text_readonly_color="DkGray" +       label="Objects by Description" +       layout="topleft" +       left_pad="0" +       top_pad="-17" +       name="filter_by_description" +       select_on_focus="true" +       width="162"> +    </search_editor>      <combo_box          height="20"          layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_settings_debug.xml b/indra/newview/skins/default/xui/en/floater_settings_debug.xml index 3ed2bd7206..e4fda5cd10 100644 --- a/indra/newview/skins/default/xui/en/floater_settings_debug.xml +++ b/indra/newview/skins/default/xui/en/floater_settings_debug.xml @@ -2,41 +2,79 @@  <floater   legacy_header_height="18"   can_minimize="false" - height="215" + height="360" + min_height="367"   layout="topleft"   name="settings_debug"   help_topic="settings_debug"   title="DEBUG SETTINGS" - width="350"> -    <combo_box -     allow_text_entry="true" -     follows="top|left" -     height="22" -     layout="topleft" -     left="15" -     max_chars="255" -     name="settings_combo" -     top="30" -     width="320"> -      <combo_box.commit_callback -       function="SettingSelect" /> -    </combo_box> -    <text_editor -     enabled="false" -     height="60" -     layout="topleft" -     left_delta="0" -     name="comment_text" -     top_pad="10" -     width="320" -     word_wrap="true" /> + reuse_instance="true" + can_resize="true" + min_width="550" + width="570"> +  <filter_editor +   follows="left|top|right" +   height="23" +   layout="topleft" +   left="10" +   right="-10" +   label="Enter search text" +   max_length_chars="300" +   name="filter_input" +   text_pad_left="10" +   top="30" /> +  <scroll_list +   column_padding="0" +   draw_heading="true" +   draw_stripes="false" +   heading_height="23" +   height="266" +   layout="topleft" +   search_column="1" +   left="10" +   follows="left|top|bottom" +   name="setting_list" +   top_pad="2" +   width="300"> +    <scroll_list.columns +     name="changed_setting" +     relative_width="0.05"  /> +    <scroll_list.columns +     label="Setting" +     name="setting" /> +  </scroll_list> +  <text +   type="string" +   length="1" +   follows="left|top" +   height="16" +   layout="topleft" +   name="setting_name_txt" +   font="SansSerifSmallBold" +   top_delta="8" +   left_pad="10" +   visible="false" +   use_ellipses="true" +   text_color="White" +   width="240"> +    Debug setting name +  </text> +  <text_editor +   enabled="false" +   height="75" +   layout="topleft" +   visible="false" +   name="comment_text" +   follows="left|top" +   width="240" +   top_delta="20" +   word_wrap="true" />    <radio_group     follows="top|left"     height="30"     layout="topleft" -   left_delta="0"     name="boolean_combo" -   top_pad="10" +   top_pad="15"     visible="false"     tab_stop="true"      width="100"> @@ -55,21 +93,25 @@    </radio_group>      <line_editor       height="20" +     follows="top|left"       layout="topleft"       left_delta="0"       name="val_text"       top_delta="0"       visible="false" -     width="300" > +     width="220" >        <line_editor.commit_callback         function="CommitSettings" />      </line_editor>      <color_swatch -     bottom="185" +     top_delta="0" +     left_delta="0" +     follows="top|left"       can_apply_immediately="true"       height="55"       name="val_color_swatch"       label="Color" +     visible="false"       layout="topleft"       width="37" >        <color_swatch.commit_callback @@ -79,10 +121,11 @@       height="20"       label="x"       layout="topleft" +     follows="top|left"       left_delta="0"       max_val="1e+007"       name="val_spinner_1" -     top_delta="10" +     top_delta="5"       visible="false"       width="120" >        <spinner.commit_callback @@ -92,10 +135,11 @@       height="20"       label="x"       layout="topleft" -     left_pad="15" +     follows="top|left" +     left_delta="0"       max_val="1e+007"       name="val_spinner_2" -     top_delta="0" +     top_pad="10"       visible="false"       width="120">        <spinner.commit_callback @@ -105,10 +149,11 @@       height="20"       label="x"       layout="topleft" -     left="15" +     follows="top|left" +     left_delta="0"       max_val="1e+007"       name="val_spinner_3" -     top="160" +     top_pad="10"       visible="false"       width="120">        <spinner.commit_callback @@ -118,10 +163,11 @@       height="20"       label="x"       layout="topleft" -     left_pad="15" +     follows="top|left" +     left_delta="0"       max_val="1e+007"       name="val_spinner_4" -     top_delta="0" +     top_pad="10"       visible="false"       width="120" >        <spinner.commit_callback @@ -130,12 +176,26 @@      <button       height="22"       label="Reset to default" +     follows="left|top"       layout="topleft" -     left="15" +     left_delta="0"       name="default_btn" -     top="186" +     visible="false" +     top_pad="10"       width="150" >        <button.commit_callback         function="ClickDefault" />      </button> +    <check_box +      control_name="DebugSettingsHideDefault" +      height="16" +      initial_value="true" +      label="Show changed settings only" +      layout="topleft" +      top_pad="10" +      left="10" +      follows="left|bottom" +      name="hide_default" +      width="330"> +    </check_box>  </floater> diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml index 2a24c74feb..d74dca8b95 100644 --- a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml @@ -18,6 +18,7 @@       follows="all"       keep_one_selected="true"       multi_select="true" +     show_item_widgets="true"       name="wearable_items_list"       translate="false"       standalone="false" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml index 42a7974316..b2dc975c6e 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml @@ -36,6 +36,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/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 2ec5cef640..ef08fdf7c4 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -19,7 +19,7 @@        follows="left|top"        height="23"        label="Clear History" -      tool_tip="Clear login image, last location, teleport history, web and texture cache" +      tool_tip="Clear search and teleport history, web and texture cache"        layout="topleft"        left="30"        name="clear_cache" diff --git a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml index 551b477876..777b37d666 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml @@ -9,9 +9,13 @@   follows="all"   layout="topleft"  > +  <!-- +  Date from server comes already converted to stl timezone, +  so display it as an UTC+0 +  -->     <string       name="date_format" -    value="SL birthdate: [mth,datetime,slt] [day,datetime,slt], [year,datetime,slt]" /> +    value="SL birthdate: [mth,datetime,utc] [day,datetime,utc], [year,datetime,utc]" />     <string      name="age_format"      value="[AGE]" /> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index cf5d98aa9a..42a10e8c56 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3983,7 +3983,7 @@ Please check http://status.secondlifegrid.net to see if there is a known problem    <string name="Premium_PlusMembership">Premium Plus</string>    <string name="InternalMembership">Internal</string> <!-- No need to translate --> -  <string name="MembershipUpgradeText">Upgrade to Premium</string> +  <string name="MembershipUpgradeText">Change membership plan...</string>    <string name="MembershipPremiumText">My Premium membership</string>    <!-- Question strings for delete items notifications --> diff --git a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml index 1c4822b8d5..9c80deeafc 100644 --- a/indra/newview/skins/default/xui/en/widgets/filter_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/filter_editor.xml @@ -6,7 +6,7 @@    text_pad_left="7"    select_on_focus="true"    text_tentative_color="TextFgTentativeColor" -  highlight_text_field="false" +  highlight_text_field="true"    background_image="TextField_Search_Off"    background_image_disabled="TextField_Search_Disabled"    background_image_focused="TextField_Search_Active" diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml index dc5a07bf4f..18d99f1ed1 100644 --- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml +++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml @@ -7,7 +7,7 @@    text_pad_right="6"     select_on_focus="true"    text_tentative_color="TextFgTentativeColor" -  highlight_text_field="false" +  highlight_text_field="true"    background_image="TextField_Search_Off"    background_image_disabled="TextField_Search_Disabled"    background_image_focused="TextField_Search_Active" diff --git a/indra/newview/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..cd84b91b1f --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/wearable_outfit_list_item.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<inventory_list_item +  follows="top|right|left" +  height="20" +  name="inventory_item" +  tab_stop="false"  +  hover_image="ListItem_Over" +  selected_image="ListItem_Select" +  separator_image="Wearables_Divider"  +  width="380"> +  <!-- DEFAULT style for inventory list item --> +  <default_style +   font="SansSerifSmall" +   font.style="NORMAL" /> + +  <!-- style for inventory list item WORN on avatar --> +  <worn_style +   font="SansSerifSmall" +   font.style="BOLD" +   color="EmphasisColor" /> +  <item_icon +    height="16" +    follows="top|left" +    image_name="Inv_Object" +    layout="topleft" +    left="0" +    name="item_icon" +    top="0" +    width="16" /> +  <item_name +    follows="left|right" +    height="20" +    layout="topleft" +    left="21" +    parse_urls="false" +    use_ellipses="true" +    name="item_name" +    text_color="white" +    top="4" +    value="..." +    width="359" /> +    <add_btn +     name="add_wearable" +     layout="topleft" +     follows="top|right" +     image_unselected="Add_Icon" +     image_selected="Add_Icon" +     top="1" +     left="0" +     height="16" +     width="16" +     tab_stop="false" /> +    <remove_btn +     name="remove_wearable" +     layout="topleft" +     follows="top|right" +     image_unselected="Remove_Icon" +     image_selected="Remove_Icon" +     top="1" +     left="26" +     height="16" +     width="16" +     tab_stop="false" /> +</inventory_list_item> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 59eb18b734..6d68fd5453 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -518,7 +518,7 @@ class WindowsManifest(ViewerManifest):                  self.path("alut.dll")              # For textures -            self.path("openjpeg.dll") +            self.path("openjp2.dll")              # Uriparser              self.path("uriparser.dll") @@ -1501,7 +1501,7 @@ class Linux_i686_Manifest(LinuxManifest):              self.path("libdirectfb-1.*.so.*")              self.path("libfusion-1.*.so.*")              self.path("libdirect-1.*.so.*") -            self.path("libopenjpeg.so*") +            self.path("libopenjp2.so*")              self.path("libdirectfb-1.4.so.5")              self.path("libfusion-1.4.so.5")              self.path("libdirect-1.4.so.5*") | 
