diff options
160 files changed, 7284 insertions, 8562 deletions
diff --git a/BuildParams b/BuildParams index cff51a286b..e17ca925ef 100644 --- a/BuildParams +++ b/BuildParams @@ -112,6 +112,18 @@ viewer-mesh.login_channel = "Project Viewer - Mesh"  viewer-mesh.viewer_grid = aditi  viewer-mesh.email = shining@lists.lindenlab.com +# ======================================== +# viewer-chui +# +# ======================================== + +viewer-chui.viewer_channel = "Project Viewer - CHUI" +viewer-chui.login_channel = "Project Viewer - CHUI" +viewer-chui.viewer_grid = agni +viewer-chui.build_debug_release_separately = true +viewer-chui.build_CYGWIN_Debug = false +viewer-chui.build_viewer_update_version_manager = false +  # ================  # oz  # ================ diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 34d841a4e0..11f582372e 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -43,7 +43,7 @@   * semantics: one instance per process, rather than one instance per module as   * sometimes happens with data simply declared static.   */ -class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable +class LL_COMMON_API LLInstanceTrackerBase  {  protected:  	/// Get a process-unique void* pointer slot for the specified type_info @@ -209,6 +209,9 @@ protected:  	virtual const KEY& getKey() const { return mInstanceKey; }  private: +	LLInstanceTracker( const LLInstanceTracker& ); +	const LLInstanceTracker& operator=( const LLInstanceTracker& ); +  	void add_(KEY key)   	{   		mInstanceKey = key;  diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h index 8eb5d53f3f..32ae15435a 100644 --- a/indra/llcommon/llrefcount.h +++ b/indra/llcommon/llrefcount.h @@ -27,6 +27,7 @@  #define LLREFCOUNT_H  #include <boost/noncopyable.hpp> +#include <boost/intrusive_ptr.hpp>  #define LL_REF_COUNT_DEBUG 0  #if LL_REF_COUNT_DEBUG @@ -86,4 +87,22 @@ private:  #endif  }; +/** + * intrusive pointer support + * this allows you to use boost::intrusive_ptr with any LLRefCount-derived type + */ +namespace boost +{ +	inline void intrusive_ptr_add_ref(LLRefCount* p) +	{ +		p->ref(); +	} + +	inline void intrusive_ptr_release(LLRefCount* p) +	{ +		p->unref(); +	} +}; + +  #endif diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index b52e70ab2e..cf39696b4f 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -30,6 +30,7 @@  #include "llapp.h"  #include "llapr.h"  #include "apr_thread_cond.h" +#include "boost/intrusive_ptr.hpp"  class LLThread;  class LLMutex; @@ -266,6 +267,22 @@ private:  	S32	mRef;   }; +/** + * intrusive pointer support for LLThreadSafeRefCount + * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type + */ +namespace boost +{ +	inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p)  +	{ +		p->ref(); +	} + +	inline void intrusive_ptr_release(LLThreadSafeRefCount* p)  +	{ +		p->unref();  +	} +};  //============================================================================  // Simple responder for self destructing callbacks diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 8ca1e685a9..a1c902d562 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1406,7 +1406,6 @@ void LLFloater::setHost(LLMultiFloater* host)  		mButtonScale = 1.f;  		//mButtonsEnabled[BUTTON_TEAR_OFF] = FALSE;  	} -	updateTitleButtons();  	if (host)  	{  		mHostHandle = host->getHandle(); @@ -1416,6 +1415,8 @@ void LLFloater::setHost(LLMultiFloater* host)  	{  		mHostHandle.markDead();  	} +     +	updateTitleButtons();  }  void LLFloater::moveResizeHandlesToFront() @@ -1682,6 +1683,7 @@ void LLFloater::onClickTearOff(LLFloater* self)  		self->setTornOff(false);  	}  	self->updateTitleButtons(); +    self->setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE);  }  // static diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 64d6dcea04..17402b8d63 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -324,6 +324,8 @@ public:  	virtual void    setDocked(bool docked, bool pop_on_undock = true);  	virtual void    setTornOff(bool torn_off) { mTornOff = torn_off; } +	bool getTornOff() {return mTornOff;} +	void setOpenPositioning(LLFloaterEnums::EOpenPositioning pos) {mPositioning = pos;}  	// Return a closeable floater, if any, given the current focus.  	static LLFloater* getClosableFloaterFromFocus();  diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 648cd5fdce..883331c792 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -179,6 +179,8 @@ public:  	F32 getVisibleAmount() const;  	S32 getVisibleDim() const; +	bool isCollapsed() const { return mCollapsed;} +  	void setOrientation(LLLayoutStack::ELayoutOrientation orientation);  	void storeOriginalDim(); diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp index 6ac38f5ad4..1ede5b706f 100644 --- a/indra/llui/llloadingindicator.cpp +++ b/indra/llui/llloadingindicator.cpp @@ -52,7 +52,7 @@ LLLoadingIndicator::LLLoadingIndicator(const Params& p)  void LLLoadingIndicator::initFromParams(const Params& p)  { -	BOOST_FOREACH(LLUIImage* image, p.images.image) +	BOOST_FOREACH(LLUIImage* image, p.images().image)  	{  		mImages.push_back(image);  	} diff --git a/indra/llui/llloadingindicator.h b/indra/llui/llloadingindicator.h index c1f979c111..ffcb329f42 100644 --- a/indra/llui/llloadingindicator.h +++ b/indra/llui/llloadingindicator.h @@ -51,7 +51,7 @@ class LLLoadingIndicator  	LOG_CLASS(LLLoadingIndicator);  public: -	struct Images : public LLInitParam::BatchBlock<Images> +	struct Images : public LLInitParam::Block<Images>  	{  		Multiple<LLUIImage*>	image; @@ -62,8 +62,8 @@ public:  	struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>  	{ -		Optional<F32>			images_per_sec; -		Optional<Images>		images; +		Optional<F32>				images_per_sec; +		Optional<Atomic<Images> >	images;  		Params()  		:	images_per_sec("images_per_sec", 1.0f), diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index 50d59f79f4..746ade4648 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -44,33 +44,27 @@ void LLMenuButton::MenuPositions::declareValues()  LLMenuButton::Params::Params()  :	menu_filename("menu_filename"), -	position("position", MP_BOTTOM_LEFT) +	position("menu_position", MP_BOTTOM_LEFT)  { +	addSynonym(position, "position");  }  LLMenuButton::LLMenuButton(const LLMenuButton::Params& p)  :	LLButton(p),  	mIsMenuShown(false), -	mMenuPosition(p.position) +	mMenuPosition(p.position), +	mOwnMenu(false)  {  	std::string menu_filename = p.menu_filename; -	if (!menu_filename.empty()) -	{ -		LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); -		if (!menu) -		{ -			llwarns << "Error loading menu_button menu" << llendl; -			return; -		} - -		menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2)); - -		mMenuHandle = menu->getHandle(); +	setMenu(menu_filename, mMenuPosition); +	updateMenuOrigin(); +} -		updateMenuOrigin(); -	} +LLMenuButton::~LLMenuButton() +{ +	cleanup();  }  boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_signal_t::slot_type& cb ) @@ -80,9 +74,7 @@ boost::signals2::connection LLMenuButton::setMouseDownCallback( const mouse_sign  void LLMenuButton::hideMenu()  { -	if(mMenuHandle.isDead()) return; - -	LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); +	LLToggleableMenu* menu = getMenu();  	if (menu)  	{  		menu->setVisible(FALSE); @@ -94,19 +86,39 @@ LLToggleableMenu* LLMenuButton::getMenu()  	return dynamic_cast<LLToggleableMenu*>(mMenuHandle.get());  } -void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/) +void LLMenuButton::setMenu(const std::string& menu_filename, EMenuPosition position /*MP_TOP_LEFT*/) +{ +	if (menu_filename.empty()) +	{ +		return; +	} + +	LLToggleableMenu* menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>(menu_filename, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); +	if (!menu) +	{ +		llwarns << "Error loading menu_button menu" << llendl; +		return; +	} + +	setMenu(menu, position, true); +} + +void LLMenuButton::setMenu(LLToggleableMenu* menu, EMenuPosition position /*MP_TOP_LEFT*/, bool take_ownership /*false*/)  {  	if (!menu) return; +	cleanup(); // destroy the previous memnu if we own it +  	mMenuHandle = menu->getHandle();  	mMenuPosition = position; +	mOwnMenu = take_ownership;  	menu->setVisibilityChangeCallback(boost::bind(&LLMenuButton::onMenuVisibilityChange, this, _2));  }  BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )  { -	if (mMenuHandle.isDead()) return FALSE; +	if (!getMenu()) return FALSE;  	if( KEY_RETURN == key && mask == MASK_NONE && !gKeyboard->getKeyRepeated(key))  	{ @@ -118,7 +130,7 @@ BOOL LLMenuButton::handleKeyHere(KEY key, MASK mask )  		return TRUE;  	} -	LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); +	LLToggleableMenu* menu = getMenu();  	if (menu && menu->getVisible() && key == KEY_ESCAPE && mask == MASK_NONE)  	{  		menu->setVisible(FALSE); @@ -139,9 +151,12 @@ BOOL LLMenuButton::handleMouseDown(S32 x, S32 y, MASK mask)  void LLMenuButton::toggleMenu()  { -	if(mMenuHandle.isDead()) return; +	if (mValidateSignal && !(*mValidateSignal)(this, LLSD())) +	{ +		return; +	} -	LLToggleableMenu* menu = dynamic_cast<LLToggleableMenu*>(mMenuHandle.get()); +	LLToggleableMenu* menu = getMenu();  	if (!menu) return;  	// Store the button rectangle to toggle menu visibility if a mouse event @@ -170,7 +185,8 @@ void LLMenuButton::toggleMenu()  void LLMenuButton::updateMenuOrigin()  { -	if (mMenuHandle.isDead()) return; +	LLToggleableMenu* menu = getMenu(); +	if (!menu) return;  	LLRect rect = getRect(); @@ -179,12 +195,12 @@ void LLMenuButton::updateMenuOrigin()  		case MP_TOP_LEFT:  		{  			mX = rect.mLeft; -			mY = rect.mTop + mMenuHandle.get()->getRect().getHeight(); +			mY = rect.mTop + menu->getRect().getHeight();  			break;  		}  		case MP_TOP_RIGHT:  		{ -			const LLRect& menu_rect = mMenuHandle.get()->getRect(); +			const LLRect& menu_rect = menu->getRect();  			mX = rect.mRight - menu_rect.getWidth();  			mY = rect.mTop + menu_rect.getHeight();  			break; @@ -211,3 +227,11 @@ void LLMenuButton::onMenuVisibilityChange(const LLSD& param)  		mIsMenuShown = false;  	}  } + +void LLMenuButton::cleanup() +{ +	if (mMenuHandle.get() && mOwnMenu) +	{ +		mMenuHandle.get()->die(); +	} +} diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index e2396e7fb2..67ec1983b3 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -34,6 +34,8 @@ class LLToggleableMenu;  class LLMenuButton  : public LLButton  { +	LOG_CLASS(LLMenuButton); +  public:  	typedef enum e_menu_position  	{ @@ -53,7 +55,7 @@ public:  	{  		// filename for it's toggleable menu  		Optional<std::string>	menu_filename; -		Optional<EMenuPosition>	position; +		Optional<EMenuPosition, MenuPositions>	position;  		Params();  	}; @@ -68,13 +70,15 @@ public:  	void hideMenu();  	LLToggleableMenu* getMenu(); -	void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT); +	void setMenu(const std::string& menu_filename, EMenuPosition position = MP_TOP_LEFT); +	void setMenu(LLToggleableMenu* menu, EMenuPosition position = MP_TOP_LEFT, bool take_ownership = false);  	void setMenuPosition(EMenuPosition position) { mMenuPosition = position; }  protected:  	friend class LLUICtrlFactory;  	LLMenuButton(const Params&); +	~LLMenuButton();  	void toggleMenu();  	void updateMenuOrigin(); @@ -82,11 +86,14 @@ protected:  	void onMenuVisibilityChange(const LLSD& param);  private: +	void cleanup(); +  	LLHandle<LLView>		mMenuHandle;  	bool					mIsMenuShown;  	EMenuPosition			mMenuPosition;  	S32						mX;  	S32						mY; +	bool					mOwnMenu; // true if we manage the menu lifetime  }; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index ff6928ffda..32e5cdd556 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -4021,11 +4021,6 @@ BOOL LLContextMenu::handleRightMouseUp( S32 x, S32 y, MASK mask )  	return result;  } -void LLContextMenu::draw() -{ -	LLMenuGL::draw(); -} -  BOOL LLContextMenu::appendContextSubMenu(LLContextMenu *menu)  { diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 36f3ba34b9..c6ee5434b0 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -668,8 +668,6 @@ public:  	// can't set visibility directly, must call show or hide  	virtual void	setVisible			(BOOL visible); -	virtual void	draw				(); -	  	virtual void	show				(S32 x, S32 y);  	virtual void	hide				(); diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index f3a48835b1..540ac74aee 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -468,23 +468,12 @@ BOOL LLMultiFloater::postBuild()  void LLMultiFloater::updateResizeLimits()  { -	static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); -	const LLFloater::Params& default_params = LLFloater::getDefaultParams(); -	S32 floater_header_size = default_params.header_height; -	S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size;  	// initialize minimum size constraint to the original xml values.  	S32 new_min_width = mOrigMinWidth;  	S32 new_min_height = mOrigMinHeight; -	// possibly increase minimum size constraint due to children's minimums. -	for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) -	{ -		LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx); -		if (floaterp) -		{ -			new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2); -			new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height); -		} -	} + +	computeResizeLimits(new_min_width, new_min_height); +  	setResizeLimits(new_min_width, new_min_height);  	S32 cur_height = getRect().getHeight(); @@ -510,3 +499,22 @@ void LLMultiFloater::updateResizeLimits()  		gFloaterView->adjustToFitScreen(this, TRUE);  	}  } + +void LLMultiFloater::computeResizeLimits(S32& new_min_width, S32& new_min_height) +{ +	static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0); +	const LLFloater::Params& default_params = LLFloater::getDefaultParams(); +	S32 floater_header_size = default_params.header_height; +	S32 tabcntr_header_height = LLPANEL_BORDER_WIDTH + tabcntr_close_btn_size; + +	// possibly increase minimum size constraint due to children's minimums. +	for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +	{ +		LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx); +		if (floaterp) +		{ +			new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2); +			new_min_height = llmax(new_min_height, floaterp->getMinHeight() + floater_header_size + tabcntr_header_height); +		} +	} +} diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index 9fa917eca1..f299ae5dd3 100644 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -93,6 +93,9 @@ protected:  	LLTabContainer::TabPosition mTabPos;  	BOOL				mAutoResize;  	S32					mOrigMinWidth, mOrigMinHeight;  // logically const but initialized late + +private: +	virtual void computeResizeLimits(S32& new_min_width, S32& new_min_height);  };  #endif  // LL_MULTI_FLOATER_H diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 8aa548b974..487a2e5fe7 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -60,7 +60,8 @@ void NotificationPriorityValues::declareValues()  }  LLNotificationForm::FormElementBase::FormElementBase() -:	name("name") +:	name("name"), +	enabled("enabled", true)  {}  LLNotificationForm::FormIgnore::FormIgnore() @@ -104,39 +105,7 @@ LLNotificationForm::Params::Params()  	form_elements("")  {} -// Local channel for persistent notifications -// Stores only persistent notifications. -// Class users can use connectChanged() to process persistent notifications -// (see LLNotificationStorage for example). -class LLPersistentNotificationChannel : public LLNotificationChannel -{ -	LOG_CLASS(LLPersistentNotificationChannel); -public: -	LLPersistentNotificationChannel() : -		LLNotificationChannel("Persistent", "Visible", ¬ificationFilter, LLNotificationComparators::orderByUUID()) -	{ -	} - -private: -	// The channel gets all persistent notifications except those that have been canceled -	static bool notificationFilter(LLNotificationPtr pNotification) -	{ -		bool handle_notification = false; - -		handle_notification = pNotification->isPersistent() -			&& !pNotification->isCancelled(); - -		return handle_notification; -	} - -	void onDelete(LLNotificationPtr pNotification) -	{ -		// we want to keep deleted notifications in our log, otherwise some  -		// notifications will be lost on exit. -		mItems.insert(pNotification); -	} -};  bool filterIgnoredNotifications(LLNotificationPtr notification)  { @@ -210,6 +179,14 @@ LLNotificationForm::LLNotificationForm()  {  } +LLNotificationForm::LLNotificationForm( const LLNotificationForm& other ) +{ +	mFormData 	   = other.mFormData; +	mIgnore 	   = other.mIgnore; +	mIgnoreMsg 	   = other.mIgnoreMsg; +	mIgnoreSetting = other.mIgnoreSetting; +	mInvertSetting = other.mInvertSetting; +}  LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotificationForm::Params& p)   :	mIgnore(IGNORE_NO), @@ -246,7 +223,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica  	LLParamSDParser parser;  	parser.writeSD(mFormData, p.form_elements); -	if (!mFormData.isArray()) +	if (!mFormData.isArray() && !mFormData.isUndefined())  	{  		// change existing contents to a one element array  		LLSD new_llsd_array = LLSD::emptyArray(); @@ -300,7 +277,7 @@ LLSD LLNotificationForm::getElement(const std::string& element_name)  } -bool LLNotificationForm::hasElement(const std::string& element_name) +bool LLNotificationForm::hasElement(const std::string& element_name) const  {  	for (LLSD::array_const_iterator it = mFormData.beginArray();  		it != mFormData.endArray(); @@ -311,7 +288,36 @@ bool LLNotificationForm::hasElement(const std::string& element_name)  	return false;  } -void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value) +bool LLNotificationForm::getElementEnabled(const std::string& element_name) const +{ +	for (LLSD::array_const_iterator it = mFormData.beginArray(); +		it != mFormData.endArray(); +		++it) +	{ +		if ((*it)["name"].asString() == element_name) +		{ +			return (*it)["enabled"].asBoolean(); +		} +	} + +	return false; +} + +void LLNotificationForm::setElementEnabled(const std::string& element_name, bool enabled) +{ +	for (LLSD::array_iterator it = mFormData.beginArray(); +		it != mFormData.endArray(); +		++it) +	{ +		if ((*it)["name"].asString() == element_name) +		{ +			(*it)["enabled"] = enabled; +		} +	} +} + + +void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value, bool enabled)  {  	LLSD element;  	element["type"] = type; @@ -319,6 +325,7 @@ void LLNotificationForm::addElement(const std::string& type, const std::string&  	element["text"] = name;  	element["value"] = value;  	element["index"] = mFormData.size(); +	element["enabled"] = enabled;  	mFormData.append(element);  } @@ -407,9 +414,13 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par  	mURLOption(p.url.option),  	mURLTarget(p.url.target),  	mUnique(p.unique.isProvided()), +	mCombineBehavior(p.unique.combine),  	mPriority(p.priority),  	mPersist(p.persist), -	mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()) +	mDefaultFunctor(p.functor.isProvided() ? p.functor() : p.name()), +	mLogToChat(p.log_to_chat), +	mLogToIM(p.log_to_im), +	mShowToast(p.show_toast)  {  	if (p.sound.isProvided()  		&& LLUI::sSettingGroups["config"]->controlExists(p.sound)) @@ -459,18 +470,18 @@ LLNotificationVisibilityRule::LLNotificationVisibilityRule(const LLNotificationV  	}  } -LLNotification::LLNotification(const LLNotification::Params& p) :  +LLNotification::LLNotification(const LLSDParamAdapter<Params>& p) :   	mTimestamp(p.time_stamp),   	mSubstitutions(p.substitutions),  	mPayload(p.payload), -	mExpiresAt(0), +	mExpiresAt(p.expiry),  	mTemporaryResponder(false),  	mRespondedTo(false),  	mPriority(p.priority),  	mCancelled(false),  	mIgnored(false),  	mResponderObj(NULL), -	mIsReusable(false) +	mId(p.id.isProvided() ? p.id : LLUUID::generateNewID())  {  	if (p.functor.name.isChosen())  	{ @@ -493,52 +504,32 @@ LLNotification::LLNotification(const LLNotification::Params& p) :  		mResponderObj = p.responder;  	} -	mId.generate();  	init(p.name, p.form_elements);  } -LLNotification::LLNotification(const LLSD& sd) : -	mTemporaryResponder(false), -	mRespondedTo(false), -	mCancelled(false), -	mIgnored(false), -	mResponderObj(NULL), -	mIsReusable(false) -{  -	mId.generate(); -	mSubstitutions = sd["substitutions"]; -	mPayload = sd["payload"];  -	mTimestamp = sd["time"];  -	mExpiresAt = sd["expiry"]; -	mPriority = (ENotificationPriority)sd["priority"].asInteger(); -	mResponseFunctorName = sd["responseFunctor"].asString(); -	std::string templatename = sd["name"].asString(); -	init(templatename, LLSD()); -	// replace form with serialized version -	mForm = LLNotificationFormPtr(new LLNotificationForm(sd["form"])); -} - -  LLSD LLNotification::asLLSD()  { -	LLSD output; -	output["id"] = mId; -	output["name"] = mTemplatep->mName; -	output["form"] = getForm()->asLLSD(); -	output["substitutions"] = mSubstitutions; -	output["payload"] = mPayload; -	output["time"] = mTimestamp; -	output["expiry"] = mExpiresAt; -	output["priority"] = (S32)mPriority; -	output["responseFunctor"] = mResponseFunctorName; -	output["reusable"] = mIsReusable; +	LLParamSDParser parser; -	if(mResponder) +	Params p; +	p.id = mId; +	p.name = mTemplatep->mName; +	p.form_elements = getForm()->asLLSD(); + +	p.substitutions = mSubstitutions; +	p.payload = mPayload; +	p.time_stamp = mTimestamp; +	p.expiry = mExpiresAt; +	p.priority = mPriority; + +	if(!mResponseFunctorName.empty())  	{ -		output["responder"] = mResponder->asLLSD(); +		p.functor.name = mResponseFunctorName;  	} +	LLSD output; +	parser.writeSD(output, p);  	return output;  } @@ -568,7 +559,6 @@ void LLNotification::updateFrom(LLNotificationPtr other)  	mRespondedTo = other->mRespondedTo;  	mResponse = other->mResponse;  	mTemporaryResponder = other->mTemporaryResponder; -	mIsReusable = other->isReusable();  	update();  } @@ -667,7 +657,7 @@ void LLNotification::respond(const LLSD& response)  		return;  	} -	if (mTemporaryResponder && !isReusable()) +	if (mTemporaryResponder)  	{  		LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);  		mResponseFunctorName = ""; @@ -886,6 +876,44 @@ std::string LLNotification::getURL() const  	return (mTemplatep ? url : "");  } +bool LLNotification::canLogToChat() const +{ +	return mTemplatep->mLogToChat; +} + +bool LLNotification::canLogToIM() const +{ +	return mTemplatep->mLogToIM; +} + +bool LLNotification::canShowToast() const +{ +	return mTemplatep->mShowToast; +} + +bool LLNotification::hasFormElements() const +{ +	return mTemplatep->mForm->getNumElements() != 0; +} + +LLNotification::ECombineBehavior LLNotification::getCombineBehavior() const +{ +	return mTemplatep->mCombineBehavior; +} + +void LLNotification::updateForm( const LLNotificationFormPtr& form ) +{ +	mForm = form; +} + +void LLNotification::repost() +{ +	mRespondedTo = false; +	LLNotifications::instance().update(shared_from_this()); +} + + +  // =========================================================  // LLNotificationChannel implementation  // --- @@ -946,7 +974,7 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  	std::string cmd = payload["sigtype"];  	LLNotificationSet::iterator foundItem = mItems.find(pNotification);  	bool wasFound = (foundItem != mItems.end()); -	bool passesFilter = mFilter(pNotification); +	bool passesFilter = mFilter ? mFilter(pNotification) : true;  	// first, we offer the result of the filter test to the simple  	// signals for pass/fail. One of these is guaranteed to be called. @@ -976,8 +1004,8 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  		{  			// not in our list, add it and say so  			mItems.insert(pNotification); -			abortProcessing = mChanged(payload);  			onLoad(pNotification); +			abortProcessing = mChanged(payload);  		}  	}  	else if (cmd == "change") @@ -992,18 +1020,18 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  			{  				// it already existed, so this is a change  				// since it changed in place, all we have to do is resend the signal -				abortProcessing = mChanged(payload);  				onChange(pNotification); +				abortProcessing = mChanged(payload);  			}  			else  			{  				// not in our list, add it and say so  				mItems.insert(pNotification); +				onChange(pNotification);  				// our payload is const, so make a copy before changing it  				LLSD newpayload = payload;  				newpayload["sigtype"] = "add";  				abortProcessing = mChanged(newpayload); -				onChange(pNotification);  			}  		}  		else @@ -1012,11 +1040,11 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  			{  				// it already existed, so this is a delete  				mItems.erase(pNotification); +				onChange(pNotification);  				// our payload is const, so make a copy before changing it  				LLSD newpayload = payload;  				newpayload["sigtype"] = "delete";  				abortProcessing = mChanged(newpayload); -				onChange(pNotification);  			}  			// didn't pass, not on our list, do nothing  		} @@ -1030,8 +1058,8 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  		{  			// not in our list, add it and say so  			mItems.insert(pNotification); -			abortProcessing = mChanged(payload);  			onAdd(pNotification); +			abortProcessing = mChanged(payload);  		}  	}  	else if (cmd == "delete") @@ -1039,65 +1067,35 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  		// if we have it in our list, pass on the delete, then delete it, else do nothing  		if (wasFound)  		{ +			onDelete(pNotification);  			abortProcessing = mChanged(payload); -			// do not delete the notification to make LLChatHistory::appendMessage add notification panel to IM window -			if( ! pNotification->isReusable() ) -			{ -				mItems.erase(pNotification); -				onDelete(pNotification); -			} +			mItems.erase(pNotification);  		}  	}  	return abortProcessing;  } -/* static */ -LLNotificationChannelPtr LLNotificationChannel::buildChannel(const std::string& name,  -															 const std::string& parent, -															 LLNotificationFilter filter,  -															 LLNotificationComparator comparator) +LLNotificationChannel::LLNotificationChannel(const Params& p) +:	LLNotificationChannelBase(p.filter()), +	LLInstanceTracker<LLNotificationChannel, std::string>(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()), +	mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()) +{ +	BOOST_FOREACH(const std::string& source, p.sources)  { -	// note: this is not a leak; notifications are self-registering. -	// This factory helps to prevent excess deletions by making sure all smart -	// pointers to notification channels come from the same source -	new LLNotificationChannel(name, parent, filter, comparator); -	return LLNotifications::instance().getChannel(name); +		connectToChannel(source); +	}  }  LLNotificationChannel::LLNotificationChannel(const std::string& name,   											 const std::string& parent, -											 LLNotificationFilter filter,  -											 LLNotificationComparator comparator) :  -LLNotificationChannelBase(filter, comparator), -mName(name), -mParent(parent) -{ -	// store myself in the channel map -	LLNotifications::instance().addChannel(LLNotificationChannelPtr(this)); +											 LLNotificationFilter filter)  +:	LLNotificationChannelBase(filter), +	LLInstanceTracker<LLNotificationChannel, std::string>(name), +	mName(name) +{  	// bind to notification broadcast -	if (parent.empty()) -	{ -		LLNotifications::instance().connectChanged( -			boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); -	} -	else -	{ -		LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent); -		p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); -	} -} - - -void LLNotificationChannel::setComparator(LLNotificationComparator comparator)  -{  -	mComparator = comparator;  -	LLNotificationSet s2(mComparator); -	s2.insert(mItems.begin(), mItems.end()); -	mItems.swap(s2); -	 -	// notify clients that we've been resorted -	mChanged(LLSD().with("sigtype", "sort"));  +	connectToChannel(parent);  }  bool LLNotificationChannel::isEmpty() const @@ -1115,6 +1113,11 @@ LLNotificationChannel::Iterator LLNotificationChannel::end()  	return mItems.end();  } +size_t LLNotificationChannel::size() +{ +	return mItems.size(); +} +  std::string LLNotificationChannel::summarize()  {  	std::string s("Channel '"); @@ -1128,18 +1131,31 @@ std::string LLNotificationChannel::summarize()  	return s;  } +void LLNotificationChannel::connectToChannel( const std::string& channel_name ) +{ +	if (channel_name.empty()) +	{ +		LLNotifications::instance().connectChanged( +			boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); +	} +	else +	{ +		LLNotificationChannelPtr p = LLNotifications::instance().getChannel(channel_name); +		p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); +	} +}  // ---  // END OF LLNotificationChannel implementation  // ========================================================= -// ========================================================= +// ==============================================	===========  // LLNotifications implementation  // --- -LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything, -															   LLNotificationComparators::orderByUUID()), -									mIgnoreAllNotifications(false) +LLNotifications::LLNotifications()  +:	LLNotificationChannelBase(LLNotificationFilters::includeEverything), +	mIgnoreAllNotifications(false)  {  	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2)); @@ -1180,7 +1196,15 @@ bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif)  		if (pNotif != existing_notification   			&& pNotif->isEquivalentTo(existing_notification))  		{ -			return false; +			if (pNotif->getCombineBehavior() == LLNotification::CANCEL_OLD) +			{ +				cancel(existing_notification); +				return true; +			} +			else +			{ +				return false; +			}  		}  	} @@ -1220,43 +1244,43 @@ bool LLNotifications::failedUniquenessTest(const LLSD& payload)  		return false;  	} -	// Update the existing unique notification with the data from this particular instance... -	// This guarantees that duplicate notifications will be collapsed to the one -	// most recently triggered -	for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); -		existing_it != mUniqueNotifications.end(); -		++existing_it) +	switch(pNotif->getCombineBehavior())  	{ -		LLNotificationPtr existing_notification = existing_it->second; -		if (pNotif != existing_notification  -			&& pNotif->isEquivalentTo(existing_notification)) +	case  LLNotification::REPLACE_WITH_NEW: +		// Update the existing unique notification with the data from this particular instance... +		// This guarantees that duplicate notifications will be collapsed to the one +		// most recently triggered +		for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName()); +			existing_it != mUniqueNotifications.end(); +			++existing_it)  		{ -			// copy notification instance data over to oldest instance -			// of this unique notification and update it -			existing_notification->updateFrom(pNotif); -			// then delete the new one -			cancel(pNotif); +			LLNotificationPtr existing_notification = existing_it->second; +			if (pNotif != existing_notification  +				&& pNotif->isEquivalentTo(existing_notification)) +			{ +				// copy notification instance data over to oldest instance +				// of this unique notification and update it +				existing_notification->updateFrom(pNotif); +				// then delete the new one +				cancel(pNotif); +			}  		} +		break; +	case LLNotification::KEEP_OLD: +		break; +	case LLNotification::CANCEL_OLD: +		// already handled by filter logic +		break; +	default: +		break;  	}  	return false;  } - -void LLNotifications::addChannel(LLNotificationChannelPtr pChan) -{ -	mChannels[pChan->getName()] = pChan; -} -  LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName)  { -	ChannelMap::iterator p = mChannels.find(channelName); -	if(p == mChannels.end()) -	{ -		llerrs << "Did not find channel named " << channelName << llendl; -		return LLNotificationChannelPtr(); -	} -	return p->second; +	return LLNotificationChannelPtr(LLNotificationChannel::getInstance(channelName));  } @@ -1272,24 +1296,21 @@ void LLNotifications::createDefaultChannels()  {  	// now construct the various channels AFTER loading the notifications,  	// because the history channel is going to rewrite the stored notifications file -	LLNotificationChannel::buildChannel("Enabled", "", -		!boost::bind(&LLNotifications::getIgnoreAllNotifications, this)); -	LLNotificationChannel::buildChannel("Expiration", "Enabled", -		boost::bind(&LLNotifications::expirationFilter, this, _1)); -	LLNotificationChannel::buildChannel("Unexpired", "Enabled", -		!boost::bind(&LLNotifications::expirationFilter, this, _1)); // use negated bind -	LLNotificationChannel::buildChannel("Unique", "Unexpired", -		boost::bind(&LLNotifications::uniqueFilter, this, _1)); -	LLNotificationChannel::buildChannel("Ignore", "Unique", -		filterIgnoredNotifications); -	LLNotificationChannel::buildChannel("VisibilityRules", "Ignore", -		boost::bind(&LLNotifications::isVisibleByRules, this, _1)); -	LLNotificationChannel::buildChannel("Visible", "VisibilityRules", -		&LLNotificationFilters::includeEverything); - -	// create special persistent notification channel -	// this isn't a leak, don't worry about the empty "new" -	new LLPersistentNotificationChannel(); +	mDefaultChannels.push_back(new LLNotificationChannel("Enabled", "", +		!boost::bind(&LLNotifications::getIgnoreAllNotifications, this))); +	mDefaultChannels.push_back(new LLNotificationChannel("Expiration", "Enabled", +		boost::bind(&LLNotifications::expirationFilter, this, _1))); +	mDefaultChannels.push_back(new LLNotificationChannel("Unexpired", "Enabled", +		!boost::bind(&LLNotifications::expirationFilter, this, _1))); // use negated bind +	mDefaultChannels.push_back(new LLNotificationChannel("Unique", "Unexpired", +		boost::bind(&LLNotifications::uniqueFilter, this, _1))); +	mDefaultChannels.push_back(new LLNotificationChannel("Ignore", "Unique", +		filterIgnoredNotifications)); +	mDefaultChannels.push_back(new LLNotificationChannel("VisibilityRules", "Ignore", +		boost::bind(&LLNotifications::isVisibleByRules, this, _1))); +	mDefaultChannels.push_back(new LLNotificationChannel("Visible", "VisibilityRules", +		&LLNotificationFilters::includeEverything)); +	mDefaultChannels.push_back(new LLPersistentNotificationChannel());  	// connect action methods to these channels  	LLNotifications::instance().getChannel("Enabled")-> @@ -1579,12 +1600,11 @@ void LLNotifications::cancel(LLNotificationPtr pNotif)  	if (pNotif == NULL || pNotif->isCancelled()) return;  	LLNotificationSet::iterator it=mItems.find(pNotif); -	if (it == mItems.end()) +	if (it != mItems.end())  	{ -		llerrs << "Attempted to delete nonexistent notification " << pNotif->getName() << llendl; +		pNotif->cancel(); +		updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);  	} -	pNotif->cancel(); -	updateItem(LLSD().with("sigtype", "delete").with("id", pNotif->id()), pNotif);  }  void LLNotifications::cancelByName(const std::string& name) @@ -1623,7 +1643,7 @@ void LLNotifications::update(const LLNotificationPtr pNotif)  LLNotificationPtr LLNotifications::find(LLUUID uuid)  { -	LLNotificationPtr target = LLNotificationPtr(new LLNotification(uuid)); +	LLNotificationPtr target = LLNotificationPtr(new LLNotification(LLNotification::Params().id(uuid)));  	LLNotificationSet::iterator it=mItems.find(target);  	if (it == mItems.end())  	{ diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 3df2efcac3..12479f0788 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -88,16 +88,14 @@  #include <boost/enable_shared_from_this.hpp>  #include <boost/type_traits.hpp> -// we want to minimize external dependencies, but this one is important -#include "llsd.h" - -// and we need this to manage the notification callbacks  #include "llevents.h"  #include "llfunctorregistry.h" -#include "llpointer.h"  #include "llinitparam.h"  #include "llnotificationslistener.h"  #include "llnotificationptr.h" +#include "llpointer.h" +#include "llrefcount.h" +#include "llsdparam.h"  class LLAvatarName;  typedef enum e_notification_priority @@ -164,6 +162,7 @@ public:  	struct FormElementBase : public LLInitParam::Block<FormElementBase>  	{  		Optional<std::string>	name; +		Optional<bool>			enabled;  		FormElementBase();  	}; @@ -233,16 +232,20 @@ public:  	} EIgnoreType;  	LLNotificationForm(); +	LLNotificationForm(const LLNotificationForm&);  	LLNotificationForm(const LLSD& sd);  	LLNotificationForm(const std::string& name, const Params& p); +	void fromLLSD(const LLSD& sd);  	LLSD asLLSD() const;  	S32 getNumElements() { return mFormData.size(); }  	LLSD getElement(S32 index) { return mFormData.get(index); }  	LLSD getElement(const std::string& element_name); -	bool hasElement(const std::string& element_name); -	void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD()); +	bool hasElement(const std::string& element_name) const; +	bool getElementEnabled(const std::string& element_name) const; +	void setElementEnabled(const std::string& element_name, bool enabled); +	void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD(), bool enabled = true);  	void formatElements(const LLSD& substitutions);  	// appends form elements from another form serialized as LLSD  	void append(const LLSD& sub_form); @@ -296,19 +299,20 @@ LOG_CLASS(LLNotification);  friend class LLNotifications;  public: +  	// parameter object used to instantiate a new notification  	struct Params : public LLInitParam::Block<Params>  	{  		friend class LLNotification;  		Mandatory<std::string>					name; - -		// optional -		Optional<LLSD>							substitutions; -		Optional<LLSD>							payload; +		Optional<LLUUID>						id; +		Optional<LLSD>							substitutions, +												form_elements, +												payload;  		Optional<ENotificationPriority, NotificationPriorityValues>	priority; -		Optional<LLSD>							form_elements; -		Optional<LLDate>						time_stamp; +		Optional<LLDate>						time_stamp, +												expiry;  		Optional<LLNotificationContext*>		context;  		Optional<void*>							responder; @@ -319,7 +323,7 @@ public:  			Alternative<LLNotificationResponderPtr>						responder;  			Functor() -			:	name("functor_name"), +			:	name("responseFunctor"),  				function("functor"),  				responder("responder")  			{} @@ -328,10 +332,13 @@ public:  		Params()  		:	name("name"), +			id("id"),  			priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), -			time_stamp("time_stamp"), +			time_stamp("time"),  			payload("payload"), -			form_elements("form_elements") +			form_elements("form"), +			substitutions("substitutions"), +			expiry("expiry")  		{  			time_stamp = LLDate::now();  			responder = NULL; @@ -340,9 +347,11 @@ public:  		Params(const std::string& _name)   		:	name("name"),  			priority("priority", NOTIFICATION_PRIORITY_UNSPECIFIED), -			time_stamp("time_stamp"), +			time_stamp("time"),  			payload("payload"), -			form_elements("form_elements") +			form_elements("form"), +			substitutions("substitutions"), +			expiry("expiry")  		{  			functor.name = _name;  			name = _name; @@ -355,7 +364,7 @@ public:  private: -	LLUUID mId; +	const LLUUID mId;  	LLSD mPayload;  	LLSD mSubstitutions;  	LLDate mTimestamp; @@ -367,7 +376,6 @@ private:  	ENotificationPriority mPriority;  	LLNotificationFormPtr mForm;  	void* mResponderObj; // TODO - refactor/remove this field -	bool mIsReusable;  	LLNotificationResponderPtr mResponder;  	// a reference to the template @@ -392,18 +400,10 @@ private:  	void init(const std::string& template_name, const LLSD& form_elements); -	LLNotification(const Params& p); - -	// this is just for making it easy to look things up in a set organized by UUID -- DON'T USE IT -	// for anything real! - LLNotification(LLUUID uuid) : mId(uuid), mCancelled(false), mRespondedTo(false), mIgnored(false), mPriority(NOTIFICATION_PRIORITY_UNSPECIFIED), mTemporaryResponder(false) {} -  	void cancel();  public: - -	// constructor from a saved notification -	LLNotification(const LLSD& sd); +	LLNotification(const LLSDParamAdapter<Params>& p);  	void setResponseFunctor(std::string const &responseFunctorName); @@ -448,6 +448,11 @@ public:  	// ["responseFunctor"] = name of registered functor that handles responses to notification;  	LLSD asLLSD(); +	const LLNotificationFormPtr getForm(); +	void updateForm(const LLNotificationFormPtr& form); + +	void repost(); +  	void respond(const LLSD& sd);  	void respondWithDefault(); @@ -513,8 +518,20 @@ public:  	std::string getURL() const;  	S32 getURLOption() const;      S32 getURLOpenExternally() const; +	bool canLogToChat() const; +	bool canLogToIM() const; +	bool canShowToast() const; +	bool hasFormElements() const; + +	typedef enum e_combine_behavior +	{ +		REPLACE_WITH_NEW, +		KEEP_OLD, +		CANCEL_OLD + +	} ECombineBehavior; -	const LLNotificationFormPtr getForm(); +	ECombineBehavior getCombineBehavior() const;  	const LLDate getExpiration() const  	{ @@ -531,10 +548,6 @@ public:  		return mId;  	} -	bool isReusable() { return mIsReusable; } - -	void setReusable(bool reusable) { mIsReusable = reusable; } -	  	// comparing two notifications normally means comparing them by UUID (so we can look them  	// up quickly this way)  	bool operator<(const LLNotification& rhs) const @@ -646,44 +659,18 @@ namespace LLNotificationFilters  namespace LLNotificationComparators  { -	typedef enum e_direction { ORDER_DECREASING, ORDER_INCREASING } EDirection; - -	// generic order functor that takes method or member variable reference -	template<typename T> -	struct orderBy +	struct orderByUUID  	{ -		typedef boost::function<T (LLNotificationPtr)> field_t; -        	orderBy(field_t field, EDirection direction = ORDER_INCREASING) : mField(field), mDirection(direction) {}  		bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs)  		{ -			if (mDirection == ORDER_DECREASING) -			{ -				return mField(lhs) > mField(rhs); -			} -			else -			{ -				return mField(lhs) < mField(rhs); -			} +			return lhs->id() < rhs->id();  		} - -		field_t mField; -		EDirection mDirection; -	}; - -	struct orderByUUID : public orderBy<const LLUUID&> -	{ -		orderByUUID(EDirection direction = ORDER_INCREASING) : orderBy<const LLUUID&>(&LLNotification::id, direction) {} -	}; - -	struct orderByDate : public orderBy<const LLDate&> -	{ -		orderByDate(EDirection direction = ORDER_INCREASING) : orderBy<const LLDate&>(&LLNotification::getDate, direction) {}  	};  };  typedef boost::function<bool (LLNotificationPtr)> LLNotificationFilter;  typedef boost::function<bool (LLNotificationPtr, LLNotificationPtr)> LLNotificationComparator; -typedef std::set<LLNotificationPtr, LLNotificationComparator> LLNotificationSet; +typedef std::set<LLNotificationPtr, LLNotificationComparators::orderByUUID> LLNotificationSet;  typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap;  // ======================================================== @@ -704,12 +691,14 @@ typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap;  // all of the built-in tests should attach to the "Visible" channel  //  class LLNotificationChannelBase : -	public LLEventTrackable +	public LLEventTrackable, +	public LLRefCount  {  	LOG_CLASS(LLNotificationChannelBase);  public: -	LLNotificationChannelBase(LLNotificationFilter filter, LLNotificationComparator comp) :  -		mFilter(filter), mItems(comp)  +	LLNotificationChannelBase(LLNotificationFilter filter)  +	:	mFilter(filter),  +		mItems()   	{}  	virtual ~LLNotificationChannelBase() {}  	// you can also connect to a Channel, so you can be notified of @@ -784,59 +773,49 @@ protected:  // destroy it, but if it becomes necessary to do so, the shared_ptr model  // will ensure that we don't leak resources.  class LLNotificationChannel; -typedef boost::shared_ptr<LLNotificationChannel> LLNotificationChannelPtr; +typedef boost::intrusive_ptr<LLNotificationChannel> LLNotificationChannelPtr;  // manages a list of notifications  // Note that if this is ever copied around, we might find ourselves with multiple copies  // of a queue with notifications being added to different nonequivalent copies. So we  -// make it inherit from boost::noncopyable, and then create a map of shared_ptr to manage it. -//  -// NOTE: LLNotificationChannel is self-registering. The *correct* way to create one is to  -// do something like: -//		LLNotificationChannel::buildChannel("name", "parent"...); -// This returns an LLNotificationChannelPtr, which you can store, or -// you can then retrieve the channel by using the registry: -//		LLNotifications::instance().getChannel("name")... +// make it inherit from boost::noncopyable, and then create a map of LLPointer to manage it.  //  class LLNotificationChannel :   	boost::noncopyable,  -	public LLNotificationChannelBase +	public LLNotificationChannelBase, +	public LLInstanceTracker<LLNotificationChannel, std::string>  {  	LOG_CLASS(LLNotificationChannel);  public:   +	// Notification Channels have a filter, which determines which notifications +	// will be added to this channel.  +	// Channel filters cannot change. +	struct Params : public LLInitParam::Block<Params> +	{ +		Mandatory<std::string>				name; +		Optional<LLNotificationFilter>		filter; +		Multiple<std::string>				sources; +	}; + +	LLNotificationChannel(const Params& p = Params()); +	LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter); +  	virtual ~LLNotificationChannel() {}  	typedef LLNotificationSet::iterator Iterator;  	std::string getName() const { return mName; } -	std::string getParentChannelName() { return mParent; } +     +	void connectToChannel(const std::string& channel_name);      bool isEmpty() const;      Iterator begin();      Iterator end(); +	size_t size(); -    // Channels have a comparator to control sort order; -	// the default sorts by arrival date -    void setComparator(LLNotificationComparator comparator); -	  	std::string summarize(); -	// factory method for constructing these channels; since they're self-registering, -	// we want to make sure that you can't use new to make them -	static LLNotificationChannelPtr buildChannel(const std::string& name, const std::string& parent, -						LLNotificationFilter filter=LLNotificationFilters::includeEverything,  -						LLNotificationComparator comparator=LLNotificationComparators::orderByUUID()); -	 -protected: -    // Notification Channels have a filter, which determines which notifications -	// will be added to this channel.  -	// Channel filters cannot change. -	// Channels have a protected constructor so you can't make smart pointers that don't  -	// come from our internal reference; call NotificationChannel::build(args) -	LLNotificationChannel(const std::string& name, const std::string& parent, -						  LLNotificationFilter filter, LLNotificationComparator comparator); -  private:  	std::string mName;  	std::string mParent; @@ -923,10 +902,6 @@ public:  	void createDefaultChannels(); -	typedef std::map<std::string, LLNotificationChannelPtr> ChannelMap; -	ChannelMap mChannels; - -	void addChannel(LLNotificationChannelPtr pChan);  	LLNotificationChannelPtr getChannel(const std::string& channelName);  	std::string getGlobalString(const std::string& key) const; @@ -965,6 +940,7 @@ private:  	bool mIgnoreAllNotifications;      boost::scoped_ptr<LLNotificationsListener> mListener; +	std::vector<LLNotificationChannelPtr> mDefaultChannels;  };  /** @@ -1027,5 +1003,56 @@ protected:  	std::string mName;  }; +// Stores only persistent notifications. +// Class users can use connectChanged() to process persistent notifications +// (see LLNotificationStorage for example). +class LLPersistentNotificationChannel : public LLNotificationChannel +{ +	LOG_CLASS(LLPersistentNotificationChannel); +public: +	LLPersistentNotificationChannel()  +		:	LLNotificationChannel("Persistent", "Visible", ¬ificationFilter) +	{ +	} + +	typedef std::vector<LLNotificationPtr> history_list_t; +	history_list_t::iterator beginHistory() { sortHistory(); return mHistory.begin(); } +	history_list_t::iterator endHistory() { return mHistory.end(); } + +private: + +	struct sortByTime +	{ +		S32 operator ()(const LLNotificationPtr& a, const LLNotificationPtr& b) +		{ +			return a->getDate() < b->getDate(); +		} +	}; + +	void sortHistory() +	{ +		std::sort(mHistory.begin(), mHistory.end(), sortByTime()); +	} + + +	// The channel gets all persistent notifications except those that have been canceled +	static bool notificationFilter(LLNotificationPtr pNotification) +	{ +		bool handle_notification = false; + +		handle_notification = pNotification->isPersistent() +			&& !pNotification->isCancelled(); + +		return handle_notification; +	} + +	void onAdd(LLNotificationPtr p)  +	{ +		mHistory.push_back(p); +	} + +	std::vector<LLNotificationPtr> mHistory; +}; +  #endif//LL_LLNOTIFICATIONS_H diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index 3bbeb3a778..e4e127336b 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -121,13 +121,13 @@ void LLNotificationsListener::listChannels(const LLSD& params) const  {      LLReqID reqID(params);      LLSD response(reqID.makeResponse()); -    for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()), -                                                     cmend(mNotifications.mChannels.end()); +    for (LLNotificationChannel::instance_iter cmi(LLNotificationChannel::beginInstances()), +                                                     cmend(LLNotificationChannel::endInstances());           cmi != cmend; ++cmi)      {          LLSD channelInfo; -        channelInfo["parent"] = cmi->second->getParentChannelName(); -        response[cmi->first] = channelInfo; +        //channelInfo["parent"] = cmi->second->getParentChannelName(); +        response[cmi->getName()] = channelInfo;      }      LLEventPumps::instance().obtain(params["reply"]).post(response);  } diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index fb50c9c123..ca9c4294c1 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -61,6 +61,18 @@ typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;  // from the appropriate local language directory).  struct LLNotificationTemplate  { +	struct CombineBehaviorNames +		:	public LLInitParam::TypeValuesHelper<LLNotification::ECombineBehavior, CombineBehaviorNames> +	{ +		static void declareValues() +		{ +			declare("replace_with_new", LLNotification::REPLACE_WITH_NEW); +			declare("keep_old", LLNotification::KEEP_OLD); +			declare("cancel_old", LLNotification::CANCEL_OLD); +		} +	}; + +  	struct GlobalString : public LLInitParam::Block<GlobalString>  	{  		Mandatory<std::string>	name, @@ -94,9 +106,11 @@ struct LLNotificationTemplate  		Optional<LLInitParam::Flag>	dummy_val;  	public:  		Multiple<UniquenessContext>	contexts; +		Optional<LLNotification::ECombineBehavior, CombineBehaviorNames> combine;  		UniquenessConstraint()  		:	contexts("context"), +			combine("combine", LLNotification::REPLACE_WITH_NEW),  			dummy_val("")  		{}  	}; @@ -170,7 +184,10 @@ struct LLNotificationTemplate  	struct Params : public LLInitParam::Block<Params>  	{  		Mandatory<std::string>			name; -		Optional<bool>					persist; +		Optional<bool>					persist, +										log_to_im, +										show_toast, +										log_to_chat;  		Optional<std::string>			functor,  										icon,  										label, @@ -190,6 +207,9 @@ struct LLNotificationTemplate  		Params()  		:	name("name"),  			persist("persist", false), +			log_to_im("log_to_im", false), +			show_toast("show_toast", true), +			log_to_chat("log_to_chat", true),  			functor("functor"),  			icon("icon"),  			label("label"), @@ -245,6 +265,7 @@ struct LLNotificationTemplate      // (used for things like progress indications, or repeating warnings      // like "the grid is going down in N minutes")      bool mUnique; +	LLNotification::ECombineBehavior mCombineBehavior;      // if we want to be unique only if a certain part of the payload or substitutions args  	// are constant specify the field names for the payload. The notification will only be      // combined if all of the fields named in the context are identical in the @@ -291,6 +312,11 @@ struct LLNotificationTemplate  	LLUUID mSoundEffect;  	// List of tags that rules can match against.  	std::list<std::string> mTags; + +	// inject these notifications into chat/IM streams +	bool mLogToChat; +	bool mLogToIM; +	bool mShowToast;  };  #endif //LL_LLNOTIFICATION_TEMPLATE_H diff --git a/indra/llui/llsdparam.cpp b/indra/llui/llsdparam.cpp index 0e29873bb0..811e20e810 100644 --- a/indra/llui/llsdparam.cpp +++ b/indra/llui/llsdparam.cpp @@ -283,7 +283,10 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI  			it != sd.endArray();  			++it)  		{ -			stack.back().second = true; +			if (!stack.empty()) +			{ +				stack.back().second = true; +			}  			readSDValues(cb, *it, stack);  		}  	} @@ -313,7 +316,7 @@ namespace LLInitParam  {  	// LLSD specialization  	// block param interface -	bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) +	bool ParamValue<LLSD, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name)  	{  		LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack); @@ -328,15 +331,14 @@ namespace LLInitParam  	}  	//static -	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) +	void ParamValue<LLSD, NOT_BLOCK>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)  	{  		p.writeValue<LLSD::String>(sd.asString(), name_stack);  	} -	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const +	void ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const  	{  		// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) -		Parser::name_stack_t stack; -		LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack); +		LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack);  	}  } diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 5fc2cc350d..d0920685bf 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1209,7 +1209,11 @@ void LLTabContainer::removeTabPanel(LLPanel* child)  				update_images(mTabList[mTabList.size()-2], mLastTabParams, getTabPosition());  			} -			removeChild( tuple->mButton ); +			if (!getTabsHidden()) +			{ +				// We need to remove tab buttons only if the tabs are not hidden. +				removeChild( tuple->mButton ); +			}   			delete tuple->mButton;   			removeChild( tuple->mTabPanel ); diff --git a/indra/llui/lltoggleablemenu.h b/indra/llui/lltoggleablemenu.h index 2094bd776f..dd9ac5b8c1 100644 --- a/indra/llui/lltoggleablemenu.h +++ b/indra/llui/lltoggleablemenu.h @@ -58,6 +58,8 @@ public:  	// its visibility off.  	bool toggleVisibility(); +	LLHandle<LLToggleableMenu> getHandle() { return getDerivedHandle<LLToggleableMenu>(); } +  protected:  	bool mClosedByButtonClick;  	LLRect mButtonRect; diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index b5e27616b7..8da0d58f51 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -974,31 +974,31 @@ void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)  {  	if (!LLGLSLShader::sNoFixedFunction)  	{  -		// Initialize the first time this is called. -		const S32 PIXELS = 32; -		static GLubyte checkerboard[PIXELS * PIXELS]; -		static BOOL first = TRUE; -		if( first ) +	// Initialize the first time this is called. +	const S32 PIXELS = 32; +	static GLubyte checkerboard[PIXELS * PIXELS]; +	static BOOL first = TRUE; +	if( first ) +	{ +		for( S32 i = 0; i < PIXELS; i++ )  		{ -			for( S32 i = 0; i < PIXELS; i++ ) +			for( S32 j = 0; j < PIXELS; j++ )  			{ -				for( S32 j = 0; j < PIXELS; j++ ) -				{ -					checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; -				} +				checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF;  			} -			first = FALSE;  		} +		first = FALSE; +	} -		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -		// ...white squares -		gGL.color4f( 1.f, 1.f, 1.f, alpha ); -		gl_rect_2d(rect); +	// ...white squares +	gGL.color4f( 1.f, 1.f, 1.f, alpha ); +	gl_rect_2d(rect); -		// ...gray squares -		gGL.color4f( .7f, .7f, .7f, alpha ); -		gGL.flush(); +	// ...gray squares +	gGL.color4f( .7f, .7f, .7f, alpha ); +	gGL.flush();  		glPolygonStipple( checkerboard ); @@ -1474,144 +1474,132 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left,  	gGL.popUIMatrix();  } -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width,  -							  const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, -							  const U32 edges) +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect,  +							 const LLVector3& width_vec, const LLVector3& height_vec)  { -	LLVector3 left_border_width = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? border_width : LLVector3::zero; -	LLVector3 right_border_width = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? border_width : LLVector3::zero; - -	LLVector3 top_border_height = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? border_height : LLVector3::zero; -	LLVector3 bottom_border_height = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? border_height : LLVector3::zero; - -  	gGL.begin(LLRender::QUADS);  	{  		// draw bottom left -		gGL.texCoord2f(0.f, 0.f); +		gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom);  		gGL.vertex3f(0.f, 0.f, 0.f); -		gGL.texCoord2f(border_scale.mV[VX], 0.f); -		gGL.vertex3fv(left_border_width.mV); +		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(0.f, border_scale.mV[VY]); -		gGL.vertex3fv(bottom_border_height.mV); +		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);  		// draw bottom middle -		gGL.texCoord2f(border_scale.mV[VX], 0.f); -		gGL.vertex3fv(left_border_width.mV); +		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); -		gGL.vertex3fv((width_vec - right_border_width).mV); +		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);  		// draw bottom right -		gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); -		gGL.vertex3fv((width_vec - right_border_width).mV); +		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); -		gGL.texCoord2f(1.f, 0.f); +		gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom);  		gGL.vertex3fv(width_vec.mV); -		gGL.texCoord2f(1.f, border_scale.mV[VY]); -		gGL.vertex3fv((width_vec + bottom_border_height).mV); +		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);  		// draw left  -		gGL.texCoord2f(0.f, border_scale.mV[VY]); -		gGL.vertex3fv(bottom_border_height.mV); +		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((height_vec - top_border_height).mV); +		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);  		// draw middle -		gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);  		// draw right  -		gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(1.f, border_scale.mV[VY]); -		gGL.vertex3fv((width_vec + bottom_border_height).mV); +		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); +		gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); -		gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); +		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);  		// draw top left -		gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((height_vec - top_border_height).mV); +		gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], 1.f); -		gGL.vertex3fv((left_border_width + height_vec).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); -		gGL.texCoord2f(0.f, 1.f); +		gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop);  		gGL.vertex3fv((height_vec).mV);  		// draw top middle -		gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); -		gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); +		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); -		gGL.texCoord2f(border_scale.mV[VX], 1.f); -		gGL.vertex3fv((left_border_width + height_vec).mV); +		gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);  		// draw top right -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); +		gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); -		gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); +		gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); +		gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); -		gGL.texCoord2f(1.f, 1.f); +		gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop);  		gGL.vertex3fv((width_vec + height_vec).mV); -		gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); -		gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); +		gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); +		gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);  	}  	gGL.end();  } -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec) -{ -	gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP); -}  void LLUI::initClass(const settings_map_t& settings,  					 LLImageProviderInterface* image_provider, @@ -2114,7 +2102,7 @@ const LLView* LLUI::resolvePath(const LLView* context, const std::string& path)  namespace LLInitParam  { -	ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) +	ParamValue<LLUIColor>::ParamValue(const LLUIColor& color)  	:	super_t(color),  		red("red"),  		green("green"), @@ -2125,7 +2113,7 @@ namespace LLInitParam  		updateBlockFromValue(false);  	} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() +	void ParamValue<LLUIColor>::updateValueFromBlock()  	{  		if (control.isProvided() && !control().empty())  		{ @@ -2137,7 +2125,7 @@ namespace LLInitParam  		}  	} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue(bool make_block_authoritative) +	void ParamValue<LLUIColor>::updateBlockFromValue(bool make_block_authoritative)  	{  		LLColor4 color = getValue();  		red.set(color.mV[VRED], make_block_authoritative); @@ -2153,7 +2141,7 @@ namespace LLInitParam  			&& !(b->getFontDesc() < a->getFontDesc());  	} -	ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) +	ParamValue<const LLFontGL*>::ParamValue(const LLFontGL* fontp)  	:	super_t(fontp),  		name("name"),  		size("size"), @@ -2167,7 +2155,7 @@ namespace LLInitParam  		updateBlockFromValue(false);  	} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() +	void ParamValue<const LLFontGL*>::updateValueFromBlock()  	{  		const LLFontGL* res_fontp = LLFontGL::getFontByName(name);  		if (res_fontp) @@ -2190,7 +2178,7 @@ namespace LLInitParam  		}  	} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue(bool make_block_authoritative) +	void ParamValue<const LLFontGL*>::updateBlockFromValue(bool make_block_authoritative)  	{  		if (getValue())  		{ @@ -2200,7 +2188,7 @@ namespace LLInitParam  		}  	} -	ParamValue<LLRect, TypeValues<LLRect> >::ParamValue(const LLRect& rect) +	ParamValue<LLRect>::ParamValue(const LLRect& rect)  	:	super_t(rect),  		left("left"),  		top("top"), @@ -2212,7 +2200,7 @@ namespace LLInitParam  		updateBlockFromValue(false);  	} -	void ParamValue<LLRect, TypeValues<LLRect> >::updateValueFromBlock() +	void ParamValue<LLRect>::updateValueFromBlock()  	{  		LLRect rect; @@ -2276,7 +2264,7 @@ namespace LLInitParam  		updateValue(rect);  	} -	void ParamValue<LLRect, TypeValues<LLRect> >::updateBlockFromValue(bool make_block_authoritative) +	void ParamValue<LLRect>::updateBlockFromValue(bool make_block_authoritative)  	{  		// because of the ambiguity in specifying a rect by position and/or dimensions  		// we use the lowest priority pairing so that any valid pairing in xui  @@ -2293,7 +2281,7 @@ namespace LLInitParam  		height.set(value.getHeight(), make_block_authoritative);  	} -	ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::ParamValue(const LLCoordGL& coord) +	ParamValue<LLCoordGL>::ParamValue(const LLCoordGL& coord)  	:	super_t(coord),  		x("x"),  		y("y") @@ -2301,12 +2289,12 @@ namespace LLInitParam  		updateBlockFromValue(false);  	} -	void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateValueFromBlock() +	void ParamValue<LLCoordGL>::updateValueFromBlock()  	{  		updateValue(LLCoordGL(x, y));  	} -	void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateBlockFromValue(bool make_block_authoritative) +	void ParamValue<LLCoordGL>::updateBlockFromValue(bool make_block_authoritative)  	{  		x.set(getValue().mX, make_block_authoritative);  		y.set(getValue().mY, make_block_authoritative); diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 28e84fa444..1fbfbd7a07 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -127,8 +127,7 @@ typedef enum e_rounded_edge  void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL);  void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec); +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec);  inline void gl_rect_2d( const LLRect& rect, BOOL filled )  { @@ -512,7 +511,7 @@ public:  namespace LLInitParam  {  	template<> -	class ParamValue<LLRect, TypeValues<LLRect> >  +	class ParamValue<LLRect>   	:	public CustomParamValue<LLRect>  	{          typedef CustomParamValue<LLRect> super_t; @@ -531,7 +530,7 @@ namespace LLInitParam  	};  	template<> -	class ParamValue<LLUIColor, TypeValues<LLUIColor> >  +	class ParamValue<LLUIColor>   	:	public CustomParamValue<LLUIColor>  	{          typedef CustomParamValue<LLUIColor> super_t; @@ -549,7 +548,7 @@ namespace LLInitParam  	};  	template<> -	class ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >  +	class ParamValue<const LLFontGL*>   	:	public CustomParamValue<const LLFontGL* >  	{          typedef CustomParamValue<const LLFontGL*> super_t; @@ -589,7 +588,7 @@ namespace LLInitParam  	template<> -	class ParamValue<LLCoordGL, TypeValues<LLCoordGL> > +	class ParamValue<LLCoordGL>  	:	public CustomParamValue<LLCoordGL>  	{  		typedef CustomParamValue<LLCoordGL> super_t; diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp index 1d9ce29ba9..9ed98f941f 100644 --- a/indra/llui/lluiimage.cpp +++ b/indra/llui/lluiimage.cpp @@ -112,6 +112,50 @@ void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4&  	drawSolid(border_rect, color);  } +void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis,  +						const LLRect& rect, const LLColor4& color) +{ +	F32 border_scale = 1.f; +	F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight(); +	F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth(); +	if (rect.getHeight() < border_height || rect.getWidth() < border_width) +	{ +		 if(border_height - rect.getHeight() > border_width - rect.getWidth()) +		 { +			 border_scale = (F32)rect.getHeight() / border_height; +		 } +		 else +		 { +			border_scale = (F32)rect.getWidth() / border_width; +		 } +	} + +	LLUI::pushMatrix(); +	{  +		LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis);  +		LLUI::translate(rect_origin.mV[VX], +						rect_origin.mV[VY],  +						rect_origin.mV[VZ]); +		gGL.getTexUnit(0)->bind(getImage()); +		gGL.color4fv(color.mV); + +		LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(), +							mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(), +							mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(), +							mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight()); +		gl_segmented_rect_3d_tex(mClipRegion, +								center_uv_rect, +								LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(), +										(rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(), +										(rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(), +										(border_height * border_scale * 0.5f) / (F32)rect.getHeight()), +								rect.getWidth() * x_axis,  +								rect.getHeight() * y_axis); +		 +	} LLUI::popMatrix(); +} + +  S32 LLUIImage::getWidth() const  {   	// return clipped dimensions of actual image area @@ -155,7 +199,7 @@ void LLUIImage::onImageLoaded()  namespace LLInitParam  { -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() +	void ParamValue<LLUIImage*>::updateValueFromBlock()  	{  		// The keyword "none" is specifically requesting a null image  		// do not default to current value. Used to overwrite template images.  @@ -172,7 +216,7 @@ namespace LLInitParam  		}  	} -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue(bool make_block_authoritative) +	void ParamValue<LLUIImage*>::updateBlockFromValue(bool make_block_authoritative)  	{  		if (getValue() == NULL)  		{ diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h index f07e8fa746..7817ba1c7b 100644 --- a/indra/llui/lluiimage.h +++ b/indra/llui/lluiimage.h @@ -64,7 +64,9 @@ public:  	void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;  	void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }  	void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); } -	 + +	void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color); +  	const std::string& getName() const { return mName; }  	virtual S32 getWidth() const; @@ -92,7 +94,7 @@ protected:  namespace LLInitParam  {  	template<> -	class ParamValue<LLUIImage*, TypeValues<LLUIImage*> >  +	class ParamValue<LLUIImage*>   	:	public CustomParamValue<LLUIImage*>  	{  		typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type	T_const_ref; @@ -100,7 +102,7 @@ namespace LLInitParam  	public:  		Optional<std::string> name; -		ParamValue(LLUIImage* const& image) +		ParamValue(LLUIImage* const& image = NULL)  		:	super_t(image)  		{  			updateBlockFromValue(false); diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 54843227b7..5c2b3236f6 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -349,7 +349,7 @@ void LLView::removeChild(LLView* child)  	}  	else  	{ -		llwarns << child->getName() << "is not a child of " << getName() << llendl; +		llwarns << "\"" << child->getName() << "\" is not a child of " << getName() << llendl;  	}  	updateBoundingRect();  } diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index c75df86891..61e30d89d0 100644 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -110,10 +110,12 @@ namespace LLInitParam  	{  		const U8* my_addr = reinterpret_cast<const U8*>(this);  		const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); -		mEnclosingBlockOffset = (U16)(my_addr - block_addr); +		U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); +		mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; +		mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16;  	} -	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){} +	void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name){}  	void BaseBlock::addSynonym(Param& param, const std::string& synonym) {}  	param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;} @@ -127,14 +129,14 @@ namespace LLInitParam  	bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }  	bool BaseBlock::validateBlock(bool emit_errors) const { return true; } -	ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) +	ParamValue<LLUIColor>::ParamValue(const LLUIColor& color)  	:	super_t(color)  	{} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock()  +	void ParamValue<LLUIColor>::updateValueFromBlock()   	{} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue(bool) +	void ParamValue<LLUIColor>::updateBlockFromValue(bool)  	{}  	bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -142,14 +144,14 @@ namespace LLInitParam  		return false;  	} -	ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) +	ParamValue<const LLFontGL*>::ParamValue(const LLFontGL* fontp)  	:	super_t(fontp)  	{} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() +	void ParamValue<const LLFontGL*>::updateValueFromBlock()  	{} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue(bool) +	void ParamValue<const LLFontGL*>::updateBlockFromValue(bool)  	{}  	void TypeValues<LLFontGL::HAlign>::declareValues() @@ -161,10 +163,10 @@ namespace LLInitParam  	void TypeValues<LLFontGL::ShadowType>::declareValues()  	{} -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() +	void ParamValue<LLUIImage*>::updateValueFromBlock()  	{} -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue(bool) +	void ParamValue<LLUIImage*>::updateBlockFromValue(bool)  	{} diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp index 7183413463..97fe5b2eea 100644 --- a/indra/llui/tests/llurlmatch_test.cpp +++ b/indra/llui/tests/llurlmatch_test.cpp @@ -74,7 +74,7 @@ namespace LLInitParam  						S32 max_count){}  	ParamDescriptor::~ParamDescriptor() {} -	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name){} +	void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name){}  	param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}  	void BaseBlock::addSynonym(Param& param, const std::string& synonym) {} @@ -88,7 +88,9 @@ namespace LLInitParam  	{  		const U8* my_addr = reinterpret_cast<const U8*>(this);  		const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); -		mEnclosingBlockOffset = 0x7FFFffff & ((U32)(my_addr - block_addr)); +		U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); +		mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; +		mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16;  	}  	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name){ return true; } @@ -97,14 +99,14 @@ namespace LLInitParam  	bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }  	bool BaseBlock::validateBlock(bool emit_errors) const { return true; } -	ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color) +	ParamValue<LLUIColor>::ParamValue(const LLUIColor& color)  	:	super_t(color)  	{} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock() +	void ParamValue<LLUIColor>::updateValueFromBlock()  	{} -	void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue(bool) +	void ParamValue<LLUIColor>::updateBlockFromValue(bool)  	{}  	bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b) @@ -113,14 +115,14 @@ namespace LLInitParam  	} -	ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp) +	ParamValue<const LLFontGL*>::ParamValue(const LLFontGL* fontp)  	:	super_t(fontp)  	{} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock() +	void ParamValue<const LLFontGL*>::updateValueFromBlock()  	{} -	void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue(bool) +	void ParamValue<const LLFontGL*>::updateBlockFromValue(bool)  	{}  	void TypeValues<LLFontGL::HAlign>::declareValues() @@ -132,10 +134,10 @@ namespace LLInitParam  	void TypeValues<LLFontGL::ShadowType>::declareValues()  	{} -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateValueFromBlock() +	void ParamValue<LLUIImage*>::updateValueFromBlock()  	{} -	void ParamValue<LLUIImage*, TypeValues<LLUIImage*> >::updateBlockFromValue(bool) +	void ParamValue<LLUIImage*>::updateBlockFromValue(bool)  	{}  	bool ParamCompare<LLUIImage*, false>::equals( diff --git a/indra/llxuixml/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp index db72aa19b9..3c0d0aaa7e 100644 --- a/indra/llxuixml/llinitparam.cpp +++ b/indra/llxuixml/llinitparam.cpp @@ -40,7 +40,9 @@ namespace LLInitParam  	{  		const U8* my_addr = reinterpret_cast<const U8*>(this);  		const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); -		mEnclosingBlockOffset = 0x7FFFffff & (U32)(my_addr - block_addr); +		U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); +		mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; +		mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16;  	}  	// @@ -112,6 +114,35 @@ namespace LLInitParam  		std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));  	} +	void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name) +	{ +		// create a copy of the param descriptor in mAllParams +		// so other data structures can store a pointer to it +		mAllParams.push_back(in_param); +		ParamDescriptorPtr param(mAllParams.back()); + +		std::string name(char_name); +		if ((size_t)param->mParamHandle > mMaxParamOffset) +		{ +			llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl; +		} + +		if (name.empty()) +		{ +			mUnnamedParams.push_back(param); +		} +		else +		{ +			// don't use insert, since we want to overwrite existing entries +			mNamedParams[name] = param; +		} + +		if (param->mValidationFunc) +		{ +			mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); +		} +	} +  	BlockDescriptor::BlockDescriptor()  	:	mMaxParamOffset(0),  		mInitializationState(UNINITIALIZED), @@ -358,36 +389,6 @@ namespace LLInitParam  		return false;  	} -	//static  -	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name) -	{ -		// create a copy of the param descriptor in mAllParams -		// so other data structures can store a pointer to it -		block_data.mAllParams.push_back(in_param); -		ParamDescriptorPtr param(block_data.mAllParams.back()); - -		std::string name(char_name); -		if ((size_t)param->mParamHandle > block_data.mMaxParamOffset) -		{ -			llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl; -		} - -		if (name.empty()) -		{ -			block_data.mUnnamedParams.push_back(param); -		} -		else -		{ -			// don't use insert, since we want to overwrite existing entries -			block_data.mNamedParams[name] = param; -		} - -		if (param->mValidationFunc) -		{ -			block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); -		} -	} -  	void BaseBlock::addSynonym(Param& param, const std::string& synonym)  	{  		BlockDescriptor& block_data = mostDerivedBlockDescriptor(); @@ -460,7 +461,7 @@ namespace LLInitParam  			if (merge_func)  			{  				Param* paramp = getParamFromHandle((*it)->mParamHandle); -				llassert(paramp->mEnclosingBlockOffset == (*it)->mParamHandle); +				llassert(paramp->getEnclosingBlockOffset() == (*it)->mParamHandle);  				some_param_changed |= merge_func(*paramp, *other_paramp, overwrite);  			}  		} diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index 4ab1d891a3..ce59401e87 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -36,6 +36,71 @@  #include "llerror.h" +namespace LLTypeTags +{ +	template <typename INNER_TYPE, int _SORT_ORDER> +	struct TypeTagBase +	{ +		typedef void		is_tag_t; +		typedef INNER_TYPE	inner_t; +		static const int	SORT_ORDER=_SORT_ORDER; +	}; + +	template <int VAL1, int VAL2> +	struct GreaterThan +	{ +		static const bool value = VAL1 > VAL2; +	}; + +	template<typename ITEM, typename REST, bool NEEDS_SWAP = GreaterThan<ITEM::SORT_ORDER, REST::SORT_ORDER>::value > +	struct Swap +	{ +		typedef typename ITEM::template Cons<REST>::value_t value_t; +	}; + +	template<typename ITEM, typename REST> +	struct Swap<ITEM, REST, true> +	{ +		typedef typename REST::template Cons<Swap<ITEM, typename REST::inner_t>::value_t>::value_t value_t; +	}; + +	template<typename T, typename SORTABLE = void> +	struct IsSortable +	{ +		static const bool value = false; +	}; + +	template<typename T> +	struct IsSortable<T, typename T::is_tag_t> +	{ +		static const bool value = true; +	}; + +	template<typename ITEM, typename REST, bool IS_REST_SORTABLE = IsSortable<REST>::value> +	struct InsertInto +	{ +		typedef typename ITEM::template Cons<REST>::value_t value_t; +	}; + +	template<typename ITEM, typename REST> +	struct InsertInto <ITEM, REST, true> +	{ +		typedef typename Swap<ITEM, REST>::value_t value_t; +	}; + +	template<typename T, bool SORTABLE = IsSortable<T>::value> +	struct Sorted +	{ +		typedef T value_t; +	}; + +	template<typename T> +	struct Sorted <T, true> +	{ +		typedef typename InsertInto<T, typename Sorted<typename T::inner_t>::value_t>::value_t value_t; +	}; +} +  namespace LLInitParam  {  	// used to indicate no matching value to a given name when parsing @@ -43,6 +108,8 @@ namespace LLInitParam  	template<typename T> const T& defaultValue() { static T value; return value; } +	// wraps comparison operator between any 2 values of the same type +	// specialize to handle cases where equality isn't defined well, or at all  	template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value >      struct ParamCompare   	{ @@ -77,24 +144,123 @@ namespace LLInitParam  	// helper functions and classes  	typedef ptrdiff_t param_handle_t; +	struct IS_A_BLOCK {}; +	struct NOT_BLOCK {}; + +	// these templates allow us to distinguish between template parameters +	// that derive from BaseBlock and those that don't +	template<typename T, typename BLOCK_IDENTIFIER = void> +	struct IsBlock +	{ +		typedef NOT_BLOCK value_t; +	}; + +	template<typename T> +	struct IsBlock<T, typename T::baseblock_base_class_t> +	{ +		typedef IS_A_BLOCK value_t; +	}; + +	// ParamValue class directly manages the wrapped value +	// by holding on to a copy (scalar params) +	// or deriving from it (blocks) +	// has specializations for custom value behavior +	// and "tag" values like Lazy and Atomic +	template<typename T, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> +	class ParamValue +	{ +		typedef ParamValue<T, VALUE_IS_BLOCK>	self_t; + +	public: +		typedef T	default_value_t; +		typedef T	value_t; + +		ParamValue(): mValue() {} +		ParamValue(const default_value_t& other) : mValue(other) {} + +		void setValue(const value_t& val) +		{ +			mValue = val; +		} + +		const value_t& getValue() const +		{ +			return mValue; +		} + +		T& getValue() +		{ +			return mValue; +		} + +	protected: +		T mValue; +	}; + +	template<typename T> +	class ParamValue<T, IS_A_BLOCK>  +	:	public T +	{ +		typedef ParamValue<T, IS_A_BLOCK>	self_t; +	public: +		typedef T	default_value_t; +		typedef T	value_t; + +		ParamValue()  +		:	T(), +			mValidated(false) +		{} + +		ParamValue(const default_value_t& other) +			:	T(other), +			mValidated(false) +		{} + +		void setValue(const value_t& val) +		{ +			*this = val; +		} + +		const value_t& getValue() const +		{ +			return *this; +		} + +		T& getValue() +		{ +			return *this; +		} + +	protected: +		mutable bool 	mValidated; // lazy validation flag +	}; +  	// empty default implementation of key cache  	// leverages empty base class optimization  	template <typename T>  	class TypeValues +	:	public ParamValue<typename LLTypeTags::Sorted<T>::value_t>  	{  	private:  		struct Inaccessable{};  	public:  		typedef std::map<std::string, T> value_name_map_t;  		typedef Inaccessable name_t; +		typedef TypeValues<T> type_value_t; +		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t>	param_value_t; +		typedef typename param_value_t::value_t	value_t; + +		TypeValues(const typename param_value_t::value_t& val) +		:	param_value_t(val) +		{}  		void setValueName(const std::string& key) {}  		std::string getValueName() const { return ""; } -		std::string calcValueName(const T& value) const { return ""; } +		std::string calcValueName(const value_t& value) const { return ""; }  		void clearValueName() const {} -		static bool getValueFromName(const std::string& name, T& value) +		static bool getValueFromName(const std::string& name, value_t& value)  		{  			return false;  		} @@ -109,15 +275,39 @@ namespace LLInitParam  			return NULL;  		} +		void assignNamedValue(const Inaccessable& name) +		{} + +		operator const value_t&() const +		{ +			return param_value_t::getValue(); +		} + +		const value_t& operator()() const +		{ +			return param_value_t::getValue(); +		} +  		static value_name_map_t* getValueNames() {return NULL;}  	}; -	template <typename T, typename DERIVED_TYPE = TypeValues<T> > +	// helper class to implement name value lookups +	// and caching of last used name +	template <typename T, typename DERIVED_TYPE = TypeValues<T>, bool IS_SPECIALIZED = true >  	class TypeValuesHelper +	:	public ParamValue<typename LLTypeTags::Sorted<T>::value_t>  	{ +		typedef TypeValuesHelper<T, DERIVED_TYPE, IS_SPECIALIZED> self_t;  	public:  		typedef typename std::map<std::string, T> value_name_map_t;  		typedef std::string name_t; +		typedef self_t type_value_t; +		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; +		typedef typename param_value_t::value_t	value_t; + +		TypeValuesHelper(const typename param_value_t::value_t& val) +		:	param_value_t(val) +		{}  		//TODO: cache key by index to save on param block size  		void setValueName(const std::string& value_name)  @@ -130,7 +320,7 @@ namespace LLInitParam  			return mValueName;   		} -		std::string calcValueName(const T& value) const +		std::string calcValueName(const value_t& value) const  		{  			value_name_map_t* map = getValueNames();  			for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end(); @@ -151,7 +341,7 @@ namespace LLInitParam  			mValueName.clear();  		} -		static bool getValueFromName(const std::string& name, T& value) +		static bool getValueFromName(const std::string& name, value_t& value)  		{  			value_name_map_t* map = getValueNames();  			typename value_name_map_t::iterator found_it = map->find(name); @@ -193,18 +383,90 @@ namespace LLInitParam  			return &sValues;  		} -		static void declare(const std::string& name, const T& value) +		static void declare(const std::string& name, const value_t& value)  		{  			(*getValueNames())[name] = value;  		} +		void operator ()(const std::string& name) +		{ +			*this = name; +		} + +		void assignNamedValue(const std::string& name) +		{ +			if (getValueFromName(name, param_value_t::getValue())) +			{ +				setValueName(name); +			} +		} + +		operator const value_t&() const +		{ +			return param_value_t::getValue(); +		} + +		const value_t& operator()() const +		{ +			return param_value_t::getValue(); +		} +  	protected: -		static void getName(const std::string& name, const T& value) +		static void getName(const std::string& name, const value_t& value)  		{}  		mutable std::string	mValueName;  	}; +	// string types can support custom named values, but need +	// to disambiguate in code between a string that is a named value +	// and a string that is a name +	template <typename DERIVED_TYPE> +	class TypeValuesHelper<std::string, DERIVED_TYPE, true> +	:	public TypeValuesHelper<std::string, DERIVED_TYPE, false> +	{ +	public: +		typedef TypeValuesHelper<std::string, DERIVED_TYPE, true> self_t; +		typedef TypeValuesHelper<std::string, DERIVED_TYPE, false> base_t; +		typedef std::string value_t; +		typedef std::string name_t; +		typedef self_t type_value_t; + +		TypeValuesHelper(const std::string& val) +		:	TypeValuesHelper(val) +		{} + +		void operator ()(const std::string& name) +		{ +			*this = name; +		} + +		self_t& operator =(const std::string& name) +		{ +			if (base_t::getValueFromName(name, ParamValue<std::string>::getValue())) +			{ +				base_t::setValueName(name); +			} +			else +			{ +				ParamValue<std::string>::setValue(name); +			} +			return *this; +		} +		 +		operator const value_t&() const +		{ +			return ParamValue<std::string>::getValue(); +		} + +		const value_t& operator()() const +		{ +			return ParamValue<std::string>::getValue(); +		} + +	}; + +	// parser base class with mechanisms for registering readers/writers/inspectors of different types  	class Parser  	{  		LOG_CLASS(Parser); @@ -354,6 +616,7 @@ namespace LLInitParam  		} EInitializationState;  		void aggregateBlockData(BlockDescriptor& src_block_data); +		void addParam(ParamDescriptorPtr param, const char* name);  		typedef boost::unordered_map<const std::string, ParamDescriptorPtr>						param_map_t;   		typedef std::vector<ParamDescriptorPtr>													param_list_t;  @@ -369,48 +632,58 @@ namespace LLInitParam  		class BaseBlock*				mCurrentBlockPtr;		// pointer to block currently being constructed  	}; -	class BaseBlock -	{ -	public:  		//TODO: implement in terms of owned_ptr  		template<typename T> -		class Lazy +	class LazyValue  		{  		public: -			Lazy() +		LazyValue()  				: mPtr(NULL)  			{} -			~Lazy() +		~LazyValue()  			{  				delete mPtr;  			} -			Lazy(const Lazy& other) +		LazyValue(const T& value)  			{ -				if (other.mPtr) +			mPtr = new T(value); +		} + +		LazyValue(const LazyValue& other) +		:	mPtr(NULL)  				{ -					mPtr = new T(*other.mPtr); +			*this = other;  				} -				else + +		LazyValue& operator = (const LazyValue& other) +		{ +			if (!other.mPtr)  				{ +				delete mPtr;  					mPtr = NULL;  				} -			} - -			Lazy<T>& operator = (const Lazy<T>& other) +			else  			{ -				if (other.mPtr) +				if (!mPtr)  				{  					mPtr = new T(*other.mPtr);  				}  				else  				{ -					mPtr = NULL; +					*mPtr = *(other.mPtr); +				}  				}  				return *this;  			} +		bool operator==(const LazyValue& other) const +		{ +			if (empty() || other.empty()) return false; +			return *mPtr == *other.mPtr; +		} +  			bool empty() const  			{  				return mPtr == NULL; @@ -418,18 +691,29 @@ namespace LLInitParam  			void set(const T& other)  			{ -				delete mPtr; +			if (!mPtr) +			{  				mPtr = new T(other);  			} +			else +			{ +				*mPtr = other; +			} +		}  			const T& get() const  			{ -				return ensureInstance(); +			return *ensureInstance();  			}  			T& get()  			{ -				return ensureInstance(); +			return *ensureInstance(); +		} + +		operator const T&() const +		{  +			return get();   			}  		private: @@ -444,13 +728,50 @@ namespace LLInitParam  			}  		private: -			// if you get a compilation error with this, that means you are using a forward declared struct for T -			// unfortunately, the type traits we rely on don't work with forward declared typed -			//static const int dummy = sizeof(T);  			mutable T* mPtr;  		}; +	// root class of all parameter blocks + +	class BaseBlock +	{ +	public: +		// lift block tags into baseblock namespace so derived classes do not need to qualify them +		typedef LLInitParam::IS_A_BLOCK IS_A_BLOCK; +		typedef LLInitParam::NOT_BLOCK NOT_A_BLOCK; + +		template<typename T> +		struct Sequential : public LLTypeTags::TypeTagBase<T, 2> +		{ +			template <typename S> struct Cons { typedef Sequential<ParamValue<S> > value_t; }; +			template <typename S> struct Cons<Sequential<S> > { typedef Sequential<S> value_t; }; +		}; + +		template<typename T> +		struct Atomic : public LLTypeTags::TypeTagBase<T, 1> +		{ +			template <typename S> struct Cons { typedef Atomic<ParamValue<S> > value_t; }; +			template <typename S> struct Cons<Atomic<S> > { typedef Atomic<S> value_t; }; +		}; + +		template<typename T, typename BLOCK_T = typename IsBlock<T>::value_t > +		struct Lazy : public LLTypeTags::TypeTagBase<T, 0> +		{ +			template <typename S> struct Cons +			{ +				typedef Lazy<ParamValue<S, BLOCK_T>, BLOCK_T> value_t; +			}; +			template <typename S> struct Cons<Lazy<S, IS_A_BLOCK> > +			{ +				typedef Lazy<S, IS_A_BLOCK> value_t; +			}; +			template <typename S> struct Cons<Lazy<S, NOT_A_BLOCK> > +			{ +				typedef Lazy<S, BLOCK_T> value_t; +			}; +		}; +  		// "Multiple" constraint types, put here in root class to avoid ambiguity during use  		struct AnyAmount  		{ @@ -520,8 +841,8 @@ namespace LLInitParam  		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;  		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const; -		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } -		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } +		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } +		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }  		// take all provided params from other and apply to self  		bool overwriteFrom(const BaseBlock& other) @@ -535,10 +856,17 @@ namespace LLInitParam  			return false;  		} -		static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name); -  		ParamDescriptorPtr findParamDescriptor(const Param& param); +		// take all provided params from other and apply to self +		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); + +		static BlockDescriptor& getBlockDescriptor() +		{ +			static BlockDescriptor sBlockDescriptor; +			return sBlockDescriptor; +		} +  	protected:  		void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size); @@ -547,25 +875,11 @@ namespace LLInitParam  		{  			return mergeBlock(block_data, source, overwrite);  		} -		// take all provided params from other and apply to self -		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); - -		static BlockDescriptor& selfBlockDescriptor() -		{ -			static BlockDescriptor sBlockDescriptor; -			return sBlockDescriptor; -		}  	private:  		const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;  	}; -	template<typename T> -	struct ParamCompare<BaseBlock::Lazy<T>, false > -	{ -		static bool equals(const BaseBlock::Lazy<T>& a, const BaseBlock::Lazy<T>& b) { return !a.empty() || !b.empty(); } -	}; -  	class Param  	{  	public: @@ -594,251 +908,63 @@ namespace LLInitParam  			// get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class  			return *const_cast<BaseBlock*>  				(reinterpret_cast<const BaseBlock*> -					(my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset)); -		} - -	private: -		friend class BaseBlock; - -		U32		mEnclosingBlockOffset:31; -		U32		mIsProvided:1; - -	}; - -	// these templates allow us to distinguish between template parameters -	// that derive from BaseBlock and those that don't -	template<typename T, typename Void = void> -	struct IsBlock -	{ -		static const bool value = false; -		struct EmptyBase {}; -		typedef EmptyBase base_class_t; -	}; - -	template<typename T> -	struct IsBlock<T, typename T::baseblock_base_class_t> -	{ -		static const bool value = true; -		typedef BaseBlock base_class_t; -	}; - -	template<typename T> -	struct IsBlock<BaseBlock::Lazy<T>, typename T::baseblock_base_class_t > -	{ -		static const bool value = true; -		typedef BaseBlock base_class_t; -	}; - -	template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value> -	class ParamValue : public NAME_VALUE_LOOKUP -	{ -	public: -		typedef const T&							value_assignment_t; -		typedef T									value_t; -		typedef ParamValue<T, NAME_VALUE_LOOKUP, VALUE_IS_BLOCK>	self_t; - -		ParamValue(): mValue() {} -		ParamValue(value_assignment_t other) : mValue(other) {} - -		void setValue(value_assignment_t val) -		{ -			mValue = val; -		} - -		value_assignment_t getValue() const -		{ -			return mValue; -		} - -		T& getValue() -		{ -			return mValue; -		} - -		operator value_assignment_t() const -		{ -			return mValue; -		} - -		value_assignment_t operator()() const -		{ -			return mValue; -		} - -		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			*this = name; -		} - -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			if (NAME_VALUE_LOOKUP::getValueFromName(name, mValue)) -			{ -				setValueName(name); -			} - -			return *this; -		} - -	protected: -		T mValue; -	}; - -	template<typename T, typename NAME_VALUE_LOOKUP> -	class ParamValue<T, NAME_VALUE_LOOKUP, true>  -	:	public T, -		public NAME_VALUE_LOOKUP -	{ -	public: -		typedef const T&							value_assignment_t; -		typedef T									value_t; -		typedef ParamValue<T, NAME_VALUE_LOOKUP, true>	self_t; - -		ParamValue()  -		:	T(), -			mValidated(false) -		{} - -		ParamValue(value_assignment_t other) -		:	T(other), -			mValidated(false) -		{} - -		void setValue(value_assignment_t val) -		{ -			*this = val; -		} - -		value_assignment_t getValue() const -		{ -			return *this; -		} - -		T& getValue() -		{ -			return *this; -		} - -		operator value_assignment_t() const -		{ -			return *this; -		} -		 -		value_assignment_t operator()() const -		{ -			return *this; -		} - -		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			*this = name; -		} - -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			if (NAME_VALUE_LOOKUP::getValueFromName(name, *this)) -			{ -				setValueName(name); -			} - -			return *this; -		} - -	protected: -		mutable bool 	mValidated; // lazy validation flag -	}; - -	template<typename NAME_VALUE_LOOKUP> -	class ParamValue<std::string, NAME_VALUE_LOOKUP, false> -	: public NAME_VALUE_LOOKUP -	{ -	public: -		typedef const std::string&	value_assignment_t; -		typedef std::string			value_t; -		typedef ParamValue<std::string, NAME_VALUE_LOOKUP, false>	self_t; - -		ParamValue(): mValue() {} -		ParamValue(value_assignment_t other) : mValue(other) {} - -		void setValue(value_assignment_t val) -		{ -			if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue)) -			{ -				NAME_VALUE_LOOKUP::setValueName(val); -			} -			else -			{ -				mValue = val; -			} -		} - -		value_assignment_t getValue() const -		{ -			return mValue; +					(my_addr - (ptrdiff_t)getEnclosingBlockOffset()));  		} -		std::string& getValue() +		U32 getEnclosingBlockOffset() const  		{ -			return mValue; +			return ((U32)mEnclosingBlockOffsetHigh << 16) | (U32)mEnclosingBlockOffsetLow;  		} -		operator value_assignment_t() const -		{ -			return mValue; -		} +	private: +		friend class BaseBlock; -		value_assignment_t operator()() const -		{ -			return mValue; -		} +		//24 bits for member offset field and 1 bit for provided flag +		U16		mEnclosingBlockOffsetLow; +		U8		mEnclosingBlockOffsetHigh:7; +		U8		mIsProvided:1; -	protected: -		std::string mValue;  	}; -  	template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >  	struct ParamIterator  	{ -		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator		const_iterator; -		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator			iterator; +		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::const_iterator	const_iterator; +		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::iterator			iterator;  	}; -	// specialize for custom parsing/decomposition of specific classes -	// e.g. TypedParam<LLRect> has left, top, right, bottom, etc... +	// wrapper for parameter with a known type +	// specialized to handle 4 cases: +	// simple "scalar" value +	// parameter that is itself a block +	// multiple scalar values, stored in a vector +	// multiple blocks, stored in a vector  	template<typename	T,  			typename	NAME_VALUE_LOOKUP = TypeValues<T>,  			bool		HAS_MULTIPLE_VALUES = false, -			bool		VALUE_IS_BLOCK = IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> +			typename	VALUE_IS_BLOCK = typename IsBlock<ParamValue<typename LLTypeTags::Sorted<T>::value_t> >::value_t>  	class TypedParam   	:	public Param,  -		public ParamValue<T, NAME_VALUE_LOOKUP> +		public NAME_VALUE_LOOKUP::type_value_t  	{ +	protected: +		typedef	TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK>	self_t; +		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t>						param_value_t; +		typedef typename param_value_t::default_value_t									default_value_t; +		typedef typename NAME_VALUE_LOOKUP::type_value_t								named_value_t;  	public: -		typedef	TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK>		self_t; -		typedef ParamValue<T, NAME_VALUE_LOOKUP>											param_value_t; -		typedef typename param_value_t::value_assignment_t				value_assignment_t; -		typedef NAME_VALUE_LOOKUP															name_value_lookup_t; +		typedef typename param_value_t::value_t											value_t; -		using param_value_t::operator(); +		using named_value_t::operator(); -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  -		:	Param(block_descriptor.mCurrentBlockPtr) +		TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) +		:	Param(block_descriptor.mCurrentBlockPtr), +			named_value_t(value)  		{  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ - 				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func, -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name);  			} - -			setValue(value);  		}   		bool isProvided() const { return Param::anyProvided(); } @@ -857,14 +983,15 @@ namespace LLInitParam  				}  				// try to parse a known named value -				if(name_value_lookup_t::valueNamesExist()) +				if(named_value_t::valueNamesExist())  				{  					// try to parse a known named value  					std::string name;  					if (parser.readValue(name))  					{  						// try to parse a per type named value -						if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + +						if (named_value_t::getValueFromName(name, typed_param.getValue()))  						{  							typed_param.setValueName(name);  							typed_param.setProvided(); @@ -904,7 +1031,9 @@ namespace LLInitParam  				if (!parser.writeValue(typed_param.getValue(), name_stack))   				{  					std::string calculated_key = typed_param.calcValueName(typed_param.getValue()); -					if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key)) +					if (calculated_key.size()  +						&& (!diff_param  +							|| !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key)))  					{  						parser.writeValue(calculated_key, name_stack);  					} @@ -917,22 +1046,23 @@ namespace LLInitParam  			// tell parser about our actual type  			parser.inspectValue<T>(name_stack, min_count, max_count, NULL);  			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) -			if (name_value_lookup_t::getPossibleValues()) +			if (named_value_t::getPossibleValues())  			{ -				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());  			}  		} -		void set(value_assignment_t val, bool flag_as_provided = true) +		void set(const value_t& val, bool flag_as_provided = true)  		{ -			param_value_t::clearValueName(); +			named_value_t::clearValueName();  			setValue(val);  			setProvided(flag_as_provided);  		} -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) +		self_t& operator =(const typename named_value_t::name_t& name)  		{ -			return static_cast<self_t&>(param_value_t::operator =(name)); +			named_value_t::assignNamedValue(name); +			return *this;  		}  	protected: @@ -957,37 +1087,43 @@ namespace LLInitParam  			}  			return false;  		} +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func, +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	};  	// parameter that is a block  	template <typename T, typename NAME_VALUE_LOOKUP> -	class TypedParam<T, NAME_VALUE_LOOKUP, false, true>  +	class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>   	:	public Param, -		public ParamValue<T, NAME_VALUE_LOOKUP> +		public NAME_VALUE_LOOKUP::type_value_t  	{ +	protected: +		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t>	param_value_t; +		typedef typename param_value_t::default_value_t				default_value_t; +		typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>	self_t; +		typedef typename NAME_VALUE_LOOKUP::type_value_t			named_value_t;  	public: -		typedef ParamValue<T, NAME_VALUE_LOOKUP>				param_value_t; -		typedef typename param_value_t::value_assignment_t		value_assignment_t; -		typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true>	self_t; -		typedef NAME_VALUE_LOOKUP								name_value_lookup_t; +		using named_value_t::operator(); +		typedef typename param_value_t::value_t						value_t; -		using param_value_t::operator(); - -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) +		TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  		:	Param(block_descriptor.mCurrentBlockPtr), -			param_value_t(value) +			named_value_t(value)  		{  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func,  -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name);  			}  		} @@ -1002,14 +1138,14 @@ namespace LLInitParam  				return true;  			} -			if(name_value_lookup_t::valueNamesExist()) +			if(named_value_t::valueNamesExist())  			{  				// try to parse a known named value  				std::string name;  				if (parser.readValue(name))  				{  					// try to parse a per type named value -					if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) +					if (named_value_t::getValueFromName(name, typed_param.getValue()))  					{  						typed_param.setValueName(name);  						typed_param.setProvided(); @@ -1034,9 +1170,9 @@ namespace LLInitParam  			std::string key = typed_param.getValueName();  			if (!key.empty())  			{ -				if (!parser.writeValue(key, name_stack)) +				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))  				{ -					return; +					parser.writeValue(key, name_stack);  				}  			}  			else @@ -1047,8 +1183,16 @@ namespace LLInitParam  		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)  		{ -			// I am a param that is also a block, so just recurse into my contents  			const self_t& typed_param = static_cast<const self_t&>(param); + +			// tell parser about our actual type +			parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL); +			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) +			if (named_value_t::getPossibleValues()) +			{ +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); +			} +  			typed_param.inspectBlock(parser, name_stack, min_count, max_count);  		} @@ -1066,32 +1210,34 @@ namespace LLInitParam  		}  		// assign block contents to this param-that-is-a-block -		void set(value_assignment_t val, bool flag_as_provided = true) +		void set(const value_t& val, bool flag_as_provided = true)  		{  			setValue(val); -			param_value_t::clearValueName(); +			named_value_t::clearValueName();  			// force revalidation of block  			// next call to isProvided() will update provision status based on validity  			param_value_t::mValidated = false;  			setProvided(flag_as_provided);  		} -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) +		self_t& operator =(const typename named_value_t::name_t& name)  		{ -			return static_cast<self_t&>(param_value_t::operator =(name)); +			named_value_t::assignNamedValue(name); +			return *this;  		}  		// propagate changed status up to enclosing block  		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)  		{   			param_value_t::paramChanged(changed_param, user_provided); +  			if (user_provided)  			{  				// a child param has been explicitly changed  				// so *some* aspect of this block is now provided  				param_value_t::mValidated = false;  				setProvided(); -				param_value_t::clearValueName(); +				named_value_t::clearValueName();  			}  			else  			{ @@ -1115,7 +1261,7 @@ namespace LLInitParam  			if (src_typed_param.anyProvided())  			{ -				if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite)) +				if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::getBlockDescriptor(), src_typed_param, overwrite))  				{  					dst_typed_param.clearValueName();  					dst_typed_param.setProvided(true); @@ -1124,38 +1270,46 @@ namespace LLInitParam  			}  			return false;  		} + +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func,  +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	};  	// container of non-block parameters  	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> -	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>  +	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK>   	:	public Param  	{ +	protected: +		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK>		self_t; +		typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t>	param_value_t; +		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t>	container_t; +		typedef container_t														default_value_t; +		typedef typename NAME_VALUE_LOOKUP::type_value_t						named_value_t; +		  	public: -		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>		self_t; -		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>					param_value_t; -		typedef typename std::vector<param_value_t>							container_t; -		typedef const container_t&											value_assignment_t; -  		typedef typename param_value_t::value_t								value_t; -		typedef NAME_VALUE_LOOKUP											name_value_lookup_t; -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  +		TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  		:	Param(block_descriptor.mCurrentBlockPtr)  		{  			std::copy(value.begin(), value.end(), std::back_inserter(mValues));  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func, -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name); +  			}  		}  @@ -1176,14 +1330,14 @@ namespace LLInitParam  				}  				// try to parse a known named value -				if(name_value_lookup_t::valueNamesExist()) +				if(named_value_t::valueNamesExist())  				{  					// try to parse a known named value  					std::string name;  					if (parser.readValue(name))  					{  						// try to parse a per type named value -						if (name_value_lookup_t::getValueFromName(name, value)) +						if (named_value_t::getValueFromName(name, value))  						{  							typed_param.add(value);  							typed_param.mValues.back().setValueName(name); @@ -1234,13 +1388,13 @@ namespace LLInitParam  		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)  		{  			parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL); -			if (name_value_lookup_t::getPossibleValues()) +			if (named_value_t::getPossibleValues())  			{ -				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());  			}  		} -		void set(value_assignment_t val, bool flag_as_provided = true) +		void set(const container_t& val, bool flag_as_provided = true)  		{  			mValues = val;  			setProvided(flag_as_provided); @@ -1248,26 +1402,24 @@ namespace LLInitParam  		param_value_t& add()  		{ -			mValues.push_back(param_value_t(value_t())); +			mValues.push_back(value_t());  			Param::setProvided();  			return mValues.back();  		}  		self_t& add(const value_t& item)  		{ -			param_value_t param_value; -			param_value.setValue(item); -			mValues.push_back(param_value); +			mValues.push_back(item);  			setProvided();  			return *this;  		} -		self_t& add(const typename name_value_lookup_t::name_t& name) +		self_t& add(const typename named_value_t::name_t& name)  		{  			value_t value;  			// try to parse a per type named value -			if (name_value_lookup_t::getValueFromName(name, value)) +			if (named_value_t::getValueFromName(name, value))  			{  				add(value);  				mValues.back().setValueName(name); @@ -1277,9 +1429,9 @@ namespace LLInitParam  		}  		// implicit conversion -		operator value_assignment_t() const { return mValues; }  +		operator const container_t&() const { return mValues; }   		// explicit conversion		 -		value_assignment_t operator()() const { return mValues; } +		const container_t& operator()() const { return mValues; }  		typedef typename container_t::iterator iterator;  		typedef typename container_t::const_iterator const_iterator; @@ -1320,37 +1472,46 @@ namespace LLInitParam  		}  		container_t		mValues; + +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func, +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	};  	// container of block parameters  	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> -	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>  +	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>   	:	public Param  	{ +	protected: +		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>		self_t; +		typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t>	param_value_t; +		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t>	container_t; +		typedef typename NAME_VALUE_LOOKUP::type_value_t						named_value_t; +		typedef container_t														default_value_t; +		typedef typename container_t::iterator									iterator; +		typedef typename container_t::const_iterator							const_iterator;  	public: -		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>	self_t; -		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>				param_value_t; -		typedef typename std::vector<param_value_t>						container_t; -		typedef const container_t&										value_assignment_t;  		typedef typename param_value_t::value_t							value_t; -		typedef NAME_VALUE_LOOKUP										name_value_lookup_t; -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  +		TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  		:	Param(block_descriptor.mCurrentBlockPtr)  		{  			std::copy(value.begin(), value.end(), back_inserter(mValues));  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func, -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name);  			}  		}  @@ -1375,14 +1536,14 @@ namespace LLInitParam  				typed_param.setProvided();  				return true;  			} -			else if(name_value_lookup_t::valueNamesExist()) +			else if(named_value_t::valueNamesExist())  			{  				// try to parse a known named value  				std::string name;  				if (parser.readValue(name))  				{  					// try to parse a per type named value -					if (name_value_lookup_t::getValueFromName(name, value.getValue())) +					if (named_value_t::getValueFromName(name, value.getValue()))  					{  						typed_param.mValues.back().setValueName(name);  						typed_param.setProvided(); @@ -1427,11 +1588,20 @@ namespace LLInitParam  		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)  		{ -			// I am a vector of blocks, so describe my contents recursively -			param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count); +			const param_value_t& value_param = param_value_t(value_t()); + +			// tell parser about our actual type +			parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL); +			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) +			if (named_value_t::getPossibleValues()) +			{ +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());  		} -		void set(value_assignment_t val, bool flag_as_provided = true) +			value_param.inspectBlock(parser, name_stack, min_count, max_count); +		} + +		void set(const container_t& val, bool flag_as_provided = true)  		{  			mValues = val;  			setProvided(flag_as_provided); @@ -1451,12 +1621,12 @@ namespace LLInitParam  			return *this;  		} -		self_t& add(const typename name_value_lookup_t::name_t& name) +		self_t& add(const typename named_value_t::name_t& name)  		{  			value_t value;  			// try to parse a per type named value -			if (name_value_lookup_t::getValueFromName(name, value)) +			if (named_value_t::getValueFromName(name, value))  			{  				add(value);  				mValues.back().setValueName(name); @@ -1465,12 +1635,10 @@ namespace LLInitParam  		}  		// implicit conversion -		operator value_assignment_t() const { return mValues; }  +		operator const container_t&() const { return mValues; }   		// explicit conversion -		value_assignment_t operator()() const { return mValues; } +		const container_t& operator()() const { return mValues; } -		typedef typename container_t::iterator iterator; -		typedef typename container_t::const_iterator const_iterator;  		iterator begin() { return mValues.begin(); }  		iterator end() { return mValues.end(); }  		const_iterator begin() const { return mValues.begin(); } @@ -1517,6 +1685,20 @@ namespace LLInitParam  		}  		container_t			mValues; + +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func, +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	};  	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> @@ -1531,13 +1713,13 @@ namespace LLInitParam  		// take all provided params from other and apply to self  		bool overwriteFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true);  		}  		// take all provided params that are not already provided, and apply to self  		bool fillFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false);  		}  		bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) @@ -1555,7 +1737,7 @@ namespace LLInitParam  		bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite)  		{  			mCurChoice = other.mCurChoice; -			return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite); +			return base_block_t::mergeBlock(getBlockDescriptor(), other, overwrite);  		}  		// clear out old choice when param has changed @@ -1576,38 +1758,38 @@ namespace LLInitParam  			base_block_t::paramChanged(changed_param, user_provided);  		} -		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } -		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } +		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } +		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }  	protected:  		ChoiceBlock()  		:	mCurChoice(0)  		{ -			BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); +			BaseBlock::init(getBlockDescriptor(), base_block_t::getBlockDescriptor(), sizeof(DERIVED_BLOCK));  		}  		// Alternatives are mutually exclusive wrt other Alternatives in the same block.    		// One alternative in a block will always have isChosen() == true.  		// At most one alternative in a block will have isProvided() == true. -		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false>  		{ +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false>	super_t; +			typedef typename super_t::value_t				value_t; +			typedef typename super_t::default_value_t		default_value_t; +  		public:  			friend class ChoiceBlock<DERIVED_BLOCK>; -			typedef Alternative<T, NAME_VALUE_LOOKUP>									self_t; -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t; -			typedef typename super_t::value_assignment_t								value_assignment_t; -  			using super_t::operator =; -			explicit Alternative(const char* name = "", value_assignment_t val = defaultValue<T>()) -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1), +			explicit Alternative(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1),  				mOriginalValue(val)  			{  				// assign initial choice to first declared option -				DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr); -				if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) +				DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr); +				if (LL_UNLIKELY(DERIVED_BLOCK::getBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING))  				{  					if(blockp->mCurChoice == 0)  					{ @@ -1621,27 +1803,27 @@ namespace LLInitParam  				static_cast<enclosing_block_t&>(Param::enclosingBlock()).paramChanged(*this, true);  			} -			void chooseAs(value_assignment_t val) +			void chooseAs(const value_t& val)  			{  				super_t::set(val);  			} -			void operator =(value_assignment_t val) +			void operator =(const value_t& val)  			{  				super_t::set(val);  			} -			void operator()(typename super_t::value_assignment_t val)  +			void operator()(const value_t& val)   			{   				super_t::set(val);  			} -			operator value_assignment_t() const  +			operator const value_t&() const   			{  				return (*this)();  			}  -			value_assignment_t operator()() const  +			const value_t& operator()() const   			{   				if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)  				{ @@ -1656,11 +1838,11 @@ namespace LLInitParam  			}  		private: -			T			mOriginalValue; +			default_value_t mOriginalValue;  		}; -	protected: -		static BlockDescriptor& selfBlockDescriptor() +	public: +		static BlockDescriptor& getBlockDescriptor()  		{  			static BlockDescriptor sBlockDescriptor;  			return sBlockDescriptor; @@ -1680,6 +1862,8 @@ namespace LLInitParam  	:	public BASE_BLOCK  	{  		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	self_t; + +	protected:  		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	block_t;  	public: @@ -1688,80 +1872,82 @@ namespace LLInitParam  		// take all provided params from other and apply to self  		bool overwriteFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true);  		}  		// take all provided params that are not already provided, and apply to self  		bool fillFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false);  		} -		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } -		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } +		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } +		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }  	protected:  		Block()  		{  			//#pragma message("Parsing LLInitParam::Block") -			BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); +			BaseBlock::init(getBlockDescriptor(), BASE_BLOCK::getBlockDescriptor(), sizeof(DERIVED_BLOCK));  		}  		//  		// Nested classes for declaring parameters  		// -		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>  		{ -		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t; -			typedef typename super_t::value_assignment_t								value_assignment_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false>		super_t; +			typedef typename super_t::value_t					value_t; +			typedef typename super_t::default_value_t			default_value_t; +		public:  			using super_t::operator();  			using super_t::operator =; -			explicit Optional(const char* name = "", value_assignment_t val = defaultValue<T>()) -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1) +			explicit Optional(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1)  			{  				//#pragma message("Parsing LLInitParam::Block::Optional")  			} -			Optional& operator =(value_assignment_t val) +			Optional& operator =(const value_t& val)  			{  				set(val);  				return *this;  			} -			DERIVED_BLOCK& operator()(value_assignment_t val) +			DERIVED_BLOCK& operator()(const value_t& val)  			{  				super_t::set(val);  				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());  			}  		}; -		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>  		{ -		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false>		super_t;  			typedef Mandatory<T, NAME_VALUE_LOOKUP>										self_t; -			typedef typename super_t::value_assignment_t								value_assignment_t; +			typedef typename super_t::value_t					value_t; +			typedef typename super_t::default_value_t			default_value_t; +		public:  			using super_t::operator();  			using super_t::operator =;  			// mandatory parameters require a name to be parseable -			explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue<T>()) -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1) +			explicit Mandatory(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, &validate, 1, 1)  			{} -			Mandatory& operator =(value_assignment_t val) +			Mandatory& operator =(const value_t& val)  			{  				set(val);  				return *this;  			} -			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) +			DERIVED_BLOCK& operator()(const value_t& val)  			{  				super_t::set(val);  				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1775,28 +1961,29 @@ namespace LLInitParam  		}; -		template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>  		{ -		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>	super_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, true>	super_t;  			typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP>							self_t;  			typedef typename super_t::container_t									container_t; -			typedef typename super_t::value_assignment_t							value_assignment_t; +			typedef typename super_t::value_t				value_t; + +		public:  			typedef typename super_t::iterator										iterator;  			typedef typename super_t::const_iterator								const_iterator;  			explicit Multiple(const char* name = "") -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount)  			{} -			Multiple& operator =(value_assignment_t val) +			Multiple& operator =(const container_t& val)  			{  				set(val);  				return *this;  			} -			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) +			DERIVED_BLOCK& operator()(const container_t& val)  			{  				super_t::set(val);  				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1813,9 +2000,9 @@ namespace LLInitParam  		{  		public:  			explicit Deprecated(const char* name) -			:	Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr) +			:	Param(DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr)  			{ -				BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); +				BlockDescriptor& block_descriptor = DERIVED_BLOCK::getBlockDescriptor();  				if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  				{  					ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( @@ -1826,7 +2013,7 @@ namespace LLInitParam  													NULL,  													NULL,   													0, S32_MAX)); -					BaseBlock::addParam(block_descriptor, param_descriptor, name); +					block_descriptor.addParam(param_descriptor, name);  				}  			} @@ -1846,16 +2033,17 @@ namespace LLInitParam  		// different semantics for documentation purposes, but functionally identical  		typedef Deprecated Ignored; -	protected: -		static BlockDescriptor& selfBlockDescriptor() +	public: +		static BlockDescriptor& getBlockDescriptor()  		{  			static BlockDescriptor sBlockDescriptor;  			return sBlockDescriptor;  		} -		template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, bool is_block> +	protected: +		template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, typename is_block>  		void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param,  -			typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_assignment_t value) +			const typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_t& value)  		{  			if (!param.isProvided())  			{ @@ -1865,202 +2053,414 @@ namespace LLInitParam  	}; -	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> -	class BatchBlock -	:	public Block<DERIVED_BLOCK, BASE_BLOCK> +	template<typename T, typename BLOCK_T> +	struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::IS_A_BLOCK>, BLOCK_T >, void> +	{ +		typedef IS_A_BLOCK value_t; +	}; + +	template<typename T, typename BLOCK_T> +	struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::NOT_A_BLOCK>, BLOCK_T >, void> +	{ +		typedef NOT_BLOCK value_t; +	}; + +	template<typename T, typename BLOCK_IDENTIFIER> +	struct IsBlock<ParamValue<BaseBlock::Atomic<T>, typename IsBlock<BaseBlock::Atomic<T> >::value_t >, BLOCK_IDENTIFIER> +	{ +		typedef typename IsBlock<T>::value_t value_t; +	}; + +	template<typename T, typename BLOCK_IDENTIFIER> +	struct IsBlock<ParamValue<BaseBlock::Sequential<T>, typename IsBlock<BaseBlock::Sequential<T> >::value_t >, BLOCK_IDENTIFIER>  	{ +		typedef typename IsBlock<T>::value_t value_t; +	}; + + +	template<typename T> +	struct InnerMostType +	{ +		typedef T value_t; +	}; + +	template<typename T> +	struct InnerMostType<ParamValue<T, NOT_BLOCK> > +	{ +		typedef typename InnerMostType<T>::value_t value_t; +	}; + +	template<typename T> +	struct InnerMostType<ParamValue<T, IS_A_BLOCK> > +	{ +		typedef typename InnerMostType<T>::value_t value_t; +	}; + +	template<typename T, typename BLOCK_T> +	class ParamValue <BaseBlock::Atomic<T>, BLOCK_T> +	{ +		typedef ParamValue <BaseBlock::Atomic<T>, BLOCK_T> self_t; +  	public: -		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> self_t; -		typedef Block<DERIVED_BLOCK, BASE_BLOCK> super_t; +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef T									default_value_t; -		BatchBlock() +		ParamValue() +		:	mValue(), +			mValidated(false) +		{} + +		ParamValue(const default_value_t& value) +		:	mValue(value), +			mValidated(false)  		{} +		void setValue(const value_t& val) +		{ +			mValue.setValue(val); +		} + +		const value_t& getValue() const +		{ +			return mValue.getValue(); +		} + +		value_t& getValue() +		{ +			return mValue.getValue(); +		} +  		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)  		{  			if (new_name)  			{ -				// reset block -				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue(); +				resetToDefault(); +			} +			return mValue.deserializeBlock(p, name_stack_range, new_name);  			} -			return super_t::deserializeBlock(p, name_stack_range, new_name); + +		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const +		{ +			const BaseBlock* base_block = diff_block +				? &(diff_block->mValue) +				: NULL; +			mValue.serializeBlock(p, name_stack, base_block);  		} -		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) +		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const +		{ +			return mValue.inspectBlock(p, name_stack, min_count, max_count); +		} + +		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)  		{  			if (overwrite)  			{ -				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue(); -				// merge individual parameters into destination -				return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite); +				resetToDefault(); +				return mValue.mergeBlock(block_data, source.getValue(), overwrite);  			}  			return false;  		} -	protected: -		static const DERIVED_BLOCK& defaultBatchValue() + +		bool validateBlock(bool emit_errors = true) const +		{ +			return mValue.validateBlock(emit_errors); +		} + +		static BlockDescriptor& getBlockDescriptor() +		{ +			return value_t::getBlockDescriptor(); +		} + + +		mutable bool 	mValidated; // lazy validation flag + +	private: +		void resetToDefault()  		{ -			static DERIVED_BLOCK default_value; -			return default_value; +			static T default_value; +			mValue = default_value;  		} + +		T	mValue;  	}; -	// FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class -	// and not the derived class with the actual params -	template<typename DERIVED_BLOCK, -			typename BASE_BLOCK, -			typename NAME_VALUE_LOOKUP> -	class ParamValue <BatchBlock<DERIVED_BLOCK, BASE_BLOCK>, -					NAME_VALUE_LOOKUP, -					true> -	:	public NAME_VALUE_LOOKUP, -		protected BatchBlock<DERIVED_BLOCK, BASE_BLOCK> +	template<typename T> +	class ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK>  	{ +		typedef ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK> self_t; +  	public: -		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> block_t; -		typedef const BatchBlock<DERIVED_BLOCK, BASE_BLOCK>&	value_assignment_t; -		typedef block_t value_t; +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef T									default_value_t;  		ParamValue() -		:	block_t(), +		:	mValue(),  			mValidated(false) -		{} +		{ +			mCurParam = getBlockDescriptor().mAllParams.begin(); +		} -		ParamValue(value_assignment_t other) -		:	block_t(other), +		ParamValue(const default_value_t& value) +		:	mValue(value),  			mValidated(false)  		{ +			mCurParam = getBlockDescriptor().mAllParams.begin();  		} -		void setValue(value_assignment_t val) +		void setValue(const value_t& val)  		{ -			*this = val; +			mValue.setValue(val);  		} -		value_assignment_t getValue() const +		const value_t& getValue() const  		{ -			return *this; +			return mValue.getValue();  		} -		BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& getValue() +		value_t& getValue()  		{ -			return *this; +			return mValue.getValue();  		} -		operator value_assignment_t() const +		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)  		{ -			return *this; +			if (new_name) +			{ +				mCurParam = getBlockDescriptor().mAllParams.begin(); +			} +			if (name_stack_range.first == name_stack_range.second  +				&& mCurParam != getBlockDescriptor().mAllParams.end()) +			{ +				// deserialize to mCurParam +				ParamDescriptor& pd = *(*mCurParam); +				ParamDescriptor::deserialize_func_t deserialize_func = pd.mDeserializeFunc; +				Param* paramp = mValue.getParamFromHandle(pd.mParamHandle); + +				if (deserialize_func  +					&& paramp  +					&& deserialize_func(*paramp, p, name_stack_range, new_name)) +				{ +					++mCurParam; +					return true; +				} +				else +				{ +					return false; +				} +			} +			else +			{ +				return mValue.deserializeBlock(p, name_stack_range, new_name); +			}  		} -		value_assignment_t operator()() const +		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const  		{ -			return *this; +			const BaseBlock* base_block = diff_block +				? &(diff_block->mValue) +				: NULL; +			mValue.serializeBlock(p, name_stack, base_block); +		} + +		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const +		{ +			return mValue.inspectBlock(p, name_stack, min_count, max_count); +		} + +		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) +		{ +			return mValue.mergeBlock(block_data, source.getValue(), overwrite); +		} + +		bool validateBlock(bool emit_errors = true) const +		{ +			return mValue.validateBlock(emit_errors); +		} + +		static BlockDescriptor& getBlockDescriptor() +		{ +			return value_t::getBlockDescriptor();  		} -	protected:  		mutable bool 	mValidated; // lazy validation flag + +	private: + +		BlockDescriptor::all_params_list_t::iterator	mCurParam; +		T												mValue;  	}; -	template<typename T, bool IS_BLOCK> -	class ParamValue <BaseBlock::Lazy<T>, -					TypeValues<T>, -					IS_BLOCK> -	:	public IsBlock<T>::base_class_t +	template<typename T> +	class ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> +	: public T  	{ +		typedef ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> self_t; +  	public: -		typedef ParamValue <BaseBlock::Lazy<T>, TypeValues<T>, false> self_t; -		typedef const T& value_assignment_t; -		typedef T value_t; +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef T									default_value_t; + +		ParamValue() +		:	T(), +			mValidated(false) +		{} + +		ParamValue(const default_value_t& value) +		:	T(value.getValue()), +			mValidated(false) +		{} + +		mutable bool 	mValidated; // lazy validation flag +	}; + +	template<typename T, typename BLOCK_T> +	class ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T>  +	{ +		typedef ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T> self_t; + +	public: +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef LazyValue<T>						default_value_t;  		ParamValue()  		:	mValue(),  			mValidated(false)  		{} -		ParamValue(value_assignment_t other) +		ParamValue(const default_value_t& other)  		:	mValue(other),  			mValidated(false)  		{} -		void setValue(value_assignment_t val) +		ParamValue(const T& value) +		:	mValue(value), +			mValidated(false) +		{} + +		void setValue(const value_t& val)  		{  			mValue.set(val);  		} -		value_assignment_t getValue() const +		const value_t& getValue() const  		{ -			return mValue.get(); +			return mValue.get().getValue();  		} -		T& getValue() +		value_t& getValue() +		{ +			return mValue.get().getValue(); +		} + +		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name)  		{ -			return mValue.get(); +			return mValue.get().deserializeBlock(p, name_stack_range, new_name);  		} -		operator value_assignment_t() const +		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const  		{ -			return mValue.get(); +			if (mValue.empty()) return; +			 +			const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty()) +											? &(diff_block->mValue.get().getValue()) +											: NULL; +			mValue.get().serializeBlock(p, name_stack, base_block);  		} -		value_assignment_t operator()() const +		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const  		{ -			return mValue.get(); +			return mValue.get().inspectBlock(p, name_stack, min_count, max_count);  		} -		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) +		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)  		{ -			return mValue.get().deserializeBlock(p, name_stack_range, new_name); +			return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite);  		} -		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const +		bool validateBlock(bool emit_errors = true) const  		{ -			if (mValue.empty()) return; +			return mValue.empty() || mValue.get().validateBlock(emit_errors); +		} + +		static BlockDescriptor& getBlockDescriptor() +		{ +			return value_t::getBlockDescriptor(); +		} + +		mutable bool 	mValidated; // lazy validation flag + +	private: +		LazyValue<T>	mValue; +	}; + +	template<typename T, typename BLOCK_T> +	class ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> +		{ +		typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> self_t; + +	public: +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef LazyValue<T>						default_value_t; + +		ParamValue() +		:	mValue(), +			mValidated(false) +		{} + +		ParamValue(const default_value_t& other) +		:	mValue(other), +			mValidated(false) +		{} + +		ParamValue(const T& value) +		:	mValue(value), +			mValidated(false) +		{} -			mValue.get().serializeBlock(p, name_stack, diff_block); +		void setValue(const value_t& val) +		{ +			mValue.set(val);  		} -		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const +		const value_t& getValue() const  		{ -			if (mValue.empty()) return false; +			return mValue.get().getValue(); +		} -			return mValue.get().inspectBlock(p, name_stack, min_count, max_count); +		value_t& getValue() +		{ +			return mValue.get().getValue();  		} -	protected:  		mutable bool 	mValidated; // lazy validation flag  	private: -		BaseBlock::Lazy<T>	mValue; +		LazyValue<T>	mValue;  	};  	template <> -	class ParamValue <LLSD, -					TypeValues<LLSD>, -					false> -	:	public TypeValues<LLSD>, -		public BaseBlock +	class ParamValue <LLSD, NOT_BLOCK> +	:	public BaseBlock  	{  	public: -		typedef ParamValue<LLSD, TypeValues<LLSD>, false> self_t; -		typedef const LLSD&	value_assignment_t; +		typedef LLSD			value_t; +		typedef LLSD			default_value_t;  		ParamValue()  		:	mValidated(false)  		{} -		ParamValue(value_assignment_t other) +		ParamValue(const default_value_t& other)  		:	mValue(other),  			mValidated(false)  		{} -		void setValue(value_assignment_t val) { mValue = val; } +		void setValue(const value_t& val) { mValue = val; } -		value_assignment_t getValue() const { return mValue; } +		const value_t& getValue() const { return mValue; }  		LLSD& getValue() { return mValue; } -		operator value_assignment_t() const { return mValue; } -		value_assignment_t operator()() const { return mValue; } -		 -  		// block param interface  		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);  		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; @@ -2081,8 +2481,7 @@ namespace LLInitParam  	template<typename T>  	class CustomParamValue -	:	public Block<ParamValue<T, TypeValues<T> > >, -		public TypeValues<T> +	:	public Block<ParamValue<T> >  	{  	public:  		typedef enum e_value_age @@ -2092,14 +2491,15 @@ namespace LLInitParam  			BLOCK_AUTHORITATIVE		// mValue is derived from the block parameters, which are authoritative  		} EValueAge; -		typedef ParamValue<T, TypeValues<T> >	derived_t; +		typedef ParamValue<T>			derived_t;  		typedef CustomParamValue<T>				self_t;  		typedef Block<derived_t>				block_t; -		typedef const T&						value_assignment_t; +		typedef T						default_value_t;  		typedef T								value_t; +		typedef void					baseblock_base_class_t; -		CustomParamValue(const T& value = T()) +		CustomParamValue(const default_value_t& value = T())  		:	mValue(value),  			mValueAge(VALUE_AUTHORITATIVE),  			mValidated(false) @@ -2116,8 +2516,6 @@ namespace LLInitParam  					typed_param.mValueAge = VALUE_AUTHORITATIVE;  					typed_param.updateBlockFromValue(false); -					typed_param.clearValueName(); -  					return true;  				}  			} @@ -2131,18 +2529,8 @@ namespace LLInitParam  			const derived_t& typed_param = static_cast<const derived_t&>(*this);  			const derived_t* diff_param = static_cast<const derived_t*>(diff_block); -			std::string key = typed_param.getValueName(); - -			// first try to write out name of name/value pair -			if (!key.empty()) -			{ -				if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key)) -				{ -					parser.writeValue(key, name_stack); -				} -			}  			// then try to serialize value directly -			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue())) +			if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))              {  				if (!parser.writeValue(typed_param.getValue(), name_stack))  @@ -2172,19 +2560,6 @@ namespace LLInitParam  			}  		} -		bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const -		{ -			// first, inspect with actual type... -			parser.inspectValue<T>(name_stack, min_count, max_count, NULL); -			if (TypeValues<T>::getPossibleValues()) -			{ -				//...then inspect with possible string values... -				parser.inspectValue<std::string>(name_stack, min_count, max_count, TypeValues<T>::getPossibleValues()); -			} -			// then recursively inspect contents... -			return block_t::inspectBlock(parser, name_stack, min_count, max_count); -		} -  		bool validateBlock(bool emit_errors = true) const  		{  			if (mValueAge == VALUE_NEEDS_UPDATE) @@ -2192,7 +2567,6 @@ namespace LLInitParam  				if (block_t::validateBlock(emit_errors))  				{  					// clear stale keyword associated with old value -					TypeValues<T>::clearValueName();  					mValueAge = BLOCK_AUTHORITATIVE;  					static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock();  					return true; @@ -2222,17 +2596,15 @@ namespace LLInitParam  			}  		} -		void setValue(value_assignment_t val) +		void setValue(const value_t& val)  		{ -			derived_t& typed_param = static_cast<derived_t&>(*this);  			// set param version number to be up to date, so we ignore block contents  			mValueAge = VALUE_AUTHORITATIVE;  			mValue = val; -			typed_param.clearValueName();  			static_cast<derived_t*>(this)->updateBlockFromValue(false);  		} -		value_assignment_t getValue() const +		const value_t& getValue() const  		{  			validateBlock(true);  			return mValue; @@ -2244,20 +2616,10 @@ namespace LLInitParam  			return mValue;  		} -		operator value_assignment_t() const -		{ -			return getValue(); -		} - -		value_assignment_t operator()() const -		{ -			return getValue(); -		} -  	protected:  		// use this from within updateValueFromBlock() to set the value without making it authoritative -		void updateValue(value_assignment_t value) +		void updateValue(const value_t& value)  		{  			mValue = value;  		} diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp index afc76024d1..9cd88a1620 100644 --- a/indra/llxuixml/llxuiparser.cpp +++ b/indra/llxuixml/llxuiparser.cpp @@ -42,7 +42,7 @@  #include <boost/spirit/include/classic_core.hpp>  #include "lluicolor.h" - +#include "v3math.h"  using namespace BOOST_SPIRIT_CLASSIC_NS;  const S32 MAX_STRING_ATTRIBUTE_SIZE = 40; @@ -79,7 +79,6 @@ struct Occurs : public LLInitParam::Block<Occurs>  	{}  }; -  typedef enum  {  	USE_REQUIRED, @@ -101,14 +100,23 @@ namespace LLInitParam  struct Element;  struct Group; -struct Choice;  struct Sequence; -struct Any; + +struct All : public LLInitParam::Block<All, Occurs> +{ +	Multiple< Lazy<Element, IS_A_BLOCK> > elements; + +	All() +	:	elements("element") +	{ +		maxOccurs = 1; +	} +};  struct Attribute : public LLInitParam::Block<Attribute>  { -	Mandatory<std::string>	name; -	Mandatory<std::string>	type; +	Mandatory<std::string>	name, +							type;  	Mandatory<EUse>			use;  	Attribute() @@ -127,24 +135,13 @@ struct Any : public LLInitParam::Block<Any, Occurs>  	{}  }; -struct All : public LLInitParam::Block<All, Occurs> -{ -	Multiple< Lazy<Element> > elements; - -	All() -	:	elements("element") -	{ -		maxOccurs = 1; -	} -}; -  struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs>  { -	Alternative< Lazy<Element> >	element; -	Alternative< Lazy<Group> >		group; -	Alternative< Lazy<Choice> >		choice; -	Alternative< Lazy<Sequence> >	sequence; -	Alternative< Lazy<Any> >		any; +	Alternative< Lazy<Element, IS_A_BLOCK> >	element; +	Alternative< Lazy<Group, IS_A_BLOCK> >		group; +	Alternative< Lazy<Choice, IS_A_BLOCK> >		choice; +	Alternative< Lazy<Sequence, IS_A_BLOCK> >	sequence; +	Alternative< Lazy<Any> >					any;  	Choice()  	:	element("element"), @@ -158,11 +155,11 @@ struct Choice : public LLInitParam::ChoiceBlock<Choice, Occurs>  struct Sequence : public LLInitParam::ChoiceBlock<Sequence, Occurs>  { -	Alternative< Lazy<Element> >	element; -	Alternative< Lazy<Group> >		group; -	Alternative< Lazy<Choice> >		choice; -	Alternative< Lazy<Sequence> >	sequence; -	Alternative< Lazy<Any> >		any; +	Alternative< Lazy<Element, IS_A_BLOCK> >	element; +	Alternative< Lazy<Group, IS_A_BLOCK> >		group; +	Alternative< Lazy<Choice> >					choice; +	Alternative< Lazy<Sequence, IS_A_BLOCK> >	sequence; +	Alternative< Lazy<Any> >					any;  };  struct GroupContents : public LLInitParam::ChoiceBlock<GroupContents, Occurs> @@ -247,7 +244,7 @@ struct ComplexType : public LLInitParam::Block<ComplexType, ComplexTypeContents>  	Optional<bool>					mixed;  	Multiple<Attribute>				attribute; -	Multiple< Lazy<Element> >			elements; +	Multiple< Lazy<Element, IS_A_BLOCK > >			elements;  	ComplexType()  	:	name("name"), @@ -313,7 +310,6 @@ public:  			setNameSpace(ns);  		};  	} -  };  // @@ -670,6 +666,7 @@ LLXUIParser::LLXUIParser()  		registerParserFuncs<S32>(readS32Value, writeS32Value);  		registerParserFuncs<F32>(readF32Value, writeF32Value);  		registerParserFuncs<F64>(readF64Value, writeF64Value); +		registerParserFuncs<LLVector3>(readVector3Value, writeVector3Value);  		registerParserFuncs<LLColor4>(readColor4Value, writeColor4Value);  		registerParserFuncs<LLUIColor>(readUIColorValue, writeUIColorValue);  		registerParserFuncs<LLUUID>(readUUIDValue, writeUUIDValue); @@ -1144,6 +1141,31 @@ bool LLXUIParser::writeF64Value(Parser& parser, const void* val_ptr, name_stack_  	return false;  } +bool LLXUIParser::readVector3Value(Parser& parser, void* val_ptr) +{ +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	LLVector3* vecp = (LLVector3*)val_ptr; +	if(self.mCurReadNode->getFloatValue(3, vecp->mV) >= 3) +	{ +		return true; +	} + +	return false; +} + +bool LLXUIParser::writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t& stack) +{ +	LLXUIParser& self = static_cast<LLXUIParser&>(parser); +	LLXMLNodePtr node = self.getNode(stack); +	if (node.notNull()) +	{ +		LLVector3 vector = *((LLVector3*)val_ptr); +		node->setFloatValue(3, vector.mV); +		return true; +	} +	return false; +} +  bool LLXUIParser::readColor4Value(Parser& parser, void* val_ptr)  {  	LLXUIParser& self = static_cast<LLXUIParser&>(parser); diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h index d7cd256967..e48663e5cc 100644 --- a/indra/llxuixml/llxuiparser.h +++ b/indra/llxuixml/llxuiparser.h @@ -127,6 +127,7 @@ private:  	static bool readS32Value(Parser& parser, void* val_ptr);  	static bool readF32Value(Parser& parser, void* val_ptr);  	static bool readF64Value(Parser& parser, void* val_ptr); +	static bool readVector3Value(Parser& parser, void* val_ptr);  	static bool readColor4Value(Parser& parser, void* val_ptr);  	static bool readUIColorValue(Parser& parser, void* val_ptr);  	static bool readUUIDValue(Parser& parser, void* val_ptr); @@ -144,6 +145,7 @@ private:  	static bool writeS32Value(Parser& parser, const void* val_ptr, name_stack_t&);  	static bool writeF32Value(Parser& parser, const void* val_ptr, name_stack_t&);  	static bool writeF64Value(Parser& parser, const void* val_ptr, name_stack_t&); +	static bool writeVector3Value(Parser& parser, const void* val_ptr, name_stack_t&);  	static bool writeColor4Value(Parser& parser, const void* val_ptr, name_stack_t&);  	static bool writeUIColorValue(Parser& parser, const void* val_ptr, name_stack_t&);  	static bool writeUUIDValue(Parser& parser, const void* val_ptr, name_stack_t&); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9aaefa9c6a..785bf4b868 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -245,6 +245,7 @@ set(viewer_SOURCE_FILES      llfloateruipreview.cpp      llfloaterurlentry.cpp      llfloatervoiceeffect.cpp +    llfloatervoicevolume.cpp      llfloaterwebcontent.cpp      llfloaterwebprofile.cpp      llfloaterwhitelistentry.cpp @@ -277,6 +278,7 @@ set(viewer_SOURCE_FILES      llhudrender.cpp      llhudtext.cpp      llhudview.cpp +    llimconversation.cpp      llimfloater.cpp      llimfloatercontainer.cpp      llimhandler.cpp @@ -331,7 +333,6 @@ set(viewer_SOURCE_FILES      llnamelistctrl.cpp      llnavigationbar.cpp      llnearbychat.cpp -    llnearbychatbar.cpp      llnearbychathandler.cpp      llnearbychatbarlistener.cpp      llnetmap.cpp @@ -363,7 +364,6 @@ set(viewer_SOURCE_FILES      llpanelgroupnotices.cpp      llpanelgrouproles.cpp      llpanelhome.cpp -    llpanelimcontrolpanel.cpp      llpanelland.cpp      llpanellandaudio.cpp      llpanellandmarkinfo.cpp @@ -801,6 +801,7 @@ set(viewer_HEADER_FILES      llfloateruipreview.h      llfloaterurlentry.h      llfloatervoiceeffect.h +    llfloatervoicevolume.h      llfloaterwebcontent.h      llfloaterwebprofile.h      llfloaterwhitelistentry.h @@ -833,6 +834,7 @@ set(viewer_HEADER_FILES      llhudrender.h      llhudtext.h      llhudview.h +    llimconversation.h      llimfloater.h      llimfloatercontainer.h      llimview.h @@ -887,7 +889,6 @@ set(viewer_HEADER_FILES      llnamelistctrl.h      llnavigationbar.h      llnearbychat.h -    llnearbychatbar.h      llnearbychathandler.h      llnearbychatbarlistener.h      llnetmap.h @@ -913,7 +914,6 @@ set(viewer_HEADER_FILES      llpanelgroupnotices.h      llpanelgrouproles.h      llpanelhome.h -    llpanelimcontrolpanel.h      llpanelland.h      llpanellandaudio.h      llpanellandmarkinfo.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 05c05b9393..46c29e32e2 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2,6 +2,28 @@  <llsd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="llsd.xsd">  <map> +    <key>IMShowTime</key> +    <map> +      <key>Comment</key> +      <string>Enable(disable) timestamp showing in the chat.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map> +    <key>IMShowNamesForP2PConv</key> +    <map> +      <key>Comment</key> +      <string>Enable(disable) showing of a names in the chat.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map>  	<key>CrashHostUrl</key>      <map>        <key>Comment</key> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 143126b334..1f637ef3ff 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -22,6 +22,61 @@          <key>Value</key>              <string>The Resident you messaged is in 'busy mode' which means they have requested not to be disturbed.  Your message will still be shown in their IM panel for later viewing.</string>          </map> +    <key>ConversationsExpandMessagePaneFirst</key> +    <map> +        <key>Comment</key> +            <string>Expand either messages or conversations list pane from Conversations compact mode.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>1</integer> +    </map> +    <key>ConversationsListPaneCollapsed</key> +    <map> +        <key>Comment</key> +            <string>Stores the expanded/collapsed state of the conversations list pane in Conversations floater.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +    </map> +    <key>ConversationsListPaneWidth</key> +    <map> +        <key>Comment</key> +            <string>Conversations floater list pane width.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>268</integer> +    </map> +    <key>ConversationsMessagePaneCollapsed</key> +    <map> +        <key>Comment</key> +            <string>Stores the expanded/collapsed state of Conversations floater message pane.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>Boolean</string> +        <key>Value</key> +            <integer>0</integer> +    </map> +    <key>ConversationsMessagePaneWidth</key> +    <map> +        <key>Comment</key> +            <string>Conversations floater message pane width.</string> +        <key>Persist</key> +            <integer>1</integer> +        <key>Type</key> +            <string>S32</string> +        <key>Value</key> +            <integer>412</integer> +    </map>      <key>InstantMessageLogPath</key>          <map>          <key>Comment</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 3870a3be2e..0db03289d8 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -54,7 +54,7 @@  #include "llmorphview.h"  #include "llmoveview.h"  #include "llnavigationbar.h" // to show/hide navigation bar when changing mouse look state -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llnotificationsutil.h"  #include "llpaneltopinfobar.h"  #include "llparcel.h" @@ -1778,7 +1778,7 @@ void LLAgent::startTyping()  	{  		sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_START);  	} -	LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE); +	LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_START, FALSE);  }  //----------------------------------------------------------------------------- @@ -1790,7 +1790,7 @@ void LLAgent::stopTyping()  	{  		clearRenderState(AGENT_STATE_TYPING);  		sendAnimationRequest(ANIM_AGENT_TYPE, ANIM_REQUEST_STOP); -		LLNearbyChatBar::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE); +		LLNearbyChat::getInstance()->sendChatFromViewer("", CHAT_TYPE_STOP, FALSE);  	}  } diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index f618af9536..c3d560540d 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -814,6 +814,26 @@ void LLAvatarActions::toggleBlock(const LLUUID& id)  }  // static +void LLAvatarActions::toggleMuteVoice(const LLUUID& id) +{ +	std::string name; +	gCacheName->getFullName(id, name); // needed for mute + +	LLMuteList* mute_list = LLMuteList::getInstance(); +	bool is_muted = mute_list->isMuted(id, LLMute::flagVoiceChat); + +	LLMute mute(id, name, LLMute::AGENT); +	if (!is_muted) +	{ +		mute_list->add(mute, LLMute::flagVoiceChat); +	} +	else +	{ +		mute_list->remove(mute, LLMute::flagVoiceChat); +	} +} + +// static  bool LLAvatarActions::canOfferTeleport(const LLUUID& id)  {  	// First use LLAvatarTracker::isBuddy() @@ -1009,7 +1029,6 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri  	LLSD payload;  	payload["from_id"] = target_id; -	payload["SUPPRESS_TOAST"] = true;  	LLNotificationsUtil::add("FriendshipOffered", args, payload);  } @@ -1028,6 +1047,12 @@ bool LLAvatarActions::isBlocked(const LLUUID& id)  }  // static +bool LLAvatarActions::isVoiceMuted(const LLUUID& id) +{ +	return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat); +} + +// static  bool LLAvatarActions::canBlock(const LLUUID& id)  {  	std::string full_name; diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index 748b7cb3d1..e5dad74fc8 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -124,6 +124,11 @@ public:  	static void toggleBlock(const LLUUID& id);  	/** +	 * Block/unblock the avatar voice. +	 */ +	static void toggleMuteVoice(const LLUUID& id); + +	/**  	 * Return true if avatar with "id" is a friend  	 */  	static bool isFriend(const LLUUID& id); @@ -134,6 +139,11 @@ public:  	static bool isBlocked(const LLUUID& id);  	/** +	 * @return true if the avatar voice is blocked +	 */ +	static bool isVoiceMuted(const LLUUID& id); + +	/**  	 * @return true if you can block the avatar  	 */  	static bool canBlock(const LLUUID& id); diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp index 6e77d1e336..9e608d2c8b 100644 --- a/indra/newview/llbrowsernotification.cpp +++ b/indra/newview/llbrowsernotification.cpp @@ -35,11 +35,8 @@  using namespace LLNotificationsUI; -bool LLBrowserNotification::processNotification(const LLSD& notify) +bool LLBrowserNotification::processNotification(const LLNotificationPtr& notification)  { -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); -	if (!notification) return false; -  	LLUUID media_id = notification->getPayload()["media_id"].asUUID();  	LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(media_id);  	if (media_instance) diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 0d55c4429a..60d60abd45 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -54,6 +54,7 @@  #include "llresmgr.h"  #include "llslurl.h"  #include "llimview.h" +#include "lltrans.h"  #include "llviewercontrol.h"  #include "llviewernetwork.h"  #include "llviewerobjectlist.h" @@ -723,12 +724,13 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,  	// Use display name only because this user is your friend  	LLSD args;  	args["NAME"] = av_name.mDisplayName; +	args["STATUS"] = online ? LLTrans::getString("OnlineStatus") : LLTrans::getString("OfflineStatus");  	LLNotificationPtr notification;  	if (online)  	{  		notification = -			LLNotificationsUtil::add("FriendOnline", +			LLNotificationsUtil::add("FriendOnlineOffline",  									 args,  									 payload.with("respond_on_mousedown", TRUE),  									 boost::bind(&LLAvatarActions::startIM, agent_id)); @@ -736,7 +738,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,  	else  	{  		notification = -			LLNotificationsUtil::add("FriendOffline", args, payload); +			LLNotificationsUtil::add("FriendOnlineOffline", args, payload);  	}  	// If there's an open IM session with this agent, send a notification there too. diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index f530d10ddc..c514261b60 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -143,7 +143,8 @@ public:  		{  			LLMuteList::getInstance()->add(LLMute(getAvatarId(), mFrom, LLMute::OBJECT)); -			LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD().with("blocked_to_select", getAvatarId())); +			LLFloaterSidePanelContainer::showPanel("people", "panel_people", +				LLSD().with("people_panel_tab_name", "blocked_panel").with("blocked_to_select", getAvatarId()));  		}  	} @@ -699,9 +700,10 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		return;  	} +	bool from_me = chat.mFromID == gAgent.getID();  	mEditor->setPlainText(use_plain_text_chat_history); -	if (!mEditor->scrolledToEnd() && chat.mFromID != gAgent.getID() && !chat.mFromName.empty()) +	if (!mEditor->scrolledToEnd() && !from_me && !chat.mFromName.empty())  	{  		mUnreadChatSources.insert(chat.mFromName);  		mMoreChatPanel->setVisible(TRUE); @@ -774,18 +776,28 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		style_params.readonly_color(LLColor4::grey);  	} +	bool prependNewLineState = mEditor->getText().size() != 0; + +	// show timestamps and names in the compact mode  	if (use_plain_text_chat_history)  	{  		LLStyle::Params timestamp_style(style_params); + +		// timestams showing +		if (args["show_time"].asBoolean()) +		{  		if (!message_from_log)  		{  			LLColor4 timestamp_color = LLUIColorTable::instance().getColor("ChatTimestampColor");  			timestamp_style.color(timestamp_color);  			timestamp_style.readonly_color(timestamp_color);  		} -		mEditor->appendText("[" + chat.mTimeStr + "] ", mEditor->getText().size() != 0, timestamp_style); +			mEditor->appendText("[" + chat.mTimeStr + "] ", prependNewLineState, timestamp_style); +			prependNewLineState = false; +		} -		if (utf8str_trim(chat.mFromName).size() != 0) +		// names showing +		if (args["show_names_for_p2p_conv"].asBoolean() && utf8str_trim(chat.mFromName).size() != 0)  		{  			// Don't hotlink any messages from the system (e.g. "Second Life:"), so just add those in plain text.  			if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull()) @@ -802,25 +814,40 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  				link_params.is_link = true;  				link_params.link_href = url; -				mEditor->appendText(chat.mFromName + delimiter, -									false, link_params); +				mEditor->appendText(chat.mFromName + delimiter, prependNewLineState, link_params); +				prependNewLineState = false;  			}  			else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log)  			{  				LLStyle::Params link_params(style_params);  				link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID)); +				if (from_me) +				{	std::string localized_name; +					bool is_localized = LLTrans::findString(localized_name, "AgentNameSubst"); +					mEditor->appendText((is_localized? localized_name:"(You)") + delimiter, +							prependNewLineState, link_params); +					prependNewLineState = false; +				} +				else +				{  				// Add link to avatar's inspector and delimiter to message. -				mEditor->appendText(std::string(link_params.link_href) + delimiter, false, link_params); +					mEditor->appendText(std::string(link_params.link_href) + delimiter, +							prependNewLineState, link_params); +					prependNewLineState = false; +				}  			}  			else  			{ -				mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, false, style_params); +				mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, +						prependNewLineState, style_params); +				prependNewLineState = false;  			}  		}  	} -	else +	else // showing timestamp and name in the expanded mode  	{ +		prependNewLineState = false;  		LLView* view = NULL;  		LLInlineViewSegment::Params p;  		p.force_newline = true; @@ -876,35 +903,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		if (notification != NULL)  		{  			LLIMToastNotifyPanel* notify_box = new LLIMToastNotifyPanel( -					notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history); -			//we can't set follows in xml since it broke toasts behavior -			notify_box->setFollowsLeft(); -			notify_box->setFollowsRight(); -			notify_box->setFollowsTop(); - -			ctrl_list_t ctrls = notify_box->getControlPanel()->getCtrlList(); -			S32 offset = 0; -			// Children were added by addChild() which uses push_front to insert them into list, -			// so to get buttons in correct order reverse iterator is used (EXT-5906)  -			for (ctrl_list_t::reverse_iterator it = ctrls.rbegin(); it != ctrls.rend(); it++) -			{ -				LLButton * button = dynamic_cast<LLButton*> (*it); -				if (button != NULL) -				{ -					button->setOrigin( offset, -							button->getRect().mBottom); -					button->setLeftHPad(2 * HPAD); -					button->setRightHPad(2 * HPAD); -					// set zero width before perform autoResize() -					button->setRect(LLRect(button->getRect().mLeft, -							button->getRect().mTop, button->getRect().mLeft, -							button->getRect().mBottom)); -					button->setAutoResize(true); -					button->autoResize(); -					offset += HPAD + button->getRect().getWidth(); -					button->setFollowsNone(); -				} -			} +					notification, chat.mSessionID, LLRect::null, !use_plain_text_chat_history, mEditor);  			//Prepare the rect for the view  			LLRect target_rect = mEditor->getDocumentView()->getRect(); @@ -928,7 +927,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  		//MESSAGE TEXT PROCESSING  		//*HACK getting rid of redundant sender names in system notifications sent using sender name (see EXT-5010) -		if (use_plain_text_chat_history && gAgentID != chat.mFromID && chat.mFromID.notNull()) +		if (use_plain_text_chat_history && !from_me && chat.mFromID.notNull())  		{  			std::string slurl_about = SLURL_APP_AGENT + chat.mFromID.asString() + SLURL_ABOUT;  			if (message.length() > slurl_about.length() &&  @@ -943,13 +942,14 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL  			message = chat.mFromName + message;  		} -		mEditor->appendText(message, FALSE, style_params); +		mEditor->appendText(message, prependNewLineState, style_params); +		prependNewLineState = false;  	}  	mEditor->blockUndo();  	// automatically scroll to end when receiving chat from myself -	if (chat.mFromID == gAgentID) +	if (from_me)  	{  		mEditor->setCursorAndScrollToEnd();  	} diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 9a84280f25..477bdb3967 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -35,7 +35,7 @@  #include "llfloaterreg.h"  #include "lllocalcliprect.h"  #include "lltrans.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llviewercontrol.h"  #include "llagentdata.h" @@ -316,12 +316,12 @@ BOOL	LLNearbyChatToastPanel::handleMouseUp	(S32 x, S32 y, MASK mask)  			return TRUE;  		else  		{ -			LLNearbyChatBar::getInstance()->showHistory(); +			LLNearbyChat::getInstance()->showHistory();  			return FALSE;  		}  	} -	LLNearbyChatBar::getInstance()->showHistory(); +	LLNearbyChat::getInstance()->showHistory();  	return LLPanel::handleMouseUp(x,y,mask);  } @@ -372,7 +372,6 @@ void LLNearbyChatToastPanel::draw()  		}  		mIsDirty = false;  	} -	LLToastPanelBase::draw();  } diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index 1d700dcede..89b0c4f37a 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -40,7 +40,7 @@ typedef enum e_show_item_header  	CHATITEMHEADER_SHOW_BOTH  } EShowItemHeader; -class LLNearbyChatToastPanel: public LLToastPanelBase +class LLNearbyChatToastPanel : public LLPanel  {  protected:          LLNearbyChatToastPanel() diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index a661808d1f..17181edffc 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -335,30 +335,15 @@ void LLIMWellChiclet::messageCountChanged(const LLSD& session_data)  /*               LLNotificationChiclet implementation                   */  /************************************************************************/  LLNotificationChiclet::LLNotificationChiclet(const Params& p) -: LLSysWellChiclet(p) -, mUreadSystemNotifications(0) +:	LLSysWellChiclet(p), +	mUreadSystemNotifications(0)  { -	// connect counter handlers to the signals -	connectCounterUpdatersToSignal("notify"); -	connectCounterUpdatersToSignal("groupnotify"); -	connectCounterUpdatersToSignal("offer"); - +	mNotificationChannel.reset(new ChicletNotificationChannel(this));  	// ensure that notification well window exists, to synchronously  	// handle toast add/delete events.  	LLNotificationWellWindow::getInstance()->setSysWellChiclet(this);  } -void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& notification_type) -{ -	LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); -	LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); -	if(n_handler) -	{ -		n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); -		n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); -	} -} -  void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)  {  	std::string action = user_data.asString(); @@ -407,6 +392,18 @@ void LLNotificationChiclet::setCounter(S32 counter)  	updateWidget(getCounter() == 0);  } + +bool LLNotificationChiclet::ChicletNotificationChannel::filterNotification( LLNotificationPtr notification ) +{ +	if( !(notification->canLogToIM() && notification->hasFormElements()) +		&& (!notification->getPayload().has("give_inventory_notification") +			|| notification->getPayload()["give_inventory_notification"])) +	{ +		return true; +	} +	return false; +} +  //////////////////////////////////////////////////////////////////////////  //////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 19683492c2..3973b6547a 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -34,6 +34,7 @@  #include "lloutputmonitorctrl.h"  #include "llgroupmgr.h"  #include "llimview.h" +#include "llnotifications.h"  class LLMenuGL;  class LLIMFloater; @@ -911,11 +912,35 @@ protected:  class LLNotificationChiclet : public LLSysWellChiclet  { +	LOG_CLASS(LLNotificationChiclet); +	  	friend class LLUICtrlFactory;  public:  	struct Params : public LLInitParam::Block<Params, LLSysWellChiclet::Params>{};  protected: +	struct ChicletNotificationChannel : public LLNotificationChannel +	{ +		ChicletNotificationChannel(LLNotificationChiclet* chiclet)  +		:	LLNotificationChannel(LLNotificationChannel::Params().filter(filterNotification).name(chiclet->getSessionId().asString())), +			mChiclet(chiclet) +		{ +			// connect counter handlers to the signals +			connectToChannel("Group Notifications"); +			connectToChannel("Offer"); +			connectToChannel("Notifications"); +		} + +		static bool filterNotification(LLNotificationPtr notify); +		// connect counter updaters to the corresponding signals +		/*virtual*/ void onAdd(LLNotificationPtr p) { mChiclet->setCounter(++mChiclet->mUreadSystemNotifications); } +		/*virtual*/ void onDelete(LLNotificationPtr p) { mChiclet->setCounter(--mChiclet->mUreadSystemNotifications); } + +		LLNotificationChiclet* const mChiclet; +	}; + +	boost::scoped_ptr<ChicletNotificationChannel> mNotificationChannel; +  	LLNotificationChiclet(const Params& p);  	/** @@ -933,12 +958,6 @@ protected:  	 */  	/*virtual*/ void createMenu(); -	// connect counter updaters to the corresponding signals -	void connectCounterUpdatersToSignal(const std::string& notification_type); - -	// methods for updating a number of unread System notifications -	void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); } -	void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); }  	/*virtual*/ void setCounter(S32 counter);  	S32 mUreadSystemNotifications;  }; diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp index 2681d4b34d..4f35c325a8 100644 --- a/indra/newview/llfloaternotificationsconsole.cpp +++ b/indra/newview/llfloaternotificationsconsole.cpp @@ -44,21 +44,16 @@ public:  	BOOL postBuild();  private: -	bool update(const LLSD& payload, bool passed_filter); +	bool update(const LLSD& payload);  	static void toggleClick(void* user_data);  	static void onClickNotification(void* user_data); -	static void onClickNotificationReject(void* user_data);  	LLNotificationChannelPtr mChannelPtr; -	LLNotificationChannelPtr mChannelRejectsPtr;  };  LLNotificationChannelPanel::LLNotificationChannelPanel(const LLNotificationChannelPanel::Params& p)   :	LLLayoutPanel(p)  {  	mChannelPtr = LLNotifications::instance().getChannel(p.name); -	mChannelRejectsPtr = LLNotificationChannelPtr( -		LLNotificationChannel::buildChannel(p.name() + "rejects", mChannelPtr->getParentChannelName(), -											!boost::bind(mChannelPtr->getFilter(), _1)));  	buildFromFile( "panel_notifications_channel.xml");  } @@ -68,15 +63,11 @@ BOOL LLNotificationChannelPanel::postBuild()  	header_button->setLabel(mChannelPtr->getName());  	header_button->setClickedCallback(toggleClick, this); -	mChannelPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, true)); -	mChannelRejectsPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, false)); +	mChannelPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1));  	LLScrollListCtrl* scroll = getChild<LLScrollListCtrl>("notifications_list");  	scroll->setDoubleClickCallback(onClickNotification, this);  	scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0)); -	scroll = getChild<LLScrollListCtrl>("notification_rejects_list"); -	scroll->setDoubleClickCallback(onClickNotificationReject, this); -	scroll->setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mRight, 0));  	return TRUE;  } @@ -97,8 +88,6 @@ void LLNotificationChannelPanel::toggleClick(void *user_data)  	// turn off tab stop for collapsed panel  	self->getChild<LLScrollListCtrl>("notifications_list")->setTabStop(!header_button->getToggleState());  	self->getChild<LLScrollListCtrl>("notifications_list")->setVisible(!header_button->getToggleState()); -	self->getChild<LLScrollListCtrl>("notification_rejects_list")->setTabStop(!header_button->getToggleState()); -	self->getChild<LLScrollListCtrl>("notification_rejects_list")->setVisible(!header_button->getToggleState());  }  /*static*/ @@ -118,24 +107,7 @@ void LLNotificationChannelPanel::onClickNotification(void* user_data)  	}  } -/*static*/ -void LLNotificationChannelPanel::onClickNotificationReject(void* user_data) -{ -	LLNotificationChannelPanel* self = (LLNotificationChannelPanel*)user_data; -	if (!self) return; -	LLScrollListItem* firstselected = self->getChild<LLScrollListCtrl>("notification_rejects_list")->getFirstSelected(); -	llassert(firstselected); -	if (firstselected) -	{ -		void* data = firstselected->getUserdata(); -		if (data) -		{ -			gFloaterView->getParentFloater(self)->addDependentFloater(new LLFloaterNotification((LLNotification*)data), TRUE); -		} -	} -} - -bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter) +bool LLNotificationChannelPanel::update(const LLSD& payload)  {  	LLNotificationPtr notification = LLNotifications::instance().find(payload["id"].asUUID());  	if (notification) @@ -151,9 +123,7 @@ bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter)  		row["columns"][2]["column"] = "date";  		row["columns"][2]["type"] = "date"; -		LLScrollListItem* sli = passed_filter ?  -			getChild<LLScrollListCtrl>("notifications_list")->addElement(row) : -			getChild<LLScrollListCtrl>("notification_rejects_list")->addElement(row); +		LLScrollListItem* sli = getChild<LLScrollListCtrl>("notifications_list")->addElement(row);  		sli->setUserdata(&(*notification));  	} diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index 540f977305..c55970ad69 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -44,14 +44,12 @@  #include "llviewernetwork.h"  #include "llwindowshade.h" -#define USE_WINDOWSHADE_DIALOGS	0 -  ///----------------------------------------------------------------------------  /// LLOutboxNotification class  ///---------------------------------------------------------------------------- -bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& notify) +bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLNotificationPtr& notify)  {  	LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox"); @@ -60,6 +58,14 @@ bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& no  	return false;  } +void LLNotificationsUI::LLOutboxNotification::onDelete(LLNotificationPtr p) +{ +	LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get()); +	if (sys_handler) +	{ +		sys_handler->onDelete(p); +	} +}  ///----------------------------------------------------------------------------  /// LLOutboxAddedObserver helper class @@ -516,52 +522,11 @@ void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content)  	updateView();  } -void LLFloaterOutbox::showNotification(const LLSD& notify) +void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification)  { -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); -	 -	if (!notification) -	{ -		llerrs << "Unable to find outbox notification!" << notify.asString() << llendl; -		 -		return; -	} - -#if USE_WINDOWSHADE_DIALOGS - -	if (mWindowShade) -	{ -		delete mWindowShade; -	} -	 -	LLRect floater_rect = getLocalRect(); -	floater_rect.mTop -= getHeaderHeight(); -	floater_rect.stretch(-5, 0); -	 -	LLWindowShade::Params params; -	params.name = "notification_shade"; -	params.rect = floater_rect; -	params.follows.flags = FOLLOWS_ALL; -	params.modal = true; -	params.can_close = false; -	params.shade_color = LLColor4::white % 0.25f; -	params.text_color = LLColor4::white; -	 -	mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params); -	 -	addChild(mWindowShade); -	mWindowShade->show(notification); -	 -#else -	 -	LLNotificationsUI::LLEventHandler * handler = -		LLNotificationsUI::LLNotificationManager::instance().getHandlerForNotification("alertmodal"); -	 -	LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler *>(handler); +	LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler*>(LLNotifications::instance().getChannel("AlertModal").get());  	llassert(sys_handler); -	sys_handler->processNotification(notify); -	 -#endif +	sys_handler->processNotification(notification);  } diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h index 18baccf1c9..a91d8c1139 100644 --- a/indra/newview/llfloateroutbox.h +++ b/indra/newview/llfloateroutbox.h @@ -64,7 +64,7 @@ public:  						   EAcceptance* accept,  						   std::string& tooltip_msg); -	void showNotification(const LLSD& notify); +	void showNotification(const LLNotificationPtr& notification);  	BOOL handleHover(S32 x, S32 y, MASK mask);  	void onMouseLeave(S32 x, S32 y, MASK mask); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 173b0e538c..18ab9dc264 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -423,13 +423,9 @@ void LLFloaterPreference::saveAvatarProperties( void )  BOOL LLFloaterPreference::postBuild()  { -	gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2)); +//	gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate)); -	gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2)); - -	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2)); - -	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2)); +	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLIMConversation::processChatHistoryStyleUpdate));  	gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLViewerChat::signalChatFontChanged)); @@ -457,14 +453,11 @@ BOOL LLFloaterPreference::postBuild()  void LLFloaterPreference::onBusyResponseChanged()  {  	// set "BusyResponseChanged" TRUE if user edited message differs from default, FALSE otherwise -	if (LLTrans::getString("BusyModeResponseDefault") != getChild<LLUICtrl>("busy_response")->getValue().asString()) -	{ -		gSavedPerAccountSettings.setBOOL("BusyResponseChanged", TRUE ); -	} -	else -	{ -		gSavedPerAccountSettings.setBOOL("BusyResponseChanged", FALSE ); -	} +	bool busy_flag = +			LLTrans::getString("BusyModeResponseDefault") +					!= getChild<LLUICtrl>("busy_response")->getValue().asString(); + +	gSavedPerAccountSettings.setBOOL("BusyResponseChanged", busy_flag );  }  LLFloaterPreference::~LLFloaterPreference() @@ -1502,7 +1495,8 @@ void LLFloaterPreference::onChangeMaturity()  // but the UI for this will still be enabled  void LLFloaterPreference::onClickBlockList()  { -	LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); +	LLFloaterSidePanelContainer::showPanel("people", "panel_people", +		LLSD().with("people_panel_tab_name", "blocked_panel"));  }  void LLFloaterPreference::onClickProxySettings() diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index 5385977d95..96b5c6b09b 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -61,7 +61,7 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na  	if (!getVisible())  	{ -		openFloater(); +	openFloater();  	}  	LLPanel* panel = NULL; @@ -69,10 +69,7 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na  	LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent());  	if (container)  	{ -		LLSD new_params = params; -		new_params[LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME] = panel_name; -		container->onOpen(new_params); - +		container->openPanel(panel_name, params);  		panel = container->getCurrentPanel();  	}  	else if ((panel = dynamic_cast<LLPanel*>(view)) != NULL) diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 1a17183efd..bb01ce5a7e 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -29,7 +29,7 @@  #include "llfloatertranslationsettings.h"  // Viewer includes -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "lltranslate.h"  #include "llviewercontrol.h" // for gSavedSettings @@ -293,6 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK()  	gSavedSettings.setString("TranslationService", getSelectedService());  	gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey());  	gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); -	LLNearbyChatBar::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured()); +	LLNearbyChat::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured());  	closeFloater(false);  } diff --git a/indra/newview/llfloatervoicevolume.cpp b/indra/newview/llfloatervoicevolume.cpp new file mode 100644 index 0000000000..87b388b30a --- /dev/null +++ b/indra/newview/llfloatervoicevolume.cpp @@ -0,0 +1,209 @@ +/**  + * @file llfloatervoicevolume.cpp + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatervoicevolume.h" + +// Linden libraries +#include "llavatarname.h" +#include "llavatarnamecache.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "lltextbox.h" + +// viewer files +#include "llagent.h" +#include "llavataractions.h" +#include "llinspect.h" +#include "lltransientfloatermgr.h" +#include "llvoiceclient.h" + +class LLAvatarName; + +////////////////////////////////////////////////////////////////////////////// +// LLFloaterVoiceVolume +////////////////////////////////////////////////////////////////////////////// + +// Avatar Inspector, a small information window used when clicking +// on avatar names in the 2D UI and in the ambient inspector widget for +// the 3D world. +class LLFloaterVoiceVolume : public LLInspect, LLTransientFloater +{ +	friend class LLFloaterReg; +	 +public: +	// avatar_id - Avatar ID for which to show information +	// Inspector will be positioned relative to current mouse position +	LLFloaterVoiceVolume(const LLSD& avatar_id); +	virtual ~LLFloaterVoiceVolume(); +	 +	/*virtual*/ BOOL postBuild(void); +	 +	// Because floater is single instance, need to re-parse data on each spawn +	// (for example, inspector about same avatar but in different position) +	/*virtual*/ void onOpen(const LLSD& avatar_id); + +	/*virtual*/ LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; } + +private: +	// Set the volume slider to this user's current client-side volume setting, +	// hiding/disabling if the user is not nearby. +	void updateVolumeControls(); + +	void onClickMuteVolume(); +	void onVolumeChange(const LLSD& data); +	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); +	 +private: +	LLUUID				mAvatarID; +	// Need avatar name information to spawn friend add request +	LLAvatarName		mAvatarName; +}; + +LLFloaterVoiceVolume::LLFloaterVoiceVolume(const LLSD& sd) +:	LLInspect(LLSD())		// single_instance, doesn't really need key +,	mAvatarID()				// set in onOpen()  *Note: we used to show partner's name but we dont anymore --angela 3rd Dec* +,	mAvatarName() +{ +	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this); +	LLTransientFloater::init(this); +} + +LLFloaterVoiceVolume::~LLFloaterVoiceVolume() +{ +	LLTransientFloaterMgr::getInstance()->removeControlView(this); +} + +/*virtual*/ +BOOL LLFloaterVoiceVolume::postBuild(void) +{ +	getChild<LLUICtrl>("mute_btn")->setCommitCallback( +		boost::bind(&LLFloaterVoiceVolume::onClickMuteVolume, this) ); + +	getChild<LLUICtrl>("volume_slider")->setCommitCallback( +		boost::bind(&LLFloaterVoiceVolume::onVolumeChange, this, _2)); + +	return TRUE; +} + + +// Multiple calls to showInstance("floater_voice_volume", foo) will provide different +// LLSD for foo, which we will catch here. +//virtual +void LLFloaterVoiceVolume::onOpen(const LLSD& data) +{ +	// Start open animation +	LLInspect::onOpen(data); + +	// Extract appropriate avatar id +	mAvatarID = data["avatar_id"]; + +	LLUI::positionViewNearMouse(this); + +	getChild<LLUICtrl>("avatar_name")->setValue(""); +	updateVolumeControls(); + +	LLAvatarNameCache::get(mAvatarID, +		boost::bind(&LLFloaterVoiceVolume::onAvatarNameCache, this, _1, _2)); +} + +void LLFloaterVoiceVolume::updateVolumeControls() +{ +	bool voice_enabled = LLVoiceClient::getInstance()->getVoiceEnabled(mAvatarID); + +	LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); +	LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); + +	// Do not display volume slider and mute button if it  +	// is ourself or we are not in a voice channel together +	if (!voice_enabled || (mAvatarID == gAgent.getID())) +	{ +		mute_btn->setVisible(false); +		volume_slider->setVisible(false); +	} +	else  +	{ +		mute_btn->setVisible(true); +		volume_slider->setVisible(true); + +		// By convention, we only display and toggle voice mutes, not all mutes +		bool is_muted = LLAvatarActions::isVoiceMuted(mAvatarID); +		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); + +		mute_btn->setEnabled(!is_linden); +		mute_btn->setValue(is_muted); + +		volume_slider->setEnabled(!is_muted); + +		F32 volume; +		if (is_muted) +		{ +			// it's clearer to display their volume as zero +			volume = 0.f; +		} +		else +		{ +			// actual volume +			volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); +		} +		volume_slider->setValue((F64)volume); +	} + +} + +void LLFloaterVoiceVolume::onClickMuteVolume() +{ +	LLAvatarActions::toggleMuteVoice(mAvatarID); +	updateVolumeControls(); +} + +void LLFloaterVoiceVolume::onVolumeChange(const LLSD& data) +{ +	F32 volume = (F32)data.asReal(); +	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); +} + +void LLFloaterVoiceVolume::onAvatarNameCache( +		const LLUUID& agent_id, +		const LLAvatarName& av_name) +{ +	if (agent_id != mAvatarID) +	{ +		return; +	} + +	getChild<LLUICtrl>("avatar_name")->setValue(av_name.getCompleteName()); +	mAvatarName = av_name; +} + +////////////////////////////////////////////////////////////////////////////// +// LLFloaterVoiceVolumeUtil +////////////////////////////////////////////////////////////////////////////// +void LLFloaterVoiceVolumeUtil::registerFloater() +{ +	LLFloaterReg::add("floater_voice_volume", "floater_voice_volume.xml", +					  &LLFloaterReg::build<LLFloaterVoiceVolume>); +} diff --git a/indra/newview/llfloatervoicevolume.h b/indra/newview/llfloatervoicevolume.h new file mode 100644 index 0000000000..8fcf7f250b --- /dev/null +++ b/indra/newview/llfloatervoicevolume.h @@ -0,0 +1,35 @@ +/**  + * @file llfloatervoicevolume.h + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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$ + */ + +#ifndef LL_LLFLOATERVOICEVOLUME_H +#define LL_LLFLOATERVOICEVOLUME_H + +namespace LLFloaterVoiceVolumeUtil +{ +	// Register with LLFloaterReg +	void registerFloater(); +} + +#endif // LL_LLFLOATERVOICEVOLUME_H diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 1fa194ab19..57fc3f7efd 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -203,6 +203,7 @@ LLFolderView::Params::Params()  	show_load_status("show_load_status", true),  	use_ellipses("use_ellipses", false)  { +	folder_indentation = -4;  } @@ -251,10 +252,7 @@ LLFolderView::LLFolderView(const Params& p)  	mAutoOpenCandidate = NULL;  	mAutoOpenTimer.stop();  	mKeyboardSelection = FALSE; -	const LLFolderViewItem::Params& item_params = -		LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); -	S32 indentation = item_params.folder_indentation(); -	mIndentation = -indentation; // children start at indentation 0 +	mIndentation = p.folder_indentation;  	gIdleCallbacks.addFunction(idle, this);  	//clear label @@ -262,7 +260,6 @@ LLFolderView::LLFolderView(const Params& p)  	// just make sure the label ("Inventory Folder") never shows up  	mLabel = LLStringUtil::null; -	//mRenamer->setWriteableBgColor(LLColor4::white);  	// Escape is handled by reverting the rename, not commiting it (default behavior)  	LLLineEditor::Params params;  	params.name("ren"); @@ -554,7 +551,7 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)  		LLView::reshape(width, height, called_from_parent);  		scroll_rect = mScrollContainer->getContentWindowRect();  	} -	width  = llmax(mMinWidth, scroll_rect.getWidth()); +	width = llmax(mMinWidth, scroll_rect.getWidth());  	height = llmax(mRunningHeight, scroll_rect.getHeight());  	// Restrict width within scroll container's width @@ -1971,21 +1968,11 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,  	// when drop is not handled by child, it should be handled  	// by the folder which is the hierarchy root. -	if (!handled) -	{ -		if (getListener()->getUUID().notNull()) +	if (!handled +		&& getListener()->getUUID().notNull())  		{  			handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);  		} -		else -		{ -			if (!mFolders.empty()) -			{ -				// dispatch to last folder as a hack to support "Contents" folder in object inventory -				handled = mFolders.back()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); -			} -		} -	}  	if (handled)  	{ diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index da8bb15f8e..dc3d02eac6 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -210,14 +210,6 @@ public:  	// Public rename functionality - can only start the process  	void startRenamingSelectedItem( void ); -	// These functions were used when there was only one folderview, -	// and relied on that concept. This functionality is now handled -	// by the listeners and the lldraganddroptool. -	//LLFolderViewItem*	getMovingItem() { return mMovingItem; } -	//void setMovingItem( LLFolderViewItem* item ) { mMovingItem = item; } -	//void				dragItemIntoFolder( LLFolderViewItem* moving_item, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept ); -	//void				dragFolderIntoFolder( LLFolderViewFolder* moving_folder, LLFolderViewFolder* dst_folder, BOOL drop, BOOL* accept ); -  	// LLView functionality  	///*virtual*/ BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent );  	/*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index d2b4866987..f40f051537 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -363,7 +363,7 @@ void LLFolderViewItem::arrangeAndSet(BOOL set_selection,  	LLFolderView* root = getRoot();  	if (getParentFolder())  	{ -	getParentFolder()->requestArrange(); +		getParentFolder()->requestArrange();  	}  	if(set_selection)  	{ @@ -423,9 +423,8 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)  	const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>();  	S32 indentation = p.folder_indentation();  	// Only indent deeper items in hierarchy -	mIndentation = (getParentFolder()  -					&& getParentFolder()->getParentFolder() ) -		? mParentFolder->getIndentation() + indentation +	mIndentation = (getParentFolder()) +		? getParentFolder()->getIndentation() + indentation  		: 0;  	if (mLabelWidthDirty)  	{ diff --git a/indra/newview/llfollowcam.cpp b/indra/newview/llfollowcam.cpp index b670af1782..47612fe25c 100644 --- a/indra/newview/llfollowcam.cpp +++ b/indra/newview/llfollowcam.cpp @@ -38,7 +38,6 @@ std::vector<LLFollowCamParams*> LLFollowCamMgr::sParamStack;  //-------------------------------------------------------  // constants  //------------------------------------------------------- -const F32 ONE_HALF							= 0.5;   const F32 FOLLOW_CAM_ZOOM_FACTOR			= 0.1f;  const F32 FOLLOW_CAM_MIN_ZOOM_AMOUNT		= 0.1f;  const F32 DISTANCE_EPSILON					= 0.0001f; diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 66ca76bfb0..26b63bdacb 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -51,7 +51,7 @@  #include "llviewermessage.h"  #include "llvoavatarself.h"  #include "llviewerstats.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llappearancemgr.h"  #include "llgesturelistener.h" @@ -997,7 +997,7 @@ void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step)  			const BOOL animate = FALSE; -			LLNearbyChatBar::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate); +			LLNearbyChat::getInstance()->sendChatFromViewer(chat_text, CHAT_TYPE_NORMAL, animate);  			gesture->mCurrentStep++;  			break; diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 129cddda45..2de891565c 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -86,7 +86,7 @@ LLGroupList::LLGroupList(const Params& p)  	registrar.add("People.Groups.Action",			boost::bind(&LLGroupList::onContextMenuItemClick,	this, _2));  	enable_registrar.add("People.Groups.Enable",	boost::bind(&LLGroupList::onContextMenuItemEnable,	this, _2)); -	LLMenuGL* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups.xml", +	LLToggleableMenu* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups.xml",  			gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());  	if(context_menu)  		mContextMenuHandle = context_menu->getHandle(); @@ -112,7 +112,7 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)  {  	BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask); -	LLMenuGL* context_menu = (LLMenuGL*)mContextMenuHandle.get(); +	LLToggleableMenu* context_menu = mContextMenuHandle.get();  	if (context_menu && size() > 0)  	{  		context_menu->buildDrawLabels(); diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 8abf14b3d0..6c8f4406ab 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -28,10 +28,13 @@  #define LL_LLGROUPLIST_H  #include "llevent.h" +#include "llpointer.h" +  #include "llflatlistview.h"  #include "llpanel.h" -#include "llpointer.h"  #include "llstyle.h" +#include "lltoggleablemenu.h" +  #include "llgroupmgr.h"  /** @@ -57,6 +60,8 @@ public:  	void toggleIcons();  	bool getIconsVisible() const { return mShowIcons; } +	LLToggleableMenu* getContextMenu() const { return mContextMenuHandle.get(); } +  private:  	void setDirty(bool val = true)		{ mDirty = val; }  	void refresh(); @@ -66,7 +71,7 @@ private:  	bool onContextMenuItemClick(const LLSD& userdata);  	bool onContextMenuItemEnable(const LLSD& userdata); -	LLHandle<LLView>	mContextMenuHandle; +	LLHandle<LLToggleableMenu>	mContextMenuHandle;  	bool mShowIcons;  	bool mDirty; diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 482294c8a6..3336097955 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -166,7 +166,6 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3&  	}  	// scale screen size of borders down -	//RN: for now, text on hud objects is never occluded  	LLVector3 x_pixel_vec;  	LLVector3 y_pixel_vec; @@ -187,45 +186,29 @@ BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3&  			+ (y_pixel_vec * screen_offset.mV[VY]); -	//if (mUseBubble) +	LLVector3 bg_pos = render_position +		+ (F32)mOffsetY * y_pixel_vec +		- (width_vec / 2.f) +		- (height_vec); + +	LLVector3 v[] =   	{ -		LLVector3 bg_pos = render_position -			+ (F32)mOffsetY * y_pixel_vec -			- (width_vec / 2.f) -			- (height_vec); -		//LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); +		bg_pos, +		bg_pos + width_vec, +		bg_pos + width_vec + height_vec, +		bg_pos + height_vec, +	}; -		LLVector3 v[] =  -		{ -			bg_pos, -			bg_pos + width_vec, -			bg_pos + width_vec + height_vec, -			bg_pos + height_vec, -		}; +	LLVector3 dir = end-start; +	F32 a, b, t; -		if (debug_render) +	if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || +		LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) +	{ +		if (t <= 1.f)  		{ -			gGL.begin(LLRender::LINE_STRIP); -			gGL.vertex3fv(v[0].mV); -			gGL.vertex3fv(v[1].mV); -			gGL.vertex3fv(v[2].mV); -			gGL.vertex3fv(v[3].mV); -			gGL.vertex3fv(v[0].mV); -			gGL.vertex3fv(v[2].mV); -			gGL.end(); -		} - -		LLVector3 dir = end-start; -		F32 a, b, t; - -		if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || -			LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) -		{ -			if (t <= 1.f) -			{ -				intersection = start + dir*t; -				return TRUE; -			} +			intersection = start + dir*t; +			return TRUE;  		}  	} @@ -241,12 +224,6 @@ void LLHUDNameTag::render()  	}  } -void LLHUDNameTag::renderForSelect() -{ -	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); -	renderText(TRUE); -} -  void LLHUDNameTag::renderText(BOOL for_select)  {  	if (!mVisible || mHidden) @@ -299,24 +276,6 @@ void LLHUDNameTag::renderText(BOOL for_select)  	LLColor4 bg_color = LLUIColorTable::instance().getColor("NameTagBackground");  	bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); -	// maybe a no-op? -	//const S32 border_height = 16; -	//const S32 border_width = 16; -	const S32 border_height = 8; -	const S32 border_width = 8; - -	// *TODO move this into helper function -	F32 border_scale = 1.f; - -	if (border_height * 2 > mHeight) -	{ -		border_scale = (F32)mHeight / ((F32)border_height * 2.f); -	} -	if (border_width * 2 > mWidth) -	{ -		border_scale = llmin(border_scale, (F32)mWidth / ((F32)border_width * 2.f)); -	} -  	// scale screen size of borders down  	//RN: for now, text on hud objects is never occluded @@ -325,152 +284,34 @@ void LLHUDNameTag::renderText(BOOL for_select)  	LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec); -	LLVector2 border_scale_vec((F32)border_width / (F32)imagep->getTextureWidth(), (F32)border_height / (F32)imagep->getTextureHeight());  	LLVector3 width_vec = mWidth * x_pixel_vec;  	LLVector3 height_vec = mHeight * y_pixel_vec; -	LLVector3 scaled_border_width = (F32)llfloor(border_scale * (F32)border_width) * x_pixel_vec; -	LLVector3 scaled_border_height = (F32)llfloor(border_scale * (F32)border_height) * y_pixel_vec;  	mRadius = (width_vec + height_vec).magVec() * 0.5f;  	LLCoordGL screen_pos;  	LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE); -	LLVector2 screen_offset; -//	if (!mUseBubble) -//	{ -//		screen_offset = mPositionOffset; -//	} -//	else -//	{ -		screen_offset = updateScreenPos(mPositionOffset); -//	} +	LLVector2 screen_offset = updateScreenPos(mPositionOffset);  	LLVector3 render_position = mPositionAgent    			+ (x_pixel_vec * screen_offset.mV[VX])  			+ (y_pixel_vec * screen_offset.mV[VY]); -//	if (mUseBubble) +	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); +	LLRect screen_rect; +	screen_rect.setCenterAndSize(0, static_cast<S32>(lltrunc(-mHeight / 2 + mOffsetY)), static_cast<S32>(lltrunc(mWidth)), static_cast<S32>(lltrunc(mHeight))); +	imagep->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); +	if (mLabelSegments.size())  	{ -		LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); -		LLUI::pushMatrix(); -		{ -			LLVector3 bg_pos = render_position -				+ (F32)mOffsetY * y_pixel_vec -				- (width_vec / 2.f) -				- (height_vec); -			LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - -			if (for_select) -			{ -				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -				S32 name = mSourceObject->mGLName; -				LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); -				gGL.color4ubv(coloru.mV); -				gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); -				LLUI::popMatrix(); -				return; -			} -			else -			{ -				gGL.getTexUnit(0)->bind(imagep->getImage()); -				 -				gGL.color4fv(bg_color.mV); -				gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); -		 -				if ( mLabelSegments.size()) -				{ -					LLUI::pushMatrix(); -					{ -						gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); -						LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; -						LLVector3 label_offset = height_vec - label_height; -						LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); -						gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); -					} -					LLUI::popMatrix(); -				} -			} - -			BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f; -			BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f); +		LLUIImagePtr rect_top_image = LLUI::getUIImage("Rounded_Rect_Top"); +		LLRect label_top_rect = screen_rect; +		const S32 label_height = llround((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f))); +		label_top_rect.mBottom = label_top_rect.mTop - label_height; +		LLColor4 label_top_color = text_color; +		label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor; -			// draw line segments pointing to parent object -			if (!mOffscreen && (outside_width || outside_height)) -			{ -				LLUI::pushMatrix(); -				{ -					gGL.color4fv(bg_color.mV); -					LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec); -					target_pos += (width_vec / 2.f); -					target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero; -					target_pos -= 3.f * x_pixel_vec; -					target_pos -= 6.f * y_pixel_vec; -					LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]); -					gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec);	 -				} -				LLUI::popMatrix(); - -				gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -				LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE); -				 -				LLVector3 box_center_offset; -				box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f); -				LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]); -				gGL.color4fv(bg_color.mV); -				LLUI::setLineWidth(2.0); -				gGL.begin(LLRender::LINES); -				{ -					if (outside_width) -					{ -						LLVector3 vert; -						// draw line in x then y -						if (mPositionOffset.mV[VX] < 0.f) -						{ -							// start at right edge -							vert = width_vec * 0.5f; -							gGL.vertex3fv(vert.mV); -						} -						else -						{ -							// start at left edge -							vert = width_vec * -0.5f; -							gGL.vertex3fv(vert.mV); -						} -						vert = -mPositionOffset.mV[VX] * x_pixel_vec; -						gGL.vertex3fv(vert.mV); -						gGL.vertex3fv(vert.mV); -						vert -= mPositionOffset.mV[VY] * y_pixel_vec; -						vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); -						gGL.vertex3fv(vert.mV); -					} -					else -					{ -						LLVector3 vert; -						// draw line in y then x -						if (mPositionOffset.mV[VY] < 0.f) -						{ -							// start at top edge -							vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); -							gGL.vertex3fv(vert.mV); -						} -						else -						{ -							// start at bottom edge -							vert = (height_vec * -0.5f)  - (mPositionOffset.mV[VX] * x_pixel_vec); -							gGL.vertex3fv(vert.mV); -						} -						vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec; -						vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); -						gGL.vertex3fv(vert.mV); -					} -				} -				gGL.end(); -				LLUI::setLineWidth(1.0); - -			} -		} -		LLUI::popMatrix(); +		rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color);  	}  	F32 y_offset = (F32)mOffsetY; @@ -874,29 +715,26 @@ void LLHUDNameTag::updateAll()  	for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it)  	{  		LLHUDNameTag* textp = (*r_it); -//		if (textp->mUseBubble) -//		{ -			if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) -			{ -				textp->setLOD(3); -			} -			else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) -			{ -				textp->setLOD(2); -			} -			else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) -			{ -				textp->setLOD(1); -			} -			else -			{ -				textp->setLOD(0); -			} -			textp->updateSize(); -			// find on-screen position and initialize collision rectangle -			textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); -			current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight()); -//		} +		if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE) +		{ +			textp->setLOD(3); +		} +		else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE) +		{ +			textp->setLOD(2); +		} +		else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE) +		{ +			textp->setLOD(1); +		} +		else +		{ +			textp->setLOD(0); +		} +		textp->updateSize(); +		// find on-screen position and initialize collision rectangle +		textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero); +		current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight());  	}  	LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat(); @@ -914,20 +752,12 @@ void LLHUDNameTag::updateAll()  		{  			LLHUDNameTag* src_textp = (*src_it); -//			if (!src_textp->mUseBubble) -//			{ -//				continue; -//			}  			VisibleTextObjectIterator dst_it = src_it;  			++dst_it;  			for (; dst_it != sVisibleTextObjects.end(); ++dst_it)  			{  				LLHUDNameTag* dst_textp = (*dst_it); -//				if (!dst_textp->mUseBubble) -//				{ -//					continue; -//				}  				if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect))  				{  					LLRectf intersect_rect = src_textp->mSoftScreenRect; @@ -976,10 +806,6 @@ void LLHUDNameTag::updateAll()  	VisibleTextObjectIterator this_object_it;  	for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it)  	{ -//		if (!(*this_object_it)->mUseBubble) -//		{ -//			continue; -//		}  		(*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC));  	}  } @@ -1037,10 +863,6 @@ void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list)  	VisibleTextObjectIterator text_it;  	for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it)  	{ -//		if (!(*text_it)->mUseBubble) -//		{ -//			continue; -//		}  		pick_list.insert((*text_it)->mSourceObject);  	}  } diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h index 3325c22def..72647d5b26 100644 --- a/indra/newview/llhudnametag.h +++ b/indra/newview/llhudnametag.h @@ -118,7 +118,6 @@ public:  	/*virtual*/ void markDead();  	friend class LLHUDObject;  	/*virtual*/ F32 getDistance() const { return mLastDistance; } -	//void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; }  	S32  getLOD() { return mLOD; }  	BOOL getVisible() { return mVisible; }  	BOOL getHidden() const { return mHidden; } @@ -136,7 +135,6 @@ protected:  	LLHUDNameTag(const U8 type);  	/*virtual*/ void render(); -	/*virtual*/ void renderForSelect();  	void renderText(BOOL for_select);  	static void updateAll();  	void setLOD(S32 lod); diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp index 95d57d08d8..0960846510 100644 --- a/indra/newview/llhudobject.cpp +++ b/indra/newview/llhudobject.cpp @@ -232,9 +232,11 @@ LLHUDEffect *LLHUDObject::addHUDEffect(const U8 type)  	case LL_HUD_EFFECT_LOOKAT:  		hud_objectp = new LLHUDEffectLookAt(type);  		break; +#ifdef XXX_STINSON_CHUI_REWORK  	case LL_HUD_EFFECT_VOICE_VISUALIZER:  		hud_objectp = new LLVoiceVisualizer(type);  		break; +#endif // XXX_STINSON_CHUI_REWORK  	case LL_HUD_EFFECT_POINTAT:  		hud_objectp = new LLHUDEffectPointAt(type);  		break; diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h index 2f7a98c86c..21cf5fe17c 100644 --- a/indra/newview/llhudobject.h +++ b/indra/newview/llhudobject.h @@ -94,7 +94,9 @@ public:  		LL_HUD_EFFECT_EDIT,  		LL_HUD_EFFECT_LOOKAT,  		LL_HUD_EFFECT_POINTAT, +#ifdef XXX_STINSON_CHUI_REWORK  		LL_HUD_EFFECT_VOICE_VISUALIZER,	// Ventrella +#endif // XXX_STINSON_CHUI_REWORK  		LL_HUD_NAME_TAG,  		LL_HUD_EFFECT_BLOB  	}; diff --git a/indra/newview/llimconversation.cpp b/indra/newview/llimconversation.cpp new file mode 100644 index 0000000000..708913bbee --- /dev/null +++ b/indra/newview/llimconversation.cpp @@ -0,0 +1,329 @@ +/** + * @file llimconversation.cpp + * @brief LLIMConversation class implements the common behavior of LNearbyChatBar + * @brief and LLIMFloater for hosting both in LLIMContainer + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llimconversation.h" + +#include "lldraghandle.h" +#include "llfloaterreg.h" +#include "llimfloater.h" +#include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container +#include "lllayoutstack.h" +#include "llnearbychat.h" +#include "llnearbychat.h" + +const F32 REFRESH_INTERVAL = 0.2f; + +LLIMConversation::LLIMConversation(const LLUUID& session_id) +  : LLTransientDockableFloater(NULL, true, session_id) +  ,	LLEventTimer(REFRESH_INTERVAL) +  ,  mIsP2PChat(false) +  ,  mExpandCollapseBtn(NULL) +  ,  mTearOffBtn(NULL) +  ,  mCloseBtn(NULL) +  ,  mSessionID(session_id) +  , mParticipantList(NULL) +{ +	mCommitCallbackRegistrar.add("IMSession.Menu.Action", +			boost::bind(&LLIMConversation::onIMSessionMenuItemClicked,  this, _2)); +//	mCommitCallbackRegistrar.add("IMSession.ExpCollapseBtn.Click", +//			boost::bind(&LLIMConversation::onSlide,  this)); +//	mCommitCallbackRegistrar.add("IMSession.CloseBtn.Click", +//			boost::bind(&LLFloater::onClickClose, this)); +	mCommitCallbackRegistrar.add("IMSession.TearOffBtn.Click", +			boost::bind(&LLIMConversation::onTearOffClicked, this)); +	mEnableCallbackRegistrar.add("IMSession.Menu.CompactExpandedModes.CheckItem", +			boost::bind(&LLIMConversation::onIMCompactExpandedMenuItemCheck, this, _2)); +	mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.CheckItem", +			boost::bind(&LLIMConversation::onIMShowModesMenuItemCheck,   this, _2)); +	mEnableCallbackRegistrar.add("IMSession.Menu.ShowModes.Enable", +			boost::bind(&LLIMConversation::onIMShowModesMenuItemEnable,  this, _2)); +} + +LLIMConversation::~LLIMConversation() +{ +	if (mParticipantList) +	{ +		delete mParticipantList; +		mParticipantList = NULL; +	} +} + +BOOL LLIMConversation::postBuild() +{ +	mCloseBtn = getChild<LLButton>("close_btn"); +	mCloseBtn->setCommitCallback(boost::bind(&LLFloater::onClickClose, this)); + +	mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); +	mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMConversation::onSlide, this)); + +	mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel"); +	mParticipantListPanel->setVisible( +			mIsNearbyChat? false : gSavedSettings.getBOOL("IMShowControlPanel")); +	mExpandCollapseBtn->setImageOverlay( +				getString(mParticipantListPanel->getVisible() ? "collapse_icon" : "expand_icon")); +	mExpandCollapseBtn->setEnabled(!mIsP2PChat); + +	mTearOffBtn = getChild<LLButton>("tear_off_btn"); +	mTearOffBtn->setCommitCallback(boost::bind(&LLIMConversation::onTearOffClicked, this)); + +	if (!getTornOff()) +	{ +		setOpenPositioning(LLFloaterEnums::POSITIONING_RELATIVE); +	} + +	buildParticipantList(); + +	if (isChatMultiTab()) +	{ +		return LLFloater::postBuild(); +	} +	else +	{ +		return LLDockableFloater::postBuild(); +	} + +} + +BOOL LLIMConversation::tick() +{ +	// Need to resort the participant list if it's in sort by recent speaker order. +	if (mParticipantList) +	{ +		mParticipantList->update(); +	} + +	return false; +} + +void LLIMConversation::buildParticipantList() +{	if (mIsNearbyChat) +	{ +	} +	else +	{ +		// for group and ad-hoc chat we need to include agent into list +		if(!mIsP2PChat && !mParticipantList && mSessionID.notNull()) +		{ +			LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(mSessionID); +			mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true, false); +		} +	} +} + +void LLIMConversation::onSortMenuItemClicked(const LLSD& userdata) +{ +	// TODO: Check this code when when sort order menu will be added. (EM) +	if (true || !mParticipantList) +		return; + +	std::string chosen_item = userdata.asString(); + +	if (chosen_item == "sort_name") +	{ +		mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); +	} + +} + +void LLIMConversation::onIMSessionMenuItemClicked(const LLSD& userdata) +{ +	std::string item = userdata.asString(); + +	if (item == "compact_view" || item == "expanded_view") +	{ +		gSavedSettings.setBOOL("PlainTextChatHistory", item == "compact_view"); +	} +	else +	{ +		bool prev_value = gSavedSettings.getBOOL(item); +		gSavedSettings.setBOOL(item, !prev_value); +	} + +	LLIMConversation::processChatHistoryStyleUpdate(); +} + + +bool LLIMConversation::onIMCompactExpandedMenuItemCheck(const LLSD& userdata) +{ +	std::string item = userdata.asString(); +	bool is_plain_text_mode = gSavedSettings.getBOOL("PlainTextChatHistory"); + +	return is_plain_text_mode? item == "compact_view" : item == "expanded_view"; +} + + +bool LLIMConversation::onIMShowModesMenuItemCheck(const LLSD& userdata) +{ +	return gSavedSettings.getBOOL(userdata.asString()); +} + +// enable/disable states for the "show time" and "show names" items of the show-modes menu +bool LLIMConversation::onIMShowModesMenuItemEnable(const LLSD& userdata) +{ +	std::string item = userdata.asString(); +	bool plain_text = gSavedSettings.getBOOL("PlainTextChatHistory"); +	bool is_not_names = (item != "IMShowNamesForP2PConv"); +	return (plain_text && (is_not_names || mIsP2PChat)); +} + +void LLIMConversation::updateHeaderAndToolbar() +{ +	bool is_hosted = getHost() != NULL; + +	if (is_hosted) +	{ +		for (S32 i = 0; i < BUTTON_COUNT; i++) +		{ +			if (mButtons[i]) +			{ +				// Hide the standard header buttons in a docked IM floater. +				mButtons[i]->setVisible(false); +			} +		} +	} + +	bool is_control_panel_visible = false; +	if (!mIsP2PChat) +	{ +		// Control panel should be visible only in torn off floaters. +		is_control_panel_visible = !is_hosted && gSavedSettings.getBOOL("IMShowControlPanel"); +		mParticipantListPanel->setVisible(is_control_panel_visible); +	} + +	// Display collapse image (<<) if the floater is hosted +	// or if it is torn off but has an open control panel. +	bool is_expanded = is_hosted || is_control_panel_visible; +	mExpandCollapseBtn->setImageOverlay(getString(is_expanded ? "collapse_icon" : "expand_icon")); + +	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(mSessionID); +	if (session) +	{ +		// The button (>>) should be disabled for torn off P2P conversations. +		mExpandCollapseBtn->setEnabled(is_hosted || !session->isP2PSessionType()); +	} +	else +	{ +		if (!mIsNearbyChat) +		{ +			llwarns << "IM session not found." << llendl; +		} +	} + +	if (mDragHandle) +	{ +		// toggle floater's drag handle and title visibility +		mDragHandle->setVisible(!is_hosted); +	} + +	mTearOffBtn->setImageOverlay(getString(is_hosted ? "tear_off_icon" : "return_icon")); + +	mCloseBtn->setVisible(is_hosted); + +	enableDisableCallBtn(); +} + +// static +void LLIMConversation::processChatHistoryStyleUpdate() +{ +	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); +	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); +			iter != inst_list.end(); ++iter) +	{ +		LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); +		if (floater) +		{ +			floater->reloadMessages(); +		} +	} + +	LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); +	if (nearby_chat) +	{ +		nearby_chat->reloadMessages(); +	} +} + +void LLIMConversation::updateCallBtnState(bool callIsActive) +{ +	getChild<LLButton>("voice_call_btn")->setImageOverlay( +			callIsActive? getString("call_btn_stop") : getString("call_btn_start")); +    enableDisableCallBtn(); + +} + +void LLIMConversation::onSlide(LLIMConversation* self) +{ +	LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(self->getHost()); +	if (host_floater) +	{ +		// Hide the messages pane if a floater is hosted in the Conversations +		host_floater->collapseMessagesPane(true); +	} +	else ///< floater is torn off +	{ +		if (!self->mIsP2PChat) +		{ +			bool expand = !self->mParticipantListPanel->getVisible(); + +			// Expand/collapse the IM control panel +			self->mParticipantListPanel->setVisible(expand); + +			gSavedSettings.setBOOL("IMShowControlPanel", expand); + +			self->mExpandCollapseBtn->setImageOverlay(self->getString(expand ? "collapse_icon" : "expand_icon")); +		} +	} +} + +/*virtual*/ +void LLIMConversation::onOpen(const LLSD& key) +{ +	LLIMFloaterContainer* host_floater = dynamic_cast<LLIMFloaterContainer*>(getHost()); +	if (host_floater) +	{ +		// Show the messages pane when opening a floater hosted in the Conversations +		host_floater->collapseMessagesPane(false); +	} + +	updateHeaderAndToolbar(); +} + +void LLIMConversation::onTearOffClicked() +{ +	onClickTearOff(this); +	updateHeaderAndToolbar(); +} + +// static +bool LLIMConversation::isChatMultiTab() +{ +	// Restart is required in order to change chat window type. +	static bool is_single_window = gSavedSettings.getS32("ChatWindow") == 1; +	return is_single_window; +} diff --git a/indra/newview/llimconversation.h b/indra/newview/llimconversation.h new file mode 100644 index 0000000000..d31ae0808a --- /dev/null +++ b/indra/newview/llimconversation.h @@ -0,0 +1,105 @@ +/** + * @file llimconversation.h + * @brief LLIMConversation class implements the common behavior of LNearbyChatBar + * @brief and LLIMFloater for hosting both in LLIMContainer + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, 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$ + */ + +#ifndef LL_IMCONVERSATION_H +#define LL_IMCONVERSATION_H + +#include "lllayoutstack.h" +#include "llparticipantlist.h" +#include "lltransientdockablefloater.h" +#include "llviewercontrol.h" +#include "lleventtimer.h" + +class LLPanelChatControlPanel; + +class LLIMConversation +	: public LLTransientDockableFloater +	, public LLEventTimer +{ + +public: +	LOG_CLASS(LLIMConversation); + +	LLIMConversation(const LLUUID& session_id); +	~LLIMConversation(); + +	// reload all message with new settings of visual modes +	static void processChatHistoryStyleUpdate(); + +	/** +	 * Returns true if chat is displayed in multi tabbed floater +	 *         false if chat is displayed in multiple windows +	 */ +	static bool isChatMultiTab(); + +	// LLFloater overrides +	/*virtual*/ void onOpen(const LLSD& key); +	/*virtual*/ BOOL postBuild(); + +protected: + +	// callback for click on any items of the visual states menu +	void onIMSessionMenuItemClicked(const LLSD& userdata); + +	// callback for check/uncheck of the expanded/collapse mode's switcher +	bool onIMCompactExpandedMenuItemCheck(const LLSD& userdata); + +	// +	bool onIMShowModesMenuItemCheck(const LLSD& userdata); +	bool onIMShowModesMenuItemEnable(const LLSD& userdata); +	static void onSlide(LLIMConversation *self); +	void onTearOffClicked(); + +	// refresh a visual state of the Call button +	void updateCallBtnState(bool callIsActive); + +	// set the enable/disable state for the Call button +	virtual void enableDisableCallBtn() = 0; + +	void buildParticipantList(); +	void onSortMenuItemClicked(const LLSD& userdata); + +	/*virtual*/ BOOL tick(); + +	bool mIsNearbyChat; +	bool mIsP2PChat; + +	LLLayoutPanel* mParticipantListPanel; +	LLParticipantList* mParticipantList; +	LLUUID mSessionID; + +	LLButton* mExpandCollapseBtn; +	LLButton* mTearOffBtn; +	LLButton* mCloseBtn; + +private: +	/// Update floater header and toolbar buttons when hosted/torn off state is toggled. +	void updateHeaderAndToolbar(); +}; + + +#endif // LL_IMCONVERSATION_H diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index f67464078b..c99da9e9c1 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -28,6 +28,7 @@  #include "llimfloater.h" +#include "lldraghandle.h"  #include "llnotificationsutil.h"  #include "llagent.h" @@ -40,35 +41,31 @@  #include "llfloaterreg.h"  #include "llimfloatercontainer.h" // to replace separate IM Floaters with multifloater container  #include "llinventoryfunctions.h" -#include "lllayoutstack.h" +//#include "lllayoutstack.h"  #include "lllineeditor.h"  #include "lllogchat.h" -#include "llpanelimcontrolpanel.h"  #include "llscreenchannel.h"  #include "llsyswellwindow.h"  #include "lltrans.h"  #include "llchathistory.h"  #include "llnotifications.h"  #include "llviewerwindow.h" -#include "llvoicechannel.h"  #include "lltransientfloatermgr.h"  #include "llinventorymodel.h"  #include "llrootview.h"  #include "llspeakers.h"  #include "llviewerchat.h" - +#include "llnotificationmanager.h"  LLIMFloater::LLIMFloater(const LLUUID& session_id) -  : LLTransientDockableFloater(NULL, true, session_id), -	mControlPanel(NULL), -	mSessionID(session_id), +  : LLIMConversation(session_id),  	mLastMessageIndex(-1),  	mDialog(IM_NOTHING_SPECIAL), -	mChatHistory(NULL),  	mInputEditor(NULL),  	mSavedTitle(),  	mTypingStart(),  	mShouldSendTypingState(false), +	mChatHistory(NULL),  	mMeTyping(false),  	mOtherTyping(false),  	mTypingTimer(), @@ -76,35 +73,15 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)  	mPositioned(false),  	mSessionInitialized(false)  { -	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionID); -	if (im_session) +	mIsNearbyChat = false; + +	mSession = LLIMModel::getInstance()->findIMSession(mSessionID); + +	if (mSession)  	{ -		mSessionInitialized = im_session->mSessionInitialized; -		 -		mDialog = im_session->mType; -		switch(mDialog){ -		case IM_NOTHING_SPECIAL: -		case IM_SESSION_P2P_INVITE: -			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this); -			break; -		case IM_SESSION_CONFERENCE_START: -			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); -			break; -		case IM_SESSION_GROUP_START: -			mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); -			break; -		case IM_SESSION_INVITE:		 -			if (gAgent.isInGroup(mSessionID)) -			{ -				mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); -			} -			else -			{ -				mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this); -			} -			break; -		default: break; -		} +		mIsP2PChat = mSession->isP2PSessionType(); +		mSessionInitialized = mSession->mSessionInitialized; +		mDialog = mSession->mType;  	}  	setOverlapsScreenChannel(true); @@ -116,7 +93,7 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)  void LLIMFloater::onFocusLost()  {  	LLIMModel::getInstance()->resetActiveSessionID(); -	 +  	LLChicletBar::getInstance()->getChicletPanel()->setChicletToggleState(mSessionID, false);  } @@ -146,17 +123,16 @@ void LLIMFloater::onClose(bool app_quitting)  }  /* static */ -void LLIMFloater::newIMCallback(const LLSD& data){ -	 +void LLIMFloater::newIMCallback(const LLSD& data) +{  	if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull())  	{  		LLUUID session_id = data["session_id"].asUUID();  		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -		if (floater == NULL) return;          // update if visible, otherwise will be updated when opened -		if (floater->getVisible()) +		if (floater && floater->getVisible())  		{  			floater->updateMessages();  		} @@ -189,67 +165,64 @@ void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata )  void LLIMFloater::sendMsg()  { -	if (!gAgent.isGodlike()  -		&& (mDialog == IM_NOTHING_SPECIAL) -		&& mOtherParticipantUUID.isNull()) -	{ -		llinfos << "Cannot send IM to everyone unless you're a god." << llendl; -		return; -	} - -	if (mInputEditor) +	if (gAgent.isGodlike() +		|| (mDialog != IM_NOTHING_SPECIAL) +		|| !mOtherParticipantUUID.isNull())  	{ -		LLWString text = mInputEditor->getConvertedText(); -		if(!text.empty()) +		if (mInputEditor)  		{ -			// Truncate and convert to UTF8 for transport -			std::string utf8_text = wstring_to_utf8str(text); -			utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); -			 -			if (mSessionInitialized) -			{ -				LLIMModel::sendMessage(utf8_text, mSessionID, -					mOtherParticipantUUID,mDialog); -			} -			else +			LLWString text = mInputEditor->getConvertedText(); +			if(!text.empty())  			{ -				//queue up the message to send once the session is initialized -				mQueuedMsgsForInit.append(utf8_text); -			} +				// Truncate and convert to UTF8 for transport +				std::string utf8_text = wstring_to_utf8str(text); +				utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); -			mInputEditor->setText(LLStringUtil::null); +				if (mSessionInitialized) +				{ +					LLIMModel::sendMessage(utf8_text, mSessionID, mOtherParticipantUUID, mDialog); +				} +				else +				{ +					//queue up the message to send once the session is initialized +					mQueuedMsgsForInit.append(utf8_text); +				} + +				mInputEditor->setText(LLStringUtil::null); -			updateMessages(); +				updateMessages(); +			}  		}  	} +	else +	{ +		llinfos << "Cannot send IM to everyone unless you're a god." << llendl; +	}  } - -  LLIMFloater::~LLIMFloater()  { +	mVoiceChannelStateChangeConnection.disconnect(); +	if(LLVoiceClient::instanceExists()) +	{ +		LLVoiceClient::getInstance()->removeObserver(this); +	} +  	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);  }  //virtual  BOOL LLIMFloater::postBuild()  { -	const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID); +	const LLUUID& other_party_id = +			LLIMModel::getInstance()->getOtherParticipantID(mSessionID);  	if (other_party_id.notNull())  	{  		mOtherParticipantUUID = other_party_id;  	} -	mControlPanel->setSessionId(mSessionID); -	mControlPanel->getParent()->setVisible(gSavedSettings.getBOOL("IMShowControlPanel")); +	boundVoiceChannel(); -	LLButton* slide_left = getChild<LLButton>("slide_left_btn"); -	slide_left->setVisible(mControlPanel->getParent()->getVisible()); -	slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); - -	LLButton* slide_right = getChild<LLButton>("slide_right_btn"); -	slide_right->setVisible(!mControlPanel->getParent()->getVisible()); -	slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));  	mInputEditor = getChild<LLLineEditor>("chat_editor");  	mInputEditor->setMaxTextLength(1023); @@ -276,18 +249,16 @@ BOOL LLIMFloater::postBuild()  	mTypingStart = LLTrans::getString("IM_typing_start_string");  	// Disable input editor if session cannot accept text -	LLIMModel::LLIMSession* im_session = -		LLIMModel::instance().findIMSession(mSessionID); -	if( im_session && !im_session->mTextIMPossible ) +	if ( mSession && !mSession->mTextIMPossible )  	{  		mInputEditor->setEnabled(FALSE);  		mInputEditor->setLabel(LLTrans::getString("IM_unavailable_text_label"));  	} -	if ( im_session && im_session->isP2PSessionType()) +	if (mIsP2PChat)  	{  		// look up display name for window title -		LLAvatarNameCache::get(im_session->mOtherParticipantID, +		LLAvatarNameCache::get(mSession->mOtherParticipantID,  							   boost::bind(&LLIMFloater::onAvatarNameCache,  										   this, _1, _2));  	} @@ -297,19 +268,88 @@ BOOL LLIMFloater::postBuild()  		updateSessionName(session_name, session_name);  	} +	childSetAction("voice_call_btn", boost::bind(&LLIMFloater::onCallButtonClicked, this)); + +	LLVoiceClient::getInstance()->addObserver(this); +	  	//*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"  	//see LLFloaterIMPanel for how it is done (IB) -	if(isChatMultiTab()) +	return LLIMConversation::postBuild(); +} + +void LLIMFloater::boundVoiceChannel() +{ +	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); +	if(voice_channel)  	{ -		return LLFloater::postBuild(); +		mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback( +				boost::bind(&LLIMFloater::onVoiceChannelStateChanged, this, _1, _2)); + +		//call (either p2p, group or ad-hoc) can be already in started state +		bool callIsActive = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; +		updateCallBtnState(callIsActive); +	} +} + +void LLIMFloater::enableDisableCallBtn() +{ +	bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() +			&& LLVoiceClient::getInstance()->isVoiceWorking(); + +	if (mSession) +	{ +		bool session_initialized = mSession->mSessionInitialized; +		bool callback_enabled = mSession->mCallBackEnabled; + +		BOOL enable_connect = +				session_initialized && voice_enabled && callback_enabled; +		getChildView("voice_call_btn")->setEnabled(enable_connect);  	}  	else  	{ -		return LLDockableFloater::postBuild(); +		getChildView("voice_call_btn")->setEnabled(false); +	} +} + + +void LLIMFloater::onCallButtonClicked() +{ +	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); +	if (voice_channel) +	{ +		bool is_call_active = voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED; +	    if (is_call_active) +	    { +		    gIMMgr->endCall(mSessionID); +	    } +	    else +	    { +		    gIMMgr->startCall(mSessionID); +	    }  	}  } +/*void LLIMFloater::onOpenVoiceControlsClicked() +{ +	LLFloaterReg::showInstance("voice_controls"); +}*/ + +void LLIMFloater::onChange(EStatusType status, const std::string &channelURI, bool proximal) +{ +	if(status != STATUS_JOINING && status != STATUS_LEFT_CHANNEL) +	{ +		enableDisableCallBtn(); +	} +} + +void LLIMFloater::onVoiceChannelStateChanged( +		const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) +{ +	bool callIsActive = new_state >= LLVoiceChannel::STATE_CALL_STARTED; +	updateCallBtnState(callIsActive); +} +  void LLIMFloater::updateSessionName(const std::string& ui_title,  									const std::string& ui_label)  { @@ -328,8 +368,10 @@ void LLIMFloater::onAvatarNameCache(const LLUUID& agent_id,  }  // virtual -void LLIMFloater::draw() +BOOL LLIMFloater::tick()  { +	BOOL parents_retcode = LLIMConversation::tick(); +  	if ( mMeTyping )  	{  		// Time out if user hasn't typed for a while. @@ -339,46 +381,7 @@ void LLIMFloater::draw()  		}  	} -	LLTransientDockableFloater::draw(); -} - - -// static -void* LLIMFloater::createPanelIMControl(void* userdata) -{ -	LLIMFloater *self = (LLIMFloater*)userdata; -	self->mControlPanel = new LLPanelIMControlPanel(); -	self->mControlPanel->setXMLFilename("panel_im_control_panel.xml"); -	return self->mControlPanel; -} - - -// static -void* LLIMFloater::createPanelGroupControl(void* userdata) -{ -	LLIMFloater *self = (LLIMFloater*)userdata; -	self->mControlPanel = new LLPanelGroupControlPanel(self->mSessionID); -	self->mControlPanel->setXMLFilename("panel_group_control_panel.xml"); -	return self->mControlPanel; -} - -// static -void* LLIMFloater::createPanelAdHocControl(void* userdata) -{ -	LLIMFloater *self = (LLIMFloater*)userdata; -	self->mControlPanel = new LLPanelAdHocControlPanel(self->mSessionID); -	self->mControlPanel->setXMLFilename("panel_adhoc_control_panel.xml"); -	return self->mControlPanel; -} - -void LLIMFloater::onSlide() -{ -	mControlPanel->getParent()->setVisible(!mControlPanel->getParent()->getVisible()); - -	gSavedSettings.setBOOL("IMShowControlPanel", mControlPanel->getParent()->getVisible()); - -	getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getParent()->getVisible()); -	getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getParent()->getVisible()); +	return parents_retcode;  }  //static @@ -386,7 +389,8 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)  {  	closeHiddenIMToasts(); -	if (!gIMMgr->hasSession(session_id)) return NULL; +	if (!gIMMgr->hasSession(session_id)) +		return NULL;  	if(!isChatMultiTab())  	{ @@ -406,7 +410,8 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)  	bool exist = findInstance(session_id);  	LLIMFloater* floater = getInstance(session_id); -	if (!floater) return NULL; +	if (!floater) +		return NULL;  	if(isChatMultiTab())  	{ @@ -456,6 +461,22 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)  	return floater;  } +//static +LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) +{ +    LLIMFloater* conversation = +    		LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); + +	return conversation; +} + +LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) +{ +	LLIMFloater* conversation = +				LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id); + +	return conversation; +}  void LLIMFloater::setDocked(bool docked, bool pop_on_undock)  { @@ -518,9 +539,12 @@ void LLIMFloater::setVisible(BOOL visible)  BOOL LLIMFloater::getVisible()  { +	bool visible; +  	if(isChatMultiTab())  	{ -		LLIMFloaterContainer* im_container = LLIMFloaterContainer::getInstance(); +		LLIMFloaterContainer* im_container = +				LLIMFloaterContainer::getInstance();  		// Treat inactive floater as invisible.  		bool is_active = im_container->getActiveFloater() == this; @@ -528,16 +552,21 @@ BOOL LLIMFloater::getVisible()  		//torn off floater is always inactive  		if (!is_active && getHost() != im_container)  		{ -			return LLTransientDockableFloater::getVisible(); +			visible = LLTransientDockableFloater::getVisible(); +		} +		else +		{ +			// getVisible() returns TRUE when Tabbed IM window is minimized. +			visible = is_active && !im_container->isMinimized() +						&& im_container->getVisible();  		} - -		// getVisible() returns TRUE when Tabbed IM window is minimized. -		return is_active && !im_container->isMinimized() && im_container->getVisible();  	}  	else  	{ -		return LLTransientDockableFloater::getVisible(); +		visible = LLTransientDockableFloater::getVisible();  	} + +	return visible;  }  //static @@ -545,7 +574,8 @@ bool LLIMFloater::toggle(const LLUUID& session_id)  {  	if(!isChatMultiTab())  	{ -		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); +		LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>( +				"impanel", session_id);  		if (floater && floater->getVisible() && floater->hasFocus())  		{  			// clicking on chiclet to close floater just hides it to maintain existing @@ -566,17 +596,6 @@ bool LLIMFloater::toggle(const LLUUID& session_id)  	return true;  } -//static -LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id) -{ -	return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -} - -LLIMFloater* LLIMFloater::getInstance(const LLUUID& session_id) -{ -	return LLFloaterReg::getTypedInstance<LLIMFloater>("impanel", session_id); -} -  void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)  {  	mSessionInitialized = true; @@ -586,51 +605,59 @@ void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)  	{  		mSessionID = im_session_id;  		setKey(im_session_id); -		mControlPanel->setSessionId(im_session_id); -	} -	// updating "Call" button from group control panel here to enable it without placing into draw() (EXT-4796) -	if(gAgent.isInGroup(im_session_id)) -	{ -		mControlPanel->updateCallButton(); +		boundVoiceChannel(); + +		mSession = LLIMModel::getInstance()->findIMSession(mSessionID); +		mIsP2PChat = mSession && mSession->isP2PSessionType(); + +		buildParticipantList();  	}  	//*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) -  	//need to send delayed messaged collected while waiting for session initialization -	if (!mQueuedMsgsForInit.size()) return; -	LLSD::array_iterator iter; -	for ( iter = mQueuedMsgsForInit.beginArray(); -		iter != mQueuedMsgsForInit.endArray(); -		++iter) +	if (mQueuedMsgsForInit.size())  	{ -		LLIMModel::sendMessage(iter->asString(), mSessionID, -			mOtherParticipantUUID, mDialog); +		LLSD::array_iterator iter; +		for ( iter = mQueuedMsgsForInit.beginArray(); +				iter != mQueuedMsgsForInit.endArray(); ++iter) +		{ +			LLIMModel::sendMessage(iter->asString(), mSessionID, +				mOtherParticipantUUID, mDialog); +		}  	}  } -void LLIMFloater::updateMessages() +void LLIMFloater::appendMessage(const LLChat& chat, const LLSD &args)  { -	bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory"); +	LLChat& tmp_chat = const_cast<LLChat&>(chat); +	if (!chat.mMuted) +	{ +		tmp_chat.mFromName = chat.mFromName; +		LLSD chat_args; +		if (args) chat_args = args; +		chat_args["use_plain_text_chat_history"] = +				gSavedSettings.getBOOL("PlainTextChatHistory"); +		chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); +		chat_args["show_names_for_p2p_conv"] = !mIsP2PChat +				|| gSavedSettings.getBOOL("IMShowNamesForP2PConv"); + +		mChatHistory->appendMessage(chat, chat_args); +	} +} + +void LLIMFloater::updateMessages() +{  	std::list<LLSD> messages;  	// we shouldn't reset unread message counters if IM floater doesn't have focus -	if (hasFocus()) -	{ -		LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1); -	} -	else -	{ -		LLIMModel::instance().getMessagesSilently(mSessionID, messages, mLastMessageIndex+1); -	} +    LLIMModel::instance().getMessages( +    		mSessionID, messages, mLastMessageIndex + 1, hasFocus());  	if (messages.size())  	{ -		LLSD chat_args; -		chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; -  		std::ostringstream message;  		std::list<LLSD>::const_reverse_iterator iter = messages.rbegin();  		std::list<LLSD>::const_reverse_iterator iter_end = messages.rend(); @@ -680,23 +707,23 @@ void LLIMFloater::updateMessages()  				chat.mText = message;  			} -			mChatHistory->appendMessage(chat, chat_args); +			appendMessage(chat);  			mLastMessageIndex = msg["index"].asInteger();  			// if it is a notification - next message is a notification history log, so skip it  			if (chat.mNotifId.notNull() && LLNotificationsUtil::find(chat.mNotifId) != NULL)  			{  				if (++iter == iter_end) -				{ -					break; -				} -				else -				{ -					mLastMessageIndex++; -				} -			} -		} -	} +			    { +				    break; +			    } +			    else +			    { +				    mLastMessageIndex++; +			    } +		    } +	    } +    }  }  void LLIMFloater::reloadMessages() @@ -704,6 +731,7 @@ void LLIMFloater::reloadMessages()  	mChatHistory->clear();  	mLastMessageIndex = -1;  	updateMessages(); +	mInputEditor->setFont(LLViewerChat::getChatFont());  }  // static @@ -732,28 +760,22 @@ void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userd  // static  void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata)  { -	LLIMFloater* self = (LLIMFloater*)userdata; +	LLIMFloater* self = (LLIMFloater*) userdata;  	std::string text = self->mInputEditor->getText(); -	if (!text.empty()) -	{ -		self->setTyping(true); -	} -	else -	{ -		// Deleting all text counts as stopping typing. -		self->setTyping(false); -	} + +	// Deleting all text counts as stopping typing. +	self->setTyping(!text.empty());  }  void LLIMFloater::setTyping(bool typing)  { -	if ( typing ) +	if (typing)  	{  		// Started or proceeded typing, reset the typing timeout timer  		mTypingTimeoutTimer.reset();  	} -	if ( mMeTyping != typing ) +	if (mMeTyping != typing)  	{  		// Typing state is changed  		mMeTyping = typing; @@ -765,34 +787,32 @@ void LLIMFloater::setTyping(bool typing)  	// Don't want to send typing indicators to multiple people, potentially too  	// much network traffic. Only send in person-to-person IMs. -	if ( mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL ) +	if (mShouldSendTypingState && mDialog == IM_NOTHING_SPECIAL)  	{ -		if ( mMeTyping ) -		{ -			if ( mTypingTimer.getElapsedTimeF32() > 1.f ) -			{ -				// Still typing, send 'start typing' notification -				LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, TRUE); -				mShouldSendTypingState = false; -			} -		} -		else +		// Still typing, send 'start typing' notification or +		// send 'stop typing' notification immediately +		if (!mMeTyping || mTypingTimer.getElapsedTimeF32() > 1.f)  		{ -			// Send 'stop typing' notification immediately -			LLIMModel::instance().sendTypingState(mSessionID, mOtherParticipantUUID, FALSE); +			LLIMModel::instance().sendTypingState(mSessionID, +					mOtherParticipantUUID, mMeTyping);  			mShouldSendTypingState = false; +  		}  	} -	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); -	if (speaker_mgr) -		speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); - +	if (!mIsNearbyChat) +	{ +		LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); +		if (speaker_mgr) +		{ +			speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); +		} +	}  }  void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)  { -	if ( typing ) +	if (typing)  	{  		// other user started typing  		addTypingIndicator(im_info); @@ -806,9 +826,7 @@ void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing)  void LLIMFloater::processAgentListUpdates(const LLSD& body)  { -	if ( !body.isMap() ) return; - -	if ( body.has("agent_updates") && body["agent_updates"].isMap() ) +	if (body.isMap() && body.has("agent_updates") && body["agent_updates"].isMap())  	{  		LLSD agent_data = body["agent_updates"].get(gAgentID.asString());  		if (agent_data.isMap() && agent_data.has("info")) @@ -817,7 +835,7 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body)  			if (agent_info.has("mutes"))  			{ -				BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean();  +				BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean();  				mInputEditor->setEnabled(!moderator_muted_text);  				std::string label;  				if (moderator_muted_text) @@ -833,42 +851,19 @@ void LLIMFloater::processAgentListUpdates(const LLSD& body)  	}  } -void LLIMFloater::updateChatHistoryStyle() -{ -	mChatHistory->clear(); -	mLastMessageIndex = -1; -	updateMessages(); -} - -void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue) -{ -	LLFontGL* font = LLViewerChat::getChatFont(); -	LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); -	for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); -		 iter != inst_list.end(); ++iter) -	{ -		LLIMFloater* floater = dynamic_cast<LLIMFloater*>(*iter); -		if (floater) -		{ -			floater->updateChatHistoryStyle(); -			floater->mInputEditor->setFont(font); -		} -	} - -} -  void LLIMFloater::processSessionUpdate(const LLSD& session_update)  {  	// *TODO : verify following code when moderated mode will be implemented -	if ( false && session_update.has("moderated_mode") && -		 session_update["moderated_mode"].has("voice") ) +	if (false && session_update.has("moderated_mode") && +			session_update["moderated_mode"].has("voice"))  	{  		BOOL voice_moderated = session_update["moderated_mode"]["voice"];  		const std::string session_label = LLIMModel::instance().getName(mSessionID);  		if (voice_moderated)  		{ -			setTitle(session_label + std::string(" ") + LLTrans::getString("IM_moderated_chat_label")); +			setTitle(session_label + std::string(" ") +							+ LLTrans::getString("IM_moderated_chat_label"));  		}  		else  		{ @@ -882,15 +877,14 @@ void LLIMFloater::processSessionUpdate(const LLSD& session_update)  }  BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask, -						   BOOL drop, EDragAndDropType cargo_type, -						   void *cargo_data, EAcceptance *accept, -						   std::string& tooltip_msg) +		BOOL drop, EDragAndDropType cargo_type, +		void *cargo_data, EAcceptance *accept, +		std::string& tooltip_msg)  { -  	if (mDialog == IM_NOTHING_SPECIAL)  	{  		LLToolDragAndDrop::handleGiveDragAndDrop(mOtherParticipantUUID, mSessionID, drop, -												 cargo_type, cargo_data, accept); +				cargo_type, cargo_data, accept);  	}  	// handle case for dropping calling cards (and folders of calling cards) onto invitation panel for invites @@ -900,14 +894,14 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask,  		if (cargo_type == DAD_CALLINGCARD)  		{ -			if (dropCallingCard((LLInventoryItem*)cargo_data, drop)) +			if (dropCallingCard((LLInventoryItem*) cargo_data, drop))  			{  				*accept = ACCEPT_YES_MULTI;  			}  		}  		else if (cargo_type == DAD_CATEGORY)  		{ -			if (dropCategory((LLInventoryCategory*)cargo_data, drop)) +			if (dropCategory((LLInventoryCategory*) cargo_data, drop))  			{  				*accept = ACCEPT_YES_MULTI;  			} @@ -919,9 +913,9 @@ BOOL LLIMFloater::handleDragAndDrop(S32 x, S32 y, MASK mask,  BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop)  {  	BOOL rv = isInviteAllowed(); -	if(rv && item && item->getCreatorUUID().notNull()) +	if (rv && item && item->getCreatorUUID().notNull())  	{ -		if(drop) +		if (drop)  		{  			uuid_vec_t ids;  			ids.push_back(item->getCreatorUUID()); @@ -939,26 +933,26 @@ BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop)  BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop)  {  	BOOL rv = isInviteAllowed(); -	if(rv && category) +	if (rv && category)  	{  		LLInventoryModel::cat_array_t cats;  		LLInventoryModel::item_array_t items;  		LLUniqueBuddyCollector buddies;  		gInventory.collectDescendentsIf(category->getUUID(), -										cats, -										items, -										LLInventoryModel::EXCLUDE_TRASH, -										buddies); +				cats, +				items, +				LLInventoryModel::EXCLUDE_TRASH, +				buddies);  		S32 count = items.count(); -		if(count == 0) +		if (count == 0)  		{  			rv = FALSE;  		} -		else if(drop) +		else if (drop)  		{  			uuid_vec_t ids;  			ids.reserve(count); -			for(S32 i = 0; i < count; ++i) +			for (S32 i = 0; i < count; ++i)  			{  				ids.push_back(items.get(i)->getCreatorUUID());  			} @@ -970,12 +964,11 @@ BOOL LLIMFloater::dropCategory(LLInventoryCategory* category, BOOL drop)  BOOL LLIMFloater::isInviteAllowed() const  { - -	return ( (IM_SESSION_CONFERENCE_START == mDialog) -			 || (IM_SESSION_INVITE == mDialog) ); +	return ((IM_SESSION_CONFERENCE_START == mDialog) +			|| (IM_SESSION_INVITE == mDialog));  } -class LLSessionInviteResponder : public LLHTTPClient::Responder +class LLSessionInviteResponder: public LLHTTPClient::Responder  {  public:  	LLSessionInviteResponder(const LLUUID& session_id) @@ -996,61 +989,60 @@ private:  BOOL LLIMFloater::inviteToSession(const uuid_vec_t& ids)  {  	LLViewerRegion* region = gAgent.getRegion(); -	if (!region) +	bool is_region_exist = !!region; + +	if (is_region_exist)  	{ -		return FALSE; -	} +		S32 count = ids.size(); -	S32 count = ids.size(); +		if (isInviteAllowed() && (count > 0)) +		{ +			llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; -	if( isInviteAllowed() && (count > 0) ) -	{ -		llinfos << "LLIMFloater::inviteToSession() - inviting participants" << llendl; +			std::string url = region->getCapability("ChatSessionRequest"); -		std::string url = region->getCapability("ChatSessionRequest"); +			LLSD data; -		LLSD data; +			data["params"] = LLSD::emptyArray(); +			for (int i = 0; i < count; i++) +			{ +				data["params"].append(ids[i]); +			} -		data["params"] = LLSD::emptyArray(); -		for (int i = 0; i < count; i++) +			data["method"] = "invite"; +			data["session-id"] = mSessionID; +			LLHTTPClient::post( +					url, +					data, +					new LLSessionInviteResponder(mSessionID)); +		} +		else  		{ -			data["params"].append(ids[i]); +			llinfos << "LLIMFloater::inviteToSession -" +					<< " no need to invite agents for " +					<< mDialog << llendl; +			// successful add, because everyone that needed to get added +			// was added.  		} - -		data["method"] = "invite"; -		data["session-id"] = mSessionID; -		LLHTTPClient::post( -			url, -			data, -			new LLSessionInviteResponder( -					mSessionID)); -	} -	else -	{ -		llinfos << "LLIMFloater::inviteToSession -" -				<< " no need to invite agents for " -				<< mDialog << llendl; -		// successful add, because everyone that needed to get added -		// was added.  	} -	return TRUE; +	return is_region_exist;  }  void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info)  {  	// We may have lost a "stop-typing" packet, don't add it twice -	if ( im_info && !mOtherTyping ) +	if (im_info && !mOtherTyping)  	{  		mOtherTyping = true;  		// Save and set new title  		mSavedTitle = getTitle(); -		setTitle (mTypingStart); +		setTitle(mTypingStart);  		// Update speaker  		LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); -		if ( speaker_mgr ) +		if (speaker_mgr)  		{  			speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE);  		} @@ -1059,23 +1051,22 @@ void LLIMFloater::addTypingIndicator(const LLIMInfo* im_info)  void LLIMFloater::removeTypingIndicator(const LLIMInfo* im_info)  { -	if ( mOtherTyping ) +	if (mOtherTyping)  	{  		mOtherTyping = false;  		// Revert the title to saved one  		setTitle(mSavedTitle); -		if ( im_info ) +		if (im_info)  		{  			// Update speaker  			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); -			if ( speaker_mgr ) +			if (speaker_mgr)  			{  				speaker_mgr->setSpeakerTyping(im_info->mFromID, FALSE);  			}  		} -  	}  } @@ -1092,7 +1083,8 @@ void LLIMFloater::closeHiddenIMToasts()  		}  	}; -	LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getNotificationScreenChannel(); +	LLNotificationsUI::LLScreenChannel* channel = +			LLNotificationsUI::LLChannelManager::getNotificationScreenChannel();  	if (channel != NULL)  	{  		channel->closeHiddenToasts(IMToastMatcher()); @@ -1115,14 +1107,6 @@ void LLIMFloater::confirmLeaveCallCallback(const LLSD& notification, const LLSD&  }  // static -bool LLIMFloater::isChatMultiTab() -{ -	// Restart is required in order to change chat window type. -	static bool is_single_window = gSavedSettings.getS32("ChatWindow") == 1; -	return is_single_window; -} - -// static  void LLIMFloater::initIMFloater()  {  	// This is called on viewer start up @@ -1134,41 +1118,51 @@ void LLIMFloater::initIMFloater()  void LLIMFloater::sRemoveTypingIndicator(const LLSD& data)  {  	LLUUID session_id = data["session_id"]; -	if (session_id.isNull()) return; +	if (session_id.isNull()) +		return;  	LLUUID from_id = data["from_id"]; -	if (gAgentID == from_id || LLUUID::null == from_id) return; +	if (gAgentID == from_id || LLUUID::null == from_id) +		return;  	LLIMFloater* floater = LLIMFloater::findInstance(session_id); -	if (!floater) return; +	if (!floater) +		return; -	if (IM_NOTHING_SPECIAL != floater->mDialog) return; +	if (IM_NOTHING_SPECIAL != floater->mDialog) +		return;  	floater->removeTypingIndicator();  }  void LLIMFloater::onIMChicletCreated( const LLUUID& session_id )  { +	LLIMFloater::addToHost(session_id); +} -	if (isChatMultiTab()) +void LLIMFloater::addToHost(const LLUUID& session_id) +{ +	if (LLIMConversation::isChatMultiTab())  	{ -		LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); -		if (!im_box) return; - -		if (LLIMFloater::findInstance(session_id)) return; - -		LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); +		LLIMFloaterContainer* im_box = LLIMFloaterContainer::findInstance(); +		if (!im_box) +	    { +			im_box = LLIMFloaterContainer::getInstance(); +	    } -		im_box->addFloater(new_tab, FALSE, LLTabContainer::END); +		if (im_box && !LLIMFloater::findInstance(session_id)) +		{ +			LLIMFloater* new_tab = LLIMFloater::getInstance(session_id); +			im_box->addFloater(new_tab, FALSE, LLTabContainer::END); +		}  	} -  }  void	LLIMFloater::onClickCloseBtn()  {  	LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( -				mSessionID); +			mSessionID);  	if (session == NULL)  	{ @@ -1181,7 +1175,8 @@ void	LLIMFloater::onClickCloseBtn()  	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionID); -	if (is_call_with_chat && voice_channel != NULL && voice_channel->isActive()) +	if (is_call_with_chat && voice_channel != NULL +			&& voice_channel->isActive())  	{  		LLSD payload;  		payload["session_id"] = mSessionID; diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index f7cd35b5eb..24f28c8aee 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -27,14 +27,17 @@  #ifndef LL_IMFLOATER_H  #define LL_IMFLOATER_H +#include "llimview.h" +#include "llimconversation.h"  #include "llinstantmessage.h"  #include "lllogchat.h"  #include "lltooldraganddrop.h" -#include "lltransientdockablefloater.h" +#include "llvoicechannel.h" +#include "llvoiceclient.h"  class LLAvatarName; +class LLButton;  class LLLineEditor; -class LLPanelChatControlPanel;  class LLChatHistory;  class LLInventoryItem;  class LLInventoryCategory; @@ -43,25 +46,33 @@ class LLInventoryCategory;   * Individual IM window that appears at the bottom of the screen,   * optionally "docked" to the bottom tray.   */ -class LLIMFloater : public LLTransientDockableFloater +class LLIMFloater +    : public LLVoiceClientStatusObserver +    , public LLIMConversation  {  	LOG_CLASS(LLIMFloater);  public:  	LLIMFloater(const LLUUID& session_id);  	virtual ~LLIMFloater(); -	 +  	// LLView overrides  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setVisible(BOOL visible);  	/*virtual*/ BOOL getVisible();  	// Check typing timeout timer. -	/*virtual*/ void draw(); +	/*virtual*/ BOOL tick(); + +	static LLIMFloater* findInstance(const LLUUID& session_id); +	static LLIMFloater* getInstance(const LLUUID& session_id); +	static void addToHost(const LLUUID& session_id); + +	static void* createPanelGroupControl(void* userdata); +	static void* createPanelAdHocControl(void* userdata);  	// LLFloater overrides  	/*virtual*/ void onClose(bool app_quitting);  	/*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); -  	// Make IM conversion visible and update the message history  	static LLIMFloater* show(const LLUUID& session_id); @@ -69,16 +80,12 @@ public:  	// Returns true iff panel became visible  	static bool toggle(const LLUUID& session_id); -	static LLIMFloater* findInstance(const LLUUID& session_id); - -	static LLIMFloater* getInstance(const LLUUID& session_id); -  	void sessionInitReplyReceived(const LLUUID& im_session_id);  	// get new messages from LLIMModel  	void updateMessages();  	void reloadMessages(); -	static void onSendMsg( LLUICtrl*, void*); +	static void onSendMsg(LLUICtrl*, void*);  	void sendMsg();  	// callback for LLIMModel on new messages @@ -89,36 +96,35 @@ public:  	void setPositioned(bool b) { mPositioned = b; };  	void onVisibilityChange(const LLSD& new_visibility); + +	// Implements LLVoiceClientStatusObserver::onChange() to enable the call +	// button when voice is available +	void onChange(EStatusType status, const std::string &channelURI, +			bool proximal); + +	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } +	virtual void onVoiceChannelStateChanged( +			const LLVoiceChannel::EState& old_state, +			const LLVoiceChannel::EState& new_state); +  	void processIMTyping(const LLIMInfo* im_info, BOOL typing);  	void processAgentListUpdates(const LLSD& body);  	void processSessionUpdate(const LLSD& session_update); -	void updateChatHistoryStyle(); -	static void processChatHistoryStyleUpdate(const LLSD& newvalue); -  	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, -							   BOOL drop, EDragAndDropType cargo_type, -							   void *cargo_data, EAcceptance *accept, -							   std::string& tooltip_msg); +			BOOL drop, EDragAndDropType cargo_type, +			void *cargo_data, EAcceptance *accept, +			std::string& tooltip_msg); -	/** -	 * Returns true if chat is displayed in multi tabbed floater -	 *         false if chat is displayed in multiple windows -	 */ -	static bool isChatMultiTab();  	static void initIMFloater();  	//used as a callback on receiving new IM message  	static void sRemoveTypingIndicator(const LLSD& data); -  	static void onIMChicletCreated(const LLUUID& session_id); -	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; } -  protected: -	/* virtual */ -	void	onClickCloseBtn(); +	/* virtual */ void onClickCloseBtn();  private:  	// process focus events to set a currently active session @@ -127,24 +133,26 @@ private:  	// Update the window title, input field help text, etc.  	void updateSessionName(const std::string& ui_title, const std::string& ui_label); -	 +  	// For display name lookups for IM window titles  	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); -	 +  	BOOL dropCallingCard(LLInventoryItem* item, BOOL drop);  	BOOL dropCategory(LLInventoryCategory* category, BOOL drop);  	BOOL isInviteAllowed() const;  	BOOL inviteToSession(const uuid_vec_t& agent_ids); -	 -	static void		onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ); -	static void		onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); -	static void		onInputEditorKeystroke(LLLineEditor* caller, void* userdata); -	void			setTyping(bool typing); -	void			onSlide(); -	static void*	createPanelIMControl(void* userdata); -	static void*	createPanelGroupControl(void* userdata); -	static void* 	createPanelAdHocControl(void* userdata); +	void appendMessage(const LLChat& chat, const LLSD &args = 0); +	static void onInputEditorFocusReceived( LLFocusableElement* caller,void* userdata ); +	static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); +	static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); +	void setTyping(bool typing); +	void onCallButtonClicked(); + +	// set the enable/disable state for the Call button +	virtual void enableDisableCallBtn(); + +	void boundVoiceChannel();  	// Add the "User is typing..." indicator.  	void addTypingIndicator(const LLIMInfo* im_info); @@ -156,13 +164,14 @@ private:  	static void confirmLeaveCallCallback(const LLSD& notification, const LLSD& response); -	LLPanelChatControlPanel* mControlPanel; -	LLUUID mSessionID; + +	LLIMModel::LLIMSession* mSession;  	S32 mLastMessageIndex; +	LLChatHistory* mChatHistory; +  	EInstantMessage mDialog;  	LLUUID mOtherParticipantUUID; -	LLChatHistory* mChatHistory;  	LLLineEditor* mInputEditor;  	bool mPositioned; @@ -176,7 +185,9 @@ private:  	bool mSessionInitialized;  	LLSD mQueuedMsgsForInit; -}; +	// connection to voice channel state change signal +	boost::signals2::connection mVoiceChannelStateChangeConnection; +};  #endif  // LL_IMFLOATER_H diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index c8e48b0d42..3b6240de44 100644 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -28,18 +28,24 @@  #include "llviewerprecompiledheaders.h"  #include "llimfloatercontainer.h" +  #include "llfloaterreg.h" -#include "llimview.h" +#include "lllayoutstack.h" +#include "llnearbychat.h" + +#include "llagent.h"  #include "llavatariconctrl.h"  #include "llgroupiconctrl.h" -#include "llagent.h" +#include "llimview.h"  #include "lltransientfloatermgr.h" +#include "llviewercontrol.h"  //  // LLIMFloaterContainer  //  LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)  :	LLMultiFloater(seed) +	,mExpandCollapseBtn(NULL)  {  	mAutoResize = FALSE;  	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this); @@ -49,6 +55,9 @@ LLIMFloaterContainer::~LLIMFloaterContainer()  {  	mNewMessageConnection.disconnect();  	LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this); + +	gSavedPerAccountSettings.setBOOL("ConversationsListPaneCollapsed", mConversationsPane->isCollapsed()); +	gSavedPerAccountSettings.setBOOL("ConversationsMessagePaneCollapsed", mMessagesPane->isCollapsed());  }  BOOL LLIMFloaterContainer::postBuild() @@ -56,6 +65,19 @@ BOOL LLIMFloaterContainer::postBuild()  	mNewMessageConnection = LLIMModel::instance().mNewMsgSignal.connect(boost::bind(&LLIMFloaterContainer::onNewMessageReceived, this, _1));  	// Do not call base postBuild to not connect to mCloseSignal to not close all floaters via Close button  	// mTabContainer will be initialized in LLMultiFloater::addChild() +	 +	setTabContainer(getChild<LLTabContainer>("im_box_tab_container")); + +	mConversationsStack = getChild<LLLayoutStack>("conversations_stack"); +	mConversationsPane = getChild<LLLayoutPanel>("conversations_layout_panel"); +	mMessagesPane = getChild<LLLayoutPanel>("messages_layout_panel"); + +	mExpandCollapseBtn = getChild<LLButton>("expand_collapse_btn"); +	mExpandCollapseBtn->setClickedCallback(boost::bind(&LLIMFloaterContainer::onExpandCollapseButtonClicked, this)); + +	collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); +	collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed")); +  	return TRUE;  } @@ -74,6 +96,7 @@ void LLIMFloaterContainer::onOpen(const LLSD& key)  */  } +// virtual  void LLIMFloaterContainer::addFloater(LLFloater* floaterp,   									BOOL select_added_floater,   									LLTabContainer::eInsertionPoint insertion_point) @@ -89,6 +112,12 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,  	LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); +	LLView* floater_contents = floaterp->getChild<LLView>("contents_view"); + +	// we don't show the header when the floater is hosted, +	// so reshape floater contents to occupy the header space +	floater_contents->setShape(floaterp->getRect()); +  	LLUUID session_id = floaterp->getKey();  	LLIconCtrl* icon = 0; @@ -116,11 +145,56 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,  	mTabContainer->setTabImage(floaterp, icon);  } +// virtual +void LLIMFloaterContainer::removeFloater(LLFloater* floaterp) +{ +	LLMultiFloater::removeFloater(floaterp); + +	LLRect contents_rect = floaterp->getRect(); + +	// reduce the floater contents height by header height +	contents_rect.mTop -= floaterp->getHeaderHeight(); + +	LLView* floater_contents = floaterp->getChild<LLView>("contents_view"); +	floater_contents->setShape(contents_rect); +} +  void LLIMFloaterContainer::onCloseFloater(LLUUID& id)  {  	mSessions.erase(id);  } +// virtual +void LLIMFloaterContainer::computeResizeLimits(S32& new_min_width, S32& new_min_height) +{ +	bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); +	bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); + +	S32 conversations_pane_min_dim = mConversationsPane->getMinDim(); + +	if (is_right_pane_expanded) +	{ +		S32 conversations_pane_width = +				(is_left_pane_expanded ? gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") : conversations_pane_min_dim); + +		// possibly increase minimum size constraint due to children's minimums. +		for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) +		{ +			LLFloater* floaterp = dynamic_cast<LLFloater*>(mTabContainer->getPanelByIndex(tab_idx)); +			if (floaterp) +			{ +				new_min_width = llmax(new_min_width, +						floaterp->getMinWidth() + conversations_pane_width + LLPANEL_BORDER_WIDTH * 2); +				new_min_height = llmax(new_min_height, floaterp->getMinHeight()); +			} +		} +	} +	else +	{ +		new_min_width = conversations_pane_min_dim; +	} +} +  void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data)  {  	LLUUID session_id = data["session_id"].asUUID(); @@ -135,6 +209,21 @@ void LLIMFloaterContainer::onNewMessageReceived(const LLSD& data)  	}  } +void LLIMFloaterContainer::onExpandCollapseButtonClicked() +{ +	if (mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed() +			&& gSavedPerAccountSettings.getBOOL("ConversationsExpandMessagePaneFirst")) +	{ +		// Expand the messages pane from ultra minimized state +		// if it was collapsed last in order. +		collapseMessagesPane(false); +	} +	else +	{ +		collapseConversationsPane(!mConversationsPane->isCollapsed()); +	} +} +  LLIMFloaterContainer* LLIMFloaterContainer::findInstance()  {  	return LLFloaterReg::findTypedInstance<LLIMFloaterContainer>("im_container"); @@ -161,4 +250,67 @@ void LLIMFloaterContainer::setMinimized(BOOL b)  	}  } +void LLIMFloaterContainer::collapseMessagesPane(bool collapse) +{ +	if (mMessagesPane->isCollapsed() == collapse) +	{ +		return; +	} + +	if (collapse) +	{ +		// Save the messages pane width before collapsing it. +		gSavedPerAccountSettings.setS32("ConversationsMessagePaneWidth", mMessagesPane->getRect().getWidth()); + +		// Save the order in which the panels are closed to reverse user's last action. +		gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", mConversationsPane->isCollapsed()); +	} + +	// Show/hide the messages pane. +	mConversationsStack->collapsePanel(mMessagesPane, collapse); + +	updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsMessagePaneWidth")); +} + +void LLIMFloaterContainer::collapseConversationsPane(bool collapse) +{ +	if (mConversationsPane->isCollapsed() == collapse) +	{ +		return; +	} + +	LLView* button_panel = getChild<LLView>("conversations_pane_buttons_expanded"); +	button_panel->setVisible(!collapse); +	mExpandCollapseBtn->setImageOverlay(getString(collapse ? "expand_icon" : "collapse_icon")); + +	if (collapse) +	{ +		// Save the conversations pane width before collapsing it. +		gSavedPerAccountSettings.setS32("ConversationsListPaneWidth", mConversationsPane->getRect().getWidth()); + +		// Save the order in which the panels are closed to reverse user's last action. +		gSavedPerAccountSettings.setBOOL("ConversationsExpandMessagePaneFirst", !mMessagesPane->isCollapsed()); +	} + +	mConversationsStack->collapsePanel(mConversationsPane, collapse); + +	S32 collapsed_width = mConversationsPane->getMinDim(); +	updateState(collapse, gSavedPerAccountSettings.getS32("ConversationsListPaneWidth") - collapsed_width); +} + +void LLIMFloaterContainer::updateState(bool collapse, S32 delta_width) +{ +	LLRect floater_rect = getRect(); +	floater_rect.mRight += ((collapse ? -1 : 1) * delta_width); +	setShape(floater_rect); + +	updateResizeLimits(); + +	bool is_left_pane_expanded = !mConversationsPane->isCollapsed(); +	bool is_right_pane_expanded = !mMessagesPane->isCollapsed(); + +	setCanResize(is_left_pane_expanded || is_right_pane_expanded); +	setCanMinimize(is_left_pane_expanded || is_right_pane_expanded); +} +  // EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index 892ecef48d..92938ff405 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -35,6 +35,9 @@  #include "llavatarpropertiesprocessor.h"  #include "llgroupmgr.h" +class LLButton; +class LLLayoutPanel; +class LLLayoutStack;  class LLTabContainer;  class LLIMFloaterContainer : public LLMultiFloater @@ -50,6 +53,7 @@ public:  	/*virtual*/ void addFloater(LLFloater* floaterp,   								BOOL select_added_floater,   								LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); +	/*virtual*/ void removeFloater(LLFloater* floaterp);  	static LLFloater* getCurrentVoiceFloater(); @@ -59,12 +63,27 @@ public:  	virtual void setMinimized(BOOL b); +	void collapseMessagesPane(bool collapse); +  private:  	typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t;  	avatarID_panel_map_t mSessions;  	boost::signals2::connection mNewMessageConnection; +	/*virtual*/ void computeResizeLimits(S32& new_min_width, S32& new_min_height); +  	void onNewMessageReceived(const LLSD& data); + +	void onExpandCollapseButtonClicked(); + +	void collapseConversationsPane(bool collapse); + +	void updateState(bool collapse, S32 delta_width); + +	LLButton* mExpandCollapseBtn; +	LLLayoutPanel* mMessagesPane; +	LLLayoutPanel* mConversationsPane; +	LLLayoutStack* mConversationsStack;  };  #endif // LL_LLIMFLOATERCONTAINER_H diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index 07d73c8c66..047472a282 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -37,10 +37,9 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLIMHandler::LLIMHandler(e_notification_type type, const LLSD& id) +LLIMHandler::LLIMHandler() +:	LLSysHandler("IM Notifications", "notifytoast")  { -	mType = type; -  	// Getting a Channel for our notifications  	mChannel = LLChannelManager::getInstance()->createNotificationChannel()->getHandle();  } @@ -59,72 +58,49 @@ void LLIMHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLIMHandler::processNotification(const LLSD& notify) +bool LLIMHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{ -		LLSD substitutions = notification->getSubstitutions(); - -		// According to comments in LLIMMgr::addMessage(), if we get message -		// from ourselves, the sender id is set to null. This fixes EXT-875. -		LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); -		if (avatar_id.isNull()) -			avatar_id = gAgentID; - -		LLToastIMPanel::Params im_p; -		im_p.notification = notification; -		im_p.avatar_id = avatar_id; -		im_p.from = substitutions["FROM"].asString(); -		im_p.time = substitutions["TIME"].asString(); -		im_p.message = substitutions["MESSAGE"].asString(); -		im_p.session_id = substitutions["SESSION_ID"].asUUID(); - -		LLToastIMPanel* im_box = new LLToastIMPanel(im_p); - -		LLToast::Params p; -		p.notif_id = notification->getID(); -		p.session_id = im_p.session_id; -		p.notification = notification; -		p.panel = im_box; -		p.can_be_stored = false; -		p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); - -		// send a signal to the counter manager; -		mNewNotificationSignal(); -	} -	else if (notify["sigtype"].asString() == "delete") -	{ -		mChannel.get()->killToastByNotificationID(notification->getID()); -	} -	return false; -} +	LLSD substitutions = notification->getSubstitutions(); + +	// According to comments in LLIMMgr::addMessage(), if we get message +	// from ourselves, the sender id is set to null. This fixes EXT-875. +	LLUUID avatar_id = substitutions["FROM_ID"].asUUID(); +	if (avatar_id.isNull()) +		avatar_id = gAgentID; + +	LLToastIMPanel::Params im_p; +	im_p.notification = notification; +	im_p.avatar_id = avatar_id; +	im_p.from = substitutions["FROM"].asString(); +	im_p.time = substitutions["TIME"].asString(); +	im_p.message = substitutions["MESSAGE"].asString(); +	im_p.session_id = substitutions["SESSION_ID"].asUUID(); + +	LLToastIMPanel* im_box = new LLToastIMPanel(im_p); + +	LLToast::Params p; +	p.notif_id = notification->getID(); +	p.session_id = im_p.session_id; +	p.notification = notification; +	p.panel = im_box; +	p.can_be_stored = false; +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); -//-------------------------------------------------------------------------- -void LLIMHandler::onDeleteToast(LLToast* toast) -{ -	// send a signal to the counter manager -	mDelNotificationSignal(); +	return false;  } -//-------------------------------------------------------------------------- diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a7c4618fa4..46b1cb5f18 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -41,7 +41,7 @@  #include "lltextutil.h"  #include "lltrans.h"  #include "lluictrlfactory.h" - +#include "llimconversation.h"  #include "llagent.h"  #include "llagentui.h"  #include "llappviewer.h" @@ -716,6 +716,16 @@ bool LLIMModel::clearSession(const LLUUID& session_id)  	return true;  } +void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index, const bool sendNoUnreadMsgs) +{ +	getMessagesSilently(session_id, messages, start_index); + +	if (sendNoUnreadMsgs) +	{ +		sendNoUnreadMessages(session_id); +	} +} +  void LLIMModel::getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)  {  	LLIMSession* session = findIMSession(session_id); @@ -757,13 +767,6 @@ void LLIMModel::sendNoUnreadMessages(const LLUUID& session_id)  	mNoUnreadMsgsSignal(arg);  } -void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index) -{ -	getMessagesSilently(session_id, messages, start_index); - -	sendNoUnreadMessages(session_id); -} -  bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text) {  	LLIMSession* session = findIMSession(session_id); @@ -904,7 +907,7 @@ const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const  	LLIMSession* session = findIMSession(session_id);  	if (!session)  	{ -		llwarns << "session " << session_id << "does not exist " << llendl; +		llwarns << "session " << session_id << " does not exist " << llendl;  		return LLUUID::null;  	} @@ -2480,8 +2483,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess  		LLChat chat(message);  		chat.mSourceType = CHAT_SOURCE_SYSTEM; -		LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); -		LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); +		LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();  		if(nearby_chat)  		{ @@ -2497,6 +2499,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess  			gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString());  		}  		// log message to file +  		else  		{  			std::string session_name; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 7c2cd03d97..9d19af4b62 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -192,12 +192,6 @@ public:  	bool clearSession(const LLUUID& session_id);  	/** -	 * Populate supplied std::list with messages starting from index specified by start_index without -	 * emitting no unread messages signal. -	 */ -	void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); - -	/**  	 * Sends no unread messages signal.  	 */  	void sendNoUnreadMessages(const LLUUID& session_id); @@ -205,7 +199,7 @@ public:  	/**  	 * Populate supplied std::list with messages starting from index specified by start_index  	 */ -	void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); +	void getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0, const bool sendNoUnreadMsgs = true);  	/**  	 * Add a message to an IM Model - the message is saved in a message store associated with a session specified by session_id @@ -288,6 +282,12 @@ public:  private:  	/** +	 * Populate supplied std::list with messages starting from index specified by start_index without +	 * emitting no unread messages signal. +	 */ +	void getMessagesSilently(const LLUUID& session_id, std::list<LLSD>& messages, int start_index = 0); + +	/**  	 * Add message to a list of message associated with session specified by session_id  	 */  	bool addToHistory(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text); diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 17d0b0ffbb..8a15cd279f 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -28,38 +28,21 @@  #include "llinspectavatar.h"  // viewer files -#include "llagent.h" -#include "llagentdata.h" -#include "llavataractions.h" +#include "llavatariconctrl.h"  #include "llavatarnamecache.h"  #include "llavatarpropertiesprocessor.h" -#include "llcallingcard.h"  #include "lldateutil.h" -#include "llfloaterreporter.h" -#include "llfloaterworldmap.h" -#include "llimview.h"  #include "llinspect.h" -#include "llmutelist.h" -#include "llpanelblockedlist.h" +#include "llslurl.h"  #include "llstartup.h" -#include "llspeakers.h" -#include "llviewermenu.h" -#include "llvoiceclient.h" -#include "llviewerobjectlist.h"  #include "lltransientfloatermgr.h" -#include "llnotificationsutil.h"  // Linden libraries  #include "llfloater.h"  #include "llfloaterreg.h" -#include "llmenubutton.h"  #include "lltextbox.h" -#include "lltoggleablemenu.h"  #include "lltooltip.h"	// positionViewNearMouse()  #include "lltrans.h" -#include "lluictrl.h" - -#include "llavatariconctrl.h"  class LLFetchAvatarData; @@ -81,22 +64,13 @@ public:  	LLInspectAvatar(const LLSD& avatar_id);  	virtual ~LLInspectAvatar(); -	/*virtual*/ BOOL postBuild(void); -	  	// Because floater is single instance, need to re-parse data on each spawn  	// (for example, inspector about same avatar but in different position)  	/*virtual*/ void onOpen(const LLSD& avatar_id); -	// When closing they should close their gear menu  -	/*virtual*/ void onClose(bool app_quitting); -	  	// Update view based on information from avatar properties processor  	void processAvatarData(LLAvatarData* data); -	// override the inspector mouse leave so timer is only paused if  -	// gear menu is not open -	/* virtual */ void onMouseLeave(S32 x, S32 y, MASK mask); -	  	virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; }  private: @@ -104,47 +78,6 @@ private:  	// Used on construction and if avatar id changes.  	void requestUpdate(); -	// Set the volume slider to this user's current client-side volume setting, -	// hiding/disabling if the user is not nearby. -	void updateVolumeSlider(); - -	// Shows/hides moderator panel depending on voice state  -	void updateModeratorPanel(); - -	// Moderator ability to enable/disable voice chat for avatar -	void toggleSelectedVoice(bool enabled); -	 -	// Button callbacks -	void onClickAddFriend(); -	void onClickViewProfile(); -	void onClickIM(); -	void onClickCall(); -	void onClickTeleport(); -	void onClickInviteToGroup(); -	void onClickPay(); -	void onClickShare(); -	void onToggleMute(); -	void onClickReport(); -	void onClickFreeze(); -	void onClickEject(); -	void onClickKick(); -	void onClickCSR(); -	void onClickZoomIn();   -	void onClickFindOnMap(); -	bool onVisibleFindOnMap(); -	bool onVisibleEject(); -	bool onVisibleFreeze(); -	bool onVisibleZoomIn(); -	void onClickMuteVolume(); -	void onVolumeChange(const LLSD& data); -	bool enableMute(); -	bool enableUnmute(); -	bool enableTeleportOffer(); -	bool godModeEnabled(); - -	// Is used to determine if "Add friend" option should be enabled in gear menu -	bool isNotFriend(); -	  	void onAvatarNameCache(const LLUUID& agent_id,  						   const LLAvatarName& av_name); @@ -209,39 +142,8 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd)  	mAvatarName(),  	mPropertiesRequest(NULL)  { -	mCommitCallbackRegistrar.add("InspectAvatar.ViewProfile",	boost::bind(&LLInspectAvatar::onClickViewProfile, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.AddFriend",	boost::bind(&LLInspectAvatar::onClickAddFriend, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.IM", -		boost::bind(&LLInspectAvatar::onClickIM, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Call",		boost::bind(&LLInspectAvatar::onClickCall, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Teleport",	boost::bind(&LLInspectAvatar::onClickTeleport, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.InviteToGroup",	boost::bind(&LLInspectAvatar::onClickInviteToGroup, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Pay",	boost::bind(&LLInspectAvatar::onClickPay, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Share",	boost::bind(&LLInspectAvatar::onClickShare, this)); -	mCommitCallbackRegistrar.add("InspectAvatar.ToggleMute",	boost::bind(&LLInspectAvatar::onToggleMute, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Freeze", boost::bind(&LLInspectAvatar::onClickFreeze, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Eject", boost::bind(&LLInspectAvatar::onClickEject, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Kick", boost::bind(&LLInspectAvatar::onClickKick, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.CSR", boost::bind(&LLInspectAvatar::onClickCSR, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.Report",	boost::bind(&LLInspectAvatar::onClickReport, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.FindOnMap",	boost::bind(&LLInspectAvatar::onClickFindOnMap, this));	 -	mCommitCallbackRegistrar.add("InspectAvatar.ZoomIn", boost::bind(&LLInspectAvatar::onClickZoomIn, this)); -	mCommitCallbackRegistrar.add("InspectAvatar.DisableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, false)); -	mCommitCallbackRegistrar.add("InspectAvatar.EnableVoice", boost::bind(&LLInspectAvatar::toggleSelectedVoice, this, true)); - -	mEnableCallbackRegistrar.add("InspectAvatar.EnableGod",	boost::bind(&LLInspectAvatar::godModeEnabled, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleFindOnMap",	boost::bind(&LLInspectAvatar::onVisibleFindOnMap, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleEject",	boost::bind(&LLInspectAvatar::onVisibleEject, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleFreeze",	boost::bind(&LLInspectAvatar::onVisibleFreeze, this));	 -	mEnableCallbackRegistrar.add("InspectAvatar.VisibleZoomIn", boost::bind(&LLInspectAvatar::onVisibleZoomIn, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.Gear.Enable", boost::bind(&LLInspectAvatar::isNotFriend, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableCall", boost::bind(&LLAvatarActions::canCall)); -	mEnableCallbackRegistrar.add("InspectAvatar.Gear.EnableTeleportOffer", boost::bind(&LLInspectAvatar::enableTeleportOffer, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.EnableMute", boost::bind(&LLInspectAvatar::enableMute, this)); -	mEnableCallbackRegistrar.add("InspectAvatar.EnableUnmute", boost::bind(&LLInspectAvatar::enableUnmute, this)); -  	// can't make the properties request until the widgets are constructed -	// as it might return immediately, so do it in postBuild. +	// as it might return immediately, so do it in onOpen.  	LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::GLOBAL, this);  	LLTransientFloater::init(this); @@ -257,25 +159,6 @@ LLInspectAvatar::~LLInspectAvatar()  	LLTransientFloaterMgr::getInstance()->removeControlView(this);  } -/*virtual*/ -BOOL LLInspectAvatar::postBuild(void) -{ -	getChild<LLUICtrl>("add_friend_btn")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onClickAddFriend, this) ); - -	getChild<LLUICtrl>("view_profile_btn")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onClickViewProfile, this) ); - -	getChild<LLUICtrl>("mute_btn")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onClickMuteVolume, this) ); - -	getChild<LLUICtrl>("volume_slider")->setCommitCallback( -		boost::bind(&LLInspectAvatar::onVolumeChange, this, _2)); - -	return TRUE; -} - -  // Multiple calls to showInstance("inspect_avatar", foo) will provide different  // LLSD for foo, which we will catch here.  //virtual @@ -287,11 +170,6 @@ void LLInspectAvatar::onOpen(const LLSD& data)  	// Extract appropriate avatar id  	mAvatarID = data["avatar_id"]; -	BOOL self = mAvatarID == gAgent.getID(); -	 -	getChild<LLUICtrl>("gear_self_btn")->setVisible(self); -	getChild<LLUICtrl>("gear_btn")->setVisible(!self); -  	// Position the inspector relative to the mouse cursor  	// Similar to how tooltips are positioned  	// See LLToolTipMgr::createToolTip @@ -304,20 +182,13 @@ void LLInspectAvatar::onOpen(const LLSD& data)  		LLUI::positionViewNearMouse(this);  	} +	// Generate link to avatar profile. +	getChild<LLUICtrl>("avatar_profile_link")->setTextArg("[LINK]", LLSLURL("agent", mAvatarID, "about").getSLURLString()); +  	// can't call from constructor as widgets are not built yet  	requestUpdate(); - -	updateVolumeSlider(); - -	updateModeratorPanel();  } -// virtual -void LLInspectAvatar::onClose(bool app_quitting) -{   -  getChild<LLMenuButton>("gear_btn")->hideMenu(); -}	 -  void LLInspectAvatar::requestUpdate()  {  	// Don't make network requests when spawning from the debug menu at the @@ -344,25 +215,6 @@ void LLInspectAvatar::requestUpdate()  	delete mPropertiesRequest;  	mPropertiesRequest = new LLFetchAvatarData(mAvatarID, this); -	// You can't re-add someone as a friend if they are already your friend -	bool is_friend = LLAvatarTracker::instance().getBuddyInfo(mAvatarID) != NULL; -	bool is_self = (mAvatarID == gAgentID); -	if (is_self) -	{ -		getChild<LLUICtrl>("add_friend_btn")->setVisible(false); -		getChild<LLUICtrl>("im_btn")->setVisible(false); -	} -	else if (is_friend) -	{ -		getChild<LLUICtrl>("add_friend_btn")->setVisible(false); -		getChild<LLUICtrl>("im_btn")->setVisible(true); -	} -	else -	{ -		getChild<LLUICtrl>("add_friend_btn")->setVisible(true); -		getChild<LLUICtrl>("im_btn")->setVisible(false); -	} -  	// Use an avatar_icon even though the image id will come down with the  	// avatar properties because the avatar_icon code maintains a cache of icons  	// and this may result in the image being visible sooner. @@ -405,214 +257,6 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data)  	mPropertiesRequest = NULL;  } -// For the avatar inspector, we only want to unpause the fade timer  -// if neither the gear menu or self gear menu are open -void LLInspectAvatar::onMouseLeave(S32 x, S32 y, MASK mask) -{ -	LLToggleableMenu* gear_menu = getChild<LLMenuButton>("gear_btn")->getMenu(); -	LLToggleableMenu* gear_menu_self = getChild<LLMenuButton>("gear_self_btn")->getMenu(); -	if ( gear_menu && gear_menu->getVisible() && -		 gear_menu_self && gear_menu_self->getVisible() ) -	{ -		return; -	} - -	if(childHasVisiblePopupMenu()) -	{ -		return; -	} - -	mOpenTimer.unpause(); -} - -void LLInspectAvatar::updateModeratorPanel() -{ -	bool enable_moderator_panel = false; - -    if (LLVoiceChannel::getCurrentVoiceChannel() && -		mAvatarID != gAgent.getID()) -    { -		LLUUID session_id = LLVoiceChannel::getCurrentVoiceChannel()->getSessionID(); - -		if (session_id != LLUUID::null) -		{ -			LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); - -			if (speaker_mgr) -			{ -				LLPointer<LLSpeaker> self_speakerp = speaker_mgr->findSpeaker(gAgent.getID()); -				LLPointer<LLSpeaker> selected_speakerp = speaker_mgr->findSpeaker(mAvatarID); -				 -				if(speaker_mgr->isVoiceActive() && selected_speakerp &&  -					selected_speakerp->isInVoiceChannel() && -					((self_speakerp && self_speakerp->mIsModerator) || gAgent.isGodlike())) -				{ -					getChild<LLUICtrl>("enable_voice")->setVisible(selected_speakerp->mModeratorMutedVoice); -					getChild<LLUICtrl>("disable_voice")->setVisible(!selected_speakerp->mModeratorMutedVoice); - -					enable_moderator_panel = true; -				} -			} -		} -	} - -	if (enable_moderator_panel) -	{ -		if (!getChild<LLUICtrl>("moderator_panel")->getVisible()) -		{ -			getChild<LLUICtrl>("moderator_panel")->setVisible(true); -			// stretch the floater so it can accommodate the moderator panel -			reshape(getRect().getWidth(), getRect().getHeight() + getChild<LLUICtrl>("moderator_panel")->getRect().getHeight()); -		} -	} -	else if (getChild<LLUICtrl>("moderator_panel")->getVisible()) -	{ -		getChild<LLUICtrl>("moderator_panel")->setVisible(false); -		// shrink the inspector floater back to original size -		reshape(getRect().getWidth(), getRect().getHeight() - getChild<LLUICtrl>("moderator_panel")->getRect().getHeight());					 -	} -} - -void LLInspectAvatar::toggleSelectedVoice(bool enabled) -{ -	LLUUID session_id = LLVoiceChannel::getCurrentVoiceChannel()->getSessionID(); -	LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); - -	if (speaker_mgr) -	{ -		if (!gAgent.getRegion()) -			return; - -		std::string url = gAgent.getRegion()->getCapability("ChatSessionRequest"); -		LLSD data; -		data["method"] = "mute update"; -		data["session-id"] = session_id; -		data["params"] = LLSD::emptyMap(); -		data["params"]["agent_id"] = mAvatarID; -		data["params"]["mute_info"] = LLSD::emptyMap(); -		// ctrl value represents ability to type, so invert -		data["params"]["mute_info"]["voice"] = !enabled; - -		class MuteVoiceResponder : public LLHTTPClient::Responder -		{ -		public: -			MuteVoiceResponder(const LLUUID& session_id) -			{ -				mSessionID = session_id; -			} - -			virtual void error(U32 status, const std::string& reason) -			{ -				llwarns << status << ": " << reason << llendl; - -				if ( gIMMgr ) -				{ -					//403 == you're not a mod -					//should be disabled if you're not a moderator -					if ( 403 == status ) -					{ -						gIMMgr->showSessionEventError( -							"mute", -							"not_a_moderator", -							mSessionID); -					} -					else -					{ -						gIMMgr->showSessionEventError( -							"mute", -							"generic", -							mSessionID); -					} -				} -			} - -		private: -			LLUUID mSessionID; -		}; - -		LLHTTPClient::post( -			url, -			data, -			new MuteVoiceResponder(speaker_mgr->getSessionID())); -	} - -	closeFloater(); - -} - -void LLInspectAvatar::updateVolumeSlider() -{ -	bool voice_enabled = LLVoiceClient::getInstance()->getVoiceEnabled(mAvatarID); - -	// Do not display volume slider and mute button if it  -	// is ourself or we are not in a voice channel together -	if (!voice_enabled || (mAvatarID == gAgent.getID())) -	{ -		getChild<LLUICtrl>("mute_btn")->setVisible(false); -		getChild<LLUICtrl>("volume_slider")->setVisible(false); -	} - -	else  -	{ -		getChild<LLUICtrl>("mute_btn")->setVisible(true); -		getChild<LLUICtrl>("volume_slider")->setVisible(true); - -		// By convention, we only display and toggle voice mutes, not all mutes -		bool is_muted = LLMuteList::getInstance()-> -							isMuted(mAvatarID, LLMute::flagVoiceChat); - -		LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); - -		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); - -		mute_btn->setEnabled( !is_linden); -		mute_btn->setValue( is_muted ); - -		LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); -		volume_slider->setEnabled( !is_muted ); - -		F32 volume; -		 -		if (is_muted) -		{ -			// it's clearer to display their volume as zero -			volume = 0.f; -		} -		else -		{ -			// actual volume -			volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); -		} -		volume_slider->setValue( (F64)volume ); -	} - -} - -void LLInspectAvatar::onClickMuteVolume() -{ -	// By convention, we only display and toggle voice mutes, not all mutes -	LLMuteList* mute_list = LLMuteList::getInstance(); -	bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat); - -	LLMute mute(mAvatarID, mAvatarName.getLegacyName(), LLMute::AGENT); -	if (!is_muted) -	{ -		mute_list->add(mute, LLMute::flagVoiceChat); -	} -	else -	{ -		mute_list->remove(mute, LLMute::flagVoiceChat); -	} - -	updateVolumeSlider(); -} - -void LLInspectAvatar::onVolumeChange(const LLSD& data) -{ -	F32 volume = (F32)data.asReal(); -	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); -} -  void LLInspectAvatar::onAvatarNameCache(  		const LLUUID& agent_id,  		const LLAvatarName& av_name) @@ -640,215 +284,6 @@ void LLInspectAvatar::onAvatarNameCache(  	}  } -void LLInspectAvatar::onClickAddFriend() -{ -	LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName.getLegacyName()); -	closeFloater(); -} - -void LLInspectAvatar::onClickViewProfile() -{ -	LLAvatarActions::showProfile(mAvatarID); -	closeFloater(); -} - -bool LLInspectAvatar::isNotFriend() -{ -	return !LLAvatarActions::isFriend(mAvatarID); -} - -bool LLInspectAvatar::onVisibleFindOnMap() -{ -	return gAgent.isGodlike() || is_agent_mappable(mAvatarID); -} - -bool LLInspectAvatar::onVisibleEject() -{ -	return enable_freeze_eject( LLSD(mAvatarID) ); -} - -bool LLInspectAvatar::onVisibleFreeze() -{ -	// either user is a god and can do long distance freeze -	// or check for target proximity and permissions -	return gAgent.isGodlike() || enable_freeze_eject(LLSD(mAvatarID)); -} - -bool LLInspectAvatar::onVisibleZoomIn() -{ -	return gObjectList.findObject(mAvatarID); -} - -void LLInspectAvatar::onClickIM() -{  -	LLAvatarActions::startIM(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickCall() -{  -	LLAvatarActions::startCall(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickTeleport() -{ -	LLAvatarActions::offerTeleport(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickInviteToGroup() -{ -	LLAvatarActions::inviteToGroup(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickPay() -{ -	LLAvatarActions::pay(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickShare() -{ -	LLAvatarActions::share(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onToggleMute() -{ -	LLMute mute(mAvatarID, mAvatarName.mDisplayName, LLMute::AGENT); - -	if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName)) -	{ -		LLMuteList::getInstance()->remove(mute); -	} -	else -	{ -		LLMuteList::getInstance()->add(mute); -	} - -	LLPanelBlockedList::showPanelAndSelect(mute.mID); -	closeFloater(); -} - -void LLInspectAvatar::onClickReport() -{ -	LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName.getCompleteName()); -	closeFloater(); -} - -bool godlike_freeze(const LLSD& notification, const LLSD& response) -{ -	LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - -	switch (option) -	{ -	case 0: -		LLAvatarActions::freeze(avatar_id); -		break; -	case 1: -		LLAvatarActions::unfreeze(avatar_id); -		break; -	default: -		break; -	} - -	return false; -} - -void LLInspectAvatar::onClickFreeze() -{ -	if (gAgent.isGodlike()) -	{ -		// use godlike freeze-at-a-distance, with confirmation -		LLNotificationsUtil::add("FreezeAvatar", -			LLSD(), -			LLSD().with("avatar_id", mAvatarID), -			godlike_freeze); -	} -	else -	{ -		// use default "local" version of freezing that requires avatar to be in range -		handle_avatar_freeze( LLSD(mAvatarID) ); -	} -	closeFloater(); -} - -void LLInspectAvatar::onClickEject() -{ -	handle_avatar_eject( LLSD(mAvatarID) ); -	closeFloater(); -} - -void LLInspectAvatar::onClickKick() -{ -	LLAvatarActions::kick(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickCSR() -{ -	std::string name; -	gCacheName->getFullName(mAvatarID, name); -	LLAvatarActions::csr(mAvatarID, name); -	closeFloater(); -} - -void LLInspectAvatar::onClickZoomIn()  -{ -	handle_zoom_to_object(mAvatarID); -	closeFloater(); -} - -void LLInspectAvatar::onClickFindOnMap() -{ -	gFloaterWorldMap->trackAvatar(mAvatarID, mAvatarName.mDisplayName); -	LLFloaterReg::showInstance("world_map"); -} - - -bool LLInspectAvatar::enableMute() -{ -		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); -		bool is_self = mAvatarID == gAgent.getID(); - -		if (!is_linden && !is_self && !LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName())) -		{ -			return true; -		} -		else -		{ -			return false; -		} -} - -bool LLInspectAvatar::enableUnmute() -{ -		bool is_linden = LLStringUtil::endsWith(mAvatarName.getLegacyName(), " Linden"); -		bool is_self = mAvatarID == gAgent.getID(); - -		if (!is_linden && !is_self && LLMuteList::getInstance()->isMuted(mAvatarID, mAvatarName.getLegacyName())) -		{ -			return true; -		} -		else -		{ -			return false; -		} -} - -bool LLInspectAvatar::enableTeleportOffer() -{ -	return LLAvatarActions::canOfferTeleport(mAvatarID); -} - -bool LLInspectAvatar::godModeEnabled() -{ -	return gAgent.isGodlike(); -} -  //////////////////////////////////////////////////////////////////////////////  // LLInspectAvatarUtil  ////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/lllistcontextmenu.h b/indra/newview/lllistcontextmenu.h index fabd68ee20..04d3314829 100644 --- a/indra/newview/lllistcontextmenu.h +++ b/indra/newview/lllistcontextmenu.h @@ -37,7 +37,7 @@ class LLContextMenu;  /**   * Context menu for single or multiple list items.   *  - * Derived classes must implement contextMenu(). + * Derived classes must implement createMenu().   *    * Typical usage:   * <code> diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index a7303ad035..8b54c6ce53 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -1,8 +1,8 @@  /**    * @file LLNearbyChat.cpp - * @brief Nearby chat history scrolling panel implementation + * @brief LLNearbyChat class implementation   * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc.   *  @@ -26,68 +26,66 @@  #include "llviewerprecompiledheaders.h" -#include "llnearbychat.h" -#include "llviewercontrol.h" -#include "llviewerwindow.h" -#include "llrootview.h" -//#include "llchatitemscontainerctrl.h" +#include "message.h" +  #include "lliconctrl.h" +#include "llappviewer.h" +#include "llfloaterreg.h" +#include "lltrans.h" +#include "llimfloatercontainer.h"  #include "llfloatersidepanelcontainer.h"  #include "llfocusmgr.h"  #include "lllogchat.h"  #include "llresizebar.h"  #include "llresizehandle.h" +#include "lldraghandle.h"  #include "llmenugl.h" -#include "llviewermenu.h"//for gMenuHolder - +#include "llviewermenu.h" // for gMenuHolder  #include "llnearbychathandler.h"  #include "llchannelmanager.h" - -#include "llagent.h" 			// gAgent  #include "llchathistory.h"  #include "llstylemap.h" -  #include "llavatarnamecache.h" - -#include "lldraghandle.h" - -#include "llnearbychatbar.h"  #include "llfloaterreg.h"  #include "lltrans.h" -static const S32 RESIZE_BAR_THICKNESS = 3; - - -static LLRegisterPanelClassWrapper<LLNearbyChat> t_panel_nearby_chat("panel_nearby_chat"); +#include "llfirstuse.h" +#include "llnearbychat.h" +#include "llagent.h" // gAgent +#include "llgesturemgr.h" +#include "llmultigesture.h" +#include "llkeyboard.h" +#include "llanimationstates.h" +#include "llviewerstats.h" +#include "llcommandhandler.h" +#include "llviewercontrol.h" +#include "llnavigationbar.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llrootview.h" +#include "llviewerchat.h" +#include "lltranslate.h" -LLNearbyChat::LLNearbyChat(const LLNearbyChat::Params& p)  -:	LLPanel(p), -	mChatHistory(NULL) -{ -} +S32 LLNearbyChat::sLastSpecialChatChannel = 0; -BOOL LLNearbyChat::postBuild() +// --- 2 functions in the global namespace :( --- +bool isWordsName(const std::string& name)  { -	//menu -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; - -	enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); -	registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); - -	 -	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(menu) -		mPopupMenuHandle = menu->getHandle(); - -	gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true); - -	mChatHistory = getChild<LLChatHistory>("chat_history"); +	// checking to see if it's display name plus username in parentheses +	S32 open_paren = name.find(" (", 0); +	S32 close_paren = name.find(')', 0); -	if(!LLPanel::postBuild()) -		return false; -	 -	return true; +	if (open_paren != std::string::npos && +		close_paren == name.length()-1) +	{ +		return true; +	} +	else +	{ +		//checking for a single space +		S32 pos = name.find(' ', 0); +		return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; +	}  }  std::string appendTime() @@ -106,53 +104,86 @@ std::string appendTime()  } -void	LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +const S32 EXPANDED_HEIGHT = 266; +const S32 COLLAPSED_HEIGHT = 60; +const S32 EXPANDED_MIN_HEIGHT = 150; + +// legacy callback glue +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); + +struct LLChatTypeTrigger { +	std::string name; +	EChatType type; +}; + +static LLChatTypeTrigger sChatTypeTriggers[] = { +	{ "/whisper"	, CHAT_TYPE_WHISPER}, +	{ "/shout"	, CHAT_TYPE_SHOUT} +}; + + +LLNearbyChat::LLNearbyChat(const LLSD& key) +:	LLIMConversation(key), +	mChatBox(NULL), +	mChatHistory(NULL), +	mOutputMonitor(NULL), +	mSpeakerMgr(NULL), +	mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT)  { -	LLChat& tmp_chat = const_cast<LLChat&>(chat); +	mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); +} -	if(tmp_chat.mTimeStr.empty()) -		tmp_chat.mTimeStr = appendTime(); +//virtual +BOOL LLNearbyChat::postBuild() +{ +	mChatBox = getChild<LLLineEditor>("chat_editor"); -	bool use_plain_text_chat_history = gSavedSettings.getBOOL("PlainTextChatHistory"); -	 -	if (!chat.mMuted) -	{ -		tmp_chat.mFromName = chat.mFromName; -		LLSD chat_args = args; -		chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history; -		mChatHistory->appendMessage(chat, chat_args); -	} +	mChatBox->setCommitCallback(boost::bind(&LLNearbyChat::onChatBoxCommit, this)); +	mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); +	mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); +	mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChat::onChatBoxFocusReceived, this)); +	mChatBox->setIgnoreArrowKeys( FALSE );  +	mChatBox->setCommitOnFocusLost( FALSE ); +	mChatBox->setRevertOnEsc( FALSE ); +	mChatBox->setIgnoreTab(TRUE); +	mChatBox->setPassDelete(TRUE); +	mChatBox->setReplaceNewlinesWithSpaces(FALSE); +	mChatBox->setEnableLineHistory(TRUE); +	mChatBox->setFont(LLViewerChat::getChatFont()); -	if(archive) -	{ -		mMessageArchive.push_back(chat); -		if(mMessageArchive.size()>200) -			mMessageArchive.erase(mMessageArchive.begin()); -	} +	mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); +	mOutputMonitor->setVisible(FALSE); -	if (args["do_not_log"].asBoolean())  -	{ -		return; -	} +	// Register for font change notifications +	LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChat::onChatFontChange, this, _1)); -	if (gSavedPerAccountSettings.getBOOL("LogNearbyChat")) -	{ -		std::string from_name = chat.mFromName; +	enableResizeCtrls(true, true, false); -		if (chat.mSourceType == CHAT_SOURCE_AGENT) -		{ -			// if the chat is coming from an agent, log the complete name -			LLAvatarName av_name; -			LLAvatarNameCache::get(chat.mFromID, &av_name); +	addToHost(); -			if (!av_name.mIsDisplayNameDefault) -			{ -				from_name = av_name.getCompleteName(); -			} -		} +	//for menu +	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; +	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; -		LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); +	enable_registrar.add("NearbyChat.Check", boost::bind(&LLNearbyChat::onNearbyChatCheckContextMenuItem, this, _2)); +	registrar.add("NearbyChat.Action", boost::bind(&LLNearbyChat::onNearbyChatContextMenuItemClicked, this, _2)); + +	LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_nearby_chat.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); +	if(menu) +	{ +		mPopupMenuHandle = menu->getHandle();  	} + +	// obsolete, but may be needed for backward compatibility? +	gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); + +	mChatHistory = getChild<LLChatHistory>("chat_history"); +	if (gSavedPerAccountSettings.getBOOL("LogShowHistory")) +	{ +		loadHistory(); +	} + +	return LLIMConversation::postBuild();  }  void LLNearbyChat::onNearbySpeakers() @@ -162,44 +193,51 @@ void LLNearbyChat::onNearbySpeakers()  	LLFloaterSidePanelContainer::showPanel("people", "panel_people", param);  } -  void	LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata)  {  } +  bool	LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata)  {  	std::string str = userdata.asString();  	if(str == "nearby_people") -		onNearbySpeakers();	 +		onNearbySpeakers();  	return false;  } -void LLNearbyChat::removeScreenChat() +void LLNearbyChat::getAllowedRect(LLRect& rect)  { -	LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); -	if(chat_channel) -	{ -		chat_channel->removeToastsFromChannel(); -	} +	rect = gViewerWindow->getWorldViewRectScaled();  } - -void	LLNearbyChat::setVisible(BOOL visible) +//////////////////////////////////////////////////////////////////////////////// +// +void LLNearbyChat::onFocusReceived()  { -	if(visible) -	{ -		removeScreenChat(); -	} - -	LLPanel::setVisible(visible); +	setBackgroundOpaque(true); +	LLIMConversation::onFocusReceived();  } +//////////////////////////////////////////////////////////////////////////////// +// +void LLNearbyChat::onFocusLost() +{ +	setBackgroundOpaque(false); +	LLIMConversation::onFocusLost(); +} -void LLNearbyChat::getAllowedRect(LLRect& rect) +BOOL	LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask)  { -	rect = gViewerWindow->getWorldViewRectScaled(); +	//fix for EXT-6625 +	//highlight NearbyChat history whenever mouseclick happen in NearbyChat +	//setting focus to eidtor will force onFocusLost() call that in its turn will change +	//background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. + +	if(mChatHistory) +		mChatHistory->setFocus(TRUE); +	return LLPanel::handleMouseDown(x, y, mask);  } -void LLNearbyChat::updateChatHistoryStyle() +void LLNearbyChat::reloadMessages()  {  	mChatHistory->clear(); @@ -212,34 +250,6 @@ void LLNearbyChat::updateChatHistoryStyle()  	}  } -//static  -void LLNearbyChat::processChatHistoryStyleUpdate(const LLSD& newvalue) -{ -	LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); -	LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); -	if(nearby_chat) -		nearby_chat->updateChatHistoryStyle(); -} - -bool isWordsName(const std::string& name) -{ -	// checking to see if it's display name plus username in parentheses  -	S32 open_paren = name.find(" (", 0); -	S32 close_paren = name.find(')', 0); - -	if (open_paren != std::string::npos && -		close_paren == name.length()-1) -	{ -		return true; -	} -	else -	{ -		//checking for a single space -		S32 pos = name.find(' ', 0); -		return std::string::npos != pos && name.rfind(' ', name.length()) == pos && 0 != pos && name.length()-1 != pos; -	} -} -  void LLNearbyChat::loadHistory()  {  	LLSD do_not_log; @@ -274,9 +284,9 @@ void LLNearbyChat::loadHistory()  		chat.mSourceType = CHAT_SOURCE_AGENT;  		if (from_id.isNull() && SYSTEM_FROM == from) -		{	 +		{  			chat.mSourceType = CHAT_SOURCE_SYSTEM; -			 +  		}  		else if (from_id.isNull())  		{ @@ -289,43 +299,113 @@ void LLNearbyChat::loadHistory()  	}  } -//static -LLNearbyChat* LLNearbyChat::getInstance() +void LLNearbyChat::removeScreenChat()  { -	LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); -	return chat_bar->findChild<LLNearbyChat>("nearby_chat"); +	LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); +	if(chat_channel) +	{ +		chat_channel->removeToastsFromChannel(); +	}  } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusReceived() +void	LLNearbyChat::setVisible(BOOL visible)  { -	setBackgroundOpaque(true); -	LLPanel::onFocusReceived(); +	if(visible) +	{ +		removeScreenChat(); +	} + +	LLIMConversation::setVisible(visible);  } -//////////////////////////////////////////////////////////////////////////////// -// -void LLNearbyChat::onFocusLost() + +void LLNearbyChat::enableDisableCallBtn()  { -	setBackgroundOpaque(false); -	LLPanel::onFocusLost(); +	// bool btn_enabled = LLAgent::isActionAllowed("speak"); + +	getChildView("voice_call_btn")->setEnabled(false /*btn_enabled*/);  } -BOOL	LLNearbyChat::handleMouseDown(S32 x, S32 y, MASK mask) +void LLNearbyChat::addToHost()  { -	//fix for EXT-6625 -	//highlight NearbyChat history whenever mouseclick happen in NearbyChat -	//setting focus to eidtor will force onFocusLost() call that in its turn will change  -	//background opaque. This all happenn since NearByChat is "chrome" and didn't process focus change. +	if (LLIMConversation::isChatMultiTab()) +	{ +		LLIMFloaterContainer* im_box = LLIMFloaterContainer::getInstance(); + +		if (im_box) +		{ +			im_box->addFloater(this, FALSE, LLTabContainer::END); +		} +	} +} + +// virtual +void LLNearbyChat::onOpen(const LLSD& key) +{ +	LLIMConversation::onOpen(key); +	showTranslationCheckbox(LLTranslate::isTranslationConfigured()); +} + +bool LLNearbyChat::applyRectControl() +{ +	bool rect_controlled = LLFloater::applyRectControl(); + +/*	if (!mNearbyChat->getVisible()) +	{ +		reshape(getRect().getWidth(), getMinHeight()); +		enableResizeCtrls(true, true, false); +	} +	else +	{*/ +		enableResizeCtrls(true); +		setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); +//	} -	if(mChatHistory) -		mChatHistory->setFocus(TRUE); -	return LLPanel::handleMouseDown(x, y, mask); +	return rect_controlled;  } -void LLNearbyChat::draw() +void LLNearbyChat::onChatFontChange(LLFontGL* fontp)  { +	// Update things with the new font whohoo +	if (mChatBox) +	{ +		mChatBox->setFont(fontp); +	} +} + +//static +LLNearbyChat* LLNearbyChat::getInstance() +{ +	return LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar"); +} + +//static +//LLNearbyChat* LLNearbyChat::findInstance() +//{ +//	return LLFloaterReg::findTypedInstance<LLNearbyChat>("chat_bar"); +//} + +void LLNearbyChat::showHistory() +{ +	openFloater(); +	setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); +	reshape(getRect().getWidth(), mExpandedHeight); +	enableResizeCtrls(true); +	storeRectControl(); +} + +void LLNearbyChat::showTranslationCheckbox(BOOL show) +{ +	getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show); +} + +BOOL LLNearbyChat::tick() +{ +	BOOL parents_retcode = LLIMConversation::tick(); + +	displaySpeakingIndicator(); +	updateCallBtnState(LLVoiceClient::getInstance()->getUserPTTState()); +  	// *HACK: Update transparency type depending on whether our children have focus.  	// This is needed because this floater is chrome and thus cannot accept focus, so  	// the transparency type setting code from LLFloater::setFocus() isn't reached. @@ -334,5 +414,511 @@ void LLNearbyChat::draw()  		setTransparencyType(hasFocus() ? TT_ACTIVE : TT_INACTIVE);  	} -	LLPanel::draw(); +	return parents_retcode; +} + +std::string LLNearbyChat::getCurrentChat() +{ +	return mChatBox ? mChatBox->getText() : LLStringUtil::null; +} + +// virtual +BOOL LLNearbyChat::handleKeyHere( KEY key, MASK mask ) +{ +	BOOL handled = FALSE; + +	if( KEY_RETURN == key && mask == MASK_CONTROL) +	{ +		// shout +		sendChat(CHAT_TYPE_SHOUT); +		handled = TRUE; +	} + +	return handled; +} + +BOOL LLNearbyChat::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) +{ +	U32 in_len = in_str.length(); +	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); +	 +	bool string_was_found = false; + +	for (S32 n = 0; n < cnt && !string_was_found; n++) +	{ +		if (in_len <= sChatTypeTriggers[n].name.length()) +		{ +			std::string trigger_trunc = sChatTypeTriggers[n].name; +			LLStringUtil::truncate(trigger_trunc, in_len); + +			if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) +			{ +				*out_str = sChatTypeTriggers[n].name; +				string_was_found = true; +			} +		} +	} + +	return string_was_found; +} + +void LLNearbyChat::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) +{ +	LLFirstUse::otherAvatarChatFirst(false); + +	LLNearbyChat* self = (LLNearbyChat *)userdata; + +	LLWString raw_text = self->mChatBox->getWText(); + +	// Can't trim the end, because that will cause autocompletion +	// to eat trailing spaces that might be part of a gesture. +	LLWStringUtil::trimHead(raw_text); + +	S32 length = raw_text.length(); + +	if( (length > 0) && (raw_text[0] != '/') )  // forward slash is used for escape (eg. emote) sequences +	{ +		gAgent.startTyping(); +	} +	else +	{ +		gAgent.stopTyping(); +	} + +	/* Doesn't work -- can't tell the difference between a backspace +	   that killed the selection vs. backspace at the end of line. +	if (length > 1  +		&& text[0] == '/' +		&& key == KEY_BACKSPACE) +	{ +		// the selection will already be deleted, but we need to trim +		// off the character before +		std::string new_text = raw_text.substr(0, length-1); +		self->mInputEditor->setText( new_text ); +		self->mInputEditor->setCursorToEnd(); +		length = length - 1; +	} +	*/ + +	KEY key = gKeyboard->currentKey(); + +	// Ignore "special" keys, like backspace, arrows, etc. +	if (length > 1  +		&& raw_text[0] == '/' +		&& key < KEY_SPECIAL) +	{ +		// we're starting a gesture, attempt to autocomplete + +		std::string utf8_trigger = wstring_to_utf8str(raw_text); +		std::string utf8_out_str(utf8_trigger); + +		if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) +		{ +			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); +			self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part +			S32 outlength = self->mChatBox->getLength(); // in characters + +			// Select to end of line, starting from the character +			// after the last one the user typed. +			self->mChatBox->setSelection(length, outlength); +		} +		else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) +		{ +			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); +			self->mChatBox->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part +			self->mChatBox->setCursorToEnd(); +		} + +		//llinfos << "GESTUREDEBUG " << trigger  +		//	<< " len " << length +		//	<< " outlen " << out_str.getLength() +		//	<< llendl; +	} +} + +// static +void LLNearbyChat::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) +{ +	// stop typing animation +	gAgent.stopTyping(); +} + +void LLNearbyChat::onChatBoxFocusReceived() +{ +	mChatBox->setEnabled(!gDisconnected); +} + +EChatType LLNearbyChat::processChatTypeTriggers(EChatType type, std::string &str) +{ +	U32 length = str.length(); +	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); +	 +	for (S32 n = 0; n < cnt; n++) +	{ +		if (length >= sChatTypeTriggers[n].name.length()) +		{ +			std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); + +			if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) +			{ +				U32 trigger_length = sChatTypeTriggers[n].name.length(); + +				// It's to remove space after trigger name +				if (length > trigger_length && str[trigger_length] == ' ') +					trigger_length++; + +				str = str.substr(trigger_length, length); + +				if (CHAT_TYPE_NORMAL == type) +					return sChatTypeTriggers[n].type; +				else +					break; +			} +		} +	} + +	return type; +} + +void LLNearbyChat::sendChat( EChatType type ) +{ +	if (mChatBox) +	{ +		LLWString text = mChatBox->getConvertedText(); +		if (!text.empty()) +		{ +			// store sent line in history, duplicates will get filtered +			mChatBox->updateHistory(); +			// Check if this is destined for another channel +			S32 channel = 0; +			stripChannelNumber(text, &channel); +			 +			std::string utf8text = wstring_to_utf8str(text); +			// Try to trigger a gesture, if not chat to a script. +			std::string utf8_revised_text; +			if (0 == channel) +			{ +				// discard returned "found" boolean +				LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); +			} +			else +			{ +				utf8_revised_text = utf8text; +			} + +			utf8_revised_text = utf8str_trim(utf8_revised_text); + +			type = processChatTypeTriggers(type, utf8_revised_text); + +			if (!utf8_revised_text.empty()) +			{ +				// Chat with animation +				sendChatFromViewer(utf8_revised_text, type, TRUE); +			} +		} + +		mChatBox->setText(LLStringExplicit("")); +	} + +	gAgent.stopTyping(); + +	// If the user wants to stop chatting on hitting return, lose focus +	// and go out of chat mode. +	if (gSavedSettings.getBOOL("CloseChatOnReturn")) +	{ +		stopChat(); +	} +} + + +void LLNearbyChat::appendMessage(const LLChat& chat, const LLSD &args) +{ +	LLChat& tmp_chat = const_cast<LLChat&>(chat); + +	if(tmp_chat.mTimeStr.empty()) +		tmp_chat.mTimeStr = appendTime(); + +	if (!chat.mMuted) +	{ +		tmp_chat.mFromName = chat.mFromName; +		LLSD chat_args; +		if (args) chat_args = args; +		chat_args["use_plain_text_chat_history"] = +				gSavedSettings.getBOOL("PlainTextChatHistory"); +		chat_args["show_time"] = gSavedSettings.getBOOL("IMShowTime"); +		chat_args["show_names_for_p2p_conv"] = true; + +		mChatHistory->appendMessage(chat, chat_args); +	} +} + +void	LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args) +{ +	appendMessage(chat, args); + +	if(archive) +	{ +		mMessageArchive.push_back(chat); +		if(mMessageArchive.size()>200) +			mMessageArchive.erase(mMessageArchive.begin()); +	} + +	// logging +	if (!args["do_not_log"].asBoolean() +			&& gSavedPerAccountSettings.getBOOL("LogNearbyChat")) +	{ +		std::string from_name = chat.mFromName; + +		if (chat.mSourceType == CHAT_SOURCE_AGENT) +		{ +			// if the chat is coming from an agent, log the complete name +			LLAvatarName av_name; +			LLAvatarNameCache::get(chat.mFromID, &av_name); + +			if (!av_name.mIsDisplayNameDefault) +			{ +				from_name = av_name.getCompleteName(); +			} +		} + +		LLLogChat::saveHistory("chat", from_name, chat.mFromID, chat.mText); +	} +} + + +void LLNearbyChat::onChatBoxCommit() +{ +	if (mChatBox->getText().length() > 0) +	{ +		sendChat(CHAT_TYPE_NORMAL); +	} + +	gAgent.stopTyping();  } + +void LLNearbyChat::displaySpeakingIndicator() +{ +	LLSpeakerMgr::speaker_list_t speaker_list; +	LLUUID id; + +	id.setNull(); +	mSpeakerMgr->update(TRUE); +	mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); + +	for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) +	{ +		LLPointer<LLSpeaker> s = *i; +		if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) +		{ +			id = s->mID; +			break; +		} +	} + +	if (!id.isNull()) +	{ +		mOutputMonitor->setVisible(TRUE); +		mOutputMonitor->setSpeakerId(id); +	} +	else +	{ +		mOutputMonitor->setVisible(FALSE); +	} +} + +void LLNearbyChat::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) +{ +	sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); +} + +void LLNearbyChat::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) +{ +	// Look for "/20 foo" channel chats. +	S32 channel = 0; +	LLWString out_text = stripChannelNumber(wtext, &channel); +	std::string utf8_out_text = wstring_to_utf8str(out_text); +	std::string utf8_text = wstring_to_utf8str(wtext); + +	utf8_text = utf8str_trim(utf8_text); +	if (!utf8_text.empty()) +	{ +		utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); +	} + +	// Don't animate for chats people can't hear (chat to scripts) +	if (animate && (channel == 0)) +	{ +		if (type == CHAT_TYPE_WHISPER) +		{ +			lldebugs << "You whisper " << utf8_text << llendl; +			gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START); +		} +		else if (type == CHAT_TYPE_NORMAL) +		{ +			lldebugs << "You say " << utf8_text << llendl; +			gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START); +		} +		else if (type == CHAT_TYPE_SHOUT) +		{ +			lldebugs << "You shout " << utf8_text << llendl; +			gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START); +		} +		else +		{ +			llinfos << "send_chat_from_viewer() - invalid volume" << llendl; +			return; +		} +	} +	else +	{ +		if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) +		{ +			lldebugs << "Channel chat: " << utf8_text << llendl; +		} +	} + +	send_chat_from_viewer(utf8_out_text, type, channel); +} + +// static  +void LLNearbyChat::startChat(const char* line) +{ +	LLNearbyChat* cb = LLNearbyChat::getInstance(); + +	if (cb ) +	{ +		cb->setVisible(TRUE); +		cb->setFocus(TRUE); +		cb->mChatBox->setFocus(TRUE); + +		if (line) +		{ +			std::string line_string(line); +			cb->mChatBox->setText(line_string); +		} + +		cb->mChatBox->setCursorToEnd(); +	} +} + +// Exit "chat mode" and do the appropriate focus changes +// static +void LLNearbyChat::stopChat() +{ +	LLNearbyChat* cb = LLNearbyChat::getInstance(); + +	if (cb) +	{ +		cb->mChatBox->setFocus(FALSE); + +		// stop typing animation +		gAgent.stopTyping(); +	} +} + +// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. +// Otherwise returns input and channel 0. +LLWString LLNearbyChat::stripChannelNumber(const LLWString &mesg, S32* channel) +{ +	if (mesg[0] == '/' +		&& mesg[1] == '/') +	{ +		// This is a "repeat channel send" +		*channel = sLastSpecialChatChannel; +		return mesg.substr(2, mesg.length() - 2); +	} +	else if (mesg[0] == '/' +			 && mesg[1] +			 && LLStringOps::isDigit(mesg[1])) +	{ +		// This a special "/20" speak on a channel +		S32 pos = 0; + +		// Copy the channel number into a string +		LLWString channel_string; +		llwchar c; +		do +		{ +			c = mesg[pos+1]; +			channel_string.push_back(c); +			pos++; +		} +		while(c && pos < 64 && LLStringOps::isDigit(c)); +		 +		// Move the pointer forward to the first non-whitespace char +		// Check isspace before looping, so we can handle "/33foo" +		// as well as "/33 foo" +		while(c && iswspace(c)) +		{ +			c = mesg[pos+1]; +			pos++; +		} +		 +		sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10); +		*channel = sLastSpecialChatChannel; +		return mesg.substr(pos, mesg.length() - pos); +	} +	else +	{ +		// This is normal chat. +		*channel = 0; +		return mesg; +	} +} + +void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) +{ +	LLMessageSystem* msg = gMessageSystem; +	msg->newMessageFast(_PREHASH_ChatFromViewer); +	msg->nextBlockFast(_PREHASH_AgentData); +	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); +	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); +	msg->nextBlockFast(_PREHASH_ChatData); +	msg->addStringFast(_PREHASH_Message, utf8_out_text); +	msg->addU8Fast(_PREHASH_Type, type); +	msg->addS32("Channel", channel); + +	gAgent.sendReliableMessage(); + +	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); +} + +class LLChatCommandHandler : public LLCommandHandler +{ +public: +	// not allowed from outside the app +	LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } + +    // Your code here +	bool handle(const LLSD& tokens, const LLSD& query_map, +				LLMediaCtrl* web) +	{ +		bool retval = false; +		// Need at least 2 tokens to have a valid message. +		if (tokens.size() < 2) +		{ +			retval = false; +		} +		else +		{ +		S32 channel = tokens[0].asInteger(); +			// VWR-19499 Restrict function to chat channels greater than 0. +			if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) +			{ +				retval = true; +		// Send unescaped message, see EXT-6353. +		std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); +		send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); +			} +			else +			{ +				retval = false; +				// Tell us this is an unsupported SLurl. +			} +		} +		return retval; +	} +}; + +// Creating the object registers with the dispatcher. +LLChatCommandHandler gChatHandler; diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index 7c5975cbc5..bc0e54de15 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -1,8 +1,8 @@ - /**  +/**    * @file llnearbychat.h - * @brief nearby chat history scrolling panel implementation + * @brief LLNearbyChat class definition   * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * $LicenseInfo:firstyear=2002&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc.   *  @@ -24,60 +24,115 @@   * $/LicenseInfo$   */ -#ifndef LL_LLNEARBYCHAT_H_ -#define LL_LLNEARBYCHAT_H_ +#ifndef LL_LLNEARBYCHAT_H +#define LL_LLNEARBYCHAT_H +#include "llimconversation.h" +#include "llcombobox.h" +#include "llgesturemgr.h" +#include "llchat.h" +#include "llvoiceclient.h" +#include "lloutputmonitorctrl.h" +#include "llspeakers.h"  #include "llscrollbar.h"  #include "llviewerchat.h" -#include "llfloater.h" +#include "llpanel.h"  class LLResizeBar;  class LLChatHistory; -class LLNearbyChat: public LLPanel +class LLNearbyChat +	:	public LLIMConversation  {  public: -	LLNearbyChat(const Params& p = LLPanel::getDefaultParams()); +	// constructor for inline chat-bars (e.g. hosted in chat history window) +	LLNearbyChat(const LLSD& key); +	~LLNearbyChat() {} -	BOOL	postBuild			(); +	/*virtual*/ BOOL postBuild(); +	/*virtual*/ void onOpen(const LLSD& key); + +	// focus overrides +	/*virtual*/ void	onFocusLost(); +	/*virtual*/ void	onFocusReceived(); + +	/*virtual*/ void	setVisible(BOOL visible); + +	void loadHistory(); +    void reloadMessages(); +	void removeScreenChat(); + +	static LLNearbyChat* getInstance(); + +	void addToHost();  	/** @param archive true - to save a message to the chat history log */ -	void	addMessage			(const LLChat& message,bool archive = true, const LLSD &args = LLSD());	 +	void	addMessage			(const LLChat& message,bool archive = true, const LLSD &args = LLSD());  	void	onNearbyChatContextMenuItemClicked(const LLSD& userdata);  	bool	onNearbyChatCheckContextMenuItem(const LLSD& userdata); +	LLLineEditor* getChatBox() { return mChatBox; } + +	//virtual void draw(); + +	std::string getCurrentChat(); + +	virtual BOOL handleKeyHere( KEY key, MASK mask );  	virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask); -	virtual void	draw(); -	// focus overrides -	/*virtual*/ void	onFocusLost(); -	/*virtual*/ void	onFocusReceived(); -	 -	/*virtual*/ void	setVisible(BOOL visible); -	 -	virtual void updateChatHistoryStyle(); +	static void startChat(const char* line); +	static void stopChat(); -	static void processChatHistoryStyleUpdate(const LLSD& newvalue); +	static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); +	static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); -	void loadHistory(); +	void showHistory(); +	void showTranslationCheckbox(BOOL show); -	static LLNearbyChat* getInstance(); -	void removeScreenChat(); +protected: +	static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); +	static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); +	static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); +	void onChatBoxFocusReceived(); -private: +	void sendChat( EChatType type ); +	void onChatBoxCommit(); +	void onChatFontChange(LLFontGL* fontp); -	void	getAllowedRect		(LLRect& rect); +	/* virtual */ bool applyRectControl(); -	void	onNearbySpeakers	(); +	void onToggleNearbyChatPanel(); + +	static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); +	EChatType processChatTypeTriggers(EChatType type, std::string &str); + +	void displaySpeakingIndicator(); + +	// set the enable/disable state for the Call button +	virtual void enableDisableCallBtn(); + +	// Which non-zero channel did we last chat on? +	static S32 sLastSpecialChatChannel; + +	LLLineEditor*			mChatBox; +	LLOutputMonitorCtrl*	mOutputMonitor; +	LLLocalSpeakerMgr*		mSpeakerMgr; +	S32 mExpandedHeight; + +	/*virtual*/ BOOL tick();  private: + +	void	getAllowedRect		(LLRect& rect); +	// prepare chat's params and out one message to chatHistory +	void appendMessage(const LLChat& chat, const LLSD &args = 0); +	void	onNearbySpeakers	(); +  	LLHandle<LLView>	mPopupMenuHandle; +	std::vector<LLChat> mMessageArchive;  	LLChatHistory*		mChatHistory; -	std::vector<LLChat> mMessageArchive;  };  #endif - - diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp deleted file mode 100644 index b4224e30e6..0000000000 --- a/indra/newview/llnearbychatbar.cpp +++ /dev/null @@ -1,672 +0,0 @@ -/**  - * @file llnearbychatbar.cpp - * @brief LLNearbyChatBar class implementation - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, 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$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "message.h" - -#include "llappviewer.h" -#include "llfloaterreg.h" -#include "lltrans.h" - -#include "llfirstuse.h" -#include "llnearbychatbar.h" -#include "llagent.h" -#include "llgesturemgr.h" -#include "llmultigesture.h" -#include "llkeyboard.h" -#include "llanimationstates.h" -#include "llviewerstats.h" -#include "llcommandhandler.h" -#include "llviewercontrol.h" -#include "llnavigationbar.h" -#include "llwindow.h" -#include "llviewerwindow.h" -#include "llrootview.h" -#include "llviewerchat.h" -#include "llnearbychat.h" -#include "lltranslate.h" - -#include "llresizehandle.h" - -S32 LLNearbyChatBar::sLastSpecialChatChannel = 0; - -const S32 EXPANDED_HEIGHT = 300; -const S32 COLLAPSED_HEIGHT = 60; -const S32 EXPANDED_MIN_HEIGHT = 150; - -// legacy callback glue -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel); - -struct LLChatTypeTrigger { -	std::string name; -	EChatType type; -}; - -static LLChatTypeTrigger sChatTypeTriggers[] = { -	{ "/whisper"	, CHAT_TYPE_WHISPER}, -	{ "/shout"	, CHAT_TYPE_SHOUT} -}; - -LLNearbyChatBar::LLNearbyChatBar(const LLSD& key) -:	LLFloater(key), -	mChatBox(NULL), -	mNearbyChat(NULL), -	mOutputMonitor(NULL), -	mSpeakerMgr(NULL), -	mExpandedHeight(COLLAPSED_HEIGHT + EXPANDED_HEIGHT) -{ -	mSpeakerMgr = LLLocalSpeakerMgr::getInstance(); -} - -//virtual -BOOL LLNearbyChatBar::postBuild() -{ -	mChatBox = getChild<LLLineEditor>("chat_box"); - -	mChatBox->setCommitCallback(boost::bind(&LLNearbyChatBar::onChatBoxCommit, this)); -	mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this); -	mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this)); -	mChatBox->setFocusReceivedCallback(boost::bind(&LLNearbyChatBar::onChatBoxFocusReceived, this)); - -	mChatBox->setIgnoreArrowKeys( FALSE );  -	mChatBox->setCommitOnFocusLost( FALSE ); -	mChatBox->setRevertOnEsc( FALSE ); -	mChatBox->setIgnoreTab(TRUE); -	mChatBox->setPassDelete(TRUE); -	mChatBox->setReplaceNewlinesWithSpaces(FALSE); -	mChatBox->setEnableLineHistory(TRUE); -	mChatBox->setFont(LLViewerChat::getChatFont()); - -	mNearbyChat = getChildView("nearby_chat"); - -	LLUICtrl* show_btn = getChild<LLUICtrl>("show_nearby_chat"); -	show_btn->setCommitCallback(boost::bind(&LLNearbyChatBar::onToggleNearbyChatPanel, this)); - -	mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); -	mOutputMonitor->setVisible(FALSE); - -	gSavedSettings.declareBOOL("nearbychat_history_visibility", mNearbyChat->getVisible(), "Visibility state of nearby chat history", TRUE); - -	mNearbyChat->setVisible(gSavedSettings.getBOOL("nearbychat_history_visibility")); - -	// Register for font change notifications -	LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1)); - -	enableResizeCtrls(true, true, false); - -	return TRUE; -} - -// virtual -void LLNearbyChatBar::onOpen(const LLSD& key) -{ -	showTranslationCheckbox(LLTranslate::isTranslationConfigured()); -} - -bool LLNearbyChatBar::applyRectControl() -{ -	bool rect_controlled = LLFloater::applyRectControl(); - -	if (!mNearbyChat->getVisible()) -	{ -		reshape(getRect().getWidth(), getMinHeight()); -		enableResizeCtrls(true, true, false); -	} -	else -	{ -		enableResizeCtrls(true); -		setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); -	} -	 -	return rect_controlled; -} - -void LLNearbyChatBar::onChatFontChange(LLFontGL* fontp) -{ -	// Update things with the new font whohoo -	if (mChatBox) -	{ -		mChatBox->setFont(fontp); -	} -} - -//static -LLNearbyChatBar* LLNearbyChatBar::getInstance() -{ -	return LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar"); -} - -void LLNearbyChatBar::showHistory() -{ -	openFloater(); - -	if (!getChildView("nearby_chat")->getVisible()) -	{ -		onToggleNearbyChatPanel(); -	} -} - -void LLNearbyChatBar::showTranslationCheckbox(BOOL show) -{ -	getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show); -} - -void LLNearbyChatBar::draw() -{ -	displaySpeakingIndicator(); -	LLFloater::draw(); -} - -std::string LLNearbyChatBar::getCurrentChat() -{ -	return mChatBox ? mChatBox->getText() : LLStringUtil::null; -} - -// virtual -BOOL LLNearbyChatBar::handleKeyHere( KEY key, MASK mask ) -{ -	BOOL handled = FALSE; - -	if( KEY_RETURN == key && mask == MASK_CONTROL) -	{ -		// shout -		sendChat(CHAT_TYPE_SHOUT); -		handled = TRUE; -	} - -	return handled; -} - -BOOL LLNearbyChatBar::matchChatTypeTrigger(const std::string& in_str, std::string* out_str) -{ -	U32 in_len = in_str.length(); -	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); -	 -	for (S32 n = 0; n < cnt; n++) -	{ -		if (in_len > sChatTypeTriggers[n].name.length()) -			continue; - -		std::string trigger_trunc = sChatTypeTriggers[n].name; -		LLStringUtil::truncate(trigger_trunc, in_len); - -		if (!LLStringUtil::compareInsensitive(in_str, trigger_trunc)) -		{ -			*out_str = sChatTypeTriggers[n].name; -			return TRUE; -		} -	} - -	return FALSE; -} - -void LLNearbyChatBar::onChatBoxKeystroke(LLLineEditor* caller, void* userdata) -{ -	LLFirstUse::otherAvatarChatFirst(false); - -	LLNearbyChatBar* self = (LLNearbyChatBar *)userdata; - -	LLWString raw_text = self->mChatBox->getWText(); - -	// Can't trim the end, because that will cause autocompletion -	// to eat trailing spaces that might be part of a gesture. -	LLWStringUtil::trimHead(raw_text); - -	S32 length = raw_text.length(); - -	if( (length > 0) && (raw_text[0] != '/') )  // forward slash is used for escape (eg. emote) sequences -	{ -		gAgent.startTyping(); -	} -	else -	{ -		gAgent.stopTyping(); -	} - -	/* Doesn't work -- can't tell the difference between a backspace -	   that killed the selection vs. backspace at the end of line. -	if (length > 1  -		&& text[0] == '/' -		&& key == KEY_BACKSPACE) -	{ -		// the selection will already be deleted, but we need to trim -		// off the character before -		std::string new_text = raw_text.substr(0, length-1); -		self->mInputEditor->setText( new_text ); -		self->mInputEditor->setCursorToEnd(); -		length = length - 1; -	} -	*/ - -	KEY key = gKeyboard->currentKey(); - -	// Ignore "special" keys, like backspace, arrows, etc. -	if (length > 1  -		&& raw_text[0] == '/' -		&& key < KEY_SPECIAL) -	{ -		// we're starting a gesture, attempt to autocomplete - -		std::string utf8_trigger = wstring_to_utf8str(raw_text); -		std::string utf8_out_str(utf8_trigger); - -		if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) -		{ -			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); -			self->mChatBox->setText(utf8_trigger + rest_of_match); // keep original capitalization for user-entered part -			S32 outlength = self->mChatBox->getLength(); // in characters - -			// Select to end of line, starting from the character -			// after the last one the user typed. -			self->mChatBox->setSelection(length, outlength); -		} -		else if (matchChatTypeTrigger(utf8_trigger, &utf8_out_str)) -		{ -			std::string rest_of_match = utf8_out_str.substr(utf8_trigger.size()); -			self->mChatBox->setText(utf8_trigger + rest_of_match + " "); // keep original capitalization for user-entered part -			self->mChatBox->setCursorToEnd(); -		} - -		//llinfos << "GESTUREDEBUG " << trigger  -		//	<< " len " << length -		//	<< " outlen " << out_str.getLength() -		//	<< llendl; -	} -} - -// static -void LLNearbyChatBar::onChatBoxFocusLost(LLFocusableElement* caller, void* userdata) -{ -	// stop typing animation -	gAgent.stopTyping(); -} - -void LLNearbyChatBar::onChatBoxFocusReceived() -{ -	mChatBox->setEnabled(!gDisconnected); -} - -EChatType LLNearbyChatBar::processChatTypeTriggers(EChatType type, std::string &str) -{ -	U32 length = str.length(); -	S32 cnt = sizeof(sChatTypeTriggers) / sizeof(*sChatTypeTriggers); -	 -	for (S32 n = 0; n < cnt; n++) -	{ -		if (length >= sChatTypeTriggers[n].name.length()) -		{ -			std::string trigger = str.substr(0, sChatTypeTriggers[n].name.length()); - -			if (!LLStringUtil::compareInsensitive(trigger, sChatTypeTriggers[n].name)) -			{ -				U32 trigger_length = sChatTypeTriggers[n].name.length(); - -				// It's to remove space after trigger name -				if (length > trigger_length && str[trigger_length] == ' ') -					trigger_length++; - -				str = str.substr(trigger_length, length); - -				if (CHAT_TYPE_NORMAL == type) -					return sChatTypeTriggers[n].type; -				else -					break; -			} -		} -	} - -	return type; -} - -void LLNearbyChatBar::sendChat( EChatType type ) -{ -	if (mChatBox) -	{ -		LLWString text = mChatBox->getConvertedText(); -		if (!text.empty()) -		{ -			// store sent line in history, duplicates will get filtered -			mChatBox->updateHistory(); -			// Check if this is destined for another channel -			S32 channel = 0; -			stripChannelNumber(text, &channel); -			 -			std::string utf8text = wstring_to_utf8str(text); -			// Try to trigger a gesture, if not chat to a script. -			std::string utf8_revised_text; -			if (0 == channel) -			{ -				// discard returned "found" boolean -				LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); -			} -			else -			{ -				utf8_revised_text = utf8text; -			} - -			utf8_revised_text = utf8str_trim(utf8_revised_text); - -			type = processChatTypeTriggers(type, utf8_revised_text); - -			if (!utf8_revised_text.empty()) -			{ -				// Chat with animation -				sendChatFromViewer(utf8_revised_text, type, TRUE); -			} -		} - -		mChatBox->setText(LLStringExplicit("")); -	} - -	gAgent.stopTyping(); - -	// If the user wants to stop chatting on hitting return, lose focus -	// and go out of chat mode. -	if (gSavedSettings.getBOOL("CloseChatOnReturn")) -	{ -		stopChat(); -	} -} - - -void LLNearbyChatBar::onToggleNearbyChatPanel() -{ -	LLView* nearby_chat = getChildView("nearby_chat"); - -	if (nearby_chat->getVisible()) -	{ -		if (!isMinimized()) -		{ -			mExpandedHeight = getRect().getHeight(); -		} -		setResizeLimits(getMinWidth(), COLLAPSED_HEIGHT); -		nearby_chat->setVisible(FALSE); -		reshape(getRect().getWidth(), COLLAPSED_HEIGHT); -		enableResizeCtrls(true, true, false); -		storeRectControl(); -	} -	else -	{ -		nearby_chat->setVisible(TRUE); -		setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); -		reshape(getRect().getWidth(), mExpandedHeight); -		enableResizeCtrls(true); -		storeRectControl(); -	} - -	gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible()); -} - -void LLNearbyChatBar::setMinimized(BOOL b) -{ -	LLNearbyChat* nearby_chat = getChild<LLNearbyChat>("nearby_chat"); -	// when unminimizing with nearby chat visible, go ahead and kill off screen chats -	if (!b && nearby_chat->getVisible()) -	{ -		nearby_chat->removeScreenChat(); -	} -		LLFloater::setMinimized(b); -} - -void LLNearbyChatBar::onChatBoxCommit() -{ -	if (mChatBox->getText().length() > 0) -	{ -		sendChat(CHAT_TYPE_NORMAL); -	} - -	gAgent.stopTyping(); -} - -void LLNearbyChatBar::displaySpeakingIndicator() -{ -	LLSpeakerMgr::speaker_list_t speaker_list; -	LLUUID id; - -	id.setNull(); -	mSpeakerMgr->update(TRUE); -	mSpeakerMgr->getSpeakerList(&speaker_list, FALSE); - -	for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i) -	{ -		LLPointer<LLSpeaker> s = *i; -		if (s->mSpeechVolume > 0 || s->mStatus == LLSpeaker::STATUS_SPEAKING) -		{ -			id = s->mID; -			break; -		} -	} - -	if (!id.isNull()) -	{ -		mOutputMonitor->setVisible(TRUE); -		mOutputMonitor->setSpeakerId(id); -	} -	else -	{ -		mOutputMonitor->setVisible(FALSE); -	} -} - -void LLNearbyChatBar::sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate) -{ -	sendChatFromViewer(utf8str_to_wstring(utf8text), type, animate); -} - -void LLNearbyChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate) -{ -	// Look for "/20 foo" channel chats. -	S32 channel = 0; -	LLWString out_text = stripChannelNumber(wtext, &channel); -	std::string utf8_out_text = wstring_to_utf8str(out_text); -	std::string utf8_text = wstring_to_utf8str(wtext); - -	utf8_text = utf8str_trim(utf8_text); -	if (!utf8_text.empty()) -	{ -		utf8_text = utf8str_truncate(utf8_text, MAX_STRING - 1); -	} - -	// Don't animate for chats people can't hear (chat to scripts) -	if (animate && (channel == 0)) -	{ -		if (type == CHAT_TYPE_WHISPER) -		{ -			lldebugs << "You whisper " << utf8_text << llendl; -			gAgent.sendAnimationRequest(ANIM_AGENT_WHISPER, ANIM_REQUEST_START); -		} -		else if (type == CHAT_TYPE_NORMAL) -		{ -			lldebugs << "You say " << utf8_text << llendl; -			gAgent.sendAnimationRequest(ANIM_AGENT_TALK, ANIM_REQUEST_START); -		} -		else if (type == CHAT_TYPE_SHOUT) -		{ -			lldebugs << "You shout " << utf8_text << llendl; -			gAgent.sendAnimationRequest(ANIM_AGENT_SHOUT, ANIM_REQUEST_START); -		} -		else -		{ -			llinfos << "send_chat_from_viewer() - invalid volume" << llendl; -			return; -		} -	} -	else -	{ -		if (type != CHAT_TYPE_START && type != CHAT_TYPE_STOP) -		{ -			lldebugs << "Channel chat: " << utf8_text << llendl; -		} -	} - -	send_chat_from_viewer(utf8_out_text, type, channel); -} - -// static  -void LLNearbyChatBar::startChat(const char* line) -{ -	LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - -	if (!cb ) -		return; - -	cb->setVisible(TRUE); -	cb->setFocus(TRUE); -	cb->mChatBox->setFocus(TRUE); - -	if (line) -	{ -		std::string line_string(line); -		cb->mChatBox->setText(line_string); -	} - -	cb->mChatBox->setCursorToEnd(); -} - -// Exit "chat mode" and do the appropriate focus changes -// static -void LLNearbyChatBar::stopChat() -{ -	LLNearbyChatBar* cb = LLNearbyChatBar::getInstance(); - -	if (!cb) -		return; - -	cb->mChatBox->setFocus(FALSE); - - 	// stop typing animation - 	gAgent.stopTyping(); -} - -// If input of the form "/20foo" or "/20 foo", returns "foo" and channel 20. -// Otherwise returns input and channel 0. -LLWString LLNearbyChatBar::stripChannelNumber(const LLWString &mesg, S32* channel) -{ -	if (mesg[0] == '/' -		&& mesg[1] == '/') -	{ -		// This is a "repeat channel send" -		*channel = sLastSpecialChatChannel; -		return mesg.substr(2, mesg.length() - 2); -	} -	else if (mesg[0] == '/' -			 && mesg[1] -			 && LLStringOps::isDigit(mesg[1])) -	{ -		// This a special "/20" speak on a channel -		S32 pos = 0; - -		// Copy the channel number into a string -		LLWString channel_string; -		llwchar c; -		do -		{ -			c = mesg[pos+1]; -			channel_string.push_back(c); -			pos++; -		} -		while(c && pos < 64 && LLStringOps::isDigit(c)); -		 -		// Move the pointer forward to the first non-whitespace char -		// Check isspace before looping, so we can handle "/33foo" -		// as well as "/33 foo" -		while(c && iswspace(c)) -		{ -			c = mesg[pos+1]; -			pos++; -		} -		 -		sLastSpecialChatChannel = strtol(wstring_to_utf8str(channel_string).c_str(), NULL, 10); -		*channel = sLastSpecialChatChannel; -		return mesg.substr(pos, mesg.length() - pos); -	} -	else -	{ -		// This is normal chat. -		*channel = 0; -		return mesg; -	} -} - -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) -{ -	LLMessageSystem* msg = gMessageSystem; -	msg->newMessageFast(_PREHASH_ChatFromViewer); -	msg->nextBlockFast(_PREHASH_AgentData); -	msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -	msg->nextBlockFast(_PREHASH_ChatData); -	msg->addStringFast(_PREHASH_Message, utf8_out_text); -	msg->addU8Fast(_PREHASH_Type, type); -	msg->addS32("Channel", channel); - -	gAgent.sendReliableMessage(); - -	LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); -} - -class LLChatCommandHandler : public LLCommandHandler -{ -public: -	// not allowed from outside the app -	LLChatCommandHandler() : LLCommandHandler("chat", UNTRUSTED_BLOCK) { } - -    // Your code here -	bool handle(const LLSD& tokens, const LLSD& query_map, -				LLMediaCtrl* web) -	{ -		bool retval = false; -		// Need at least 2 tokens to have a valid message. -		if (tokens.size() < 2) -		{ -			retval = false; -		} -		else -		{ -		S32 channel = tokens[0].asInteger(); -			// VWR-19499 Restrict function to chat channels greater than 0. -			if ((channel > 0) && (channel < CHAT_CHANNEL_DEBUG)) -			{ -				retval = true; -		// Send unescaped message, see EXT-6353. -		std::string unescaped_mesg (LLURI::unescape(tokens[1].asString())); -		send_chat_from_viewer(unescaped_mesg, CHAT_TYPE_NORMAL, channel); -			} -			else -			{ -				retval = false; -				// Tell us this is an unsupported SLurl. -			} -		} -		return retval; -	} -}; - -// Creating the object registers with the dispatcher. -LLChatCommandHandler gChatHandler; - - diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h deleted file mode 100644 index 8547cf0bce..0000000000 --- a/indra/newview/llnearbychatbar.h +++ /dev/null @@ -1,97 +0,0 @@ -/**  - * @file llnearbychatbar.h - * @brief LLNearbyChatBar class definition - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, 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$ - */ - -#ifndef LL_LLNEARBYCHATBAR_H -#define LL_LLNEARBYCHATBAR_H - -#include "llfloater.h" -#include "llcombobox.h" -#include "llgesturemgr.h" -#include "llchat.h" -#include "llvoiceclient.h" -#include "lloutputmonitorctrl.h" -#include "llspeakers.h" - -class LLNearbyChatBar :	public LLFloater -{ -public: -	// constructor for inline chat-bars (e.g. hosted in chat history window) -	LLNearbyChatBar(const LLSD& key); -	~LLNearbyChatBar() {} - -	virtual BOOL postBuild(); -	/*virtual*/ void onOpen(const LLSD& key); - -	static LLNearbyChatBar* getInstance(); - -	LLLineEditor* getChatBox() { return mChatBox; } - -	virtual void draw(); - -	std::string getCurrentChat(); -	virtual BOOL handleKeyHere( KEY key, MASK mask ); - -	static void startChat(const char* line); -	static void stopChat(); - -	static void sendChatFromViewer(const std::string &utf8text, EChatType type, BOOL animate); -	static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); - -	void showHistory(); -	void showTranslationCheckbox(BOOL show); -	/*virtual*/void setMinimized(BOOL b); - -protected: -	static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str); -	static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata); -	static void onChatBoxFocusLost(LLFocusableElement* caller, void* userdata); -	void onChatBoxFocusReceived(); - -	void sendChat( EChatType type ); -	void onChatBoxCommit(); -	void onChatFontChange(LLFontGL* fontp); - -	/* virtual */ bool applyRectControl(); - -	void onToggleNearbyChatPanel(); - -	static LLWString stripChannelNumber(const LLWString &mesg, S32* channel); -	EChatType processChatTypeTriggers(EChatType type, std::string &str); - -	void displaySpeakingIndicator(); - -	// Which non-zero channel did we last chat on? -	static S32 sLastSpecialChatChannel; - -	LLLineEditor*			mChatBox; -	LLView*					mNearbyChat; -	LLOutputMonitorCtrl*	mOutputMonitor; -	LLLocalSpeakerMgr*		mSpeakerMgr; - -	S32 mExpandedHeight; -}; - -#endif diff --git a/indra/newview/llnearbychatbarlistener.cpp b/indra/newview/llnearbychatbarlistener.cpp index a63e1fb76e..61815d1864 100644 --- a/indra/newview/llnearbychatbarlistener.cpp +++ b/indra/newview/llnearbychatbarlistener.cpp @@ -29,14 +29,14 @@  #include "llviewerprecompiledheaders.h"  #include "llnearbychatbarlistener.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llagent.h"  #include "llchat.h" -LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChatBar & chatbar) +LLNearbyChatBarListener::LLNearbyChatBarListener(LLNearbyChat & chatbar)    : LLEventAPI("LLChatBar",                 "LLChatBar listener to (e.g.) sendChat, etc."),  	mChatbar(chatbar) diff --git a/indra/newview/llnearbychatbarlistener.h b/indra/newview/llnearbychatbarlistener.h index 9af9bc1f7b..0537275424 100644 --- a/indra/newview/llnearbychatbarlistener.h +++ b/indra/newview/llnearbychatbarlistener.h @@ -33,17 +33,17 @@  #include "lleventapi.h"  class LLSD; -class LLNearbyChatBar; +class LLNearbyChat;  class LLNearbyChatBarListener : public LLEventAPI  {  public: -	LLNearbyChatBarListener(LLNearbyChatBar & chatbar); +	LLNearbyChatBarListener(LLNearbyChat & chatbar);  private:      void sendChat(LLSD const & chat_data) const; -	LLNearbyChatBar & mChatbar; +	LLNearbyChat & mChatbar;  };  #endif // LL_LLNEARBYCHATBARLISTENER_H diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 600fd395fb..e91a3fc334 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -1,6 +1,6 @@  /**    * @file LLNearbyChatHandler.cpp - * @brief Nearby chat notification managment + * @brief Nearby chat chat managment   *   * $LicenseInfo:firstyear=2009&license=viewerlgpl$   * Second Life Viewer Source Code @@ -40,22 +40,24 @@  #include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance  #include "llviewerwindow.h"//for screen channel position -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llrootview.h"  #include "lllayoutstack.h"  //add LLNearbyChatHandler to LLNotificationsUI namespace  using namespace LLNotificationsUI; -//----------------------------------------------------------------------------------------------- -//LLNearbyChatScreenChannel -//-----------------------------------------------------------------------------------------------	 -LLToastPanelBase* createToastPanel() +static LLNearbyChatToastPanel* createToastPanel()  {  	LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance();  	return item;  } + +//----------------------------------------------------------------------------------------------- +//LLNearbyChatScreenChannel +//-----------------------------------------------------------------------------------------------	 +  class LLNearbyChatScreenChannel: public LLScreenChannelBase  {  	LOG_CLASS(LLNearbyChatScreenChannel); @@ -81,10 +83,10 @@ public:  		}  	} -	void addNotification	(LLSD& notification); +	void addChat	(LLSD& chat);  	void arrangeToasts		(); -	typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t; +	typedef boost::function<LLNearbyChatToastPanel* (void )> create_toast_panel_callback_t;  	void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;}  	void onToastDestroyed	(LLToast* toast, bool app_quitting); @@ -152,6 +154,8 @@ protected:  	bool	mChannelRect;  }; + +  //-----------------------------------------------------------------------------------------------  // LLNearbyChatToast  //----------------------------------------------------------------------------------------------- @@ -255,7 +259,7 @@ void LLNearbyChatScreenChannel::updateToastFadingTime()  bool	LLNearbyChatScreenChannel::createPoolToast()  { -	LLToastPanelBase* panel= m_create_toast_panel_callback_t(); +	LLNearbyChatToastPanel* panel= m_create_toast_panel_callback_t();  	if(!panel)  		return false; @@ -277,7 +281,7 @@ bool	LLNearbyChatScreenChannel::createPoolToast()  	return true;  } -void LLNearbyChatScreenChannel::addNotification(LLSD& notification) +void LLNearbyChatScreenChannel::addChat(LLSD& chat)  {  	//look in pool. if there is any message  	if(mStopProcessing) @@ -289,8 +293,8 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  	if(m_active_toasts.size())  	{ -		LLUUID fromID = notification["from_id"].asUUID();		// agent id or object id -		std::string from = notification["from"].asString(); +		LLUUID fromID = chat["from_id"].asUUID();		// agent id or object id +		std::string from = chat["from"].asString();  		LLToast* toast = m_active_toasts[0].get();  		if (toast)  		{ @@ -298,7 +302,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  			if(panel && panel->messageID() == fromID && panel->getFromName() == from && panel->canAddText())  			{ -				panel->addMessage(notification); +				panel->addMessage(chat);  				toast->reshapeToPanel();  				toast->startTimer(); @@ -316,11 +320,11 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  		LL_DEBUGS("NearbyChat") << "Empty pool" << llendl;  		if(!createPoolToast())//created toast will go to pool. so next call will find it  			return; -		addNotification(notification); +		addChat(chat);  		return;  	} -	int chat_type = notification["chat_type"].asInteger(); +	int chat_type = chat["chat_type"].asInteger();  	if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG))  	{ @@ -339,10 +343,10 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification)  	m_toast_pool.pop_back(); -	LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel()); +	LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel());  	if(!panel)  		return; -	panel->init(notification); +	panel->init(chat);  	toast->reshapeToPanel();  	toast->startTimer(); @@ -445,10 +449,8 @@ void LLNearbyChatScreenChannel::arrangeToasts()  //-----------------------------------------------------------------------------------------------  boost::scoped_ptr<LLEventPump> LLNearbyChatHandler::sChatWatcher(new LLEventStream("LLChat")); -LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id) +LLNearbyChatHandler::LLNearbyChatHandler()  { -	mType = type; -  	// Getting a Channel for our notifications  	LLNearbyChatScreenChannel::Params p;  	p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID")); @@ -485,28 +487,26 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  	if(chat_msg.mText.empty())  		return;//don't process empty messages -	LLFloater* chat_bar = LLFloaterReg::getInstance("chat_bar"); - -	LLNearbyChat* nearby_chat = chat_bar->findChild<LLNearbyChat>("nearby_chat"); +	LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();  	// Build notification data  -	LLSD notification; -	notification["message"] = chat_msg.mText; -	notification["from"] = chat_msg.mFromName; -	notification["from_id"] = chat_msg.mFromID; -	notification["time"] = chat_msg.mTime; -	notification["source"] = (S32)chat_msg.mSourceType; -	notification["chat_type"] = (S32)chat_msg.mChatType; -	notification["chat_style"] = (S32)chat_msg.mChatStyle; +	LLSD chat; +	chat["message"] = chat_msg.mText; +	chat["from"] = chat_msg.mFromName; +	chat["from_id"] = chat_msg.mFromID; +	chat["time"] = chat_msg.mTime; +	chat["source"] = (S32)chat_msg.mSourceType; +	chat["chat_type"] = (S32)chat_msg.mChatType; +	chat["chat_style"] = (S32)chat_msg.mChatStyle;  	// Pass sender info so that it can be rendered properly (STORM-1021). -	notification["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args); +	chat["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args);  	if (chat_msg.mChatType == CHAT_TYPE_DIRECT &&  		chat_msg.mText.length() > 0 &&  		chat_msg.mText[0] == '@')  	{  		// Send event on to LLEventStream and exit -		sChatWatcher->post(notification); +		sChatWatcher->post(chat);  		return;  	} @@ -553,11 +553,10 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  	}  	// Send event on to LLEventStream -	sChatWatcher->post(notification); +	sChatWatcher->post(chat); -	if( !chat_bar->isMinimized() -		&& nearby_chat->isInVisibleChain()  +	if( nearby_chat->isInVisibleChain()  		|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT  			&& gSavedSettings.getBOOL("UseChatBubbles") )  		|| mChannel.isDead() @@ -604,23 +603,19 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg,  		// Add a nearby chat toast.  		LLUUID id;  		id.generate(); -		notification["id"] = id; +		chat["id"] = id;  		std::string r_color_name = "White";  		F32 r_color_alpha = 1.0f;   		LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha); -		notification["text_color"] = r_color_name; -		notification["color_alpha"] = r_color_alpha; -		notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ; -		notification["message"] = toast_msg; -		channel->addNotification(notification);	 +		chat["text_color"] = r_color_name; +		chat["color_alpha"] = r_color_alpha; +		chat["font_size"] = (S32)LLViewerChat::getChatFontSize() ; +		chat["message"] = toast_msg; +		channel->addChat(chat);	  	}  } -void LLNearbyChatHandler::onDeleteToast(LLToast* toast) -{ -} -  //-----------------------------------------------------------------------------------------------  // LLNearbyChatToast diff --git a/indra/newview/llnearbychathandler.h b/indra/newview/llnearbychathandler.h index b0e4f62d51..a5034ac1cb 100644 --- a/indra/newview/llnearbychathandler.h +++ b/indra/newview/llnearbychathandler.h @@ -37,14 +37,13 @@ namespace LLNotificationsUI{  class LLNearbyChatHandler : public LLChatHandler  {  public: -	LLNearbyChatHandler(e_notification_type type,const LLSD& id); +	LLNearbyChatHandler();  	virtual ~LLNearbyChatHandler();  	virtual void processChat(const LLChat& chat_msg, const LLSD &args);  protected: -	virtual void onDeleteToast(LLToast* toast);  	virtual void initChannel();  	static boost::scoped_ptr<LLEventPump> sChatWatcher; diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index 89fe7bb3c2..2bc9cdd3c1 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -40,10 +40,10 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLAlertHandler::LLAlertHandler(e_notification_type type, const LLSD& id) : mIsModal(false) +LLAlertHandler::LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal)  +:	LLSysHandler(name, notification_type), +	mIsModal(is_modal)  { -	mType = type; -  	LLScreenChannelBase::Params p;  	p.id = LLUUID(gSavedSettings.getString("AlertChannelUUID"));  	p.display_toasts_always = true; @@ -68,79 +68,58 @@ void LLAlertHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLAlertHandler::processNotification(const LLSD& notify) +bool LLAlertHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load") +	if (notification->canLogToIM() && notification->hasFormElements())  	{ -		if (LLHandlerUtil::canSpawnSessionAndLogToIM(notification)) -		{ -			const std::string name = LLHandlerUtil::getSubstitutionName(notification); - -			LLUUID from_id = notification->getPayload()["from_id"]; - -			// firstly create session... -			LLHandlerUtil::spawnIMSession(name, from_id); - -			// ...then log message to have IM Well notified about new message -			LLHandlerUtil::logToIMP2P(notification); -		} - -		LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); -		LLToast::Params p; -		p.notif_id = notification->getID(); -		p.notification = notification; -		p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); -		p.enable_hide_btn = false; -		p.can_fade = false; -		p.is_modal = mIsModal; -		p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); - -		// Show alert in middle of progress view (during teleport) (EXT-1093) -		LLProgressView* progress = gViewerWindow->getProgressView(); -		LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); -		mChannel.get()->updatePositionAndSize(rc); - -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); -	} -	else if (notify["sigtype"].asString() == "change") -	{ -		LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); -	} -	else -	{ -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->killToastByNotificationID(notification->getID()); +		const std::string name = LLHandlerUtil::getSubstitutionName(notification); + +		LLUUID from_id = notification->getPayload()["from_id"]; + +		// firstly create session... +		LLHandlerUtil::spawnIMSession(name, from_id); + +		// ...then log message to have IM Well notified about new message +		LLHandlerUtil::logToIMP2P(notification);  	} + +	LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); +	LLToast::Params p; +	p.notif_id = notification->getID(); +	p.notification = notification; +	p.panel = dynamic_cast<LLToastPanel*>(alert_dialog); +	p.enable_hide_btn = false; +	p.can_fade = false; +	p.is_modal = mIsModal; +	p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); + +	// Show alert in middle of progress view (during teleport) (EXT-1093) +	LLProgressView* progress = gViewerWindow->getProgressView(); +	LLRect rc = progress && progress->getVisible() ? progress->getRect() : gViewerWindow->getWorldViewRectScaled(); +	mChannel.get()->updatePositionAndSize(rc); + +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); +	  	return false;  } -//-------------------------------------------------------------------------- - -void LLAlertHandler::onDeleteToast(LLToast* toast) +void LLAlertHandler::onChange( LLNotificationPtr notification )  { +	LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog);  } - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index ad51389241..18cd94e685 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -37,15 +37,13 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLGroupHandler::LLGroupHandler(e_notification_type type, const LLSD& id) +LLGroupHandler::LLGroupHandler() +:	LLSysHandler("Group Notifications", "groupnotify")  { -	mType = type; -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{ -		channel->setOnRejectToastCallback(boost::bind(&LLGroupHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -64,72 +62,37 @@ void LLGroupHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLGroupHandler::processNotification(const LLSD& notify) +bool LLGroupHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{ -		LLHandlerUtil::logGroupNoticeToIMGroup(notification); +	LLHandlerUtil::logGroupNoticeToIMGroup(notification); -		LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); -		LLToast::Params p; -		p.notif_id = notification->getID(); -		p.notification = notification; -		p.panel = notify_box; -		p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); +	LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); +	LLToast::Params p; +	p.notif_id = notification->getID(); +	p.notification = notification; +	p.panel = notify_box; +	p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); -		// send a signal to the counter manager -		mNewNotificationSignal(); +	LLGroupActions::refresh_notices(); -		LLGroupActions::refresh_notices(); -	} -	else if (notify["sigtype"].asString() == "delete") -	{ -		mChannel.get()->killToastByNotificationID(notification->getID()); -	}  	return false;  } -//-------------------------------------------------------------------------- -void LLGroupHandler::onDeleteToast(LLToast* toast) -{ -	// send a signal to the counter manager -	mDelNotificationSignal(); - -	// send a signal to a listener to let him perform some action -	// in this case listener is a SysWellWindow and it will remove a corresponding item from its list -	mNotificationIDSignal(toast->getNotificationID()); -} - -//-------------------------------------------------------------------------- -void LLGroupHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); - -	if (notification && LLNotificationManager::getInstance()->getHandlerForNotification(notification->getType()) == this) -	{ -		LLNotifications::instance().cancel(notification); -	} -}  //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 3569ad6447..0899625242 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -30,7 +30,7 @@  #include "llwindow.h" -//#include "llnotificationsutil.h" +#include "llnotifications.h"  #include "llchannelmanager.h"  #include "llchat.h"  #include "llinstantmessage.h" @@ -40,20 +40,6 @@ class LLIMFloater;  namespace LLNotificationsUI  { -// ENotificationType enumerates all possible types of notifications that could be met -//  -typedef enum e_notification_type -{ -	NT_NOTIFY,  -	NT_NOTIFYTIP, -	NT_GROUPNOTIFY, -	NT_IMCHAT,  -	NT_GROUPCHAT,  -	NT_NEARBYCHAT,  -	NT_ALERT, -	NT_ALERTMODAL, -	NT_OFFER -} ENotificationType;  /**   * Handler of notification events. @@ -81,21 +67,8 @@ class LLEventHandler  public:  	virtual ~LLEventHandler() {}; -	// callbacks for counters -	typedef boost::function<void (void)> notification_callback_t; -	typedef boost::signals2::signal<void (void)> notification_signal_t; -	notification_signal_t mNewNotificationSignal; -	notification_signal_t mDelNotificationSignal; -	boost::signals2::connection setNewNotificationCallback(notification_callback_t cb) { return mNewNotificationSignal.connect(cb); } -	boost::signals2::connection setDelNotification(notification_callback_t cb) { return mDelNotificationSignal.connect(cb); } -	// callback for notification/toast -	typedef boost::function<void (const LLUUID id)> notification_id_callback_t; -	typedef boost::signals2::signal<void (const LLUUID id)> notification_id_signal_t; -	notification_id_signal_t mNotificationIDSignal; -	boost::signals2::connection setNotificationIDCallback(notification_id_callback_t cb) { return mNotificationIDSignal.connect(cb); } -  protected: -	virtual void onDeleteToast(LLToast* toast)=0; +	virtual void onDeleteToast(LLToast* toast) {}  	// arrange handler's channel on a screen  	// is necessary to unbind a moment of creation of a channel and a moment of positioning of it @@ -104,8 +77,6 @@ protected:  	virtual void initChannel()=0;  	LLHandle<LLScreenChannelBase>	mChannel; -	e_notification_type				mType; -  };  // LLSysHandler and LLChatHandler are more specific base classes @@ -115,20 +86,18 @@ protected:  /**   * Handler for system notifications.   */ -class LLSysHandler : public LLEventHandler +class LLSysHandler : public LLEventHandler, public LLNotificationChannel  {  public: -	LLSysHandler(); +	LLSysHandler(const std::string& name, const std::string& notification_type);  	virtual ~LLSysHandler() {}; -	virtual bool processNotification(const LLSD& notify)=0; - -protected : -	static void init(); -	void removeExclusiveNotifications(const LLNotificationPtr& notif); +	// base interface functions +	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onDelete(LLNotificationPtr p) { if (mChannel.get()) mChannel.get()->removeToastByNotificationID(p->getID());} -	typedef std::list< std::set<std::string> > exclusive_notif_sets; -	static exclusive_notif_sets sExclusiveNotificationGroups; +	virtual bool processNotification(const LLNotificationPtr& notify)=0;  };  /** @@ -149,15 +118,12 @@ public:  class LLIMHandler : public LLSysHandler  {  public: -	LLIMHandler(e_notification_type type, const LLSD& id); +	LLIMHandler();  	virtual ~LLIMHandler(); -	// base interface functions -	virtual bool processNotification(const LLSD& notify); -  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void initChannel(); +	bool processNotification(const LLNotificationPtr& p); +	/*virtual*/ void initChannel();  };  /** @@ -167,16 +133,15 @@ protected:  class LLTipHandler : public LLSysHandler  {  public: -	LLTipHandler(e_notification_type type, const LLSD& id); +	LLTipHandler();  	virtual ~LLTipHandler();  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void onRejectToast(const LLUUID& id); -	virtual void initChannel(); +	/*virtual*/ void initChannel();  };  /** @@ -186,18 +151,16 @@ protected:  class LLScriptHandler : public LLSysHandler  {  public: -	LLScriptHandler(e_notification_type type, const LLSD& id); +	LLScriptHandler();  	virtual ~LLScriptHandler(); +	/*virtual*/ void onDelete(LLNotificationPtr p);  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id); +	/*virtual*/ void onDeleteToast(LLToast* toast); +	/*virtual*/ void initChannel();  }; @@ -207,18 +170,15 @@ protected:  class LLGroupHandler : public LLSysHandler  {  public: -	LLGroupHandler(e_notification_type type, const LLSD& id); +	LLGroupHandler();  	virtual ~LLGroupHandler();  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast);  	virtual void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id);  };  /** @@ -227,16 +187,14 @@ protected:  class LLAlertHandler : public LLSysHandler  {  public: -	LLAlertHandler(e_notification_type type, const LLSD& id); +	LLAlertHandler(const std::string& name, const std::string& notification_type, bool is_modal);  	virtual ~LLAlertHandler(); -	void setAlertMode(bool is_modal) { mIsModal = is_modal; } - -	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p); +	/*virtual*/ void onLoad(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast);  	virtual void initChannel();  	bool	mIsModal; @@ -249,102 +207,71 @@ protected:  class LLOfferHandler : public LLSysHandler  {  public: -	LLOfferHandler(e_notification_type type, const LLSD& id); +	LLOfferHandler();  	virtual ~LLOfferHandler();  	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onChange(LLNotificationPtr p); +	/*virtual*/ void onDelete(LLNotificationPtr notification); +	/*virtual*/ bool processNotification(const LLNotificationPtr& p);  protected: -	virtual void onDeleteToast(LLToast* toast); -	virtual void initChannel(); - -	// own handlers -	void onRejectToast(LLUUID& id); +	/*virtual*/ void initChannel();  };  /**   * Handler for UI hints.   */ -class LLHintHandler : public LLSingleton<LLHintHandler> +class LLHintHandler : public LLNotificationChannel  {  public: -	LLHintHandler(); -	virtual ~LLHintHandler(); +	LLHintHandler() : LLNotificationChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint")) +	{} +	virtual ~LLHintHandler() {} -	// base interface functions -	virtual bool processNotification(const LLSD& notify); +	/*virtual*/ void onAdd(LLNotificationPtr p); +	/*virtual*/ void onLoad(LLNotificationPtr p); +	/*virtual*/ void onDelete(LLNotificationPtr p);  };  /**   * Handler for browser notifications   */ -class LLBrowserNotification : public LLSingleton<LLBrowserNotification> +class LLBrowserNotification : public LLNotificationChannel  {  public: -	virtual bool processNotification(const LLSD& notify); +	LLBrowserNotification() +	: LLNotificationChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")) +	{} +	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onChange(LLNotificationPtr p) { processNotification(p); } +	bool processNotification(const LLNotificationPtr& p);  };  /**   * Handler for outbox notifications   */ -class LLOutboxNotification : public LLSingleton<LLOutboxNotification> +class LLOutboxNotification : public LLNotificationChannel  {  public: -	virtual bool processNotification(const LLSD& notify); +	LLOutboxNotification() +	:	LLNotificationChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")) +	{} +	/*virtual*/ void onAdd(LLNotificationPtr p) { processNotification(p); } +	/*virtual*/ void onChange(LLNotificationPtr p) { } +	/*virtual*/ void onDelete(LLNotificationPtr p); +	bool processNotification(const LLNotificationPtr& p);  };  class LLHandlerUtil  {  public:  	/** -	 * Checks sufficient conditions to log notification message to IM session. -	 */ -	static bool canLogToIM(const LLNotificationPtr& notification); - -	/** -	 * Checks sufficient conditions to log notification message to nearby chat session. -	 */ -	static bool canLogToNearbyChat(const LLNotificationPtr& notification); - -	/** -	 * Checks sufficient conditions to spawn IM session. -	 */ -	static bool canSpawnIMSession(const LLNotificationPtr& notification); - -	/** -	 * Checks sufficient conditions to add notification toast panel IM floater. -	 */ -	static bool canAddNotifPanelToIM(const LLNotificationPtr& notification); - -	/** -	 * Checks whether notification can be used multiple times or not. -	 */ -	static bool isNotificationReusable(const LLNotificationPtr& notification); - -	/** -	 * Checks if passed notification can create IM session and be written into it. -	 * -	 * This method uses canLogToIM() & canSpawnIMSession(). -	 */ -	static bool canSpawnSessionAndLogToIM(const LLNotificationPtr& notification); - -	/** -	 * Checks if passed notification can create toast. -	 */ -	static bool canSpawnToast(const LLNotificationPtr& notification); - -	/**  	 * Determines whether IM floater is opened.  	 */  	static bool isIMFloaterOpened(const LLNotificationPtr& notification);  	/** -	* Determines whether IM floater is focused. -	*/ -	static bool isIMFloaterFocused(const LLNotificationPtr& notification); - -	/**  	 * Writes notification message to IM session.  	 */  	static void logToIM(const EInstantMessage& session_type, @@ -355,12 +282,7 @@ public:  	/**  	 * Writes notification message to IM  p2p session.  	 */ -	static void logToIMP2P(const LLNotificationPtr& notification); - -	/** -	 * Writes notification message to IM  p2p session. -	 */ -	static void logToIMP2P(const LLNotificationPtr& notification, bool to_file_only); +	static void logToIMP2P(const LLNotificationPtr& notification, bool to_file_only = false);  	/**  	 * Writes group notice notification message to IM  group session. @@ -406,13 +328,6 @@ public:  	 */  	static void decIMMesageCounter(const LLNotificationPtr& notification); -private: - -	/** -	 * Find IM floater based on "from_id" -	 */ -	static LLIMFloater* findIMFloater(const LLNotificationPtr& notification); -  };  } diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 7c6287967a..cba22b233b 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -41,200 +41,19 @@  using namespace LLNotificationsUI; -// static -std::list< std::set<std::string> > LLSysHandler::sExclusiveNotificationGroups; - -// static -void LLSysHandler::init() -{ -	std::set<std::string> online_offline_group; -	online_offline_group.insert("FriendOnline"); -	online_offline_group.insert("FriendOffline"); - -	sExclusiveNotificationGroups.push_back(online_offline_group); -} - -LLSysHandler::LLSysHandler() -{ -	if(sExclusiveNotificationGroups.empty()) -	{ -		init(); -	} -} - -void LLSysHandler::removeExclusiveNotifications(const LLNotificationPtr& notif) -{ -	LLScreenChannel* channel = dynamic_cast<LLScreenChannel *>(mChannel.get()); -	if (channel == NULL) -	{ -		return; -	} - -	class ExclusiveMatcher: public LLScreenChannel::Matcher -	{ -	public: -		ExclusiveMatcher(const std::set<std::string>& excl_group, -				const std::string& from_name) : -			mExclGroup(excl_group), mFromName(from_name) -		{ -		} -		bool matches(const LLNotificationPtr notification) const -		{ -			for (std::set<std::string>::const_iterator it = mExclGroup.begin(); it -					!= mExclGroup.end(); it++) -			{ -				std::string from_name = LLHandlerUtil::getSubstitutionName(notification); -				if (notification->getName() == *it && from_name == mFromName) -				{ -					return true; -				} -			} -			return false; -		} -	private: -		const std::set<std::string>& mExclGroup; -		const std::string& mFromName; -	}; - - -	for (exclusive_notif_sets::iterator it = sExclusiveNotificationGroups.begin(); it -			!= sExclusiveNotificationGroups.end(); it++) -	{ -		std::set<std::string> group = *it; -		std::set<std::string>::iterator g_it = group.find(notif->getName()); -		if (g_it != group.end()) -		{ -			channel->killMatchedToasts(ExclusiveMatcher(group, -					LLHandlerUtil::getSubstitutionName(notif))); -		} -	} -} - -const static std::string GRANTED_MODIFY_RIGHTS("GrantedModifyRights"), -		REVOKED_MODIFY_RIGHTS("RevokedModifyRights"), -		OBJECT_GIVE_ITEM("ObjectGiveItem"), -		OBJECT_GIVE_ITEM_UNKNOWN_USER("ObjectGiveItemUnknownUser"), -						PAYMENT_RECEIVED("PaymentReceived"), -						PAYMENT_SENT("PaymentSent"), -						ADD_FRIEND_WITH_MESSAGE("AddFriendWithMessage"), -						USER_GIVE_ITEM("UserGiveItem"), -						INVENTORY_ACCEPTED("InventoryAccepted"), -						INVENTORY_DECLINED("InventoryDeclined"), -						OFFER_FRIENDSHIP("OfferFriendship"), -						FRIENDSHIP_ACCEPTED("FriendshipAccepted"), -						FRIENDSHIP_OFFERED("FriendshipOffered"), -						FRIENDSHIP_ACCEPTED_BYME("FriendshipAcceptedByMe"), -						FRIENDSHIP_DECLINED_BYME("FriendshipDeclinedByMe"), -						FRIEND_ONLINE("FriendOnline"), FRIEND_OFFLINE("FriendOffline"), -						SERVER_OBJECT_MESSAGE("ServerObjectMessage"), -						TELEPORT_OFFERED("TeleportOffered"), -						TELEPORT_OFFER_SENT("TeleportOfferSent"), -						IM_SYSTEM_MESSAGE_TIP("IMSystemMessageTip"); - +LLSysHandler::LLSysHandler(const std::string& name, const std::string& notification_type) +:	LLNotificationChannel(name, "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, notification_type)) +{}  // static -bool LLHandlerUtil::canLogToIM(const LLNotificationPtr& notification) -{ -	return GRANTED_MODIFY_RIGHTS == notification->getName() -			|| REVOKED_MODIFY_RIGHTS == notification->getName() -			|| PAYMENT_RECEIVED == notification->getName() -			|| PAYMENT_SENT == notification->getName() -			|| OFFER_FRIENDSHIP == notification->getName() -			|| FRIENDSHIP_OFFERED == notification->getName() -			|| FRIENDSHIP_ACCEPTED == notification->getName() -			|| FRIENDSHIP_ACCEPTED_BYME == notification->getName() -			|| FRIENDSHIP_DECLINED_BYME == notification->getName() -			|| SERVER_OBJECT_MESSAGE == notification->getName() -			|| INVENTORY_ACCEPTED == notification->getName() -			|| INVENTORY_DECLINED == notification->getName() -			|| USER_GIVE_ITEM == notification->getName() -			|| TELEPORT_OFFERED == notification->getName() -			|| TELEPORT_OFFER_SENT == notification->getName() -			|| IM_SYSTEM_MESSAGE_TIP == notification->getName(); -} - -// static -bool LLHandlerUtil::canLogToNearbyChat(const LLNotificationPtr& notification) -{ -	return notification->getType() == "notifytip" -			&&  FRIEND_ONLINE != notification->getName() -			&& FRIEND_OFFLINE != notification->getName() -			&& INVENTORY_ACCEPTED != notification->getName() -			&& INVENTORY_DECLINED != notification->getName() -			&& IM_SYSTEM_MESSAGE_TIP != notification->getName(); -} - -// static -bool LLHandlerUtil::canSpawnIMSession(const LLNotificationPtr& notification) -{ -	return OFFER_FRIENDSHIP == notification->getName() -			|| USER_GIVE_ITEM == notification->getName() -			|| TELEPORT_OFFERED == notification->getName(); -} - -// static -bool LLHandlerUtil::canAddNotifPanelToIM(const LLNotificationPtr& notification) -{ -	return OFFER_FRIENDSHIP == notification->getName() -					|| USER_GIVE_ITEM == notification->getName() -					|| TELEPORT_OFFERED == notification->getName(); -} - -// static -bool LLHandlerUtil::isNotificationReusable(const LLNotificationPtr& notification) -{ -	return OFFER_FRIENDSHIP == notification->getName() -		|| USER_GIVE_ITEM == notification->getName() -		|| TELEPORT_OFFERED == notification->getName(); -} - -// static -bool LLHandlerUtil::canSpawnSessionAndLogToIM(const LLNotificationPtr& notification) -{ -	return canLogToIM(notification) && canSpawnIMSession(notification); -} - -// static -bool LLHandlerUtil::canSpawnToast(const LLNotificationPtr& notification) +bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification)  { -	if(INVENTORY_DECLINED == notification->getName()  -		|| INVENTORY_ACCEPTED == notification->getName()) -	{ -		// return false for inventory accepted/declined notifications if respective IM window is open (EXT-5909) -		return ! isIMFloaterOpened(notification); -	} - -	if(FRIENDSHIP_ACCEPTED == notification->getName()) -	{ -		// don't show FRIENDSHIP_ACCEPTED if IM window is opened and focused - EXT-6441 -		return ! isIMFloaterFocused(notification); -	} - -	if(OFFER_FRIENDSHIP == notification->getName() -		|| USER_GIVE_ITEM == notification->getName() -		|| TELEPORT_OFFERED == notification->getName()) -	{ -		// When ANY offer arrives, show toast, unless IM window is already open - EXT-5904 -		return ! isIMFloaterOpened(notification); -	} - -	return true; -} +	bool res = false; -// static -LLIMFloater* LLHandlerUtil::findIMFloater(const LLNotificationPtr& notification) -{  	LLUUID from_id = notification->getPayload()["from_id"];  	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); -	return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -} - -// static -bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification) -{ -	bool res = false; +	LLIMFloater* im_floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id); -	LLIMFloater* im_floater = findIMFloater(notification);  	if (im_floater != NULL)  	{  		res = im_floater->getVisible() == TRUE; @@ -243,19 +62,6 @@ bool LLHandlerUtil::isIMFloaterOpened(const LLNotificationPtr& notification)  	return res;  } -bool LLHandlerUtil::isIMFloaterFocused(const LLNotificationPtr& notification) -{ -	bool res = false; - -	LLIMFloater* im_floater = findIMFloater(notification); -	if (im_floater != NULL) -	{ -		res = im_floater->hasFocus() == TRUE; -	} - -	return res; -} -  // static  void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  		const std::string& session_name, const std::string& from_name, @@ -317,12 +123,6 @@ void LLHandlerUtil::logToIM(const EInstantMessage& session_type,  	}  } -// static -void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification) -{ -	logToIMP2P(notification, false); -} -  void log_name_callback(const std::string& full_name, const std::string& from_name,   					   const std::string& message, const LLUUID& from_id) @@ -334,9 +134,6 @@ void log_name_callback(const std::string& full_name, const std::string& from_nam  // static  void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_file_only)  { -	// don't create IM p2p session with objects, it's necessary condition to log -	if (notification->getName() != OBJECT_GIVE_ITEM) -	{  		LLUUID from_id = notification->getPayload()["from_id"];  		if (from_id.isNull()) @@ -354,7 +151,6 @@ void LLHandlerUtil::logToIMP2P(const LLNotificationPtr& notification, bool to_fi  			gCacheName->get(from_id, false, boost::bind(&log_name_callback, _2, INTERACTIVE_SYSTEM_FROM, notification->getMessage(), from_id));  		}  	} -}  // static  void LLHandlerUtil::logGroupNoticeToIMGroup( @@ -489,14 +285,10 @@ void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification)  	LLUUID from_id = notification->getPayload()["from_id"];  	LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, from_id); -	LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession( -			session_id); +	LLIMModel::LLIMSession * session = LLIMModel::getInstance()->findIMSession(session_id); -	if (session == NULL) +	if (session)  	{ -		return; -	} -  	LLSD arg;  	arg["session_id"] = session_id;  	session->mNumUnread--; @@ -505,3 +297,5 @@ void LLHandlerUtil::decIMMesageCounter(const LLNotificationPtr& notification)  	arg["participant_unread"] = session->mParticipantUnreadMessageCount;  	LLIMModel::getInstance()->mNewMsgSignal(arg);  } +} + diff --git a/indra/newview/llnotificationhinthandler.cpp b/indra/newview/llnotificationhinthandler.cpp index f7163cb04f..271f418507 100644 --- a/indra/newview/llnotificationhinthandler.cpp +++ b/indra/newview/llnotificationhinthandler.cpp @@ -33,26 +33,6 @@  using namespace LLNotificationsUI; -LLHintHandler::LLHintHandler() -{ -} - -LLHintHandler::~LLHintHandler() -{ -} - -bool LLHintHandler::processNotification(const LLSD& notify) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	std::string sigtype = notify["sigtype"].asString(); -	if (sigtype == "add" || sigtype == "load") -	{ -		LLHints::show(notification); -	} -	else if (sigtype == "delete") -	{ -		LLHints::hide(notification); -	} -	return false; -} +void LLHintHandler::onAdd(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onLoad(LLNotificationPtr p) { LLHints::show(p); } +void LLHintHandler::onDelete(LLNotificationPtr p) { LLHints::hide(p); } diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index f792f53ac5..2862ad6962 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -42,107 +42,35 @@ using namespace LLNotificationsUI;  //--------------------------------------------------------------------------  LLNotificationManager::LLNotificationManager()  { -	mNotifyHandlers.clear();  	init();  }  //--------------------------------------------------------------------------  LLNotificationManager::~LLNotificationManager()  { -	BOOST_FOREACH(listener_pair_t& pair, mChannelListeners) -	{ -		pair.second.disconnect(); -	}  }  //--------------------------------------------------------------------------  void LLNotificationManager::init()  { -	LLNotificationChannel::buildChannel("Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notify")); -	LLNotificationChannel::buildChannel("NotificationTips", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytip")); -	LLNotificationChannel::buildChannel("Group Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "groupnotify")); -	LLNotificationChannel::buildChannel("Alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); -	LLNotificationChannel::buildChannel("AlertModal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); -	LLNotificationChannel::buildChannel("IM Notifications", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "notifytoast")); -	LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "offer")); -	LLNotificationChannel::buildChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint")); -	LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")); -	LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")); +	mChannels.push_back(new LLScriptHandler()); +	mChannels.push_back(new LLTipHandler()); +	mChannels.push_back(new LLGroupHandler()); +	mChannels.push_back(new LLAlertHandler("Alerts", "alert", false)); +	mChannels.push_back(new LLAlertHandler("AlertModal", "alertmodal", true)); +	mChannels.push_back(new LLOfferHandler()); +	mChannels.push_back(new LLHintHandler()); +	mChannels.push_back(new LLBrowserNotification()); +	mChannels.push_back(new LLOutboxNotification()); +	mChannels.push_back(new LLIMHandler()); -	mChannelListeners["Notifications"] = LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["NotificationTips"] = LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Group Notifications"] = LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Alerts"] = LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["AlertModal"] = LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["IM Notifications"] = LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Offer"] = LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	mChannelListeners["Hints"] = LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); -	mChannelListeners["Browser"] = LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); -	mChannelListeners["Outbox"] = LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1)); - -	mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD())); -	mNotifyHandlers["notifytip"] =  boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD())); -	mNotifyHandlers["groupnotify"] = boost::shared_ptr<LLEventHandler>(new LLGroupHandler(NT_GROUPNOTIFY, LLSD())); -	mNotifyHandlers["alert"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD())); -	mNotifyHandlers["alertmodal"] = boost::shared_ptr<LLEventHandler>(new LLAlertHandler(NT_ALERT, LLSD())); -	static_cast<LLAlertHandler*>(mNotifyHandlers["alertmodal"].get())->setAlertMode(true); -	mNotifyHandlers["notifytoast"] = boost::shared_ptr<LLEventHandler>(new LLIMHandler(NT_IMCHAT, LLSD())); -	 -	mNotifyHandlers["nearbychat"] = boost::shared_ptr<LLEventHandler>(new LLNearbyChatHandler(NT_NEARBYCHAT, LLSD())); -	mNotifyHandlers["offer"] = boost::shared_ptr<LLEventHandler>(new LLOfferHandler(NT_OFFER, LLSD())); -} - -//-------------------------------------------------------------------------- -bool LLNotificationManager::onNotification(const LLSD& notify) -{ -	LLSysHandler* handle = NULL; - -	if (LLNotifications::destroyed()) -		return false; - -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); -	 -	if (!notification)  -		return false; - -	std::string notification_type = notification->getType(); -	handle = static_cast<LLSysHandler*>(mNotifyHandlers[notification_type].get()); - -	if(!handle) -		return false; -	 -	return handle->processNotification(notify); +	mChatHandler = boost::shared_ptr<LLNearbyChatHandler>(new LLNearbyChatHandler());  }  //--------------------------------------------------------------------------  void LLNotificationManager::onChat(const LLChat& msg, const LLSD &args)  { -	// check ENotificationType argument -	switch(args["type"].asInteger()) -	{ -	case NT_NEARBYCHAT: -		{ -			LLNearbyChatHandler* handle = dynamic_cast<LLNearbyChatHandler*>(mNotifyHandlers["nearbychat"].get()); - -			if(handle) -				handle->processChat(msg, args); -		} -		break; -	default: 	//no need to handle all enum types -		break; -	} -} - -//-------------------------------------------------------------------------- -LLEventHandler* LLNotificationManager::getHandlerForNotification(std::string notification_type)  -{  -	std::map<std::string, boost::shared_ptr<LLEventHandler> >::iterator it = mNotifyHandlers.find(notification_type); - -	if(it != mNotifyHandlers.end()) -		return (*it).second.get(); - -	return NULL; +	if(mChatHandler) +		mChatHandler->processChat(msg, args);  } -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index 27b6ba1c71..c8afdf9e46 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -28,8 +28,6 @@  #ifndef LL_LLNOTIFICATIONMANAGER_H  #define LL_LLNOTIFICATIONMANAGER_H -#include "llevents.h" -  #include "lluictrl.h"  #include "llnotificationhandler.h" @@ -49,7 +47,6 @@ class LLToast;  class LLNotificationManager : public LLSingleton<LLNotificationManager>  {  	typedef std::pair<std::string, LLEventHandler*> eventhandlers; -	typedef std::pair<const std::string, LLBoundListener> listener_pair_t;  public:	  	LLNotificationManager();	  	virtual ~LLNotificationManager(); @@ -59,22 +56,12 @@ public:  	void init(void);  	//TODO: combine processing and storage (*) -	// this method reacts on system notifications and calls an appropriate handler -	bool onNotification(const LLSD& notification); -  	// this method reacts on chat notifications and calls an appropriate handler  	void onChat(const LLChat& msg, const LLSD &args); -	// get a handler for a certain type of notification -	LLEventHandler* getHandlerForNotification(std::string notification_type); - -  private: -	//TODO (*) -	std::map<std::string, boost::shared_ptr<LLEventHandler> > mNotifyHandlers; -	// cruft std::map<std::string, LLChatHandler*> mChatHandlers; - -	std::map<std::string, LLBoundListener> mChannelListeners; +	boost::shared_ptr<class LLNearbyChatHandler> mChatHandler; +	std::vector<LLNotificationChannelPtr> mChannels;  };  } diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 1552ed3346..6e641575fa 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -40,16 +40,14 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLOfferHandler::LLOfferHandler(e_notification_type type, const LLSD& id) +LLOfferHandler::LLOfferHandler() +:	LLSysHandler("Offer", "offer")  { -	mType = type; -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{  		channel->setControlHovering(true); -		channel->setOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -68,147 +66,109 @@ void LLOfferHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLOfferHandler::processNotification(const LLSD& notify) +bool LLOfferHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{ +	if( notification->getPayload().has("give_inventory_notification") +		&& notification->getPayload()["give_inventory_notification"].asBoolean() == false) +	{ +		// This is an original inventory offer, so add a script floater +		LLScriptFloaterManager::instance().onAddNotification(notification->getID()); +	} +	else +	{ +		bool add_notif_to_im = notification->canLogToIM() && notification->hasFormElements(); -		if( notification->getPayload().has("give_inventory_notification") -			&& !notification->getPayload()["give_inventory_notification"] ) +		if (add_notif_to_im)  		{ -			// This is an original inventory offer, so add a script floater -			LLScriptFloaterManager::instance().onAddNotification(notification->getID()); +			const std::string name = LLHandlerUtil::getSubstitutionName(notification); + +			LLUUID from_id = notification->getPayload()["from_id"]; + +			LLHandlerUtil::spawnIMSession(name, from_id); +			LLHandlerUtil::addNotifPanelToIM(notification);  		} -		else + +		if (!notification->canShowToast())  		{ -			notification->setReusable(LLHandlerUtil::isNotificationReusable(notification)); - -			LLUUID session_id; -			if (LLHandlerUtil::canSpawnIMSession(notification)) -			{ -				const std::string name = LLHandlerUtil::getSubstitutionName(notification); - -				LLUUID from_id = notification->getPayload()["from_id"]; - -				session_id = LLHandlerUtil::spawnIMSession(name, from_id); -			} - -			bool show_toast = LLHandlerUtil::canSpawnToast(notification); -			bool add_notid_to_im = LLHandlerUtil::canAddNotifPanelToIM(notification); -			if (add_notid_to_im) -			{ -				LLHandlerUtil::addNotifPanelToIM(notification); -			} - -			if (notification->getPayload().has("SUPPRESS_TOAST") -						&& notification->getPayload()["SUPPRESS_TOAST"]) -			{ -				LLNotificationsUtil::cancel(notification); -			} -			else if(show_toast) -			{ -				LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); -				// don't close notification on panel destroy since it will be used by IM floater -				notify_box->setCloseNotificationOnDestroy(!add_notid_to_im); -				LLToast::Params p; -				p.notif_id = notification->getID(); -				p.notification = notification; -				p.panel = notify_box; -				p.on_delete_toast = boost::bind(&LLOfferHandler::onDeleteToast, this, _1); -				// we not save offer notifications to the syswell floater that should be added to the IM floater -				p.can_be_stored = !add_notid_to_im; - -				LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -				if(channel) -					channel->addToast(p); - -				// if we not add notification to IM - add it to notification well -				if (!add_notid_to_im) -				{ -					// send a signal to the counter manager -					mNewNotificationSignal(); -				} -			} - -			if (LLHandlerUtil::canLogToIM(notification)) -			{ -				// log only to file if notif panel can be embedded to IM and IM is opened -				if (add_notid_to_im && LLHandlerUtil::isIMFloaterOpened(notification)) -				{ -					LLHandlerUtil::logToIMP2P(notification, true); -				} -				else -				{ -					LLHandlerUtil::logToIMP2P(notification); -				} -			} +			LLNotificationsUtil::cancel(notification);  		} -	} -	else if (notify["sigtype"].asString() == "delete") -	{ -		if( notification->getPayload().has("give_inventory_notification") -			&& !notification->getPayload()["give_inventory_notification"] ) +		else if(!notification->canLogToIM() || !LLHandlerUtil::isIMFloaterOpened(notification))  		{ -			// Remove original inventory offer script floater -			LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); +			LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); +			LLToast::Params p; +			p.notif_id = notification->getID(); +			p.notification = notification; +			p.panel = notify_box; +			// we not save offer notifications to the syswell floater that should be added to the IM floater +			p.can_be_stored = !add_notif_to_im; + +			LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +			if(channel) +				channel->addToast(p);  		} -		else + +		if (notification->canLogToIM())  		{ -			if (LLHandlerUtil::canAddNotifPanelToIM(notification) -					&& !LLHandlerUtil::isIMFloaterOpened(notification)) -			{ -				LLHandlerUtil::decIMMesageCounter(notification); -			} -			mChannel.get()->killToastByNotificationID(notification->getID()); +			// log only to file if notif panel can be embedded to IM and IM is opened +			bool file_only = add_notif_to_im && LLHandlerUtil::isIMFloaterOpened(notification); +			LLHandlerUtil::logToIMP2P(notification, file_only);  		}  	}  	return false;  } -//-------------------------------------------------------------------------- - -void LLOfferHandler::onDeleteToast(LLToast* toast) +/*virtual*/ void LLOfferHandler::onChange(LLNotificationPtr p)  { -	if (!LLHandlerUtil::canAddNotifPanelToIM(toast->getNotification())) +	LLToastNotifyPanel* panelp = LLToastNotifyPanel::getInstance(p->getID()); +	if (panelp)  	{ -		// send a signal to the counter manager -		mDelNotificationSignal(); +		// +		// HACK: if we're dealing with a notification embedded in IM, update it +		// otherwise remove its toast +		// +		if (dynamic_cast<LLIMToastNotifyPanel*>(panelp)) +		{ +			panelp->updateNotification(); +		} +		else +		{ +			// if notification has changed, hide it +			mChannel.get()->removeToastByNotificationID(p->getID()); +		}  	} - -	// send a signal to a listener to let him perform some action -	// in this case listener is a SysWellWindow and it will remove a corresponding item from its list -	mNotificationIDSignal(toast->getNotificationID());  } -//-------------------------------------------------------------------------- -void LLOfferHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); -	if (notification -			&& LLNotificationManager::getInstance()->getHandlerForNotification( -					notification->getType()) == this -					// don't delete notification since it may be used by IM floater -					&& !LLHandlerUtil::canAddNotifPanelToIM(notification)) +/*virtual*/ void LLOfferHandler::onDelete(LLNotificationPtr notification) +{ +	if( notification->getPayload().has("give_inventory_notification") +		&& !notification->getPayload()["give_inventory_notification"] ) +	{ +		// Remove original inventory offer script floater +		LLScriptFloaterManager::instance().onRemoveNotification(notification->getID()); +	} +	else  	{ -		LLNotifications::instance().cancel(notification); +		if (notification->canLogToIM()  +			&& notification->hasFormElements() +			&& !LLHandlerUtil::isIMFloaterOpened(notification)) +		{ +			LLHandlerUtil::decIMMesageCounter(notification); +		} +		mChannel.get()->removeToastByNotificationID(notification->getID());  	}  } + diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 995915206b..9f7d0cc2f5 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -37,21 +37,15 @@  using namespace LLNotificationsUI; -static const std::string SCRIPT_DIALOG				("ScriptDialog"); -static const std::string SCRIPT_DIALOG_GROUP		("ScriptDialogGroup"); -static const std::string SCRIPT_LOAD_URL			("LoadWebPage"); -  //-------------------------------------------------------------------------- -LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id) +LLScriptHandler::LLScriptHandler() +:	LLSysHandler("Notifications", "notify")  { -	mType = type; -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{  		channel->setControlHovering(true); -		channel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -70,32 +64,25 @@ void LLScriptHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLScriptHandler::processNotification(const LLSD& notify) +bool LLScriptHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false; -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add") -	{ -		if (LLHandlerUtil::canLogToIM(notification)) +	if (notification->canLogToIM())  		{  			LLHandlerUtil::logToIMP2P(notification);  		} -		if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) +	if(notification->hasFormElements())  		{  			LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID());  		} @@ -114,60 +101,39 @@ bool LLScriptHandler::processNotification(const LLSD& notify)  			{  				channel->addToast(p);  			} +	} -			// send a signal to the counter manager -			mNewNotificationSignal(); +	return false;  		} -	} -	else if (notify["sigtype"].asString() == "delete") + + +void LLScriptHandler::onDelete( LLNotificationPtr notification )  	{ -		if(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName() || SCRIPT_LOAD_URL == notification->getName()) +	if(notification->hasFormElements())  		{  			LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());  		}  		else  		{ -			mChannel.get()->killToastByNotificationID(notification->getID()); +			mChannel.get()->removeToastByNotificationID(notification->getID());  		}  	} -	return false; -} +  //--------------------------------------------------------------------------  void LLScriptHandler::onDeleteToast(LLToast* toast)  { -	// send a signal to the counter manager -	mDelNotificationSignal(); -  	// send a signal to a listener to let him perform some action  	// in this case listener is a SysWellWindow and it will remove a corresponding item from its list -	mNotificationIDSignal(toast->getNotificationID()); -  	LLNotificationPtr notification = LLNotifications::getInstance()->find(toast->getNotificationID()); -	if( notification &&  -		(SCRIPT_DIALOG == notification->getName() || SCRIPT_DIALOG_GROUP == notification->getName()) ) +	if( notification && notification->hasFormElements())  	{  		LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID());  	}  } -//-------------------------------------------------------------------------- -void LLScriptHandler::onRejectToast(LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); - -	if (notification -			&& LLNotificationManager::getInstance()->getHandlerForNotification( -					notification->getType()) == this) -	{ -		LLNotifications::instance().cancel(notification); -	} -} - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationstorage.cpp b/indra/newview/llnotificationstorage.cpp index fb1adc7ddf..a31b95811e 100644 --- a/indra/newview/llnotificationstorage.cpp +++ b/indra/newview/llnotificationstorage.cpp @@ -84,9 +84,11 @@ bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& pay  	return false;  } +static LLFastTimer::DeclareTimer FTM_SAVE_NOTIFICATIONS("Save Notifications"); +  void LLPersistentNotificationStorage::saveNotifications()  { -	// TODO - think about save optimization. +	LLFastTimer _(FTM_SAVE_NOTIFICATIONS);  	llofstream notify_file(mFileName.c_str());  	if (!notify_file.is_open()) @@ -98,10 +100,15 @@ void LLPersistentNotificationStorage::saveNotifications()  	LLSD output;  	LLSD& data = output["data"]; -	LLNotificationChannelPtr history_channel = LLNotifications::instance().getChannel("Persistent"); -	LLNotificationSet::iterator it = history_channel->begin(); +	boost::intrusive_ptr<LLPersistentNotificationChannel> history_channel = boost::dynamic_pointer_cast<LLPersistentNotificationChannel>(LLNotifications::instance().getChannel("Persistent")); +	if (!history_channel) +	{ +		return; +	} -	for ( ; history_channel->end() != it; ++it) +	for ( std::vector<LLNotificationPtr>::iterator it = history_channel->beginHistory(), end_it = history_channel->endHistory(); +		it != end_it; +		++it)  	{  		LLNotificationPtr notification = *it; @@ -120,8 +127,11 @@ void LLPersistentNotificationStorage::saveNotifications()  	formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY);  } +static LLFastTimer::DeclareTimer FTM_LOAD_NOTIFICATIONS("Load Notifications"); +  void LLPersistentNotificationStorage::loadNotifications()  { +	LLFastTimer _(FTM_LOAD_NOTIFICATIONS);  	LLResponderRegistry::registerResponders();  	LLNotifications::instance().getChannel("Persistent")-> diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index e397cfa046..507c6686fd 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -29,7 +29,7 @@  #include "llfloaterreg.h"  #include "llnearbychat.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llnotificationhandler.h"  #include "llnotifications.h"  #include "lltoastnotifypanel.h" @@ -41,15 +41,13 @@  using namespace LLNotificationsUI;  //-------------------------------------------------------------------------- -LLTipHandler::LLTipHandler(e_notification_type type, const LLSD& id) +LLTipHandler::LLTipHandler() +:	LLSysHandler("NotificationTips", "notifytip")  { -	mType = type;	 -  	// Getting a Channel for our notifications  	LLScreenChannel* channel = LLChannelManager::getInstance()->createNotificationChannel();  	if(channel)  	{ -		channel->setOnRejectToastCallback(boost::bind(&LLTipHandler::onRejectToast, this, _1));  		mChannel = channel->getHandle();  	}  } @@ -68,102 +66,67 @@ void LLTipHandler::initChannel()  }  //-------------------------------------------------------------------------- -bool LLTipHandler::processNotification(const LLSD& notify) +bool LLTipHandler::processNotification(const LLNotificationPtr& notification)  {  	if(mChannel.isDead())  	{  		return false;  	} -	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); - -	if(!notification) -		return false;	 -  	// arrange a channel on a screen  	if(!mChannel.get()->getVisible())  	{  		initChannel();  	} -	if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") -	{  		// archive message in nearby chat -		if (LLHandlerUtil::canLogToNearbyChat(notification)) -		{ -			LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); - -			// don't show toast if Nearby Chat is opened -			LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); -			LLNearbyChatBar* nearby_chat_bar = LLNearbyChatBar::getInstance(); -			if (!nearby_chat_bar->isMinimized() && nearby_chat_bar->getVisible() && nearby_chat->getVisible()) -			{ -				return false; -			} -		} - -		std::string session_name = notification->getPayload()["SESSION_NAME"]; -		const std::string name = notification->getSubstitutions()["NAME"]; -		if (session_name.empty()) -		{ -			session_name = name; -		} -		LLUUID from_id = notification->getPayload()["from_id"]; -		if (LLHandlerUtil::canLogToIM(notification)) -		{ -			LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, -					notification->getMessage(), from_id, from_id); -		} - -		if (LLHandlerUtil::canSpawnIMSession(notification)) -		{ -			LLHandlerUtil::spawnIMSession(name, from_id); -		} +	if (notification->canLogToChat()) +	{ +		LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); -		// don't spawn toast for inventory accepted/declined offers if respective IM window is open (EXT-5909) -		if (!LLHandlerUtil::canSpawnToast(notification)) +		// don't show toast if Nearby Chat is opened +		LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); +		if (!nearby_chat->isMinimized() && nearby_chat->getVisible())  		{  			return false;  		} +	} -		LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); - -		LLToast::Params p; -		p.notif_id = notification->getID(); -		p.notification = notification; -		p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); -		p.panel = notify_box; -		p.is_tip = true; -		p.can_be_stored = false; -		 -		removeExclusiveNotifications(notification); - -		LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); -		if(channel) -			channel->addToast(p); +	std::string session_name = notification->getPayload()["SESSION_NAME"]; +	const std::string name = notification->getSubstitutions()["NAME"]; +	if (session_name.empty()) +	{ +		session_name = name;  	} -	else if (notify["sigtype"].asString() == "delete") +	LLUUID from_id = notification->getPayload()["from_id"]; +	if (notification->canLogToIM())  	{ -		mChannel.get()->killToastByNotificationID(notification->getID()); +		LLHandlerUtil::logToIM(IM_NOTHING_SPECIAL, session_name, name, +				notification->getMessage(), from_id, from_id);  	} -	return false; -} - -//-------------------------------------------------------------------------- -void LLTipHandler::onDeleteToast(LLToast* toast) -{ -} - -//-------------------------------------------------------------------------- -void LLTipHandler::onRejectToast(const LLUUID& id) -{ -	LLNotificationPtr notification = LLNotifications::instance().find(id); +	if (notification->canLogToIM() && notification->hasFormElements()) +	{ +		LLHandlerUtil::spawnIMSession(name, from_id); +	} -	if (notification -			&& LLNotificationManager::getInstance()->getHandlerForNotification( -					notification->getType()) == this) +	if (notification->canLogToIM() && LLHandlerUtil::isIMFloaterOpened(notification))  	{ -		LLNotifications::instance().cancel(notification); +		return false;  	} + +	LLToastPanel* notify_box = LLToastPanel::buidPanelFromNotification(notification); + +	LLToast::Params p; +	p.notif_id = notification->getID(); +	p.notification = notification; +	p.lifetime_secs = gSavedSettings.getS32("NotificationTipToastLifeTime"); +	p.panel = notify_box; +	p.is_tip = true; +	p.can_be_stored = false; +		 +	LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel.get()); +	if(channel) +		channel->addToast(p); +	return false;  } diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 85626d8783..096e714981 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -28,6 +28,7 @@  #include "lloutputmonitorctrl.h"  // library includes  +#include "llfloaterreg.h"  #include "llui.h"  // viewer includes @@ -241,6 +242,17 @@ void LLOutputMonitorCtrl::draw()  		gl_rect_2d(0, monh, monw, 0, sColorBound, FALSE);  } +// virtual +BOOL LLOutputMonitorCtrl::handleMouseUp(S32 x, S32 y, MASK mask) +{ +	if (mSpeakerId != gAgentID) +	{ +		LLFloaterReg::showInstance("floater_voice_volume", LLSD().with("avatar_id", mSpeakerId)); +	} + +	return TRUE; +} +  void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id, const LLUUID& session_id/* = LLUUID::null*/)  {  	if (speaker_id.isNull() && mSpeakerId.notNull()) diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 2d23753d46..7b02e84744 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -68,6 +68,7 @@ public:  	// llview overrides  	virtual void	draw(); +	virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);  	void			setPower(F32 val);  	F32				getPower(F32 val) const { return mPower; } diff --git a/indra/newview/llpanelblockedlist.cpp b/indra/newview/llpanelblockedlist.cpp index 5c85ec438c..d2dff63948 100644 --- a/indra/newview/llpanelblockedlist.cpp +++ b/indra/newview/llpanelblockedlist.cpp @@ -69,8 +69,6 @@ BOOL LLPanelBlockedList::postBuild()  	mBlockedList = getChild<LLScrollListCtrl>("blocked");  	mBlockedList->setCommitOnSelectionChange(TRUE); -	childSetCommitCallback("back", boost::bind(&LLPanelBlockedList::onBackBtnClick, this), NULL); -  	LLMuteList::getInstance()->addObserver(this);  	refreshBlockedList(); @@ -99,7 +97,8 @@ void LLPanelBlockedList::selectBlocked(const LLUUID& mute_id)  void LLPanelBlockedList::showPanelAndSelect(const LLUUID& idToSelect)  { -	LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD().with(BLOCKED_PARAM_NAME, idToSelect)); +	LLFloaterSidePanelContainer::showPanel("people", "panel_people", +		LLSD().with("people_panel_tab_name", "blocked_panel").with(BLOCKED_PARAM_NAME, idToSelect));  } @@ -130,17 +129,6 @@ void LLPanelBlockedList::updateButtons()  	getChildView("Unblock")->setEnabled(hasSelected);  } - - -void LLPanelBlockedList::onBackBtnClick() -{ -	LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent()); -	if(parent) -	{ -		parent->openPreviousPanel(); -	} -} -  void LLPanelBlockedList::onRemoveBtnClick()  {  	std::string name = mBlockedList->getSelectedItemLabel(); diff --git a/indra/newview/llpanelblockedlist.h b/indra/newview/llpanelblockedlist.h index 74ad82e32d..97236ecdbf 100644 --- a/indra/newview/llpanelblockedlist.h +++ b/indra/newview/llpanelblockedlist.h @@ -68,7 +68,6 @@ private:  	void updateButtons();  	// UI callbacks -	void onBackBtnClick();  	void onRemoveBtnClick();  	void onPickBtnClick();  	void onBlockByNameClick(); diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index eda0749cdb..389baa86cd 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -1,31 +1,30 @@ -/**  +/**   * @file llpanelavatar.cpp   * @brief LLPanelAvatar and related class implementations   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, 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$   */  #include "llviewerprecompiledheaders.h" -  #include "llfloaterreg.h"  #include "llpanelimcontrolpanel.h" @@ -39,393 +38,7 @@  #include "llavatarlist.h"  #include "llparticipantlist.h"  #include "llimview.h" -#include "llvoicechannel.h"  #include "llspeakers.h"  #include "lltrans.h" -void LLPanelChatControlPanel::onCallButtonClicked() -{ -	gIMMgr->startCall(mSessionId); -} - -void LLPanelChatControlPanel::onEndCallButtonClicked() -{ -	gIMMgr->endCall(mSessionId); -} - -void LLPanelChatControlPanel::onOpenVoiceControlsClicked() -{ -	LLFloaterReg::showInstance("voice_controls"); -} - -void LLPanelChatControlPanel::onChange(EStatusType status, const std::string &channelURI, bool proximal) -{ -	if(status == STATUS_JOINING || status == STATUS_LEFT_CHANNEL) -	{ -		return; -	} - -	updateCallButton(); -} - -void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) -{ -	updateButtons(new_state); -} - -void LLPanelChatControlPanel::updateCallButton() -{ -	// hide/show call button -	bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking(); - -	LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId); -	 -	if (!session)  -	{ -		getChildView("call_btn")->setEnabled(false); -		return; -	} - -	bool session_initialized = session->mSessionInitialized; -	bool callback_enabled = session->mCallBackEnabled; - -	BOOL enable_connect = session_initialized -		&& voice_enabled -		&& callback_enabled; -	getChildView("call_btn")->setEnabled(enable_connect); -} - -void LLPanelChatControlPanel::updateButtons(LLVoiceChannel::EState state) -{ -	bool is_call_started = state >= LLVoiceChannel::STATE_CALL_STARTED; -	getChildView("end_call_btn_panel")->setVisible( is_call_started); -	getChildView("voice_ctrls_btn_panel")->setVisible( is_call_started && findChild<LLView>("voice_ctrls_btn_panel")); -	getChildView("call_btn_panel")->setVisible( ! is_call_started); -	 -	getChildView("volume_ctrl_panel")->setVisible(state == LLVoiceChannel::STATE_CONNECTED); -	 -	updateCallButton(); -	 -} - -LLPanelChatControlPanel::~LLPanelChatControlPanel() -{ -	mVoiceChannelStateChangeConnection.disconnect(); -	if(LLVoiceClient::instanceExists()) -	{ -		LLVoiceClient::getInstance()->removeObserver(this); -	} -} - -BOOL LLPanelChatControlPanel::postBuild() -{ -	childSetAction("call_btn", boost::bind(&LLPanelChatControlPanel::onCallButtonClicked, this)); -	childSetAction("end_call_btn", boost::bind(&LLPanelChatControlPanel::onEndCallButtonClicked, this)); -	childSetAction("voice_ctrls_btn", boost::bind(&LLPanelChatControlPanel::onOpenVoiceControlsClicked, this)); - -	LLVoiceClient::getInstance()->addObserver(this); - -	return TRUE; -} - -void LLPanelChatControlPanel::setSessionId(const LLUUID& session_id) -{ -	//Method is called twice for AdHoc and Group chat. Second time when server init reply received -	mSessionId = session_id; -	LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionId); -	if(voice_channel) -	{ -		mVoiceChannelStateChangeConnection = voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2)); -		 -		//call (either p2p, group or ad-hoc) can be already in started state -		updateButtons(voice_channel->getState()); -	} -} - -LLPanelIMControlPanel::LLPanelIMControlPanel() -{ -} - -LLPanelIMControlPanel::~LLPanelIMControlPanel() -{ -	LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); -} - -BOOL LLPanelIMControlPanel::postBuild() -{ -	childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this)); -	childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this)); - -	childSetAction("share_btn", boost::bind(&LLPanelIMControlPanel::onShareButtonClicked, this)); -	childSetAction("teleport_btn", boost::bind(&LLPanelIMControlPanel::onTeleportButtonClicked, this)); -	childSetAction("pay_btn", boost::bind(&LLPanelIMControlPanel::onPayButtonClicked, this)); - -	childSetAction("mute_btn", boost::bind(&LLPanelIMControlPanel::onClickMuteVolume, this)); -	childSetAction("block_btn", boost::bind(&LLPanelIMControlPanel::onClickBlock, this)); -	childSetAction("unblock_btn", boost::bind(&LLPanelIMControlPanel::onClickUnblock, this)); -	 -	getChild<LLUICtrl>("volume_slider")->setCommitCallback(boost::bind(&LLPanelIMControlPanel::onVolumeChange, this, _2)); - -	getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId())); - -	setFocusReceivedCallback(boost::bind(&LLPanelIMControlPanel::onFocusReceived, this)); -	 -	return LLPanelChatControlPanel::postBuild(); -} - -void LLPanelIMControlPanel::draw() -{ -	bool is_muted = LLMuteList::getInstance()->isMuted(mAvatarID); - -	getChild<LLUICtrl>("block_btn_panel")->setVisible(!is_muted); -	getChild<LLUICtrl>("unblock_btn_panel")->setVisible(is_muted); - -	if (getChildView("volume_ctrl_panel")->getVisible()) -	{ - -		bool is_muted_voice = LLMuteList::getInstance()->isMuted(mAvatarID, LLMute::flagVoiceChat); - -		LLUICtrl* mute_btn = getChild<LLUICtrl>("mute_btn"); -		mute_btn->setValue( is_muted_voice ); - -		LLUICtrl* volume_slider = getChild<LLUICtrl>("volume_slider"); -		volume_slider->setEnabled( !is_muted_voice ); - -		F32 volume; - -		if (is_muted_voice) -		{ -			// it's clearer to display their volume as zero -			volume = 0.f; -		} -		else -		{ -			// actual volume -			volume = LLVoiceClient::getInstance()->getUserVolume(mAvatarID); -		} -		volume_slider->setValue( (F64)volume ); -	} - -	LLPanelChatControlPanel::draw(); -} - -void LLPanelIMControlPanel::onClickMuteVolume() -{ -	// By convention, we only display and toggle voice mutes, not all mutes -	LLMuteList* mute_list = LLMuteList::getInstance(); -	bool is_muted = mute_list->isMuted(mAvatarID, LLMute::flagVoiceChat); - -	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); -	if (!is_muted) -	{ -		mute_list->add(mute, LLMute::flagVoiceChat); -	} -	else -	{ -		mute_list->remove(mute, LLMute::flagVoiceChat); -	} -} - -void LLPanelIMControlPanel::onClickBlock() -{ -	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); -	 -	LLMuteList::getInstance()->add(mute); -} - -void LLPanelIMControlPanel::onClickUnblock() -{ -	LLMute mute(mAvatarID, getChild<LLTextBox>("avatar_name")->getText(), LLMute::AGENT); - -	LLMuteList::getInstance()->remove(mute); -} - -void LLPanelIMControlPanel::onVolumeChange(const LLSD& data) -{ -	F32 volume = (F32)data.asReal(); -	LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); -} - -void LLPanelIMControlPanel::onTeleportButtonClicked() -{ -	LLAvatarActions::offerTeleport(mAvatarID); -} -void LLPanelIMControlPanel::onPayButtonClicked() -{ -	LLAvatarActions::pay(mAvatarID); -} - -void LLPanelIMControlPanel::onViewProfileButtonClicked() -{ -	LLAvatarActions::showProfile(mAvatarID); -} - -void LLPanelIMControlPanel::onAddFriendButtonClicked() -{ -	LLAvatarIconCtrl* avatar_icon = getChild<LLAvatarIconCtrl>("avatar_icon"); -	std::string full_name = avatar_icon->getFullName(); -	LLAvatarActions::requestFriendshipDialog(mAvatarID, full_name); -} - -void LLPanelIMControlPanel::onShareButtonClicked() -{ -	LLAvatarActions::share(mAvatarID); -} - -void LLPanelIMControlPanel::onFocusReceived() -{ -	// Disable all the buttons (Call, Teleport, etc) if disconnected. -	if (gDisconnected) -	{ -		setAllChildrenEnabled(FALSE); -	} -} - -void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id) -{ -	LLPanelChatControlPanel::setSessionId(session_id); - -	LLIMModel& im_model = LLIMModel::instance(); - -	LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarID, this); -	mAvatarID = im_model.getOtherParticipantID(session_id); -	LLAvatarTracker::instance().addParticularFriendObserver(mAvatarID, this); - -	// Disable "Add friend" button for friends. -	getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(mAvatarID)); -	 -	// Disable "Teleport" button if friend is offline -	if(LLAvatarActions::isFriend(mAvatarID)) -	{ -		getChildView("teleport_btn")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(mAvatarID)); -	} - -	getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(mAvatarID); - -	// Disable most profile buttons if the participant is -	// not really an SL avatar (e.g., an Avaline caller). -	LLIMModel::LLIMSession* im_session = -		im_model.findIMSession(session_id); -	if( im_session && !im_session->mOtherParticipantIsAvatar ) -	{ -		getChildView("view_profile_btn")->setEnabled(FALSE); -		getChildView("add_friend_btn")->setEnabled(FALSE); - -		getChildView("share_btn")->setEnabled(FALSE); -		getChildView("teleport_btn")->setEnabled(FALSE); -		getChildView("pay_btn")->setEnabled(FALSE); - -        getChild<LLTextBox>("avatar_name")->setValue(im_session->mName); -        getChild<LLTextBox>("avatar_name")->setToolTip(im_session->mName); -	} -	else -	{ -		// If the participant is an avatar, fetch the currect name -		gCacheName->get(mAvatarID, false, -			boost::bind(&LLPanelIMControlPanel::onNameCache, this, _1, _2, _3)); -	} -} - -//virtual -void LLPanelIMControlPanel::changed(U32 mask) -{ -	getChildView("add_friend_btn")->setEnabled(!LLAvatarActions::isFriend(mAvatarID)); -	 -	// Disable "Teleport" button if friend is offline -	if(LLAvatarActions::isFriend(mAvatarID)) -	{ -		getChildView("teleport_btn")->setEnabled(LLAvatarTracker::instance().isBuddyOnline(mAvatarID)); -	} -} - -void LLPanelIMControlPanel::onNameCache(const LLUUID& id, const std::string& full_name, bool is_group) -{ -	if ( id == mAvatarID ) -	{ -		std::string avatar_name = full_name; -		getChild<LLTextBox>("avatar_name")->setValue(avatar_name); -		getChild<LLTextBox>("avatar_name")->setToolTip(avatar_name); - -		bool is_linden = LLStringUtil::endsWith(full_name, " Linden"); -		getChild<LLUICtrl>("mute_btn")->setEnabled( !is_linden); -	} -} - -LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id): -mParticipantList(NULL) -{ -} - -BOOL LLPanelGroupControlPanel::postBuild() -{ -	childSetAction("group_info_btn", boost::bind(&LLPanelGroupControlPanel::onGroupInfoButtonClicked, this)); - -	return LLPanelChatControlPanel::postBuild(); -} - -LLPanelGroupControlPanel::~LLPanelGroupControlPanel() -{ -	delete mParticipantList; -	mParticipantList = NULL; -} - -// virtual -void LLPanelGroupControlPanel::draw() -{ -	// Need to resort the participant list if it's in sort by recent speaker order. -	if (mParticipantList) -		mParticipantList->update(); -	LLPanelChatControlPanel::draw(); -} - -void LLPanelGroupControlPanel::onGroupInfoButtonClicked() -{ -	LLGroupActions::show(mGroupID); -} - -void LLPanelGroupControlPanel::onSortMenuItemClicked(const LLSD& userdata) -{ -	// TODO: Check this code when when sort order menu will be added. (EM) -	if (false && !mParticipantList) -		return; - -	std::string chosen_item = userdata.asString(); - -	if (chosen_item == "sort_name") -	{ -		mParticipantList->setSortOrder(LLParticipantList::E_SORT_BY_NAME); -	} - -} - -void LLPanelGroupControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state) -{ -	LLPanelChatControlPanel::onVoiceChannelStateChanged(old_state, new_state); -	mParticipantList->setSpeakingIndicatorsVisible(new_state >= LLVoiceChannel::STATE_CALL_STARTED); -} - -void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id) -{ -	LLPanelChatControlPanel::setSessionId(session_id); - -	mGroupID = session_id; - -	// for group and Ad-hoc chat we need to include agent into list  -	if(!mParticipantList) -	{ -		LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id); -		mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true,false); -	} -} - - -LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLPanelGroupControlPanel(session_id) -{ -} - -BOOL LLPanelAdHocControlPanel::postBuild() -{ -	//We don't need LLPanelGroupControlPanel::postBuild() to be executed as there is no group_info_btn at AdHoc chat -	return LLPanelChatControlPanel::postBuild(); -} diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h index bba847b5d4..02915ec4bb 100644 --- a/indra/newview/llpanelimcontrolpanel.h +++ b/indra/newview/llpanelimcontrolpanel.h @@ -28,14 +28,12 @@  #define LL_LLPANELIMCONTROLPANEL_H  #include "llpanel.h" -#include "llvoicechannel.h"  #include "llcallingcard.h"  class LLParticipantList; -class LLPanelChatControlPanel  +class LLPanelChatControlPanel  	: public LLPanel -	, public LLVoiceClientStatusObserver  {  public:  	LLPanelChatControlPanel() : @@ -44,21 +42,6 @@ public:  	virtual BOOL postBuild(); -	void onCallButtonClicked(); -	void onEndCallButtonClicked(); -	void onOpenVoiceControlsClicked(); - -	// Implements LLVoiceClientStatusObserver::onChange() to enable the call -	// button when voice is available -	/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); - -	virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state); - -	void updateButtons(LLVoiceChannel::EState state); -	 -	// Enables/disables call button depending on voice availability -	void updateCallButton(); -  	virtual void setSessionId(const LLUUID& session_id);  	const LLUUID& getSessionId() { return mSessionId; } @@ -69,41 +52,6 @@ private:  	boost::signals2::connection mVoiceChannelStateChangeConnection;  }; - -class LLPanelIMControlPanel : public LLPanelChatControlPanel, LLFriendObserver -{ -public: -	LLPanelIMControlPanel(); -	~LLPanelIMControlPanel(); - -	BOOL postBuild(); - -	void setSessionId(const LLUUID& session_id); - -	// LLFriendObserver trigger -	virtual void changed(U32 mask); - -protected: -	void onNameCache(const LLUUID& id, const std::string& full_name, bool is_group); - -private: -	void onViewProfileButtonClicked(); -	void onAddFriendButtonClicked(); -	void onShareButtonClicked(); -	void onTeleportButtonClicked(); -	void onPayButtonClicked(); -	void onFocusReceived(); - -	void onClickMuteVolume(); -	void onClickBlock(); -	void onClickUnblock(); -	/*virtual*/ void draw(); -	void onVolumeChange(const LLSD& data); - -	LLUUID mAvatarID; -}; - -  class LLPanelGroupControlPanel : public LLPanelChatControlPanel  {  public: @@ -121,9 +69,7 @@ protected:  	LLParticipantList* mParticipantList;  private: -	void onGroupInfoButtonClicked();  	void onSortMenuItemClicked(const LLSD& userdata); -	/*virtual*/ void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);  };  class LLPanelAdHocControlPanel : public LLPanelGroupControlPanel diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 1ca24f3031..f84d6e5cc1 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -739,15 +739,7 @@ const std::string& LLTaskCategoryBridge::getDisplayName() const  	if (cat)  	{ -		// Localize "Contents" folder. -		if (cat->getParentUUID().isNull() && cat->getName() == "Contents") -		{ -			mDisplayName.assign(LLTrans::getString("ViewerObjectContents")); -		} -		else -		{ -			mDisplayName.assign(cat->getName()); -		} +		mDisplayName.assign(cat->getName());  	}  	return mDisplayName; @@ -1553,6 +1545,7 @@ void LLPanelObjectInventory::reset()  	p.parent_panel = this;  	p.tool_tip= LLTrans::getString("PanelContentsTooltip");  	p.listener = LLTaskInvFVBridge::createObjectBridge(this, NULL); +	p.folder_indentation = -14; // subtract space normally reserved for folder expanders  	mFolders = LLUICtrlFactory::create<LLFolderView>(p);  	// this ensures that we never say "searching..." or "no items found"  	mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); @@ -1631,10 +1624,11 @@ void LLPanelObjectInventory::updateInventory()  		LLInventoryObject* inventory_root = objectp->getInventoryRoot();  		LLInventoryObject::object_list_t contents;  		objectp->getInventoryContents(contents); -		if (inventory_root) +		mHaveInventory = TRUE; + +		if (inventory_root && !contents.empty())  		{  			createFolderViews(inventory_root, contents); -			mHaveInventory = TRUE;  			mIsInventoryEmpty = FALSE;  			mFolders->setEnabled(TRUE);  		} @@ -1642,7 +1636,6 @@ void LLPanelObjectInventory::updateInventory()  		{  			// TODO: create an empty inventory  			mIsInventoryEmpty = TRUE; -			mHaveInventory = TRUE;  		}  	}  	else @@ -1694,19 +1687,19 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root  	bridge = LLTaskInvFVBridge::createObjectBridge(this, inventory_root);  	if(bridge)  	{ -		LLFolderViewFolder* new_folder = NULL; -		LLFolderViewFolder::Params p; -		p.name = inventory_root->getName(); -		p.icon = LLUI::getUIImage("Inv_FolderClosed"); -		p.icon_open = LLUI::getUIImage("Inv_FolderOpen"); -		p.root = mFolders; -		p.listener = bridge; -		p.tool_tip = p.name; -		new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); -		new_folder->addToFolder(mFolders, mFolders); -		new_folder->toggleOpen(); - -		createViewsForCategory(&contents, inventory_root, new_folder); +		//LLFolderViewFolder* new_folder = NULL; +		//LLFolderViewFolder::Params p; +		//p.name = inventory_root->getName(); +		//p.icon = LLUI::getUIImage("Inv_FolderClosed"); +		//p.icon_open = LLUI::getUIImage("Inv_FolderOpen"); +		//p.root = mFolders; +		//p.listener = bridge; +		//p.tool_tip = p.name; +		//new_folder = LLUICtrlFactory::create<LLFolderViewFolder>(p); +		//new_folder->addToFolder(mFolders, mFolders); +		//new_folder->toggleOpen(); + +		createViewsForCategory(&contents, inventory_root, mFolders);  	}  } diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index f1380e7a36..260de40eef 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -72,6 +72,7 @@ static const std::string NEARBY_TAB_NAME	= "nearby_panel";  static const std::string FRIENDS_TAB_NAME	= "friends_panel";  static const std::string GROUP_TAB_NAME		= "groups_panel";  static const std::string RECENT_TAB_NAME	= "recent_panel"; +static const std::string BLOCKED_TAB_NAME	= "blocked_panel"; // blocked avatars  static const std::string COLLAPSED_BY_USER  = "collapsed_by_user"; @@ -492,26 +493,37 @@ public:  LLPanelPeople::LLPanelPeople()  	:	LLPanel(), -		mFilterSubString(LLStringUtil::null), -		mFilterSubStringOrig(LLStringUtil::null), -		mFilterEditor(NULL),  		mTabContainer(NULL),  		mOnlineFriendList(NULL),  		mAllFriendList(NULL),  		mNearbyList(NULL),  		mRecentList(NULL),  		mGroupList(NULL), -		mNearbyGearButton(NULL), -		mFriendsGearButton(NULL), -		mGroupsGearButton(NULL), -		mRecentGearButton(NULL),  		mMiniMap(NULL)  {  	mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList,	this));  	mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList,	this));  	mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList,	this));  	mButtonsUpdater = new LLButtonsUpdater(boost::bind(&LLPanelPeople::updateButtons, this)); -	mCommitCallbackRegistrar.add("People.addFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); + +	mCommitCallbackRegistrar.add("People.AddFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); +	mCommitCallbackRegistrar.add("People.AddFriendWizard",	boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked,	this)); +	mCommitCallbackRegistrar.add("People.DelFriend",		boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked,	this)); +	mCommitCallbackRegistrar.add("People.Group.Minus",		boost::bind(&LLPanelPeople::onGroupMinusButtonClicked,  this)); +	mCommitCallbackRegistrar.add("People.Chat",			boost::bind(&LLPanelPeople::onChatButtonClicked,		this)); +	mCommitCallbackRegistrar.add("People.Gear",			boost::bind(&LLPanelPeople::onGearButtonClicked,		this, _1)); + +	mCommitCallbackRegistrar.add("People.Group.Plus.Action",  boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Friends.ViewSort.Action",  boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Nearby.ViewSort.Action",  boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Groups.ViewSort.Action",  boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked,  this, _2)); +	mCommitCallbackRegistrar.add("People.Recent.ViewSort.Action",  boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked,  this, _2)); + +	mEnableCallbackRegistrar.add("People.Friends.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck,	this, _2)); +	mEnableCallbackRegistrar.add("People.Recent.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck,	this, _2)); +	mEnableCallbackRegistrar.add("People.Nearby.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck,	this, _2)); + +	mEnableCallbackRegistrar.add("People.Group.Plus.Validate",	boost::bind(&LLPanelPeople::onGroupPlusButtonValidate,	this));  }  LLPanelPeople::~LLPanelPeople() @@ -525,13 +537,6 @@ LLPanelPeople::~LLPanelPeople()  	{  		LLVoiceClient::getInstance()->removeObserver(this);  	} - -	if (mGroupPlusMenuHandle.get()) mGroupPlusMenuHandle.get()->die(); -	if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); -	if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); -	if (mGroupsViewSortMenuHandle.get()) mGroupsViewSortMenuHandle.get()->die(); -	if (mRecentViewSortMenuHandle.get()) mRecentViewSortMenuHandle.get()->die(); -  }  void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LLSD& param, LLAvatarList* avatar_list) @@ -553,11 +558,15 @@ void LLPanelPeople::onFriendsAccordionExpandedCollapsed(LLUICtrl* ctrl, const LL  BOOL LLPanelPeople::postBuild()  { -	mFilterEditor = getChild<LLFilterEditor>("filter_input"); -	mFilterEditor->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("nearby_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("friends_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("groups_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); +	getChild<LLFilterEditor>("recent_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));  	mTabContainer = getChild<LLTabContainer>("tabs");  	mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2)); +	mSavedFilters.resize(mTabContainer->getTabCount()); +	mSavedOriginalFilters.resize(mTabContainer->getTabCount());  	LLPanel* friends_tab = getChild<LLPanel>(FRIENDS_TAB_NAME);  	// updater is active only if panel is visible to user. @@ -601,14 +610,6 @@ BOOL LLPanelPeople::postBuild()  	setSortOrder(mAllFriendList,	(ESortOrder)gSavedSettings.getU32("FriendsSortOrder"),		false);  	setSortOrder(mNearbyList,		(ESortOrder)gSavedSettings.getU32("NearbyPeopleSortOrder"),	false); -	LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME); -	groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked,	this)); -	groups_panel->childSetAction("plus_btn",	boost::bind(&LLPanelPeople::onGroupPlusButtonClicked,	this)); - -	LLPanel* friends_panel = getChild<LLPanel>(FRIENDS_TAB_NAME); -	friends_panel->childSetAction("add_btn",	boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked,	this)); -	friends_panel->childSetAction("del_btn",	boost::bind(&LLPanelPeople::onDeleteFriendButtonClicked,	this)); -  	mOnlineFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));  	mAllFriendList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1));  	mNearbyList->setItemDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, _1)); @@ -629,6 +630,19 @@ BOOL LLPanelPeople::postBuild()  	mGroupList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this));  	mGroupList->setReturnCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this)); +	LLMenuButton* groups_gear_btn = getChild<LLMenuButton>("groups_gear_btn"); + +	// Use the context menu of the Groups list for the Groups tab gear menu. +	LLToggleableMenu* groups_gear_menu = mGroupList->getContextMenu(); +	if (groups_gear_menu) +	{ +		groups_gear_btn->setMenu(groups_gear_menu, LLMenuButton::MP_BOTTOM_LEFT); +	} +	else +	{ +		llwarns << "People->Groups list menu not found" << llendl; +	} +  	LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>("tab_all");  	accordion_tab->setDropDownStateChangedCallback(  		boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mAllFriendList)); @@ -637,70 +651,9 @@ BOOL LLPanelPeople::postBuild()  	accordion_tab->setDropDownStateChangedCallback(  		boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _1, _2, mOnlineFriendList)); -	buttonSetAction("view_profile_btn",	boost::bind(&LLPanelPeople::onViewProfileButtonClicked,	this)); -	buttonSetAction("group_info_btn",	boost::bind(&LLPanelPeople::onGroupInfoButtonClicked,	this)); -	buttonSetAction("chat_btn",			boost::bind(&LLPanelPeople::onChatButtonClicked,		this)); -	buttonSetAction("im_btn",			boost::bind(&LLPanelPeople::onImButtonClicked,			this)); -	buttonSetAction("call_btn",			boost::bind(&LLPanelPeople::onCallButtonClicked,		this)); -	buttonSetAction("group_call_btn",	boost::bind(&LLPanelPeople::onGroupCallButtonClicked,	this)); -	buttonSetAction("teleport_btn",		boost::bind(&LLPanelPeople::onTeleportButtonClicked,	this)); -	buttonSetAction("share_btn",		boost::bind(&LLPanelPeople::onShareButtonClicked,		this)); -  	// Must go after setting commit callback and initializing all pointers to children.  	mTabContainer->selectTabByName(NEARBY_TAB_NAME); -	// Create menus. -	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; -	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; -	 -	registrar.add("People.Group.Plus.Action",  boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked,  this, _2)); -	registrar.add("People.Group.Minus.Action", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked,  this)); -	registrar.add("People.Friends.ViewSort.Action",  boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked,  this, _2)); -	registrar.add("People.Nearby.ViewSort.Action",  boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked,  this, _2)); -	registrar.add("People.Groups.ViewSort.Action",  boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked,  this, _2)); -	registrar.add("People.Recent.ViewSort.Action",  boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked,  this, _2)); - -	enable_registrar.add("People.Group.Minus.Enable",	boost::bind(&LLPanelPeople::isRealGroup,	this)); -	enable_registrar.add("People.Friends.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck,	this, _2)); -	enable_registrar.add("People.Recent.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck,	this, _2)); -	enable_registrar.add("People.Nearby.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemCheck,	this, _2)); - -	mNearbyGearButton = getChild<LLMenuButton>("nearby_view_sort_btn"); -	mFriendsGearButton = getChild<LLMenuButton>("friends_viewsort_btn"); -	mGroupsGearButton = getChild<LLMenuButton>("groups_viewsort_btn"); -	mRecentGearButton = getChild<LLMenuButton>("recent_viewsort_btn"); - -	LLMenuGL* plus_menu  = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	mGroupPlusMenuHandle  = plus_menu->getHandle(); - -	LLToggleableMenu* nearby_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_nearby_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(nearby_view_sort) -	{ -		mNearbyViewSortMenuHandle  = nearby_view_sort->getHandle(); -		mNearbyGearButton->setMenu(nearby_view_sort); -	} - -	LLToggleableMenu* friend_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_friends_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(friend_view_sort) -	{ -		mFriendsViewSortMenuHandle  = friend_view_sort->getHandle(); -		mFriendsGearButton->setMenu(friend_view_sort); -	} - -	LLToggleableMenu* group_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_groups_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(group_view_sort) -	{ -		mGroupsViewSortMenuHandle  = group_view_sort->getHandle(); -		mGroupsGearButton->setMenu(group_view_sort); -	} - -	LLToggleableMenu* recent_view_sort  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_people_recent_view_sort.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); -	if(recent_view_sort) -	{ -		mRecentViewSortMenuHandle  = recent_view_sort->getHandle(); -		mRecentGearButton->setMenu(recent_view_sort); -	} -  	LLVoiceClient::getInstance()->addObserver(this);  	// call this method in case some list is empty and buttons can be in inconsistent state @@ -735,9 +688,11 @@ void LLPanelPeople::updateFriendListHelpText()  	if (no_friends_text->getVisible())  	{  		//update help text for empty lists -		std::string message_name = mFilterSubString.empty() ? "no_friends_msg" : "no_filtered_friends_msg"; +		const std::string& filter = mSavedOriginalFilters[mTabContainer->getCurrentPanelIndex()]; + +		std::string message_name = filter.empty() ? "no_friends_msg" : "no_filtered_friends_msg";  		LLStringUtil::format_map_t args; -		args["[SEARCH_TERM]"] = LLURI::escape(mFilterSubStringOrig); +		args["[SEARCH_TERM]"] = LLURI::escape(filter);  		no_friends_text->setText(getString(message_name, args));  	}  } @@ -821,31 +776,9 @@ void LLPanelPeople::updateRecentList()  	mRecentList->setDirty();  } -void LLPanelPeople::buttonSetVisible(std::string btn_name, BOOL visible) -{ -	// To make sure we're referencing the right widget (a child of the button bar). -	LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); -	button->setVisible(visible); -} - -void LLPanelPeople::buttonSetEnabled(const std::string& btn_name, bool enabled) -{ -	// To make sure we're referencing the right widget (a child of the button bar). -	LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); -	button->setEnabled(enabled); -} - -void LLPanelPeople::buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb) -{ -	// To make sure we're referencing the right widget (a child of the button bar). -	LLButton* button = getChild<LLView>("button_bar")->getChild<LLButton>(btn_name); -	button->setClickedCallback(cb); -} -  void LLPanelPeople::updateButtons()  {  	std::string cur_tab		= getActiveTabName(); -	bool nearby_tab_active	= (cur_tab == NEARBY_TAB_NAME);  	bool friends_tab_active = (cur_tab == FRIENDS_TAB_NAME);  	bool group_tab_active	= (cur_tab == GROUP_TAB_NAME);  	//bool recent_tab_active	= (cur_tab == RECENT_TAB_NAME); @@ -856,28 +789,15 @@ void LLPanelPeople::updateButtons()  	bool item_selected = (selected_uuids.size() == 1);  	bool multiple_selected = (selected_uuids.size() >= 1); -	buttonSetVisible("group_info_btn",		group_tab_active); -	buttonSetVisible("chat_btn",			group_tab_active); -	buttonSetVisible("view_profile_btn",	!group_tab_active); -	buttonSetVisible("im_btn",				!group_tab_active); -	buttonSetVisible("call_btn",			!group_tab_active); -	buttonSetVisible("group_call_btn",		group_tab_active); -	buttonSetVisible("teleport_btn",		friends_tab_active); -	buttonSetVisible("share_btn",			nearby_tab_active || friends_tab_active); -  	if (group_tab_active)  	{ -		bool cur_group_active = true; -  		if (item_selected)  		{  			selected_id = mGroupList->getSelectedUUID(); -			cur_group_active = (gAgent.getGroupID() == selected_id);  		}  		LLPanel* groups_panel = mTabContainer->getCurrentPanel(); -		groups_panel->getChildView("activate_btn")->setEnabled(item_selected && !cur_group_active); // "none" or a non-active group selected -		groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); +		groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected  	}  	else  	{ @@ -893,26 +813,20 @@ void LLPanelPeople::updateButtons()  		LLPanel* cur_panel = mTabContainer->getCurrentPanel();  		if (cur_panel)  		{ -			cur_panel->getChildView("add_friend_btn")->setEnabled(!is_friend); +			if (cur_panel->hasChild("add_friend_btn", TRUE)) +				cur_panel->getChildView("add_friend_btn")->setEnabled(item_selected && !is_friend); +  			if (friends_tab_active)  			{ -				cur_panel->getChildView("del_btn")->setEnabled(multiple_selected); +				cur_panel->getChildView("friends_del_btn")->setEnabled(multiple_selected); +			} + +			if (!group_tab_active) +			{ +				cur_panel->getChildView("gear_btn")->setEnabled(multiple_selected);  			}  		}  	} - -	bool enable_calls = LLVoiceClient::getInstance()->isVoiceWorking() && LLVoiceClient::getInstance()->voiceEnabled(); - -	buttonSetEnabled("view_profile_btn",item_selected); -	buttonSetEnabled("share_btn",		item_selected); -	buttonSetEnabled("im_btn",			multiple_selected); // allow starting the friends conference for multiple selection -	buttonSetEnabled("call_btn",		multiple_selected && enable_calls); -	buttonSetEnabled("teleport_btn",	multiple_selected && LLAvatarActions::canOfferTeleport(selected_uuids)); - -	bool none_group_selected = item_selected && selected_id.isNull(); -	buttonSetEnabled("group_info_btn", !none_group_selected); -	buttonSetEnabled("group_call_btn", !none_group_selected && enable_calls); -	buttonSetEnabled("chat_btn", !none_group_selected);  }  std::string LLPanelPeople::getActiveTabName() const @@ -943,6 +857,9 @@ LLUUID LLPanelPeople::getCurrentItemID() const  	if (cur_tab == GROUP_TAB_NAME)  		return mGroupList->getSelectedUUID(); +	if (cur_tab == BLOCKED_TAB_NAME) +		return LLUUID::null; // FIXME? +  	llassert(0 && "unknown tab selected");  	return LLUUID::null;  } @@ -963,6 +880,8 @@ void LLPanelPeople::getCurrentItemIDs(uuid_vec_t& selected_uuids) const  		mRecentList->getSelectedUUIDs(selected_uuids);  	else if (cur_tab == GROUP_TAB_NAME)  		mGroupList->getSelectedUUIDs(selected_uuids); +	else if (cur_tab == BLOCKED_TAB_NAME) +		selected_uuids.clear(); // FIXME?  	else  		llassert(0 && "unknown tab selected"); @@ -1031,49 +950,60 @@ void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save  	}  } -bool LLPanelPeople::isRealGroup() -{ -	return getCurrentItemID() != LLUUID::null; -} -  void LLPanelPeople::onFilterEdit(const std::string& search_string)  { -	mFilterSubStringOrig = search_string; -	LLStringUtil::trimHead(mFilterSubStringOrig); +	const S32 cur_tab_idx = mTabContainer->getCurrentPanelIndex(); +	std::string& filter = mSavedOriginalFilters[cur_tab_idx]; +	std::string& saved_filter = mSavedFilters[cur_tab_idx]; + +	filter = search_string; +	LLStringUtil::trimHead(filter); +  	// Searches are case-insensitive -	std::string search_upper = mFilterSubStringOrig; +	std::string search_upper = filter;  	LLStringUtil::toUpper(search_upper); -	if (mFilterSubString == search_upper) +	if (saved_filter == search_upper)  		return; -	mFilterSubString = search_upper; +	saved_filter = search_upper; -	//store accordion tabs state before any manipulation with accordion tabs -	if(!mFilterSubString.empty()) +	// Apply new filter to the current tab. +	const std::string cur_tab = getActiveTabName(); +	if (cur_tab == NEARBY_TAB_NAME) +	{ +		mNearbyList->setNameFilter(filter); +	} +	else if (cur_tab == FRIENDS_TAB_NAME) +	{ +		// store accordion tabs opened/closed state before any manipulation with accordion tabs +		if (!saved_filter.empty())  	{  		notifyChildren(LLSD().with("action","store_state"));  	} - -	// Apply new filter. -	mNearbyList->setNameFilter(mFilterSubStringOrig); -	mOnlineFriendList->setNameFilter(mFilterSubStringOrig); -	mAllFriendList->setNameFilter(mFilterSubStringOrig); -	mRecentList->setNameFilter(mFilterSubStringOrig); -	mGroupList->setNameFilter(mFilterSubStringOrig); +		mOnlineFriendList->setNameFilter(filter); +		mAllFriendList->setNameFilter(filter);  	setAccordionCollapsedByUser("tab_online", false);  	setAccordionCollapsedByUser("tab_all", false); -  	showFriendsAccordionsIfNeeded(); -	//restore accordion tabs state _after_ all manipulations... -	if(mFilterSubString.empty()) +		// restore accordion tabs state _after_ all manipulations +		if(saved_filter.empty())  	{  		notifyChildren(LLSD().with("action","restore_state"));  	}  } +	else if (cur_tab == GROUP_TAB_NAME) +	{ +		mGroupList->setNameFilter(filter); +	} +	else if (cur_tab == RECENT_TAB_NAME) +	{ +		mRecentList->setNameFilter(filter); +	} +}  void LLPanelPeople::onTabSelected(const LLSD& param)  { @@ -1081,11 +1011,6 @@ void LLPanelPeople::onTabSelected(const LLSD& param)  	updateButtons();  	showFriendsAccordionsIfNeeded(); - -	if (GROUP_TAB_NAME == tab_name) -		mFilterEditor->setLabel(getString("groups_filter_label")); -	else -		mFilterEditor->setLabel(getString("people_filter_label"));  }  void LLPanelPeople::onAvatarListDoubleClicked(LLUICtrl* ctrl) @@ -1127,12 +1052,6 @@ void LLPanelPeople::onAvatarListCommitted(LLAvatarList* list)  	updateButtons();  } -void LLPanelPeople::onViewProfileButtonClicked() -{ -	LLUUID id = getCurrentItemID(); -	LLAvatarActions::showProfile(id); -} -  void LLPanelPeople::onAddFriendButtonClicked()  {  	LLUUID id = getCurrentItemID(); @@ -1191,11 +1110,6 @@ void LLPanelPeople::onDeleteFriendButtonClicked()  	}  } -void LLPanelPeople::onGroupInfoButtonClicked() -{ -	LLGroupActions::show(getCurrentItemID()); -} -  void LLPanelPeople::onChatButtonClicked()  {  	LLUUID group_id = getCurrentItemID(); @@ -1203,6 +1117,14 @@ void LLPanelPeople::onChatButtonClicked()  		LLGroupActions::startIM(group_id);  } +void LLPanelPeople::onGearButtonClicked(LLUICtrl* btn) +{ +	uuid_vec_t selected_uuids; +	getCurrentItemIDs(selected_uuids); +	// Spawn at bottom left corner of the button. +	LLPanelPeopleMenus::gNearbyMenu.show(btn, selected_uuids, 0, 0); +} +  void LLPanelPeople::onImButtonClicked()  {  	uuid_vec_t selected_uuids; @@ -1219,11 +1141,6 @@ void LLPanelPeople::onImButtonClicked()  	}  } -void LLPanelPeople::onActivateButtonClicked() -{ -	LLGroupActions::activate(mGroupList->getSelectedUUID()); -} -  // static  void LLPanelPeople::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAvatarName> names)  { @@ -1231,19 +1148,15 @@ void LLPanelPeople::onAvatarPicked(const uuid_vec_t& ids, const std::vector<LLAv  		LLAvatarActions::requestFriendshipDialog(ids[0], names[0].getCompleteName());  } -void LLPanelPeople::onGroupPlusButtonClicked() +bool LLPanelPeople::onGroupPlusButtonValidate()  {  	if (!gAgent.canJoinGroups())  	{  		LLNotificationsUtil::add("JoinedTooManyGroups"); -		return; +		return false;  	} -	LLMenuGL* plus_menu = (LLMenuGL*)mGroupPlusMenuHandle.get(); -	if (!plus_menu) -		return; - -	showGroupMenu(plus_menu); +	return true;  }  void LLPanelPeople::onGroupMinusButtonClicked() @@ -1288,10 +1201,6 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)  		mAllFriendList->showPermissions(show_permissions);  		mOnlineFriendList->showPermissions(show_permissions);  	} -	else if (chosen_item == "panel_block_list_sidetray") -	{ -		LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); -	}  }  void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata) @@ -1324,10 +1233,6 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)  	{  		setSortOrder(mNearbyList, E_SORT_BY_DISTANCE);  	} -	else if (chosen_item == "panel_block_list_sidetray") -	{ -		LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); -	}  }  bool LLPanelPeople::onNearbyViewSortMenuItemCheck(const LLSD& userdata) @@ -1361,10 +1266,6 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata)  	{  		mRecentList->toggleIcons();  	} -	else if (chosen_item == "panel_block_list_sidetray") -	{ -		LLFloaterSidePanelContainer::showPanel("people", "panel_block_list_sidetray", LLSD()); -	}  }  bool LLPanelPeople::onFriendsViewSortMenuItemCheck(const LLSD& userdata)  @@ -1393,40 +1294,6 @@ bool LLPanelPeople::onRecentViewSortMenuItemCheck(const LLSD& userdata)  	return false;  } -void LLPanelPeople::onCallButtonClicked() -{ -	uuid_vec_t selected_uuids; -	getCurrentItemIDs(selected_uuids); - -	if (selected_uuids.size() == 1) -	{ -		// initiate a P2P voice chat with the selected user -		LLAvatarActions::startCall(getCurrentItemID()); -	} -	else if (selected_uuids.size() > 1) -	{ -		// initiate an ad-hoc voice chat with multiple users -		LLAvatarActions::startAdhocCall(selected_uuids); -	} -} - -void LLPanelPeople::onGroupCallButtonClicked() -{ -	LLGroupActions::startCall(getCurrentItemID()); -} - -void LLPanelPeople::onTeleportButtonClicked() -{ -	uuid_vec_t selected_uuids; -	getCurrentItemIDs(selected_uuids); -	LLAvatarActions::offerTeleport(selected_uuids); -} - -void LLPanelPeople::onShareButtonClicked() -{ -	LLAvatarActions::share(getCurrentItemID()); -} -  void LLPanelPeople::onMoreButtonClicked()  {  	// *TODO: not implemented yet diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 46c58cd139..da27f83074 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -80,31 +80,22 @@ private:  	std::string				getActiveTabName() const;  	LLUUID					getCurrentItemID() const;  	void					getCurrentItemIDs(uuid_vec_t& selected_uuids) const; -	void					buttonSetVisible(std::string btn_name, BOOL visible); -	void					buttonSetEnabled(const std::string& btn_name, bool enabled); -	void					buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb);  	void					showGroupMenu(LLMenuGL* menu);  	void					setSortOrder(LLAvatarList* list, ESortOrder order, bool save = true);  	// UI callbacks  	void					onFilterEdit(const std::string& search_string);  	void					onTabSelected(const LLSD& param); -	void					onViewProfileButtonClicked();  	void					onAddFriendButtonClicked();  	void					onAddFriendWizButtonClicked();  	void					onDeleteFriendButtonClicked(); -	void					onGroupInfoButtonClicked();  	void					onChatButtonClicked(); +	void					onGearButtonClicked(LLUICtrl* btn);  	void					onImButtonClicked(); -	void					onCallButtonClicked(); -	void					onGroupCallButtonClicked(); -	void					onTeleportButtonClicked(); -	void					onShareButtonClicked();  	void					onMoreButtonClicked(); -	void					onActivateButtonClicked();  	void					onAvatarListDoubleClicked(LLUICtrl* ctrl);  	void					onAvatarListCommitted(LLAvatarList* list); -	void					onGroupPlusButtonClicked(); +	bool					onGroupPlusButtonValidate();  	void					onGroupMinusButtonClicked();  	void					onGroupPlusMenuItemClicked(const LLSD& userdata); @@ -113,8 +104,6 @@ private:  	void					onGroupsViewSortMenuItemClicked(const LLSD& userdata);  	void					onRecentViewSortMenuItemClicked(const LLSD& userdata); -	//returns false only if group is "none" -	bool					isRealGroup();  	bool					onFriendsViewSortMenuItemCheck(const LLSD& userdata);  	bool					onRecentViewSortMenuItemCheck(const LLSD& userdata);  	bool					onNearbyViewSortMenuItemCheck(const LLSD& userdata); @@ -135,7 +124,6 @@ private:  	bool					isAccordionCollapsedByUser(LLUICtrl* acc_tab);  	bool					isAccordionCollapsedByUser(const std::string& name); -	LLFilterEditor*			mFilterEditor;  	LLTabContainer*			mTabContainer;  	LLAvatarList*			mOnlineFriendList;  	LLAvatarList*			mAllFriendList; @@ -144,24 +132,13 @@ private:  	LLGroupList*			mGroupList;  	LLNetMap*				mMiniMap; -	LLHandle<LLView>		mGroupPlusMenuHandle; -	LLHandle<LLView>		mNearbyViewSortMenuHandle; -	LLHandle<LLView>		mFriendsViewSortMenuHandle; -	LLHandle<LLView>		mGroupsViewSortMenuHandle; -	LLHandle<LLView>		mRecentViewSortMenuHandle; +	std::vector<std::string> mSavedOriginalFilters; +	std::vector<std::string> mSavedFilters;  	Updater*				mFriendListUpdater;  	Updater*				mNearbyListUpdater;  	Updater*				mRecentListUpdater;  	Updater*				mButtonsUpdater; - -	LLMenuButton*			mNearbyGearButton; -	LLMenuButton*			mFriendsGearButton; -	LLMenuButton*			mGroupsGearButton; -	LLMenuButton*			mRecentGearButton; - -	std::string				mFilterSubString; -	std::string				mFilterSubStringOrig;  };  #endif //LL_LLPANELPEOPLE_H diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index f12c4de2f7..c84790d839 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -51,6 +51,7 @@ LLContextMenu* NearbyMenu::createMenu()  	// set up the callbacks for all of the avatar menu items  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;  	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; +	LLContextMenu* menu;  	if ( mUUIDs.size() == 1 )  	{ @@ -67,12 +68,13 @@ LLContextMenu* NearbyMenu::createMenu()  		registrar.add("Avatar.Share",			boost::bind(&LLAvatarActions::share,					id));  		registrar.add("Avatar.Pay",				boost::bind(&LLAvatarActions::pay,						id));  		registrar.add("Avatar.BlockUnblock",	boost::bind(&LLAvatarActions::toggleBlock,				id)); +		registrar.add("Avatar.InviteToGroup",	boost::bind(&LLAvatarActions::inviteToGroup,			id));  		enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem,	this, _2));  		enable_registrar.add("Avatar.CheckItem",  boost::bind(&NearbyMenu::checkContextMenuItem,	this, _2));  		// create the context menu from the XUI -		return createFromFile("menu_people_nearby.xml"); +		menu = createFromFile("menu_people_nearby.xml");  	}  	else  	{ @@ -88,8 +90,10 @@ LLContextMenu* NearbyMenu::createMenu()  		enable_registrar.add("Avatar.EnableItem",	boost::bind(&NearbyMenu::enableContextMenuItem,	this, _2));  		// create the context menu from the XUI -		return createFromFile("menu_people_nearby_multiselect.xml"); +		menu = createFromFile("menu_people_nearby_multiselect.xml");  	} + +    return menu;  }  bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 975a6c67d8..59d26edff2 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -32,6 +32,7 @@  #include "llagent.h"  #include "llimview.h" +#include "llpanelpeoplemenus.h"  #include "llnotificationsutil.h"  #include "llparticipantlist.h"  #include "llspeakers.h" @@ -197,10 +198,10 @@ private:  	uuid_set_t mAvalineCallers;  }; -LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,  +LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,  									 LLAvatarList* avatar_list,  									 bool use_context_menu/* = true*/, -									 bool exclude_agent /*= true*/,  +									 bool exclude_agent /*= true*/,  									 bool can_toggle_icons /*= true*/) :  	mSpeakerMgr(data_source),  	mAvatarList(avatar_list), @@ -233,8 +234,9 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source,  	if (use_context_menu)  	{ -		mParticipantListMenu = new LLParticipantListMenu(*this); -		mAvatarList->setContextMenu(mParticipantListMenu); +		//mParticipantListMenu = new LLParticipantListMenu(*this); +		//mAvatarList->setContextMenu(mParticipantListMenu); +		mAvatarList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);  	}  	else  	{ @@ -670,7 +672,7 @@ bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::  	return mParent.onSpeakerMuteEvent(event, userdata);  } -LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu() +/*LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  {  	// set up the callbacks for all of the avatar menu items  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -708,7 +710,7 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()  	main_menu->arrangeAndClear();  	return main_menu; -} +}*/  void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y)  { diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 88727bf59b..29eb5ce69e 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -305,7 +305,11 @@ BOOL LLFloaterScriptSearch::handleKeyHere(KEY key, MASK mask)  {  	if (mEditorCore)  	{ -		return mEditorCore->handleKeyHere(key, mask); +		BOOL handled = mEditorCore->handleKeyHere(key, mask); +		if (!handled) +		{ +			LLFloater::handleKeyHere(key, mask); +		}  	}  	return FALSE; diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index d340b304ca..a4a0198305 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -253,12 +253,26 @@ void LLScreenChannel::addToast(const LLToast::Params& p)  {  	bool store_toast = false, show_toast = false; -	mDisplayToastsAlways ? show_toast = true : show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); +	if (mDisplayToastsAlways) +	{ +		show_toast = true; +	} +	else +	{ +		show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); +	}  	store_toast = !show_toast && p.can_be_stored && mCanStoreToasts;  	if(!show_toast && !store_toast)  	{ -		mRejectToastSignal(p.notif_id); +		LLNotificationPtr notification = LLNotifications::instance().find(p.notif_id); + +		if (notification && +			(!notification->canLogToIM() || !notification->hasFormElements())) +		{ +			// only cancel notification if it isn't being used in IM session +			LLNotifications::instance().cancel(notification); +		}  		return;  	} @@ -371,7 +385,7 @@ void LLScreenChannel::storeToast(ToastElem& toast_elem)  	const LLToast* toast = toast_elem.getToast();  	if (toast)  	{ -		mStoredToastList.push_back(toast_elem); +	mStoredToastList.push_back(toast_elem);  		mOnStoreToast(toast->getPanel(), toast->getNotificationID());  	}  } @@ -410,14 +424,14 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)  	LLToast* toast = it->getToast();  	if (toast)  	{ -		if(toast->getVisible()) -		{ -			// toast is already in channel -			return; -		} +	if(toast->getVisible()) +	{ +		// toast is already in channel +		return; +	} -		toast->setIsHidden(false); -		toast->startTimer(); +	toast->setIsHidden(false); +	toast->startTimer();  		mToastList.push_back(*it);  	} @@ -425,34 +439,12 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)  }  //-------------------------------------------------------------------------- -void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id) -{ -	// *TODO: may be remove this function -	std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - -	if( it == mStoredToastList.end() ) -		return; - -	const LLToast* toast = it->getToast(); -	if (toast) -	{ -		mRejectToastSignal(toast->getNotificationID()); -	} - -	// Call find() once more, because the mStoredToastList could have been changed -	// in mRejectToastSignal callback and the iterator could have become invalid. -	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); -	if (it != mStoredToastList.end()) -	{ -		mStoredToastList.erase(it); -	} -} - -//--------------------------------------------------------------------------  void LLScreenChannel::killToastByNotificationID(LLUUID id)  {  	// searching among toasts on a screen  	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); +	LLNotificationPtr notification = LLNotifications::instance().find(id); +	if (!notification) return;  	if( it != mToastList.end())  	{ @@ -465,42 +457,67 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id)  		//			the toast will be destroyed.  		if(toast && toast->isNotificationValid())  		{ -			mRejectToastSignal(toast->getNotificationID()); +			if (!notification->canLogToIM() || !notification->hasFormElements()) +			{ +				// only cancel notification if it isn't being used in IM session +				LLNotifications::instance().cancel(notification); +			}  		}  		else  		{ - -			deleteToast(toast); -			mToastList.erase(it); -			redrawToasts(); +			removeToastByNotificationID(id);  		} -		return;  	} - -	// searching among stored toasts -	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); - -	if (it != mStoredToastList.end()) +	else  	{ -		LLToast* toast = it->getToast(); -		if (toast) +		// searching among stored toasts +		it = find(mStoredToastList.begin(), mStoredToastList.end(), id); + +		if( it != mStoredToastList.end() )  		{ -			// send signal to a listener to let him perform some action on toast rejecting -			mRejectToastSignal(toast->getNotificationID()); -			deleteToast(toast); +			LLToast* toast = it->getToast(); +			if (toast) +			{ +				if (!notification->canLogToIM() || !notification->hasFormElements()) +				{ +					// only cancel notification if it isn't being used in IM session +					LLNotifications::instance().cancel(notification); +				} +				deleteToast(toast); +			} +		} +	 +		// Call find() once more, because the mStoredToastList could have been changed +		// via notification cancellation and the iterator could have become invalid. +		it = find(mStoredToastList.begin(), mStoredToastList.end(), id); +		if (it != mStoredToastList.end()) +		{ +			mStoredToastList.erase(it);  		}  	} +} + +void LLScreenChannel::removeToastByNotificationID(LLUUID id) +{ +	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), id); +	while( it != mToastList.end()) +	{ +		deleteToast(it->getToast()); +		mToastList.erase(it); +		redrawToasts(); +		// find next toast with matching id +		it = find(mToastList.begin(), mToastList.end(), id); +	} -	// Call find() once more, because the mStoredToastList could have been changed -	// in mRejectToastSignal callback and the iterator could have become invalid.  	it = find(mStoredToastList.begin(), mStoredToastList.end(), id);  	if (it != mStoredToastList.end())  	{ +		deleteToast(it->getToast());  		mStoredToastList.erase(it);  	} -  } +  void LLScreenChannel::killMatchedToasts(const Matcher& matcher)  {  	std::list<const LLToast*> to_delete = findToasts(matcher); @@ -521,11 +538,11 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)  		LLToast* toast = it->getToast();  		if (toast)  		{ -			LLPanel* old_panel = toast->getPanel(); -			toast->removeChild(old_panel); -			delete old_panel; -			toast->insertPanel(panel); -			toast->startTimer(); +		LLPanel* old_panel = toast->getPanel(); +		toast->removeChild(old_panel); +		delete old_panel; +		toast->insertPanel(panel); +		toast->startTimer();  		}  		redrawToasts();  	} @@ -679,7 +696,7 @@ void LLScreenChannel::showToastsCentre()  		return;  	} -	LLRect	toast_rect; +	LLRect	toast_rect;	  	S32		bottom = (getRect().mTop - getRect().mBottom)/2 + toast->getRect().getHeight()/2;  	std::vector<ToastElem>::reverse_iterator it; diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 56a9cf8b4b..e5f4807ab7 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -84,6 +84,7 @@ public:  	// kill or modify a toast by its ID  	virtual void		killToastByNotificationID(LLUUID id) {};  	virtual void		modifyToastNotificationByID(LLUUID id, LLSD data) {}; +	virtual void		removeToastByNotificationID(LLUUID id){};  	// hide all toasts from screen, but not remove them from a channel  	virtual void		hideToastsFromScreen() {}; @@ -175,6 +176,7 @@ public:  	void		addToast(const LLToast::Params& p);  	// kill or modify a toast by its ID  	void		killToastByNotificationID(LLUUID id); +	void		removeToastByNotificationID(LLUUID id);  	void		killMatchedToasts(const Matcher& matcher);  	void		modifyToastByNotificationID(LLUUID id, LLPanel* panel);  	// hide all toasts from screen, but not remove them from a channel @@ -195,8 +197,6 @@ public:  	void		loadStoredToastsToChannel();  	// finds a toast among stored by its Notification ID and throws it on a screen to a channel  	void		loadStoredToastByNotificationIDToChannel(LLUUID id); -	// removes a toast from stored finding it by its Notification ID  -	void		removeStoredToastByNotificationID(LLUUID id);  	// removes from channel all toasts that belongs to the certain IM session   	void		removeToastsBySessionID(LLUUID id);  	// remove all storable toasts from screen and store them @@ -227,16 +227,12 @@ public:  	// Channel's signals  	// signal on storing of faded toasts event -	typedef boost::function<void (LLPanel* info_panel, const LLUUID id)> store_tost_callback_t; -	typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_tost_signal_t; -	store_tost_signal_t mOnStoreToast;	 -	boost::signals2::connection setOnStoreToastCallback(store_tost_callback_t cb) { return mOnStoreToast.connect(cb); } -	// signal on rejecting of a toast event -	typedef boost::function<void (LLUUID id)> reject_tost_callback_t; -	typedef boost::signals2::signal<void (LLUUID id)> reject_tost_signal_t; -	reject_tost_signal_t mRejectToastSignal; boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); } +	typedef boost::signals2::signal<void (LLPanel* info_panel, const LLUUID id)> store_toast_signal_t; +	boost::signals2::connection addOnStoreToastCallback(store_toast_signal_t::slot_type cb) { return mOnStoreToast.connect(cb); }  private: +	store_toast_signal_t mOnStoreToast;	 +  	class ToastElem  	{  	public: diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 5d196a465f..1333862855 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2774,7 +2774,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)  void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color)  { -	gGL.diffuseColor4fv(color.mV); +	gGL.color4fv(color.mV);  	gGL.begin(LLRender::LINES);  	{  		gGL.vertex3fv((position - LLVector3(size, 0.f, 0.f)).mV); @@ -3904,7 +3904,7 @@ void renderAgentTarget(LLVOAvatar* avatar)  	if (avatar->isSelf())  	{  		renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); -		renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f)); +		renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 0, 0.8f));  		renderCrossHairs(avatar->mRoot.getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f));  		renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f));  	} diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index b9358cf37c..1c6f51e131 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -29,7 +29,6 @@  #include "llevent.h"  #include "lleventtimer.h" -#include "llspeakers.h"  #include "llvoicechannel.h"  class LLSpeakerMgr; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 0ac8c1fe39..2f13ba5ab1 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1376,15 +1376,6 @@ bool idle_startup()  		LLVoiceClient::getInstance()->updateSettings();  		display_startup(); -		//gCacheName is required for nearby chat history loading -		//so I just moved nearby history loading a few states further -		if (gSavedPerAccountSettings.getBOOL("LogShowHistory")) -		{ -			LLNearbyChat* nearby_chat = LLNearbyChat::getInstance(); -			if (nearby_chat) nearby_chat->loadHistory(); -		} -		display_startup(); -  		// *Note: this is where gWorldMap used to be initialized.  		// register null callbacks for audio until the audio system is initialized diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 0cb6c85012..18e0d9d0d2 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -433,13 +433,19 @@ BOOL LLIMWellWindow::ObjectRowPanel::handleRightMouseDown(S32 x, S32 y, MASK mas  //////////////////////////////////////////////////////////////////////////  // PUBLIC METHODS +LLNotificationWellWindow::WellNotificationChannel::WellNotificationChannel(LLNotificationWellWindow* well_window) +:	LLNotificationChannel(LLNotificationChannel::Params().name(well_window->getPathname())), +	mWellWindow(well_window) +{ +	connectToChannel("Notifications"); +	connectToChannel("Group Notifications"); +	connectToChannel("Offer"); +} +  LLNotificationWellWindow::LLNotificationWellWindow(const LLSD& key) -: LLSysWellWindow(key) +:	LLSysWellWindow(key)  { -	// init connections to the list's update events -	connectListUpdaterToSignal("notify"); -	connectListUpdaterToSignal("groupnotify"); -	connectListUpdaterToSignal("offer"); +	mNotificationUpdates.reset(new WellNotificationChannel(this));  }  // static @@ -519,7 +525,7 @@ void LLNotificationWellWindow::initChannel()  	LLSysWellWindow::initChannel();  	if(mChannel)  	{ -		mChannel->setOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2)); +		mChannel->addOnStoreToastCallback(boost::bind(&LLNotificationWellWindow::onStoreToast, this, _1, _2));  	}  } @@ -546,20 +552,6 @@ void LLNotificationWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id)  	addItem(p);  } -void LLNotificationWellWindow::connectListUpdaterToSignal(std::string notification_type) -{ -	LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); -	LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); -	if(n_handler) -	{ -		n_handler->setNotificationIDCallback(boost::bind(&LLNotificationWellWindow::removeItemByID, this, _1)); -	} -	else -	{ -		llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl; -	} -} -  void LLNotificationWellWindow::onItemClick(LLSysWellItem* item)  {  	LLUUID id = item->getID(); @@ -574,6 +566,12 @@ void LLNotificationWellWindow::onItemClose(LLSysWellItem* item)  		mChannel->killToastByNotificationID(id);  } +void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) +{ +	removeItemByID(notify->getID()); +} + +  /************************************************************************/ @@ -867,4 +865,4 @@ bool LLIMWellWindow::confirmCloseAll(const LLSD& notification, const LLSD& respo  	return false;  } -// EOF + diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 272e9cfcb1..f497f546aa 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -34,6 +34,7 @@  #include "llscreenchannel.h"  #include "llscrollcontainer.h"  #include "llimview.h" +#include "llnotifications.h"  #include "boost/shared_ptr.hpp" @@ -111,7 +112,7 @@ public:  	/*virtual*/ BOOL postBuild();  	/*virtual*/ void setVisible(BOOL visible); - +	/*virtual*/ void onAdd(LLNotificationPtr notify);  	// Operating with items  	void addItem(LLSysWellItem::Params p); @@ -119,6 +120,18 @@ public:  	void closeAll();  protected: +	struct WellNotificationChannel : public LLNotificationChannel +	{ +		WellNotificationChannel(LLNotificationWellWindow*); +		void onDelete(LLNotificationPtr notify) +		{ +			mWellWindow->removeItemByID(notify->getID()); +		}  + +		LLNotificationWellWindow* mWellWindow; +	}; + +	LLNotificationChannelPtr mNotificationUpdates;  	/*virtual*/ const std::string& getAnchorViewName() { return NOTIFICATION_WELL_ANCHOR_NAME; }  private: @@ -126,12 +139,8 @@ private:  	void initChannel();  	void clearScreenChannels(); -  	void onStoreToast(LLPanel* info_panel, LLUUID id); -	// connect counter and list updaters to the corresponding signals -	void connectListUpdaterToSignal(std::string notification_type); -  	// Handlers  	void onItemClick(LLSysWellItem* item);  	void onItemClose(LLSysWellItem* item); diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index e1d99b1bcb..ea62f758f8 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -169,6 +169,7 @@ public:  	// get/set Toast's flags or states  	// get information whether the notification corresponding to the toast is valid or not  	bool isNotificationValid(); +  	// get toast's Notification ID  	const LLUUID getNotificationID() const { return mNotificationID;}  	// get toast's Session ID @@ -212,7 +213,7 @@ private:  	//LLRootHandle<LLToast>	mHandle; -	LLPanel* mWrapperPanel; +	LLPanel*	 mWrapperPanel;  	// timer counts a lifetime of a toast  	std::auto_ptr<LLToastLifeTimer> mTimer; @@ -220,8 +221,8 @@ private:  	F32			mToastLifetime; // in seconds  	F32			mToastFadingTime; // in seconds -	LLPanel*		mPanel; -	LLButton*		mHideBtn; +	LLPanel*	mPanel; +	LLButton*	mHideBtn;  	LLColor4	mBgColor;  	bool		mCanFade; diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 75178a6ef8..707d2d9765 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -51,7 +51,7 @@  const S32 LLToastGroupNotifyPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT	= 7; -LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification) +LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(const LLNotificationPtr& notification)  :	LLToastPanel(notification),  	mInventoryOffer(NULL)  { diff --git a/indra/newview/lltoastgroupnotifypanel.h b/indra/newview/lltoastgroupnotifypanel.h index 7794ec9f63..dfdc6ae559 100644 --- a/indra/newview/lltoastgroupnotifypanel.h +++ b/indra/newview/lltoastgroupnotifypanel.h @@ -47,13 +47,10 @@ class LLToastGroupNotifyPanel  public:  	void close(); -	static bool onNewNotification(const LLSD& notification); - -  	// Non-transient messages.  You can specify non-default button  	// layouts (like one for script dialogs) by passing various  	// numbers in for "layout". -	LLToastGroupNotifyPanel(LLNotificationPtr& notification); +	LLToastGroupNotifyPanel(const LLNotificationPtr& notification);  	/*virtual*/ ~LLToastGroupNotifyPanel();  protected: diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index a803387576..279dd69bc7 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -41,11 +41,11 @@ public:  	struct Params  	{  		LLNotificationPtr	notification; -		LLUUID				avatar_id; -		LLUUID				session_id; -		std::string			from; -		std::string			time; -		std::string			message; +		LLUUID				avatar_id, +							session_id; +		std::string			from, +							time, +							message;  		Params() {}  	}; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index a8060649ba..807d8e03d9 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -45,6 +45,9 @@  const S32 BOTTOM_PAD = VPAD * 3;  const S32 IGNORE_BTN_TOP_DELTA = 3*VPAD;//additional ignore_btn padding  S32 BUTTON_WIDTH = 90; +// *TODO: magic numbers(???) - copied from llnotify.cpp(250) +const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;  +  //static  const LLFontGL* LLToastNotifyPanel::sFont = NULL; @@ -52,171 +55,11 @@ const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;  LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal; -LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification, const LLRect& rect, bool show_images) :  -LLToastPanel(notification), -mTextBox(NULL), -mInfoPanel(NULL), -mControlPanel(NULL), -mNumOptions(0), -mNumButtons(0), -mAddedDefaultBtn(false), -mCloseNotificationOnDestroy(true) +LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images)  +:	LLToastPanel(notification), +	LLInstanceTracker<LLToastNotifyPanel, LLUUID>(notification->getID())  { -	buildFromFile( "panel_notification.xml"); -	if(rect != LLRect::null) -	{ -		this->setShape(rect); -	}		  -	mInfoPanel = getChild<LLPanel>("info_panel"); -	mControlPanel = getChild<LLPanel>("control_panel"); -	BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); -	// customize panel's attributes -	// is it intended for displaying a tip? -	mIsTip = notification->getType() == "notifytip"; -	// is it a script dialog? -	mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup"); -	// is it a caution? -	// -	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the -	// notify xml template specifies that it is a caution -	// tip-style notification handle 'caution' differently -they display the tip in a different color -	mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; - -	// setup parameters -	// get a notification message -	mMessage = notification->getMessage(); -	// init font variables -	if (!sFont) -	{ -		sFont = LLFontGL::getFontSansSerif(); -		sFontSmall = LLFontGL::getFontSansSerifSmall(); -	} -	// initialize -	setFocusRoot(!mIsTip); -	// get a form for the notification -	LLNotificationFormPtr form(notification->getForm()); -	// get number of elements -	mNumOptions = form->getNumElements(); - -	// customize panel's outfit -	// preliminary adjust panel's layout -	//move to the end  -	//mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); - -	// adjust text options according to the notification type -	// add a caution textbox at the top of a caution notification -	if (mIsCaution && !mIsTip) -	{ -		mTextBox = getChild<LLTextBox>("caution_text_box"); -	} -	else -	{ -		mTextBox = getChild<LLTextEditor>("text_editor_box");  -	} - -	// *TODO: magic numbers(???) - copied from llnotify.cpp(250) -	const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;  - -	mTextBox->setMaxTextLength(MAX_LENGTH); -	mTextBox->setVisible(TRUE); -	mTextBox->setPlainText(!show_images); -	mTextBox->setValue(notification->getMessage()); - -	// add buttons for a script notification -	if (mIsTip) -	{ -		adjustPanelForTipNotice(); -	} -	else -	{ -		std::vector<index_button_pair_t> buttons; -		buttons.reserve(mNumOptions); -		S32 buttons_width = 0; -		// create all buttons and accumulate they total width to reshape mControlPanel -		for (S32 i = 0; i < mNumOptions; i++) -		{ -			LLSD form_element = form->getElement(i); -			if (form_element["type"].asString() != "button") -			{ -				// not a button. -				continue; -			} -			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) -			{ -				// a textbox pretending to be a button. -				continue; -			} -			LLButton* new_button = createButton(form_element, TRUE); -			buttons_width += new_button->getRect().getWidth(); -			S32 index = form_element["index"].asInteger(); -			buttons.push_back(index_button_pair_t(index,new_button)); -		} -		if (buttons.empty()) -		{ -			addDefaultButton(); -		} -		else -		{ -			const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel -			S32 button_panel_height = mControlPanel->getRect().getHeight(); -			//try get an average h_pad to spread out buttons -			S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); -			if(h_pad < 2*HPAD) -			{ -				/* -				 * Probably it is a scriptdialog toast -				 * for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. -				 * In last case set default h_pad to avoid heaping of buttons  -				 */ -				S32 button_per_row = button_panel_width / BUTTON_WIDTH; -				h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1  because we do not need space after last button in a row    -				if(h_pad < 2*HPAD) // still not enough space between buttons ? -				{ -					h_pad = 2*HPAD; -				} -			} -			if (mIsScriptDialog) -			{ -				// we are using default width for script buttons so we can determinate button_rows -				//to get a number of rows we divide the required width of the buttons to button_panel_width -				S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); -				//S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; -				//reserve one row for the ignore_btn -				button_rows++; -				//calculate required panel height for scripdialog notification. -				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; -			} -			else -			{ -				// in common case buttons can have different widths so we need to calculate button_rows according to buttons_width -				//S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); -				S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); -				//calculate required panel height  -				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ BOTTOM_PAD; -			} -		 -			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed -			adjustPanelForScriptNotice(button_panel_width, button_panel_height); -			updateButtonsLayout(buttons, h_pad); -			// save buttons for later use in disableButtons() -			mButtons.assign(buttons.begin(), buttons.end()); -		} -	} -	// adjust panel's height to the text size -	mInfoPanel->setFollowsAll(); -	snapToMessageHeight(mTextBox, MAX_LENGTH); - -	if(notification->isReusable()) -	{ -		mButtonClickConnection = sButtonClickSignal.connect( -			boost::bind(&LLToastNotifyPanel::onToastPanelButtonClicked, this, _1, _2)); - -		if(notification->isRespondedTo()) -		{ -			// User selected an option in toast, now disable required buttons in IM window -			disableRespondedOptions(notification); -		} -	} +	init(rect, show_images);  }  void LLToastNotifyPanel::addDefaultButton()  { @@ -235,7 +78,6 @@ void LLToastNotifyPanel::addDefaultButton()  }  LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_option)  { -  	InstanceAndS32* userdata = new InstanceAndS32;  	userdata->mSelf = this;  	userdata->mButtonName = is_option ? form_element["name"].asString() : ""; @@ -245,14 +87,15 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt  	LLButton::Params p;  	bool make_small_btn = form_element["index"].asInteger() == -1 || form_element["index"].asInteger() == -2;  	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.font(font); +	p.name = form_element["name"].asString(); +	p.label = form_element["text"].asString(); +	p.font = font;  	p.rect.height = BTN_HEIGHT;  	p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata));  	p.rect.width = BUTTON_WIDTH;  	p.auto_resize = false;  	p.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); +	p.enabled = !form_element.has("enabled") || form_element["enabled"].asBoolean();  	if (mIsCaution)  	{  		p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); @@ -287,14 +130,9 @@ LLToastNotifyPanel::~LLToastNotifyPanel()  	mButtonClickConnection.disconnect();  	std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); -	if (mCloseNotificationOnDestroy && LLNotificationsUtil::find(mNotification->getID()) != NULL) +	if (mIsTip)  	{ -		// let reusable notification be deleted -		mNotification->setReusable(false); -		if (!mNotification->isPersistent()) -		{ -			LLNotifications::getInstance()->cancel(mNotification); -		} +		LLNotifications::getInstance()->cancel(mNotification);  	}  } @@ -393,103 +231,103 @@ void LLToastNotifyPanel::adjustPanelForTipNotice()  	}  } -typedef std::set<std::string> button_name_set_t; -typedef std::map<std::string, button_name_set_t> disable_button_map_t; - -disable_button_map_t initUserGiveItemDisableButtonMap() -{ -	// see EXT-5905 for disable rules - -	disable_button_map_t disable_map; -	button_name_set_t buttons; - -	buttons.insert("Show"); -	disable_map.insert(std::make_pair("Show", buttons)); - -	buttons.insert("Discard"); -	disable_map.insert(std::make_pair("Discard", buttons)); - -	buttons.insert("Mute"); -	disable_map.insert(std::make_pair("Mute", buttons)); - -	return disable_map; -} - -disable_button_map_t initTeleportOfferedDisableButtonMap() -{ -	disable_button_map_t disable_map; -	button_name_set_t buttons; - -	buttons.insert("Teleport"); -	buttons.insert("Cancel"); - -	disable_map.insert(std::make_pair("Teleport", buttons)); -	disable_map.insert(std::make_pair("Cancel", buttons)); - -	return disable_map; -} - -disable_button_map_t initFriendshipOfferedDisableButtonMap() -{ -	disable_button_map_t disable_map; -	button_name_set_t buttons; - -	buttons.insert("Accept"); -	buttons.insert("Decline"); - -	disable_map.insert(std::make_pair("Accept", buttons)); -	disable_map.insert(std::make_pair("Decline", buttons)); - -	return disable_map; -} - -button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) -{ -	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); -	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); -	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); - -	disable_button_map_t::const_iterator it; -	disable_button_map_t::const_iterator it_end; -	disable_button_map_t search_map; - -	if("UserGiveItem" == notification_name) -	{ -		search_map = user_give_item_disable_map; -	} -	else if("TeleportOffered" == notification_name) -	{ -		search_map = teleport_offered_disable_map; -	} -	else if("OfferFriendship" == notification_name) -	{ -		search_map = friendship_offered_disable_map; -	} - -	it = search_map.find(button_name); -	it_end = search_map.end(); - -	if(it_end != it) -	{ -		return it->second; -	} -	return button_name_set_t(); -} - -void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) -{ -	button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); - -	std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); -	for ( ; it != mButtons.end(); it++) -	{ -		LLButton* btn = it->second; -		if(buttons.find(btn->getName()) != buttons.end()) -		{ -			btn->setEnabled(FALSE); -		} -	} -} +//typedef std::set<std::string> button_name_set_t; +//typedef std::map<std::string, button_name_set_t> disable_button_map_t; +// +//disable_button_map_t initUserGiveItemDisableButtonMap() +//{ +//	// see EXT-5905 for disable rules +// +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Show"); +//	disable_map.insert(std::make_pair("Show", buttons)); +// +//	buttons.insert("Discard"); +//	disable_map.insert(std::make_pair("Discard", buttons)); +// +//	buttons.insert("Mute"); +//	disable_map.insert(std::make_pair("Mute", buttons)); +// +//	return disable_map; +//} +// +//disable_button_map_t initTeleportOfferedDisableButtonMap() +//{ +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Teleport"); +//	buttons.insert("Cancel"); +// +//	disable_map.insert(std::make_pair("Teleport", buttons)); +//	disable_map.insert(std::make_pair("Cancel", buttons)); +// +//	return disable_map; +//} +// +//disable_button_map_t initFriendshipOfferedDisableButtonMap() +//{ +//	disable_button_map_t disable_map; +//	button_name_set_t buttons; +// +//	buttons.insert("Accept"); +//	buttons.insert("Decline"); +// +//	disable_map.insert(std::make_pair("Accept", buttons)); +//	disable_map.insert(std::make_pair("Decline", buttons)); +// +//	return disable_map; +//} +// +//button_name_set_t getButtonDisableList(const std::string& notification_name, const std::string& button_name) +//{ +//	static disable_button_map_t user_give_item_disable_map = initUserGiveItemDisableButtonMap(); +//	static disable_button_map_t teleport_offered_disable_map = initTeleportOfferedDisableButtonMap(); +//	static disable_button_map_t friendship_offered_disable_map = initFriendshipOfferedDisableButtonMap(); +// +//	disable_button_map_t::const_iterator it; +//	disable_button_map_t::const_iterator it_end; +//	disable_button_map_t search_map; +// +//	if("UserGiveItem" == notification_name) +//	{ +//		search_map = user_give_item_disable_map; +//	} +//	else if("TeleportOffered" == notification_name) +//	{ +//		search_map = teleport_offered_disable_map; +//	} +//	else if("OfferFriendship" == notification_name) +//	{ +//		search_map = friendship_offered_disable_map; +//	} +// +//	it = search_map.find(button_name); +//	it_end = search_map.end(); +// +//	if(it_end != it) +//	{ +//		return it->second; +//	} +//	return button_name_set_t(); +//} + +//void LLToastNotifyPanel::disableButtons(const std::string& notification_name, const std::string& selected_button) +//{ +	//button_name_set_t buttons = getButtonDisableList(notification_name, selected_button); + +	//std::vector<index_button_pair_t>::const_iterator it = mButtons.begin(); +	//for ( ; it != mButtons.end(); it++) +	//{ +	//	LLButton* btn = it->second; +	//	if(buttons.find(btn->getName()) != buttons.end()) +	//	{ +	//		btn->setEnabled(FALSE); +	//	} +	//} +//}  // static  void LLToastNotifyPanel::onClickButton(void* data) @@ -504,99 +342,263 @@ void LLToastNotifyPanel::onClickButton(void* data)  		response[button_name] = true;  	} -	bool is_reusable = self->mNotification->isReusable(); -	// When we call respond(), LLOfferInfo will delete itself in inventory_offer_callback(),  -	// lets copy it while it's still valid. -	LLOfferInfo* old_info = static_cast<LLOfferInfo*>(self->mNotification->getResponder()); -	LLOfferInfo* new_info = NULL; -	if(is_reusable && old_info) +	// disable all buttons +	self->mControlPanel->setEnabled(FALSE); + +	// this might repost notification with new form data/enabled buttons +	self->mNotification->respond(response); +} + +void LLToastNotifyPanel::init( LLRect rect, bool show_images ) +{ +	deleteAllChildren(); + +	mTextBox = NULL; +	mInfoPanel = NULL; +	mControlPanel = NULL; +	mNumOptions = 0; +	mNumButtons = 0; +	mAddedDefaultBtn = false; + +	buildFromFile( "panel_notification.xml"); +	if(rect != LLRect::null)  	{ -		new_info = new LLOfferInfo(*old_info); -		self->mNotification->setResponder(new_info); +		this->setShape(rect); +	}		  +	mInfoPanel = getChild<LLPanel>("info_panel"); +	mInfoPanel->setFollowsAll(); + +	mControlPanel = getChild<LLPanel>("control_panel"); +	BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); +	// customize panel's attributes +	// is it intended for displaying a tip? +	mIsTip = mNotification->getType() == "notifytip"; +	// is it a script dialog? +	mIsScriptDialog = (mNotification->getName() == "ScriptDialog" || mNotification->getName() == "ScriptDialogGroup"); +	// is it a caution? +	// +	// caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the +	// notify xml template specifies that it is a caution +	// tip-style notification handle 'caution' differently -they display the tip in a different color +	mIsCaution = mNotification->getPriority() >= NOTIFICATION_PRIORITY_HIGH; + +	// setup parameters +	// get a notification message +	mMessage = mNotification->getMessage(); +	// init font variables +	if (!sFont) +	{ +		sFont = LLFontGL::getFontSansSerif(); +		sFontSmall = LLFontGL::getFontSansSerifSmall();  	} +	// initialize +	setFocusRoot(!mIsTip); +	// get a form for the notification +	LLNotificationFormPtr form(mNotification->getForm()); +	// get number of elements +	mNumOptions = form->getNumElements(); -	self->mNotification->respond(response); +	// customize panel's outfit +	// preliminary adjust panel's layout +	//move to the end  +	//mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); -	if(is_reusable) +	// adjust text options according to the notification type +	// add a caution textbox at the top of a caution notification +	if (mIsCaution && !mIsTip)  	{ -		sButtonClickSignal(self->mNotification->getID(), button_name); +		mTextBox = getChild<LLTextBox>("caution_text_box");  	}  	else  	{ -		// disable all buttons -		self->mControlPanel->setEnabled(FALSE); +		mTextBox = getChild<LLTextEditor>("text_editor_box");   	} -} -void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) -{ -	if(mNotification->getID() == notification_id) +	mTextBox->setMaxTextLength(MAX_LENGTH); +	mTextBox->setVisible(TRUE); +	mTextBox->setPlainText(!show_images); +	mTextBox->setValue(mNotification->getMessage()); + +	// add buttons for a script notification +	if (mIsTip)  	{ -		disableButtons(mNotification->getName(), btn_name); +		adjustPanelForTipNotice();  	} -} - -void LLToastNotifyPanel::disableRespondedOptions(LLNotificationPtr& notification) -{ -	LLSD response = notification->getResponse(); -	for (LLSD::map_const_iterator response_it = response.beginMap();  -		response_it != response.endMap(); ++response_it) +	else  	{ -		if (response_it->second.isBoolean() && response_it->second.asBoolean()) +		std::vector<index_button_pair_t> buttons; +		buttons.reserve(mNumOptions); +		S32 buttons_width = 0; +		// create all buttons and accumulate they total width to reshape mControlPanel +		for (S32 i = 0; i < mNumOptions; i++)  		{ -			// that after multiple responses there can be many pressed buttons -			// need to process them all -			disableButtons(notification->getName(), response_it->first); +			LLSD form_element = form->getElement(i); +			if (form_element["type"].asString() != "button") +			{ +				// not a button. +				continue; +			} +			if (form_element["name"].asString() == TEXTBOX_MAGIC_TOKEN) +			{ +				// a textbox pretending to be a button. +				continue; +			} +			LLButton* new_button = createButton(form_element, TRUE); +			buttons_width += new_button->getRect().getWidth(); +			S32 index = form_element["index"].asInteger(); +			buttons.push_back(index_button_pair_t(index,new_button)); +		} +		if (buttons.empty()) +		{ +			addDefaultButton(); +		} +		else +		{ +			const S32 button_panel_width = mControlPanel->getRect().getWidth();// do not change width of the panel +			S32 button_panel_height = mControlPanel->getRect().getHeight(); +			//try get an average h_pad to spread out buttons +			S32 h_pad = (button_panel_width - buttons_width) / (S32(buttons.size())); +			if(h_pad < 2*HPAD) +			{ +				/* +				* Probably it is a scriptdialog toast +				* for a scriptdialog toast h_pad can be < 2*HPAD if we have a lot of buttons. +				* In last case set default h_pad to avoid heaping of buttons  +				*/ +				S32 button_per_row = button_panel_width / BUTTON_WIDTH; +				h_pad = (button_panel_width % BUTTON_WIDTH) / (button_per_row - 1);// -1  because we do not need space after last button in a row    +				if(h_pad < 2*HPAD) // still not enough space between buttons ? +				{ +					h_pad = 2*HPAD; +				} +			} +			if (mIsScriptDialog) +			{ +				// we are using default width for script buttons so we can determinate button_rows +				//to get a number of rows we divide the required width of the buttons to button_panel_width +				S32 button_rows = llceil(F32(buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width); +				//S32 button_rows = (buttons.size() - 1) * (BUTTON_WIDTH + h_pad) / button_panel_width; +				//reserve one row for the ignore_btn +				button_rows++; +				//calculate required panel height for scripdialog notification. +				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ IGNORE_BTN_TOP_DELTA + BOTTOM_PAD; +			} +			else +			{ +				// in common case buttons can have different widths so we need to calculate button_rows according to buttons_width +				//S32 button_rows = llceil(F32(buttons.size()) * (buttons_width + h_pad) / button_panel_width); +				S32 button_rows = llceil(F32((buttons.size() - 1) * h_pad + buttons_width) / button_panel_width); +				//calculate required panel height  +				button_panel_height = button_rows * (BTN_HEIGHT + VPAD)	+ BOTTOM_PAD; +			} + +			// we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed +			adjustPanelForScriptNotice(button_panel_width, button_panel_height); +			updateButtonsLayout(buttons, h_pad); +			// save buttons for later use in disableButtons() +			//mButtons.assign(buttons.begin(), buttons.end());  		}  	} +	// adjust panel's height to the text size +	snapToMessageHeight(mTextBox, MAX_LENGTH);  } + +//void LLToastNotifyPanel::onToastPanelButtonClicked(const LLUUID& notification_id, const std::string btn_name) +//{ +//	if(mNotification->getID() == notification_id) +//	{ +//		disableButtons(mNotification->getName(), btn_name); +//	} +//} + +//void LLToastNotifyPanel::disableRespondedOptions(const LLNotificationPtr& notification) +//{ +//	LLSD response = notification->getResponse(); +//	for (LLSD::map_const_iterator response_it = response.beginMap();  +//		response_it != response.endMap(); ++response_it) +//	{ +//		if (response_it->second.isBoolean() && response_it->second.asBoolean()) +//		{ +//			// that after multiple responses there can be many pressed buttons +//			// need to process them all +//			disableButtons(notification->getName(), response_it->first); +//		} +//	} +//} + +  //////////////////////////////////////////////////////////////////////////  LLIMToastNotifyPanel::LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect /* = LLRect::null */, -										   bool show_images /* = true */) - : mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images) +										   bool show_images /* = true */, LLTextBase* parent_text) +:	mSessionID(session_id), LLToastNotifyPanel(pNotification, rect, show_images), +	mParentText(parent_text)  { -	mTextBox->setFollowsAll(); +	compactButtons();  }  LLIMToastNotifyPanel::~LLIMToastNotifyPanel()  { -	// We shouldn't delete notification when IM floater exists -	// since that notification will be reused by IM floater. -	// This may happened when IM floater reloads messages, exactly when user -	// changes layout of IM chat log(disable/enable plaintext mode). -	// See EXT-6500 -	LLIMFloater* im_floater = LLIMFloater::findInstance(mSessionID); -	if (im_floater != NULL && !im_floater->isDead()) -	{ -		mCloseNotificationOnDestroy = false; -	}  }  void LLIMToastNotifyPanel::reshape(S32 width, S32 height, BOOL called_from_parent /* = TRUE */)  { -	S32 text_height = mTextBox->getTextBoundingRect().getHeight(); -	S32 widget_height = mTextBox->getRect().getHeight(); -	S32 delta = text_height - widget_height; -	LLRect rc = getRect(); +	LLToastPanel::reshape(width, height, called_from_parent); -	rc.setLeftTopAndSize(rc.mLeft, rc.mTop, width, height + delta); -	height = rc.getHeight(); -	width = rc.getWidth(); +	snapToMessageHeight(mTextBox, MAX_LENGTH); +} -	bool is_width_changed = width != getRect().getWidth(); +void LLIMToastNotifyPanel::compactButtons() +{ +	mTextBox->setFollowsAll(); -	LLToastPanel::reshape(width, height, called_from_parent); +	//we can't set follows in xml since it broke toasts behavior +	setFollows(FOLLOWS_LEFT|FOLLOWS_RIGHT|FOLLOWS_TOP); -	// Notification height required to display the text message depends on -	// the width of the text box thus if panel width is changed the text box -	// width is also changed then reshape() is called to adjust proper height. -	if (is_width_changed) +	const child_list_t* children = getControlPanel()->getChildList(); +	S32 offset = 0; +	// Children were added by addChild() which uses push_front to insert them into list, +	// so to get buttons in correct order reverse iterator is used (EXT-5906)  +	for (child_list_t::const_reverse_iterator it = children->rbegin(); it != children->rend(); it++)  	{ -		reshape(width, height, called_from_parent); +		LLButton * button = dynamic_cast<LLButton*> (*it); +		if (button != NULL) +		{ +			button->setOrigin( offset,button->getRect().mBottom); +			button->setLeftHPad(2 * HPAD); +			button->setRightHPad(2 * HPAD); +			// set zero width before perform autoResize() +			button->setRect(LLRect(button->getRect().mLeft, +				button->getRect().mTop,  +				button->getRect().mLeft, +				button->getRect().mBottom)); +			button->setAutoResize(true); +			button->autoResize(); +			offset += HPAD + button->getRect().getWidth(); +			button->setFollowsNone(); +		}  	} + +	if (mParentText) +	{ +		mParentText->needsReflow(); +	} +} + +void LLIMToastNotifyPanel::updateNotification() +{ +	init(LLRect(), true); +} + +void LLIMToastNotifyPanel::init( LLRect rect, bool show_images ) +{ +	LLToastNotifyPanel::init(LLRect(), show_images); + +	compactButtons();  } +  // EOF + diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index 57711b3d80..f93c7745af 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -47,7 +47,7 @@ class LLNotificationForm;   * @deprecated this class will be removed after all toast panel types are   *  implemented in separate classes.   */ -class LLToastNotifyPanel: public LLToastPanel  +class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID>  {  public:  	/** @@ -60,11 +60,15 @@ public:  	 * @deprecated if you intend to instantiate LLToastNotifyPanel - it's point to  	 * implement right class for desired toast panel. @see LLGenericTipPanel as example.  	 */ -	LLToastNotifyPanel(LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); +	LLToastNotifyPanel(const LLNotificationPtr& pNotification, const LLRect& rect = LLRect::null, bool show_images = true); + +	virtual void init( LLRect rect, bool show_images ); +  	virtual ~LLToastNotifyPanel();  	LLPanel * getControlPanel() { return mControlPanel; } -	void setCloseNotificationOnDestroy(bool close) { mCloseNotificationOnDestroy = close; } +	virtual void updateNotification() {} +  protected:  	LLButton* createButton(const LLSD& form_element, BOOL is_option); @@ -76,8 +80,6 @@ protected:  	};  	std::vector<InstanceAndS32*> mBtnCallbackData; -	bool mCloseNotificationOnDestroy; -  	typedef std::pair<int,LLButton*> index_button_pair_t;   	void adjustPanelForScriptNotice(S32 max_width, S32 max_height);  	void adjustPanelForTipNotice(); @@ -93,9 +95,9 @@ protected:  	/**  	 * Disable specific button(s) based on notification name and clicked button  	 */ -	void disableButtons(const std::string& notification_name, const std::string& selected_button); +	//void disableButtons(const std::string& notification_name, const std::string& selected_button); -	std::vector<index_button_pair_t> mButtons; +	//std::vector<index_button_pair_t> mButtons;  	// panel elements  	LLTextBase*		mTextBox; @@ -118,7 +120,7 @@ protected:  	/**  	 * Process response data. Will disable selected options  	 */ -	void disableRespondedOptions(LLNotificationPtr& notification); +	//void disableRespondedOptions(const LLNotificationPtr& notification);  	bool mIsTip;  	bool mAddedDefaultBtn; @@ -137,13 +139,23 @@ class LLIMToastNotifyPanel : public LLToastNotifyPanel  {  public: -	LLIMToastNotifyPanel(LLNotificationPtr& pNotification, const LLUUID& session_id, const LLRect& rect = LLRect::null, bool show_images = true); +	LLIMToastNotifyPanel(LLNotificationPtr& pNotification,  +						const LLUUID& session_id,  +						const LLRect& rect = LLRect::null,  +						bool show_images = true,  +						LLTextBase* parent_text = NULL); + +	void compactButtons(); + +	virtual void updateNotification(); +	virtual void init( LLRect rect, bool show_images );  	~LLIMToastNotifyPanel();  	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);  protected: +	LLTextBase* mParentText;  	LLUUID	mSessionID;  }; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index d2a4ce8745..e20d516392 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -78,11 +78,14 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)  		S32 requiredTextHeight = message->getTextBoundingRect().getHeight();  		S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight); -		//Calculate last delta height deducting previous heightDelta  -		heightDelta = newTextHeight - oldTextHeight - heightDelta; +		heightDelta = newTextHeight - oldTextHeight; +		S32 new_panel_height = llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT);  		//reshape the panel with new height -		reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT)); +		if (new_panel_height != getRect().getHeight()) +		{ +			reshape( getRect().getWidth(), new_panel_height); +		}  	}  } @@ -96,7 +99,7 @@ LLToastPanel* LLToastPanel::buidPanelFromNotification(  	if ("notifytip" == notification->getType())  	{  		// if it is online/offline notification -		if ("FriendOffline" == notification->getName() || "FriendOnline" == notification->getName()) +		if ("FriendOnlineOffline" == notification->getName())  		{  			res = new LLPanelOnlineStatus(notification);  		} diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index 346e014d73..c22557206b 100644 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -33,19 +33,13 @@  #include <string> -class LLToastPanelBase: public LLPanel  -{ -public: -	virtual void init(LLSD& data){}; -}; -  /**   * Base class for all panels that can be added to the toast.   * All toast panels should contain necessary logic for representing certain notification   * but shouldn't contain logic related to this panel lifetime control and positioning   * on the parent view.   */ -class LLToastPanel: public LLPanel { +class LLToastPanel : public LLPanel {  public:  	LLToastPanel(const LLNotificationPtr&);  	virtual ~LLToastPanel() = 0; diff --git a/indra/newview/lltoastscripttextbox.h b/indra/newview/lltoastscripttextbox.h index 8e69d8834d..7d33446248 100644 --- a/indra/newview/lltoastscripttextbox.h +++ b/indra/newview/lltoastscripttextbox.h @@ -39,8 +39,6 @@ class LLToastScriptTextbox  public:  	void close(); -	static bool onNewNotification(const LLSD& notification); -  	// Non-transient messages.  You can specify non-default button  	// layouts (like one for script dialogs) by passing various  	// numbers in for "layout". diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 7fdaac68c8..df1962f5fe 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -110,6 +110,7 @@  #include "llfloatertranslationsettings.h"  #include "llfloateruipreview.h"  #include "llfloatervoiceeffect.h" +#include "llfloatervoicevolume.h"  #include "llfloaterwhitelistentry.h"  #include "llfloaterwindowsize.h"  #include "llfloaterworldmap.h" @@ -133,7 +134,6 @@  #include "llscriptfloater.h"  #include "llfloatermodelpreview.h"  #include "llcommandhandler.h" -#include "llnearbychatbar.h"  // *NOTE: Please add files in alphabetical order to keep merges easy. @@ -186,8 +186,6 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>);  	LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>); -	LLFloaterReg::add("chat_bar", "floater_chat_bar.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChatBar>); -  	LLFloaterReg::add("compile_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCompileQueue>);  	LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>); @@ -210,6 +208,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterReg::add("help_browser", "floater_help_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHelpBrowser>);	  	LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>); +	LLFloaterReg::add("chat_bar", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>);  	LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>);  	LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloaterContainer>);  	LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMWellWindow>); @@ -220,6 +219,7 @@ void LLViewerFloaterReg::registerFloaters()  	LLInspectGroupUtil::registerFloater();  	LLInspectObjectUtil::registerFloater();  	LLInspectRemoteObjectUtil::registerFloater(); +	LLFloaterVoiceVolumeUtil::registerFloater();  	LLNotificationsUI::registerFloater();  	LLFloaterDisplayNameUtil::registerFloater(); diff --git a/indra/newview/llviewergesture.cpp b/indra/newview/llviewergesture.cpp index a32a78cbf9..c7d37e102e 100644 --- a/indra/newview/llviewergesture.cpp +++ b/indra/newview/llviewergesture.cpp @@ -40,7 +40,7 @@  #include "llviewermessage.h" // send_guid_sound_trigger  #include "llviewernetwork.h"  #include "llagent.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  // Globals  LLViewerGestureList gGestureList; @@ -130,7 +130,7 @@ void LLViewerGesture::doTrigger( BOOL send_chat )  	{  		// Don't play nodding animation, since that might not blend  		// with the gesture animation. -		LLNearbyChatBar::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE); +		LLNearbyChat::getInstance()->sendChatFromViewer(mOutputString, CHAT_TYPE_NORMAL, FALSE);  	}  } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 1aa9fd8a45..385d3cd29a 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -31,7 +31,7 @@  #include "llmath.h"  #include "llagent.h"  #include "llagentcamera.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llviewercontrol.h"  #include "llfocusmgr.h"  #include "llmorphview.h" @@ -534,7 +534,7 @@ void stop_moving( EKeystate s )  void start_chat( EKeystate s )  {  	// start chat -	LLNearbyChatBar::startChat(NULL); +	LLNearbyChat::startChat(NULL);  }  void start_gesture( EKeystate s ) @@ -543,15 +543,15 @@ void start_gesture( EKeystate s )  	if (KEYSTATE_UP == s &&  		! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))  	{ - 		if (LLNearbyChatBar::getInstance()->getCurrentChat().empty()) + 		if (LLNearbyChat::getInstance()->getCurrentChat().empty())   		{   			// No existing chat in chat editor, insert '/' - 			LLNearbyChatBar::startChat("/"); + 			LLNearbyChat::startChat("/");   		}   		else   		{   			// Don't overwrite existing text in chat editor - 			LLNearbyChatBar::startChat(NULL); + 			LLNearbyChat::startChat(NULL);   		}  	}  } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 7481414b5c..903d7228e4 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3204,15 +3204,6 @@ bool enable_freeze_eject(const LLSD& avatar_id)  	return new_value;  } - -void login_done(S32 which, void *user) -{ -	llinfos << "Login done " << which << llendl; - -	LLPanelLogin::closePanel(); -} - -  bool callback_leave_group(const LLSD& notification, const LLSD& response)  {  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 854e2bea52..dd78bbd491 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -181,6 +181,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);  	LLMessageSystem* msg = gMessageSystem;  	const LLSD& payload = notification["payload"]; +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID());  	// add friend to recent people list  	LLRecentPeople::instance().add(payload["from_id"]); @@ -206,7 +207,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  		msg->sendReliable(LLHost(payload["sender"].asString()));  		LLSD payload = notification["payload"]; -		payload["SUPPRESS_TOAST"] = true;  		LLNotificationsUtil::add("FriendshipAcceptedByMe",  				notification["substitutions"], payload);  		break; @@ -214,7 +214,6 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  	case 1: // Decline  	{  		LLSD payload = notification["payload"]; -		payload["SUPPRESS_TOAST"] = true;  		LLNotificationsUtil::add("FriendshipDeclinedByMe",  				notification["substitutions"], payload);  	} @@ -243,6 +242,12 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)  		break;  	} +	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); +	modified_form->setElementEnabled("Accept", false); +	modified_form->setElementEnabled("Decline", false); +	notification_ptr->updateForm(modified_form); +	notification_ptr->repost(); +  	return false;  }  static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback); @@ -1152,7 +1157,7 @@ bool check_offer_throttle(const std::string& from_name, bool check_only)  		}  	}  } - +   // Return "true" if we have a preview method for that asset type, "false" otherwise  bool check_asset_previewable(const LLAssetType::EType asset_type)  { @@ -1475,16 +1480,16 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  		itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);  	} +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); +	llassert(notification_ptr != NULL); +	  	// For muting, we need to add the mute, then decline the offer.  	// This must be done here because:  	// * callback may be called immediately,  	// * adding the mute sends a message,  	// * we can't build two messages at once. -	if (2 == button) // Block +	if (IOR_MUTE == button) // Block  	{ -		LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); - -		llassert(notification_ptr != NULL);  		if (notification_ptr != NULL)  		{  			gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback, _1, _2, _3)); @@ -1499,6 +1504,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	bool busy = gAgent.getBusy(); +	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); +  	switch(button)  	{  	case IOR_SHOW: @@ -1542,6 +1549,8 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;  			break;  		} + +		modified_form->setElementEnabled("Show", false);  		break;  		// end switch (mIM) @@ -1554,9 +1563,11 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			args["MESSAGE"] = log_message;  			LLNotificationsUtil::add("SystemMessageTip", args);  		} +  		break;  	case IOR_MUTE: +		modified_form->setElementEnabled("Mute", false);  		// MUTE falls through to decline  	case IOR_DECLINE:  		{ @@ -1592,6 +1603,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  			{  				busy_message(gMessageSystem, mFromID);  			} + +			modified_form->setElementEnabled("Show", false); +			modified_form->setElementEnabled("Discard", false); +  			break;  		}  	default: @@ -1611,6 +1626,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&  	{  		delete this;  	} + +	notification_ptr->updateForm(modified_form); +	notification_ptr->repost(); +  	return false;  } @@ -1988,6 +2007,15 @@ bool lure_callback(const LLSD& notification, const LLSD& response)  					   lure_id);  		break;  	} + +	LLNotificationPtr notification_ptr = LLNotifications::instance().find(notification["id"].asUUID()); + +	LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); +	modified_form->setElementEnabled("Teleport", false); +	modified_form->setElementEnabled("Cancel", false); +	notification_ptr->updateForm(modified_form); +	notification_ptr->repost(); +  	return false;  }  static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback); @@ -2377,7 +2405,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;  			bool mute_im = is_muted; -			if (accept_im_from_only_friend && !is_friend) +			if(accept_im_from_only_friend&&!is_friend)  			{  				if (!gIMMgr->isNonFriendSessionNotified(session_id))  				{ @@ -2800,7 +2828,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  				chat.mOwnerID = from_id;  				LLSD args;  				args["slurl"] = location; -				args["type"] = LLNotificationsUI::NT_NEARBYCHAT;  				// Look for IRC-style emotes here so object name formatting is correct  				std::string prefix = message.substr(0, 4); @@ -3403,7 +3430,6 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)  		// pass owner_id to chat so that we can display the remote  		// object inspect for an object that is chatting with you  		LLSD args; -		args["type"] = LLNotificationsUI::NT_NEARBYCHAT;  		chat.mOwnerID = owner_id;  		if (gSavedSettings.getBOOL("TranslateChat") && chat.mSourceType != CHAT_SOURCE_SYSTEM) @@ -6400,7 +6426,6 @@ bool handle_lure_callback(const LLSD& notification, const LLSD& response)  				//*TODO please rewrite all keys to the same case, lower or upper  				payload["from_id"] = target_id; -				payload["SUPPRESS_TOAST"] = true;  				LLNotificationsUtil::add("TeleportOfferSent", args, payload);  				// Add the recepient to the recent people list. diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ecd76f5495..7f14e021fd 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -185,7 +185,7 @@  #include "llviewerjoystick.h"  #include "llviewernetwork.h"  #include "llpostprocess.h" -#include "llnearbychatbar.h" +#include "llnearbychat.h"  #include "llagentui.h"  #include "llwearablelist.h" @@ -1544,11 +1544,12 @@ LLViewerWindow::LLViewerWindow(const Params& p)  	// boost::lambda::var() constructs such a functor on the fly.  	mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard)));  	mViewerWindowListener.reset(new LLViewerWindowListener(this)); -	LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert")); -	LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); -	LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert); -	LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert); +	mAlertsChannel.reset(new LLNotificationChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"))); +	mModalAlertsChannel.reset(new LLNotificationChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"))); + +	mAlertsChannel->connectChanged(&LLViewerWindow::onAlert); +	mModalAlertsChannel->connectChanged(&LLViewerWindow::onAlert);  	LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications"));  	llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl; @@ -2487,7 +2488,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  	// Traverses up the hierarchy  	if( keyboard_focus )  	{ -		LLNearbyChatBar* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChatBar>("chat_bar"); +		LLNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLNearbyChat>("chat_bar");  		if (nearby_chat)  		{ @@ -2554,11 +2555,11 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  	if ( gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() &&   		!keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) )  	{ -		LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance<LLNearbyChatBar>("chat_bar")->getChatBox(); +		LLLineEditor* chat_editor = LLFloaterReg::getTypedInstance<LLNearbyChat>("chat_bar")->getChatBox();  		if (chat_editor)  		{  			// passing NULL here, character will be added later when it is handled by character handler. -			LLNearbyChatBar::getInstance()->startChat(NULL); +			LLNearbyChat::getInstance()->startChat(NULL);  			return TRUE;  		}  	} diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 6efcaeaf18..ee6a7793f8 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -418,6 +418,9 @@ private:  	bool			mActive;  	bool			mUIVisible; +	boost::shared_ptr<class LLNotificationChannel>	mAlertsChannel, +													mModalAlertsChannel; +  	LLRect			mWindowRectRaw;				// whole window, including UI  	LLRect			mWindowRectScaled;			// whole window, scaled by UI size  	LLRect			mWorldViewRectRaw;			// area of screen for 3D world diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index a7a4281860..82dadf1dc8 100644 --- 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 "llinitparam.h"  #include "llkeyframefallmotion.h"  #include "llkeyframestandmotion.h"  #include "llkeyframewalkmotion.h" @@ -189,6 +190,9 @@ const S32 MAX_BUBBLE_CHAT_LENGTH = DB_CHAT_MSG_STR_LEN;  const S32 MAX_BUBBLE_CHAT_UTTERANCES = 12;  const F32 CHAT_FADE_TIME = 8.0;  const F32 BUBBLE_CHAT_TIME = CHAT_FADE_TIME * 3.f; +const F32 NAMETAG_UPDATE_THRESHOLD = 0.3f; +const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f; +const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f;  const LLColor4 DUMMY_COLOR = LLColor4(0.5,0.5,0.5,1.0); @@ -220,55 +224,62 @@ struct LLTextureMaskData   **/  //------------------------------------------------------------------------ -// LLVOBoneInfo +// LLVOAvatarBoneInfo  // Trans/Scale/Rot etc. info about each avatar bone.  Used by LLVOAvatarSkeleton.  //------------------------------------------------------------------------ -class LLVOAvatarBoneInfo +struct LLVOAvatarCollisionVolumeInfo : public LLInitParam::Block<LLVOAvatarCollisionVolumeInfo>  { -	friend class LLVOAvatar; -	friend class LLVOAvatarSkeletonInfo; -public: -	LLVOAvatarBoneInfo() : mIsJoint(FALSE) {} -	~LLVOAvatarBoneInfo() -	{ -		std::for_each(mChildList.begin(), mChildList.end(), DeletePointer()); -	} -	BOOL parseXml(LLXmlTreeNode* node); +	LLVOAvatarCollisionVolumeInfo()  +	:	name("name"), +		pos("pos"), +		rot("rot"), +		scale("scale") +	{} + +	Mandatory<std::string>	name; +	Mandatory<LLVector3>	pos, +							rot, +							scale; +}; + +struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint> +{ +	Alternative<Lazy<struct LLVOAvatarBoneInfo, IS_A_BLOCK> >	bone; +	Alternative<LLVOAvatarCollisionVolumeInfo>		collision_volume; + +	LLVOAvatarChildJoint() +	:	bone("bone"), +		collision_volume("collision_volume") +	{} +}; + +struct LLVOAvatarBoneInfo : public LLInitParam::Block<LLVOAvatarBoneInfo, LLVOAvatarCollisionVolumeInfo> +{ +	LLVOAvatarBoneInfo()  +	:	pivot("pivot") +	{} -private: -	std::string mName; -	BOOL mIsJoint; -	LLVector3 mPos; -	LLVector3 mRot; -	LLVector3 mScale; -	LLVector3 mPivot; -	typedef std::vector<LLVOAvatarBoneInfo*> child_list_t; -	child_list_t mChildList; +	Mandatory<LLVector3>					pivot; +	Multiple<LLVOAvatarChildJoint>			children;  };  //------------------------------------------------------------------------  // LLVOAvatarSkeletonInfo  // Overall avatar skeleton  //------------------------------------------------------------------------ -class LLVOAvatarSkeletonInfo +struct LLVOAvatarSkeletonInfo : public LLInitParam::Block<LLVOAvatarSkeletonInfo>  { -	friend class LLVOAvatar; -public: -	LLVOAvatarSkeletonInfo() : -		mNumBones(0), mNumCollisionVolumes(0) {} -	~LLVOAvatarSkeletonInfo() -	{ -		std::for_each(mBoneInfoList.begin(), mBoneInfoList.end(), DeletePointer()); -	} -	BOOL parseXml(LLXmlTreeNode* node); -	S32 getNumBones() const { return mNumBones; } -	S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } +	LLVOAvatarSkeletonInfo() +	:	skeleton_root(""), +		num_bones("num_bones"), +		num_collision_volumes("num_collision_volumes"), +		version("version") +	{} -private: -	S32 mNumBones; -	S32 mNumCollisionVolumes; -	typedef std::vector<LLVOAvatarBoneInfo*> bone_info_list_t; -	bone_info_list_t mBoneInfoList; +	Mandatory<std::string>			version; +	Mandatory<S32>					num_bones, +									num_collision_volumes; +	Mandatory<LLVOAvatarChildJoint>	skeleton_root;  };  //----------------------------------------------------------------------------- @@ -593,7 +604,7 @@ private:  // Static Data  //-----------------------------------------------------------------------------  LLXmlTree LLVOAvatar::sXMLTree; -LLXmlTree LLVOAvatar::sSkeletonXMLTree; +LLXMLNodePtr LLVOAvatar::sSkeletonXMLTree;  LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL;  LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL;  LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL; @@ -694,9 +705,13 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	LLMemType mt(LLMemType::MTYPE_AVATAR);  	//VTResume();  // VTune +#ifdef XXX_STINSON_CHUI_REWORK  	// mVoiceVisualizer is created by the hud effects manager and uses the HUD Effects pipeline  	const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job  	mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim ); +#else // XXX_STINSON_CHUI_REWORK +	mVoiceVisualizer = new LLVoiceVisualizer(); +#endif // XXX_STINSON_CHUI_REWORK  	lldebugs << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << llendl; @@ -855,7 +870,11 @@ void LLVOAvatar::markDead()  		mNameText = NULL;  		sNumVisibleChatBubbles--;  	} +#ifdef XXX_STINSON_CHUI_REWORK  	mVoiceVisualizer->markDead(); +#else // XXX_STINSON_CHUI_REWORK +	mVoiceVisualizer->setStopSpeaking(); +#endif // XXX_STINSON_CHUI_REWORK  	LLLoadedCallbackEntry::cleanUpCallbackList(&mCallbackTextureList) ;  	LLViewerObject::markDead();  } @@ -1119,18 +1138,6 @@ void LLVOAvatar::initClass()  		llerrs << "Error parsing skeleton file: " << skeleton_path << llendl;  	} -	// Process XML data - -	// avatar_skeleton.xml -	if (sAvatarSkeletonInfo) -	{ //this can happen if a login attempt failed -		delete sAvatarSkeletonInfo; -	} -	sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; -	if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) -	{ -		llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; -	}  	// parse avatar_lad.xml  	if (sAvatarXmlInfo)  	{ //this can happen if a login attempt failed @@ -1179,7 +1186,7 @@ void LLVOAvatar::initClass()  void LLVOAvatar::cleanupClass()  {  	deleteAndClear(sAvatarXmlInfo); -	sSkeletonXMLTree.cleanup(); +	sSkeletonXMLTree = NULL;  	sXMLTree.cleanup();  } @@ -1325,7 +1332,9 @@ void LLVOAvatar::initInstance(void)  	//VTPause();  // VTune +#ifdef XXX_STINSON_CHUI_REWORK  	mVoiceVisualizer->setVoiceEnabled( LLVoiceClient::getInstance()->getVoiceEnabled( mID ) ); +#endif // XXX_STINSON_CHUI_REWORK  } @@ -1651,33 +1660,39 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename)  	//-------------------------------------------------------------------------  	// parse the file  	//------------------------------------------------------------------------- -	BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE ); +	 +	LLXMLNodePtr skeleton_xml; +	BOOL parsesuccess = LLXMLNode::parseFile(filename, skeleton_xml, NULL); -	if (!parsesuccess) +	if (!parsesuccess || skeleton_xml.isNull())  	{  		llerrs << "Can't parse skeleton file: " << filename << llendl;  		return FALSE;  	} -	// now sanity check xml file -	LLXmlTreeNode* root = sSkeletonXMLTree.getRoot(); -	if (!root)  +	// Process XML data +	if (sAvatarSkeletonInfo) +	{ //this can happen if a login attempt failed +		delete sAvatarSkeletonInfo; +	} +	sAvatarSkeletonInfo = new LLVOAvatarSkeletonInfo; + +	LLXUIParser parser; +	parser.readXUI(skeleton_xml, *sAvatarSkeletonInfo, filename); +	if (!sAvatarSkeletonInfo->validateBlock())  	{ -		llerrs << "No root node found in avatar skeleton file: " << filename << llendl; -		return FALSE; +		llerrs << "Error parsing skeleton XML file: " << filename << llendl;  	} -	if( !root->hasName( "linden_skeleton" ) ) +	if( !skeleton_xml->hasName( "linden_skeleton" ) )  	{  		llerrs << "Invalid avatar skeleton file header: " << filename << llendl;  		return FALSE;  	} -	std::string version; -	static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); -	if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) +	if (sAvatarSkeletonInfo->version() != "1.0")  	{ -		llerrs << "Invalid avatar skeleton file version: " << version << " in file: " << filename << llendl; +		llerrs << "Invalid avatar skeleton file version: " << sAvatarSkeletonInfo->version() << " in file: " << filename << llendl;  		return FALSE;  	} @@ -1686,14 +1701,13 @@ BOOL LLVOAvatar::parseSkeletonFile(const std::string& filename)  //-----------------------------------------------------------------------------  // setupBone() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num) +//----------------------------------------------------------- +BOOL LLVOAvatar::setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 &volume_num, S32 &joint_num)  {  	LLMemType mt(LLMemType::MTYPE_AVATAR);  	LLViewerJoint* joint = NULL; - -	if (info->mIsJoint) +	if (info.bone.isChosen())  	{  		joint = (LLViewerJoint*)getCharacterJoint(joint_num);  		if (!joint) @@ -1701,7 +1715,23 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent  			llwarns << "Too many bones" << llendl;  			return FALSE;  		} -		joint->setName( info->mName ); +		joint->setName( info.bone().name ); +		joint->setPosition(info.bone().pos); +		joint->setRotation(mayaQ(info.bone().rot().mV[VX], info.bone().rot().mV[VY], info.bone().rot().mV[VZ], LLQuaternion::XYZ)); +		joint->setScale(info.bone().scale); +		joint->setSkinOffset( info.bone().pivot ); +		joint_num++; + +		for (LLInitParam::ParamIterator<LLVOAvatarChildJoint>::const_iterator child_it = info.bone().children.begin(), +				end_it = info.bone().children.end(); +			child_it != end_it; +			++child_it) +		{ +			if (!setupBone(*child_it, joint, volume_num, joint_num)) +			{ +				return FALSE; +			} +		}  	}  	else // collision volume  	{ @@ -1711,7 +1741,11 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent  			return FALSE;  		}  		joint = (LLViewerJoint*)(&mCollisionVolumes[volume_num]); -		joint->setName( info->mName ); +		joint->setName( info.collision_volume.name); +		joint->setPosition(info.collision_volume.pos); +		joint->setRotation(mayaQ(info.collision_volume.rot().mV[VX], info.collision_volume.rot().mV[VY], info.collision_volume.rot().mV[VZ], LLQuaternion::XYZ)); +		joint->setScale(info.collision_volume.scale); +		volume_num++;  	}  	// add to parent @@ -1720,34 +1754,8 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent  		parent->addChild( joint );  	} -	joint->setPosition(info->mPos); -	joint->setRotation(mayaQ(info->mRot.mV[VX], info->mRot.mV[VY], -							 info->mRot.mV[VZ], LLQuaternion::XYZ)); -	joint->setScale(info->mScale); -  	joint->setDefaultFromCurrentXform(); -	if (info->mIsJoint) -	{ -		joint->setSkinOffset( info->mPivot ); -		joint_num++; -	} -	else // collision volume -	{ -		volume_num++; -	} - -	// setup children -	LLVOAvatarBoneInfo::child_list_t::const_iterator iter; -	for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) -	{ -		LLVOAvatarBoneInfo *child_info = *iter; -		if (!setupBone(child_info, joint, volume_num, joint_num)) -		{ -			return FALSE; -		} -	} -  	return TRUE;  } @@ -1761,35 +1769,31 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info)  	//-------------------------------------------------------------------------  	// allocate joints  	//------------------------------------------------------------------------- -	if (!allocateCharacterJoints(info->mNumBones)) +	if (!allocateCharacterJoints(info->num_bones))  	{ -		llerrs << "Can't allocate " << info->mNumBones << " joints" << llendl; +		llerrs << "Can't allocate " << info->num_bones() << " joints" << llendl;  		return FALSE;  	}  	//-------------------------------------------------------------------------  	// allocate volumes  	//------------------------------------------------------------------------- -	if (info->mNumCollisionVolumes) +	if (info->num_collision_volumes)  	{ -		if (!allocateCollisionVolumes(info->mNumCollisionVolumes)) +		if (!allocateCollisionVolumes(info->num_collision_volumes))  		{ -			llerrs << "Can't allocate " << info->mNumCollisionVolumes << " collision volumes" << llendl; +			llerrs << "Can't allocate " << info->num_collision_volumes() << " collision volumes" << llendl;  			return FALSE;  		}  	}  	S32 current_joint_num = 0;  	S32 current_volume_num = 0; -	LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; -	for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter) + +	if (!setupBone(info->skeleton_root, NULL, current_volume_num, current_joint_num))  	{ -		LLVOAvatarBoneInfo *info = *iter; -		if (!setupBone(info, NULL, current_volume_num, current_joint_num)) -		{ -			llerrs << "Error parsing bone in skeleton file" << llendl; -			return FALSE; -		} +		llerrs << "Error parsing bone in skeleton file" << llendl; +		return FALSE;  	}  	return TRUE; @@ -2426,6 +2430,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)  void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  { +#ifdef XXX_STINSON_CHUI_REWORK  	bool render_visualizer = voice_enabled;  	// Don't render the user's own voice visualizer when in mouselook, or when opening the mic is disabled. @@ -2438,6 +2443,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  	}  	mVoiceVisualizer->setVoiceEnabled(render_visualizer); +#endif // XXX_STINSON_CHUI_REWORK  	if ( voice_enabled )  	{		 @@ -2513,6 +2519,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  			}  		} +#ifdef XXX_STINSON_CHUI_REWORK  		//--------------------------------------------------------------------------------------------  		// here we get the approximate head position and set as sound source for the voice symbol  		// (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing) @@ -2530,6 +2537,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)  			tagPos[VZ] += ( mBodySize[VZ] + 0.125f );  			mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos );  		} +#endif // XXX_STINSON_CHUI_REWORK  	}//if ( voiceEnabled )  }		 @@ -2918,43 +2926,43 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)  		return;  	} -		BOOL new_name = FALSE; -		if (visible_chat != mVisibleChat) -		{ -			mVisibleChat = visible_chat; -			new_name = TRUE; -		} +	BOOL new_name = FALSE; +	if (visible_chat != mVisibleChat) +	{ +		mVisibleChat = visible_chat; +		new_name = TRUE; +	} -		if (sRenderGroupTitles != mRenderGroupTitles) -		{ -			mRenderGroupTitles = sRenderGroupTitles; -			new_name = TRUE; -		} +	if (sRenderGroupTitles != mRenderGroupTitles) +	{ +		mRenderGroupTitles = sRenderGroupTitles; +		new_name = TRUE; +	} -		// First Calculate Alpha -		// If alpha > 0, create mNameText if necessary, otherwise delete it -			F32 alpha = 0.f; -			if (mAppAngle > 5.f) +	// First Calculate Alpha +	// If alpha > 0, create mNameText if necessary, otherwise delete it +		F32 alpha = 0.f; +		if (mAppAngle > 5.f) +		{ +			const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; +			if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME)  			{ -				const F32 START_FADE_TIME = NAME_SHOW_TIME - FADE_DURATION; -				if (!visible_chat && sRenderName == RENDER_NAME_FADE && time_visible > START_FADE_TIME) -				{ -					alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION; -				} -				else -				{ -					// ...not fading, full alpha -					alpha = 1.f; -				} +				alpha = 1.f - (time_visible - START_FADE_TIME) / FADE_DURATION;  			} -			else if (mAppAngle > 2.f) +			else  			{ -				// far away is faded out also -				alpha = (mAppAngle-2.f)/3.f; +				// ...not fading, full alpha +				alpha = 1.f;  			} +		} +		else if (mAppAngle > 2.f) +		{ +			// far away is faded out also +			alpha = (mAppAngle-2.f)/3.f; +		}  	if (alpha <= 0.f) -			{ +	{  		if (mNameText)  		{  			mNameText->markDead(); @@ -2964,31 +2972,30 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)  		return;  	} -				if (!mNameText) -				{ +	if (!mNameText) +	{  		mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject(  			LLHUDObject::LL_HUD_NAME_TAG) );  		//mNameText->setMass(10.f); -					mNameText->setSourceObject(this); +		mNameText->setSourceObject(this);  		mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP); -					mNameText->setVisibleOffScreen(TRUE); -					mNameText->setMaxLines(11); -					mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); -					sNumVisibleChatBubbles++; -					new_name = TRUE; -				} +		mNameText->setVisibleOffScreen(TRUE); +		mNameText->setMaxLines(11); +		mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); +		sNumVisibleChatBubbles++; +		new_name = TRUE; +	} -	LLVector3 name_position = idleUpdateNameTagPosition(root_pos_last); -	mNameText->setPositionAgent(name_position);				 +	idleUpdateNameTagPosition(root_pos_last);  	idleUpdateNameTagText(new_name);			  	idleUpdateNameTagAlpha(new_name, alpha);  }  void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) -			{ -		LLNameValue *title = getNVPair("Title"); -		LLNameValue* firstname = getNVPair("FirstName"); -		LLNameValue* lastname = getNVPair("LastName"); +{ +	LLNameValue *title = getNVPair("Title"); +	LLNameValue* firstname = getNVPair("FirstName"); +	LLNameValue* lastname = getNVPair("LastName");  	// Avatars must have a first and last name  	if (!firstname || !lastname) return; @@ -3002,34 +3009,29 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  		is_muted = false;  	}  	else -		{ +	{  		is_muted = LLMuteList::getInstance()->isMuted(getID());  	}  	bool is_friend = LLAvatarTracker::instance().isBuddy(getID());  	bool is_cloud = getIsCloud(); -			if (gSavedSettings.getBOOL("DebugAvatarRezTime")) -			{ -				if (is_appearance != mNameAppearance) -				{ -					if (is_appearance) -					{ -						LLSD args; -						args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); -						args["NAME"] = getFullname(); -						LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args); -						llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl; -					} -					else -					{ -						LLSD args; -						args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); -						args["NAME"] = getFullname(); -						LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args); -						llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl; -					} -				} -			} +	if (gSavedSettings.getBOOL("DebugAvatarRezTime") +		&& is_appearance != mNameAppearance) +	{ +		LLSD args; +		args["EXISTENCE"] = llformat("%d",(U32)mDebugExistenceTimer.getElapsedTimeF32()); +		args["NAME"] = getFullname(); +		if (is_appearance) +		{ +			LLNotificationsUtil::add("AvatarRezEnteredAppearanceNotification",args); +			llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' entered appearance mode." << llendl; +		} +		else +		{ +			LLNotificationsUtil::add("AvatarRezLeftAppearanceNotification",args); +			llinfos << "REZTIME: [ " << (U32)mDebugExistenceTimer.getElapsedTimeF32() << "sec ] Avatar '" << getFullname() << "' left appearance mode." << llendl; +		} +	}  	// Rebuild name tag if state change detected  	if (mNameString.empty() @@ -3039,39 +3041,39 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  		|| is_away != mNameAway   		|| is_busy != mNameBusy   		|| is_muted != mNameMute -				|| is_appearance != mNameAppearance  +		|| is_appearance != mNameAppearance   		|| is_friend != mNameFriend  		|| is_cloud != mNameCloud) -				{ +	{  		LLColor4 name_tag_color = getNameTagColor(is_friend);  		clearNameTag();  		if (is_away || is_muted || is_busy || is_appearance) -				{ +		{  			std::string line; -					if (is_away) -					{ -						line += LLTrans::getString("AvatarAway"); +			if (is_away) +			{ +				line += LLTrans::getString("AvatarAway");  				line += ", "; -					} -					if (is_busy) -					{ +			} +			if (is_busy) +			{  				line += LLTrans::getString("AvatarBusy");  				line += ", ";  			}  			if (is_muted) -						{ +			{  				line += LLTrans::getString("AvatarMuted"); -							line += ", "; -						} +				line += ", "; +			}  			if (is_appearance)  			{  				line += LLTrans::getString("AvatarEditingAppearance");  				line += ", "; -					} +			}  			if (is_cloud) -					{ +			{  				line += LLTrans::getString("LoadingData");  				line += ", ";  			} @@ -3083,12 +3085,12 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  		if (sRenderGroupTitles  			&& title && title->getString() && title->getString()[0] != '\0') -						{ +		{  			std::string title_str = title->getString();  			LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR);  			addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL,  				LLFontGL::getFontSansSerifSmall()); -						} +		}  		static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames");  		static LLUICachedControl<bool> show_usernames("NameTagShowUsernames"); @@ -3102,119 +3104,118 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)  				// and force a rebuild  				LLAvatarNameCache::get(getID(),  					boost::bind(&LLVOAvatar::clearNameTag, this)); -					} +			}  			// Might be blank if name not available yet, that's OK  			if (show_display_names)  			{  				addNameTagLine(av_name.mDisplayName, name_tag_color, LLFontGL::NORMAL,  					LLFontGL::getFontSansSerif()); -				} +			}  			// Suppress SLID display if display name matches exactly (ugh)  			if (show_usernames && !av_name.mIsDisplayNameDefault) -				{ +			{  				// *HACK: Desaturate the color  				LLColor4 username_color = name_tag_color * 0.83f;  				addNameTagLine(av_name.mUsername, username_color, LLFontGL::NORMAL,  					LLFontGL::getFontSansSerifSmall());  			} -				} +		}  		else -				{ +		{  			const LLFontGL* font = LLFontGL::getFontSansSerif(); -			std::string full_name = -				LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); +			std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() );  			addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); -				} +		} -				mNameAway = is_away; -				mNameBusy = is_busy; -				mNameMute = is_muted; -				mNameAppearance = is_appearance; -		mNameFriend = is_friend; -				mNameCloud = is_cloud; -				mTitle = title ? title->getString() : ""; -				LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); -				new_name = TRUE; -			} +		mNameAway 		= is_away; +		mNameBusy 		= is_busy; +		mNameMute 		= is_muted; +		mNameAppearance = is_appearance; +		mNameFriend 	= is_friend; +		mNameCloud 		= is_cloud; +		mTitle 			= title ? title->getString() : ""; +		LLStringFn::replace_ascii_controlchars(mTitle, LL_UNKNOWN_CHAR); +		new_name = TRUE; +	}  	if (mVisibleChat) -			{ -				mNameText->setFont(LLFontGL::getFontSansSerif()); +	{ +		mNameText->setFont(LLFontGL::getFontSansSerif());  		mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); -				mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); -			 -				char line[MAX_STRING];		/* Flawfinder: ignore */ -				line[0] = '\0'; -				std::deque<LLChat>::iterator chat_iter = mChats.begin(); -				mNameText->clearString(); - -				LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); -				LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); -				LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); -				if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES)  -				{ -					++chat_iter; -				} +		mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); -				for(; chat_iter != mChats.end(); ++chat_iter) -				{ -					F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); -					LLFontGL::StyleFlags style; -					switch(chat_iter->mChatType) -					{ -						case CHAT_TYPE_WHISPER: -							style = LLFontGL::ITALIC; -							break; -						case CHAT_TYPE_SHOUT: -							style = LLFontGL::BOLD; -							break; -						default: -							style = LLFontGL::NORMAL; -							break; -					} -					if (chat_fade_amt < 1.f) -					{ -						F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); -						mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); -					} -					else if (chat_fade_amt < 2.f) -					{ -						F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); -						mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); -					} -					else if (chat_fade_amt < 3.f) -					{ -						// *NOTE: only remove lines down to minimum number -						mNameText->addLine(chat_iter->mText, old_chat, style); -					} -				} -				mNameText->setVisibleOffScreen(TRUE); +		char line[MAX_STRING];		/* Flawfinder: ignore */ +		line[0] = '\0'; +		std::deque<LLChat>::iterator chat_iter = mChats.begin(); +		mNameText->clearString(); -				if (mTyping) -				{ -					S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; -					switch(dot_count) -					{ -						case 1: -							mNameText->addLine(".", new_chat); -							break; -						case 2: -							mNameText->addLine("..", new_chat); -							break; -						case 3: -							mNameText->addLine("...", new_chat); -							break; -					} +		LLColor4 new_chat = LLUIColorTable::instance().getColor( isSelf() ? "UserChatColor" : "AgentChatColor" ); +		LLColor4 normal_chat = lerp(new_chat, LLColor4(0.8f, 0.8f, 0.8f, 1.f), 0.7f); +		LLColor4 old_chat = lerp(normal_chat, LLColor4(0.6f, 0.6f, 0.6f, 1.f), 0.7f); +		if (mTyping && mChats.size() >= MAX_BUBBLE_CHAT_UTTERANCES)  +		{ +			++chat_iter; +		} -				} +		for(; chat_iter != mChats.end(); ++chat_iter) +		{ +			F32 chat_fade_amt = llclamp((F32)((LLFrameTimer::getElapsedSeconds() - chat_iter->mTime) / CHAT_FADE_TIME), 0.f, 4.f); +			LLFontGL::StyleFlags style; +			switch(chat_iter->mChatType) +			{ +			case CHAT_TYPE_WHISPER: +				style = LLFontGL::ITALIC; +				break; +			case CHAT_TYPE_SHOUT: +				style = LLFontGL::BOLD; +				break; +			default: +				style = LLFontGL::NORMAL; +				break;  			} -			else +			if (chat_fade_amt < 1.f)  			{ +				F32 u = clamp_rescale(chat_fade_amt, 0.9f, 1.f, 0.f, 1.f); +				mNameText->addLine(chat_iter->mText, lerp(new_chat, normal_chat, u), style); +			} +			else if (chat_fade_amt < 2.f) +			{ +				F32 u = clamp_rescale(chat_fade_amt, 1.9f, 2.f, 0.f, 1.f); +				mNameText->addLine(chat_iter->mText, lerp(normal_chat, old_chat, u), style); +			} +			else if (chat_fade_amt < 3.f) +			{ +				// *NOTE: only remove lines down to minimum number +				mNameText->addLine(chat_iter->mText, old_chat, style); +			} +		} +		mNameText->setVisibleOffScreen(TRUE); + +		if (mTyping) +		{ +			S32 dot_count = (llfloor(mTypingTimer.getElapsedTimeF32() * 3.f) + 2) % 3 + 1; +			switch(dot_count) +			{ +			case 1: +				mNameText->addLine(".", new_chat); +				break; +			case 2: +				mNameText->addLine("..", new_chat); +				break; +			case 3: +				mNameText->addLine("...", new_chat); +				break; +			} + +		} +	} +	else +	{  		// ...not using chat bubbles, just names  		mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER); -				mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); -				mNameText->setVisibleOffScreen(FALSE); +		mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f); +		mNameText->setVisibleOffScreen(FALSE);  	}  } @@ -3237,8 +3238,8 @@ void LLVOAvatar::clearNameTag()  {  	mNameString.clear();  	if (mNameText) -				{ -					mNameText->setLabel(""); +	{ +		mNameText->setLabel("");  		mNameText->setString( "" );  	}  } @@ -3266,34 +3267,45 @@ void LLVOAvatar::invalidateNameTags()  		if (avatar->isDead()) continue;  		avatar->clearNameTag(); -  	}  }  // Compute name tag position during idle update -LLVector3 LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) +void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last)  {  	LLQuaternion root_rot = mRoot.getWorldRotation(); +	LLQuaternion inv_root_rot = ~root_rot;  	LLVector3 pixel_right_vec;  	LLVector3 pixel_up_vec;  	LLViewerCamera::getInstance()->getPixelVectors(root_pos_last, pixel_up_vec, pixel_right_vec);  	LLVector3 camera_to_av = root_pos_last - LLViewerCamera::getInstance()->getOrigin();  	camera_to_av.normalize(); -	LLVector3 local_camera_at = camera_to_av * ~root_rot; +	LLVector3 local_camera_at = camera_to_av * inv_root_rot;  	LLVector3 local_camera_up = camera_to_av % LLViewerCamera::getInstance()->getLeftAxis();  	local_camera_up.normalize(); -	local_camera_up = local_camera_up * ~root_rot; +	local_camera_up = local_camera_up * inv_root_rot; + +	LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f, +								mBodySize.mV[VY] * 0.4f, +								mBodySize.mV[VZ] * NAMETAG_VERT_OFFSET_WEIGHT); -	local_camera_up.scaleVec(mBodySize * 0.5f); -	local_camera_at.scaleVec(mBodySize * 0.5f); +	local_camera_up.scaleVec(avatar_ellipsoid); +	local_camera_at.scaleVec(avatar_ellipsoid); -	LLVector3 name_position = mRoot.getWorldPosition(); -	name_position[VZ] -= mPelvisToFoot; -	name_position[VZ] += (mBodySize[VZ]* 0.55f); +	LLVector3 head_offset = (mHeadp->getLastWorldPosition() - mRoot.getLastWorldPosition()) * inv_root_rot; + +	if (dist_vec(head_offset, mTargetRootToHeadOffset) > NAMETAG_UPDATE_THRESHOLD) +	{ +		mTargetRootToHeadOffset = head_offset; +	} +	 +	mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLCriticalDamp::getInterpolant(0.2f)); + +	LLVector3 name_position = mRoot.getLastWorldPosition() + (mCurRootToHeadOffset * root_rot);  	name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av));	 -	name_position += pixel_up_vec * 15.f; +	name_position += pixel_up_vec * NAMETAG_VERTICAL_SCREEN_OFFSET; -	return name_position; +	mNameText->setPositionAgent(name_position);				  }  void LLVOAvatar::idleUpdateNameTagAlpha(BOOL new_name, F32 alpha) @@ -3329,7 +3341,7 @@ LLColor4 LLVOAvatar::getNameTagColor(bool is_friend)  		else  		{  			color_name = "NameTagMismatch"; -	} +		}  	}  	else  	{ @@ -3366,9 +3378,9 @@ bool LLVOAvatar::isVisuallyMuted() const  	static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");  	static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); -	return LLMuteList::getInstance()->isMuted(getID()) || -			(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || -			(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); +	return LLMuteList::getInstance()->isMuted(getID())  +			|| (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0)  +			|| (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f);  }  //------------------------------------------------------------------------ @@ -3409,8 +3421,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		}  	} -	LLVector3d root_pos_global; -  	if (!mIsBuilt)  	{  		return FALSE; @@ -3424,7 +3434,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  	{  		mTimeVisible.reset();  	} -  	//--------------------------------------------------------------------  	// the rest should only be done occasionally for far away avatars @@ -3828,10 +3837,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		if ( playSound )  		{ -//			F32 gain = clamp_rescale( mSpeedAccum, -//							AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, -//							AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); -  			const F32 STEP_VOLUME = 0.1f;  			const LLUUID& step_sound_id = getStepSound(); @@ -4048,13 +4053,6 @@ void LLVOAvatar::updateVisibility()  		{  			releaseMeshData();  		} -		// this breaks off-screen chat bubbles -		//if (mNameText) -		//{ -		//	mNameText->markDead(); -		//	mNameText = NULL; -		//	sNumVisibleChatBubbles--; -		//}  	}  	mVisible = visible; @@ -4070,46 +4068,6 @@ bool LLVOAvatar::shouldAlphaMask()  } -U32 LLVOAvatar::renderSkinnedAttachments() -{ -	/*U32 num_indices = 0; -	 -	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX |  -							LLVertexBuffer::MAP_NORMAL |  -							LLVertexBuffer::MAP_TEXCOORD0 | -							LLVertexBuffer::MAP_COLOR | -							LLVertexBuffer::MAP_WEIGHT4; - -	for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();  -		 iter != mAttachmentPoints.end(); -		 ++iter) -	{ -		LLViewerJointAttachment* attachment = iter->second; -		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); -			 attachment_iter != attachment->mAttachedObjects.end(); -			 ++attachment_iter) -		{ -			const LLViewerObject* attached_object = (*attachment_iter); -			if (attached_object && !attached_object->isHUDAttachment()) -			{ -				const LLDrawable* drawable = attached_object->mDrawable; -				if (drawable) -				{ -					for (S32 i = 0; i < drawable->getNumFaces(); ++i) -					{ -						LLFace* face = drawable->getFace(i); -						if (face->isState(LLFace::RIGGED)) -						{ -							 -				} -			} -		} -	} - -	return num_indices;*/ -	return 0; -} -  //-----------------------------------------------------------------------------  // renderSkinned()  //----------------------------------------------------------------------------- @@ -4130,11 +4088,11 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)  	{	//LOD changed or new mesh created, allocate new vertex buffer if needed  		if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4)  		{ -		updateMeshData(); +			updateMeshData();  			mDirtyMesh = 0; -		mNeedsSkin = TRUE; -		mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); -	} +			mNeedsSkin = TRUE; +			mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); +		}  	}  	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) @@ -5795,36 +5753,34 @@ BOOL LLVOAvatar::updateJointLODs()  	F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor);  	F32 area_scale = 0.16f; +	if (isSelf())  	{ -		if (isSelf()) -		{ -			if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook()) -			{ -				mAdjustedPixelArea = MAX_PIXEL_AREA; -			} -			else -			{ -				mAdjustedPixelArea = mPixelArea*area_scale; -			} -		} -		else if (mIsDummy) +		if(gAgentCamera.cameraCustomizeAvatar() || gAgentCamera.cameraMouselook())  		{  			mAdjustedPixelArea = MAX_PIXEL_AREA;  		}  		else  		{ -			// reported avatar pixel area is dependent on avatar render load, based on number of visible avatars -			mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; +			mAdjustedPixelArea = mPixelArea*area_scale;  		} +	} +	else if (mIsDummy) +	{ +		mAdjustedPixelArea = MAX_PIXEL_AREA; +	} +	else +	{ +		// reported avatar pixel area is dependent on avatar render load, based on number of visible avatars +		mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; +	} -		// now select meshes to render based on adjusted pixel area -		BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); - 		if (res) -		{ -			sNumLODChangesThisFrame++; -			dirtyMesh(2); -			return TRUE; -		} +	// now select meshes to render based on adjusted pixel area +	BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); + 	if (res) +	{ +		sNumLODChangesThisFrame++; +		dirtyMesh(2); +		return TRUE;  	}  	return FALSE; @@ -6114,25 +6070,18 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )  		if ( pVObj )  		{  			const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); -			if ( pSkinData ) -			{ -				const int jointCnt = pSkinData->mJointNames.size(); -				bool fullRig = ( jointCnt>=20 ) ? true : false; -				if ( fullRig ) +			if (pSkinData  +				&& pSkinData->mJointNames.size() > 20				// full rig +				&& pSkinData->mAlternateBindMatrix.size() > 0) +			{ +				LLVOAvatar::resetJointPositionsToDefault(); +				//Need to handle the repositioning of the cam, updating rig data etc during outfit editing  +				//This handles the case where we detach a replacement rig. +				if ( gAgentCamera.cameraCustomizeAvatar() )  				{ -					const int bindCnt = pSkinData->mAlternateBindMatrix.size();							 -					if ( bindCnt > 0 ) -					{ -						LLVOAvatar::resetJointPositionsToDefault(); -						//Need to handle the repositioning of the cam, updating rig data etc during outfit editing  -						//This handles the case where we detach a replacement rig. -						if ( gAgentCamera.cameraCustomizeAvatar() ) -						{ -							gAgent.unpauseAnimation(); -							//Still want to refocus on head bone -							gAgentCamera.changeCameraToCustomizeAvatar(); -						} -					} +					gAgent.unpauseAnimation(); +					//Still want to refocus on head bone +					gAgentCamera.changeCameraToCustomizeAvatar();  				}  			}				  		} @@ -6286,11 +6235,7 @@ void LLVOAvatar::getOffObject()  		at_axis.mV[VZ] = 0.f;  		at_axis.normalize();  		gAgent.resetAxes(at_axis); - -		//reset orientation -//		mRoot.setRotation(avWorldRot);  		gAgentCamera.setThirdPersonHeadOffset(LLVector3(0.f, 0.f, 1.f)); -  		gAgentCamera.setSitCamera(LLUUID::null);  	}  } @@ -6340,7 +6285,6 @@ LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const  	}  	else  	{ -//		return LLColor4( .5f, .5f, .5f, .5f );  		return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color  	}  } @@ -7072,10 +7016,6 @@ LLBBox LLVOAvatar::getHUDBBox() const  	return bbox;  } -void LLVOAvatar::rebuildHUD() -{ -} -  //-----------------------------------------------------------------------------  // onFirstTEMessageReceived()  //----------------------------------------------------------------------------- @@ -7197,7 +7137,10 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )  			&& baked_index != BAKED_SKIRT)  		{  			setTEImage(mBakedTextureDatas[baked_index].mTextureIndex,  -				LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); +						LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex,  +																TRUE,  +																LLViewerTexture::BOOST_NONE,  +																LLViewerTexture::LOD_TEXTURE));  		}  	} @@ -7488,11 +7431,6 @@ void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_  // Called when baked texture is loaded and also when we start up with a baked texture  void LLVOAvatar::useBakedTexture( const LLUUID& id )  { -	/* if(id == head_baked->getID()) -		 mHeadBakedLoaded = TRUE; -		 mLastHeadBakedID = id; -		 mHeadMesh0.setTexture( head_baked ); -		 mHeadMesh1.setTexture( head_baked ); */  	for (U32 i = 0; i < mBakedTextureDatas.size(); i++)  	{  		LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); @@ -7732,111 +7670,111 @@ LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo()  	std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer());  } -//----------------------------------------------------------------------------- -// LLVOAvatarBoneInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) -{ -	if (node->hasName("bone")) -	{ -		mIsJoint = TRUE; -		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); -		if (!node->getFastAttributeString(name_string, mName)) -		{ -			llwarns << "Bone without name" << llendl; -			return FALSE; -		} -	} -	else if (node->hasName("collision_volume")) -	{ -		mIsJoint = FALSE; -		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); -		if (!node->getFastAttributeString(name_string, mName)) -		{ -			mName = "Collision Volume"; -		} -	} -	else -	{ -		llwarns << "Invalid node " << node->getName() << llendl; -		return FALSE; -	} - -	static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); -	if (!node->getFastAttributeVector3(pos_string, mPos)) -	{ -		llwarns << "Bone without position" << llendl; -		return FALSE; -	} - -	static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); -	if (!node->getFastAttributeVector3(rot_string, mRot)) -	{ -		llwarns << "Bone without rotation" << llendl; -		return FALSE; -	} -	 -	static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); -	if (!node->getFastAttributeVector3(scale_string, mScale)) -	{ -		llwarns << "Bone without scale" << llendl; -		return FALSE; -	} - -	if (mIsJoint) -	{ -		static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); -		if (!node->getFastAttributeVector3(pivot_string, mPivot)) -		{ -			llwarns << "Bone without pivot" << llendl; -			return FALSE; -		} -	} - -	// parse children -	LLXmlTreeNode* child; -	for( child = node->getFirstChild(); child; child = node->getNextChild() ) -	{ -		LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; -		if (!child_info->parseXml(child)) -		{ -			delete child_info; -			return FALSE; -		} -		mChildList.push_back(child_info); -	} -	return TRUE; -} - -//----------------------------------------------------------------------------- -// LLVOAvatarSkeletonInfo::parseXml() -//----------------------------------------------------------------------------- -BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) -{ -	static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); -	if (!node->getFastAttributeS32(num_bones_string, mNumBones)) -	{ -		llwarns << "Couldn't find number of bones." << llendl; -		return FALSE; -	} - -	static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); -	node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); - -	LLXmlTreeNode* child; -	for( child = node->getFirstChild(); child; child = node->getNextChild() ) -	{ -		LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; -		if (!info->parseXml(child)) -		{ -			delete info; -			llwarns << "Error parsing bone in skeleton file" << llendl; -			return FALSE; -		} -		mBoneInfoList.push_back(info); -	} -	return TRUE; -} +////----------------------------------------------------------------------------- +//// LLVOAvatarBoneInfo::parseXml() +////----------------------------------------------------------------------------- +//BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) +//{ +//	if (node->hasName("bone")) +//	{ +//		mIsJoint = TRUE; +//		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); +//		if (!node->getFastAttributeString(name_string, mName)) +//		{ +//			llwarns << "Bone without name" << llendl; +//			return FALSE; +//		} +//	} +//	else if (node->hasName("collision_volume")) +//	{ +//		mIsJoint = FALSE; +//		static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name"); +//		if (!node->getFastAttributeString(name_string, mName)) +//		{ +//			mName = "Collision Volume"; +//		} +//	} +//	else +//	{ +//		llwarns << "Invalid node " << node->getName() << llendl; +//		return FALSE; +//	} +// +//	static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos"); +//	if (!node->getFastAttributeVector3(pos_string, mPos)) +//	{ +//		llwarns << "Bone without position" << llendl; +//		return FALSE; +//	} +// +//	static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot"); +//	if (!node->getFastAttributeVector3(rot_string, mRot)) +//	{ +//		llwarns << "Bone without rotation" << llendl; +//		return FALSE; +//	} +//	 +//	static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale"); +//	if (!node->getFastAttributeVector3(scale_string, mScale)) +//	{ +//		llwarns << "Bone without scale" << llendl; +//		return FALSE; +//	} +// +//	if (mIsJoint) +//	{ +//		static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); +//		if (!node->getFastAttributeVector3(pivot_string, mPivot)) +//		{ +//			llwarns << "Bone without pivot" << llendl; +//			return FALSE; +//		} +//	} +// +//	// parse children +//	LLXmlTreeNode* child; +//	for( child = node->getFirstChild(); child; child = node->getNextChild() ) +//	{ +//		LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo; +//		if (!child_info->parseXml(child)) +//		{ +//			delete child_info; +//			return FALSE; +//		} +//		mChildList.push_back(child_info); +//	} +//	return TRUE; +//} +// +////----------------------------------------------------------------------------- +//// LLVOAvatarSkeletonInfo::parseXml() +////----------------------------------------------------------------------------- +//BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) +//{ +//	static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); +//	if (!node->getFastAttributeS32(num_bones_string, mNumBones)) +//	{ +//		llwarns << "Couldn't find number of bones." << llendl; +//		return FALSE; +//	} +// +//	static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes"); +//	node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes); +// +//	LLXmlTreeNode* child; +//	for( child = node->getFirstChild(); child; child = node->getNextChild() ) +//	{ +//		LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo; +//		if (!info->parseXml(child)) +//		{ +//			delete info; +//			llwarns << "Error parsing bone in skeleton file" << llendl; +//			return FALSE; +//		} +//		mBoneInfoList.push_back(info); +//	} +//	return TRUE; +//}  //-----------------------------------------------------------------------------  // parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 6a4e09593c..036e282d8e 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -66,8 +66,9 @@ class LLVoiceVisualizer;  class LLHUDNameTag;  class LLHUDEffectSpiral;  class LLTexGlobalColor; -class LLVOAvatarBoneInfo; -class LLVOAvatarSkeletonInfo; +struct LLVOAvatarBoneInfo; +struct LLVOAvatarChildJoint; +struct LLVOAvatarSkeletonInfo;  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // LLVOAvatar @@ -232,7 +233,7 @@ public:  	void 			idleUpdateWindEffect();  	void 			idleUpdateNameTag(const LLVector3& root_pos_last);  	void			idleUpdateNameTagText(BOOL new_name); -	LLVector3		idleUpdateNameTagPosition(const LLVector3& root_pos_last); +	void			idleUpdateNameTagPosition(const LLVector3& root_pos_last);  	void			idleUpdateNameTagAlpha(BOOL new_name, F32 alpha);  	LLColor4		getNameTagColor(bool is_friend);  	void			clearNameTag(); @@ -317,6 +318,8 @@ public:  	F32					mLastPelvisToFoot;  	F32					mPelvisFixup;  	F32					mLastPelvisFixup; +	LLVector3			mCurRootToHeadOffset; +	LLVector3			mTargetRootToHeadOffset;  	LLVector3			mHeadOffset; // current head position  	LLViewerJoint		mRoot; @@ -325,7 +328,7 @@ protected:  	void				buildCharacter();  	virtual BOOL		loadAvatar(); -	BOOL				setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); +	BOOL				setupBone(const LLVOAvatarChildJoint& info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num);  	BOOL				buildSkeleton(const LLVOAvatarSkeletonInfo *info);  private:  	BOOL				mIsBuilt; // state of deferred character building @@ -369,7 +372,7 @@ public:  	//--------------------------------------------------------------------  private:  	static LLXmlTree 	sXMLTree; // avatar config file -	static LLXmlTree 	sSkeletonXMLTree; // avatar skeleton file +	static LLXMLNodePtr	sSkeletonXMLTree; // avatar skeleton file  /**                    Skeleton   **                                                                            ** @@ -387,7 +390,6 @@ public:  	U32 		renderRigid();  	U32 		renderSkinned(EAvatarRenderPass pass);  	F32			getLastSkinTime() { return mLastSkinTime; } -	U32			renderSkinnedAttachments();  	U32 		renderTransparent(BOOL first_pass);  	void 		renderCollisionVolumes();  	static void	deleteCachedImages(bool clearAll=true); @@ -735,7 +737,6 @@ public:  public:  	BOOL 				hasHUDAttachment() const;  	LLBBox 				getHUDBBox() const; -	void 				rebuildHUD();  	void 				resetHUDAttachments();  	BOOL				canAttachMoreObjects() const;  	BOOL				canAttachMoreObjects(U32 n) const; diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 47060720e7..dcf33bce10 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -1,625 +1,642 @@ -/**  - * @file llvoicevisualizer.cpp - * @brief Draws in-world speaking indicators. - * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, 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$ - */ - -//---------------------------------------------------------------------- -// Voice Visualizer -// author: JJ Ventrella -// (information about this stuff can be found in "llvoicevisualizer.h") -//---------------------------------------------------------------------- -#include "llviewerprecompiledheaders.h" -#include "llviewercontrol.h" -#include "llglheaders.h" -#include "llsphere.h" -#include "llvoicevisualizer.h" -#include "llviewercamera.h" -#include "llviewerobject.h" -#include "llviewertexture.h" -#include "llviewertexturelist.h" -#include "llvoiceclient.h" -#include "llrender.h" - -//brent's wave image -//29de489d-0491-fb00-7dab-f9e686d31e83 - - -//-------------------------------------------------------------------------------------- -// sound symbol constants -//-------------------------------------------------------------------------------------- -const F32	HEIGHT_ABOVE_HEAD	= 0.3f;		// how many meters vertically above the av's head the voice symbol will appear -const F32	RED_THRESHOLD		= LLVoiceClient::OVERDRIVEN_POWER_LEVEL;		// value above which speaking amplitude causes the voice symbol to turn red -const F32	GREEN_THRESHOLD		= 0.2f;		// value above which speaking amplitude causes the voice symbol to turn green -const F32	FADE_OUT_DURATION	= 0.4f;		// how many seconds it takes for a pair of waves to fade away -const F32	EXPANSION_RATE		= 1.0f;		// how many seconds it takes for the waves to expand to twice their original size -const F32	EXPANSION_MAX		= 1.5f;		// maximum size scale to which the waves can expand before popping back to 1.0  -const F32	WAVE_WIDTH_SCALE	= 0.03f;	// base width of the waves  -const F32	WAVE_HEIGHT_SCALE	= 0.02f;	// base height of the waves  -const F32	BASE_BRIGHTNESS		= 0.7f;		// gray level of the voice indicator when quiet (below green threshold) -const F32	DOT_SIZE			= 0.05f;	// size of the dot billboard texture -const F32	DOT_OPACITY			= 0.7f;		// how opaque the dot is -const F32	WAVE_MOTION_RATE	= 1.5f;		// scalar applied to consecutive waves as a function of speaking amplitude - -//-------------------------------------------------------------------------------------- -// gesticulation constants -//-------------------------------------------------------------------------------------- -const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE	= 0.2f;  -const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE	= 1.0f; - -//-------------------------------------------------------------------------------------- -// other constants -//-------------------------------------------------------------------------------------- -const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code.  -const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL - - -//------------------------------------------------------------------ -// handles parameter updates -//------------------------------------------------------------------ -static bool handleVoiceVisualizerPrefsChanged(const LLSD& newvalue) -{ -	// Note: Ignore the specific event value, we look up the ones we want -	LLVoiceVisualizer::setPreferences(); -	return true; -} - -//------------------------------------------------------------------ -// Initialize the statics -//------------------------------------------------------------------ -bool LLVoiceVisualizer::sPrefsInitialized	= false; -BOOL LLVoiceVisualizer::sLipSyncEnabled		= FALSE; -F32* LLVoiceVisualizer::sOoh				= NULL; -F32* LLVoiceVisualizer::sAah				= NULL; -U32	 LLVoiceVisualizer::sOohs				= 0; -U32	 LLVoiceVisualizer::sAahs				= 0; -F32	 LLVoiceVisualizer::sOohAahRate			= 0.0f; -F32* LLVoiceVisualizer::sOohPowerTransfer	= NULL; -U32	 LLVoiceVisualizer::sOohPowerTransfers	= 0; -F32	 LLVoiceVisualizer::sOohPowerTransfersf = 0.0f; -F32* LLVoiceVisualizer::sAahPowerTransfer	= NULL; -U32	 LLVoiceVisualizer::sAahPowerTransfers	= 0; -F32	 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f; - - -//----------------------------------------------- -// constructor -//----------------------------------------------- -LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) -:LLHUDEffect( type ) -{ -	mCurrentTime					= mTimer.getTotalSeconds(); -	mPreviousTime					= mCurrentTime; -	mStartTime						= mCurrentTime; -	mVoiceSourceWorldPosition		= LLVector3( 0.0f, 0.0f, 0.0f ); -	mSpeakingAmplitude				= 0.0f; -	mCurrentlySpeaking				= false; -	mVoiceEnabled					= false; -	mMinGesticulationAmplitude		= DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE; -	mMaxGesticulationAmplitude		= DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE; -	mSoundSymbol.mActive			= true; -	mSoundSymbol.mPosition			= LLVector3( 0.0f, 0.0f, 0.0f ); -	 -	mTimer.reset(); -	 -	const char* sound_level_img[] =  -	{ -		"voice_meter_dot.j2c", -		"voice_meter_rings.j2c", -		"voice_meter_rings.j2c", -		"voice_meter_rings.j2c", -		"voice_meter_rings.j2c", -		"voice_meter_rings.j2c", -		"voice_meter_rings.j2c" -	}; - -	for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) -	{ -		mSoundSymbol.mWaveFadeOutStartTime	[i] = mCurrentTime; -		mSoundSymbol.mTexture				[i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FALSE, LLViewerTexture::BOOST_UI); -		mSoundSymbol.mWaveActive			[i] = false; -		mSoundSymbol.mWaveOpacity			[i] = 1.0f; -		mSoundSymbol.mWaveExpansion			[i] = 1.0f; -	} - -	mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - -	// The first instance loads the initial state from prefs. -	if (!sPrefsInitialized) -	{ -		setPreferences(); -        -		// Set up our listener to get updates on all prefs values we care about. -		gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&handleVoiceVisualizerPrefsChanged, _2)); -		 -		sPrefsInitialized = true; -	} - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m ) -{ -	mMinGesticulationAmplitude = m; - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setMaxGesticulationAmplitude( F32 m ) -{ -	mMaxGesticulationAmplitude = m; - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setVoiceEnabled( bool v ) -{ -	mVoiceEnabled = v; - -}//--------------------------------------------------- - -//--------------------------------------------------- -void LLVoiceVisualizer::setStartSpeaking() -{ -	mStartTime				= mTimer.getTotalSeconds(); -	mCurrentlySpeaking		= true; -	mSoundSymbol.mActive	= true; -		 -}//--------------------------------------------------- - - -//--------------------------------------------------- -bool LLVoiceVisualizer::getCurrentlySpeaking() -{ -	return mCurrentlySpeaking; -	 -}//--------------------------------------------------- - - -//--------------------------------------------------- -void LLVoiceVisualizer::setStopSpeaking() -{ -	mCurrentlySpeaking = false; -	mSpeakingAmplitude = 0.0f; -	 -}//--------------------------------------------------- - - -//--------------------------------------------------- -void LLVoiceVisualizer::setSpeakingAmplitude( F32 a ) -{ -	mSpeakingAmplitude = a; -	 -}//--------------------------------------------------- - - -//--------------------------------------------------- -void LLVoiceVisualizer::setPreferences( ) -{ -	sLipSyncEnabled = gSavedSettings.getBOOL("LipSyncEnabled"); -	sOohAahRate		= gSavedSettings.getF32("LipSyncOohAahRate"); - -	std::string oohString = gSavedSettings.getString("LipSyncOoh"); -	lipStringToF32s (oohString, sOoh, sOohs); - -	std::string aahString = gSavedSettings.getString("LipSyncAah"); -	lipStringToF32s (aahString, sAah, sAahs); - -	std::string oohPowerString = gSavedSettings.getString("LipSyncOohPowerTransfer"); -	lipStringToF32s (oohPowerString, sOohPowerTransfer, sOohPowerTransfers); -	sOohPowerTransfersf = (F32) sOohPowerTransfers; - -	std::string aahPowerString = gSavedSettings.getString("LipSyncAahPowerTransfer"); -	lipStringToF32s (aahPowerString, sAahPowerTransfer, sAahPowerTransfers); -	sAahPowerTransfersf = (F32) sAahPowerTransfers; - -}//--------------------------------------------------- - - -//--------------------------------------------------- -// convert a string of digits to an array of floats. -// the result for each digit is the value of the -// digit multiplied by 0.11 -//--------------------------------------------------- -void LLVoiceVisualizer::lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ) -{ -	delete[] out_F32s;	// get rid of the current array - -	count_F32s = in_string.length(); -	if (count_F32s == 0) -	{ -		// we don't like zero length arrays - -		count_F32s  = 1; -		out_F32s	   = new F32[1]; -		out_F32s[0] = 0.0f; -	} -	else -	{ -		out_F32s = new F32[count_F32s]; - -		for (U32 i=0; i<count_F32s; i++) -		{ -			// we convert the characters 0 to 9 to their numeric value -			// anything else we take the low order four bits with a ceiling of 9 - -		    U8 digit = in_string[i]; -			U8 four_bits = digit % 16; -			if (four_bits > 9) -			{ -				four_bits = 9; -			} -			out_F32s[i] = 0.11f * (F32) four_bits; -		}  -	} - -}//--------------------------------------------------- - - -//-------------------------------------------------------------------------- -// find the amount to blend the ooh and aah mouth morphs -//-------------------------------------------------------------------------- -void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah ) -{ -	if( ( sLipSyncEnabled == TRUE ) && mCurrentlySpeaking ) -	{ -		U32 transfer_index = (U32) (sOohPowerTransfersf * mSpeakingAmplitude); -		if (transfer_index >= sOohPowerTransfers) -		{ -		   transfer_index = sOohPowerTransfers - 1; -		} -		F32 transfer_ooh = sOohPowerTransfer[transfer_index]; - -		transfer_index = (U32) (sAahPowerTransfersf * mSpeakingAmplitude); -		if (transfer_index >= sAahPowerTransfers) -		{ -		   transfer_index = sAahPowerTransfers - 1; -		} -		F32 transfer_aah = sAahPowerTransfer[transfer_index]; - -		F64 current_time   = mTimer.getTotalSeconds(); -		F64 elapsed_time   = current_time - mStartTime; -		U32 elapsed_frames = (U32) (elapsed_time * sOohAahRate); -		U32 elapsed_oohs   = elapsed_frames % sOohs; -		U32 elapsed_aahs   = elapsed_frames % sAahs; - -		ooh = transfer_ooh * sOoh[elapsed_oohs]; -		aah = transfer_aah * sAah[elapsed_aahs]; - -		/* -		llinfos << " elapsed frames " << elapsed_frames -				<< " ooh "            << ooh -				<< " aah "            << aah -				<< " transfer ooh"    << transfer_ooh -				<< " transfer aah"    << transfer_aah -				<< " start time "     << mStartTime -				<< " current time "   << current_time -				<< " elapsed time "   << elapsed_time -				<< " elapsed oohs "   << elapsed_oohs -				<< " elapsed aahs "   << elapsed_aahs -				<< llendl; -		*/ -	} -	else -	{ -		ooh = 0.0f; -		aah = 0.0f; -	} -	 -}//--------------------------------------------------- - - -//--------------------------------------------------- -// this method is inherited from HUD Effect -//--------------------------------------------------- -void LLVoiceVisualizer::render() -{ -	if ( ! mVoiceEnabled ) -	{ -		return; -	} -	 -	if ( mSoundSymbol.mActive )  -	{				 -		mPreviousTime = mCurrentTime; -		mCurrentTime = mTimer.getTotalSeconds(); -	 -		//--------------------------------------------------------------- -		// set the sound symbol position over the source (avatar's head) -		//--------------------------------------------------------------- -		mSoundSymbol.mPosition = mVoiceSourceWorldPosition + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD; -	 -		//--------------------------------------------------------------- -		// some gl state -		//--------------------------------------------------------------- -		LLGLSPipelineAlpha alpha_blend; -		LLGLDepthTest depth(GL_TRUE, GL_FALSE); -		 -		//------------------------------------------------------------- -		// create coordinates of the geometry for the dot -		//------------------------------------------------------------- -		LLViewerCamera* camera = LLViewerCamera::getInstance(); -		LLVector3 l	= camera->getLeftAxis() * DOT_SIZE; -		LLVector3 u	= camera->getUpAxis()   * DOT_SIZE; - -		LLVector3 bottomLeft	= mSoundSymbol.mPosition + l - u; -		LLVector3 bottomRight	= mSoundSymbol.mPosition - l - u; -		LLVector3 topLeft		= mSoundSymbol.mPosition + l + u; -		LLVector3 topRight		= mSoundSymbol.mPosition - l + u; -		 -		//----------------------------- -		// bind texture 0 (the dot) -		//----------------------------- -		gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[0]); -		 -		//------------------------------------------------------------- -		// now render the dot -		//------------------------------------------------------------- -		gGL.color4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV );	 -		 -		gGL.begin( LLRender::TRIANGLE_STRIP ); -			gGL.texCoord2i( 0,	0	); gGL.vertex3fv( bottomLeft.mV ); -			gGL.texCoord2i( 1,	0	); gGL.vertex3fv( bottomRight.mV ); -			gGL.texCoord2i( 0,	1	); gGL.vertex3fv( topLeft.mV ); -		gGL.end(); - -		gGL.begin( LLRender::TRIANGLE_STRIP ); -			gGL.texCoord2i( 1,	0	); gGL.vertex3fv( bottomRight.mV ); -			gGL.texCoord2i( 1,	1	); gGL.vertex3fv( topRight.mV ); -			gGL.texCoord2i( 0,	1	); gGL.vertex3fv( topLeft.mV ); -		gGL.end(); -		 -		 -		 -		//-------------------------------------------------------------------------------------- -		// if currently speaking, trigger waves (1 through 6) based on speaking amplitude -		//-------------------------------------------------------------------------------------- -		if ( mCurrentlySpeaking ) -		{ -			F32 min = 0.2f; -			F32 max = 0.7f; -			F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min ); -		 -			// in case mSpeakingAmplitude > max.... -			if ( fraction > 1.0f ) -			{ -				fraction = 1.0f; -			} -														 -			S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) ); -																										 -			for (int i=0; i<level+1; i++) -			{ -				mSoundSymbol.mWaveActive			[i] = true; -				mSoundSymbol.mWaveOpacity			[i] = 1.0f; -				mSoundSymbol.mWaveFadeOutStartTime	[i] = mCurrentTime; -			}			 -			 -		} // if currently speaking -								 -		//--------------------------------------------------- -		// determine color -		//--------------------------------------------------- -		F32 red		= 0.0f; -		F32 green	= 0.0f; -		F32 blue	= 0.0f; -        if ( mSpeakingAmplitude < RED_THRESHOLD ) -        { -			if ( mSpeakingAmplitude < GREEN_THRESHOLD ) -			{ -				red		= BASE_BRIGHTNESS; -				green	= BASE_BRIGHTNESS; -				blue	= BASE_BRIGHTNESS; -			} -			else -			{ -				//--------------------------------------------------- -				// fade from gray to bright green -				//--------------------------------------------------- -				F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD ); -				red		= BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); -				green	= BASE_BRIGHTNESS +   fraction * ( 1.0f - BASE_BRIGHTNESS ); -				blue	= BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS ); -			} -        } -        else -        { -			//--------------------------------------------------- -			// redish -			//--------------------------------------------------- -			red		= 1.0f; -			green	= 0.2f; -			blue	= 0.2f; -        } -														 -		for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++) -		{ -			if ( mSoundSymbol.mWaveActive[i] )  -			{ -				F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION; - -				mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction; -				 -				if ( mSoundSymbol.mWaveOpacity[i] < 0.0f ) -				{ -					mSoundSymbol.mWaveFadeOutStartTime	[i] = mCurrentTime; -					mSoundSymbol.mWaveOpacity			[i] = 0.0f; -					mSoundSymbol.mWaveActive			[i] = false; -				} -				 -				//---------------------------------------------------------------------------------- -				// This is where we calculate the expansion of the waves - that is, the -				// rate at which they are scaled greater than 1.0 so that they grow over time. -				//---------------------------------------------------------------------------------- -				F32 timeSlice = (F32)( mCurrentTime - mPreviousTime ); -				F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE; -				mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed ); -				 -				if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX ) -				{ -					mSoundSymbol.mWaveExpansion[i] = 1.0f; -				}			 -								 -				//---------------------------------------------------------------------------------- -				// create geometry for the wave billboard textures -				//---------------------------------------------------------------------------------- -				F32 width	= i * WAVE_WIDTH_SCALE  * mSoundSymbol.mWaveExpansion[i]; -				F32 height	= i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i]; - -				LLVector3 l	= camera->getLeftAxis() * width; -				LLVector3 u	= camera->getUpAxis()   * height; - -				LLVector3 bottomLeft	= mSoundSymbol.mPosition + l - u; -				LLVector3 bottomRight	= mSoundSymbol.mPosition - l - u; -				LLVector3 topLeft		= mSoundSymbol.mPosition + l + u; -				LLVector3 topRight		= mSoundSymbol.mPosition - l + u; -							 -				gGL.color4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV );		 -				gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[i]); - -				 -				//--------------------------------------------------- -				// now, render the mofo -				//--------------------------------------------------- -				gGL.begin( LLRender::TRIANGLE_STRIP ); -					gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV ); -					gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); -					gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); -				gGL.end(); - -				gGL.begin( LLRender::TRIANGLE_STRIP ); -					gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV ); -					gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV ); -					gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV ); -				gGL.end(); -				 -			} //if ( mSoundSymbol.mWaveActive[i] )  -			 -		}// for loop -											 -	}//if ( mSoundSymbol.mActive )  - -}//--------------------------------------------------- - - - - - -//--------------------------------------------------- -void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p ) -{ -	mVoiceSourceWorldPosition	= p; - -}//--------------------------------------------------- - -//--------------------------------------------------- -VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel() -{ -	VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF; //default -	 -	//----------------------------------------------------------------------------------------- -	// Within the range of gesticulation amplitudes, the sound signal is split into -	// three equal amplitude regimes, each specifying one of three gesticulation levels. -	//----------------------------------------------------------------------------------------- -	F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude; -	 -			if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.5f	)	{ gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH;		} -	else	if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.25f	)	{ gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM;	} -	else	if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f	)	{ gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW;		} - -	return gesticulationLevel; - -}//--------------------------------------------------- - - - -//------------------------------------ -// Destructor -//------------------------------------ -LLVoiceVisualizer::~LLVoiceVisualizer() -{ -}//---------------------------------------------- - - -//--------------------------------------------------- -// "packData" is inherited from HUDEffect -//--------------------------------------------------- -void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys) -{ -	// Pack the default data -	LLHUDEffect::packData(mesgsys); - -	// TODO -- pack the relevant data for voice effects -	// we'll come up with some cool configurations....TBD -	//U8 packed_data[41]; -	//mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41); -	U8 packed_data = 0; -	mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1); -} - - -//--------------------------------------------------- -// "unpackData" is inherited from HUDEffect -//--------------------------------------------------- -void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum) -{ -	// TODO -- find the speaker, unpack binary data, set the properties of this effect -	/* -	LLHUDEffect::unpackData(mesgsys, blocknum); -	LLUUID source_id; -	LLUUID target_id; -	S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); -	if (size != 1) -	{ -		llwarns << "Voice effect with bad size " << size << llendl; -		return; -	} -	mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 1, blocknum); -	*/ -} - - -//------------------------------------------------------------------ -// this method is inherited from HUD Effect -//------------------------------------------------------------------ -void LLVoiceVisualizer::markDead() -{ -	mCurrentlySpeaking		= false; -	mVoiceEnabled			= false; -	mSoundSymbol.mActive	= false; - -	LLHUDEffect::markDead(); -}//------------------------------------------------------------------ - - - - - - - - +/** 
 + * @file llvoicevisualizer.cpp
 + * @brief Draws in-world speaking indicators.
 + *
 + * $LicenseInfo:firstyear=2000&license=viewerlgpl$
 + * Second Life Viewer Source Code
 + * Copyright (C) 2010, 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$
 + */
 +
 +//----------------------------------------------------------------------
 +// Voice Visualizer
 +// author: JJ Ventrella
 +// (information about this stuff can be found in "llvoicevisualizer.h")
 +//----------------------------------------------------------------------
 +#include "llviewerprecompiledheaders.h"
 +#include "llviewercontrol.h"
 +#include "llglheaders.h"
 +#include "llsphere.h"
 +#include "llvoicevisualizer.h"
 +#include "llviewercamera.h"
 +#include "llviewerobject.h"
 +#include "llviewertexture.h"
 +#include "llviewertexturelist.h"
 +#include "llvoiceclient.h"
 +#include "llrender.h"
 +
 +//brent's wave image
 +//29de489d-0491-fb00-7dab-f9e686d31e83
 +
 +
 +#ifdef XXX_STINSON_CHUI_REWORK
 +//--------------------------------------------------------------------------------------
 +// sound symbol constants
 +//--------------------------------------------------------------------------------------
 +const F32	HEIGHT_ABOVE_HEAD	= 0.3f;		// how many meters vertically above the av's head the voice symbol will appear
 +const F32	RED_THRESHOLD		= LLVoiceClient::OVERDRIVEN_POWER_LEVEL;		// value above which speaking amplitude causes the voice symbol to turn red
 +const F32	GREEN_THRESHOLD		= 0.2f;		// value above which speaking amplitude causes the voice symbol to turn green
 +const F32	FADE_OUT_DURATION	= 0.4f;		// how many seconds it takes for a pair of waves to fade away
 +const F32	EXPANSION_RATE		= 1.0f;		// how many seconds it takes for the waves to expand to twice their original size
 +const F32	EXPANSION_MAX		= 1.5f;		// maximum size scale to which the waves can expand before popping back to 1.0 
 +const F32	WAVE_WIDTH_SCALE	= 0.03f;	// base width of the waves 
 +const F32	WAVE_HEIGHT_SCALE	= 0.02f;	// base height of the waves 
 +const F32	BASE_BRIGHTNESS		= 0.7f;		// gray level of the voice indicator when quiet (below green threshold)
 +const F32	DOT_SIZE			= 0.05f;	// size of the dot billboard texture
 +const F32	DOT_OPACITY			= 0.7f;		// how opaque the dot is
 +const F32	WAVE_MOTION_RATE	= 1.5f;		// scalar applied to consecutive waves as a function of speaking amplitude
 +#endif // XXX_STINSON_CHUI_REWORK
 +
 +//--------------------------------------------------------------------------------------
 +// gesticulation constants
 +//--------------------------------------------------------------------------------------
 +const F32 DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE	= 0.2f; 
 +const F32 DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE	= 1.0f;
 +
 +#ifdef XXX_STINSON_CHUI_REWORK
 +//--------------------------------------------------------------------------------------
 +// other constants
 +//--------------------------------------------------------------------------------------
 +const F32 ONE_HALF = 1.0f; // to clarify intent and reduce magic numbers in the code. 
 +const LLVector3 WORLD_UPWARD_DIRECTION = LLVector3( 0.0f, 0.0f, 1.0f ); // Z is up in SL
 +#endif // XXX_STINSON_CHUI_REWORK
 +
 +//------------------------------------------------------------------
 +// Initialize the statics
 +//------------------------------------------------------------------
 +bool LLVoiceVisualizer::sPrefsInitialized	= false;
 +BOOL LLVoiceVisualizer::sLipSyncEnabled		= FALSE;
 +F32* LLVoiceVisualizer::sOoh				= NULL;
 +F32* LLVoiceVisualizer::sAah				= NULL;
 +U32	 LLVoiceVisualizer::sOohs				= 0;
 +U32	 LLVoiceVisualizer::sAahs				= 0;
 +F32	 LLVoiceVisualizer::sOohAahRate			= 0.0f;
 +F32* LLVoiceVisualizer::sOohPowerTransfer	= NULL;
 +U32	 LLVoiceVisualizer::sOohPowerTransfers	= 0;
 +F32	 LLVoiceVisualizer::sOohPowerTransfersf = 0.0f;
 +F32* LLVoiceVisualizer::sAahPowerTransfer	= NULL;
 +U32	 LLVoiceVisualizer::sAahPowerTransfers	= 0;
 +F32	 LLVoiceVisualizer::sAahPowerTransfersf = 0.0f;
 +
 +
 +//-----------------------------------------------
 +// constructor
 +//-----------------------------------------------
 +#ifdef XXX_STINSON_CHUI_REWORK
 +LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
 +#else // XXX_STINSON_CHUI_REWORK
 +LLVoiceVisualizer::LLVoiceVisualizer()
 +	: LLRefCount(),
 +	mTimer(),
 +	mStartTime(0.0),
 +	mCurrentlySpeaking(false),
 +	mSpeakingAmplitude(0.0f),
 +	mMaxGesticulationAmplitude(DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE),
 +	mMinGesticulationAmplitude(DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE)
 +#endif // XXX_STINSON_CHUI_REWORK
 +{
 +#ifdef XXX_STINSON_CHUI_REWORK
 +	mCurrentTime					= mTimer.getTotalSeconds();
 +	mPreviousTime					= mCurrentTime;
 +	mStartTime						= mCurrentTime;
 +#else // XXX_STINSON_CHUI_REWORK
 +	mStartTime						= mTimer.getTotalSeconds();
 +#endif // XXX_STINSON_CHUI_REWORK
 +#ifdef XXX_STINSON_CHUI_REWORK
 +	mVoiceSourceWorldPosition		= LLVector3( 0.0f, 0.0f, 0.0f );
 +	mSpeakingAmplitude				= 0.0f;
 +	mCurrentlySpeaking				= false;
 +	mVoiceEnabled					= false;
 +	mMinGesticulationAmplitude		= DEFAULT_MINIMUM_GESTICULATION_AMPLITUDE;
 +	mMaxGesticulationAmplitude		= DEFAULT_MAXIMUM_GESTICULATION_AMPLITUDE;
 +	mSoundSymbol.mActive			= true;
 +	mSoundSymbol.mPosition			= LLVector3( 0.0f, 0.0f, 0.0f );
 +#endif // XXX_STINSON_CHUI_REWORK
 +	
 +	mTimer.reset();
 +	
 +#ifdef XXX_STINSON_CHUI_REWORK
 +	const char* sound_level_img[] = 
 +	{
 +		"voice_meter_dot.j2c",
 +		"voice_meter_rings.j2c",
 +		"voice_meter_rings.j2c",
 +		"voice_meter_rings.j2c",
 +		"voice_meter_rings.j2c",
 +		"voice_meter_rings.j2c",
 +		"voice_meter_rings.j2c"
 +	};
 +
 +	for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
 +	{
 +		mSoundSymbol.mWaveFadeOutStartTime	[i] = mCurrentTime;
 +		mSoundSymbol.mTexture				[i] = LLViewerTextureManager::getFetchedTextureFromFile(sound_level_img[i], FALSE, LLViewerTexture::BOOST_UI);
 +		mSoundSymbol.mWaveActive			[i] = false;
 +		mSoundSymbol.mWaveOpacity			[i] = 1.0f;
 +		mSoundSymbol.mWaveExpansion			[i] = 1.0f;
 +	}
 +
 +	mSoundSymbol.mTexture[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
 +#endif // XXX_STINSON_CHUI_REWORK
 +
 +	// The first instance loads the initial state from prefs.
 +	if (!sPrefsInitialized)
 +	{
 +		setPreferences();
 +       
 +		// Set up our listener to get updates on all prefs values we care about.
 +		gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +		gSavedSettings.getControl("LipSyncOohAahRate")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +		gSavedSettings.getControl("LipSyncOoh")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +		gSavedSettings.getControl("LipSyncAah")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +		gSavedSettings.getControl("LipSyncOohPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +		gSavedSettings.getControl("LipSyncAahPowerTransfer")->getSignal()->connect(boost::bind(&LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged, _2));
 +		
 +		sPrefsInitialized = true;
 +	}
 +
 +}//---------------------------------------------------
 +
 +#ifdef XXX_STINSON_CHUI_REWORK
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setMinGesticulationAmplitude( F32 m )
 +{
 +	mMinGesticulationAmplitude = m;
 +
 +}//---------------------------------------------------
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setMaxGesticulationAmplitude( F32 m )
 +{
 +	mMaxGesticulationAmplitude = m;
 +
 +}//---------------------------------------------------
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setVoiceEnabled( bool v )
 +{
 +	mVoiceEnabled = v;
 +
 +}//---------------------------------------------------
 +#endif // XXX_STINSON_CHUI_REWORK
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setStartSpeaking()
 +{
 +	mStartTime				= mTimer.getTotalSeconds();
 +	mCurrentlySpeaking		= true;
 +#ifdef XXX_STINSON_CHUI_REWORK
 +	mSoundSymbol.mActive	= true;
 +#endif // XXX_STINSON_CHUI_REWORK
 +		
 +}//---------------------------------------------------
 +
 +
 +//---------------------------------------------------
 +bool LLVoiceVisualizer::getCurrentlySpeaking()
 +{
 +	return mCurrentlySpeaking;
 +	
 +}//---------------------------------------------------
 +
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setStopSpeaking()
 +{
 +	mCurrentlySpeaking = false;
 +	mSpeakingAmplitude = 0.0f;
 +	
 +}//---------------------------------------------------
 +
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setSpeakingAmplitude( F32 a )
 +{
 +	mSpeakingAmplitude = a;
 +	
 +}//---------------------------------------------------
 +
 +//------------------------------------------------------------------
 +// handles parameter updates
 +//------------------------------------------------------------------
 +bool LLVoiceVisualizer::handleVoiceVisualizerPrefsChanged(const LLSD& newvalue)
 +{
 +	// Note: Ignore the specific event value, we look up the ones we want
 +	LLVoiceVisualizer::setPreferences();
 +	return true;
 +}
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setPreferences( )
 +{
 +	sLipSyncEnabled = gSavedSettings.getBOOL("LipSyncEnabled");
 +	sOohAahRate		= gSavedSettings.getF32("LipSyncOohAahRate");
 +
 +	std::string oohString = gSavedSettings.getString("LipSyncOoh");
 +	lipStringToF32s (oohString, sOoh, sOohs);
 +
 +	std::string aahString = gSavedSettings.getString("LipSyncAah");
 +	lipStringToF32s (aahString, sAah, sAahs);
 +
 +	std::string oohPowerString = gSavedSettings.getString("LipSyncOohPowerTransfer");
 +	lipStringToF32s (oohPowerString, sOohPowerTransfer, sOohPowerTransfers);
 +	sOohPowerTransfersf = (F32) sOohPowerTransfers;
 +
 +	std::string aahPowerString = gSavedSettings.getString("LipSyncAahPowerTransfer");
 +	lipStringToF32s (aahPowerString, sAahPowerTransfer, sAahPowerTransfers);
 +	sAahPowerTransfersf = (F32) sAahPowerTransfers;
 +
 +}//---------------------------------------------------
 +
 +
 +//---------------------------------------------------
 +// convert a string of digits to an array of floats.
 +// the result for each digit is the value of the
 +// digit multiplied by 0.11
 +//---------------------------------------------------
 +void LLVoiceVisualizer::lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s )
 +{
 +	delete[] out_F32s;	// get rid of the current array
 +
 +	count_F32s = in_string.length();
 +	if (count_F32s == 0)
 +	{
 +		// we don't like zero length arrays
 +
 +		count_F32s  = 1;
 +		out_F32s	   = new F32[1];
 +		out_F32s[0] = 0.0f;
 +	}
 +	else
 +	{
 +		out_F32s = new F32[count_F32s];
 +
 +		for (U32 i=0; i<count_F32s; i++)
 +		{
 +			// we convert the characters 0 to 9 to their numeric value
 +			// anything else we take the low order four bits with a ceiling of 9
 +
 +		    U8 digit = in_string[i];
 +			U8 four_bits = digit % 16;
 +			if (four_bits > 9)
 +			{
 +				four_bits = 9;
 +			}
 +			out_F32s[i] = 0.11f * (F32) four_bits;
 +		} 
 +	}
 +
 +}//---------------------------------------------------
 +
 +
 +//--------------------------------------------------------------------------
 +// find the amount to blend the ooh and aah mouth morphs
 +//--------------------------------------------------------------------------
 +void LLVoiceVisualizer::lipSyncOohAah( F32& ooh, F32& aah )
 +{
 +	if( ( sLipSyncEnabled == TRUE ) && mCurrentlySpeaking )
 +	{
 +		U32 transfer_index = (U32) (sOohPowerTransfersf * mSpeakingAmplitude);
 +		if (transfer_index >= sOohPowerTransfers)
 +		{
 +		   transfer_index = sOohPowerTransfers - 1;
 +		}
 +		F32 transfer_ooh = sOohPowerTransfer[transfer_index];
 +
 +		transfer_index = (U32) (sAahPowerTransfersf * mSpeakingAmplitude);
 +		if (transfer_index >= sAahPowerTransfers)
 +		{
 +		   transfer_index = sAahPowerTransfers - 1;
 +		}
 +		F32 transfer_aah = sAahPowerTransfer[transfer_index];
 +
 +		F64 current_time   = mTimer.getTotalSeconds();
 +		F64 elapsed_time   = current_time - mStartTime;
 +		U32 elapsed_frames = (U32) (elapsed_time * sOohAahRate);
 +		U32 elapsed_oohs   = elapsed_frames % sOohs;
 +		U32 elapsed_aahs   = elapsed_frames % sAahs;
 +
 +		ooh = transfer_ooh * sOoh[elapsed_oohs];
 +		aah = transfer_aah * sAah[elapsed_aahs];
 +
 +		/*
 +		llinfos << " elapsed frames " << elapsed_frames
 +				<< " ooh "            << ooh
 +				<< " aah "            << aah
 +				<< " transfer ooh"    << transfer_ooh
 +				<< " transfer aah"    << transfer_aah
 +				<< " start time "     << mStartTime
 +				<< " current time "   << current_time
 +				<< " elapsed time "   << elapsed_time
 +				<< " elapsed oohs "   << elapsed_oohs
 +				<< " elapsed aahs "   << elapsed_aahs
 +				<< llendl;
 +		*/
 +	}
 +	else
 +	{
 +		ooh = 0.0f;
 +		aah = 0.0f;
 +	}
 +	
 +}//---------------------------------------------------
 +
 +
 +#ifdef XXX_STINSON_CHUI_REWORK
 +//---------------------------------------------------
 +// this method is inherited from HUD Effect
 +//---------------------------------------------------
 +void LLVoiceVisualizer::render()
 +{
 +	if ( ! mVoiceEnabled )
 +	{
 +		return;
 +	}
 +	
 +	if ( mSoundSymbol.mActive ) 
 +	{				
 +		mPreviousTime = mCurrentTime;
 +		mCurrentTime = mTimer.getTotalSeconds();
 +	
 +		//---------------------------------------------------------------
 +		// set the sound symbol position over the source (avatar's head)
 +		//---------------------------------------------------------------
 +		mSoundSymbol.mPosition = mVoiceSourceWorldPosition + WORLD_UPWARD_DIRECTION * HEIGHT_ABOVE_HEAD;
 +	
 +		//---------------------------------------------------------------
 +		// some gl state
 +		//---------------------------------------------------------------
 +		LLGLSPipelineAlpha alpha_blend;
 +		LLGLDepthTest depth(GL_TRUE, GL_FALSE);
 +		
 +		//-------------------------------------------------------------
 +		// create coordinates of the geometry for the dot
 +		//-------------------------------------------------------------
 +		LLViewerCamera* camera = LLViewerCamera::getInstance();
 +		LLVector3 l	= camera->getLeftAxis() * DOT_SIZE;
 +		LLVector3 u	= camera->getUpAxis()   * DOT_SIZE;
 +
 +		LLVector3 bottomLeft	= mSoundSymbol.mPosition + l - u;
 +		LLVector3 bottomRight	= mSoundSymbol.mPosition - l - u;
 +		LLVector3 topLeft		= mSoundSymbol.mPosition + l + u;
 +		LLVector3 topRight		= mSoundSymbol.mPosition - l + u;
 +		
 +		//-----------------------------
 +		// bind texture 0 (the dot)
 +		//-----------------------------
 +		gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[0]);
 +		
 +		//-------------------------------------------------------------
 +		// now render the dot
 +		//-------------------------------------------------------------
 +		gGL.color4fv( LLColor4( 1.0f, 1.0f, 1.0f, DOT_OPACITY ).mV );	
 +		
 +		gGL.begin( LLRender::TRIANGLE_STRIP );
 +			gGL.texCoord2i( 0,	0	); gGL.vertex3fv( bottomLeft.mV );
 +			gGL.texCoord2i( 1,	0	); gGL.vertex3fv( bottomRight.mV );
 +			gGL.texCoord2i( 0,	1	); gGL.vertex3fv( topLeft.mV );
 +		gGL.end();
 +
 +		gGL.begin( LLRender::TRIANGLE_STRIP );
 +			gGL.texCoord2i( 1,	0	); gGL.vertex3fv( bottomRight.mV );
 +			gGL.texCoord2i( 1,	1	); gGL.vertex3fv( topRight.mV );
 +			gGL.texCoord2i( 0,	1	); gGL.vertex3fv( topLeft.mV );
 +		gGL.end();
 +		
 +		
 +		
 +		//--------------------------------------------------------------------------------------
 +		// if currently speaking, trigger waves (1 through 6) based on speaking amplitude
 +		//--------------------------------------------------------------------------------------
 +		if ( mCurrentlySpeaking )
 +		{
 +			F32 min = 0.2f;
 +			F32 max = 0.7f;
 +			F32 fraction = ( mSpeakingAmplitude - min ) / ( max - min );
 +		
 +			// in case mSpeakingAmplitude > max....
 +			if ( fraction > 1.0f )
 +			{
 +				fraction = 1.0f;
 +			}
 +														
 +			S32 level = 1 + (int)( fraction * ( NUM_VOICE_SYMBOL_WAVES - 2 ) );
 +																										
 +			for (int i=0; i<level+1; i++)
 +			{
 +				mSoundSymbol.mWaveActive			[i] = true;
 +				mSoundSymbol.mWaveOpacity			[i] = 1.0f;
 +				mSoundSymbol.mWaveFadeOutStartTime	[i] = mCurrentTime;
 +			}			
 +			
 +		} // if currently speaking
 +								
 +		//---------------------------------------------------
 +		// determine color
 +		//---------------------------------------------------
 +		F32 red		= 0.0f;
 +		F32 green	= 0.0f;
 +		F32 blue	= 0.0f;
 +        if ( mSpeakingAmplitude < RED_THRESHOLD )
 +        {
 +			if ( mSpeakingAmplitude < GREEN_THRESHOLD )
 +			{
 +				red		= BASE_BRIGHTNESS;
 +				green	= BASE_BRIGHTNESS;
 +				blue	= BASE_BRIGHTNESS;
 +			}
 +			else
 +			{
 +				//---------------------------------------------------
 +				// fade from gray to bright green
 +				//---------------------------------------------------
 +				F32 fraction = ( mSpeakingAmplitude - GREEN_THRESHOLD ) / ( 1.0f - GREEN_THRESHOLD );
 +				red		= BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
 +				green	= BASE_BRIGHTNESS +   fraction * ( 1.0f - BASE_BRIGHTNESS );
 +				blue	= BASE_BRIGHTNESS - ( fraction * BASE_BRIGHTNESS );
 +			}
 +        }
 +        else
 +        {
 +			//---------------------------------------------------
 +			// redish
 +			//---------------------------------------------------
 +			red		= 1.0f;
 +			green	= 0.2f;
 +			blue	= 0.2f;
 +        }
 +														
 +		for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
 +		{
 +			if ( mSoundSymbol.mWaveActive[i] ) 
 +			{
 +				F32 fadeOutFraction = (F32)( mCurrentTime - mSoundSymbol.mWaveFadeOutStartTime[i] ) / FADE_OUT_DURATION;
 +
 +				mSoundSymbol.mWaveOpacity[i] = 1.0f - fadeOutFraction;
 +				
 +				if ( mSoundSymbol.mWaveOpacity[i] < 0.0f )
 +				{
 +					mSoundSymbol.mWaveFadeOutStartTime	[i] = mCurrentTime;
 +					mSoundSymbol.mWaveOpacity			[i] = 0.0f;
 +					mSoundSymbol.mWaveActive			[i] = false;
 +				}
 +				
 +				//----------------------------------------------------------------------------------
 +				// This is where we calculate the expansion of the waves - that is, the
 +				// rate at which they are scaled greater than 1.0 so that they grow over time.
 +				//----------------------------------------------------------------------------------
 +				F32 timeSlice = (F32)( mCurrentTime - mPreviousTime );
 +				F32 waveSpeed = mSpeakingAmplitude * WAVE_MOTION_RATE;
 +				mSoundSymbol.mWaveExpansion[i] *= ( 1.0f + EXPANSION_RATE * timeSlice * waveSpeed );
 +				
 +				if ( mSoundSymbol.mWaveExpansion[i] > EXPANSION_MAX )
 +				{
 +					mSoundSymbol.mWaveExpansion[i] = 1.0f;
 +				}			
 +								
 +				//----------------------------------------------------------------------------------
 +				// create geometry for the wave billboard textures
 +				//----------------------------------------------------------------------------------
 +				F32 width	= i * WAVE_WIDTH_SCALE  * mSoundSymbol.mWaveExpansion[i];
 +				F32 height	= i * WAVE_HEIGHT_SCALE * mSoundSymbol.mWaveExpansion[i];
 +
 +				LLVector3 l	= camera->getLeftAxis() * width;
 +				LLVector3 u	= camera->getUpAxis()   * height;
 +
 +				LLVector3 bottomLeft	= mSoundSymbol.mPosition + l - u;
 +				LLVector3 bottomRight	= mSoundSymbol.mPosition - l - u;
 +				LLVector3 topLeft		= mSoundSymbol.mPosition + l + u;
 +				LLVector3 topRight		= mSoundSymbol.mPosition - l + u;
 +							
 +				gGL.color4fv( LLColor4( red, green, blue, mSoundSymbol.mWaveOpacity[i] ).mV );		
 +				gGL.getTexUnit(0)->bind(mSoundSymbol.mTexture[i]);
 +
 +				
 +				//---------------------------------------------------
 +				// now, render the mofo
 +				//---------------------------------------------------
 +				gGL.begin( LLRender::TRIANGLE_STRIP );
 +					gGL.texCoord2i( 0, 0 ); gGL.vertex3fv( bottomLeft.mV );
 +					gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV );
 +					gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV );
 +				gGL.end();
 +
 +				gGL.begin( LLRender::TRIANGLE_STRIP );
 +					gGL.texCoord2i( 1, 0 ); gGL.vertex3fv( bottomRight.mV );
 +					gGL.texCoord2i( 1, 1 ); gGL.vertex3fv( topRight.mV );
 +					gGL.texCoord2i( 0, 1 ); gGL.vertex3fv( topLeft.mV );
 +				gGL.end();
 +				
 +			} //if ( mSoundSymbol.mWaveActive[i] ) 
 +			
 +		}// for loop
 +											
 +	}//if ( mSoundSymbol.mActive ) 
 +
 +}//---------------------------------------------------
 +
 +//---------------------------------------------------
 +void LLVoiceVisualizer::setVoiceSourceWorldPosition( const LLVector3 &p )
 +{
 +	mVoiceSourceWorldPosition	= p;
 +
 +}//---------------------------------------------------
 +#endif // XXX_STINSON_CHUI_REWORK
 +
 +//---------------------------------------------------
 +VoiceGesticulationLevel LLVoiceVisualizer::getCurrentGesticulationLevel()
 +{
 +	VoiceGesticulationLevel gesticulationLevel = VOICE_GESTICULATION_LEVEL_OFF; //default
 +	
 +	//-----------------------------------------------------------------------------------------
 +	// Within the range of gesticulation amplitudes, the sound signal is split into
 +	// three equal amplitude regimes, each specifying one of three gesticulation levels.
 +	//-----------------------------------------------------------------------------------------
 +	F32 range = mMaxGesticulationAmplitude - mMinGesticulationAmplitude;
 +	
 +			if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.5f	)	{ gesticulationLevel = VOICE_GESTICULATION_LEVEL_HIGH;		}
 +	else	if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.25f	)	{ gesticulationLevel = VOICE_GESTICULATION_LEVEL_MEDIUM;	}
 +	else	if ( mSpeakingAmplitude > mMinGesticulationAmplitude + range * 0.00000f	)	{ gesticulationLevel = VOICE_GESTICULATION_LEVEL_LOW;		}
 +
 +	return gesticulationLevel;
 +
 +}//---------------------------------------------------
 +
 +
 +
 +//------------------------------------
 +// Destructor
 +//------------------------------------
 +LLVoiceVisualizer::~LLVoiceVisualizer()
 +{
 +}//----------------------------------------------
 +
 +
 +#ifdef XXX_STINSON_CHUI_REWORK
 +//---------------------------------------------------
 +// "packData" is inherited from HUDEffect
 +//---------------------------------------------------
 +void LLVoiceVisualizer::packData(LLMessageSystem *mesgsys)
 +{
 +	// Pack the default data
 +	LLHUDEffect::packData(mesgsys);
 +
 +	// TODO -- pack the relevant data for voice effects
 +	// we'll come up with some cool configurations....TBD
 +	//U8 packed_data[41];
 +	//mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, 41);
 +	U8 packed_data = 0;
 +	mesgsys->addBinaryDataFast(_PREHASH_TypeData, &packed_data, 1);
 +}
 +
 +
 +//---------------------------------------------------
 +// "unpackData" is inherited from HUDEffect
 +//---------------------------------------------------
 +void LLVoiceVisualizer::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
 +{
 +	// TODO -- find the speaker, unpack binary data, set the properties of this effect
 +	/*
 +	LLHUDEffect::unpackData(mesgsys, blocknum);
 +	LLUUID source_id;
 +	LLUUID target_id;
 +	S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData);
 +	if (size != 1)
 +	{
 +		llwarns << "Voice effect with bad size " << size << llendl;
 +		return;
 +	}
 +	mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, 1, blocknum);
 +	*/
 +}
 +
 +
 +//------------------------------------------------------------------
 +// this method is inherited from HUD Effect
 +//------------------------------------------------------------------
 +void LLVoiceVisualizer::markDead()
 +{
 +	mCurrentlySpeaking		= false;
 +	mVoiceEnabled			= false;
 +	mSoundSymbol.mActive	= false;
 +
 +	LLHUDEffect::markDead();
 +}//------------------------------------------------------------------
 +
 +#endif // XXX_STINSON_CHUI_REWORK
 diff --git a/indra/newview/llvoicevisualizer.h b/indra/newview/llvoicevisualizer.h index e434c7f3f1..6258de163d 100644 --- a/indra/newview/llvoicevisualizer.h +++ b/indra/newview/llvoicevisualizer.h @@ -42,7 +42,11 @@  #ifndef LL_VOICE_VISUALIZER_H  #define LL_VOICE_VISUALIZER_H +#ifdef XXX_STINSON_CHUI_REWORK  #include "llhudeffect.h" +#else // XXX_STINSON_CHUI_REWORK +#include "llpointer.h" +#endif // XXX_STINSON_CHUI_REWORK  //-----------------------------------------------------------------------------------------------  // The values of voice gesticulation represent energy levels for avatar animation, based on  @@ -60,34 +64,45 @@ enum VoiceGesticulationLevel  	NUM_VOICE_GESTICULATION_LEVELS  }; +#ifdef XXX_STINSON_CHUI_REWORK  const static int NUM_VOICE_SYMBOL_WAVES = 7; +#endif // XXX_STINSON_CHUI_REWORK  //----------------------------------------------------  // LLVoiceVisualizer class   //---------------------------------------------------- +#ifdef XXX_STINSON_CHUI_REWORK  class LLVoiceVisualizer : public LLHUDEffect +#else // XXX_STINSON_CHUI_REWORK +class LLVoiceVisualizer : public LLRefCount +#endif // XXX_STINSON_CHUI_REWORK  {  	//---------------------------------------------------  	// public methods   	//---------------------------------------------------  	public: -		LLVoiceVisualizer ( const U8 type );	//constructor +#ifdef XXX_STINSON_CHUI_REWORK +		LLVoiceVisualizer( const U8 type );	//constructor +#else // XXX_STINSON_CHUI_REWORK +		LLVoiceVisualizer();	//constructor +#endif // XXX_STINSON_CHUI_REWORK  		~LLVoiceVisualizer();					//destructor -		 -		friend class LLHUDObject; +#ifdef XXX_STINSON_CHUI_REWORK  		void					setVoiceSourceWorldPosition( const LLVector3 &p );		// this should be the position of the speaking avatar's head  		void					setMinGesticulationAmplitude( F32 );					// the lower range of meaningful amplitude for setting gesticulation level   		void					setMaxGesticulationAmplitude( F32 );					// the upper range of meaningful amplitude for setting gesticulation level  +#endif // XXX_STINSON_CHUI_REWORK  		void					setStartSpeaking();										// tell me when the av starts speaking +#ifdef XXX_STINSON_CHUI_REWORK  		void					setVoiceEnabled( bool );								// tell me whether or not the user is voice enabled +#endif // XXX_STINSON_CHUI_REWORK  		void					setSpeakingAmplitude( F32 );							// tell me how loud the av is speaking (ranges from 0 to 1)  		void					setStopSpeaking();										// tell me when the av stops speaking  		bool					getCurrentlySpeaking();									// the get for the above set  		VoiceGesticulationLevel	getCurrentGesticulationLevel();							// based on voice amplitude, I'll give you the current "energy level" of avatar speech -		static void				setPreferences( ); -		static void				lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ); // convert a string of digits to an array of floats  		void					lipSyncOohAah( F32& ooh, F32& aah ); +#ifdef XXX_STINSON_CHUI_REWORK  		void					render();												// inherited from HUD Effect  		void 					packData(LLMessageSystem *mesgsys);						// inherited from HUD Effect  		void 					unpackData(LLMessageSystem *mesgsys, S32 blocknum);		// inherited from HUD Effect @@ -103,12 +118,17 @@ class LLVoiceVisualizer : public LLHUDEffect  		//----------------------------------------------------------------------------------------------  		void setMaxGesticulationAmplitude();   		void setMinGesticulationAmplitude();  +#endif // XXX_STINSON_CHUI_REWORK  	//---------------------------------------------------  	// private members   	//---------------------------------------------------  	private: -	 +		static bool				handleVoiceVisualizerPrefsChanged(const LLSD& newvalue); +		static void				setPreferences( ); +		static void				lipStringToF32s ( std::string& in_string, F32*& out_F32s, U32& count_F32s ); // convert a string of digits to an array of floats + +#ifdef XXX_STINSON_CHUI_REWORK  		struct SoundSymbol  		{  			F32						mWaveExpansion			[ NUM_VOICE_SYMBOL_WAVES ]; @@ -119,15 +139,20 @@ class LLVoiceVisualizer : public LLHUDEffect  			bool					mActive;  			LLVector3				mPosition;  		}; +#endif // XXX_STINSON_CHUI_REWORK  		LLFrameTimer			mTimer;							// so I can ask the current time in seconds  		F64						mStartTime;						// time in seconds when speaking started +#ifdef XXX_STINSON_CHUI_REWORK  		F64						mCurrentTime;					// current time in seconds, captured every step  		F64						mPreviousTime;					// copy of "current time" from last frame  		SoundSymbol				mSoundSymbol;					// the sound symbol that appears over the avatar's head  		bool					mVoiceEnabled;					// if off, no rendering should happen +#endif // XXX_STINSON_CHUI_REWORK  		bool					mCurrentlySpeaking;				// is the user currently speaking? +#ifdef XXX_STINSON_CHUI_REWORK  		LLVector3				mVoiceSourceWorldPosition;		// give this to me every step - I need it to update the sound symbol +#endif // XXX_STINSON_CHUI_REWORK  		F32						mSpeakingAmplitude;				// this should be set as often as possible when the user is speaking  		F32						mMaxGesticulationAmplitude;		// this is the upper-limit of the envelope of detectable gesticulation leves  		F32						mMinGesticulationAmplitude;		// this is the lower-limit of the envelope of detectable gesticulation leves diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ab994c71cb..72455e4cd8 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -4697,11 +4697,6 @@ void LLPipeline::rebuildPools()  		}  		max_count--;  	} - -	if (isAgentAvatarValid()) -	{ -		gAgentAvatarp->rebuildHUD(); -	}  }  void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) @@ -6217,7 +6212,7 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable)  }  void LLPipeline::resetVertexBuffers() -{ +{	  	mResetVertexBuffers = true;  } diff --git a/indra/newview/skins/default/xui/en/floater_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml deleted file mode 100644 index 688a01ce7b..0000000000 --- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - positioning="specified" - left="10" - bottom="-10" - height="60" - layout="topleft" - legacy_header_height="25" - single_instance="true" - title="NEARBY CHAT" - save_rect="true" - save_visibility="true" - can_close="true" - can_minimize="true" - help_topic="chat_bar" - min_height="60" - min_width="150" - can_resize="true" - default_tab_group="1" - name="chat_bar" - width="300"> -    <panel -        top="20" -        class="panel_nearby_chat" -        follow="all" -        width="300" -        height="0" -        visible="false" -        filename="panel_nearby_chat.xml" -        name="nearby_chat" /> -    <panel width="300"  -           height="31"  -           left="0"  -           name="bottom_panel" -           bottom="-1"  -           follows="left|right|bottom"  -           tab_group="1"> -      <line_editor -        border_style="line" -        border_thickness="1" -        follows="left|right" -        height="23" -        label="Click here to chat." -        layout="topleft" -        left_delta="7" -        left="0" -        max_length_bytes="1023" -        name="chat_box" -        text_pad_left="5" -        text_pad_right="25" -        tool_tip="Press Enter to say, Ctrl+Enter to shout" -        top="2" -        width="255" /> -      <output_monitor -        auto_update="true" -        follows="right" -        draw_border="false" -        height="16" -        layout="topleft" -        left_pad="-24" -        mouse_opaque="true" -        name="chat_zone_indicator" -        top="6" -        visible="true" -        width="20" /> -      <button -        follows="right" -        is_toggle="true" -        width="20" -        top="2" -        layout="topleft" -        left_pad="12" -        image_disabled="ComboButton_UpOff" -        image_unselected="ComboButton_UpOff" -        image_selected="ComboButton_On" -        image_pressed="ComboButton_UpSelected" -        image_pressed_selected="ComboButton_Selected" -        height="23" -        chrome="true" -        name="show_nearby_chat" -        tool_tip="Shows/hides nearby chat log"> -      </button> -    </panel> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index e123de46c2..ce40f44a64 100644 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -1,49 +1,122 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <multi_floater - can_close="false"   + can_close="true"     can_minimize="true"   can_resize="true" - height="390" + height="430"   layout="topleft" + min_height="50"   name="floater_im_box"   help_topic="floater_im_box"   save_rect="true"   save_visibility="true"   single_instance="true"   title="CONVERSATIONS" - width="396"> -    <tab_container -     follows="left|right|top|bottom" -     height="390" + width="680"> +    <string +     name="collapse_icon" +     value="TabIcon_Open_Off"/> +    <string +     name="expand_icon" +     value="TabIcon_Close_Off"/> +    <layout_stack +     animate="true"  +     follows="all" +     height="430"       layout="topleft" -     left="1" -     name="im_box_tab_container" -     tab_position="bottom" -     tab_width="64" -     tab_max_width = "134" -     tab_height="16" -     use_custom_icon_ctrl="true" -     tab_icon_ctrl_pad="2" -     halign="left" -     use_ellipses="true" +     left="0" +     name="conversations_stack" +     orientation="horizontal"       top="0" -     width="394"> -      <first_tab -       tab_bottom_image_flash="Toolbar_Left_Flash"/> -      <middle_tab -       tab_bottom_image_flash="Toolbar_Middle_Flash"/> -      <last_tab -       tab_bottom_image_flash="Toolbar_Right_Flash"/> -    </tab_container> -    <icon -     color="DefaultShadowLight" -     enabled="false" -     follows="left|right|bottom" -     height="17" -     image_name="tabarea.tga" -     layout="bottomleft" -     left="1" -     name="im_box_tab_container_icon" -     bottom="10" -     width="394" /> +     width="680"> +        <layout_panel +         auto_resize="true" +         height="430" +         name="conversations_layout_panel" +         min_dim="41" +         width="268"> +            <layout_stack +             animate="false"  +             follows="left|top|right" +             height="35" +             layout="topleft" +             left="0" +             name="conversations_pane_buttons_stack" +             orientation="horizontal" +             top="0" +             width="268"> +                <layout_panel +                 auto_resize="true" +                 height="35" +                 name="conversations_pane_buttons_expanded"> +                    <menu_button +                     follows="top|left" +                     height="25" +                     image_hover_unselected="Toolbar_Middle_Over" +                     image_overlay="OptionsMenu_Off" +                     image_selected="Toolbar_Middle_Selected" +                     image_unselected="Toolbar_Middle_Off" +                     layout="topleft" +                     left="10" +                     name="sort_btn" +                     top="5" +                     width="31" /> +                    <button +                     follows="top|left" +                     height="25" +                     image_hover_unselected="Toolbar_Middle_Over" +                     image_overlay="AddItem_Off" +                     image_selected="Toolbar_Middle_Selected" +                      image_unselected="Toolbar_Middle_Off" +                     layout="topleft" +                     top="5" +                     left_pad="4" +                     name="add_btn" +                     tool_tip="Add button on the left panel" +                     width="31"/> +                </layout_panel> +                <layout_panel +                 auto_resize="false" +                 height="35" +                 name="conversations_pane_buttons_collapsed" +                 width="41"> +                    <button +                     follows="right|top" +                     height="25" +                     image_hover_unselected="Toolbar_Middle_Over" +                     image_overlay="TabIcon_Open_Off" +                     image_selected="Toolbar_Middle_Selected" +                     image_unselected="Toolbar_Middle_Off" +                     layout="topleft" +                     top="5" +                     left="5" +                     name="expand_collapse_btn" +                     width="31" /> +                </layout_panel> +            </layout_stack> +            <panel +             follows="all" +             layout="topleft" +             name="conversations_list_panel" +             opaque="true" +             top_pad="0" +             left="5" +             height="390" +             width="263"/> +        </layout_panel> +        <layout_panel +         auto_resize="true" +         height="430" +         name="messages_layout_panel" +         width="412"> +            <panel_container +             follows="all" +             height="430" +             layout="topleft" +             left="10" +             name="im_box_tab_container" +             top="0" +             width="402"/> +        </layout_panel> +    </layout_stack>  </multi_floater> diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index ca73883e53..beeb4eea9b 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <floater - legacy_header_height="18"   background_visible="true"   default_tab_group="1"   height="355" @@ -13,79 +12,253 @@   visible="false"   width="394"   can_resize="true" + can_tear_off="false"   min_width="250"   min_height="190"> +    <floater.string name="call_btn_start">VoicePTT_Off</floater.string> +    <floater.string name="call_btn_stop">VoicePTT_On</floater.string> +    <floater.string +     name="collapse_icon" +     value="TabIcon_Open_Off"/> +    <floater.string +     name="expand_icon" +     value="TabIcon_Close_Off"/> +    <floater.string +     name="tear_off_icon" +     value="tearoffbox.tga"/> +    <floater.string +     name="return_icon" +     value="Icon_Dock_Foreground"/> +    <view +        follows="all" +        layout="topleft" +        name="contents_view" +        top="0" +        left="0" +        height="355" +        width="394">  +     <panel +         follows="left|top|right" +         layout="topleft" +         name="toolbar_panel" +         top="0" +         left="0" +         height="35" +         width="394">          +             <menu_button +                 menu_filename="menu_im_session_showmodes.xml" +                 follows="top|left" +                 height="25" +                 image_hover_unselected="Toolbar_Left_Over" +                 image_overlay="OptionsMenu_Off" +                 image_selected="Toolbar_Left_Selected" +                 image_unselected="Toolbar_Left_Off" +                 layout="topleft" +                 left="5" +                 name="view_options_btn" +                 top="5" +                 width="31" /> +             <button +                 follows="top|left" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="AddItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left_pad="4" +                 name="add_btn" +                 width="31"> +             </button>    +             <button +                 follows="top|left" +                 height="25" +                 image_hover_unselected="Toolbar_Right_Over" +                 image_overlay="VoicePTT_Off" +                 image_selected="Toolbar_Right_Selected" +                 image_unselected="Toolbar_Right_Off" +                 layout="topleft" +                 top="5" +                 left_pad="4" +                 name="voice_call_btn" +                 width="31"> +             </button> +             <button +                 follows="right|top" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Icon_Close_Foreground" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left="283" +                 name="close_btn" +                 width="31" /> +             <button +                 follows="right|top" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TabIcon_Open_Off" +                 image_selected="Toolbar_Middle_Selected" +             	 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left_pad="5" +                 name="expand_collapse_btn" +                 width="31" /> +             <button +                 follows="right|top" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="tearoffbox.tga" +                 image_selected="Toolbar_Middle_Selected" +             	 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 top="5" +                 left_pad="5" +                 name="tear_off_btn" +                 width="31" /> +     </panel>    <layout_stack     animate="true"      default_tab_group="2"    follows="all" -  height="320" +  height="310"    width="394"    layout="topleft"    orientation="horizontal"    name="im_panels"    tab_group="1" -  top="20" -  left="0"> +  top_pad="0" +  left="0" +  auto_resize="true" +  user_resize="true">      <layout_panel -      name="im_control_panel_holder" +      name="speakers_list_panel" +      follows="all"        min_width="115"        width="150"  -      height="320"  +      height="310"         auto_resize="false"> -      <panel -        name="panel_im_control_panel" -        layout="topleft" -        height="320" -        width="150"  -        follows="all"/> -      </layout_panel> +            <avatar_list +             color="DkGray2" +             follows="all" +             height="310" +             ignore_online_status="true" +             layout="topleft" +             name="speakers_list" +             opaque="false" +             show_info_btn="true" +             show_profile_btn="false" +             show_speaking_indicator="false" +             width="150" /> +    </layout_panel>      <layout_panel         default_tab_group="3"         left="0"         tab_group="2" +       follows="all"         top="0" -       height="200" -	     width="254" -       user_resize="true"> -        <button -          height="20" -          follows="left|top" -          top="0" -          left="2" -          image_overlay="TabIcon_Open_Off" +       height="310" +	   width="244" +       layout="topleft" +       user_resize="true" +       auto_resize="true" +       visible="true" +       name="left_part_holder"> +        <panel +         name="trnsAndChat_panel" +         follows="all" +         layout="topleft" +         visible="true" +         height="275" +         width="244"> +         <layout_stack +          animate="true"  +          default_tab_group="2" +          follows="all" +          height="275" +          width="244"            layout="topleft" -          width="25" -          name="slide_left_btn" /> -         <button -          height="20" -          follows="left|top" +          visible="true" +          orientation="vertical" +          name="translate_and_chat_stack" +          tab_group="1" +          auto_resize="true" +          user_resize="true" +          left_pad="0"            top="0" -          left="2" -          image_overlay="TabIcon_Close_Off" -          width="25" -          name="slide_right_btn" /> -        <chat_history -	 font="SansSerifSmall" -         follows="left|right|top|bottom" -         height="150" -         name="chat_history" -         parse_highlights="true" -         parse_urls="true" -        left="1" -         width="249"> -        </chat_history> -        <line_editor -         bottom="0" -         follows="left|right|bottom" -	 font="SansSerifSmall" -         height="20" -         label="To" -         layout="bottomleft" -         name="chat_editor" -         tab_group="3" -         width="249"> -        </line_editor> +          left="0"> +            <layout_panel +             auto_resize="false" +             height="26" +             layout="topleft" +             left_delta="0" +             name="translate_chat_checkbox_lp" +             top_delta="0" +             visible="true" +             width="230"> +                <check_box +                 top="10" +                 control_name="TranslateChat" +                 enabled="true" +                 height="16" +                 label="Translate chat" +                 layout="topleft" +                 left="5" +                 name="translate_chat_checkbox" +                 width="230" /> +            </layout_panel> +            <layout_panel +             height="248" +             width="234" +             layout="topleft" +             follows="all" +             left_delta="0" +             top_delta="0" +             bottom="0" +             visible="true" +             user_resize="true" +             auto_resize="true" +             name="chat_holder">       +           		<chat_history +    	     		font="SansSerifSmall" +             		follows="all" +             		visible="true" +             		height="240" +            	 	name="chat_history" +             		parse_highlights="true" +             		parse_urls="true" +             		left="1" +             		width="229"> +            	</chat_history>            +            </layout_panel> +           </layout_stack> +           </panel> +            <panel width="228"  +             height="31"  +             left="4" +             right="4"  +             name="bottom_panel" +             bottom="-1"  +             follows="left|right|bottom"  +             tab_group="1">     +            	<line_editor +             		bottom="0" +             		follows="left|right|bottom" +	         		font="SansSerifSmall" +	         		visible="true" +             		height="20" +             		label="To" +             		layout="bottomleft" +             		name="chat_editor" +             		tab_group="3" +             		width="240"> +            	</line_editor> +              </panel>      </layout_panel>    </layout_stack> +    </view>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_people.xml b/indra/newview/skins/default/xui/en/floater_people.xml index 08d0b00a83..8e143623ab 100644 --- a/indra/newview/skins/default/xui/en/floater_people.xml +++ b/indra/newview/skins/default/xui/en/floater_people.xml @@ -7,20 +7,20 @@    height="570"    help_topic="sidebar_people"    min_height="440" -  min_width="333" +  min_width="390"    layout="topleft"    name="floater_people"    save_rect="true"    single_instance="true"    reuse_instance="true"    title="PEOPLE" -  width="333"> +  width="390">      <panel_container        default_panel_name="panel_people"        follows="all"        height="570"        name="main_panel" -      width="333"> +      width="390">        <panel          class="panel_people"          name="panel_people" @@ -31,11 +31,5 @@          filename="panel_group_info_sidetray.xml"          label="Group Profile"          font="SansSerifBold"/> -      <panel -        class="panel_block_list_sidetray" -        name="panel_block_list_sidetray" -        filename="panel_block_list_sidetray.xml" -        label="Blocked Residents & Objects" -        font="SansSerifBold"/>      </panel_container>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_voice_volume.xml b/indra/newview/skins/default/xui/en/floater_voice_volume.xml new file mode 100644 index 0000000000..9346295d5b --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_voice_volume.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<!-- +  Not can_close / no title to avoid window chrome +  Single instance - only have one at a time, recycle it each spawn +--> +<floater + legacy_header_height="25" + bevel_style="in" + bg_opaque_image="Inspector_Background" + can_close="false" + can_minimize="false" + height="90" + layout="topleft" + name="floater_voice_volume" + single_instance="true" + sound_flags="0" + title="VOICE VOLUME" + visible="true" + width="245"> +    <text +     follows="top|left|right" +     font="SansSerifSmall" +     height="21" +     left="10" +     name="avatar_name" +     parse_urls="false" +     top="35" +     text_color="White" +     translate="false" +     use_ellipses="true" +     value="TestString PleaseIgnore" +     width="225" /> +    <slider +     follows="top|left" +     height="23" +     increment="0.01" +     left="1" +     max_val="0.95" +     min_val="0.05" +     name="volume_slider" +     show_text="false" +     tool_tip="Voice volume" +     top_pad="0" +     value="0.5" +     width="200" /> +    <button +     follows="top|left" +     height="16" +     image_disabled="Audio_Off" +     image_disabled_selected="AudioMute_Off" +     image_hover_selected="AudioMute_Over" +     image_selected="AudioMute_Off" +     image_unselected="Audio_Off" +     is_toggle="true" +     left_pad="0" +     top_delta="4" +     name="mute_btn" +     width="16" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml index bc3bcd331b..c3481e6d4c 100644 --- a/indra/newview/skins/default/xui/en/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml @@ -9,7 +9,7 @@   bg_opaque_image="Inspector_Background"   can_close="false"   can_minimize="false" - height="164" + height="130"   layout="topleft"   name="inspect_avatar"   single_instance="true" @@ -94,32 +94,17 @@       use_ellipses="true"       width="220">This is my second life description and I really think it is great. But for some reason my description is super extra long because I like to talk a whole lot      </text> -    <slider -     follows="top|left" -     height="23" -     increment="0.01" -     left="1" -     max_val="0.95" -     min_val="0.05" -     name="volume_slider" -     show_text="false" -     tool_tip="Voice volume" -     top_pad="0" -     value="0.5" -     width="200" /> -    <button +    <text       follows="top|left"       height="16" -     image_disabled="Audio_Off" -     image_disabled_selected="AudioMute_Off" -     image_hover_selected="AudioMute_Over" -     image_selected="AudioMute_Off" -     image_unselected="Audio_Off" -     is_toggle="true" -     left_pad="0" -     top_delta="4" -     name="mute_btn" -     width="16" /> +     left="8" +     name="avatar_profile_link" +     font="SansSerifSmall" +     text_color="White" +     top_pad="5" +     translate="false" +     value="[[LINK] View full profile]" +     width="175" />      <avatar_icon       follows="top|left"       height="38" @@ -130,83 +115,4 @@       name="avatar_icon"       top="10"       width="38" /> -<!-- Overlapping buttons for default actions -    llinspectavatar.cpp makes visible the most likely default action  ---> -    <button -     follows="top|left" -     height="20" -     label="Add Friend" -     left="8" -     top="135" -     name="add_friend_btn" -     width="90" /> -    <button -     follows="top|left" -     height="20" -     label="IM" -     left_delta="0" -     top_delta="0" -     name="im_btn" -     width="80" -     commit_callback.function="InspectAvatar.IM"/> -	<button -     follows="top|left" -     height="20" -     label="Profile" -     layout="topleft" -     name="view_profile_btn" -     left_delta="96" -     top_delta="0" -     tab_stop="false" -     width="80" /> -      <!--  gear buttons here --> -  <menu_button -     follows="top|left" -     height="20" -     layout="topleft" -     image_overlay="OptionsMenu_Off" -     menu_filename="menu_inspect_avatar_gear.xml" -     name="gear_btn" -     right="-5" -     top_delta="0" -     width="35" /> -	<menu_button -     follows="top|left" -     height="20" -     image_overlay="OptionsMenu_Off" -     menu_filename="menu_inspect_self_gear.xml" -     name="gear_self_btn" -     right="-5" -     top_delta="0" -     width="35" /> -  <panel  -    follows="top|left"  -    top="164"  -    left="0"  -    height="60"  -    width="228"  -    visible="false" -    background_visible="true" -    name="moderator_panel" -    background_opaque="true"  -    bg_opaque_color="MouseGray"> -    <button -      name="disable_voice" -      label="Disable Voice" -      top="20" -      width="95" -      height="20" -      left="10" -      commit_callback.function="InspectAvatar.DisableVoice"/> -    <button -      name="enable_voice" -      label="Enable Voice" -      top="20" -      width="95" -      height="20" -      left="10" -      visible="false"  -      commit_callback.function="InspectAvatar.EnableVoice"/> -  </panel>  </floater> diff --git a/indra/newview/skins/default/xui/en/menu_group_plus.xml b/indra/newview/skins/default/xui/en/menu_group_plus.xml index fce7414d80..eca9e7f3c9 100644 --- a/indra/newview/skins/default/xui/en/menu_group_plus.xml +++ b/indra/newview/skins/default/xui/en/menu_group_plus.xml @@ -1,5 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<menu name="menu_group_plus" +<toggleable_menu name="menu_group_plus"       left="0" bottom="0" visible="false"       mouse_opaque="false">    <menu_item_call name="item_join" label="Join Group..."> @@ -8,4 +8,4 @@    <menu_item_call name="item_new" label="New Group...">      <menu_item_call.on_click function="People.Group.Plus.Action" userdata="new_group" />    </menu_item_call> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml new file mode 100644 index 0000000000..483f24afd0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_modes" + left="0" bottom="0" visible="false" + mouse_opaque="false"> +    <menu_item_check +       label="Compact view" +       name="compact_view"> +      <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="compact_view"/> +      <menu_item_check.on_check +         function="IMSession.Menu.CompactExpandedModes.CheckItem" +         parameter="compact_view"/> +    </menu_item_check> +    <menu_item_check +       label="Expanded view" +       name="expanded_view"> +      <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="expanded_view"/> +      <menu_item_check.on_check +         function="IMSession.Menu.CompactExpandedModes.CheckItem" +         parameter="expanded_view"/> +    </menu_item_check> +    <menu_item_separator layout="topleft" /> +    <menu_item_check name="IMShowTime" label="Show time"> +        <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="IMShowTime" /> +        <menu_item_check.on_check +         function="IMSession.Menu.ShowModes.CheckItem" +         parameter="IMShowTime" /> +        <menu_item_check.on_enable +         function="IMSession.Menu.ShowModes.Enable" +         parameter="IMShowTime" /> +    </menu_item_check> +    <menu_item_check name="IMShowNamesForP2PConv" label="Show names in one-to-one conversations"> +        <menu_item_check.on_click +         function="IMSession.Menu.Action" +         parameter="IMShowNamesForP2PConv" /> +        <menu_item_check.on_check +         function="IMSession.Menu.ShowModes.CheckItem" +         parameter="IMShowNamesForP2PConv" /> +        <menu_item_check.on_enable +         function="IMSession.Menu.ShowModes.Enable" +         parameter="IMShowNamesForP2PConv" /> +          +    </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml deleted file mode 100644 index 76b188220d..0000000000 --- a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml +++ /dev/null @@ -1,143 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<toggleable_menu -         create_jump_keys="true" -         layout="topleft" -         mouse_opaque="false" -         visible="false" -         name="Gear Menu"> -  <menu_item_call -   label="View Profile" -   enabled="true"  -   name="view_profile"> -    <menu_item_call.on_click -     function="InspectAvatar.ViewProfile"/> -  </menu_item_call> -  <menu_item_call -   label="Add Friend" -   name="add_friend"> -    <menu_item_call.on_click -     function="InspectAvatar.AddFriend"/> -    <menu_item_call.on_enable -     function="InspectAvatar.Gear.Enable"/> -  </menu_item_call> -  <menu_item_call -   label="IM" -   name="im"> -    <menu_item_call.on_click -     function="InspectAvatar.IM"/> -  </menu_item_call> -  <menu_item_call -   label="Call" -   enabled="true" -   name="call"> -    <menu_item_call.on_click -     function="InspectAvatar.Call"/> -    <menu_item_call.on_enable -     function="InspectAvatar.Gear.EnableCall"/> -  </menu_item_call> -  <menu_item_call -   label="Teleport" -   name="teleport"> -    <menu_item_call.on_click -     function="InspectAvatar.Teleport"/> -    <menu_item_call.on_enable -     function="InspectAvatar.Gear.EnableTeleportOffer"/> -  </menu_item_call> -  <menu_item_call -   label="Invite to Group" -   name="invite_to_group"> -    <menu_item_call.on_click -     function="InspectAvatar.InviteToGroup"/> -  </menu_item_call> -  <menu_item_separator /> -  <menu_item_call -   label="Block" -   name="block"> -    <menu_item_call.on_click -     function="InspectAvatar.ToggleMute"/> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableMute" /> -  </menu_item_call> -  <menu_item_call -   label="Unblock" -   name="unblock"> -    <menu_item_call.on_click -     function="InspectAvatar.ToggleMute"/> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableUnmute" /> -  </menu_item_call> -  <menu_item_call -   label="Report" -   name="report"> -    <menu_item_call.on_click -     function="InspectAvatar.Report"/> -  </menu_item_call>   -  <menu_item_call -   label="Freeze" -   name="freeze"> -    <menu_item_call.on_click -     function="InspectAvatar.Freeze"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleFreeze"/> -  </menu_item_call> -  <menu_item_call -   label="Eject" -   name="eject"> -    <menu_item_call.on_click -     function="InspectAvatar.Eject"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleEject"/> -  </menu_item_call> -  <menu_item_call -   label="Kick" -   name="kick"> -    <menu_item_call.on_click -     function="InspectAvatar.Kick"/> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableGod"/> -  </menu_item_call> -  <menu_item_call -  label="CSR" -  name="csr"> -    <menu_item_call.on_click -     function="InspectAvatar.CSR" /> -    <menu_item_call.on_visible -     function="InspectAvatar.EnableGod" /> -  </menu_item_call> -  <menu_item_call -   label="Debug Textures" -   name="debug"> -    <menu_item_call.on_click -     function="Avatar.Debug"/> -    <menu_item_call.on_visible -     function="IsGodCustomerService"/> -  </menu_item_call> -  <menu_item_call -   label="Find On Map" -   name="find_on_map"> -    <menu_item_call.on_click -     function="InspectAvatar.FindOnMap"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleFindOnMap"/> -  </menu_item_call> -  <menu_item_call -   label="Zoom In" -   name="zoom_in"> -    <menu_item_call.on_click -     function="InspectAvatar.ZoomIn"/> -    <menu_item_call.on_visible -     function="InspectAvatar.VisibleZoomIn"/> -  </menu_item_call>   -  <menu_item_call -   label="Pay" -   name="pay"> -    <menu_item_call.on_click -     function="InspectAvatar.Pay"/> -  </menu_item_call> -  <menu_item_call -   label="Share" -   name="share"> -    <menu_item_call.on_click -     function="InspectAvatar.Share"/> -  </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml deleted file mode 100644 index 5e7b16ed4a..0000000000 --- a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml +++ /dev/null @@ -1,252 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu - layout="topleft" - name="Self Pie"> -  <menu_item_call -   label="Sit Down" -   layout="topleft" -   name="Sit Down Here"> -    <menu_item_call.on_click -     function="Self.SitDown" -     parameter="" /> -    <menu_item_call.on_enable -     function="Self.EnableSitDown" /> -  </menu_item_call> -  <menu_item_call -   label="Stand Up" -   layout="topleft" -   name="Stand Up"> -    <menu_item_call.on_click -     function="Self.StandUp" -     parameter="" /> -    <menu_item_call.on_enable -     function="Self.EnableStandUp" /> -  </menu_item_call> -  <context_menu -   label="Take Off" -   layout="topleft" -   name="Take Off >"> -    <context_menu -     label="Clothes" -     layout="topleft" -     name="Clothes >"> -      <menu_item_call -       enabled="false" -       label="Shirt" -       layout="topleft" -       name="Shirt"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="shirt" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="shirt" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Pants" -       layout="topleft" -       name="Pants"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="pants" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="pants" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Skirt" -       layout="topleft" -       name="Skirt"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="skirt" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="skirt" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Shoes" -       layout="topleft" -       name="Shoes"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="shoes" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="shoes" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Socks" -       layout="topleft" -       name="Socks"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="socks" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="socks" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Jacket" -       layout="topleft" -       name="Jacket"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="jacket" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="jacket" /> -      </menu_item_call> -      <menu_item_call -       enabled="false" -       label="Gloves" -       layout="topleft" -       name="Gloves"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="gloves" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="gloves" /> -      </menu_item_call> -      <menu_item_call -            enabled="false" -            label="Undershirt" -            layout="topleft" -            name="Self Undershirt"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="undershirt" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="undershirt" /> -      </menu_item_call> -      <menu_item_call -        enabled="false" -        label="Underpants" -        layout="topleft" -        name="Self Underpants"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="underpants" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="underpants" /> -      </menu_item_call> -      <menu_item_call -        enabled="false" -        label="Tattoo" -        layout="topleft" -        name="Self Tattoo"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="tattoo" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="tattoo" /> -      </menu_item_call> -      <menu_item_call -        enabled="false" -        label="Alpha" -        layout="topleft" -        name="Self Alpha"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="alpha" /> -        <menu_item_call.on_enable -         function="Edit.EnableTakeOff" -         parameter="alpha" /> -      </menu_item_call> -      <menu_item_separator -       layout="topleft" /> -      <menu_item_call -       label="All Clothes" -       layout="topleft" -       name="All Clothes"> -        <menu_item_call.on_click -         function="Edit.TakeOff" -         parameter="all" /> -      </menu_item_call> -    </context_menu> -    <context_menu -     label="HUD" -     layout="topleft" -     name="Object Detach HUD" /> -    <context_menu -     label="Detach" -     layout="topleft" -     name="Object Detach" /> -    <menu_item_call -     label="Detach All" -     layout="topleft" -     name="Detach All"> -      <menu_item_call.on_click -       function="Self.RemoveAllAttachments" -       parameter="" /> -      <menu_item_call.on_enable -       function="Self.EnableRemoveAllAttachments" /> -    </menu_item_call> -  </context_menu> -  <menu_item_call -  label="Change Outfit" -  layout="topleft" -  name="Chenge Outfit"> -    <menu_item_call.on_click -     function="CustomizeAvatar" /> -    <menu_item_call.on_enable -     function="Edit.EnableCustomizeAvatar" /> -  </menu_item_call> -  <menu_item_call label="Edit My Outfit" -  layout="topleft" -  name="Edit Outfit"> -    <menu_item_call.on_click -     function="EditOutfit" /> -    <menu_item_call.on_enable -     function="Edit.EnableCustomizeAvatar" /> -  </menu_item_call> -  <menu_item_call label="Edit My Shape" -  layout="topleft" -  name="Edit My Shape"> -    <menu_item_call.on_click -     function="EditShape" /> -    <menu_item_call.on_enable -     function="Edit.EnableEditShape" /> -  </menu_item_call> -  <menu_item_call -    label="My Friends" -    layout="topleft" -    name="Friends..."> -    <menu_item_call.on_click -     function="SideTray.PanelPeopleTab" -     parameter="friends_panel" /> -  </menu_item_call> -  <menu_item_call -   label="My Groups" -   layout="topleft" -   name="Groups..."> -    <menu_item_call.on_click -     function="SideTray.PanelPeopleTab" -     parameter="groups_panel" /> -  </menu_item_call> -  <menu_item_call -    label="My Profile" -    layout="topleft" -    name="Profile..."> -    <menu_item_call.on_click -     function="ShowAgentProfile" -     parameter="agent" /> -  </menu_item_call> -  <menu_item_call -   label="Debug Textures" -       name="Debug..."> -    <menu_item_call.on_click -     function="Avatar.Debug" /> -    <menu_item_call.on_visible -     function="IsGodCustomerService"/> -  </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml index b452f96e7a..eab7b8c085 100644 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -40,8 +40,4 @@       function="CheckControl"       parameter="FriendsListShowPermissions" />    </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> -    <menu_item_call.on_click function="People.Friends.ViewSort.Action" parameter="panel_block_list_sidetray" /> -  </menu_item_call>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups.xml b/indra/newview/skins/default/xui/en/menu_people_groups.xml index 8f89d37dbb..1e0364b84e 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups.xml @@ -1,8 +1,18 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<menu name="menu_group_plus" +<toggleable_menu name="menu_group_plus"   left="0" bottom="0" visible="false"   mouse_opaque="false" opaque="true" color="MenuDefaultBgColor">    <menu_item_call +   label="Activate" +   name="Activate"> +    <menu_item_call.on_click +     function="People.Groups.Action" +     parameter="activate" /> +    <menu_item_call.on_enable +     function="People.Groups.Enable" +     parameter="activate" /> +  </menu_item_call> +  <menu_item_call     label="View Info"     name="View Info">      <menu_item_call.on_click @@ -23,7 +33,7 @@       parameter="chat" />    </menu_item_call>    <menu_item_call -   label="Call" +   label="Voice call"     name="Call">      <menu_item_call.on_click       function="People.Groups.Action" @@ -34,17 +44,6 @@    </menu_item_call>    <menu_item_separator />    <menu_item_call -   label="Activate" -   name="Activate"> -    <menu_item_call.on_click -     function="People.Groups.Action" -     parameter="activate" /> -    <menu_item_call.on_enable -     function="People.Groups.Enable" -     parameter="activate" /> -  </menu_item_call> -  <menu_item_separator /> -  <menu_item_call     label="Leave"     name="Leave">      <menu_item_call.on_click @@ -54,4 +53,4 @@       function="People.Groups.Enable"       parameter="leave" />    </menu_item_call> -</menu> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view.xml index c710fe3b9b..73f79f1e70 100644 --- a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_groups_view.xml @@ -14,13 +14,4 @@         function="CheckControl"         parameter="GroupListShowIcons" />    </menu_item_check> -  <menu_item_call -   label="Leave Selected Group" -   layout="topleft" -   name="Leave Selected Group"> -      <menu_item_call.on_click -       function="People.Group.Minus.Action"/> -      <menu_item_call.on_enable -       function="People.Group.Minus.Enable"/> -  </menu_item_call>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index d2e35e4cc0..b7c9ab1fe3 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -10,12 +10,39 @@           function="Avatar.Profile" />      </menu_item_call>      <menu_item_call +     label="IM" +     layout="topleft" +     name="IM"> +        <menu_item_call.on_click +         function="Avatar.IM" /> +    </menu_item_call> +    <menu_item_call +    label="Offer Teleport" +    name="teleport"> +      <menu_item_call.on_click +       function="Avatar.OfferTeleport"/> +      <menu_item_call.on_enable +      function="Avatar.EnableItem" +      parameter="can_offer_teleport"/> +    </menu_item_call> +    <menu_item_call +     label="Voice call" +     layout="topleft" +     name="Call"> +        <menu_item_call.on_click +         function="Avatar.Call" /> +        <menu_item_call.on_enable +         function="Avatar.EnableItem" +         parameter="can_call" /> +    </menu_item_call> +    <menu_item_separator /> +    <menu_item_call       label="Add Friend"       layout="topleft"       name="Add Friend">          <menu_item_call.on_click           function="Avatar.AddFriend" /> -        <menu_item_call.on_enable +        <menu_item_call.on_visible           function="Avatar.EnableItem"           parameter="can_add" />      </menu_item_call> @@ -30,22 +57,13 @@           parameter="can_delete" />      </menu_item_call>      <menu_item_call -     label="IM" +     label="Invite to group..."       layout="topleft" -     name="IM"> +     name="Invite">          <menu_item_call.on_click -         function="Avatar.IM" /> -    </menu_item_call> -    <menu_item_call -     label="Call" -     layout="topleft" -     name="Call"> -        <menu_item_call.on_click -         function="Avatar.Call" /> -        <menu_item_call.on_enable -         function="Avatar.EnableItem" -         parameter="can_call" /> +         function="Avatar.InviteToGroup" />      </menu_item_call> +    <menu_item_separator />      <menu_item_call       label="Map"       layout="topleft" @@ -83,13 +101,5 @@           function="Avatar.EnableItem"           parameter="can_block" />      </menu_item_check> -    <menu_item_call -    label="Offer Teleport" -    name="teleport"> -      <menu_item_call.on_click -       function="Avatar.OfferTeleport"/> -      <menu_item_call.on_enable -      function="Avatar.EnableItem" -      parameter="can_offer_teleport"/> -    </menu_item_call> +  </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml new file mode 100644 index 0000000000..da88ca9f4d --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_nearby_view.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_group_plus" + left="0" bottom="0" visible="false" + mouse_opaque="false"> +    <menu_item_check +       label="Sort by Recent Speakers" +       name="sort_by_recent_speakers"> +      <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +       parameter="sort_by_recent_speakers"/> +      <menu_item_check.on_check +         function="People.Nearby.ViewSort.CheckItem" +         parameter="sort_by_recent_speakers"/> +    </menu_item_check> +    <menu_item_check +       label="Sort by Name" +       name="sort_name"> +      <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +         parameter="sort_name"/> +      <menu_item_check.on_check +         function="People.Nearby.ViewSort.CheckItem" +         parameter="sort_name"/> +    </menu_item_check> +    <menu_item_check +       label="Sort by Distance" +       name="sort_distance"> +      <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +         parameter="sort_distance"/> +      <menu_item_check.on_check +         function="People.Nearby.ViewSort.CheckItem" +         parameter="sort_distance"/> +    </menu_item_check> +    <menu_item_separator layout="topleft" /> +    <menu_item_check name="view_icons" label="View People Icons"> +        <menu_item_check.on_click +         function="People.Nearby.ViewSort.Action" +         parameter="view_icons" /> +        <menu_item_check.on_check +         function="CheckControl" +         parameter="NearbyListShowIcons" /> +    </menu_item_check> +    <menu_item_check name ="view_map" label="View Map"> +        <menu_item_check.on_check +         function="CheckControl" +         parameter="NearbyListShowMap" /> +        <menu_item_check.on_click +         function="ToggleControl" +         parameter="NearbyListShowMap" /> +    </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml deleted file mode 100644 index 614dd693c5..0000000000 --- a/indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<toggleable_menu -     name="menu_group_plus" -     left="0" bottom="0" visible="false" -     mouse_opaque="false"> -  <menu_item_check -     label="Sort by Recent Speakers" -     name="sort_by_recent_speakers"> -    <menu_item_check.on_click -       function="People.Nearby.ViewSort.Action" -       parameter="sort_by_recent_speakers"/> -    <menu_item_check.on_check -       function="People.Nearby.ViewSort.CheckItem" -       parameter="sort_by_recent_speakers"/> -  </menu_item_check> -  <menu_item_check -     label="Sort by Name" -     name="sort_name"> -    <menu_item_check.on_click -       function="People.Nearby.ViewSort.Action" -       parameter="sort_name"/> -    <menu_item_check.on_check -       function="People.Nearby.ViewSort.CheckItem" -       parameter="sort_name"/> -  </menu_item_check> -  <menu_item_check -     label="Sort by Distance" -     name="sort_distance"> -    <menu_item_check.on_click -       function="People.Nearby.ViewSort.Action" -       parameter="sort_distance"/> -    <menu_item_check.on_check -       function="People.Nearby.ViewSort.CheckItem" -       parameter="sort_distance"/> -  </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_check name="view_icons" label="View People Icons"> -    <menu_item_check.on_click -     function="People.Nearby.ViewSort.Action" -     parameter="view_icons" /> -    <menu_item_check.on_check -     function="CheckControl" -     parameter="NearbyListShowIcons" /> -  </menu_item_check> -  <menu_item_check name ="view_map" label="View Map"> -    <menu_item_check.on_check -      function="CheckControl" -      parameter="NearbyListShowMap" /> -    <menu_item_check.on_click -      function="ToggleControl" -      parameter="NearbyListShowMap" /> -  </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> -    <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="panel_block_list_sidetray" /> -  </menu_item_call> -</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml index 485a5a658c..1dbc90dd2b 100644 --- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_recent_view.xml @@ -32,8 +32,4 @@       function="CheckControl"       parameter="RecentListShowIcons" />    </menu_item_check> -  <menu_item_separator layout="topleft" /> -  <menu_item_call name="show_blocked_list" label="Show Blocked Residents & Objects"> -    <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="panel_block_list_sidetray" /> -  </menu_item_call>  </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index afc5b916e7..8f8f4ae7ff 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2904,6 +2904,7 @@ Would you like to trust this authority?     icon="alertmodal.tga"     name="GrantedModifyRights"     persist="true" +   log_to_im="true"        type="notify">  [NAME] has given you permission to edit their objects.    </notification> @@ -2912,6 +2913,7 @@ Would you like to trust this authority?     icon="alertmodal.tga"     name="RevokedModifyRights"     persist="true" +   log_to_im="true"        type="notify">  Your privilege to modify [NAME]'s objects has been revoked    </notification> @@ -5161,6 +5163,8 @@ The string [STRING_NAME] is missing from strings.xml    <notification     icon="notifytip.tga"     name="IMSystemMessageTip" +   log_to_im="true"    +   log_to_chat="false"        type="notifytip">  [MESSAGE]    </notification> @@ -5204,18 +5208,14 @@ Topic: [SUBJECT], Message: [MESSAGE]    <notification     icon="notifytip.tga" -   name="FriendOnline" +   name="FriendOnlineOffline" +   log_to_chat="false"     type="notifytip">      <tag>friendship</tag> -<nolink>[NAME]</nolink> is Online -  </notification> - -  <notification -   icon="notifytip.tga" -   name="FriendOffline" -   type="notifytip"> -    <tag>friendship</tag> -<nolink>[NAME]</nolink> is Offline +<nolink>[NAME]</nolink> is [STATUS] +    <unique combine="cancel_old"> +      <context>NAME</context> +    </unique>    </notification>    <notification @@ -5459,6 +5459,8 @@ You don't have permission to copy this.    <notification     icon="notifytip.tga"     name="InventoryAccepted" +   log_to_im="true"    +   log_to_chat="false"     type="notifytip">  [NAME] received your inventory offer.    </notification> @@ -5466,6 +5468,8 @@ You don't have permission to copy this.    <notification     icon="notifytip.tga"     name="InventoryDeclined" +   log_to_im="true"    +   log_to_chat="false"     type="notifytip">  [NAME] declined your inventory offer.    </notification> @@ -5547,6 +5551,7 @@ Please select at least one type of content to search (General, Moderate, or Adul    <notification     icon="notify.tga"     name="PaymentReceived" +   log_to_im="true"        persist="true"     type="notify">      <tag>funds</tag> @@ -5556,6 +5561,7 @@ Please select at least one type of content to search (General, Moderate, or Adul    <notification     icon="notify.tga"     name="PaymentSent" +   log_to_im="true"        persist="true"     type="notify">      <tag>funds</tag> @@ -5700,6 +5706,7 @@ The objects on the selected parcel that are NOT owned by you have been returned    <notification     icon="notify.tga"     name="ServerObjectMessage" +   log_to_im="true"        persist="true"     type="notify">  Message from [NAME]: @@ -6070,6 +6077,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="UserGiveItem" +   log_to_im ="true"     type="offer">  [NAME_SLURL] has given you this [OBJECTTYPE]:  [ITEM_SLURL] @@ -6125,6 +6133,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="TeleportOffered" +   log_to_im="true"     type="offer">  [NAME_SLURL] has offered to teleport you to their location: @@ -6145,6 +6154,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="TeleportOfferSent" +   log_to_im="true" +   show_toast="false"     type="offer">  	Teleport offer sent to [TO_NAME]    </notification> @@ -6172,6 +6183,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="OfferFriendship" +   log_to_im="true"     type="offer">      <tag>friendship</tag>      <tag>confirm</tag> @@ -6195,6 +6207,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="FriendshipOffered" +   log_to_im="true"    +   show_toast="false"        type="offer">      <tag>friendship</tag>  	You have offered friendship to [TO_NAME] @@ -6224,6 +6238,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="FriendshipAccepted" +   log_to_im="true"        type="offer">      <tag>friendship</tag>  <nolink>[NAME]</nolink> accepted your friendship offer. @@ -6232,6 +6247,7 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th    <notification     icon="notify.tga"     name="FriendshipDeclined" +   log_to_im="true"        persist="true"     type="notify">      <tag>friendship</tag> @@ -6241,6 +6257,8 @@ Your object named <nolink>[OBJECTFROMNAME]</nolink> has given you th      <notification     icon="notify.tga"     name="FriendshipAcceptedByMe" +   log_to_im="true"    +   show_toast="false"     type="offer">      <tag>friendship</tag>  Friendship offer accepted. @@ -6249,6 +6267,8 @@ Friendship offer accepted.    <notification     icon="notify.tga"     name="FriendshipDeclinedByMe" +   log_to_im="true"    +   show_toast="false"        type="offer">      <tag>friendship</tag>  Friendship offer declined. diff --git a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml deleted file mode 100644 index d68fa6ca6c..0000000000 --- a/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml +++ /dev/null @@ -1,95 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - follows="all" - height="215" - name="panel_im_control_panel" - width="150"> -    <layout_stack -     mouse_opaque="false" -     border_size="0" -     clip="false" -     follows="all" -     height="215" -     layout="topleft" -     left="3" -     name="vertical_stack" -     orientation="vertical" -     top="0" -     width="147"> -        <layout_panel -         auto_resize="true" -         follows="top|left" -         height="130" -         layout="topleft" -         left="0" -         min_height="0" -         mouse_opaque="false" -         width="147" -         top="0" -         name="speakers_list_panel"> -            <avatar_list -             color="DkGray2" -             follows="all" -             height="130" -             ignore_online_status="true" -             layout="topleft" -             name="speakers_list" -             opaque="false" -             show_info_btn="true" -             show_profile_btn="false" -             show_speaking_indicator="false" -             width="147" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="130" -         name="call_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="20" -             label="Call" -             name="call_btn" -             width="130" -             top="0" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="130" -         name="end_call_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="20" -             label="Leave Call" -             name="end_call_btn" -             top="0"/> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="130" -         name="voice_ctrls_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="20" -             label="Voice Controls" -             name="voice_ctrls_btn" -             top="0" -             use_ellipses="true" /> -        </layout_panel> -    </layout_stack> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 7c67fd7f83..3577d2f457 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -4,6 +4,8 @@   follows="left|top|right|bottom"   height="305"   layout="topleft" + left="0" + right="-1"   name="block_list_panel"   help_topic="blocked_list"   min_height="350" @@ -28,7 +30,7 @@       layout="topleft"       left_pad="10"       name="title_text" -     text_color="White" +     text_color="white"       top="5"       width="250">          Block List @@ -41,6 +43,7 @@       name="blocked"       tool_tip="List of currently blocked Residents"       top="30" +  	 right="-1"       width="270">          <scroll_list.columns           name="item_name" /> diff --git a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml deleted file mode 100644 index ad10e53a4e..0000000000 --- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml +++ /dev/null @@ -1,109 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - follows="all" - height="238" - name="panel_im_control_panel" - width="150"> -    <layout_stack -     mouse_opaque="false" -     border_size="0" -     clip="false" -     follows="all" -     height="238" -     layout="topleft" -     left="5" -     name="vertical_stack" -     orientation="vertical" -     top="0" -     width="145"> -        <layout_panel -         auto_resize="true" -         follows="top|left" -         height="100" -         layout="topleft" -         min_height="0" -         mouse_opaque="false" -         width="145" -         top="0" -         name="speakers_list_panel"> -            <avatar_list -             color="DkGray2" -             follows="all" -             height="100" -             ignore_online_status="true" -             layout="topleft" -             name="speakers_list" -             opaque="false" -             show_info_btn="true" -             show_profile_btn="false" -             show_speaking_indicator="false" -             width="145" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="group_info_btn_panel"> -            <button -             follows="left|right|bottom" -             height="23" -             label="Group Profile" -             name="group_info_btn" -             use_ellipses="true" -             top="5" -             width="130" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="call_btn_panel"> -            <button -             follows="all" -             height="23" -             label="Call Group" -             name="call_btn" -             use_ellipses="true"  -             width="130" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="end_call_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="23" -             label="Leave Call" -             name="end_call_btn" -             use_ellipses="true" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="28" -         layout="topleft" -         min_height="28" -         width="130" -         name="voice_ctrls_btn_panel" -         visible="false"> -            <button -             follows="all" -             height="23" -             label="Open Voice Controls" -             name="voice_ctrls_btn" -             use_ellipses="true" /> -        </layout_panel> -    </layout_stack> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml deleted file mode 100644 index 8fcd6ccbaf..0000000000 --- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml +++ /dev/null @@ -1,166 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - border="false" - height="300" - name="panel_im_control_panel" - width="150"> -    <avatar_icon -     follows="left|top" -     height="105" -     left_delta="20" -     name="avatar_icon" -     top="-5" -     width="114"/> -    <layout_stack -     mouse_opaque="false" -     border_size="0" -     clip="false" -     follows="all" -     height="183" -     layout="topleft" -     left="5" -     name="button_stack" -     orientation="vertical" -     top_pad="5" -     width="145"> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="20" -         layout="topleft" -         left="2"  -         min_height="20" -         width="140" -         name="view_profile_btn_panel" -         top="0" > -            <button -             follows="left|top|right" -             height="23" -             label="Profile" -             name="view_profile_btn" -             top="0" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="add_friend_btn_panel"> -            <button -             follows="left|top|right" -             height="23" -             label="Add Friend" -             name="add_friend_btn" -             top="5" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="teleport_btn_panel"> -        <button -             auto_resize="false" -             follows="left|top|right" -             height="23" -             label="Teleport" -             name="teleport_btn" -             tool_tip = "Offer to teleport this person" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="share_btn_panel"> -           <button -             auto_resize="true" -             follows="left|top|right" -             height="23" -             label="Share" -             name="share_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="pay_btn_panel"> -           <button -             auto_resize="true" -             follows="left|top|right" -             height="23" -             label="Pay" -             name="pay_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="call_btn_panel"> -            <button -             follows="left|top|right" -             height="23" -             label="Call" -             name="call_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="end_call_btn_panel" -         visible="false"> -            <button -             follows="left|top|right" -             height="23" -             label="End Call" -             name="end_call_btn" -             width="140" /> -        </layout_panel> -        <layout_panel -         auto_resize="false" -         follows="top|left|right" -         height="25" -         layout="topleft" -         min_height="25" -         width="140" -         name="voice_ctrls_btn_panel" -         visible="false"> -            <button -             follows="left|top|right" -             height="23" -             label="Voice Controls" -             name="voice_ctrls_btn" -             width="140" /> -        </layout_panel> -      <layout_panel -       mouse_opaque="false" -       auto_resize="true" -       follows="top|left" -       height="0" -       layout="topleft" -       min_height="0" -       width="140" -       name="spacer"/> -    </layout_stack> -</panel> diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml index d683116eb8..4de56b424e 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml @@ -1,20 +1,22 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel   follows="all" - height="300" + top="0" + bottom_delta="10"   help_topic="nearby_chat"   layout="topleft"   name="nearby_chat" - width="320"> + width="242" + height="169">    <layout_stack     follows="all" -   height="295" +   height="164"     layout="topleft"     left="0"     name="stack"     top="5"     orientation="vertical" -   width="320"> +   width="242">      <layout_panel       auto_resize="false"       height="26" @@ -23,7 +25,7 @@       name="translate_chat_checkbox_lp"       top_delta="0"       visible="true" -     width="313"> +     width="230">        <check_box         top="10"         control_name="TranslateChat" @@ -33,15 +35,15 @@         layout="topleft"         left="5"         name="translate_chat_checkbox" -       width="300" /> +       width="230" />      </layout_panel>      <layout_panel       auto_resize="true" -     height="277" +     height="138"       left_delta="0"       layout="topleft"       name="chat_history_lp" -     width="318"> +     width="242">        <chat_history         bg_readonly_color="ChatHistoryBgColor"         bg_writeable_color="ChatHistoryBgColor" @@ -49,7 +51,7 @@         layout="topleft"         left="5"         left_widget_pad="0" -       height="272" +       height="138"         name="chat_history"         parse_highlights="true"         parse_urls="true" @@ -57,7 +59,7 @@         text_color="ChatHistoryTextColor"         text_readonly_color="ChatHistoryTextColor"         top="0" -       width="313" /> +       width="237" />      </layout_panel>    </layout_stack>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 98c7c49ff4..ceb03d03a9 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -38,12 +38,6 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M       name="no_filtered_friends_msg">           Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search].      </string> -    <string -     name="people_filter_label" -     value="Filter People" /> -    <string -     name="groups_filter_label" -     value="Filter Groups" />       <!--       *WORKAROUND: for group_list.no_items_msg & group_list.no_filtered_items_msg attributes.       They are not defined as translatable in VLT. See EXT-5931 @@ -60,21 +54,9 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M  	<string  	 name="AltMiniMapToolTipMsg"  	 value="[REGION](Double-click to teleport, shift-drag to pan)"/> -	<filter_editor -     follows="left|top|right" -     height="23" -     layout="topleft" -     left="10" -     label="Filter" -     max_length_chars="300" -     name="filter_input" -     text_color="Black" -     text_pad_left="10" -     top="3" -     width="303" />      <tab_container +     bottom="-10"       follows="all" -     height="383"       layout="topleft"       left="3"       name="tabs" @@ -82,31 +64,116 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M       tab_min_width="70"       tab_height="30"       tab_position="top" -     top_pad="10" +     top="0"       halign="center" -     width="319"> -     	<panel +     right="-5"> + +<!-- ================================= NEARBY tab =========================== --> + +        <panel           background_opaque="true"           background_visible="true"           bg_alpha_color="DkGray"           bg_opaque_color="DkGray" +         bottom="-1"           follows="all" -         height="383"           label="NEARBY"           layout="topleft"           left="0"           help_topic="people_nearby_tab"           name="nearby_panel" -         top="0" -         width="313"> +         right="-1" +         top="0"> +            <panel +             follows="left|top|right" +             height="27" +             label="bottom_panel" +             layout="topleft" +             left="0" +             name="nearby_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter People" +                 max_length_chars="300" +                 name="nearby_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="178" /> +                <button +                 commit_callback.function="People.Gear" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="OptionsMenu_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="7" +                 name="gear_btn" +                 top="3" +                 width="31" /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Inv_Underpants" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_people_nearby_view.xml" +                 menu_position="bottomleft" +                 name="nearby_view_btn" +                 top_delta="0" +                 width="31" /> +                <button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="AddItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 name="add_friend_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.AddFriend" /> +                </button> +                <dnd_button +                 enabled="false" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="nearby_del_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.DelFriend" /> +                 </dnd_button> +            </panel>           <layout_stack             clip="false"             follows="all" -           height="355" +           height="410"             layout="topleft" +           left="0"             mouse_opaque="false"             orientation="vertical" -           width="313"> +           right="-1" +           top_pad="0">             <layout_panel               height="142"               layout="topleft" @@ -123,16 +190,16 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                 left="3"                 mouse_opaque="false"                 name="Net Map" -               top="4" -               width="305"/> +               right="-1" +               top="4" />             </layout_panel>             <layout_panel               height="213"               layout="topleft"               min_dim="100"               mouse_opaque="false" -             user_resize="true" -             width="313"> +             right="-1" +             user_resize="true">               <avatar_list                 allow_select="true"                 follows="all" @@ -143,84 +210,118 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                 keep_one_selected="false"                 multi_select="true"                 name="avatar_list" -               top="2" -               width="306" /> +               right="-1" +               top="2" />             </layout_panel>           </layout_stack> -         <panel -             background_visible="true" -             follows="left|right|bottom" -             height="27" -             label="bottom_panel" -             layout="topleft" -             left="3" -             name="bottom_panel" -             top_pad="0" -             width="313"> -             <menu_button -             follows="bottom|left" -             height="25" -             image_hover_unselected="Toolbar_Left_Over" -             image_overlay="OptionsMenu_Off" -             image_selected="Toolbar_Left_Selected" -             image_unselected="Toolbar_Left_Off" -             layout="topleft" -             left="0" -             name="nearby_view_sort_btn" -             tool_tip="Options" -             top="1" -             width="31" /> -             <button -                 follows="bottom|left" -                 height="25" -                 image_hover_unselected="Toolbar_Middle_Over" -             	 image_overlay="AddItem_Off" -                 image_selected="Toolbar_Middle_Selected" -             	 image_unselected="Toolbar_Middle_Off" -                 layout="topleft" -                 left_pad="1" -                 name="add_friend_btn" -                 tool_tip="Add selected Resident to your friends List" -                 width="31"> -               <commit_callback -                  function="People.addFriend" /> -             </button> -             <icon -             follows="bottom|left|right" -             height="25" -             image_name="Toolbar_Right_Off" -             layout="topleft" -             left_pad="1" -             name="dummy_icon" -             width="243" -             /> -            </panel>          </panel> + +<!-- ================================= FRIENDS tab ========================== --> +          <panel           background_opaque="true"         background_visible="true"           bg_alpha_color="DkGray"           bg_opaque_color="DkGray" +         bottom="-1"           follows="all" -         height="383"           label="MY FRIENDS"           layout="topleft"           left="0"           help_topic="people_friends_tab"           name="friends_panel" -         top="0" -         width="313"> +         right="-1" +         top="0"> +            <panel +             follows="left|top|right" +             height="27" +             label="bottom_panel" +             layout="topleft" +             left="0" +             name="friends_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter People" +                 max_length_chars="300" +                 name="friends_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="177" /> +                <button +                 commit_callback.function="People.Gear" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="OptionsMenu_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="8" +                 name="gear_btn" +                 top="3" +                 width="31" /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Inv_Underpants" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_people_friends_view.xml" +                 menu_position="bottomleft" +                 name="friends_view_btn" +                 top_delta="0" +                 width="31" /> +                <button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="AddItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 name="friends_add_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.AddFriendWizard" /> +                </button> +                <dnd_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="friends_del_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.DelFriend" /> +                </dnd_button> +            </panel>              <accordion         		 background_visible="true"         		 bg_alpha_color="DkGray2"         		 bg_opaque_color="DkGray2"               follows="all" -             height="356" +             height="408"               layout="topleft"               left="3"               name="friends_accordion" -             top="0" -             width="307"> +             right="-2" +             top_pad="2">                  <accordion_tab                   layout="topleft"                   height="172" @@ -257,247 +358,129 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M                           width="307" />                  </accordion_tab>              </accordion> -            <panel -             background_visible="true" -             follows="left|right|bottom" -             height="27" -             label="bottom_panel" -             layout="topleft" -             left="3" -             name="bottom_panel" -             top_pad="0" -             width="313"> -              -             	  <layout_stack -				   animate="false" -				   border_size="0" -				   follows="left|right|bottom" -				   height="25" -				   layout="topleft" -				   orientation="horizontal" -				   top_pad="1" -				   left="0" -				   name="bottom_panel" -				   width="308"> -				      <layout_panel -				       auto_resize="false" -				       height="25" -				       layout="topleft" -				       name="options_gear_btn_panel" -				       width="32"> -				          <menu_button -				           follows="bottom|left" -				           tool_tip="Show additional options" -				           height="25" -				           image_hover_unselected="Toolbar_Left_Over" -				           image_overlay="OptionsMenu_Off" -				           image_selected="Toolbar_Left_Selected" -				           image_unselected="Toolbar_Left_Off" -				           layout="topleft" -				           left="0" -				           name="friends_viewsort_btn" -				           top="0" -				           width="31" /> -				      </layout_panel> -				      <layout_panel -				       auto_resize="false" -				       height="25" -				       layout="topleft" -				       name="add_btn_panel" -				       width="32"> -				          <button -				           follows="bottom|left" -				           height="25" -				           image_hover_unselected="Toolbar_Middle_Over" -				           image_overlay="AddItem_Off" -				           image_selected="Toolbar_Middle_Selected" -				           image_unselected="Toolbar_Middle_Off" -				           layout="topleft" -				           left="0" -				           name="add_btn" -				           tool_tip="Offer friendship to a Resident" -				           top="0" -				           width="31" /> -				      </layout_panel> -				      <layout_panel -				       auto_resize="true" -				       height="25" -				       layout="topleft" -				       name="dummy_panel" -				       width="210"> -				          <icon -				           follows="bottom|left|right" -				           height="25" -				           image_name="Toolbar_Middle_Off" -				           layout="topleft" -				           left="0" -				           top="0" -				           name="dummy_icon" -				           width="210" /> -				      </layout_panel> -				      <layout_panel -				       auto_resize="false" -				       height="25" -				       layout="topleft" -				       name="trash_btn_panel" -				       width="31"> -				          <dnd_button -				           follows="bottom|left" -				           height="25" -				           image_hover_unselected="Toolbar_Right_Over" -				           image_overlay="TrashItem_Off" -				           image_selected="Toolbar_Right_Selected" -				           image_unselected="Toolbar_Right_Off" -				           left="0" -				           layout="topleft" -				           name="del_btn" -				           tool_tip="Remove selected person from your Friends list" -				           top="0" -				           width="31"/> -				      </layout_panel> -				  </layout_stack><!-- -              -               <button -               follows="bottom|left" -               tool_tip="Options" -               height="25" -               image_hover_unselected="Toolbar_Left_Over" -               image_overlay="OptionsMenu_Off" -               image_selected="Toolbar_Left_Selected" -               image_unselected="Toolbar_Left_Off" -               layout="topleft" -               left="0" -               name="friends_viewsort_btn" -               top="1" -               width="31" /> -                <button -                 follows="bottom|left" -                 height="25" -                 image_hover_unselected="Toolbar_Middle_Over" -             	 image_overlay="AddItem_Off" -             	 image_selected="Toolbar_Middle_Selected" -             	 image_unselected="Toolbar_Middle_Off" -                 layout="topleft" -                 left_pad="1" -                 name="add_btn" -                 tool_tip="Offer friendship to a Resident" -                 width="31" /> -                <icon -             	 follows="bottom|left|right" -             	 height="25" -             	 image_name="Toolbar_Middle_Off" -             	 layout="topleft" -             	 left_pad="1" -             	 name="dummy_icon" -             	 width="209" -             /> -                <button -                 follows="bottom|left" -                 height="25" -                 image_hover_unselected="Toolbar_Right_Over" -                 image_overlay="TrashItem_Off" -                 image_selected="Toolbar_Right_Selected" -                 image_unselected="Toolbar_Right_Off" -                 layout="topleft" -                 left_pad="1" -                 name="del_btn" -                 tool_tip="Remove selected person from your Friends list" -                 width="31" /> -            --></panel>              <text               follows="all"               height="450"               left="13"               name="no_friends_help_text" -             top="10" -             width="293" +             right="-13" +             top="37"               wrap="true" />          </panel> + +<!-- ================================= GROUPS tab =========================== --> +          <panel           background_opaque="true"         background_visible="true"           bg_alpha_color="DkGray"           bg_opaque_color="DkGray" +         bottom="-1"           follows="all" -         height="383"           label="MY GROUPS"           layout="topleft"           left="0"           help_topic="people_groups_tab"           name="groups_panel" -         top="0" -         width="313"> +         right="-1" +         top="0">      <!--       *NOTE: no_groups_msg & group_list attributes are not defined as translatable in VLT. See EXT-5931       Values are set from appropriate strings at the top of file via LLPeoplePanel::postBuild()      --> -            <group_list -             allow_select="true"  -             follows="all" -             height="356" -             layout="topleft" -             left="3" -             name="group_list" -             top="0" -             width="307" />              <panel -             background_visible="true" -             follows="left|right|bottom" +             follows="left|top|right"               height="27"               label="bottom_panel"               layout="topleft"               left="0" -             name="bottom_panel" -             top_pad="0" -             width="313"> -               <menu_button -               follows="bottom|left" -               tool_tip="Options" -               height="25" -               image_hover_unselected="Toolbar_Left_Over" -               image_overlay="OptionsMenu_Off" -               image_selected="Toolbar_Left_Selected" -               image_unselected="Toolbar_Left_Off" -               layout="topleft" -               left="3" -               name="groups_viewsort_btn" -               top="1" -               width="31" /> -                <button -                 follows="bottom|left" +             name="groups_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter Groups" +                 max_length_chars="300" +                 name="groups_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="177" /> +                <menu_button +                 follows="right"                   height="25"                   image_hover_unselected="Toolbar_Middle_Over" -                 image_overlay="AddItem_Off" +                 image_overlay="OptionsMenu_Off"                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 left_pad="1" -                 name="plus_btn" -                 tool_tip="Join group/Create new group" +                 left_pad="8" +                 name="groups_gear_btn" +                 top="3"                   width="31" /> -                <button -                 follows="bottom|left" +                <menu_button +                 follows="right"                   height="25"                   image_hover_unselected="Toolbar_Middle_Over" -                 image_overlay="Activate_Checkmark" +                 image_overlay="Inv_Underpants"                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 left_pad="1" -                 name="activate_btn" -                 tool_tip="Activate selected group" +                 left_pad="2" +                 menu_filename="menu_people_groups_view.xml" +                 menu_position="bottomleft" +                 name="groups_view_btn" +                 top_delta="0"                   width="31" /> -                 <icon -             	 follows="bottom|left|right" -             	 height="25" -             	 image_name="Toolbar_Right_Off" -             	 layout="topleft" -             	 left_pad="1" -             	 name="dummy_icon" -             	 width="212" -             /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="AddItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_group_plus.xml" +                 menu_position="bottomleft" +                 name="plus_btn" +                 top_delta="0" +                 width="31"> +                    <validate_callback +                     function="People.Group.Plus.Validate" /> +                </menu_button> +                <dnd_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="minus_btn" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.Group.Minus" /> +                </dnd_button>              </panel> +            <group_list +             allow_select="true"  +             follows="all" +             height="406" +             layout="topleft" +             left="3" +             name="group_list" +             right="-2" +             top_pad="4" />          </panel> + +<!-- ================================= RECENT tab =========================== --> +          <panel           background_opaque="true"         background_visible="true" @@ -510,265 +493,128 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M           left="0"           help_topic="people_recent_tab"           name="recent_panel" -         top="0" -         width="313"> -            <avatar_list -             allow_select="true" -             follows="all" -             height="356" -             layout="topleft" -             left="3" -             multi_select="true" -             name="avatar_list" -             show_last_interaction_time="true" -             top="0" -             width="307" /> +         right="-1" +         top="0">              <panel -             background_visible="true" -             follows="left|right|bottom" +             follows="left|top|right"               height="27"               label="bottom_panel"               layout="topleft" -             left="3" -             name="bottom_panel" -             top_pad="0" -             width="313"> -               <menu_button -               follows="bottom|left" -               tool_tip="Options" -               height="25" -               image_hover_unselected="Toolbar_Left_Over" -               image_overlay="OptionsMenu_Off" -               image_selected="Toolbar_Left_Selected" -               image_unselected="Toolbar_Left_Off" -               layout="topleft" -               name="recent_viewsort_btn" -               top="1" -               width="31" /> -              <button -                 follows="bottom|left" +             left="0" +             name="recent_buttons_panel" +             right="-1" +             top="0"> +                <filter_editor +                 follows="left|top|right" +                 height="23" +                 layout="topleft" +                 left="6" +                 label="Filter People" +                 max_length_chars="300" +                 name="recent_filter_input" +                 text_color="Black" +                 text_pad_left="10" +                 top="4" +                 width="177" /> +                <button +                 commit_callback.function="People.Gear" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="OptionsMenu_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="8" +                 name="gear_btn" +                 top="3" +                 width="31" /> +                <menu_button +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Inv_Underpants" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="2" +                 menu_filename="menu_people_recent_view.xml" +                 menu_position="bottomleft" +                 name="recent_view_btn" +                 top_delta="0" +                 width="31" /> +                <button +                 follows="right"                   height="25"                   image_hover_unselected="Toolbar_Middle_Over"                   image_overlay="AddItem_Off"                   image_selected="Toolbar_Middle_Selected"                   image_unselected="Toolbar_Middle_Off"                   layout="topleft" -                 left_pad="1" +                 left_pad="2"                   name="add_friend_btn" -                 tool_tip="Add selected Resident to your friends List" +                 top_delta="0" +                 width="31"> +                    <commit_callback +                     function="People.AddFriend" /> +                </button> +                <dnd_button +                 enabled="false" +                 follows="right" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="TrashItem_Off" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 left_pad="2" +                 layout="topleft" +                 name="recent_del_btn" +                 top_delta="0"                   width="31"> -                <commit_callback -                   function="People.addFriend" /> -              </button> -              <icon -             	 follows="bottom|left|right" -             	 height="25" -             	 image_name="Toolbar_Right_Off" -             	 layout="topleft" -             	 left_pad="1" -             	 name="dummy_icon" -             	 width="244" -             /> +                    <commit_callback +                     function="People.DelFriend" /> +                 </dnd_button>              </panel> +            <avatar_list +             allow_select="true" +             follows="all" +             height="351" +             layout="topleft" +             left="3" +             multi_select="true" +             name="avatar_list" +             show_last_interaction_time="true" +             right="-2" +             top_pad="4" />          </panel> -    </tab_container> -    <panel -     follows="bottom|left|right" -     height="23" -     layout="topleft" -     left="8" -     top_pad="4" -     name="button_bar" -     width="313"> -<!--********************************Profile; IM; Call, Share, Teleport********************************--> 	 -     	<layout_stack -     	follows="bottom|left|right" -		height="23" -		layout="topleft" -		name="bottom_bar_ls" -		left="0" -		orientation="horizontal" -		top_pad="0" -		width="313"> +<!-- ================================= BLOCKED tab ========================== --> -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left="0" -			name="view_profile_btn_lp" -		    auto_resize="true" -			width="68"> -				<button -		         follows="bottom|left|right" -		         height="23" -		         label="Profile" -		         layout="topleft" -		         left="1" -		         name="view_profile_btn" -		         tool_tip="Show picture, groups, and other Residents information" -		         top="0" -		         width="67" />	 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="im_btn_lp" -		    auto_resize="true" -			width="41"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="IM" -		         layout="topleft" -		         name="im_btn" -		         tool_tip="Open instant message session" -		         top="0" -		         width="40" />			 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="call_btn_lp" -		    auto_resize="true" -			width="52"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="Call" -		         layout="topleft" -		         name="call_btn" -		         tool_tip="Call this Resident" -		         top="0" -		         width="51" />		 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="share_btn_lp" -		    auto_resize="true" -			width="66"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="Share" -		         layout="topleft" -		         name="share_btn" -		         tool_tip="Share an inventory item" -		         top="0" -		         width="65" />	 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			name="teleport_btn_lp" -		    auto_resize="true" -			width="77"> -				<button -		         follows="bottom|left|right" -		         left="1" -		         height="23" -		         label="Teleport" -		         layout="topleft" -		         name="teleport_btn" -		         tool_tip="Offer teleport" -		         top="0" -		         width="76" />		 -			</layout_panel> -		</layout_stack> -		 -<!--********************************Group Profile; Group Chat; Group Call buttons************************-->			 -		<layout_stack -     	follows="bottom|left|right" -		height="23" -		layout="topleft" -		mouse_opaque="false" -		name="bottom_bar_ls1" -		left="0" -		orientation="horizontal" -		top="0" -		width="313">	 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left="0"			 -			mouse_opaque="false" -			name="group_info_btn_lp" -		    auto_resize="true" -			width="108"> -				<button -		        follows="bottom|left|right" -		        left="1" -		        height="23" -		        label="Group Profile" -		        layout="topleft" -				mouse_opaque="false" -		        name="group_info_btn" -		        tool_tip="Show group information" -		        top="0" -		        width="107" />		 -			</layout_panel> -			 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			mouse_opaque="false" -			name="chat_btn_lp" -		    auto_resize="true" -			width="101"> -				<button -		        follows="bottom|left|right" -		        left="1" -		        height="23" -		        label="Group Chat" -		        layout="topleft" -				mouse_opaque="false" -		        name="chat_btn" -		        tool_tip="Open chat session" -		        top="0" -		        width="100" />			 -			</layout_panel> -		 -			<layout_panel -			follows="bottom|left|right" -			height="23" -			layout="bottomleft" -			left_pad="3" -			mouse_opaque="false" -			name="group_call_btn_lp" -		    auto_resize="true" -			width="96"> -				<button -				follows="bottom|left|right" -				left="1" -				height="23" -         		label="Group Call" -         		layout="topleft" -				mouse_opaque="false" -         		name="group_call_btn" -         		tool_tip="Call this group" -		        top="0" -         		width="95" />			 -			</layout_panel>		 -		</layout_stack> -    </panel> +        <panel +         background_opaque="true" +         background_visible="true" +         bg_alpha_color="DkGray" +         bg_opaque_color="DkGray" +         follows="all" +         height="383" +         label="BLOCKED" +         layout="topleft" +         left="0" +         help_topic="people_blocked_tab" +         name="blocked_panel" +         right="-1" +         top="0"> +          <panel +           class="panel_block_list_sidetray" +           height="383" +           name="panel_block_list_sidetray" +           filename="panel_block_list_sidetray.xml" +           follows="all" +           label="Blocked Residents & Objects" +           left="0" +           font="SansSerifBold" +           top="0" +           right="-1" /> +        </panel> +    </tab_container>  </panel> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 4ccec4838a..0a2fc13aff 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -403,9 +403,10 @@ Please try logging in again in a minute.</string>  	<string name="AddAndRemoveJoints">Add and remove joints with other objects</string>  	<string name="ChangePermissions">Change its permissions</string>  	<string name="TrackYourCamera">Track your camera</string> -  <string name="ControlYourCamera">Control your camera</string> -  <string name="TeleportYourAgent">Teleport you</string> -  <string name="NotConnected">Not Connected</string> +	<string name="ControlYourCamera">Control your camera</string> +	<string name="NotConnected">Not Connected</string> +	<string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name --> +    <string name="TeleportYourAgent">Teleport you</string>  	<!-- Sim Access labels -->  	<string name="SIM_ACCESS_PG">General</string> @@ -3243,6 +3244,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE].  	<string name="IM_moderator_label">(Moderator)</string>  	<string name="Saved_message">(Saved [LONG_TIMESTAMP])</string>  	<string name="IM_unblock_only_groups_friends">To see this message, you must uncheck 'Only friends and groups can call or IM me' in Preferences/Privacy.</string> +  <string name="OnlineStatus">Online</string> +  <string name="OfflineStatus">Offline</string>  	<!-- voice calls -->  	<string name="answered_call">Your call has been answered</string>  | 
