aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llui/llui.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llui/llui.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llui/llui.cpp')
-rw-r--r--linden/indra/llui/llui.cpp1783
1 files changed, 1783 insertions, 0 deletions
diff --git a/linden/indra/llui/llui.cpp b/linden/indra/llui/llui.cpp
new file mode 100644
index 0000000..c62f353
--- /dev/null
+++ b/linden/indra/llui/llui.cpp
@@ -0,0 +1,1783 @@
1/**
2 * @file llui.cpp
3 * @brief UI implementation
4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28// Utilities functions the user interface needs
29
30//#include "llviewerprecompiledheaders.h"
31#include "linden_common.h"
32
33#include <string>
34#include <map>
35
36// Linden library includes
37#include "audioengine.h"
38#include "v2math.h"
39#include "v4color.h"
40#include "llgl.h"
41#include "llrect.h"
42#include "llimagegl.h"
43//#include "llviewerimage.h"
44#include "lldir.h"
45#include "llfontgl.h"
46
47// Project includes
48//#include "audioengine.h"
49#include "llcontrol.h"
50//#include "llstartup.h"
51#include "llui.h"
52#include "llview.h"
53#include "llwindow.h"
54
55#include "llglheaders.h"
56
57//
58// Globals
59//
60const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f);
61
62// Used to hide the flashing text cursor when window doesn't have focus.
63BOOL gShowTextEditCursor = TRUE;
64
65// Language for UI construction
66LLString gLanguage = "english-usa";
67std::map<LLString, LLString> gTranslation;
68std::list<LLString> gUntranslated;
69
70LLControlGroup* LLUI::sConfigGroup = NULL;
71LLControlGroup* LLUI::sColorsGroup = NULL;
72LLControlGroup* LLUI::sAssetsGroup = NULL;
73LLImageProviderInterface* LLUI::sImageProvider = NULL;
74LLUIAudioCallback LLUI::sAudioCallback = NULL;
75LLVector2 LLUI::sGLScaleFactor(1.f, 1.f);
76LLWindow* LLUI::sWindow = NULL;
77BOOL LLUI::sShowXUINames = FALSE;
78//
79// Functions
80//
81void make_ui_sound(const LLString& name)
82{
83 if (!LLUI::sConfigGroup->controlExists(name))
84 {
85 llwarns << "tried to make ui sound for unknown sound name: " << name << llendl;
86 }
87 else
88 {
89 LLUUID uuid(LLUI::sConfigGroup->getString(name));
90 if (uuid.isNull())
91 {
92 if ("00000000-0000-0000-0000-000000000000" == LLUI::sConfigGroup->getString(name))
93 {
94 if (LLUI::sConfigGroup->getBOOL("UISndDebugSpamToggle"))
95 {
96 llinfos << "ui sound name: " << name << " triggered but silent (null uuid)" << llendl;
97 }
98 }
99 else
100 {
101 llwarns << "ui sound named: " << name << " does not translate to a valid uuid" << llendl;
102 }
103
104 }
105 else if (LLUI::sAudioCallback != NULL)
106 {
107 if (LLUI::sConfigGroup->getBOOL("UISndDebugSpamToggle"))
108 {
109 llinfos << "ui sound name: " << name << llendl;
110 }
111 LLUI::sAudioCallback(uuid, LLUI::sConfigGroup->getF32("AudioLevelUI"));
112 }
113 }
114}
115
116BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom)
117{
118 if (x < left || right < x) return FALSE;
119 if (y < bottom || top < y) return FALSE;
120 return TRUE;
121}
122
123
124// Puts GL into 2D drawing mode by turning off lighting, setting to an
125// orthographic projection, etc.
126void gl_state_for_2d(S32 width, S32 height)
127{
128 stop_glerror();
129 F32 window_width = (F32) width;//gViewerWindow->getWindowWidth();
130 F32 window_height = (F32) height;//gViewerWindow->getWindowHeight();
131
132 glMatrixMode(GL_PROJECTION);
133 glLoadIdentity();
134 glOrtho(0.0f, window_width, 0.0f, window_height, -1.0f, 1.0f);
135 glMatrixMode(GL_MODELVIEW);
136 glLoadIdentity();
137 stop_glerror();
138}
139
140
141void gl_draw_x(const LLRect& rect, const LLColor4& color)
142{
143 LLGLSNoTexture no_texture;
144
145 glColor4fv( color.mV );
146
147 glBegin( GL_LINES );
148 glVertex2i( rect.mLeft, rect.mTop );
149 glVertex2i( rect.mRight, rect.mBottom );
150 glVertex2i( rect.mLeft, rect.mBottom );
151 glVertex2i( rect.mRight, rect.mTop );
152 glEnd();
153}
154
155
156void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset, BOOL filled)
157{
158 glColor4fv(color.mV);
159 gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled);
160}
161
162void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled)
163{
164 glPushMatrix();
165 left += LLFontGL::sCurOrigin.mX;
166 right += LLFontGL::sCurOrigin.mX;
167 bottom += LLFontGL::sCurOrigin.mY;
168 top += LLFontGL::sCurOrigin.mY;
169
170 glLoadIdentity();
171 gl_rect_2d(llfloor((F32)left * LLUI::sGLScaleFactor.mV[VX]) - pixel_offset,
172 llfloor((F32)top * LLUI::sGLScaleFactor.mV[VY]) + pixel_offset,
173 llfloor((F32)right * LLUI::sGLScaleFactor.mV[VX]) + pixel_offset,
174 llfloor((F32)bottom * LLUI::sGLScaleFactor.mV[VY]) - pixel_offset,
175 filled);
176 glPopMatrix();
177}
178
179
180void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
181{
182 stop_glerror();
183 LLGLSNoTexture no_texture;
184
185 // Counterclockwise quad will face the viewer
186 if( filled )
187 {
188 glBegin( GL_QUADS );
189 glVertex2i(left, top);
190 glVertex2i(left, bottom);
191 glVertex2i(right, bottom);
192 glVertex2i(right, top);
193 glEnd();
194 }
195 else
196 {
197 if( gGLManager.mATIOffsetVerticalLines )
198 {
199 // Work around bug in ATI driver: vertical lines are offset by (-1,-1)
200 glBegin( GL_LINES );
201
202 // Verticals
203 glVertex2i(left + 1, top);
204 glVertex2i(left + 1, bottom);
205
206 glVertex2i(right, bottom);
207 glVertex2i(right, top);
208
209 // Horizontals
210 top--;
211 right--;
212 glVertex2i(left, bottom);
213 glVertex2i(right, bottom);
214
215 glVertex2i(left, top);
216 glVertex2i(right, top);
217 glEnd();
218 }
219 else
220 {
221 top--;
222 right--;
223 glBegin( GL_LINE_STRIP );
224 glVertex2i(left, top);
225 glVertex2i(left, bottom);
226 glVertex2i(right, bottom);
227 glVertex2i(right, top);
228 glVertex2i(left, top);
229 glEnd();
230 }
231 }
232 stop_glerror();
233}
234
235void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled )
236{
237 glColor4fv( color.mV );
238 gl_rect_2d( left, top, right, bottom, filled );
239}
240
241
242void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled )
243{
244 glColor4fv( color.mV );
245 gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
246}
247
248// Given a rectangle on the screen, draws a drop shadow _outside_
249// the right and bottom edges of it. Along the right it has width "lines"
250// and along the bottom it has height "lines".
251void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines)
252{
253 stop_glerror();
254 LLGLSNoTexture no_texture;
255
256 // HACK: Overlap with the rectangle by a single pixel.
257 right--;
258 bottom++;
259 lines++;
260
261 LLColor4 end_color = start_color;
262 end_color.mV[VALPHA] = 0.f;
263
264 glBegin(GL_QUADS);
265
266 // Right edge, CCW faces screen
267 glColor4fv(start_color.mV);
268 glVertex2i(right, top-lines);
269 glVertex2i(right, bottom);
270 glColor4fv(end_color.mV);
271 glVertex2i(right+lines, bottom);
272 glVertex2i(right+lines, top-lines);
273
274 // Bottom edge, CCW faces screen
275 glColor4fv(start_color.mV);
276 glVertex2i(right, bottom);
277 glVertex2i(left+lines, bottom);
278 glColor4fv(end_color.mV);
279 glVertex2i(left+lines, bottom-lines);
280 glVertex2i(right, bottom-lines);
281
282 // bottom left Corner
283 glColor4fv(start_color.mV);
284 glVertex2i(left+lines, bottom);
285 glColor4fv(end_color.mV);
286 glVertex2i(left, bottom);
287 // make the bottom left corner not sharp
288 glVertex2i(left+1, bottom-lines+1);
289 glVertex2i(left+lines, bottom-lines);
290
291 // bottom right corner
292 glColor4fv(start_color.mV);
293 glVertex2i(right, bottom);
294 glColor4fv(end_color.mV);
295 glVertex2i(right, bottom-lines);
296 // make the rightmost corner not sharp
297 glVertex2i(right+lines-1, bottom-lines+1);
298 glVertex2i(right+lines, bottom);
299
300 // top right corner
301 glColor4fv(start_color.mV);
302 glVertex2i( right, top-lines );
303 glColor4fv(end_color.mV);
304 glVertex2i( right+lines, top-lines );
305 // make the corner not sharp
306 glVertex2i( right+lines-1, top-1 );
307 glVertex2i( right, top );
308
309 glEnd();
310 stop_glerror();
311}
312
313void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 )
314{
315 // Work around bug in ATI driver: vertical lines are offset by (-1,-1)
316 if( gGLManager.mATIOffsetVerticalLines && (x1 == x2) )
317 {
318 x1++;
319 x2++;
320 y1++;
321 y2++;
322 }
323
324 LLGLSNoTexture no_texture;
325
326 glBegin(GL_LINES);
327 glVertex2i(x1, y1);
328 glVertex2i(x2, y2);
329 glEnd();
330}
331
332void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color )
333{
334 // Work around bug in ATI driver: vertical lines are offset by (-1,-1)
335 if( gGLManager.mATIOffsetVerticalLines && (x1 == x2) )
336 {
337 x1++;
338 x2++;
339 y1++;
340 y2++;
341 }
342
343 LLGLSNoTexture no_texture;
344
345 glColor4fv( color.mV );
346
347 glBegin(GL_LINES);
348 glVertex2i(x1, y1);
349 glVertex2i(x2, y2);
350 glEnd();
351}
352
353void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled)
354{
355 LLGLSNoTexture no_texture;
356
357 glColor4fv(color.mV);
358
359 if (filled)
360 {
361 glBegin(GL_TRIANGLES);
362 }
363 else
364 {
365 glBegin(GL_LINE_LOOP);
366 }
367 glVertex2i(x1, y1);
368 glVertex2i(x2, y2);
369 glVertex2i(x3, y3);
370 glEnd();
371}
372
373void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac)
374{
375 LLGLSNoTexture no_texture;
376
377 length = llmin((S32)(max_frac*(right - left)), length);
378 length = llmin((S32)(max_frac*(top - bottom)), length);
379 glBegin(GL_LINES);
380 glVertex2i(left, top);
381 glVertex2i(left + length, top);
382
383 glVertex2i(left, top);
384 glVertex2i(left, top - length);
385
386 glVertex2i(left, bottom);
387 glVertex2i(left + length, bottom);
388
389 glVertex2i(left, bottom);
390 glVertex2i(left, bottom + length);
391
392 glVertex2i(right, top);
393 glVertex2i(right - length, top);
394
395 glVertex2i(right, top);
396 glVertex2i(right, top - length);
397
398 glVertex2i(right, bottom);
399 glVertex2i(right - length, bottom);
400
401 glVertex2i(right, bottom);
402 glVertex2i(right, bottom + length);
403 glEnd();
404}
405
406
407void gl_draw_image( S32 x, S32 y, LLImageGL* image, const LLColor4& color )
408{
409 gl_draw_scaled_rotated_image( x, y, image->getWidth(), image->getHeight(), 0.f, image, color );
410}
411
412void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color)
413{
414 gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color );
415}
416
417void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLImageGL* image, const LLColor4& color, BOOL solid_color)
418{
419 stop_glerror();
420 F32 border_scale = 1.f;
421
422 if (border_height * 2 > height)
423 {
424 border_scale = (F32)height / ((F32)border_height * 2.f);
425 }
426 if (border_width * 2 > width)
427 {
428 border_scale = llmin(border_scale, (F32)width / ((F32)border_width * 2.f));
429 }
430
431 // scale screen size of borders down
432 S32 scaled_border_width = llfloor(border_scale * (F32)border_width);
433 S32 scaled_border_height = llfloor(border_scale * (F32)border_height);
434
435 LLGLSUIDefault gls_ui;
436
437 if (solid_color)
438 {
439 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
440 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
441 glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE);
442
443 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
444 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
445
446 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
447 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
448
449 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB);
450 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA);
451 }
452
453 glPushMatrix();
454 {
455 glTranslatef((F32)x, (F32)y, 0.f);
456
457 image->bind();
458
459 glColor4fv(color.mV);
460
461 F32 border_width_fraction = (F32)border_width / (F32)image->getWidth();
462 F32 border_height_fraction = (F32)border_height / (F32)image->getHeight();
463
464 glBegin(GL_QUADS);
465 {
466 // draw bottom left
467 glTexCoord2f(0.f, 0.f);
468 glVertex2i(0, 0);
469
470 glTexCoord2f(border_width_fraction, 0.f);
471 glVertex2i(scaled_border_width, 0);
472
473 glTexCoord2f(border_width_fraction, border_height_fraction);
474 glVertex2i(scaled_border_width, scaled_border_height);
475
476 glTexCoord2f(0.f, border_height_fraction);
477 glVertex2i(0, scaled_border_height);
478
479 // draw bottom middle
480 glTexCoord2f(border_width_fraction, 0.f);
481 glVertex2i(scaled_border_width, 0);
482
483 glTexCoord2f(1.f - border_width_fraction, 0.f);
484 glVertex2i(width - scaled_border_width, 0);
485
486 glTexCoord2f(1.f - border_width_fraction, border_height_fraction);
487 glVertex2i(width - scaled_border_width, scaled_border_height);
488
489 glTexCoord2f(border_width_fraction, border_height_fraction);
490 glVertex2i(scaled_border_width, scaled_border_height);
491
492 // draw bottom right
493 glTexCoord2f(1.f - border_width_fraction, 0.f);
494 glVertex2i(width - scaled_border_width, 0);
495
496 glTexCoord2f(1.f, 0.f);
497 glVertex2i(width, 0);
498
499 glTexCoord2f(1.f, border_height_fraction);
500 glVertex2i(width, scaled_border_height);
501
502 glTexCoord2f(1.f - border_width_fraction, border_height_fraction);
503 glVertex2i(width - scaled_border_width, scaled_border_height);
504
505 // draw left
506 glTexCoord2f(0.f, border_height_fraction);
507 glVertex2i(0, scaled_border_height);
508
509 glTexCoord2f(border_width_fraction, border_height_fraction);
510 glVertex2i(scaled_border_width, scaled_border_height);
511
512 glTexCoord2f(border_width_fraction, 1.f - border_height_fraction);
513 glVertex2i(scaled_border_width, height - scaled_border_height);
514
515 glTexCoord2f(0.f, 1.f - border_height_fraction);
516 glVertex2i(0, height - scaled_border_height);
517
518 // draw middle
519 glTexCoord2f(border_width_fraction, border_height_fraction);
520 glVertex2i(scaled_border_width, scaled_border_height);
521
522 glTexCoord2f(1.f - border_width_fraction, border_height_fraction);
523 glVertex2i(width - scaled_border_width, scaled_border_height);
524
525 glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction);
526 glVertex2i(width - scaled_border_width, height - scaled_border_height);
527
528 glTexCoord2f(border_width_fraction, 1.f - border_height_fraction);
529 glVertex2i(scaled_border_width, height - scaled_border_height);
530
531 // draw right
532 glTexCoord2f(1.f - border_width_fraction, border_height_fraction);
533 glVertex2i(width - scaled_border_width, scaled_border_height);
534
535 glTexCoord2f(1.f, border_height_fraction);
536 glVertex2i(width, scaled_border_height);
537
538 glTexCoord2f(1.f, 1.f - border_height_fraction);
539 glVertex2i(width, height - scaled_border_height);
540
541 glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction);
542 glVertex2i(width - scaled_border_width, height - scaled_border_height);
543
544 // draw top left
545 glTexCoord2f(0.f, 1.f - border_height_fraction);
546 glVertex2i(0, height - scaled_border_height);
547
548 glTexCoord2f(border_width_fraction, 1.f - border_height_fraction);
549 glVertex2i(scaled_border_width, height - scaled_border_height);
550
551 glTexCoord2f(border_width_fraction, 1.f);
552 glVertex2i(scaled_border_width, height);
553
554 glTexCoord2f(0.f, 1.f);
555 glVertex2i(0, height);
556
557 // draw top middle
558 glTexCoord2f(border_width_fraction, 1.f - border_height_fraction);
559 glVertex2i(scaled_border_width, height - scaled_border_height);
560
561 glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction);
562 glVertex2i(width - scaled_border_width, height - scaled_border_height);
563
564 glTexCoord2f(1.f - border_width_fraction, 1.f);
565 glVertex2i(width - scaled_border_width, height);
566
567 glTexCoord2f(border_width_fraction, 1.f);
568 glVertex2i(scaled_border_width, height);
569
570 // draw top right
571 glTexCoord2f(1.f - border_width_fraction, 1.f - border_height_fraction);
572 glVertex2i(width - scaled_border_width, height - scaled_border_height);
573
574 glTexCoord2f(1.f, 1.f - border_height_fraction);
575 glVertex2i(width, height - scaled_border_height);
576
577 glTexCoord2f(1.f, 1.f);
578 glVertex2i(width, height);
579
580 glTexCoord2f(1.f - border_width_fraction, 1.f);
581 glVertex2i(width - scaled_border_width, height);
582 }
583 glEnd();
584 }
585 glPopMatrix();
586
587 if (solid_color)
588 {
589 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
590 }
591}
592
593void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLImageGL* image, const LLColor4& color)
594{
595 gl_draw_scaled_rotated_image( x, y, image->getWidth(), image->getHeight(), degrees, image, color );
596}
597
598void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLImageGL* image, const LLColor4& color)
599{
600 LLGLSUIDefault gls_ui;
601
602 glPushMatrix();
603 {
604 glTranslatef((F32)x, (F32)y, 0.f);
605 if( degrees )
606 {
607 F32 offset_x = F32(width/2);
608 F32 offset_y = F32(height/2);
609 glTranslatef( offset_x, offset_y, 0.f);
610 glRotatef( degrees, 0.f, 0.f, 1.f );
611 glTranslatef( -offset_x, -offset_y, 0.f );
612 }
613
614 image->bind();
615
616 glColor4fv(color.mV);
617
618 glBegin(GL_QUADS);
619 {
620 glTexCoord2f(1.f, 1.f);
621 glVertex2i(width, height );
622
623 glTexCoord2f(0.f, 1.f);
624 glVertex2i(0, height );
625
626 glTexCoord2f(0.f, 0.f);
627 glVertex2i(0, 0);
628
629 glTexCoord2f(1.f, 0.f);
630 glVertex2i(width, 0);
631 }
632 glEnd();
633 }
634 glPopMatrix();
635}
636
637
638void gl_draw_scaled_image_inverted(S32 x, S32 y, S32 width, S32 height, LLImageGL* image, const LLColor4& color)
639{
640 LLGLSUIDefault gls_ui;
641
642 glPushMatrix();
643 {
644 glTranslatef((F32)x, (F32)y, 0.f);
645
646 image->bind();
647
648 glColor4fv(color.mV);
649
650 glBegin(GL_QUADS);
651 {
652 glTexCoord2f(1.f, 0.f);
653 glVertex2i(width, height );
654
655 glTexCoord2f(0.f, 0.f);
656 glVertex2i(0, height );
657
658 glTexCoord2f(0.f, 1.f);
659 glVertex2i(0, 0);
660
661 glTexCoord2f(1.f, 1.f);
662 glVertex2i(width, 0);
663 }
664 glEnd();
665 }
666 glPopMatrix();
667}
668
669
670void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase )
671{
672 phase = fmod(phase, 1.f);
673
674 S32 shift = S32(phase * 4.f) % 4;
675
676 // Stippled line
677 LLGLEnable stipple(GL_LINE_STIPPLE);
678
679 glColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]);
680 glLineWidth(2.5f);
681 glLineStipple(2, 0x3333 << shift);
682
683 glBegin(GL_LINES);
684 {
685 glVertex3fv( start.mV );
686 glVertex3fv( end.mV );
687 }
688 glEnd();
689
690 LLUI::setLineWidth(1.f);
691}
692
693
694void gl_rect_2d_xor(S32 left, S32 top, S32 right, S32 bottom)
695{
696 glColor4fv( LLColor4::white.mV );
697 glLogicOp( GL_XOR );
698 stop_glerror();
699
700 glBegin(GL_QUADS);
701 glVertex2i(left, top);
702 glVertex2i(left, bottom);
703 glVertex2i(right, bottom);
704 glVertex2i(right, top);
705 glEnd();
706
707 glLogicOp( GL_COPY );
708 stop_glerror();
709}
710
711
712void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle)
713{
714 if (end_angle < start_angle)
715 {
716 end_angle += F_TWO_PI;
717 }
718
719 glPushMatrix();
720 {
721 glTranslatef(center_x, center_y, 0.f);
722
723 // Inexact, but reasonably fast.
724 F32 delta = (end_angle - start_angle) / steps;
725 F32 sin_delta = sin( delta );
726 F32 cos_delta = cos( delta );
727 F32 x = cosf(start_angle) * radius;
728 F32 y = sinf(start_angle) * radius;
729
730 if (filled)
731 {
732 glBegin(GL_TRIANGLE_FAN);
733 glVertex2f(0.f, 0.f);
734 // make sure circle is complete
735 steps += 1;
736 }
737 else
738 {
739 glBegin(GL_LINE_STRIP);
740 }
741
742 while( steps-- )
743 {
744 // Successive rotations
745 glVertex2f( x, y );
746 F32 x_new = x * cos_delta - y * sin_delta;
747 y = x * sin_delta + y * cos_delta;
748 x = x_new;
749 }
750 glEnd();
751 }
752 glPopMatrix();
753}
754
755void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled)
756{
757 glPushMatrix();
758 {
759 LLGLSNoTexture gls_no_texture;
760 glTranslatef(center_x, center_y, 0.f);
761
762 // Inexact, but reasonably fast.
763 F32 delta = F_TWO_PI / steps;
764 F32 sin_delta = sin( delta );
765 F32 cos_delta = cos( delta );
766 F32 x = radius;
767 F32 y = 0.f;
768
769 if (filled)
770 {
771 glBegin(GL_TRIANGLE_FAN);
772 glVertex2f(0.f, 0.f);
773 // make sure circle is complete
774 steps += 1;
775 }
776 else
777 {
778 glBegin(GL_LINE_LOOP);
779 }
780
781 while( steps-- )
782 {
783 // Successive rotations
784 glVertex2f( x, y );
785 F32 x_new = x * cos_delta - y * sin_delta;
786 y = x * sin_delta + y * cos_delta;
787 x = x_new;
788 }
789 glEnd();
790 }
791 glPopMatrix();
792}
793
794// Renders a ring with sides (tube shape)
795void gl_deep_circle( F32 radius, F32 depth, S32 steps )
796{
797 F32 x = radius;
798 F32 y = 0.f;
799 F32 angle_delta = F_TWO_PI / (F32)steps;
800 glBegin( GL_TRIANGLE_STRIP );
801 {
802 S32 step = steps + 1; // An extra step to close the circle.
803 while( step-- )
804 {
805 glVertex3f( x, y, depth );
806 glVertex3f( x, y, 0.f );
807
808 F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta);
809 y = x * sinf(angle_delta) + y * cosf(angle_delta);
810 x = x_new;
811 }
812 }
813 glEnd();
814}
815
816void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center )
817{
818 glPushMatrix();
819 {
820 glTranslatef(0.f, 0.f, -width / 2);
821 if( render_center )
822 {
823 glColor4fv(center_color.mV);
824 gl_deep_circle( radius, width, steps );
825 }
826 else
827 {
828 gl_washer_2d(radius, radius - width, steps, side_color, side_color);
829 glTranslatef(0.f, 0.f, width);
830 gl_washer_2d(radius - width, radius, steps, side_color, side_color);
831 }
832 }
833 glPopMatrix();
834}
835
836// Draw gray and white checkerboard with black border
837void gl_rect_2d_checkerboard(const LLRect& rect)
838{
839 // Initialize the first time this is called.
840 const S32 PIXELS = 32;
841 static GLubyte checkerboard[PIXELS * PIXELS];
842 static BOOL first = TRUE;
843 if( first )
844 {
845 for( S32 i = 0; i < PIXELS; i++ )
846 {
847 for( S32 j = 0; j < PIXELS; j++ )
848 {
849 checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF;
850 }
851 }
852 first = FALSE;
853 }
854
855 LLGLSNoTexture gls_no_texture;
856
857 // ...white squares
858 glColor3f( 1.f, 1.f, 1.f );
859 gl_rect_2d(rect);
860
861 // ...gray squares
862 glColor3f( .7f, .7f, .7f );
863 glPolygonStipple( checkerboard );
864
865 LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE);
866 gl_rect_2d(rect);
867}
868
869
870// Draws the area between two concentric circles, like
871// a doughnut or washer.
872void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color)
873{
874 const F32 DELTA = F_TWO_PI / steps;
875 const F32 SIN_DELTA = sin( DELTA );
876 const F32 COS_DELTA = cos( DELTA );
877
878 F32 x1 = outer_radius;
879 F32 y1 = 0.f;
880 F32 x2 = inner_radius;
881 F32 y2 = 0.f;
882
883 LLGLSNoTexture gls_no_texture;
884
885 glBegin( GL_TRIANGLE_STRIP );
886 {
887 steps += 1; // An extra step to close the circle.
888 while( steps-- )
889 {
890 glColor4fv(outer_color.mV);
891 glVertex2f( x1, y1 );
892 glColor4fv(inner_color.mV);
893 glVertex2f( x2, y2 );
894
895 F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
896 y1 = x1 * SIN_DELTA + y1 * COS_DELTA;
897 x1 = x1_new;
898
899 F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
900 y2 = x2 * SIN_DELTA + y2 * COS_DELTA;
901 x2 = x2_new;
902 }
903 }
904 glEnd();
905}
906
907// Draws the area between two concentric circles, like
908// a doughnut or washer.
909void 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)
910{
911 const F32 DELTA = (end_radians - start_radians) / steps;
912 const F32 SIN_DELTA = sin( DELTA );
913 const F32 COS_DELTA = cos( DELTA );
914
915 F32 x1 = outer_radius * cos( start_radians );
916 F32 y1 = outer_radius * sin( start_radians );
917 F32 x2 = inner_radius * cos( start_radians );
918 F32 y2 = inner_radius * sin( start_radians );
919
920 LLGLSNoTexture gls_no_texture;
921 glBegin( GL_TRIANGLE_STRIP );
922 {
923 steps += 1; // An extra step to close the circle.
924 while( steps-- )
925 {
926 glColor4fv(outer_color.mV);
927 glVertex2f( x1, y1 );
928 glColor4fv(inner_color.mV);
929 glVertex2f( x2, y2 );
930
931 F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
932 y1 = x1 * SIN_DELTA + y1 * COS_DELTA;
933 x1 = x1_new;
934
935 F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
936 y2 = x2 * SIN_DELTA + y2 * COS_DELTA;
937 x2 = x2_new;
938 }
939 }
940 glEnd();
941}
942
943// Draws spokes around a circle.
944void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color)
945{
946 const F32 DELTA = F_TWO_PI / count;
947 const F32 HALF_DELTA = DELTA * 0.5f;
948 const F32 SIN_DELTA = sin( DELTA );
949 const F32 COS_DELTA = cos( DELTA );
950
951 F32 x1 = outer_radius * cos( HALF_DELTA );
952 F32 y1 = outer_radius * sin( HALF_DELTA );
953 F32 x2 = inner_radius * cos( HALF_DELTA );
954 F32 y2 = inner_radius * sin( HALF_DELTA );
955
956 LLGLSNoTexture gls_no_texture;
957
958 glBegin( GL_LINES );
959 {
960 while( count-- )
961 {
962 glColor4fv(outer_color.mV);
963 glVertex2f( x1, y1 );
964 glColor4fv(inner_color.mV);
965 glVertex2f( x2, y2 );
966
967 F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
968 y1 = x1 * SIN_DELTA + y1 * COS_DELTA;
969 x1 = x1_new;
970
971 F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
972 y2 = x2 * SIN_DELTA + y2 * COS_DELTA;
973 x2 = x2_new;
974 }
975 }
976 glEnd();
977}
978
979void gl_rect_2d_simple_tex( S32 width, S32 height )
980{
981 glBegin( GL_QUADS );
982
983 glTexCoord2f(1.f, 1.f);
984 glVertex2i(width, height);
985
986 glTexCoord2f(0.f, 1.f);
987 glVertex2i(0, height);
988
989 glTexCoord2f(0.f, 0.f);
990 glVertex2i(0, 0);
991
992 glTexCoord2f(1.f, 0.f);
993 glVertex2i(width, 0);
994
995 glEnd();
996}
997
998void gl_rect_2d_simple( S32 width, S32 height )
999{
1000 glBegin( GL_QUADS );
1001 glVertex2i(width, height);
1002 glVertex2i(0, height);
1003 glVertex2i(0, 0);
1004 glVertex2i(width, 0);
1005 glEnd();
1006}
1007
1008void gl_segmented_rect_2d_tex(const S32 left,
1009 const S32 top,
1010 const S32 right,
1011 const S32 bottom,
1012 const S32 texture_width,
1013 const S32 texture_height,
1014 const S32 border_size,
1015 const U32 edges)
1016{
1017 S32 width = llabs(right - left);
1018 S32 height = llabs(top - bottom);
1019
1020 glPushMatrix();
1021
1022 glTranslatef((F32)left, (F32)bottom, 0.f);
1023 LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
1024
1025 if (border_uv_scale.mV[VX] > 0.5f)
1026 {
1027 border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
1028 }
1029 if (border_uv_scale.mV[VY] > 0.5f)
1030 {
1031 border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
1032 }
1033
1034 F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
1035 LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
1036 LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
1037 LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
1038 LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
1039 LLVector2 width_vec((F32)width, 0.f);
1040 LLVector2 height_vec(0.f, (F32)height);
1041
1042 glBegin(GL_QUADS);
1043 {
1044 // draw bottom left
1045 glTexCoord2f(0.f, 0.f);
1046 glVertex2f(0.f, 0.f);
1047
1048 glTexCoord2f(border_uv_scale.mV[VX], 0.f);
1049 glVertex2fv(border_width_left.mV);
1050
1051 glTexCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1052 glVertex2fv((border_width_left + border_height_bottom).mV);
1053
1054 glTexCoord2f(0.f, border_uv_scale.mV[VY]);
1055 glVertex2fv(border_height_bottom.mV);
1056
1057 // draw bottom middle
1058 glTexCoord2f(border_uv_scale.mV[VX], 0.f);
1059 glVertex2fv(border_width_left.mV);
1060
1061 glTexCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
1062 glVertex2fv((width_vec - border_width_right).mV);
1063
1064 glTexCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1065 glVertex2fv((width_vec - border_width_right + border_height_bottom).mV);
1066
1067 glTexCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1068 glVertex2fv((border_width_left + border_height_bottom).mV);
1069
1070 // draw bottom right
1071 glTexCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
1072 glVertex2fv((width_vec - border_width_right).mV);
1073
1074 glTexCoord2f(1.f, 0.f);
1075 glVertex2fv(width_vec.mV);
1076
1077 glTexCoord2f(1.f, border_uv_scale.mV[VY]);
1078 glVertex2fv((width_vec + border_height_bottom).mV);
1079
1080 glTexCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1081 glVertex2fv((width_vec - border_width_right + border_height_bottom).mV);
1082
1083 // draw left
1084 glTexCoord2f(0.f, border_uv_scale.mV[VY]);
1085 glVertex2fv(border_height_bottom.mV);
1086
1087 glTexCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1088 glVertex2fv((border_width_left + border_height_bottom).mV);
1089
1090 glTexCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1091 glVertex2fv((border_width_left + height_vec - border_height_top).mV);
1092
1093 glTexCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
1094 glVertex2fv((height_vec - border_height_top).mV);
1095
1096 // draw middle
1097 glTexCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1098 glVertex2fv((border_width_left + border_height_bottom).mV);
1099
1100 glTexCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1101 glVertex2fv((width_vec - border_width_right + border_height_bottom).mV);
1102
1103 glTexCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1104 glVertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
1105
1106 glTexCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1107 glVertex2fv((border_width_left + height_vec - border_height_top).mV);
1108
1109 // draw right
1110 glTexCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1111 glVertex2fv((width_vec - border_width_right + border_height_bottom).mV);
1112
1113 glTexCoord2f(1.f, border_uv_scale.mV[VY]);
1114 glVertex2fv((width_vec + border_height_bottom).mV);
1115
1116 glTexCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
1117 glVertex2fv((width_vec + height_vec - border_height_top).mV);
1118
1119 glTexCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1120 glVertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
1121
1122 // draw top left
1123 glTexCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
1124 glVertex2fv((height_vec - border_height_top).mV);
1125
1126 glTexCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1127 glVertex2fv((border_width_left + height_vec - border_height_top).mV);
1128
1129 glTexCoord2f(border_uv_scale.mV[VX], 1.f);
1130 glVertex2fv((border_width_left + height_vec).mV);
1131
1132 glTexCoord2f(0.f, 1.f);
1133 glVertex2fv((height_vec).mV);
1134
1135 // draw top middle
1136 glTexCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1137 glVertex2fv((border_width_left + height_vec - border_height_top).mV);
1138
1139 glTexCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1140 glVertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
1141
1142 glTexCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
1143 glVertex2fv((width_vec - border_width_right + height_vec).mV);
1144
1145 glTexCoord2f(border_uv_scale.mV[VX], 1.f);
1146 glVertex2fv((border_width_left + height_vec).mV);
1147
1148 // draw top right
1149 glTexCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1150 glVertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
1151
1152 glTexCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
1153 glVertex2fv((width_vec + height_vec - border_height_top).mV);
1154
1155 glTexCoord2f(1.f, 1.f);
1156 glVertex2fv((width_vec + height_vec).mV);
1157
1158 glTexCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
1159 glVertex2fv((width_vec - border_width_right + height_vec).mV);
1160 }
1161 glEnd();
1162
1163 glPopMatrix();
1164}
1165
1166void gl_segmented_rect_2d_fragment_tex(const S32 left,
1167 const S32 top,
1168 const S32 right,
1169 const S32 bottom,
1170 const S32 texture_width,
1171 const S32 texture_height,
1172 const S32 border_size,
1173 const F32 start_fragment,
1174 const F32 end_fragment,
1175 const U32 edges)
1176{
1177 S32 width = llabs(right - left);
1178 S32 height = llabs(top - bottom);
1179
1180 glPushMatrix();
1181
1182 glTranslatef((F32)left, (F32)bottom, 0.f);
1183 LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
1184
1185 if (border_uv_scale.mV[VX] > 0.5f)
1186 {
1187 border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
1188 }
1189 if (border_uv_scale.mV[VY] > 0.5f)
1190 {
1191 border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
1192 }
1193
1194 F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
1195 LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
1196 LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
1197 LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
1198 LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
1199 LLVector2 width_vec((F32)width, 0.f);
1200 LLVector2 height_vec(0.f, (F32)height);
1201
1202 F32 middle_start = border_scale / (F32)width;
1203 F32 middle_end = 1.f - middle_start;
1204
1205 F32 u_min;
1206 F32 u_max;
1207 LLVector2 x_min;
1208 LLVector2 x_max;
1209
1210 glBegin(GL_QUADS);
1211 {
1212 if (start_fragment < middle_start)
1213 {
1214 u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX];
1215 u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX];
1216 x_min = (start_fragment / middle_start) * border_width_left;
1217 x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left;
1218
1219 // draw bottom left
1220 glTexCoord2f(u_min, 0.f);
1221 glVertex2fv(x_min.mV);
1222
1223 glTexCoord2f(border_uv_scale.mV[VX], 0.f);
1224 glVertex2fv(x_max.mV);
1225
1226 glTexCoord2f(u_max, border_uv_scale.mV[VY]);
1227 glVertex2fv((x_max + border_height_bottom).mV);
1228
1229 glTexCoord2f(u_min, border_uv_scale.mV[VY]);
1230 glVertex2fv((x_min + border_height_bottom).mV);
1231
1232 // draw left
1233 glTexCoord2f(u_min, border_uv_scale.mV[VY]);
1234 glVertex2fv((x_min + border_height_bottom).mV);
1235
1236 glTexCoord2f(u_max, border_uv_scale.mV[VY]);
1237 glVertex2fv((x_max + border_height_bottom).mV);
1238
1239 glTexCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
1240 glVertex2fv((x_max + height_vec - border_height_top).mV);
1241
1242 glTexCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
1243 glVertex2fv((x_min + height_vec - border_height_top).mV);
1244
1245 // draw top left
1246 glTexCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
1247 glVertex2fv((x_min + height_vec - border_height_top).mV);
1248
1249 glTexCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
1250 glVertex2fv((x_max + height_vec - border_height_top).mV);
1251
1252 glTexCoord2f(u_max, 1.f);
1253 glVertex2fv((x_max + height_vec).mV);
1254
1255 glTexCoord2f(u_min, 1.f);
1256 glVertex2fv((x_min + height_vec).mV);
1257 }
1258
1259 if (end_fragment > middle_start || start_fragment < middle_end)
1260 {
1261 x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec;
1262 x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec;
1263
1264 // draw bottom middle
1265 glTexCoord2f(border_uv_scale.mV[VX], 0.f);
1266 glVertex2fv(x_min.mV);
1267
1268 glTexCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
1269 glVertex2fv((x_max).mV);
1270
1271 glTexCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1272 glVertex2fv((x_max + border_height_bottom).mV);
1273
1274 glTexCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1275 glVertex2fv((x_min + border_height_bottom).mV);
1276
1277 // draw middle
1278 glTexCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1279 glVertex2fv((x_min + border_height_bottom).mV);
1280
1281 glTexCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
1282 glVertex2fv((x_max + border_height_bottom).mV);
1283
1284 glTexCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1285 glVertex2fv((x_max + height_vec - border_height_top).mV);
1286
1287 glTexCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1288 glVertex2fv((x_min + height_vec - border_height_top).mV);
1289
1290 // draw top middle
1291 glTexCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1292 glVertex2fv((x_min + height_vec - border_height_top).mV);
1293
1294 glTexCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
1295 glVertex2fv((x_max + height_vec - border_height_top).mV);
1296
1297 glTexCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
1298 glVertex2fv((x_max + height_vec).mV);
1299
1300 glTexCoord2f(border_uv_scale.mV[VX], 1.f);
1301 glVertex2fv((x_min + height_vec).mV);
1302 }
1303
1304 if (end_fragment > middle_end)
1305 {
1306 u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX];
1307 u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX];
1308 x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right);
1309 x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right);
1310
1311 // draw bottom right
1312 glTexCoord2f(u_min, 0.f);
1313 glVertex2fv((x_min).mV);
1314
1315 glTexCoord2f(u_max, 0.f);
1316 glVertex2fv(x_max.mV);
1317
1318 glTexCoord2f(u_max, border_uv_scale.mV[VY]);
1319 glVertex2fv((x_max + border_height_bottom).mV);
1320
1321 glTexCoord2f(u_min, border_uv_scale.mV[VY]);
1322 glVertex2fv((x_min + border_height_bottom).mV);
1323
1324 // draw right
1325 glTexCoord2f(u_min, border_uv_scale.mV[VY]);
1326 glVertex2fv((x_min + border_height_bottom).mV);
1327
1328 glTexCoord2f(u_max, border_uv_scale.mV[VY]);
1329 glVertex2fv((x_max + border_height_bottom).mV);
1330
1331 glTexCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
1332 glVertex2fv((x_max + height_vec - border_height_top).mV);
1333
1334 glTexCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
1335 glVertex2fv((x_min + height_vec - border_height_top).mV);
1336
1337 // draw top right
1338 glTexCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
1339 glVertex2fv((x_min + height_vec - border_height_top).mV);
1340
1341 glTexCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
1342 glVertex2fv((x_max + height_vec - border_height_top).mV);
1343
1344 glTexCoord2f(u_max, 1.f);
1345 glVertex2fv((x_max + height_vec).mV);
1346
1347 glTexCoord2f(u_min, 1.f);
1348 glVertex2fv((x_min + height_vec).mV);
1349 }
1350 }
1351 glEnd();
1352
1353 glPopMatrix();
1354}
1355
1356void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width,
1357 const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec,
1358 const U32 edges)
1359{
1360 LLVector3 left_border_width = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? border_width : LLVector3::zero;
1361 LLVector3 right_border_width = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? border_width : LLVector3::zero;
1362
1363 LLVector3 top_border_height = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? border_height : LLVector3::zero;
1364 LLVector3 bottom_border_height = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? border_height : LLVector3::zero;
1365
1366 glBegin(GL_QUADS);
1367 {
1368 // draw bottom left
1369 glTexCoord2f(0.f, 0.f);
1370 glVertex3f(0.f, 0.f, 0.f);
1371
1372 glTexCoord2f(border_scale.mV[VX], 0.f);
1373 glVertex3fv(left_border_width.mV);
1374
1375 glTexCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
1376 glVertex3fv((left_border_width + bottom_border_height).mV);
1377
1378 glTexCoord2f(0.f, border_scale.mV[VY]);
1379 glVertex3fv(bottom_border_height.mV);
1380
1381 // draw bottom middle
1382 glTexCoord2f(border_scale.mV[VX], 0.f);
1383 glVertex3fv(left_border_width.mV);
1384
1385 glTexCoord2f(1.f - border_scale.mV[VX], 0.f);
1386 glVertex3fv((width_vec - right_border_width).mV);
1387
1388 glTexCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
1389 glVertex3fv((width_vec - right_border_width + bottom_border_height).mV);
1390
1391 glTexCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
1392 glVertex3fv((left_border_width + bottom_border_height).mV);
1393
1394 // draw bottom right
1395 glTexCoord2f(1.f - border_scale.mV[VX], 0.f);
1396 glVertex3fv((width_vec - right_border_width).mV);
1397
1398 glTexCoord2f(1.f, 0.f);
1399 glVertex3fv(width_vec.mV);
1400
1401 glTexCoord2f(1.f, border_scale.mV[VY]);
1402 glVertex3fv((width_vec + bottom_border_height).mV);
1403
1404 glTexCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
1405 glVertex3fv((width_vec - right_border_width + bottom_border_height).mV);
1406
1407 // draw left
1408 glTexCoord2f(0.f, border_scale.mV[VY]);
1409 glVertex3fv(bottom_border_height.mV);
1410
1411 glTexCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
1412 glVertex3fv((left_border_width + bottom_border_height).mV);
1413
1414 glTexCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
1415 glVertex3fv((left_border_width + height_vec - top_border_height).mV);
1416
1417 glTexCoord2f(0.f, 1.f - border_scale.mV[VY]);
1418 glVertex3fv((height_vec - top_border_height).mV);
1419
1420 // draw middle
1421 glTexCoord2f(border_scale.mV[VX], border_scale.mV[VY]);
1422 glVertex3fv((left_border_width + bottom_border_height).mV);
1423
1424 glTexCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
1425 glVertex3fv((width_vec - right_border_width + bottom_border_height).mV);
1426
1427 glTexCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
1428 glVertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
1429
1430 glTexCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
1431 glVertex3fv((left_border_width + height_vec - top_border_height).mV);
1432
1433 // draw right
1434 glTexCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]);
1435 glVertex3fv((width_vec - right_border_width + bottom_border_height).mV);
1436
1437 glTexCoord2f(1.f, border_scale.mV[VY]);
1438 glVertex3fv((width_vec + bottom_border_height).mV);
1439
1440 glTexCoord2f(1.f, 1.f - border_scale.mV[VY]);
1441 glVertex3fv((width_vec + height_vec - top_border_height).mV);
1442
1443 glTexCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
1444 glVertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
1445
1446 // draw top left
1447 glTexCoord2f(0.f, 1.f - border_scale.mV[VY]);
1448 glVertex3fv((height_vec - top_border_height).mV);
1449
1450 glTexCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
1451 glVertex3fv((left_border_width + height_vec - top_border_height).mV);
1452
1453 glTexCoord2f(border_scale.mV[VX], 1.f);
1454 glVertex3fv((left_border_width + height_vec).mV);
1455
1456 glTexCoord2f(0.f, 1.f);
1457 glVertex3fv((height_vec).mV);
1458
1459 // draw top middle
1460 glTexCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]);
1461 glVertex3fv((left_border_width + height_vec - top_border_height).mV);
1462
1463 glTexCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
1464 glVertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
1465
1466 glTexCoord2f(1.f - border_scale.mV[VX], 1.f);
1467 glVertex3fv((width_vec - right_border_width + height_vec).mV);
1468
1469 glTexCoord2f(border_scale.mV[VX], 1.f);
1470 glVertex3fv((left_border_width + height_vec).mV);
1471
1472 // draw top right
1473 glTexCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]);
1474 glVertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV);
1475
1476 glTexCoord2f(1.f, 1.f - border_scale.mV[VY]);
1477 glVertex3fv((width_vec + height_vec - top_border_height).mV);
1478
1479 glTexCoord2f(1.f, 1.f);
1480 glVertex3fv((width_vec + height_vec).mV);
1481
1482 glTexCoord2f(1.f - border_scale.mV[VX], 1.f);
1483 glVertex3fv((width_vec - right_border_width + height_vec).mV);
1484 }
1485 glEnd();
1486}
1487
1488void 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)
1489{
1490 gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP);
1491}
1492
1493#if 0 // No longer used
1494void load_tr(const LLString& lang)
1495{
1496 LLString inname = "words." + lang + ".txt";
1497 LLString filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, inname.c_str());
1498
1499 llifstream file;
1500 file.open(filename.c_str(), std::ios_base::binary);
1501 if (!file)
1502 {
1503 llinfos << "No translation dictionary for: " << filename << llendl;
1504 return;
1505 }
1506
1507 llinfos << "Reading language translation dictionary: " << filename << llendl;
1508
1509 gTranslation.clear();
1510 gUntranslated.clear();
1511
1512 const S32 MAX_LINE_LEN = 1024;
1513 char buffer[MAX_LINE_LEN];
1514 while (!file.eof())
1515 {
1516 file.getline(buffer, MAX_LINE_LEN);
1517 LLString line(buffer);
1518 S32 commentpos = line.find("//");
1519 if (commentpos != LLString::npos)
1520 {
1521 line = line.substr(0, commentpos);
1522 }
1523 S32 offset = line.find('\t');
1524 if (offset != LLString::npos)
1525 {
1526 LLString english = line.substr(0,offset);
1527 LLString translation = line.substr(offset+1);
1528 //llinfos << "TR: " << english << " = " << translation << llendl;
1529 gTranslation[english] = translation;
1530 }
1531 }
1532
1533 file.close();
1534}
1535
1536void init_tr(const LLString& language)
1537{
1538 if (!language.empty())
1539 {
1540 gLanguage = language;
1541 }
1542 load_tr(gLanguage);
1543}
1544
1545void cleanup_tr()
1546{
1547 // Dump untranslated phrases to help with translation
1548 if (gUntranslated.size() > 0)
1549 {
1550 LLString outname = "untranslated_" + gLanguage + ".txt";
1551 LLString outfilename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, outname.c_str());
1552 llofstream outfile;
1553 outfile.open(outfilename.c_str());
1554 if (!outfile)
1555 {
1556 return;
1557 }
1558 llinfos << "Writing untranslated words to: " << outfilename << llendl;
1559 LLString outtext;
1560 for (std::list<LLString>::iterator iter = gUntranslated.begin();
1561 iter != gUntranslated.end(); ++iter)
1562 {
1563 // output: english_phrase english_phrase
1564 outtext += *iter;
1565 outtext += "\t";
1566 outtext += *iter;
1567 outtext += "\n";
1568 }
1569 outfile << outtext.c_str();
1570 outfile.close();
1571 }
1572}
1573
1574LLString tr(const LLString& english_string)
1575{
1576 std::map<LLString, LLString>::iterator it = gTranslation.find(english_string);
1577 if (it != gTranslation.end())
1578 {
1579 return it->second;
1580 }
1581 else
1582 {
1583 gUntranslated.push_back(english_string);
1584 return english_string;
1585 }
1586}
1587
1588#endif
1589
1590
1591class LLShowXUINamesListener: public LLSimpleListener
1592{
1593 bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
1594 {
1595 LLUI::sShowXUINames = (BOOL) event->getValue().asBoolean();
1596 return true;
1597 }
1598};
1599static LLShowXUINamesListener show_xui_names_listener;
1600
1601
1602void LLUI::initClass(LLControlGroup* config,
1603 LLControlGroup* colors,
1604 LLControlGroup* assets,
1605 LLImageProviderInterface* image_provider,
1606 LLUIAudioCallback audio_callback,
1607 const LLVector2* scale_factor,
1608 const LLString& language)
1609{
1610 sConfigGroup = config;
1611 sColorsGroup = colors;
1612 sAssetsGroup = assets;
1613 sImageProvider = image_provider;
1614 sAudioCallback = audio_callback;
1615 sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor;
1616 sWindow = NULL; // set later in startup
1617 LLFontGL::sShadowColor = colors->getColor("ColorDropShadow");
1618
1619 LLUI::sShowXUINames = LLUI::sConfigGroup->getBOOL("ShowXUINames");
1620 LLUI::sConfigGroup->getControl("ShowXUINames")->addListener(&show_xui_names_listener);
1621// init_tr(language);
1622}
1623
1624void LLUI::cleanupClass()
1625{
1626// cleanup_tr();
1627}
1628
1629
1630//static
1631void LLUI::translate(F32 x, F32 y, F32 z)
1632{
1633 glTranslatef(x,y,z);
1634 LLFontGL::sCurOrigin.mX += (S32) x;
1635 LLFontGL::sCurOrigin.mY += (S32) y;
1636 LLFontGL::sCurOrigin.mZ += z;
1637}
1638
1639//static
1640void LLUI::pushMatrix()
1641{
1642 glPushMatrix();
1643 LLFontGL::sOriginStack.push_back(LLFontGL::sCurOrigin);
1644}
1645
1646//static
1647void LLUI::popMatrix()
1648{
1649 glPopMatrix();
1650 LLFontGL::sCurOrigin = *LLFontGL::sOriginStack.rbegin();
1651 LLFontGL::sOriginStack.pop_back();
1652}
1653
1654//static
1655void LLUI::loadIdentity()
1656{
1657 glLoadIdentity();
1658 LLFontGL::sCurOrigin.mX = 0;
1659 LLFontGL::sCurOrigin.mY = 0;
1660 LLFontGL::sCurOrigin.mZ = 0;
1661}
1662
1663//static
1664void LLUI::setScissorRegionScreen(const LLRect& rect)
1665{
1666 stop_glerror();
1667 S32 x,y,w,h;
1668 x = llround(rect.mLeft * LLUI::sGLScaleFactor.mV[VX]);
1669 y = llround(rect.mBottom * LLUI::sGLScaleFactor.mV[VY]);
1670 w = llround(rect.getWidth() * LLUI::sGLScaleFactor.mV[VX]);
1671 h = llround(rect.getHeight() * LLUI::sGLScaleFactor.mV[VY]);
1672 glScissor( x,y,w,h );
1673 stop_glerror();
1674}
1675
1676//static
1677void LLUI::setScissorRegionLocal(const LLRect& rect)
1678{
1679 stop_glerror();
1680 S32 screen_left = LLFontGL::sCurOrigin.mX + rect.mLeft;
1681 S32 screen_bottom = LLFontGL::sCurOrigin.mY + rect.mBottom;
1682
1683 S32 x,y,w,h;
1684
1685 x = llround((F32)screen_left * LLUI::sGLScaleFactor.mV[VX]);
1686 y = llround((F32)screen_bottom * LLUI::sGLScaleFactor.mV[VY]);
1687 w = llround((F32)rect.getWidth() * LLUI::sGLScaleFactor.mV[VX]);
1688 h = llround((F32)rect.getHeight() * LLUI::sGLScaleFactor.mV[VY]);
1689
1690 w = llmax(0,w);
1691 h = llmax(0,h);
1692
1693 glScissor(x,y,w,h);
1694 stop_glerror();
1695}
1696
1697//static
1698void LLUI::setScaleFactor(const LLVector2 &scale_factor)
1699{
1700 sGLScaleFactor = scale_factor;
1701}
1702
1703//static
1704void LLUI::setLineWidth(F32 width)
1705{
1706 glLineWidth(width * lerp(sGLScaleFactor.mV[VX], sGLScaleFactor.mV[VY], 0.5f));
1707}
1708
1709//static
1710void LLUI::setCursorPositionScreen(S32 x, S32 y)
1711{
1712 S32 screen_x, screen_y;
1713 screen_x = llround((F32)x * sGLScaleFactor.mV[VX]);
1714 screen_y = llround((F32)y * sGLScaleFactor.mV[VY]);
1715
1716 LLCoordWindow window_point;
1717 LLView::getWindow()->convertCoords(LLCoordGL(screen_x, screen_y), &window_point);
1718
1719 LLView::getWindow()->setCursorPosition(window_point);
1720}
1721
1722//static
1723void LLUI::setCursorPositionLocal(LLView* viewp, S32 x, S32 y)
1724{
1725 S32 screen_x, screen_y;
1726 viewp->localPointToScreen(x, y, &screen_x, &screen_y);
1727
1728 setCursorPositionScreen(screen_x, screen_y);
1729}
1730
1731//static
1732LLString LLUI::locateSkin(const LLString& filename)
1733{
1734 LLString slash = gDirUtilp->getDirDelimiter();
1735 LLString found_file = filename;
1736 if (!gDirUtilp->fileExists(found_file))
1737 {
1738 found_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); // Should be CUSTOM_SKINS?
1739 }
1740 if (sConfigGroup && sConfigGroup->controlExists("Language"))
1741 {
1742 if (!gDirUtilp->fileExists(found_file))
1743 {
1744 LLString localization(sConfigGroup->getString("Language"));
1745 LLString local_skin = "xui" + slash + localization + slash + filename;
1746 found_file = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, local_skin);
1747 }
1748 }
1749 if (!gDirUtilp->fileExists(found_file))
1750 {
1751 LLString local_skin = "xui" + slash + "en-us" + slash + filename;
1752 found_file = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, local_skin);
1753 }
1754 if (!gDirUtilp->fileExists(found_file))
1755 {
1756 found_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename);
1757 }
1758 return found_file;
1759}
1760
1761//static
1762LLVector2 LLUI::getWindowSize()
1763{
1764 LLCoordWindow window_rect;
1765 sWindow->getSize(&window_rect);
1766
1767 return LLVector2(window_rect.mX / sGLScaleFactor.mV[VX], window_rect.mY / sGLScaleFactor.mV[VY]);
1768}
1769
1770//static
1771LLUUID LLUI::findAssetUUIDByName(const LLString &asset_name)
1772{
1773 if(asset_name == LLString::null) return LLUUID::null;
1774 LLString foundValue = LLUI::sConfigGroup->findString(asset_name);
1775 if(foundValue==LLString::null)
1776 {
1777 foundValue = LLUI::sAssetsGroup->findString(asset_name);
1778 }
1779 if(foundValue == LLString::null){
1780 return LLUUID::null;
1781 }
1782 return LLUUID( foundValue );
1783}