diff options
| -rw-r--r-- | indra/llui/llmultislider.cpp | 125 | ||||
| -rw-r--r-- | indra/llui/llmultislider.h | 10 | ||||
| -rw-r--r-- | indra/llui/llmultisliderctrl.cpp | 12 | ||||
| -rw-r--r-- | indra/llui/llmultisliderctrl.h | 13 | ||||
| -rw-r--r-- | indra/newview/llenvironment.cpp | 31 | ||||
| -rw-r--r-- | indra/newview/llfloatereditextdaycycle.cpp | 28 | ||||
| -rw-r--r-- | indra/newview/llfloaterland.cpp | 72 | ||||
| -rw-r--r-- | indra/newview/llfloaterregioninfo.cpp | 22 | ||||
| -rw-r--r-- | indra/newview/llinventorybridge.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/llpanelenvironment.cpp | 89 | ||||
| -rw-r--r-- | indra/newview/llpanelenvironment.h | 32 | ||||
| -rw-r--r-- | indra/newview/llviewerparcelmgr.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml | 1 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/floater_fixedenvironment.xml | 1 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/menu_viewer.xml | 4 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_region_environment.xml | 36 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/strings.xml | 6 | 
17 files changed, 338 insertions, 149 deletions
diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index b5e3032626..c35b7c5496 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -61,9 +61,11 @@ LLMultiSlider::Params::Params()  	use_triangle("use_triangle", false),  	track_color("track_color"),  	thumb_disabled_color("thumb_disabled_color"), +	thumb_highlight_color("thumb_highlight_color"),  	thumb_outline_color("thumb_outline_color"),  	thumb_center_color("thumb_center_color"),  	thumb_center_selected_color("thumb_center_selected_color"), +	thumb_image("thumb_image"),  	triangle_color("triangle_color"),  	mouse_down_callback("mouse_down_callback"),  	mouse_up_callback("mouse_up_callback"), @@ -133,6 +135,12 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)  			addSlider(it->value);  		}  	} + +	if (p.thumb_image.isProvided()) +	{ +		mThumbImagep = LLUI::getUIImage(p.thumb_image()); +	} +	mThumbHighlightColor = p.thumb_highlight_color.isProvided() ? p.thumb_highlight_color() : static_cast<LLUIColor>(gFocusMgr.getFocusColor());  }  LLMultiSlider::~LLMultiSlider() @@ -169,13 +177,15 @@ void LLMultiSlider::setSliderValue(const std::string& name, F32 value, BOOL from  		// increment is our distance between points, use to eliminate round error  		F32 threshold = mOverlapThreshold + (mIncrement / 4);  		// If loop overlap is enabled, check if we overlap with points 'after' max value (project to lower) -		F32 loop_up_check = (mLoopOverlap && (value + threshold) > mMaxValue) ? (value + threshold - mMaxValue + mMinValue) : 0.0f; +		F32 loop_up_check = (mLoopOverlap && (value + threshold) > mMaxValue) ? (value + threshold - mMaxValue + mMinValue) : mMinValue - 1.0f;  		// If loop overlap is enabled, check if we overlap with points 'before' min value (project to upper) -		F32 loop_down_check = (mLoopOverlap && (value - threshold) < mMinValue) ? (value - threshold - mMinValue + mMaxValue) : 0.0f; +		F32 loop_down_check = (mLoopOverlap && (value - threshold) < mMinValue) ? (value - threshold - mMinValue + mMaxValue) : mMaxValue + 1.0f; -		for(;mIt != mValue.endMap(); mIt++) { -			 -			F32 testVal = (F32)mIt->second.asReal() - newValue; +		for(;mIt != mValue.endMap(); mIt++) +		{ +			F32 locationVal = (F32)mIt->second.asReal(); +			// Check nearby values +			F32 testVal = locationVal - newValue;  			if (testVal > -threshold  				&& testVal < threshold  				&& mIt->first != name) @@ -183,17 +193,19 @@ void LLMultiSlider::setSliderValue(const std::string& name, F32 value, BOOL from  				hit = true;  				break;  			} -			if (loop_up_check != 0 -				&& testVal < loop_up_check) +			if (mLoopOverlap)  			{ -				hit = true; -				break; -			} -			if (loop_down_check != 0 -				&& testVal > loop_down_check) -			{ -				hit = true; -				break; +				// Check edge overlap values +				if (locationVal < loop_up_check) +				{ +					hit = true; +					break; +				} +				if (locationVal > loop_down_check) +				{ +					hit = true; +					break; +				}  			}  		} @@ -644,7 +656,7 @@ void LLMultiSlider::draw()  				mTriangleColor.get() % opacity, TRUE);  		}  	} -	else if (!thumb_imagep) +	else if (!thumb_imagep && !mThumbImagep)  	{  		// draw all the thumbs  		curSldrIt = mThumbRects.end(); @@ -674,15 +686,33 @@ void LLMultiSlider::draw()  			gl_rect_2d(mDragStartThumbRect, mThumbCenterColor.get() % opacity, FALSE);  		}  	} -	else if( gFocusMgr.getMouseCapture() == this ) +	else  	{ -		// draw drag start -		thumb_imagep->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f); +		LLMouseHandler* capture = gFocusMgr.getMouseCapture(); +		if (capture == this) +		{ +			// draw drag start (ghost) +			if (mThumbImagep) +			{ +				mThumbImagep->draw(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f); +			} +			else +			{ +				thumb_imagep->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f); +			} +		}  		// draw the highlight  		if (hasFocus() && !mCurSlider.empty())  		{ -			thumb_imagep->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth()); +			if (mThumbImagep) +			{ +				mThumbImagep->drawBorder(mThumbRects[mCurSlider], mThumbHighlightColor, gFocusMgr.getFocusFlashWidth()); +			} +			else +			{ +				thumb_imagep->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth()); +			}  		}  		// draw the thumbs @@ -699,44 +729,35 @@ void LLMultiSlider::draw()  			}  			// the draw command -			thumb_imagep->drawSolid(mIt->second, curThumbColor); +			if (mThumbImagep) +			{ +				mThumbImagep->draw(mIt->second); +			} +			else if (capture == this) +			{ +				thumb_imagep->drawSolid(mIt->second, curThumbColor); +			} +			else +			{ +				thumb_imagep->drawSolid(mIt->second, curThumbColor % opacity); +			}  		}  		// draw cur slider last  		if(curSldrIt != mThumbRects.end())   		{ -			thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get()); -		} -		 -	} -	else -	{  -		// draw highlight -		if (hasFocus() && !mCurSlider.empty()) -		{ -			thumb_imagep->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth()); -		} - -		// draw thumbs -		curSldrIt = mThumbRects.end(); -		for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++)  -		{ -			 -			// choose the color -			curThumbColor = mThumbCenterColor.get(); -			if(mIt->first == mCurSlider)  +			if (mThumbImagep)  			{ -				curSldrIt = mIt; -				continue; -				//curThumbColor = mThumbCenterSelectedColor; -			}				 -			 -			thumb_imagep->drawSolid(mIt->second, curThumbColor % opacity); -		} - -		if(curSldrIt != mThumbRects.end())  -		{ -			thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity); +				mThumbImagep->draw(curSldrIt->second); +			} +			else if (capture == this) +			{ +				thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get()); +			} +			else +			{ +				thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity); +			}  		}  	} diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h index 3884b0a2a0..52c6d1ddef 100644 --- a/indra/llui/llmultislider.h +++ b/indra/llui/llmultislider.h @@ -55,12 +55,14 @@ public:  		Optional<LLUIColor>	track_color,  							thumb_disabled_color, +							thumb_highlight_color,  							thumb_outline_color,  							thumb_center_color,  							thumb_center_selected_color,  							triangle_color; -		Optional<std::string>	orientation; +		Optional<std::string>	orientation, +								thumb_image;  		Optional<CommitCallbackParam>	mouse_down_callback,  										mouse_up_callback; @@ -105,6 +107,10 @@ public:  	/*virtual*/ BOOL	handleKeyHere(KEY key, MASK mask);  	/*virtual*/ void	draw(); +	S32				getMaxNumSliders() { return mMaxNumSliders; } +	S32				getCurNumSliders() { return mValue.size(); } +	bool			canAddSliders() { return mValue.size() < mMaxNumSliders; } +  protected:  	LLSD			mValue;  	std::string		mCurSlider; @@ -125,10 +131,12 @@ protected:  					mThumbRects;  	LLUIColor		mTrackColor;  	LLUIColor		mThumbOutlineColor; +	LLUIColor		mThumbHighlightColor;  	LLUIColor		mThumbCenterColor;  	LLUIColor		mThumbCenterSelectedColor;  	LLUIColor		mDisabledThumbColor;  	LLUIColor		mTriangleColor; +	LLUIImagePtr	mThumbImagep; //blimps on the slider, for now no 'disabled' support  	const EOrientation	mOrientation; diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index 73792206a6..972567ef9b 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -55,6 +55,9 @@ LLMultiSliderCtrl::Params::Params()  	allow_overlap("allow_overlap", false),  	loop_overlap("loop_overlap", false),  	orientation("orientation"), +	thumb_image("thumb_image"), +	thumb_width("thumb_width"), +	thumb_highlight_color("thumb_highlight_color"),  	overlap_threshold("overlap_threshold", 0),  	draw_track("draw_track", true),  	use_triangle("use_triangle", false), @@ -171,11 +174,18 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)  	params.max_sliders(p.max_sliders);  	params.allow_overlap(p.allow_overlap);  	params.loop_overlap(p.loop_overlap); -	params.orientation(p.orientation());  	if (p.overlap_threshold.isProvided())  	{  		params.overlap_threshold = p.overlap_threshold;  	} +	params.orientation(p.orientation); +	params.thumb_image(p.thumb_image); +	params.thumb_highlight_color(p.thumb_highlight_color); +	if (p.thumb_width.isProvided()) +	{ +		// otherwise should be provided by template +		params.thumb_width(p.thumb_width); +	}  	params.draw_track(p.draw_track);  	params.use_triangle(p.use_triangle);  	params.control_name(p.control_name); diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h index a1593c28e0..c370ebf505 100644 --- a/indra/llui/llmultisliderctrl.h +++ b/indra/llui/llmultisliderctrl.h @@ -51,19 +51,22 @@ public:  								text_width;  		Optional<bool>			show_text,  								can_edit_text; -		Optional<S32>			decimal_digits; +		Optional<S32>			decimal_digits, +								thumb_width;  		Optional<S32>			max_sliders;	  		Optional<bool>			allow_overlap,  								loop_overlap,  								draw_track,  								use_triangle; -		Optional<std::string>	orientation; +		Optional<std::string>	orientation, +								thumb_image;  		Optional<F32>			overlap_threshold;  		Optional<LLUIColor>		text_color, -								text_disabled_color; +								text_disabled_color, +								thumb_highlight_color;  		Optional<CommitCallbackParam>	mouse_down_callback,  										mouse_up_callback; @@ -115,6 +118,10 @@ public:  	F32				getMinValue() const { return mMultiSlider->getMinValue(); }  	F32				getMaxValue() const { return mMultiSlider->getMaxValue(); } +	S32				getMaxNumSliders() { return mMultiSlider->getMaxNumSliders(); } +	S32				getCurNumSliders() { return mMultiSlider->getCurNumSliders(); } +	bool			canAddSliders() { return mMultiSlider->canAddSliders(); } +  	void			setLabel(const std::string& label)				{ if (mLabelBox) mLabelBox->setText(label); }  	void			setLabelColor(const LLColor4& c)			{ mTextEnabledColor = c; }  	void			setDisabledLabelColor(const LLColor4& c)	{ mTextDisabledColor = c; } diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 4b60ed4e68..3b1990c850 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -1166,18 +1166,18 @@ void LLEnvironment::coroRequestEnvironment(S32 parcel_id, LLEnvironment::environ      LLSD result = httpAdapter->getAndSuspend(httpRequest, url);      // results that come back may contain the new settings -    LLSD notify; +//     LLSD notify;      LLSD httpResults = result["http_result"];      LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);      if (!status)      { -        LL_WARNS("WindlightCaps") << "Couldn't retrieve Windlight settings for " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL; +        LL_WARNS("WindlightCaps") << "Couldn't retrieve environment settings for " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL; -        std::stringstream msg; -        msg << status.toString() << " (Code " << status.toTerseString() << ")"; -        notify = LLSD::emptyMap(); -        notify["FAIL_REASON"] = msg.str(); +//         std::stringstream msg; +//         msg << status.toString() << " (Code " << status.toTerseString() << ")"; +//         notify = LLSD::emptyMap(); +//         notify["FAIL_REASON"] = msg.str();      }      else @@ -1190,11 +1190,11 @@ void LLEnvironment::coroRequestEnvironment(S32 parcel_id, LLEnvironment::environ          }      } -    if (!notify.isUndefined()) -    { -        LLNotificationsUtil::add("WLRegionApplyFail", notify); -        //LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false); -    } +//     if (!notify.isUndefined()) +//     { +//         LLNotificationsUtil::add("WLRegionApplyFail", notify); +//         //LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false); +//     }  }  void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, LLSettingsDay::ptr_t pday, LLUUID settings_asset, S32 day_length, S32 day_offset, LLEnvironment::environment_apply_fn apply) @@ -1818,7 +1818,14 @@ LLSettingsBase::BlendFactor LLTrackBlenderLoopingManual::setPosition(const LLSet      F64 spanPos = ((mPosition < (*bounds.first).first) ? (mPosition + 1.0) : mPosition) - (*bounds.first).first; -    F64 blendf = fmod(spanPos, spanLength) / spanLength; +    if (spanPos > spanLength) +    { +        // we are clamping position to 0-1 and spanLength is 1 +        // so don't account for case of spanPos == spanLength +        spanPos = fmod(spanPos, spanLength); +    } + +    F64 blendf = spanPos / spanLength;      return LLSettingsBlender::setBlendFactor(blendf);  } diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp index ad797c686a..5bf34455bb 100644 --- a/indra/newview/llfloatereditextdaycycle.cpp +++ b/indra/newview/llfloatereditextdaycycle.cpp @@ -277,6 +277,11 @@ void LLFloaterEditExtDayCycle::onOpen(const LLSD& key)      }      else      { +        mInventoryItem = nullptr; +        mInventoryId.setNull(); +        mCanCopy = true; +        mCanMod = true; +        mMakeNoTrans = false;          setEditDefaultDayCycle();      } @@ -551,6 +556,12 @@ void LLFloaterEditExtDayCycle::onAddTrack()          LL_WARNS("ENVDAYEDIT") << "Attempt to add new frame too close to existing frame." << LL_ENDL;          return;      } +    if (!mFramesSlider->canAddSliders()) +    { +        // Shouldn't happen, button should be disabled +        LL_WARNS("ENVDAYEDIT") << "Attempt to add new frame when slider is full." << LL_ENDL; +        return; +    }      if (mCurrentTrack == LLSettingsDay::TRACK_WATER)      { @@ -903,7 +914,7 @@ void LLFloaterEditExtDayCycle::updateButtons()      //bool can_add = static_cast<bool>(settings);      //mAddFrameButton->setEnabled(can_add);      //mDeleteFrameButton->setEnabled(!can_add); -    mAddFrameButton->setEnabled(true && mCanMod); +    mAddFrameButton->setEnabled(mCanMod && mFramesSlider->canAddSliders());      mDeleteFrameButton->setEnabled(isRemovingFrameAllowed() && mCanMod);  } @@ -964,13 +975,16 @@ void LLFloaterEditExtDayCycle::addSliderFrame(const F32 frame, LLSettingsBase::p      // multi slider distinguishes elements by key/name in string format      // store names to map to be able to recall dependencies      std::string new_slider = mFramesSlider->addSlider(frame); -    mSliderKeyMap[new_slider] = FrameData(frame, setting); - -    if (update_ui) +    if (!new_slider.empty())      { -        mLastFrameSlider = new_slider; -        mTimeSlider->setCurSliderValue(frame); -        updateTabs(); +        mSliderKeyMap[new_slider] = FrameData(frame, setting); + +        if (update_ui) +        { +            mLastFrameSlider = new_slider; +            mTimeSlider->setCurSliderValue(frame); +            updateTabs(); +        }      }  } diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index a2886d5010..38ced18edf 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -155,10 +155,15 @@ public:      virtual LLParcel *  getParcel() override;      virtual bool        canEdit() override; +    virtual S32         getParcelId() override;  +  protected: +    virtual void        refreshFromSource() override; -    LLSafeHandle<LLParcelSelection>&	mParcel; +    bool                isSameRegion(); +    LLSafeHandle<LLParcelSelection> &   mParcel; +    S32                 mLastParcelId;  }; @@ -3248,9 +3253,10 @@ void LLPanelLandExperiences::refresh()  //========================================================================= -LLPanelLandEnvironment::LLPanelLandEnvironment(LLSafeHandle<LLParcelSelection>& parcelp): +LLPanelLandEnvironment::LLPanelLandEnvironment(LLParcelSelectionHandle& parcel) :      LLPanelEnvironmentInfo(), -    mParcel(parcelp) +    mParcel(parcel), +    mLastParcelId(INVALID_PARCEL_ID)  {  } @@ -3270,25 +3276,64 @@ void LLPanelLandEnvironment::refresh()      if (gDisconnected)          return; -    LLParcel *parcel = getParcel(); -    if (!parcel) +    if (!isSameRegion())      { -        LL_INFOS("ENVPANEL") << "No parcel selected." << LL_ENDL; +        setCrossRegion(true);          mCurrentEnvironment.reset(); -        mCurrentParcelId = INVALID_PARCEL_ID; +        mLastParcelId = INVALID_PARCEL_ID;          setControlsEnabled(false);          return;      } -    if (LLEnvironment::instance().isExtendedEnvironmentEnabled() && ((!mCurrentEnvironment) || (mCurrentEnvironment->mParcelId != parcel->getLocalID()))) +    if (mLastParcelId != getParcelId()) +    { +        mCurrentEnvironment.reset(); +    } + +    if (!mCurrentEnvironment)      { -        mCurrentParcelId = parcel->getLocalID();          refreshFromSource();          return;      }      LLPanelEnvironmentInfo::refresh(); +    getChild<LLUICtrl>(PNL_ENVIRONMENT_ALTITUDES)->setVisible(FALSE); +} + +void LLPanelLandEnvironment::refreshFromSource() +{ +    LLParcel *parcel = getParcel(); + +    if (!parcel) +    { +        setNoSelection(true); +        setControlsEnabled(false); +        return; +    } +    setNoSelection(false); +    if (isSameRegion()) +    { +        setCrossRegion(false); + +        LLEnvironment::instance().requestParcel(parcel->getLocalID(), +            [this](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { mLastParcelId = parcel_id; onEnvironmentReceived(parcel_id, envifo); }); +    } +    else +    { +        setCrossRegion(true); +        mCurrentEnvironment.reset(); +        mLastParcelId = INVALID_PARCEL_ID; +        setControlsEnabled(false); +    } +} + + +bool LLPanelLandEnvironment::isSameRegion() +{ +    LLViewerRegion* regionp = LLViewerParcelMgr::instance().getSelectionRegion(); + +    return (!regionp || (regionp->getRegionID() == gAgent.getRegion()->getRegionID()));  }  LLParcel *LLPanelLandEnvironment::getParcel() @@ -3304,3 +3349,12 @@ bool LLPanelLandEnvironment::canEdit()          return false;      return LLEnvironment::instance().canAgentUpdateParcelEnvironment(parcel);  } + +S32 LLPanelLandEnvironment::getParcelId()  +{ +    LLParcel *parcel = getParcel(); +    if (!parcel) +        return INVALID_PARCEL_ID; + +    return parcel->getLocalID(); +} diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index d13190254f..6aa35b40b6 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -192,11 +192,14 @@ public:      virtual BOOL        postBuild() override; +    virtual S32         getParcelId() override { return INVALID_PARCEL_ID; } +  protected:      static const U32    DIRTY_FLAG_OVERRIDE;      virtual void        doApply() override; +    virtual void        refreshFromSource() override;      bool                doUpdateEstate(const LLSD& notification, const LLSD& response); @@ -3418,6 +3421,19 @@ void LLPanelRegionEnvironment::refresh()  bool LLPanelRegionEnvironment::refreshFromRegion(LLViewerRegion* region)  { +    if (!region) +    { +        setNoSelection(true); +        setControlsEnabled(false); +    } +    setNoSelection(false); + +    if (gAgent.getRegion()->getRegionID() != region->getRegionID()) +    { +        setCrossRegion(true); +    } +    setCrossRegion(false); +              refreshFromSource();      return true;  } @@ -3429,6 +3445,12 @@ void LLPanelRegionEnvironment::refreshFromEstate()      mAllowOverride = estate_info.getAllowEnvironmentOverride();  } +void LLPanelRegionEnvironment::refreshFromSource() +{ +    LLEnvironment::instance().requestRegion( +        [this](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) {onEnvironmentReceived(parcel_id, envifo); }); +} +  void LLPanelRegionEnvironment::doApply()  {      LLPanelEnvironmentInfo::doApply(); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index e50055feb2..8d084f3ece 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3940,6 +3940,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items  		disabled_items.push_back(std::string("New Folder"));  		disabled_items.push_back(std::string("New Script"));  		disabled_items.push_back(std::string("New Note")); +		disabled_items.push_back(std::string("New Settings"));  		disabled_items.push_back(std::string("New Gesture"));  		disabled_items.push_back(std::string("New Clothes"));  		disabled_items.push_back(std::string("New Body Parts")); diff --git a/indra/newview/llpanelenvironment.cpp b/indra/newview/llpanelenvironment.cpp index 41d7d8b54f..8d7ec48d63 100644 --- a/indra/newview/llpanelenvironment.cpp +++ b/indra/newview/llpanelenvironment.cpp @@ -46,6 +46,7 @@  #include "llappviewer.h"  #include "llcallbacklist.h" +#include "llviewerparcelmgr.h"  //=========================================================================  namespace  @@ -72,11 +73,15 @@ const std::string LLPanelEnvironmentInfo::PNL_SETTINGS("pnl_environment_config")  const std::string LLPanelEnvironmentInfo::PNL_ENVIRONMENT_ALTITUDES("pnl_environment_altitudes");  const std::string LLPanelEnvironmentInfo::PNL_BUTTONS("pnl_environment_buttons");  const std::string LLPanelEnvironmentInfo::PNL_DISABLED("pnl_environment_disabled"); +const std::string LLPanelEnvironmentInfo::TXT_DISABLED("txt_environment_disabled");  const std::string LLPanelEnvironmentInfo::STR_LABEL_USEDEFAULT("str_label_use_default");  const std::string LLPanelEnvironmentInfo::STR_LABEL_USEREGION("str_label_use_region");  const std::string LLPanelEnvironmentInfo::STR_LABEL_UNKNOWNINV("str_unknow_inventory");  const std::string LLPanelEnvironmentInfo::STR_ALTITUDE_DESCRIPTION("str_altitude_desription"); +const std::string LLPanelEnvironmentInfo::STR_NO_PARCEL("str_no_parcel"); +const std::string LLPanelEnvironmentInfo::STR_CROSS_REGION("str_cross_region"); +const std::string LLPanelEnvironmentInfo::STR_LEGACY("str_legacy");  const U32 LLPanelEnvironmentInfo::DIRTY_FLAG_DAYCYCLE(0x01 << 0);  const U32 LLPanelEnvironmentInfo::DIRTY_FLAG_DAYLENGTH(0x01 << 1); @@ -111,8 +116,9 @@ const std::string alt_labels[] = {  //=========================================================================  LLPanelEnvironmentInfo::LLPanelEnvironmentInfo():       mCurrentEnvironment(), -    mCurrentParcelId(INVALID_PARCEL_ID),      mDirtyFlag(0), +    mCrossRegion(false), +    mNoSelection(false),      mSettingsFloater(),      mEditFloater()  { @@ -173,7 +179,8 @@ void LLPanelEnvironmentInfo::refresh()      if (gDisconnected)          return; -    setControlsEnabled(canEdit()); +    if (!setControlsEnabled(canEdit())) +        return;      if (!mCurrentEnvironment)      { @@ -235,12 +242,6 @@ void LLPanelEnvironmentInfo::refresh()  } -void LLPanelEnvironmentInfo::refreshFromSource() -{ -    LLEnvironment::instance().requestParcel(mCurrentParcelId,  -        [this](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) {onEnvironmentReceived(parcel_id, envifo); }); -} -  std::string LLPanelEnvironmentInfo::getInventoryNameForAssetId(LLUUID asset_id)   {      LLFloaterSettingsPicker *picker = getSettingsPicker(); @@ -270,7 +271,7 @@ LLFloaterSettingsPicker * LLPanelEnvironmentInfo::getSettingsPicker(bool create)          mSettingsFloater = picker->getHandle(); -        picker->setCommitCallback([this](LLUICtrl *, const LLSD &data){ onPickerCommited(data.asUUID()); }); +        picker->setCommitCallback([this](LLUICtrl *, const LLSD &data){ onPickerCommitted(data.asUUID()); });      }      return picker; @@ -284,7 +285,7 @@ LLFloaterEditExtDayCycle * LLPanelEnvironmentInfo::getEditFloater(bool create)      // Show the dialog      if (!editor && create)      { -        LLSD params(LLSDMap(LLFloaterEditExtDayCycle::KEY_EDIT_CONTEXT, (mCurrentParcelId == INVALID_PARCEL_ID) ? LLFloaterEditExtDayCycle::CONTEXT_REGION : LLFloaterEditExtDayCycle::CONTEXT_PARCEL) +        LLSD params(LLSDMap(LLFloaterEditExtDayCycle::KEY_EDIT_CONTEXT, isRegion() ? LLFloaterEditExtDayCycle::CONTEXT_REGION : LLFloaterEditExtDayCycle::CONTEXT_PARCEL)              (LLFloaterEditExtDayCycle::KEY_DAY_LENGTH, mCurrentEnvironment ? (S32)(mCurrentEnvironment->mDayLength.value()) : FOURHOURS));          editor = (LLFloaterEditExtDayCycle *)LLFloaterReg::getInstance(FLOATER_DAY_CYCLE_EDIT, params); @@ -295,7 +296,7 @@ LLFloaterEditExtDayCycle * LLPanelEnvironmentInfo::getEditFloater(bool create)      }      if (editor && !mCommitConnection.connected()) -        mCommitConnection = editor->setEditCommitSignal([this](LLSettingsDay::ptr_t pday) { onEditCommited(pday); }); +        mCommitConnection = editor->setEditCommitSignal([this](LLSettingsDay::ptr_t pday) { onEditCommitted(pday); });      return editor;  } @@ -324,12 +325,42 @@ void LLPanelEnvironmentInfo::updateEditFloater(const LLEnvironment::EnvironmentI      }  } -void LLPanelEnvironmentInfo::setControlsEnabled(bool enabled) +bool LLPanelEnvironmentInfo::setControlsEnabled(bool enabled)  { -    S32 rdo_selection = getChild<LLRadioGroup>(RDG_ENVIRONMENT_SELECT)->getSelectedIndex(); +    bool is_unavailable(false);      bool is_legacy = (mCurrentEnvironment) ? mCurrentEnvironment->mIsLegacy : true; -    bool is_unavailable = (is_legacy && (!mCurrentEnvironment || (mCurrentEnvironment->mParcelId != INVALID_PARCEL_ID))); +    if (!LLEnvironment::instance().isExtendedEnvironmentEnabled() && !isRegion()) +    { +        is_unavailable = true; +        getChild<LLTextBox>(TXT_DISABLED)->setText(getString(STR_LEGACY)); +    } +    else if (mNoSelection) +    { +        is_unavailable = true; +        getChild<LLTextBox>(TXT_DISABLED)->setText(getString(STR_NO_PARCEL)); +    } +    else if (mCrossRegion) +    { +        is_unavailable = true; +        getChild<LLTextBox>(TXT_DISABLED)->setText(getString(STR_CROSS_REGION)); +    } + +    if (is_unavailable) +    { +        getChild<LLUICtrl>(PNL_SETTINGS)->setVisible(false); +        getChild<LLUICtrl>(PNL_BUTTONS)->setVisible(false); +        getChild<LLUICtrl>(PNL_DISABLED)->setVisible(true); + +        updateEditFloater(mCurrentEnvironment); + +        return false; +    } +    getChild<LLUICtrl>(PNL_SETTINGS)->setVisible(true); +    getChild<LLUICtrl>(PNL_BUTTONS)->setVisible(true); +    getChild<LLUICtrl>(PNL_DISABLED)->setVisible(false); + +    S32 rdo_selection = getChild<LLRadioGroup>(RDG_ENVIRONMENT_SELECT)->getSelectedIndex();      getChild<LLUICtrl>(RDG_ENVIRONMENT_SELECT)->setEnabled(enabled);      getChild<LLUICtrl>(RDO_USEDEFAULT)->setEnabled(enabled && !is_legacy); @@ -340,15 +371,11 @@ void LLPanelEnvironmentInfo::setControlsEnabled(bool enabled)      getChild<LLUICtrl>(BTN_EDIT)->setEnabled(enabled);      getChild<LLUICtrl>(SLD_DAYLENGTH)->setEnabled(enabled && (rdo_selection != 0) && !is_legacy);      getChild<LLUICtrl>(SLD_DAYOFFSET)->setEnabled(enabled && (rdo_selection != 0) && !is_legacy); -    getChild<LLUICtrl>(CHK_ALLOWOVERRIDE)->setEnabled(enabled && (mCurrentParcelId == INVALID_PARCEL_ID) && !is_legacy); +    getChild<LLUICtrl>(CHK_ALLOWOVERRIDE)->setEnabled(enabled && isRegion() && !is_legacy);      getChild<LLUICtrl>(BTN_APPLY)->setEnabled(enabled && (mDirtyFlag != 0));      getChild<LLUICtrl>(BTN_CANCEL)->setEnabled(enabled && (mDirtyFlag != 0)); -    getChild<LLUICtrl>(PNL_SETTINGS)->setVisible(!is_unavailable); -    getChild<LLUICtrl>(PNL_BUTTONS)->setVisible(!is_unavailable); -    getChild<LLUICtrl>(PNL_DISABLED)->setVisible(is_unavailable); - -    updateEditFloater(mCurrentEnvironment); +    return true;  }  void LLPanelEnvironmentInfo::setApplyProgress(bool started) @@ -389,7 +416,7 @@ void LLPanelEnvironmentInfo::updateAltLabel(const std::string &alt_name, U32 sky      LLRect sld_rect = sld->getRect();      U32 sld_range = sld_rect.getHeight();      U32 sld_bottom = sld_rect.mBottom; -    U32 sld_offset = 8 + 1; // Default slider-thumb width plus stretch. Placeholder until images are implemented. +    U32 sld_offset = sld_rect.getWidth(); // Roughly identical to thumb's width in slider.      U32 pos = (sld_range - sld_offset) * ((alt_value - 100) / (4000 - 100));      // get related text box @@ -399,7 +426,7 @@ void LLPanelEnvironmentInfo::updateAltLabel(const std::string &alt_name, U32 sky          // move related text box          LLRect rect = text->getRect();          U32 height = rect.getHeight(); -        rect.mBottom = sld_bottom + sld_offset + pos - (height / 2); +        rect.mBottom = sld_bottom + (sld_offset / 2 + 1) + pos - (height / 2);          rect.mTop = rect.mBottom + height;          text->setRect(rect); @@ -517,7 +544,7 @@ void LLPanelEnvironmentInfo::onBtnEdit()      LLFloaterEditExtDayCycle *dayeditor = getEditFloater(); -    LLSD params(LLSDMap(LLFloaterEditExtDayCycle::KEY_EDIT_CONTEXT, (mCurrentParcelId == INVALID_PARCEL_ID) ? LLFloaterEditExtDayCycle::VALUE_CONTEXT_REGION : LLFloaterEditExtDayCycle::VALUE_CONTEXT_REGION) +    LLSD params(LLSDMap(LLFloaterEditExtDayCycle::KEY_EDIT_CONTEXT, isRegion() ? LLFloaterEditExtDayCycle::VALUE_CONTEXT_REGION : LLFloaterEditExtDayCycle::VALUE_CONTEXT_REGION)              (LLFloaterEditExtDayCycle::KEY_DAY_LENGTH,  mCurrentEnvironment ? (S32)(mCurrentEnvironment->mDayLength.value()) : FOURHOURS)              (LLFloaterEditExtDayCycle::KEY_CANMOD,      LLSD::Boolean(true))); @@ -543,24 +570,26 @@ void LLPanelEnvironmentInfo::onBtnSelect()  void LLPanelEnvironmentInfo::doApply()  { +    S32 parcel_id = getParcelId(); +      if (getIsDirtyFlag(DIRTY_FLAG_MASK))      {          S32 rdo_selection = getChild<LLRadioGroup>(RDG_ENVIRONMENT_SELECT)->getSelectedIndex();          if (rdo_selection == 0)          { -            LLEnvironment::instance().resetParcel(mCurrentParcelId, +            LLEnvironment::instance().resetParcel(parcel_id,                  [this](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) {onEnvironmentReceived(parcel_id, envifo); });          }          else if (rdo_selection == 1)          { -            LLEnvironment::instance().updateParcel(mCurrentParcelId,  +            LLEnvironment::instance().updateParcel(parcel_id,                  mCurrentEnvironment->mDayCycle->getAssetId(), mCurrentEnvironment->mDayLength.value(), mCurrentEnvironment->mDayOffset.value(),                  [this](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) {onEnvironmentReceived(parcel_id, envifo); });          }          else          { -            LLEnvironment::instance().updateParcel(mCurrentParcelId,  +            LLEnvironment::instance().updateParcel(parcel_id,                  mCurrentEnvironment->mDayCycle, mCurrentEnvironment->mDayLength.value(), mCurrentEnvironment->mDayOffset.value(),                   [this](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) {onEnvironmentReceived(parcel_id, envifo); });          } @@ -615,7 +644,7 @@ void LLPanelEnvironmentInfo::onIdlePlay(void *data)      ((LLPanelEnvironmentInfo *)data)->udpateApparentTimeOfDay();  } -void LLPanelEnvironmentInfo::onPickerCommited(LLUUID asset_id) +void LLPanelEnvironmentInfo::onPickerCommitted(LLUUID asset_id)  {      LLSettingsVOBase::getSettingsAsset(asset_id, [this](LLUUID, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) {           if (status) @@ -624,7 +653,7 @@ void LLPanelEnvironmentInfo::onPickerCommited(LLUUID asset_id)      });  } -void LLPanelEnvironmentInfo::onEditCommited(LLSettingsDay::ptr_t newday) +void LLPanelEnvironmentInfo::onEditCommitted(LLSettingsDay::ptr_t newday)  {      if (!newday)      { @@ -657,9 +686,9 @@ void LLPanelEnvironmentInfo::onPickerAssetDownloaded(LLSettingsBase::ptr_t setti  void LLPanelEnvironmentInfo::onEnvironmentReceived(S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo)  {   -    if (parcel_id != mCurrentParcelId) +    if (parcel_id != getParcelId())      { -        LL_WARNS("ENVPANEL") << "Have environment for parcel " << parcel_id << " expecting " << mCurrentParcelId << ". Discarding." << LL_ENDL; +        LL_WARNS("ENVPANEL") << "Have environment for parcel " << parcel_id << " expecting " << getParcelId() << ". Discarding." << LL_ENDL;          return;      }      mCurrentEnvironment = envifo; diff --git a/indra/newview/llpanelenvironment.h b/indra/newview/llpanelenvironment.h index bd3db34332..fdf0fe46a7 100644 --- a/indra/newview/llpanelenvironment.h +++ b/indra/newview/llpanelenvironment.h @@ -52,12 +52,10 @@ public:      virtual void                refresh() override; -    S32                         getCurrentParcelId() const          { return mCurrentParcelId; } -    void                        setCurrentParcelId(S32 parcel_id)   { mCurrentParcelId = parcel_id; } -      virtual bool                isRegion() const = 0;      virtual LLParcel *          getParcel() = 0;      virtual bool                canEdit() = 0; +    virtual S32                 getParcelId() = 0;  protected:      LOG_CLASS(LLPanelEnvironmentInfo); @@ -80,12 +78,15 @@ protected:      static const std::string    PNL_ENVIRONMENT_ALTITUDES;      static const std::string    PNL_BUTTONS;      static const std::string    PNL_DISABLED; - +    static const std::string    TXT_DISABLED;      static const std::string    STR_LABEL_USEDEFAULT;      static const std::string    STR_LABEL_USEREGION;      static const std::string    STR_LABEL_UNKNOWNINV;      static const std::string    STR_ALTITUDE_DESCRIPTION; +    static const std::string    STR_NO_PARCEL; +    static const std::string    STR_CROSS_REGION; +    static const std::string    STR_LEGACY;      static const U32            DIRTY_FLAG_DAYCYCLE;      static const U32            DIRTY_FLAG_DAYLENGTH; @@ -94,7 +95,7 @@ protected:      static const U32            DIRTY_FLAG_MASK; -    void                        setControlsEnabled(bool enabled); +    bool setControlsEnabled(bool enabled);      void                        setApplyProgress(bool started);      void                        setDirtyFlag(U32 flag);      void                        clearDirtyFlag(U32 flag); @@ -116,12 +117,12 @@ protected:      void                        udpateApparentTimeOfDay(); -    void                        onPickerCommited(LLUUID asset_id); -    void                        onEditCommited(LLSettingsDay::ptr_t newday); +    void                        onPickerCommitted(LLUUID asset_id); +    void                        onEditCommitted(LLSettingsDay::ptr_t newday);      void                        onPickerAssetDownloaded(LLSettingsBase::ptr_t settings);      void                        onEnvironmentReceived(S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo); -    void                        refreshFromSource(); +    virtual void                refreshFromSource() = 0;      std::string                 getInventoryNameForAssetId(LLUUID asset_id); @@ -129,8 +130,10 @@ protected:      LLFloaterEditExtDayCycle *  getEditFloater(bool create = true);      void                        updateEditFloater(const LLEnvironment::EnvironmentInfo::ptr_t &nextenv); +    void                        setCrossRegion(bool val) { mCrossRegion = val; } +    void                        setNoSelection(bool val) { mNoSelection = val; } +      LLEnvironment::EnvironmentInfo::ptr_t   mCurrentEnvironment; -    S32                                     mCurrentParcelId;      class AltitudeData      { @@ -156,9 +159,12 @@ private:      typedef boost::signals2::connection connection_t; -    connection_t                mCommitConnection; -    LLHandle<LLFloater>         mSettingsFloater; -    LLHandle<LLFloater>         mEditFloater; -    S32                         mDirtyFlag; +    connection_t                    mCommitConnection; +    LLHandle<LLFloater>             mSettingsFloater; +    LLHandle<LLFloater>             mEditFloater; +    S32                             mDirtyFlag; +    bool                            mCrossRegion; +    bool                            mNoSelection; +  };  #endif // LL_LLPANELEXPERIENCES_H diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index d263e15a10..5a393220c3 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -659,6 +659,10 @@ LLParcel * LLViewerParcelMgr::getAgentOrSelectedParcel() const          if (selection)          {              parcel = selection->getParcel(); +            if (parcel && (parcel->getLocalID() == INVALID_PARCEL_ID)) +            { +                parcel = NULL; +            }          }      } diff --git a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml index aec71fda07..0c4d342297 100644 --- a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml +++ b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml @@ -55,6 +55,7 @@                      left_pad="10"                      max_length_bytes="100"                      name="day_cycle_name" +                    prevalidate_callback="ascii"                      top="5"                      width="200"                      height="21" /> diff --git a/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml index 9b572ce9b0..7cf7e8bb32 100644 --- a/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml +++ b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml @@ -43,6 +43,7 @@                      left_delta="45"                      width="250"                      name="settings_name" +                    prevalidate_callback="ascii"                      max_length_chars="32"                      height="20"/>              <button diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b6bc271cf1..8af754ffec 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -698,8 +698,8 @@                   parameter="midnight" />              </menu_item_check>              <menu_item_check -             label="Use Region Settings" -             name="Use Region Settings"> +             label="Use Shared Environment" +             name="Use Shared Environment">                  <menu_item_check.on_click                   function="World.EnvSettings"                   parameter="region" /> diff --git a/indra/newview/skins/default/xui/en/panel_region_environment.xml b/indra/newview/skins/default/xui/en/panel_region_environment.xml index 8229dcb91d..3ce0d7a2ef 100644 --- a/indra/newview/skins/default/xui/en/panel_region_environment.xml +++ b/indra/newview/skins/default/xui/en/panel_region_environment.xml @@ -13,7 +13,9 @@      <string name="str_label_use_region">Use Region Settings</string>      <string name="str_unknow_inventory">Unknown</string>      <string name="str_altitude_desription">Sky [INDEX]([ALTITUDE]m)</string> - +    <string name="str_no_parcel">No parcel is selected. Environmental settings are disabled.</string> +    <string name="str_cross_region">Environmental settings are not available across region boundries.</string> +    <string name="str_legacy">Environmental settings are not available on this region.</string>      <layout_stack               width="530"              height="367" @@ -26,13 +28,12 @@                  name="pnl_environment_disabled"                  visible="false">              <text follows="top|left|bottom|right" -                            font="SansSerif"                              halign="center"                              valign="top" -                            top_pad="20" +                            top_pad="40" +                            name="txt_environment_disabled"                              text_color="white"> -No Parcel parcel is selected. Environmental  -settings are disabled. +            ...              </text>          </layout_panel>          <layout_panel  @@ -237,8 +238,8 @@ settings are disabled.                  <multi_slider                      decimal_digits="0"                      follows="bottom" -                    height="120" -                    width="10" +                    height="123" +                    width="17"                      orientation="vertical"                      increment="10"                      initial_value="100" @@ -248,22 +249,25 @@ settings are disabled.                      top="20"                      max_sliders="20"                      name="sld_altitudes" -                    show_text="false"> +                    show_text="false" +                    thumb_image="Inv_SettingsSky" +                    thumb_width="17" +                    thumb_highlight_color="white">                      <slider name="sld1" value="200"/>                      <slider name="sld2" value="400"/>                      <slider name="sld3" value="600"/>                  </multi_slider>                  <icon                      follows="left|top" -                    height="10" -                    width="10" -                    image_name="Rounded_Square" +                    height="17" +                    width="17" +                    image_name="Inv_SettingsSky"                      layout="topleft" -                    name="camera_icon" +                    name="icon_ground"                      mouse_opaque="false"                      visible="true"                      left_delta="0" -                    top_pad="-3"/> +                    top_pad="-9"/>                  <text                          type="string"                          length="1" @@ -282,7 +286,7 @@ settings are disabled.                          follows="left"                          height="12"                          layout="topleft" -                        left="25" +                        left="35"                          top="30"                          width="200"                          name="alt1"> @@ -294,7 +298,7 @@ settings are disabled.                          follows="left|top"                          height="12"                          layout="topleft" -                        left="25" +                        left="35"                          top="40"                          width="200"                          name="alt2"> @@ -306,7 +310,7 @@ settings are disabled.                          follows="left|top"                          height="12"                          layout="topleft" -                        left="25" +                        left="35"                          top="50"                          width="200"                          name="alt3"> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 3a882a73d3..76d040150d 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -404,9 +404,9 @@ http://secondlife.com/support for help fixing this problem.  	<string name="simstate">simstate</string>  	<string name="favorite">favorite</string>  	<string name="symbolic link">link</string> -	<string name="symbolic folder link">folder link</string> -  <string name="mesh">mesh</string> -  <string name="settings">settings</string> +    <string name="settings blob">settings</string> +    <string name="symbolic folder link">folder link</string> +    <string name="mesh">mesh</string>  	<!-- llvoavatar. Displayed in the avatar chat bubble -->  	<string name="AvatarEditingAppearance">(Editing Appearance)</string>  | 
