////////////////////////////////////////////////////////////////////////////// // called (infrequently) when the color changes so the subject of the swatch can be updated. void LLColorSwatchCtrl::onColorChanged ( void* data, EColorPickOp pick_op ) { LLColorSwatchCtrl* subject = ( LLColorSwatchCtrl* )data; if ( subject ) { LLFloaterColorPicker* pickerp = (LLFloaterColorPicker*)subject->mPickerHandle.get(); if (pickerp) { // move color across from selector to internal widget storage LLColor4 updatedColor ( pickerp->getCurR (), pickerp->getCurG (), pickerp->getCurB (), subject->mColor.mV[VALPHA] ); // keep current alpha subject->mColor = updatedColor; subject->setControlValue(updatedColor.getValue()); if (pick_op == COLOR_CANCEL && subject->mOnCancelCallback) { subject->mOnCancelCallback(subject, subject->mCallbackUserData); } else if (pick_op == COLOR_SELECT && subject->mOnSelectCallback) { subject->mOnSelectCallback(subject, subject->mCallbackUserData); } else { // just commit change subject->onCommit (); } } } }
LLColor4U lggBeamMaps::beamColorFromData(lggBeamsColors data) { F32 r, g, b; LLColor4 output; LLColor4U toReturn; F32 timeinc = timer.getElapsedTimeF32()*0.3f*((data.rotateSpeed+.01f)) * (360/(data.endHue-data.startHue)); S32 diference = llround(data.endHue - data.startHue); if(diference == 360 || diference == 720) { //full rainbow //liner one hslToRgb(fmod(timeinc,1.0f), 1.0f, 0.5f, r, g, b); }else { F32 variance = ((data.endHue/360.0f)-(data.startHue/360.0f))/2.0f; hslToRgb((data.startHue/360.0f) + variance + (sinf(timeinc)*(variance)), 1.0f, 0.5f, r, g, b); } output.set(r, g, b); toReturn.setVecScaleClamp(output); return toReturn; }
//static BOOL LLUICtrlFactory::getAttributeColor(LLXMLNodePtr node, const std::string& name, LLColor4& color) { std::string colorstring; BOOL res = node->getAttributeString(name.c_str(), colorstring); if (res && LLUI::sColorsGroup) { if (LLUI::sColorsGroup->controlExists(colorstring)) { color.setVec(LLUI::sColorsGroup->getColor(colorstring)); } else { res = FALSE; } } if (!res) { res = LLColor4::parseColor(colorstring, &color); } if (!res) { res = node->getAttributeColor(name.c_str(), color); } return res; }
//static void LLViewerChat::getChatColor(const LLChat& chat, LLColor4& r_color) { if(chat.mMuted) { r_color= LLUIColorTable::instance().getColor("LtGray"); } else { switch(chat.mSourceType) { case CHAT_SOURCE_SYSTEM: r_color = LLUIColorTable::instance().getColor("SystemChatColor"); break; case CHAT_SOURCE_AGENT: if (chat.mFromID.isNull() || SYSTEM_FROM == chat.mFromName) { r_color = LLUIColorTable::instance().getColor("SystemChatColor"); } else { if(gAgentID == chat.mFromID) { r_color = LLUIColorTable::instance().getColor("UserChatColor"); } else { r_color = LLUIColorTable::instance().getColor("AgentChatColor"); } } break; case CHAT_SOURCE_OBJECT: if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) { r_color = LLUIColorTable::instance().getColor("ScriptErrorColor"); } else if ( chat.mChatType == CHAT_TYPE_OWNER ) { r_color = LLUIColorTable::instance().getColor("llOwnerSayChatColor"); } else { r_color = LLUIColorTable::instance().getColor("ObjectChatColor"); } break; default: r_color.setToWhite(); } if (!chat.mPosAgent.isExactlyZero()) { LLVector3 pos_agent = gAgent.getPositionAgent(); F32 distance = dist_vec(pos_agent, chat.mPosAgent); if (distance > gAgent.getNearChatRadius()) { // diminish far-off chat r_color.mV[VALPHA] = 0.8f; } } } }
void LLControlGroup::setColor4(const LLString& name, const LLColor4 &val) { LLControlBase* control = getControl(name); if (control && control->isType(TYPE_COL4)) { control->set(val.getValue()); } else { CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl; } }
void init_colors() { gTrackColor = LLColor4::red; gDisabledTrackColor.setVec( 0.5f, 0.f, 0.f, 1.f ); gLandmarkMapColor = LLColor4::red; gLocationMapColor.setVec( 0.f, 0.72f, 1.f, 1.f); gTelehubMapColor.setVec( 0.9f, 0.9f, 0.f, 1.f); // dk yellow gEventColor.setVec( 1.f, 0.5f, 1.f, 1.f ); gPopularColor.setVec( 1.f, 0.0f, 0.f, 1.f ); gPickColor.setVec( 1.f, 0.0f, 0.f, 1.f ); gHomeColor.setVec( 0.f, 0.5f, 1.f, 1.f ); }
void LLControlGroup::setColor4(const std::string& name, const LLColor4 &val) { LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_COL4)) { control->set(val.getValue()); if(mChangeCallback) mChangeCallback(name,llformat("<%f,%f,%f,%f>",val.mV[VX],val.mV[VY],val.mV[VZ],val.mV[VW])); } else { CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl; } }
void init_colors() { gTrackColor = LLColor4::red; gDisabledTrackColor.setVec( 0.5f, 0.f, 0.f, 1.f ); gSelfMapColor = LLColor4::white; gAvatarMapColor = LLColor4::green; gFriendMapColor = LLColor4::yellow; // fleshy color //gAvatarMapColor.setVec( 255.f/255.f, 223.f/255.f, 170.f/255.f, 1.f); gLandmarkMapColor = LLColor4::red; gLocationMapColor.setVec( 0.f, 0.72f, 1.f, 1.f); gTelehubMapColor.setVec( 0.9f, 0.9f, 0.f, 1.f); // dk yellow gFrustumMapColor.setVec( 1.f, 1.f, 1.f, 0.08f); gRotatingFrustumMapColor.setVec(1.f, 1.f, 1.f, 0.2f); gEventColor.setVec( 1.f, 0.5f, 1.f, 1.f ); gPopularColor.setVec( 1.f, 0.0f, 0.f, 1.f ); gPickColor.setVec( 1.f, 0.0f, 0.f, 1.f ); gHomeColor.setVec( 0.f, 0.5f, 1.f, 1.f ); }
//Generate highlight color segments for this paragraph. Pass in default color of paragraph. void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color) { LLSD paragraph_color_segments; LLColor4 lcolor=color; paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText); LLSD color_sd = color.getValue(); paragraph_color_segments[0]["color"]=color_sd; for(LLSD::array_const_iterator color_segment_it = paragraph_color_segments.beginArray(); color_segment_it != paragraph_color_segments.endArray(); ++color_segment_it) { LLSD color_llsd = (*color_segment_it)["color"]; std::string color_str = (*color_segment_it)["text"].asString(); ParagraphColorSegment color_segment; color_segment.mColor.setValue(color_llsd); color_segment.mNumChars = color_str.length(); mParagraphColorSegments.push_back(color_segment); } }
BOOL LLControlGroup::declareColor4(const LLString& name, const LLColor4 &initial_val, const LLString& comment, BOOL persist ) { return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist); }
/** * Redraws the avatar list * Only does anything if the avatar list is visible. * @author Dale Glass */ void LLFloaterAvatarList::refreshAvatarList() { // Don't update list when interface is hidden if (!sInstance->getVisible()) return; // We rebuild the list fully each time it's refreshed // The assumption is that it's faster to refill it and sort than // to rebuild the whole list. LLDynamicArray<LLUUID> selected = mAvatarList->getSelectedIDs(); S32 scrollpos = mAvatarList->getScrollPos(); mAvatarList->deleteAllItems(); LLVector3d mypos = gAgent.getPositionGlobal(); LLVector3d posagent; posagent.setVec(gAgent.getPositionAgent()); LLVector3d simpos = mypos - posagent; std::map<LLUUID, LLAvatarListEntry>::iterator iter; for (iter = mAvatars.begin(); iter != mAvatars.end(); iter++) { LLSD element; LLUUID av_id; LLAvatarListEntry *entry = &iter->second; // Skip if avatar hasn't been around if (entry->isDead()) { continue; } av_id = entry->getID(); LLVector3d position = entry->getPosition(); BOOL UnknownAltitude = false; LLVector3d delta = position - mypos; F32 distance = (F32)delta.magVec(); if (position.mdV[VZ] == 0.0) { UnknownAltitude = true; distance = 9000.0; } delta.mdV[2] = 0.0f; F32 side_distance = (F32)delta.magVec(); // HACK: Workaround for an apparent bug: // sometimes avatar entries get stuck, and are registered // by the client as perpetually moving in the same direction. // this makes sure they get removed from the visible list eventually //jcool410 -- this f***s up seeing dueds thru minimap data > 1024m away, so, lets just say > 2048m to the side is bad //aka 8 sims if (side_distance > 2048.0f) { continue; } if (av_id.isNull()) { //llwarns << "Avatar with null key somehow got into the list!" << llendl; continue; } element["id"] = av_id; element["columns"][LIST_MARK]["column"] = "marked"; element["columns"][LIST_MARK]["type"] = "text"; if (entry->isMarked()) { element["columns"][LIST_MARK]["value"] = "X"; element["columns"][LIST_MARK]["color"] = LLColor4::blue.getValue(); element["columns"][LIST_MARK]["font-style"] = "BOLD"; } else { element["columns"][LIST_MARK]["value"] = ""; } element["columns"][LIST_AVATAR_NAME]["column"] = "avatar_name"; element["columns"][LIST_AVATAR_NAME]["type"] = "text"; element["columns"][LIST_AVATAR_NAME]["value"] = entry->getName().c_str(); if (entry->isFocused()) { element["columns"][LIST_AVATAR_NAME]["font-style"] = "BOLD"; } if (LLMuteList::getInstance()->isMuted(av_id)) { element["columns"][LIST_AVATAR_NAME]["color"] = LLColor4::red2.getValue(); } char temp[32]; LLColor4 color = LLColor4::black; element["columns"][LIST_DISTANCE]["column"] = "distance"; element["columns"][LIST_DISTANCE]["type"] = "text"; if (UnknownAltitude) { strcpy(temp, "?"); if (entry->isDrawn()) { color = LLColor4::red; } } else { if (distance < 100.0) { snprintf(temp, sizeof(temp), "%.1f", distance); if (distance > 20.0f) { color = LLColor4::yellow1; } else { color = LLColor4::green2; } } else { if (entry->isDrawn()) { color = LLColor4::red; } snprintf(temp, sizeof(temp), "%d", (S32)distance); } } element["columns"][LIST_DISTANCE]["value"] = temp; element["columns"][LIST_DISTANCE]["color"] = color.getValue(); position = position - simpos; S32 x = (S32)position.mdV[VX]; S32 y = (S32)position.mdV[VY]; if (x >= 0 && x <= 256 && y >= 0 && y <= 256) { snprintf(temp, sizeof(temp), "%d, %d", x, y); } else { temp[0] = '\0'; if (y < 0) { strcat(temp, "S"); } else if (y > 256) { strcat(temp, "N"); } if (x < 0) { strcat(temp, "W"); } else if (x > 256) { strcat(temp, "E"); } } element["columns"][LIST_POSITION]["column"] = "position"; element["columns"][LIST_POSITION]["type"] = "text"; element["columns"][LIST_POSITION]["value"] = temp; element["columns"][LIST_ALTITUDE]["column"] = "altitude"; element["columns"][LIST_ALTITUDE]["type"] = "text"; if (UnknownAltitude) { strcpy(temp, "?"); } else { snprintf(temp, sizeof(temp), "%d", (S32)position.mdV[VZ]); } element["columns"][LIST_ALTITUDE]["value"] = temp; // Add to list mAvatarList->addElement(element, ADD_BOTTOM); } // finish mAvatarList->sortItems(); mAvatarList->selectMultiple(selected); mAvatarList->setScrollPos(scrollpos); // llinfos << "radar refresh: done" << llendl; }
void LLTextureBar::draw() { if (!mImagep) { return; } LLColor4 color; if (mImagep->getID() == LLAppViewer::getTextureFetch()->mDebugID) { color = LLColor4::cyan2; } else if (mHilite) { S32 idx = llclamp(mHilite,1,3); if (idx==1) color = LLColor4::orange; else if (idx==2) color = LLColor4::yellow; else color = LLColor4::pink2; } else if (mImagep->mDontDiscard) { color = LLColor4::green4; } else if (mImagep->getBoostLevel()) { color = LLColor4::magenta; } else if (mImagep->getDecodePriority() == 0.0f) { color = LLColor4::grey; color[VALPHA] = .7f; } else { color = LLColor4::white; color[VALPHA] = .7f; } // We need to draw: // The texture UUID or name // The progress bar for the texture, highlighted if it's being download // Various numerical stats. std::string tex_str; S32 left, right; S32 top = 0; S32 bottom = top + 6; LLColor4 clr; LLGLSUIDefault gls_ui; // Name, pixel_area, requested pixel area, decode priority std::string uuid_str; mImagep->mID.toString(uuid_str); uuid_str = uuid_str.substr(0,7); if (mTextureView->mOrderFetch) { tex_str = llformat("%s %7.0f %d(%d) 0x%08x(%8.0f)", uuid_str.c_str(), mImagep->mMaxVirtualSize, mImagep->mDesiredDiscardLevel, mImagep->mRequestedDiscardLevel, mImagep->mFetchPriority, mImagep->getDecodePriority()); } else { tex_str = llformat("%s %7.0f %d(%d) %8.0f(0x%08x)", uuid_str.c_str(), mImagep->mMaxVirtualSize, mImagep->mDesiredDiscardLevel, mImagep->mRequestedDiscardLevel, mImagep->getDecodePriority(), mImagep->mFetchPriority); } LLFontGL::sMonospace->renderUTF8(tex_str, 0, title_x1, getRect().getHeight(), color, LLFontGL::LEFT, LLFontGL::TOP); // State // Hack: mirrored from lltexturefetch.cpp struct { const std::string desc; LLColor4 color; } fetch_state_desc[] = { { "---", LLColor4::red }, // INVALID { "INI", LLColor4::white }, // INIT { "DSK", LLColor4::cyan }, // LOAD_FROM_TEXTURE_CACHE { "DSK", LLColor4::blue }, // CACHE_POST { "NET", LLColor4::green }, // LOAD_FROM_NETWORK { "SIM", LLColor4::green }, // LOAD_FROM_SIMULATOR { "URL", LLColor4::green2 },// LOAD_FROM_HTTP_GET_URL { "HTP", LLColor4::green }, // LOAD_FROM_HTTP_GET_DATA { "DEC", LLColor4::yellow },// DECODE_IMAGE { "DEC", LLColor4::yellow },// DECODE_IMAGE_UPDATE { "WRT", LLColor4::purple },// WRITE_TO_CACHE { "WRT", LLColor4::orange },// WAIT_ON_WRITE { "END", LLColor4::red }, // DONE #define LAST_STATE 12 { "CRE", LLColor4::magenta }, // LAST_STATE+1 { "FUL", LLColor4::green }, // LAST_STATE+2 { "BAD", LLColor4::red }, // LAST_STATE+3 { "MIS", LLColor4::red }, // LAST_STATE+4 { "---", LLColor4::white }, // LAST_STATE+5 }; const S32 fetch_state_desc_size = (S32)(sizeof(fetch_state_desc)/sizeof(fetch_state_desc[0])); S32 state = mImagep->mNeedsCreateTexture ? LAST_STATE+1 : mImagep->mFullyLoaded ? LAST_STATE+2 : mImagep->mMinDiscardLevel > 0 ? LAST_STATE+3 : mImagep->mIsMissingAsset ? LAST_STATE+4 : !mImagep->mIsFetching ? LAST_STATE+5 : mImagep->mFetchState; state = llclamp(state,0,fetch_state_desc_size-1); LLFontGL::sMonospace->renderUTF8(fetch_state_desc[state].desc, 0, title_x2, getRect().getHeight(), fetch_state_desc[state].color, LLFontGL::LEFT, LLFontGL::TOP); LLGLSNoTexture gls_no_texture; // Draw the progress bar. S32 bar_width = 100; S32 bar_left = 280; left = bar_left; right = left + bar_width; gGL.color4f(0.f, 0.f, 0.f, 0.75f); gl_rect_2d(left, top, right, bottom); F32 data_progress = mImagep->mDownloadProgress; if (data_progress > 0.0f) { // Downloaded bytes right = left + llfloor(data_progress * (F32)bar_width); if (right > left) { gGL.color4f(0.f, 0.f, 1.f, 0.75f); gl_rect_2d(left, top, right, bottom); } } S32 pip_width = 6; S32 pip_space = 14; S32 pip_x = title_x3 + pip_space/2; // Draw the packet pip F32 last_event = mImagep->mLastPacketTimer.getElapsedTimeF32(); if (last_event < 1.f) { clr = LLColor4::white; } else { last_event = mImagep->mRequestDeltaTime; if (last_event < 1.f) { clr = LLColor4::green; } else { last_event = mImagep->mFetchDeltaTime; if (last_event < 1.f) { clr = LLColor4::yellow; } } } if (last_event < 1.f) { clr.setAlpha(1.f - last_event); gGL.color4fv(clr.mV); gl_rect_2d(pip_x, top, pip_x + pip_width, bottom); } pip_x += pip_width + pip_space; // we don't want to show bind/resident pips for textures using the default texture if (mImagep->getHasGLTexture()) { // Draw the bound pip last_event = mImagep->sLastFrameTime - mImagep->mLastBindTime; if (last_event < 1.f) { clr = mImagep->getMissed() ? LLColor4::red : LLColor4::magenta1; clr.setAlpha(1.f - last_event); gGL.color4fv(clr.mV); gl_rect_2d(pip_x, top, pip_x + pip_width, bottom); } } pip_x += pip_width + pip_space; { LLGLSUIDefault gls_ui; // draw the packet data // { // std::string num_str = llformat("%3d/%3d", mImagep->mLastPacket+1, mImagep->mPackets); // LLFontGL::sMonospace->renderUTF8(num_str, 0, bar_left + 100, getRect().getHeight(), color, // LLFontGL::LEFT, LLFontGL::TOP); // } // draw the image size at the end { std::string num_str = llformat("%3dx%3d (%d) %7d", mImagep->getWidth(), mImagep->getHeight(), mImagep->getDiscardLevel(), mImagep->mTextureMemory); LLFontGL::sMonospace->renderUTF8(num_str, 0, title_x4, getRect().getHeight(), color, LLFontGL::LEFT, LLFontGL::TOP); } } }
S32 LLFontGL::render(const LLWString &wstr, const S32 begin_offset, const F32 x, const F32 y, const LLColor4 &color, const HAlign halign, const VAlign valign, U8 style, const S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_embedded, BOOL use_ellipses) const { if(!sDisplayFont) //do not display texts { return wstr.length() ; } if (wstr.empty()) { return 0; } gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); // Strip off any style bits that are already accounted for by the font. style = style & (~getFontDesc().getStyle()); F32 drop_shadow_strength = 0.f; if (style & (DROP_SHADOW | DROP_SHADOW_SOFT)) { F32 luminance; color.calcHSL(NULL, NULL, &luminance); drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f); if (luminance < 0.35f) { style = style & ~(DROP_SHADOW | DROP_SHADOW_SOFT); } } gGL.pushMatrix(); glLoadIdentity(); gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ); // this code snaps the text origin to a pixel grid to start with F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX); F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY); gGL.translatef(-pixel_offset_x, -pixel_offset_y, 0.f); LLFastTimer t(LLFastTimer::FTM_RENDER_FONTS); gGL.color4fv( color.mV ); S32 chars_drawn = 0; S32 i; S32 length; if (-1 == max_chars) { length = (S32)wstr.length() - begin_offset; } else { length = llmin((S32)wstr.length() - begin_offset, max_chars ); } F32 cur_x, cur_y, cur_render_x, cur_render_y; // Not guaranteed to be set correctly gGL.setSceneBlendType(LLRender::BT_ALPHA); cur_x = ((F32)x * sScaleX); cur_y = ((F32)y * sScaleY); // Offset y by vertical alignment. switch (valign) { case TOP: cur_y -= mAscender; break; case BOTTOM: cur_y += mDescender; break; case VCENTER: cur_y -= ((mAscender - mDescender)/2.f); break; case BASELINE: // Baseline, do nothing. break; default: break; } switch (halign) { case LEFT: break; case RIGHT: cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), 0, length) * sScaleX)); break; case HCENTER: cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), 0, length) * sScaleX)) / 2; break; default: break; } cur_render_y = cur_y; cur_render_x = cur_x; F32 start_x = cur_x; F32 inv_width = 1.f / mFontBitmapCachep->getBitmapWidth(); F32 inv_height = 1.f / mFontBitmapCachep->getBitmapHeight(); const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL; BOOL draw_ellipses = FALSE; if (use_ellipses && halign == LEFT) { // check for too long of a string if (getWidthF32(wstr.c_str(), 0, max_chars) * sScaleX > scaled_max_pixels) { // use four dots for ellipsis width to generate padding const LLWString dots(utf8str_to_wstring(std::string("...."))); scaled_max_pixels = llmax(0, scaled_max_pixels - llround(getWidthF32(dots.c_str()))); draw_ellipses = TRUE; } } // Remember last-used texture to avoid unnecesssary bind calls. LLImageGL *last_bound_texture = NULL; for (i = begin_offset; i < begin_offset + length; i++) { llwchar wch = wstr[i]; // Handle embedded characters first, if they're enabled. // Embedded characters are a hack for notecards const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL; if (ext_data) { LLImageGL* ext_image = ext_data->mImage; const LLWString& label = ext_data->mLabel; F32 ext_height = (F32)ext_image->getHeight() * sScaleY; F32 ext_width = (F32)ext_image->getWidth() * sScaleX; F32 ext_advance = (EXT_X_BEARING * sScaleX) + ext_width; if (!label.empty()) { ext_advance += (EXT_X_BEARING + getFontExtChar()->getWidthF32( label.c_str() )) * sScaleX; } if (start_x + scaled_max_pixels < cur_x + ext_advance) { // Not enough room for this character. break; } if (last_bound_texture != ext_image) { gGL.getTexUnit(0)->bind(ext_image); last_bound_texture = ext_image; } // snap origin to whole screen pixel const F32 ext_x = (F32)llround(cur_render_x + (EXT_X_BEARING * sScaleX)); const F32 ext_y = (F32)llround(cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight)); LLRectf uv_rect(0.f, 1.f, 1.f, 0.f); LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); drawGlyph(screen_rect, uv_rect, LLColor4::white, style, drop_shadow_strength); if (!label.empty()) { gGL.pushMatrix(); //glLoadIdentity(); //gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f); //glScalef(sScaleX, sScaleY, 1.f); getFontExtChar()->render(label, 0, /*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX), /*llfloor*/(cur_y / sScaleY), color, halign, BASELINE, NORMAL, S32_MAX, S32_MAX, NULL, TRUE ); gGL.popMatrix(); } gGL.color4fv(color.mV); chars_drawn++; cur_x += ext_advance; if (((i + 1) < length) && wstr[i+1]) { cur_x += EXT_KERNING * sScaleX; } cur_render_x = cur_x; } else { if (!hasGlyph(wch)) { addChar(wch); } const LLFontGlyphInfo* fgi= getGlyphInfo(wch); if (!fgi) { llerrs << "Missing Glyph Info" << llendl; break; } // Per-glyph bitmap texture. LLImageGL *image_gl = mFontBitmapCachep->getImageGL(fgi->mBitmapNum); if (last_bound_texture != image_gl) { gGL.getTexUnit(0)->bind(image_gl); last_bound_texture = image_gl; } if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth)) { // Not enough room for this character. break; } // Draw the text at the appropriate location //Specify vertices and texture coordinates LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width, (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height, (fgi->mXBitmapOffset + fgi->mWidth) * inv_width, (fgi->mYBitmapOffset - PAD_UVY) * inv_height); // snap glyph origin to whole screen pixel LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing), llround(cur_render_y + (F32)fgi->mYBearing), llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength); chars_drawn++; cur_x += fgi->mXAdvance; cur_y += fgi->mYAdvance; llwchar next_char = wstr[i+1]; if (next_char && (next_char < LAST_CHARACTER)) { // Kern this puppy. if (!hasGlyph(next_char)) { addChar(next_char); } cur_x += getXKerning(wch, next_char); } // Round after kerning. // Must do this to cur_x, not just to cur_render_x, otherwise you // will squish sub-pixel kerned characters too close together. // For example, "CCCCC" looks bad. cur_x = (F32)llfloor(cur_x + 0.5f); //cur_y = (F32)llfloor(cur_y + 0.5f); cur_render_x = cur_x; cur_render_y = cur_y; } } if (right_x) { *right_x = cur_x / sScaleX; } if (style & UNDERLINE) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.begin(LLRender::LINES); gGL.vertex2f(start_x, cur_y - (mDescender)); gGL.vertex2f(cur_x, cur_y - (mDescender)); gGL.end(); } // *FIX: get this working in all alignment cases, etc. if (draw_ellipses) { // recursively render ellipses at end of string // we've already reserved enough room gGL.pushMatrix(); //glLoadIdentity(); //gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f); //glScalef(sScaleX, sScaleY, 1.f); renderUTF8(std::string("..."), 0, cur_x / sScaleX, (F32)y, color, LEFT, valign, style, S32_MAX, max_pixels, right_x, FALSE); gGL.popMatrix(); } gGL.popMatrix(); return chars_drawn; }
void LLMemoryView::draw() { std::string tdesc; S32 width = mRect.getWidth(); S32 height = mRect.getHeight(); LLGLSUIDefault gls_ui; LLGLSNoTexture gls_no_tex; gl_rect_2d(0, height, width, 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); #if MEM_TRACK_TYPE S32 left, top, right, bottom; S32 x, y; S32 margin = 10; S32 texth = (S32)LLFontGL::sMonospace->getLineHeight(); S32 xleft = margin; S32 ytop = height - margin; S32 labelwidth = 0; S32 maxmaxbytes = 1; // Make sure all timers are accounted for // Set 'MT_OTHER' to unaccounted ticks last frame { S32 display_memtypes[LLMemType::MTYPE_NUM_TYPES]; for (S32 i=0; i < LLMemType::MTYPE_NUM_TYPES; i++) { display_memtypes[i] = 0; } for (S32 i=0; i < MTV_DISPLAY_NUM; i++) { S32 tidx = mtv_display_table[i].memtype; display_memtypes[tidx]++; } LLMemType::sMemCount[LLMemType::MTYPE_OTHER] = 0; LLMemType::sMaxMemCount[LLMemType::MTYPE_OTHER] = 0; for (S32 tidx = 0; tidx < LLMemType::MTYPE_NUM_TYPES; tidx++) { if (display_memtypes[tidx] == 0) { LLMemType::sMemCount[LLMemType::MTYPE_OTHER] += LLMemType::sMemCount[tidx]; LLMemType::sMaxMemCount[LLMemType::MTYPE_OTHER] += LLMemType::sMaxMemCount[tidx]; } } } // Labels { LLGLSTexture gls_texture; y = ytop; S32 peak = 0; for (S32 i=0; i<MTV_DISPLAY_NUM; i++) { x = xleft; int tidx = mtv_display_table[i].memtype; S32 bytes = LLMemType::sMemCount[tidx]; S32 maxbytes = LLMemType::sMaxMemCount[tidx]; maxmaxbytes = llmax(maxbytes, maxmaxbytes); peak += maxbytes; S32 mbytes = bytes >> 20; tdesc = llformat("%s [%4d MB]",mtv_display_table[i].desc,mbytes); LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); y -= (texth + 2); S32 textw = LLFontGL::sMonospace->getWidth(tdesc); if (textw > labelwidth) labelwidth = textw; } x = xleft; tdesc = llformat("Total Bytes: %d MB Overhead: %d KB", LLMemType::sTotalMem >> 20, LLMemType::sOverheadMem >> 10); LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); } // Bars y = ytop; labelwidth += 8; S32 barw = width - labelwidth - xleft - margin; for (S32 i=0; i<MTV_DISPLAY_NUM; i++) { x = xleft + labelwidth; int tidx = mtv_display_table[i].memtype; S32 bytes = LLMemType::sMemCount[tidx]; F32 frac = (F32)bytes / (F32)maxmaxbytes; S32 w = (S32)(frac * (F32)barw); left = x; right = x + w; top = y; bottom = y - texth; gl_rect_2d(left, top, right, bottom, *mtv_display_table[i].color); S32 maxbytes = LLMemType::sMaxMemCount[tidx]; F32 frac2 = (F32)maxbytes / (F32)maxmaxbytes; S32 w2 = (S32)(frac2 * (F32)barw); left = x + w + 1; right = x + w2; top = y; bottom = y - texth; LLColor4 tcolor = *mtv_display_table[i].color; tcolor.setAlpha(.5f); gl_rect_2d(left, top, right, bottom, tcolor); y -= (texth + 2); } #endif LLView::draw(); }
// we've switched controls, or doing per-frame update, so update spinners, etc. void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp) { LLSpinCtrl* spinner1 = getChild<LLSpinCtrl>("val_spinner_1"); LLSpinCtrl* spinner2 = getChild<LLSpinCtrl>("val_spinner_2"); LLSpinCtrl* spinner3 = getChild<LLSpinCtrl>("val_spinner_3"); LLSpinCtrl* spinner4 = getChild<LLSpinCtrl>("val_spinner_4"); LLColorSwatchCtrl* color_swatch = getChild<LLColorSwatchCtrl>("val_color_swatch"); if (!spinner1 || !spinner2 || !spinner3 || !spinner4 || !color_swatch) { llwarns << "Could not find all desired controls by name" << llendl; return; } spinner1->setVisible(FALSE); spinner2->setVisible(FALSE); spinner3->setVisible(FALSE); spinner4->setVisible(FALSE); color_swatch->setVisible(FALSE); getChildView("val_text")->setVisible( FALSE); mComment->setText(LLStringUtil::null); if (controlp) { // [RLVa:KB] - Checked: 2011-05-28 (RLVa-1.4.0a) | Modified: RLVa-1.4.0a // If "HideFromEditor" was toggled while the floater is open then we need to manually disable access to the control // NOTE: this runs per-frame so there's no need to explictly handle onCommitSettings() or onClickDefault() bool fEnable = !controlp->isHiddenFromSettingsEditor(); spinner1->setEnabled(fEnable); spinner2->setEnabled(fEnable); spinner3->setEnabled(fEnable); spinner4->setEnabled(fEnable); color_swatch->setEnabled(fEnable); childSetEnabled("val_text", fEnable); childSetEnabled("boolean_combo", fEnable); childSetEnabled("default_btn", fEnable); // [/RLVa:KB] eControlType type = controlp->type(); //hide combo box only for non booleans, otherwise this will result in the combo box closing every frame getChildView("boolean_combo")->setVisible( type == TYPE_BOOLEAN); mComment->setText(controlp->getComment()); spinner1->setMaxValue(F32_MAX); spinner2->setMaxValue(F32_MAX); spinner3->setMaxValue(F32_MAX); spinner4->setMaxValue(F32_MAX); spinner1->setMinValue(-F32_MAX); spinner2->setMinValue(-F32_MAX); spinner3->setMinValue(-F32_MAX); spinner4->setMinValue(-F32_MAX); if (!spinner1->hasFocus()) { spinner1->setIncrement(0.1f); } if (!spinner2->hasFocus()) { spinner2->setIncrement(0.1f); } if (!spinner3->hasFocus()) { spinner3->setIncrement(0.1f); } if (!spinner4->hasFocus()) { spinner4->setIncrement(0.1f); } LLSD sd = controlp->get(); switch(type) { case TYPE_U32: spinner1->setVisible(TRUE); spinner1->setLabel(std::string("value")); // Debug, don't translate if (!spinner1->hasFocus()) { spinner1->setValue(sd); spinner1->setMinValue((F32)U32_MIN); spinner1->setMaxValue((F32)U32_MAX); spinner1->setIncrement(1.f); spinner1->setPrecision(0); } break; case TYPE_S32: spinner1->setVisible(TRUE); spinner1->setLabel(std::string("value")); // Debug, don't translate if (!spinner1->hasFocus()) { spinner1->setValue(sd); spinner1->setMinValue((F32)S32_MIN); spinner1->setMaxValue((F32)S32_MAX); spinner1->setIncrement(1.f); spinner1->setPrecision(0); } break; case TYPE_F32: spinner1->setVisible(TRUE); spinner1->setLabel(std::string("value")); // Debug, don't translate if (!spinner1->hasFocus()) { spinner1->setPrecision(3); spinner1->setValue(sd); } break; case TYPE_BOOLEAN: if (!getChild<LLUICtrl>("boolean_combo")->hasFocus()) { if (sd.asBoolean()) { getChild<LLUICtrl>("boolean_combo")->setValue(LLSD("true")); } else { getChild<LLUICtrl>("boolean_combo")->setValue(LLSD("")); } } break; case TYPE_STRING: getChildView("val_text")->setVisible( TRUE); if (!getChild<LLUICtrl>("val_text")->hasFocus()) { getChild<LLUICtrl>("val_text")->setValue(sd); } break; case TYPE_VEC3: { LLVector3 v; v.setValue(sd); spinner1->setVisible(TRUE); spinner1->setLabel(std::string("X")); spinner2->setVisible(TRUE); spinner2->setLabel(std::string("Y")); spinner3->setVisible(TRUE); spinner3->setLabel(std::string("Z")); if (!spinner1->hasFocus()) { spinner1->setPrecision(3); spinner1->setValue(v[VX]); } if (!spinner2->hasFocus()) { spinner2->setPrecision(3); spinner2->setValue(v[VY]); } if (!spinner3->hasFocus()) { spinner3->setPrecision(3); spinner3->setValue(v[VZ]); } break; } case TYPE_VEC3D: { LLVector3d v; v.setValue(sd); spinner1->setVisible(TRUE); spinner1->setLabel(std::string("X")); spinner2->setVisible(TRUE); spinner2->setLabel(std::string("Y")); spinner3->setVisible(TRUE); spinner3->setLabel(std::string("Z")); if (!spinner1->hasFocus()) { spinner1->setPrecision(3); spinner1->setValue(v[VX]); } if (!spinner2->hasFocus()) { spinner2->setPrecision(3); spinner2->setValue(v[VY]); } if (!spinner3->hasFocus()) { spinner3->setPrecision(3); spinner3->setValue(v[VZ]); } break; } case TYPE_RECT: { LLRect r; r.setValue(sd); spinner1->setVisible(TRUE); spinner1->setLabel(std::string("Left")); spinner2->setVisible(TRUE); spinner2->setLabel(std::string("Right")); spinner3->setVisible(TRUE); spinner3->setLabel(std::string("Bottom")); spinner4->setVisible(TRUE); spinner4->setLabel(std::string("Top")); if (!spinner1->hasFocus()) { spinner1->setPrecision(0); spinner1->setValue(r.mLeft); } if (!spinner2->hasFocus()) { spinner2->setPrecision(0); spinner2->setValue(r.mRight); } if (!spinner3->hasFocus()) { spinner3->setPrecision(0); spinner3->setValue(r.mBottom); } if (!spinner4->hasFocus()) { spinner4->setPrecision(0); spinner4->setValue(r.mTop); } spinner1->setMinValue((F32)S32_MIN); spinner1->setMaxValue((F32)S32_MAX); spinner1->setIncrement(1.f); spinner2->setMinValue((F32)S32_MIN); spinner2->setMaxValue((F32)S32_MAX); spinner2->setIncrement(1.f); spinner3->setMinValue((F32)S32_MIN); spinner3->setMaxValue((F32)S32_MAX); spinner3->setIncrement(1.f); spinner4->setMinValue((F32)S32_MIN); spinner4->setMaxValue((F32)S32_MAX); spinner4->setIncrement(1.f); break; } case TYPE_COL4: { LLColor4 clr; clr.setValue(sd); color_swatch->setVisible(TRUE); // only set if changed so color picker doesn't update if(clr != LLColor4(color_swatch->getValue())) { color_swatch->set(LLColor4(sd), TRUE, FALSE); } spinner4->setVisible(TRUE); spinner4->setLabel(std::string("Alpha")); if (!spinner4->hasFocus()) { spinner4->setPrecision(3); spinner4->setMinValue(0.0); spinner4->setMaxValue(1.f); spinner4->setValue(clr.mV[VALPHA]); } break; } case TYPE_COL3: { LLColor3 clr; clr.setValue(sd); color_swatch->setVisible(TRUE); color_swatch->setValue(sd); break; } default: mComment->setText(std::string("unknown")); break; } } }
LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, EHighlightPosition part, S32 index) { //evil recursive string atomizer. LLSD ret_llsd, start_llsd, middle_llsd, end_llsd; for (S32 i=index;i<mHighlights.size();i++) { S32 condition = mHighlights[i]["condition"]; if ((S32)mHighlights[i]["highlight"]==PART && condition!=MATCHES) { if ( (condition==STARTS_WITH && part==START) || (condition==ENDS_WITH && part==END) || condition==CONTAINS || part==WHOLE ) { S32 start = findPattern(text,mHighlights[i]); if (start >= 0 ) { S32 end = std::string(mHighlights[i]["pattern"]).length(); S32 len = text.length(); EHighlightPosition newpart; if (start==0) { start_llsd[0]["text"] =text.substr(0,end); start_llsd[0]["color"]=mHighlights[i]["color"]; if (end < len) { if (part==END || part==WHOLE) newpart=END; else newpart=MIDDLE; end_llsd=parsePartialLineHighlights(text.substr( end ),color,newpart,i); } } else { if (part==START || part==WHOLE) newpart=START; else newpart=MIDDLE; start_llsd=parsePartialLineHighlights(text.substr(0,start),color,newpart,i+1); if (end < len) { middle_llsd[0]["text"] =text.substr(start,end); middle_llsd[0]["color"]=mHighlights[i]["color"]; if (part==END || part==WHOLE) newpart=END; else newpart=MIDDLE; end_llsd=parsePartialLineHighlights(text.substr( (start+end) ),color,newpart,i); } else { end_llsd[0]["text"] =text.substr(start,end); end_llsd[0]["color"]=mHighlights[i]["color"]; } } S32 retcount=0; //FIXME These loops should be wrapped into a subroutine. for (LLSD::array_iterator iter = start_llsd.beginArray(); iter != start_llsd.endArray();++iter) { LLSD highlight = *iter; ret_llsd[retcount++]=highlight; } for (LLSD::array_iterator iter = middle_llsd.beginArray(); iter != middle_llsd.endArray();++iter) { LLSD highlight = *iter; ret_llsd[retcount++]=highlight; } for (LLSD::array_iterator iter = end_llsd.beginArray(); iter != end_llsd.endArray();++iter) { LLSD highlight = *iter; ret_llsd[retcount++]=highlight; } return ret_llsd; } } } } //No patterns found. Just send back what was passed in. ret_llsd[0]["text"] =text; LLSD color_sd = color.getValue(); ret_llsd[0]["color"]=color_sd; return ret_llsd; }
template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in) { return in.getValue(); }
S32 LLFontGL::render(const LLWString &wstr, const S32 begin_offset, const F32 x, const F32 y, const LLColor4 &color, const HAlign halign, const VAlign valign, U8 style, const S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_embedded, BOOL use_ellipses) const { if(!sDisplayFont) //do not display texts { return wstr.length() ; } LLGLEnable tex(GL_TEXTURE_2D); if (wstr.empty()) { return 0; } S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); // HACK for better bolding if (style & BOLD) { if (this == LLFontGL::sSansSerif) { return LLFontGL::sSansSerifBold->render( wstr, begin_offset, x, y, color, halign, valign, (style & ~BOLD), max_chars, max_pixels, right_x, use_embedded); } } F32 drop_shadow_strength = 0.f; if (style & (DROP_SHADOW | DROP_SHADOW_SOFT)) { F32 luminance; color.calcHSL(NULL, NULL, &luminance); drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f); if (luminance < 0.35f) { style = style & ~(DROP_SHADOW | DROP_SHADOW_SOFT); } } gGL.pushMatrix(); glLoadIdentity(); gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ); //glScalef(sScaleX, sScaleY, 1.0f); // avoid half pixels // RN: if we're going to this trouble, might as well snap to nearest pixel all the time // but the plan is to get rid of this so that fonts "just work" //F32 half_pixel_distance = llabs(fmodf(sCurOrigin.mX * sScaleX, 1.f) - 0.5f); //if (half_pixel_distance < PIXEL_BORDER_THRESHOLD) //{ gGL.translatef(PIXEL_CORRECTION_DISTANCE*sScaleX, 0.f, 0.f); //} // this code would just snap to pixel grid, although it seems to introduce more jitter //F32 pixel_offset_x = llround(sCurOrigin.mX * sScaleX) - (sCurOrigin.mX * sScaleX); //F32 pixel_offset_y = llround(sCurOrigin.mY * sScaleY) - (sCurOrigin.mY * sScaleY); //gGL.translatef(-pixel_offset_x, -pixel_offset_y, 0.f); // scale back to native pixel size //glScalef(1.f / sScaleX, 1.f / sScaleY, 1.f); //glScaled(1.0 / (F64) sScaleX, 1.0 / (F64) sScaleY, 1.0f); LLFastTimer t(LLFastTimer::FTM_RENDER_FONTS); gGL.color4fv( color.mV ); S32 chars_drawn = 0; S32 i; S32 length; if (-1 == max_chars) { length = (S32)wstr.length() - begin_offset; } else { length = llmin((S32)wstr.length() - begin_offset, max_chars ); } F32 cur_x, cur_y, cur_render_x, cur_render_y; // Bind the font texture mImageGLp->bind(0); // Not guaranteed to be set correctly gGL.setSceneBlendType(LLRender::BT_ALPHA); cur_x = ((F32)x * sScaleX); cur_y = ((F32)y * sScaleY); // Offset y by vertical alignment. switch (valign) { case TOP: cur_y -= mAscender; break; case BOTTOM: cur_y += mDescender; break; case VCENTER: cur_y -= ((mAscender - mDescender)/2.f); break; case BASELINE: // Baseline, do nothing. break; default: break; } switch (halign) { case LEFT: break; case RIGHT: cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), 0, length) * sScaleX)); break; case HCENTER: cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), 0, length) * sScaleX)) / 2; break; default: break; } // Round properly. //cur_render_y = (F32)llfloor(cur_y/sScaleY + 0.5f)*sScaleY; //cur_render_x = (F32)llfloor(cur_x/sScaleX + 0.5f)*sScaleX; cur_render_y = cur_y; cur_render_x = cur_x; F32 start_x = cur_x; F32 inv_width = 1.f / mImageGLp->getWidth(); F32 inv_height = 1.f / mImageGLp->getHeight(); const S32 LAST_CHARACTER = LLFont::LAST_CHAR_FULL; BOOL draw_ellipses = FALSE; if (use_ellipses && halign == LEFT) { // check for too long of a string if (getWidthF32(wstr.c_str(), 0, max_chars) * sScaleX > scaled_max_pixels) { // use four dots for ellipsis width to generate padding const LLWString dots(utf8str_to_wstring(std::string("...."))); scaled_max_pixels = llmax(0, scaled_max_pixels - llround(getWidthF32(dots.c_str()))); draw_ellipses = TRUE; } } for (i = begin_offset; i < begin_offset + length; i++) { llwchar wch = wstr[i]; // Handle embedded characters first, if they're enabled. // Embedded characters are a hack for notecards const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL; if (ext_data) { LLImageGL* ext_image = ext_data->mImage; const LLWString& label = ext_data->mLabel; F32 ext_height = (F32)ext_image->getHeight() * sScaleY; F32 ext_width = (F32)ext_image->getWidth() * sScaleX; F32 ext_advance = (EXT_X_BEARING * sScaleX) + ext_width; if (!label.empty()) { ext_advance += (EXT_X_BEARING + gExtCharFont->getWidthF32( label.c_str() )) * sScaleX; } if (start_x + scaled_max_pixels < cur_x + ext_advance) { // Not enough room for this character. break; } ext_image->bind(); const F32 ext_x = cur_render_x + (EXT_X_BEARING * sScaleX); const F32 ext_y = cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight); LLRectf uv_rect(0.f, 1.f, 1.f, 0.f); LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); drawGlyph(screen_rect, uv_rect, LLColor4::white, style, drop_shadow_strength); if (!label.empty()) { gGL.pushMatrix(); //glLoadIdentity(); //gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f); //glScalef(sScaleX, sScaleY, 1.f); gExtCharFont->render(label, 0, /*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX), /*llfloor*/(cur_y / sScaleY), color, halign, BASELINE, NORMAL, S32_MAX, S32_MAX, NULL, TRUE ); gGL.popMatrix(); } gGL.color4fv(color.mV); chars_drawn++; cur_x += ext_advance; if (((i + 1) < length) && wstr[i+1]) { cur_x += EXT_KERNING * sScaleX; } cur_render_x = cur_x; // Bind the font texture mImageGLp->bind(); } else { if (!hasGlyph(wch)) { (const_cast<LLFontGL*>(this))->addChar(wch); } const LLFontGlyphInfo* fgi= getGlyphInfo(wch); if (!fgi) { llerrs << "Missing Glyph Info" << llendl; break; } if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth)) { // Not enough room for this character. break; } // Draw the text at the appropriate location //Specify vertices and texture coordinates LLRectf uv_rect((fgi->mXBitmapOffset - PAD_AMT) * inv_width, (fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height, (fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width, (fgi->mYBitmapOffset - PAD_AMT) * inv_height); LLRectf screen_rect(cur_render_x + (F32)fgi->mXBearing - PAD_AMT, cur_render_y + (F32)fgi->mYBearing + PAD_AMT, cur_render_x + (F32)fgi->mXBearing + (F32)fgi->mWidth + PAD_AMT, cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT); drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength); chars_drawn++; cur_x += fgi->mXAdvance; cur_y += fgi->mYAdvance; llwchar next_char = wstr[i+1]; if (next_char && (next_char < LAST_CHARACTER)) { // Kern this puppy. if (!hasGlyph(next_char)) { (const_cast<LLFontGL*>(this))->addChar(next_char); } cur_x += getXKerning(wch, next_char); } // Round after kerning. // Must do this to cur_x, not just to cur_render_x, otherwise you // will squish sub-pixel kerned characters too close together. // For example, "CCCCC" looks bad. cur_x = (F32)llfloor(cur_x + 0.5f); //cur_y = (F32)llfloor(cur_y + 0.5f); cur_render_x = cur_x; cur_render_y = cur_y; } } if (right_x) { *right_x = cur_x / sScaleX; } if (style & UNDERLINE) { LLGLSNoTexture no_texture; gGL.begin(LLVertexBuffer::LINES); gGL.vertex2f(start_x, cur_y - (mDescender)); gGL.vertex2f(cur_x, cur_y - (mDescender)); gGL.end(); } // *FIX: get this working in all alignment cases, etc. if (draw_ellipses) { // recursively render ellipses at end of string // we've already reserved enough room gGL.pushMatrix(); //glLoadIdentity(); //gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f); //glScalef(sScaleX, sScaleY, 1.f); renderUTF8(std::string("..."), 0, cur_x / sScaleX, (F32)y, color, LEFT, valign, style, S32_MAX, max_pixels, right_x, FALSE); gGL.popMatrix(); } gGL.popMatrix(); return chars_drawn; }
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses) const { LLFastTimer _(FTM_RENDER_FONTS); if(!sDisplayFont) //do not display texts { return wstr.length() ; } if (wstr.empty()) { return 0; } gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); // determine which style flags need to be added programmatically by stripping off the // style bits that are drawn by the underlying Freetype font U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle(); F32 drop_shadow_strength = 0.f; if (shadow != NO_SHADOW) { F32 luminance; color.calcHSL(NULL, NULL, &luminance); drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f); if (luminance < 0.35f) { shadow = NO_SHADOW; } } gGL.pushUIMatrix(); gGL.loadUIIdentity(); //gGL.translateUI(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ); // this code snaps the text origin to a pixel grid to start with //F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX); //F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY); //gGL.translateUI(-pixel_offset_x, -pixel_offset_y, 0.f); LLVector2 origin(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY)); // snap the text origin to a pixel grid to start with origin.mV[VX] -= llround((F32)sCurOrigin.mX) - (sCurOrigin.mX); origin.mV[VY] -= llround((F32)sCurOrigin.mY) - (sCurOrigin.mY); S32 chars_drawn = 0; S32 i; S32 length; if (-1 == max_chars) { length = (S32)wstr.length() - begin_offset; } else { length = llmin((S32)wstr.length() - begin_offset, max_chars ); } F32 cur_x, cur_y, cur_render_x, cur_render_y; // Not guaranteed to be set correctly gGL.setSceneBlendType(LLRender::BT_ALPHA); cur_x = ((F32)x * sScaleX) + origin.mV[VX]; cur_y = ((F32)y * sScaleY) + origin.mV[VY]; // Offset y by vertical alignment. switch (valign) { case TOP: cur_y -= mFontFreetype->getAscenderHeight(); break; case BOTTOM: cur_y += mFontFreetype->getDescenderHeight(); break; case VCENTER: cur_y -= (mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight()) / 2.f; break; case BASELINE: // Baseline, do nothing. break; default: break; } switch (halign) { case LEFT: break; case RIGHT: cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)); break; case HCENTER: cur_x -= llmin(scaled_max_pixels, llround(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)) / 2; break; default: break; } cur_render_y = cur_y; cur_render_x = cur_x; F32 start_x = llround(cur_x); const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth(); F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight(); const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL; BOOL draw_ellipses = FALSE; if (use_ellipses) { // check for too long of a string S32 string_width = llround(getWidthF32(wstr.c_str(), begin_offset, max_chars) * sScaleX); if (string_width > scaled_max_pixels) { // use four dots for ellipsis width to generate padding const LLWString dots(utf8str_to_wstring(std::string("...."))); scaled_max_pixels = llmax(0, scaled_max_pixels - llround(getWidthF32(dots.c_str()))); draw_ellipses = TRUE; } } const LLFontGlyphInfo* next_glyph = NULL; const S32 GLYPH_BATCH_SIZE = 30; LLVector3 vertices[GLYPH_BATCH_SIZE * 4]; LLVector2 uvs[GLYPH_BATCH_SIZE * 4]; LLColor4U colors[GLYPH_BATCH_SIZE * 4]; LLColor4U text_color(color); S32 bitmap_num = -1; S32 glyph_count = 0; for (i = begin_offset; i < begin_offset + length; i++) { llwchar wch = wstr[i]; const LLFontGlyphInfo* fgi = next_glyph; next_glyph = NULL; if(!fgi) { fgi = mFontFreetype->getGlyphInfo(wch); } if (!fgi) { llerrs << "Missing Glyph Info" << llendl; break; } // Per-glyph bitmap texture. S32 next_bitmap_num = fgi->mBitmapNum; if (next_bitmap_num != bitmap_num) { bitmap_num = next_bitmap_num; LLImageGL *font_image = font_bitmap_cache->getImageGL(bitmap_num); gGL.getTexUnit(0)->bind(font_image); } if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth)) { // Not enough room for this character. break; } // Draw the text at the appropriate location //Specify vertices and texture coordinates LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width, (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height, (fgi->mXBitmapOffset + fgi->mWidth) * inv_width, (fgi->mYBitmapOffset - PAD_UVY) * inv_height); // snap glyph origin to whole screen pixel LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing), llround(cur_render_y + (F32)fgi->mYBearing), llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); if (glyph_count >= GLYPH_BATCH_SIZE) { gGL.begin(LLRender::QUADS); { gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); } gGL.end(); glyph_count = 0; } drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style_to_add, shadow, drop_shadow_strength); chars_drawn++; cur_x += fgi->mXAdvance; cur_y += fgi->mYAdvance; llwchar next_char = wstr[i+1]; if (next_char && (next_char < LAST_CHARACTER)) { // Kern this puppy. next_glyph = mFontFreetype->getGlyphInfo(next_char); cur_x += mFontFreetype->getXKerning(fgi, next_glyph); } // Round after kerning. // Must do this to cur_x, not just to cur_render_x, otherwise you // will squish sub-pixel kerned characters too close together. // For example, "CCCCC" looks bad. cur_x = (F32)llround(cur_x); //cur_y = (F32)llround(cur_y); cur_render_x = cur_x; cur_render_y = cur_y; } gGL.begin(LLRender::QUADS); { gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); } gGL.end(); if (right_x) { *right_x = (cur_x - origin.mV[VX]) / sScaleX; } //FIXME: add underline as glyph? if (style_to_add & UNDERLINE) { F32 descender = mFontFreetype->getDescenderHeight(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.begin(LLRender::LINES); gGL.vertex2f(start_x, cur_y - (descender)); gGL.vertex2f(cur_x, cur_y - (descender)); gGL.end(); } if (draw_ellipses) { // recursively render ellipses at end of string // we've already reserved enough room gGL.pushUIMatrix(); renderUTF8(std::string("..."), 0, (cur_x - origin.mV[VX]) / sScaleX, (F32)y, color, LEFT, valign, style_to_add, shadow, S32_MAX, max_pixels, right_x, FALSE); gGL.popUIMatrix(); } gGL.popUIMatrix(); return chars_drawn; }
U32 LLControlGroup::loadFromFileLegacy(const LLString& filename, BOOL require_declaration, eControlType declare_as) { U32 item = 0; U32 validitems = 0; llifstream file; S32 version; file.open(filename.c_str()); /*Flawfinder: ignore*/ if (!file) { llinfos << "LLControlGroup::loadFromFile unable to open." << llendl; return 0; } // Check file version LLString name; file >> name; file >> version; if (name != "version" || version != CURRENT_VERSION) { llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl; return 0; } while (!file.eof()) { file >> name; if (name.empty()) { continue; } if (name.substr(0,2) == "//") { // This is a comment. char buffer[MAX_STRING]; /*Flawfinder: ignore*/ file.getline(buffer, MAX_STRING); continue; } BOOL declared = mNameTable.find(name) != mNameTable.end(); if (require_declaration && !declared) { // Declaration required, but this name not declared. // Complain about non-empty names. if (!name.empty()) { //read in to end of line char buffer[MAX_STRING]; /*Flawfinder: ignore*/ file.getline(buffer, MAX_STRING); llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl; } continue; } // Got an item. Load it up. item++; // If not declared, assume it's a string if (!declared) { switch(declare_as) { case TYPE_COL4: declareColor4(name, LLColor4::white, LLString::null, NO_PERSIST); break; case TYPE_COL4U: declareColor4U(name, LLColor4U::white, LLString::null, NO_PERSIST); break; case TYPE_STRING: default: declareString(name, LLString::null, LLString::null, NO_PERSIST); break; } } // Control name has been declared in code. LLControlBase *control = getControl(name); llassert(control); mLoadedSettings.insert(name); switch(control->mType) { case TYPE_F32: { F32 initial; file >> initial; control->set(initial); validitems++; } break; case TYPE_S32: { S32 initial; file >> initial; control->set(initial); validitems++; } break; case TYPE_U32: { U32 initial; file >> initial; control->set((LLSD::Integer) initial); validitems++; } break; case TYPE_BOOLEAN: { char boolstring[256]; /*Flawfinder: ignore*/ BOOL valid = FALSE; BOOL initial = FALSE; file >> boolstring; if (!strcmp("TRUE", boolstring)) { initial = TRUE; valid = TRUE; } else if (!strcmp("FALSE", boolstring)) { initial = FALSE; valid = TRUE; } if (valid) { control->set(initial); } else { llinfos << filename << "Item " << item << ": Invalid BOOL control " << name << ", " << boolstring << llendl; } validitems++; } break; case TYPE_STRING: { LLString string; file >> string; control->set(string); validitems++; } break; case TYPE_VEC3: { F32 x, y, z; file >> x >> y >> z; LLVector3 vector(x, y, z); control->set(vector.getValue()); validitems++; } break; case TYPE_VEC3D: { F64 x, y, z; file >> x >> y >> z; LLVector3d vector(x, y, z); control->set(vector.getValue()); validitems++; } break; case TYPE_RECT: { S32 left, bottom, width, height; file >> left >> bottom >> width >> height; LLRect rect; rect.setOriginAndSize(left, bottom, width, height); control->set(rect.getValue()); validitems++; } break; case TYPE_COL4U: { S32 red, green, blue, alpha; LLColor4U color; file >> red >> green >> blue >> alpha; color.setVec(red, green, blue, alpha); control->set(color.getValue()); validitems++; } break; case TYPE_COL4: { LLColor4 color; file >> color.mV[VRED] >> color.mV[VGREEN] >> color.mV[VBLUE] >> color.mV[VALPHA]; control->set(color.getValue()); validitems++; } break; case TYPE_COL3: { LLColor3 color; file >> color.mV[VRED] >> color.mV[VGREEN] >> color.mV[VBLUE]; control->set(color.getValue()); validitems++; } break; } } file.close(); return validitems; }
// Returns number of controls loaded, so 0 if failure U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declaration, eControlType declare_as) { LLString name; LLXmlTree xml_controls; if (!xml_controls.parseFile(filename)) { llwarns << "Unable to open control file " << filename << llendl; return 0; } LLXmlTreeNode* rootp = xml_controls.getRoot(); if (!rootp || !rootp->hasAttribute("version")) { llwarns << "No valid settings header found in control file " << filename << llendl; return 0; } U32 item = 0; U32 validitems = 0; S32 version; rootp->getAttributeS32("version", version); // Check file version if (version != CURRENT_VERSION) { llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl; return 0; } LLXmlTreeNode* child_nodep = rootp->getFirstChild(); while(child_nodep) { name = child_nodep->getName(); BOOL declared = controlExists(name); if (require_declaration && !declared) { // Declaration required, but this name not declared. // Complain about non-empty names. if (!name.empty()) { //read in to end of line llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl; } child_nodep = rootp->getNextChild(); continue; } // Got an item. Load it up. item++; // If not declared, assume it's a string if (!declared) { switch(declare_as) { case TYPE_COL4: declareColor4(name, LLColor4::white, "", NO_PERSIST); break; case TYPE_COL4U: declareColor4U(name, LLColor4U::white, "", NO_PERSIST); break; case TYPE_STRING: default: declareString(name, LLString::null, "", NO_PERSIST); break; } } // Control name has been declared in code. LLControlBase *control = getControl(name); llassert(control); mLoadedSettings.insert(name); switch(control->mType) { case TYPE_F32: { F32 initial = 0.f; child_nodep->getAttributeF32("value", initial); control->set(initial); validitems++; } break; case TYPE_S32: { S32 initial = 0; child_nodep->getAttributeS32("value", initial); control->set(initial); validitems++; } break; case TYPE_U32: { U32 initial = 0; child_nodep->getAttributeU32("value", initial); control->set((LLSD::Integer) initial); validitems++; } break; case TYPE_BOOLEAN: { BOOL initial = FALSE; child_nodep->getAttributeBOOL("value", initial); control->set(initial); validitems++; } break; case TYPE_STRING: { LLString string; child_nodep->getAttributeString("value", string); if (string == LLString::null) { string = ""; } control->set(string); validitems++; } break; case TYPE_VEC3: { LLVector3 vector; child_nodep->getAttributeVector3("value", vector); control->set(vector.getValue()); validitems++; } break; case TYPE_VEC3D: { LLVector3d vector; child_nodep->getAttributeVector3d("value", vector); control->set(vector.getValue()); validitems++; } break; case TYPE_RECT: { //RN: hack to support reading rectangles from a string LLString rect_string; child_nodep->getAttributeString("value", rect_string); std::istringstream istream(rect_string); S32 left, bottom, width, height; istream >> left >> bottom >> width >> height; LLRect rect; rect.setOriginAndSize(left, bottom, width, height); control->set(rect.getValue()); validitems++; } break; case TYPE_COL4U: { LLColor4U color; child_nodep->getAttributeColor4U("value", color); control->set(color.getValue()); validitems++; } break; case TYPE_COL4: { LLColor4 color; child_nodep->getAttributeColor4("value", color); control->set(color.getValue()); validitems++; } break; case TYPE_COL3: { LLVector3 color; child_nodep->getAttributeVector3("value", color); control->set(LLColor3(color.mV).getValue()); validitems++; } break; } child_nodep = rootp->getNextChild(); } return validitems; }
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_embedded, BOOL use_ellipses) const { LLFastTimer _(FTM_RENDER_FONTS); if(!sDisplayFont) //do not display texts { return wstr.length() ; } if (wstr.empty() || !max_pixels) { return 0; } if (max_chars == -1) max_chars = S32_MAX; const S32 max_index = llmin(llmax(max_chars, begin_offset + max_chars), S32(wstr.length())); if (max_index <= 0 || begin_offset >= max_index || max_pixels <= 0) return 0; gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); // Strip off any style bits that are already accounted for by the font. style = style & (~getFontDesc().getStyle()); F32 drop_shadow_strength = 0.f; if (shadow != NO_SHADOW) { F32 luminance; color.calcHSL(NULL, NULL, &luminance); drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f); if (luminance < 0.35f) { shadow = NO_SHADOW; } } gGL.pushUIMatrix(); gGL.loadUIIdentity(); LLVector2 origin(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY)); // Depth translation, so that floating text appears 'in-world' // and is correctly occluded. gGL.translatef(0.f,0.f,sCurDepth); S32 chars_drawn = 0; S32 i; S32 length = max_index - begin_offset; F32 cur_x, cur_y, cur_render_x, cur_render_y; // Not guaranteed to be set correctly gGL.setSceneBlendType(LLRender::BT_ALPHA); cur_x = ((F32)x * sScaleX) + origin.mV[VX]; cur_y = ((F32)y * sScaleY) + origin.mV[VY]; // Offset y by vertical alignment. // use unscaled font metrics here switch (valign) { case TOP: cur_y -= llceil(mFontFreetype->getAscenderHeight()); break; case BOTTOM: cur_y += llceil(mFontFreetype->getDescenderHeight()); break; case VCENTER: cur_y -= llceil((llceil(mFontFreetype->getAscenderHeight()) - llceil(mFontFreetype->getDescenderHeight())) / 2.f); break; case BASELINE: // Baseline, do nothing. break; default: break; } switch (halign) { case LEFT: break; case RIGHT: cur_x -= llmin(scaled_max_pixels, ll_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)); break; case HCENTER: cur_x -= llmin(scaled_max_pixels, ll_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)) / 2; break; default: break; } cur_render_y = cur_y; cur_render_x = cur_x; F32 start_x = (F32)ll_round(cur_x); const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth(); F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight(); const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL; BOOL draw_ellipses = FALSE; if (use_ellipses && halign == LEFT) { // check for too long of a string S32 string_width = ll_round(getWidthF32(wstr, begin_offset, max_chars) * sScaleX); if (string_width > scaled_max_pixels) { // use four dots for ellipsis width to generate padding const LLWString dots(utf8str_to_wstring(std::string("...."))); scaled_max_pixels = llmax(0, scaled_max_pixels - ll_round(getWidthF32(dots.c_str()))); draw_ellipses = TRUE; } } const LLFontGlyphInfo* next_glyph = NULL; const S32 GLYPH_BATCH_SIZE = 30; static LL_ALIGN_16(LLVector4a vertices[GLYPH_BATCH_SIZE * 4]); static LLVector2 uvs[GLYPH_BATCH_SIZE * 4]; static LLColor4U colors[GLYPH_BATCH_SIZE * 4]; LLColor4U text_color(color); S32 bitmap_num = -1; S32 glyph_count = 0; for (i = begin_offset; i < begin_offset + length; i++) { llwchar wch = wstr[i]; // Handle embedded characters first, if they're enabled. // Embedded characters are a hack for notecards const embedded_data_t* ext_data = use_embedded ? getEmbeddedCharData(wch) : NULL; if (ext_data) { LLImageGL* ext_image = ext_data->mImage; const LLWString& label = ext_data->mLabel; F32 ext_height = (F32)ext_image->getHeight() * sScaleY; F32 ext_width = (F32)ext_image->getWidth() * sScaleX; F32 ext_advance = (EXT_X_BEARING * sScaleX) + ext_width; if (!label.empty()) { ext_advance += (EXT_X_BEARING + getFontExtChar()->getWidthF32( label.c_str() )) * sScaleX; } if (start_x + scaled_max_pixels < cur_x + ext_advance) { // Not enough room for this character. break; } gGL.getTexUnit(0)->bind(ext_image); // snap origin to whole screen pixel const F32 ext_x = (F32)ll_round(cur_render_x + (EXT_X_BEARING * sScaleX)); const F32 ext_y = (F32)ll_round(cur_render_y + (EXT_Y_BEARING * sScaleY + mFontFreetype->getAscenderHeight() - mFontFreetype->getLineHeight())); LLRectf uv_rect(0.f, 1.f, 1.f, 0.f); LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); if (glyph_count > 0) { gGL.begin(LLRender::QUADS); { gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); } gGL.end(); glyph_count = 0; } renderQuad(vertices, uvs, colors, screen_rect, uv_rect, LLColor4U::white, 0); //No batching here. It will never happen. gGL.begin(LLRender::QUADS); { gGL.vertexBatchPreTransformed(vertices, uvs, colors, 4); } gGL.end(); if (!label.empty()) { gGL.pushMatrix(); getFontExtChar()->render(label, 0, /*llfloor*/(ext_x / sScaleX) + ext_image->getWidth() + EXT_X_BEARING - sCurOrigin.mX, /*llfloor*/(cur_render_y / sScaleY) - sCurOrigin.mY, color, halign, BASELINE, UNDERLINE, NO_SHADOW, S32_MAX, S32_MAX, NULL, TRUE ); gGL.popMatrix(); } chars_drawn++; cur_x += ext_advance; if (((i + 1) < length) && wstr[i+1]) { cur_x += EXT_KERNING * sScaleX; } cur_render_x = cur_x; } else { const LLFontGlyphInfo* fgi = next_glyph; next_glyph = NULL; if(!fgi) { fgi = mFontFreetype->getGlyphInfo(wch); } if (!fgi) { LL_ERRS() << "Missing Glyph Info" << LL_ENDL; break; } // Per-glyph bitmap texture. S32 next_bitmap_num = fgi->mBitmapNum; if (next_bitmap_num != bitmap_num) { // Actually draw the queued glyphs before switching their texture; // otherwise the queued glyphs will be taken from wrong textures. if (glyph_count > 0) { gGL.begin(LLRender::QUADS); { gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); } gGL.end(); glyph_count = 0; } bitmap_num = next_bitmap_num; LLImageGL *font_image = font_bitmap_cache->getImageGL(bitmap_num); gGL.getTexUnit(0)->bind(font_image); } if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth)) { // Not enough room for this character. break; } // Draw the text at the appropriate location //Specify vertices and texture coordinates LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width, (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height, (fgi->mXBitmapOffset + fgi->mWidth) * inv_width, (fgi->mYBitmapOffset - PAD_UVY) * inv_height); // snap glyph origin to whole screen pixel LLRectf screen_rect((F32)ll_round(cur_render_x + (F32)fgi->mXBearing), (F32)ll_round(cur_render_y + (F32)fgi->mYBearing), (F32)ll_round(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, (F32)ll_round(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); if (glyph_count >= GLYPH_BATCH_SIZE) { gGL.begin(LLRender::QUADS); { gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); } gGL.end(); glyph_count = 0; } drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style, shadow, drop_shadow_strength); chars_drawn++; cur_x += fgi->mXAdvance; cur_y += fgi->mYAdvance; llwchar next_char = wstr[i+1]; if (next_char && (next_char < LAST_CHARACTER)) { // Kern this puppy. next_glyph = mFontFreetype->getGlyphInfo(next_char); cur_x += mFontFreetype->getXKerning(fgi, next_glyph); } // Round after kerning. // Must do this to cur_x, not just to cur_render_x, otherwise you // will squish sub-pixel kerned characters too close together. // For example, "CCCCC" looks bad. cur_x = (F32)ll_round(cur_x); //cur_y = (F32)ll_round(cur_y); cur_render_x = cur_x; cur_render_y = cur_y; } } if(glyph_count) { gGL.begin(LLRender::QUADS); { gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); } gGL.end(); } if (right_x) { *right_x = (cur_x - origin.mV[VX]) / sScaleX; } if (style & UNDERLINE) { F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight()); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.begin(LLRender::LINES); gGL.vertex2f(start_x, cur_y - descender); gGL.vertex2f(cur_x, cur_y - descender); gGL.end(); } if (draw_ellipses) { // recursively render ellipses at end of string // we've already reserved enough room gGL.pushUIMatrix(); renderUTF8(std::string("..."), 0, (cur_x - origin.mV[VX]) / sScaleX, (F32)y, color, LEFT, valign, style, shadow, S32_MAX, max_pixels, right_x, FALSE); gGL.popUIMatrix(); } gGL.popUIMatrix(); return chars_drawn; }
void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { if ((avatar->isSelf() && !gAgent.needsRenderAvatar()) || !gMeshRepo.meshRezEnabled()) { return; } stop_glerror(); for (U32 i = 0; i < mRiggedFace[type].size(); ++i) { LLFace* face = mRiggedFace[type][i]; LLDrawable* drawable = face->getDrawable(); if (!drawable) { continue; } LLVOVolume* vobj = drawable->getVOVolume(); if (!vobj) { continue; } LLVolume* volume = vobj->getVolume(); S32 te = face->getTEOffset(); if (!volume || volume->getNumVolumeFaces() <= te || !volume->isMeshAssetLoaded()) { continue; } LLUUID mesh_id = volume->getParams().getSculptID(); if (mesh_id.isNull()) { continue; } const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, vobj); if (!skin) { continue; } //stop_glerror(); //const LLVolumeFace& vol_face = volume->getVolumeFace(te); //updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); //stop_glerror(); U32 data_mask = LLFace::getRiggedDataMask(type); LLVertexBuffer* buff = face->getVertexBuffer(); if (buff) { if (sShaderLevel > 0) { //upload matrix palette to shader LLMatrix4 mat[JOINT_COUNT]; U32 count = llmin((U32) skin->mJointNames.size(), (U32) JOINT_COUNT); for (U32 i = 0; i < count; ++i) { LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); if(!joint) { joint = avatar->getJoint("mRoot"); } if (joint) { LLMatrix4a tmp; tmp.loadu((F32*)skin->mInvBindMatrix[i].mMatrix); tmp.setMul(joint->getWorldMatrix(),tmp); mat[i] = LLMatrix4(tmp.getF32ptr()); } } stop_glerror(); F32 mp[JOINT_COUNT*12]; for (U32 i = 0; i < count; ++i) { F32* m = (F32*) mat[i].mMatrix; U32 idx = i*12; mp[idx+0] = m[0]; mp[idx+1] = m[1]; mp[idx+2] = m[2]; mp[idx+3] = m[12]; mp[idx+4] = m[4]; mp[idx+5] = m[5]; mp[idx+6] = m[6]; mp[idx+7] = m[13]; mp[idx+8] = m[8]; mp[idx+9] = m[9]; mp[idx+10] = m[10]; mp[idx+11] = m[14]; } LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX, count, FALSE, (GLfloat*) mp); LLDrawPoolAvatar::sVertexProgram->uniform1f(LLShaderMgr::AVATAR_MAX_WEIGHT, F32(count-1)); stop_glerror(); } else { data_mask &= ~LLVertexBuffer::MAP_WEIGHT4; } U16 start = face->getGeomStart(); U16 end = start + face->getGeomCount()-1; S32 offset = face->getIndicesStart(); U32 count = face->getIndicesCount(); /*if (glow) { gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow()); }*/ const LLTextureEntry* te = face->getTextureEntry(); LLMaterial* mat = te->getMaterialParams().get(); if (mat && is_deferred_render) { gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture(LLRender::DIFFUSE_MAP)); gGL.getTexUnit(normal_channel)->bind(face->getTexture(LLRender::NORMAL_MAP)); gGL.getTexUnit(specular_channel)->bind(face->getTexture(LLRender::SPECULAR_MAP)); LLColor4 col = mat->getSpecularLightColor(); F32 spec = llmax(0.0001f, mat->getSpecularLightExponent() / 255.f); F32 env = mat->getEnvironmentIntensity()/255.f; if (mat->getSpecularID().isNull()) { env = te->getShiny()*0.25f; col.set(env,env,env,0); spec = env; } BOOL fullbright = te->getFullbright(); sVertexProgram->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, fullbright ? 1.f : 0.f); sVertexProgram->uniform4f(LLShaderMgr::SPECULAR_COLOR, col.mV[0], col.mV[1], col.mV[2], spec); sVertexProgram->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env); if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) { sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()/255.f); } else { sVertexProgram->setMinimumAlpha(0.004f); } for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i) { LLViewerTexture* tex = face->getTexture(i); if (tex) { tex->addTextureStats(avatar->getPixelArea()); } } } else { gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); if(sVertexProgram) { if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK) { sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()/255.f); } else { sVertexProgram->setMinimumAlpha(0.004f); } } if (normal_channel > -1) { LLDrawPoolBump::bindBumpMap(face, normal_channel); } } if (face->mTextureMatrix && vobj->mTexAnimMode) { gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadMatrix(*face->mTextureMatrix); buff->setBuffer(data_mask); buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); gGL.loadIdentity(); gGL.matrixMode(LLRender::MM_MODELVIEW); } else { buff->setBuffer(data_mask); buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); } gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES); } } }
void LLHUDEffectSpiral::triggerLocal() { mKillTime = mTimer.getElapsedTimeF32() + mDuration; BOOL show_beam = gSavedSettings.getBOOL("ShowSelectionBeam"); LLColor4 color; color.setVec(mColor); if (!mPartSourcep) { if (!mTargetObject.isNull() && !mSourceObject.isNull()) { if (show_beam) { LLPointer<LLViewerPartSourceBeam> psb = new LLViewerPartSourceBeam; psb->setColor(color); psb->setSourceObject(mSourceObject); psb->setTargetObject(mTargetObject); psb->setOwnerUUID(gAgent.getID()); LLViewerPartSim::getInstance()->addPartSource(psb); mPartSourcep = psb; } } else { if (!mSourceObject.isNull() && !mPositionGlobal.isExactlyZero()) { if (show_beam) { LLPointer<LLViewerPartSourceBeam> psb = new LLViewerPartSourceBeam; psb->setSourceObject(mSourceObject); psb->setTargetObject(NULL); psb->setColor(color); psb->mLKGTargetPosGlobal = mPositionGlobal; psb->setOwnerUUID(gAgent.getID()); LLViewerPartSim::getInstance()->addPartSource(psb); mPartSourcep = psb; } } else { LLVector3 pos; if (mSourceObject) { pos = mSourceObject->getPositionAgent(); } else { pos = gAgent.getPosAgentFromGlobal(mPositionGlobal); } LLPointer<LLViewerPartSourceSpiral> pss = new LLViewerPartSourceSpiral(pos); if (!mSourceObject.isNull()) { pss->setSourceObject(mSourceObject); } pss->setColor(color); pss->setOwnerUUID(gAgent.getID()); LLViewerPartSim::getInstance()->addPartSource(pss); mPartSourcep = pss; } } } else { LLPointer<LLViewerPartSource>& ps = mPartSourcep; if (mPartSourcep->getType() == LLViewerPartSource::LL_PART_SOURCE_BEAM) { LLViewerPartSourceBeam *psb = (LLViewerPartSourceBeam *)ps.get(); psb->setSourceObject(mSourceObject); psb->setTargetObject(mTargetObject); psb->setColor(color); if (mTargetObject.isNull()) { psb->mLKGTargetPosGlobal = mPositionGlobal; } } else { LLViewerPartSourceSpiral *pss = (LLViewerPartSourceSpiral *)ps.get(); pss->setSourceObject(mSourceObject); } } mbInit = TRUE; }
/** * Redraws the avatar list * Only does anything if the avatar list is visible. * @author Dale Glass */ void LLFloaterAvatarList::refreshAvatarList() { // Don't update list when interface is hidden if (!sInstance->getVisible()) return; // We rebuild the list fully each time it's refreshed // The assumption is that it's faster to refill it and sort than // to rebuild the whole list. LLDynamicArray<LLUUID> selected = mAvatarList->getSelectedIDs(); S32 scrollpos = mAvatarList->getScrollPos(); mAvatarList->deleteAllItems(); LLVector3d mypos = gAgent.getPositionGlobal(); LLVector3d posagent; posagent.setVec(gAgent.getPositionAgent()); LLVector3d simpos = mypos - posagent; std::map<LLUUID, LLAvatarListEntry>::iterator iter; for (iter = mAvatars.begin(); iter != mAvatars.end(); iter++) { LLSD element; LLUUID av_id; std::string av_name; LLAvatarListEntry *entry = &iter->second; // Skip if avatar hasn't been around if (entry->isDead()) { continue; } av_id = entry->getID(); av_name = entry->getName().c_str(); LLVector3d position = entry->getPosition(); BOOL UnknownAltitude = false; LLVector3d delta = position - mypos; F32 distance = (F32)delta.magVec(); if (position.mdV[VZ] == 0.0) { UnknownAltitude = true; distance = 9000.0; } delta.mdV[2] = 0.0f; F32 side_distance = (F32)delta.magVec(); // HACK: Workaround for an apparent bug: // sometimes avatar entries get stuck, and are registered // by the client as perpetually moving in the same direction. // this makes sure they get removed from the visible list eventually //jcool410 -- this f***s up seeing dueds thru minimap data > 1024m away, so, lets just say > 2048m to the side is bad //aka 8 sims if (side_distance > 2048.0f) { continue; } if (av_id.isNull()) { //llwarns << "Avatar with null key somehow got into the list!" << llendl; continue; } element["id"] = av_id; element["columns"][LIST_MARK]["column"] = "marked"; element["columns"][LIST_MARK]["type"] = "text"; if (entry->isMarked()) { element["columns"][LIST_MARK]["value"] = "X"; element["columns"][LIST_MARK]["color"] = LLColor4::blue.getValue(); element["columns"][LIST_MARK]["font-style"] = "BOLD"; } else { element["columns"][LIST_MARK]["value"] = ""; } element["columns"][LIST_AVATAR_NAME]["column"] = "avatar_name"; element["columns"][LIST_AVATAR_NAME]["type"] = "text"; element["columns"][LIST_AVATAR_NAME]["value"] = av_name; if (entry->isFocused()) { element["columns"][LIST_AVATAR_NAME]["font-style"] = "BOLD"; } //<edit> custom colors for certain types of avatars! //Changed a bit so people can modify them in settings. And since they're colors, again it's possibly account-based. Starting to think I need a function just to determine that. - HgB //element["columns"][LIST_AVATAR_NAME]["color"] = gColors.getColor( "MapAvatar" ).getValue(); LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(entry->getPosition()); LLUUID estate_owner = LLUUID::null; if(parent_estate && parent_estate->isAlive()) { estate_owner = parent_estate->getOwner(); } static const LLCachedControl<LLColor4> unselected_color(gColors, "ScrollUnselectedColor",LLColor4(LLColor4U(0, 0, 0, 204)) ); LLColor4 name_color = unselected_color; //Lindens are always more Linden than your friend, make that take precedence if(LLMuteList::getInstance()->isLinden(av_name)) { static const LLCachedControl<LLColor4> ascent_linden_color("AscentLindenColor",LLColor4(0.f,0.f,1.f,1.f)); name_color = ascent_linden_color; } //check if they are an estate owner at their current position else if(estate_owner.notNull() && av_id == estate_owner) { static const LLCachedControl<LLColor4> ascent_estate_owner_color("AscentEstateOwnerColor",LLColor4(1.f,0.6f,1.f,1.f)); name_color = ascent_estate_owner_color; } //without these dots, SL would suck. else if(is_agent_friend(av_id)) { static const LLCachedControl<LLColor4> ascent_friend_color("AscentFriendColor",LLColor4(1.f,1.f,0.f,1.f)); name_color = ascent_friend_color; } //big fat jerkface who is probably a jerk, display them as such. else if(LLMuteList::getInstance()->isMuted(av_id)) { static const LLCachedControl<LLColor4> ascent_muted_color("AscentMutedColor",LLColor4(0.7f,0.7f,0.7f,1.f)); name_color = ascent_muted_color; } name_color = name_color*0.5f + unselected_color*0.5f; element["columns"][LIST_AVATAR_NAME]["color"] = name_color.getValue(); char temp[32]; LLColor4 color = LLColor4::black; element["columns"][LIST_DISTANCE]["column"] = "distance"; element["columns"][LIST_DISTANCE]["type"] = "text"; if (UnknownAltitude) { strcpy(temp, "?"); if (entry->isDrawn()) { color = LLColor4::green2; } } else { if (distance < 100.0) { snprintf(temp, sizeof(temp), "%.1f", distance); if (distance > 20.0f) { color = LLColor4::yellow1; } else { color = LLColor4::red; } } else { if (entry->isDrawn()) { color = LLColor4::green2; } snprintf(temp, sizeof(temp), "%d", (S32)distance); } } element["columns"][LIST_DISTANCE]["value"] = temp; element["columns"][LIST_DISTANCE]["color"] = color.getValue(); position = position - simpos; S32 x = (S32)position.mdV[VX]; S32 y = (S32)position.mdV[VY]; if (x >= 0 && x <= 256 && y >= 0 && y <= 256) { snprintf(temp, sizeof(temp), "%d, %d", x, y); } else { temp[0] = '\0'; if (y < 0) { strcat(temp, "S"); } else if (y > 256) { strcat(temp, "N"); } if (x < 0) { strcat(temp, "W"); } else if (x > 256) { strcat(temp, "E"); } } element["columns"][LIST_POSITION]["column"] = "position"; element["columns"][LIST_POSITION]["type"] = "text"; element["columns"][LIST_POSITION]["value"] = temp; element["columns"][LIST_ALTITUDE]["column"] = "altitude"; element["columns"][LIST_ALTITUDE]["type"] = "text"; if (UnknownAltitude) { strcpy(temp, "?"); } else { snprintf(temp, sizeof(temp), "%d", (S32)position.mdV[VZ]); } element["columns"][LIST_ALTITUDE]["value"] = temp; element["columns"][LIST_CLIENT]["column"] = "client"; element["columns"][LIST_CLIENT]["type"] = "text"; //element["columns"][LIST_METADATA]["column"] = "metadata"; //element["columns"][LIST_METADATA]["type"] = "text"; static const LLCachedControl<LLColor4> avatar_name_color(gColors, "AvatarNameColor",LLColor4(LLColor4U(251, 175, 93, 255)) ); LLColor4 client_color(avatar_name_color); std::string client; LLVOAvatar *avatarp = gObjectList.findAvatar(av_id); if(avatarp) { avatarp->getClientInfo(client, client_color, TRUE); if(client == "") { client_color = unselected_color; client = "?"; } element["columns"][LIST_CLIENT]["value"] = client.c_str(); // <dogmode> // Don't expose Emerald's metadata. //if(avatarp->extraMetadata.length()) //{ // element["columns"][LIST_METADATA]["value"] = avatarp->extraMetadata.c_str(); //} } else { element["columns"][LIST_CLIENT]["value"] = "Out Of Range"; } //Blend to make the color show up better client_color = client_color *.5f + unselected_color * .5f; element["columns"][LIST_CLIENT]["color"] = client_color.getValue(); // Add to list mAvatarList->addElement(element, ADD_BOTTOM); } // finish mAvatarList->sortItems(); mAvatarList->selectMultiple(selected); mAvatarList->setScrollPos(scrollpos); // llinfos << "radar refresh: done" << llendl; }
// we've switched controls, or doing per-frame update, so update spinners, etc. void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp) { LLSpinCtrl* spinner1 = getChild<LLSpinCtrl>("val_spinner_1"); LLSpinCtrl* spinner2 = getChild<LLSpinCtrl>("val_spinner_2"); LLSpinCtrl* spinner3 = getChild<LLSpinCtrl>("val_spinner_3"); LLSpinCtrl* spinner4 = getChild<LLSpinCtrl>("val_spinner_4"); LLColorSwatchCtrl* color_swatch = getChild<LLColorSwatchCtrl>("color_swatch"); if (!spinner1 || !spinner2 || !spinner3 || !spinner4 || !color_swatch) { llwarns << "Could not find all desired controls by name" << llendl; return; } spinner1->setVisible(FALSE); spinner2->setVisible(FALSE); spinner3->setVisible(FALSE); spinner4->setVisible(FALSE); color_swatch->setVisible(FALSE); childSetVisible("val_text", FALSE); mComment->setText(LLStringUtil::null); if (controlp) { // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.1d if (rlv_handler_t::isEnabled()) { // Don't allow changing DBG_WRITE debug settings under @setdebug=n bool fEnable = !( (gRlvHandler.hasBehaviour(RLV_BHVR_SETDEBUG)) && (RlvExtGetSet::getDebugSettingFlags(controlp->getName()) & RlvExtGetSet::DBG_WRITE) ); // Don't allow toggling "Basic Shaders" and/or "Atmopsheric Shaders" through the debug settings under @setenv=n fEnable &= !((gRlvHandler.hasBehaviour(RLV_BHVR_SETENV)) && (("VertexShaderEnable" == controlp->getName()) || ("WindLightUseAtmosShaders" == controlp->getName()))); #ifdef RLV_EXTENSION_STARTLOCATION // Don't allow toggling RLVaLoginLastLocation fEnable &= !(RLV_SETTING_LOGINLASTLOCATION == controlp->getName()); #endif // RLV_EXTENSION_STARTLOCATION // NOTE: this runs per-frame so there's no need to explictly handle onCommitSettings() or onClickDefault() spinner1->setEnabled(fEnable); spinner2->setEnabled(fEnable); spinner3->setEnabled(fEnable); spinner4->setEnabled(fEnable); color_swatch->setEnabled(fEnable); childSetEnabled("val_text", fEnable); childSetEnabled("boolean_combo", fEnable); childSetEnabled("default_btn", fEnable); } // [/RLVa:KB] controlp = controlp->getCOAActive(); eControlType type = controlp->type(); //hide combo box only for non booleans, otherwise this will result in the combo box closing every frame childSetVisible("boolean_combo", type == TYPE_BOOLEAN); mComment->setText(controlp->getComment()); spinner1->setMaxValue(F32_MAX); spinner2->setMaxValue(F32_MAX); spinner3->setMaxValue(F32_MAX); spinner4->setMaxValue(F32_MAX); spinner1->setMinValue(-F32_MAX); spinner2->setMinValue(-F32_MAX); spinner3->setMinValue(-F32_MAX); spinner4->setMinValue(-F32_MAX); if (!spinner1->hasFocus()) { spinner1->setIncrement(0.1f); } if (!spinner2->hasFocus()) { spinner2->setIncrement(0.1f); } if (!spinner3->hasFocus()) { spinner3->setIncrement(0.1f); } if (!spinner4->hasFocus()) { spinner4->setIncrement(0.1f); } LLSD sd = controlp->get(); switch(type) { case TYPE_U32: spinner1->setVisible(TRUE); spinner1->setLabel(std::string("value")); // Debug, don't translate if (!spinner1->hasFocus()) { spinner1->setValue(sd); spinner1->setMinValue((F32)U32_MIN); spinner1->setMaxValue((F32)U32_MAX); spinner1->setIncrement(1.f); spinner1->setPrecision(0); } break; case TYPE_S32: spinner1->setVisible(TRUE); spinner1->setLabel(std::string("value")); // Debug, don't translate if (!spinner1->hasFocus()) { spinner1->setValue(sd); spinner1->setMinValue((F32)S32_MIN); spinner1->setMaxValue((F32)S32_MAX); spinner1->setIncrement(1.f); spinner1->setPrecision(0); } break; case TYPE_F32: spinner1->setVisible(TRUE); spinner1->setLabel(std::string("value")); // Debug, don't translate if (!spinner1->hasFocus()) { spinner1->setPrecision(3); spinner1->setValue(sd); } break; case TYPE_BOOLEAN: if (!childHasFocus("boolean_combo")) { if (sd.asBoolean()) { childSetValue("boolean_combo", LLSD("true")); } else { childSetValue("boolean_combo", LLSD("")); } } break; case TYPE_STRING: childSetVisible("val_text", TRUE); if (!childHasFocus("val_text")) { childSetValue("val_text", sd); } break; case TYPE_VEC3: { LLVector3 v; v.setValue(sd); spinner1->setVisible(TRUE); spinner1->setLabel(std::string("X")); spinner2->setVisible(TRUE); spinner2->setLabel(std::string("Y")); spinner3->setVisible(TRUE); spinner3->setLabel(std::string("Z")); if (!spinner1->hasFocus()) { spinner1->setPrecision(3); spinner1->setValue(v[VX]); } if (!spinner2->hasFocus()) { spinner2->setPrecision(3); spinner2->setValue(v[VY]); } if (!spinner3->hasFocus()) { spinner3->setPrecision(3); spinner3->setValue(v[VZ]); } break; } case TYPE_VEC3D: { LLVector3d v; v.setValue(sd); spinner1->setVisible(TRUE); spinner1->setLabel(std::string("X")); spinner2->setVisible(TRUE); spinner2->setLabel(std::string("Y")); spinner3->setVisible(TRUE); spinner3->setLabel(std::string("Z")); if (!spinner1->hasFocus()) { spinner1->setPrecision(3); spinner1->setValue(v[VX]); } if (!spinner2->hasFocus()) { spinner2->setPrecision(3); spinner2->setValue(v[VY]); } if (!spinner3->hasFocus()) { spinner3->setPrecision(3); spinner3->setValue(v[VZ]); } break; } case TYPE_RECT: { LLRect r; r.setValue(sd); spinner1->setVisible(TRUE); spinner1->setLabel(std::string("Left")); spinner2->setVisible(TRUE); spinner2->setLabel(std::string("Right")); spinner3->setVisible(TRUE); spinner3->setLabel(std::string("Bottom")); spinner4->setVisible(TRUE); spinner4->setLabel(std::string("Top")); if (!spinner1->hasFocus()) { spinner1->setPrecision(0); spinner1->setValue(r.mLeft); } if (!spinner2->hasFocus()) { spinner2->setPrecision(0); spinner2->setValue(r.mRight); } if (!spinner3->hasFocus()) { spinner3->setPrecision(0); spinner3->setValue(r.mBottom); } if (!spinner4->hasFocus()) { spinner4->setPrecision(0); spinner4->setValue(r.mTop); } spinner1->setMinValue((F32)S32_MIN); spinner1->setMaxValue((F32)S32_MAX); spinner1->setIncrement(1.f); spinner2->setMinValue((F32)S32_MIN); spinner2->setMaxValue((F32)S32_MAX); spinner2->setIncrement(1.f); spinner3->setMinValue((F32)S32_MIN); spinner3->setMaxValue((F32)S32_MAX); spinner3->setIncrement(1.f); spinner4->setMinValue((F32)S32_MIN); spinner4->setMaxValue((F32)S32_MAX); spinner4->setIncrement(1.f); break; } case TYPE_COL4: { LLColor4 clr; clr.setValue(sd); color_swatch->setVisible(TRUE); // only set if changed so color picker doesn't update if(clr != LLColor4(color_swatch->getValue())) { color_swatch->set(LLColor4(sd), TRUE, FALSE); } spinner4->setVisible(TRUE); spinner4->setLabel(std::string("Alpha")); if (!spinner4->hasFocus()) { spinner4->setPrecision(3); spinner4->setMinValue(0.0); spinner4->setMaxValue(1.f); spinner4->setValue(clr.mV[VALPHA]); } break; } case TYPE_COL3: { LLColor3 clr; clr.setValue(sd); color_swatch->setVisible(TRUE); color_swatch->setValue(sd); break; } case TYPE_COL4U: { LLColor4U clr; clr.setValue(sd); color_swatch->setVisible(TRUE); if(LLColor4(clr) != LLColor4(color_swatch->getValue())) { color_swatch->set(LLColor4(clr), TRUE, FALSE); } spinner4->setVisible(TRUE); spinner4->setLabel(std::string("Alpha")); if(!spinner4->hasFocus()) { spinner4->setPrecision(0); spinner4->setValue(clr.mV[VALPHA]); } spinner4->setMinValue(0); spinner4->setMaxValue(255); spinner4->setIncrement(1.f); break; } default: mComment->setText(std::string("unknown")); break; } } }
LLSD FSData::resolveClientTag(LLUUID id, bool new_system, LLColor4 color){ //WS: Create a new LLSD based on the data from the LegacyClientList if LLSD curtag; curtag["uuid"]=id.asString(); curtag["id_based"]=new_system; curtag["tex_color"]=color.getValue(); // If we don't want to display anything...return if(gSavedSettings.getU32("FSClientTagsVisibility2") == 0) { return curtag; } //WS: Do we want to use Legacy Clienttags? if(gSavedSettings.getU32("FSUseLegacyClienttags") > 0) { if(LegacyClientList.has(id.asString())) { curtag=LegacyClientList[id.asString()]; } else { if(id == LLUUID("5d9581af-d615-bc16-2667-2f04f8eeefe4"))//green { curtag["name"]="Phoenix"; curtag["color"] = LLColor4::green.getValue(); curtag["alt"] = "ed63fbd0-589e-fe1d-a3d0-16905efaa96b"; } else if(id == LLUUID("e35f7d40-6071-4b29-9727-5647bdafb5d5"))//white { curtag["name"] = "Phoenix"; curtag["color"] = LLColor4::white.getValue(); curtag["alt"] = "ed63fbd0-589e-fe1d-a3d0-16905efaa96b"; } else if(id == LLUUID("ae4e92fb-023d-23ba-d060-3403f953ab1a"))//pink { curtag["name"] = "Phoenix"; curtag["color"] = LLColor4::pink.getValue(); curtag["alt"] = "ed63fbd0-589e-fe1d-a3d0-16905efaa96b"; } else if(id == LLUUID("e71b780e-1a57-400d-4649-959f69ec7d51"))//red { curtag["name"] = "Phoenix"; curtag["color"] = LLColor4::red.getValue(); curtag["alt"] = "ed63fbd0-589e-fe1d-a3d0-16905efaa96b"; } else if(id == LLUUID("c1c189f5-6dab-fc03-ea5a-f9f68f90b018"))//orange { curtag["name"] = "Phoenix"; curtag["color"] = LLColor4::orange.getValue(); curtag["alt"] = "ed63fbd0-589e-fe1d-a3d0-16905efaa96b"; } else if(id == LLUUID("8cf0577c-22d3-6a73-523c-15c0a90d6c27")) //purple { curtag["name"] = "Phoenix"; curtag["color"] = LLColor4::purple.getValue(); curtag["alt"] = "ed63fbd0-589e-fe1d-a3d0-16905efaa96b"; } else if(id == LLUUID("5f0e7c32-38c3-9214-01f0-fb16a5b40128"))//yellow { curtag["name"] = "Phoenix"; curtag["color"] = LLColor4::yellow.getValue(); curtag["alt"] = "ed63fbd0-589e-fe1d-a3d0-16905efaa96b"; } else if(id == LLUUID("5bb6e4a6-8e24-7c92-be2e-91419bb0ebcb"))//blue { curtag["name"] = "Phoenix"; curtag["color"] = LLColor4::blue.getValue(); curtag["alt"] = "ed63fbd0-589e-fe1d-a3d0-16905efaa96b"; } else if(id == LLUUID("ed63fbd0-589e-fe1d-a3d0-16905efaa96b"))//default (red) { curtag["name"] = "Phoenix"; curtag["color"] = LLColor4::red.getValue(); } else if(id == LLUUID("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"))//viewer 2.0 { curtag["name"] = "LL Viewer"; } else if(id == LLUUID("cc7a030f-282f-c165-44d2-b5ee572e72bf")) { curtag["name"] = "Imprudence"; } else if(id == LLUUID("54d93609-1392-2a93-255c-a9dd429ecca5")) { curtag["name"] = "Emergence"; } else if(id == LLUUID("8873757c-092a-98fb-1afd-ecd347566fcd")) { curtag["name"] = "Ascent"; } else if(id == LLUUID("f25263b7-6167-4f34-a4ef-af65213b2e39")) { curtag["name"] = "Singularity"; } if(curtag.has("name")) curtag["tpvd"]=true; } } // Filtering starts here: //WS: If the current tag has an "alt" definied and we don't want multiple colors. Resolve the alt. if((gSavedSettings.getU32("FSColorClienttags") == 1) && curtag.has("alt")) { curtag = resolveClientTag(curtag["alt"], new_system, color); } //WS: If we have a tag using the new system, check if we want to display it's name and/or color if(new_system) { if(gSavedSettings.getU32("FSClientTagsVisibility2") >= 3) { // strnlen() doesn't exist on OS X before 10.7. -- TS char tag_temp[UUID_BYTES+1]; strncpy(tag_temp,(const char*)&id.mData[0], UUID_BYTES); tag_temp[UUID_BYTES] = '\0'; U32 tag_len = strlen(tag_temp); std::string clienttagname = std::string((const char*)&id.mData[0], tag_len); LLStringFn::replace_ascii_controlchars(clienttagname, LL_UNKNOWN_CHAR); curtag["name"] = clienttagname; } if(gSavedSettings.getU32("FSColorClienttags") >= 3 || curtag["tpvd"].asBoolean()) { if(curtag["tpvd"].asBoolean() && gSavedSettings.getU32("FSColorClienttags") < 3) { if(color == LLColor4::blue || color == LLColor4::yellow || color == LLColor4::purple || color == LLColor4((F32)0.99,(F32)0.39,(F32)0.12,(F32)1) || color == LLColor4::red || color == LLColor4((F32)0.99,(F32)0.56,(F32)0.65,(F32)1) || color == LLColor4::white || color == LLColor4::green) { curtag["color"] = color.getValue(); } } else { curtag["color"] = color.getValue(); } } } //If we only want to display tpvd viewer. And "tpvd" is not available or false, then // clear the data, but keep the basedata (like uuid, id_based and tex_color) for (maybe) later displaying. if(gSavedSettings.getU32("FSClientTagsVisibility2") <= 1 && (!curtag.has("tpvd") || !curtag["tpvd"].asBoolean())) { curtag.clear(); } curtag["uuid"]=id.asString(); curtag["id_based"]=new_system; curtag["tex_color"]=color.getValue(); return curtag; }
//static void LLViewerChat::getChatColor(const LLChat& chat, LLColor4& r_color, bool is_local) { if(chat.mMuted) { r_color= LLUIColorTable::instance().getColor("LtGray"); } else { switch(chat.mSourceType) { case CHAT_SOURCE_SYSTEM: r_color = LLUIColorTable::instance().getColor("SystemChatColor"); break; case CHAT_SOURCE_AGENT: if (chat.mFromID.isNull() || SYSTEM_FROM == chat.mFromName) { r_color = LLUIColorTable::instance().getColor("SystemChatColor"); } else { if(gAgentID == chat.mFromID) { r_color = LLUIColorTable::instance().getColor("UserChatColor"); } else { r_color = LLUIColorTable::instance().getColor("AgentChatColor"); } //color based on contact sets prefs if(LGGContactSets::getInstance()->hasFriendColorThatShouldShow(chat.mFromID,TRUE)) { r_color = LGGContactSets::getInstance()->getFriendColor(chat.mFromID); } } break; case CHAT_SOURCE_OBJECT: if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) { r_color = LLUIColorTable::instance().getColor("ScriptErrorColor"); } else if ( chat.mChatType == CHAT_TYPE_OWNER ) { r_color = LLUIColorTable::instance().getColor("llOwnerSayChatColor"); } else if ( chat.mChatType == CHAT_TYPE_DIRECT ) { r_color = LLUIColorTable::instance().getColor("DirectChatColor"); } else if ( chat.mChatType == CHAT_TYPE_IM ) { r_color = LLUIColorTable::instance().getColor("ObjectIMColor"); } else { r_color = LLUIColorTable::instance().getColor("ObjectChatColor"); } break; default: r_color.setToWhite(); } //Keyword alerts -KC if ((gAgentID != chat.mFromID || chat.mFromName == SYSTEM_FROM) && FSKeywords::getInstance()->chatContainsKeyword(chat, is_local)) { std::string msg = chat.mFromName; std::string prefix = chat.mText.substr(0, 4); if(prefix == "/me " || prefix == "/me'") { msg = msg + chat.mText.substr(3); } else { msg = msg + ": " + chat.mText; } #if LL_WINDOWS gGrowlManager->notify("Keyword Alert", msg, "Keyword Alert"); #endif static LLCachedControl<bool> sFSKeywordChangeColor(gSavedPerAccountSettings, "FSKeywordChangeColor"); if (sFSKeywordChangeColor) { static LLCachedControl<LLColor4> sFSKeywordColor(gSavedPerAccountSettings, "FSKeywordColor"); r_color = sFSKeywordColor; } } if (!chat.mPosAgent.isExactlyZero()) { LLVector3 pos_agent = gAgent.getPositionAgent(); F32 distance_squared = dist_vec_squared(pos_agent, chat.mPosAgent); F32 dist_near_chat = LLWorld::getInstance()->getSayDistance(); if (distance_squared > dist_near_chat * dist_near_chat) { // diminish far-off chat r_color.mV[VALPHA] = 0.8f; } } } }
// we've switched controls, or doing per-frame update, so update spinners, etc. void LLFloaterSettingsDebug::updateControl(LLControlVariable* controlp) { LLSpinCtrl* spinner1 = getChild<LLSpinCtrl>("val_spinner_1"); LLSpinCtrl* spinner2 = getChild<LLSpinCtrl>("val_spinner_2"); LLSpinCtrl* spinner3 = getChild<LLSpinCtrl>("val_spinner_3"); LLSpinCtrl* spinner4 = getChild<LLSpinCtrl>("val_spinner_4"); LLColorSwatchCtrl* color_swatch = getChild<LLColorSwatchCtrl>("color_swatch"); if (!spinner1 || !spinner2 || !spinner3 || !spinner4 || !color_swatch) { llwarns << "Could not find all desired controls by name" << llendl; return; } spinner1->setVisible(FALSE); spinner2->setVisible(FALSE); spinner3->setVisible(FALSE); spinner4->setVisible(FALSE); color_swatch->setVisible(FALSE); childSetVisible("val_text", FALSE); mComment->setText(LLStringUtil::null); if (controlp) { eControlType type = controlp->type(); //hide combo box only for non booleans, otherwise this will result in the combo box closing every frame childSetVisible("boolean_combo", type == TYPE_BOOLEAN); mComment->setText(controlp->getComment()); spinner1->setMaxValue(F32_MAX); spinner2->setMaxValue(F32_MAX); spinner3->setMaxValue(F32_MAX); spinner4->setMaxValue(F32_MAX); spinner1->setMinValue(-F32_MAX); spinner2->setMinValue(-F32_MAX); spinner3->setMinValue(-F32_MAX); spinner4->setMinValue(-F32_MAX); if (!spinner1->hasFocus()) { spinner1->setIncrement(0.1f); } if (!spinner2->hasFocus()) { spinner2->setIncrement(0.1f); } if (!spinner3->hasFocus()) { spinner3->setIncrement(0.1f); } if (!spinner4->hasFocus()) { spinner4->setIncrement(0.1f); } LLSD sd = controlp->get(); switch(type) { case TYPE_U32: spinner1->setVisible(TRUE); spinner1->setLabel(std::string("value")); // Debug, don't translate if (!spinner1->hasFocus()) { spinner1->setValue(sd); spinner1->setMinValue((F32)U32_MIN); spinner1->setMaxValue((F32)U32_MAX); spinner1->setIncrement(1.f); spinner1->setPrecision(0); } break; case TYPE_S32: spinner1->setVisible(TRUE); spinner1->setLabel(std::string("value")); // Debug, don't translate if (!spinner1->hasFocus()) { spinner1->setValue(sd); spinner1->setMinValue((F32)S32_MIN); spinner1->setMaxValue((F32)S32_MAX); spinner1->setIncrement(1.f); spinner1->setPrecision(0); } break; case TYPE_F32: spinner1->setVisible(TRUE); spinner1->setLabel(std::string("value")); // Debug, don't translate if (!spinner1->hasFocus()) { spinner1->setPrecision(3); spinner1->setValue(sd); } break; case TYPE_BOOLEAN: if (!childHasFocus("boolean_combo")) { if (sd.asBoolean()) { childSetValue("boolean_combo", LLSD("true")); } else { childSetValue("boolean_combo", LLSD("")); } } break; case TYPE_STRING: childSetVisible("val_text", TRUE); if (!childHasFocus("val_text")) { childSetValue("val_text", sd); } break; case TYPE_VEC3: { LLVector3 v; v.setValue(sd); spinner1->setVisible(TRUE); spinner1->setLabel(std::string("X")); spinner2->setVisible(TRUE); spinner2->setLabel(std::string("Y")); spinner3->setVisible(TRUE); spinner3->setLabel(std::string("Z")); if (!spinner1->hasFocus()) { spinner1->setPrecision(3); spinner1->setValue(v[VX]); } if (!spinner2->hasFocus()) { spinner2->setPrecision(3); spinner2->setValue(v[VY]); } if (!spinner3->hasFocus()) { spinner3->setPrecision(3); spinner3->setValue(v[VZ]); } break; } case TYPE_VEC3D: { LLVector3d v; v.setValue(sd); spinner1->setVisible(TRUE); spinner1->setLabel(std::string("X")); spinner2->setVisible(TRUE); spinner2->setLabel(std::string("Y")); spinner3->setVisible(TRUE); spinner3->setLabel(std::string("Z")); if (!spinner1->hasFocus()) { spinner1->setPrecision(3); spinner1->setValue(v[VX]); } if (!spinner2->hasFocus()) { spinner2->setPrecision(3); spinner2->setValue(v[VY]); } if (!spinner3->hasFocus()) { spinner3->setPrecision(3); spinner3->setValue(v[VZ]); } break; } case TYPE_RECT: { LLRect r; r.setValue(sd); spinner1->setVisible(TRUE); spinner1->setLabel(std::string("Left")); spinner2->setVisible(TRUE); spinner2->setLabel(std::string("Right")); spinner3->setVisible(TRUE); spinner3->setLabel(std::string("Bottom")); spinner4->setVisible(TRUE); spinner4->setLabel(std::string("Top")); if (!spinner1->hasFocus()) { spinner1->setPrecision(0); spinner1->setValue(r.mLeft); } if (!spinner2->hasFocus()) { spinner2->setPrecision(0); spinner2->setValue(r.mRight); } if (!spinner3->hasFocus()) { spinner3->setPrecision(0); spinner3->setValue(r.mBottom); } if (!spinner4->hasFocus()) { spinner4->setPrecision(0); spinner4->setValue(r.mTop); } spinner1->setMinValue((F32)S32_MIN); spinner1->setMaxValue((F32)S32_MAX); spinner1->setIncrement(1.f); spinner2->setMinValue((F32)S32_MIN); spinner2->setMaxValue((F32)S32_MAX); spinner2->setIncrement(1.f); spinner3->setMinValue((F32)S32_MIN); spinner3->setMaxValue((F32)S32_MAX); spinner3->setIncrement(1.f); spinner4->setMinValue((F32)S32_MIN); spinner4->setMaxValue((F32)S32_MAX); spinner4->setIncrement(1.f); break; } case TYPE_COL4: { LLColor4 clr; clr.setValue(sd); color_swatch->setVisible(TRUE); // only set if changed so color picker doesn't update if(clr != LLColor4(color_swatch->getValue())) { color_swatch->set(LLColor4(sd), TRUE, FALSE); } spinner4->setVisible(TRUE); spinner4->setLabel(std::string("Alpha")); if (!spinner4->hasFocus()) { spinner4->setPrecision(3); spinner4->setMinValue(0.0); spinner4->setMaxValue(1.f); spinner4->setValue(clr.mV[VALPHA]); } break; } case TYPE_COL3: { LLColor3 clr; clr.setValue(sd); color_swatch->setVisible(TRUE); color_swatch->setValue(sd); break; } case TYPE_COL4U: { LLColor4U clr; clr.setValue(sd); color_swatch->setVisible(TRUE); if(LLColor4(clr) != LLColor4(color_swatch->getValue())) { color_swatch->set(LLColor4(clr), TRUE, FALSE); } spinner4->setVisible(TRUE); spinner4->setLabel(std::string("Alpha")); if(!spinner4->hasFocus()) { spinner4->setPrecision(0); spinner4->setValue(clr.mV[VALPHA]); } spinner4->setMinValue(0); spinner4->setMaxValue(255); spinner4->setIncrement(1.f); break; } default: mComment->setText(std::string("unknown")); break; } } }
template <> eControlType get_control_type<LLColor4>(const LLColor4& in, LLSD& out) { out = in.getValue(); return TYPE_COL4; }