llnearbychathandler.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:11k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file LLNearbyChatHandler.cpp
  3.  * @brief Nearby chat notification managment
  4.  *
  5.  * $LicenseInfo:firstyear=2009&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2009-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llnearbychathandler.h"
  34. #include "llchatitemscontainerctrl.h"
  35. #include "llnearbychat.h"
  36. #include "llrecentpeople.h"
  37. #include "llviewercontrol.h"
  38. #include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance
  39. #include "llviewerwindow.h"//for screen channel position
  40. //add LLNearbyChatHandler to LLNotificationsUI namespace
  41. using namespace LLNotificationsUI;
  42. //-----------------------------------------------------------------------------------------------
  43. //LLNearbyChatScreenChannel
  44. //-----------------------------------------------------------------------------------------------
  45. LLToastPanelBase* createToastPanel()
  46. {
  47. LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance();
  48. return item;
  49. }
  50. class LLNearbyChatScreenChannel: public LLScreenChannelBase
  51. {
  52. public:
  53. LLNearbyChatScreenChannel(const LLUUID& id):LLScreenChannelBase(id) { mStopProcessing = false;};
  54. void addNotification (LLSD& notification);
  55. void arrangeToasts ();
  56. void showToastsBottom ();
  57. typedef boost::function<LLToastPanelBase* (void )> create_toast_panel_callback_t;
  58. void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;}
  59. void onToastDestroyed (LLToast* toast);
  60. void onToastFade (LLToast* toast);
  61. void reshape (S32 width, S32 height, BOOL called_from_parent);
  62. void redrawToasts()
  63. {
  64. arrangeToasts();
  65. }
  66. // hide all toasts from screen, but not remove them from a channel
  67. virtual void hideToastsFromScreen() 
  68. {
  69. };
  70. // removes all toasts from a channel
  71. virtual void removeToastsFromChannel() 
  72. {
  73. for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
  74. {
  75. LLToast* toast = (*it);
  76. toast->setVisible(FALSE);
  77. toast->stopTimer();
  78. m_toast_pool.push_back(toast);
  79. }
  80. m_active_toasts.clear();
  81. };
  82. virtual void deleteAllChildren()
  83. {
  84. m_toast_pool.clear();
  85. m_active_toasts.clear();
  86. LLScreenChannelBase::deleteAllChildren();
  87. }
  88. protected:
  89. void createOverflowToast(S32 bottom, F32 timer);
  90. create_toast_panel_callback_t m_create_toast_panel_callback_t;
  91. bool createPoolToast();
  92. std::vector<LLToast*> m_active_toasts;
  93. std::list<LLToast*> m_toast_pool;
  94. bool mStopProcessing;
  95. };
  96. void LLNearbyChatScreenChannel::createOverflowToast(S32 bottom, F32 timer)
  97. {
  98. //we don't need overflow toast in nearby chat
  99. }
  100. void LLNearbyChatScreenChannel::onToastDestroyed(LLToast* toast)
  101. {
  102. mStopProcessing = true;
  103. }
  104. void LLNearbyChatScreenChannel::onToastFade(LLToast* toast)
  105. {
  106. //fade mean we put toast to toast pool
  107. if(!toast)
  108. return;
  109. m_toast_pool.push_back(toast);
  110. std::vector<LLToast*>::iterator pos = std::find(m_active_toasts.begin(),m_active_toasts.end(),toast);
  111. if(pos!=m_active_toasts.end())
  112. m_active_toasts.erase(pos);
  113. arrangeToasts();
  114. }
  115. bool LLNearbyChatScreenChannel::createPoolToast()
  116. {
  117. LLToastPanelBase* panel= m_create_toast_panel_callback_t();
  118. if(!panel)
  119. return false;
  120. LLToast::Params p;
  121. p.panel = panel;
  122. p.lifetime_secs = gSavedSettings.getS32("NearbyToastLifeTime");
  123. p.fading_time_secs = gSavedSettings.getS32("NearbyToastFadingTime");
  124. LLToast* toast = new LLToast(p); 
  125. toast->setOnFadeCallback(boost::bind(&LLNearbyChatScreenChannel::onToastFade, this, _1));
  126. toast->setOnToastDestroyedCallback(boost::bind(&LLNearbyChatScreenChannel::onToastDestroyed, this, _1));
  127. m_toast_pool.push_back(toast);
  128. return true;
  129. }
  130. void LLNearbyChatScreenChannel::addNotification(LLSD& notification)
  131. {
  132. //look in pool. if there is any message
  133. if(mStopProcessing)
  134. return;
  135. /*
  136.     find last toast and check ID
  137. */
  138. if(m_active_toasts.size())
  139. {
  140. LLUUID fromID = notification["from_id"].asUUID(); // agent id or object id
  141. LLToast* toast = m_active_toasts[0];
  142. LLNearbyChatToastPanel* panel = dynamic_cast<LLNearbyChatToastPanel*>(toast->getPanel());
  143. if(panel && panel->messageID() == fromID && panel->canAddText())
  144. {
  145. panel->addMessage(notification);
  146. toast->reshapeToPanel();
  147. toast->resetTimer();
  148. arrangeToasts();
  149. return;
  150. }
  151. }
  152. if(m_toast_pool.empty())
  153. {
  154. //"pool" is empty - create one more panel
  155. if(!createPoolToast())//created toast will go to pool. so next call will find it
  156. return;
  157. addNotification(notification);
  158. return;
  159. }
  160. int chat_type = notification["chat_type"].asInteger();
  161. if( ((EChatType)chat_type == CHAT_TYPE_DEBUG_MSG))
  162. {
  163. if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) 
  164. return;
  165. if(gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)
  166. return;
  167. }
  168. //take 1st element from pool, (re)initialize it, put it in active toasts
  169. LLToast* toast = m_toast_pool.back();
  170. m_toast_pool.pop_back();
  171. LLToastPanelBase* panel = dynamic_cast<LLToastPanelBase*>(toast->getPanel());
  172. if(!panel)
  173. return;
  174. panel->init(notification);
  175. toast->reshapeToPanel();
  176. toast->resetTimer();
  177. m_active_toasts.insert(m_active_toasts.begin(),toast);
  178. arrangeToasts();
  179. }
  180. void LLNearbyChatScreenChannel::arrangeToasts()
  181. {
  182. if(m_active_toasts.size() == 0 || isHovering())
  183. return;
  184. hideToastsFromScreen();
  185. showToastsBottom();
  186. }
  187. void LLNearbyChatScreenChannel::showToastsBottom()
  188. {
  189. if(mStopProcessing)
  190. return;
  191. LLRect toast_rect;
  192. S32 bottom = getRect().mBottom;
  193. S32 margin = gSavedSettings.getS32("ToastGap");
  194. for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
  195. {
  196. LLToast* toast = (*it);
  197. S32 toast_top = bottom + toast->getRect().getHeight() + margin;
  198. if(toast_top > gFloaterView->getRect().getHeight())
  199. {
  200. while(it!=m_active_toasts.end())
  201. {
  202. toast->setVisible(FALSE);
  203. toast->stopTimer();
  204. m_toast_pool.push_back(toast);
  205. it=m_active_toasts.erase(it);
  206. }
  207. break;
  208. }
  209. else
  210. {
  211. toast_rect = toast->getRect();
  212. toast_rect.setLeftTopAndSize(getRect().mLeft , toast_top, toast_rect.getWidth() ,toast_rect.getHeight());
  213. toast->setRect(toast_rect);
  214. toast->setIsHidden(false);
  215. toast->setVisible(TRUE);
  216. if(!toast->hasFocus())
  217. {
  218. // Fixing Z-order of toasts (EXT-4862)
  219. // Next toast will be positioned under this one.
  220. gFloaterView->sendChildToBack(toast);
  221. }
  222. bottom = toast->getRect().mTop - toast->getTopPad();
  223. }
  224. }
  225. }
  226. void LLNearbyChatScreenChannel::reshape (S32 width, S32 height, BOOL called_from_parent)
  227. {
  228. LLScreenChannelBase::reshape(width, height, called_from_parent);
  229. arrangeToasts();
  230. }
  231. //-----------------------------------------------------------------------------------------------
  232. //LLNearbyChatHandler
  233. //-----------------------------------------------------------------------------------------------
  234. LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id)
  235. {
  236. mType = type;
  237. // Getting a Channel for our notifications
  238. LLNearbyChatScreenChannel* channel = new LLNearbyChatScreenChannel(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
  239. LLNearbyChatScreenChannel::create_toast_panel_callback_t callback = createToastPanel;
  240. channel->setCreatePanelCallback(callback);
  241. mChannel = LLChannelManager::getInstance()->addChannel(channel);
  242. }
  243. LLNearbyChatHandler::~LLNearbyChatHandler()
  244. {
  245. }
  246. void LLNearbyChatHandler::initChannel()
  247. {
  248. LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
  249. S32 channel_right_bound = nearby_chat->getRect().mRight;
  250. S32 channel_width = nearby_chat->getRect().mRight; 
  251. mChannel->init(channel_right_bound - channel_width, channel_right_bound);
  252. }
  253. void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
  254. {
  255. if(chat_msg.mMuted == TRUE)
  256. return;
  257. if(chat_msg.mSourceType == CHAT_SOURCE_AGENT && chat_msg.mFromID.notNull())
  258.          LLRecentPeople::instance().add(chat_msg.mFromID);
  259. if(chat_msg.mText.empty())
  260. return;//don't process empty messages
  261. LLChat& tmp_chat = const_cast<LLChat&>(chat_msg);
  262. LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
  263. {
  264. //sometimes its usefull to have no name at all...
  265. //if(tmp_chat.mFromName.empty() && tmp_chat.mFromID!= LLUUID::null)
  266. // tmp_chat.mFromName = tmp_chat.mFromID.asString();
  267. }
  268. nearby_chat->addMessage(chat_msg, true, args);
  269. if( nearby_chat->getVisible()
  270. || ( chat_msg.mSourceType == CHAT_SOURCE_AGENT
  271. && gSavedSettings.getBOOL("UseChatBubbles") ) )
  272. return;//no need in toast if chat is visible or if bubble chat is enabled
  273. // Handle irc styled messages for toast panel
  274. if (tmp_chat.mChatStyle == CHAT_STYLE_IRC)
  275. {
  276. if(!tmp_chat.mFromName.empty())
  277. tmp_chat.mText = tmp_chat.mFromName + tmp_chat.mText.substr(3);
  278. else
  279. tmp_chat.mText = tmp_chat.mText.substr(3);
  280. }
  281. // arrange a channel on a screen
  282. if(!mChannel->getVisible())
  283. {
  284. initChannel();
  285. }
  286. /*
  287. //comment all this due to EXT-4432
  288. ..may clean up after some time...
  289. //only messages from AGENTS
  290. if(CHAT_SOURCE_OBJECT == chat_msg.mSourceType)
  291. {
  292. if(chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG)
  293. return;//ok for now we don't skip messeges from object, so skip only debug messages
  294. }
  295. */
  296. LLUUID id;
  297. id.generate();
  298. LLNearbyChatScreenChannel* channel = dynamic_cast<LLNearbyChatScreenChannel*>(mChannel);
  299. if(channel)
  300. {
  301. LLSD notification;
  302. notification["id"] = id;
  303. notification["message"] = chat_msg.mText;
  304. notification["from"] = chat_msg.mFromName;
  305. notification["from_id"] = chat_msg.mFromID;
  306. notification["time"] = chat_msg.mTime;
  307. notification["source"] = (S32)chat_msg.mSourceType;
  308. notification["chat_type"] = (S32)chat_msg.mChatType;
  309. notification["chat_style"] = (S32)chat_msg.mChatStyle;
  310. std::string r_color_name = "White";
  311. F32 r_color_alpha = 1.0f; 
  312. LLViewerChat::getChatColor( chat_msg, r_color_name, r_color_alpha);
  313. notification["text_color"] = r_color_name;
  314. notification["color_alpha"] = r_color_alpha;
  315. notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ;
  316. channel->addNotification(notification);
  317. }
  318. }
  319. void LLNearbyChatHandler::onDeleteToast(LLToast* toast)
  320. {
  321. }