summaryrefslogtreecommitdiff
path: root/indra/llui/llui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/llui.cpp')
-rw-r--r--indra/llui/llui.cpp661
1 files changed, 383 insertions, 278 deletions
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index bf12384a28..8020ca802b 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -2,31 +2,25 @@
* @file llui.cpp
* @brief UI implementation
*
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -67,6 +61,8 @@
// for XUIParse
#include "llquaternion.h"
#include <boost/tokenizer.hpp>
+#include <boost/algorithm/string/find_iterator.hpp>
+#include <boost/algorithm/string/finder.hpp>
//
// Globals
@@ -97,7 +93,6 @@ static LLDefaultChildRegistry::Register<LLFlyoutButton> register_flyout_button("
static LLDefaultChildRegistry::Register<LLSearchEditor> register_search_editor("search_editor");
// register other widgets which otherwise may not be linked in
-static LLDefaultChildRegistry::Register<LLMenuButton> register_menu_button("menu_button");
static LLDefaultChildRegistry::Register<LLLoadingIndicator> register_loading_indicator("loading_indicator");
@@ -467,7 +462,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border
gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect);
}
-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)
+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_outer_rect, const LLRectf& center_rect)
{
stop_glerror();
@@ -477,36 +472,53 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
return;
}
+ // add in offset of current image to current ui translation
+ const LLVector3 ui_scale = gGL.getUIScale();
+ const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale);
+
+ F32 uv_width = uv_outer_rect.getWidth();
+ F32 uv_height = uv_outer_rect.getHeight();
+
// shrink scaling region to be proportional to clipped image region
- LLRectf scale_rect_uv(
- uv_rect.mLeft + (scale_rect.mLeft * uv_rect.getWidth()),
- uv_rect.mBottom + (scale_rect.mTop * uv_rect.getHeight()),
- uv_rect.mLeft + (scale_rect.mRight * uv_rect.getWidth()),
- uv_rect.mBottom + (scale_rect.mBottom * uv_rect.getHeight()));
-
- S32 image_natural_width = llround((F32)image->getWidth(0) * uv_rect.getWidth());
- S32 image_natural_height = llround((F32)image->getHeight(0) * uv_rect.getHeight());
-
- LLRect draw_rect(0, height, width, 0);
- LLRect draw_scale_rect(llround(scale_rect_uv.mLeft * (F32)image->getWidth(0)),
- llround(scale_rect_uv.mTop * (F32)image->getHeight(0)),
- llround(scale_rect_uv.mRight * (F32)image->getWidth(0)),
- llround(scale_rect_uv.mBottom * (F32)image->getHeight(0)));
- // scale fixed region of image to drawn region
- draw_scale_rect.mRight += width - image_natural_width;
- draw_scale_rect.mTop += height - image_natural_height;
-
- S32 border_shrink_width = llmax(0, draw_scale_rect.mLeft - draw_scale_rect.mRight);
- S32 border_shrink_height = llmax(0, draw_scale_rect.mBottom - draw_scale_rect.mTop);
-
- F32 shrink_width_ratio = scale_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - scale_rect.getWidth()));
- F32 shrink_height_ratio = scale_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - scale_rect.getHeight()));
-
- F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
- draw_scale_rect.mLeft = llround((F32)draw_scale_rect.mLeft * shrink_scale);
- draw_scale_rect.mTop = llround(lerp((F32)height, (F32)draw_scale_rect.mTop, shrink_scale));
- draw_scale_rect.mRight = llround(lerp((F32)width, (F32)draw_scale_rect.mRight, shrink_scale));
- draw_scale_rect.mBottom = llround((F32)draw_scale_rect.mBottom * shrink_scale);
+ LLRectf uv_center_rect(
+ uv_outer_rect.mLeft + (center_rect.mLeft * uv_width),
+ uv_outer_rect.mBottom + (center_rect.mTop * uv_height),
+ uv_outer_rect.mLeft + (center_rect.mRight * uv_width),
+ uv_outer_rect.mBottom + (center_rect.mBottom * uv_height));
+
+ F32 image_width = image->getWidth(0);
+ F32 image_height = image->getHeight(0);
+
+ S32 image_natural_width = llround(image_width * uv_width);
+ S32 image_natural_height = llround(image_height * uv_height);
+
+ LLRectf draw_center_rect( uv_center_rect.mLeft * image_width,
+ uv_center_rect.mTop * image_height,
+ uv_center_rect.mRight * image_width,
+ uv_center_rect.mBottom * image_height);
+
+ { // scale fixed region of image to drawn region
+ draw_center_rect.mRight += width - image_natural_width;
+ draw_center_rect.mTop += height - image_natural_height;
+
+ F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight);
+ F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop);
+
+ F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth()));
+ F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight()));
+
+ F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
+
+ draw_center_rect.mLeft = llround(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]);
+ draw_center_rect.mTop = llround(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]);
+ draw_center_rect.mRight = llround(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]);
+ draw_center_rect.mBottom = llround(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]);
+ }
+
+ LLRectf draw_outer_rect(ui_translation.mV[VX],
+ ui_translation.mV[VY] + height * ui_scale.mV[VY],
+ ui_translation.mV[VX] + width * ui_scale.mV[VX],
+ ui_translation.mV[VY]);
LLGLSUIDefault gls_ui;
@@ -516,136 +528,174 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex
gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
}
- gGL.pushUIMatrix();
- {
- gGL.translateUI((F32)x, (F32)y, 0.f);
+ gGL.getTexUnit(0)->bind(image);
- gGL.getTexUnit(0)->bind(image);
+ gGL.color4fv(color.mV);
+
+ const S32 NUM_VERTICES = 9 * 4; // 9 quads
+ LLVector2 uv[NUM_VERTICES];
+ LLVector3 pos[NUM_VERTICES];
- gGL.color4fv(color.mV);
-
- gGL.begin(LLRender::QUADS);
- {
- // draw bottom left
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
- gGL.vertex2i(0, 0);
+ S32 index = 0;
- gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, 0);
+ gGL.begin(LLRender::QUADS);
+ {
+ // draw bottom left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(0, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- // draw bottom middle
- gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, 0);
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, 0);
+ // draw bottom middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
- // draw bottom right
- gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, 0);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
- gGL.vertex2i(width, 0);
+ // draw bottom right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(width, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
- // draw left
- gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(0, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ // draw left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(0, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- // draw middle
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mBottom);
+ // draw middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- // draw right
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mBottom);
+ // draw right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mBottom);
- gGL.vertex2i(width, draw_scale_rect.mBottom);
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(width, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- // draw top left
- gGL.texCoord2f(uv_rect.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(0, draw_scale_rect.mTop);
+ // draw top left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, height);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
- gGL.vertex2i(0, height);
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
- // draw top middle
- gGL.texCoord2f(scale_rect_uv.mLeft, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, draw_scale_rect.mTop);
+ // draw top middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, height);
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mLeft, uv_rect.mTop);
- gGL.vertex2i(draw_scale_rect.mLeft, height);
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
- // draw top right
- gGL.texCoord2f(scale_rect_uv.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, draw_scale_rect.mTop);
+ // draw top right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, scale_rect_uv.mTop);
- gGL.vertex2i(width, draw_scale_rect.mTop);
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
- gGL.vertex2i(width, height);
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
- gGL.texCoord2f(scale_rect_uv.mRight, uv_rect.mTop);
- gGL.vertex2i(draw_scale_rect.mRight, height);
- }
- gGL.end();
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
}
- gGL.popUIMatrix();
+ gGL.end();
if (solid_color)
{
@@ -675,25 +725,40 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
if (degrees == 0.f)
{
- gGL.pushUIMatrix();
- gGL.translateUI((F32)x, (F32)y, 0.f);
-
+ const S32 NUM_VERTICES = 4; // 9 quads
+ LLVector2 uv[NUM_VERTICES];
+ LLVector3 pos[NUM_VERTICES];
+
gGL.begin(LLRender::QUADS);
{
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
- gGL.vertex2i(width, height );
-
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
- gGL.vertex2i(0, height );
-
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
- gGL.vertex2i(0, 0);
-
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
- gGL.vertex2i(width, 0);
+ LLVector3 ui_scale = gGL.getUIScale();
+ LLVector3 ui_translation = gGL.getUITranslation();
+ ui_translation.mV[VX] += x;
+ ui_translation.mV[VY] += y;
+ ui_translation.scaleVec(ui_scale);
+ S32 index = 0;
+ S32 scaled_width = llround(width * ui_scale.mV[VX]);
+ S32 scaled_height = llround(height * ui_scale.mV[VY]);
+
+ uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
+ pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
+ pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
+ pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
+ pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f);
+ index++;
+
+ gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
}
gGL.end();
- gGL.popUIMatrix();
}
else
{
@@ -762,25 +827,6 @@ void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LL
LLUI::setLineWidth(1.f);
}
-
-void gl_rect_2d_xor(S32 left, S32 top, S32 right, S32 bottom)
-{
- gGL.color4fv( LLColor4::white.mV );
- glLogicOp( GL_XOR );
- stop_glerror();
-
- gGL.begin(LLRender::QUADS);
- gGL.vertex2i(left, top);
- gGL.vertex2i(left, bottom);
- gGL.vertex2i(right, bottom);
- gGL.vertex2i(right, top);
- gGL.end();
-
- glLogicOp( GL_COPY );
- stop_glerror();
-}
-
-
void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle)
{
if (end_angle < start_angle)
@@ -906,7 +952,7 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor
}
// Draw gray and white checkerboard with black border
-void gl_rect_2d_checkerboard(const LLRect& rect)
+void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)
{
// Initialize the first time this is called.
const S32 PIXELS = 32;
@@ -927,11 +973,11 @@ void gl_rect_2d_checkerboard(const LLRect& rect)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
// ...white squares
- gGL.color3f( 1.f, 1.f, 1.f );
+ gGL.color4f( 1.f, 1.f, 1.f, alpha );
gl_rect_2d(rect);
// ...gray squares
- gGL.color3f( .7f, .7f, .7f );
+ gGL.color4f( .7f, .7f, .7f, alpha );
gGL.flush();
glPolygonStipple( checkerboard );
@@ -1014,42 +1060,6 @@ void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians,
gGL.end();
}
-// Draws spokes around a circle.
-void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color)
-{
- const F32 DELTA = F_TWO_PI / count;
- const F32 HALF_DELTA = DELTA * 0.5f;
- const F32 SIN_DELTA = sin( DELTA );
- const F32 COS_DELTA = cos( DELTA );
-
- F32 x1 = outer_radius * cos( HALF_DELTA );
- F32 y1 = outer_radius * sin( HALF_DELTA );
- F32 x2 = inner_radius * cos( HALF_DELTA );
- F32 y2 = inner_radius * sin( HALF_DELTA );
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- gGL.begin( LLRender::LINES );
- {
- while( count-- )
- {
- gGL.color4fv(outer_color.mV);
- gGL.vertex2f( x1, y1 );
- gGL.color4fv(inner_color.mV);
- gGL.vertex2f( x2, y2 );
-
- F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
- y1 = x1 * SIN_DELTA + y1 * COS_DELTA;
- x1 = x1_new;
-
- F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
- y2 = x2 * SIN_DELTA + y2 * COS_DELTA;
- x2 = x2_new;
- }
- }
- gGL.end();
-}
-
void gl_rect_2d_simple_tex( S32 width, S32 height )
{
gGL.begin( LLRender::QUADS );
@@ -1237,6 +1247,7 @@ void gl_segmented_rect_2d_tex(const S32 left,
gGL.popUIMatrix();
}
+//FIXME: rewrite to use scissor?
void gl_segmented_rect_2d_fragment_tex(const S32 left,
const S32 top,
const S32 right,
@@ -1587,23 +1598,25 @@ void LLUI::initClass(const settings_map_t& settings,
sWindow = NULL; // set later in startup
LLFontGL::sShadowColor = LLUIColorTable::instance().getColor("ColorDropShadow");
+ LLUICtrl::CommitCallbackRegistry::Registrar& reg = LLUICtrl::CommitCallbackRegistry::defaultRegistrar();
+
// Callbacks for associating controls with floater visibilty:
- LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleFloaterInstance, _2));
- LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Show", boost::bind(&LLFloaterReg::showFloaterInstance, _2));
- LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.Hide", boost::bind(&LLFloaterReg::hideFloaterInstance, _2));
- LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Floater.InitToVisibilityControl", boost::bind(&LLFloaterReg::initUICtrlToFloaterVisibilityControl, _1, _2));
+ reg.add("Floater.Toggle", boost::bind(&LLFloaterReg::toggleFloaterInstance, _2));
+ reg.add("Floater.Show", boost::bind(&LLFloaterReg::showFloaterInstance, _2));
+ reg.add("Floater.Hide", boost::bind(&LLFloaterReg::hideFloaterInstance, _2));
+ reg.add("Floater.InitToVisibilityControl", boost::bind(&LLFloaterReg::initUICtrlToFloaterVisibilityControl, _1, _2));
// Button initialization callback for toggle buttons
- LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.SetFloaterToggle", boost::bind(&LLButton::setFloaterToggle, _1, _2));
+ reg.add("Button.SetFloaterToggle", boost::bind(&LLButton::setFloaterToggle, _1, _2));
// Button initialization callback for toggle buttons on dockale floaters
- LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.SetDockableFloaterToggle", boost::bind(&LLButton::setDockableFloaterToggle, _1, _2));
+ reg.add("Button.SetDockableFloaterToggle", boost::bind(&LLButton::setDockableFloaterToggle, _1, _2));
// Display the help topic for the current context
- LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.ShowHelp", boost::bind(&LLButton::showHelp, _1, _2));
+ reg.add("Button.ShowHelp", boost::bind(&LLButton::showHelp, _1, _2));
// Currently unused, but kept for reference:
- LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("Button.ToggleFloater", boost::bind(&LLButton::toggleFloaterAndSetToggleState, _1, _2));
+ reg.add("Button.ToggleFloater", boost::bind(&LLButton::toggleFloaterAndSetToggleState, _1, _2));
// Used by menus along with Floater.Toggle to display visibility as a checkmark
LLUICtrl::EnableCallbackRegistry::defaultRegistrar().add("Floater.Visible", boost::bind(&LLFloaterReg::floaterInstanceVisible, _2));
@@ -1611,8 +1624,11 @@ void LLUI::initClass(const settings_map_t& settings,
void LLUI::cleanupClass()
{
+ if(sImageProvider)
+ {
sImageProvider->cleanUp();
}
+}
void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup, const clear_popups_t& clear_popups)
{
@@ -1752,6 +1768,33 @@ std::string LLUI::getLanguage()
return language;
}
+struct SubDir : public LLInitParam::Block<SubDir>
+{
+ Mandatory<std::string> value;
+
+ SubDir()
+ : value("value")
+ {}
+};
+
+struct Directory : public LLInitParam::Block<Directory>
+{
+ Multiple<SubDir, AtLeast<1> > subdirs;
+
+ Directory()
+ : subdirs("subdir")
+ {}
+};
+
+struct Paths : public LLInitParam::Block<Paths>
+{
+ Multiple<Directory, AtLeast<1> > directories;
+
+ Paths()
+ : directories("directory")
+ {}
+};
+
//static
void LLUI::setupPaths()
{
@@ -1759,21 +1802,37 @@ void LLUI::setupPaths()
LLXMLNodePtr root;
BOOL success = LLXMLNode::parseFile(filename, root, NULL);
+ Paths paths;
+ LLXUIParser parser;
+ parser.readXUI(root, paths, filename);
+
sXUIPaths.clear();
- if (success)
+ if (success && paths.validateBlock())
{
LLStringUtil::format_map_t path_args;
path_args["[LANGUAGE]"] = LLUI::getLanguage();
- for (LLXMLNodePtr path = root->getFirstChild(); path.notNull(); path = path->getNextSibling())
+ for (LLInitParam::ParamIterator<Directory>::const_iterator it = paths.directories.begin(),
+ end_it = paths.directories.end();
+ it != end_it;
+ ++it)
{
- std::string path_val_ui(path->getValue());
+ std::string path_val_ui;
+ for (LLInitParam::ParamIterator<SubDir>::const_iterator subdir_it = it->subdirs.begin(),
+ subdir_end_it = it->subdirs.end();
+ subdir_it != subdir_end_it;)
+ {
+ path_val_ui += subdir_it->value();
+ if (++subdir_it != subdir_end_it)
+ path_val_ui += gDirUtilp->getDirDelimiter();
+ }
LLStringUtil::format(path_val_ui, path_args);
if (std::find(sXUIPaths.begin(), sXUIPaths.end(), path_val_ui) == sXUIPaths.end())
{
sXUIPaths.push_back(path_val_ui);
}
+
}
}
else // parsing failed
@@ -1963,37 +2022,84 @@ void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y)
view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect, FALSE );
}
+LLView* LLUI::resolvePath(LLView* context, const std::string& path)
+{
+ // Nothing about resolvePath() should require non-const LLView*. If caller
+ // wants non-const, call the const flavor and then cast away const-ness.
+ return const_cast<LLView*>(resolvePath(const_cast<const LLView*>(context), path));
+}
+
+const LLView* LLUI::resolvePath(const LLView* context, const std::string& path)
+{
+ // Create an iterator over slash-separated parts of 'path'. Dereferencing
+ // this iterator returns an iterator_range over the substring. Unlike
+ // LLStringUtil::getTokens(), this split_iterator doesn't combine adjacent
+ // delimiters: leading/trailing slash produces an empty substring, double
+ // slash produces an empty substring. That's what we need.
+ boost::split_iterator<std::string::const_iterator> ti(path, boost::first_finder("/")), tend;
+
+ if (ti == tend)
+ {
+ // 'path' is completely empty, no navigation
+ return context;
+ }
+
+ // leading / means "start at root"
+ if (ti->empty())
+ {
+ context = getRootView();
+ ++ti;
+ }
+
+ bool recurse = false;
+ for (; ti != tend && context; ++ti)
+ {
+ if (ti->empty())
+ {
+ recurse = true;
+ }
+ else
+ {
+ std::string part(ti->begin(), ti->end());
+ context = context->findChildView(part, recurse);
+ recurse = false;
+ }
+ }
+
+ return context;
+}
+
// LLLocalClipRect and LLScreenClipRect moved to lllocalcliprect.h/cpp
namespace LLInitParam
{
- TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
- : super_t(descriptor, name, value, func, min_count, max_count),
+ ParamValue<LLUIColor, TypeValues<LLUIColor> >::ParamValue(const LLUIColor& color)
+ : super_t(color),
red("red"),
green("green"),
blue("blue"),
alpha("alpha"),
control("")
{
- setBlockFromValue();
+ updateBlockFromValue();
}
- void TypedParam<LLUIColor>::setValueFromBlock() const
+ void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateValueFromBlock()
{
if (control.isProvided())
{
- mData.mValue = LLUIColorTable::instance().getColor(control);
+ updateValue(LLUIColorTable::instance().getColor(control));
}
else
{
- mData.mValue = LLColor4(red, green, blue, alpha);
+ updateValue(LLColor4(red, green, blue, alpha));
}
}
- void TypedParam<LLUIColor>::setBlockFromValue()
+ void ParamValue<LLUIColor, TypeValues<LLUIColor> >::updateBlockFromValue()
{
- LLColor4 color = mData.mValue.get();
+ LLColor4 color = getValue();
red.set(color.mV[VRED], false);
green.set(color.mV[VGREEN], false);
blue.set(color.mV[VBLUE], false);
@@ -2001,38 +2107,32 @@ namespace LLInitParam
control.set("", false);
}
- void TypeValues<LLUIColor>::declareValues()
- {
- declare("white", LLColor4::white);
- declare("black", LLColor4::black);
- declare("red", LLColor4::red);
- declare("green", LLColor4::green);
- declare("blue", LLColor4::blue);
- }
-
bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
{
return !(a->getFontDesc() < b->getFontDesc())
&& !(b->getFontDesc() < a->getFontDesc());
}
- TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
- : super_t(descriptor, _name, value, func, min_count, max_count),
+ ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::ParamValue(const LLFontGL* fontp)
+ : super_t(fontp),
name("name"),
size("size"),
style("style")
{
- setBlockFromValue();
+ if (!fontp)
+ {
+ updateValue(LLFontGL::getFontDefault());
+ }
addSynonym(name, "");
- setBlockFromValue();
+ updateBlockFromValue();
}
- void TypedParam<const LLFontGL*>::setValueFromBlock() const
+ void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateValueFromBlock()
{
const LLFontGL* res_fontp = LLFontGL::getFontByName(name);
if (res_fontp)
{
- mData.mValue = res_fontp;
+ updateValue(res_fontp);
return;
}
@@ -2042,22 +2142,26 @@ namespace LLInitParam
const LLFontGL* fontp = LLFontGL::getFont(desc);
if (fontp)
{
- mData.mValue = fontp;
- }
+ updateValue(fontp);
+ }
+ else
+ {
+ updateValue(LLFontGL::getFontDefault());
+ }
}
- void TypedParam<const LLFontGL*>::setBlockFromValue()
+ void ParamValue<const LLFontGL*, TypeValues<const LLFontGL*> >::updateBlockFromValue()
{
- if (mData.mValue)
+ if (getValue())
{
- name.set(LLFontGL::nameFromFont(mData.mValue), false);
- size.set(LLFontGL::sizeFromFont(mData.mValue), false);
- style.set(LLFontGL::getStringFromStyle(mData.mValue->getFontDesc().getStyle()), false);
+ name.set(LLFontGL::nameFromFont(getValue()), false);
+ size.set(LLFontGL::sizeFromFont(getValue()), false);
+ style.set(LLFontGL::getStringFromStyle(getValue()->getFontDesc().getStyle()), false);
}
}
- TypedParam<LLRect>::TypedParam(BlockDescriptor& descriptor, const char* name, const LLRect& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
- : super_t(descriptor, name, value, func, min_count, max_count),
+ ParamValue<LLRect, TypeValues<LLRect> >::ParamValue(const LLRect& rect)
+ : super_t(rect),
left("left"),
top("top"),
right("right"),
@@ -2065,10 +2169,10 @@ namespace LLInitParam
width("width"),
height("height")
{
- setBlockFromValue();
+ updateBlockFromValue();
}
- void TypedParam<LLRect>::setValueFromBlock() const
+ void ParamValue<LLRect, TypeValues<LLRect> >::updateValueFromBlock()
{
LLRect rect;
@@ -2129,40 +2233,41 @@ namespace LLInitParam
rect.mBottom = bottom;
rect.mTop = top;
}
- mData.mValue = rect;
+ updateValue(rect);
}
- void TypedParam<LLRect>::setBlockFromValue()
+ void ParamValue<LLRect, TypeValues<LLRect> >::updateBlockFromValue()
{
// because of the ambiguity in specifying a rect by position and/or dimensions
// we clear the "provided" flag so that values from xui/etc have priority
// over those calculated from the rect object
- left.set(mData.mValue.mLeft, false);
- right.set(mData.mValue.mRight, false);
- bottom.set(mData.mValue.mBottom, false);
- top.set(mData.mValue.mTop, false);
- width.set(mData.mValue.getWidth(), false);
- height.set(mData.mValue.getHeight(), false);
+ LLRect& value = getValue();
+ left.set(value.mLeft, false);
+ right.set(value.mRight, false);
+ bottom.set(value.mBottom, false);
+ top.set(value.mTop, false);
+ width.set(value.getWidth(), false);
+ height.set(value.getHeight(), false);
}
- TypedParam<LLCoordGL>::TypedParam(BlockDescriptor& descriptor, const char* name, LLCoordGL value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
- : super_t(descriptor, name, value, func, min_count, max_count),
+ ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::ParamValue(const LLCoordGL& coord)
+ : super_t(coord),
x("x"),
y("y")
{
- setBlockFromValue();
+ updateBlockFromValue();
}
- void TypedParam<LLCoordGL>::setValueFromBlock() const
+ void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateValueFromBlock()
{
- mData.mValue.set(x, y);
+ updateValue(LLCoordGL(x, y));
}
- void TypedParam<LLCoordGL>::setBlockFromValue()
+ void ParamValue<LLCoordGL, TypeValues<LLCoordGL> >::updateBlockFromValue()
{
- x.set(mData.mValue.mX, false);
- y.set(mData.mValue.mY, false);
+ x.set(getValue().mX, false);
+ y.set(getValue().mY, false);
}