aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llstatusbar.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llstatusbar.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llstatusbar.cpp631
1 files changed, 631 insertions, 0 deletions
diff --git a/linden/indra/newview/llstatusbar.cpp b/linden/indra/newview/llstatusbar.cpp
new file mode 100644
index 0000000..a358f1e
--- /dev/null
+++ b/linden/indra/newview/llstatusbar.cpp
@@ -0,0 +1,631 @@
1/**
2 * @file llstatusbar.cpp
3 * @brief LLStatusBar class implementation
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "llstatusbar.h"
31
32#include <iomanip>
33
34#include "imageids.h"
35#include "llfontgl.h"
36#include "llrect.h"
37#include "llerror.h"
38#include "llparcel.h"
39#include "llstring.h"
40#include "message.h"
41
42#include "llagent.h"
43#include "llbutton.h"
44#include "llviewercontrol.h"
45#include "llfloaterbuycurrency.h"
46#include "llfloaterchat.h"
47#include "llfloaterland.h"
48#include "llfloaterregioninfo.h"
49#include "llfloaterscriptdebug.h"
50#include "llhudicon.h"
51#include "llinventoryview.h"
52#include "llkeyboard.h"
53#include "lllineeditor.h"
54#include "llmenugl.h"
55#include "llnotify.h"
56#include "llimview.h"
57#include "lltextbox.h"
58#include "llui.h"
59#include "llviewerparceloverlay.h"
60#include "llviewerregion.h"
61#include "llviewerstats.h"
62#include "llviewerwindow.h"
63#include "llframetimer.h"
64#include "llvoavatar.h"
65#include "llresmgr.h"
66#include "llworld.h"
67#include "llstatgraph.h"
68#include "llviewermenu.h" // for gMenuBarView
69#include "llviewerparcelmgr.h"
70#include "llviewerthrottle.h"
71#include "llvieweruictrlfactory.h"
72
73#include "lltoolmgr.h"
74#include "llfocusmgr.h"
75#include "viewer.h"
76
77//
78// Globals
79//
80LLStatusBar *gStatusBar = NULL;
81S32 STATUS_BAR_HEIGHT = 0;
82extern S32 MENU_BAR_HEIGHT;
83
84// TODO: these values ought to be in the XML too
85const S32 MENU_PARCEL_SPACING = 1; // Distance from right of menu item to parcel information
86const S32 SIM_STAT_WIDTH = 8;
87const F32 SIM_WARN_FRACTION = 0.75f;
88const F32 SIM_FULL_FRACTION = 0.98f;
89const LLColor4 SIM_OK_COLOR(0.f, 1.f, 0.f, 1.f);
90const LLColor4 SIM_WARN_COLOR(1.f, 1.f, 0.f, 1.f);
91const LLColor4 SIM_FULL_COLOR(1.f, 0.f, 0.f, 1.f);
92const F32 ICON_TIMER_EXPIRY = 3.f; // How long the balance and health icons should flash after a change.
93const F32 ICON_FLASH_FREQUENCY = 2.f;
94const S32 GRAPHIC_FUDGE = 4;
95const S32 TEXT_HEIGHT = 18;
96
97LLStatusBar::LLStatusBar(const std::string& name, const LLRect& rect)
98: LLPanel(name, LLRect(), FALSE), // not mouse opaque
99 mBalance(0),
100 mHealth(100),
101 mSquareMetersCredit(0),
102 mSquareMetersCommitted(0)
103{
104 // status bar can possible overlay menus?
105 mMouseOpaque = FALSE;
106 setIsChrome(TRUE);
107
108 mBalanceTimer = new LLFrameTimer();
109 mHealthTimer = new LLFrameTimer();
110
111 gUICtrlFactory->buildPanel(this,"panel_status_bar.xml");
112
113 // status bar can never get a tab
114 setFocusRoot(FALSE);
115
116 mBtnScriptOut = LLUICtrlFactory::getButtonByName( this, "scriptout" );
117 mBtnHealth = LLUICtrlFactory::getButtonByName( this, "health" );
118 mBtnFly = LLUICtrlFactory::getButtonByName( this, "fly" );
119 mBtnBuild = LLUICtrlFactory::getButtonByName( this, "build" );
120 mBtnScripts = LLUICtrlFactory::getButtonByName( this, "scripts" );
121 mBtnPush = LLUICtrlFactory::getButtonByName( this, "restrictpush" );
122 mBtnBuyLand = LLUICtrlFactory::getButtonByName( this, "buyland" );
123 mBtnBuyCurrency = LLUICtrlFactory::getButtonByName( this, "buycurrency" );
124
125 mTextParcelName = LLUICtrlFactory::getTextBoxByName( this, "ParcelNameText" );
126 mTextBalance = LLUICtrlFactory::getTextBoxByName( this, "BalanceText" );
127
128 mTextHealth = LLUICtrlFactory::getTextBoxByName( this, "HealthText" );
129 mTextTime = LLUICtrlFactory::getTextBoxByName( this, "TimeText" );
130
131 S32 x = mRect.getWidth() - 2;
132 S32 y = 0;
133 LLRect r;
134 r.set( x-SIM_STAT_WIDTH, y+MENU_BAR_HEIGHT-1, x, y+1);
135 mSGBandwidth = new LLStatGraph("BandwidthGraph", r);
136 mSGBandwidth->setFollows(FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
137 mSGBandwidth->setStat(&gViewerStats->mKBitStat);
138 LLString text = childGetText("bandwidth_tooltip") + " ";
139 LLUIString bandwidth_tooltip = text; // get the text from XML until this widget is XML driven
140 mSGBandwidth->setLabel(bandwidth_tooltip.getString().c_str());
141 mSGBandwidth->setUnits("Kbps");
142 mSGBandwidth->setPrecision(0);
143 addChild(mSGBandwidth);
144 x -= SIM_STAT_WIDTH + 2;
145
146 r.set( x-SIM_STAT_WIDTH, y+MENU_BAR_HEIGHT-1, x, y+1);
147 mSGPacketLoss = new LLStatGraph("PacketLossPercent", r);
148 mSGPacketLoss->setFollows(FOLLOWS_BOTTOM | FOLLOWS_RIGHT);
149 mSGPacketLoss->setStat(&gViewerStats->mPacketsLostPercentStat);
150 text = childGetText("packet_loss_tooltip") + " ";
151 LLUIString packet_loss_tooltip = text; // get the text from XML until this widget is XML driven
152 mSGPacketLoss->setLabel(packet_loss_tooltip.getString().c_str());
153 mSGPacketLoss->setUnits("%");
154 mSGPacketLoss->setMin(0.f);
155 mSGPacketLoss->setMax(5.f);
156 mSGPacketLoss->setThreshold(0, 0.5f);
157 mSGPacketLoss->setThreshold(1, 1.f);
158 mSGPacketLoss->setThreshold(2, 3.f);
159 mSGPacketLoss->setPrecision(1);
160 mSGPacketLoss->mPerSec = FALSE;
161 addChild(mSGPacketLoss);
162
163}
164
165LLStatusBar::~LLStatusBar()
166{
167 delete mBalanceTimer;
168 mBalanceTimer = NULL;
169
170 delete mHealthTimer;
171 mHealthTimer = NULL;
172
173 // LLView destructor cleans up children
174}
175
176BOOL LLStatusBar::postBuild()
177{
178 childSetAction("scriptout", onClickScriptDebug, this);
179 childSetAction("health", onClickHealth, this);
180 childSetAction("fly", onClickFly, this);
181 childSetAction("buyland", onClickBuyLand, this );
182 childSetAction("buycurrency", onClickBuyCurrency, this );
183 childSetAction("build", onClickBuild, this );
184 childSetAction("scripts", onClickScripts, this );
185 childSetAction("restrictpush", onClickPush, this );
186
187 childSetActionTextbox("ParcelNameText", onClickParcelInfo );
188 childSetActionTextbox("BalanceText", onClickBalance );
189
190 return TRUE;
191}
192
193EWidgetType LLStatusBar::getWidgetType() const
194{
195 return WIDGET_TYPE_STATUS_BAR;
196}
197
198LLString LLStatusBar::getWidgetTag() const
199{
200 return LL_STATUS_BAR_TAG;
201}
202
203//-----------------------------------------------------------------------
204// Overrides
205//-----------------------------------------------------------------------
206
207// virtual
208void LLStatusBar::draw()
209{
210 refresh();
211
212 LLView::draw();
213}
214
215
216// Per-frame updates of visibility
217void LLStatusBar::refresh()
218{
219 F32 bwtotal = gViewerThrottle.getMaxBandwidth() / 1000.f;
220 mSGBandwidth->setMin(0.f);
221 mSGBandwidth->setMax(bwtotal*1.25f);
222 mSGBandwidth->setThreshold(0, bwtotal*0.75f);
223 mSGBandwidth->setThreshold(1, bwtotal);
224 mSGBandwidth->setThreshold(2, bwtotal);
225
226 // Get current UTC time, adjusted for the user's clock
227 // being off.
228 U32 utc_time;
229 utc_time = time_corrected();
230
231 // There's only one internal tm buffer.
232 struct tm* internal_time;
233
234 // Convert to Pacific, based on server's opinion of whether
235 // it's daylight savings time there.
236 internal_time = utc_to_pacific_time(utc_time, gPacificDaylightTime);
237
238 S32 hour = internal_time->tm_hour;
239 S32 min = internal_time->tm_min;
240
241 std::string am_pm = "AM";
242 if (hour > 11)
243 {
244 hour -= 12;
245 am_pm = "PM";
246 }
247
248 std::string tz = "PST";
249 if (gPacificDaylightTime)
250 {
251 tz = "PDT";
252 }
253 // Zero hour is 12 AM
254 if (hour == 0) hour = 12;
255 std::ostringstream t;
256 t << std::setfill(' ') << std::setw(2) << hour << ":"
257 << std::setfill('0') << std::setw(2) << min
258 << " " << am_pm << " " << tz;
259 mTextTime->setText(t.str().c_str());
260
261 LLRect r;
262 const S32 MENU_RIGHT = gMenuBarView->getRightmostMenuEdge();
263 S32 x = MENU_RIGHT + MENU_PARCEL_SPACING;
264 S32 y = 0;
265
266 LLViewerRegion *region = gAgent.getRegion();
267 LLParcel *parcel = gParcelMgr->getAgentParcel();
268
269 LLRect buttonRect;
270
271 if (LLHUDIcon::iconsNearby())
272 {
273 childGetRect( "scriptout", buttonRect );
274 r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
275 mBtnScriptOut->setRect(r);
276 mBtnScriptOut->setVisible(TRUE);
277 x += buttonRect.getWidth();
278 }
279 else
280 {
281 mBtnScriptOut->setVisible(FALSE);
282 }
283
284 if ((region && region->getAllowDamage()) ||
285 (parcel && parcel->getAllowDamage()) )
286 {
287 // set visibility based on flashing
288 if( mHealthTimer->hasExpired() )
289 {
290 mBtnHealth->setVisible( TRUE );
291 }
292 else
293 {
294 BOOL flash = S32(mHealthTimer->getElapsedSeconds() * ICON_FLASH_FREQUENCY) & 1;
295 mBtnHealth->setVisible( flash );
296 }
297 mTextHealth->setVisible(TRUE);
298
299 // Health
300 childGetRect( "health", buttonRect );
301 r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight());
302 mBtnHealth->setRect(r);
303 x += buttonRect.getWidth();
304
305 const S32 health_width = S32( LLFontGL::sSansSerifSmall->getWidth("100%") );
306 r.set(x, y+TEXT_HEIGHT - 2, x+health_width, y);
307 mTextHealth->setRect(r);
308 x += health_width;
309 }
310 else
311 {
312 // invisible if region doesn't allow damage
313 mBtnHealth->setVisible(FALSE);
314 mTextHealth->setVisible(FALSE);
315 }
316
317 if ((region && region->getBlockFly()) ||
318 (parcel && !parcel->getAllowFly()) )
319 {
320 // No Fly Zone
321 childGetRect( "fly", buttonRect );
322 mBtnFly->setVisible(TRUE);
323 r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight());
324 mBtnFly->setRect(r);
325 x += buttonRect.getWidth();
326 }
327 else
328 {
329 mBtnFly->setVisible(FALSE);
330 }
331
332 BOOL no_build = parcel && !parcel->getAllowModify();
333 mBtnBuild->setVisible( no_build );
334 if (no_build)
335 {
336 childGetRect( "build", buttonRect );
337 // No Build Zone
338 r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight());
339 mBtnBuild->setRect(r);
340 x += buttonRect.getWidth();
341 }
342
343 BOOL no_scripts = FALSE;
344 if((region
345 && ((region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
346 || (region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)))
347 || (parcel && !parcel->getAllowOtherScripts()))
348 {
349 no_scripts = TRUE;
350 }
351 mBtnScripts->setVisible( no_scripts );
352 if (no_scripts)
353 {
354 // No scripts
355 childGetRect( "scripts", buttonRect );
356 r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight());
357 mBtnScripts->setRect(r);
358 x += buttonRect.getWidth();
359 }
360
361 BOOL no_region_push = (region && region->getRestrictPushObject());
362 BOOL no_push = no_region_push || (parcel && parcel->getRestrictPushObject());
363 mBtnPush->setVisible( no_push );
364 if (no_push)
365 {
366 childGetRect( "restrictpush", buttonRect );
367 // No Push Zone
368 r.setOriginAndSize( x, y-GRAPHIC_FUDGE, buttonRect.getWidth(), buttonRect.getHeight());
369 mBtnPush->setRect(r);
370 x += buttonRect.getWidth();
371 }
372
373 BOOL canBuyLand = parcel
374 && !parcel->isPublic()
375 && gParcelMgr->canAgentBuyParcel(parcel, false);
376 mBtnBuyLand->setVisible(canBuyLand);
377 if (canBuyLand)
378 {
379 childGetRect( "buyland", buttonRect );
380 r.setOriginAndSize( x, y, buttonRect.getWidth(), buttonRect.getHeight());
381 mBtnBuyLand->setRect(r);
382 x += buttonRect.getWidth();
383 }
384
385 LLString location_name;
386 if (region)
387 {
388 const LLVector3& agent_pos_region = gAgent.getPositionAgent();
389 S32 pos_x = lltrunc( agent_pos_region.mV[VX] );
390 S32 pos_y = lltrunc( agent_pos_region.mV[VY] );
391 S32 pos_z = lltrunc( agent_pos_region.mV[VZ] );
392
393 // Round the numbers based on the velocity
394 LLVector3 agent_velocity = gAgent.getVelocity();
395 F32 velocity_mag_sq = agent_velocity.magVecSquared();
396
397 const F32 FLY_CUTOFF = 6.f; // meters/sec
398 const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
399 const F32 WALK_CUTOFF = 1.5f; // meters/sec
400 const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;
401
402 if (velocity_mag_sq > FLY_CUTOFF_SQ)
403 {
404 pos_x -= pos_x % 4;
405 pos_y -= pos_y % 4;
406 }
407 else if (velocity_mag_sq > WALK_CUTOFF_SQ)
408 {
409 pos_x -= pos_x % 2;
410 pos_y -= pos_y % 2;
411 }
412
413 if (parcel && parcel->getName())
414 {
415 location_name = region->getName()
416 + llformat(" %d, %d, %d (%s) - %s",
417 pos_x, pos_y, pos_z,
418 region->getSimAccessString(),
419 parcel->getName());
420 }
421 else
422 {
423 location_name = region->getName()
424 + llformat(" %d, %d, %d (%s)",
425 pos_x, pos_y, pos_z,
426 region->getSimAccessString());
427 }
428 }
429 else
430 {
431 // no region
432 location_name = "(Unknown)";
433 }
434 mTextParcelName->setText(location_name);
435
436 // Adjust region name and parcel name
437 x += 4;
438
439 const S32 PARCEL_RIGHT = llmin(mTextTime->getRect().mLeft, mTextParcelName->getTextPixelWidth() + x + 5);
440 r.set(x+4, mRect.getHeight() - 2, PARCEL_RIGHT, 0);
441 mTextParcelName->setRect(r);
442}
443
444void LLStatusBar::setVisibleForMouselook(bool visible)
445{
446 mTextBalance->setVisible(visible);
447 mTextTime->setVisible(visible);
448 mSGBandwidth->setVisible(visible);
449 mSGPacketLoss->setVisible(visible);
450 mBtnBuyCurrency->setVisible(visible);
451}
452
453void LLStatusBar::debitBalance(S32 debit)
454{
455 setBalance(getBalance() - debit);
456}
457
458void LLStatusBar::creditBalance(S32 credit)
459{
460 setBalance(getBalance() + credit);
461}
462
463void LLStatusBar::setBalance(S32 balance)
464{
465 LLString balance_str;
466 gResMgr->getMonetaryString( balance_str, balance );
467 mTextBalance->setText( balance_str );
468
469 if (mBalance && (fabs((F32)(mBalance - balance)) > gSavedSettings.getF32("UISndMoneyChangeThreshold")))
470 {
471 if (mBalance > balance)
472 make_ui_sound("UISndMoneyChangeDown");
473 else
474 make_ui_sound("UISndMoneyChangeUp");
475 }
476
477 if( balance != mBalance )
478 {
479 mBalanceTimer->reset();
480 mBalanceTimer->setTimerExpirySec( ICON_TIMER_EXPIRY );
481 mBalance = balance;
482 }
483}
484
485void LLStatusBar::setHealth(S32 health)
486{
487 char buffer[MAX_STRING];
488 sprintf(buffer, "%d%%", health);
489 //llinfos << "Setting health to: " << buffer << llendl;
490 mTextHealth->setText(buffer);
491
492 if( mHealth > health )
493 {
494 if (mHealth > (health + gSavedSettings.getF32("UISndHealthReductionThreshold")))
495 {
496 LLVOAvatar *me;
497
498 if ((me = gAgent.getAvatarObject()))
499 {
500 if (me->getSex() == SEX_FEMALE)
501 {
502 make_ui_sound("UISndHealthReductionF");
503 }
504 else
505 {
506 make_ui_sound("UISndHealthReductionM");
507 }
508 }
509 }
510
511 mHealthTimer->reset();
512 mHealthTimer->setTimerExpirySec( ICON_TIMER_EXPIRY );
513 }
514
515 mHealth = health;
516}
517
518S32 LLStatusBar::getBalance() const
519{
520 return mBalance;
521}
522
523
524S32 LLStatusBar::getHealth() const
525{
526 return mHealth;
527}
528
529void LLStatusBar::setLandCredit(S32 credit)
530{
531 mSquareMetersCredit = credit;
532}
533void LLStatusBar::setLandCommitted(S32 committed)
534{
535 mSquareMetersCommitted = committed;
536}
537
538BOOL LLStatusBar::isUserTiered() const
539{
540 return (mSquareMetersCredit > 0);
541}
542
543S32 LLStatusBar::getSquareMetersCredit() const
544{
545 return mSquareMetersCredit;
546}
547
548S32 LLStatusBar::getSquareMetersCommitted() const
549{
550 return mSquareMetersCommitted;
551}
552
553S32 LLStatusBar::getSquareMetersLeft() const
554{
555 return mSquareMetersCredit - mSquareMetersCommitted;
556}
557
558// static
559void LLStatusBar::onClickParcelInfo(void* data)
560{
561 gParcelMgr->selectParcelAt(gAgent.getPositionGlobal());
562
563 LLFloaterLand::show();
564}
565
566// static
567void LLStatusBar::onClickBalance(void* data)
568{
569 LLFloaterBuyCurrency::buyCurrency();
570}
571
572// static
573void LLStatusBar::onClickBuyCurrency(void* data)
574{
575 LLFloaterBuyCurrency::buyCurrency();
576}
577
578// static
579void LLStatusBar::onClickHealth(void* )
580{
581 LLNotifyBox::showXml("NotSafe");
582}
583
584// static
585void LLStatusBar::onClickScriptDebug(void*)
586{
587 LLFloaterScriptDebug::show(LLUUID::null);
588}
589
590// static
591void LLStatusBar::onClickFly(void* )
592{
593 LLNotifyBox::showXml("NoFly");
594}
595
596// static
597void LLStatusBar::onClickPush(void* )
598{
599 LLNotifyBox::showXml("PushRestricted");
600}
601
602// static
603void LLStatusBar::onClickBuild(void*)
604{
605 LLNotifyBox::showXml("NoBuild");
606}
607
608// static
609void LLStatusBar::onClickScripts(void*)
610{
611 LLViewerRegion* region = gAgent.getRegion();
612 if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)
613 {
614 LLNotifyBox::showXml("ScriptsStopped");
615 }
616 else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
617 {
618 LLNotifyBox::showXml("ScriptsNotRunning");
619 }
620 else
621 {
622 LLNotifyBox::showXml("NoOutsideScripts");
623 }
624}
625
626// static
627void LLStatusBar::onClickBuyLand(void*)
628{
629 gParcelMgr->selectParcelAt(gAgent.getPositionGlobal());
630 gParcelMgr->startBuyLand();
631}