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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llui.cpp
  3.  * @brief UI implementation
  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. // Utilities functions the user interface needs
  33. #include "linden_common.h"
  34. #include <string>
  35. #include <map>
  36. // Linden library includes
  37. #include "v2math.h"
  38. #include "v4color.h"
  39. #include "llrender.h"
  40. #include "llrect.h"
  41. #include "lldir.h"
  42. #include "llgl.h"
  43. // Project includes
  44. #include "llcontrol.h"
  45. #include "llui.h"
  46. #include "lluicolortable.h"
  47. #include "llview.h"
  48. #include "lllineeditor.h"
  49. #include "llfloater.h"
  50. #include "llfloaterreg.h"
  51. #include "llmenugl.h"
  52. #include "llmenubutton.h"
  53. #include "llwindow.h"
  54. // for registration
  55. #include "llfiltereditor.h"
  56. #include "llflyoutbutton.h"
  57. #include "llsearcheditor.h"
  58. // for XUIParse
  59. #include "llquaternion.h"
  60. #include <boost/tokenizer.hpp>
  61. //
  62. // Globals
  63. //
  64. const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f);
  65. // Language for UI construction
  66. std::map<std::string, std::string> gTranslation;
  67. std::list<std::string> gUntranslated;
  68. /*static*/ LLUI::settings_map_t LLUI::sSettingGroups;
  69. /*static*/ LLImageProviderInterface* LLUI::sImageProvider = NULL;
  70. /*static*/ LLUIAudioCallback LLUI::sAudioCallback = NULL;
  71. /*static*/ LLVector2 LLUI::sGLScaleFactor(1.f, 1.f);
  72. /*static*/ LLWindow* LLUI::sWindow = NULL;
  73. /*static*/ LLView* LLUI::sRootView = NULL;
  74. /*static*/ BOOL                         LLUI::sDirty = FALSE;
  75. /*static*/ LLRect                       LLUI::sDirtyRect;
  76. /*static*/ LLHelp* LLUI::sHelpImpl = NULL;
  77. /*static*/ std::vector<std::string> LLUI::sXUIPaths;
  78. /*static*/ LLFrameTimer LLUI::sMouseIdleTimer;
  79. // register filtereditor here
  80. static LLDefaultChildRegistry::Register<LLFilterEditor> register_filter_editor("filter_editor");
  81. static LLDefaultChildRegistry::Register<LLFlyoutButton> register_flyout_button("flyout_button");
  82. static LLDefaultChildRegistry::Register<LLSearchEditor> register_search_editor("search_editor");
  83. static LLDefaultChildRegistry::Register<LLMenuButton> register_menu_button("menu_button");
  84. //
  85. // Functions
  86. //
  87. void make_ui_sound(const char* namep)
  88. {
  89. std::string name = ll_safe_string(namep);
  90. if (!LLUI::sSettingGroups["config"]->controlExists(name))
  91. {
  92. llwarns << "tried to make ui sound for unknown sound name: " << name << llendl;
  93. }
  94. else
  95. {
  96. LLUUID uuid(LLUI::sSettingGroups["config"]->getString(name));
  97. if (uuid.isNull())
  98. {
  99. if (LLUI::sSettingGroups["config"]->getString(name) == LLUUID::null.asString())
  100. {
  101. if (LLUI::sSettingGroups["config"]->getBOOL("UISndDebugSpamToggle"))
  102. {
  103. llinfos << "ui sound name: " << name << " triggered but silent (null uuid)" << llendl;
  104. }
  105. }
  106. else
  107. {
  108. llwarns << "ui sound named: " << name << " does not translate to a valid uuid" << llendl;
  109. }
  110. }
  111. else if (LLUI::sAudioCallback != NULL)
  112. {
  113. if (LLUI::sSettingGroups["config"]->getBOOL("UISndDebugSpamToggle"))
  114. {
  115. llinfos << "ui sound name: " << name << llendl;
  116. }
  117. LLUI::sAudioCallback(uuid);
  118. }
  119. }
  120. }
  121. BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom)
  122. {
  123. if (x < left || right < x) return FALSE;
  124. if (y < bottom || top < y) return FALSE;
  125. return TRUE;
  126. }
  127. // Puts GL into 2D drawing mode by turning off lighting, setting to an
  128. // orthographic projection, etc.
  129. void gl_state_for_2d(S32 width, S32 height)
  130. {
  131. stop_glerror();
  132. F32 window_width = (F32) width;//gViewerWindow->getWindowWidth();
  133. F32 window_height = (F32) height;//gViewerWindow->getWindowHeight();
  134. glMatrixMode(GL_PROJECTION);
  135. glLoadIdentity();
  136. glOrtho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f);
  137. glMatrixMode(GL_MODELVIEW);
  138. glLoadIdentity();
  139. stop_glerror();
  140. }
  141. void gl_draw_x(const LLRect& rect, const LLColor4& color)
  142. {
  143. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  144. gGL.color4fv( color.mV );
  145. gGL.begin( LLRender::LINES );
  146. gGL.vertex2i( rect.mLeft, rect.mTop );
  147. gGL.vertex2i( rect.mRight, rect.mBottom );
  148. gGL.vertex2i( rect.mLeft, rect.mBottom );
  149. gGL.vertex2i( rect.mRight, rect.mTop );
  150. gGL.end();
  151. }
  152. void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset, BOOL filled)
  153. {
  154. gGL.color4fv(color.mV);
  155. gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled);
  156. }
  157. void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled)
  158. {
  159. gGL.pushMatrix();
  160. left += LLFontGL::sCurOrigin.mX;
  161. right += LLFontGL::sCurOrigin.mX;
  162. bottom += LLFontGL::sCurOrigin.mY;
  163. top += LLFontGL::sCurOrigin.mY;
  164. glLoadIdentity();
  165. gl_rect_2d(llfloor((F32)left * LLUI::sGLScaleFactor.mV[VX]) - pixel_offset,
  166. llfloor((F32)top * LLUI::sGLScaleFactor.mV[VY]) + pixel_offset,
  167. llfloor((F32)right * LLUI::sGLScaleFactor.mV[VX]) + pixel_offset,
  168. llfloor((F32)bottom * LLUI::sGLScaleFactor.mV[VY]) - pixel_offset,
  169. filled);
  170. gGL.popMatrix();
  171. }
  172. void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
  173. {
  174. stop_glerror();
  175. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  176. // Counterclockwise quad will face the viewer
  177. if( filled )
  178. {
  179. gGL.begin( LLRender::QUADS );
  180. gGL.vertex2i(left, top);
  181. gGL.vertex2i(left, bottom);
  182. gGL.vertex2i(right, bottom);
  183. gGL.vertex2i(right, top);
  184. gGL.end();
  185. }
  186. else
  187. {
  188. if( gGLManager.mATIOffsetVerticalLines )
  189. {
  190. // Work around bug in ATI driver: vertical lines are offset by (-1,-1)
  191. gGL.begin( LLRender::LINES );
  192. // Verticals 
  193. gGL.vertex2i(left + 1, top);
  194. gGL.vertex2i(left + 1, bottom);
  195. gGL.vertex2i(right, bottom);
  196. gGL.vertex2i(right, top);
  197. // Horizontals
  198. top--;
  199. right--;
  200. gGL.vertex2i(left, bottom);
  201. gGL.vertex2i(right, bottom);
  202. gGL.vertex2i(left, top);
  203. gGL.vertex2i(right, top);
  204. gGL.end();
  205. }
  206. else
  207. {
  208. top--;
  209. right--;
  210. gGL.begin( LLRender::LINE_STRIP );
  211. gGL.vertex2i(left, top);
  212. gGL.vertex2i(left, bottom);
  213. gGL.vertex2i(right, bottom);
  214. gGL.vertex2i(right, top);
  215. gGL.vertex2i(left, top);
  216. gGL.end();
  217. }
  218. }
  219. stop_glerror();
  220. }
  221. void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled )
  222. {
  223. gGL.color4fv( color.mV );
  224. gl_rect_2d( left, top, right, bottom, filled );
  225. }
  226. void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled )
  227. {
  228. gGL.color4fv( color.mV );
  229. gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
  230. }
  231. // Given a rectangle on the screen, draws a drop shadow _outside_
  232. // the right and bottom edges of it.  Along the right it has width "lines"
  233. // and along the bottom it has height "lines".
  234. void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines)
  235. {
  236. stop_glerror();
  237. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  238. // HACK: Overlap with the rectangle by a single pixel.
  239. right--;
  240. bottom++;
  241. lines++;
  242. LLColor4 end_color = start_color;
  243. end_color.mV[VALPHA] = 0.f;
  244. gGL.begin(LLRender::QUADS);
  245. // Right edge, CCW faces screen
  246. gGL.color4fv(start_color.mV);
  247. gGL.vertex2i(right, top-lines);
  248. gGL.vertex2i(right, bottom);
  249. gGL.color4fv(end_color.mV);
  250. gGL.vertex2i(right+lines, bottom);
  251. gGL.vertex2i(right+lines, top-lines);
  252. // Bottom edge, CCW faces screen
  253. gGL.color4fv(start_color.mV);
  254. gGL.vertex2i(right, bottom);
  255. gGL.vertex2i(left+lines, bottom);
  256. gGL.color4fv(end_color.mV);
  257. gGL.vertex2i(left+lines, bottom-lines);
  258. gGL.vertex2i(right, bottom-lines);
  259. // bottom left Corner
  260. gGL.color4fv(start_color.mV);
  261. gGL.vertex2i(left+lines, bottom);
  262. gGL.color4fv(end_color.mV);
  263. gGL.vertex2i(left, bottom);
  264. // make the bottom left corner not sharp
  265. gGL.vertex2i(left+1, bottom-lines+1);
  266. gGL.vertex2i(left+lines, bottom-lines);
  267. // bottom right corner
  268. gGL.color4fv(start_color.mV);
  269. gGL.vertex2i(right, bottom);
  270. gGL.color4fv(end_color.mV);
  271. gGL.vertex2i(right, bottom-lines);
  272. // make the rightmost corner not sharp
  273. gGL.vertex2i(right+lines-1, bottom-lines+1);
  274. gGL.vertex2i(right+lines, bottom);
  275. // top right corner
  276. gGL.color4fv(start_color.mV);
  277. gGL.vertex2i( right, top-lines );
  278. gGL.color4fv(end_color.mV);
  279. gGL.vertex2i( right+lines, top-lines );
  280. // make the corner not sharp
  281. gGL.vertex2i( right+lines-1, top-1 );
  282. gGL.vertex2i( right, top );
  283. gGL.end();
  284. stop_glerror();
  285. }
  286. void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 )
  287. {
  288. // Work around bug in ATI driver: vertical lines are offset by (-1,-1)
  289. if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines )
  290. {
  291. x1++;
  292. x2++;
  293. y1++;
  294. y2++;
  295. }
  296. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  297. gGL.begin(LLRender::LINES);
  298. gGL.vertex2i(x1, y1);
  299. gGL.vertex2i(x2, y2);
  300. gGL.end();
  301. }
  302. void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color )
  303. {
  304. // Work around bug in ATI driver: vertical lines are offset by (-1,-1)
  305. if( (x1 == x2) && gGLManager.mATIOffsetVerticalLines )
  306. {
  307. x1++;
  308. x2++;
  309. y1++;
  310. y2++;
  311. }
  312. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  313. gGL.color4fv( color.mV );
  314. gGL.begin(LLRender::LINES);
  315. gGL.vertex2i(x1, y1);
  316. gGL.vertex2i(x2, y2);
  317. gGL.end();
  318. }
  319. void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled)
  320. {
  321. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  322. gGL.color4fv(color.mV);
  323. if (filled)
  324. {
  325. gGL.begin(LLRender::TRIANGLES);
  326. }
  327. else
  328. {
  329. gGL.begin(LLRender::LINE_LOOP);
  330. }
  331. gGL.vertex2i(x1, y1);
  332. gGL.vertex2i(x2, y2);
  333. gGL.vertex2i(x3, y3);
  334. gGL.end();
  335. }
  336. void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac)
  337. {
  338. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  339. length = llmin((S32)(max_frac*(right - left)), length);
  340. length = llmin((S32)(max_frac*(top - bottom)), length);
  341. gGL.begin(LLRender::LINES);
  342. gGL.vertex2i(left, top);
  343. gGL.vertex2i(left + length, top);
  344. gGL.vertex2i(left, top);
  345. gGL.vertex2i(left, top - length);
  346. gGL.vertex2i(left, bottom);
  347. gGL.vertex2i(left + length, bottom);
  348. gGL.vertex2i(left, bottom);
  349. gGL.vertex2i(left, bottom + length);
  350. gGL.vertex2i(right, top);
  351. gGL.vertex2i(right - length, top);
  352. gGL.vertex2i(right, top);
  353. gGL.vertex2i(right, top - length);
  354. gGL.vertex2i(right, bottom);
  355. gGL.vertex2i(right - length, bottom);
  356. gGL.vertex2i(right, bottom);
  357. gGL.vertex2i(right, bottom + length);
  358. gGL.end();
  359. }
  360. void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect )
  361. {
  362. if (NULL == image)
  363. {
  364. llwarns << "image == NULL; aborting function" << llendl;
  365. return;
  366. }
  367. gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect );
  368. }
  369. void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
  370. {
  371. if (NULL == image)
  372. {
  373. llwarns << "image == NULL; aborting function" << llendl;
  374. return;
  375. }
  376. gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect );
  377. }
  378. void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect)
  379. {
  380. if (NULL == image)
  381. {
  382. llwarns << "image == NULL; aborting function" << llendl;
  383. return;
  384. }
  385. // scale screen size of borders down
  386. F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0);
  387. F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0);
  388. LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction);
  389. gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect);
  390. }
  391. void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect, const LLRectf& scale_rect)
  392. {
  393. stop_glerror();
  394. if (NULL == image)
  395. {
  396. llwarns << "image == NULL; aborting function" << llendl;
  397. return;
  398. }
  399. // shrink scaling region to be proportional to clipped image region
  400. LLRectf scale_rect_uv(
  401. uv_rect.mLeft + (scale_rect.mLeft * uv_rect.getWidth()),
  402. uv_rect.mBottom + (scale_rect.mTop * uv_rect.getHeight()),
  403. uv_rect.mLeft + (scale_rect.mRight * uv_rect.getWidth()),
  404. uv_rect.mBottom + (scale_rect.mBottom * uv_rect.getHeight()));
  405. S32 image_natural_width = llround((F32)image->getWidth(0) * uv_rect.getWidth());
  406. S32 image_natural_height = llround((F32)image->getHeight(0) * uv_rect.getHeight());
  407. LLRect draw_rect(0, height, width, 0);
  408. LLRect draw_scale_rect(llround(scale_rect_uv.mLeft * (F32)image->getWidth(0)),
  409. llround(scale_rect_uv.mTop * (F32)image->getHeight(0)),
  410. llround(scale_rect_uv.mRight * (F32)image->getWidth(0)),
  411. llround(scale_rect_uv.mBottom * (F32)image->getHeight(0)));
  412. // scale fixed region of image to drawn region
  413. draw_scale_rect.mRight += width - image_natural_width;
  414. draw_scale_rect.mTop += height - image_natural_height;
  415. S32 border_shrink_width = llmax(0, draw_scale_rect.mLeft - draw_scale_rect.mRight);
  416. S32 border_shrink_height = llmax(0, draw_scale_rect.mBottom - draw_scale_rect.mTop);
  417. F32 shrink_width_ratio = scale_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - scale_rect.getWidth()));
  418. F32 shrink_height_ratio = scale_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - scale_rect.getHeight()));
  419. F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
  420. draw_scale_rect.mLeft = llround((F32)draw_scale_rect.mLeft * shrink_scale);
  421. draw_scale_rect.mTop = llround(lerp((F32)height, (F32)draw_scale_rect.mTop, shrink_scale));
  422. draw_scale_rect.mRight = llround(lerp((F32)width, (F32)draw_scale_rect.mRight, shrink_scale));
  423. draw_scale_rect.mBottom = llround((F32)draw_scale_rect.mBottom * shrink_scale);
  424. LLGLSUIDefault gls_ui;
  425. if (solid_color)
  426. {
  427. gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR);
  428. gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
  429. }
  430. gGL.pushMatrix();
  431. {
  432. gGL.translatef((F32)x, (F32)y, 0.f);
  433. gGL.getTexUnit(0)->bind(image);
  434. gGL.color4fv(color.mV);
  435. gGL.begin(LLRender::QUADS);
  436. {
  437. // draw bottom left
  438. gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
  439. gGL.vertex2i(0, 0);
  440. gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mBottom);
  441. gGL.vertex2i(draw_scale_rect.mLeft, 0);
  442. gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
  443. gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
  444. gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mBottom);
  445. gGL.vertex2i(0, draw_scale_rect.mBottom);
  446. // draw bottom middle
  447. gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mBottom);
  448. gGL.vertex2i(draw_scale_rect.mLeft, 0);
  449. gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mBottom);
  450. gGL.vertex2i(draw_scale_rect.mRight, 0);
  451. gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
  452. gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
  453. gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
  454. gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
  455. // draw bottom right
  456. gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mBottom);
  457. gGL.vertex2i(draw_scale_rect.mRight, 0);
  458. gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
  459. gGL.vertex2i(width, 0);
  460. gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mBottom);
  461. gGL.vertex2i(width, draw_scale_rect.mBottom);
  462. gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
  463. gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
  464. // draw left 
  465. gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mBottom);
  466. gGL.vertex2i(0, draw_scale_rect.mBottom);
  467. gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
  468. gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
  469. gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
  470. gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
  471. gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mTop);
  472. gGL.vertex2i(0, draw_scale_rect.mTop);
  473. // draw middle
  474. gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
  475. gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
  476. gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
  477. gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
  478. gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
  479. gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
  480. gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
  481. gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
  482. // draw right 
  483. gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
  484. gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
  485. gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mBottom);
  486. gGL.vertex2i(width, draw_scale_rect.mBottom);
  487. gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mTop);
  488. gGL.vertex2i(width, draw_scale_rect.mTop);
  489. gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
  490. gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
  491. // draw top left
  492. gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mTop);
  493. gGL.vertex2i(0, draw_scale_rect.mTop);
  494. gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
  495. gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
  496. gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mTop);
  497. gGL.vertex2i(draw_scale_rect.mLeft, height);
  498. gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
  499. gGL.vertex2i(0, height);
  500. // draw top middle
  501. gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
  502. gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
  503. gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
  504. gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
  505. gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mTop);
  506. gGL.vertex2i(draw_scale_rect.mRight, height);
  507. gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mTop);
  508. gGL.vertex2i(draw_scale_rect.mLeft, height);
  509. // draw top right
  510. gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
  511. gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
  512. gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mTop);
  513. gGL.vertex2i(width, draw_scale_rect.mTop);
  514. gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
  515. gGL.vertex2i(width, height);
  516. gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mTop);
  517. gGL.vertex2i(draw_scale_rect.mRight, height);
  518. }
  519. gGL.end();
  520. }
  521. gGL.popMatrix();
  522. if (solid_color)
  523. {
  524. gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  525. }
  526. }
  527. void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
  528. {
  529. gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect );
  530. }
  531. void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
  532. {
  533. if (NULL == image)
  534. {
  535. llwarns << "image == NULL; aborting function" << llendl;
  536. return;
  537. }
  538. LLGLSUIDefault gls_ui;
  539. gGL.pushMatrix();
  540. {
  541. gGL.translatef((F32)x, (F32)y, 0.f);
  542. if( degrees )
  543. {
  544. F32 offset_x = F32(width/2);
  545. F32 offset_y = F32(height/2);
  546. gGL.translatef( offset_x, offset_y, 0.f);
  547. glRotatef( degrees, 0.f, 0.f, 1.f );
  548. gGL.translatef( -offset_x, -offset_y, 0.f );
  549. }
  550. gGL.getTexUnit(0)->bind(image);
  551. gGL.color4fv(color.mV);
  552. gGL.begin(LLRender::QUADS);
  553. {
  554. gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
  555. gGL.vertex2i(width, height );
  556. gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
  557. gGL.vertex2i(0, height );
  558. gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
  559. gGL.vertex2i(0, 0);
  560. gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
  561. gGL.vertex2i(width, 0);
  562. }
  563. gGL.end();
  564. }
  565. gGL.popMatrix();
  566. }
  567. void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase )
  568. {
  569. phase = fmod(phase, 1.f);
  570. S32 shift = S32(phase * 4.f) % 4;
  571. // Stippled line
  572. LLGLEnable stipple(GL_LINE_STIPPLE);
  573. gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]);
  574. gGL.flush();
  575. glLineWidth(2.5f);
  576. glLineStipple(2, 0x3333 << shift);
  577. gGL.begin(LLRender::LINES);
  578. {
  579. gGL.vertex3fv( start.mV );
  580. gGL.vertex3fv( end.mV );
  581. }
  582. gGL.end();
  583. LLUI::setLineWidth(1.f);
  584. }
  585. void gl_rect_2d_xor(S32 left, S32 top, S32 right, S32 bottom)
  586. {
  587. gGL.color4fv( LLColor4::white.mV );
  588. glLogicOp( GL_XOR );
  589. stop_glerror();
  590. gGL.begin(LLRender::QUADS);
  591. gGL.vertex2i(left, top);
  592. gGL.vertex2i(left, bottom);
  593. gGL.vertex2i(right, bottom);
  594. gGL.vertex2i(right, top);
  595. gGL.end();
  596. glLogicOp( GL_COPY );
  597. stop_glerror();
  598. }
  599. void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle)
  600. {
  601. if (end_angle < start_angle)
  602. {
  603. end_angle += F_TWO_PI;
  604. }
  605. gGL.pushMatrix();
  606. {
  607. gGL.translatef(center_x, center_y, 0.f);
  608. // Inexact, but reasonably fast.
  609. F32 delta = (end_angle - start_angle) / steps;
  610. F32 sin_delta = sin( delta );
  611. F32 cos_delta = cos( delta );
  612. F32 x = cosf(start_angle) * radius;
  613. F32 y = sinf(start_angle) * radius;
  614. if (filled)
  615. {
  616. gGL.begin(LLRender::TRIANGLE_FAN);
  617. gGL.vertex2f(0.f, 0.f);
  618. // make sure circle is complete
  619. steps += 1;
  620. }
  621. else
  622. {
  623. gGL.begin(LLRender::LINE_STRIP);
  624. }
  625. while( steps-- )
  626. {
  627. // Successive rotations
  628. gGL.vertex2f( x, y );
  629. F32 x_new = x * cos_delta - y * sin_delta;
  630. y = x * sin_delta +  y * cos_delta;
  631. x = x_new;
  632. }
  633. gGL.end();
  634. }
  635. gGL.popMatrix();
  636. }
  637. void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled)
  638. {
  639. gGL.pushMatrix();
  640. {
  641. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  642. gGL.translatef(center_x, center_y, 0.f);
  643. // Inexact, but reasonably fast.
  644. F32 delta = F_TWO_PI / steps;
  645. F32 sin_delta = sin( delta );
  646. F32 cos_delta = cos( delta );
  647. F32 x = radius;
  648. F32 y = 0.f;
  649. if (filled)
  650. {
  651. gGL.begin(LLRender::TRIANGLE_FAN);
  652. gGL.vertex2f(0.f, 0.f);
  653. // make sure circle is complete
  654. steps += 1;
  655. }
  656. else
  657. {
  658. gGL.begin(LLRender::LINE_LOOP);
  659. }
  660. while( steps-- )
  661. {
  662. // Successive rotations
  663. gGL.vertex2f( x, y );
  664. F32 x_new = x * cos_delta - y * sin_delta;
  665. y = x * sin_delta +  y * cos_delta;
  666. x = x_new;
  667. }
  668. gGL.end();
  669. }
  670. gGL.popMatrix();
  671. }
  672. // Renders a ring with sides (tube shape)
  673. void gl_deep_circle( F32 radius, F32 depth, S32 steps )
  674. {
  675. F32 x = radius;
  676. F32 y = 0.f;
  677. F32 angle_delta = F_TWO_PI / (F32)steps;
  678. gGL.begin( LLRender::TRIANGLE_STRIP  );
  679. {
  680. S32 step = steps + 1; // An extra step to close the circle.
  681. while( step-- )
  682. {
  683. gGL.vertex3f( x, y, depth );
  684. gGL.vertex3f( x, y, 0.f );
  685. F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta);
  686. y = x * sinf(angle_delta) +  y * cosf(angle_delta);
  687. x = x_new;
  688. }
  689. }
  690. gGL.end();
  691. }
  692. void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center )
  693. {
  694. gGL.pushMatrix();
  695. {
  696. gGL.translatef(0.f, 0.f, -width / 2);
  697. if( render_center )
  698. {
  699. gGL.color4fv(center_color.mV);
  700. gl_deep_circle( radius, width, steps );
  701. }
  702. else
  703. {
  704. gl_washer_2d(radius, radius - width, steps, side_color, side_color);
  705. gGL.translatef(0.f, 0.f, width);
  706. gl_washer_2d(radius - width, radius, steps, side_color, side_color);
  707. }
  708. }
  709. gGL.popMatrix();
  710. }
  711. // Draw gray and white checkerboard with black border
  712. void gl_rect_2d_checkerboard(const LLRect& rect)
  713. {
  714. // Initialize the first time this is called.
  715. const S32 PIXELS = 32;
  716. static GLubyte checkerboard[PIXELS * PIXELS];
  717. static BOOL first = TRUE;
  718. if( first )
  719. {
  720. for( S32 i = 0; i < PIXELS; i++ )
  721. {
  722. for( S32 j = 0; j < PIXELS; j++ )
  723. {
  724. checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF;
  725. }
  726. }
  727. first = FALSE;
  728. }
  729. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  730. // ...white squares
  731. gGL.color3f( 1.f, 1.f, 1.f );
  732. gl_rect_2d(rect);
  733. // ...gray squares
  734. gGL.color3f( .7f, .7f, .7f );
  735. gGL.flush();
  736. glPolygonStipple( checkerboard );
  737. LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE);
  738. gl_rect_2d(rect);
  739. gGL.flush();
  740. }
  741. // Draws the area between two concentric circles, like
  742. // a doughnut or washer.
  743. void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color)
  744. {
  745. const F32 DELTA = F_TWO_PI / steps;
  746. const F32 SIN_DELTA = sin( DELTA );
  747. const F32 COS_DELTA = cos( DELTA );
  748. F32 x1 = outer_radius;
  749. F32 y1 = 0.f;
  750. F32 x2 = inner_radius;
  751. F32 y2 = 0.f;
  752. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  753. gGL.begin( LLRender::TRIANGLE_STRIP  );
  754. {
  755. steps += 1; // An extra step to close the circle.
  756. while( steps-- )
  757. {
  758. gGL.color4fv(outer_color.mV);
  759. gGL.vertex2f( x1, y1 );
  760. gGL.color4fv(inner_color.mV);
  761. gGL.vertex2f( x2, y2 );
  762. F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
  763. y1 = x1 * SIN_DELTA +  y1 * COS_DELTA;
  764. x1 = x1_new;
  765. F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
  766. y2 = x2 * SIN_DELTA +  y2 * COS_DELTA;
  767. x2 = x2_new;
  768. }
  769. }
  770. gGL.end();
  771. }
  772. // Draws the area between two concentric circles, like
  773. // a doughnut or washer.
  774. void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color)
  775. {
  776. const F32 DELTA = (end_radians - start_radians) / steps;
  777. const F32 SIN_DELTA = sin( DELTA );
  778. const F32 COS_DELTA = cos( DELTA );
  779. F32 x1 = outer_radius * cos( start_radians );
  780. F32 y1 = outer_radius * sin( start_radians );
  781. F32 x2 = inner_radius * cos( start_radians );
  782. F32 y2 = inner_radius * sin( start_radians );
  783. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  784. gGL.begin( LLRender::TRIANGLE_STRIP  );
  785. {
  786. steps += 1; // An extra step to close the circle.
  787. while( steps-- )
  788. {
  789. gGL.color4fv(outer_color.mV);
  790. gGL.vertex2f( x1, y1 );
  791. gGL.color4fv(inner_color.mV);
  792. gGL.vertex2f( x2, y2 );
  793. F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
  794. y1 = x1 * SIN_DELTA +  y1 * COS_DELTA;
  795. x1 = x1_new;
  796. F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
  797. y2 = x2 * SIN_DELTA +  y2 * COS_DELTA;
  798. x2 = x2_new;
  799. }
  800. }
  801. gGL.end();
  802. }
  803. // Draws spokes around a circle.
  804. void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color)
  805. {
  806. const F32 DELTA = F_TWO_PI / count;
  807. const F32 HALF_DELTA = DELTA * 0.5f;
  808. const F32 SIN_DELTA = sin( DELTA );
  809. const F32 COS_DELTA = cos( DELTA );
  810. F32 x1 = outer_radius * cos( HALF_DELTA );
  811. F32 y1 = outer_radius * sin( HALF_DELTA );
  812. F32 x2 = inner_radius * cos( HALF_DELTA );
  813. F32 y2 = inner_radius * sin( HALF_DELTA );
  814. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  815. gGL.begin( LLRender::LINES  );
  816. {
  817. while( count-- )
  818. {
  819. gGL.color4fv(outer_color.mV);
  820. gGL.vertex2f( x1, y1 );
  821. gGL.color4fv(inner_color.mV);
  822. gGL.vertex2f( x2, y2 );
  823. F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
  824. y1 = x1 * SIN_DELTA +  y1 * COS_DELTA;
  825. x1 = x1_new;
  826. F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
  827. y2 = x2 * SIN_DELTA +  y2 * COS_DELTA;
  828. x2 = x2_new;
  829. }
  830. }
  831. gGL.end();
  832. }
  833. void gl_rect_2d_simple_tex( S32 width, S32 height )
  834. {
  835. gGL.begin( LLRender::QUADS );
  836. gGL.texCoord2f(1.f, 1.f);
  837. gGL.vertex2i(width, height);
  838. gGL.texCoord2f(0.f, 1.f);
  839. gGL.vertex2i(0, height);
  840. gGL.texCoord2f(0.f, 0.f);
  841. gGL.vertex2i(0, 0);
  842. gGL.texCoord2f(1.f, 0.f);
  843. gGL.vertex2i(width, 0);
  844. gGL.end();
  845. }
  846. void gl_rect_2d_simple( S32 width, S32 height )
  847. {
  848. gGL.begin( LLRender::QUADS );
  849. gGL.vertex2i(width, height);
  850. gGL.vertex2i(0, height);
  851. gGL.vertex2i(0, 0);
  852. gGL.vertex2i(width, 0);
  853. gGL.end();
  854. }
  855. void gl_segmented_rect_2d_tex(const S32 left, 
  856.   const S32 top, 
  857.   const S32 right, 
  858.   const S32 bottom, 
  859.   const S32 texture_width, 
  860.   const S32 texture_height, 
  861.   const S32 border_size, 
  862.   const U32 edges)
  863. {
  864. S32 width = llabs(right - left);
  865. S32 height = llabs(top - bottom);
  866. gGL.pushMatrix();
  867. gGL.translatef((F32)left, (F32)bottom, 0.f);
  868. LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
  869. if (border_uv_scale.mV[VX] > 0.5f)
  870. {
  871. border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
  872. }
  873. if (border_uv_scale.mV[VY] > 0.5f)
  874. {
  875. border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
  876. }
  877. F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
  878. LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
  879. LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
  880. LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
  881. LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
  882. LLVector2 width_vec((F32)width, 0.f);
  883. LLVector2 height_vec(0.f, (F32)height);
  884. gGL.begin(LLRender::QUADS);
  885. {
  886. // draw bottom left
  887. gGL.texCoord2f(0.f, 0.f);
  888. gGL.vertex2f(0.f, 0.f);
  889. gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
  890. gGL.vertex2fv(border_width_left.mV);
  891. gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  892. gGL.vertex2fv((border_width_left + border_height_bottom).mV);
  893. gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
  894. gGL.vertex2fv(border_height_bottom.mV);
  895. // draw bottom middle
  896. gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
  897. gGL.vertex2fv(border_width_left.mV);
  898. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
  899. gGL.vertex2fv((width_vec - border_width_right).mV);
  900. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  901. gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
  902. gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  903. gGL.vertex2fv((border_width_left + border_height_bottom).mV);
  904. // draw bottom right
  905. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
  906. gGL.vertex2fv((width_vec - border_width_right).mV);
  907. gGL.texCoord2f(1.f, 0.f);
  908. gGL.vertex2fv(width_vec.mV);
  909. gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
  910. gGL.vertex2fv((width_vec + border_height_bottom).mV);
  911. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  912. gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
  913. // draw left 
  914. gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
  915. gGL.vertex2fv(border_height_bottom.mV);
  916. gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  917. gGL.vertex2fv((border_width_left + border_height_bottom).mV);
  918. gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  919. gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
  920. gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
  921. gGL.vertex2fv((height_vec - border_height_top).mV);
  922. // draw middle
  923. gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  924. gGL.vertex2fv((border_width_left + border_height_bottom).mV);
  925. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  926. gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
  927. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  928. gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
  929. gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  930. gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
  931. // draw right 
  932. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  933. gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
  934. gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
  935. gGL.vertex2fv((width_vec + border_height_bottom).mV);
  936. gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
  937. gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
  938. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  939. gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
  940. // draw top left
  941. gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
  942. gGL.vertex2fv((height_vec - border_height_top).mV);
  943. gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  944. gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
  945. gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
  946. gGL.vertex2fv((border_width_left + height_vec).mV);
  947. gGL.texCoord2f(0.f, 1.f);
  948. gGL.vertex2fv((height_vec).mV);
  949. // draw top middle
  950. gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  951. gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
  952. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  953. gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
  954. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
  955. gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
  956. gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
  957. gGL.vertex2fv((border_width_left + height_vec).mV);
  958. // draw top right
  959. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  960. gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
  961. gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
  962. gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
  963. gGL.texCoord2f(1.f, 1.f);
  964. gGL.vertex2fv((width_vec + height_vec).mV);
  965. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
  966. gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
  967. }
  968. gGL.end();
  969. gGL.popMatrix();
  970. }
  971. void gl_segmented_rect_2d_fragment_tex(const S32 left, 
  972.    const S32 top, 
  973.    const S32 right, 
  974.    const S32 bottom, 
  975.    const S32 texture_width, 
  976.    const S32 texture_height, 
  977.    const S32 border_size, 
  978.    const F32 start_fragment, 
  979.    const F32 end_fragment, 
  980.    const U32 edges)
  981. {
  982. S32 width = llabs(right - left);
  983. S32 height = llabs(top - bottom);
  984. gGL.pushMatrix();
  985. gGL.translatef((F32)left, (F32)bottom, 0.f);
  986. LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
  987. if (border_uv_scale.mV[VX] > 0.5f)
  988. {
  989. border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
  990. }
  991. if (border_uv_scale.mV[VY] > 0.5f)
  992. {
  993. border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
  994. }
  995. F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
  996. LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
  997. LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
  998. LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
  999. LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
  1000. LLVector2 width_vec((F32)width, 0.f);
  1001. LLVector2 height_vec(0.f, (F32)height);
  1002. F32 middle_start = border_scale / (F32)width;
  1003. F32 middle_end = 1.f - middle_start;
  1004. F32 u_min;
  1005. F32 u_max;
  1006. LLVector2 x_min;
  1007. LLVector2 x_max;
  1008. gGL.begin(LLRender::QUADS);
  1009. {
  1010. if (start_fragment < middle_start)
  1011. {
  1012. u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX];
  1013. u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX];
  1014. x_min = (start_fragment / middle_start) * border_width_left;
  1015. x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left;
  1016. // draw bottom left
  1017. gGL.texCoord2f(u_min, 0.f);
  1018. gGL.vertex2fv(x_min.mV);
  1019. gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
  1020. gGL.vertex2fv(x_max.mV);
  1021. gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
  1022. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1023. gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
  1024. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1025. // draw left 
  1026. gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
  1027. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1028. gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
  1029. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1030. gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
  1031. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1032. gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
  1033. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1034. // draw top left
  1035. gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
  1036. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1037. gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
  1038. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1039. gGL.texCoord2f(u_max, 1.f);
  1040. gGL.vertex2fv((x_max + height_vec).mV);
  1041. gGL.texCoord2f(u_min, 1.f);
  1042. gGL.vertex2fv((x_min + height_vec).mV);
  1043. }
  1044. if (end_fragment > middle_start || start_fragment < middle_end)
  1045. {
  1046. x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec;
  1047. x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec;
  1048. // draw bottom middle
  1049. gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
  1050. gGL.vertex2fv(x_min.mV);
  1051. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
  1052. gGL.vertex2fv((x_max).mV);
  1053. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  1054. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1055. gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  1056. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1057. // draw middle
  1058. gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  1059. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1060. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
  1061. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1062. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  1063. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1064. gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  1065. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1066. // draw top middle
  1067. gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  1068. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1069. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
  1070. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1071. gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
  1072. gGL.vertex2fv((x_max + height_vec).mV);
  1073. gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
  1074. gGL.vertex2fv((x_min + height_vec).mV);
  1075. }
  1076. if (end_fragment > middle_end)
  1077. {
  1078. u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX];
  1079. u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX];
  1080. x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right);
  1081. x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right);
  1082. // draw bottom right
  1083. gGL.texCoord2f(u_min, 0.f);
  1084. gGL.vertex2fv((x_min).mV);
  1085. gGL.texCoord2f(u_max, 0.f);
  1086. gGL.vertex2fv(x_max.mV);
  1087. gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
  1088. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1089. gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
  1090. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1091. // draw right 
  1092. gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
  1093. gGL.vertex2fv((x_min + border_height_bottom).mV);
  1094. gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
  1095. gGL.vertex2fv((x_max + border_height_bottom).mV);
  1096. gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
  1097. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1098. gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
  1099. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1100. // draw top right
  1101. gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
  1102. gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
  1103. gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
  1104. gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
  1105. gGL.texCoord2f(u_max, 1.f);
  1106. gGL.vertex2fv((x_max + height_vec).mV);
  1107. gGL.texCoord2f(u_min, 1.f);
  1108. gGL.vertex2fv((x_min + height_vec).mV);
  1109. }
  1110. }
  1111. gGL.end();
  1112. gGL.popMatrix();
  1113. }
  1114. void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, 
  1115.   const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec,
  1116.   const U32 edges)
  1117. {
  1118. LLVector3 left_border_width = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? border_width : LLVector3::zero;
  1119. LLVector3 right_border_width = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? border_width : LLVector3::zero;
  1120. LLVector3 top_border_height = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? border_height : LLVector3::zero;
  1121. LLVector3 bottom_border_height = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? border_height : LLVector3::zero;
  1122. gGL.begin(LLRender::QUADS);
  1123. {
  1124. // draw bottom left
  1125. gGL.texCoord2f(0.f, 0.f);
  1126. gGL.vertex3f(0.f, 0.f, 0.f);
  1127. gGL.texCoord2f(border_scale.mV[VX], 0.f);
  1128. gGL.vertex3fv(left_border_width.mV);
  1129. gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
  1130. gGL.vertex3fv((left_border_width + bottom_border_height).mV);
  1131. gGL.texCoord2f(0.f, border_scale.mV[VY]);
  1132. gGL.vertex3fv(bottom_border_height.mV);
  1133. // draw bottom middle
  1134. gGL.texCoord2f(border_scale.mV[VX], 0.f);
  1135. gGL.vertex3fv(left_border_width.mV);
  1136. gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f);
  1137. gGL.vertex3fv((width_vec - right_border_width).mV);
  1138. gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
  1139. gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV);
  1140. gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
  1141. gGL.vertex3fv((left_border_width + bottom_border_height).mV);
  1142. // draw bottom right
  1143. gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f);
  1144. gGL.vertex3fv((width_vec - right_border_width).mV);
  1145. gGL.texCoord2f(1.f, 0.f);
  1146. gGL.vertex3fv(width_vec.mV);
  1147. gGL.texCoord2f(1.f, border_scale.mV[VY]);
  1148. gGL.vertex3fv((width_vec + bottom_border_height).mV);
  1149. gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
  1150. gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV);
  1151. // draw left 
  1152. gGL.texCoord2f(0.f, border_scale.mV[VY]);
  1153. gGL.vertex3fv(bottom_border_height.mV);
  1154. gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
  1155. gGL.vertex3fv((left_border_width + bottom_border_height).mV);
  1156. gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
  1157. gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV);
  1158. gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]);
  1159. gGL.vertex3fv((height_vec - top_border_height).mV);
  1160. // draw middle
  1161. gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
  1162. gGL.vertex3fv((left_border_width + bottom_border_height).mV);
  1163. gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
  1164. gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV);
  1165. gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
  1166. gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
  1167. gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
  1168. gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV);
  1169. // draw right 
  1170. gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
  1171. gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV);
  1172. gGL.texCoord2f(1.f, border_scale.mV[VY]);
  1173. gGL.vertex3fv((width_vec + bottom_border_height).mV);
  1174. gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]);
  1175. gGL.vertex3fv((width_vec + height_vec - top_border_height).mV);
  1176. gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
  1177. gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
  1178. // draw top left
  1179. gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]);
  1180. gGL.vertex3fv((height_vec - top_border_height).mV);
  1181. gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
  1182. gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV);
  1183. gGL.texCoord2f(border_scale.mV[VX], 1.f);
  1184. gGL.vertex3fv((left_border_width + height_vec).mV);
  1185. gGL.texCoord2f(0.f, 1.f);
  1186. gGL.vertex3fv((height_vec).mV);
  1187. // draw top middle
  1188. gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
  1189. gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV);
  1190. gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
  1191. gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
  1192. gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f);
  1193. gGL.vertex3fv((width_vec - right_border_width + height_vec).mV);
  1194. gGL.texCoord2f(border_scale.mV[VX], 1.f);
  1195. gGL.vertex3fv((left_border_width + height_vec).mV);
  1196. // draw top right
  1197. gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
  1198. gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
  1199. gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]);
  1200. gGL.vertex3fv((width_vec + height_vec - top_border_height).mV);
  1201. gGL.texCoord2f(1.f, 1.f);
  1202. gGL.vertex3fv((width_vec + height_vec).mV);
  1203. gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f);
  1204. gGL.vertex3fv((width_vec - right_border_width + height_vec).mV);
  1205. }
  1206. gGL.end();
  1207. }
  1208. 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)
  1209. {
  1210. gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP);
  1211. }
  1212. void LLUI::initClass(const settings_map_t& settings,
  1213.  LLImageProviderInterface* image_provider,
  1214.  LLUIAudioCallback audio_callback,
  1215.  const LLVector2* scale_factor,
  1216.  const std::string& language)
  1217. {
  1218. sSettingGroups = settings;
  1219. if ((get_ptr_in_map(sSettingGroups, std::string("config")) == NULL) ||
  1220. (get_ptr_in_map(sSettingGroups, std::string("floater")) == NULL) ||
  1221. (get_ptr_in_map(sSettingGroups, std::string("ignores")) == NULL))
  1222. {
  1223. llerrs << "Failure to initialize configuration groups" << llendl;
  1224. }
  1225. sImageProvider = image_provider;
  1226. sAudioCallback = audio_callback;
  1227. sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor;
  1228. sWindow = NULL; // set later in startup
  1229. LLFontGL::sShadowColor = LLUIColorTable::instance().getColor("ColorDropShadow");
  1230. // Callbacks for associating controls with floater visibilty:
  1231. LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleFloaterInstance, _2));
  1232. LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Show", boost::bind(&LLFloaterReg::showFloaterInstance, _2));
  1233. LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Hide", boost::bind(&LLFloaterReg::hideFloaterInstance, _2));
  1234. LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.InitToVisibilityControl", boost::bind(&LLFloaterReg::initUICtrlToFloaterVisibilityControl, _1, _2));
  1235. // Button initialization callback for toggle buttons
  1236. LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.SetFloaterToggle", boost::bind(&LLButton::setFloaterToggle, _1, _2));
  1237. // Button initialization callback for toggle buttons on dockale floaters
  1238. LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.SetDockableFloaterToggle", boost::bind(&LLButton::setDockableFloaterToggle, _1, _2));
  1239. // Display the help topic for the current context
  1240. LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.ShowHelp", boost::bind(&LLButton::showHelp, _1, _2));
  1241. // Currently unused, but kept for reference:
  1242. LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.ToggleFloater", boost::bind(&LLButton::toggleFloaterAndSetToggleState, _1, _2));
  1243. // Used by menus along with Floater.Toggle to display visibility as a checkmark
  1244. LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.Visible", boost::bind(&LLFloaterReg::floaterInstanceVisible, _2));
  1245. }
  1246. void LLUI::cleanupClass()
  1247. {
  1248. sImageProvider->cleanUp();
  1249. }
  1250. //static
  1251. void LLUI::dirtyRect(LLRect rect)
  1252. {
  1253. if (!sDirty)
  1254. {
  1255. sDirtyRect = rect;
  1256. sDirty = TRUE;
  1257. }
  1258. else
  1259. {
  1260. sDirtyRect.unionWith(rect);
  1261. }
  1262. }
  1263.  
  1264. //static
  1265. void LLUI::translate(F32 x, F32 y, F32 z)
  1266. {
  1267. gGL.translatef(x,y,z);
  1268. LLFontGL::sCurOrigin.mX += (S32) x;
  1269. LLFontGL::sCurOrigin.mY += (S32) y;
  1270. LLFontGL::sCurOrigin.mZ += z;
  1271. }
  1272. //static
  1273. void LLUI::pushMatrix()
  1274. {
  1275. gGL.pushMatrix();
  1276. LLFontGL::sOriginStack.push_back(LLFontGL::sCurOrigin);
  1277. }
  1278. //static
  1279. void LLUI::popMatrix()
  1280. {
  1281. gGL.popMatrix();
  1282. LLFontGL::sCurOrigin = *LLFontGL::sOriginStack.rbegin();
  1283. LLFontGL::sOriginStack.pop_back();
  1284. }
  1285. //static 
  1286. void LLUI::loadIdentity()
  1287. {
  1288. glLoadIdentity();
  1289. LLFontGL::sCurOrigin.mX = 0;
  1290. LLFontGL::sCurOrigin.mY = 0;
  1291. LLFontGL::sCurOrigin.mZ = 0;
  1292. }
  1293. //static
  1294. void LLUI::setScaleFactor(const LLVector2 &scale_factor)
  1295. {
  1296. sGLScaleFactor = scale_factor;
  1297. }
  1298. //static
  1299. void LLUI::setLineWidth(F32 width)
  1300. {
  1301. gGL.flush();
  1302. glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f));
  1303. }
  1304. //static 
  1305. void LLUI::setMousePositionScreen(S32 x, S32 y)
  1306. {
  1307. S32 screen_x, screen_y;
  1308. screen_x = llround((F32)x * sGLScaleFactor.mV[VX]);
  1309. screen_y = llround((F32)y * sGLScaleFactor.mV[VY]);
  1310. LLCoordWindow window_point;
  1311. LLView::getWindow()->convertCoords(LLCoordGL(screen_x, screen_y), &window_point);
  1312. LLView::getWindow()->setCursorPosition(window_point);
  1313. }
  1314. //static 
  1315. void LLUI::getMousePositionScreen(S32 *x, S32 *y)
  1316. {
  1317. LLCoordWindow cursor_pos_window;
  1318. getWindow()->getCursorPosition(&cursor_pos_window);
  1319. LLCoordGL cursor_pos_gl;
  1320. getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
  1321. *x = llround((F32)cursor_pos_gl.mX / sGLScaleFactor.mV[VX]);
  1322. *y = llround((F32)cursor_pos_gl.mY / sGLScaleFactor.mV[VX]);
  1323. }
  1324. //static 
  1325. void LLUI::setMousePositionLocal(const LLView* viewp, S32 x, S32 y)
  1326. {
  1327. S32 screen_x, screen_y;
  1328. viewp->localPointToScreen(x, y, &screen_x, &screen_y);
  1329. setMousePositionScreen(screen_x, screen_y);
  1330. }
  1331. //static 
  1332. void LLUI::getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y)
  1333. {
  1334. S32 screen_x, screen_y;
  1335. getMousePositionScreen(&screen_x, &screen_y);
  1336. viewp->screenPointToLocal(screen_x, screen_y, x, y);
  1337. }
  1338. // On Windows, the user typically sets the language when they install the
  1339. // app (by running it with a shortcut that sets InstallLanguage).  On Mac,
  1340. // or on Windows if the SecondLife.exe executable is run directly, the 
  1341. // language follows the OS language.  In all cases the user can override
  1342. // the language manually in preferences. JC
  1343. // static
  1344. std::string LLUI::getLanguage()
  1345. {
  1346. std::string language = "en";
  1347. if (sSettingGroups["config"])
  1348. {
  1349. language = sSettingGroups["config"]->getString("Language");
  1350. if (language.empty() || language == "default")
  1351. {
  1352. language = sSettingGroups["config"]->getString("InstallLanguage");
  1353. }
  1354. if (language.empty() || language == "default")
  1355. {
  1356. language = sSettingGroups["config"]->getString("SystemLanguage");
  1357. }
  1358. if (language.empty() || language == "default")
  1359. {
  1360. language = "en";
  1361. }
  1362. }
  1363. return language;
  1364. }
  1365. //static
  1366. void LLUI::setupPaths()
  1367. {
  1368. std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "paths.xml");
  1369. LLXMLNodePtr root;
  1370. BOOL success  = LLXMLNode::parseFile(filename, root, NULL);
  1371. sXUIPaths.clear();
  1372. if (success)
  1373. {
  1374. LLStringUtil::format_map_t path_args;
  1375. path_args["[LANGUAGE]"] = LLUI::getLanguage();
  1376. for (LLXMLNodePtr path = root->getFirstChild(); path.notNull(); path = path->getNextSibling())
  1377. {
  1378. std::string path_val_ui(path->getValue());
  1379. LLStringUtil::format(path_val_ui, path_args);
  1380. if (std::find(sXUIPaths.begin(), sXUIPaths.end(), path_val_ui) == sXUIPaths.end())
  1381. {
  1382. sXUIPaths.push_back(path_val_ui);
  1383. }
  1384. }
  1385. }
  1386. else // parsing failed
  1387. {
  1388. std::string slash = gDirUtilp->getDirDelimiter();
  1389. std::string dir = "xui" + slash + "en";
  1390. llwarns << "XUI::config file unable to open: " << filename << llendl;
  1391. sXUIPaths.push_back(dir);
  1392. }
  1393. }
  1394. //static
  1395. std::string LLUI::locateSkin(const std::string& filename)
  1396. {
  1397. std::string slash = gDirUtilp->getDirDelimiter();
  1398. std::string found_file = filename;
  1399. if (!gDirUtilp->fileExists(found_file))
  1400. {
  1401. found_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); // Should be CUSTOM_SKINS?
  1402. }
  1403. if (sSettingGroups["config"] && sSettingGroups["config"]->controlExists("Language"))
  1404. {
  1405. if (!gDirUtilp->fileExists(found_file))
  1406. {
  1407. std::string localization = getLanguage();
  1408. std::string local_skin = "xui" + slash + localization + slash + filename;
  1409. found_file = gDirUtilp->findSkinnedFilename(local_skin);
  1410. }
  1411. }
  1412. if (!gDirUtilp->fileExists(found_file))
  1413. {
  1414. std::string local_skin = "xui" + slash + "en" + slash + filename;
  1415. found_file = gDirUtilp->findSkinnedFilename(local_skin);
  1416. }
  1417. if (!gDirUtilp->fileExists(found_file))
  1418. {
  1419. found_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename);
  1420. }
  1421. return found_file;
  1422. }
  1423. //static
  1424. LLVector2 LLUI::getWindowSize()
  1425. {
  1426. LLCoordWindow window_rect;
  1427. sWindow->getSize(&window_rect);
  1428. return LLVector2(window_rect.mX / sGLScaleFactor.mV[VX], window_rect.mY / sGLScaleFactor.mV[VY]);
  1429. }
  1430. //static
  1431. void LLUI::screenPointToGL(S32 screen_x, S32 screen_y, S32 *gl_x, S32 *gl_y)
  1432. {
  1433. *gl_x = llround((F32)screen_x * sGLScaleFactor.mV[VX]);
  1434. *gl_y = llround((F32)screen_y * sGLScaleFactor.mV[VY]);
  1435. }
  1436. //static
  1437. void LLUI::glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y)
  1438. {
  1439. *screen_x = llround((F32)gl_x / sGLScaleFactor.mV[VX]);
  1440. *screen_y = llround((F32)gl_y / sGLScaleFactor.mV[VY]);
  1441. }
  1442. //static
  1443. void LLUI::screenRectToGL(const LLRect& screen, LLRect *gl)
  1444. {
  1445. screenPointToGL(screen.mLeft, screen.mTop, &gl->mLeft, &gl->mTop);
  1446. screenPointToGL(screen.mRight, screen.mBottom, &gl->mRight, &gl->mBottom);
  1447. }
  1448. //static
  1449. void LLUI::glRectToScreen(const LLRect& gl, LLRect *screen)
  1450. {
  1451. glPointToScreen(gl.mLeft, gl.mTop, &screen->mLeft, &screen->mTop);
  1452. glPointToScreen(gl.mRight, gl.mBottom, &screen->mRight, &screen->mBottom);
  1453. }
  1454. //static
  1455. LLPointer<LLUIImage> LLUI::getUIImageByID(const LLUUID& image_id, S32 priority)
  1456. {
  1457. if (sImageProvider)
  1458. {
  1459. return sImageProvider->getUIImageByID(image_id, priority);
  1460. }
  1461. else
  1462. {
  1463. return NULL;
  1464. }
  1465. }
  1466. //static 
  1467. LLPointer<LLUIImage> LLUI::getUIImage(const std::string& name, S32 priority)
  1468. {
  1469. if (!name.empty() && sImageProvider)
  1470. return sImageProvider->getUIImage(name, priority);
  1471. else
  1472. return NULL;
  1473. }
  1474. LLControlGroup& LLUI::getControlControlGroup (const std::string& controlname)
  1475. {
  1476. for (settings_map_t::iterator itor = sSettingGroups.begin();
  1477.  itor != sSettingGroups.end(); ++itor)
  1478. {
  1479. LLControlGroup* control_group = itor->second;
  1480. if(control_group != NULL)
  1481. {
  1482. if (control_group->controlExists(controlname))
  1483. return *control_group;
  1484. }
  1485. }
  1486. return *sSettingGroups["config"]; // default group
  1487. }
  1488. //static
  1489. // spawn_x and spawn_y are top left corner of view in screen GL coordinates
  1490. void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y)
  1491. {
  1492. const S32 CURSOR_HEIGHT = 16; // Approximate "normal" cursor size
  1493. const S32 CURSOR_WIDTH = 8;
  1494. LLView* parent = view->getParent();
  1495. S32 mouse_x;
  1496. S32 mouse_y;
  1497. LLUI::getMousePositionScreen(&mouse_x, &mouse_y);
  1498. // If no spawn location provided, use mouse position
  1499. if (spawn_x == S32_MAX || spawn_y == S32_MAX)
  1500. {
  1501. spawn_x = mouse_x + CURSOR_WIDTH;
  1502. spawn_y = mouse_y - CURSOR_HEIGHT;
  1503. }
  1504. LLRect virtual_window_rect = parent->getLocalRect();
  1505. LLRect mouse_rect;
  1506. const S32 MOUSE_CURSOR_PADDING = 1;
  1507. mouse_rect.setLeftTopAndSize(mouse_x - MOUSE_CURSOR_PADDING, 
  1508. mouse_y + MOUSE_CURSOR_PADDING, 
  1509. CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2, 
  1510. CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2);
  1511. S32 local_x, local_y;
  1512. // convert screen coordinates to tooltipview-local coordinates
  1513. parent->screenPointToLocal(spawn_x, spawn_y, &local_x, &local_y);
  1514. // Start at spawn position (using left/top)
  1515. view->setOrigin( local_x, local_y - view->getRect().getHeight());
  1516. // Make sure we're onscreen and not overlapping the mouse
  1517. view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect, FALSE );
  1518. }
  1519. // LLLocalClipRect and LLScreenClipRect moved to lllocalcliprect.h/cpp
  1520. namespace LLInitParam
  1521. {
  1522. TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
  1523. : super_t(descriptor, name, value, func, min_count, max_count),
  1524. red("red"),
  1525. green("green"),
  1526. blue("blue"),
  1527. alpha("alpha"),
  1528. control("")
  1529. {
  1530. setBlockFromValue();
  1531. }
  1532. void TypedParam<LLUIColor>::setValueFromBlock() const
  1533. {
  1534. if (control.isProvided())
  1535. {
  1536. mData.mValue = LLUIColorTable::instance().getColor(control);
  1537. }
  1538. else
  1539. {
  1540. mData.mValue = LLColor4(red, green, blue, alpha);
  1541. }
  1542. }
  1543. void TypedParam<LLUIColor>::setBlockFromValue()
  1544. {
  1545. LLColor4 color = mData.mValue.get();
  1546. red.set(color.mV[VRED], false);
  1547. green.set(color.mV[VGREEN], false);
  1548. blue.set(color.mV[VBLUE], false);
  1549. alpha.set(color.mV[VALPHA], false);
  1550. control.set("", false);
  1551. }
  1552. void TypeValues<LLUIColor>::declareValues()
  1553. {
  1554. declare("white", LLColor4::white);
  1555. declare("black", LLColor4::black);
  1556. declare("red", LLColor4::red);
  1557. declare("green", LLColor4::green);
  1558. declare("blue", LLColor4::blue);
  1559. }
  1560. bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
  1561. {
  1562. return !(a->getFontDesc() < b->getFontDesc())
  1563. && !(b->getFontDesc() < a->getFontDesc());
  1564. }
  1565. TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
  1566. : super_t(descriptor, _name, value, func, min_count, max_count),
  1567. name("name"),
  1568. size("size"),
  1569. style("style")
  1570. {
  1571. setBlockFromValue();
  1572. addSynonym(name, "");
  1573. }
  1574. void TypedParam<const LLFontGL*>::setValueFromBlock() const
  1575. {
  1576. const LLFontGL* res_fontp = LLFontGL::getFontByName(name);
  1577. if (res_fontp)
  1578. {
  1579. mData.mValue = res_fontp;
  1580. return;
  1581. }
  1582. U8 fontstyle = 0;
  1583. fontstyle = LLFontGL::getStyleFromString(style());
  1584. LLFontDescriptor desc(name(), size(), fontstyle);
  1585. const LLFontGL* fontp = LLFontGL::getFont(desc);
  1586. if (fontp)
  1587. {
  1588. mData.mValue = fontp;
  1589. }
  1590. }
  1591. void TypedParam<const LLFontGL*>::setBlockFromValue()
  1592. {
  1593. if (mData.mValue)
  1594. {
  1595. name.set(LLFontGL::nameFromFont(mData.mValue), false);
  1596. size.set(LLFontGL::sizeFromFont(mData.mValue), false);
  1597. style.set(LLFontGL::getStringFromStyle(mData.mValue->getFontDesc().getStyle()), false);
  1598. }
  1599. }
  1600. TypedParam<LLRect>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
  1601. : super_t(descriptor, name, value, func, min_count, max_count),
  1602. left("left"),
  1603. top("top"),
  1604. right("right"),
  1605. bottom("bottom"),
  1606. width("width"),
  1607. height("height")
  1608. {
  1609. setBlockFromValue();
  1610. }
  1611. void TypedParam<LLRect>::setValueFromBlock() const
  1612. {
  1613. LLRect rect;
  1614. //calculate from params
  1615. // prefer explicit left and right
  1616. if (left.isProvided() && right.isProvided())
  1617. {
  1618. rect.mLeft = left;
  1619. rect.mRight = right;
  1620. }
  1621. // otherwise use width along with specified side, if any
  1622. else if (width.isProvided())
  1623. {
  1624. // only right + width provided
  1625. if (right.isProvided())
  1626. {
  1627. rect.mRight = right;
  1628. rect.mLeft = right - width;
  1629. }
  1630. else // left + width, or just width
  1631. {
  1632. rect.mLeft = left;
  1633. rect.mRight = left + width;
  1634. }
  1635. }
  1636. // just left, just right, or none
  1637. else
  1638. {
  1639. rect.mLeft = left;
  1640. rect.mRight = right;
  1641. }
  1642. // prefer explicit bottom and top
  1643. if (bottom.isProvided() && top.isProvided())
  1644. {
  1645. rect.mBottom = bottom;
  1646. rect.mTop = top;
  1647. }
  1648. // otherwise height along with specified side, if any
  1649. else if (height.isProvided())
  1650. {
  1651. // top + height provided
  1652. if (top.isProvided())
  1653. {
  1654. rect.mTop = top;
  1655. rect.mBottom = top - height;
  1656. }
  1657. // bottom + height or just height
  1658. else
  1659. {
  1660. rect.mBottom = bottom;
  1661. rect.mTop = bottom + height;
  1662. }
  1663. }
  1664. // just bottom, just top, or none
  1665. else
  1666. {
  1667. rect.mBottom = bottom;
  1668. rect.mTop = top;
  1669. }
  1670. mData.mValue = rect;
  1671. }
  1672. void TypedParam<LLRect>::setBlockFromValue()
  1673. {
  1674. // because of the ambiguity in specifying a rect by position and/or dimensions
  1675. // we clear the "provided" flag so that values from xui/etc have priority
  1676. // over those calculated from the rect object
  1677. left.set(mData.mValue.mLeft, false);
  1678. right.set(mData.mValue.mRight, false);
  1679. bottom.set(mData.mValue.mBottom, false);
  1680. top.set(mData.mValue.mTop, false);
  1681. width.set(mData.mValue.getWidth(), false);
  1682. height.set(mData.mValue.getHeight(), false);
  1683. }
  1684. TypedParam<LLCoordGL>::TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
  1685. : super_t(descriptor, name, value, func, min_count, max_count),
  1686. x("x"),
  1687. y("y")
  1688. {
  1689. setBlockFromValue();
  1690. }
  1691. void TypedParam<LLCoordGL>::setValueFromBlock() const
  1692. {
  1693. mData.mValue.set(x, y);
  1694. }
  1695. void TypedParam<LLCoordGL>::setBlockFromValue()
  1696. {
  1697. x.set(mData.mValue.mX, false);
  1698. y.set(mData.mValue.mY, false);
  1699. }
  1700. void TypeValues<LLFontGL::HAlign>::declareValues()
  1701. {
  1702. declare("left", LLFontGL::LEFT);
  1703. declare("right", LLFontGL::RIGHT);
  1704. declare("center", LLFontGL::HCENTER);
  1705. }
  1706. void TypeValues<LLFontGL::VAlign>::declareValues()
  1707. {
  1708. declare("top", LLFontGL::TOP);
  1709. declare("center", LLFontGL::VCENTER);
  1710. declare("baseline", LLFontGL::BASELINE);
  1711. declare("bottom", LLFontGL::BOTTOM);
  1712. }
  1713. void TypeValues<LLFontGL::ShadowType>::declareValues()
  1714. {
  1715. declare("none", LLFontGL::NO_SHADOW);
  1716. declare("hard", LLFontGL::DROP_SHADOW);
  1717. declare("soft", LLFontGL::DROP_SHADOW_SOFT);
  1718. }
  1719. }