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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llconsole.cpp
  3.  * @brief a scrolling console output device
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-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 "linden_common.h"
  34. #include "llconsole.h"
  35. // linden library includes
  36. #include "llmath.h"
  37. //#include "llviewercontrol.h"
  38. #include "llcriticaldamp.h"
  39. #include "llfontgl.h"
  40. #include "llgl.h"
  41. #include "llui.h"
  42. #include "lluiimage.h"
  43. //#include "llviewerimage.h"
  44. //#include "llviewerimagelist.h"
  45. //#include "llviewerwindow.h"
  46. #include "llsd.h"
  47. #include "llfontgl.h"
  48. #include "llmath.h"
  49. //#include "llstartup.h"
  50. // Used for LCD display
  51. extern void AddNewDebugConsoleToLCD(const LLWString &newLine);
  52. LLConsole* gConsole = NULL;  // Created and destroyed in LLViewerWindow.
  53. const F32 FADE_DURATION = 2.f;
  54. const S32 MIN_CONSOLE_WIDTH = 200;
  55.  
  56. static LLDefaultChildRegistry::Register<LLConsole> r("console");
  57. LLConsole::LLConsole(const LLConsole::Params& p) 
  58. : LLUICtrl(p),
  59. LLFixedBuffer(p.max_lines),
  60. mLinePersistTime(p.persist_time), // seconds
  61. mFont(p.font),
  62. mConsoleWidth(0),
  63. mConsoleHeight(0)
  64. {
  65. if (p.font_size_index.isProvided())
  66. {
  67. setFontSize(p.font_size_index);
  68. }
  69. mFadeTime = mLinePersistTime - FADE_DURATION;
  70. setMaxLines(LLUI::sSettingGroups["config"]->getS32("ConsoleMaxLines"));
  71. }
  72. void LLConsole::setLinePersistTime(F32 seconds)
  73. {
  74. mLinePersistTime = seconds;
  75. mFadeTime = mLinePersistTime - FADE_DURATION;
  76. }
  77. void LLConsole::reshape(S32 width, S32 height, BOOL called_from_parent)
  78. {
  79. S32 new_width = llmax(50, llmin(getRect().getWidth(), width));
  80. S32 new_height = llmax(llfloor(mFont->getLineHeight()) + 15, llmin(getRect().getHeight(), height));
  81. if (   mConsoleWidth == new_width
  82. && mConsoleHeight == new_height )
  83. {
  84. return;
  85. }
  86. mConsoleWidth = new_width;
  87. mConsoleHeight= new_height;
  88. LLUICtrl::reshape(new_width, new_height, called_from_parent);
  89. for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++)
  90. {
  91. (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true);
  92. }
  93. }
  94. void LLConsole::setFontSize(S32 size_index)
  95. {
  96. if (-1 == size_index)
  97. {
  98. mFont = LLFontGL::getFontMonospace();
  99. }
  100. else if (0 == size_index)
  101. {
  102. mFont = LLFontGL::getFontSansSerif();
  103. }
  104. else if (1 == size_index)
  105. {
  106. mFont = LLFontGL::getFontSansSerifBig();
  107. }
  108. else
  109. {
  110. mFont = LLFontGL::getFontSansSerifHuge();
  111. }
  112. // Make sure the font exists
  113. if (mFont == NULL)
  114. {
  115. mFont = LLFontGL::getFontDefault();
  116. }
  117. for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++)
  118. {
  119. (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true);
  120. }
  121. }
  122. void LLConsole::draw()
  123. {
  124. LLGLSUIDefault gls_ui;
  125. // skip lines added more than mLinePersistTime ago
  126. F32 cur_time = mTimer.getElapsedTimeF32();
  127. F32 skip_time = cur_time - mLinePersistTime;
  128. F32 fade_time = cur_time - mFadeTime;
  129. if (mParagraphs.empty())  //No text to draw.
  130. {
  131. return;
  132. }
  133. U32 num_lines=0;
  134. paragraph_t::reverse_iterator paragraph_it;
  135. paragraph_it = mParagraphs.rbegin();
  136. U32 paragraph_num=mParagraphs.size();
  137. while (!mParagraphs.empty() && paragraph_it != mParagraphs.rend())
  138. {
  139. num_lines += (*paragraph_it).mLines.size();
  140. if(num_lines > mMaxLines 
  141. || ( (mLinePersistTime > (F32)0.f) && ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime) <= (F32)0.f)) 
  142. { //All lines above here are done.  Lose them.
  143. for (U32 i=0;i<paragraph_num;i++)
  144. {
  145. if (!mParagraphs.empty())
  146. mParagraphs.pop_front();
  147. }
  148. break;
  149. }
  150. paragraph_num--;
  151. paragraph_it++;
  152. }
  153. if (mParagraphs.empty())
  154. {
  155. return;
  156. }
  157. // draw remaining lines
  158. F32 y_pos = 0.f;
  159. LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
  160. // F32 console_opacity = llclamp(gSavedSettings.getF32("ConsoleBackgroundOpacity"), 0.f, 1.f);
  161. F32 console_opacity = llclamp(LLUI::sSettingGroups["config"]->getF32("ConsoleBackgroundOpacity"), 0.f, 1.f);
  162. // LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground");
  163. LLColor4 color = LLUIColorTable::instance().getColor("ConsoleBackground");
  164. color.mV[VALPHA] *= console_opacity;
  165. F32 line_height = mFont->getLineHeight();
  166. for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++)
  167. {
  168. S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + 8);
  169. S32 target_width =  llfloor( (*paragraph_it).mMaxWidth +15);
  170. y_pos += ((*paragraph_it).mLines.size()) * line_height;
  171. imagep->drawSolid(-14, (S32)(y_pos + line_height - target_height), target_width, target_height, color);
  172. F32 y_off=0;
  173. F32 alpha;
  174. if ((mLinePersistTime > 0.f) && ((*paragraph_it).mAddTime < fade_time))
  175. {
  176. alpha = ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime);
  177. }
  178. else
  179. {
  180. alpha = 1.0f;
  181. }
  182. if( alpha > 0.f )
  183. {
  184. for (lines_t::iterator line_it=(*paragraph_it).mLines.begin(); 
  185. line_it != (*paragraph_it).mLines.end();
  186. line_it ++)
  187. {
  188. for (line_color_segments_t::iterator seg_it = (*line_it).mLineColorSegments.begin();
  189. seg_it != (*line_it).mLineColorSegments.end();
  190. seg_it++)
  191. {
  192. mFont->render((*seg_it).mText, 0, (*seg_it).mXPosition - 8, y_pos -  y_off,
  193. LLColor4(
  194. (*seg_it).mColor.mV[VRED], 
  195. (*seg_it).mColor.mV[VGREEN], 
  196. (*seg_it).mColor.mV[VBLUE], 
  197. (*seg_it).mColor.mV[VALPHA]*alpha),
  198. LLFontGL::LEFT, 
  199. LLFontGL::BASELINE,
  200. LLFontGL::NORMAL,
  201. LLFontGL::DROP_SHADOW,
  202. S32_MAX,
  203. target_width
  204. );
  205. }
  206. y_off += line_height;
  207. }
  208. }
  209. y_pos  += 8;
  210. }
  211. }
  212. //Generate highlight color segments for this paragraph.  Pass in default color of paragraph.
  213. void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color) 
  214. {
  215. LLSD paragraph_color_segments;
  216. LLColor4 lcolor=color;
  217. paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText);
  218. LLSD color_sd = color.getValue();
  219. paragraph_color_segments[0]["color"]=color_sd;
  220. for(LLSD::array_const_iterator color_segment_it = paragraph_color_segments.beginArray();
  221. color_segment_it != paragraph_color_segments.endArray();
  222. ++color_segment_it)
  223. {
  224. LLSD color_llsd = (*color_segment_it)["color"];
  225. std::string color_str  = (*color_segment_it)["text"].asString();
  226. ParagraphColorSegment color_segment;
  227. color_segment.mColor.setValue(color_llsd);
  228. color_segment.mNumChars = color_str.length();
  229. mParagraphColorSegments.push_back(color_segment);
  230. }
  231. }
  232. //Called when a paragraph is added to the console or window is resized.
  233. void LLConsole::Paragraph::updateLines(F32 screen_width, const LLFontGL* font, bool force_resize)
  234. {
  235. if ( !force_resize )
  236. {
  237. if ( mMaxWidth >= 0.0f 
  238.  &&  mMaxWidth < screen_width )
  239. {
  240. return; //No resize required.
  241. }
  242. }
  243. screen_width = screen_width - 30; //Margin for small windows.
  244. if ( mParagraphText.empty() 
  245. || mParagraphColorSegments.empty()
  246. || font == NULL)
  247. {
  248. return; //Not enough info to complete.
  249. }
  250. mLines.clear(); //Chuck everything.
  251. mMaxWidth = 0.0f;
  252. paragraph_color_segments_t::iterator current_color = mParagraphColorSegments.begin();
  253. U32 current_color_length = (*current_color).mNumChars;
  254. S32 paragraph_offset = 0; //Offset into the paragraph text.
  255. // Wrap lines that are longer than the view is wide.
  256. while( paragraph_offset < (S32)mParagraphText.length() &&
  257.    mParagraphText[paragraph_offset] != 0)
  258. {
  259. S32 skip_chars; // skip 'n'
  260. // Figure out if a word-wrapped line fits here.
  261. LLWString::size_type line_end = mParagraphText.find_first_of(llwchar('n'), paragraph_offset);
  262. if (line_end != LLWString::npos)
  263. {
  264. skip_chars = 1; // skip 'n'
  265. }
  266. else
  267. {
  268. line_end = mParagraphText.size();
  269. skip_chars = 0;
  270. }
  271. U32 drawable = font->maxDrawableChars(mParagraphText.c_str()+paragraph_offset, screen_width, line_end - paragraph_offset, LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
  272. if (drawable != 0)
  273. {
  274. F32 x_position = 0; //Screen X position of text.
  275. mMaxWidth = llmax( mMaxWidth, (F32)font->getWidth( mParagraphText.substr( paragraph_offset, drawable ).c_str() ) );
  276. Line line;
  277. U32 left_to_draw = drawable;
  278. U32 drawn = 0;
  279. while (left_to_draw >= current_color_length 
  280. && current_color != mParagraphColorSegments.end() )
  281. {
  282. LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, current_color_length );
  283. line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line.
  284. (*current_color).mColor, 
  285. x_position ) );
  286. x_position += font->getWidth( color_text.c_str() ); //Set up next screen position.
  287. drawn += current_color_length;
  288. left_to_draw -= current_color_length;
  289. current_color++; //Goto next paragraph color record.
  290. if (current_color != mParagraphColorSegments.end())
  291. {
  292. current_color_length = (*current_color).mNumChars;
  293. }
  294. }
  295. if (left_to_draw > 0 && current_color != mParagraphColorSegments.end() )
  296. {
  297. LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, left_to_draw );
  298. line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line.
  299. (*current_color).mColor, 
  300. x_position ) );
  301. current_color_length -= left_to_draw;
  302. }
  303. mLines.push_back(line); //Append line to paragraph line list.
  304. }
  305. paragraph_offset += (drawable + skip_chars);
  306. }
  307. }
  308. //Pass in the string and the default color for this block of text.
  309. LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width) 
  310. : mParagraphText(str), mAddTime(add_time), mMaxWidth(-1)
  311. {
  312. makeParagraphColorSegments(color);
  313. updateLines( screen_width, font );
  314. }
  315. // called once per frame regardless of console visibility
  316. // static
  317. void LLConsole::updateClass()
  318. {
  319. LLInstanceTrackerScopedGuard guard;
  320. for (instance_iter it = guard.beginInstances(); it != guard.endInstances(); ++it)
  321. {
  322. it->update();
  323. }
  324. void LLConsole::update()
  325. {
  326. {
  327. LLMutexLock lock(&mMutex);
  328. while (!mLines.empty())
  329. {
  330. mParagraphs.push_back(
  331. Paragraph( mLines.front(), 
  332. LLColor4::white, 
  333. mTimer.getElapsedTimeF32(), 
  334. mFont, 
  335. (F32)getRect().getWidth()));
  336. mLines.pop_front();
  337. }
  338. }
  339. // remove old paragraphs which can't possibly be visible any more.  ::draw() will do something similar but more conservative - we do this here because ::draw() isn't guaranteed to ever be called!  (i.e. the console isn't visible)
  340. while ((S32)mParagraphs.size() > llmax((S32)0, (S32)(mMaxLines)))
  341. {
  342. mParagraphs.pop_front();
  343. }
  344. }