void LLHUDText::renderText() { if (!mVisible || mHidden) { return; } gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); LLGLState gls_blend(GL_BLEND, TRUE); LLGLState gls_alpha(GL_ALPHA_TEST, TRUE); LLColor4 shadow_color(0.f, 0.f, 0.f, 1.f); F32 alpha_factor = 1.f; LLColor4 text_color = mColor; if (mDoFade) { if (mLastDistance > mFadeDistance) { alpha_factor = llmax(0.f, 1.f - (mLastDistance - mFadeDistance)/mFadeRange); text_color.mV[3] = text_color.mV[3]*alpha_factor; } } if (text_color.mV[3] < 0.01f) { return; } shadow_color.mV[3] = text_color.mV[3]; mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f)); // *TODO: cache this image LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); // *TODO: make this a per-text setting LLColor4 bg_color = LLUIColorTable::instance().getColor("ObjectBubbleColor"); bg_color.setAlpha(gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor); const S32 border_height = 16; const S32 border_width = 16; // *TODO move this into helper function F32 border_scale = 1.f; if (border_height * 2 > mHeight) { border_scale = (F32)mHeight / ((F32)border_height * 2.f); } if (border_width * 2 > mWidth) { border_scale = llmin(border_scale, (F32)mWidth / ((F32)border_width * 2.f)); } // scale screen size of borders down //RN: for now, text on hud objects is never occluded LLVector3 x_pixel_vec; LLVector3 y_pixel_vec; if (mOnHUDAttachment) { x_pixel_vec = LLVector3::y_axis / (F32)gViewerWindow->getWorldViewWidthRaw(); y_pixel_vec = LLVector3::z_axis / (F32)gViewerWindow->getWorldViewHeightRaw(); } else { LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec); } LLVector3 width_vec = mWidth * x_pixel_vec; LLVector3 height_vec = mHeight * y_pixel_vec; mRadius = (width_vec + height_vec).magVec() * 0.5f; LLVector2 screen_offset; screen_offset = mPositionOffset; LLVector3 render_position = mPositionAgent + (x_pixel_vec * screen_offset.mV[VX]) + (y_pixel_vec * screen_offset.mV[VY]); F32 y_offset = (F32)mOffsetY; // Render label { gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } // Render text { // -1 mMaxLines means unlimited lines. S32 start_segment; S32 max_lines = getMaxLines(); if (max_lines < 0) { start_segment = 0; } else { start_segment = llmax((S32)0, (S32)mTextSegments.size() - max_lines); } for (std::vector<LLHUDTextSegment>::iterator segment_iter = mTextSegments.begin() + start_segment; segment_iter != mTextSegments.end(); ++segment_iter ) { const LLFontGL* fontp = segment_iter->mFont; y_offset -= fontp->getLineHeight() - 1; // correction factor to match legacy font metrics U8 style = segment_iter->mStyle; LLFontGL::ShadowType shadow = LLFontGL::DROP_SHADOW; F32 x_offset; if (mTextAlignment== ALIGN_TEXT_CENTER) { x_offset = -0.5f*segment_iter->getWidth(fontp); } else // ALIGN_LEFT { x_offset = -0.5f * mWidth + (HORIZONTAL_PADDING / 2.f); } text_color = segment_iter->mColor; text_color.mV[VALPHA] *= alpha_factor; hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, mOnHUDAttachment); } } /// Reset the default color to white. The renderer expects this to be the default. gGL.color4f(1.0f, 1.0f, 1.0f, 1.0f); }
BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) { LL_RECORD_BLOCK_TIME(FTM_UPDATE_TERRAIN); dirtySpatialGroup(TRUE); S32 min_comp, max_comp, range; min_comp = lltrunc(mPatchp->getMinComposition()); max_comp = lltrunc(ceil(mPatchp->getMaxComposition())); range = (max_comp - min_comp); range++; S32 new_base_comp = lltrunc(mPatchp->getMinComposition()); if (range > 3) { if ((mPatchp->getMinComposition() - min_comp) > (max_comp - mPatchp->getMaxComposition())) { // The top side runs over more new_base_comp++; } range = 3; } // Pick the two closest detail textures for this patch... // Then create the draw pool for it. // Actually, should get the average composition instead of the center. mBaseComp = new_base_comp; ////////////////////////// // // Figure out the strides // // U32 patch_width, render_stride, north_stride, east_stride, length; render_stride = mPatchp->getRenderStride(); patch_width = mPatchp->getSurface()->getGridsPerPatchEdge(); length = patch_width / render_stride; if (mPatchp->getNeighborPatch(NORTH)) { north_stride = mPatchp->getNeighborPatch(NORTH)->getRenderStride(); } else { north_stride = render_stride; } if (mPatchp->getNeighborPatch(EAST)) { east_stride = mPatchp->getNeighborPatch(EAST)->getRenderStride(); } else { east_stride = render_stride; } mLastLength = length; mLastStride = render_stride; mLastNorthStride = north_stride; mLastEastStride = east_stride; return TRUE; }
// Per-frame updates of visibility void LLStatusBar::refresh() { // Adding Net Stat Meter back in F32 bwtotal = gViewerThrottle.getMaxBandwidth() / 1000.f; mSGBandwidth->setMin(0.f); mSGBandwidth->setMax(bwtotal*1.25f); mSGBandwidth->setThreshold(0, bwtotal*0.75f); mSGBandwidth->setThreshold(1, bwtotal); mSGBandwidth->setThreshold(2, bwtotal); // *TODO: Localize / translate time // Get current UTC time, adjusted for the user's clock // being off. time_t utc_time; utc_time = time_corrected(); // There's only one internal tm buffer. struct tm* internal_time; // Convert to Pacific, based on server's opinion of whether // it's daylight savings time there. internal_time = utc_to_pacific_time(utc_time, gPacificDaylightTime); S32 hour = internal_time->tm_hour; S32 min = internal_time->tm_min; std::string am_pm = "AM"; if (hour > 11) { hour -= 12; am_pm = "PM"; } std::string tz = "PST"; if (gPacificDaylightTime) { tz = "PDT"; } // Zero hour is 12 AM if (hour == 0) hour = 12; std::ostringstream t; t << std::setfill(' ') << std::setw(2) << hour << ":" << std::setfill('0') << std::setw(2) << min << " " << am_pm << " " << tz; mTextTime->setText(t.str()); // Year starts at 1900, set the tooltip to have the date std::ostringstream date; date << sDays[internal_time->tm_wday] << ", " << std::setfill('0') << std::setw(2) << internal_time->tm_mday << " " << sMonths[internal_time->tm_mon] << " " << internal_time->tm_year + 1900; mTextTime->setToolTip(date.str()); LLRect r; const S32 MENU_RIGHT = gMenuBarView->getRightmostMenuEdge(); S32 x = MENU_RIGHT + MENU_PARCEL_SPACING; S32 y = 0; bool search_visible = gSavedSettings.getBOOL("ShowSearchBar"); // reshape menu bar to its content's width if (MENU_RIGHT != gMenuBarView->getRect().getWidth()) { gMenuBarView->reshape(MENU_RIGHT, gMenuBarView->getRect().getHeight()); } LLViewerRegion *region = gAgent.getRegion(); LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); LLRect buttonRect; if (LLHUDIcon::iconsNearby()) { childGetRect( "scriptout", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect("scriptout",r); childSetVisible("scriptout", true); x += buttonRect.getWidth(); } else { childSetVisible("scriptout", false); } if ((region && region->getAllowDamage()) || (parcel && parcel->getAllowDamage()) ) { // set visibility based on flashing if( mHealthTimer->hasExpired() ) { childSetVisible("health", true); } else { BOOL flash = S32(mHealthTimer->getElapsedSeconds() * ICON_FLASH_FREQUENCY) & 1; childSetVisible("health", flash); } mTextHealth->setVisible(TRUE); // Health childGetRect( "health", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect("health", r); x += buttonRect.getWidth(); const S32 health_width = S32( LLFontGL::getFontSansSerifSmall()->getWidth(std::string("100%")) ); r.set(x, y+TEXT_HEIGHT - 2, x+health_width, y); mTextHealth->setRect(r); x += health_width; } else { // invisible if region doesn't allow damage childSetVisible("health", false); mTextHealth->setVisible(FALSE); } if ((region && region->getBlockFly()) || (parcel && !parcel->getAllowFly()) ) { // No Fly Zone childGetRect( "no_fly", buttonRect ); childSetVisible( "no_fly", true ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_fly", r ); x += buttonRect.getWidth(); } else { // Fly Zone childSetVisible("no_fly", false); } BOOL no_build = parcel && !parcel->getAllowModify(); if (no_build) { childSetVisible("no_build", TRUE); childGetRect( "no_build", buttonRect ); // No Build Zone r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_build", r ); x += buttonRect.getWidth(); } else { childSetVisible("no_build", FALSE); } BOOL no_scripts = FALSE; if((region && ((region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) || (region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS))) || (parcel && !parcel->getAllowOtherScripts())) { no_scripts = TRUE; } if (no_scripts) { // No scripts childSetVisible("no_scripts", TRUE); childGetRect( "no_scripts", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_scripts", r ); x += buttonRect.getWidth(); } else { // Yes scripts childSetVisible("no_scripts", FALSE); } BOOL no_region_push = (region && region->getRestrictPushObject()); BOOL no_push = no_region_push || (parcel && parcel->getRestrictPushObject()); if (no_push) { childSetVisible("restrictpush", TRUE); childGetRect( "restrictpush", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "restrictpush", r ); x += buttonRect.getWidth(); } else { childSetVisible("restrictpush", FALSE); } BOOL have_voice = parcel && parcel->getParcelFlagAllowVoice(); if (have_voice) { childSetVisible("status_no_voice", FALSE); } else { childSetVisible("status_no_voice", TRUE); childGetRect( "status_no_voice", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "status_no_voice", r ); x += buttonRect.getWidth(); } BOOL canBuyLand = parcel && !parcel->isPublic() && LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false); childSetVisible("buyland", canBuyLand); if (canBuyLand) { //HACK: layout tweak until this is all xml x += 9; childGetRect( "buyland", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "buyland", r ); x += buttonRect.getWidth(); } std::string location_name; if (region) { const LLVector3& agent_pos_region = gAgent.getPositionAgent(); S32 pos_x = lltrunc( agent_pos_region.mV[VX] ); S32 pos_y = lltrunc( agent_pos_region.mV[VY] ); S32 pos_z = lltrunc( agent_pos_region.mV[VZ] ); // Round the numbers based on the velocity LLVector3 agent_velocity = gAgent.getVelocity(); F32 velocity_mag_sq = agent_velocity.magVecSquared(); const F32 FLY_CUTOFF = 6.f; // meters/sec const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF; const F32 WALK_CUTOFF = 1.5f; // meters/sec const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF; if (velocity_mag_sq > FLY_CUTOFF_SQ) { pos_x -= pos_x % 4; pos_y -= pos_y % 4; } else if (velocity_mag_sq > WALK_CUTOFF_SQ) { pos_x -= pos_x % 2; pos_y -= pos_y % 2; } mRegionDetails.mTime = mTextTime->getText(); mRegionDetails.mBalance = mBalance; mRegionDetails.mAccessString = region->getSimAccessString(); mRegionDetails.mPing = region->getNetDetailsForLCD(); if (parcel) { location_name = region->getName() + llformat(" %d, %d, %d (%s) - %s", pos_x, pos_y, pos_z, region->getSimAccessString().c_str(), parcel->getName().c_str()); // keep these around for the LCD to use mRegionDetails.mRegionName = region->getName(); mRegionDetails.mParcelName = parcel->getName(); mRegionDetails.mX = pos_x; mRegionDetails.mY = pos_y; mRegionDetails.mZ = pos_z; mRegionDetails.mArea = parcel->getArea(); mRegionDetails.mForSale = parcel->getForSale(); mRegionDetails.mTraffic = LLViewerParcelMgr::getInstance()->getDwelling(); if (parcel->isPublic()) { mRegionDetails.mOwner = "Public"; } else { if (parcel->getIsGroupOwned()) { if(!parcel->getGroupID().isNull()) { gCacheName->getGroupName(parcel->getGroupID(), mRegionDetails.mOwner); } else { mRegionDetails.mOwner = "Group Owned"; } } else { // Figure out the owner's name gCacheName->getFullName(parcel->getOwnerID(), mRegionDetails.mOwner); } } } else { location_name = region->getName() + llformat(" %d, %d, %d (%s)", pos_x, pos_y, pos_z, region->getSimAccessString().c_str()); // keep these around for the LCD to use mRegionDetails.mRegionName = region->getName(); mRegionDetails.mParcelName = "Unknown"; mRegionDetails.mX = pos_x; mRegionDetails.mY = pos_y; mRegionDetails.mZ = pos_z; mRegionDetails.mArea = 0; mRegionDetails.mForSale = FALSE; mRegionDetails.mOwner = "Unknown"; mRegionDetails.mTraffic = 0.0f; } } else { // no region location_name = "(Unknown)"; // keep these around for the LCD to use mRegionDetails.mRegionName = "Unknown"; mRegionDetails.mParcelName = "Unknown"; mRegionDetails.mAccessString = "Unknown"; mRegionDetails.mX = 0; mRegionDetails.mY = 0; mRegionDetails.mZ = 0; mRegionDetails.mArea = 0; mRegionDetails.mForSale = FALSE; mRegionDetails.mOwner = "Unknown"; mRegionDetails.mTraffic = 0.0f; } // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Modified: RLVa-1.0.0a if ( (region) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) // region == NULL if we loose our connection to the grid { // TODO-RLVa: find out whether the LCD code is still used because if so then we need to filter that as well location_name = llformat("%s (%s) - %s", rlv_handler_t::cstrHiddenRegion.c_str(), region->getSimAccessString().c_str(), rlv_handler_t::cstrHidden.c_str()); } // [/RLVa:KB] mTextParcelName->setText(location_name); // x = right edge // loop through: stat graphs, search btn, search text editor, money, buy money, clock // adjust rect // finally adjust parcel name rect S32 new_right = getRect().getWidth(); if (search_visible) { childGetRect("search_btn", r); //r.translate( new_right - r.mRight, 0); //childSetRect("search_btn", r); new_right -= r.getWidth(); childGetRect("search_editor", r); //r.translate( new_right - r.mRight, 0); //childSetRect("search_editor", r); new_right -= r.getWidth() + 6; } else { childGetRect("stat_btn", r); r.translate( new_right - r.mRight, 0); childSetRect("stat_btn", r); new_right -= r.getWidth() + 6; } // Set rects of money, buy money, time childGetRect("BalanceText", r); r.translate( new_right - r.mRight, 0); childSetRect("BalanceText", r); new_right -= r.getWidth() - 18; childGetRect("buycurrency", r); r.translate( new_right - r.mRight, 0); childSetRect("buycurrency", r); new_right -= r.getWidth() + 6; childGetRect("TimeText", r); // mTextTime->getTextPixelWidth(); r.translate( new_right - r.mRight, 0); childSetRect("TimeText", r); // new_right -= r.getWidth() + MENU_PARCEL_SPACING; // Adjust region name and parcel name x += 8; const S32 PARCEL_RIGHT = llmin(mTextTime->getRect().mLeft, mTextParcelName->getTextPixelWidth() + x + 5); r.set(x+4, getRect().getHeight() - 2, PARCEL_RIGHT, 0); mTextParcelName->setRect(r); // Set search bar visibility childSetVisible("search_editor", search_visible); childSetVisible("search_btn", search_visible); childSetVisible("menubar_search_bevel_bg", search_visible); mSGBandwidth->setVisible(! search_visible); mSGPacketLoss->setVisible(! search_visible); childSetEnabled("stat_btn", ! search_visible); }
// Uses the last GL matrices set in set_perspective to project a point from // the agent's region space to the nearest edge in screen coordinates. // Returns TRUE if projection succeeds. BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLCoordGL &out_point) const { LLVector3 dir_to_point = pos_agent - getOrigin(); dir_to_point /= dir_to_point.magVec(); BOOL in_front = TRUE; if (dir_to_point * getAtAxis() < 0.f) { in_front = FALSE; } GLdouble x, y, z; // object's window coords, GL-style if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ], gGLModelView, gGLProjection, (GLint*)gGLViewport, &x, &y, &z)) { x /= gViewerWindow->getDisplayScale().mV[VX]; y /= gViewerWindow->getDisplayScale().mV[VY]; // should now have the x,y coords of grab_point in screen space const LLRect& window_rect = gViewerWindow->getVirtualWindowRect(); // ...sanity check S32 int_x = lltrunc(x); S32 int_y = lltrunc(y); // find the center GLdouble center_x = (GLdouble)(0.5f * (window_rect.mLeft + window_rect.mRight)); GLdouble center_y = (GLdouble)(0.5f * (window_rect.mBottom + window_rect.mTop)); if (x == center_x && y == center_y) { // can't project to edge from exact center return FALSE; } // find the line from center to local GLdouble line_x = x - center_x; GLdouble line_y = y - center_y; int_x = lltrunc(center_x); int_y = lltrunc(center_y); if (0.f == line_x) { // the slope of the line is undefined if (line_y > 0.f) { int_y = window_rect.mTop; } else { int_y = window_rect.mBottom; } } else if (0 == window_rect.getWidth()) { // the diagonal slope of the view is undefined if (y < window_rect.mBottom) { int_y = window_rect.mBottom; } else if ( y > window_rect.mTop) { int_y = window_rect.mTop; } } else { F32 line_slope = (F32)(line_y / line_x); F32 rect_slope = ((F32)window_rect.getHeight()) / ((F32)window_rect.getWidth()); if (fabs(line_slope) > rect_slope) { if (line_y < 0.f) { // bottom int_y = window_rect.mBottom; } else { // top int_y = window_rect.mTop; } int_x = lltrunc(((GLdouble)int_y - center_y) / line_slope + center_x); } else if (fabs(line_slope) < rect_slope) { if (line_x < 0.f) { // left int_x = window_rect.mLeft; } else { // right int_x = window_rect.mRight; } int_y = lltrunc(((GLdouble)int_x - center_x) * line_slope + center_y); } else { // exactly parallel ==> push to the corners if (line_x > 0.f) { int_x = window_rect.mRight; } else { int_x = window_rect.mLeft; } if (line_y > 0.0f) { int_y = window_rect.mTop; } else { int_y = window_rect.mBottom; } } } if (!in_front) { int_x = window_rect.mLeft + window_rect.mRight - int_x; int_y = window_rect.mBottom + window_rect.mTop - int_y; } out_point.mX = int_x; out_point.mY = int_y; return TRUE; } return FALSE; }
// Per-frame updates of visibility void LLStatusBar::refresh() { F32 bwtotal = gViewerThrottle.getMaxBandwidth() / 1000.f; mSGBandwidth->setMin(0.f); mSGBandwidth->setMax(bwtotal*1.25f); mSGBandwidth->setThreshold(0, bwtotal*0.75f); mSGBandwidth->setThreshold(1, bwtotal); mSGBandwidth->setThreshold(2, bwtotal); // Get current UTC time, adjusted for the user's clock // being off. U32 utc_time; utc_time = time_corrected(); // There's only one internal tm buffer. struct tm* internal_time; // Convert to Pacific, based on server's opinion of whether // it's daylight savings time there. internal_time = utc_to_pacific_time(utc_time, gPacificDaylightTime); S32 hour = internal_time->tm_hour; S32 min = internal_time->tm_min; std::string am_pm = "AM"; if (hour > 11) { hour -= 12; am_pm = "PM"; } std::string tz = "PST"; if (gPacificDaylightTime) { tz = "PDT"; } // Zero hour is 12 AM if (hour == 0) hour = 12; std::ostringstream t; t << std::setfill(' ') << std::setw(2) << hour << ":" << std::setfill('0') << std::setw(2) << min << " " << am_pm << " " << tz; mTextTime->setText(t.str().c_str()); LLRect r; const S32 MENU_RIGHT = gMenuBarView->getRightmostMenuEdge(); S32 x = MENU_RIGHT + MENU_PARCEL_SPACING; S32 y = 0; // reshape menu bar to its content's width if (MENU_RIGHT != gMenuBarView->getRect().getWidth()) { gMenuBarView->reshape(MENU_RIGHT, gMenuBarView->getRect().getHeight()); } LLViewerRegion *region = gAgent.getRegion(); LLParcel *parcel = gParcelMgr->getAgentParcel(); LLRect buttonRect; if (LLHUDIcon::iconsNearby()) { childGetRect( "scriptout", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); mBtnScriptOut->setRect(r); mBtnScriptOut->setVisible(TRUE); x += buttonRect.getWidth(); } else { mBtnScriptOut->setVisible(FALSE); } if ((region && region->getAllowDamage()) || (parcel && parcel->getAllowDamage()) ) { // set visibility based on flashing if( mHealthTimer->hasExpired() ) { mBtnHealth->setVisible( TRUE ); } else { BOOL flash = S32(mHealthTimer->getElapsedSeconds() * ICON_FLASH_FREQUENCY) & 1; mBtnHealth->setVisible( flash ); } mTextHealth->setVisible(TRUE); // Health childGetRect( "health", buttonRect ); r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); mBtnHealth->setRect(r); x += buttonRect.getWidth(); const S32 health_width = S32( LLFontGL::sSansSerifSmall->getWidth("100%") ); r.set(x, y+TEXT_HEIGHT - 2, x+health_width, y); mTextHealth->setRect(r); x += health_width; } else { // invisible if region doesn't allow damage mBtnHealth->setVisible(FALSE); mTextHealth->setVisible(FALSE); } if ((region && region->getBlockFly()) || (parcel && !parcel->getAllowFly()) ) { // No Fly Zone childGetRect( "fly", buttonRect ); mBtnFly->setVisible(TRUE); r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); mBtnFly->setRect(r); x += buttonRect.getWidth(); } else { mBtnFly->setVisible(FALSE); } BOOL no_build = parcel && !parcel->getAllowModify(); mBtnBuild->setVisible( no_build ); if (no_build) { childGetRect( "build", buttonRect ); // No Build Zone r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); mBtnBuild->setRect(r); x += buttonRect.getWidth(); } BOOL no_scripts = FALSE; if((region && ((region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) || (region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS))) || (parcel && !parcel->getAllowOtherScripts())) { no_scripts = TRUE; } mBtnScripts->setVisible( no_scripts ); if (no_scripts) { // No scripts childGetRect( "scripts", buttonRect ); r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); mBtnScripts->setRect(r); x += buttonRect.getWidth(); } BOOL no_region_push = (region && region->getRestrictPushObject()); BOOL no_push = no_region_push || (parcel && parcel->getRestrictPushObject()); mBtnPush->setVisible( no_push ); if (no_push) { childGetRect( "restrictpush", buttonRect ); // No Push Zone r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight()); mBtnPush->setRect(r); x += buttonRect.getWidth(); } BOOL canBuyLand = parcel && !parcel->isPublic() && gParcelMgr->canAgentBuyParcel(parcel, false); mBtnBuyLand->setVisible(canBuyLand); if (canBuyLand) { childGetRect( "buyland", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); mBtnBuyLand->setRect(r); x += buttonRect.getWidth(); } LLString location_name; if (region) { const LLVector3& agent_pos_region = gAgent.getPositionAgent(); S32 pos_x = lltrunc( agent_pos_region.mV[VX] ); S32 pos_y = lltrunc( agent_pos_region.mV[VY] ); S32 pos_z = lltrunc( agent_pos_region.mV[VZ] ); // Round the numbers based on the velocity LLVector3 agent_velocity = gAgent.getVelocity(); F32 velocity_mag_sq = agent_velocity.magVecSquared(); const F32 FLY_CUTOFF = 6.f; // meters/sec const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF; const F32 WALK_CUTOFF = 1.5f; // meters/sec const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF; if (velocity_mag_sq > FLY_CUTOFF_SQ) { pos_x -= pos_x % 4; pos_y -= pos_y % 4; } else if (velocity_mag_sq > WALK_CUTOFF_SQ) { pos_x -= pos_x % 2; pos_y -= pos_y % 2; } if (parcel && parcel->getName()) { location_name = region->getName() + llformat(" %d, %d, %d (%s) - %s", pos_x, pos_y, pos_z, region->getSimAccessString(), parcel->getName()); } else { location_name = region->getName() + llformat(" %d, %d, %d (%s)", pos_x, pos_y, pos_z, region->getSimAccessString()); } } else { // no region location_name = "(Unknown)"; } mTextParcelName->setText(location_name); // Adjust region name and parcel name x += 4; const S32 PARCEL_RIGHT = llmin(mTextTime->getRect().mLeft, mTextParcelName->getTextPixelWidth() + x + 5); r.set(x+4, mRect.getHeight() - 2, PARCEL_RIGHT, 0); mTextParcelName->setRect(r); }
void LLSurfacePatch::updateVisibility() { if (mVObjp.isNull()) { return; } const F32 DEFAULT_DELTA_ANGLE = (0.15f); U32 old_render_stride, max_render_stride; U32 new_render_level; F32 stride_per_distance = DEFAULT_DELTA_ANGLE / mSurfacep->getMetersPerGrid(); U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); LLVector4a center; center.load3( (mCenterRegion + mSurfacep->getOriginAgent()).mV); LLVector4a radius; radius.splat(mRadius); // sphere in frustum on global coordinates if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, radius)) { // We now need to calculate the render stride based on patchp's distance // from LLCamera render_stride is governed by a relation something like this... // // delta_angle * patch.distance // render_stride <= ---------------------------------------- // mMetersPerGrid // // where 'delta_angle' is the desired solid angle of the average polgon on a patch. // // Any render_stride smaller than the RHS would be 'satisfactory'. Smaller // strides give more resolution, but efficiency suggests that we use the largest // of the render_strides that obey the relation. Flexibility is achieved by // modulating 'delta_angle' until we have an acceptable number of triangles. old_render_stride = mVisInfo.mRenderStride; // Calculate the render_stride using information in agent max_render_stride = lltrunc(mVisInfo.mDistance * stride_per_distance); max_render_stride = llmin(max_render_stride , 2*grids_per_patch_edge); // We only use render_strides that are powers of two, so we use look-up tables to figure out // the render_level and corresponding render_stride new_render_level = mVisInfo.mRenderLevel = mSurfacep->getRenderLevel(max_render_stride); mVisInfo.mRenderStride = mSurfacep->getRenderStride(new_render_level); if ((mVisInfo.mRenderStride != old_render_stride)) // The reason we check !mbIsVisible is because non-visible patches normals // are not updated when their data is changed. When this changes we can get // rid of mbIsVisible altogether. { if (mVObjp) { mVObjp->dirtyGeom(); if (getNeighborPatch(WEST)) { getNeighborPatch(WEST)->mVObjp->dirtyGeom(); } if (getNeighborPatch(SOUTH)) { getNeighborPatch(SOUTH)->mVObjp->dirtyGeom(); } } } mVisInfo.mbIsVisible = TRUE; } else { mVisInfo.mbIsVisible = FALSE; } }
// Uses the last GL matrices set in set_perspective to project a point from // the agent's region space to screen coordinates. Returns TRUE if point in within // the current window. BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp) const { BOOL in_front = TRUE; GLdouble x, y, z; // object's window coords, GL-style LLVector3 dir_to_point = pos_agent - getOrigin(); dir_to_point /= dir_to_point.magVec(); if (dir_to_point * getAtAxis() < 0.f) { if (clamp) { return FALSE; } else { in_front = FALSE; } } if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ], gGLModelView, gGLProjection, (GLint*)gGLViewport, &x, &y, &z)) { // convert screen coordinates to virtual UI coordinates x /= gViewerWindow->getDisplayScale().mV[VX]; y /= gViewerWindow->getDisplayScale().mV[VY]; // should now have the x,y coords of grab_point in screen space const LLRect& window_rect = gViewerWindow->getWindowRect(); // ...sanity check S32 int_x = lltrunc(x); S32 int_y = lltrunc(y); BOOL valid = TRUE; if (clamp) { if (int_x < window_rect.mLeft) { out_point.mX = window_rect.mLeft; valid = FALSE; } else if (int_x > window_rect.mRight) { out_point.mX = window_rect.mRight; valid = FALSE; } else { out_point.mX = int_x; } if (int_y < window_rect.mBottom) { out_point.mY = window_rect.mBottom; valid = FALSE; } else if (int_y > window_rect.mTop) { out_point.mY = window_rect.mTop; valid = FALSE; } else { out_point.mY = int_y; } return valid; } else { out_point.mX = int_x; out_point.mY = int_y; if (int_x < window_rect.mLeft) { valid = FALSE; } else if (int_x > window_rect.mRight) { valid = FALSE; } if (int_y < window_rect.mBottom) { valid = FALSE; } else if (int_y > window_rect.mTop) { valid = FALSE; } return in_front && valid; } } else { return FALSE; } }
inline long long lltrunc(__gmp_expr<T,U> const& x, const Policy& pol) { return lltrunc(static_cast<mpfr_class>(x), pol); }
void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string& suffix, const LLColor4 &color) { LLLocale locale(LLLocale::USER_LOCALE); const LLFontGL* big_fontp = LLFontGL::getFontSansSerif(); const LLFontGL* small_fontp = LLFontGL::getFontSansSerifSmall(); std::string val_string; std::string fraction_string; F32 val_to_print = ll_round(value, 0.001f); S32 fractional_portion = ll_round(fmodf(llabs(val_to_print), 1.f) * 100.f); if (val_to_print < 0.f) { if (fractional_portion == 0) { val_string = llformat("-%d%s", lltrunc(llabs(val_to_print)), suffix.c_str()); } else { val_string = llformat("-%d", lltrunc(llabs(val_to_print))); } } else { if (fractional_portion == 0) { val_string = llformat("%d%s", lltrunc(llabs(val_to_print)), suffix.c_str()); } else { val_string = llformat("%d", lltrunc(val_to_print)); } } BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD; gGL.matrixMode(LLRender::MM_MODELVIEW); gGL.pushMatrix(); LLVector3 render_pos = pos; if (hud_selection) { F32 zoom_amt = gAgentCamera.mHUDCurZoom; F32 inv_zoom_amt = 1.f / zoom_amt; // scale text back up to counter-act zoom level render_pos = pos * zoom_amt; gGL.scalef(inv_zoom_amt, inv_zoom_amt, inv_zoom_amt); } LLColor4 shadow_color = LLColor4::black; shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f; if (fractional_portion != 0) { fraction_string = llformat("%c%02d%s", LLResMgr::getInstance()->getDecimalPoint(), fractional_portion, suffix.c_str()); gViewerWindow->setup3DViewport(1, -1); hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -1.f * big_fontp->getWidthF32(val_string), 3.f, shadow_color, hud_selection); hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 1.f, 3.f, shadow_color, hud_selection); gViewerWindow->setup3DViewport(); hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -1.f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection); hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, 1.f, 3.f, color, hud_selection); } else { gViewerWindow->setup3DViewport(1, -1); hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(val_string), 3.f, shadow_color, hud_selection); gViewerWindow->setup3DViewport(); hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, -0.5f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection); } gGL.popMatrix(); }
BOOL LLVLComposition::generateTexture(const F32 x, const F32 y, const F32 width, const F32 height) { llassert(mSurfacep); llassert(x >= 0.f); llassert(y >= 0.f); LLTimer gen_timer; /////////////////////////// // // Generate raw data arrays for surface textures // // // These have already been validated by generateComposition. U8* st_data[4]; S32 st_data_size[4]; // for debugging for (S32 i = 0; i < 4; i++) { if (mRawImages[i].isNull()) { // Read back a raw image for this discard level, if it exists S32 min_dim = llmin(mDetailTextures[i]->getFullWidth(), mDetailTextures[i]->getFullHeight()); S32 ddiscard = 0; while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL) { ddiscard++; min_dim /= 2; } BOOL delete_raw = (mDetailTextures[i]->reloadRawImage(ddiscard) != NULL); if (mDetailTextures[i]->getRawImageLevel() != ddiscard) //raw iamge is not ready, will enter here again later. { if(delete_raw) { mDetailTextures[i]->destroyRawImage(); } lldebugs << "cached raw data for terrain detail texture is not ready yet: " << mDetailTextures[i]->getID() << llendl; return FALSE; } mRawImages[i] = mDetailTextures[i]->getCachedRawImage(); if (delete_raw) { mDetailTextures[i]->destroyRawImage(); } if (mDetailTextures[i]->getWidth(ddiscard) != BASE_SIZE || mDetailTextures[i]->getHeight(ddiscard) != BASE_SIZE || mDetailTextures[i]->getComponents() != 3) { LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3); newraw->composite(mRawImages[i]); mRawImages[i] = newraw; // deletes old } } st_data[i] = mRawImages[i]->getData(); st_data_size[i] = mRawImages[i]->getDataSize(); } /////////////////////////////////////// // // Generate and clamp x/y bounding box. // // S32 x_begin, y_begin, x_end, y_end; x_begin = (S32)(x * mScaleInv); y_begin = (S32)(y * mScaleInv); x_end = llround( (x + width) * mScaleInv ); y_end = llround( (y + width) * mScaleInv ); if (x_end > mWidth) { llwarns << "x end > width" << llendl; x_end = mWidth; } if (y_end > mWidth) { llwarns << "y end > width" << llendl; y_end = mWidth; } /////////////////////////////////////////// // // Generate target texture information, stride ratios. // // LLViewerTexture *texturep; U32 tex_width, tex_height, tex_comps; U32 tex_stride; F32 tex_x_scalef, tex_y_scalef; S32 tex_x_begin, tex_y_begin, tex_x_end, tex_y_end; F32 tex_x_ratiof, tex_y_ratiof; texturep = mSurfacep->getSTexture(); tex_width = texturep->getWidth(); tex_height = texturep->getHeight(); tex_comps = texturep->getComponents(); tex_stride = tex_width * tex_comps; U32 st_comps = 3; U32 st_width = BASE_SIZE; U32 st_height = BASE_SIZE; if (tex_comps != st_comps) { llwarns << "Base texture comps != input texture comps" << llendl; return FALSE; } tex_x_scalef = (F32)tex_width / (F32)mWidth; tex_y_scalef = (F32)tex_height / (F32)mWidth; tex_x_begin = (S32)((F32)x_begin * tex_x_scalef); tex_y_begin = (S32)((F32)y_begin * tex_y_scalef); tex_x_end = (S32)((F32)x_end * tex_x_scalef); tex_y_end = (S32)((F32)y_end * tex_y_scalef); tex_x_ratiof = (F32)mWidth*mScale / (F32)tex_width; tex_y_ratiof = (F32)mWidth*mScale / (F32)tex_height; LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps); U8 *rawp = raw->getData(); F32 tex_width_inv = 1.f/tex_width; F32 tex_height_inv = 1.f/tex_height; F32 st_x_stride, st_y_stride; st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width); st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height); llassert(st_x_stride > 0.f); llassert(st_y_stride > 0.f); //////////////////////////////// // // Iterate through the target texture, striding through the // subtextures and interpolating appropriately. // // F32 sti, stj; S32 st_offset; sti = (tex_x_begin * st_x_stride) - st_width*(llfloor((tex_x_begin * st_x_stride)/st_width)); stj = (tex_y_begin * st_y_stride) - st_height*(llfloor((tex_y_begin * st_y_stride)/st_height)); st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps; for (S32 j = tex_y_begin; j < tex_y_end; j++) { U32 offset = j * tex_stride + tex_x_begin * tex_comps; sti = (tex_x_begin * st_x_stride) - st_width*((U32)(tex_x_begin * st_x_stride)/st_width); for (S32 i = tex_x_begin; i < tex_x_end; i++) { S32 tex0, tex1; F32 composition = getValueScaled(i*tex_x_ratiof, j*tex_y_ratiof); tex0 = llfloor( composition ); tex0 = llclamp(tex0, 0, 3); composition -= tex0; tex1 = tex0 + 1; tex1 = llclamp(tex1, 0, 3); F32 xy_int_i, xy_int_j; xy_int_i = i * tex_width_inv; xy_int_j = j * tex_height_inv; st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps; for (U32 k = 0; k < tex_comps; k++) { // Linearly interpolate based on composition. if (st_offset >= st_data_size[tex0] || st_offset >= st_data_size[tex1]) { // SJB: This shouldn't be happening, but does... Rounding error? //llwarns << "offset 0 [" << tex0 << "] =" << st_offset << " >= size=" << st_data_size[tex0] << llendl; //llwarns << "offset 1 [" << tex1 << "] =" << st_offset << " >= size=" << st_data_size[tex1] << llendl; } else { F32 a = *(st_data[tex0] + st_offset); F32 b = *(st_data[tex1] + st_offset); rawp[ offset ] = (U8)lltrunc( a + composition * (b - a) ); } offset++; st_offset++; } sti += st_x_stride; if (sti >= st_width) { sti -= st_width; } } stj += st_y_stride; if (stj >= st_height) { stj -= st_height; } } if (!texturep->hasGLTexture()) { texturep->createGLTexture(0, raw); } texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin); LLSurface::sTextureUpdateTime += gen_timer.getElapsedTimeF32(); LLSurface::sTexelsUpdated += (tex_x_end - tex_x_begin) * (tex_y_end - tex_y_begin); for (S32 i = 0; i < 4; i++) { // Un-boost detatil textures (will get re-boosted if rendering in high detail) mDetailTextures[i]->setBoostLevel(LLViewerTexture::BOOST_NONE); mDetailTextures[i]->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1); } return TRUE; }
inline mpfr_class modf(const mpfr_class& v, long long* ipart, const Policy& pol) { *ipart = lltrunc(v, pol); return v - boost::math::tools::real_cast<mpfr_class>(*ipart); }
inline T modf(const T& v, boost::long_long_type* ipart, const Policy& pol) { *ipart = lltrunc(v, pol); return v - *ipart; }
void LLTracker::drawMarker(const LLVector3d& pos_global, const LLColor4& color) { // get position LLVector3 pos_local = gAgent.getPosAgentFromGlobal(pos_global); // check in frustum LLCoordGL screen; S32 x = 0; S32 y = 0; const BOOL CLAMP = TRUE; if (LLViewerCamera::getInstance()->projectPosAgentToScreen(pos_local, screen, CLAMP) || LLViewerCamera::getInstance()->projectPosAgentToScreenEdge(pos_local, screen) ) { gHUDView->screenPointToLocal(screen.mX, screen.mY, &x, &y); // the center of the rendered position of the arrow obeys // the following rules: // (1) it lies on an ellipse centered on the target position // (2) it lies on the line between the target and the window center // (3) right now the radii of the ellipse are fixed, but eventually // they will be a function of the target text // // from those rules we can compute the position of the // lower left corner of the image LLRect rect = gHUDView->getRect(); S32 x_center = lltrunc(0.5f * (F32)rect.getWidth()); S32 y_center = lltrunc(0.5f * (F32)rect.getHeight()); x = x - x_center; // x and y relative to center y = y - y_center; F32 dist = sqrt((F32)(x*x + y*y)); S32 half_arrow_size = lltrunc(0.5f * HUD_ARROW_SIZE); if (dist > 0.f) { const F32 ARROW_ELLIPSE_RADIUS_X = 2 * HUD_ARROW_SIZE; const F32 ARROW_ELLIPSE_RADIUS_Y = HUD_ARROW_SIZE; // compute where the arrow should be F32 x_target = (F32)(x + x_center) - (ARROW_ELLIPSE_RADIUS_X * ((F32)x / dist) ); F32 y_target = (F32)(y + y_center) - (ARROW_ELLIPSE_RADIUS_Y * ((F32)y / dist) ); // keep the arrow within the window F32 x_clamped = llclamp( x_target, (F32)half_arrow_size, (F32)(rect.getWidth() - half_arrow_size)); F32 y_clamped = llclamp( y_target, (F32)half_arrow_size, (F32)(rect.getHeight() - half_arrow_size)); F32 slope = (F32)(y) / (F32)(x); F32 window_ratio = (F32)(rect.getHeight() - HUD_ARROW_SIZE) / (F32)(rect.getWidth() - HUD_ARROW_SIZE); // if the arrow has been clamped on one axis // then we need to compute the other axis if (llabs(slope) > window_ratio) { if (y_clamped != (F32)y_target) { // clamp by y x_clamped = (y_clamped - (F32)y_center) / slope + (F32)x_center; } } else if (x_clamped != (F32)x_target) { // clamp by x y_clamped = (x_clamped - (F32)x_center) * slope + (F32)y_center; } mHUDArrowCenterX = lltrunc(x_clamped); mHUDArrowCenterY = lltrunc(y_clamped); } else { // recycle the old values x = mHUDArrowCenterX - x_center; y = mHUDArrowCenterY - y_center; } F32 angle = atan2( (F32)y, (F32)x ); gl_draw_scaled_rotated_image(mHUDArrowCenterX - half_arrow_size, mHUDArrowCenterY - half_arrow_size, HUD_ARROW_SIZE, HUD_ARROW_SIZE, RAD_TO_DEG * angle, LLWorldMapView::sTrackArrowImage->getImage(), color); } }
// Per-frame updates of visibility void LLStatusBar::refresh() { if(gDisconnected) return; //or crash if the sim crashes; because: already ~LLMenuBarGL() // Adding Net Stat Meter back in F32 bwtotal = gViewerThrottle.getMaxBandwidth() / 1000.f; mSGBandwidth->setMin(0.f); mSGBandwidth->setMax(bwtotal*1.25f); mSGBandwidth->setThreshold(0, bwtotal*0.75f); mSGBandwidth->setThreshold(1, bwtotal); mSGBandwidth->setThreshold(2, bwtotal); // Let's not have to reformat time everywhere, shall we? -- MC gViewerTime->refresh(); mTextTime->setText(gViewerTime->getCurTimeStr()); mTextTime->setToolTip(gViewerTime->getCurDateStr()); LLRect r; const S32 MENU_RIGHT = gMenuBarView->getRightmostMenuEdge(); S32 x = MENU_RIGHT + MENU_PARCEL_SPACING; S32 y = 0; bool search_visible = gSavedSettings.getBOOL("ShowSearchBar"); // reshape menu bar to its content's width if (MENU_RIGHT != gMenuBarView->getRect().getWidth()) { gMenuBarView->reshape(MENU_RIGHT, gMenuBarView->getRect().getHeight()); } LLViewerRegion *region = gAgent.getRegion(); LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); LLRect buttonRect; if (LLHUDIcon::iconsNearby()) { childGetRect( "scriptout", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect("scriptout",r); childSetVisible("scriptout", true); x += buttonRect.getWidth(); } else { childSetVisible("scriptout", false); } if ((region && region->getAllowDamage()) || (parcel && parcel->getAllowDamage()) ) { // set visibility based on flashing if( mHealthTimer->hasExpired() ) { childSetVisible("health", true); } else { BOOL flash = S32(mHealthTimer->getElapsedSeconds() * ICON_FLASH_FREQUENCY) & 1; childSetVisible("health", flash); } mTextHealth->setVisible(TRUE); // Health childGetRect( "health", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect("health", r); x += buttonRect.getWidth(); const S32 health_width = S32( LLFontGL::getFontSansSerifSmall()->getWidth(std::string("100%")) ); r.set(x, y+TEXT_HEIGHT - 2, x+health_width, y); mTextHealth->setRect(r); x += health_width; } else { // invisible if region doesn't allow damage childSetVisible("health", false); mTextHealth->setVisible(FALSE); } if ((region && region->getBlockFly()) || (parcel && !parcel->getAllowFly()) ) { // No Fly Zone childGetRect( "no_fly", buttonRect ); childSetVisible( "no_fly", true ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_fly", r ); x += buttonRect.getWidth(); } else { // Fly Zone childSetVisible("no_fly", false); } BOOL no_build = parcel && !parcel->getAllowModify(); if (no_build) { childSetVisible("no_build", TRUE); childGetRect( "no_build", buttonRect ); // No Build Zone r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_build", r ); x += buttonRect.getWidth(); } else { childSetVisible("no_build", FALSE); } BOOL no_scripts = FALSE; if((region && ((region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) || (region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS))) || (parcel && !parcel->getAllowOtherScripts())) { no_scripts = TRUE; } if (no_scripts) { // No scripts childSetVisible("no_scripts", TRUE); childGetRect( "no_scripts", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_scripts", r ); x += buttonRect.getWidth(); } else { // Yes scripts childSetVisible("no_scripts", FALSE); } BOOL no_region_push = (region && region->getRestrictPushObject()); BOOL no_push = no_region_push || (parcel && parcel->getRestrictPushObject()); if (no_push) { childSetVisible("restrictpush", TRUE); childGetRect( "restrictpush", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "restrictpush", r ); x += buttonRect.getWidth(); } else { childSetVisible("restrictpush", FALSE); } BOOL have_voice = parcel && parcel->getParcelFlagAllowVoice(); if (have_voice) { childSetVisible("status_no_voice", FALSE); } else { childSetVisible("status_no_voice", TRUE); childGetRect( "status_no_voice", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "status_no_voice", r ); x += buttonRect.getWidth(); } // TODO: disable buy land button when connected to non-SL grids // that don't support currency. // TODO: make this brandable -- MC BOOL canBuyLand = parcel && !parcel->isPublic() && LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false); childSetVisible("buyland", canBuyLand); if (canBuyLand) { //HACK: layout tweak until this is all xml x += 9; childGetRect( "buyland", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "buyland", r ); x += buttonRect.getWidth(); } std::string location_name; if (region) { const LLVector3& agent_pos_region = gAgent.getPositionAgent(); S32 pos_x = lltrunc( agent_pos_region.mV[VX] ); S32 pos_y = lltrunc( agent_pos_region.mV[VY] ); S32 pos_z = lltrunc( agent_pos_region.mV[VZ] ); // Round the numbers based on the velocity LLVector3 agent_velocity = gAgent.getVelocity(); F32 velocity_mag_sq = agent_velocity.magVecSquared(); const F32 FLY_CUTOFF = 6.f; // meters/sec const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF; const F32 WALK_CUTOFF = 1.5f; // meters/sec const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF; if (velocity_mag_sq > FLY_CUTOFF_SQ) { pos_x -= pos_x % 4; pos_y -= pos_y % 4; } else if (velocity_mag_sq > WALK_CUTOFF_SQ) { pos_x -= pos_x % 2; pos_y -= pos_y % 2; } mRegionDetails.mTime = mTextTime->getText(); mRegionDetails.mBalance = mBalance; mRegionDetails.mAccessString = region->getSimAccessString(); mRegionDetails.mPing = region->getNetDetailsForLCD(); if (parcel) { location_name = region->getName() + llformat(" %d, %d, %d (%s) - %s", pos_x, pos_y, pos_z, region->getSimAccessString().c_str(), parcel->getName().c_str()); // keep these around for the LCD to use mRegionDetails.mRegionName = region->getName(); mRegionDetails.mParcelName = parcel->getName(); mRegionDetails.mX = pos_x; mRegionDetails.mY = pos_y; mRegionDetails.mZ = pos_z; mRegionDetails.mArea = parcel->getArea(); mRegionDetails.mForSale = parcel->getForSale(); mRegionDetails.mTraffic = LLViewerParcelMgr::getInstance()->getDwelling(); if (parcel->isPublic()) { mRegionDetails.mOwner = "Public"; } else { if (parcel->getIsGroupOwned()) { if(!parcel->getGroupID().isNull()) { gCacheName->getGroupName(parcel->getGroupID(), mRegionDetails.mOwner); } else { mRegionDetails.mOwner = "Group Owned"; } } else { // Figure out the owner's name gCacheName->getFullName(parcel->getOwnerID(), mRegionDetails.mOwner); } } } else { location_name = region->getName() + llformat(" %d, %d, %d (%s)", pos_x, pos_y, pos_z, region->getSimAccessString().c_str()); // keep these around for the LCD to use mRegionDetails.mRegionName = region->getName(); mRegionDetails.mParcelName = "Unknown"; mRegionDetails.mX = pos_x; mRegionDetails.mY = pos_y; mRegionDetails.mZ = pos_z; mRegionDetails.mArea = 0; mRegionDetails.mForSale = FALSE; mRegionDetails.mOwner = "Unknown"; mRegionDetails.mTraffic = 0.0f; } } else { // no region location_name = "(Unknown)"; // keep these around for the LCD to use mRegionDetails.mRegionName = "Unknown"; mRegionDetails.mParcelName = "Unknown"; mRegionDetails.mAccessString = "Unknown"; mRegionDetails.mX = 0; mRegionDetails.mY = 0; mRegionDetails.mZ = 0; mRegionDetails.mArea = 0; mRegionDetails.mForSale = FALSE; mRegionDetails.mOwner = "Unknown"; mRegionDetails.mTraffic = 0.0f; } // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Modified: RLVa-1.0.0a if ( (region) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) // region == NULL if we loose our connection to the grid { // TODO-RLVa: find out whether the LCD code is still used because if so then we need to filter that as well location_name = llformat("%s (%s) - %s", RlvStrings::getString(RLV_STRING_HIDDEN_REGION).c_str(), region->getSimAccessString().c_str(), RlvStrings::getString(RLV_STRING_HIDDEN).c_str()); } // [/RLVa:KB] mTextParcelName->setText(location_name); // x = right edge // loop through: stat graphs, search btn, search text editor, money, buy money, clock // adjust rect // finally adjust parcel name rect S32 new_right = getRect().getWidth(); if (search_visible) { childGetRect("search_btn", r); //r.translate( new_right - r.mRight, 0); //childSetRect("search_btn", r); new_right -= r.getWidth(); childGetRect("search_editor", r); //r.translate( new_right - r.mRight, 0); //childSetRect("search_editor", r); new_right -= r.getWidth() + 6; } else { childGetRect("stat_btn", r); r.translate( new_right - r.mRight, 0); childSetRect("stat_btn", r); new_right -= r.getWidth() + 6; } // Set rects of money, buy money, time childGetRect("BalanceText", r); r.translate( new_right - r.mRight, 0); childSetRect("BalanceText", r); new_right -= r.getWidth() - 2; childGetRect("buycurrency", r); r.translate( new_right - r.mRight, 0); childSetRect("buycurrency", r); new_right -= r.getWidth() + 6; // Don't toggle this visibility while in mouselook -- MC if (!gAgent.cameraMouselook()) { // Set search bar visibility childSetVisible("search_editor", search_visible); childSetVisible("search_btn", search_visible); childSetVisible("menubar_search_bevel_bg", search_visible); mSGBandwidth->setVisible(! search_visible); mSGPacketLoss->setVisible(! search_visible); childSetEnabled("stat_btn", ! search_visible); } childGetRect("TimeText", r); // mTextTime->getTextPixelWidth(); r.translate( new_right - r.mRight, 0); childSetRect("TimeText", r); // new_right -= r.getWidth() + MENU_PARCEL_SPACING; // Adjust region name and parcel name x += 8; const S32 PARCEL_RIGHT = llmin(mTextTime->getRect().mLeft, mTextParcelName->getTextPixelWidth() + x + 5); r.set(x+4, getRect().getHeight() - 2, PARCEL_RIGHT, 0); mTextParcelName->setRect(r); }
inline mpfr::mpreal modf(const mpfr::mpreal& v, long long* ipart, const Policy& pol) { *ipart = lltrunc(v, pol); return v - lslboost::math::tools::real_cast<mpfr::mpreal>(*ipart); }
// Per-frame updates of visibility void LLStatusBar::refresh() { if(gDisconnected) return; //or crash if the sim crashes; because: already ~LLMenuBarGL() // Adding Net Stat Meter back in F32 bwtotal = gViewerThrottle.getMaxBandwidth() / 1000.f; mSGBandwidth->setMin(0.f); mSGBandwidth->setMax(bwtotal*1.25f); mSGBandwidth->setThreshold(0, bwtotal*0.75f); mSGBandwidth->setThreshold(1, bwtotal); mSGBandwidth->setThreshold(2, bwtotal); // *TODO: Localize / translate time // Get current UTC time, adjusted for the user's clock // being off. time_t utc_time; utc_time = time_corrected(); // There's only one internal tm buffer. struct tm* internal_time; // Convert to Pacific, based on server's opinion of whether // it's daylight savings time there. internal_time = utc_to_pacific_time(utc_time, gPacificDaylightTime); std::string t; timeStructToFormattedString(internal_time, gSavedSettings.getString("ShortTimeFormat"), t); if (gPacificDaylightTime) { t += " PDT"; } else { t += " PST"; } mTextTime->setText(t); std::string date; timeStructToFormattedString(internal_time, gSavedSettings.getString("LongDateFormat"), date); mTextTime->setToolTip(date); LLRect r; const S32 MENU_RIGHT = gMenuBarView->getRightmostMenuEdge(); S32 x = MENU_RIGHT + MENU_PARCEL_SPACING; S32 y = 0; bool search_visible = gSavedSettings.getBOOL("ShowSearchBar"); // reshape menu bar to its content's width if (MENU_RIGHT != gMenuBarView->getRect().getWidth()) { gMenuBarView->reshape(MENU_RIGHT, gMenuBarView->getRect().getHeight()); } LLViewerRegion *region = gAgent.getRegion(); LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); LLRect buttonRect; if (LLHUDIcon::iconsNearby()) { childGetRect( "scriptout", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect("scriptout",r); childSetVisible("scriptout", true); x += buttonRect.getWidth(); } else { childSetVisible("scriptout", false); } if ((region && region->getAllowDamage()) || (parcel && parcel->getAllowDamage()) ) { // set visibility based on flashing if( mHealthTimer->hasExpired() ) { childSetVisible("health", true); } else { BOOL flash = S32(mHealthTimer->getElapsedSeconds() * ICON_FLASH_FREQUENCY) & 1; childSetVisible("health", flash); } mTextHealth->setVisible(TRUE); // Health childGetRect( "health", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect("health", r); x += buttonRect.getWidth(); const S32 health_width = S32( LLFontGL::getFontSansSerifSmall()->getWidth(std::string("100%")) ); r.set(x, y+TEXT_HEIGHT - 2, x+health_width, y); mTextHealth->setRect(r); x += health_width; } else { // invisible if region doesn't allow damage childSetVisible("health", false); mTextHealth->setVisible(FALSE); } if ((region && region->getBlockFly()) || (parcel && !parcel->getAllowFly()) ) { // No Fly Zone childGetRect( "no_fly", buttonRect ); childSetVisible( "no_fly", true ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_fly", r ); x += buttonRect.getWidth(); } else { // Fly Zone childSetVisible("no_fly", false); } BOOL no_build = parcel && !parcel->getAllowModify(); if (no_build) { childSetVisible("no_build", TRUE); childGetRect( "no_build", buttonRect ); // No Build Zone r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_build", r ); x += buttonRect.getWidth(); } else { childSetVisible("no_build", FALSE); } BOOL no_scripts = FALSE; if((region && (region->getRegionFlag(REGION_FLAGS_SKIP_SCRIPTS) || region->getRegionFlag(REGION_FLAGS_ESTATE_SKIP_SCRIPTS))) || (parcel && !parcel->getAllowOtherScripts())) { no_scripts = TRUE; } if (no_scripts) { // No scripts childSetVisible("no_scripts", TRUE); childGetRect( "no_scripts", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "no_scripts", r ); x += buttonRect.getWidth(); } else { // Yes scripts childSetVisible("no_scripts", FALSE); } BOOL no_region_push = (region && region->getRestrictPushObject()); BOOL no_push = no_region_push || (parcel && parcel->getRestrictPushObject()); if (no_push) { childSetVisible("restrictpush", TRUE); childGetRect( "restrictpush", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "restrictpush", r ); x += buttonRect.getWidth(); } else { childSetVisible("restrictpush", FALSE); } BOOL have_voice = parcel && parcel->getParcelFlagAllowVoice(); if (have_voice) { childSetVisible("status_no_voice", FALSE); } else { childSetVisible("status_no_voice", TRUE); childGetRect( "status_no_voice", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "status_no_voice", r ); x += buttonRect.getWidth(); } bool no_see_avs = parcel && !parcel->getSeeAVs(); childSetVisible("status_SeeAV", no_see_avs); if (no_see_avs) { childGetRect( "status_SeeAV", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "status_SeeAV", r ); x += buttonRect.getWidth(); } BOOL canBuyLand = parcel && !parcel->isPublic() && LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false); childSetVisible("buyland", canBuyLand); if (canBuyLand) { //HACK: layout tweak until this is all xml x += 9; childGetRect( "buyland", buttonRect ); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); childSetRect( "buyland", r ); x += buttonRect.getWidth(); } std::string location_name; if (region) { const LLVector3& agent_pos_region = gAgent.getPositionAgent(); S32 pos_x = lltrunc( agent_pos_region.mV[VX] ); S32 pos_y = lltrunc( agent_pos_region.mV[VY] ); S32 pos_z = lltrunc( agent_pos_region.mV[VZ] ); // Round the numbers based on the velocity LLVector3 agent_velocity = gAgent.getVelocity(); F32 velocity_mag_sq = agent_velocity.magVecSquared(); const F32 FLY_CUTOFF = 6.f; // meters/sec const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF; const F32 WALK_CUTOFF = 1.5f; // meters/sec const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF; if (velocity_mag_sq > FLY_CUTOFF_SQ) { pos_x -= pos_x % 4; pos_y -= pos_y % 4; } else if (velocity_mag_sq > WALK_CUTOFF_SQ) { pos_x -= pos_x % 2; pos_y -= pos_y % 2; } if (parcel) { if (!LLAgentUI::buildLocationString(location_name, LLAgentUI::LOCATION_FORMAT_FULL)) { location_name = "???"; } } else { location_name = region->getName() + llformat(" %d, %d, %d (%s)", pos_x, pos_y, pos_z, region->getSimAccessString().c_str()); } static LLCachedControl<bool> show_channel("ShowSimChannel"); if (show_channel && !gLastVersionChannel.empty()) location_name += " - " + gLastVersionChannel; } else { // no region location_name = "(Unknown)"; } // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Modified: RLVa-1.0.0a if ( (region) && (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) ) // region == NULL if we lose our connection to the grid { location_name = llformat("%s (%s) - %s", RlvStrings::getString(RLV_STRING_HIDDEN_REGION).c_str(), region->getSimAccessString().c_str(), RlvStrings::getString(RLV_STRING_HIDDEN).c_str()); } // [/RLVa:KB] mTextParcelName->setText(location_name); // x = right edge // loop through: stat graphs, search btn, search text editor, money, buy money, clock // adjust rect // finally adjust parcel name rect S32 new_right = getRect().getWidth(); if (search_visible) { childGetRect("search_btn", r); //r.translate( new_right - r.mRight, 0); //childSetRect("search_btn", r); new_right -= r.getWidth(); childGetRect("search_editor", r); //r.translate( new_right - r.mRight, 0); //childSetRect("search_editor", r); new_right -= r.getWidth() + 6; } else { childGetRect("stat_btn", r); r.translate( new_right - r.mRight, 0); childSetRect("stat_btn", r); new_right -= r.getWidth() + 6; } // Set rects of money, buy money, time childGetRect("BalanceText", r); r.translate( new_right - r.mRight, 0); childSetRect("BalanceText", r); new_right -= r.getWidth() - 18; childGetRect("buycurrency", r); r.translate( new_right - r.mRight, 0); childSetRect("buycurrency", r); new_right -= r.getWidth() + 6; childGetRect("TimeText", r); // mTextTime->getTextPixelWidth(); r.translate( new_right - r.mRight, 0); childSetRect("TimeText", r); // new_right -= r.getWidth() + MENU_PARCEL_SPACING; // Adjust region name and parcel name x += 8; const S32 PARCEL_RIGHT = llmin(mTextTime->getRect().mLeft, mTextParcelName->getTextPixelWidth() + x + 5); r.set(x+4, getRect().getHeight() - 2, PARCEL_RIGHT, 0); mTextParcelName->setRect(r); // Set search bar visibility childSetVisible("search_editor", search_visible); childSetVisible("search_btn", search_visible); childSetVisible("menubar_search_bevel_bg", search_visible); mSGBandwidth->setVisible(! search_visible); mSGPacketLoss->setVisible(! search_visible); childSetEnabled("stat_btn", ! search_visible); }