summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2010-03-09 14:28:48 -0800
committerJames Cook <james@lindenlab.com>2010-03-09 14:28:48 -0800
commit717a4800f1ae0ae6ea0bbe9ed0af21c7851f5d0a (patch)
tree88eaacce1385606e9f0f98b3d46108dc0f06ed26 /indra/newview
parent60aa61e1cc5d3c42f54368a2b0b9eccfe5d315ff (diff)
Break name tag code out into LLHUDNameTag
Start by duplicating the LLHUDText code, then stripping out functionality that only needs to exist in one place (like force-based juggling of name tag positions)
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/llhudnametag.cpp1070
-rw-r--r--indra/newview/llhudnametag.h195
-rw-r--r--indra/newview/llhudobject.cpp18
-rw-r--r--indra/newview/llhudobject.h7
-rw-r--r--indra/newview/llhudtext.cpp442
-rw-r--r--indra/newview/llhudtext.h21
-rw-r--r--indra/newview/llviewerobjectlist.cpp4
-rw-r--r--indra/newview/llviewerwindow.cpp7
-rw-r--r--indra/newview/llvoavatar.cpp13
-rw-r--r--indra/newview/llvoavatar.h4
-rw-r--r--indra/newview/pipeline.cpp5
12 files changed, 1322 insertions, 466 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 8ad3b2085d..7b306d03ab 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -233,6 +233,7 @@ set(viewer_SOURCE_FILES
llhudeffecttrail.cpp
llhudicon.cpp
llhudmanager.cpp
+ llhudnametag.cpp
llhudobject.cpp
llhudrender.cpp
llhudtext.cpp
@@ -734,6 +735,7 @@ set(viewer_HEADER_FILES
llhudeffecttrail.h
llhudicon.h
llhudmanager.h
+ llhudnametag.h
llhudobject.h
llhudrender.h
llhudtext.h
diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp
new file mode 100644
index 0000000000..5d4c4571d5
--- /dev/null
+++ b/indra/newview/llhudnametag.cpp
@@ -0,0 +1,1070 @@
+/**
+ * @file llhudnametag.cpp
+ * @brief Name tags for avatars
+ * @author James Cook
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * 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
+ *
+ * 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
+ *
+ * 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.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llhudnametag.h"
+
+#include "llrender.h"
+
+#include "llagent.h"
+#include "llviewercontrol.h"
+#include "llcriticaldamp.h"
+#include "lldrawable.h"
+#include "llfontgl.h"
+#include "llglheaders.h"
+#include "llhudrender.h"
+#include "llui.h"
+#include "llviewercamera.h"
+#include "llviewertexturelist.h"
+#include "llviewerobject.h"
+#include "llvovolume.h"
+#include "llviewerwindow.h"
+#include "llstatusbar.h"
+#include "llmenugl.h"
+#include "pipeline.h"
+#include <boost/tokenizer.hpp>
+
+
+const F32 SPRING_STRENGTH = 0.7f;
+const F32 RESTORATION_SPRING_TIME_CONSTANT = 0.1f;
+const F32 HORIZONTAL_PADDING = 15.f;
+const F32 VERTICAL_PADDING = 12.f;
+const F32 BUFFER_SIZE = 2.f;
+const F32 MIN_EDGE_OVERLAP = 3.f;
+const F32 HUD_TEXT_MAX_WIDTH = 190.f;
+const F32 HUD_TEXT_MAX_WIDTH_NO_BUBBLE = 1000.f;
+const F32 RESIZE_TIME = 0.f;
+const S32 NUM_OVERLAP_ITERATIONS = 10;
+const F32 NEIGHBOR_FORCE_FRACTION = 1.f;
+const F32 POSITION_DAMPING_TC = 0.2f;
+const F32 MAX_STABLE_CAMERA_VELOCITY = 0.1f;
+const F32 LOD_0_SCREEN_COVERAGE = 0.15f;
+const F32 LOD_1_SCREEN_COVERAGE = 0.30f;
+const F32 LOD_2_SCREEN_COVERAGE = 0.40f;
+
+std::set<LLPointer<LLHUDNameTag> > LLHUDNameTag::sTextObjects;
+std::vector<LLPointer<LLHUDNameTag> > LLHUDNameTag::sVisibleTextObjects;
+BOOL LLHUDNameTag::sDisplayText = TRUE ;
+
+bool llhudnametag_further_away::operator()(const LLPointer<LLHUDNameTag>& lhs, const LLPointer<LLHUDNameTag>& rhs) const
+{
+ return lhs->getDistance() > rhs->getDistance();
+}
+
+
+LLHUDNameTag::LLHUDNameTag(const U8 type)
+: LLHUDObject(type),
+// mUseBubble(FALSE),
+ mVisibleOffScreen(FALSE),
+ mWidth(0.f),
+ mHeight(0.f),
+ mFontp(LLFontGL::getFontSansSerifSmall()),
+ mBoldFontp(LLFontGL::getFontSansSerifBold()),
+ mMass(1.f),
+ mMaxLines(10),
+ mOffsetY(0),
+ mTextAlignment(ALIGN_TEXT_CENTER),
+ mVertAlignment(ALIGN_VERT_CENTER),
+ mLOD(0),
+ mHidden(FALSE)
+{
+ mColor = LLColor4(1.f, 1.f, 1.f, 1.f);
+ mDoFade = TRUE;
+ mFadeDistance = 8.f;
+ mFadeRange = 4.f;
+ mZCompare = TRUE;
+ mDropShadow = TRUE;
+ mOffscreen = FALSE;
+ mRadius = 0.1f;
+ LLPointer<LLHUDNameTag> ptr(this);
+ sTextObjects.insert(ptr);
+}
+
+LLHUDNameTag::~LLHUDNameTag()
+{
+}
+
+
+BOOL LLHUDNameTag::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render)
+{
+ if (!mVisible || mHidden)
+ {
+ return FALSE;
+ }
+
+ // don't pick text that isn't bound to a viewerobject
+ if (!mSourceObject || mSourceObject->mDrawable.isNull())
+ {
+ return FALSE;
+ }
+
+ F32 alpha_factor = 1.f;
+ LLColor4 text_color = mColor;
+ if (mDoFade)
+ {
+ if (mLastDistance > mFadeDistance)
+ {
+ alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange);
+ text_color.mV[3] = text_color.mV[3]*alpha_factor;
+ }
+ }
+ if (text_color.mV[3] < 0.01f)
+ {
+ return FALSE;
+ }
+
+ mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
+
+ // scale screen size of borders down
+ //RN: for now, text on hud objects is never occluded
+
+ LLVector3 x_pixel_vec;
+ LLVector3 y_pixel_vec;
+
+ LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+
+ LLVector3 width_vec = mWidth * x_pixel_vec;
+ LLVector3 height_vec = mHeight * y_pixel_vec;
+
+ LLCoordGL screen_pos;
+ LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
+
+ LLVector2 screen_offset;
+ screen_offset = updateScreenPos(mPositionOffset);
+
+ LLVector3 render_position = mPositionAgent
+ + (x_pixel_vec * screen_offset.mV[VX])
+ + (y_pixel_vec * screen_offset.mV[VY]);
+
+
+ //if (mUseBubble)
+ {
+ LLVector3 bg_pos = render_position
+ + (F32)mOffsetY * y_pixel_vec
+ - (width_vec / 2.f)
+ - (height_vec);
+ //LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
+
+ LLVector3 v[] =
+ {
+ bg_pos,
+ bg_pos + width_vec,
+ bg_pos + width_vec + height_vec,
+ bg_pos + height_vec,
+ };
+
+ if (debug_render)
+ {
+ gGL.begin(LLRender::LINE_STRIP);
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[1].mV);
+ gGL.vertex3fv(v[2].mV);
+ gGL.vertex3fv(v[3].mV);
+ gGL.vertex3fv(v[0].mV);
+ gGL.vertex3fv(v[2].mV);
+ gGL.end();
+ }
+
+ LLVector3 dir = end-start;
+ F32 t = 0.f;
+
+ if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, NULL, NULL, &t, FALSE) ||
+ LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, NULL, NULL, &t, FALSE) )
+ {
+ if (t <= 1.f)
+ {
+ intersection = start + dir*t;
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+void LLHUDNameTag::render()
+{
+ if (sDisplayText)
+ {
+ LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+ renderText(FALSE);
+ }
+}
+
+void LLHUDNameTag::renderForSelect()
+{
+ LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+ renderText(TRUE);
+}
+
+void LLHUDNameTag::renderText(BOOL for_select)
+{
+ if (!mVisible || mHidden)
+ {
+ return;
+ }
+
+ // don't pick text that isn't bound to a viewerobject
+ if (for_select &&
+ (!mSourceObject || mSourceObject->mDrawable.isNull()))
+ {
+ return;
+ }
+
+ if (for_select)
+ {
+ gGL.getTexUnit(0)->disable();
+ }
+ else
+ {
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ }
+
+ LLGLState gls_blend(GL_BLEND, for_select ? FALSE : TRUE);
+ LLGLState gls_alpha(GL_ALPHA_TEST, for_select ? FALSE : TRUE);
+
+ LLColor4 shadow_color(0.f, 0.f, 0.f, 1.f);
+ F32 alpha_factor = 1.f;
+ LLColor4 text_color = mColor;
+ if (mDoFade)
+ {
+ if (mLastDistance > mFadeDistance)
+ {
+ alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange);
+ text_color.mV[3] = text_color.mV[3]*alpha_factor;
+ }
+ }
+ if (text_color.mV[3] < 0.01f)
+ {
+ return;
+ }
+ shadow_color.mV[3] = text_color.mV[3];
+
+ mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
+
+ // *TODO: cache this image
+ LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square");
+
+ // *TODO: make this a per-text setting
+ LLColor4 bg_color = LLUIColorTable::instance().getColor("BackgroundChatColor");
+ bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
+
+ const S32 border_height = 16;
+ const S32 border_width = 16;
+
+ // *TODO move this into helper function
+ F32 border_scale = 1.f;
+
+ if (border_height * 2 > mHeight)
+ {
+ border_scale = (F32)mHeight / ((F32)border_height * 2.f);
+ }
+ if (border_width * 2 > mWidth)
+ {
+ border_scale = llmin(border_scale, (F32)mWidth / ((F32)border_width * 2.f));
+ }
+
+ // scale screen size of borders down
+ //RN: for now, text on hud objects is never occluded
+
+ LLVector3 x_pixel_vec;
+ LLVector3 y_pixel_vec;
+
+ LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+
+ LLVector2 border_scale_vec((F32)border_width / (F32)imagep->getTextureWidth(), (F32)border_height / (F32)imagep->getTextureHeight());
+ LLVector3 width_vec = mWidth * x_pixel_vec;
+ LLVector3 height_vec = mHeight * y_pixel_vec;
+ LLVector3 scaled_border_width = (F32)llfloor(border_scale * (F32)border_width) * x_pixel_vec;
+ LLVector3 scaled_border_height = (F32)llfloor(border_scale * (F32)border_height) * y_pixel_vec;
+
+ mRadius = (width_vec + height_vec).magVec() * 0.5f;
+
+ LLCoordGL screen_pos;
+ LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
+
+ LLVector2 screen_offset;
+// if (!mUseBubble)
+// {
+// screen_offset = mPositionOffset;
+// }
+// else
+// {
+ screen_offset = updateScreenPos(mPositionOffset);
+// }
+
+ LLVector3 render_position = mPositionAgent
+ + (x_pixel_vec * screen_offset.mV[VX])
+ + (y_pixel_vec * screen_offset.mV[VY]);
+
+// if (mUseBubble)
+ {
+ LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+ LLUI::pushMatrix();
+ {
+ LLVector3 bg_pos = render_position
+ + (F32)mOffsetY * y_pixel_vec
+ - (width_vec / 2.f)
+ - (height_vec);
+ LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
+
+ if (for_select)
+ {
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ S32 name = mSourceObject->mGLName;
+ LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name);
+ gGL.color4ubv(coloru.mV);
+ gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
+ LLUI::popMatrix();
+ return;
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bind(imagep->getImage());
+
+ gGL.color4fv(bg_color.mV);
+ gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
+
+ if ( mLabelSegments.size())
+ {
+ LLUI::pushMatrix();
+ {
+ gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
+ LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec;
+ LLVector3 label_offset = height_vec - label_height;
+ LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]);
+ gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height);
+ }
+ LLUI::popMatrix();
+ }
+ }
+
+ BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f;
+ BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f);
+
+ // draw line segments pointing to parent object
+ if (!mOffscreen && (outside_width || outside_height))
+ {
+ LLUI::pushMatrix();
+ {
+ gGL.color4fv(bg_color.mV);
+ LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec);
+ target_pos += (width_vec / 2.f);
+ target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero;
+ target_pos -= 3.f * x_pixel_vec;
+ target_pos -= 6.f * y_pixel_vec;
+ LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]);
+ gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec);
+ }
+ LLUI::popMatrix();
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE);
+
+ LLVector3 box_center_offset;
+ box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f);
+ LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]);
+ gGL.color4fv(bg_color.mV);
+ LLUI::setLineWidth(2.0);
+ gGL.begin(LLRender::LINES);
+ {
+ if (outside_width)
+ {
+ LLVector3 vert;
+ // draw line in x then y
+ if (mPositionOffset.mV[VX] < 0.f)
+ {
+ // start at right edge
+ vert = width_vec * 0.5f;
+ gGL.vertex3fv(vert.mV);
+ }
+ else
+ {
+ // start at left edge
+ vert = width_vec * -0.5f;
+ gGL.vertex3fv(vert.mV);
+ }
+ vert = -mPositionOffset.mV[VX] * x_pixel_vec;
+ gGL.vertex3fv(vert.mV);
+ gGL.vertex3fv(vert.mV);
+ vert -= mPositionOffset.mV[VY] * y_pixel_vec;
+ vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
+ gGL.vertex3fv(vert.mV);
+ }
+ else
+ {
+ LLVector3 vert;
+ // draw line in y then x
+ if (mPositionOffset.mV[VY] < 0.f)
+ {
+ // start at top edge
+ vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec);
+ gGL.vertex3fv(vert.mV);
+ }
+ else
+ {
+ // start at bottom edge
+ vert = (height_vec * -0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec);
+ gGL.vertex3fv(vert.mV);
+ }
+ vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec;
+ vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
+ gGL.vertex3fv(vert.mV);
+ }
+ }
+ gGL.end();
+ LLUI::setLineWidth(1.0);
+
+ }
+ }
+ LLUI::popMatrix();
+ }
+
+ F32 y_offset = (F32)mOffsetY;
+
+ // Render label
+ {
+ gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+ for(std::vector<LLHUDTextSegment>::iterator segment_iter = mLabelSegments.begin();
+ segment_iter != mLabelSegments.end(); ++segment_iter )
+ {
+ // Label segments use default font
+ const LLFontGL* fontp = (segment_iter->mStyle == LLFontGL::BOLD) ? mBoldFontp : mFontp;
+ y_offset -= fontp->getLineHeight();
+
+ F32 x_offset;
+ if (mTextAlignment == ALIGN_TEXT_CENTER)
+ {
+ x_offset = -0.5f*segment_iter->getWidth(fontp);
+ }
+ else // ALIGN_LEFT
+ {
+ x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f);
+ }
+
+ LLColor4 label_color(0.f, 0.f, 0.f, 1.f);
+ label_color.mV[VALPHA] = alpha_factor;
+ hud_render_text(segment_iter->getText(), render_position, *fontp, segment_iter->mStyle, LLFontGL::NO_SHADOW, x_offset, y_offset, label_color, FALSE);
+ }
+ }
+
+ // Render text
+ {
+ // -1 mMaxLines means unlimited lines.
+ S32 start_segment;
+ S32 max_lines = getMaxLines();
+
+ if (max_lines < 0)
+ {
+ start_segment = 0;
+ }
+ else
+ {
+ start_segment = llmax((S32)0, (S32)mTextSegments.size() - max_lines);
+ }
+
+ for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin() + start_segment;
+ segment_iter != mTextSegments.end(); ++segment_iter )
+ {
+ const LLFontGL* fontp = segment_iter->mFont;
+ y_offset -= fontp->getLineHeight();
+
+ U8 style = segment_iter->mStyle;
+ LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW;
+ if (mDropShadow)
+ {
+ shadow = LLFontGL::DROP_SHADOW;
+ }
+
+ F32 x_offset;
+ if (mTextAlignment== ALIGN_TEXT_CENTER)
+ {
+ x_offset = -0.5f*segment_iter->getWidth(fontp);
+ }
+ else // ALIGN_LEFT
+ {
+ x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f);
+ }
+
+ text_color = segment_iter->mColor;
+ text_color.mV[VALPHA] *= alpha_factor;
+
+ hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, FALSE);
+ }
+ }
+ /// Reset the default color to white. The renderer expects this to be the default.
+ gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f);
+ if (for_select)
+ {
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ }
+}
+
+void LLHUDNameTag::setString(const std::string &text_utf8)
+{
+ mTextSegments.clear();
+ addLine(text_utf8, mColor);
+}
+
+void LLHUDNameTag::clearString()
+{
+ mTextSegments.clear();
+}
+
+
+void LLHUDNameTag::addLine(const std::string &text_utf8,
+ const LLColor4& color,
+ const LLFontGL::StyleFlags style,
+ const LLFontGL* font)
+{
+ LLWString wline = utf8str_to_wstring(text_utf8);
+ if (!wline.empty())
+ {
+ // use default font for segment if custom font not specified
+ if (!font)
+ {
+ font = mFontp;
+ }
+ typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
+ LLWString seps(utf8str_to_wstring("\r\n"));
+ boost::char_separator<llwchar> sep(seps.c_str());
+
+ tokenizer tokens(wline, sep);
+ tokenizer::iterator iter = tokens.begin();
+
+ while (iter != tokens.end())
+ {
+ U32 line_length = 0;
+ do
+ {
+ F32 max_pixels = HUD_TEXT_MAX_WIDTH;
+ S32 segment_length = font->maxDrawableChars(iter->substr(line_length).c_str(), max_pixels, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
+ LLHUDTextSegment segment(iter->substr(line_length, segment_length), style, color, font);
+ mTextSegments.push_back(segment);
+ line_length += segment_length;
+ }
+ while (line_length != iter->size());
+ ++iter;
+ }
+ }
+}
+
+void LLHUDNameTag::setLabel(const std::string &label_utf8)
+{
+ mLabelSegments.clear();
+ addLabel(label_utf8);
+}
+
+void LLHUDNameTag::addLabel(const std::string& label_utf8)
+{
+ LLWString wstr = utf8string_to_wstring(label_utf8);
+ if (!wstr.empty())
+ {
+ LLWString seps(utf8str_to_wstring("\r\n"));
+ LLWString empty;
+
+ typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
+ boost::char_separator<llwchar> sep(seps.c_str(), empty.c_str(), boost::keep_empty_tokens);
+
+ tokenizer tokens(wstr, sep);
+ tokenizer::iterator iter = tokens.begin();
+
+ while (iter != tokens.end())
+ {
+ U32 line_length = 0;
+ do
+ {
+ S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(),
+ HUD_TEXT_MAX_WIDTH, wstr.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
+ LLHUDTextSegment segment(iter->substr(line_length, segment_length), LLFontGL::NORMAL, mColor, mFontp);
+ mLabelSegments.push_back(segment);
+ line_length += segment_length;
+ }
+ while (line_length != iter->size());
+ ++iter;
+ }
+ }
+}
+
+void LLHUDNameTag::setDropShadow(const BOOL do_shadow)
+{
+ mDropShadow = do_shadow;
+}
+
+void LLHUDNameTag::setZCompare(const BOOL zcompare)
+{
+ mZCompare = zcompare;
+}
+
+void LLHUDNameTag::setFont(const LLFontGL* font)
+{
+ mFontp = font;
+}
+
+
+void LLHUDNameTag::setColor(const LLColor4 &color)
+{
+ mColor = color;
+ for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin();
+ segment_iter != mTextSegments.end(); ++segment_iter )
+ {
+ segment_iter->mColor = color;
+ }
+}
+
+void LLHUDNameTag::setAlpha(F32 alpha)
+{
+ mColor.mV[VALPHA] = alpha;
+ for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin();
+ segment_iter != mTextSegments.end(); ++segment_iter )
+ {
+ segment_iter->mColor.mV[VALPHA] = alpha;
+ }
+}
+
+
+void LLHUDNameTag::setDoFade(const BOOL do_fade)
+{
+ mDoFade = do_fade;
+}
+
+void LLHUDNameTag::updateVisibility()
+{
+ if (mSourceObject)
+ {
+ mSourceObject->updateText();
+ }
+
+ mPositionAgent = gAgent.getPosAgentFromGlobal(mPositionGlobal);
+
+ if (!mSourceObject)
+ {
+ //llwarns << "LLHUDNameTag::updateScreenPos -- mSourceObject is NULL!" << llendl;
+ mVisible = TRUE;
+ sVisibleTextObjects.push_back(LLPointer<LLHUDNameTag> (this));
+ return;
+ }
+
+ // Not visible if parent object is dead
+ if (mSourceObject->isDead())
+ {
+ mVisible = FALSE;
+ return;
+ }
+
+ // push text towards camera by radius of object, but not past camera
+ LLVector3 vec_from_camera = mPositionAgent - LLViewerCamera::getInstance()->getOrigin();
+ LLVector3 dir_from_camera = vec_from_camera;
+ dir_from_camera.normVec();
+
+ if (dir_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= 0.f)
+ { //text is behind camera, don't render
+ mVisible = FALSE;
+ return;
+ }
+
+ if (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis() <= LLViewerCamera::getInstance()->getNear() + 0.1f + mSourceObject->getVObjRadius())
+ {
+ mPositionAgent = LLViewerCamera::getInstance()->getOrigin() + vec_from_camera * ((LLViewerCamera::getInstance()->getNear() + 0.1f) / (vec_from_camera * LLViewerCamera::getInstance()->getAtAxis()));
+ }
+ else
+ {
+ mPositionAgent -= dir_from_camera * mSourceObject->getVObjRadius();
+ }
+
+ mLastDistance = (mPositionAgent - LLViewerCamera::getInstance()->getOrigin()).magVec();
+
+ if (mLOD >= 3 || !mTextSegments.size() || (mDoFade && (mLastDistance > mFadeDistance + mFadeRange)))
+ {
+ mVisible = FALSE;
+ return;
+ }
+
+ LLVector3 x_pixel_vec;
+ LLVector3 y_pixel_vec;
+
+ LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+
+ LLVector3 render_position = mPositionAgent +
+ (x_pixel_vec * mPositionOffset.mV[VX]) +
+ (y_pixel_vec * mPositionOffset.mV[VY]);
+
+ mOffscreen = FALSE;
+ if (!LLViewerCamera::getInstance()->sphereInFrustum(render_position, mRadius))
+ {
+ if (!mVisibleOffScreen)
+ {
+ mVisible = FALSE;
+ return;
+ }
+ else
+ {
+ mOffscreen = TRUE;
+ }
+ }
+
+ mVisible = TRUE;
+ sVisibleTextObjects.push_back(LLPointer<LLHUDNameTag> (this));
+}
+
+LLVector2 LLHUDNameTag::updateScreenPos(LLVector2 &offset)
+{
+ LLCoordGL screen_pos;
+ LLVector2 screen_pos_vec;
+ LLVector3 x_pixel_vec;
+ LLVector3 y_pixel_vec;
+ LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
+ LLVector3 world_pos = mPositionAgent + (offset.mV[VX] * x_pixel_vec) + (offset.mV[VY] * y_pixel_vec);
+ if (!LLViewerCamera::getInstance()->projectPosAgentToScreen(world_pos, screen_pos, FALSE) && mVisibleOffScreen)
+ {
+ // bubble off-screen, so find a spot for it along screen edge
+ LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(world_pos, screen_pos);
+ }
+
+ screen_pos_vec.setVec((F32)screen_pos.mX, (F32)screen_pos.mY);
+
+ LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
+ S32 bottom = world_rect.mBottom + STATUS_BAR_HEIGHT;
+
+ LLVector2 screen_center;
+ screen_center.mV[VX] = llclamp((F32)screen_pos_vec.mV[VX], (F32)world_rect.mLeft + mWidth * 0.5f, (F32)world_rect.mRight - mWidth * 0.5f);
+
+ if(mVertAlignment == ALIGN_VERT_TOP)
+ {
+ screen_center.mV[VY] = llclamp((F32)screen_pos_vec.mV[VY],
+ (F32)bottom,
+ (F32)world_rect.mTop - mHeight - (F32)MENU_BAR_HEIGHT);
+ mSoftScreenRect.setLeftTopAndSize(screen_center.mV[VX] - (mWidth + BUFFER_SIZE) * 0.5f,
+ screen_center.mV[VY] + (mHeight + BUFFER_SIZE), mWidth + BUFFER_SIZE, mHeight + BUFFER_SIZE);
+ }
+ else
+ {
+ screen_center.mV[VY] = llclamp((F32)screen_pos_vec.mV[VY],
+ (F32)bottom + mHeight * 0.5f,
+ (F32)world_rect.mTop - mHeight * 0.5f - (F32)MENU_BAR_HEIGHT);
+ mSoftScreenRect.setCenterAndSize(screen_center.mV[VX], screen_center.mV[VY], mWidth + BUFFER_SIZE, mHeight + BUFFER_SIZE);
+ }
+
+ return offset + (screen_center - LLVector2((F32)screen_pos.mX, (F32)screen_pos.mY));
+}
+
+void LLHUDNameTag::updateSize()
+{
+ F32 height = 0.f;
+ F32 width = 0.f;
+
+ S32 max_lines = getMaxLines();
+ //S32 lines = (max_lines < 0) ? (S32)mTextSegments.size() : llmin((S32)mTextSegments.size(), max_lines);
+ //F32 height = (F32)mFontp->getLineHeight() * (lines + mLabelSegments.size());
+
+ S32 start_segment;
+ if (max_lines < 0) start_segment = 0;
+ else start_segment = llmax((S32)0, (S32)mTextSegments.size() - max_lines);
+
+ std::vector<LLHUDTextSegment>::iterator iter = mTextSegments.begin() + start_segment;
+ while (iter != mTextSegments.end())
+ {
+ const LLFontGL* fontp = iter->mFont;
+ height += fontp->getLineHeight();
+ width = llmax(width, llmin(iter->getWidth(fontp), HUD_TEXT_MAX_WIDTH));
+ ++iter;
+ }
+
+ iter = mLabelSegments.begin();
+ while (iter != mLabelSegments.end())
+ {
+ height += mFontp->getLineHeight();
+ width = llmax(width, llmin(iter->getWidth(mFontp), HUD_TEXT_MAX_WIDTH));
+ ++iter;
+ }
+
+ if (width == 0.f)
+ {
+ return;
+ }
+
+ width += HORIZONTAL_PADDING;
+ height += VERTICAL_PADDING;
+
+ if (!mResizeTimer.getStarted() && (width != mWidth || height != mHeight))
+ {
+ mResizeTimer.start();
+ }
+
+ // *NOTE: removed logic which did a divide by zero.
+ F32 u = 1.f;//llclamp(mResizeTimer.getElapsedTimeF32() / RESIZE_TIME, 0.f, 1.f);
+ if (u == 1.f)
+ {
+ mResizeTimer.stop();
+ }
+
+ mWidth = llmax(width, lerp(mWidth, (F32)width, u));
+ mHeight = llmax(height, lerp(mHeight, (F32)height, u));
+}
+
+void LLHUDNameTag::updateAll()
+{
+ // iterate over all text objects, calculate their restoration forces,
+ // and add them to the visible set if they are on screen and close enough
+ sVisibleTextObjects.clear();
+
+ TextObjectIterator text_it;
+ for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
+ {
+ LLHUDNameTag* textp = (*text_it);
+ textp->mTargetPositionOffset.clearVec();
+ textp->updateSize();
+ textp->updateVisibility();
+ }
+
+ // sort back to front for rendering purposes
+ std::sort(sVisibleTextObjects.begin(), sVisibleTextObjects.end(), llhudnametag_further_away());
+
+ // iterate from front to back, and set LOD based on current screen coverage
+ F32 screen_area = (F32)(gViewerWindow->getWindowWidthScaled() * gViewerWindow->getWindowHeightScaled());
+ F32 current_screen_area = 0.f;
+ std::vector<LLPointer<LLHUDNameTag> >::reverse_iterator r_it;
+ for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it)
+ {
+ LLHUDNameTag* textp = (*r_it);
+// if (textp->mUseBubble)
+// {
+ if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE)
+ {
+ textp->setLOD(3);
+ }
+ else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE)
+ {
+ textp->setLOD(2);
+ }
+ else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE)
+ {
+ textp->setLOD(1);
+ }
+ else
+ {
+ textp->setLOD(0);
+ }
+ textp->updateSize();
+ // find on-screen position and initialize collision rectangle
+ textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero);
+ current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight());
+// }
+ }
+
+ LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat();
+ F32 camera_vel = camera_vel_stat->getCurrent();
+ if (camera_vel > MAX_STABLE_CAMERA_VELOCITY)
+ {
+ return;
+ }
+
+ VisibleTextObjectIterator src_it;
+
+ for (S32 i = 0; i < NUM_OVERLAP_ITERATIONS; i++)
+ {
+ for (src_it = sVisibleTextObjects.begin(); src_it != sVisibleTextObjects.end(); ++src_it)
+ {
+ LLHUDNameTag* src_textp = (*src_it);
+
+// if (!src_textp->mUseBubble)
+// {
+// continue;
+// }
+ VisibleTextObjectIterator dst_it = src_it;
+ ++dst_it;
+ for (; dst_it != sVisibleTextObjects.end(); ++dst_it)
+ {
+ LLHUDNameTag* dst_textp = (*dst_it);
+
+// if (!dst_textp->mUseBubble)
+// {
+// continue;
+// }
+ if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect))
+ {
+ LLRectf intersect_rect = src_textp->mSoftScreenRect;
+ intersect_rect.intersectWith(dst_textp->mSoftScreenRect);
+ intersect_rect.stretch(-BUFFER_SIZE * 0.5f);
+
+ F32 src_center_x = src_textp->mSoftScreenRect.getCenterX();
+ F32 src_center_y = src_textp->mSoftScreenRect.getCenterY();
+ F32 dst_center_x = dst_textp->mSoftScreenRect.getCenterX();
+ F32 dst_center_y = dst_textp->mSoftScreenRect.getCenterY();
+ F32 intersect_center_x = intersect_rect.getCenterX();
+ F32 intersect_center_y = intersect_rect.getCenterY();
+ LLVector2 force = lerp(LLVector2(dst_center_x - intersect_center_x, dst_center_y - intersect_center_y),
+ LLVector2(intersect_center_x - src_center_x, intersect_center_y - src_center_y),
+ 0.5f);
+ force.setVec(dst_center_x - src_center_x, dst_center_y - src_center_y);
+ force.normVec();
+
+ LLVector2 src_force = -1.f * force;
+ LLVector2 dst_force = force;
+
+ LLVector2 force_strength;
+ F32 src_mult = dst_textp->mMass / (dst_textp->mMass + src_textp->mMass);
+ F32 dst_mult = 1.f - src_mult;
+ F32 src_aspect_ratio = src_textp->mSoftScreenRect.getWidth() / src_textp->mSoftScreenRect.getHeight();
+ F32 dst_aspect_ratio = dst_textp->mSoftScreenRect.getWidth() / dst_textp->mSoftScreenRect.getHeight();
+ src_force.mV[VY] *= src_aspect_ratio;
+ src_force.normVec();
+ dst_force.mV[VY] *= dst_aspect_ratio;
+ dst_force.normVec();
+
+ src_force.mV[VX] *= llmin(intersect_rect.getWidth() * src_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
+ src_force.mV[VY] *= llmin(intersect_rect.getHeight() * src_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
+ dst_force.mV[VX] *= llmin(intersect_rect.getWidth() * dst_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
+ dst_force.mV[VY] *= llmin(intersect_rect.getHeight() * dst_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
+
+ src_textp->mTargetPositionOffset += src_force;
+ dst_textp->mTargetPositionOffset += dst_force;
+ src_textp->mTargetPositionOffset = src_textp->updateScreenPos(src_textp->mTargetPositionOffset);
+ dst_textp->mTargetPositionOffset = dst_textp->updateScreenPos(dst_textp->mTargetPositionOffset);
+ }
+ }
+ }
+ }
+
+ VisibleTextObjectIterator this_object_it;
+ for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it)
+ {
+// if (!(*this_object_it)->mUseBubble)
+// {
+// continue;
+// }
+ (*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC));
+ }
+}
+
+void LLHUDNameTag::setLOD(S32 lod)
+{
+ mLOD = lod;
+ //RN: uncomment this to visualize LOD levels
+ //std::string label = llformat("%d", lod);
+ //setLabel(label);
+}
+
+S32 LLHUDNameTag::getMaxLines()
+{
+ switch(mLOD)
+ {
+ case 0:
+ return mMaxLines;
+ case 1:
+ return mMaxLines > 0 ? mMaxLines / 2 : 5;
+ case 2:
+ return mMaxLines > 0 ? mMaxLines / 3 : 2;
+ default:
+ // label only
+ return 0;
+ }
+}
+
+void LLHUDNameTag::markDead()
+{
+ sTextObjects.erase(LLPointer<LLHUDNameTag>(this));
+ LLHUDObject::markDead();
+}
+
+void LLHUDNameTag::shiftAll(const LLVector3& offset)
+{
+ TextObjectIterator text_it;
+ for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
+ {
+ LLHUDNameTag *textp = text_it->get();
+ textp->shift(offset);
+ }
+}
+
+void LLHUDNameTag::shift(const LLVector3& offset)
+{
+ mPositionAgent += offset;
+}
+
+//static
+void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list)
+{
+ //this might put an object on the pick list a second time, overriding it's mGLName, which is ok
+ // *FIX: we should probably cull against pick frustum
+ VisibleTextObjectIterator text_it;
+ for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it)
+ {
+// if (!(*text_it)->mUseBubble)
+// {
+// continue;
+// }
+ pick_list.insert((*text_it)->mSourceObject);
+ }
+}
+
+//static
+// called when UI scale changes, to flush font width caches
+void LLHUDNameTag::reshape()
+{
+ TextObjectIterator text_it;
+ for (text_it = sTextObjects.begin(); text_it != sTextObjects.end(); ++text_it)
+ {
+ LLHUDNameTag* textp = (*text_it);
+ std::vector<LLHUDTextSegment>::iterator segment_iter;
+ for (segment_iter = textp->mTextSegments.begin();
+ segment_iter != textp->mTextSegments.end(); ++segment_iter )
+ {
+ segment_iter->clearFontWidthMap();
+ }
+ for(segment_iter = textp->mLabelSegments.begin();
+ segment_iter != textp->mLabelSegments.end(); ++segment_iter )
+ {
+ segment_iter->clearFontWidthMap();
+ }
+ }
+}
+
+//============================================================================
+
+F32 LLHUDNameTag::LLHUDTextSegment::getWidth(const LLFontGL* font)
+{
+ std::map<const LLFontGL*, F32>::iterator iter = mFontWidthMap.find(font);
+ if (iter != mFontWidthMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ F32 width = font->getWidthF32(mText.c_str());
+ mFontWidthMap[font] = width;
+ return width;
+ }
+}
diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h
new file mode 100644
index 0000000000..56b17bef6b
--- /dev/null
+++ b/indra/newview/llhudnametag.h
@@ -0,0 +1,195 @@
+/**
+ * @file llhudnametag.h
+ * @brief Name tags for avatars
+ * @author James Cook
+ *
+ * $LicenseInfo:firstyear=2010&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * 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
+ *
+ * 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
+ *
+ * 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.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLHUDNAMETAG_H
+#define LLHUDNAMETAG_H
+
+#include "llpointer.h"
+
+#include "llhudobject.h"
+#include "v4color.h"
+#include "v4coloru.h"
+#include "v2math.h"
+#include "llrect.h"
+#include "llframetimer.h"
+#include "llfontgl.h"
+#include <set>
+#include <vector>
+
+class LLDrawable;
+class LLHUDNameTag;
+
+struct llhudnametag_further_away
+{
+ bool operator()(const LLPointer<LLHUDNameTag>& lhs, const LLPointer<LLHUDNameTag>& rhs) const;
+};
+
+class LLHUDNameTag : public LLHUDObject
+{
+protected:
+ class LLHUDTextSegment
+ {
+ public:
+ LLHUDTextSegment(const LLWString& text, const LLFontGL::StyleFlags style, const LLColor4& color, const LLFontGL* font)
+ : mColor(color),
+ mStyle(style),
+ mText(text),
+ mFont(font)
+ {}
+ F32 getWidth(const LLFontGL* font);
+ const LLWString& getText() const { return mText; }
+ void clearFontWidthMap() { mFontWidthMap.clear(); }
+
+ LLColor4 mColor;
+ LLFontGL::StyleFlags mStyle;
+ const LLFontGL* mFont;
+ private:
+ LLWString mText;
+ std::map<const LLFontGL*, F32> mFontWidthMap;
+ };
+
+public:
+ typedef enum e_text_alignment
+ {
+ ALIGN_TEXT_LEFT,
+ ALIGN_TEXT_CENTER
+ } ETextAlignment;
+
+ typedef enum e_vert_alignment
+ {
+ ALIGN_VERT_TOP,
+ ALIGN_VERT_CENTER
+ } EVertAlignment;
+
+public:
+ // Set entire string, eliminating existing lines
+ void setString(const std::string& text_utf8);
+
+ void clearString();
+
+ // Add text a line at a time, allowing custom formatting
+ void addLine(const std::string &text_utf8, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL, const LLFontGL* font = NULL);
+
+ // For bubble chat, set the part above the chat text
+ void setLabel(const std::string& label_utf8);
+ void addLabel(const std::string& label_utf8);
+
+ void setDropShadow(const BOOL do_shadow);
+
+ // Sets the default font for lines with no font specified
+ void setFont(const LLFontGL* font);
+ void setColor(const LLColor4 &color);
+ void setAlpha(F32 alpha);
+ void setZCompare(const BOOL zcompare);
+ void setDoFade(const BOOL do_fade);
+ void setVisibleOffScreen(BOOL visible) { mVisibleOffScreen = visible; }
+
+ // mMaxLines of -1 means unlimited lines.
+ void setMaxLines(S32 max_lines) { mMaxLines = max_lines; }
+ void setFadeDistance(F32 fade_distance, F32 fade_range) { mFadeDistance = fade_distance; mFadeRange = fade_range; }
+ void updateVisibility();
+ LLVector2 updateScreenPos(LLVector2 &offset_target);
+ void updateSize();
+ void setMass(F32 mass) { mMass = llmax(0.1f, mass); }
+ void setTextAlignment(ETextAlignment alignment) { mTextAlignment = alignment; }
+ void setVertAlignment(EVertAlignment alignment) { mVertAlignment = alignment; }
+ /*virtual*/ void markDead();
+ friend class LLHUDObject;
+ /*virtual*/ F32 getDistance() const { return mLastDistance; }
+ //void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; }
+ S32 getLOD() { return mLOD; }
+ BOOL getVisible() { return mVisible; }
+ BOOL getHidden() const { return mHidden; }
+ void setHidden( BOOL hide ) { mHidden = hide; }
+ void shift(const LLVector3& offset);
+
+ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render = FALSE);
+
+ static void shiftAll(const LLVector3& offset);
+ static void addPickable(std::set<LLViewerObject*> &pick_list);
+ static void reshape();
+ static void setDisplayText(BOOL flag) { sDisplayText = flag ; }
+
+protected:
+ LLHUDNameTag(const U8 type);
+
+ /*virtual*/ void render();
+ /*virtual*/ void renderForSelect();
+ void renderText(BOOL for_select);
+ static void updateAll();
+ void setLOD(S32 lod);
+ S32 getMaxLines();
+
+private:
+ ~LLHUDNameTag();
+ //BOOL mUseBubble; always true
+ BOOL mDropShadow;
+ BOOL mDoFade;
+ F32 mFadeRange;
+ F32 mFadeDistance;
+ F32 mLastDistance;
+ BOOL mZCompare;
+ BOOL mVisibleOffScreen;
+ BOOL mOffscreen;
+ LLColor4 mColor;
+ LLVector3 mScale;
+ F32 mWidth;
+ F32 mHeight;
+ LLColor4U mPickColor;
+ const LLFontGL* mFontp;
+ const LLFontGL* mBoldFontp;
+ LLRectf mSoftScreenRect;
+ LLVector3 mPositionAgent;
+ LLVector2 mPositionOffset;
+ LLVector2 mTargetPositionOffset;
+ F32 mMass;
+ S32 mMaxLines;
+ S32 mOffsetY;
+ F32 mRadius;
+ std::vector<LLHUDTextSegment> mTextSegments;
+ std::vector<LLHUDTextSegment> mLabelSegments;
+ LLFrameTimer mResizeTimer;
+ ETextAlignment mTextAlignment;
+ EVertAlignment mVertAlignment;
+ S32 mLOD;
+ BOOL mHidden;
+
+ static BOOL sDisplayText ;
+ static std::set<LLPointer<LLHUDNameTag> > sTextObjects;
+ static std::vector<LLPointer<LLHUDNameTag> > sVisibleTextObjects;
+ static std::vector<LLPointer<LLHUDNameTag> > sVisibleHUDTextObjects;
+ typedef std::set<LLPointer<LLHUDNameTag> >::iterator TextObjectIterator;
+ typedef std::vector<LLPointer<LLHUDNameTag> >::iterator VisibleTextObjectIterator;
+};
+
+#endif
diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp
index dc55aba0db..73fa987f3b 100644
--- a/indra/newview/llhudobject.cpp
+++ b/indra/newview/llhudobject.cpp
@@ -30,9 +30,6 @@
* $/LicenseInfo$
*/
-// llhudobject.cpp
-// Copyright 2002, Linden Research, Inc.
-
#include "llviewerprecompiledheaders.h"
#include "llhudobject.h"
@@ -43,7 +40,7 @@
#include "llhudeffectbeam.h"
#include "llhudeffecttrail.h"
#include "llhudeffectlookat.h"
-
+#include "llhudnametag.h"
#include "llvoicevisualizer.h"
#include "llagent.h"
@@ -71,7 +68,6 @@ LLHUDObject::LLHUDObject(const U8 type) :
mVisible = TRUE;
mType = type;
mDead = FALSE;
- mOnHUDAttachment = FALSE;
}
LLHUDObject::~LLHUDObject()
@@ -150,6 +146,9 @@ LLHUDObject *LLHUDObject::addHUDObject(const U8 type)
case LL_HUD_ICON:
hud_objectp = new LLHUDIcon(type);
break;
+ case LL_HUD_NAME_TAG:
+ hud_objectp = new LLHUDNameTag(type);
+ break;
default:
llwarns << "Unknown type of hud object:" << (U32) type << llendl;
}
@@ -262,6 +261,7 @@ void LLHUDObject::updateAll()
LLFastTimer ftm(FTM_HUD_UPDATE);
LLHUDText::updateAll();
LLHUDIcon::updateAll();
+ LLHUDNameTag::updateAll();
sortObjects();
}
@@ -310,6 +310,14 @@ void LLHUDObject::renderAllForSelect()
}
// static
+void LLHUDObject::reshapeAll()
+{
+ // only hud objects that use fonts care about window size/scale changes
+ LLHUDText::reshape();
+ LLHUDNameTag::reshape();
+}
+
+// static
void LLHUDObject::sortObjects()
{
sHUDObjects.sort(hud_object_further_away());
diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h
index 6b70d1922c..a370b31a20 100644
--- a/indra/newview/llhudobject.h
+++ b/indra/newview/llhudobject.h
@@ -76,6 +76,9 @@ public:
static void renderAll();
static void renderAllForSelect();
+ // Some objects may need to update when window shape changes
+ static void reshapeAll();
+
static void cleanupHUDObjects();
enum
@@ -96,7 +99,8 @@ public:
LL_HUD_EFFECT_EDIT,
LL_HUD_EFFECT_LOOKAT,
LL_HUD_EFFECT_POINTAT,
- LL_HUD_EFFECT_VOICE_VISUALIZER // Ventrella
+ LL_HUD_EFFECT_VOICE_VISUALIZER, // Ventrella
+ LL_HUD_NAME_TAG
};
protected:
static void sortObjects();
@@ -112,7 +116,6 @@ protected:
BOOL mDead;
BOOL mVisible;
LLVector3d mPositionGlobal;
- BOOL mOnHUDAttachment;
LLPointer<LLViewerObject> mSourceObject;
LLPointer<LLViewerObject> mTargetObject;
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index b14753ff2a..406ad8c51e 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -62,7 +62,7 @@ const F32 HORIZONTAL_PADDING = 15.f;
const F32 VERTICAL_PADDING = 12.f;
const F32 BUFFER_SIZE = 2.f;
const F32 MIN_EDGE_OVERLAP = 3.f;
-F32 HUD_TEXT_MAX_WIDTH = 190.f;
+const F32 HUD_TEXT_MAX_WIDTH = 190.f;
const F32 HUD_TEXT_MAX_WIDTH_NO_BUBBLE = 1000.f;
const F32 RESIZE_TIME = 0.f;
const S32 NUM_OVERLAP_ITERATIONS = 10;
@@ -80,13 +80,13 @@ BOOL LLHUDText::sDisplayText = TRUE ;
bool lltextobject_further_away::operator()(const LLPointer<LLHUDText>& lhs, const LLPointer<LLHUDText>& rhs) const
{
- return (lhs->getDistance() > rhs->getDistance()) ? true : false;
+ return lhs->getDistance() > rhs->getDistance();
}
LLHUDText::LLHUDText(const U8 type) :
LLHUDObject(type),
- mUseBubble(FALSE),
+ mOnHUDAttachment(FALSE),
mVisibleOffScreen(FALSE),
mWidth(0.f),
mHeight(0.f),
@@ -116,112 +116,6 @@ LLHUDText::~LLHUDText()
{
}
-
-BOOL LLHUDText::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render)
-{
- if (!mVisible || mHidden)
- {
- return FALSE;
- }
-
- // don't pick text that isn't bound to a viewerobject or isn't in a bubble
- if (!mSourceObject || mSourceObject->mDrawable.isNull() || !mUseBubble)
- {
- return FALSE;
- }
-
- F32 alpha_factor = 1.f;
- LLColor4 text_color = mColor;
- if (mDoFade)
- {
- if (mLastDistance > mFadeDistance)
- {
- alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange);
- text_color.mV[3] = text_color.mV[3]*alpha_factor;
- }
- }
- if (text_color.mV[3] < 0.01f)
- {
- return FALSE;
- }
-
- mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f));
-
- // scale screen size of borders down
- //RN: for now, text on hud objects is never occluded
-
- LLVector3 x_pixel_vec;
- LLVector3 y_pixel_vec;
-
- if (mOnHUDAttachment)
- {
- x_pixel_vec = LLVector3::y_axis / (F32)gViewerWindow->getWindowWidthScaled();
- y_pixel_vec = LLVector3::z_axis / (F32)gViewerWindow->getWindowHeightScaled();
- }
- else
- {
- LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec);
- }
-
- LLVector3 width_vec = mWidth * x_pixel_vec;
- LLVector3 height_vec = mHeight * y_pixel_vec;
-
- LLCoordGL screen_pos;
- LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
-
- LLVector2 screen_offset;
- screen_offset = updateScreenPos(mPositionOffset);
-
- LLVector3 render_position = mPositionAgent
- + (x_pixel_vec * screen_offset.mV[VX])
- + (y_pixel_vec * screen_offset.mV[VY]);
-
-
- if (mUseBubble)
- {
- LLVector3 bg_pos = render_position
- + (F32)mOffsetY * y_pixel_vec
- - (width_vec / 2.f)
- - (height_vec);
- //LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
-
- LLVector3 v[] =
- {
- bg_pos,
- bg_pos + width_vec,
- bg_pos + width_vec + height_vec,
- bg_pos + height_vec,
- };
-
- if (debug_render)
- {
- gGL.begin(LLRender::LINE_STRIP);
- gGL.vertex3fv(v[0].mV);
- gGL.vertex3fv(v[1].mV);
- gGL.vertex3fv(v[2].mV);
- gGL.vertex3fv(v[3].mV);
- gGL.vertex3fv(v[0].mV);
- gGL.vertex3fv(v[2].mV);
- gGL.end();
- }
-
- LLVector3 dir = end-start;
- F32 t = 0.f;
-
- if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, NULL, NULL, &t, FALSE) ||
- LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, NULL, NULL, &t, FALSE) )
- {
- if (t <= 1.f)
- {
- intersection = start + dir*t;
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
void LLHUDText::render()
{
if (!mOnHUDAttachment && sDisplayText)
@@ -247,21 +141,13 @@ void LLHUDText::renderText(BOOL for_select)
return;
}
- // don't pick text that isn't bound to a viewerobject or isn't in a bubble
- if (for_select &&
- (!mSourceObject || mSourceObject->mDrawable.isNull() || !mUseBubble))
+ // don't pick text
+ if (for_select)
{
return;
}
- if (for_select)
- {
- gGL.getTexUnit(0)->disable();
- }
- else
- {
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- }
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
LLGLState gls_blend(GL_BLEND, for_select ? FALSE : TRUE);
LLGLState gls_alpha(GL_ALPHA_TEST, for_select ? FALSE : TRUE);
@@ -335,152 +221,12 @@ void LLHUDText::renderText(BOOL for_select)
LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE);
LLVector2 screen_offset;
- if (!mUseBubble)
- {
- screen_offset = mPositionOffset;
- }
- else
- {
- screen_offset = updateScreenPos(mPositionOffset);
- }
+ screen_offset = mPositionOffset;
LLVector3 render_position = mPositionAgent
+ (x_pixel_vec * screen_offset.mV[VX])
+ (y_pixel_vec * screen_offset.mV[VY]);
- //if (mOnHUD)
- //{
- // render_position.mV[VY] -= fmodf(render_position.mV[VY], 1.f / (F32)gViewerWindow->getWindowWidthScaled());
- // render_position.mV[VZ] -= fmodf(render_position.mV[VZ], 1.f / (F32)gViewerWindow->getWindowHeightScaled());
- //}
- //else
- //{
- // render_position = LLViewerCamera::getInstance()->roundToPixel(render_position);
- //}
-
- if (mUseBubble)
- {
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- LLUI::pushMatrix();
- {
- LLVector3 bg_pos = render_position
- + (F32)mOffsetY * y_pixel_vec
- - (width_vec / 2.f)
- - (height_vec);
- LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]);
-
- if (for_select)
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- S32 name = mSourceObject->mGLName;
- LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name);
- gGL.color4ubv(coloru.mV);
- gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
- LLUI::popMatrix();
- return;
- }
- else
- {
- gGL.getTexUnit(0)->bind(imagep->getImage());
-
- gGL.color4fv(bg_color.mV);
- gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec);
-
- if ( mLabelSegments.size())
- {
- LLUI::pushMatrix();
- {
- gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor);
- LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec;
- LLVector3 label_offset = height_vec - label_height;
- LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]);
- gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height);
- }
- LLUI::popMatrix();
- }
- }
-
- BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f;
- BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f);
-
- // draw line segments pointing to parent object
- if (!mOffscreen && (outside_width || outside_height))
- {
- LLUI::pushMatrix();
- {
- gGL.color4fv(bg_color.mV);
- LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec);
- target_pos += (width_vec / 2.f);
- target_pos += mVertAlignment == ALIGN_VERT_CENTER ? (height_vec * 0.5f) : LLVector3::zero;
- target_pos -= 3.f * x_pixel_vec;
- target_pos -= 6.f * y_pixel_vec;
- LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]);
- gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec);
- }
- LLUI::popMatrix();
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE);
-
- LLVector3 box_center_offset;
- box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f);
- LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]);
- gGL.color4fv(bg_color.mV);
- LLUI::setLineWidth(2.0);
- gGL.begin(LLRender::LINES);
- {
- if (outside_width)
- {
- LLVector3 vert;
- // draw line in x then y
- if (mPositionOffset.mV[VX] < 0.f)
- {
- // start at right edge
- vert = width_vec * 0.5f;
- gGL.vertex3fv(vert.mV);
- }
- else
- {
- // start at left edge
- vert = width_vec * -0.5f;
- gGL.vertex3fv(vert.mV);
- }
- vert = -mPositionOffset.mV[VX] * x_pixel_vec;
- gGL.vertex3fv(vert.mV);
- gGL.vertex3fv(vert.mV);
- vert -= mPositionOffset.mV[VY] * y_pixel_vec;
- vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
- gGL.vertex3fv(vert.mV);
- }
- else
- {
- LLVector3 vert;
- // draw line in y then x
- if (mPositionOffset.mV[VY] < 0.f)
- {
- // start at top edge
- vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec);
- gGL.vertex3fv(vert.mV);
- }
- else
- {
- // start at bottom edge
- vert = (height_vec * -0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec);
- gGL.vertex3fv(vert.mV);
- }
- vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec;
- vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero);
- gGL.vertex3fv(vert.mV);
- }
- }
- gGL.end();
- LLUI::setLineWidth(1.0);
-
- }
- }
- LLUI::popMatrix();
- }
-
F32 y_offset = (F32)mOffsetY;
// Render label
@@ -556,10 +302,6 @@ void LLHUDText::renderText(BOOL for_select)
}
/// Reset the default color to white. The renderer expects this to be the default.
gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f);
- if (for_select)
- {
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- }
}
void LLHUDText::setString(const std::string &text_utf8)
@@ -599,7 +341,7 @@ void LLHUDText::addLine(const std::string &text_utf8,
U32 line_length = 0;
do
{
- F32 max_pixels = (mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE);
+ F32 max_pixels = HUD_TEXT_MAX_WIDTH_NO_BUBBLE;
S32 segment_length = font->maxDrawableChars(iter->substr(line_length).c_str(), max_pixels, wline.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
LLHUDTextSegment segment(iter->substr(line_length, segment_length), style, color, font);
mTextSegments.push_back(segment);
@@ -611,42 +353,6 @@ void LLHUDText::addLine(const std::string &text_utf8,
}
}
-void LLHUDText::setLabel(const std::string &label_utf8)
-{
- mLabelSegments.clear();
- addLabel(label_utf8);
-}
-
-void LLHUDText::addLabel(const std::string& label_utf8)
-{
- LLWString wstr = utf8string_to_wstring(label_utf8);
- if (!wstr.empty())
- {
- LLWString seps(utf8str_to_wstring("\r\n"));
- LLWString empty;
-
- typedef boost::tokenizer<boost::char_separator<llwchar>, LLWString::const_iterator, LLWString > tokenizer;
- boost::char_separator<llwchar> sep(seps.c_str(), empty.c_str(), boost::keep_empty_tokens);
-
- tokenizer tokens(wstr, sep);
- tokenizer::iterator iter = tokens.begin();
-
- while (iter != tokens.end())
- {
- U32 line_length = 0;
- do
- {
- S32 segment_length = mFontp->maxDrawableChars(iter->substr(line_length).c_str(), mUseBubble ? HUD_TEXT_MAX_WIDTH : HUD_TEXT_MAX_WIDTH_NO_BUBBLE, wstr.length(), LLFontGL::WORD_BOUNDARY_IF_POSSIBLE);
- LLHUDTextSegment segment(iter->substr(line_length, segment_length), LLFontGL::NORMAL, mColor, mFontp);
- mLabelSegments.push_back(segment);
- line_length += segment_length;
- }
- while (line_length != iter->size());
- ++iter;
- }
- }
-}
-
void LLHUDText::setDropShadow(const BOOL do_shadow)
{
mDropShadow = do_shadow;
@@ -898,122 +604,6 @@ void LLHUDText::updateAll()
// sort back to front for rendering purposes
std::sort(sVisibleTextObjects.begin(), sVisibleTextObjects.end(), lltextobject_further_away());
std::sort(sVisibleHUDTextObjects.begin(), sVisibleHUDTextObjects.end(), lltextobject_further_away());
-
- // iterate from front to back, and set LOD based on current screen coverage
- F32 screen_area = (F32)(gViewerWindow->getWindowWidthScaled() * gViewerWindow->getWindowHeightScaled());
- F32 current_screen_area = 0.f;
- std::vector<LLPointer<LLHUDText> >::reverse_iterator r_it;
- for (r_it = sVisibleTextObjects.rbegin(); r_it != sVisibleTextObjects.rend(); ++r_it)
- {
- LLHUDText* textp = (*r_it);
- if (textp->mUseBubble)
- {
- if (current_screen_area / screen_area > LOD_2_SCREEN_COVERAGE)
- {
- textp->setLOD(3);
- }
- else if (current_screen_area / screen_area > LOD_1_SCREEN_COVERAGE)
- {
- textp->setLOD(2);
- }
- else if (current_screen_area / screen_area > LOD_0_SCREEN_COVERAGE)
- {
- textp->setLOD(1);
- }
- else
- {
- textp->setLOD(0);
- }
- textp->updateSize();
- // find on-screen position and initialize collision rectangle
- textp->mTargetPositionOffset = textp->updateScreenPos(LLVector2::zero);
- current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight());
- }
- }
-
- LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat();
- F32 camera_vel = camera_vel_stat->getCurrent();
- if (camera_vel > MAX_STABLE_CAMERA_VELOCITY)
- {
- return;
- }
-
- VisibleTextObjectIterator src_it;
-
- for (S32 i = 0; i < NUM_OVERLAP_ITERATIONS; i++)
- {
- for (src_it = sVisibleTextObjects.begin(); src_it != sVisibleTextObjects.end(); ++src_it)
- {
- LLHUDText* src_textp = (*src_it);
-
- if (!src_textp->mUseBubble)
- {
- continue;
- }
- VisibleTextObjectIterator dst_it = src_it;
- ++dst_it;
- for (; dst_it != sVisibleTextObjects.end(); ++dst_it)
- {
- LLHUDText* dst_textp = (*dst_it);
-
- if (!dst_textp->mUseBubble)
- {
- continue;
- }
- if (src_textp->mSoftScreenRect.overlaps(dst_textp->mSoftScreenRect))
- {
- LLRectf intersect_rect = src_textp->mSoftScreenRect;
- intersect_rect.intersectWith(dst_textp->mSoftScreenRect);
- intersect_rect.stretch(-BUFFER_SIZE * 0.5f);
-
- F32 src_center_x = src_textp->mSoftScreenRect.getCenterX();
- F32 src_center_y = src_textp->mSoftScreenRect.getCenterY();
- F32 dst_center_x = dst_textp->mSoftScreenRect.getCenterX();
- F32 dst_center_y = dst_textp->mSoftScreenRect.getCenterY();
- F32 intersect_center_x = intersect_rect.getCenterX();
- F32 intersect_center_y = intersect_rect.getCenterY();
- LLVector2 force = lerp(LLVector2(dst_center_x - intersect_center_x, dst_center_y - intersect_center_y),
- LLVector2(intersect_center_x - src_center_x, intersect_center_y - src_center_y),
- 0.5f);
- force.setVec(dst_center_x - src_center_x, dst_center_y - src_center_y);
- force.normVec();
-
- LLVector2 src_force = -1.f * force;
- LLVector2 dst_force = force;
-
- LLVector2 force_strength;
- F32 src_mult = dst_textp->mMass / (dst_textp->mMass + src_textp->mMass);
- F32 dst_mult = 1.f - src_mult;
- F32 src_aspect_ratio = src_textp->mSoftScreenRect.getWidth() / src_textp->mSoftScreenRect.getHeight();
- F32 dst_aspect_ratio = dst_textp->mSoftScreenRect.getWidth() / dst_textp->mSoftScreenRect.getHeight();
- src_force.mV[VY] *= src_aspect_ratio;
- src_force.normVec();
- dst_force.mV[VY] *= dst_aspect_ratio;
- dst_force.normVec();
-
- src_force.mV[VX] *= llmin(intersect_rect.getWidth() * src_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
- src_force.mV[VY] *= llmin(intersect_rect.getHeight() * src_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
- dst_force.mV[VX] *= llmin(intersect_rect.getWidth() * dst_mult, intersect_rect.getHeight() * SPRING_STRENGTH);
- dst_force.mV[VY] *= llmin(intersect_rect.getHeight() * dst_mult, intersect_rect.getWidth() * SPRING_STRENGTH);
-
- src_textp->mTargetPositionOffset += src_force;
- dst_textp->mTargetPositionOffset += dst_force;
- src_textp->mTargetPositionOffset = src_textp->updateScreenPos(src_textp->mTargetPositionOffset);
- dst_textp->mTargetPositionOffset = dst_textp->updateScreenPos(dst_textp->mTargetPositionOffset);
- }
- }
- }
- }
-
- VisibleTextObjectIterator this_object_it;
- for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it)
- {
- if (!(*this_object_it)->mUseBubble)
- {
- continue;
- }
- (*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC));
- }
}
void LLHUDText::setLOD(S32 lod)
@@ -1088,22 +678,6 @@ void LLHUDText::shift(const LLVector3& offset)
mPositionAgent += offset;
}
-//static
-void LLHUDText::addPickable(std::set<LLViewerObject*> &pick_list)
-{
- //this might put an object on the pick list a second time, overriding it's mGLName, which is ok
- // *FIX: we should probably cull against pick frustum
- VisibleTextObjectIterator text_it;
- for (text_it = sVisibleTextObjects.begin(); text_it != sVisibleTextObjects.end(); ++text_it)
- {
- if (!(*text_it)->mUseBubble)
- {
- continue;
- }
- pick_list.insert((*text_it)->mSourceObject);
- }
-}
-
//static
// called when UI scale changes, to flush font width caches
void LLHUDText::reshape()
diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h
index 8219358cc1..3acd2934e1 100644
--- a/indra/newview/llhudtext.h
+++ b/indra/newview/llhudtext.h
@@ -92,15 +92,17 @@ public:
} EVertAlignment;
public:
+ // Set entire string, eliminating existing lines
void setString(const std::string& text_utf8);
-// void setString(const LLWString &wstring);
+
void clearString();
+
+ // Add text a line at a time, allowing custom formatting
void addLine(const std::string &text_utf8, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL, const LLFontGL* font = NULL);
-// void addLine(const LLWString &wtext, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL, const LLFontGL* font = NULL);
- void setLabel(const std::string& label_utf8);
-// void setLabel(const LLWString &label);
- void addLabel(const std::string& label_utf8);
+
void setDropShadow(const BOOL do_shadow);
+
+ // Sets the default font for lines with no font specified
void setFont(const LLFontGL* font);
void setColor(const LLColor4 &color);
void setAlpha(F32 alpha);
@@ -120,7 +122,6 @@ public:
/*virtual*/ void markDead();
friend class LLHUDObject;
/*virtual*/ F32 getDistance() const { return mLastDistance; }
- void setUseBubble(BOOL use_bubble) { mUseBubble = use_bubble; }
S32 getLOD() { return mLOD; }
BOOL getVisible() { return mVisible; }
BOOL getHidden() const { return mHidden; }
@@ -128,13 +129,11 @@ public:
void setOnHUDAttachment(BOOL on_hud) { mOnHUDAttachment = on_hud; }
void shift(const LLVector3& offset);
- BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3& intersection, BOOL debug_render = FALSE);
-
static void shiftAll(const LLVector3& offset);
static void renderAllHUD();
- static void addPickable(std::set<LLViewerObject*> &pick_list);
static void reshape();
static void setDisplayText(BOOL flag) { sDisplayText = flag ; }
+
protected:
LLHUDText(const U8 type);
@@ -147,8 +146,8 @@ protected:
private:
~LLHUDText();
- BOOL mOnHUD;
- BOOL mUseBubble;
+ BOOL mOnHUDAttachment;
+// BOOL mUseBubble;
BOOL mDropShadow;
BOOL mDoFade;
F32 mFadeRange;
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 6347090f71..d920e96ded 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -52,7 +52,7 @@
#include "lltooltip.h"
#include "llworld.h"
#include "llstring.h"
-#include "llhudtext.h"
+#include "llhudnametag.h"
#include "lldrawable.h"
#include "xform.h"
#include "llsky.h"
@@ -1193,7 +1193,7 @@ void LLViewerObjectList::generatePickList(LLCamera &camera)
}
}
- LLHUDText::addPickable(mSelectPickList);
+ LLHUDNameTag::addPickable(mSelectPickList);
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
iter != LLCharacter::sInstances.end(); ++iter)
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ea1afafe85..16b8711561 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -120,6 +120,7 @@
#include "llglheaders.h"
#include "lltooltip.h"
#include "llhudmanager.h"
+#include "llhudobject.h"
#include "llhudview.h"
#include "llimagebmp.h"
#include "llimagej2c.h"
@@ -1902,7 +1903,7 @@ void LLViewerWindow::reshape(S32 width, S32 height)
// clear font width caches
if (display_scale_changed)
{
- LLHUDText::reshape();
+ LLHUDObject::reshapeAll();
}
sendShapeToSim();
@@ -4132,7 +4133,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
send_agent_pause();
//rescale fonts
initFonts(scale_factor);
- LLHUDText::reshape();
+ LLHUDObject::reshapeAll();
}
S32 output_buffer_offset_y = 0;
@@ -4261,7 +4262,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
if (high_res)
{
initFonts(1.f);
- LLHUDText::reshape();
+ LLHUDObject::reshapeAll();
}
// Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index b56e4d3d2e..e039544779 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -63,7 +63,8 @@
#include "llheadrotmotion.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llhudtext.h"
+#include "llhudnametag.h"
+#include "llhudtext.h" // for mText/mDebugText
#include "llkeyframefallmotion.h"
#include "llkeyframestandmotion.h"
#include "llkeyframewalkmotion.h"
@@ -2750,14 +2751,14 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
if (!mNameText)
{
- mNameText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
+ mNameText = static_cast<LLHUDNameTag*>( LLHUDObject::addHUDObject(
+ LLHUDObject::LL_HUD_NAME_TAG) );
mNameText->setMass(10.f);
mNameText->setSourceObject(this);
- mNameText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
+ mNameText->setVertAlignment(LLHUDNameTag::ALIGN_VERT_TOP);
mNameText->setVisibleOffScreen(TRUE);
mNameText->setMaxLines(11);
mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
- mNameText->setUseBubble(TRUE);
sNumVisibleChatBubbles++;
new_name = TRUE;
}
@@ -2896,7 +2897,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
{
mNameText->setDropShadow(TRUE);
mNameText->setFont(LLFontGL::getFontSansSerif());
- mNameText->setTextAlignment(LLHUDText::ALIGN_TEXT_LEFT);
+ mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT);
mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f);
char line[MAX_STRING]; /* Flawfinder: ignore */
@@ -2967,7 +2968,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name)
else
{
// ...not using chat bubbles, just names
- mNameText->setTextAlignment(LLHUDText::ALIGN_TEXT_CENTER);
+ mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_CENTER);
mNameText->setFadeDistance(CHAT_NORMAL_RADIUS, 5.f);
mNameText->setVisibleOffScreen(FALSE);
}
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index b63e3b2ebd..c31369358c 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -65,7 +65,7 @@ extern const LLUUID ANIM_AGENT_WALK_ADJUST;
class LLTexLayerSet;
class LLVoiceVisualizer;
-class LLHUDText;
+class LLHUDNameTag;
class LLHUDEffectSpiral;
class LLTexGlobalColor;
class LLVOAvatarBoneInfo;
@@ -842,7 +842,7 @@ private:
//--------------------------------------------------------------------
public:
LLFrameTimer mChatTimer;
- LLPointer<LLHUDText> mNameText;
+ LLPointer<LLHUDNameTag> mNameText;
private:
LLFrameTimer mTimeVisible;
std::deque<LLChat> mChats;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 4de1560f16..31c245dc57 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -69,6 +69,7 @@
#include "llfloaterreg.h"
#include "llgldbg.h"
#include "llhudmanager.h"
+#include "llhudnametag.h"
#include "llhudtext.h"
#include "lllightconstants.h"
#include "llresmgr.h"
@@ -2080,6 +2081,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset)
}
LLHUDText::shiftAll(offset);
+ LLHUDNameTag::shiftAll(offset);
display_update_camera();
}
@@ -5269,7 +5271,8 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start,
++iter)
{
LLVOAvatar* av = (LLVOAvatar*) *iter;
- if (av->mNameText.notNull() && av->mNameText->lineSegmentIntersect(start, local_end, position))
+ if (av->mNameText.notNull()
+ && av->mNameText->lineSegmentIntersect(start, local_end, position))
{
drawable = av->mDrawable;
local_end = position;