llviewerwindow.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:146k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llviewerwindow.cpp
  3.  * @brief Implementation of the LLViewerWindow class.
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llviewerwindow.h"
  34. #if LL_WINDOWS
  35. #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
  36. #endif
  37. // system library includes
  38. #include <stdio.h>
  39. #include <iostream>
  40. #include <fstream>
  41. #include <algorithm>
  42. #include "llfloaterreg.h"
  43. #include "llpanellogin.h"
  44. #include "llviewerkeyboard.h"
  45. #include "llviewermenu.h"
  46. #include "llviewquery.h"
  47. #include "llxmltree.h"
  48. #include "llslurl.h"
  49. //#include "llviewercamera.h"
  50. #include "llrender.h"
  51. #include "llvoiceclient.h" // for push-to-talk button handling
  52. //
  53. // TODO: Many of these includes are unnecessary.  Remove them.
  54. //
  55. // linden library includes
  56. #include "llaudioengine.h" // mute on minimize
  57. #include "indra_constants.h"
  58. #include "llassetstorage.h"
  59. #include "llerrorcontrol.h"
  60. #include "llfontgl.h"
  61. #include "llmousehandler.h"
  62. #include "llrect.h"
  63. #include "llsky.h"
  64. #include "llstring.h"
  65. #include "llui.h"
  66. #include "lluuid.h"
  67. #include "llview.h"
  68. #include "llxfermanager.h"
  69. #include "message.h"
  70. #include "object_flags.h"
  71. #include "lltimer.h"
  72. #include "timing.h"
  73. #include "llviewermenu.h"
  74. #include "lltooltip.h"
  75. #include "llmediaentry.h"
  76. #include "llurldispatcher.h"
  77. #include "llurlsimstring.h"
  78. // newview includes
  79. #include "llagent.h"
  80. #include "llbox.h"
  81. #include "llconsole.h"
  82. #include "llviewercontrol.h"
  83. #include "llcylinder.h"
  84. #include "lldebugview.h"
  85. #include "lldir.h"
  86. #include "lldrawable.h"
  87. #include "lldrawpoolalpha.h"
  88. #include "lldrawpoolbump.h"
  89. #include "lldrawpoolwater.h"
  90. #include "llmaniptranslate.h"
  91. #include "llface.h"
  92. #include "llfeaturemanager.h"
  93. #include "llfilepicker.h"
  94. #include "llfloater.h"
  95. #include "llfloaterbuildoptions.h"
  96. #include "llfloaterbuyland.h"
  97. #include "llfloatercamera.h"
  98. #include "llfloatercustomize.h"
  99. #include "llfloaterland.h"
  100. #include "llfloaterinspect.h"
  101. #include "llfloatermap.h"
  102. #include "llfloaternamedesc.h"
  103. #include "llfloaterpreference.h"
  104. #include "llfloatersnapshot.h"
  105. #include "llfloatertools.h"
  106. #include "llfloaterworldmap.h"
  107. #include "llfocusmgr.h"
  108. #include "llfontfreetype.h"
  109. #include "llgesturemgr.h"
  110. #include "llglheaders.h"
  111. #include "lltooltip.h"
  112. #include "llhudmanager.h"
  113. #include "llhudview.h"
  114. #include "llimagebmp.h"
  115. #include "llimagej2c.h"
  116. #include "llimageworker.h"
  117. #include "llkeyboard.h"
  118. #include "lllineeditor.h"
  119. #include "llmenugl.h"
  120. #include "llmodaldialog.h"
  121. #include "llmorphview.h"
  122. #include "llmoveview.h"
  123. #include "llnavigationbar.h"
  124. #include "llpreviewtexture.h"
  125. #include "llprogressview.h"
  126. #include "llresmgr.h"
  127. #include "llsidetray.h"
  128. #include "llselectmgr.h"
  129. #include "llrootview.h"
  130. #include "llrendersphere.h"
  131. #include "llstartup.h"
  132. #include "llstatusbar.h"
  133. #include "llstatview.h"
  134. #include "llsurface.h"
  135. #include "llsurfacepatch.h"
  136. #include "lltexlayer.h"
  137. #include "lltextbox.h"
  138. #include "lltexturecache.h"
  139. #include "lltexturefetch.h"
  140. #include "lltextureview.h"
  141. #include "lltool.h"
  142. #include "lltoolcomp.h"
  143. #include "lltooldraganddrop.h"
  144. #include "lltoolface.h"
  145. #include "lltoolfocus.h"
  146. #include "lltoolgrab.h"
  147. #include "lltoolmgr.h"
  148. #include "lltoolmorph.h"
  149. #include "lltoolpie.h"
  150. #include "lltoolselectland.h"
  151. #include "lltrans.h"
  152. #include "lluictrlfactory.h"
  153. #include "llurldispatcher.h" // SLURL from other app instance
  154. #include "llvieweraudio.h"
  155. #include "llviewercamera.h"
  156. #include "llviewergesture.h"
  157. #include "llviewertexturelist.h"
  158. #include "llviewerinventory.h"
  159. #include "llviewerkeyboard.h"
  160. #include "llviewermedia.h"
  161. #include "llviewermediafocus.h"
  162. #include "llviewermenu.h"
  163. #include "llviewermessage.h"
  164. #include "llviewerobjectlist.h"
  165. #include "llviewerparcelmgr.h"
  166. #include "llviewerregion.h"
  167. #include "llviewershadermgr.h"
  168. #include "llviewerstats.h"
  169. #include "llvoavatarself.h"
  170. #include "llvovolume.h"
  171. #include "llworld.h"
  172. #include "llworldmapview.h"
  173. #include "pipeline.h"
  174. #include "llappviewer.h"
  175. #include "llviewerdisplay.h"
  176. #include "llspatialpartition.h"
  177. #include "llviewerjoystick.h"
  178. #include "llviewernetwork.h"
  179. #include "llpostprocess.h"
  180. #include "llbottomtray.h"
  181. #include "llnearbychatbar.h"
  182. #include "llagentui.h"
  183. #include "llwearablelist.h"
  184. #include "llnotifications.h"
  185. #include "llnotificationsutil.h"
  186. #include "llnotificationmanager.h"
  187. #include "llfloaternotificationsconsole.h"
  188. #include "llnearbychat.h"
  189. #include "llviewerwindowlistener.h"
  190. #if LL_WINDOWS
  191. #include <tchar.h> // For Unicode conversion methods
  192. #endif
  193. //
  194. // Globals
  195. //
  196. void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
  197. extern BOOL gDebugClicks;
  198. extern BOOL gDisplaySwapBuffers;
  199. extern BOOL gDepthDirty;
  200. extern BOOL gResizeScreenTexture;
  201. LLViewerWindow *gViewerWindow = NULL;
  202. LLFrameTimer gAwayTimer;
  203. LLFrameTimer gAwayTriggerTimer;
  204. BOOL gShowOverlayTitle = FALSE;
  205. LLViewerObject*  gDebugRaycastObject = NULL;
  206. LLVector3       gDebugRaycastIntersection;
  207. LLVector2       gDebugRaycastTexCoord;
  208. LLVector3       gDebugRaycastNormal;
  209. LLVector3       gDebugRaycastBinormal;
  210. S32 gDebugRaycastFaceHit;
  211. // HUD display lines in lower right
  212. BOOL gDisplayWindInfo = FALSE;
  213. BOOL gDisplayCameraPos = FALSE;
  214. BOOL gDisplayFOV = FALSE;
  215. BOOL gDisplayBadge = FALSE;
  216. S32 CHAT_BAR_HEIGHT = 28; 
  217. S32 OVERLAY_BAR_HEIGHT = 20;
  218. const U8 NO_FACE = 255;
  219. BOOL gQuietSnapshot = FALSE;
  220. const F32 MIN_AFK_TIME = 2.f; // minimum time after setting away state before coming back
  221. const F32 MAX_FAST_FRAME_TIME = 0.5f;
  222. const F32 FAST_FRAME_INCREMENT = 0.1f;
  223. const F32 MIN_DISPLAY_SCALE = 0.75f;
  224. std::string LLViewerWindow::sSnapshotBaseName;
  225. std::string LLViewerWindow::sSnapshotDir;
  226. std::string LLViewerWindow::sMovieBaseName;
  227. class RecordToChatConsole : public LLError::Recorder, public LLSingleton<RecordToChatConsole>
  228. {
  229. public:
  230. virtual void recordMessage(LLError::ELevel level,
  231. const std::string& message)
  232. {
  233. //FIXME: this is NOT thread safe, and will do bad things when a warning is issued from a non-UI thread
  234. // only log warnings to chat console
  235. //if (level == LLError::LEVEL_WARN)
  236. //{
  237. //LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance<LLFloaterChat>("chat");
  238. //if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat"))
  239. //{
  240. // LLChat chat;
  241. // chat.mText = message;
  242. // chat.mSourceType = CHAT_SOURCE_SYSTEM;
  243. // chat_floater->addChat(chat, FALSE, FALSE);
  244. //}
  245. //}
  246. }
  247. };
  248. ////////////////////////////////////////////////////////////////////////////
  249. //
  250. // LLDebugText
  251. //
  252. class LLDebugText
  253. {
  254. private:
  255. struct Line
  256. {
  257. Line(const std::string& in_text, S32 in_x, S32 in_y) : text(in_text), x(in_x), y(in_y) {}
  258. std::string text;
  259. S32 x,y;
  260. };
  261. LLViewerWindow *mWindow;
  262. typedef std::vector<Line> line_list_t;
  263. line_list_t mLineList;
  264. LLColor4 mTextColor;
  265. public:
  266. LLDebugText(LLViewerWindow* window) : mWindow(window) {}
  267. void addText(S32 x, S32 y, const std::string &text) 
  268. {
  269. mLineList.push_back(Line(text, x, y));
  270. }
  271. void update()
  272. {
  273. std::string wind_vel_text;
  274. std::string wind_vector_text;
  275. std::string rwind_vel_text;
  276. std::string rwind_vector_text;
  277. std::string audio_text;
  278. // Draw the statistics in a light gray
  279. // and in a thin font
  280. mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f );
  281. // Draw stuff growing up from right lower corner of screen
  282. U32 xpos = mWindow->getWindowWidthScaled() - 350;
  283. U32 ypos = 64;
  284. const U32 y_inc = 20;
  285. if (gSavedSettings.getBOOL("DebugShowTime"))
  286. {
  287. const U32 y_inc2 = 15;
  288. for (std::map<S32,LLFrameTimer>::reverse_iterator iter = gDebugTimers.rbegin();
  289.  iter != gDebugTimers.rend(); ++iter)
  290. {
  291. S32 idx = iter->first;
  292. LLFrameTimer& timer = iter->second;
  293. F32 time = timer.getElapsedTimeF32();
  294. S32 hours = (S32)(time / (60*60));
  295. S32 mins = (S32)((time - hours*(60*60)) / 60);
  296. S32 secs = (S32)((time - hours*(60*60) - mins*60));
  297. std::string label = gDebugTimerLabel[idx];
  298. if (label.empty()) label = llformat("Debug: %d", idx);
  299. addText(xpos, ypos, llformat(" %s: %d:%02d:%02d", label.c_str(), hours,mins,secs)); ypos += y_inc2;
  300. }
  301. F32 time = gFrameTimeSeconds;
  302. S32 hours = (S32)(time / (60*60));
  303. S32 mins = (S32)((time - hours*(60*60)) / 60);
  304. S32 secs = (S32)((time - hours*(60*60) - mins*60));
  305. addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc;
  306. }
  307. if (gDisplayCameraPos)
  308. {
  309. std::string camera_view_text;
  310. std::string camera_center_text;
  311. std::string agent_view_text;
  312. std::string agent_left_text;
  313. std::string agent_center_text;
  314. std::string agent_root_center_text;
  315. LLVector3d tvector; // Temporary vector to hold data for printing.
  316. // Update camera center, camera view, wind info every other frame
  317. tvector = gAgent.getPositionGlobal();
  318. agent_center_text = llformat("AgentCenter  %f %f %f",
  319.  (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
  320. if (gAgent.getAvatarObject())
  321. {
  322. tvector = gAgent.getPosGlobalFromAgent(gAgent.getAvatarObject()->mRoot.getWorldPosition());
  323. agent_root_center_text = llformat("AgentRootCenter %f %f %f",
  324.   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
  325. }
  326. else
  327. {
  328. agent_root_center_text = "---";
  329. }
  330. tvector = LLVector4(gAgent.getFrameAgent().getAtAxis());
  331. agent_view_text = llformat("AgentAtAxis  %f %f %f",
  332.    (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
  333. tvector = LLVector4(gAgent.getFrameAgent().getLeftAxis());
  334. agent_left_text = llformat("AgentLeftAxis  %f %f %f",
  335.    (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
  336. tvector = gAgent.getCameraPositionGlobal();
  337. camera_center_text = llformat("CameraCenter %f %f %f",
  338.   (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
  339. tvector = LLVector4(LLViewerCamera::getInstance()->getAtAxis());
  340. camera_view_text = llformat("CameraAtAxis    %f %f %f",
  341. (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ]));
  342. addText(xpos, ypos, agent_center_text);  ypos += y_inc;
  343. addText(xpos, ypos, agent_root_center_text);  ypos += y_inc;
  344. addText(xpos, ypos, agent_view_text);  ypos += y_inc;
  345. addText(xpos, ypos, agent_left_text);  ypos += y_inc;
  346. addText(xpos, ypos, camera_center_text);  ypos += y_inc;
  347. addText(xpos, ypos, camera_view_text);  ypos += y_inc;
  348. }
  349. if (gDisplayWindInfo)
  350. {
  351. wind_vel_text = llformat("Wind velocity %.2f m/s", gWindVec.magVec());
  352. wind_vector_text = llformat("Wind vector   %.2f %.2f %.2f", gWindVec.mV[0], gWindVec.mV[1], gWindVec.mV[2]);
  353. rwind_vel_text = llformat("RWind vel %.2f m/s", gRelativeWindVec.magVec());
  354. rwind_vector_text = llformat("RWind vec   %.2f %.2f %.2f", gRelativeWindVec.mV[0], gRelativeWindVec.mV[1], gRelativeWindVec.mV[2]);
  355. addText(xpos, ypos, wind_vel_text);  ypos += y_inc;
  356. addText(xpos, ypos, wind_vector_text);  ypos += y_inc;
  357. addText(xpos, ypos, rwind_vel_text);  ypos += y_inc;
  358. addText(xpos, ypos, rwind_vector_text);  ypos += y_inc;
  359. }
  360. if (gDisplayWindInfo)
  361. {
  362. if (gAudiop)
  363. {
  364. audio_text= llformat("Audio for wind: %d", gAudiop->isWindEnabled());
  365. }
  366. addText(xpos, ypos, audio_text);  ypos += y_inc;
  367. }
  368. if (gDisplayFOV)
  369. {
  370. addText(xpos, ypos, llformat("FOV: %2.1f deg", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));
  371. ypos += y_inc;
  372. }
  373. if (gDisplayBadge)
  374. {
  375. addText(xpos, ypos+(y_inc/2), llformat("Hippos!", RAD_TO_DEG * LLViewerCamera::getInstance()->getView()));
  376. ypos += y_inc * 2;
  377. }
  378. /*if (LLViewerJoystick::getInstance()->getOverrideCamera())
  379. {
  380. addText(xpos + 200, ypos, llformat("Flycam"));
  381. ypos += y_inc;
  382. }*/
  383. if (gSavedSettings.getBOOL("DebugShowRenderInfo"))
  384. {
  385. if (gPipeline.getUseVertexShaders() == 0)
  386. {
  387. addText(xpos, ypos, "Shaders Disabled");
  388. ypos += y_inc;
  389. }
  390. addText(xpos, ypos, llformat("%d MB Vertex Data", LLVertexBuffer::sAllocatedBytes/(1024*1024)));
  391. ypos += y_inc;
  392. addText(xpos, ypos, llformat("%d Vertex Buffers", LLVertexBuffer::sGLCount));
  393. ypos += y_inc;
  394. addText(xpos, ypos, llformat("%d Mapped Buffers", LLVertexBuffer::sMappedCount));
  395. ypos += y_inc;
  396. addText(xpos, ypos, llformat("%d Vertex Buffer Binds", LLVertexBuffer::sBindCount));
  397. ypos += y_inc;
  398. addText(xpos, ypos, llformat("%d Vertex Buffer Sets", LLVertexBuffer::sSetCount));
  399. ypos += y_inc;
  400. addText(xpos, ypos, llformat("%d Texture Binds", LLImageGL::sBindCount));
  401. ypos += y_inc;
  402. addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount));
  403. ypos += y_inc;
  404. addText(xpos, ypos, llformat("%d Render Calls", gPipeline.mBatchCount));
  405.             ypos += y_inc;
  406. addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount));
  407. ypos += y_inc;
  408. addText(xpos, ypos, llformat("%d Texture Matrix Ops", gPipeline.mTextureMatrixOps));
  409. ypos += y_inc;
  410. gPipeline.mTextureMatrixOps = 0;
  411. gPipeline.mMatrixOpCount = 0;
  412. if (gPipeline.mBatchCount > 0)
  413. {
  414. addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", gPipeline.mMinBatchSize, gPipeline.mMaxBatchSize, 
  415. gPipeline.mTrianglesDrawn/gPipeline.mBatchCount));
  416. gPipeline.mMinBatchSize = gPipeline.mMaxBatchSize;
  417. gPipeline.mMaxBatchSize = 0;
  418. gPipeline.mBatchCount = 0;
  419. }
  420.             ypos += y_inc;
  421. addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount));
  422. ypos += y_inc;
  423. addText(xpos,ypos, llformat("%d Avatars visible", LLVOAvatar::sNumVisibleAvatars));
  424. ypos += y_inc;
  425. addText(xpos,ypos, llformat("%d Lights visible", LLPipeline::sVisibleLightCount));
  426. ypos += y_inc;
  427. LLVertexBuffer::sBindCount = LLImageGL::sBindCount = 
  428. LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = 
  429. gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0;
  430. }
  431. if (gSavedSettings.getBOOL("DebugShowRenderMatrices"))
  432. {
  433. addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[12], gGLProjection[13], gGLProjection[14], gGLProjection[15]));
  434. ypos += y_inc;
  435. addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[8], gGLProjection[9], gGLProjection[10], gGLProjection[11]));
  436. ypos += y_inc;
  437. addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[4], gGLProjection[5], gGLProjection[6], gGLProjection[7]));
  438. ypos += y_inc;
  439. addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[0], gGLProjection[1], gGLProjection[2], gGLProjection[3]));
  440. ypos += y_inc;
  441. addText(xpos, ypos, "Projection Matrix");
  442. ypos += y_inc;
  443. addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[12], gGLModelView[13], gGLModelView[14], gGLModelView[15]));
  444. ypos += y_inc;
  445. addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[8], gGLModelView[9], gGLModelView[10], gGLModelView[11]));
  446. ypos += y_inc;
  447. addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[4], gGLModelView[5], gGLModelView[6], gGLModelView[7]));
  448. ypos += y_inc;
  449. addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[0], gGLModelView[1], gGLModelView[2], gGLModelView[3]));
  450. ypos += y_inc;
  451. addText(xpos, ypos, "View Matrix");
  452. ypos += y_inc;
  453. }
  454. if (gSavedSettings.getBOOL("DebugShowColor"))
  455. {
  456. U8 color[4];
  457. LLCoordGL coord = gViewerWindow->getCurrentMouse();
  458. glReadPixels(coord.mX, coord.mY, 1,1,GL_RGBA, GL_UNSIGNED_BYTE, color);
  459. addText(xpos, ypos, llformat("%d %d %d %d", color[0], color[1], color[2], color[3]));
  460. ypos += y_inc;
  461. }
  462. // only display these messages if we are actually rendering beacons at this moment
  463. if (LLPipeline::getRenderBeacons(NULL) && LLFloaterReg::instanceVisible("beacons"))
  464. {
  465. if (LLPipeline::getRenderParticleBeacons(NULL))
  466. {
  467. addText(xpos, ypos, "Viewing particle beacons (blue)");
  468. ypos += y_inc;
  469. }
  470. if (LLPipeline::toggleRenderTypeControlNegated((void*)LLPipeline::RENDER_TYPE_PARTICLES))
  471. {
  472. addText(xpos, ypos, "Hiding particles");
  473. ypos += y_inc;
  474. }
  475. if (LLPipeline::getRenderPhysicalBeacons(NULL))
  476. {
  477. addText(xpos, ypos, "Viewing physical object beacons (green)");
  478. ypos += y_inc;
  479. }
  480. if (LLPipeline::getRenderScriptedBeacons(NULL))
  481. {
  482. addText(xpos, ypos, "Viewing scripted object beacons (red)");
  483. ypos += y_inc;
  484. }
  485. else
  486. if (LLPipeline::getRenderScriptedTouchBeacons(NULL))
  487. {
  488. addText(xpos, ypos, "Viewing scripted object with touch function beacons (red)");
  489. ypos += y_inc;
  490. }
  491. if (LLPipeline::getRenderSoundBeacons(NULL))
  492. {
  493. addText(xpos, ypos, "Viewing sound beacons (yellow)");
  494. ypos += y_inc;
  495. }
  496. }
  497. }
  498. void draw()
  499. {
  500. for (line_list_t::iterator iter = mLineList.begin();
  501.  iter != mLineList.end(); ++iter)
  502. {
  503. const Line& line = *iter;
  504. LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor,
  505.  LLFontGL::LEFT, LLFontGL::TOP,
  506.  LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
  507. }
  508. mLineList.clear();
  509. }
  510. };
  511. void LLViewerWindow::updateDebugText()
  512. {
  513. mDebugText->update();
  514. }
  515. ////////////////////////////////////////////////////////////////////////////
  516. //
  517. // LLViewerWindow
  518. //
  519. BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window,  LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
  520. {
  521. const char* buttonname = "";
  522. const char* buttonstatestr = "";
  523. S32 x = pos.mX;
  524. S32 y = pos.mY;
  525. x = llround((F32)x / mDisplayScale.mV[VX]);
  526. y = llround((F32)y / mDisplayScale.mV[VY]);
  527. if (down)
  528. {
  529. buttonstatestr = "down" ;
  530. }
  531. else
  532. {
  533. buttonstatestr = "up" ;
  534. }
  535. switch (clicktype)
  536. {
  537. case LLMouseHandler::CLICK_LEFT:
  538. mLeftMouseDown = down;
  539. buttonname = "Left";
  540. break;
  541. case LLMouseHandler::CLICK_RIGHT:
  542. mRightMouseDown = down;
  543. buttonname = "Right";
  544. break;
  545. case LLMouseHandler::CLICK_MIDDLE:
  546. mMiddleMouseDown = down;
  547. buttonname = "Middle";
  548. break;
  549. case LLMouseHandler::CLICK_DOUBLELEFT:
  550. mLeftMouseDown = down;
  551. buttonname = "Left Double Click";
  552. break;
  553. }
  554. LLView::sMouseHandlerMessage.clear();
  555. if (gMenuBarView)
  556. {
  557. // stop ALT-key access to menu
  558. gMenuBarView->resetMenuTrigger();
  559. }
  560. if (gDebugClicks)
  561. {
  562. llinfos << "ViewerWindow " << buttonname << " mouse " << buttonstatestr << " at " << x << "," << y << llendl;
  563. }
  564. // Make sure we get a corresponding mouseup event, even if the mouse leaves the window
  565. if (down)
  566. mWindow->captureMouse();
  567. else
  568. mWindow->releaseMouse();
  569. // Indicate mouse was active
  570. LLUI::resetMouseIdleTimer();
  571. // Don't let the user move the mouse out of the window until mouse up.
  572. if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() )
  573. {
  574. mWindow->setMouseClipping(down);
  575. }
  576. LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
  577. if( mouse_captor )
  578. {
  579. S32 local_x;
  580. S32 local_y;
  581. mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
  582. if (LLView::sDebugMouseHandling)
  583. {
  584. llinfos << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << llendl;
  585. }
  586. return mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down);
  587. }
  588. // Topmost view gets a chance before the hierarchy
  589. LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
  590. if (top_ctrl)
  591. {
  592. S32 local_x, local_y;
  593. top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
  594. if (down)
  595. {
  596. if (top_ctrl->pointInView(local_x, local_y))
  597. {
  598. return top_ctrl->handleAnyMouseClick(local_x, local_y, mask, clicktype, down) ;
  599. }
  600. else
  601. {
  602. gFocusMgr.setTopCtrl(NULL);
  603. }
  604. }
  605. else
  606. {
  607. if (top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleMouseUp(local_x, local_y, mask))
  608. {
  609. return TRUE;
  610. }
  611. }
  612. }
  613. // Give the UI views a chance to process the click
  614. if( mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) )
  615. {
  616. if (LLView::sDebugMouseHandling)
  617. {
  618. llinfos << buttonname << " Mouse " << buttonstatestr << " " << LLView::sMouseHandlerMessage << llendl;
  619. }
  620. return TRUE;
  621. }
  622. else if (LLView::sDebugMouseHandling)
  623. {
  624. llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl;
  625. }
  626. // Do not allow tool manager to handle mouseclicks if we have disconnected
  627. if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) )
  628. {
  629. return TRUE;
  630. }
  631. // If we got this far on a down-click, it wasn't handled.
  632. // Up-clicks, though, are always handled as far as the OS is concerned.
  633. BOOL default_rtn = !down;
  634. return default_rtn;
  635. }
  636. BOOL LLViewerWindow::handleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
  637. {
  638. BOOL down = TRUE;
  639. return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
  640. }
  641. BOOL LLViewerWindow::handleDoubleClick(LLWindow *window,  LLCoordGL pos, MASK mask)
  642. {
  643. // try handling as a double-click first, then a single-click if that
  644. // wasn't handled.
  645. BOOL down = TRUE;
  646. if (handleAnyMouseClick(window, pos, mask,
  647. LLMouseHandler::CLICK_DOUBLELEFT, down))
  648. {
  649. return TRUE;
  650. }
  651. return handleMouseDown(window, pos, mask);
  652. }
  653. BOOL LLViewerWindow::handleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
  654. {
  655. BOOL down = FALSE;
  656. return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
  657. }
  658. BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
  659. {
  660. S32 x = pos.mX;
  661. S32 y = pos.mY;
  662. x = llround((F32)x / mDisplayScale.mV[VX]);
  663. y = llround((F32)y / mDisplayScale.mV[VY]);
  664. BOOL down = TRUE;
  665. BOOL handle = handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
  666. if (handle)
  667. return handle;
  668. // *HACK: this should be rolled into the composite tool logic, not
  669. // hardcoded at the top level.
  670. if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance())
  671. {
  672. // If the current tool didn't process the click, we should show
  673. // the pie menu.  This can be done by passing the event to the pie
  674. // menu tool.
  675. LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
  676. // show_context_menu( x, y, mask );
  677. }
  678. return TRUE;
  679. }
  680. BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
  681. {
  682. BOOL down = FALSE;
  683.   return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
  684. }
  685. BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window,  LLCoordGL pos, MASK mask)
  686. {
  687. BOOL down = TRUE;
  688. gVoiceClient->middleMouseState(true);
  689.   handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
  690.   
  691.    // Always handled as far as the OS is concerned.
  692. return TRUE;
  693. }
  694. LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data)
  695. {
  696. LLWindowCallbacks::DragNDropResult result = LLWindowCallbacks::DND_NONE;
  697. const bool prim_media_dnd_enabled = gSavedSettings.getBOOL("PrimMediaDragNDrop");
  698. const bool slurl_dnd_enabled = gSavedSettings.getBOOL("SLURLDragNDrop");
  699. if ( prim_media_dnd_enabled || slurl_dnd_enabled )
  700. {
  701. switch(action)
  702. {
  703. // Much of the handling for these two cases is the same.
  704. case LLWindowCallbacks::DNDA_TRACK:
  705. case LLWindowCallbacks::DNDA_DROPPED:
  706. case LLWindowCallbacks::DNDA_START_TRACKING:
  707. {
  708. bool drop = (LLWindowCallbacks::DNDA_DROPPED == action);
  709. if (slurl_dnd_enabled)
  710. {
  711. // special case SLURLs
  712. if ( LLSLURL::isSLURL( data ) )
  713. {
  714. if (drop)
  715. {
  716. LLURLDispatcher::dispatch( data, NULL, true );
  717. LLURLSimString::setStringRaw( LLSLURL::stripProtocol( data ) );
  718. LLPanelLogin::refreshLocation( true );
  719. LLPanelLogin::updateLocationUI();
  720. }
  721. return LLWindowCallbacks::DND_MOVE;
  722. };
  723. }
  724. if (prim_media_dnd_enabled)
  725. {
  726. LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY,  TRUE /*BOOL pick_transparent*/ );
  727. LLUUID object_id = pick_info.getObjectID();
  728. S32 object_face = pick_info.mObjectFace;
  729. std::string url = data;
  730. lldebugs << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << llendl;
  731. LLVOVolume *obj = dynamic_cast<LLVOVolume*>(static_cast<LLViewerObject*>(pick_info.getObject()));
  732. if (obj && !obj->getRegion()->getCapability("ObjectMedia").empty())
  733. {
  734. LLTextureEntry *te = obj->getTE(object_face);
  735. if (te)
  736. {
  737. if (drop)
  738. {
  739. // object does NOT have media already
  740. if ( ! te->hasMedia() )
  741. {
  742. // we are allowed to modify the object
  743. if ( obj->permModify() )
  744. {
  745. // Create new media entry
  746. LLSD media_data;
  747. // XXX Should we really do Home URL too?
  748. media_data[LLMediaEntry::HOME_URL_KEY] = url;
  749. media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
  750. media_data[LLMediaEntry::AUTO_PLAY_KEY] = true;
  751. obj->syncMediaData(object_face, media_data, true, true);
  752. // XXX This shouldn't be necessary, should it ?!?
  753. if (obj->getMediaImpl(object_face))
  754. obj->getMediaImpl(object_face)->navigateReload();
  755. obj->sendMediaDataUpdate();
  756. result = LLWindowCallbacks::DND_COPY;
  757. }
  758. }
  759. else 
  760. // object HAS media already
  761. {
  762. // URL passes the whitelist
  763. if (te->getMediaData()->checkCandidateUrl( url ) )
  764. {
  765. // we are allowed to modify the object or we have navigate permissions
  766. // NOTE: Design states you you can change the URL if you have media 
  767. //       navigate permissions even if you do not have prim modify rights
  768. if ( obj->permModify() || obj->hasMediaPermission( te->getMediaData(), LLVOVolume::MEDIA_PERM_INTERACT ) )
  769. {
  770. // just navigate to the URL
  771. if (obj->getMediaImpl(object_face))
  772. {
  773. obj->getMediaImpl(object_face)->navigateTo(url);
  774. }
  775. else 
  776. {
  777. // This is very strange.  Navigation should
  778. // happen via the Impl, but we don't have one.
  779. // This sends it to the server, which /should/
  780. // trigger us getting it.  Hopefully.
  781. LLSD media_data;
  782. media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
  783. obj->syncMediaData(object_face, media_data, true, true);
  784. obj->sendMediaDataUpdate();
  785. }
  786. result = LLWindowCallbacks::DND_LINK;
  787. }
  788. }
  789. }
  790. LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
  791. mDragHoveredObject = NULL;
  792. }
  793. else 
  794. {
  795. // Check the whitelist, if there's media (otherwise just show it)
  796. if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url))
  797. {
  798. if ( obj != mDragHoveredObject)
  799. {
  800. // Highlight the dragged object
  801. LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
  802. mDragHoveredObject = obj;
  803. LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject);
  804. }
  805. result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK;
  806. }
  807. }
  808. }
  809. }
  810. }
  811. }
  812. break;
  813. case LLWindowCallbacks::DNDA_STOP_TRACKING:
  814. // The cleanup case below will make sure things are unhilighted if necessary.
  815. break;
  816. }
  817. if (prim_media_dnd_enabled &&
  818. result == LLWindowCallbacks::DND_NONE && !mDragHoveredObject.isNull())
  819. {
  820. LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
  821. mDragHoveredObject = NULL;
  822. }
  823. }
  824. return result;
  825. }
  826.   
  827. BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window,  LLCoordGL pos, MASK mask)
  828. {
  829. BOOL down = FALSE;
  830. gVoiceClient->middleMouseState(false);
  831.   handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
  832.   
  833.    // Always handled as far as the OS is concerned.
  834. return TRUE;
  835. }
  836. // WARNING: this is potentially called multiple times per frame
  837. void LLViewerWindow::handleMouseMove(LLWindow *window,  LLCoordGL pos, MASK mask)
  838. {
  839. S32 x = pos.mX;
  840. S32 y = pos.mY;
  841. x = llround((F32)x / mDisplayScale.mV[VX]);
  842. y = llround((F32)y / mDisplayScale.mV[VY]);
  843. mMouseInWindow = TRUE;
  844. // Save mouse point for access during idle() and display()
  845. LLCoordGL mouse_point(x, y);
  846. if (mouse_point != mCurrentMousePoint)
  847. {
  848. LLUI::resetMouseIdleTimer();
  849. }
  850. saveLastMouse(mouse_point);
  851. mWindow->showCursorFromMouseMove();
  852. if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
  853. {
  854. gAgent.clearAFK();
  855. }
  856. }
  857. void LLViewerWindow::handleMouseLeave(LLWindow *window)
  858. {
  859. // Note: we won't get this if we have captured the mouse.
  860. llassert( gFocusMgr.getMouseCapture() == NULL );
  861. mMouseInWindow = FALSE;
  862. LLToolTipMgr::instance().blockToolTips();
  863. }
  864. BOOL LLViewerWindow::handleCloseRequest(LLWindow *window)
  865. {
  866. // User has indicated they want to close, but we may need to ask
  867. // about modified documents.
  868. LLAppViewer::instance()->userQuit();
  869. // Don't quit immediately
  870. return FALSE;
  871. }
  872. void LLViewerWindow::handleQuit(LLWindow *window)
  873. {
  874. LLAppViewer::instance()->forceQuit();
  875. }
  876. void LLViewerWindow::handleResize(LLWindow *window,  S32 width,  S32 height)
  877. {
  878. reshape(width, height);
  879. mResDirty = true;
  880. }
  881. // The top-level window has gained focus (e.g. via ALT-TAB)
  882. void LLViewerWindow::handleFocus(LLWindow *window)
  883. {
  884. gFocusMgr.setAppHasFocus(TRUE);
  885. LLModalDialog::onAppFocusGained();
  886. gAgent.onAppFocusGained();
  887. LLToolMgr::getInstance()->onAppFocusGained();
  888. // See if we're coming in with modifier keys held down
  889. if (gKeyboard)
  890. {
  891. gKeyboard->resetMaskKeys();
  892. }
  893. // resume foreground running timer
  894. // since we artifically limit framerate when not frontmost
  895. gForegroundTime.unpause();
  896. }
  897. // The top-level window has lost focus (e.g. via ALT-TAB)
  898. void LLViewerWindow::handleFocusLost(LLWindow *window)
  899. {
  900. gFocusMgr.setAppHasFocus(FALSE);
  901. //LLModalDialog::onAppFocusLost();
  902. LLToolMgr::getInstance()->onAppFocusLost();
  903. gFocusMgr.setMouseCapture( NULL );
  904. if (gMenuBarView)
  905. {
  906. // stop ALT-key access to menu
  907. gMenuBarView->resetMenuTrigger();
  908. }
  909. // restore mouse cursor
  910. showCursor();
  911. getWindow()->setMouseClipping(FALSE);
  912. // If losing focus while keys are down, reset them.
  913. if (gKeyboard)
  914. {
  915. gKeyboard->resetKeys();
  916. }
  917. // pause timer that tracks total foreground running time
  918. gForegroundTime.pause();
  919. }
  920. BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key,  MASK mask, BOOL repeated)
  921. {
  922. // Let the voice chat code check for its PTT key.  Note that this never affects event processing.
  923. gVoiceClient->keyDown(key, mask);
  924. if (gAwayTimer.getElapsedTimeF32() > MIN_AFK_TIME)
  925. {
  926. gAgent.clearAFK();
  927. }
  928. // *NOTE: We want to interpret KEY_RETURN later when it arrives as
  929. // a Unicode char, not as a keydown.  Otherwise when client frame
  930. // rate is really low, hitting return sends your chat text before
  931. // it's all entered/processed.
  932. if (key == KEY_RETURN && mask == MASK_NONE)
  933. {
  934. return FALSE;
  935. }
  936. return gViewerKeyboard.handleKey(key, mask, repeated);
  937. }
  938. BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key,  MASK mask)
  939. {
  940. // Let the voice chat code check for its PTT key.  Note that this never affects event processing.
  941. gVoiceClient->keyUp(key, mask);
  942. return FALSE;
  943. }
  944. void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
  945. {
  946. LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
  947. return gViewerKeyboard.scanKey(key, key_down, key_up, key_level);
  948. }
  949. BOOL LLViewerWindow::handleActivate(LLWindow *window, BOOL activated)
  950. {
  951. if (activated)
  952. {
  953. mActive = TRUE;
  954. send_agent_resume();
  955. gAgent.clearAFK();
  956. if (mWindow->getFullscreen() && !mIgnoreActivate)
  957. {
  958. if (!LLApp::isExiting() )
  959. {
  960. if (LLStartUp::getStartupState() >= STATE_STARTED)
  961. {
  962. // if we're in world, show a progress bar to hide reloading of textures
  963. llinfos << "Restoring GL during activate" << llendl;
  964. restoreGL("Restoring...");
  965. }
  966. else
  967. {
  968. // otherwise restore immediately
  969. restoreGL();
  970. }
  971. }
  972. else
  973. {
  974. llwarns << "Activating while quitting" << llendl;
  975. }
  976. }
  977. // Unmute audio
  978. audio_update_volume();
  979. }
  980. else
  981. {
  982. mActive = FALSE;
  983. if (gSavedSettings.getS32("AFKTimeout"))
  984. {
  985. gAgent.setAFK();
  986. }
  987. // SL-53351: Make sure we're not in mouselook when minimised, to prevent control issues
  988. if (gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
  989. {
  990. gAgent.changeCameraToDefault();
  991. }
  992. send_agent_pause();
  993. if (mWindow->getFullscreen() && !mIgnoreActivate)
  994. {
  995. llinfos << "Stopping GL during deactivation" << llendl;
  996. stopGL();
  997. }
  998. // Mute audio
  999. audio_update_volume();
  1000. }
  1001. return TRUE;
  1002. }
  1003. BOOL LLViewerWindow::handleActivateApp(LLWindow *window, BOOL activating)
  1004. {
  1005. //if (!activating) gAgent.changeCameraToDefault();
  1006. LLViewerJoystick::getInstance()->setNeedsReset(true);
  1007. return FALSE;
  1008. }
  1009. void LLViewerWindow::handleMenuSelect(LLWindow *window,  S32 menu_item)
  1010. {
  1011. }
  1012. BOOL LLViewerWindow::handlePaint(LLWindow *window,  S32 x,  S32 y, S32 width,  S32 height)
  1013. {
  1014. #if LL_WINDOWS
  1015. if (gNoRender)
  1016. {
  1017. HWND window_handle = (HWND)window->getPlatformWindow();
  1018. PAINTSTRUCT ps; 
  1019. HDC hdc; 
  1020.  
  1021. RECT wnd_rect;
  1022. wnd_rect.left = 0;
  1023. wnd_rect.top = 0;
  1024. wnd_rect.bottom = 200;
  1025. wnd_rect.right = 500;
  1026. hdc = BeginPaint(window_handle, &ps); 
  1027. //SetBKColor(hdc, RGB(255, 255, 255));
  1028. FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255)));
  1029. std::string name_str;
  1030. LLAgentUI::buildName(name_str);
  1031. std::string temp_str;
  1032. temp_str = llformat( "%s FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */
  1033. name_str.c_str(),
  1034. LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(),
  1035. LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0),
  1036. LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0));
  1037. S32 len = temp_str.length();
  1038. TextOutA(hdc, 0, 0, temp_str.c_str(), len); 
  1039. LLVector3d pos_global = gAgent.getPositionGlobal();
  1040. temp_str = llformat( "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]);
  1041. len = temp_str.length();
  1042. TextOutA(hdc, 0, 25, temp_str.c_str(), len); 
  1043. TextOutA(hdc, 0, 50, "Set "DisableRendering FALSE" in settings.ini file to reenable", 61);
  1044. EndPaint(window_handle, &ps); 
  1045. return TRUE;
  1046. }
  1047. #endif
  1048. return FALSE;
  1049. }
  1050. void LLViewerWindow::handleScrollWheel(LLWindow *window,  S32 clicks)
  1051. {
  1052. handleScrollWheel( clicks );
  1053. }
  1054. void LLViewerWindow::handleWindowBlock(LLWindow *window)
  1055. {
  1056. send_agent_pause();
  1057. }
  1058. void LLViewerWindow::handleWindowUnblock(LLWindow *window)
  1059. {
  1060. send_agent_resume();
  1061. }
  1062. void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data)
  1063. {
  1064. const S32 SLURL_MESSAGE_TYPE = 0;
  1065. switch (data_type)
  1066. {
  1067. case SLURL_MESSAGE_TYPE:
  1068. // received URL
  1069. std::string url = (const char*)data;
  1070. LLMediaCtrl* web = NULL;
  1071. const bool trusted_browser = false;
  1072. if (LLURLDispatcher::dispatch(url, web, trusted_browser))
  1073. {
  1074. // bring window to foreground, as it has just been "launched" from a URL
  1075. mWindow->bringToFront();
  1076. }
  1077. break;
  1078. }
  1079. }
  1080. BOOL LLViewerWindow::handleTimerEvent(LLWindow *window)
  1081. {
  1082. if (LLViewerJoystick::getInstance()->getOverrideCamera())
  1083. {
  1084. LLViewerJoystick::getInstance()->updateStatus();
  1085. return TRUE;
  1086. }
  1087. return FALSE;
  1088. }
  1089. BOOL LLViewerWindow::handleDeviceChange(LLWindow *window)
  1090. {
  1091. // give a chance to use a joystick after startup (hot-plugging)
  1092. if (!LLViewerJoystick::getInstance()->isJoystickInitialized() )
  1093. {
  1094. LLViewerJoystick::getInstance()->init(true);
  1095. return TRUE;
  1096. }
  1097. return FALSE;
  1098. }
  1099. void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg)
  1100. {
  1101. LLAppViewer::instance()->pingMainloopTimeout(msg);
  1102. }
  1103. void LLViewerWindow::handleResumeWatchdog(LLWindow *window)
  1104. {
  1105. LLAppViewer::instance()->resumeMainloopTimeout();
  1106. }
  1107. void LLViewerWindow::handlePauseWatchdog(LLWindow *window)
  1108. {
  1109. LLAppViewer::instance()->pauseMainloopTimeout();
  1110. }
  1111. //virtual
  1112. std::string LLViewerWindow::translateString(const char* tag)
  1113. {
  1114. return LLTrans::getString( std::string(tag) );
  1115. }
  1116. //virtual
  1117. std::string LLViewerWindow::translateString(const char* tag,
  1118. const std::map<std::string, std::string>& args)
  1119. {
  1120. // LLTrans uses a special subclass of std::string for format maps,
  1121. // but we must use std::map<> in these callbacks, otherwise we create
  1122. // a dependency between LLWindow and LLFormatMapString.  So copy the data.
  1123. LLStringUtil::format_map_t args_copy;
  1124. std::map<std::string,std::string>::const_iterator it = args.begin();
  1125. for ( ; it != args.end(); ++it)
  1126. {
  1127. args_copy[it->first] = it->second;
  1128. }
  1129. return LLTrans::getString( std::string(tag), args_copy);
  1130. }
  1131. //
  1132. // Classes
  1133. //
  1134. LLViewerWindow::LLViewerWindow(
  1135. const std::string& title, const std::string& name,
  1136. S32 x, S32 y,
  1137. S32 width, S32 height,
  1138. BOOL fullscreen, BOOL ignore_pixel_depth)
  1139. :
  1140. mWindow(NULL),
  1141. mActive(TRUE),
  1142. mWantFullscreen(fullscreen),
  1143. mShowFullscreenProgress(FALSE),
  1144. mWindowRectRaw(0, height, width, 0),
  1145. mWindowRectScaled(0, height, width, 0),
  1146. mWorldViewRectRaw(0, height, width, 0),
  1147. mLeftMouseDown(FALSE),
  1148. mMiddleMouseDown(FALSE),
  1149. mRightMouseDown(FALSE),
  1150. mMouseInWindow( FALSE ),
  1151. mLastMask( MASK_NONE ),
  1152. mToolStored( NULL ),
  1153. mHideCursorPermanent( FALSE ),
  1154. mCursorHidden(FALSE),
  1155. mIgnoreActivate( FALSE ),
  1156. mResDirty(false),
  1157. mStatesDirty(false),
  1158. mIsFullscreenChecked(false),
  1159. mCurrResolutionIndex(0),
  1160.     mViewerWindowListener(new LLViewerWindowListener(this))
  1161. {
  1162. LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
  1163. LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
  1164. LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert);
  1165. LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert);
  1166. LLNotifications::instance().setIgnoreAllNotifications(gSavedSettings.getBOOL("IgnoreAllNotifications"));
  1167. llinfos << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << llendl;
  1168. // Default to application directory.
  1169. LLViewerWindow::sSnapshotBaseName = "Snapshot";
  1170. LLViewerWindow::sMovieBaseName = "SLmovie";
  1171. resetSnapshotLoc();
  1172. // create window
  1173. mWindow = LLWindowManager::createWindow(this,
  1174. title, name, x, y, width, height, 0,
  1175. fullscreen, 
  1176. gNoRender,
  1177. gSavedSettings.getBOOL("DisableVerticalSync"),
  1178. !gNoRender,
  1179. ignore_pixel_depth,
  1180. gSavedSettings.getU32("RenderFSAASamples"));
  1181. if (!LLAppViewer::instance()->restoreErrorTrap())
  1182. {
  1183. LL_WARNS("Window") << " Someone took over my signal/exception handler (post createWindow)!" << LL_ENDL;
  1184. }
  1185. if (NULL == mWindow)
  1186. {
  1187. LLSplashScreen::update("Shutting down...");
  1188. #if LL_LINUX || LL_SOLARIS
  1189. 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."
  1190. << llendl;
  1191. #else
  1192. LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings"
  1193. << LL_ENDL;
  1194. #endif
  1195.         LLAppViewer::instance()->forceExit(1);
  1196. }
  1197. // Get the real window rect the window was created with (since there are various OS-dependent reasons why
  1198. // the size of a window or fullscreen context may have been adjusted slightly...)
  1199. F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
  1200. mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
  1201. mDisplayScale *= ui_scale_factor;
  1202. LLUI::setScaleFactor(mDisplayScale);
  1203. {
  1204. LLCoordWindow size;
  1205. mWindow->getSize(&size);
  1206. mWindowRectRaw.set(0, size.mY, size.mX, 0);
  1207. mWindowRectScaled.set(0, llround((F32)size.mY / mDisplayScale.mV[VY]), llround((F32)size.mX / mDisplayScale.mV[VX]), 0);
  1208. }
  1209. LLFontManager::initClass();
  1210. //
  1211. // We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off
  1212. // stuff like AGP if we think that it'll crash the viewer.
  1213. //
  1214. LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL;
  1215. LLFeatureManager::getInstance()->init();
  1216. // Initialize OpenGL Renderer
  1217. if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
  1218. !gGLManager.mHasVertexBufferObject)
  1219. {
  1220. gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
  1221. }
  1222. LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"));
  1223. if (LLFeatureManager::getInstance()->isSafe()
  1224. || (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion())
  1225. || (gSavedSettings.getBOOL("ProbeHardwareOnStartup")))
  1226. {
  1227. LLFeatureManager::getInstance()->applyRecommendedSettings();
  1228. gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
  1229. }
  1230. // If we crashed while initializng GL stuff last time, disable certain features
  1231. if (gSavedSettings.getBOOL("RenderInitError"))
  1232. {
  1233. mInitAlert = "DisplaySettingsNoShaders";
  1234. LLFeatureManager::getInstance()->setGraphicsLevel(0, false);
  1235. gSavedSettings.setU32("RenderQualityPerformance", 0);
  1236. }
  1237. // Init the image list.  Must happen after GL is initialized and before the images that
  1238. // LLViewerWindow needs are requested.
  1239. LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ;
  1240. gTextureList.init();
  1241. LLViewerTextureManager::init() ;
  1242. gBumpImageList.init();
  1243. // Init font system, but don't actually load the fonts yet
  1244. // because our window isn't onscreen and they take several
  1245. // seconds to parse.
  1246. LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
  1247. mDisplayScale.mV[VX],
  1248. mDisplayScale.mV[VY],
  1249. gDirUtilp->getAppRODataDir(),
  1250. LLUI::getXUIPaths());
  1251. // Create container for all sub-views
  1252. LLView::Params rvp;
  1253. rvp.name("root");
  1254. rvp.rect(mWindowRectScaled);
  1255. rvp.mouse_opaque(false);
  1256. rvp.follows.flags(FOLLOWS_NONE);
  1257. mRootView = LLUICtrlFactory::create<LLRootView>(rvp);
  1258. LLUI::setRootView(mRootView);
  1259. // Make avatar head look forward at start
  1260. mCurrentMousePoint.mX = getWindowWidthScaled() / 2;
  1261. mCurrentMousePoint.mY = getWindowHeightScaled() / 2;
  1262. gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle");
  1263. mOverlayTitle = gSavedSettings.getString("OverlayTitle");
  1264. // Can't have spaces in settings.ini strings, so use underscores instead and convert them.
  1265. LLStringUtil::replaceChar(mOverlayTitle, '_', ' ');
  1266. // sync the keyboard's setting with the saved setting
  1267. gSavedSettings.getControl("NumpadControl")->firePropertyChanged();
  1268. mDebugText = new LLDebugText(this);
  1269. mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
  1270. }
  1271. void LLViewerWindow::initGLDefaults()
  1272. {
  1273. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  1274. glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
  1275. F32 ambient[4] = {0.f,0.f,0.f,0.f };
  1276. F32 diffuse[4] = {1.f,1.f,1.f,1.f };
  1277. glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambient);
  1278. glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,diffuse);
  1279. glPixelStorei(GL_PACK_ALIGNMENT,1);
  1280. glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  1281. gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
  1282. // lights for objects
  1283. glShadeModel( GL_SMOOTH );
  1284. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
  1285. gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
  1286. glCullFace(GL_BACK);
  1287. // RN: Need this for translation and stretch manip.
  1288. gCone.prerender();
  1289. gBox.prerender();
  1290. gSphere.prerender();
  1291. gCylinder.prerender();
  1292. }
  1293. struct MainPanel : public LLPanel
  1294. {
  1295. };
  1296. void LLViewerWindow::initBase()
  1297. {
  1298. S32 height = getWindowHeightScaled();
  1299. S32 width = getWindowWidthScaled();
  1300. LLRect full_window(0, height, width, 0);
  1301. ////////////////////
  1302. //
  1303. // Set the gamma
  1304. //
  1305. F32 gamma = gSavedSettings.getF32("RenderGamma");
  1306. if (gamma != 0.0f)
  1307. {
  1308. getWindow()->setGamma(gamma);
  1309. }
  1310. // Create global views
  1311. // Create the floater view at the start so that other views can add children to it. 
  1312. // (But wait to add it as a child of the root view so that it will be in front of the 
  1313. // other views.)
  1314. MainPanel* main_view = new MainPanel();
  1315. LLUICtrlFactory::instance().buildPanel(main_view, "main_view.xml");
  1316. main_view->setShape(full_window);
  1317. getRootView()->addChild(main_view);
  1318. // placeholder widget that controls where "world" is rendered
  1319. mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle();
  1320. mNonSideTrayView = main_view->getChildView("non_side_tray_view")->getHandle();
  1321. mFloaterViewHolder = main_view->getChildView("floater_view_holder")->getHandle();
  1322. // Constrain floaters to inside the menu and status bar regions.
  1323. gFloaterView = main_view->getChild<LLFloaterView>("Floater View");
  1324. gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View");
  1325. // Console
  1326. llassert( !gConsole );
  1327. LLConsole::Params cp;
  1328. cp.name("console");
  1329. cp.max_lines(gSavedSettings.getS32("ConsoleBufferSize"));
  1330. cp.rect(getChatConsoleRect());
  1331. cp.persist_time(gSavedSettings.getF32("ChatPersistTime"));
  1332. cp.font_size_index(gSavedSettings.getS32("ChatFontSize"));
  1333. cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
  1334. gConsole = LLUICtrlFactory::create<LLConsole>(cp);
  1335. getRootView()->addChild(gConsole);
  1336. // optionally forward warnings to chat console/chat floater
  1337. // for qa runs and dev builds
  1338. #if  !LL_RELEASE_FOR_DOWNLOAD
  1339. LLError::addRecorder(RecordToChatConsole::getInstance());
  1340. #else
  1341. if(gSavedSettings.getBOOL("QAMode"))
  1342. {
  1343. LLError::addRecorder(RecordToChatConsole::getInstance());
  1344. }
  1345. #endif
  1346. gDebugView = getRootView()->getChild<LLDebugView>("DebugView");
  1347. gDebugView->init();
  1348. gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view");
  1349. // Add the progress bar view (startup view), which overrides everything
  1350. mProgressView = new LLProgressView(full_window);
  1351. getRootView()->addChild(mProgressView);
  1352. setShowProgress(FALSE);
  1353. setProgressCancelButtonVisible(FALSE);
  1354. gMenuHolder = getRootView()->getChild<LLViewerMenuHolderGL>("Menu Holder");
  1355. LLMenuGL::sMenuContainer = gMenuHolder;
  1356. }
  1357. void LLViewerWindow::initWorldUI()
  1358. {
  1359. S32 height = mRootView->getRect().getHeight();
  1360. S32 width = mRootView->getRect().getWidth();
  1361. LLRect full_window(0, height, width, 0);
  1362. gIMMgr = LLIMMgr::getInstance();
  1363. getRootView()->sendChildToFront(gFloaterView);
  1364. getRootView()->sendChildToFront(gSnapshotFloaterView);
  1365. // new bottom panel
  1366. LLPanel* bottom_tray_container = getRootView()->getChild<LLPanel>("bottom_tray_container");
  1367. LLBottomTray* bottom_tray = LLBottomTray::getInstance();
  1368. bottom_tray->setShape(bottom_tray_container->getLocalRect());
  1369. bottom_tray->setFollowsAll();
  1370. bottom_tray_container->addChild(bottom_tray);
  1371. bottom_tray_container->setVisible(TRUE);
  1372. LLRect morph_view_rect = full_window;
  1373. morph_view_rect.stretch( -STATUS_BAR_HEIGHT );
  1374. morph_view_rect.mTop = full_window.mTop - 32;
  1375. LLMorphView::Params mvp;
  1376. mvp.name("MorphView");
  1377. mvp.rect(morph_view_rect);
  1378. mvp.visible(false);
  1379. gMorphView = LLUICtrlFactory::create<LLMorphView>(mvp);
  1380. getRootView()->addChild(gMorphView);
  1381. LLWorldMapView::initClass();
  1382. // Force gFloaterWorldMap to initialize
  1383. LLFloaterReg::getInstance("world_map");
  1384. // Force gFloaterTools to initialize
  1385. LLFloaterReg::getInstance("build");
  1386. LLFloaterReg::hideInstance("build");
  1387. // Status bar
  1388. LLPanel* status_bar_container = getRootView()->getChild<LLPanel>("status_bar_container");
  1389. gStatusBar = new LLStatusBar(status_bar_container->getLocalRect());
  1390. gStatusBar->setFollowsAll();
  1391. gStatusBar->setShape(status_bar_container->getLocalRect());
  1392. // sync bg color with menu bar
  1393. gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() );
  1394. status_bar_container->addChild(gStatusBar);
  1395. status_bar_container->setVisible(TRUE);
  1396. // Navigation bar
  1397. LLPanel* nav_bar_container = getRootView()->getChild<LLPanel>("nav_bar_container");
  1398. LLNavigationBar* navbar = LLNavigationBar::getInstance();
  1399. navbar->setShape(nav_bar_container->getLocalRect());
  1400. navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get());
  1401. nav_bar_container->addChild(navbar);
  1402. nav_bar_container->setVisible(TRUE);
  1403. if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))
  1404. {
  1405. navbar->showNavigationPanel(FALSE);
  1406. }
  1407. if (!gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"))
  1408. {
  1409. navbar->showFavoritesPanel(FALSE);
  1410. }
  1411. if (!gSavedSettings.getBOOL("ShowCameraButton"))
  1412. {
  1413. LLBottomTray::getInstance()->showCameraButton(FALSE);
  1414. }
  1415. if (!gSavedSettings.getBOOL("ShowSnapshotButton"))
  1416. {
  1417. LLBottomTray::getInstance()->showSnapshotButton(FALSE);
  1418. }
  1419. if (!gSavedSettings.getBOOL("ShowMoveButton"))
  1420. {
  1421. LLBottomTray::getInstance()->showMoveButton(FALSE);
  1422. }
  1423. if (!gSavedSettings.getBOOL("ShowGestureButton"))
  1424. {
  1425. LLBottomTray::getInstance()->showGestureButton(FALSE);
  1426. }
  1427. if ( gHUDView == NULL )
  1428. {
  1429. LLRect hud_rect = full_window;
  1430. hud_rect.mBottom += 50;
  1431. if (gMenuBarView)
  1432. {
  1433. hud_rect.mTop -= gMenuBarView->getRect().getHeight();
  1434. }
  1435. gHUDView = new LLHUDView(hud_rect);
  1436. // put behind everything else in the UI
  1437. getRootView()->addChildInBack(gHUDView);
  1438. }
  1439. LLPanel* panel_ssf_container = getRootView()->getChild<LLPanel>("stand_stop_flying_container");
  1440. LLPanelStandStopFlying* panel_stand_stop_flying = LLPanelStandStopFlying::getInstance();
  1441. panel_ssf_container->addChild(panel_stand_stop_flying);
  1442. panel_ssf_container->setVisible(TRUE);
  1443. // put sidetray in container
  1444. LLPanel* side_tray_container = getRootView()->getChild<LLPanel>("side_tray_container");
  1445. LLSideTray* sidetrayp = LLSideTray::getInstance();
  1446. sidetrayp->setShape(side_tray_container->getLocalRect());
  1447. // don't follow right edge to avoid spurious resizes, since we are using a fixed width layout
  1448. sidetrayp->setFollows(FOLLOWS_LEFT|FOLLOWS_TOP|FOLLOWS_BOTTOM);
  1449. side_tray_container->addChild(sidetrayp);
  1450. side_tray_container->setVisible(FALSE);
  1451. // put sidetray buttons in their own panel
  1452. LLPanel* buttons_panel = sidetrayp->getButtonsPanel();
  1453. LLPanel* buttons_panel_container = getRootView()->getChild<LLPanel>("side_bar_tabs");
  1454. buttons_panel->setShape(buttons_panel_container->getLocalRect());
  1455. buttons_panel->setFollowsAll();
  1456. buttons_panel_container->addChild(buttons_panel);
  1457. }
  1458. // Destroy the UI
  1459. void LLViewerWindow::shutdownViews()
  1460. {
  1461. // clean up warning logger
  1462. LLError::removeRecorder(RecordToChatConsole::getInstance());
  1463. delete mDebugText;
  1464. mDebugText = NULL;
  1465. // Cleanup global views
  1466. if (gMorphView)
  1467. {
  1468. gMorphView->setVisible(FALSE);
  1469. }
  1470. // DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open
  1471. // will crump with LL_ERRS.
  1472. LLModalDialog::shutdownModals();
  1473. // destroy the nav bar, not currently part of gViewerWindow
  1474. // *TODO: Make LLNavigationBar part of gViewerWindow
  1475. delete LLNavigationBar::getInstance();
  1476. // destroy menus after instantiating navbar above, as it needs
  1477. // access to gMenuHolder
  1478. cleanup_menus();
  1479. // Delete all child views.
  1480. delete mRootView;
  1481. mRootView = NULL;
  1482. // Automatically deleted as children of mRootView.  Fix the globals.
  1483. gStatusBar = NULL;
  1484. gIMMgr = NULL;
  1485. gToolTipView = NULL;
  1486. gFloaterView = NULL;
  1487. gMorphView = NULL;
  1488. gHUDView = NULL;
  1489. }
  1490. void LLViewerWindow::shutdownGL()
  1491. {
  1492. //--------------------------------------------------------
  1493. // Shutdown GL cleanly.  Order is very important here.
  1494. //--------------------------------------------------------
  1495. LLFontGL::destroyDefaultFonts();
  1496. LLFontManager::cleanupClass();
  1497. stop_glerror();
  1498. gSky.cleanup();
  1499. stop_glerror();
  1500. LLWearableList::instance().cleanup() ;
  1501. gTextureList.shutdown();
  1502. stop_glerror();
  1503. gBumpImageList.shutdown();
  1504. stop_glerror();
  1505. LLWorldMapView::cleanupTextures();
  1506. llinfos << "Cleaning up pipeline" << llendl;
  1507. gPipeline.cleanup();
  1508. stop_glerror();
  1509. LLViewerTextureManager::cleanup() ;
  1510. LLImageGL::cleanupClass() ;
  1511. llinfos << "All textures and llimagegl images are destroyed!" << llendl ;
  1512. llinfos << "Cleaning up select manager" << llendl;
  1513. LLSelectMgr::getInstance()->cleanup();
  1514. LLVertexBuffer::cleanupClass();
  1515. llinfos << "Stopping GL during shutdown" << llendl;
  1516. if (!gNoRender)
  1517. {
  1518. stopGL(FALSE);
  1519. stop_glerror();
  1520. }
  1521. gGL.shutdown();
  1522. }
  1523. // shutdownViews() and shutdownGL() need to be called first
  1524. LLViewerWindow::~LLViewerWindow()
  1525. {
  1526. llinfos << "Destroying Window" << llendl;
  1527. destroyWindow();
  1528. delete mDebugText;
  1529. mDebugText = NULL;
  1530. }
  1531. void LLViewerWindow::setCursor( ECursorType c )
  1532. {
  1533. mWindow->setCursor( c );
  1534. }
  1535. void LLViewerWindow::showCursor()
  1536. {
  1537. mWindow->showCursor();
  1538. mCursorHidden = FALSE;
  1539. }
  1540. void LLViewerWindow::hideCursor()
  1541. {
  1542. // And hide the cursor
  1543. mWindow->hideCursor();
  1544. mCursorHidden = TRUE;
  1545. }
  1546. void LLViewerWindow::sendShapeToSim()
  1547. {
  1548. LLMessageSystem* msg = gMessageSystem;
  1549. if(!msg) return;
  1550. msg->newMessageFast(_PREHASH_AgentHeightWidth);
  1551. msg->nextBlockFast(_PREHASH_AgentData);
  1552. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  1553. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  1554. msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode);
  1555. msg->nextBlockFast(_PREHASH_HeightWidthBlock);
  1556. msg->addU32Fast(_PREHASH_GenCounter, 0);
  1557. U16 height16 = (U16) mWorldViewRectRaw.getHeight();
  1558. U16 width16 = (U16) mWorldViewRectRaw.getWidth();
  1559. msg->addU16Fast(_PREHASH_Height, height16);
  1560. msg->addU16Fast(_PREHASH_Width, width16);
  1561. gAgent.sendReliableMessage();
  1562. }
  1563. // Must be called after window is created to set up agent
  1564. // camera variables and UI variables.
  1565. void LLViewerWindow::reshape(S32 width, S32 height)
  1566. {
  1567. // Destroying the window at quit time generates spurious
  1568. // reshape messages.  We don't care about these, and we
  1569. // don't want to send messages because the message system
  1570. // may have been destructed.
  1571. if (!LLApp::isExiting())
  1572. {
  1573. if (gNoRender)
  1574. {
  1575. return;
  1576. }
  1577. // update our window rectangle
  1578. mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width;
  1579. mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height;
  1580. //glViewport(0, 0, width, height );
  1581. if (height > 0)
  1582. LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
  1583. LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
  1584. }
  1585. calcDisplayScale();
  1586. BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor;
  1587. LLUI::setScaleFactor(mDisplayScale);
  1588. // update our window rectangle
  1589. mWindowRectScaled.mRight = mWindowRectScaled.mLeft + llround((F32)width / mDisplayScale.mV[VX]);
  1590. mWindowRectScaled.mTop = mWindowRectScaled.mBottom + llround((F32)height / mDisplayScale.mV[VY]);
  1591. setup2DViewport();
  1592. // Inform lower views of the change
  1593. // round up when converting coordinates to make sure there are no gaps at edge of window
  1594. LLView::sForceReshape = display_scale_changed;
  1595. mRootView->reshape(llceil((F32)width / mDisplayScale.mV[VX]), llceil((F32)height / mDisplayScale.mV[VY]));
  1596. LLView::sForceReshape = FALSE;
  1597. // clear font width caches
  1598. if (display_scale_changed)
  1599. {
  1600. LLHUDText::reshape();
  1601. }
  1602. sendShapeToSim();
  1603. // store the mode the user wants (even if not there yet)
  1604. gSavedSettings.setBOOL("WindowFullScreen", mWantFullscreen);
  1605. // store new settings for the mode we are in, regardless
  1606. if (!mWindow->getFullscreen())
  1607. {
  1608. // Only save size if not maximized
  1609. BOOL maximized = mWindow->getMaximized();
  1610. gSavedSettings.setBOOL("WindowMaximized", maximized);
  1611. LLCoordScreen window_size;
  1612. if (!maximized
  1613. && mWindow->getSize(&window_size))
  1614. {
  1615. gSavedSettings.setS32("WindowWidth", window_size.mX);
  1616. gSavedSettings.setS32("WindowHeight", window_size.mY);
  1617. }
  1618. }
  1619. LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width);
  1620. LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height);
  1621. }
  1622. }
  1623. // Hide normal UI when a logon fails
  1624. void LLViewerWindow::setNormalControlsVisible( BOOL visible )
  1625. {
  1626. if(LLBottomTray::instanceExists())
  1627. {
  1628. LLBottomTray::getInstance()->setVisible(visible);
  1629. LLBottomTray::getInstance()->setEnabled(visible);
  1630. }
  1631. if ( gMenuBarView )
  1632. {
  1633. gMenuBarView->setVisible( visible );
  1634. gMenuBarView->setEnabled( visible );
  1635. // ...and set the menu color appropriately.
  1636. setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, 
  1637. LLViewerLogin::getInstance()->isInProductionGrid());
  1638. }
  1639.         
  1640. if ( gStatusBar )
  1641. {
  1642. gStatusBar->setVisible( visible );
  1643. gStatusBar->setEnabled( visible );
  1644. }
  1645. LLNavigationBar* navbarp = LLUI::getRootView()->findChild<LLNavigationBar>("navigation_bar");
  1646. if (navbarp)
  1647. {
  1648. navbarp->setVisible( visible );
  1649. }
  1650. }
  1651. void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
  1652. {
  1653.     LLSD args;
  1654.     LLColor4 new_bg_color;
  1655.     if(god_mode && LLViewerLogin::getInstance()->isInProductionGrid())
  1656.     {
  1657.         new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" );
  1658.     }
  1659.     else if(god_mode && !LLViewerLogin::getInstance()->isInProductionGrid())
  1660.     {
  1661.         new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" );
  1662.     }
  1663.     else if(!god_mode && !LLViewerLogin::getInstance()->isInProductionGrid())
  1664.     {
  1665.         new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" );
  1666.     }
  1667.     else 
  1668.     {
  1669.         new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" );
  1670.     }
  1671.     if(gMenuBarView)
  1672.     {
  1673.         gMenuBarView->setBackgroundColor( new_bg_color );
  1674.     }
  1675.     if(gStatusBar)
  1676.     {
  1677.         gStatusBar->setBackgroundColor( new_bg_color );
  1678.     }
  1679. }
  1680. void LLViewerWindow::drawDebugText()
  1681. {
  1682. gGL.color4f(1,1,1,1);
  1683. gGL.pushMatrix();
  1684. {
  1685. // scale view by UI global scale factor and aspect ratio correction factor
  1686. glScalef(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
  1687. mDebugText->draw();
  1688. }
  1689. gGL.popMatrix();
  1690. gGL.flush();
  1691. }
  1692. void LLViewerWindow::draw()
  1693. {
  1694. #if LL_DEBUG
  1695. LLView::sIsDrawing = TRUE;
  1696. #endif
  1697. stop_glerror();
  1698. LLUI::setLineWidth(1.f);
  1699. LLUI::setLineWidth(1.f);
  1700. // Reset any left-over transforms
  1701. glMatrixMode(GL_MODELVIEW);
  1702. glLoadIdentity();
  1703. //S32 screen_x, screen_y;
  1704. if (!gSavedSettings.getBOOL("RenderUIBuffer"))
  1705. {
  1706. LLUI::sDirtyRect = getWindowRectScaled();
  1707. }
  1708. // HACK for timecode debugging
  1709. if (gSavedSettings.getBOOL("DisplayTimecode"))
  1710. {
  1711. // draw timecode block
  1712. std::string text;
  1713. glLoadIdentity();
  1714. microsecondsToTimecodeString(gFrameTime,text);
  1715. const LLFontGL* font = LLFontGL::getFontSansSerif();
  1716. font->renderUTF8(text, 0,
  1717. llround((getWindowWidthScaled()/2)-100.f),
  1718. llround((getWindowHeightScaled()-60.f)),
  1719. LLColor4( 1.f, 1.f, 1.f, 1.f ),
  1720. LLFontGL::LEFT, LLFontGL::TOP);
  1721. }
  1722. // Draw all nested UI views.
  1723. // No translation needed, this view is glued to 0,0
  1724. gGL.pushMatrix();
  1725. {
  1726. // scale view by UI global scale factor and aspect ratio correction factor
  1727. glScalef(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f);
  1728. LLVector2 old_scale_factor = LLUI::sGLScaleFactor;
  1729. // apply camera zoom transform (for high res screenshots)
  1730. F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor();
  1731. S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion();
  1732. if (zoom_factor > 1.f)
  1733. {
  1734. //decompose subregion number to x and y values
  1735. int pos_y = sub_region / llceil(zoom_factor);
  1736. int pos_x = sub_region - (pos_y*llceil(zoom_factor));
  1737. // offset for this tile
  1738. glTranslatef((F32)getWindowWidthScaled() * -(F32)pos_x, 
  1739. (F32)getWindowHeightScaled() * -(F32)pos_y, 
  1740. 0.f);
  1741. glScalef(zoom_factor, zoom_factor, 1.f);
  1742. LLUI::sGLScaleFactor *= zoom_factor;
  1743. }
  1744. // Draw tool specific overlay on world
  1745. LLToolMgr::getInstance()->getCurrentTool()->draw();
  1746. if( gAgent.cameraMouselook() )
  1747. {
  1748. drawMouselookInstructions();
  1749. stop_glerror();
  1750. }
  1751. // Draw all nested UI views.
  1752. // No translation needed, this view is glued to 0,0
  1753. mRootView->draw();
  1754. if (LLView::sDebugRects)
  1755. {
  1756. gToolTipView->drawStickyRect();
  1757. }
  1758. // Draw optional on-top-of-everyone view
  1759. LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
  1760. if (top_ctrl && top_ctrl->getVisible())
  1761. {
  1762. S32 screen_x, screen_y;
  1763. top_ctrl->localPointToScreen(0, 0, &screen_x, &screen_y);
  1764. glMatrixMode(GL_MODELVIEW);
  1765. LLUI::pushMatrix();
  1766. LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f);
  1767. top_ctrl->draw();
  1768. LLUI::popMatrix();
  1769. }
  1770. if( gShowOverlayTitle && !mOverlayTitle.empty() )
  1771. {
  1772. // Used for special titles such as "Second Life - Special E3 2003 Beta"
  1773. const S32 DIST_FROM_TOP = 20;
  1774. LLFontGL::getFontSansSerifBig()->renderUTF8(
  1775. mOverlayTitle, 0,
  1776. llround( getWindowWidthScaled() * 0.5f),
  1777. getWindowHeightScaled() - DIST_FROM_TOP,
  1778. LLColor4(1, 1, 1, 0.4f),
  1779. LLFontGL::HCENTER, LLFontGL::TOP);
  1780. }
  1781. LLUI::sGLScaleFactor = old_scale_factor;
  1782. }
  1783. gGL.popMatrix();
  1784. #if LL_DEBUG
  1785. LLView::sIsDrawing = FALSE;
  1786. #endif
  1787. }
  1788. // Takes a single keydown event, usually when UI is visible
  1789. BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
  1790. {
  1791. if (gFocusMgr.getKeyboardFocus() 
  1792. && !(mask & (MASK_CONTROL | MASK_ALT))
  1793. && !gFocusMgr.getKeystrokesOnly())
  1794. {
  1795. // We have keyboard focus, and it's not an accelerator
  1796. if (key < 0x80)
  1797. {
  1798. // Not a special key, so likely (we hope) to generate a character.  Let it fall through to character handler first.
  1799. return (gFocusMgr.getKeyboardFocus() != NULL);
  1800. }
  1801. }
  1802. // hide tooltips on keypress
  1803. LLToolTipMgr::instance().blockToolTips();
  1804. // Explicit hack for debug menu.
  1805. if ((MASK_ALT & mask) &&
  1806. (MASK_CONTROL & mask) &&
  1807. ('D' == key || 'd' == key))
  1808. {
  1809. toggle_debug_menus(NULL);
  1810. }
  1811. // Explicit hack for debug menu.
  1812. if ((mask == (MASK_SHIFT | MASK_CONTROL)) &&
  1813. ('G' == key || 'g' == key))
  1814. {
  1815. if  (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP)  //on splash page
  1816. {
  1817. BOOL visible = ! gSavedSettings.getBOOL("ForceShowGrid");
  1818. gSavedSettings.setBOOL("ForceShowGrid", visible);
  1819. // Initialize visibility (and don't force visibility - use prefs)
  1820. LLPanelLogin::refreshLocation( false );
  1821. }
  1822. }
  1823. // Debugging view for unified notifications: CTRL-SHIFT-5
  1824. // *FIXME: Having this special-cased right here (just so this can be invoked from the login screen) sucks.
  1825. if ((MASK_SHIFT & mask) 
  1826.     && (!(MASK_ALT & mask))
  1827.     && (MASK_CONTROL & mask)
  1828.     && ('5' == key))
  1829. {
  1830. //LLFloaterNotificationConsole::showInstance();
  1831. LLFloaterReg::showInstance("notifications_console");
  1832. return TRUE;
  1833. }
  1834. // handle escape key
  1835. //if (key == KEY_ESCAPE && mask == MASK_NONE)
  1836. //{
  1837. // *TODO: get this to play well with mouselook and hidden
  1838. // cursor modes, etc, and re-enable.
  1839. //if (gFocusMgr.getMouseCapture())
  1840. //{
  1841. // gFocusMgr.setMouseCapture(NULL);
  1842. // return TRUE;
  1843. //}
  1844. //}
  1845. // let menus handle navigation keys
  1846. if (gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE))
  1847. {
  1848. return TRUE;
  1849. }
  1850. // let menus handle navigation keys
  1851. if (gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, TRUE))
  1852. {
  1853. return TRUE;
  1854. }
  1855. //some of context menus use this container, let context menu handle navigation keys
  1856. if(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE))
  1857. {
  1858. return TRUE;
  1859. }
  1860. // Traverses up the hierarchy
  1861. LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
  1862. if( keyboard_focus )
  1863. {
  1864. LLLineEditor* chat_editor = LLBottomTray::instanceExists() ? LLBottomTray::getInstance()->getNearbyChatBar()->getChatBox() : NULL;
  1865. // arrow keys move avatar while chatting hack
  1866. if (chat_editor && chat_editor->hasFocus())
  1867. {
  1868. // If text field is empty, there's no point in trying to move
  1869. // cursor with arrow keys, so allow movement
  1870. if (chat_editor->getText().empty() 
  1871. || gSavedSettings.getBOOL("ArrowKeysAlwaysMove"))
  1872. {
  1873. // let Control-Up and Control-Down through for chat line history,
  1874. if (!(key == KEY_UP && mask == MASK_CONTROL)
  1875. && !(key == KEY_DOWN && mask == MASK_CONTROL))
  1876. {
  1877. switch(key)
  1878. {
  1879. case KEY_LEFT:
  1880. case KEY_RIGHT:
  1881. case KEY_UP:
  1882. case KEY_DOWN:
  1883. case KEY_PAGE_UP:
  1884. case KEY_PAGE_DOWN:
  1885. case KEY_HOME:
  1886. // when chatbar is empty or ArrowKeysAlwaysMove set,
  1887. // pass arrow keys on to avatar...
  1888. return FALSE;
  1889. default:
  1890. break;
  1891. }
  1892. }
  1893. }
  1894. }
  1895. if (keyboard_focus->handleKey(key, mask, FALSE))
  1896. {
  1897. return TRUE;
  1898. }
  1899. }
  1900. if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) )
  1901. {
  1902. return TRUE;
  1903. }
  1904. // Try for a new-format gesture
  1905. if (LLGestureManager::instance().triggerGesture(key, mask))
  1906. {
  1907. return TRUE;
  1908. }
  1909. // See if this is a gesture trigger.  If so, eat the key and
  1910. // don't pass it down to the menus.
  1911. if (gGestureList.trigger(key, mask))
  1912. {
  1913. return TRUE;
  1914. }
  1915. // Topmost view gets a chance before the hierarchy
  1916. // *FIX: get rid of this?
  1917. //LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
  1918. //if (top_ctrl)
  1919. //{
  1920. // if( top_ctrl->handleKey( key, mask, TRUE ) )
  1921. // {
  1922. // return TRUE;
  1923. // }
  1924. //}
  1925. // give floaters first chance to handle TAB key
  1926. // so frontmost floater gets focus
  1927. if (key == KEY_TAB)
  1928. {
  1929. // if nothing has focus, go to first or last UI element as appropriate
  1930. if (mask & MASK_CONTROL || gFocusMgr.getKeyboardFocus() == NULL)
  1931. {
  1932. if (gMenuHolder) gMenuHolder->hideMenus();
  1933. // if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode
  1934. gFloaterView->setCycleMode((mask & MASK_CONTROL) != 0);
  1935. // do CTRL-TAB and CTRL-SHIFT-TAB logic
  1936. if (mask & MASK_SHIFT)
  1937. {
  1938. mRootView->focusPrevRoot();
  1939. }
  1940. else
  1941. {
  1942. mRootView->focusNextRoot();
  1943. }
  1944. return TRUE;
  1945. }
  1946. }
  1947. // give menus a chance to handle keys
  1948. if (gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask))
  1949. {
  1950. return TRUE;
  1951. }
  1952. // give menus a chance to handle keys
  1953. if (gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask))
  1954. {
  1955. return TRUE;
  1956. }
  1957. // don't pass keys on to world when something in ui has focus
  1958. return gFocusMgr.childHasKeyboardFocus(mRootView) 
  1959. || LLMenuGL::getKeyboardMode() 
  1960. || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive());
  1961. }
  1962. BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
  1963. {
  1964. // HACK:  We delay processing of return keys until they arrive as a Unicode char,
  1965. // so that if you're typing chat text at low frame rate, we don't send the chat
  1966. // until all keystrokes have been entered. JC
  1967. // HACK: Numeric keypad <enter> on Mac is Unicode 3
  1968. // HACK: Control-M on Windows is Unicode 13
  1969. if ((uni_char == 13 && mask != MASK_CONTROL)
  1970. || (uni_char == 3 && mask == MASK_NONE))
  1971. {
  1972. return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
  1973. }
  1974. // let menus handle navigation (jump) keys
  1975. if (gMenuBarView && gMenuBarView->handleUnicodeChar(uni_char, TRUE))
  1976. {
  1977. return TRUE;
  1978. }
  1979. // Traverses up the hierarchy
  1980. LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
  1981. if( keyboard_focus )
  1982. {
  1983. if (keyboard_focus->handleUnicodeChar(uni_char, FALSE))
  1984. {
  1985. return TRUE;
  1986. }
  1987. //// Topmost view gets a chance before the hierarchy
  1988. //LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
  1989. //if (top_ctrl && top_ctrl->handleUnicodeChar( uni_char, FALSE ) )
  1990. //{
  1991. // return TRUE;
  1992. //}
  1993. return TRUE;
  1994. }
  1995. return FALSE;
  1996. }
  1997. void LLViewerWindow::handleScrollWheel(S32 clicks)
  1998. {
  1999. LLView::sMouseHandlerMessage.clear();
  2000. LLUI::resetMouseIdleTimer();
  2001. LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
  2002. if( mouse_captor )
  2003. {
  2004. S32 local_x;
  2005. S32 local_y;
  2006. mouse_captor->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
  2007. mouse_captor->handleScrollWheel(local_x, local_y, clicks);
  2008. if (LLView::sDebugMouseHandling)
  2009. {
  2010. llinfos << "Scroll Wheel handled by captor " << mouse_captor->getName() << llendl;
  2011. }
  2012. return;
  2013. }
  2014. LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
  2015. if (top_ctrl)
  2016. {
  2017. S32 local_x;
  2018. S32 local_y;
  2019. top_ctrl->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y );
  2020. if (top_ctrl->handleScrollWheel(local_x, local_y, clicks)) return;
  2021. }
  2022. if (mRootView->handleScrollWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks) )
  2023. {
  2024. if (LLView::sDebugMouseHandling)
  2025. {
  2026. llinfos << "Scroll Wheel" << LLView::sMouseHandlerMessage << llendl;
  2027. }
  2028. return;
  2029. }
  2030. else if (LLView::sDebugMouseHandling)
  2031. {
  2032. llinfos << "Scroll Wheel not handled by view" << llendl;
  2033. }
  2034. // Zoom the camera in and out behavior
  2035. if(top_ctrl == 0 && getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) )
  2036. gAgent.handleScrollWheel(clicks);
  2037. return;
  2038. }
  2039. void LLViewerWindow::moveCursorToCenter()
  2040. {
  2041. if (! gSavedSettings.getBOOL("DisableMouseWarp"))
  2042. {
  2043. S32 x = getWorldViewWidthScaled() / 2;
  2044. S32 y = getWorldViewHeightScaled() / 2;
  2045. //on a forced move, all deltas get zeroed out to prevent jumping
  2046. mCurrentMousePoint.set(x,y);
  2047. mLastMousePoint.set(x,y);
  2048. mCurrentMouseDelta.set(0,0);
  2049. LLUI::setMousePositionScreen(x, y);
  2050. }
  2051. }
  2052. //////////////////////////////////////////////////////////////////////
  2053. //
  2054. // Hover handlers
  2055. //
  2056. void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params)
  2057. {
  2058. if (viewp) 
  2059. {
  2060. if (!params.styled_message().empty())
  2061. {
  2062. params.styled_message.add().text("n---------n"); 
  2063. }
  2064. LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView();
  2065. // NOTE: we skip "root" since it is assumed
  2066. for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView();
  2067. tooltip_it != end_tooltip_it;
  2068. ++tooltip_it)
  2069. {
  2070. LLView* viewp = *tooltip_it;
  2071. params.styled_message.add().text(viewp->getName());
  2072. LLPanel* panelp = dynamic_cast<LLPanel*>(viewp);
  2073. if (panelp && !panelp->getXMLFilename().empty())
  2074. {
  2075. params.styled_message.add()
  2076. .text("(" + panelp->getXMLFilename() + ")")
  2077. .style.color(LLColor4(0.7f, 0.7f, 1.f, 1.f));
  2078. }
  2079. params.styled_message.add().text("/");
  2080. }
  2081. }
  2082. }
  2083. // Update UI based on stored mouse position from mouse-move
  2084. // event processing.
  2085. void LLViewerWindow::updateUI()
  2086. {
  2087. static std::string last_handle_msg;
  2088. LLConsole::updateClass();
  2089. // animate layout stacks so we have up to date rect for world view
  2090. LLLayoutStack::updateClass();
  2091. updateWorldViewRect();
  2092. LLView::sMouseHandlerMessage.clear();
  2093. S32 x = mCurrentMousePoint.mX;
  2094. S32 y = mCurrentMousePoint.mY;
  2095. MASK mask = gKeyboard->currentMask(TRUE);
  2096. if (gNoRender)
  2097. {
  2098. return;
  2099. }
  2100. if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
  2101. {
  2102. gDebugRaycastFaceHit = -1;
  2103. gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
  2104.   &gDebugRaycastFaceHit,
  2105.   &gDebugRaycastIntersection,
  2106.   &gDebugRaycastTexCoord,
  2107.   &gDebugRaycastNormal,
  2108.   &gDebugRaycastBinormal);
  2109. }
  2110. updateMouseDelta();
  2111. updateKeyboardFocus();
  2112. BOOL handled = FALSE;
  2113. BOOL handled_by_top_ctrl = FALSE;
  2114. LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
  2115. LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
  2116. LLView* captor_view = dynamic_cast<LLView*>(mouse_captor);
  2117. //FIXME: only include captor and captor's ancestors if mouse is truly over them --RN
  2118. //build set of views containing mouse cursor by traversing UI hierarchy and testing 
  2119. //screen rect against mouse cursor
  2120. view_handle_set_t mouse_hover_set;
  2121. // constraint mouse enter events to children of mouse captor
  2122. LLView* root_view = captor_view;
  2123. // if mouse captor doesn't exist or isn't a LLView
  2124. // then allow mouse enter events on entire UI hierarchy
  2125. if (!root_view)
  2126. {
  2127. root_view = mRootView;
  2128. }
  2129. // include all ancestors of captor_view as automatically having mouse
  2130. if (captor_view)
  2131. {
  2132. LLView* captor_parent_view = captor_view->getParent();
  2133. while(captor_parent_view)
  2134. {
  2135. mouse_hover_set.insert(captor_parent_view->getHandle());
  2136. captor_parent_view = captor_parent_view->getParent();
  2137. }
  2138. }
  2139. // aggregate visible views that contain mouse cursor in display order
  2140. // while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events
  2141. if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y))
  2142. {
  2143. // iterator over contents of top_ctrl, and throw into mouse_hover_set
  2144. for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS();
  2145. it != top_ctrl->endTreeDFS();
  2146. ++it)
  2147. {
  2148. LLView* viewp = *it;
  2149. if (viewp->getVisible()
  2150. && viewp->calcScreenBoundingRect().pointInRect(x, y))
  2151. {
  2152. // we have a view that contains the mouse, add it to the set
  2153. mouse_hover_set.insert(viewp->getHandle());
  2154. }
  2155. else
  2156. {
  2157. // skip this view and all of its children
  2158. it.skipDescendants();
  2159. }
  2160. }
  2161. }
  2162. else
  2163. {
  2164. // walk UI tree in depth-first order
  2165. for (LLView::tree_iterator_t it = root_view->beginTreeDFS();
  2166. it != root_view->endTreeDFS();
  2167. ++it)
  2168. {
  2169. LLView* viewp = *it;
  2170. // calculating the screen rect involves traversing the parent, so this is less than optimal
  2171. if (viewp->getVisible()
  2172. && viewp->calcScreenBoundingRect().pointInRect(x, y))
  2173. {
  2174. // if this view is mouse opaque, nothing behind it should be in mouse_hover_set
  2175. if (viewp->getMouseOpaque())
  2176. {
  2177. // constrain further iteration to children of this widget
  2178. it = viewp->beginTreeDFS();
  2179. }
  2180. // we have a view that contains the mouse, add it to the set
  2181. mouse_hover_set.insert(viewp->getHandle());
  2182. }
  2183. else
  2184. {
  2185. // skip this view and all of its children
  2186. it.skipDescendants();
  2187. }
  2188. }
  2189. }
  2190. typedef std::vector<LLHandle<LLView> > view_handle_list_t;
  2191. // call onMouseEnter() on all views which contain the mouse cursor but did not before
  2192. view_handle_list_t mouse_enter_views;
  2193. std::set_difference(mouse_hover_set.begin(), mouse_hover_set.end(),
  2194. mMouseHoverViews.begin(), mMouseHoverViews.end(),
  2195. std::back_inserter(mouse_enter_views));
  2196. for (view_handle_list_t::iterator it = mouse_enter_views.begin();
  2197. it != mouse_enter_views.end();
  2198. ++it)
  2199. {
  2200. LLView* viewp = it->get();
  2201. if (viewp)
  2202. {
  2203. LLRect view_screen_rect = viewp->calcScreenRect();