/** * @file llstatusbar.cpp * @brief LLStatusBar class implementation * * $LicenseInfo:firstyear=2002&license=viewergpl$ * * Copyright (c) 2002-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include "llstatusbar.h" // viewer includes #include "llagent.h" #include "llbutton.h" #include "llcommandhandler.h" #include "llfloaterbuycurrency.h" #include "llfloaterchat.h" #include "llfloaterinventory.h" #include "llfloaterland.h" #include "llfloaterregioninfo.h" #include "llfloaterscriptdebug.h" #include "llfloatersearch.h" #include "llhudicon.h" #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" #include "llmenuoptionpathfindingrebakenavmesh.h" #include "llnotify.h" #include "llpathfindingmanager.h" #include "llpathfindingnavmeshstatus.h" #include "llimview.h" #include "lltextbox.h" #include "llui.h" #include "llviewerparceloverlay.h" #include "llviewerregion.h" #include "llviewerstats.h" #include "llviewerwindow.h" #include "llframetimer.h" #include "llvoavatarself.h" #include "llresmgr.h" #include "llworld.h" #include "llstatgraph.h" #include "llviewercontrol.h" #include "llviewergenericmessage.h" #include "llviewermenu.h" // for gMenuBarView #include "llviewerparcelmgr.h" #include "llviewerthrottle.h" #include "lluictrlfactory.h" #include "llagentui.h" #include "lltoolmgr.h" #include "llfocusmgr.h" #include "llappviewer.h" // library includes #include "imageids.h" #include "llfontgl.h" #include "llrect.h" #include "llerror.h" #include "llnotificationsutil.h" #include "llparcel.h" #include "llstring.h" #include "message.h" // system includes #include #include "hippogridmanager.h" #include "lfsimfeaturehandler.h" // [RLVa:KB] #include "rlvactions.h" #include "rlvcommon.h" // [/RLVa:KB] // // Globals // LLStatusBar *gStatusBar = NULL; S32 STATUS_BAR_HEIGHT = 0; extern S32 MENU_BAR_HEIGHT; // TODO: these values ought to be in the XML too const S32 MENU_PARCEL_SPACING = 1; // Distance from right of menu item to parcel information const S32 SIM_STAT_WIDTH = 8; const F32 SIM_WARN_FRACTION = 0.75f; const F32 SIM_FULL_FRACTION = 0.98f; const LLColor4 SIM_OK_COLOR(0.f, 1.f, 0.f, 1.f); const LLColor4 SIM_WARN_COLOR(1.f, 1.f, 0.f, 1.f); const LLColor4 SIM_FULL_COLOR(1.f, 0.f, 0.f, 1.f); const F32 ICON_TIMER_EXPIRY = 3.f; // How long the balance and health icons should flash after a change. const F32 ICON_FLASH_FREQUENCY = 2.f; const S32 TEXT_HEIGHT = 18; static void onClickParcelInfo(); static bool rebakeRegionCallback(const LLSD& n, const LLSD& r); static void pf_dirty_click() { LLNotificationsUtil::add("PathfindingDirty", LLSD(), LLSD(), rebakeRegionCallback); } static void onClickScripts(); static void onClickSearch(const std::string& query); std::vector LLStatusBar::sDays; std::vector LLStatusBar::sMonths; const U32 LLStatusBar::MAX_DATE_STRING_LENGTH = 2000; class LLDispatchUPCBalance : public LLDispatchHandler { public: virtual bool operator()( const LLDispatcher* dispatcher, const std::string& key, const LLUUID& invoice, const sparam_t& strings) { S32 upc = atoi(strings[0].c_str()); gStatusBar->setUPC(upc); return true; } }; static LLDispatchUPCBalance sDispatchUPCBalance; static void toggle_time_value() { LLControlVariable* control = gSavedSettings.getControl("LiruLocalTime"); control->set(!control->get()); } LLStatusBar::LLStatusBar(const std::string& name, const LLRect& rect) : LLPanel(name, LLRect(), FALSE), // not mouse opaque mBalance(0), mUPC(0), mHealth(100), mSquareMetersCredit(0), mSquareMetersCommitted(0), mRegionCrossingSlot(), mNavMeshSlot(), mIsNavMeshDirty(false) { mUPCSupported = gHippoGridManager->getConnectedGrid()->getUPCSupported(); if (mUPCSupported) gGenericDispatcher.addHandler("upcbalance", &sDispatchUPCBalance); // status bar can possible overlay menus? setMouseOpaque(FALSE); setIsChrome(TRUE); // size of day of the weeks and year sDays.reserve(7); sMonths.reserve(12); mBalanceTimer = new LLFrameTimer(); mHealthTimer = new LLFrameTimer(); LLUICtrlFactory::getInstance()->buildPanel(this,"panel_status_bar.xml"); // status bar can never get a tab setFocusRoot(FALSE); // build date necessary data (must do after panel built) setupDate(); mTextParcelName = getChild("ParcelNameText" ); mTextBalance = getChild("BalanceText" ); mTextUPC = getChild("UPCText" ); mTextHealth = getChild("HealthText" ); mTextTime = getChild("TimeText" ); mTextTime->setClickedCallback(boost::bind(toggle_time_value)); if (!mUPCSupported) mTextUPC->setVisible(false); mScriptOut = getChild("scriptout"); mScriptOut->setCommitCallback(boost::bind(LLFloaterScriptDebug::show, LLUUID::null)); mHealthV = getChild("health"); mHealthV->setCommitCallback(boost::bind(LLNotificationsUtil::add, "NotSafe")); mNoFly = getChild("no_fly"); mNoFly->setCommitCallback(boost::bind(LLNotificationsUtil::add, "NoFly")); mBuyLand = getChild("buyland"); mBuyLand->setCommitCallback(boost::bind(&LLViewerParcelMgr::startBuyLand, boost::bind(LLViewerParcelMgr::getInstance), 0)); mBuyCurrency = getChild("buycurrency"); mBuyCurrency->setCommitCallback(boost::bind(LLFloaterBuyCurrency::buyCurrency)); mNoBuild = getChild("no_build"); mNoBuild->setCommitCallback(boost::bind(LLNotificationsUtil::add, "NoBuild")); mPFDirty = getChild("pf_dirty"); mPFDirty->setCommitCallback(boost::bind(pf_dirty_click)); mPFDisabled = getChild("pf_disabled"); mPFDisabled->setCommitCallback(boost::bind(LLNotificationsUtil::add, "DynamicPathfindingDisabled")); mStatusSeeAV = getChild("status_SeeAV"); mStatusSeeAV->setCommitCallback(boost::bind(LLNotificationsUtil::add, "SeeAvatars")); mNoScripts = getChild("no_scripts"); mNoScripts->setCommitCallback(boost::bind(onClickScripts)); mRestrictPush = getChild("restrictpush"); mRestrictPush->setCommitCallback(boost::bind(LLNotificationsUtil::add, "PushRestricted")); mStatusNoVoice = getChild("status_no_voice"); mStatusNoVoice->setCommitCallback(boost::bind(LLNotificationsUtil::add, "NoVoice")); mSearchEditor = getChild("search_editor"); mSearchEditor->setCommitCallback(boost::bind(onClickSearch, _2)); mSearchBtn = getChild("search_btn"); mSearchBtn->setCommitCallback(boost::bind(onClickSearch, boost::bind(&LLView::getValue, mSearchEditor))); bool show_search(gSavedSettings.getBOOL("ShowSearchBar")); mSearchEditor->setVisible(show_search); mSearchBtn->setVisible(show_search); mSearchBevel = getChildView("menubar_search_bevel_bg"); mSearchBevel->setVisible(show_search); mTextParcelName->setClickedCallback(boost::bind(onClickParcelInfo)); mTextBalance->setClickedCallback(boost::bind(LLFloaterBuyCurrency::buyCurrency)); // TODO: Disable buying currency when connected to non-SL grids // that don't support currency yet -- MC mBuyCurrency->setLabelArg("[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); mRegionCrossingSlot = gAgent.addRegionChangedCallback(boost::bind(&LLStatusBar::createNavMeshStatusListenerForCurrentRegion, this)); createNavMeshStatusListenerForCurrentRegion(); // Adding Net Stat Graph S32 x = getRect().getWidth() - 2; S32 y = 0; LLRect r; r.set( x-SIM_STAT_WIDTH, y+MENU_BAR_HEIGHT-1, x, y+1); mSGBandwidth = new LLStatGraph("BandwidthGraph", r); mSGBandwidth->setFollows(FOLLOWS_BOTTOM | FOLLOWS_RIGHT); mSGBandwidth->setStat(&LLViewerStats::getInstance()->mKBitStat); mSGBandwidth->setLabel(getString("bandwidth_tooltip") + " "); mSGBandwidth->setUnits("Kbps"); mSGBandwidth->setPrecision(0); mSGBandwidth->setMouseOpaque(FALSE); addChild(mSGBandwidth); x -= SIM_STAT_WIDTH + 2; r.set( x-SIM_STAT_WIDTH, y+MENU_BAR_HEIGHT-1, x, y+1); mSGPacketLoss = new LLStatGraph("PacketLossPercent", r); mSGPacketLoss->setFollows(FOLLOWS_BOTTOM | FOLLOWS_RIGHT); mSGPacketLoss->setStat(&LLViewerStats::getInstance()->mPacketsLostPercentStat); mSGPacketLoss->setLabel(getString("packet_loss_tooltip") + " "); mSGPacketLoss->setUnits("%"); mSGPacketLoss->setMin(0.f); mSGPacketLoss->setMax(5.f); mSGPacketLoss->setThreshold(0, 0.5f); mSGPacketLoss->setThreshold(1, 1.f); mSGPacketLoss->setThreshold(2, 3.f); mSGPacketLoss->setPrecision(1); mSGPacketLoss->setMouseOpaque(FALSE); mSGPacketLoss->mPerSec = FALSE; addChild(mSGPacketLoss); mStatBtn = getChild("stat_btn"); } LLStatusBar::~LLStatusBar() { delete mBalanceTimer; mBalanceTimer = NULL; delete mHealthTimer; mHealthTimer = NULL; mRegionCrossingSlot.disconnect(); mNavMeshSlot.disconnect(); // LLView destructor cleans up children } //----------------------------------------------------------------------- // Overrides //----------------------------------------------------------------------- // virtual void LLStatusBar::draw() { refresh(); if (isBackgroundVisible()) { static const LLCachedControl color_drop_shadow(*LLUI::sColorsGroup,"ColorDropShadow",LLColor4(LLColor4U(0,0,0,200))); static const LLCachedControl drop_shadow_floater(*LLUI::sConfigGroup,"DropShadowFloater"); gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0, color_drop_shadow, drop_shadow_floater ); } LLPanel::draw(); } // 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); // Singu Note: Use system's time if the user desires, otherwise use server time static const LLCachedControl show_local_time("LiruLocalTime"); // Get current UTC time, adjusted for the user's clock // being off. time_t utc_time = show_local_time ? time(NULL) : 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 = show_local_time ? std::localtime(&utc_time) : utc_to_pacific_time(utc_time, gPacificDaylightTime); static const LLCachedControl short_time_fmt(gSavedSettings, "ShortTimeFormat"); std::string t; timeStructToFormattedString(internal_time, short_time_fmt, t); if (show_local_time) { static const std::string local(" " + getString("Local")); t += local; } else if (gPacificDaylightTime) { t += " PDT"; } else { t += " PST"; } mTextTime->setText(t); static const LLCachedControl long_date_fmt(gSavedSettings, "LongDateFormat"); std::string date; timeStructToFormattedString(internal_time, long_date_fmt, date); mTextTime->setToolTip(date); 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 = LLViewerParcelMgr::getInstance()->getAgentParcel(); if (LLHUDIcon::iconsNearby()) { const LLRect& buttonRect = mScriptOut->getRect(); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); mScriptOut->setRect(r); mScriptOut->setVisible(true); x += buttonRect.getWidth(); } else { mScriptOut->setVisible(false); } if ((region && region->getAllowDamage()) || (parcel && parcel->getAllowDamage()) ) { // set visibility based on flashing mHealthV->setVisible(mHealthTimer->hasExpired() || S32(mHealthTimer->getElapsedSeconds() * ICON_FLASH_FREQUENCY) & 1); mTextHealth->setVisible(TRUE); // Health const LLRect& buttonRect = mHealthV->getRect(); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); mHealthV->setRect(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 mHealthV->setVisible(false); mTextHealth->setVisible(FALSE); } if ((region && region->getBlockFly()) || (parcel && !parcel->getAllowFly()) ) { // No Fly Zone mNoFly->setVisible(true); const LLRect& buttonRect(mNoFly->getRect()); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); mNoFly->setRect(r); x += buttonRect.getWidth(); } else { // Fly Zone mNoFly->setVisible(false); } if (parcel && !parcel->getAllowModify()) { // No Build Zone mNoBuild->setVisible(true); const LLRect& buttonRect(mNoBuild->getRect()); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); mNoBuild->setRect(r); x += buttonRect.getWidth(); } else { mNoBuild->setVisible(false); } if ((region && (region->getRegionFlag(REGION_FLAGS_SKIP_SCRIPTS) || region->getRegionFlag(REGION_FLAGS_ESTATE_SKIP_SCRIPTS))) || (parcel && !parcel->getAllowOtherScripts())) { // No scripts mNoScripts->setVisible(true); const LLRect& buttonRect(mNoScripts->getRect()); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); mNoScripts->setRect(r); x += buttonRect.getWidth(); } else { // Yes scripts mNoScripts->setVisible(false); } if ((region && region->getRestrictPushObject()) || (parcel && parcel->getRestrictPushObject())) { mRestrictPush->setVisible(true); const LLRect& buttonRect(mRestrictPush->getRect()); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); mRestrictPush->setRect(r); x += buttonRect.getWidth(); } else { mRestrictPush->setVisible(false); } if (parcel && parcel->getParcelFlagAllowVoice()) { mStatusNoVoice->setVisible(false); } else { mStatusNoVoice->setVisible(true); const LLRect& buttonRect(mStatusNoVoice->getRect()); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); mStatusNoVoice->setRect(r); x += buttonRect.getWidth(); } if (parcel && !parcel->getSeeAVs()) { mStatusSeeAV->setVisible(true); const LLRect& buttonRect(mStatusSeeAV->getRect()); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); mStatusSeeAV->setRect(r); x += buttonRect.getWidth(); } else mStatusSeeAV->setVisible(false); if (region) { bool pf_disabled = !region->dynamicPathfindingEnabled(); mPFDirty->setVisible(!pf_disabled && mIsNavMeshDirty); mPFDisabled->setVisible(pf_disabled); if (LLView* pf_icon = pf_disabled ? mPFDisabled : mIsNavMeshDirty ? mPFDirty : NULL) { x += 6; const LLRect& buttonRect(pf_icon->getRect()); r.setOriginAndSize(x, y, buttonRect.getWidth(), buttonRect.getHeight()); pf_icon->setRect(r); x += buttonRect.getWidth(); } } if (parcel && !parcel->isPublic() && LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false)) { mBuyLand->setVisible(true); //HACK: layout tweak until this is all xml x += 9; const LLRect& buttonRect(mBuyLand->getRect()); r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight()); mBuyLand->setRect(r); x += buttonRect.getWidth(); } else mBuyLand->setVisible(false); std::string location_name; if (region && parcel) { // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) | Modified: RLVa-1.0.0a if (RlvActions::hasBehaviour(RLV_BHVR_SHOWLOC)) { 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()); } else // [/RLVa:KB] if (!LLAgentUI::buildLocationString(location_name, LLAgentUI::LOCATION_FORMAT_FULL)) location_name = "???"; else { const std::string& grid(LFSimFeatureHandler::instance().gridName()); if (!grid.empty()) location_name += ", " + grid; } static const LLCachedControl show_channel("ShowSimChannel"); if (show_channel && !gLastVersionChannel.empty()) location_name += " - " + gLastVersionChannel; } else { // no region location_name = "(Unknown)"; } 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(); static const LLCachedControl search_visible(gSavedSettings, "ShowSearchBar"); if (search_visible) { new_right -= mSearchBtn->getRect().getWidth(); new_right -= mSearchEditor->getRect().getWidth() + 6; } else { r = mStatBtn->getRect(); r.translate( new_right - r.mRight, 0); mStatBtn->setRect(r); new_right -= r.getWidth() + 6; } // Set search bar visibility mSearchEditor->setVisible(search_visible); mSearchBtn->setVisible(search_visible); mSearchBevel->setVisible(search_visible); mSGBandwidth->setVisible(! search_visible); mSGPacketLoss->setVisible(! search_visible); mStatBtn->setEnabled(!search_visible); // Set rects of money, buy money, time if (mUPCSupported) { r = mTextUPC->getRect(); r.translate( new_right - r.mRight, 0); mTextUPC->setRect(r); new_right -= r.getWidth() - 18; } r = mTextBalance->getRect(); r.translate( new_right - r.mRight, 0); mTextBalance->setRect(r); new_right -= r.getWidth() - 18; r = mBuyCurrency->getRect(); r.translate( new_right - r.mRight, 0); mBuyCurrency->setRect(r); new_right -= r.getWidth() + 6; r = mTextTime->getRect(); r.translate( new_right - r.mRight, 0); mTextTime->setRect(r); // 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); } void LLStatusBar::setVisibleForMouselook(bool visible) { mTextBalance->setVisible(visible); if (mUPCSupported) mTextUPC->setVisible(visible); mTextTime->setVisible(visible); mBuyCurrency->setVisible(visible); mSearchEditor->setVisible(visible); mSearchBtn->setVisible(visible); mSGBandwidth->setVisible(visible); mSGPacketLoss->setVisible(visible); setBackgroundVisible(visible); } void LLStatusBar::debitBalance(S32 debit) { setBalance(getBalance() - debit); } void LLStatusBar::creditBalance(S32 credit) { setBalance(getBalance() + credit); } void LLStatusBar::setBalance(S32 balance) { mTextBalance->setText(gHippoGridManager->getConnectedGrid()->getCurrencySymbol().c_str() + LLResMgr::getInstance()->getMonetaryString(balance - mUPC)); if (mBalance && (fabs((F32)(mBalance - balance)) > gSavedSettings.getF32("UISndMoneyChangeThreshold"))) { if (mBalance > balance) make_ui_sound("UISndMoneyChangeDown"); else make_ui_sound("UISndMoneyChangeUp"); } if( balance != mBalance ) { mBalanceTimer->reset(ICON_TIMER_EXPIRY); mBalance = balance; } } void LLStatusBar::setUPC(S32 upc) { mTextUPC->setText("UPC " + LLResMgr::getInstance()->getMonetaryString(upc)); mUPC = upc; setBalance(mBalance); } // static void LLStatusBar::sendMoneyBalanceRequest() { LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_MoneyBalanceRequest); msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); msg->nextBlockFast(_PREHASH_MoneyData); msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null ); gAgent.sendReliableMessage(); } void LLStatusBar::setHealth(S32 health) { //LL_INFOS() << "Setting health to: " << buffer << LL_ENDL; mTextHealth->setText(llformat("%d%%", health)); if( mHealth > health ) { if (mHealth > (health + gSavedSettings.getF32("UISndHealthReductionThreshold"))) { if (isAgentAvatarValid()) { if (gAgentAvatarp->getSex() == SEX_FEMALE) { make_ui_sound("UISndHealthReductionF"); } else { make_ui_sound("UISndHealthReductionM"); } } } mHealthTimer->reset(ICON_TIMER_EXPIRY); } mHealth = health; } S32 LLStatusBar::getBalance() const { return mBalance; } S32 LLStatusBar::getHealth() const { return mHealth; } void LLStatusBar::setLandCredit(S32 credit) { mSquareMetersCredit = credit; } void LLStatusBar::setLandCommitted(S32 committed) { mSquareMetersCommitted = committed; } BOOL LLStatusBar::isUserTiered() const { return (mSquareMetersCredit > 0); } S32 LLStatusBar::getSquareMetersCredit() const { return mSquareMetersCredit; } S32 LLStatusBar::getSquareMetersCommitted() const { return mSquareMetersCommitted; } S32 LLStatusBar::getSquareMetersLeft() const { return mSquareMetersCredit - mSquareMetersCommitted; } static void onClickParcelInfo() { LLViewerParcelMgr::getInstance()->selectParcelAt(gAgent.getPositionGlobal()); LLFloaterLand::showInstance(); } static bool rebakeRegionCallback(const LLSD& n, const LLSD& r) { if(!LLNotificationsUtil::getSelectedOption(n, r)) //0 is Yes { LLMenuOptionPathfindingRebakeNavmesh::getInstance()->sendRequestRebakeNavmesh(); return true; } return false; } void LLStatusBar::createNavMeshStatusListenerForCurrentRegion() { if (mNavMeshSlot.connected()) { mNavMeshSlot.disconnect(); } LLViewerRegion *currentRegion = gAgent.getRegion(); if (currentRegion != NULL) { mNavMeshSlot = LLPathfindingManager::getInstance()->registerNavMeshListenerForRegion(currentRegion, boost::bind(&LLStatusBar::onNavMeshStatusChange, this, _2)); LLPathfindingManager::getInstance()->requestGetNavMeshForRegion(currentRegion, true); } } void LLStatusBar::onNavMeshStatusChange(const LLPathfindingNavMeshStatus &pNavMeshStatus) { mIsNavMeshDirty = pNavMeshStatus.isValid() && (pNavMeshStatus.getStatus() != LLPathfindingNavMeshStatus::kComplete); refresh(); } static void onClickScripts() { LLViewerRegion* region = gAgent.getRegion(); if(region && region->getRegionFlag(REGION_FLAGS_ESTATE_SKIP_SCRIPTS)) { LLNotificationsUtil::add("ScriptsStopped"); } else if(region && region->getRegionFlag(REGION_FLAGS_SKIP_SCRIPTS)) { LLNotificationsUtil::add("ScriptsNotRunning"); } else { LLNotificationsUtil::add("NoOutsideScripts"); } } // sets the static variables necessary for the date void LLStatusBar::setupDate() { // fill the day array with what's in the xui std::string day_list = getString("StatBarDaysOfWeek"); size_t length = day_list.size(); // quick input check if(length < MAX_DATE_STRING_LENGTH) { // tokenize it and put it in the array std::string cur_word; for(size_t i = 0; i < length; ++i) { if(day_list[i] == ':') { sDays.push_back(cur_word); cur_word.clear(); } else { cur_word.append(1, day_list[i]); } } sDays.push_back(cur_word); } // fill the day array with what's in the xui std::string month_list = getString( "StatBarMonthsOfYear" ); length = month_list.size(); // quick input check if(length < MAX_DATE_STRING_LENGTH) { // tokenize it and put it in the array std::string cur_word; for(size_t i = 0; i < length; ++i) { if(month_list[i] == ':') { sMonths.push_back(cur_word); cur_word.clear(); } else { cur_word.append(1, month_list[i]); } } sMonths.push_back(cur_word); } // make sure we have at least 7 days and 12 months if(sDays.size() < 7) { sDays.resize(7); } if(sMonths.size() < 12) { sMonths.resize(12); } } static void onClickSearch(const std::string& query) { LLFloaterSearch::SearchQuery search; search.query = query; LLFloaterSearch::showInstance(search); } BOOL can_afford_transaction(S32 cost) { return((cost <= 0)||((gStatusBar) && (gStatusBar->getBalance() >=cost))); } // Implements secondlife:///app/balance/request to request a L$ balance // update via UDP message system. JC class LLBalanceHandler : public LLCommandHandler { public: // Requires "trusted" browser/URL source LLBalanceHandler() : LLCommandHandler("balance", UNTRUSTED_BLOCK) { } bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { if (tokens.size() == 1 && tokens[0].asString() == "request") { LLStatusBar::sendMoneyBalanceRequest(); return true; } return false; } }; // register with command dispatch system LLBalanceHandler gBalanceHandler;