void LLHUDText::updateSize() { F32 height = 0.f; F32 width = 0.f; S32 max_lines = getMaxLines(); 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() - 1; // correction factor to match legacy font metrics width = llmax(width, llmin(iter->getWidth(fontp), HUD_TEXT_MAX_WIDTH)); ++iter; } if (width == 0.f) { return; } width += HORIZONTAL_PADDING; height += VERTICAL_PADDING; // *TODO: Could do some sort of timer-based resize logic here F32 u = 1.f; mWidth = llmax(width, lerp(mWidth, (F32)width, u)); mHeight = llmax(height, lerp(mHeight, (F32)height, u)); }
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(); height += LINE_PADDING; width = llmax(width, llmin(iter->getWidth(fontp), HUD_TEXT_MAX_WIDTH)); ++iter; } // Don't want line spacing under the last line if (height > 0.f) { height -= LINE_PADDING; } 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; // *TODO: Could do a timer-based resize here //mWidth = llmax(width, lerp(mWidth, (F32)width, u)); //mHeight = llmax(height, lerp(mHeight, (F32)height, u)); mWidth = width; mHeight = height; }
bool TextInputView::onKeyDown(unsigned char const& key) { if ( !getHasFocus() ) { return false; } else if ( 32 <= key && key <= 126 ) { if (_content.length() < getMaxLines() * getMaxCharsPerLine()) _content += key; return true; } else { switch (key) { case 8: //backspace //cerr << "backspace" << endl; if (_content.length() > 0) { string::iterator it = _content.end(); --it; _content.erase(it); } break; case 127: // delete implemented as backspace because on Mac OSX, the backspace // key (delete) sends the ascii value for delete (127), // whereas fn+delete, which simulates the forward // deletion property of a linux or windows keyborad, // sends the ascii value for backspace (8) //cerr << "delete" << endl; if (_content.length() > 0) { string::iterator it = _content.end(); --it; _content.erase(it); } break; default: break; } return true; } }
void LLHUDText::renderText() { if (!mVisible || mHidden) { return; } gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); LLGLState gls_blend(GL_BLEND, TRUE); LLGLState gls_alpha(GL_ALPHA_TEST, 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("ObjectBubbleColor"); 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; if (mOnHUDAttachment) { x_pixel_vec = LLVector3::y_axis / (F32)gViewerWindow->getWorldViewWidthRaw(); y_pixel_vec = LLVector3::z_axis / (F32)gViewerWindow->getWorldViewHeightRaw(); } else { 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; LLVector2 screen_offset; screen_offset = mPositionOffset; LLVector3 render_position = mPositionAgent + (x_pixel_vec * screen_offset.mV[VX]) + (y_pixel_vec * screen_offset.mV[VY]); F32 y_offset = (F32)mOffsetY; // Render label { gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } // 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() - 1; // correction factor to match legacy font metrics U8 style = segment_iter->mStyle; LLFontGL::ShadowType 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, mOnHUDAttachment); } } /// Reset the default color to white. The renderer expects this to be the default. gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f); }
void TextInputView::draw() { // Draw the rect drawRectWithColor(this->getGlobalBounds(), this->getColor()); // Split up and draw the text based on the size of the rectangle // _lines.empty(); // start anew _lines.resize(0); string temp = ""; int cnt = 0; const int maxChars = getMaxCharsPerLine(); const int maxLines = getMaxLines(); for (string::iterator it = _content.begin(); it != _content.end(); ++it) { if (_lines.size() >= maxLines ) { break; } temp += (*it); cnt++; if (cnt >= maxChars) { _lines.push_back(temp); temp.clear(); cnt = 0; } } // add a cursor if has focus // Currently the cursor is always at the end, // this will change when we make it so that the // position can be set with a mouse click or the // arrow keys if ( getHasFocus() ) { if (temp.length() > 0) { temp += "~"; // there is more to push, so stick the cursor on the last line } // hell, this seems to work okay visually... } _lines.push_back(temp); // push the rest CGRect bounds = this->getGlobalBounds(); int x = bounds.getX() + 5; int y = bounds.getY() + 14; for(vector<string>::iterator it = _lines.begin(); it != _lines.end(); ++it) { drawStringWithColorAndFormat( (*it), this->getTextColor(), CGPoint( x, y), "small fixed"); y += this->getLineSpacing(); } // Draw the border if (getHasFocus()) drawBorderWithColor(bounds, CGColor(0.0,0.0,0.6,1.0)); else drawBorderWithColor(bounds, CGColor(0.0,0.0,0.0,1.0)); // Draw the subviews this->callDrawOnSubViews(); }
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 // <FS:Ansariel> Performance improvement //LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Rect"); // *TODO: make this a per-text setting //LLColor4 bg_color = LLUIColorTable::instance().getColor("NameTagBackground"); //bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); static LLUIColor s_bg_color = LLUIColorTable::instance().getColor("NameTagBackground"); static LLCachedControl<F32> chatBubbleOpacity(gSavedSettings, "ChatBubbleOpacity"); LLColor4 bg_color = s_bg_color.get(); F32 color_alpha = chatBubbleOpacity * alpha_factor; bg_color.setAlpha(color_alpha); // </FS:Ansariel> // 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; mRadius = (width_vec + height_vec).magVec() * 0.5f; LLCoordGL screen_pos; LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE); LLVector2 screen_offset = updateScreenPos(mPositionOffset); LLVector3 render_position = mPositionAgent + (x_pixel_vec * screen_offset.mV[VX]) + (y_pixel_vec * screen_offset.mV[VY]); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLRect screen_rect; screen_rect.setCenterAndSize(0, static_cast<S32>(lltrunc(-mHeight / 2 + mOffsetY)), static_cast<S32>(lltrunc(mWidth)), static_cast<S32>(lltrunc(mHeight))); // <FS:Ansariel> Performance improvement //imagep->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); mRoundedRectImg->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); // </FS:Ansariel> if (mLabelSegments.size()) { // <FS:Ansariel> Performance improvement //LLUIImagePtr rect_top_image = LLUI::getUIImage("Rounded_Rect_Top"); LLRect label_top_rect = screen_rect; const S32 label_height = ll_round((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f))); label_top_rect.mBottom = label_top_rect.mTop - label_height; LLColor4 label_top_color = text_color; // <FS:Ansariel> Performance improvement //label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor; label_top_color.mV[VALPHA] = color_alpha; // </FS:Ansariel> // <FS:Ansariel> Performance improvement //rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); mRoundedRectTopImg->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); // </FS:Ansariel> } 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(); y_offset -= LINE_PADDING; U8 style = segment_iter->mStyle; LLFontGL::ShadowType 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); // *HACK x_offset += 1; } 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); } }