diff options
| -rwxr-xr-x | indra/newview/app_settings/settings.xml | 26 | ||||
| -rw-r--r-- | indra/newview/lldrawpoolavatar.cpp | 135 | ||||
| -rw-r--r-- | indra/newview/llviewermenu.cpp | 59 | ||||
| -rwxr-xr-x | indra/newview/llvoavatar.cpp | 221 | ||||
| -rw-r--r-- | indra/newview/llvoavatar.h | 29 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 14 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_attachment_other.xml | 35 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_avatar_other.xml | 39 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_viewer.xml | 9 | 
9 files changed, 440 insertions, 127 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index d2c3c6089c..21c278fd3b 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9370,7 +9370,7 @@    <key>RenderAutoMuteRenderCostLimit</key>    <map>      <key>Comment</key> -    <string>Maximum render cost before an avatar is automatically visually muted (0 for no limit).</string> +    <string>Maximum render weight before an avatar is automatically visually muted (0 to not use this limit).</string>      <key>Persist</key>      <integer>1</integer>      <key>Type</key> @@ -9381,7 +9381,7 @@    <key>RenderAutoMuteSurfaceAreaLimit</key>    <map>      <key>Comment</key> -    <string>Maximum surface area of attachments before an avatar is automatically visually muted (0 for no limit).</string> +    <string>Maximum surface area of attachments before an avatar is automatically visually muted (0 to not use this limit).</string>      <key>Persist</key>      <integer>1</integer>      <key>Type</key> @@ -9389,6 +9389,28 @@      <key>Value</key>      <integer>0</integer>    </map> +  <key>RenderAutoMuteEnabled</key> +  <map> +    <key>Comment</key> +    <string>Apply visual muting to high cost, non-friends, not in IM, or somewhat distant avatars</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>0</integer> +  </map> +  <key>RenderAutoMuteVisibilityRank</key> +  <map> +    <key>Comment</key> +    <string>Number of avatars to show normally for visual muting mode.</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <integer>0</integer> +  </map>    <key>RenderAutoHideSurfaceAreaLimit</key>    <map> diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index d5afa25c9c..3d7407ab54 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1163,88 +1163,85 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)  	}  	else if (pass >= 3 && pass <= 9)  	{ //render rigged attachments -		if (!avatarp->isVisuallyMuted()) +		if (!avatarp->isVisuallyMuted())		// These details are skipped for visually muted (plain imposter) avatars  		{ -	if (pass == 3) -	{ -		if (is_deferred_render) -		{ -			renderDeferredRiggedSimple(avatarp); -		} -		else -		{ -			renderRiggedSimple(avatarp); -		} -	} +			if (pass == 3)				// To do - use switch statement +			{ +				if (is_deferred_render) +				{ +					renderDeferredRiggedSimple(avatarp); +				} +				else +				{ +					renderRiggedSimple(avatarp); +				} +			}  			else if (pass == 4) -	{ -		if (is_deferred_render) -		{ -			renderDeferredRiggedBump(avatarp); -		} -		else -		{ -			renderRiggedFullbright(avatarp); -		} -	} +			{ +				if (is_deferred_render) +				{ +					renderDeferredRiggedBump(avatarp); +				} +				else +				{ +					renderRiggedFullbright(avatarp); +				} +			}  			else if (pass == 5) -	{ -		renderRiggedShinySimple(avatarp); -	} +			{ +				renderRiggedShinySimple(avatarp); +			}  			else if (pass == 6) -	{ -		renderRiggedFullbrightShiny(avatarp); -	} -			else if (pass >= 7 && pass < 9) -	{ -		if (pass == 7) -		{ -			renderRiggedAlpha(avatarp); -		} -				else if (pass == 8) -		{ -			renderRiggedFullbrightAlpha(avatarp); -		} -	} +			{ +				renderRiggedFullbrightShiny(avatarp); +			} +			else if (pass == 7) +			{ +				renderRiggedAlpha(avatarp); +			} +			else if (pass == 8) +			{ +				renderRiggedFullbrightAlpha(avatarp); +			}  			else if (pass == 9) -	{ -		renderRiggedGlow(avatarp); -	} +			{ +				renderRiggedGlow(avatarp); +			}  		}  	}  	else  	{ -	if ((sShaderLevel >= SHADER_LEVEL_CLOTH)) -	{ -		LLMatrix4 rot_mat; -		LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat); -		LLMatrix4 cfr(OGL_TO_CFR_ROTATION); -		rot_mat *= cfr; +		if ((sShaderLevel >= SHADER_LEVEL_CLOTH)) +		{ +			LLMatrix4 rot_mat; +			LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat); +			LLMatrix4 cfr(OGL_TO_CFR_ROTATION); +			rot_mat *= cfr; -		LLVector4 wind; -		wind.setVec(avatarp->mWindVec); -		wind.mV[VW] = 0; -		wind = wind * rot_mat; -		wind.mV[VW] = avatarp->mWindVec.mV[VW]; - -		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV); -		F32 phase = -1.f * (avatarp->mRipplePhase); - -		F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f); -		LLVector4 sin_params(freq, freq, freq, phase); -		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV); - -		LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f); -		gravity = gravity * rot_mat; -		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV); -	} +			LLVector4 wind; +			wind.setVec(avatarp->mWindVec); +			wind.mV[VW] = 0; +			wind = wind * rot_mat; +			wind.mV[VW] = avatarp->mWindVec.mV[VW]; + +			sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV); +			F32 phase = -1.f * (avatarp->mRipplePhase); + +			F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f); +			LLVector4 sin_params(freq, freq, freq, phase); +			sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV); + +			LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f); +			gravity = gravity * rot_mat; +			sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV); +		} -	if( !single_avatar || (avatarp == single_avatar) ) -	{ -		avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); +		if( !single_avatar || (avatarp == single_avatar) ) +		{ +			avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); +		}  	}  } -}  void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)  { diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 4c99e65c99..aab4d93882 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2934,6 +2934,63 @@ bool enable_object_unmute()  	}  } + +// 0 = normal, 1 = always, 2 = never +class LLAvatarCheckImposterMode : public view_listener_t +{	 +	bool handleEvent(const LLSD& userdata) +	{ +		LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); +		if (!object) return false; + +		LLVOAvatar* avatar = find_avatar_from_object(object);  +		if (!avatar) return false; +		 +		U32 mode = userdata.asInteger(); +		switch (mode)  +		{ +			case 0: +				return (avatar->getVisualMuteSettings() == LLVOAvatar::VISUAL_MUTE_NOT_SET); +			case 1: +				return (avatar->getVisualMuteSettings() == LLVOAvatar::ALWAYS_VISUAL_MUTE); +			case 2: +				return (avatar->getVisualMuteSettings() == LLVOAvatar::NEVER_VISUAL_MUTE); +			default: +				return false; +		} +	}	// handleEvent() +}; + +// 0 = normal, 1 = always, 2 = never +class LLAvatarSetImposterMode : public view_listener_t +{ +	bool handleEvent(const LLSD& userdata) +	{ +		LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); +		if (!object) return false; + +		LLVOAvatar* avatar = find_avatar_from_object(object);  +		if (!avatar) return false; +		 +		U32 mode = userdata.asInteger(); +		switch (mode)  +		{ +			case 0: +				avatar->setVisualMuteSettings(LLVOAvatar::VISUAL_MUTE_NOT_SET); +				return true; +			case 1: +				avatar->setVisualMuteSettings(LLVOAvatar::VISUAL_MUTE_NOT_SET); +				return true; +			case 2: +				avatar->setVisualMuteSettings(LLVOAvatar::NEVER_VISUAL_MUTE); +				return true; +			default: +				return false; +		} +	}	// handleEvent() +}; + +  class LLObjectMute : public view_listener_t  {  	bool handleEvent(const LLSD& userdata) @@ -8644,6 +8701,8 @@ void initialize_menus()  	view_listener_t::addMenu( new LLCheckPanelPeopleTab(), "SideTray.CheckPanelPeopleTab");  	 // Avatar pie menu +	view_listener_t::addMenu(new LLAvatarCheckImposterMode(), "Avatar.CheckImposterMode"); +	view_listener_t::addMenu(new LLAvatarSetImposterMode(), "Avatar.SetImposterMode");  	view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute");  	view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend");  	view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact"); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 7d099d690a..cce4925e0a 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -62,6 +62,7 @@  #include "llhudmanager.h"  #include "llhudnametag.h"  #include "llhudtext.h"				// for mText/mDebugText +#include "llimview.h"  #include "llinitparam.h"  #include "llkeyframefallmotion.h"  #include "llkeyframestandmotion.h" @@ -784,6 +785,13 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	mLastPelvisToFoot = 0.0f;  	mPelvisFixup = 0.0f;  	mLastPelvisFixup = 0.0f; + +	mCachedVisualMute = !isSelf(); +	mCachedVisualMuteUpdateTime = LLFrameTimer::getTotalSeconds() + 5.0; +	mVisuallyMuteSetting = VISUAL_MUTE_NOT_SET; + +	F32 color_value = (F32) (getID().mData[0]); +	mMutedAVColor = calcMutedAVColor(color_value, 0, 256);  }  std::string LLVOAvatar::avString() const @@ -3435,24 +3443,82 @@ void LLVOAvatar::slamPosition()  	mRoot.updateWorldMatrixChildren();  } -bool LLVOAvatar::isVisuallyMuted() const +bool LLVOAvatar::isVisuallyMuted()  { -	bool ret = false; +	bool muted = false; + +	// Priority order (highest priority first) +	// * own avatar is never visually muted +	// * if on the "always draw normally" list, draw them normally +	// * if on the "always visually mute" list, mute them +	// * draw them normally if they meet the following criteria: +	//       - within the closest N avatars OR on friends list OR in an IM chat +	//       - AND aren't over the thresholds +	// * otherwise visually mute all other avatars  	if (!isSelf())  	{ +		static LLCachedControl<bool> render_mute_enabled(gSavedSettings, "RenderAutoMuteEnabled");  		static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");  		static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit");  		static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit"); -	 -		U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5)); +		static LLCachedControl<U32> visibility_rank(gSavedSettings, "RenderAutoMuteVisibilityRank"); + +		if (mVisuallyMuteSetting == ALWAYS_VISUAL_MUTE) +		{	// Always want to see this AV as an imposter +			muted = true; +		} +		else if (mVisuallyMuteSetting == NEVER_VISUAL_MUTE) +		{	// Never show as imposter +			muted = false; +		} +		else if (render_mute_enabled) +		{ +			F64 now = LLFrameTimer::getTotalSeconds(); + +			if (now < mCachedVisualMuteUpdateTime) +			{	// Use cached mute value +				muted = mCachedVisualMute; +			} +			else +			{	// Determine if visually muted or not + +				U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5)); -		ret = LLMuteList::getInstance()->isMuted(getID()) || -			(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) || -			(mVisualComplexity > max_cost && max_render_cost > 0); +				muted = LLMuteList::getInstance()->isMuted(getID()) || +					(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || +					(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) || +					(mVisualComplexity > max_cost && max_render_cost > 0); + +				// Could be part of the grand || collection above, but yanked out to make the logic visible +				if (!muted) +				{ +					if (visibility_rank > 0) +					{	// They are above the visibilty rank - mute them +						muted = (mVisibilityRank > visibility_rank); +					} +			 +					if (muted ||					// Don't mute friends or IMs +						visibility_rank == 0) +					{ +						muted = !(LLAvatarTracker::instance().isBuddy(getID())); +						if (muted) +						{	// Not a friend, so they are muted ... are they in an IM? +							LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL,getID()); +							muted = !gIMMgr->hasSession(session_id); +						} +					} +				} + +				// Save visual mute state and set interval for updating +				const F64 SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES = 1.5; +				mCachedVisualMuteUpdateTime = now + SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES;		 +				mCachedVisualMute = muted; +			}  +		}  	} -	return ret; +	return muted;  }  //------------------------------------------------------------------------ @@ -3509,7 +3575,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  	// the rest should only be done occasionally for far away avatars  	//-------------------------------------------------------------------- -	if (visible && (!isSelf() || isVisuallyMuted()) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter) +	bool visually_muted = isVisuallyMuted(); +	if (visible && (!isSelf() || visually_muted) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)  	{  		const LLVector4a* ext = mDrawable->getSpatialExtents();  		LLVector4a size; @@ -3518,8 +3585,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f); -		if (isVisuallyMuted()) -		{ // muted avatars update at 16 hz +		if (visually_muted) +		{ // visually muted avatars update at 16 hz  			mUpdatePeriod = 16;  		}  		else if (mVisibilityRank <= LLVOAvatar::sMaxVisible || @@ -4295,23 +4362,23 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)  		BOOL first_pass = TRUE;  		if (!LLDrawPoolAvatar::sSkipOpaque)  		{ -			bool muted = isVisuallyMuted(); +			bool visually_muted = isVisuallyMuted();  			if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)  			{ -				if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy || muted) +				if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy || visually_muted)  				{  					num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea, TRUE, mIsDummy);  					first_pass = FALSE;  				}  			} -			if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy || muted) +			if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy || visually_muted)  			{  				num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);  				first_pass = FALSE;  			} -			if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy || muted) +			if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy || visually_muted)  			{  				num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);  				first_pass = FALSE; @@ -8396,7 +8463,7 @@ void LLVOAvatar::updateImpostors()  	LLCharacter::sAllowInstancesChange = TRUE ;  } -BOOL LLVOAvatar::isImpostor() const +BOOL LLVOAvatar::isImpostor()  {  	return sUseImpostors && (isVisuallyMuted() || (mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE;  } @@ -8441,15 +8508,13 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d  	angle.mV[2] = da;  } +  void LLVOAvatar::idleUpdateRenderCost()  {  	static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit"); -	static const U32 ARC_BODY_PART_COST = 200;  	static const U32 ARC_LIMIT = 20000; -	static std::set<LLUUID> all_textures; -  	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES))  	{ //set debug text to attachment geometry bytes here so render cost will override  		setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea)); @@ -8460,6 +8525,69 @@ void LLVOAvatar::idleUpdateRenderCost()  		return;  	} +	calculateUpdateRenderCost();				// Update mVisualComplexity if needed +	 +	doRenderCostNagging(max_render_cost);		// Remind the user their AV is too complex + +	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) +	{ +		std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); +		setDebugText(llformat("%s %d", viz_string.c_str(), mVisualComplexity)); +		F32 green = 1.f-llclamp(((F32) mVisualComplexity-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f); +		F32 red = llmin((F32) mVisualComplexity/(F32)ARC_LIMIT, 1.f); +		mText->setColor(LLColor4(red,green,0,1)); +	} +} + + +// Remind the user about their expensive avatar +void LLVOAvatar::doRenderCostNagging(U32 max_render_cost) +{ +	if (isSelf()) +	{ +		static S32 sOldComplexity = 0; +		static F64 sLastRenderCostNagTime = 0.0; + +		const F64 RENDER_NAG_INTERVAL = 60.0; + +		F64 now = LLFrameTimer::getTotalSeconds(); +		if (sLastRenderCostNagTime > 0.0 && +			(now - sLastRenderCostNagTime) > RENDER_NAG_INTERVAL && +			sOldComplexity != mVisualComplexity) +		{ +			sOldComplexity = mVisualComplexity; + +			if (max_render_cost > 0) +			{ //pop up notification that you have exceeded a render cost limit +				if (mVisualComplexity > max_render_cost+max_render_cost/2) +				{ +					LLNotificationsUtil::add("ExceededHighDetailRenderCost"); +					sLastRenderCostNagTime = now; +				} +				else if (mVisualComplexity > max_render_cost) +				{ +					LLNotificationsUtil::add("ExceededMidDetailRenderCost"); +					sLastRenderCostNagTime = now; +				} +				else if (mVisualComplexity > max_render_cost/2) +				{ +					LLNotificationsUtil::add("ExceededLowDetailRenderCost"); +					sLastRenderCostNagTime = now; +				} +			} +		} +	} +} + + +// Calculations for mVisualComplexity value +void LLVOAvatar::calculateUpdateRenderCost() +{ +	static const U32 ARC_BODY_PART_COST = 200; + +	// Diagnostic list of all textures on our avatar +	static std::set<LLUUID> all_textures; +  	if (mVisualComplexityStale)  	{  		mVisualComplexityStale = FALSE; @@ -8526,8 +8654,6 @@ void LLVOAvatar::idleUpdateRenderCost()  		} - -  		// Diagnostic output to identify all avatar-related textures.  		// Does not affect rendering cost calculation.  		// Could be wrapped in a debug option if output becomes problematic. @@ -8568,34 +8694,37 @@ void LLVOAvatar::idleUpdateRenderCost()  			}  		} -		if (isSelf() && max_render_cost > 0 && mVisualComplexity != cost) -		{ //pop up notification that you have exceeded a render cost limit -			if (cost > max_render_cost+max_render_cost/2) -			{ -				LLNotificationsUtil::add("ExceededHighDetailRenderCost"); -			} -			else if (cost > max_render_cost) -			{ -				LLNotificationsUtil::add("ExceededMidDetailRenderCost"); -			} -			else if (cost > max_render_cost/2) -			{ -				LLNotificationsUtil::add("ExceededLowDetailRenderCost"); -			} -		} -  		mVisualComplexity = cost;  	} +} -	 -	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) -	{ -		std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); -		setDebugText(llformat("%s %d", viz_string.c_str(), mVisualComplexity)); -		F32 green = 1.f-llclamp(((F32) mVisualComplexity-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f); -		F32 red = llmin((F32) mVisualComplexity/(F32)ARC_LIMIT, 1.f); -		mText->setColor(LLColor4(red,green,0,1)); -	} + +// static +LLColor4 LLVOAvatar::calcMutedAVColor(F32 value, S32 range_low, S32 range_high) +{ +	F32 clamped_value = llmin(value, (F32) range_high); +	clamped_value = llmax(value, (F32) range_low); +	F32 spectrum = (clamped_value / range_high);		// spectrum is between 0 and 1.f + +	// Array of colors.  These are arranged so only one RGB color changes between each step,  +	// and it loops back to red so there is an even distribution.  It is not a heat map +	const S32 NUM_SPECTRUM_COLORS = 7;               +	static LLColor4 * spectrum_color[NUM_SPECTRUM_COLORS] = { &LLColor4::red, &LLColor4::magenta, &LLColor4::blue, &LLColor4::cyan, &LLColor4::green, &LLColor4::yellow, &LLColor4::red }; +  +	spectrum = spectrum * (NUM_SPECTRUM_COLORS - 1);		// Scale to range of number of colors +	S32 spectrum_index_1  = floor(spectrum);				// Desired color will be after this index +	S32 spectrum_index_2  = spectrum_index_1 + 1;			//    and before this index (inclusive) +	F32 fractBetween = spectrum - (F32)(spectrum_index_1);  // distance between the two indexes (0-1) +  +	LLColor4 new_color = lerp(*spectrum_color[spectrum_index_1], *spectrum_color[spectrum_index_2], fractBetween); +	//new_color.normalize(); + +	//llinfos << "From value " << std::setprecision(3) << value << " returning color " << new_color  +	//	<< " using indexes " << spectrum_index_1 << ", " << spectrum_index_2 +	//	<< " and fractBetween " << fractBetween +	//	<< llendl; + +	return new_color;  }  // static diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 386d9d7746..0e7bf7a6c9 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -253,7 +253,14 @@ public:  	static void		invalidateNameTags();  	void			addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font);  	void 			idleUpdateRenderCost(); +	void			doRenderCostNagging(U32 max_render_cost); +	void			calculateUpdateRenderCost();  	void			updateVisualComplexity() { mVisualComplexityStale = TRUE; } +	 +	S32				getVisualComplexity()		{ return mVisualComplexity;		}; +	S32				getUpdatePeriod()			{ return mUpdatePeriod;			}; +	const LLColor4 &  getMutedAVColor()			{ return mMutedAVColor;			}; +  	void 			idleUpdateBelowWater();  	//-------------------------------------------------------------------- @@ -304,11 +311,14 @@ public:  		return mPhases;  	} +	static LLColor4 calcMutedAVColor(F32 value, S32 range_low, S32 range_high); +  protected:  	BOOL			updateIsFullyLoaded();  	BOOL			processFullyLoadedChange(bool loading);  	void			updateRuthTimer(bool loading);  	F32 			calcMorphAmount(); +  private:  	BOOL			mFirstFullyVisible;  	BOOL			mFullyLoaded; @@ -317,6 +327,7 @@ private:  	S32				mFullyLoadedFrameCounter;  	S32				mVisualComplexity;  	BOOL			mVisualComplexityStale; +	LLColor4		mMutedAVColor;  	LLFrameTimer	mFullyLoadedTimer;  	LLFrameTimer	mRuthTimer; @@ -437,7 +448,16 @@ private:  public:  	U32 		renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); -	bool		isVisuallyMuted() const; +	bool		isVisuallyMuted(); + +	enum VisualMuteSettings +	{ +		VISUAL_MUTE_NOT_SET = 0, +		ALWAYS_VISUAL_MUTE  = 1, +		NEVER_VISUAL_MUTE   = 2 +	}; +	void		setVisualMuteSettings(VisualMuteSettings set)		{ mVisuallyMuteSetting = set;	}; +	VisualMuteSettings  getVisualMuteSettings()						{ return mVisuallyMuteSetting;	};  	U32 		renderRigid();  	U32 		renderSkinned(EAvatarRenderPass pass); @@ -461,6 +481,11 @@ private:  	S32	 		mUpdatePeriod;  	S32  		mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. +	bool		mCachedVisualMute;				// cached return value for isVisuallyMuted() +	F64			mCachedVisualMuteUpdateTime;	// Time to update mCachedVisualMute + +	VisualMuteSettings		mVisuallyMuteSetting;			// Always or never visually mute this AV +  	//--------------------------------------------------------------------  	// Morph masks  	//-------------------------------------------------------------------- @@ -493,7 +518,7 @@ private:  	// Impostors  	//--------------------------------------------------------------------  public: -	BOOL 		isImpostor() const; +	BOOL 		isImpostor();  	BOOL 	    needsImpostorUpdate() const;  	const LLVector3& getImpostorOffset() const;  	const LLVector2& getImpostorDim() const; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index df7a3c7593..61e42bbcee 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2862,7 +2862,7 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)  					llassert(vobj); // trying to catch a bad assumption  					if (vobj) // this test may not be needed, see above  					{ -						const LLVOAvatar* av = vobj->asAvatar(); +						LLVOAvatar* av = vobj->asAvatar();  						if (av && av->isImpostor())  						{  							return; @@ -10103,11 +10103,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  	assertInitialized(); -	bool muted = avatar->isVisuallyMuted();		 +	bool visually_muted = avatar->isVisuallyMuted();		  	pushRenderTypeMask(); -	if (muted) +	if (visually_muted)  	{  		andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);  	} @@ -10251,7 +10251,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  	F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha; -	if (muted) +	if (visually_muted)  	{ //disable alpha masking for muted avatars (get whole skin silhouette)  		LLDrawPoolAvatar::sMinimumAlpha = 0.f;  	} @@ -10282,7 +10282,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  		LLGLDisable blend(GL_BLEND); -		if (muted) +		if (visually_muted)  		{  			gGL.setColorMask(true, true); @@ -10317,8 +10317,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  			gGL.diffuseColor4ub(64,64,64,255);  		}  		else -		{ //blue visually muted avatar -			gGL.diffuseColor4ub(72,61,139,255); +		{	// Visually muted avatar +			gGL.diffuseColor4fv( avatar->getMutedAVColor().mV );  		}  		{ diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml index 00d4b1dab1..87fa7c3f00 100644 --- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml @@ -104,8 +104,43 @@           <menu_item_call.on_enable            function="Object.EnableInspect" />     </menu_item_call> + +   <menu_item_separator /> +     +      <menu_item_check +        name="Normal" +        label="Normal"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="0" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="0" /> +      </menu_item_check> +      <menu_item_check +        name="Always use imposter" +        label="Always use imposter"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="1" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="1" /> +      </menu_item_check> +      <menu_item_check +        name="Never use imposter" +        label="Never use imposter"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="2" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="2" /> +      </menu_item_check> +    <menu_item_separator         layout="topleft" /> +    <menu_item_call       enabled="false"       label="Mute Particle Owner" diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml index 73fa086f28..60b7e3e77c 100644 --- a/indra/newview/skins/default/xui/en/menu_avatar_other.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml @@ -39,8 +39,10 @@        <menu_item_call.on_click           function="Avatar.InviteToGroup" />        </menu_item_call> +         <menu_item_separator /> -    <menu_item_call +    +     <menu_item_call       enabled="false"       label="Block"       name="Avatar Mute"> @@ -95,8 +97,43 @@          <menu_item_call.on_enable           function="EnablePayAvatar" />      </menu_item_call> + +   <menu_item_separator /> +     +      <menu_item_check +        name="Normal" +        label="Normal"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="0" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="0" /> +      </menu_item_check> +      <menu_item_check +        name="Always use imposter" +        label="Always use imposter"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="1" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="1" /> +      </menu_item_check> +      <menu_item_check +        name="Never use imposter" +        label="Never use imposter"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="2" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="2" /> +      </menu_item_check> +    <menu_item_separator         layout="topleft" /> +    <menu_item_call       enabled="false"       label="Mute Particle Owner" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 544f06ac0c..4646d307aa 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -543,6 +543,15 @@              <menu_item_check.on_check                 control="NavBarShowParcelProperties" />            </menu_item_check> +          <menu_item_check +             label="Simple Imposters" +             name="RenderAutoMuteEnabled"> +            <menu_item_check.on_check +               control="RenderAutoMuteEnabled" /> +            <menu_item_check.on_click +               function="ToggleControl" +               parameter="RenderAutoMuteEnabled" /> +          </menu_item_check>            <menu_item_separator />            <menu_item_check               label="Advanced Menu"  | 
