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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llfloaterchat.cpp
  3.  * @brief LLFloaterChat class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-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. /**
  33.  * Actually the "Chat History" floater.
  34.  * Should be llfloaterchathistory, not llfloaterchat.
  35.  */
  36. #include "llviewerprecompiledheaders.h"
  37. // project include
  38. #include "llagent.h"
  39. #include "llappviewer.h"
  40. #include "llbutton.h"
  41. #include "llcheckboxctrl.h"
  42. #include "llcombobox.h"
  43. #include "llconsole.h"
  44. #include "llfloateractivespeakers.h"
  45. #include "llfloaterchatterbox.h"
  46. #include "llfloaterreg.h"
  47. #include "llfloaterscriptdebug.h"
  48. #include "llkeyboard.h"
  49. //#include "lllineeditor.h"
  50. #include "llmutelist.h"
  51. //#include "llresizehandle.h"
  52. #include "llchatbar.h"
  53. #include "llrecentpeople.h"
  54. #include "llpanelblockedlist.h"
  55. #include "llslurl.h"
  56. #include "llstatusbar.h"
  57. #include "llviewertexteditor.h"
  58. #include "llviewergesture.h" // for triggering gestures
  59. #include "llviewermessage.h"
  60. #include "llviewerwindow.h"
  61. #include "llviewercontrol.h"
  62. #include "lluictrlfactory.h"
  63. #include "lllogchat.h"
  64. #include "lltexteditor.h"
  65. #include "lltextparser.h"
  66. #include "llweb.h"
  67. #include "llstylemap.h"
  68. // linden library includes
  69. #include "llaudioengine.h"
  70. #include "llchat.h"
  71. #include "llfontgl.h"
  72. #include "llrect.h"
  73. #include "llerror.h"
  74. #include "llstring.h"
  75. #include "llwindow.h"
  76. #include "message.h"
  77. //
  78. // Constants
  79. //
  80. const F32 INSTANT_MSG_SIZE = 8.0f;
  81. const F32 CHAT_MSG_SIZE = 8.0f;
  82. //
  83. // Global statics
  84. //
  85. LLColor4 get_text_color(const LLChat& chat);
  86. //
  87. // Member Functions
  88. //
  89. LLFloaterChat::LLFloaterChat(const LLSD& seed)
  90. : LLFloater(seed),
  91.   mPanel(NULL)
  92. {
  93. mFactoryMap["chat_panel"] = LLCallbackMap(createChatPanel, NULL);
  94. mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, NULL);
  95. //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_chat_history.xml");
  96. }
  97. LLFloaterChat::~LLFloaterChat()
  98. {
  99. // Children all cleaned up by default view destructor.
  100. }
  101. void LLFloaterChat::draw()
  102. {
  103. // enable say and shout only when text available
  104. childSetValue("toggle_active_speakers_btn", childIsVisible("active_speakers_panel"));
  105. LLChatBar* chat_barp = findChild<LLChatBar>("chat_panel", TRUE);
  106. if (chat_barp)
  107. {
  108. chat_barp->refresh();
  109. }
  110. mPanel->refreshSpeakers();
  111. LLFloater::draw();
  112. }
  113. BOOL LLFloaterChat::postBuild()
  114. {
  115. // Hide the chat overlay when our history is visible.
  116. setVisibleCallback(boost::bind(&LLFloaterChat::updateConsoleVisibility, this));
  117. mPanel = (LLPanelActiveSpeakers*)getChild<LLPanel>("active_speakers_panel");
  118. childSetCommitCallback("show mutes",onClickToggleShowMute,this); //show mutes
  119. childSetVisible("Chat History Editor with mute",FALSE);
  120. childSetAction("toggle_active_speakers_btn", onClickToggleActiveSpeakers, this);
  121. return TRUE;
  122. }
  123. void LLFloaterChat::updateConsoleVisibility()
  124. {
  125. if(gDisconnected)
  126. {
  127. return;
  128. }
  129. // determine whether we should show console due to not being visible
  130. gConsole->setVisible( !isInVisibleChain() // are we not in part of UI being drawn?
  131. || isMinimized() // are we minimized?
  132. || (getHost() && getHost()->isMinimized() )); // are we hosted in a minimized floater?
  133. }
  134. void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& color)
  135. {
  136. std::string line = chat.mText;
  137. bool prepend_newline = true;
  138. if (gSavedSettings.getBOOL("ChatShowTimestamps"))
  139. {
  140. edit->appendTime(prepend_newline);
  141. prepend_newline = false;
  142. }
  143. // If the msg is from an agent (not yourself though),
  144. // extract out the sender name and replace it with the hotlinked name.
  145. if (chat.mSourceType == CHAT_SOURCE_AGENT &&
  146. chat.mFromID != LLUUID::null)
  147. {
  148. chat.mURL = LLSLURL::buildCommand("agent", chat.mFromID, "inspect");
  149. }
  150. // If the chat line has an associated url, link it up to the name.
  151. if (!chat.mURL.empty()
  152. && (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0))
  153. {
  154. std::string start_line = line.substr(0, chat.mFromName.length() + 1);
  155. line = line.substr(chat.mFromName.length() + 1);
  156. edit->appendText(start_line, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,chat.mURL));
  157. edit->blockUndo();
  158. prepend_newline = false;
  159. }
  160. edit->appendText(line, prepend_newline, LLStyle::Params().color(color));
  161. edit->blockUndo();
  162. }
  163. // static
  164. void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
  165. {
  166. if (log_to_file && (gSavedPerAccountSettings.getBOOL("LogChat"))) 
  167. {
  168. if (chat.mChatType != CHAT_TYPE_WHISPER && chat.mChatType != CHAT_TYPE_SHOUT)
  169. {
  170. LLLogChat::saveHistory("chat", chat.mFromName, chat.mFromID, chat.mText);
  171. }
  172. else
  173. {
  174. LLLogChat::saveHistory("chat", "", chat.mFromID, chat.mFromName + " " + chat.mText);
  175. }
  176. }
  177. LLColor4 color = get_text_color(chat);
  178. if (!log_to_file) color = LLColor4::grey; //Recap from log file.
  179. if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
  180. {
  181. if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE)
  182. return;
  183. if (gSavedSettings.getS32("ShowScriptErrorsLocation") == 1)
  184. {
  185. LLFloaterScriptDebug::addScriptLine(chat.mText,
  186. chat.mFromName, 
  187. color, 
  188. chat.mFromID);
  189. return;
  190. }
  191. }
  192. // could flash the chat button in the status bar here. JC
  193. LLFloaterChat* chat_floater = LLFloaterChat::getInstance();
  194. LLViewerTextEditor* history_editor = chat_floater->getChild<LLViewerTextEditor>("Chat History Editor");
  195. LLViewerTextEditor* history_editor_with_mute = chat_floater->getChild<LLViewerTextEditor>("Chat History Editor with mute");
  196. if (!chat.mMuted)
  197. {
  198. add_timestamped_line(history_editor, chat, color);
  199. add_timestamped_line(history_editor_with_mute, chat, color);
  200. }
  201. else
  202. {
  203. // desaturate muted chat
  204. LLColor4 muted_color = lerp(color, LLColor4::grey, 0.5f);
  205. add_timestamped_line(history_editor_with_mute, chat, color);
  206. }
  207. // add objects as transient speakers that can be muted
  208. if (chat.mSourceType == CHAT_SOURCE_OBJECT)
  209. {
  210. chat_floater->mPanel->setSpeaker(chat.mFromID, chat.mFromName, LLSpeaker::STATUS_NOT_IN_CHANNEL, LLSpeaker::SPEAKER_OBJECT);
  211. }
  212. // start tab flashing on incoming text from other users (ignoring system text, etc)
  213. if (!chat_floater->isInVisibleChain() && chat.mSourceType == CHAT_SOURCE_AGENT)
  214. {
  215. LLFloaterChatterBox::getInstance()->setFloaterFlashing(chat_floater, TRUE);
  216. }
  217. }
  218. // static
  219. void LLFloaterChat::setHistoryCursorAndScrollToEnd()
  220. {
  221. LLViewerTextEditor* history_editor = LLFloaterChat::getInstance()->getChild<LLViewerTextEditor>("Chat History Editor");
  222. LLViewerTextEditor* history_editor_with_mute = LLFloaterChat::getInstance()->getChild<LLViewerTextEditor>("Chat History Editor with mute");
  223. if (history_editor) 
  224. {
  225. history_editor->setCursorAndScrollToEnd();
  226. }
  227. if (history_editor_with_mute)
  228. {
  229.  history_editor_with_mute->setCursorAndScrollToEnd();
  230. }
  231. }
  232. //static 
  233. void LLFloaterChat::onClickMute(void *data)
  234. {
  235. LLFloaterChat* self = (LLFloaterChat*)data;
  236. LLComboBox* chatter_combo = self->getChild<LLComboBox>("chatter combobox");
  237. const std::string& name = chatter_combo->getSimple();
  238. LLUUID id = chatter_combo->getCurrentID();
  239. if (name.empty()) return;
  240. LLMute mute(id);
  241. mute.setFromDisplayName(name);
  242. LLMuteList::getInstance()->add(mute);
  243. LLPanelBlockedList::showPanelAndSelect(mute.mID);
  244. }
  245. //static
  246. void LLFloaterChat::onClickToggleShowMute(LLUICtrl* caller, void *data)
  247. {
  248. LLFloaterChat* floater = (LLFloaterChat*)data;
  249. //LLCheckBoxCtrl*
  250. BOOL show_mute = floater->getChild<LLCheckBoxCtrl>("show mutes")->get();
  251. LLViewerTextEditor* history_editor = floater->getChild<LLViewerTextEditor>("Chat History Editor");
  252. LLViewerTextEditor* history_editor_with_mute = floater->getChild<LLViewerTextEditor>("Chat History Editor with mute");
  253. if (!history_editor || !history_editor_with_mute)
  254. return;
  255. //BOOL show_mute = floater->mShowMuteCheckBox->get();
  256. if (show_mute)
  257. {
  258. history_editor->setVisible(FALSE);
  259. history_editor_with_mute->setVisible(TRUE);
  260. history_editor_with_mute->setCursorAndScrollToEnd();
  261. }
  262. else
  263. {
  264. history_editor->setVisible(TRUE);
  265. history_editor_with_mute->setVisible(FALSE);
  266. history_editor->setCursorAndScrollToEnd();
  267. }
  268. }
  269. // Put a line of chat in all the right places
  270. void LLFloaterChat::addChat(const LLChat& chat, BOOL local_agent)
  271. {
  272. triggerAlerts(chat.mText);
  273. // Add the sender to the list of people with which we've recently interacted.
  274. // this is not the best place to add _all_ messages to recent list
  275. // comment this for now, may remove later on code cleanup
  276. //if(chat.mSourceType == CHAT_SOURCE_AGENT && chat.mFromID.notNull())
  277. // LLRecentPeople::instance().add(chat.mFromID);
  278. addChatHistory(chat, true);
  279. }
  280. // Moved from lltextparser.cpp to break llui/llaudio library dependency.
  281. //static
  282. void LLFloaterChat::triggerAlerts(const std::string& text)
  283. {
  284. LLTextParser* parser = LLTextParser::getInstance();
  285. //    bool spoken=FALSE;
  286. for (S32 i=0;i<parser->mHighlights.size();i++)
  287. {
  288. LLSD& highlight = parser->mHighlights[i];
  289. if (parser->findPattern(text,highlight) >= 0 )
  290. {
  291. if(gAudiop)
  292. {
  293. if ((std::string)highlight["sound_lluuid"] != LLUUID::null.asString())
  294. {
  295. gAudiop->triggerSound(highlight["sound_lluuid"].asUUID(), 
  296. gAgent.getID(),
  297. 1.f,
  298. LLAudioEngine::AUDIO_TYPE_UI,
  299. gAgent.getPositionGlobal() );
  300. }
  301. /*
  302. if (!spoken) 
  303. {
  304. LLTextToSpeech* text_to_speech = NULL;
  305. text_to_speech = LLTextToSpeech::getInstance();
  306. spoken = text_to_speech->speak((LLString)highlight["voice"],text); 
  307. }
  308.  */
  309. }
  310. if (highlight["flash"])
  311. {
  312. LLWindow* viewer_window = gViewerWindow->getWindow();
  313. if (viewer_window && viewer_window->getMinimized())
  314. {
  315. viewer_window->flashIcon(5.f);
  316. }
  317. }
  318. }
  319. }
  320. }
  321. LLColor4 get_text_color(const LLChat& chat)
  322. {
  323. LLColor4 text_color;
  324. if(chat.mMuted)
  325. {
  326. text_color.setVec(0.8f, 0.8f, 0.8f, 1.f);
  327. }
  328. else
  329. {
  330. switch(chat.mSourceType)
  331. {
  332. case CHAT_SOURCE_SYSTEM:
  333. text_color = LLUIColorTable::instance().getColor("SystemChatColor");
  334. break;
  335. case CHAT_SOURCE_AGENT:
  336.     if (chat.mFromID.isNull())
  337. {
  338. text_color = LLUIColorTable::instance().getColor("SystemChatColor");
  339. }
  340. else
  341. {
  342. if(gAgent.getID() == chat.mFromID)
  343. {
  344. text_color = LLUIColorTable::instance().getColor("UserChatColor");
  345. }
  346. else
  347. {
  348. text_color = LLUIColorTable::instance().getColor("AgentChatColor");
  349. }
  350. }
  351. break;
  352. case CHAT_SOURCE_OBJECT:
  353. if (chat.mChatType == CHAT_TYPE_DEBUG_MSG)
  354. {
  355. text_color = LLUIColorTable::instance().getColor("ScriptErrorColor");
  356. }
  357. else if ( chat.mChatType == CHAT_TYPE_OWNER )
  358. {
  359. text_color = LLUIColorTable::instance().getColor("llOwnerSayChatColor");
  360. }
  361. else
  362. {
  363. text_color = LLUIColorTable::instance().getColor("ObjectChatColor");
  364. }
  365. break;
  366. default:
  367. text_color.setToWhite();
  368. }
  369. if (!chat.mPosAgent.isExactlyZero())
  370. {
  371. LLVector3 pos_agent = gAgent.getPositionAgent();
  372. F32 distance = dist_vec(pos_agent, chat.mPosAgent);
  373. if (distance > gAgent.getNearChatRadius())
  374. {
  375. // diminish far-off chat
  376. text_color.mV[VALPHA] = 0.8f;
  377. }
  378. }
  379. }
  380. return text_color;
  381. }
  382. //static
  383. void LLFloaterChat::loadHistory()
  384. {
  385. LLLogChat::loadHistory(std::string("chat"), &chatFromLogFile, (void *)LLFloaterChat::getInstance()); 
  386. }
  387. //static
  388. void LLFloaterChat::chatFromLogFile(LLLogChat::ELogLineType type , const LLSD& line, void* userdata)
  389. {
  390. switch (type)
  391. {
  392. case LLLogChat::LOG_EMPTY:
  393. case LLLogChat::LOG_END:
  394. // *TODO: nice message from XML file here
  395. break;
  396. case LLLogChat::LOG_LINE:
  397. case LLLogChat::LOG_LLSD:
  398. {
  399. LLChat chat;
  400. chat.mText = line["message"].asString();
  401. get_text_color(chat);
  402. addChatHistory(chat,  FALSE);
  403. }
  404. break;
  405. default:
  406. // nothing
  407. break;
  408. }
  409. }
  410. //static
  411. void* LLFloaterChat::createSpeakersPanel(void* data)
  412. {
  413. return new LLPanelActiveSpeakers(LLLocalSpeakerMgr::getInstance(), TRUE);
  414. }
  415. //static
  416. void* LLFloaterChat::createChatPanel(void* data)
  417. {
  418. LLChatBar* chatp = new LLChatBar();
  419. return chatp;
  420. }
  421. // static
  422. void LLFloaterChat::onClickToggleActiveSpeakers(void* userdata)
  423. {
  424. LLFloaterChat* self = (LLFloaterChat*)userdata;
  425. self->childSetVisible("active_speakers_panel", !self->childIsVisible("active_speakers_panel"));
  426. }
  427. //static
  428.  LLFloaterChat* LLFloaterChat::getInstance()
  429.  {
  430.  return LLFloaterReg::getTypedInstance<LLFloaterChat>("chat", LLSD()) ;
  431.  
  432.  }