llviewerwindow.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include "llpanellogin.h"
00035 #include "llviewerkeyboard.h"
00036 #include "llviewerwindow.h"
00037 
00038 // system library includes
00039 #include <stdio.h>
00040 #include <iostream>
00041 #include <fstream>
00042 
00043 #include "llviewquery.h"
00044 #include "llxmltree.h"
00045 //#include "llviewercamera.h"
00046 #include "llglimmediate.h"
00047 
00048 #include "llvoiceclient.h"      // for push-to-talk button handling
00049 
00050 #ifdef SABINRIG
00051 #include "cbw.h"
00052 #endif //SABINRIG
00053 
00054 //
00055 // TODO: Many of these includes are unnecessary.  Remove them.
00056 //
00057 
00058 // linden library includes
00059 #include "audioengine.h"                // mute on minimize
00060 #include "indra_constants.h"
00061 #include "llassetstorage.h"
00062 #include "llfontgl.h"
00063 #include "llrect.h"
00064 #include "llsky.h"
00065 #include "llstring.h"
00066 #include "llui.h"
00067 #include "lluuid.h"
00068 #include "llview.h"
00069 #include "llxfermanager.h"
00070 #include "message.h"
00071 #include "object_flags.h"
00072 #include "lltimer.h"
00073 #include "timing.h"
00074 #include "llviewermenu.h"
00075 
00076 // newview includes
00077 #include "llagent.h"
00078 #include "llalertdialog.h"
00079 #include "llbox.h"
00080 #include "llchatbar.h"
00081 #include "llconsole.h"
00082 #include "llviewercontrol.h"
00083 #include "llcylinder.h"
00084 #include "lldebugview.h"
00085 #include "lldir.h"
00086 #include "lldrawable.h"
00087 #include "lldrawpoolalpha.h"
00088 #include "lldrawpoolbump.h"
00089 #include "lldrawpoolwater.h"
00090 #include "llmaniptranslate.h"
00091 #include "llface.h"
00092 #include "llfeaturemanager.h"
00093 #include "llfilepicker.h"
00094 #include "llfloater.h"
00095 #include "llfloateractivespeakers.h"
00096 #include "llfloaterbuildoptions.h"
00097 #include "llfloaterbuyland.h"
00098 #include "llfloatercamera.h"
00099 #include "llfloaterchat.h"
00100 #include "llfloaterchatterbox.h"
00101 #include "llfloatercustomize.h"
00102 #include "llfloatereditui.h" // HACK JAMESDEBUG for ui editor
00103 #include "llfloaterland.h"
00104 #include "llfloaterinspect.h"
00105 #include "llfloatermap.h"
00106 #include "llfloaternamedesc.h"
00107 #include "llfloaterpreference.h"
00108 #include "llfloatersnapshot.h"
00109 #include "llfloatertools.h"
00110 #include "llfloaterworldmap.h"
00111 #include "llfocusmgr.h"
00112 #include "llframestatview.h"
00113 #include "llgesturemgr.h"
00114 #include "llglheaders.h"
00115 #include "llhippo.h"
00116 #include "llhoverview.h"
00117 #include "llhudmanager.h"
00118 #include "llhudview.h"
00119 #include "llimagebmp.h"
00120 #include "llimagej2c.h"
00121 #include "llinventoryview.h"
00122 #include "llkeyboard.h"
00123 #include "lllineeditor.h"
00124 #include "llmenugl.h"
00125 #include "llmodaldialog.h"
00126 #include "llmorphview.h"
00127 #include "llmoveview.h"
00128 #include "llnotify.h"
00129 #include "lloverlaybar.h"
00130 #include "llpreviewtexture.h"
00131 #include "llprogressview.h"
00132 #include "llresmgr.h"
00133 #include "llrootview.h"
00134 #include "llselectmgr.h"
00135 #include "llrendersphere.h"
00136 #include "llstartup.h"
00137 #include "llstatusbar.h"
00138 #include "llstatview.h"
00139 #include "llsurface.h"
00140 #include "llsurfacepatch.h"
00141 #include "llimview.h"
00142 #include "lltexlayer.h"
00143 #include "lltextbox.h"
00144 #include "lltexturecache.h"
00145 #include "lltexturefetch.h"
00146 #include "lltextureview.h"
00147 #include "lltool.h"
00148 #include "lltoolbar.h"
00149 #include "lltoolcomp.h"
00150 #include "lltooldraganddrop.h"
00151 #include "lltoolface.h"
00152 #include "lltoolfocus.h"
00153 #include "lltoolgrab.h"
00154 #include "lltoolmgr.h"
00155 #include "lltoolmorph.h"
00156 #include "lltoolpie.h"
00157 #include "lltoolplacer.h"
00158 #include "lltoolselectland.h"
00159 #include "lltoolview.h"
00160 #include "lluictrlfactory.h"
00161 #include "lluploaddialog.h"
00162 #include "llurldispatcher.h"            // SLURL from other app instance
00163 #include "llvieweraudio.h"
00164 #include "llviewercamera.h"
00165 #include "llviewergesture.h"
00166 #include "llviewerimagelist.h"
00167 #include "llviewerinventory.h"
00168 #include "llviewerkeyboard.h"
00169 #include "llviewermenu.h"
00170 #include "llviewermessage.h"
00171 #include "llviewerobjectlist.h"
00172 #include "llviewerparcelmgr.h"
00173 #include "llviewerregion.h"
00174 #include "llviewerstats.h"
00175 #include "llvoavatar.h"
00176 #include "llvovolume.h"
00177 #include "llworld.h"
00178 #include "llworldmapview.h"
00179 #include "pipeline.h"
00180 #include "llappviewer.h"
00181 #include "llurlsimstring.h"
00182 #include "llviewerdisplay.h"
00183 #include "llspatialpartition.h"
00184 #include "llviewerjoystick.h"
00185 
00186 #if LL_WINDOWS
00187 #include "llwindebug.h"
00188 #include <tchar.h> // For Unicode conversion methods
00189 #endif
00190 
00191 //
00192 // Globals
00193 //
00194 void render_ui_and_swap_if_needed();
00195 void render_ui_and_swap();
00196 LLBottomPanel* gBottomPanel = NULL;
00197 
00198 extern BOOL gDebugClicks;
00199 extern BOOL gDisplaySwapBuffers;
00200 extern BOOL gResizeScreenTexture;
00201 extern S32 gJamesInt;
00202 
00203 LLViewerWindow  *gViewerWindow = NULL;
00204 LLVelocityBar   *gVelocityBar = NULL;
00205 
00206 LLVector3d              gLastHitPosGlobal;
00207 LLVector3d              gLastHitObjectOffset;
00208 LLUUID                  gLastHitObjectID;
00209 S32                             gLastHitObjectFace = -1;
00210 BOOL                    gLastHitLand = FALSE;
00211 F32                             gLastHitUCoord;
00212 F32                             gLastHitVCoord;
00213 
00214 
00215 LLVector3d              gLastHitNonFloraPosGlobal;
00216 LLVector3d              gLastHitNonFloraObjectOffset;
00217 LLUUID                  gLastHitNonFloraObjectID;
00218 S32                             gLastHitNonFloraObjectFace = -1;
00219 BOOL                    gLastHitParcelWall = FALSE;
00220 
00221 S32                             gLastHitUIElement = 0;
00222 LLHUDIcon*              gLastHitHUDIcon = NULL;
00223 
00224 BOOL                    gDebugSelect = FALSE;
00225 U8                              gLastPickAlpha = 255;
00226 BOOL                    gUseGLPick = FALSE;
00227 
00228 // On the next pick pass (whenever that happens)
00229 // should we try to pick individual faces?
00230 // Cleared to FALSE every time a pick happens.
00231 BOOL                    gPickFaces = FALSE;
00232 
00233 LLFrameTimer    gMouseIdleTimer;
00234 LLFrameTimer    gAwayTimer;
00235 LLFrameTimer    gAwayTriggerTimer;
00236 LLFrameTimer    gAlphaFadeTimer;
00237 
00238 BOOL                    gShowOverlayTitle = FALSE;
00239 BOOL                    gPickTransparent = TRUE;
00240 
00241 BOOL                    gDebugFastUIRender = FALSE;
00242 
00243 // HUD display lines in lower right
00244 BOOL                            gDisplayWindInfo = FALSE;
00245 BOOL                            gDisplayCameraPos = FALSE;
00246 BOOL                            gDisplayNearestWater = FALSE;
00247 BOOL                            gDisplayFOV = FALSE;
00248 
00249 S32 CHAT_BAR_HEIGHT = 28; 
00250 S32 OVERLAY_BAR_HEIGHT = 20;
00251 
00252 const U8 NO_FACE = 255;
00253 BOOL gQuietSnapshot = FALSE;
00254 
00255 const F32 MIN_AFK_TIME = 2.f; // minimum time after setting away state before coming back
00256 const F32 MAX_FAST_FRAME_TIME = 0.5f;
00257 const F32 FAST_FRAME_INCREMENT = 0.1f;
00258 
00259 const S32 PICK_HALF_WIDTH = 5;
00260 const S32 PICK_DIAMETER = 2 * PICK_HALF_WIDTH+1;
00261 
00262 const F32 MIN_DISPLAY_SCALE = 0.85f;
00263 
00264 const S32 CONSOLE_BOTTOM_PAD = 40;
00265 #ifdef SABINRIG
00267 bool rigControl = false;
00268 bool voltDisplay = true;
00269 bool nominalX = false;
00270 bool nominalY = false;
00271 static F32 nomerX = 0.0f;
00272 static F32 nomerY = 0.0f;
00273 const BOARD_NUM = 0; // rig stuff!
00274 const ADRANGE = BIP10VOLTS; // rig stuff!
00275 static unsigned short DataVal; // rig stuff!
00276 static F32 oldValueX = 0;
00277 static F32 newValueX = 50;
00278 static F32 oldValueY = 0;
00279 static F32 newValueY = 50;
00280 static S32 mouseX = 50;
00281 static S32 mouseY = 50;
00282 static float VoltageX = 50; // rig stuff!
00283 static float VoltageY = 50; // rig stuff!
00284 static float nVoltX = 0;
00285 static float nVoltY = 0;
00286 static F32 temp1 = 50.f;
00287 static F32 temp2 = 20.f;
00288 LLCoordGL new_gl;
00289 #endif //SABINRIG
00290 
00291 char    LLViewerWindow::sSnapshotBaseName[LL_MAX_PATH];
00292 char    LLViewerWindow::sSnapshotDir[LL_MAX_PATH];
00293 
00294 char    LLViewerWindow::sMovieBaseName[LL_MAX_PATH];
00295 
00296 extern void toggle_debug_menus(void*);
00297 
00298 #ifdef SABINRIG
00299 // static
00300 void LLViewerWindow::printFeedback()
00301 {
00302         if(rigControl == true)
00303         {
00304                 cbAIn (BOARD_NUM, 0, ADRANGE, &DataVal);
00305                 cbToEngUnits (BOARD_NUM,ADRANGE,DataVal,&VoltageX); //Convert raw to voltage for X-axis
00306                 cbAIn (BOARD_NUM, 1, ADRANGE, &DataVal);
00307                 cbToEngUnits (BOARD_NUM,ADRANGE,DataVal,&VoltageY); //Convert raw to voltage for Y-axis
00308                 if(voltDisplay == true)
00309                 {
00310                         llinfos <<  "Current Voltages - X:" << VoltageX << " Y:" << VoltageY << llendl; //Display voltage
00311                 }
00312 
00313                 if(nVoltX == 0)
00314                 {
00315                         nVoltX = VoltageX;
00316                         nVoltY = VoltageY; //First time setup of nominal values.
00317                 }
00318 
00319                 newValueX = VoltageX;
00320                 newValueY = VoltageY; //Take in current voltage and set to a separate value for adjustment.
00321 
00322                 mouseX = mCurrentMousePoint.mX;
00323                 mouseY = mCurrentMousePoint.mY; //Take in current cursor position and set to separate value for adjustment.
00324 
00325                 if( abs(newValueX - nVoltX) > nomerX )
00326                 {
00327                         if( (newValueX - oldValueX) < 0)
00328                         {
00329                                 mouseX += (S32)( ((newValueX - oldValueX)*.5)) * -temp;
00330                         }
00331                         else
00332                         {
00333                                 mouseX += (S32)( ((newValueX - oldValueX)*.5) * temp1);
00334                         }
00335                 }
00336                 else
00337                 {
00338                         mouseX = getWindowWidth() / 2;
00339                 }
00340                 if( abs(newValueY - nVoltY) > nomerY )
00341                 {
00342                         if( (newValueY - oldValueY) < 0)
00343                         {
00344                                 mouseY += (S32)( ((newValueY - oldValueY)*(newValueY - oldValueY)) * -temp2);
00345                         }
00346                         else
00347                         {
00348                                 mouseY += (S32)( ((newValueY - oldValueY)*(newValueY - oldValueY)) * temp2);
00349                         }
00350                 }
00351                 else
00352                 {
00353                         mouseY = getWindowHeight() / 2;
00354                 }
00355                 //mouseX += (S32)( (newValueX - nVoltX) * temp1 + 0.5 );
00356                 // (newValueX - oldValueX) = difference between current position and nominal position
00357                 // * temp1 = the amplification of the number that sets sensitivity
00358                 // + 0.5 = fixes rounding errors
00359                 
00360 
00361                 //mouseY += (S32)( (newValueY - nVoltY) * temp2 + 0.5 ); //Algorithm to adjust voltage for mouse adjustment.
00362 
00363                 oldValueX = newValueX;
00364                 oldValueY = newValueY;
00365 
00366                 new_gl.mX = mouseX;
00367                 new_gl.mY = mouseY; //Setup final coordinate to move mouse to.
00368 
00369                 setCursorPosition(new_gl); //Set final cursor position
00370         }
00371 }
00372 #endif //SABINRIG
00373 
00375 //
00376 // LLDebugText
00377 //
00378 
00379 class LLDebugText
00380 {
00381 private:
00382         struct Line
00383         {
00384                 Line(const std::string& in_text, S32 in_x, S32 in_y) : text(in_text), x(in_x), y(in_y) {}
00385                 std::string text;
00386                 S32 x,y;
00387         };
00388 
00389         LLViewerWindow *mWindow;
00390         
00391         typedef std::vector<Line> line_list_t;
00392         line_list_t mLineList;
00393         LLColor4 mTextColor;
00394         
00395 public:
00396         LLDebugText(LLViewerWindow* window) : mWindow(window) {}
00397         
00398         void addText(S32 x, S32 y, const std::string &text) 
00399         {
00400                 mLineList.push_back(Line(text, x, y));
00401         }
00402 
00403         void update()
00404         {
00405                 std::string wind_vel_text;
00406                 std::string wind_vector_text;
00407                 std::string rwind_vel_text;
00408                 std::string rwind_vector_text;
00409                 std::string audio_text;
00410 
00411                 // Draw the statistics in a light gray
00412                 // and in a thin font
00413                 mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f );
00414 
00415                 // Draw stuff growing up from right lower corner of screen
00416                 U32 xpos = mWindow->getWindowWidth() - 350;
00417                 U32 ypos = 64;
00418                 const U32 y_inc = 20;
00419 
00420                 if (gSavedSettings.getBOOL("DebugShowTime"))
00421                 {
00422                         const U32 y_inc2 = 15;
00423                         for (std::map<S32,LLFrameTimer>::reverse_iterator iter = gDebugTimers.rbegin();
00424                                  iter != gDebugTimers.rend(); ++iter)
00425                         {
00426                                 S32 idx = iter->first;
00427                                 LLFrameTimer& timer = iter->second;
00428                                 F32 time = timer.getElapsedTimeF32();
00429                                 S32 hours = (S32)(time / (60*60));
00430                                 S32 mins = (S32)((time - hours*(60*60)) / 60);
00431                                 S32 secs = (S32)((time - hours*(60*60) - mins*60));
00432                                 addText(xpos, ypos, llformat(" Debug %d: %d:%02d:%02d", idx, hours,mins,secs)); ypos += y_inc2;
00433                         }
00434                         
00435                         F32 time = gFrameTimeSeconds;
00436                         S32 hours = (S32)(time / (60*60));
00437                         S32 mins = (S32)((time - hours*(60*60)) / 60);
00438                         S32 secs = (S32)((time - hours*(60*60) - mins*60));
00439                         addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc;
00440                 }
00441                 
00442                 if (gDisplayCameraPos)
00443                 {
00444                         std::string camera_view_text;
00445                         std::string camera_center_text;
00446                         std::string agent_view_text;
00447                         std::string agent_left_text;
00448                         std::string agent_center_text;
00449                         std::string agent_root_center_text;
00450 
00451                         LLVector3d tvector; // Temporary vector to hold data for printing.
00452 
00453                         // Update camera center, camera view, wind info every other frame
00454                         tvector = gAgent.getPositionGlobal();
00455                         agent_center_text = llformat("AgentCenter  %f %f %f",
00456                                                                                  (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
00457 
00458                         if (gAgent.getAvatarObject())
00459                         {
00460                                 tvector = gAgent.getPosGlobalFromAgent(gAgent.getAvatarObject()->mRoot.getWorldPosition());
00461                                 agent_root_center_text = llformat("AgentRootCenter %f %f %f",
00462                                                                                                   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
00463                         }
00464                         else
00465                         {
00466                                 agent_root_center_text = "---";
00467                         }
00468 
00469 
00470                         tvector = LLVector4(gAgent.getFrameAgent().getAtAxis());
00471                         agent_view_text = llformat("AgentAtAxis  %f %f %f",
00472                                                                            (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
00473 
00474                         tvector = LLVector4(gAgent.getFrameAgent().getLeftAxis());
00475                         agent_left_text = llformat("AgentLeftAxis  %f %f %f",
00476                                                                            (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
00477 
00478                         tvector = gAgent.getCameraPositionGlobal();
00479                         camera_center_text = llformat("CameraCenter %f %f %f",
00480                                                                                   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
00481 
00482                         tvector = LLVector4(LLViewerCamera::getInstance()->getAtAxis());
00483                         camera_view_text = llformat("CameraAtAxis    %f %f %f",
00484                                                                                 (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
00485                 
00486                         addText(xpos, ypos, agent_center_text);  ypos += y_inc;
00487                         addText(xpos, ypos, agent_root_center_text);  ypos += y_inc;
00488                         addText(xpos, ypos, agent_view_text);  ypos += y_inc;
00489                         addText(xpos, ypos, agent_left_text);  ypos += y_inc;
00490                         addText(xpos, ypos, camera_center_text);  ypos += y_inc;
00491                         addText(xpos, ypos, camera_view_text);  ypos += y_inc;
00492                 }
00493 
00494                 if (gDisplayWindInfo)
00495                 {
00496                         wind_vel_text = llformat("Wind velocity %.2f m/s", gWindVec.magVec());
00497                         wind_vector_text = llformat("Wind vector   %.2f %.2f %.2f", gWindVec.mV[0], gWindVec.mV[1], gWindVec.mV[2]);
00498                         rwind_vel_text = llformat("RWind vel %.2f m/s", gRelativeWindVec.magVec());
00499                         rwind_vector_text = llformat("RWind vec   %.2f %.2f %.2f", gRelativeWindVec.mV[0], gRelativeWindVec.mV[1], gRelativeWindVec.mV[2]);
00500 
00501                         addText(xpos, ypos, wind_vel_text);  ypos += y_inc;
00502                         addText(xpos, ypos, wind_vector_text);  ypos += y_inc;
00503                         addText(xpos, ypos, rwind_vel_text);  ypos += y_inc;
00504                         addText(xpos, ypos, rwind_vector_text);  ypos += y_inc;
00505                 }
00506                 if (gDisplayWindInfo)
00507                 {
00508                         if (gAudiop)
00509                         {
00510                                 audio_text= llformat("Audio for wind: %d", gAudiop->isWindEnabled());
00511                         }
00512                         addText(xpos, ypos, audio_text);  ypos += y_inc;
00513                 }
00514                 if (gDisplayFOV)
00515                 {
00516                         addText(xpos, ypos, llformat("FOV: %2.1f deg", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));
00517                         ypos += y_inc;
00518                 }
00519                 
00520                 if (LLViewerJoystick::getInstance()->getOverrideCamera())
00521                 {
00522                         addText(xpos + 200, ypos, llformat("Flycam"));
00523                         ypos += y_inc;
00524                 }
00525                 
00526                 if (gSavedSettings.getBOOL("DebugShowRenderInfo"))
00527                 {
00528                         if (gPipeline.getUseVertexShaders() == 0)
00529                         {
00530                                 addText(xpos, ypos, "Shaders Disabled");
00531                                 ypos += y_inc;
00532                         }
00533                         addText(xpos, ypos, llformat("%d MB Vertex Data", LLVertexBuffer::sAllocatedBytes/(1024*1024)));
00534                         ypos += y_inc;
00535 
00536                         addText(xpos, ypos, llformat("%d Vertex Buffers", LLVertexBuffer::sGLCount));
00537                         ypos += y_inc;
00538 
00539                         addText(xpos, ypos, llformat("%d Mapped Buffers", LLVertexBuffer::sMappedCount));
00540                         ypos += y_inc;
00541 
00542                         addText(xpos, ypos, llformat("%d Vertex Buffer Binds", LLVertexBuffer::sBindCount));
00543                         ypos += y_inc;
00544 
00545                         addText(xpos, ypos, llformat("%d Vertex Buffer Sets", LLVertexBuffer::sSetCount));
00546                         ypos += y_inc;
00547 
00548                         addText(xpos, ypos, llformat("%d Texture Binds", LLImageGL::sBindCount));
00549                         ypos += y_inc;
00550 
00551                         addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount));
00552                         ypos += y_inc;
00553 
00554                         addText(xpos, ypos, llformat("%d Render Calls", gPipeline.mBatchCount));
00555             ypos += y_inc;
00556 
00557                         addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount));
00558                         ypos += y_inc;
00559 
00560                         addText(xpos, ypos, llformat("%d Texture Matrix Ops", gPipeline.mTextureMatrixOps));
00561                         ypos += y_inc;
00562 
00563                         gPipeline.mTextureMatrixOps = 0;
00564                         gPipeline.mMatrixOpCount = 0;
00565 
00566                         if (gPipeline.mBatchCount > 0)
00567                         {
00568                                 addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", gPipeline.mMinBatchSize, gPipeline.mMaxBatchSize, 
00569                                         gPipeline.mMeanBatchSize));
00570 
00571                                 gPipeline.mMinBatchSize = gPipeline.mMaxBatchSize;
00572                                 gPipeline.mMaxBatchSize = 0;
00573                                 gPipeline.mBatchCount = 0;
00574                         }
00575             ypos += y_inc;
00576 
00577                         addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount));
00578                         
00579                         ypos += y_inc;
00580 
00581 
00582                         addText(xpos,ypos, llformat("%d Avatars visible", LLVOAvatar::sNumVisibleAvatars));
00583                         
00584                         ypos += y_inc;
00585 
00586                         LLVertexBuffer::sBindCount = LLImageGL::sBindCount = 
00587                                 LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = 
00588                                 gPipeline.mNumVisibleNodes = 0;
00589                 }
00590                 if (gSavedSettings.getBOOL("DebugShowColor"))
00591                 {
00592                         U8 color[4];
00593                         LLCoordGL coord = gViewerWindow->getCurrentMouse();
00594                         glReadPixels(coord.mX, coord.mY, 1,1,GL_RGBA, GL_UNSIGNED_BYTE, color);
00595                         addText(xpos, ypos, llformat("%d %d %d %d", color[0], color[1], color[2], color[3]));
00596                         ypos += y_inc;
00597                 }
00598                 // only display these messages if we are actually rendering beacons at this moment
00599                 if (LLPipeline::getRenderBeacons(NULL) && LLPipeline::getProcessBeacons(NULL))
00600                 {
00601                         if (LLPipeline::getRenderParticleBeacons(NULL))
00602                         {
00603                                 addText(xpos, ypos, "Viewing particle beacons (blue)");
00604                                 ypos += y_inc;
00605                         }
00606                         if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES))
00607                         {
00608                                 addText(xpos, ypos, "Hiding particles");
00609                                 ypos += y_inc;
00610                         }
00611                         if (LLPipeline::getRenderPhysicalBeacons(NULL))
00612                         {
00613                                 addText(xpos, ypos, "Viewing physical object beacons (green)");
00614                                 ypos += y_inc;
00615                         }
00616                         if (LLPipeline::getRenderScriptedBeacons(NULL))
00617                         {
00618                                 addText(xpos, ypos, "Viewing scripted object beacons (red)");
00619                                 ypos += y_inc;
00620                         }
00621                         else
00622                                 if (LLPipeline::getRenderScriptedTouchBeacons(NULL))
00623                                 {
00624                                         addText(xpos, ypos, "Viewing scripted object with touch function beacons (red)");
00625                                         ypos += y_inc;
00626                                 }
00627                         if (LLPipeline::getRenderSoundBeacons(NULL))
00628                         {
00629                                 addText(xpos, ypos, "Viewing sound beacons (yellow)");
00630                                 ypos += y_inc;
00631                         }
00632                 }
00633         }
00634 
00635         void draw()
00636         {
00637                 for (line_list_t::iterator iter = mLineList.begin();
00638                          iter != mLineList.end(); ++iter)
00639                 {
00640                         const Line& line = *iter;
00641                         LLFontGL::sMonospace->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor,
00642                                                                                          LLFontGL::LEFT, LLFontGL::TOP,
00643                                                                                          LLFontGL::NORMAL, S32_MAX, S32_MAX, NULL, FALSE);
00644                 }
00645                 mLineList.clear();
00646         }
00647 
00648 };
00649 
00650 void LLViewerWindow::updateDebugText()
00651 {
00652         mDebugText->update();
00653 }
00654 
00656 //
00657 // LLViewerWindow
00658 //
00659 
00660 BOOL LLViewerWindow::handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
00661 {
00662         S32 x = pos.mX;
00663         S32 y = pos.mY;
00664         x = llround((F32)x / mDisplayScale.mV[VX]);
00665         y = llround((F32)y / mDisplayScale.mV[VY]);
00666 
00667         LLView::sMouseHandlerMessage = "";
00668 
00669         if (gDebugClicks)
00670         {
00671                 llinfos << "ViewerWindow left mouse down at " << x << "," << y << llendl;
00672         }
00673 
00674         if (gMenuBarView)
00675         {
00676                 // stop ALT-key access to menu
00677                 gMenuBarView->resetMenuTrigger();
00678         }
00679 
00680         mLeftMouseDown = TRUE;
00681 
00682         // Make sure we get a coresponding mouseup event, even if the mouse leaves the window
00683         mWindow->captureMouse();
00684 
00685         // Indicate mouse was active
00686         gMouseIdleTimer.reset();
00687 
00688         // Hide tooltips on mousedown
00689         if( mToolTip )
00690         {
00691                 mToolTipBlocked = TRUE;
00692                 mToolTip->setVisible( FALSE );
00693         }
00694 
00695         // Also hide hover info on mousedown
00696         if (gHoverView)
00697         {
00698                 gHoverView->cancelHover();
00699         }
00700 
00701         // Don't let the user move the mouse out of the window until mouse up.
00702         if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() )
00703         {
00704                 mWindow->setMouseClipping(TRUE);
00705         }
00706 
00707         LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
00708         if( mouse_captor )
00709         {
00710                 S32 local_x;
00711                 S32 local_y;
00712                 mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
00713                 if (LLView::sDebugMouseHandling)
00714                 {
00715                         llinfos << "Left Mouse Down handled by captor " << mouse_captor->getName() << llendl;
00716                 }
00717 
00718                 return mouse_captor->handleMouseDown(local_x, local_y, mask);
00719         }
00720 
00721         // Topmost view gets a chance before the hierarchy
00722         LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
00723         if (top_ctrl)
00724         {
00725                 S32 local_x, local_y;
00726                 top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
00727                 if (top_ctrl->pointInView(local_x, local_y))
00728                 {
00729                         return top_ctrl->handleMouseDown(local_x, local_y, mask);
00730                 }
00731                 else
00732                 {
00733                         setTopCtrl(NULL);
00734                 }
00735         }
00736 
00737         // Give the UI views a chance to process the click
00738         if( mRootView->handleMouseDown(x, y, mask) )
00739         {
00740                 if (LLView::sDebugMouseHandling)
00741                 {
00742                         llinfos << "Left Mouse Down" << LLView::sMouseHandlerMessage << llendl;
00743                 }
00744                 return TRUE;
00745         }
00746         else if (LLView::sDebugMouseHandling)
00747         {
00748                 llinfos << "Left Mouse Down not handled by view" << llendl;
00749         }
00750 
00751         if (gDisconnected)
00752         {
00753                 return FALSE;
00754         }
00755 
00756         if(LLToolMgr::getInstance()->getCurrentTool()->handleMouseDown( x, y, mask ) )
00757         {
00758                 // This is necessary to force clicks in the world to cause edit
00759                 // boxes that might have keyboard focus to relinquish it, and hence
00760                 // cause a commit to update their value.  JC
00761                 gFocusMgr.setKeyboardFocus(NULL);
00762                 return TRUE;
00763         }
00764 
00765         return FALSE;
00766 }
00767 
00768 BOOL LLViewerWindow::handleDoubleClick(LLWindow *window,  LLCoordGL pos, MASK mask)
00769 {
00770         S32 x = pos.mX;
00771         S32 y = pos.mY;
00772         x = llround((F32)x / mDisplayScale.mV[VX]);
00773         y = llround((F32)y / mDisplayScale.mV[VY]);
00774 
00775         LLView::sMouseHandlerMessage = "";
00776 
00777         if (gDebugClicks)
00778         {
00779                 llinfos << "ViewerWindow left mouse double-click at " << x << "," << y << llendl;
00780         }
00781 
00782         mLeftMouseDown = TRUE;
00783 
00784         // Hide tooltips
00785         if( mToolTip )
00786         {
00787                 mToolTip->setVisible( FALSE );
00788         }
00789 
00790         LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
00791         if( mouse_captor )
00792         {
00793                 S32 local_x;
00794                 S32 local_y;
00795                 mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
00796                 if (LLView::sDebugMouseHandling)
00797                 {
00798                         llinfos << "Left Mouse Down handled by captor " << mouse_captor->getName() << llendl;
00799                 }
00800 
00801                 return mouse_captor->handleDoubleClick(local_x, local_y, mask);
00802         }
00803 
00804         // Check for hit on UI.
00805         LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
00806         if (top_ctrl)
00807         {
00808                 S32 local_x, local_y;
00809                 top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
00810                 if (top_ctrl->pointInView(local_x, local_y))
00811                 {
00812                         return top_ctrl->handleDoubleClick(local_x, local_y, mask);
00813                 }
00814                 else
00815                 {
00816                         setTopCtrl(NULL);
00817                 }
00818         }
00819 
00820         if (mRootView->handleDoubleClick(x, y, mask)) 
00821         {
00822                 if (LLView::sDebugMouseHandling)
00823                 {
00824                         llinfos << "Left Mouse Down" << LLView::sMouseHandlerMessage << llendl;
00825                 }
00826                 return TRUE;
00827         }
00828         else if (LLView::sDebugMouseHandling)
00829         {
00830                 llinfos << "Left Mouse Down not handled by view" << llendl;
00831         }
00832 
00833                 // Why is this here?  JC 9/3/2002
00834         if (gNoRender) 
00835         {
00836                 return TRUE;
00837         }
00838 
00839         if(LLToolMgr::getInstance()->getCurrentTool()->handleDoubleClick( x, y, mask ) )
00840         {
00841                 return TRUE;
00842         }
00843 
00844         // if we got this far and nothing handled a double click, pass a normal mouse down
00845         return handleMouseDown(window, pos, mask);
00846 }
00847 
00848 BOOL LLViewerWindow::handleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
00849 {
00850         S32 x = pos.mX;
00851         S32 y = pos.mY;
00852         x = llround((F32)x / mDisplayScale.mV[VX]);
00853         y = llround((F32)y / mDisplayScale.mV[VY]);
00854 
00855         LLView::sMouseHandlerMessage = "";
00856 
00857         if (gDebugClicks)
00858         {
00859                 llinfos << "ViewerWindow left mouse up" << llendl;
00860         }
00861 
00862         mLeftMouseDown = FALSE;
00863 
00864         // Indicate mouse was active
00865         gMouseIdleTimer.reset();
00866 
00867         // Hide tooltips on mouseup
00868         if( mToolTip )
00869         {
00870                 mToolTip->setVisible( FALSE );
00871         }
00872 
00873         // Also hide hover info on mouseup
00874         if (gHoverView) gHoverView->cancelHover();
00875 
00876         BOOL handled = FALSE;
00877 
00878         mWindow->releaseMouse();
00879 
00880         LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
00881 
00882         if( tool->clipMouseWhenDown() )
00883         {
00884                 mWindow->setMouseClipping(FALSE);
00885         }
00886 
00887         LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
00888         if( mouse_captor )
00889         {
00890                 S32 local_x;
00891                 S32 local_y;
00892                 mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
00893                 if (LLView::sDebugMouseHandling)
00894                 {
00895                         llinfos << "Left Mouse Up handled by captor " << mouse_captor->getName() << llendl;
00896                 }
00897 
00898                 return mouse_captor->handleMouseUp(local_x, local_y, mask);
00899         }
00900 
00901         LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
00902         if (top_ctrl)
00903         {
00904                 S32 local_x, local_y;
00905                 top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
00906                 handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleMouseUp(local_x, local_y, mask);
00907         }
00908 
00909         if( !handled )
00910         {
00911                 handled = mRootView->handleMouseUp(x, y, mask);
00912         }
00913 
00914         if (LLView::sDebugMouseHandling)
00915         {
00916                 if (handled)
00917                 {
00918                         llinfos << "Left Mouse Up" << LLView::sMouseHandlerMessage << llendl;
00919                 }
00920                 else 
00921                 {
00922                         llinfos << "Left Mouse Up not handled by view" << llendl;
00923                 }
00924         }
00925 
00926         if( !handled )
00927         {
00928                 if (tool)
00929                 {
00930                         handled = tool->handleMouseUp(x, y, mask);
00931                 }
00932         }
00933 
00934         // Always handled as far as the OS is concerned.
00935         return TRUE;
00936 }
00937 
00938 
00939 BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
00940 {
00941         S32 x = pos.mX;
00942         S32 y = pos.mY;
00943         x = llround((F32)x / mDisplayScale.mV[VX]);
00944         y = llround((F32)y / mDisplayScale.mV[VY]);
00945 
00946         LLView::sMouseHandlerMessage = "";
00947 
00948         if (gDebugClicks)
00949         {
00950                 llinfos << "ViewerWindow right mouse down at " << x << "," << y << llendl;
00951         }
00952 
00953         if (gMenuBarView)
00954         {
00955                 // stop ALT-key access to menu
00956                 gMenuBarView->resetMenuTrigger();
00957         }
00958 
00959         mRightMouseDown = TRUE;
00960 
00961         // Make sure we get a coresponding mouseup event, even if the mouse leaves the window
00962         mWindow->captureMouse();
00963 
00964         // Hide tooltips
00965         if( mToolTip )
00966         {
00967                 mToolTip->setVisible( FALSE );
00968         }
00969 
00970         // Also hide hover info on mousedown
00971         if (gHoverView)
00972         {
00973                 gHoverView->cancelHover();
00974         }
00975 
00976         // Don't let the user move the mouse out of the window until mouse up.
00977         if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() )
00978         {
00979                 mWindow->setMouseClipping(TRUE);
00980         }
00981 
00982         LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
00983         if( mouse_captor )
00984         {
00985                 S32 local_x;
00986                 S32 local_y;
00987                 mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
00988                 if (LLView::sDebugMouseHandling)
00989                 {
00990                         llinfos << "Right Mouse Down handled by captor " << mouse_captor->getName() << llendl;
00991                 }
00992                 return mouse_captor->handleRightMouseDown(local_x, local_y, mask);
00993         }
00994 
00995         LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
00996         if (top_ctrl)
00997         {
00998                 S32 local_x, local_y;
00999                 top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
01000                 if (top_ctrl->pointInView(local_x, local_y))
01001                 {
01002                         return top_ctrl->handleRightMouseDown(local_x, local_y, mask);
01003                 }
01004                 else
01005                 {
01006                         setTopCtrl(NULL);
01007                 }
01008         }
01009 
01010         if( mRootView->handleRightMouseDown(x, y, mask) )
01011         {
01012                 if (LLView::sDebugMouseHandling)
01013                 {
01014                         llinfos << "Right Mouse Down" << LLView::sMouseHandlerMessage << llendl;
01015                 }
01016                 return TRUE;
01017         }
01018         else if (LLView::sDebugMouseHandling)
01019         {
01020                 llinfos << "Right Mouse Down not handled by view" << llendl;
01021         }
01022 
01023         if(LLToolMgr::getInstance()->getCurrentTool()->handleRightMouseDown( x, y, mask ) )
01024         {
01025                 // This is necessary to force clicks in the world to cause edit
01026                 // boxes that might have keyboard focus to relinquish it, and hence
01027                 // cause a commit to update their value.  JC
01028                 gFocusMgr.setKeyboardFocus(NULL);
01029                 return TRUE;
01030         }
01031 
01032         // *HACK: this should be rolled into the composite tool logic, not
01033         // hardcoded at the top level.
01034         if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode())
01035         {
01036                 // If the current tool didn't process the click, we should show
01037                 // the pie menu.  This can be done by passing the event to the pie
01038                 // menu tool.
01039                 LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
01040                 // show_context_menu( x, y, mask );
01041         }
01042 
01043         return TRUE;
01044 }
01045 
01046 BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
01047 {
01048         S32 x = pos.mX;
01049         S32 y = pos.mY;
01050         x = llround((F32)x / mDisplayScale.mV[VX]);
01051         y = llround((F32)y / mDisplayScale.mV[VY]);
01052 
01053         LLView::sMouseHandlerMessage = "";
01054 
01055         // Don't care about caps lock for mouse events.
01056         if (gDebugClicks)
01057         {
01058                 llinfos << "ViewerWindow right mouse up" << llendl;
01059         }
01060 
01061         mRightMouseDown = FALSE;
01062 
01063         // Indicate mouse was active
01064         gMouseIdleTimer.reset();
01065 
01066         // Hide tooltips on mouseup
01067         if( mToolTip )
01068         {
01069                 mToolTip->setVisible( FALSE );
01070         }
01071 
01072         // Also hide hover info on mouseup
01073         if (gHoverView) gHoverView->cancelHover();
01074 
01075         BOOL handled = FALSE;
01076 
01077         mWindow->releaseMouse();
01078 
01079         LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
01080 
01081         if( tool->clipMouseWhenDown() )
01082         {
01083                 mWindow->setMouseClipping(FALSE);
01084         }
01085 
01086         LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
01087         if( mouse_captor )
01088         {
01089                 S32 local_x;
01090                 S32 local_y;
01091                 mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
01092                 if (LLView::sDebugMouseHandling)
01093                 {
01094                         llinfos << "Right Mouse Up handled by captor " << mouse_captor->getName() << llendl;
01095                 }
01096                 return mouse_captor->handleRightMouseUp(local_x, local_y, mask);
01097         }
01098 
01099         LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
01100         if (top_ctrl)
01101         {
01102                 S32 local_x, local_y;
01103                 top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
01104                 handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleRightMouseUp(local_x, local_y, mask);
01105         }
01106 
01107         if( !handled )
01108         {
01109                 handled = mRootView->handleRightMouseUp(x, y, mask);
01110         }
01111 
01112         if (LLView::sDebugMouseHandling)
01113         {
01114                 if (handled)
01115                 {
01116                         llinfos << "Right Mouse Up" << LLView::sMouseHandlerMessage << llendl;
01117                 }
01118                 else 
01119                 {
01120                         llinfos << "Right Mouse Up not handled by view" << llendl;
01121                 }
01122         }
01123 
01124         if( !handled )
01125         {
01126                 if (tool)
01127                 {
01128                         handled = tool->handleRightMouseUp(x, y, mask);
01129                 }
01130         }
01131 
01132         // Always handled as far as the OS is concerned.
01133         return TRUE;
01134 }
01135 
01136 BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
01137 {
01138         gVoiceClient->middleMouseState(true);
01139 
01140         // Always handled as far as the OS is concerned.
01141         return TRUE;
01142 }
01143 
01144 BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
01145 {
01146         gVoiceClient->middleMouseState(false);
01147 
01148         // Always handled as far as the OS is concerned.
01149         return TRUE;
01150 }
01151 
01152 void LLViewerWindow::handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask)
01153 {
01154         S32 x = pos.mX;
01155         S32 y = pos.mY;
01156 
01157         x = llround((F32)x / mDisplayScale.mV[VX]);
01158         y = llround((F32)y / mDisplayScale.mV[VY]);
01159 
01160         mMouseInWindow = TRUE;
01161 
01162         // Save mouse point for access during idle() and display()
01163 
01164         LLCoordGL prev_saved_mouse_point = mCurrentMousePoint;
01165         LLCoordGL mouse_point(x, y);
01166         saveLastMouse(mouse_point);
01167         BOOL mouse_actually_moved = !gFocusMgr.getMouseCapture() &&  // mouse is not currenty captured
01168                         ((prev_saved_mouse_point.mX != mCurrentMousePoint.mX) || (prev_saved_mouse_point.mY != mCurrentMousePoint.mY)); // mouse moved from last recorded position
01169 
01170         gMouseIdleTimer.reset();
01171 
01172         mWindow->showCursorFromMouseMove();
01173 
01174         if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
01175         {
01176                 gAgent.clearAFK();
01177         }
01178 
01179         if(mToolTip && mouse_actually_moved)
01180         {
01181                 mToolTipBlocked = FALSE;  // Blocking starts on keyboard events and (only) ends here.
01182                 if( mToolTip->getVisible() && !mToolTipStickyRect.pointInRect( x, y ) )
01183                 {
01184                         mToolTip->setVisible( FALSE );
01185                 }
01186         }
01187 
01188         // Activate the hover picker on mouse move.
01189         if (gHoverView)
01190         {
01191                 gHoverView->setTyping(FALSE);
01192         }
01193 }
01194 
01195 void LLViewerWindow::handleMouseLeave(LLWindow *window)
01196 {
01197         // Note: we won't get this if we have captured the mouse.
01198         llassert( gFocusMgr.getMouseCapture() == NULL );
01199         mMouseInWindow = FALSE;
01200         if (mToolTip)
01201         {
01202                 mToolTip->setVisible( FALSE );
01203         }
01204 }
01205 
01206 BOOL LLViewerWindow::handleCloseRequest(LLWindow *window)
01207 {
01208         // User has indicated they want to close, but we may need to ask
01209         // about modified documents.
01210         LLAppViewer::instance()->userQuit();
01211         // Don't quit immediately
01212         return FALSE;
01213 }
01214 
01215 void LLViewerWindow::handleQuit(LLWindow *window)
01216 {
01217         LLAppViewer::instance()->forceQuit();
01218 }
01219 
01220 void LLViewerWindow::handleResize(LLWindow *window,  S32 width,  S32 height)
01221 {
01222         reshape(width, height);
01223 }
01224 
01225 // The top-level window has gained focus (e.g. via ALT-TAB)
01226 void LLViewerWindow::handleFocus(LLWindow *window)
01227 {
01228         gFocusMgr.setAppHasFocus(TRUE);
01229         LLModalDialog::onAppFocusGained();
01230 
01231         gAgent.onAppFocusGained();
01232         LLToolMgr::getInstance()->onAppFocusGained();
01233 
01234         gShowTextEditCursor = TRUE;
01235 
01236         // See if we're coming in with modifier keys held down
01237         if (gKeyboard)
01238         {
01239                 gKeyboard->resetMaskKeys();
01240         }
01241 
01242         // resume foreground running timer
01243         // since we artifically limit framerate when not frontmost
01244         gForegroundTime.unpause();
01245 }
01246 
01247 // The top-level window has lost focus (e.g. via ALT-TAB)
01248 void LLViewerWindow::handleFocusLost(LLWindow *window)
01249 {
01250         gFocusMgr.setAppHasFocus(FALSE);
01251         //LLModalDialog::onAppFocusLost();
01252         LLToolMgr::getInstance()->onAppFocusLost();
01253         gFocusMgr.setMouseCapture( NULL );
01254 
01255         if (gMenuBarView)
01256         {
01257                 // stop ALT-key access to menu
01258                 gMenuBarView->resetMenuTrigger();
01259         }
01260 
01261         // restore mouse cursor
01262         showCursor();
01263         getWindow()->setMouseClipping(FALSE);
01264 
01265         // JC - Leave keyboard focus, so if you're popping in and out editing
01266         // a script, you don't have to click in the editor again and again.
01267         // gFocusMgr.setKeyboardFocus( NULL );
01268         gShowTextEditCursor = FALSE;
01269 
01270         // If losing focus while keys are down, reset them.
01271         if (gKeyboard)
01272         {
01273                 gKeyboard->resetKeys();
01274         }
01275 
01276         // pause timer that tracks total foreground running time
01277         gForegroundTime.pause();
01278 }
01279 
01280 
01281 BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key,  MASK mask, BOOL repeated)
01282 {
01283         // Let the voice chat code check for its PTT key.  Note that this never affects event processing.
01284         gVoiceClient->keyDown(key, mask);
01285         
01286         if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
01287         {
01288                 gAgent.clearAFK();
01289         }
01290 
01291         // *NOTE: We want to interpret KEY_RETURN later when it arrives as
01292         // a Unicode char, not as a keydown.  Otherwise when client frame
01293         // rate is really low, hitting return sends your chat text before
01294         // it's all entered/processed.
01295         if (key == KEY_RETURN && mask == MASK_NONE)
01296         {
01297                 return FALSE;
01298         }
01299 
01300         return gViewerKeyboard.handleKey(key, mask, repeated);
01301 }
01302 
01303 BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)
01304 {
01305         // Let the voice chat code check for its PTT key.  Note that this never affects event processing.
01306         gVoiceClient->keyUp(key, mask);
01307 
01308         return FALSE;
01309 }
01310 
01311 
01312 void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
01313 {
01314         LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
01315         return gViewerKeyboard.scanKey(key, key_down, key_up, key_level);
01316 }
01317 
01318 
01319 
01320 
01321 BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated)
01322 {
01323         if (activated)
01324         {
01325                 mActive = TRUE;
01326                 send_agent_resume();
01327                 gAgent.clearAFK();
01328                 if (mWindow->getFullscreen() && !mIgnoreActivate)
01329                 {
01330                         if (!LLApp::isExiting() )
01331                         {
01332                                 if (LLStartUp::getStartupState() >= STATE_STARTED)
01333                                 {
01334                                         // if we're in world, show a progress bar to hide reloading of textures
01335                                         llinfos << "Restoring GL during activate" << llendl;
01336                                         restoreGL("Restoring...");
01337                                 }
01338                                 else
01339                                 {
01340                                         // otherwise restore immediately
01341                                         restoreGL();
01342                                 }
01343                         }
01344                         else
01345                         {
01346                                 llwarns << "Activating while quitting" << llendl;
01347                         }
01348                 }
01349 
01350                 // Unmute audio
01351                 audio_update_volume();
01352         }
01353         else
01354         {
01355                 mActive = FALSE;
01356                 if (gAllowIdleAFK)
01357                 {
01358                         gAgent.setAFK();
01359                 }
01360                 
01361                 // SL-53351: Make sure we're not in mouselook when minimised, to prevent control issues
01362                 gAgent.changeCameraToDefault();
01363                 
01364                 send_agent_pause();
01365                 
01366                 if (mWindow->getFullscreen() && !mIgnoreActivate)
01367                 {
01368                         llinfos << "Stopping GL during deactivation" << llendl;
01369                         stopGL();
01370                 }
01371                 // Mute audio
01372                 audio_update_volume();
01373         }
01374         return TRUE;
01375 }
01376 
01377 BOOL LLViewerWindow::handleActivateApp(LLWindow *window, BOOL activating)
01378 {
01379         LLViewerJoystick::getInstance()->setNeedsReset(true);
01380         return FALSE;
01381 }
01382 
01383 
01384 void LLViewerWindow::handleMenuSelect(LLWindow *window,  S32 menu_item)
01385 {
01386 }
01387 
01388 
01389 BOOL LLViewerWindow::handlePaint(LLWindow *window,  S32 x,  S32 y, S32 width,  S32 height)
01390 {
01391 #if LL_WINDOWS
01392         if (gNoRender)
01393         {
01394                 HWND window_handle = (HWND)window->getPlatformWindow();
01395                 PAINTSTRUCT ps; 
01396                 HDC hdc; 
01397  
01398                 RECT wnd_rect;
01399                 wnd_rect.left = 0;
01400                 wnd_rect.top = 0;
01401                 wnd_rect.bottom = 200;
01402                 wnd_rect.right = 500;
01403 
01404                 hdc = BeginPaint(window_handle, &ps); 
01405                 //SetBKColor(hdc, RGB(255, 255, 255));
01406                 FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255)));
01407 
01408                 LLString name_str;
01409                 gAgent.getName(name_str);
01410 
01411                 S32 len;
01412                 char temp_str[255];             /* Flawfinder: ignore */
01413                 snprintf(temp_str, sizeof(temp_str), "%s FPS %3.1f Phy FPS %2.1f Time Dil %1.3f",               /* Flawfinder: ignore */
01414                                 name_str.c_str(),
01415                                 LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(),
01416                                 LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0),
01417                                 LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0));
01418                 len = strlen(temp_str);         /* Flawfinder: ignore */
01419                 TextOutA(hdc, 0, 0, temp_str, len); 
01420 
01421 
01422                 LLVector3d pos_global = gAgent.getPositionGlobal();
01423                 snprintf(temp_str, sizeof(temp_str), "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]);               /* Flawfinder: ignore */
01424                 len = strlen(temp_str);         /* Flawfinder: ignore */
01425                 TextOutA(hdc, 0, 25, temp_str, len); 
01426 
01427                 TextOutA(hdc, 0, 50, "Set \"DisableRendering FALSE\" in settings.ini file to reenable", 61);
01428                 EndPaint(window_handle, &ps); 
01429                 return TRUE;
01430         }
01431 #endif
01432         return FALSE;
01433 }
01434 
01435 
01436 void LLViewerWindow::handleScrollWheel(LLWindow *window,  S32 clicks)
01437 {
01438         handleScrollWheel( clicks );
01439 }
01440 
01441 void LLViewerWindow::handleWindowBlock(LLWindow *window)
01442 {
01443         send_agent_pause();
01444 }
01445 
01446 void LLViewerWindow::handleWindowUnblock(LLWindow *window)
01447 {
01448         send_agent_resume();
01449 }
01450 
01451 void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data)
01452 {
01453         const S32 SLURL_MESSAGE_TYPE = 0;
01454         switch (data_type)
01455         {
01456         case SLURL_MESSAGE_TYPE:
01457                 // received URL
01458                 std::string url = (const char*)data;
01459                 const bool from_external_browser = true;
01460                 if (LLURLDispatcher::dispatch(url, from_external_browser))
01461                 {
01462                         // bring window to foreground, as it has just been "launched" from a URL
01463                         mWindow->bringToFront();
01464                 }
01465                 break;
01466         }
01467 }
01468 
01469 BOOL LLViewerWindow::handleTimerEvent(LLWindow *window)
01470 {
01471         if (LLViewerJoystick::getInstance()->getOverrideCamera())
01472         {
01473                 LLViewerJoystick::getInstance()->updateStatus();
01474                 return TRUE;
01475         }
01476         return FALSE;
01477 }
01478 
01479 BOOL LLViewerWindow::handleDeviceChange(LLWindow *window)
01480 {
01481         // give a chance to use a joystick after startup (hot-plugging)
01482         if (!LLViewerJoystick::getInstance()->isJoystickInitialized() )
01483         {
01484                 LLViewerJoystick::getInstance()->init(true);
01485                 return TRUE;
01486         }
01487         return FALSE;
01488 }
01489 
01490 //
01491 // Classes
01492 //
01493 LLViewerWindow::LLViewerWindow(
01494         char* title, char* name,
01495         S32 x, S32 y,
01496         S32 width, S32 height,
01497         BOOL fullscreen, BOOL ignore_pixel_depth)
01498         :
01499         mActive(TRUE),
01500         mWantFullscreen(fullscreen),
01501         mShowFullscreenProgress(FALSE),
01502         mWindowRect(0, height, width, 0),
01503         mVirtualWindowRect(0, height, width, 0),
01504         mLeftMouseDown(FALSE),
01505         mRightMouseDown(FALSE),
01506         mToolTip(NULL),
01507         mToolTipBlocked(FALSE),
01508         mMouseInWindow( FALSE ),
01509         mLastMask( MASK_NONE ),
01510         mToolStored( NULL ),
01511         mSuppressToolbox( FALSE ),
01512         mHideCursorPermanent( FALSE ),
01513         mPickPending(FALSE),
01514         mIgnoreActivate( FALSE )
01515 {
01516         // Default to application directory.
01517         strcpy(LLViewerWindow::sSnapshotBaseName, "Snapshot");  /* Flawfinder: ignore */
01518         strcpy(LLViewerWindow::sMovieBaseName, "SLmovie");      /* Flawfinder: ignore */
01519         LLViewerWindow::sSnapshotDir[0] = '\0';
01520 
01521 
01522         // create window
01523         mWindow = LLWindowManager::createWindow(
01524                 title, name, x, y, width, height, 0,
01525                 fullscreen, 
01526                 gNoRender,
01527                 gSavedSettings.getBOOL("DisableVerticalSync"),
01528                 !gNoRender,
01529                 ignore_pixel_depth,
01530                 gSavedSettings.getU32("RenderFSAASamples"));
01531 #if LL_WINDOWS
01532         if (!LLWinDebug::checkExceptionHandler())
01533         {
01534                 LL_WARNS("Window") << " Someone took over my exception handler (post createWindow)!" << LL_ENDL;
01535         }
01536 #endif
01537 
01538         if (NULL == mWindow)
01539         {
01540                 LLSplashScreen::update("Shutting down...");
01541 #if LL_LINUX || LL_SOLARIS
01542                 llwarns << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly.  See README-linux.txt or README-solaris.txt for further information."
01543                                 << llendl;
01544 #else
01545                 LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings"
01546                                 << LL_ENDL;
01547 #endif
01548         LLAppViewer::instance()->forceExit(1);
01549         }
01550         
01551         // Get the real window rect the window was created with (since there are various OS-dependent reasons why
01552         // the size of a window or fullscreen context may have been adjusted slightly...)
01553         F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
01554         
01555         mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
01556         mDisplayScale *= ui_scale_factor;
01557         LLUI::setScaleFactor(mDisplayScale);
01558 
01559         {
01560                 LLCoordWindow size;
01561                 mWindow->getSize(&size);
01562                 mWindowRect.set(0, size.mY, size.mX, 0);
01563                 mVirtualWindowRect.set(0, llround((F32)size.mY / mDisplayScale.mV[VY]), llround((F32)size.mX / mDisplayScale.mV[VX]), 0);
01564         }
01565         
01566         LLFontManager::initClass();
01567 
01568         //
01569         // We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off
01570         // stuff like AGP if we think that it'll crash the viewer.
01571         //
01572         LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL;
01573 
01574         LLFeatureManager::getInstance()->init();
01575 
01576         // Initialize OpenGL Renderer
01577         if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
01578                 !gGLManager.mHasVertexBufferObject)
01579         {
01580                 gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
01581         }
01582         LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"));
01583 
01584         if (LLFeatureManager::getInstance()->isSafe()
01585                 || (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion())
01586                 || (gSavedSettings.getBOOL("ProbeHardwareOnStartup")))
01587         {
01588                 LLFeatureManager::getInstance()->applyRecommendedSettings();
01589                 gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
01590         }
01591 
01592         // If we crashed while initializng GL stuff last time, disable certain features
01593         if (gSavedSettings.getBOOL("RenderInitError"))
01594         {
01595                 mInitAlert = "DisplaySettingsNoShaders";
01596                 LLFeatureManager::getInstance()->setGraphicsLevel(0, false);
01597                 gSavedSettings.setU32("RenderQualityPerformance", 0);           
01598                 
01599         }
01600                 
01601         // set callbacks
01602         mWindow->setCallbacks(this);
01603 
01604         // Init the image list.  Must happen after GL is initialized and before the images that
01605         // LLViewerWindow needs are requested.
01606         gImageList.init();
01607         LLViewerImage::initClass();
01608         gBumpImageList.init();
01609 
01610         // Create container for all sub-views
01611         mRootView = new LLRootView("root", mVirtualWindowRect, FALSE);
01612 
01613         if (!gNoRender)
01614         {
01615                 // Init default fonts
01616                 initFonts();
01617         }
01618 
01619         // Make avatar head look forward at start
01620         mCurrentMousePoint.mX = getWindowWidth() / 2;
01621         mCurrentMousePoint.mY = getWindowHeight() / 2;
01622 
01623         mPickBuffer = new U8[PICK_DIAMETER * PICK_DIAMETER * 4];
01624 
01625         gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle");
01626         mOverlayTitle = gSavedSettings.getString("OverlayTitle");
01627         // Can't have spaces in settings.ini strings, so use underscores instead and convert them.
01628         LLString::replaceChar(mOverlayTitle, '_', ' ');
01629 
01630         LLAlertDialog::setDisplayCallback(alertCallback); // call this before calling any modal dialogs
01631 
01632         // sync the keyboard's setting with the saved setting
01633         gSavedSettings.getControl("NumpadControl")->firePropertyChanged();
01634 
01635         mDebugText = new LLDebugText(this);
01636 
01637 }
01638 
01639 void LLViewerWindow::initGLDefaults()
01640 {
01641         gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01642         glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
01643 
01644         F32 ambient[4] = {0.f,0.f,0.f,0.f };
01645         F32 diffuse[4] = {1.f,1.f,1.f,1.f };
01646         glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambient);
01647         glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,diffuse);
01648         
01649         glPixelStorei(GL_PACK_ALIGNMENT,1);
01650         glPixelStorei(GL_UNPACK_ALIGNMENT,1);
01651 
01652         glEnable(GL_TEXTURE_2D);
01653 
01654         // lights for objects
01655         glShadeModel( GL_SMOOTH );
01656 
01657         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
01658         
01659         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
01660 
01661         glCullFace(GL_BACK);
01662 
01663         // RN: Need this for translation and stretch manip.
01664         gCone.prerender();
01665         gBox.prerender();
01666         gSphere.prerender();
01667         gCylinder.prerender();
01668 }
01669 
01670 void LLViewerWindow::initBase()
01671 {
01672         S32 height = getWindowHeight();
01673         S32 width = getWindowWidth();
01674 
01675         LLRect full_window(0, height, width, 0);
01676 
01677         adjustRectanglesForFirstUse(full_window);
01678 
01680         //
01681         // Set the gamma
01682         //
01683 
01684         F32 gamma = gSavedSettings.getF32("RenderGamma");
01685         if (gamma != 0.0f)
01686         {
01687                 getWindow()->setGamma(gamma);
01688         }
01689 
01690         // Create global views
01691 
01692         // Create the floater view at the start so that other views can add children to it. 
01693         // (But wait to add it as a child of the root view so that it will be in front of the 
01694         // other views.)
01695 
01696         // Constrain floaters to inside the menu and status bar regions.
01697         LLRect floater_view_rect = full_window;
01698         // make space for menu bar if we have one
01699         floater_view_rect.mTop -= MENU_BAR_HEIGHT;
01700         floater_view_rect.mBottom += STATUS_BAR_HEIGHT + 12 + 16 + 2;
01701 
01702         // Check for non-first startup
01703         S32 floater_view_bottom = gSavedSettings.getS32("FloaterViewBottom");
01704         if (floater_view_bottom >= 0)
01705         {
01706                 floater_view_rect.mBottom = floater_view_bottom;
01707         }
01708         gFloaterView = new LLFloaterView("Floater View", floater_view_rect );
01709         gFloaterView->setVisible(TRUE);
01710 
01711         gSnapshotFloaterView = new LLSnapshotFloaterView("Snapshot Floater View", full_window);
01712         gSnapshotFloaterView->setVisible(TRUE);
01713 
01714         // Console
01715         llassert( !gConsole );
01716         LLRect console_rect = full_window;
01717         console_rect.mTop    -= 24;
01718         console_rect.mBottom += STATUS_BAR_HEIGHT + 12 + 16 + 12;
01719         console_rect.mLeft   += 24; //gSavedSettings.getS32("StatusBarButtonWidth") + gSavedSettings.getS32("StatusBarPad");
01720 
01721         if (gSavedSettings.getBOOL("ChatFullWidth"))
01722         {
01723                 console_rect.mRight -= 10;
01724         }
01725         else
01726         {
01727                 // Make console rect somewhat narrow so having inventory open is
01728                 // less of a problem.
01729                 console_rect.mRight  = console_rect.mLeft + 2 * width / 3;
01730         }
01731 
01732         gConsole = new LLConsole(
01733                 "console",
01734                 gSavedSettings.getS32("ConsoleBufferSize"),
01735                 console_rect,
01736                 gSavedSettings.getS32("ChatFontSize"),
01737                 gSavedSettings.getF32("ChatPersistTime") );
01738         gConsole->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
01739         mRootView->addChild(gConsole);
01740 
01741         // Debug view over the console
01742         gDebugView = new LLDebugView("gDebugView", full_window);
01743         gDebugView->setFollowsAll();
01744         gDebugView->setVisible(TRUE);
01745         mRootView->addChild(gDebugView);
01746 
01747         // Add floater view at the end so it will be on top, and give it tab priority over others
01748         mRootView->addChild(gFloaterView, -1);
01749         mRootView->addChild(gSnapshotFloaterView);
01750 
01751         // notify above floaters!
01752         LLRect notify_rect = full_window;
01753         //notify_rect.mTop -= 24;
01754         notify_rect.mBottom += STATUS_BAR_HEIGHT;
01755         gNotifyBoxView = new LLNotifyBoxView("notify_container", notify_rect, FALSE, FOLLOWS_ALL);
01756         mRootView->addChild(gNotifyBoxView, -2);
01757 
01758         // Tooltips go above floaters
01759         mToolTip = new LLTextBox( "tool tip", LLRect(0, 1, 1, 0 ) );
01760         mToolTip->setHPad( 4 );
01761         mToolTip->setVPad( 2 );
01762         mToolTip->setColor( gColors.getColor( "ToolTipTextColor" ) );
01763         mToolTip->setBorderColor( gColors.getColor( "ToolTipBorderColor" ) );
01764         mToolTip->setBorderVisible( FALSE );
01765         mToolTip->setBackgroundColor( gColors.getColor( "ToolTipBgColor" ) );
01766         mToolTip->setBackgroundVisible( TRUE );
01767         mToolTip->setFontStyle(LLFontGL::NORMAL);
01768         mToolTip->setBorderDropshadowVisible( TRUE );
01769         mToolTip->setVisible( FALSE );
01770 
01771         // Add the progress bar view (startup view), which overrides everything
01772         mProgressView = new LLProgressView("ProgressView", full_window);
01773         mRootView->addChild(mProgressView);
01774         setShowProgress(FALSE);
01775         setProgressCancelButtonVisible(FALSE, "");
01776 }
01777 
01778 
01779 void adjust_rect_top_left(const LLString& control, const LLRect& window)
01780 {
01781         LLRect r = gSavedSettings.getRect(control);
01782         if (r.mLeft == 0 && r.mBottom == 0)
01783         {
01784                 r.setLeftTopAndSize(0, window.getHeight(), r.getWidth(), r.getHeight());
01785                 gSavedSettings.setRect(control, r);
01786         }
01787 }
01788 
01789 void adjust_rect_top_center(const LLString& control, const LLRect& window)
01790 {
01791         LLRect r = gSavedSettings.getRect(control);
01792         if (r.mLeft == 0 && r.mBottom == 0)
01793         {
01794                 r.setLeftTopAndSize( window.getWidth()/2 - r.getWidth()/2,
01795                         window.getHeight(),
01796                         r.getWidth(),
01797                         r.getHeight() );
01798                 gSavedSettings.setRect(control, r);
01799         }
01800 }
01801 
01802 void adjust_rect_top_right(const LLString& control, const LLRect& window)
01803 {
01804         LLRect r = gSavedSettings.getRect(control);
01805         if (r.mLeft == 0 && r.mBottom == 0)
01806         {
01807                 r.setLeftTopAndSize(window.getWidth() - r.getWidth(),
01808                         window.getHeight(),
01809                         r.getWidth(), 
01810                         r.getHeight());
01811                 gSavedSettings.setRect(control, r);
01812         }
01813 }
01814 
01815 void adjust_rect_bottom_center(const LLString& control, const LLRect& window)
01816 {
01817         LLRect r = gSavedSettings.getRect(control);
01818         if (r.mLeft == 0 && r.mBottom == 0)
01819         {
01820                 // *TODO: Adjust based on XUI XML
01821                 const S32 TOOLBAR_HEIGHT = 64;
01822                 r.setOriginAndSize(
01823                         window.getWidth()/2 - r.getWidth()/2,
01824                         TOOLBAR_HEIGHT,
01825                         r.getWidth(),
01826                         r.getHeight());
01827                 gSavedSettings.setRect(control, r);
01828         }
01829 }
01830 
01831 void adjust_rect_centered_partial_zoom(const LLString& control,
01832                                                                            const LLRect& window)
01833 {
01834         LLRect rect = gSavedSettings.getRect(control);
01835         // Only adjust on first use
01836         if (rect.mLeft == 0 && rect.mBottom == 0)
01837         {
01838                 S32 width = window.getWidth();
01839                 S32 height = window.getHeight();
01840                 rect.set(0, height-STATUS_BAR_HEIGHT, width, TOOL_BAR_HEIGHT);
01841                 // Make floater fill 80% of window, leaving 20% padding on
01842                 // the sides.
01843                 const F32 ZOOM_FRACTION = 0.8f;
01844                 S32 dx = (S32)(width * (1.f - ZOOM_FRACTION));
01845                 S32 dy = (S32)(height * (1.f - ZOOM_FRACTION));
01846                 rect.stretch(-dx/2, -dy/2);
01847                 gSavedSettings.setRect(control, rect);
01848         }
01849 }
01850 
01851 
01852 // Many rectangles can't be placed until we know the screen size.
01853 // These rectangles have their bottom-left corner as 0,0
01854 void LLViewerWindow::adjustRectanglesForFirstUse(const LLRect& window)
01855 {
01856         LLRect r;
01857 
01858         adjust_rect_bottom_center("FloaterMoveRect2", window);
01859 
01860         adjust_rect_top_center("FloaterCameraRect3", window);
01861 
01862         adjust_rect_top_left("FloaterCustomizeAppearanceRect", window);
01863 
01864         adjust_rect_top_left("FloaterLandRect5", window);
01865 
01866         adjust_rect_top_left("FloaterHUDRect", window);
01867 
01868         adjust_rect_top_left("FloaterFindRect2", window);
01869 
01870         adjust_rect_top_left("FloaterGestureRect2", window);
01871 
01872         adjust_rect_top_right("FloaterMiniMapRect", window);
01873         
01874         adjust_rect_top_right("FloaterLagMeter", window);
01875 
01876         adjust_rect_top_left("FloaterBuildOptionsRect", window);
01877 
01878         // bottom-right
01879         r = gSavedSettings.getRect("FloaterInventoryRect");
01880         if (r.mLeft == 0 && r.mBottom == 0)
01881         {
01882                 r.setOriginAndSize(
01883                         window.getWidth() - r.getWidth(),
01884                         0,
01885                         r.getWidth(),
01886                         r.getHeight());
01887                 gSavedSettings.setRect("FloaterInventoryRect", r);
01888         }
01889 }
01890 
01891 
01892 void LLViewerWindow::initWorldUI()
01893 {
01894         pre_init_menus();
01895 
01896         S32 height = mRootView->getRect().getHeight();
01897         S32 width = mRootView->getRect().getWidth();
01898         LLRect full_window(0, height, width, 0);
01899 
01900         if ( gBottomPanel == NULL )                     // Don't re-enter if objects are alreay created
01901         {
01902                 // panel containing chatbar, toolbar, and overlay, over floaters
01903                 gBottomPanel = new LLBottomPanel(mRootView->getRect());
01904                 mRootView->addChild(gBottomPanel);
01905 
01906                 // View for hover information
01907                 gHoverView = new LLHoverView("gHoverView", full_window);
01908                 gHoverView->setVisible(TRUE);
01909                 mRootView->addChild(gHoverView);
01910 
01911                 //
01912                 // Map
01913                 //
01914                 // TODO: Move instance management into class
01915                 gFloaterMap = new LLFloaterMap("Map");
01916                 gFloaterMap->setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT);
01917 
01918                 // keep onscreen
01919                 gFloaterView->adjustToFitScreen(gFloaterMap, FALSE);
01920                 
01921                 gIMMgr = LLIMMgr::getInstance();
01922 
01923                 if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
01924                 {
01925                         LLFloaterChat::getInstance(LLSD())->loadHistory();
01926                 }
01927 
01928                 LLRect morph_view_rect = full_window;
01929                 morph_view_rect.stretch( -STATUS_BAR_HEIGHT );
01930                 morph_view_rect.mTop = full_window.mTop - 32;
01931                 gMorphView = new LLMorphView("gMorphView", morph_view_rect );
01932                 mRootView->addChild(gMorphView);
01933                 gMorphView->setVisible(FALSE);
01934 
01935                 // *Note: this is where gFloaterMute used to be initialized.
01936 
01937                 LLWorldMapView::initClass();
01938 
01939                 adjust_rect_centered_partial_zoom("FloaterWorldMapRect2", full_window);
01940 
01941                 gFloaterWorldMap = new LLFloaterWorldMap();
01942                 gFloaterWorldMap->setVisible(FALSE);
01943 
01944                 //
01945                 // Tools for building
01946                 //
01947 
01948                 // Toolbox floater
01949                 init_menus();
01950 
01951                 gFloaterTools = new LLFloaterTools();
01952                 gFloaterTools->setVisible(FALSE);
01953 
01954                 // Status bar
01955                 S32 menu_bar_height = gMenuBarView->getRect().getHeight();
01956                 LLRect root_rect = getRootView()->getRect();
01957                 LLRect status_rect(0, root_rect.getHeight(), root_rect.getWidth(), root_rect.getHeight() - menu_bar_height);
01958                 gStatusBar = new LLStatusBar("status", status_rect);
01959                 gStatusBar->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP);
01960 
01961                 gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE);
01962                 gStatusBar->translate(0, root_rect.getHeight() - gStatusBar->getRect().getHeight());
01963                 // sync bg color with menu bar
01964                 gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor() );
01965 
01966                 LLFloaterChatterBox::createInstance(LLSD());
01967 
01968                 getRootView()->addChild(gStatusBar);
01969 
01970                 // menu holder appears on top to get first pass at all mouse events
01971                 getRootView()->sendChildToFront(gMenuHolder);
01972         }
01973 }
01974 
01975 
01976 LLViewerWindow::~LLViewerWindow()
01977 {
01978         delete mDebugText;
01979         
01980         gSavedSettings.setS32("FloaterViewBottom", gFloaterView->getRect().mBottom);
01981 
01982         // Cleanup global views
01983         if (gMorphView)
01984         {
01985                 gMorphView->setVisible(FALSE);
01986         }
01987         
01988         // Delete all child views.
01989         delete mRootView;
01990         mRootView = NULL;
01991 
01992         // Automatically deleted as children of mRootView.  Fix the globals.
01993         gFloaterTools = NULL;
01994         gStatusBar = NULL;
01995         gIMMgr = NULL;
01996         gHoverView = NULL;
01997 
01998         gFloaterView            = NULL;
01999         gMorphView                      = NULL;
02000 
02001         gFloaterMap     = NULL;
02002         gHUDView = NULL;
02003 
02004         gNotifyBoxView = NULL;
02005 
02006         delete mToolTip;
02007         mToolTip = NULL;
02008         
02009         //--------------------------------------------------------
02010         // Shutdown GL cleanly.  Order is very important here.
02011         //--------------------------------------------------------
02012         LLFontGL::destroyDefaultFonts();
02013         LLFontManager::cleanupClass();
02014         stop_glerror();
02015 
02016         gSky.cleanup();
02017         stop_glerror();
02018 
02019         gImageList.shutdown();
02020         stop_glerror();
02021 
02022         gBumpImageList.shutdown();
02023         stop_glerror();
02024 
02025         LLWorldMapView::cleanupTextures();
02026 
02027         llinfos << "Cleaning up pipeline" << llendl;
02028         gPipeline.cleanup();
02029         stop_glerror();
02030 
02031         LLViewerImage::cleanupClass();
02032         
02033         delete[] mPickBuffer;
02034         mPickBuffer = NULL;
02035 
02036         llinfos << "Cleaning up select manager" << llendl;
02037         LLSelectMgr::getInstance()->cleanup();
02038 
02039         LLVertexBuffer::cleanupClass();
02040 
02041         llinfos << "Stopping GL during shutdown" << llendl;
02042         if (!gNoRender)
02043         {
02044                 stopGL(FALSE);
02045                 stop_glerror();
02046         }
02047 
02048 
02049         llinfos << "Destroying Window" << llendl;
02050         destroyWindow();
02051 }
02052 
02053 
02054 void LLViewerWindow::setCursor( ECursorType c )
02055 {
02056         mWindow->setCursor( c );
02057 }
02058 
02059 void LLViewerWindow::showCursor()
02060 {
02061         mWindow->showCursor();
02062 }
02063 
02064 void LLViewerWindow::hideCursor()
02065 {
02066         // Hide tooltips
02067         if(mToolTip ) mToolTip->setVisible( FALSE );
02068 
02069         // Also hide hover info
02070         if (gHoverView) gHoverView->cancelHover();
02071 
02072         // And hide the cursor
02073         mWindow->hideCursor();
02074 }
02075 
02076 void LLViewerWindow::sendShapeToSim()
02077 {
02078         LLMessageSystem* msg = gMessageSystem;
02079         if(!msg) return;
02080         msg->newMessageFast(_PREHASH_AgentHeightWidth);
02081         msg->nextBlockFast(_PREHASH_AgentData);
02082         msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
02083         msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
02084         msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode);
02085         msg->nextBlockFast(_PREHASH_HeightWidthBlock);
02086         msg->addU32Fast(_PREHASH_GenCounter, 0);
02087         U16 height16 = (U16) mWindowRect.getHeight();
02088         U16 width16 = (U16) mWindowRect.getWidth();
02089         msg->addU16Fast(_PREHASH_Height, height16);
02090         msg->addU16Fast(_PREHASH_Width, width16);
02091         gAgent.sendReliableMessage();
02092 }
02093 
02094 // Must be called after window is created to set up agent
02095 // camera variables and UI variables.
02096 void LLViewerWindow::reshape(S32 width, S32 height)
02097 {
02098         // Destroying the window at quit time generates spurious
02099         // reshape messages.  We don't care about these, and we
02100         // don't want to send messages because the message system
02101         // may have been destructed.
02102         if (!LLApp::isExiting())
02103         {
02104                 if (gNoRender)
02105                 {
02106                         return;
02107                 }
02108 
02109                 glViewport(0, 0, width, height );
02110 
02111                 if (height > 0)
02112                 { 
02113                         LLViewerCamera::getInstance()->setViewHeightInPixels( height );
02114                         if (mWindow->getFullscreen())
02115                         {
02116                                 // force to 4:3 aspect for odd resolutions
02117                                 LLViewerCamera::getInstance()->setAspect( getDisplayAspectRatio() );
02118                         }
02119                         else
02120                         {
02121                                 LLViewerCamera::getInstance()->setAspect( width / (F32) height);
02122                         }
02123                 }
02124 
02125                 // update our window rectangle
02126                 mWindowRect.mRight = mWindowRect.mLeft + width;
02127                 mWindowRect.mTop = mWindowRect.mBottom + height;
02128                 calcDisplayScale();
02129         
02130                 BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor;
02131                 LLUI::setScaleFactor(mDisplayScale);
02132 
02133                 // update our window rectangle
02134                 mVirtualWindowRect.mRight = mVirtualWindowRect.mLeft + llround((F32)width / mDisplayScale.mV[VX]);
02135                 mVirtualWindowRect.mTop = mVirtualWindowRect.mBottom + llround((F32)height / mDisplayScale.mV[VY]);
02136 
02137                 setupViewport();
02138 
02139                 // Inform lower views of the change
02140                 // round up when converting coordinates to make sure there are no gaps at edge of window
02141                 LLView::sForceReshape = display_scale_changed;
02142                 mRootView->reshape(llceil((F32)width / mDisplayScale.mV[VX]), llceil((F32)height / mDisplayScale.mV[VY]));
02143                 LLView::sForceReshape = FALSE;
02144 
02145                 // clear font width caches
02146                 if (display_scale_changed)
02147                 {
02148                         LLHUDText::reshape();
02149                 }
02150 
02151                 sendShapeToSim();
02152 
02153 
02154                 // store the mode the user wants (even if not there yet)
02155                 gSavedSettings.setBOOL("FullScreen", mWantFullscreen);
02156 
02157                 // store new settings for the mode we are in, regardless
02158                 if (mWindow->getFullscreen())
02159                 {
02160                         gSavedSettings.setS32("FullScreenWidth", width);
02161                         gSavedSettings.setS32("FullScreenHeight", height);
02162                 }
02163                 else
02164                 {
02165                         // Only save size if not maximized
02166                         BOOL maximized = mWindow->getMaximized();
02167                         gSavedSettings.setBOOL("WindowMaximized", maximized);
02168 
02169                         LLCoordScreen window_size;
02170                         if (!maximized
02171                                 && mWindow->getSize(&window_size))
02172                         {
02173                                 gSavedSettings.setS32("WindowWidth", window_size.mX);
02174                                 gSavedSettings.setS32("WindowHeight", window_size.mY);
02175                         }
02176                 }
02177 
02178                 LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width);
02179                 LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height);
02180                 gResizeScreenTexture = TRUE;
02181         }
02182 }
02183 
02184 
02185 // Hide normal UI when a logon fails
02186 void LLViewerWindow::setNormalControlsVisible( BOOL visible )
02187 {
02188         if ( gBottomPanel )
02189         {
02190                 gBottomPanel->setVisible( visible );
02191                 gBottomPanel->setEnabled( visible );
02192         }
02193 
02194         if ( gMenuBarView )
02195         {
02196                 gMenuBarView->setVisible( visible );
02197                 gMenuBarView->setEnabled( visible );
02198 
02199                 // ...and set the menu color appropriately.
02200                 setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, 
02201                         LLAppViewer::instance()->isInProductionGrid());
02202         }
02203         
02204         if ( gStatusBar )
02205         {
02206                 gStatusBar->setVisible( visible );      
02207                 gStatusBar->setEnabled( visible );      
02208         }
02209 }
02210 
02211 void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
02212 {
02213         LLString::format_map_t args;
02214     LLColor4 new_bg_color;
02215 
02216     if(god_mode && LLAppViewer::instance()->isInProductionGrid())
02217     {
02218         new_bg_color = gColors.getColor( "MenuBarGodBgColor" );
02219     }
02220     else if(god_mode && !LLAppViewer::instance()->isInProductionGrid())
02221     {
02222         new_bg_color = gColors.getColor( "MenuNonProductionGodBgColor" );
02223     }
02224     else if(!god_mode && !LLAppViewer::instance()->isInProductionGrid())
02225     {
02226         new_bg_color = gColors.getColor( "MenuNonProductionBgColor" );
02227     }
02228     else 
02229     {
02230         new_bg_color = gColors.getColor( "MenuBarBgColor" );
02231     }
02232 
02233     if(gMenuBarView)
02234     {
02235         gMenuBarView->setBackgroundColor( new_bg_color );
02236     }
02237 
02238     if(gStatusBar)
02239     {
02240         gStatusBar->setBackgroundColor( new_bg_color );
02241     }
02242 }
02243 
02244 void LLViewerWindow::drawDebugText()
02245 {
02246         gGL.color4f(1,1,1,1);
02247         gGL.pushMatrix();
02248         {
02249                 // scale view by UI global scale factor and aspect ratio correction factor
02250                 glScalef(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
02251                 mDebugText->draw();
02252         }
02253         gGL.popMatrix();
02254         gGL.flush();
02255 }
02256 
02257 void LLViewerWindow::draw()
02258 {
02259         
02260 #if LL_DEBUG
02261         LLView::sIsDrawing = TRUE;
02262 #endif
02263         stop_glerror();
02264         
02265         LLUI::setLineWidth(1.f);
02266         //popup alerts from the UI
02267         LLAlertInfo alert;
02268         while (LLPanel::nextAlert(alert))
02269         {
02270                 alertXml(alert.mLabel, alert.mArgs);
02271         }
02272 
02273         LLUI::setLineWidth(1.f);
02274         // Reset any left-over transforms
02275         glMatrixMode(GL_MODELVIEW);
02276         
02277         glLoadIdentity();
02278 
02279         //S32 screen_x, screen_y;
02280 
02281         // HACK for timecode debugging
02282         if (gSavedSettings.getBOOL("DisplayTimecode"))
02283         {
02284                 // draw timecode block
02285                 char text[256];         /* Flawfinder: ignore */
02286 
02287                 glLoadIdentity();
02288 
02289                 microsecondsToTimecodeString(gFrameTime,text);
02290                 const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
02291                 font->renderUTF8(text, 0,
02292                                                 llround((getWindowWidth()/2)-100.f),
02293                                                 llround((getWindowHeight()-60.f)),
02294                         LLColor4( 1.f, 1.f, 1.f, 1.f ),
02295                         LLFontGL::LEFT, LLFontGL::TOP);
02296         }
02297 
02298         // Draw all nested UI views.
02299         // No translation needed, this view is glued to 0,0
02300 
02301         gGL.pushMatrix();
02302         {
02303                 // scale view by UI global scale factor and aspect ratio correction factor
02304                 glScalef(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
02305 
02306                 LLVector2 old_scale_factor = LLUI::sGLScaleFactor;
02307                 // apply camera zoom transform (for high res screenshots)
02308                 F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
02309                 S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
02310                 if (zoom_factor > 1.f)
02311                 {
02312                         //decompose subregion number to x and y values
02313                         int pos_y = sub_region / llceil(zoom_factor);
02314                         int pos_x = sub_region - (pos_y*llceil(zoom_factor));
02315                         // offset for this tile
02316                         glTranslatef((F32)getWindowWidth() * -(F32)pos_x, 
02317                                                 (F32)getWindowHeight() * -(F32)pos_y, 
02318                                                 0.f);
02319                         glScalef(zoom_factor, zoom_factor, 1.f);
02320                         LLUI::sGLScaleFactor *= zoom_factor;
02321                 }
02322 
02323                 // Draw tool specific overlay on world
02324                 LLToolMgr::getInstance()->getCurrentTool()->draw();
02325 
02326                 if( gAgent.cameraMouselook() )
02327                 {
02328                         drawMouselookInstructions();
02329                         stop_glerror();
02330                 }
02331 
02332                 // Draw all nested UI views.
02333                 // No translation needed, this view is glued to 0,0
02334                 mRootView->draw();
02335 
02336                 // Draw optional on-top-of-everyone view
02337                 LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
02338                 if (top_ctrl && top_ctrl->getVisible())
02339                 {
02340                         S32 screen_x, screen_y;
02341                         top_ctrl->localPointToScreen(0, 0, &screen_x, &screen_y);
02342 
02343                         glMatrixMode(GL_MODELVIEW);
02344                         LLUI::pushMatrix();
02345                         LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f);
02346                         top_ctrl->draw();       
02347                         LLUI::popMatrix();
02348                 }
02349 
02350                 // Draw tooltips
02351                 // Adjust their rectangle so they don't go off the top or bottom
02352                 // of the screen.
02353                 if( mToolTip && mToolTip->getVisible() )
02354                 {
02355                         glMatrixMode(GL_MODELVIEW);
02356                         LLUI::pushMatrix();
02357                         {
02358                                 S32 tip_height = mToolTip->getRect().getHeight();
02359 
02360                                 S32 screen_x, screen_y;
02361                                 mToolTip->localPointToScreen(0, -24 - tip_height, 
02362                                                                                          &screen_x, &screen_y);
02363 
02364                                 // If tooltip would draw off the bottom of the screen,
02365                                 // show it from the cursor tip position.
02366                                 if (screen_y < tip_height) 
02367                                 {
02368                                         mToolTip->localPointToScreen(0, 0, &screen_x, &screen_y);
02369                                 }
02370                                 LLUI::translate( (F32) screen_x, (F32) screen_y, 0);
02371                                 mToolTip->draw();
02372                         }
02373                         LLUI::popMatrix();
02374                 }
02375 
02376                 if( gShowOverlayTitle && !mOverlayTitle.empty() )
02377                 {
02378                         // Used for special titles such as "Second Life - Special E3 2003 Beta"
02379                         const S32 DIST_FROM_TOP = 20;
02380                         LLFontGL::sSansSerifBig->renderUTF8(
02381                                 mOverlayTitle, 0,
02382                                 llround( getWindowWidth() * 0.5f),
02383                                 getWindowHeight() - DIST_FROM_TOP,
02384                                 LLColor4(1, 1, 1, 0.4f),
02385                                 LLFontGL::HCENTER, LLFontGL::TOP);
02386                 }
02387 
02388                 LLUI::sGLScaleFactor = old_scale_factor;
02389         }
02390         gGL.popMatrix();
02391 
02392 #if LL_DEBUG
02393         LLView::sIsDrawing = FALSE;
02394 #endif
02395 }
02396 
02397 // Takes a single keydown event, usually when UI is visible
02398 BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
02399 {
02400         if (gFocusMgr.getKeyboardFocus() 
02401                 && !(mask & (MASK_CONTROL | MASK_ALT))
02402                 && !gFocusMgr.getKeystrokesOnly())
02403         {
02404                 // We have keyboard focus, and it's not an accelerator
02405 
02406                 if (key < 0x80)
02407                 {
02408                         // Not a special key, so likely (we hope) to generate a character.  Let it fall through to character handler first.
02409                         return gFocusMgr.childHasKeyboardFocus(mRootView);
02410                 }
02411         }
02412 
02413         // HACK look for UI editing keys
02414         if (LLView::sEditingUI)
02415         {
02416                 if (LLFloaterEditUI::processKeystroke(key, mask))
02417                 {
02418                         return TRUE;
02419                 }
02420         }
02421 
02422         // Hide tooltips on keypress
02423         if(mToolTip )
02424         {
02425                 mToolTipBlocked = TRUE; // block until next time mouse is moved
02426                 mToolTip->setVisible( FALSE );
02427         }
02428 
02429         // Also hide hover info on keypress
02430         if (gHoverView)
02431         {
02432                 gHoverView->cancelHover();
02433 
02434                 gHoverView->setTyping(TRUE);
02435         }
02436 
02437         // Explicit hack for debug menu.
02438         if ((MASK_ALT & mask) &&
02439                 (MASK_CONTROL & mask) &&
02440                 ('D' == key || 'd' == key))
02441         {
02442                 toggle_debug_menus(NULL);
02443         }
02444 
02445                 // Explicit hack for debug menu.
02446         if ((mask == (MASK_SHIFT | MASK_CONTROL)) &&
02447                 ('G' == key || 'g' == key))
02448         {
02449                 if  (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)  //on splash page
02450                 {
02451                         BOOL visible = ! gSavedSettings.getBOOL("ForceShowGrid");
02452                         gSavedSettings.setBOOL("ForceShowGrid", visible);
02453 
02454                         // Initialize visibility (and don't force visibility - use prefs)
02455                         LLPanelLogin::refreshLocation( false );
02456                 }
02457         }
02458 
02459         // Example "bug" for bug reporter web page
02460         if ((MASK_SHIFT & mask) 
02461                 && (MASK_ALT & mask)
02462                 && (MASK_CONTROL & mask)
02463                 && ('H' == key || 'h' == key))
02464         {
02465                 trigger_hippo_bug(NULL);
02466         }
02467 
02468         // handle escape key
02469         if (key == KEY_ESCAPE && mask == MASK_NONE)
02470         {
02471                 if (gMenuHolder && gMenuHolder->hideMenus())
02472                 {
02473                         return TRUE;
02474                 }
02475 
02476                 //if quit from menu, turn off the Keyboardmode for the menu.
02477                 if(LLMenuGL::getKeyboardMode())
02478                         LLMenuGL::setKeyboardMode(FALSE);
02479 
02480                 if (gFocusMgr.getTopCtrl())
02481                 {
02482                         gFocusMgr.setTopCtrl(NULL);
02483                         return TRUE;
02484                 }
02485 
02486                 // *TODO: get this to play well with mouselook and hidden
02487                 // cursor modes, etc, and re-enable.
02488                 //if (gFocusMgr.getMouseCapture())
02489                 //{
02490                 //      gFocusMgr.setMouseCapture(NULL);
02491                 //      return TRUE;
02492                 //}
02493         }
02494 
02495         // let menus handle navigation keys
02496         if (gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE))
02497         {
02498                 return TRUE;
02499         }
02500         // let menus handle navigation keys
02501         if (gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, TRUE))
02502         {
02503                 return TRUE;
02504         }
02505 
02506         // Traverses up the hierarchy
02507         LLUICtrl* keyboard_focus = gFocusMgr.getKeyboardFocus();
02508         if( keyboard_focus )
02509         {
02510                 // arrow keys move avatar while chatting hack
02511                 if (gChatBar && gChatBar->inputEditorHasFocus())
02512                 {
02513                         if (gChatBar->getCurrentChat().empty() || gSavedSettings.getBOOL("ArrowKeysMoveAvatar"))
02514                         {
02515                                 switch(key)
02516                                 {
02517                                 case KEY_LEFT:
02518                                 case KEY_RIGHT:
02519                                 case KEY_UP:
02520                                         // let CTRL UP through for chat line history
02521                                         if( MASK_CONTROL == mask )
02522                                         {
02523                                                 break;
02524                                         }
02525                                 case KEY_DOWN:
02526                                         // let CTRL DOWN through for chat line history
02527                                         if( MASK_CONTROL == mask )
02528                                         {
02529                                                 break;
02530                                         }
02531                                 case KEY_PAGE_UP:
02532                                 case KEY_PAGE_DOWN:
02533                                 case KEY_HOME:
02534                                         // when chatbar is empty or ArrowKeysMoveAvatar set, pass arrow keys on to avatar...
02535                                         return FALSE;
02536                                 default:
02537                                         break;
02538                                 }
02539                         }
02540                 }
02541 
02542                 if (keyboard_focus->handleKey(key, mask, FALSE))
02543                 {
02544                         return TRUE;
02545                 }
02546         }
02547 
02548         if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) )
02549         {
02550                 return TRUE;
02551         }
02552 
02553         // Try for a new-format gesture
02554         if (gGestureManager.triggerGesture(key, mask))
02555         {
02556                 return TRUE;
02557         }
02558 
02559         // See if this is a gesture trigger.  If so, eat the key and
02560         // don't pass it down to the menus.
02561         if (gGestureList.trigger(key, mask))
02562         {
02563                 return TRUE;
02564         }
02565 
02566         // Topmost view gets a chance before the hierarchy
02567         // *FIX: get rid of this?
02568         //LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
02569         //if (top_ctrl)
02570         //{
02571         //      if( top_ctrl->handleKey( key, mask, TRUE ) )
02572         //      {
02573         //              return TRUE;
02574         //      }
02575         //}
02576 
02577         // give floaters first chance to handle TAB key
02578         // so frontmost floater gets focus
02579         if (key == KEY_TAB)
02580         {
02581                 // if nothing has focus, go to first or last UI element as appropriate
02582                 if (mask & MASK_CONTROL || gFocusMgr.getKeyboardFocus() == NULL)
02583                 {
02584                         if (gMenuHolder) gMenuHolder->hideMenus();
02585 
02586                         // if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode
02587                         gFloaterView->setCycleMode((mask & MASK_CONTROL) != 0);
02588 
02589                         // do CTRL-TAB and CTRL-SHIFT-TAB logic
02590                         if (mask & MASK_SHIFT)
02591                         {
02592                                 mRootView->focusPrevRoot();
02593                         }
02594                         else
02595                         {
02596                                 mRootView->focusNextRoot();
02597                         }
02598                         return TRUE;
02599                 }
02600         }
02601         
02602         // give menus a chance to handle keys
02603         if (gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
02604         {
02605                 return TRUE;
02606         }
02607         
02608         // give menus a chance to handle keys
02609         if (gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask))
02610         {
02611                 return TRUE;
02612         }
02613 
02614         // don't pass keys on to world when something in ui has focus
02615         return gFocusMgr.childHasKeyboardFocus(mRootView) 
02616                 || LLMenuGL::getKeyboardMode() 
02617                 || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive());
02618 }
02619 
02620 
02621 BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
02622 {
02623         // HACK:  We delay processing of return keys until they arrive as a Unicode char,
02624         // so that if you're typing chat text at low frame rate, we don't send the chat
02625         // until all keystrokes have been entered. JC
02626         // HACK: Numeric keypad <enter> on Mac is Unicode 3
02627         // HACK: Control-M on Windows is Unicode 13
02628         if ((uni_char == 13 && mask != MASK_CONTROL)
02629                 || (uni_char == 3 && mask == MASK_NONE))
02630         {
02631                 return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
02632         }
02633 
02634         // let menus handle navigation (jump) keys
02635         if (gMenuBarView && gMenuBarView->handleUnicodeChar(uni_char, TRUE))
02636         {
02637                 return TRUE;
02638         }
02639 
02640         // Traverses up the hierarchy
02641         LLView* keyboard_focus = gFocusMgr.getKeyboardFocus();
02642         if( keyboard_focus )
02643         {
02644                 if (keyboard_focus->handleUnicodeChar(uni_char, FALSE))
02645                 {
02646                         return TRUE;
02647                 }
02648 
02650                 //LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
02651                 //if (top_ctrl && top_ctrl->handleUnicodeChar( uni_char, FALSE ) )
02652                 //{
02653                 //      return TRUE;
02654                 //}
02655 
02656                 return TRUE;
02657         }
02658 
02659         return FALSE;
02660 }
02661 
02662 
02663 void LLViewerWindow::handleScrollWheel(S32 clicks)
02664 {
02665         LLView::sMouseHandlerMessage = "";
02666 
02667         gMouseIdleTimer.reset();
02668 
02669         // Hide tooltips
02670         if( mToolTip )
02671         {
02672                 mToolTip->setVisible( FALSE );
02673         }
02674 
02675         LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
02676         if( mouse_captor )
02677         {
02678                 S32 local_x;
02679                 S32 local_y;
02680                 mouse_captor->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
02681                 mouse_captor->handleScrollWheel(local_x, local_y, clicks);
02682                 if (LLView::sDebugMouseHandling)
02683                 {
02684                         llinfos << "Scroll Wheel handled by captor " << mouse_captor->getName() << llendl;
02685                 }
02686                 return;
02687         }
02688 
02689         LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
02690         if (top_ctrl)
02691         {
02692                 S32 local_x;
02693                 S32 local_y;
02694                 top_ctrl->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
02695                 if (top_ctrl->handleScrollWheel(local_x, local_y, clicks)) return;
02696         }
02697 
02698         if (mRootView->handleScrollWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks) )
02699         {
02700                 if (LLView::sDebugMouseHandling)
02701                 {
02702                         llinfos << "Scroll Wheel" << LLView::sMouseHandlerMessage << llendl;
02703                 }
02704                 return;
02705         }
02706         else if (LLView::sDebugMouseHandling)
02707         {
02708                 llinfos << "Scroll Wheel not handled by view" << llendl;
02709         }
02710 
02711         // Zoom the camera in and out behavior
02712         gAgent.handleScrollWheel(clicks);
02713 
02714         return;
02715 }
02716 
02717 void LLViewerWindow::moveCursorToCenter()
02718 {
02719         S32 x = mVirtualWindowRect.getWidth() / 2;
02720         S32 y = mVirtualWindowRect.getHeight() / 2;
02721         
02722         //on a forced move, all deltas get zeroed out to prevent jumping
02723         mCurrentMousePoint.set(x,y);
02724         mLastMousePoint.set(x,y);
02725         mCurrentMouseDelta.set(0,0);    
02726 
02727         LLUI::setCursorPositionScreen(x, y);    
02728 }
02729 
02731 //
02732 // Hover handlers
02733 //
02734 
02735 // Update UI based on stored mouse position from mouse-move
02736 // event processing.
02737 BOOL LLViewerWindow::handlePerFrameHover()
02738 {
02739         static std::string last_handle_msg;
02740 
02741         LLView::sMouseHandlerMessage = "";
02742 
02743         //RN: fix for asynchronous notification of mouse leaving window not working
02744         LLCoordWindow mouse_pos;
02745         mWindow->getCursorPosition(&mouse_pos);
02746         if (mouse_pos.mX < 0 || 
02747                 mouse_pos.mY < 0 ||
02748                 mouse_pos.mX > mWindowRect.getWidth() ||
02749                 mouse_pos.mY > mWindowRect.getHeight())
02750         {
02751                 mMouseInWindow = FALSE;
02752         }
02753         else
02754         {
02755                 mMouseInWindow = TRUE;
02756         }
02757 
02758         S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
02759         S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
02760 
02761         LLVector2 mouse_vel; 
02762 
02763         if (gSavedSettings.getBOOL("MouseSmooth"))
02764         {
02765                 static F32 fdx = 0.f;
02766                 static F32 fdy = 0.f;
02767 
02768                 F32 amount = 16.f;
02769                 fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f);
02770                 fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f);
02771 
02772                 mCurrentMouseDelta.set(llround(fdx), llround(fdy));
02773                 mouse_vel.setVec(fdx,fdy);
02774         }
02775         else
02776         {
02777                 mCurrentMouseDelta.set(dx, dy);
02778                 mouse_vel.setVec((F32) dx, (F32) dy);
02779         }
02780     
02781         mMouseVelocityStat.addValue(mouse_vel.magVec());
02782 
02783         if (gNoRender)
02784         {
02785                 return TRUE;
02786         }
02787 
02788         S32 x = mCurrentMousePoint.mX;
02789         S32 y = mCurrentMousePoint.mY;
02790         MASK mask = gKeyboard->currentMask(TRUE);
02791 
02792         // clean up current focus
02793         LLUICtrl* cur_focus = gFocusMgr.getKeyboardFocus();
02794         if (cur_focus)
02795         {
02796                 if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain())
02797                 {
02798                         gFocusMgr.releaseFocusIfNeeded(cur_focus);
02799 
02800                         LLUICtrl* parent = cur_focus->getParentUICtrl();
02801                         const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
02802                         while(parent)
02803                         {
02804                                 if (parent->isCtrl() && 
02805                                         (parent->hasTabStop() || parent == focus_root) && 
02806                                         !parent->getIsChrome() && 
02807                                         parent->isInVisibleChain() && 
02808                                         parent->isInEnabledChain())
02809                                 {
02810                                         if (!parent->focusFirstItem())
02811                                         {
02812                                                 parent->setFocus(TRUE);
02813                                         }
02814                                         break;
02815                                 }
02816                                 parent = parent->getParentUICtrl();
02817                         }
02818                 }
02819                 else if (cur_focus->isFocusRoot())
02820                 {
02821                         // focus roots keep trying to delegate focus to their first valid descendant
02822                         // this assumes that focus roots are not valid focus holders on their own
02823                         cur_focus->focusFirstItem();
02824                 }
02825         }
02826 
02827         gPipeline.sRenderProcessBeacons = FALSE;
02828         KEY key = gKeyboard->currentKey();
02829         if (((mask & MASK_CONTROL) && ('N' == key || 'n' == key)) || gSavedSettings.getBOOL("BeaconAlwaysOn"))
02830         {
02831                 gPipeline.sRenderProcessBeacons = TRUE;
02832         }
02833 
02834         BOOL handled = FALSE;
02835 
02836         BOOL handled_by_top_ctrl = FALSE;
02837         LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
02838 
02839         LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
02840         if( mouse_captor )
02841         {
02842                 // Pass hover events to object capturing mouse events.
02843                 S32 local_x;
02844                 S32 local_y; 
02845                 mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
02846                 handled = mouse_captor->handleHover(local_x, local_y, mask);
02847                 if (LLView::sDebugMouseHandling)
02848                 {
02849                         llinfos << "Hover handled by captor " << mouse_captor->getName() << llendl;
02850                 }
02851 
02852                 if( !handled )
02853                 {
02854                         lldebugst(LLERR_USER_INPUT) << "hover not handled by mouse captor" << llendl;
02855                 }
02856         }
02857         else
02858         {
02859                 if (top_ctrl)
02860                 {
02861                         S32 local_x, local_y;
02862                         top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
02863                         handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask);
02864                         handled_by_top_ctrl = TRUE;
02865                 }
02866 
02867                 if ( !handled )
02868                 {
02869                         // x and y are from last time mouse was in window
02870                         // mMouseInWindow tracks *actual* mouse location
02871                         if (mMouseInWindow && mRootView->handleHover(x, y, mask) )
02872                         {
02873                                 if (LLView::sDebugMouseHandling && LLView::sMouseHandlerMessage != last_handle_msg)
02874                                 {
02875                                         last_handle_msg = LLView::sMouseHandlerMessage;
02876                                         llinfos << "Hover" << LLView::sMouseHandlerMessage << llendl;
02877                                 }
02878                                 handled = TRUE;
02879                         }
02880                         else if (LLView::sDebugMouseHandling)
02881                         {
02882                                 if (last_handle_msg != "")
02883                                 {
02884                                         last_handle_msg = "";
02885                                         llinfos << "Hover not handled by view" << llendl;
02886                                 }
02887                         }
02888                 }
02889 
02890                 if( !handled )
02891                 {
02892                         lldebugst(LLERR_USER_INPUT) << "hover not handled by top view or root" << llendl;               
02893                 }
02894         }
02895 
02896         // *NOTE: sometimes tools handle the mouse as a captor, so this
02897         // logic is a little confusing
02898         LLTool *tool = NULL;
02899         if (gHoverView)
02900         {
02901                 tool = LLToolMgr::getInstance()->getCurrentTool();
02902 
02903                 if(!handled && tool)
02904                 {
02905                         handled = tool->handleHover(x, y, mask);
02906 
02907                         if (!mWindow->isCursorHidden())
02908                         {
02909                                 gHoverView->updateHover(tool);
02910                         }
02911                 }
02912                 else
02913                 {
02914                         // Cancel hovering if any UI element handled the event.
02915                         gHoverView->cancelHover();
02916                 }
02917 
02918                 // Suppress the toolbox view if our source tool was the pie tool,
02919                 // and we've overridden to something else.
02920                 mSuppressToolbox = 
02921                         (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) &&
02922                         (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance());
02923 
02924         }
02925 
02926         //llinfos << (mToolTipBlocked ? "BLOCKED" : "NOT BLOCKED") << llendl;
02927         // Show a new tool tip (or update one that is alrady shown)
02928         BOOL tool_tip_handled = FALSE;
02929         LLString tool_tip_msg;
02930         F32 tooltip_delay = gSavedSettings.getF32( "ToolTipDelay" );
02931         //HACK: hack for tool-based tooltips which need to pop up more quickly
02932         //Also for show xui names as tooltips debug mode
02933         if ((mouse_captor && !mouse_captor->isView()) || LLUI::sShowXUINames)
02934         {
02935                 tooltip_delay = gSavedSettings.getF32( "DragAndDropToolTipDelay" );
02936         }
02937         if( handled && 
02938                 !mToolTipBlocked &&
02939                 (gMouseIdleTimer.getElapsedTimeF32() > tooltip_delay) &&
02940                 !mWindow->isCursorHidden() )
02941         {
02942                 LLRect screen_sticky_rect;
02943 
02944                 if (mouse_captor)
02945                 {
02946                         S32 local_x, local_y;
02947                         mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
02948                         tool_tip_handled = mouse_captor->handleToolTip( local_x, local_y, tool_tip_msg, &screen_sticky_rect );
02949                 }
02950                 else if (handled_by_top_ctrl)
02951                 {
02952                         S32 local_x, local_y;
02953                         top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
02954                         tool_tip_handled = top_ctrl->handleToolTip( local_x, local_y, tool_tip_msg, &screen_sticky_rect );
02955                 }
02956                 else
02957                 {
02958                         tool_tip_handled = mRootView->handleToolTip(x, y, tool_tip_msg, &screen_sticky_rect );
02959                 }
02960 
02961                 if( tool_tip_handled && !tool_tip_msg.empty() )
02962                 {
02963                         mToolTipStickyRect = screen_sticky_rect;
02964                         mToolTip->setWrappedText( tool_tip_msg, 200 );
02965                         mToolTip->reshapeToFitText();
02966                         mToolTip->setOrigin( x, y );
02967                         LLRect virtual_window_rect(0, getWindowHeight(), getWindowWidth(), 0);
02968                         mToolTip->translateIntoRect( virtual_window_rect, FALSE );
02969                         mToolTip->setVisible( TRUE );
02970                 }
02971         }               
02972         
02973         if (tool && tool != gToolNull  && tool != LLToolCompInspect::getInstance() && tool != LLToolDragAndDrop::getInstance() && !gSavedSettings.getBOOL("FreezeTime"))
02974         { 
02975                 LLMouseHandler *captor = gFocusMgr.getMouseCapture();
02976                 // With the null, inspect, or drag and drop tool, don't muck
02977                 // with visibility.
02978 
02979                 if (gFloaterTools->isMinimized() ||
02980                         (tool != LLToolPie::getInstance()                                               // not default tool
02981                         && tool != LLToolCompGun::getInstance()                                 // not coming out of mouselook
02982                         && !mSuppressToolbox                                                                    // not override in third person
02983                         && LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset    // not special mode
02984                         && LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset
02985                         && (!captor || captor->isView()))                                               // not dragging
02986                         )
02987                 {
02988                         // Force floater tools to be visible (unless minimized)
02989                         if (!gFloaterTools->getVisible())
02990                         {
02991                                 gFloaterTools->open();          /* Flawfinder: ignore */
02992                         }
02993                         // Update the location of the blue box tool popup
02994                         LLCoordGL select_center_screen;
02995                         gFloaterTools->updatePopup( select_center_screen, mask );
02996                 }
02997                 else
02998                 {
02999                         gFloaterTools->setVisible(FALSE);
03000                 }
03001                 // In the future we may wish to hide the tools menu unless you
03002                 // are building. JC
03003                 //gMenuBarView->setItemVisible("Tools", gFloaterTools->getVisible());
03004                 //gMenuBarView->arrange();
03005         }
03006         if (gToolBar)
03007         {
03008                 gToolBar->refresh();
03009         }
03010 
03011         if (gChatBar)
03012         {
03013                 gChatBar->refresh();
03014         }
03015 
03016         if (gOverlayBar)
03017         {
03018                 gOverlayBar->refresh();
03019         }
03020 
03021         // Update rectangles for the various toolbars
03022         if (gOverlayBar && gNotifyBoxView && gConsole && gToolBar)
03023         {
03024                 LLRect bar_rect(-1, STATUS_BAR_HEIGHT, getWindowWidth()+1, -1);
03025 
03026                 LLRect notify_box_rect = gNotifyBoxView->getRect();
03027                 notify_box_rect.mBottom = bar_rect.mBottom;
03028                 gNotifyBoxView->reshape(notify_box_rect.getWidth(), notify_box_rect.getHeight());
03029                 gNotifyBoxView->setRect(notify_box_rect);
03030 
03031                 // make sure floaters snap to visible rect by adjusting floater view rect
03032                 LLRect floater_rect = gFloaterView->getRect();
03033                 if (floater_rect.mBottom != bar_rect.mBottom+1)
03034                 {
03035                         floater_rect.mBottom = bar_rect.mBottom+1;
03036                         // Don't bounce the floaters up and down.
03037                         gFloaterView->reshapeFloater(floater_rect.getWidth(), floater_rect.getHeight(), 
03038                                                                                  TRUE, ADJUST_VERTICAL_NO);
03039                         gFloaterView->setRect(floater_rect);
03040                 }
03041 
03042                 // snap floaters to top of chat bar/button strip
03043                 LLView* chatbar_and_buttons = gOverlayBar->getChild<LLView>("chatbar_and_buttons", TRUE);
03044                 // find top of chatbar and state buttons, if either are visible
03045                 if (chatbar_and_buttons && !chatbar_and_buttons->getLocalBoundingRect().isNull())
03046                 {
03047                         // convert top/left corner of chatbar/buttons container to gFloaterView-relative coordinates
03048                         S32 top, left;
03049                         chatbar_and_buttons->localPointToOtherView(
03050                                                                                                 chatbar_and_buttons->getLocalBoundingRect().mLeft, 
03051                                                                                                 chatbar_and_buttons->getLocalBoundingRect().mTop,
03052                                                                                                 &left,
03053                                                                                                 &top,
03054                                                                                                 gFloaterView);
03055                         gFloaterView->setSnapOffsetBottom(top);
03056                 }
03057                 else if (gToolBar->getVisible())
03058                 {
03059                         S32 top, left;
03060                         gToolBar->localPointToOtherView(
03061                                                                                         gToolBar->getLocalBoundingRect().mLeft,
03062                                                                                         gToolBar->getLocalBoundingRect().mTop,
03063                                                                                         &left,
03064                                                                                         &top,
03065                                                                                         gFloaterView);
03066                         gFloaterView->setSnapOffsetBottom(top);
03067                 }
03068                 else
03069                 {
03070                         gFloaterView->setSnapOffsetBottom(0);
03071                 }
03072 
03073                 // Always update console
03074                 LLRect console_rect = gConsole->getRect();
03075                 console_rect.mBottom = gHUDView->getRect().mBottom + CONSOLE_BOTTOM_PAD;
03076                 gConsole->reshape(console_rect.getWidth(), console_rect.getHeight());
03077                 gConsole->setRect(console_rect);
03078         }
03079 
03080         mLastMousePoint = mCurrentMousePoint;
03081 
03082         // last ditch force of edit menu to selection manager
03083         if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
03084         {
03085                 LLEditMenuHandler::gEditMenuHandler = LLSelectMgr::getInstance();
03086         }
03087 
03088         if (gFloaterView->getCycleMode())
03089         {
03090                 // sync all floaters with their focus state
03091                 gFloaterView->highlightFocusedFloater();
03092                 gSnapshotFloaterView->highlightFocusedFloater();
03093                 if ((gKeyboard->currentMask(TRUE) & MASK_CONTROL) == 0)
03094                 {
03095                         // control key no longer held down, finish cycle mode
03096                         gFloaterView->setCycleMode(FALSE);
03097 
03098                         gFloaterView->syncFloaterTabOrder();
03099                 }
03100                 else
03101                 {
03102                         // user holding down CTRL, don't update tab order of floaters
03103                 }
03104         }
03105         else
03106         {
03107                 // update focused floater
03108                 gFloaterView->highlightFocusedFloater();
03109                 gSnapshotFloaterView->highlightFocusedFloater();
03110                 // make sure floater visible order is in sync with tab order
03111                 gFloaterView->syncFloaterTabOrder();
03112         }
03113 
03114         if (gSavedSettings.getBOOL("ChatBarStealsFocus") 
03115                 && gChatBar 
03116                 && gFocusMgr.getKeyboardFocus() == NULL 
03117                 && gChatBar->isInVisibleChain())
03118         {
03119                 gChatBar->startChat(NULL);
03120         }
03121 
03122         // cleanup unused selections when no modal dialogs are open
03123         if (LLModalDialog::activeCount() == 0)
03124         {
03125                 LLViewerParcelMgr::getInstance()->deselectUnused();
03126         }
03127 
03128         if (LLModalDialog::activeCount() == 0)
03129         {
03130                 LLSelectMgr::getInstance()->deselectUnused();
03131         }
03132 
03133         return handled;
03134 }
03135 
03136 
03137 void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
03138 {
03139         // Store last mouse location.
03140         // If mouse leaves window, pretend last point was on edge of window
03141         if (point.mX < 0)
03142         {
03143                 mCurrentMousePoint.mX = 0;
03144         }
03145         else if (point.mX > getWindowWidth())
03146         {
03147                 mCurrentMousePoint.mX = getWindowWidth();
03148         }
03149         else
03150         {
03151                 mCurrentMousePoint.mX = point.mX;
03152         }
03153 
03154         if (point.mY < 0)
03155         {
03156                 mCurrentMousePoint.mY = 0;
03157         }
03158         else if (point.mY > getWindowHeight() )
03159         {
03160                 mCurrentMousePoint.mY = getWindowHeight();
03161         }
03162         else
03163         {
03164                 mCurrentMousePoint.mY = point.mY;
03165         }
03166 }
03167 
03168 
03169 // Draws the selection outlines for the currently selected objects
03170 // Must be called after displayObjects is called, which sets the mGLName parameter
03171 // NOTE: This function gets called 3 times:
03172 //  render_ui_3d:                       FALSE, FALSE, TRUE
03173 //  renderObjectsForSelect:     TRUE, pick_parcel_wall, FALSE
03174 //  render_hud_elements:        FALSE, FALSE, FALSE
03175 void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud )
03176 {
03177         LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
03178 
03179         if (!for_hud && !for_gl_pick)
03180         {
03181                 // Call this once and only once
03182                 LLSelectMgr::getInstance()->updateSilhouettes();
03183         }
03184         
03185         // Draw fence around land selections
03186         if (for_gl_pick)
03187         {
03188                 if (pick_parcel_walls)
03189                 {
03190                         LLViewerParcelMgr::getInstance()->renderParcelCollision();
03191                 }
03192         }
03193         else if (( for_hud && selection->getSelectType() == SELECT_TYPE_HUD) ||
03194                          (!for_hud && selection->getSelectType() != SELECT_TYPE_HUD))
03195         {               
03196                 LLSelectMgr::getInstance()->renderSilhouettes(for_hud);
03197                 
03198                 stop_glerror();
03199 
03200                 // setup HUD render
03201                 if (selection->getSelectType() == SELECT_TYPE_HUD && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
03202                 {
03203                         LLBBox hud_bbox = gAgent.getAvatarObject()->getHUDBBox();
03204 
03205                         // set up transform to encompass bounding box of HUD
03206                         glMatrixMode(GL_PROJECTION);
03207                         glPushMatrix();
03208                         glLoadIdentity();
03209                         F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
03210                         glOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth);
03211                         
03212                         glMatrixMode(GL_MODELVIEW);
03213                         glPushMatrix();
03214                         glLoadIdentity();
03215                         glLoadMatrixf(OGL_TO_CFR_ROTATION);             // Load Cory's favorite reference frame
03216                         glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f);
03217                 }
03218 
03219                 // Render light for editing
03220                 if (LLSelectMgr::sRenderLightRadius && LLToolMgr::getInstance()->inEdit())
03221                 {
03222                         LLImageGL::unbindTexture(0);
03223                         LLGLEnable gls_blend(GL_BLEND);
03224                         LLGLEnable gls_cull(GL_CULL_FACE);
03225                         LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
03226                         glMatrixMode(GL_MODELVIEW);
03227                         glPushMatrix();
03228                         if (selection->getSelectType() == SELECT_TYPE_HUD)
03229                         {
03230                                 F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom;
03231                                 glScalef(zoom, zoom, zoom);
03232                         }
03233 
03234                         struct f : public LLSelectedObjectFunctor
03235                         {
03236                                 virtual bool apply(LLViewerObject* object)
03237                                 {
03238                                         LLDrawable* drawable = object->mDrawable;
03239                                         if (drawable && drawable->isLight())
03240                                         {
03241                                                 LLVOVolume* vovolume = drawable->getVOVolume();
03242                                                 glPushMatrix();
03243 
03244                                                 LLVector3 center = drawable->getPositionAgent();
03245                                                 glTranslatef(center[0], center[1], center[2]);
03246                                                 F32 scale = vovolume->getLightRadius();
03247                                                 glScalef(scale, scale, scale);
03248 
03249                                                 LLColor4 color(vovolume->getLightColor(), .5f);
03250                                                 glColor4fv(color.mV);
03251                                         
03252                                                 F32 pixel_area = 100000.f;
03253                                                 // Render Outside
03254                                                 gSphere.render(pixel_area);
03255 
03256                                                 // Render Inside
03257                                                 glCullFace(GL_FRONT);
03258                                                 gSphere.render(pixel_area);
03259                                                 glCullFace(GL_BACK);
03260                                         
03261                                                 glPopMatrix();
03262                                         }
03263                                         return true;
03264                                 }
03265                         } func;
03266                         LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func);
03267                         
03268                         glPopMatrix();
03269                 }                               
03270                 
03271                 // NOTE: The average position for the axis arrows of the selected objects should
03272                 // not be recalculated at this time.  If they are, then group rotations will break.
03273 
03274                 // Draw arrows at average center of all selected objects
03275                 LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
03276                 if (tool)
03277                 {
03278                         if(tool->isAlwaysRendered())
03279                         {
03280                                 tool->render();
03281                         }
03282                         else
03283                         {
03284                                 if( !LLSelectMgr::getInstance()->getSelection()->isEmpty() )
03285                                 {
03286                                         BOOL moveable_object_selected = FALSE;
03287                                         BOOL all_selected_objects_move = TRUE;
03288                                         BOOL all_selected_objects_modify = TRUE;
03289                                         BOOL selecting_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
03290 
03291                                         for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
03292                                                  iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++)
03293                                         {
03294                                                 LLSelectNode* nodep = *iter;
03295                                                 LLViewerObject* object = nodep->getObject();
03296                                                 BOOL this_object_movable = FALSE;
03297                                                 if (object->permMove() && (object->permModify() || selecting_linked_set))
03298                                                 {
03299                                                         moveable_object_selected = TRUE;
03300                                                         this_object_movable = TRUE;
03301                                                 }
03302                                                 all_selected_objects_move = all_selected_objects_move && this_object_movable;
03303                                                 all_selected_objects_modify = all_selected_objects_modify && object->permModify();
03304                                         }
03305 
03306                                         BOOL draw_handles = TRUE;
03307 
03308                                         if (tool == LLToolCompTranslate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
03309                                         {
03310                                                 draw_handles = FALSE;
03311                                         }
03312 
03313                                         if (tool == LLToolCompRotate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
03314                                         {
03315                                                 draw_handles = FALSE;
03316                                         }
03317 
03318                                         if ( !all_selected_objects_modify && tool == LLToolCompScale::getInstance() )
03319                                         {
03320                                                 draw_handles = FALSE;
03321                                         }
03322                                 
03323                                         if( draw_handles )
03324                                         {
03325                                                 tool->render();
03326                                         }
03327                                 }
03328                         }
03329                         if (selection->getSelectType() == SELECT_TYPE_HUD && selection->getObjectCount())
03330                         {
03331                                 glMatrixMode(GL_PROJECTION);
03332                                 glPopMatrix();
03333 
03334                                 glMatrixMode(GL_MODELVIEW);
03335                                 glPopMatrix();
03336                                 stop_glerror();
03337                         }
03338                 }
03339         }
03340 }
03341 
03342 // Return a point near the clicked object representative of the place the object was clicked.
03343 LLVector3d LLViewerWindow::clickPointInWorldGlobal(S32 x, S32 y_from_bot, LLViewerObject* clicked_object) const
03344 {
03345         // create a normalized vector pointing from the camera center into the 
03346         // world at the location of the mouse click
03347         LLVector3 mouse_direction_global = mouseDirectionGlobal( x, y_from_bot );
03348 
03349         LLVector3d relative_object = clicked_object->getPositionGlobal() - gAgent.getCameraPositionGlobal();
03350 
03351         // make mouse vector as long as object vector, so it touchs a point near
03352         // where the user clicked on the object
03353         mouse_direction_global *= (F32) relative_object.magVec();
03354 
03355         LLVector3d new_pos;
03356         new_pos.setVec(mouse_direction_global);
03357         // transform mouse vector back to world coords
03358         new_pos += gAgent.getCameraPositionGlobal();
03359 
03360         return new_pos;
03361 }
03362 
03363 
03364 BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const
03365 {
03366         BOOL intersect = FALSE;
03367 
03368 //      U8 shape = objectp->mPrimitiveCode & LL_PCODE_BASE_MASK;
03369         if (!intersect)
03370         {
03371                 point_global = clickPointInWorldGlobal(x, y, objectp);
03372                 llinfos << "approx intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
03373         }
03374         else
03375         {
03376                 llinfos << "good intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
03377         }
03378 
03379         return intersect;
03380 }
03381 
03382 void LLViewerWindow::hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent, BOOL pick_parcel_walls)
03383 {
03384         if (gNoRender)
03385         {
03386                 return;
03387         }
03388         
03389         render_ui_and_swap_if_needed();
03390         glClear(GL_DEPTH_BUFFER_BIT);
03391         gDisplaySwapBuffers = FALSE;
03392 
03393         S32 scaled_x = llround((F32)x * mDisplayScale.mV[VX]);
03394         S32 scaled_y = llround((F32)y_from_bot * mDisplayScale.mV[VY]);
03395 
03396         BOOL in_build_mode = gFloaterTools && gFloaterTools->getVisible();
03397         if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
03398         {
03399                 // build mode allows interaction with all transparent objects
03400                 // "Show Debug Alpha" means no object actually transparent
03401                 pick_transparent = TRUE;
03402         }
03403         gPickTransparent = pick_transparent;
03404 
03405         gUseGLPick = FALSE;
03406         mPickCallback = callback;
03407 
03408         // Default to not hitting anything
03409         gLastHitPosGlobal.zeroVec();
03410         gLastHitObjectOffset.zeroVec();
03411         gLastHitObjectID.setNull();
03412         gLastHitObjectFace = -1;
03413 
03414         gLastHitNonFloraPosGlobal.zeroVec();
03415         gLastHitNonFloraObjectOffset.zeroVec();
03416         gLastHitNonFloraObjectID.setNull();
03417         gLastHitNonFloraObjectFace = -1;
03418 
03419         gLastHitParcelWall = FALSE;
03420 
03421         LLCamera pick_camera;
03422         pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin());
03423         pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(),
03424                                                                    LLViewerCamera::getInstance()->getUpAxis(),
03425                                                                    LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(x, y_from_bot));
03426         pick_camera.setView(0.5f*DEG_TO_RAD);
03427         pick_camera.setNear(LLViewerCamera::getInstance()->getNear());
03428         pick_camera.setFar(LLViewerCamera::getInstance()->getFar());
03429         pick_camera.setAspect(1.f);
03430 
03431         // save our drawing state
03432         // *TODO: should we be saving using the new method here using
03433         // glh_get_current_projection/glh_set_current_projection? -brad
03434         glMatrixMode(GL_MODELVIEW);
03435         glPushMatrix();
03436         glLoadIdentity();
03437         
03438         glMatrixMode(GL_PROJECTION);
03439         glPushMatrix();
03440         glLoadIdentity();
03441 
03442         // build perspective transform and picking viewport
03443         // Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point.
03444         // Don't limit the select distance for this pick.
03445         LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - (PICK_HALF_WIDTH + 2), scaled_y - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4, FALSE);
03446         // make viewport big enough to handle antialiased frame buffers
03447         gGLViewport[0] = scaled_x - (PICK_HALF_WIDTH + 2);
03448         gGLViewport[1] = scaled_y - (PICK_HALF_WIDTH + 2);
03449         gGLViewport[2] = PICK_DIAMETER + 4;
03450         gGLViewport[3] = PICK_DIAMETER + 4;
03451         glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
03452         LLViewerCamera::updateFrustumPlanes(pick_camera);
03453         stop_glerror();
03454 
03455         glClearColor(0.f, 0.f, 0.f, 0.f);
03456         glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
03457         //glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
03458 
03459         // Draw the objects so the user can select them.
03460         // The starting ID is 1, since land is zero.
03461         gObjectList.renderObjectsForSelect(pick_camera, pick_parcel_walls);
03462 
03463         stop_glerror();
03464 
03465         // restore drawing state
03466         glMatrixMode(GL_PROJECTION);
03467         glPopMatrix();
03468         glMatrixMode(GL_MODELVIEW);
03469         glPopMatrix();
03470 
03471         setupViewport();
03472 
03473         mPickPoint.set(x, y_from_bot);
03474         mPickOffset.set(0, 0);
03475         mPickMask = mask;
03476         mPickPending = TRUE;
03477 
03478         // delay further event processing until we receive results of pick
03479         mWindow->delayInputProcessing();
03480 }
03481 
03482 void LLViewerWindow::hitUIElementImmediate(S32 x, S32 y, void (*callback)(S32 x, S32 y, MASK mask))
03483 {
03484         // Performs the GL UI pick.
03485         // Stores its results in global, gLastHitUIElement
03486         if (gNoRender)
03487         {
03488                 return;
03489         }
03490         
03491         hitUIElementAsync(x, y, gKeyboard->currentMask(TRUE), NULL);
03492         performPick();
03493         if (callback)
03494         {
03495                 callback(x, y, gKeyboard->currentMask(TRUE));
03496         }
03497 }
03498 
03499 //RN: this currently doesn't do anything
03500 void LLViewerWindow::hitUIElementAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(S32 x, S32 y, MASK mask))
03501 {
03502         if (gNoRender)
03503         {
03504                 return;
03505         }
03506 
03507 //      F32 delta_time = gAlphaFadeTimer.getElapsedTimeAndResetF32();
03508 
03509         gUseGLPick = FALSE;
03510         mPickCallback = callback;
03511 
03512         // Default to not hitting anything
03513         gLastHitUIElement = 0;
03514 
03515         LLCamera pick_camera;
03516         pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin());
03517         pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(),
03518                                                                    LLViewerCamera::getInstance()->getUpAxis(),
03519                                                                    LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(x, y_from_bot));
03520         pick_camera.setView(0.5f*DEG_TO_RAD);
03521         pick_camera.setNear(LLViewerCamera::getInstance()->getNear());
03522         pick_camera.setFar(LLViewerCamera::getInstance()->getFar());
03523         pick_camera.setAspect(1.f);
03524 
03525         // save our drawing state
03526         glMatrixMode(GL_MODELVIEW);
03527         glPushMatrix();
03528         glLoadIdentity();
03529         
03530         glMatrixMode(GL_PROJECTION);
03531         glPushMatrix();
03532         glLoadIdentity();
03533 
03534         // build orthogonal transform and picking viewport
03535         // Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point.
03536         // Don't limit the select distance for this pick.
03537         setup2DRender();
03538         const LLVector2& display_scale = getDisplayScale();
03539         glScalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
03540 
03541         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
03542 
03543         // make viewport big enough to handle antialiased frame buffers
03544         glViewport(x - (PICK_HALF_WIDTH + 2), y_from_bot - (PICK_HALF_WIDTH + 2), PICK_DIAMETER + 4, PICK_DIAMETER + 4);
03545         stop_glerror();
03546 
03547         glClearColor(0.f, 0.f, 0.f, 0.f);
03548         glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
03549 
03550         // Draw the objects so the user can select them.
03551         // The starting ID is 1, since land is zero.
03552         //drawForSelect();
03553 
03554         stop_glerror();
03555 
03556         // restore drawing state
03557         glMatrixMode(GL_PROJECTION);
03558         glPopMatrix();
03559         glMatrixMode(GL_MODELVIEW);
03560         glPopMatrix();
03561 
03562         setupViewport();
03563 
03564         mPickPoint.set(x, y_from_bot);
03565         mPickOffset.set(0, 0);
03566         mPickMask = mask;
03567         mPickPending = TRUE;
03568 }
03569 
03570 void LLViewerWindow::performPick()
03571 {
03572         if (gNoRender || !mPickPending)
03573         {
03574                 return;
03575         }
03576 
03577         mPickPending = FALSE;
03578         U32     te_offset = NO_FACE;
03579         
03580         // find pick region that is fully onscreen
03581         LLCoordGL scaled_pick_point = mPickPoint;
03582         scaled_pick_point.mX = llclamp(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX]), PICK_HALF_WIDTH, getWindowDisplayWidth() - PICK_HALF_WIDTH);
03583         scaled_pick_point.mY = llclamp(llround((F32)mPickPoint.mY * mDisplayScale.mV[VY]), PICK_HALF_WIDTH, getWindowDisplayHeight() - PICK_HALF_WIDTH);
03584 
03585         glReadPixels(scaled_pick_point.mX - PICK_HALF_WIDTH, scaled_pick_point.mY - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
03586 
03587         S32 pixel_index = PICK_HALF_WIDTH * PICK_DIAMETER + PICK_HALF_WIDTH;
03588         S32 name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
03589         gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3];
03590 
03591         if (name >= (S32)GL_NAME_UI_RESERVED && name < (S32)GL_NAME_INDEX_OFFSET)
03592         {
03593                 // hit a UI element
03594                 gLastHitUIElement = name;
03595                 if (mPickCallback)
03596                 {
03597                         mPickCallback(mPickPoint.mX, mPickPoint.mY, mPickMask);
03598                 }
03599         }
03600 
03601         //imdebug("rgba rbga=bbba b=8 w=%d h=%d %p", PICK_DIAMETER, PICK_DIAMETER, mPickBuffer);
03602 
03603         S32 x_offset = mPickPoint.mX - llround((F32)scaled_pick_point.mX / mDisplayScale.mV[VX]);
03604         S32 y_offset = mPickPoint.mY - llround((F32)scaled_pick_point.mY / mDisplayScale.mV[VY]);
03605 
03606         
03607         // we hit nothing, scan surrounding pixels for something useful
03608         if (!name)
03609         {
03610                 S32 closest_distance = 10000;
03611                 //S32 closest_pick_name = 0;
03612                 for (S32 col = 0; col < PICK_DIAMETER; col++)
03613                 {
03614                         for (S32 row = 0; row < PICK_DIAMETER; row++)
03615                         {
03616                                 S32 distance_squared = (llabs(col - x_offset - PICK_HALF_WIDTH) * llabs(col - x_offset - PICK_HALF_WIDTH)) + (llabs(row - y_offset - PICK_HALF_WIDTH) * llabs(row - y_offset - PICK_HALF_WIDTH));
03617                                 pixel_index = row * PICK_DIAMETER + col;
03618                                 S32 test_name = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2];
03619                                 gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3];
03620                                 if (test_name && distance_squared < closest_distance)
03621                                 {
03622                                         closest_distance = distance_squared;
03623                                         name = test_name;
03624                                         gLastPickAlpha = mPickBuffer[(pixel_index * 4) + 3];
03625                                         mPickOffset.mX = col - PICK_HALF_WIDTH;
03626                                         mPickOffset.mY = row - PICK_HALF_WIDTH;
03627                                 }
03628                         }
03629                 }
03630         }
03631 
03632         if (name)
03633         {
03634                 mPickPoint.mX += llround((F32)mPickOffset.mX * mDisplayScale.mV[VX]);
03635                 mPickPoint.mY += llround((F32)mPickOffset.mY * mDisplayScale.mV[VY]);
03636         }
03637 
03638         if (gPickFaces)
03639         {
03640                 te_offset = ((U32)name >> 20);
03641                 name &= 0x000fffff;
03642                 // don't clear gPickFaces, as we still need to check for UV coordinates
03643         }
03644 
03645         LLViewerObject  *objectp = NULL;
03646 
03647         // Frontmost non-foreground object that isn't trees or grass
03648         LLViewerObject* nonflora_objectp = NULL;
03649         S32 nonflora_name = -1;
03650         S32 nonflora_te_offset = NO_FACE;
03651 
03652         if (name == (S32)GL_NAME_PARCEL_WALL)
03653         {
03654                 gLastHitParcelWall = TRUE;
03655         }
03656 
03657         gLastHitHUDIcon = NULL;
03658 
03659         objectp = gObjectList.getSelectedObject(name);
03660         if (objectp)
03661         {
03662                 LLViewerObject* parent = (LLViewerObject*)(objectp->getParent());
03663                 if (NULL == parent) {
03664                         // if you are the parent
03665                         parent = objectp;
03666                 }
03667                 if (objectp->mbCanSelect)
03668                 {
03669                         te_offset = (te_offset == 16) ? NO_FACE : te_offset;
03670 
03671                         // If the hit object isn't a plant, store it as the frontmost non-flora object.
03672                         LLPCode pcode = objectp->getPCode();
03673                         if( (LL_PCODE_LEGACY_GRASS != pcode) &&
03674                                 (LL_PCODE_LEGACY_TREE != pcode) &&
03675                                 (LL_PCODE_TREE_NEW != pcode))
03676                         {
03677                                 nonflora_objectp = objectp;
03678                                 nonflora_name = name;
03679                                 nonflora_te_offset = te_offset;
03680                         }
03681                 }
03682                 else
03683                 {
03684                         //llinfos << "Hit object you can't select" << llendl;
03685                 }
03686         }
03687         else
03688         {
03689                 // was this name referring to a hud icon?
03690                 gLastHitHUDIcon = LLHUDIcon::handlePick(name);
03691         }
03692 
03693         analyzeHit( 
03694                 mPickPoint.mX, mPickPoint.mY, objectp, te_offset,
03695                 &gLastHitObjectID, &gLastHitObjectFace, &gLastHitPosGlobal, &gLastHitLand, &gLastHitUCoord, &gLastHitVCoord );
03696 
03697         if (objectp && !gLastHitObjectID.isNull())
03698         {
03699                 gLastHitObjectOffset = gAgent.calcFocusOffset(objectp, mPickPoint.mX, mPickPoint.mY);
03700         }
03701 
03702         if( objectp == nonflora_objectp )
03703         {
03704                 gLastHitNonFloraObjectID        = gLastHitObjectID;
03705                 gLastHitNonFloraObjectFace      = gLastHitObjectFace;
03706                 gLastHitNonFloraPosGlobal       = gLastHitPosGlobal;
03707                 gLastHitNonFloraObjectOffset= gLastHitObjectOffset;
03708         }
03709         else
03710         {
03711                 analyzeHit(  mPickPoint.mX, mPickPoint.mY, nonflora_objectp, nonflora_te_offset,
03712                         &gLastHitNonFloraObjectID, &gLastHitNonFloraObjectFace, &gLastHitNonFloraPosGlobal,
03713                         &gLastHitLand, &gLastHitUCoord, &gLastHitVCoord);
03714 
03715                 if( nonflora_objectp )
03716                 {
03717                         gLastHitNonFloraObjectOffset = gAgent.calcFocusOffset(nonflora_objectp, mPickPoint.mX, mPickPoint.mY);
03718                 }
03719         }
03720 
03721         if (mPickCallback)
03722         {
03723                 mPickCallback(mPickPoint.mX, mPickPoint.mY, mPickMask);
03724         }
03725 
03726         gPickFaces = FALSE;
03727 }
03728 
03729 // Performs the GL object/land pick.
03730 // Stores its results in globals, gHit*
03731 void LLViewerWindow::hitObjectOrLandGlobalImmediate(S32 x, S32 y_from_bot, void (*callback)(S32 x, S32 y, MASK mask), BOOL pick_transparent)
03732 {
03733         if (gNoRender)
03734         {
03735                 return;
03736         }
03737         
03738         hitObjectOrLandGlobalAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent);
03739         performPick();
03740         if (callback)
03741         {
03742                 callback(x, y_from_bot, gKeyboard->currentMask(TRUE));
03743         }
03744 }
03745 
03746 LLViewerObject* LLViewerWindow::getObjectUnderCursor(const F32 depth)
03747 {
03748         S32 x = getCurrentMouseX();
03749         S32 y = getCurrentMouseY();
03750         
03751         LLVector3               mouse_direction_global = mouseDirectionGlobal(x,y);
03752         LLVector3               camera_pos_global = LLViewerCamera::getInstance()->getOrigin();
03753         LLVector3               pick_end = camera_pos_global + mouse_direction_global * depth;
03754         LLVector3               collision_point;
03755         return gPipeline.pickObject(camera_pos_global, pick_end, collision_point);
03756 }
03757 
03758 void LLViewerWindow::analyzeHit(
03759         S32                             x,                              // input
03760         S32                             y_from_bot,             // input
03761         LLViewerObject* objectp,                // input
03762         U32                             te_offset,              // input
03763         LLUUID*                 hit_object_id_p,// output
03764         S32*                    hit_face_p,             // output
03765         LLVector3d*             hit_pos_p,              // output
03766         BOOL*                   hit_land,               // output
03767         F32*                    hit_u_coord,    // output
03768         F32*                    hit_v_coord)    // output
03769 {
03770         // Clean up inputs
03771         S32 face = -1;
03772         
03773         if (te_offset != NO_FACE ) 
03774         {
03775                 face = te_offset;
03776         }
03777 
03778         *hit_land = FALSE;
03779 
03780         if (objectp)
03781         {
03782                 if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
03783                 {
03784                         // Hit land
03785                         *hit_land = TRUE;
03786 
03787                         // put global position into land_pos
03788                         LLVector3d land_pos;
03789                         if (mousePointOnLandGlobal(x, y_from_bot, &land_pos))
03790                         {
03791                                 *hit_object_id_p = LLUUID::null;
03792                                 *hit_face_p = -1;
03793 
03794                                 // Fudge the land focus a little bit above ground.
03795                                 *hit_pos_p = land_pos + LLVector3d(0.f, 0.f, 0.1f);
03796                                 //llinfos << "DEBUG Hit Land " << *hit_pos_p  << llendl;
03797                                 return;
03798                         }
03799                         else
03800                         {
03801                                 //llinfos << "Hit land but couldn't find position" << llendl;
03802                                 // Fall through to "Didn't hit anything"
03803                         }
03804                 }
03805                 else
03806                 {
03807                         *hit_object_id_p = objectp->mID;
03808                         *hit_face_p = face;
03809 
03810                         // Hit an object
03811                         if (objectp->isAvatar())
03812                         {
03813                                 *hit_pos_p = gAgent.getPosGlobalFromAgent(((LLVOAvatar*)objectp)->mPelvisp->getWorldPosition());
03814                         }
03815                         else if (objectp->mDrawable.notNull())
03816                         {
03817                                 *hit_pos_p = gAgent.getPosGlobalFromAgent(objectp->getRenderPosition());
03818                         }
03819                         else
03820                         {
03821                                 // regular object
03822                                 *hit_pos_p = objectp->getPositionGlobal();
03823                         }
03824 
03825                         if (gPickFaces && face > -1 &&
03826                                 objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME &&
03827                                 face < objectp->mDrawable->getNumFaces())
03828                         {
03829                                 // render red-blue gradient to get 1/256 precision
03830                                 // then render green grid to get final 1/4096 precision
03831                                 S32 scaled_x = llround((F32)x * mDisplayScale.mV[VX]);
03832                                 S32 scaled_y = llround((F32)y_from_bot * mDisplayScale.mV[VY]);
03833                                 const S32 UV_PICK_WIDTH = 41;
03834                                 const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
03835                                 U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
03836                                 S32 pick_face = face;
03837                                 LLFace* facep = objectp->mDrawable->getFace(pick_face);
03838                                 LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
03839                                 glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
03840                                 gPipeline.renderFaceForUVSelect(facep);
03841 
03842                                 glReadPixels(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, GL_RGBA, GL_UNSIGNED_BYTE, uv_pick_buffer);
03843                                 U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)];
03844                                 *hit_u_coord = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f;
03845                                 *hit_v_coord = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f;
03846                         }
03847                         else
03848                         {
03849                                 *hit_u_coord = 0.f;
03850                                 *hit_v_coord = 0.f;
03851                         }
03852 
03853                         //llinfos << "DEBUG Hit Object " << *hit_pos_p << llendl;
03854                         return;
03855                 }
03856         }
03857 
03858         // Didn't hit anything.
03859         *hit_object_id_p = LLUUID::null;
03860         *hit_face_p = -1;
03861         *hit_pos_p = LLVector3d::zero;
03862         *hit_u_coord = 0.f;
03863         *hit_v_coord = 0.f;
03864         //llinfos << "DEBUG Hit Nothing " << llendl;
03865 }
03866 
03867 // Returns unit vector relative to camera
03868 // indicating direction of point on screen x,y
03869 LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
03870 {
03871         // find vertical field of view
03872         F32                     fov = LLViewerCamera::getInstance()->getView();
03873 
03874         // find screen resolution
03875         S32                     height = getWindowHeight();
03876         S32                     width = getWindowWidth();
03877 
03878         // calculate pixel distance to screen
03879         F32                     distance = (height / 2.f) / (tan(fov / 2.f));
03880 
03881         // calculate click point relative to middle of screen
03882         F32                     click_x = x - width / 2.f;
03883         F32                     click_y = y - height / 2.f;
03884 
03885         // compute mouse vector
03886         LLVector3       mouse_vector =  distance * LLViewerCamera::getInstance()->getAtAxis()
03887                                                                 - click_x * LLViewerCamera::getInstance()->getLeftAxis()
03888                                                                 + click_y * LLViewerCamera::getInstance()->getUpAxis();
03889 
03890         mouse_vector.normVec();
03891 
03892         return mouse_vector;
03893 }
03894 
03895 
03896 // Returns unit vector relative to camera in camera space
03897 // indicating direction of point on screen x,y
03898 LLVector3 LLViewerWindow::mouseDirectionCamera(const S32 x, const S32 y) const
03899 {
03900         // find vertical field of view
03901         F32                     fov_height = LLViewerCamera::getInstance()->getView();
03902         F32                     fov_width = fov_height * LLViewerCamera::getInstance()->getAspect();
03903 
03904         // find screen resolution
03905         S32                     height = getWindowHeight();
03906         S32                     width = getWindowWidth();
03907 
03908         // calculate click point relative to middle of screen
03909         F32                     click_x = (((F32)x / (F32)width) - 0.5f) * fov_width * -1.f;
03910         F32                     click_y = (((F32)y / (F32)height) - 0.5f) * fov_height;
03911 
03912         // compute mouse vector
03913         LLVector3       mouse_vector =  LLVector3(0.f, 0.f, -1.f);
03914         LLQuaternion mouse_rotate;
03915         mouse_rotate.setQuat(click_y, click_x, 0.f);
03916 
03917         mouse_vector = mouse_vector * mouse_rotate;
03918         // project to z = -1 plane;
03919         mouse_vector = mouse_vector * (-1.f / mouse_vector.mV[VZ]);
03920 
03921         return mouse_vector;
03922 }
03923 
03924 
03925 
03926 BOOL LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, 
03927                                                                                 const LLVector3d &plane_point_global, 
03928                                                                                 const LLVector3 &plane_normal_global)
03929 {
03930         LLVector3d      mouse_direction_global_d;
03931 
03932         mouse_direction_global_d.setVec(mouseDirectionGlobal(x,y));
03933         LLVector3d      plane_normal_global_d;
03934         plane_normal_global_d.setVec(plane_normal_global);
03935         F64 plane_mouse_dot = (plane_normal_global_d * mouse_direction_global_d);
03936         LLVector3d plane_origin_camera_rel = plane_point_global - gAgent.getCameraPositionGlobal();
03937         F64     mouse_look_at_scale = (plane_normal_global_d * plane_origin_camera_rel)
03938                                                                 / plane_mouse_dot;
03939         if (llabs(plane_mouse_dot) < 0.00001)
03940         {
03941                 // if mouse is parallel to plane, return closest point on line through plane origin
03942                 // that is parallel to camera plane by scaling mouse direction vector
03943                 // by distance to plane origin, modulated by deviation of mouse direction from plane origin
03944                 LLVector3d plane_origin_dir = plane_origin_camera_rel;
03945                 plane_origin_dir.normVec();
03946                 
03947                 mouse_look_at_scale = plane_origin_camera_rel.magVec() / (plane_origin_dir * mouse_direction_global_d);
03948         }
03949 
03950         point = gAgent.getCameraPositionGlobal() + mouse_look_at_scale * mouse_direction_global_d;
03951 
03952         return mouse_look_at_scale > 0.0;
03953 }
03954 
03955 
03956 // Returns global position
03957 BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_position_global)
03958 {
03959         LLVector3               mouse_direction_global = mouseDirectionGlobal(x,y);
03960         F32                             mouse_dir_scale;
03961         BOOL                    hit_land = FALSE;
03962         LLViewerRegion  *regionp;
03963         F32                     land_z;
03964         const F32       FIRST_PASS_STEP = 1.0f;         // meters
03965         const F32       SECOND_PASS_STEP = 0.1f;        // meters
03966         LLVector3d      camera_pos_global;
03967 
03968         camera_pos_global = gAgent.getCameraPositionGlobal();
03969         LLVector3d              probe_point_global;
03970         LLVector3               probe_point_region;
03971 
03972         // walk forwards to find the point
03973         for (mouse_dir_scale = FIRST_PASS_STEP; mouse_dir_scale < gAgent.mDrawDistance; mouse_dir_scale += FIRST_PASS_STEP)
03974         {
03975                 LLVector3d mouse_direction_global_d;
03976                 mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
03977                 probe_point_global = camera_pos_global + mouse_direction_global_d;
03978 
03979                 regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
03980 
03981                 if (!regionp)
03982                 {
03983                         // ...we're outside the world somehow
03984                         continue;
03985                 }
03986 
03987                 S32 i = (S32) (probe_point_region.mV[VX]/regionp->getLand().getMetersPerGrid());
03988                 S32 j = (S32) (probe_point_region.mV[VY]/regionp->getLand().getMetersPerGrid());
03989                 S32 grids_per_edge = (S32) regionp->getLand().mGridsPerEdge;
03990                 if ((i >= grids_per_edge) || (j >= grids_per_edge))
03991                 {
03992                         //llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
03993                         continue;
03994                 }
03995 
03996                 land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
03997 
03998                 //llinfos << "mousePointOnLand initial z " << land_z << llendl;
03999 
04000                 if (probe_point_region.mV[VZ] < land_z)
04001                 {
04002                         // ...just went under land
04003 
04004                         // cout << "under land at " << probe_point << " scale " << mouse_vec_scale << endl;
04005 
04006                         hit_land = TRUE;
04007                         break;
04008                 }
04009         }
04010 
04011 
04012         if (hit_land)
04013         {
04014                 // Don't go more than one step beyond where we stopped above.
04015                 // This can't just be "mouse_vec_scale" because floating point error
04016                 // will stop the loop before the last increment.... X - 1.0 + 0.1 + 0.1 + ... + 0.1 != X
04017                 F32 stop_mouse_dir_scale = mouse_dir_scale + FIRST_PASS_STEP;
04018 
04019                 // take a step backwards, then walk forwards again to refine position
04020                 for ( mouse_dir_scale -= FIRST_PASS_STEP; mouse_dir_scale <= stop_mouse_dir_scale; mouse_dir_scale += SECOND_PASS_STEP)
04021                 {
04022                         LLVector3d mouse_direction_global_d;
04023                         mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
04024                         probe_point_global = camera_pos_global + mouse_direction_global_d;
04025 
04026                         regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
04027 
04028                         if (!regionp)
04029                         {
04030                                 // ...we're outside the world somehow
04031                                 continue;
04032                         }
04033 
04034                         /*
04035                         i = (S32) (local_probe_point.mV[VX]/regionp->getLand().getMetersPerGrid());
04036                         j = (S32) (local_probe_point.mV[VY]/regionp->getLand().getMetersPerGrid());
04037                         if ((i >= regionp->getLand().mGridsPerEdge) || (j >= regionp->getLand().mGridsPerEdge))
04038                         {
04039                                 // llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
04040                                 continue;
04041                         }
04042                         land_z = regionp->getLand().mSurfaceZ[ i + j * (regionp->getLand().mGridsPerEdge) ];
04043                         */
04044 
04045                         land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
04046 
04047                         //llinfos << "mousePointOnLand refine z " << land_z << llendl;
04048 
04049                         if (probe_point_region.mV[VZ] < land_z)
04050                         {
04051                                 // ...just went under land again
04052 
04053                                 *land_position_global = probe_point_global;
04054                                 return TRUE;
04055                         }
04056                 }
04057         }
04058 
04059         return FALSE;
04060 }
04061 
04062 // Saves an image to the harddrive as "SnapshotX" where X >= 1.
04063 BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw, const LLString& extension_in)
04064 {
04065         if (! raw)
04066         {
04067                 return FALSE;
04068         }
04069 
04070         LLString extension(extension_in);
04071         if (extension.empty())
04072         {
04073                 extension = (gSavedSettings.getBOOL("CompressSnapshotsToDisk")) ? ".j2c" : ".bmp";
04074         }
04075 
04076         LLFilePicker::ESaveFilter pick_type;
04077         if (extension == ".j2c")
04078                 pick_type = LLFilePicker::FFSAVE_J2C;
04079         else if (extension == ".bmp")
04080                 pick_type = LLFilePicker::FFSAVE_BMP;
04081         else if (extension == ".tga")
04082                 pick_type = LLFilePicker::FFSAVE_TGA;
04083         else
04084                 pick_type = LLFilePicker::FFSAVE_ALL; // ???
04085         
04086         // Get a directory if this is the first time.
04087         if (strlen(sSnapshotDir) == 0)          /* Flawfinder: ignore */
04088         {
04089                 LLString proposed_name( sSnapshotBaseName );
04090                 proposed_name.append( extension );
04091 
04092                 // pick a directory in which to save
04093                 LLFilePicker& picker = LLFilePicker::instance();
04094                 if (!picker.getSaveFile(pick_type, proposed_name.c_str()))
04095                 {
04096                         // Clicked cancel
04097                         return FALSE;
04098                 }
04099 
04100                 // Copy the directory + file name
04101                 char directory[LL_MAX_PATH];            /* Flawfinder: ignore */
04102                 strncpy(directory, picker.getFirstFile(), LL_MAX_PATH -1);              /* Flawfinder: ignore */
04103                 directory[LL_MAX_PATH -1] = '\0';
04104 
04105                 // Smash the file extension
04106                 S32 length = strlen(directory);         /* Flawfinder: ignore */
04107                 S32 index = length;
04108 
04109                 // Back up over extension
04110                 index -= extension.length();
04111                 if (index >= 0 && directory[index] == '.')
04112                 {
04113                         directory[index] = '\0';
04114                 }
04115                 else
04116                 {
04117                         index = length;
04118                 }
04119 
04120                 // Find trailing backslash
04121                 while (index >= 0 && directory[index] != gDirUtilp->getDirDelimiter()[0])
04122                 {
04123                         index--;
04124                 }
04125 
04126                 // If we found one, truncate the string there
04127                 if (index >= 0)
04128                 {
04129                         if (index + 1 <= length)
04130                         {
04131                                 strncpy(LLViewerWindow::sSnapshotBaseName, directory + index + 1, LL_MAX_PATH -1);              /* Flawfinder: ignore */
04132                                 LLViewerWindow::sSnapshotBaseName[LL_MAX_PATH -1] = '\0';
04133                         }
04134 
04135                         index++;
04136                         directory[index] = '\0';
04137                         strncpy(LLViewerWindow::sSnapshotDir, directory, LL_MAX_PATH -1);               /* Flawfinder: ignore */
04138                         LLViewerWindow::sSnapshotDir[LL_MAX_PATH -1] = '\0';
04139                 }
04140         }
04141 
04142         // Look for an unused file name
04143         LLString filepath;
04144         S32 i = 1;
04145         S32 err = 0;
04146 
04147         do
04148         {
04149                 filepath = sSnapshotDir;
04150                 filepath += sSnapshotBaseName;
04151                 filepath += llformat("_%.3d",i);
04152                 filepath += extension;
04153 
04154                 struct stat stat_info;
04155                 err = mWindow->stat( filepath.c_str(), &stat_info );
04156                 i++;
04157         }
04158         while( -1 != err );  // search until the file is not found (i.e., stat() gives an error).
04159 
04160         LLPointer<LLImageFormatted> formatted_image = LLImageFormatted::createFromExtension(extension);
04161         LLImageBase::setSizeOverride(TRUE);
04162         BOOL success = formatted_image->encode(raw, 0.0f);
04163         if( success )
04164         {
04165                 success = formatted_image->save(filepath);
04166         }
04167         else
04168         {
04169                 llwarns << "Unable to encode bmp snapshot" << llendl;
04170         }
04171         LLImageBase::setSizeOverride(FALSE);
04172 
04173         return success;
04174 }
04175 
04176 
04177 static S32 BORDERHEIGHT = 0;
04178 static S32 BORDERWIDTH = 0;
04179 
04180 // static
04181 void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
04182 {
04183         LLCoordScreen size;
04184         gViewerWindow->mWindow->getSize(&size);
04185         if (  (size.mX != new_width + BORDERWIDTH)
04186                 ||(size.mY != new_height + BORDERHEIGHT))
04187         {
04188                 // use actual display dimensions, not virtual UI dimensions
04189                 S32 x = gViewerWindow->getWindowDisplayWidth();
04190                 S32 y = gViewerWindow->getWindowDisplayHeight();
04191                 BORDERWIDTH = size.mX - x;
04192                 BORDERHEIGHT = size.mY- y;
04193                 LLCoordScreen new_size(new_width + BORDERWIDTH, 
04194                                                            new_height + BORDERHEIGHT);
04195                 BOOL disable_sync = gSavedSettings.getBOOL("DisableVerticalSync");
04196                 if (gViewerWindow->mWindow->getFullscreen())
04197                 {
04198                         gViewerWindow->changeDisplaySettings(FALSE, 
04199                                                                                                 new_size, 
04200                                                                                                 disable_sync, 
04201                                                                                                 TRUE);
04202                 }
04203                 else
04204                 {
04205                         gViewerWindow->mWindow->setSize(new_size);
04206                 }
04207         }
04208 }
04209 
04210 BOOL LLViewerWindow::saveSnapshot( const LLString& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
04211 {
04212         llinfos << "Saving snapshot to: " << filepath << llendl;
04213 
04214         LLPointer<LLImageRaw> raw = new LLImageRaw;
04215         BOOL success = rawSnapshot(raw, image_width, image_height, TRUE, FALSE, show_ui, do_rebuild);
04216 
04217         if (success)
04218         {
04219                 LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
04220                 success = bmp_image->encode(raw, 0.0f);
04221                 if( success )
04222                 {
04223                         success = bmp_image->save(filepath);
04224                 }
04225                 else
04226                 {
04227                         llwarns << "Unable to encode bmp snapshot" << llendl;
04228                 }
04229         }
04230         else
04231         {
04232                 llwarns << "Unable to capture raw snapshot" << llendl;
04233         }
04234 
04235         return success;
04236 }
04237 
04238 
04239 void LLViewerWindow::playSnapshotAnimAndSound()
04240 {
04241         gAgent.sendAnimationRequest(ANIM_AGENT_SNAPSHOT, ANIM_REQUEST_START);
04242         send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);
04243 }
04244 
04245 BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
04246 {
04247         if ((!raw) || preview_width < 10 || preview_height < 10)
04248         {
04249                 return FALSE;
04250         }
04251 
04252         if(gResizeScreenTexture) //the window is resizing
04253         {
04254                 return FALSE ;
04255         }
04256 
04257         setCursor(UI_CURSOR_WAIT);
04258 
04259         // Hide all the UI widgets first and draw a frame
04260         BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
04261 
04262         if ( prev_draw_ui != show_ui)
04263         {
04264                 LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
04265         }
04266 
04267         BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
04268         if (hide_hud)
04269         {
04270                 LLPipeline::sShowHUDAttachments = FALSE;
04271         }
04272 
04273         S32 render_name = gSavedSettings.getS32("RenderName");
04274         gSavedSettings.setS32("RenderName", 0);
04275         LLVOAvatar::updateFreezeCounter(1) ; //pause avatar updating for one frame
04276         
04277         S32 w = preview_width ;
04278         S32 h = preview_height ;        
04279         LLVector2 display_scale = mDisplayScale ;
04280         mDisplayScale.setVec((F32)w / mWindowRect.getWidth(), (F32)h / mWindowRect.getHeight()) ;
04281         LLRect window_rect = mWindowRect;
04282         mWindowRect.set(0, h, w, 0);
04283         
04284         gDisplaySwapBuffers = FALSE;    
04285         glClearColor(0.f, 0.f, 0.f, 0.f);
04286         glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
04287         setup3DRender();
04288         setupViewport();
04289 
04290         LLFontGL::setFontDisplay(FALSE) ;
04291         LLHUDText::setDisplayText(FALSE) ;
04292         if (type == SNAPSHOT_TYPE_OBJECT_ID)
04293         {
04294                 gPickTransparent = FALSE;
04295                 gObjectList.renderObjectsForSelect(*LLViewerCamera::getInstance(), FALSE, FALSE);
04296         }
04297         else
04298         {
04299                 display(do_rebuild, 1.0f, 0, TRUE);
04300                 render_ui_and_swap();
04301         }
04302 
04303         S32 glformat, gltype, glpixel_length ;
04304         if(SNAPSHOT_TYPE_DEPTH == type)
04305         {
04306                 glpixel_length = 4 ;
04307                 glformat = GL_DEPTH_COMPONENT ; 
04308                 gltype = GL_FLOAT ;
04309         }
04310         else
04311         {
04312                 glpixel_length = 3 ;
04313                 glformat = GL_RGB ;
04314                 gltype = GL_UNSIGNED_BYTE ;
04315         }
04316 
04317         raw->resize(w, h, glpixel_length);      
04318         glReadPixels(0, 0, w, h, glformat, gltype, raw->getData());
04319 
04320         if(SNAPSHOT_TYPE_DEPTH == type)
04321         {
04322                 LLViewerCamera* camerap = LLViewerCamera::getInstance();
04323                 F32 depth_conversion_factor_1 = (camerap->getFar() + camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear());
04324                 F32 depth_conversion_factor_2 = (camerap->getFar() - camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear());
04325 
04326                 //calculate the depth 
04327                 for (S32 y = 0 ; y < h ; y++)
04328                 {
04329                         for(S32 x = 0 ; x < w ; x++)
04330                         {
04331                                 S32 i = (w * y + x) << 2 ;
04332                                 
04333                                 F32 depth_float_i = *(F32*)(raw->getData() + i);
04334                                 
04335                                 F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float_i * depth_conversion_factor_2));
04336                                 U8 depth_byte = F32_to_U8(linear_depth_float, camerap->getNear(), camerap->getFar());
04337                                 *(raw->getData() + i + 0) = depth_byte;
04338                                 *(raw->getData() + i + 1) = depth_byte;
04339                                 *(raw->getData() + i + 2) = depth_byte;
04340                                 *(raw->getData() + i + 3) = 255;
04341                         }
04342                 }               
04343         }
04344 
04345         LLFontGL::setFontDisplay(TRUE) ;
04346         LLHUDText::setDisplayText(TRUE) ;
04347         mDisplayScale.setVec(display_scale) ;
04348         mWindowRect = window_rect;      
04349         setup3DRender();
04350         setupViewport();
04351         gDisplaySwapBuffers = FALSE;
04352 
04353         // POST SNAPSHOT
04354         if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
04355         {
04356                 LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
04357         }
04358 
04359         if (hide_hud)
04360         {
04361                 LLPipeline::sShowHUDAttachments = TRUE;
04362         }
04363 
04364         setCursor(UI_CURSOR_ARROW);
04365 
04366         if (do_rebuild)
04367         {
04368                 // If we had to do a rebuild, that means that the lists of drawables to be rendered
04369                 // was empty before we started.
04370                 // Need to reset these, otherwise we call state sort on it again when render gets called the next time
04371                 // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
04372                 // objects on them.
04373                 gPipeline.resetDrawOrders();
04374         }
04375         
04376         gSavedSettings.setS32("RenderName", render_name);       
04377         
04378         return TRUE;
04379 }
04380 
04381 // Saves the image from the screen to the specified filename and path.
04382 BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, 
04383                                                                  BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size)
04384 {
04385         if (!raw)
04386         {
04387                 return FALSE;
04388         }
04389 
04390         // PRE SNAPSHOT
04391         render_ui_and_swap_if_needed();
04392         gDisplaySwapBuffers = FALSE;
04393         
04394         glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
04395         setCursor(UI_CURSOR_WAIT);
04396 
04397         // Hide all the UI widgets first and draw a frame
04398         BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
04399 
04400         if ( prev_draw_ui != show_ui)
04401         {
04402                 LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
04403         }
04404 
04405         BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
04406         if (hide_hud)
04407         {
04408                 LLPipeline::sShowHUDAttachments = FALSE;
04409         }
04410 
04411         // Copy screen to a buffer
04412         // crop sides or top and bottom, if taking a snapshot of different aspect ratio
04413         // from window
04414         S32 snapshot_width = mWindowRect.getWidth();
04415         S32 snapshot_height =  mWindowRect.getHeight();
04416         // SNAPSHOT
04417         S32 window_width = mWindowRect.getWidth();
04418         S32 window_height = mWindowRect.getHeight();    
04419         LLRect window_rect = mWindowRect;
04420         BOOL use_fbo = FALSE;
04421 
04422         F32 scale_factor = 1.0f ;
04423         if(!keep_window_aspect) //image cropping
04424         {               
04425                 F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
04426                 snapshot_width = (S32)(ratio * image_width) ;
04427                 snapshot_height = (S32)(ratio * image_height) ;
04428                 scale_factor = llmax(1.0f, 1.0f / ratio) ;      
04429         }
04430 
04431         LLRenderTarget target;
04432         if (gGLManager.mHasFramebufferObject && 
04433                 (image_width > window_width ||
04434                 image_height > window_height) &&
04435                  !show_ui &&
04436                  keep_window_aspect)
04437         {
04438                 GLint max_size = 0;
04439                 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &max_size);
04440                 
04441                 if (image_width <= max_size && image_height <= max_size)
04442                 {
04443                         use_fbo = TRUE;
04444                         
04445                         snapshot_width = image_width;
04446                         snapshot_height = image_height;
04447                         target.allocate(snapshot_width, snapshot_height, GL_RGBA, TRUE, GL_TEXTURE_RECTANGLE_ARB, TRUE);
04448                         window_width = snapshot_width;
04449                         window_height = snapshot_height;
04450                         scale_factor = 1.f;
04451                         mWindowRect.set(0, 0, snapshot_width, snapshot_height);
04452                         target.bindTarget();                    
04453                 }
04454                 else //tiling
04455                 {
04456                         F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
04457                         snapshot_width = (S32)(ratio * image_width) ;
04458                         snapshot_height = (S32)(ratio * image_height) ;
04459                         scale_factor = llmax(1.0f, 1.0f / ratio) ;      
04460                 }
04461         }
04462         
04463         S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f);
04464         S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f);
04465 
04466         S32 image_buffer_x = llfloor(snapshot_width*scale_factor) ;
04467         S32 image_buffer_y = llfloor(snapshot_height *scale_factor) ;
04468         if(image_buffer_x > max_size || image_buffer_y > max_size) //boundary check to avoid memory overflow
04469         {
04470                 scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ;
04471                 image_buffer_x = llfloor(snapshot_width*scale_factor) ;
04472                 image_buffer_y = llfloor(snapshot_height *scale_factor) ;
04473         }
04474         raw->resize(image_buffer_x, image_buffer_y, type == SNAPSHOT_TYPE_DEPTH ? 4 : 3);
04475         if(raw->isBufferInvalid())
04476         {
04477                 return FALSE ;
04478         }
04479 
04480         BOOL high_res = scale_factor > 1.f;
04481         if (high_res)
04482         {
04483                 send_agent_pause();
04484                 //rescale fonts
04485                 initFonts(scale_factor);
04486                 LLHUDText::reshape();
04487         }
04488 
04489         S32 output_buffer_offset_y = 0;
04490 
04491         F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
04492         F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
04493 
04494         for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
04495         {
04496                 S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);;
04497                 // handle fractional columns
04498                 U32 read_height = llmax(0, (window_height - subimage_y_offset) -
04499                         llmax(0, (window_height * (subimage_y + 1)) - (buffer_y_offset + raw->getHeight())));
04500 
04501                 S32 output_buffer_offset_x = 0;
04502                 for (int subimage_x = 0; subimage_x < scale_factor; ++subimage_x)
04503                 {
04504                         gDisplaySwapBuffers = FALSE;
04505                         if (type == SNAPSHOT_TYPE_OBJECT_ID)
04506                         {
04507                                 glClearColor(0.f, 0.f, 0.f, 0.f);
04508                                 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
04509 
04510                                 LLViewerCamera::getInstance()->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor)));
04511                                 setup3DRender();
04512                                 setupViewport();
04513                                 BOOL first_time_through = (subimage_x + subimage_y == 0);
04514                                 gPickTransparent = FALSE;
04515                                 gObjectList.renderObjectsForSelect(*LLViewerCamera::getInstance(), FALSE, !first_time_through);
04516                         }
04517                         else
04518                         {
04519                                 display(do_rebuild, scale_factor, subimage_x+(subimage_y*llceil(scale_factor)), use_fbo);
04520                                 render_ui_and_swap();
04521                         }
04522 
04523                         S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width);
04524                         // handle fractional rows
04525                         U32 read_width = llmax(0, (window_width - subimage_x_offset) -
04526                                                                         llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth())));
04527                         for(U32 out_y = 0; out_y < read_height ; out_y++)
04528                         {
04529                                 if (type == SNAPSHOT_TYPE_OBJECT_ID || type == SNAPSHOT_TYPE_COLOR)
04530                                 {
04531                                         glReadPixels(
04532                                                 subimage_x_offset, out_y + subimage_y_offset,
04533                                                 read_width, 1,
04534                                                 GL_RGB, GL_UNSIGNED_BYTE,
04535                                                 raw->getData() + // current output pixel is beginning of buffer...
04536                                                         ( 
04537                                                                 (out_y * (raw->getWidth())) // ...plus iterated y...
04538                                                                 + (window_width * subimage_x) // ...plus subimage start in x...
04539                                                                 + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y...
04540                                                                 - output_buffer_offset_x // ...minus buffer padding x...
04541                                                                 - (output_buffer_offset_y * (raw->getWidth()))  // ...minus buffer padding y...
04542                                                         ) * 3 // times 3 bytes per pixel
04543                                         );
04544                                 }
04545                                 else // SNAPSHOT_TYPE_DEPTH
04546                                 {
04547                                         S32 output_buffer_offset = ( 
04548                                                                 (out_y * (raw->getWidth())) // ...plus iterated y...
04549                                                                 + (window_width * subimage_x) // ...plus subimage start in x...
04550                                                                 + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y...
04551                                                                 - output_buffer_offset_x // ...minus buffer padding x...
04552                                                                 - (output_buffer_offset_y * (raw->getWidth()))  // ...minus buffer padding y...
04553                                                         ) * 4; // times 4 bytes per pixel
04554 
04555                                         glReadPixels(
04556                                                 subimage_x_offset, out_y + subimage_y_offset,
04557                                                 read_width, 1,
04558                                                 GL_DEPTH_COMPONENT, GL_FLOAT,
04559                                                 raw->getData() + output_buffer_offset// current output pixel is beginning of buffer...
04560                                         );
04561 
04562                                         for (S32 i = output_buffer_offset; i < output_buffer_offset + (S32)read_width * 4; i += 4)
04563                                         {
04564                                                 F32 depth_float = *(F32*)(raw->getData() + i);
04565                                         
04566                                                 F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2));
04567                                                 U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar());
04568                                                 *(raw->getData() + i + 0) = depth_byte;
04569                                                 *(raw->getData() + i + 1) = depth_byte;
04570                                                 *(raw->getData() + i + 2) = depth_byte;
04571                                                 *(raw->getData() + i + 3) = 255;
04572                                         }
04573                                 }
04574                         }
04575                         output_buffer_offset_x += subimage_x_offset;
04576                         stop_glerror();
04577                 }
04578                 output_buffer_offset_y += subimage_y_offset;
04579         }
04580 
04581         if (use_fbo)
04582         {
04583                 mWindowRect = window_rect;
04584                 target.flush();
04585                 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
04586         }
04587         gDisplaySwapBuffers = FALSE;
04588 
04589         // POST SNAPSHOT
04590         if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
04591         {
04592                 LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
04593         }
04594 
04595         if (hide_hud)
04596         {
04597                 LLPipeline::sShowHUDAttachments = TRUE;
04598         }
04599 
04600         if (high_res)
04601         {
04602                 initFonts(1.f);
04603                 LLHUDText::reshape();
04604         }
04605 
04606         // Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
04607         // Note: this formula depends on the number of components being 3.  Not obvious, but it's correct.      
04608         image_width += (image_width * (type == SNAPSHOT_TYPE_DEPTH ? 4 : 3)) % 4 ;      
04609 
04610         // Resize image
04611         if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4)
04612         {
04613                 raw->scale( image_width, image_height );  
04614         }
04615         else if(image_width != image_buffer_x || image_height != image_buffer_y)
04616         {
04617                 raw->scale( image_width, image_height, FALSE );  
04618         }
04619         
04620 
04621         setCursor(UI_CURSOR_ARROW);
04622 
04623         if (do_rebuild)
04624         {
04625                 // If we had to do a rebuild, that means that the lists of drawables to be rendered
04626                 // was empty before we started.
04627                 // Need to reset these, otherwise we call state sort on it again when render gets called the next time
04628                 // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
04629                 // objects on them.
04630                 gPipeline.resetDrawOrders();
04631         }
04632 
04633         if (high_res)
04634         {
04635                 send_agent_resume();
04636         }
04637 
04638         return TRUE;
04639 }
04640 
04641 void LLViewerWindow::destroyWindow()
04642 {
04643         if (mWindow)
04644         {
04645                 LLWindowManager::destroyWindow(mWindow);
04646         }
04647         mWindow = NULL;
04648 }
04649 
04650 
04651 void LLViewerWindow::drawMouselookInstructions()
04652 {
04653         // Draw instructions for mouselook ("Press ESC to leave Mouselook" in a box at the top of the screen.)
04654         const char* instructions = "Press ESC to leave Mouselook.";
04655         const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF );
04656 
04657         const S32 INSTRUCTIONS_PAD = 5;
04658         LLRect instructions_rect;
04659         instructions_rect.setLeftTopAndSize( 
04660                 INSTRUCTIONS_PAD,
04661                 getWindowHeight() - INSTRUCTIONS_PAD,
04662                 font->getWidth( instructions ) + 2 * INSTRUCTIONS_PAD,
04663                 llround(font->getLineHeight() + 2 * INSTRUCTIONS_PAD));
04664 
04665         {
04666                 LLGLSNoTexture gls_no_texture;
04667                 gGL.color4f( 0.9f, 0.9f, 0.9f, 1.0f );
04668                 gl_rect_2d( instructions_rect );
04669         }
04670         
04671         font->renderUTF8( 
04672                 instructions, 0,
04673                 instructions_rect.mLeft + INSTRUCTIONS_PAD,
04674                 instructions_rect.mTop - INSTRUCTIONS_PAD,
04675                 LLColor4( 0.0f, 0.0f, 0.0f, 1.f ),
04676                 LLFontGL::LEFT, LLFontGL::TOP);
04677 }
04678 
04679 
04680 // These functions are here only because LLViewerWindow used to do the work that gFocusMgr does now.
04681 // They let other objects continue to work without change.
04682 
04683 void LLViewerWindow::setKeyboardFocus(LLUICtrl* new_focus)
04684 {
04685         gFocusMgr.setKeyboardFocus( new_focus );
04686 }
04687 
04688 LLUICtrl* LLViewerWindow::getKeyboardFocus()
04689 {
04690         return gFocusMgr.getKeyboardFocus();
04691 }
04692 
04693 BOOL LLViewerWindow::hasKeyboardFocus(const LLUICtrl* possible_focus) const
04694 {
04695         return possible_focus == gFocusMgr.getKeyboardFocus();
04696 }
04697 
04698 BOOL LLViewerWindow::childHasKeyboardFocus(const LLView* parent) const
04699 {
04700         return gFocusMgr.childHasKeyboardFocus( parent );
04701 }
04702 
04703 void LLViewerWindow::setMouseCapture(LLMouseHandler* new_captor)
04704 {
04705         gFocusMgr.setMouseCapture( new_captor );
04706 }
04707 
04708 LLMouseHandler* LLViewerWindow::getMouseCaptor() const
04709 {
04710         return gFocusMgr.getMouseCapture();
04711 }
04712 
04713 S32     LLViewerWindow::getWindowHeight()       const   
04714 { 
04715         return mVirtualWindowRect.getHeight(); 
04716 }
04717 
04718 S32     LLViewerWindow::getWindowWidth() const  
04719 { 
04720         return mVirtualWindowRect.getWidth(); 
04721 }
04722 
04723 S32     LLViewerWindow::getWindowDisplayHeight()        const   
04724 { 
04725         return mWindowRect.getHeight(); 
04726 }
04727 
04728 S32     LLViewerWindow::getWindowDisplayWidth() const   
04729 { 
04730         return mWindowRect.getWidth(); 
04731 }
04732 
04733 LLUICtrl* LLViewerWindow::getTopCtrl() const
04734 {
04735         return gFocusMgr.getTopCtrl();
04736 }
04737 
04738 BOOL LLViewerWindow::hasTopCtrl(LLView* view) const
04739 {
04740         return view == gFocusMgr.getTopCtrl();
04741 }
04742 
04743 void LLViewerWindow::setTopCtrl(LLUICtrl* new_top)
04744 {
04745         gFocusMgr.setTopCtrl( new_top );
04746 }
04747 
04748 void LLViewerWindow::setupViewport(S32 x_offset, S32 y_offset)
04749 {
04750         gGLViewport[0] = x_offset;
04751         gGLViewport[1] = y_offset;
04752         gGLViewport[2] = mWindowRect.getWidth();
04753         gGLViewport[3] = mWindowRect.getHeight();
04754         glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
04755 }
04756 
04757 void LLViewerWindow::setup3DRender()
04758 {
04759         LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, 0, 0,  mWindowRect.getWidth(), mWindowRect.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f);
04760 }
04761 
04762 void LLViewerWindow::setup2DRender()
04763 {
04764         gl_state_for_2d(mWindowRect.getWidth(), mWindowRect.getHeight());
04765 }
04766 
04767 // Could cache the pointer from the last hitObjectOrLand here.
04768 LLViewerObject *LLViewerWindow::lastObjectHit()
04769 {
04770         return gObjectList.findObject( gLastHitObjectID );
04771 }
04772 
04773 const LLVector3d& LLViewerWindow::lastObjectHitOffset()
04774 {
04775         return gLastHitObjectOffset;
04776 }
04777 
04778 // Could cache the pointer from the last hitObjectOrLand here.
04779 LLViewerObject *LLViewerWindow::lastNonFloraObjectHit()
04780 {
04781         return gObjectList.findObject( gLastHitNonFloraObjectID );
04782 }
04783 
04784 const LLVector3d& LLViewerWindow::lastNonFloraObjectHitOffset()
04785 {
04786         return gLastHitNonFloraObjectOffset;
04787 }
04788 
04789 
04790 void LLViewerWindow::setShowProgress(const BOOL show)
04791 {
04792         if (mProgressView)
04793         {
04794                 mProgressView->setVisible(show);
04795         }
04796 }
04797 
04798 BOOL LLViewerWindow::getShowProgress() const
04799 {
04800         return (mProgressView && mProgressView->getVisible());
04801 }
04802 
04803 
04804 void LLViewerWindow::moveProgressViewToFront()
04805 {
04806         if( mProgressView && mRootView )
04807         {
04808                 mRootView->removeChild( mProgressView );
04809                 mRootView->addChild( mProgressView );
04810         }
04811 }
04812 
04813 void LLViewerWindow::setProgressString(const LLString& string)
04814 {
04815         if (mProgressView)
04816         {
04817                 mProgressView->setText(string);
04818         }
04819 }
04820 
04821 void LLViewerWindow::setProgressMessage(const LLString& msg)
04822 {
04823         if(mProgressView)
04824         {
04825                 mProgressView->setMessage(msg);
04826         }
04827 }
04828 
04829 void LLViewerWindow::setProgressPercent(const F32 percent)
04830 {
04831         if (mProgressView)
04832         {
04833                 mProgressView->setPercent(percent);
04834         }
04835 }
04836 
04837 void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const LLString& label )
04838 {
04839         if (mProgressView)
04840         {
04841                 mProgressView->setCancelButtonVisible( b, label );
04842         }
04843 }
04844 
04845 
04846 LLProgressView *LLViewerWindow::getProgressView() const
04847 {
04848         return mProgressView;
04849 }
04850 
04851 void LLViewerWindow::dumpState()
04852 {
04853         llinfos << "LLViewerWindow Active " << S32(mActive) << llendl;
04854         llinfos << "mWindow visible " << S32(mWindow->getVisible())
04855                 << " minimized " << S32(mWindow->getMinimized())
04856                 << llendl;
04857 }
04858 
04859 void LLViewerWindow::stopGL(BOOL save_state)
04860 {
04861         if (!gGLManager.mIsDisabled)
04862         {
04863                 llinfos << "Shutting down GL..." << llendl;
04864 
04865                 // Pause texture decode threads (will get unpaused during main loop)
04866                 LLAppViewer::getTextureCache()->pause();
04867                 LLAppViewer::getImageDecodeThread()->pause();
04868                 LLAppViewer::getTextureFetch()->pause();
04869                 
04870                 gSky.destroyGL();
04871                 stop_glerror();
04872         
04873                 gImageList.destroyGL(save_state);
04874                 stop_glerror();
04875 
04876                 gBumpImageList.destroyGL();
04877                 stop_glerror();
04878 
04879                 LLFontGL::destroyGL();
04880                 stop_glerror();
04881 
04882                 LLVOAvatar::destroyGL();
04883                 stop_glerror();
04884 
04885                 LLDynamicTexture::destroyGL();
04886                 stop_glerror();
04887 
04888                 if (gPipeline.isInit())
04889                 {
04890                         gPipeline.destroyGL();
04891                 }
04892                 
04893                 gCone.cleanupGL();
04894                 gBox.cleanupGL();
04895                 gSphere.cleanupGL();
04896                 gCylinder.cleanupGL();
04897                 
04898                 gGLManager.mIsDisabled = TRUE;
04899                 stop_glerror();
04900                 
04901                 llinfos << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemory << " bytes" << llendl;
04902         }
04903 }
04904 
04905 void LLViewerWindow::restoreGL(const LLString& progress_message)
04906 {
04907         if (gGLManager.mIsDisabled)
04908         {
04909                 llinfos << "Restoring GL..." << llendl;
04910                 gGLManager.mIsDisabled = FALSE;
04911 
04912                 // for future support of non-square pixels, and fonts that are properly stretched
04913                 //LLFontGL::destroyDefaultFonts();
04914                 initFonts();
04915                 initGLDefaults();
04916                 LLGLState::restoreGL();
04917                 gSky.restoreGL();
04918                 gPipeline.restoreGL();
04919                 LLDrawPoolWater::restoreGL();
04920                 LLManipTranslate::restoreGL();
04921                 gImageList.restoreGL();
04922                 gBumpImageList.restoreGL();
04923                 LLDynamicTexture::restoreGL();
04924                 LLVOAvatar::restoreGL();
04925 
04926                 gResizeScreenTexture = TRUE;
04927 
04928                 if (gFloaterCustomize && gFloaterCustomize->getVisible())
04929                 {
04930                         LLVisualParamHint::requestHintUpdates();
04931                 }
04932 
04933                 if (!progress_message.empty())
04934                 {
04935                         gRestoreGLTimer.reset();
04936                         gRestoreGL = TRUE;
04937                         setShowProgress(TRUE);
04938                         setProgressString(progress_message);
04939                 }
04940                 llinfos << "...Restoring GL done" << llendl;
04941 #if LL_WINDOWS
04942                 if(!LLWinDebug::checkExceptionHandler())
04943                 {
04944                         llwarns << " Someone took over my exception handler (post restoreGL)!" << llendl;
04945                 }
04946 #endif
04947 
04948         }
04949 }
04950 
04951 void LLViewerWindow::initFonts(F32 zoom_factor)
04952 {
04953         LLFontGL::destroyGL();
04954         LLFontGL::initDefaultFonts( gSavedSettings.getF32("FontScreenDPI"),
04955                                     mDisplayScale.mV[VX] * zoom_factor,
04956                                     mDisplayScale.mV[VY] * zoom_factor,
04957                                     gSavedSettings.getString("FontMonospace"),
04958                                     gSavedSettings.getF32("FontSizeMonospace"),
04959                                     gSavedSettings.getString("FontSansSerif"), 
04960                                     gSavedSettings.getString("FontSansSerifFallback"),
04961                                     gSavedSettings.getF32("FontSansSerifFallbackScale"),
04962                                     gSavedSettings.getF32("FontSizeSmall"),     
04963                                     gSavedSettings.getF32("FontSizeMedium"), 
04964                                     gSavedSettings.getF32("FontSizeLarge"),                      
04965                                     gSavedSettings.getF32("FontSizeHuge"),                       
04966                                     gSavedSettings.getString("FontSansSerifBold"),
04967                                     gSavedSettings.getF32("FontSizeMedium"),
04968                                     gDirUtilp->getAppRODataDir()
04969                                     );
04970 }
04971 void LLViewerWindow::toggleFullscreen(BOOL show_progress)
04972 {
04973         if (mWindow)
04974         {
04975                 mWantFullscreen = mWindow->getFullscreen() ? FALSE : TRUE;
04976                 mShowFullscreenProgress = show_progress;
04977         }
04978 }
04979 
04980 void LLViewerWindow::getTargetWindow(BOOL& fullscreen, S32& width, S32& height) const
04981 {
04982         fullscreen = mWantFullscreen;
04983         
04984         if (mWindow
04985         &&  mWindow->getFullscreen() == mWantFullscreen)
04986         {
04987                 width = getWindowDisplayWidth();
04988                 height = getWindowDisplayHeight();
04989         }
04990         else if (mWantFullscreen)
04991         {
04992                 width = gSavedSettings.getS32("FullScreenWidth");
04993                 height = gSavedSettings.getS32("FullScreenHeight");
04994         }
04995         else
04996         {
04997                 width = gSavedSettings.getS32("WindowWidth");
04998                 height = gSavedSettings.getS32("WindowHeight");
04999         }
05000 }
05001 
05002 
05003 BOOL LLViewerWindow::checkSettings()
05004 {
05005         BOOL is_fullscreen = mWindow->getFullscreen();
05006         if (is_fullscreen && !mWantFullscreen)
05007         {
05008                 changeDisplaySettings(FALSE, 
05009                                                           LLCoordScreen(gSavedSettings.getS32("WindowWidth"),
05010                                                                                         gSavedSettings.getS32("WindowHeight")),
05011                                                           TRUE,
05012                                                           mShowFullscreenProgress);
05013                 return TRUE;
05014         }
05015         else if (!is_fullscreen && mWantFullscreen)
05016         {
05017                 if (!LLStartUp::canGoFullscreen())
05018                 {
05019                         return FALSE;
05020                 }
05021                 
05022                 LLGLState::checkStates();
05023                 LLGLState::checkTextureChannels();
05024                 changeDisplaySettings(TRUE, 
05025                                                           LLCoordScreen(gSavedSettings.getS32("FullScreenWidth"),
05026                                                                                         gSavedSettings.getS32("FullScreenHeight")),
05027                                                           gSavedSettings.getBOOL("DisableVerticalSync"),
05028                                                           mShowFullscreenProgress);
05029 
05030                 LLGLState::checkStates();
05031                 LLGLState::checkTextureChannels();
05032                 return TRUE;
05033         }
05034         return FALSE;
05035 }
05036 
05037 void LLViewerWindow::restartDisplay(BOOL show_progress_bar)
05038 {
05039         llinfos << "Restaring GL" << llendl;
05040         stopGL();
05041         if (show_progress_bar)
05042         {
05043                 restoreGL("Changing Resolution...");
05044         }
05045         else
05046         {
05047                 restoreGL();
05048         }
05049 }
05050 
05051 BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar)
05052 {
05053         BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized");
05054         mWantFullscreen = fullscreen;
05055         mShowFullscreenProgress = show_progress_bar;
05056         gSavedSettings.setBOOL("FullScreen", mWantFullscreen);
05057 
05058         gResizeScreenTexture = TRUE;
05059 
05060         BOOL old_fullscreen = mWindow->getFullscreen();
05061         if (!old_fullscreen && fullscreen && !LLStartUp::canGoFullscreen())
05062         {
05063                 // we can't do this now, so do it later
05064                 
05065                 gSavedSettings.setS32("FullScreenWidth", size.mX);
05066                 gSavedSettings.setS32("FullScreenHeight", size.mY);
05067                 //gSavedSettings.setBOOL("DisableVerticalSync", disable_vsync);
05068                 
05069                 return TRUE;    // a lie..., because we'll get to it later
05070         }
05071 
05072         U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
05073         U32 old_fsaa = mWindow->getFSAASamples();
05074         // going from windowed to windowed
05075         if (!old_fullscreen && !fullscreen)
05076         {
05077                 // if not maximized, use the request size
05078                 if (!mWindow->getMaximized())
05079                 {
05080                         mWindow->setSize(size);
05081                 }
05082 
05083                 if (fsaa == old_fsaa)
05084                 {
05085                         return TRUE;
05086                 }
05087         }
05088 
05089         // Close floaters that don't handle settings change
05090         LLFloaterSnapshot::hide(0);
05091         
05092         BOOL result_first_try = FALSE;
05093         BOOL result_second_try = FALSE;
05094 
05095         LLUICtrl* keyboard_focus = gFocusMgr.getKeyboardFocus();
05096         send_agent_pause();
05097         llinfos << "Stopping GL during changeDisplaySettings" << llendl;
05098         stopGL();
05099         mIgnoreActivate = TRUE;
05100         LLCoordScreen old_size;
05101         LLCoordScreen old_pos;
05102         mWindow->getSize(&old_size);
05103         BOOL got_position = mWindow->getPosition(&old_pos);
05104 
05105         if (!old_fullscreen && fullscreen && got_position)
05106         {
05107                 // switching from windowed to fullscreen, so save window position
05108                 gSavedSettings.setS32("WindowX", old_pos.mX);
05109                 gSavedSettings.setS32("WindowY", old_pos.mY);
05110         }
05111         
05112         mWindow->setFSAASamples(fsaa);
05113 
05114         result_first_try = mWindow->switchContext(fullscreen, size, disable_vsync);
05115         if (!result_first_try)
05116         {
05117                 // try to switch back
05118                 mWindow->setFSAASamples(old_fsaa);
05119                 result_second_try = mWindow->switchContext(old_fullscreen, old_size, disable_vsync);
05120 
05121                 if (!result_second_try)
05122                 {
05123                         // we are stuck...try once again with a minimal resolution?
05124                         send_agent_resume();
05125                         mIgnoreActivate = FALSE;
05126                         return FALSE;
05127                 }
05128         }
05129         send_agent_resume();
05130 
05131         llinfos << "Restoring GL during resolution change" << llendl;
05132         if (show_progress_bar)
05133         {
05134                 restoreGL("Changing Resolution...");
05135         }
05136         else
05137         {
05138                 restoreGL();
05139         }
05140 
05141         if (!result_first_try)
05142         {
05143                 LLStringBase<char>::format_map_t args;
05144                 args["[RESX]"] = llformat("%d",size.mX);
05145                 args["[RESY]"] = llformat("%d",size.mY);
05146                 alertXml("ResolutionSwitchFail", args);
05147                 size = old_size; // for reshape below
05148         }
05149 
05150         BOOL success = result_first_try || result_second_try;
05151         if (success)
05152         {
05153 #if LL_WINDOWS
05154                 // Only trigger a reshape after switching to fullscreen; otherwise rely on the windows callback
05155                 // (otherwise size is wrong; this is the entire window size, reshape wants the visible window size)
05156                 if (fullscreen)
05157 #endif
05158                 {
05159                         reshape(size.mX, size.mY);
05160                 }
05161         }
05162 
05163         if (!mWindow->getFullscreen() && success)
05164         {
05165                 // maximize window if was maximized, else reposition
05166                 if (was_maximized)
05167                 {
05168                         mWindow->maximize();
05169                 }
05170                 else
05171                 {
05172                         S32 windowX = gSavedSettings.getS32("WindowX");
05173                         S32 windowY = gSavedSettings.getS32("WindowY");
05174 
05175                         mWindow->setPosition(LLCoordScreen ( windowX, windowY ) );
05176                 }
05177         }
05178 
05179         mIgnoreActivate = FALSE;
05180         gFocusMgr.setKeyboardFocus(keyboard_focus);
05181         mWantFullscreen = mWindow->getFullscreen();
05182         mShowFullscreenProgress = FALSE;
05183         
05184         return success;
05185 }
05186 
05187 
05188 F32 LLViewerWindow::getDisplayAspectRatio() const
05189 {
05190         if (mWindow->getFullscreen())
05191         {
05192                 if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio"))
05193                 {
05194                         return mWindow->getNativeAspectRatio(); 
05195                 }
05196                 else
05197                 {
05198                         return gSavedSettings.getF32("FullScreenAspectRatio");
05199                 }
05200         }
05201         else
05202         {
05203                 return mWindow->getNativeAspectRatio();
05204         }
05205 }
05206 
05207 
05208 void LLViewerWindow::drawPickBuffer() const
05209 {
05210         if (mPickBuffer)
05211         {
05212                 gGL.color4f(1,1,1,1);
05213                 gGL.pushMatrix();
05214                 LLGLDisable no_blend(GL_BLEND);
05215                 LLGLDisable no_alpha_test(GL_ALPHA_TEST);
05216                 LLGLSNoTexture no_texture;
05217                 glPixelZoom(10.f, 10.f);
05218                 glRasterPos2f(((F32)mPickPoint.mX * mDisplayScale.mV[VX] + 10.f), 
05219                         ((F32)mPickPoint.mY * mDisplayScale.mV[VY] + 10.f));
05220                 glDrawPixels(PICK_DIAMETER, PICK_DIAMETER, GL_RGBA, GL_UNSIGNED_BYTE, mPickBuffer);
05221                 glPixelZoom(1.f, 1.f);
05222                 gGL.color4fv(LLColor4::white.mV);
05223                 gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] - (F32)(PICK_HALF_WIDTH)), 
05224                         llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
05225                         llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
05226                         llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
05227                         FALSE);
05228                 gl_line_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] - (F32)(PICK_HALF_WIDTH)), 
05229                         llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH)),
05230                         llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + 10.f), 
05231                         llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f + 10.f));
05232                 gl_line_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH)),
05233                         llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] - (F32)(PICK_HALF_WIDTH)),
05234                         llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f + 10.f), 
05235                         llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + 10.f));
05236                 gGL.translatef(10.f, 10.f, 0.f);
05237                 gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX]), 
05238                         llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_DIAMETER) * 10.f),
05239                         llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_DIAMETER) * 10.f),
05240                         llround((F32)mPickPoint.mY * mDisplayScale.mV[VY]),
05241                         FALSE);
05242                 gl_rect_2d(llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH + mPickOffset.mX)* 10.f), 
05243                         llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH + mPickOffset.mY + 1) * 10.f),
05244                         llround((F32)mPickPoint.mX * mDisplayScale.mV[VX] + (F32)(PICK_HALF_WIDTH + mPickOffset.mX + 1) * 10.f),
05245                         llround((F32)mPickPoint.mY * mDisplayScale.mV[VY] + (F32)(PICK_HALF_WIDTH  + mPickOffset.mY) * 10.f),
05246                         FALSE);
05247                 gGL.popMatrix();
05248                 gGL.flush();
05249         }
05250 }
05251 
05252 void LLViewerWindow::calcDisplayScale()
05253 {
05254         F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
05255         LLVector2 display_scale;
05256         display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
05257         F32 height_normalization = gSavedSettings.getBOOL("UIAutoScale") ? ((F32)mWindowRect.getHeight() / display_scale.mV[VY]) / 768.f : 1.f;
05258         if(mWindow->getFullscreen())
05259         {
05260                 display_scale *= (ui_scale_factor * height_normalization);
05261         }
05262         else
05263         {
05264                 display_scale *= ui_scale_factor;
05265         }
05266 
05267         // limit minimum display scale
05268         if (display_scale.mV[VX] < MIN_DISPLAY_SCALE || display_scale.mV[VY] < MIN_DISPLAY_SCALE)
05269         {
05270                 display_scale *= MIN_DISPLAY_SCALE / llmin(display_scale.mV[VX], display_scale.mV[VY]);
05271         }
05272 
05273         if (mWindow->getFullscreen())
05274         {
05275                 display_scale.mV[0] = llround(display_scale.mV[0], 2.0f/(F32) mWindowRect.getWidth());
05276                 display_scale.mV[1] = llround(display_scale.mV[1], 2.0f/(F32) mWindowRect.getHeight());
05277         }
05278         
05279         if (display_scale != mDisplayScale)
05280         {
05281                 llinfos << "Setting display scale to " << display_scale << llendl;
05282 
05283                 mDisplayScale = display_scale;
05284                 // Init default fonts
05285                 initFonts();
05286         }
05287 }
05288 
05289 //----------------------------------------------------------------------------
05290 
05291 // static
05292 bool LLViewerWindow::alertCallback(S32 modal)
05293 {
05294         if (gNoRender)
05295         {
05296                 return false;
05297         }
05298         else
05299         {
05300 //              if (modal) // we really always want to take you out of mouselook
05301                 {
05302                         // If we're in mouselook, the mouse is hidden and so the user can't click 
05303                         // the dialog buttons.  In that case, change to First Person instead.
05304                         if( gAgent.cameraMouselook() )
05305                         {
05306                                 gAgent.changeCameraToDefault();
05307                         }
05308                 }
05309                 return true;
05310         }
05311 }
05312 
05313 LLAlertDialog* LLViewerWindow::alertXml(const std::string& xml_filename,
05314                                                           LLAlertDialog::alert_callback_t callback, void* user_data)
05315 {
05316         LLString::format_map_t args;
05317         return alertXml( xml_filename, args, callback, user_data );
05318 }
05319 
05320 LLAlertDialog* LLViewerWindow::alertXml(const std::string& xml_filename, const LLString::format_map_t& args,
05321                                                           LLAlertDialog::alert_callback_t callback, void* user_data)
05322 {
05323         if (gNoRender)
05324         {
05325                 llinfos << "Alert: " << xml_filename << llendl;
05326                 if (callback)
05327                 {
05328                         callback(-1, user_data);
05329                 }
05330                 return NULL;
05331         }
05332 
05333         // If we're in mouselook, the mouse is hidden and so the user can't click 
05334         // the dialog buttons.  In that case, change to First Person instead.
05335         if( gAgent.cameraMouselook() )
05336         {
05337                 gAgent.changeCameraToDefault();
05338         }
05339 
05340         // Note: object adds, removes, and destroys itself.
05341         return LLAlertDialog::showXml( xml_filename, args, callback, user_data );
05342 }
05343 
05344 LLAlertDialog* LLViewerWindow::alertXmlEditText(const std::string& xml_filename, const LLString::format_map_t& args,
05345                                                                           LLAlertDialog::alert_callback_t callback, void* user_data,
05346                                                                           LLAlertDialog::alert_text_callback_t text_callback, void *text_data,
05347                                                                           const LLString::format_map_t& edit_args, BOOL draw_asterixes)
05348 {
05349         if (gNoRender)
05350         {
05351                 llinfos << "Alert: " << xml_filename << llendl;
05352                 if (callback)
05353                 {
05354                         callback(-1, user_data);
05355                 }
05356                 return NULL;
05357         }
05358 
05359         // If we're in mouselook, the mouse is hidden and so the user can't click 
05360         // the dialog buttons.  In that case, change to First Person instead.
05361         if( gAgent.cameraMouselook() )
05362         {
05363                 gAgent.changeCameraToDefault();
05364         }
05365 
05366         // Note: object adds, removes, and destroys itself.
05367         LLAlertDialog* alert = LLAlertDialog::createXml( xml_filename, args, callback, user_data );
05368         if (alert)
05369         {
05370                 if (text_callback)
05371                 {
05372                         alert->setEditTextCallback(text_callback, text_data);
05373                 }
05374                 alert->setEditTextArgs(edit_args);
05375                 alert->setDrawAsterixes(draw_asterixes);
05376                 alert->show();
05377         }
05378         return alert;
05379 }
05380 
05382 
05383 LLBottomPanel::LLBottomPanel(const LLRect &rect) : 
05384         LLPanel("", rect, FALSE),
05385         mIndicator(NULL)
05386 {
05387         // bottom panel is focus root, so Tab moves through the toolbar and button bar, and overlay
05388         setFocusRoot(TRUE);
05389         // flag this panel as chrome so buttons don't grab keyboard focus
05390         setIsChrome(TRUE);
05391 
05392         mFactoryMap["toolbar"] = LLCallbackMap(createToolBar, NULL);
05393         mFactoryMap["overlay"] = LLCallbackMap(createOverlayBar, NULL);
05394         mFactoryMap["hud"] = LLCallbackMap(createHUD, NULL);
05395         LLUICtrlFactory::getInstance()->buildPanel(this, "panel_bars.xml", &getFactoryMap());
05396         
05397         setOrigin(rect.mLeft, rect.mBottom);
05398         reshape(rect.getWidth(), rect.getHeight());
05399 }
05400 
05401 void LLBottomPanel::setFocusIndicator(LLView * indicator)
05402 {
05403         mIndicator = indicator;
05404 }
05405 
05406 void LLBottomPanel::draw()
05407 {
05408         if(mIndicator)
05409         {
05410                 BOOL hasFocus = gFocusMgr.childHasKeyboardFocus(this);
05411                 mIndicator->setVisible(hasFocus);
05412                 mIndicator->setEnabled(hasFocus);
05413         }
05414         LLPanel::draw();
05415 }
05416 
05417 void* LLBottomPanel::createHUD(void* data)
05418 {
05419         delete gHUDView;
05420         gHUDView = new LLHUDView();
05421         return gHUDView;
05422 }
05423 
05424 
05425 void* LLBottomPanel::createOverlayBar(void* data)
05426 {
05427         delete gOverlayBar;
05428         gOverlayBar = new LLOverlayBar();
05429         return gOverlayBar;
05430 }
05431 
05432 void* LLBottomPanel::createToolBar(void* data)
05433 {
05434         delete gToolBar;
05435         gToolBar = new LLToolBar();
05436         return gToolBar;
05437 }

Generated on Fri May 16 08:34:18 2008 for SecondLife by  doxygen 1.5.5