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

游戏引擎

开发平台:

C++ Builder

  1. viewp->onMouseEnter(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
  2. }
  3. }
  4. // call onMouseLeave() on all views which no longer contain the mouse cursor
  5. view_handle_list_t mouse_leave_views;
  6. std::set_difference(mMouseHoverViews.begin(), mMouseHoverViews.end(),
  7. mouse_hover_set.begin(), mouse_hover_set.end(),
  8. std::back_inserter(mouse_leave_views));
  9. for (view_handle_list_t::iterator it = mouse_leave_views.begin();
  10. it != mouse_leave_views.end();
  11. ++it)
  12. {
  13. LLView* viewp = it->get();
  14. if (viewp)
  15. {
  16. LLRect view_screen_rect = viewp->calcScreenRect();
  17. viewp->onMouseLeave(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
  18. }
  19. }
  20. // store resulting hover set for next frame
  21. swap(mMouseHoverViews, mouse_hover_set);
  22. if( mouse_captor )
  23. {
  24. // Pass hover events to object capturing mouse events.
  25. S32 local_x;
  26. S32 local_y; 
  27. mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
  28. handled = mouse_captor->handleHover(local_x, local_y, mask);
  29. if (LLView::sDebugMouseHandling)
  30. {
  31. llinfos << "Hover handled by captor " << mouse_captor->getName() << llendl;
  32. }
  33. if( !handled )
  34. {
  35. lldebugst(LLERR_USER_INPUT) << "hover not handled by mouse captor" << llendl;
  36. }
  37. }
  38. else
  39. {
  40. if (top_ctrl)
  41. {
  42. S32 local_x, local_y;
  43. top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
  44. handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask);
  45. handled_by_top_ctrl = TRUE;
  46. }
  47. if ( !handled )
  48. {
  49. // x and y are from last time mouse was in window
  50. // mMouseInWindow tracks *actual* mouse location
  51. if (mMouseInWindow && mRootView->handleHover(x, y, mask) )
  52. {
  53. if (LLView::sDebugMouseHandling && LLView::sMouseHandlerMessage != last_handle_msg)
  54. {
  55. last_handle_msg = LLView::sMouseHandlerMessage;
  56. llinfos << "Hover" << LLView::sMouseHandlerMessage << llendl;
  57. }
  58. handled = TRUE;
  59. }
  60. else if (LLView::sDebugMouseHandling)
  61. {
  62. if (last_handle_msg != LLStringUtil::null)
  63. {
  64. last_handle_msg.clear();
  65. llinfos << "Hover not handled by view" << llendl;
  66. }
  67. }
  68. }
  69. if (!handled)
  70. {
  71. LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
  72. if(mMouseInWindow && tool)
  73. {
  74. handled = tool->handleHover(x, y, mask);
  75. }
  76. }
  77. }
  78. // Show a new tool tip (or update one that is already shown)
  79. BOOL tool_tip_handled = FALSE;
  80. std::string tool_tip_msg;
  81. if( handled 
  82. && !mWindow->isCursorHidden())
  83. {
  84. LLRect screen_sticky_rect = mRootView->getLocalRect();
  85. S32 local_x, local_y;
  86. if (gSavedSettings.getBOOL("DebugShowXUINames"))
  87. {
  88. LLToolTip::Params params;
  89. LLView* tooltip_view = mRootView;
  90. LLView::tree_iterator_t end_it = mRootView->endTreeDFS();
  91. for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it)
  92. {
  93. LLView* viewp = *it;
  94. LLRect screen_rect;
  95. viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect);
  96. if (!(viewp->getVisible()
  97.  && screen_rect.pointInRect(x, y)))
  98. {
  99. it.skipDescendants();
  100. }
  101. // only report xui names for LLUICtrls, 
  102. // and blacklist the various containers we don't care about
  103. else if (dynamic_cast<LLUICtrl*>(viewp) 
  104. && viewp != gMenuHolder
  105. && viewp != gFloaterView
  106. && viewp != gConsole) 
  107. {
  108. if (dynamic_cast<LLFloater*>(viewp))
  109. {
  110. // constrain search to descendants of this (frontmost) floater
  111. // by resetting iterator
  112. it = viewp->beginTreeDFS();
  113. }
  114. // if we are in a new part of the tree (not a descendent of current tooltip_view)
  115. // then push the results for tooltip_view and start with a new potential view
  116. // NOTE: this emulates visiting only the leaf nodes that meet our criteria
  117. if (!viewp->hasAncestor(tooltip_view))
  118. {
  119. append_xui_tooltip(tooltip_view, params);
  120. screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
  121. }
  122. tooltip_view = viewp;
  123. }
  124. }
  125. append_xui_tooltip(tooltip_view, params);
  126. screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
  127. params.sticky_rect = screen_sticky_rect;
  128. params.max_width = 400;
  129. LLToolTipMgr::instance().show(params);
  130. }
  131. // if there is a mouse captor, nothing else gets a tooltip
  132. else if (mouse_captor)
  133. {
  134. mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
  135. tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, mask);
  136. }
  137. else 
  138. {
  139. // next is top_ctrl
  140. if (!tool_tip_handled && top_ctrl)
  141. {
  142. top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
  143. tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, mask );
  144. }
  145. if (!tool_tip_handled)
  146. {
  147. local_x = x; local_y = y;
  148. tool_tip_handled = mRootView->handleToolTip(local_x, local_y, mask );
  149. }
  150. LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool();
  151. if (!tool_tip_handled && current_tool)
  152. {
  153. current_tool->screenPointToLocal(x, y, &local_x, &local_y);
  154. tool_tip_handled = current_tool->handleToolTip(local_x, local_y, mask );
  155. }
  156. }
  157. }
  158. updateLayout();
  159. mLastMousePoint = mCurrentMousePoint;
  160. // cleanup unused selections when no modal dialogs are open
  161. if (LLModalDialog::activeCount() == 0)
  162. {
  163. LLViewerParcelMgr::getInstance()->deselectUnused();
  164. }
  165. if (LLModalDialog::activeCount() == 0)
  166. {
  167. LLSelectMgr::getInstance()->deselectUnused();
  168. }
  169. }
  170. void LLViewerWindow::updateLayout()
  171. {
  172. LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
  173. if (gFloaterTools != NULL
  174. && tool != NULL
  175. && tool != gToolNull  
  176. && tool != LLToolCompInspect::getInstance() 
  177. && tool != LLToolDragAndDrop::getInstance() 
  178. && !gSavedSettings.getBOOL("FreezeTime"))
  179. // Suppress the toolbox view if our source tool was the pie tool,
  180. // and we've overridden to something else.
  181. bool suppress_toolbox = 
  182. (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) &&
  183. (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance());
  184. LLMouseHandler *captor = gFocusMgr.getMouseCapture();
  185. // With the null, inspect, or drag and drop tool, don't muck
  186. // with visibility.
  187. if (gFloaterTools->isMinimized()
  188. || (tool != LLToolPie::getInstance() // not default tool
  189. && tool != LLToolCompGun::getInstance() // not coming out of mouselook
  190. && !suppress_toolbox // not override in third person
  191. && LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset // not special mode
  192. && LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset
  193. && (!captor || dynamic_cast<LLView*>(captor) != NULL))) // not dragging
  194. {
  195. // Force floater tools to be visible (unless minimized)
  196. if (!gFloaterTools->getVisible())
  197. {
  198. gFloaterTools->openFloater();
  199. }
  200. // Update the location of the blue box tool popup
  201. LLCoordGL select_center_screen;
  202. gFloaterTools->updatePopup( select_center_screen, gKeyboard->currentMask(TRUE) );
  203. }
  204. else
  205. {
  206. gFloaterTools->setVisible(FALSE);
  207. }
  208. //gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible());
  209. }
  210. // Always update console
  211. if(gConsole)
  212. {
  213. LLRect console_rect = getChatConsoleRect();
  214. gConsole->reshape(console_rect.getWidth(), console_rect.getHeight());
  215. gConsole->setRect(console_rect);
  216. }
  217. }
  218. void LLViewerWindow::updateMouseDelta()
  219. {
  220. S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
  221. S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
  222. //RN: fix for asynchronous notification of mouse leaving window not working
  223. LLCoordWindow mouse_pos;
  224. mWindow->getCursorPosition(&mouse_pos);
  225. if (mouse_pos.mX < 0 || 
  226. mouse_pos.mY < 0 ||
  227. mouse_pos.mX > mWindowRectRaw.getWidth() ||
  228. mouse_pos.mY > mWindowRectRaw.getHeight())
  229. {
  230. mMouseInWindow = FALSE;
  231. }
  232. else
  233. {
  234. mMouseInWindow = TRUE;
  235. }
  236. LLVector2 mouse_vel; 
  237. if (gSavedSettings.getBOOL("MouseSmooth"))
  238. {
  239. static F32 fdx = 0.f;
  240. static F32 fdy = 0.f;
  241. F32 amount = 16.f;
  242. fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f);
  243. fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f);
  244. mCurrentMouseDelta.set(llround(fdx), llround(fdy));
  245. mouse_vel.setVec(fdx,fdy);
  246. }
  247. else
  248. {
  249. mCurrentMouseDelta.set(dx, dy);
  250. mouse_vel.setVec((F32) dx, (F32) dy);
  251. }
  252.     
  253. mMouseVelocityStat.addValue(mouse_vel.magVec());
  254. }
  255. void LLViewerWindow::updateKeyboardFocus()
  256. {
  257. // clean up current focus
  258. LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
  259. if (cur_focus)
  260. {
  261. if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain())
  262. {
  263.             // don't release focus, just reassign so that if being given
  264.             // to a sibling won't call onFocusLost on all the ancestors
  265. // gFocusMgr.releaseFocusIfNeeded(cur_focus);
  266. LLUICtrl* parent = cur_focus->getParentUICtrl();
  267. const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
  268. while(parent)
  269. {
  270. if (parent->isCtrl() && 
  271. (parent->hasTabStop() || parent == focus_root) && 
  272. !parent->getIsChrome() && 
  273. parent->isInVisibleChain() && 
  274. parent->isInEnabledChain())
  275. {
  276. if (!parent->focusFirstItem())
  277. {
  278. parent->setFocus(TRUE);
  279. }
  280. break;
  281. }
  282. parent = parent->getParentUICtrl();
  283. }
  284. // if we didn't find a better place to put focus, just release it
  285. // hasFocus() will return true if and only if we didn't touch focus since we
  286. // are only moving focus higher in the hierarchy
  287. if (cur_focus->hasFocus())
  288. {
  289. cur_focus->setFocus(FALSE);
  290. }
  291. }
  292. else if (cur_focus->isFocusRoot())
  293. {
  294. // focus roots keep trying to delegate focus to their first valid descendant
  295. // this assumes that focus roots are not valid focus holders on their own
  296. cur_focus->focusFirstItem();
  297. }
  298. }
  299. // last ditch force of edit menu to selection manager
  300. if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
  301. {
  302. LLEditMenuHandler::gEditMenuHandler = LLSelectMgr::getInstance();
  303. }
  304. if (gFloaterView->getCycleMode())
  305. {
  306. // sync all floaters with their focus state
  307. gFloaterView->highlightFocusedFloater();
  308. gSnapshotFloaterView->highlightFocusedFloater();
  309. if ((gKeyboard->currentMask(TRUE) & MASK_CONTROL) == 0)
  310. {
  311. // control key no longer held down, finish cycle mode
  312. gFloaterView->setCycleMode(FALSE);
  313. gFloaterView->syncFloaterTabOrder();
  314. }
  315. else
  316. {
  317. // user holding down CTRL, don't update tab order of floaters
  318. }
  319. }
  320. else
  321. {
  322. // update focused floater
  323. gFloaterView->highlightFocusedFloater();
  324. gSnapshotFloaterView->highlightFocusedFloater();
  325. // make sure floater visible order is in sync with tab order
  326. gFloaterView->syncFloaterTabOrder();
  327. }
  328. if(LLSideTray::instanceCreated())//just getInstance will create sidetray. we don't want this
  329. LLSideTray::getInstance()->highlightFocused();
  330. }
  331. static LLFastTimer::DeclareTimer FTM_UPDATE_WORLD_VIEW("Update World View");
  332. void LLViewerWindow::updateWorldViewRect(bool use_full_window)
  333. {
  334. LLFastTimer ft(FTM_UPDATE_WORLD_VIEW);
  335. // start off using whole window to render world
  336. LLRect new_world_rect = mWindowRectRaw;
  337. if (use_full_window == false && mWorldViewPlaceholder.get())
  338. {
  339. new_world_rect = mWorldViewPlaceholder.get()->calcScreenRect();
  340. // clamp to at least a 1x1 rect so we don't try to allocate zero width gl buffers
  341. new_world_rect.mTop = llmax(new_world_rect.mTop, new_world_rect.mBottom + 1);
  342. new_world_rect.mRight = llmax(new_world_rect.mRight, new_world_rect.mLeft + 1);
  343. new_world_rect.mLeft = llround((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]);
  344. new_world_rect.mRight = llround((F32)new_world_rect.mRight * mDisplayScale.mV[VX]);
  345. new_world_rect.mBottom = llround((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]);
  346. new_world_rect.mTop = llround((F32)new_world_rect.mTop * mDisplayScale.mV[VY]);
  347. }
  348. if (mWorldViewRectRaw != new_world_rect)
  349. {
  350. LLRect old_world_rect = mWorldViewRectRaw;
  351. mWorldViewRectRaw = new_world_rect;
  352. gResizeScreenTexture = TRUE;
  353. LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
  354. LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
  355. mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
  356. // sending a signal with a new WorldView rect
  357. old_world_rect = calcScaledRect(old_world_rect, mDisplayScale);
  358. mOnWorldViewRectUpdated(old_world_rect, mWorldViewRectScaled);
  359. }
  360. }
  361. void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
  362. {
  363. // Store last mouse location.
  364. // If mouse leaves window, pretend last point was on edge of window
  365. if (point.mX < 0)
  366. {
  367. mCurrentMousePoint.mX = 0;
  368. }
  369. else if (point.mX > getWindowWidthScaled())
  370. {
  371. mCurrentMousePoint.mX = getWindowWidthScaled();
  372. }
  373. else
  374. {
  375. mCurrentMousePoint.mX = point.mX;
  376. }
  377. if (point.mY < 0)
  378. {
  379. mCurrentMousePoint.mY = 0;
  380. }
  381. else if (point.mY > getWindowHeightScaled() )
  382. {
  383. mCurrentMousePoint.mY = getWindowHeightScaled();
  384. }
  385. else
  386. {
  387. mCurrentMousePoint.mY = point.mY;
  388. }
  389. }
  390. // Draws the selection outlines for the currently selected objects
  391. // Must be called after displayObjects is called, which sets the mGLName parameter
  392. // NOTE: This function gets called 3 times:
  393. //  render_ui_3d:  FALSE, FALSE, TRUE
  394. //  renderObjectsForSelect: TRUE, pick_parcel_wall, FALSE
  395. //  render_hud_elements: FALSE, FALSE, FALSE
  396. void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud )
  397. {
  398. LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
  399. if (!for_hud && !for_gl_pick)
  400. {
  401. // Call this once and only once
  402. LLSelectMgr::getInstance()->updateSilhouettes();
  403. }
  404. // Draw fence around land selections
  405. if (for_gl_pick)
  406. {
  407. if (pick_parcel_walls)
  408. {
  409. LLViewerParcelMgr::getInstance()->renderParcelCollision();
  410. }
  411. }
  412. else if (( for_hud && selection->getSelectType() == SELECT_TYPE_HUD) ||
  413.  (!for_hud && selection->getSelectType() != SELECT_TYPE_HUD))
  414. {
  415. LLSelectMgr::getInstance()->renderSilhouettes(for_hud);
  416. stop_glerror();
  417. // setup HUD render
  418. if (selection->getSelectType() == SELECT_TYPE_HUD && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
  419. {
  420. LLBBox hud_bbox = gAgent.getAvatarObject()->getHUDBBox();
  421. // set up transform to encompass bounding box of HUD
  422. glMatrixMode(GL_PROJECTION);
  423. glPushMatrix();
  424. glLoadIdentity();
  425. F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
  426. glOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth);
  427. glMatrixMode(GL_MODELVIEW);
  428. glPushMatrix();
  429. glLoadIdentity();
  430. glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame
  431. glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f);
  432. }
  433. // Render light for editing
  434. if (LLSelectMgr::sRenderLightRadius && LLToolMgr::getInstance()->inEdit())
  435. {
  436. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  437. LLGLEnable gls_blend(GL_BLEND);
  438. LLGLEnable gls_cull(GL_CULL_FACE);
  439. LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
  440. glMatrixMode(GL_MODELVIEW);
  441. glPushMatrix();
  442. if (selection->getSelectType() == SELECT_TYPE_HUD)
  443. {
  444. F32 zoom = gAgent.mHUDCurZoom;
  445. glScalef(zoom, zoom, zoom);
  446. }
  447. struct f : public LLSelectedObjectFunctor
  448. {
  449. virtual bool apply(LLViewerObject* object)
  450. {
  451. LLDrawable* drawable = object->mDrawable;
  452. if (drawable && drawable->isLight())
  453. {
  454. LLVOVolume* vovolume = drawable->getVOVolume();
  455. glPushMatrix();
  456. LLVector3 center = drawable->getPositionAgent();
  457. glTranslatef(center[0], center[1], center[2]);
  458. F32 scale = vovolume->getLightRadius();
  459. glScalef(scale, scale, scale);
  460. LLColor4 color(vovolume->getLightColor(), .5f);
  461. glColor4fv(color.mV);
  462. F32 pixel_area = 100000.f;
  463. // Render Outside
  464. gSphere.render(pixel_area);
  465. // Render Inside
  466. glCullFace(GL_FRONT);
  467. gSphere.render(pixel_area);
  468. glCullFace(GL_BACK);
  469. glPopMatrix();
  470. }
  471. return true;
  472. }
  473. } func;
  474. LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func);
  475. glPopMatrix();
  476. }
  477. // NOTE: The average position for the axis arrows of the selected objects should
  478. // not be recalculated at this time.  If they are, then group rotations will break.
  479. // Draw arrows at average center of all selected objects
  480. LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
  481. if (tool)
  482. {
  483. if(tool->isAlwaysRendered())
  484. {
  485. tool->render();
  486. }
  487. else
  488. {
  489. if( !LLSelectMgr::getInstance()->getSelection()->isEmpty() )
  490. {
  491. BOOL moveable_object_selected = FALSE;
  492. BOOL all_selected_objects_move = TRUE;
  493. BOOL all_selected_objects_modify = TRUE;
  494. BOOL selecting_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
  495. for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
  496.  iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++)
  497. {
  498. LLSelectNode* nodep = *iter;
  499. LLViewerObject* object = nodep->getObject();
  500. BOOL this_object_movable = FALSE;
  501. if (object->permMove() && (object->permModify() || selecting_linked_set))
  502. {
  503. moveable_object_selected = TRUE;
  504. this_object_movable = TRUE;
  505. }
  506. all_selected_objects_move = all_selected_objects_move && this_object_movable;
  507. all_selected_objects_modify = all_selected_objects_modify && object->permModify();
  508. }
  509. BOOL draw_handles = TRUE;
  510. if (tool == LLToolCompTranslate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
  511. {
  512. draw_handles = FALSE;
  513. }
  514. if (tool == LLToolCompRotate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
  515. {
  516. draw_handles = FALSE;
  517. }
  518. if ( !all_selected_objects_modify && tool == LLToolCompScale::getInstance() )
  519. {
  520. draw_handles = FALSE;
  521. }
  522. if( draw_handles )
  523. {
  524. tool->render();
  525. }
  526. }
  527. }
  528. if (selection->getSelectType() == SELECT_TYPE_HUD && selection->getObjectCount())
  529. {
  530. glMatrixMode(GL_PROJECTION);
  531. glPopMatrix();
  532. glMatrixMode(GL_MODELVIEW);
  533. glPopMatrix();
  534. stop_glerror();
  535. }
  536. }
  537. }
  538. }
  539. // Return a point near the clicked object representative of the place the object was clicked.
  540. LLVector3d LLViewerWindow::clickPointInWorldGlobal(S32 x, S32 y_from_bot, LLViewerObject* clicked_object) const
  541. {
  542. // create a normalized vector pointing from the camera center into the 
  543. // world at the location of the mouse click
  544. LLVector3 mouse_direction_global = mouseDirectionGlobal( x, y_from_bot );
  545. LLVector3d relative_object = clicked_object->getPositionGlobal() - gAgent.getCameraPositionGlobal();
  546. // make mouse vector as long as object vector, so it touchs a point near
  547. // where the user clicked on the object
  548. mouse_direction_global *= (F32) relative_object.magVec();
  549. LLVector3d new_pos;
  550. new_pos.setVec(mouse_direction_global);
  551. // transform mouse vector back to world coords
  552. new_pos += gAgent.getCameraPositionGlobal();
  553. return new_pos;
  554. }
  555. BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const
  556. {
  557. BOOL intersect = FALSE;
  558. // U8 shape = objectp->mPrimitiveCode & LL_PCODE_BASE_MASK;
  559. if (!intersect)
  560. {
  561. point_global = clickPointInWorldGlobal(x, y, objectp);
  562. llinfos << "approx intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
  563. }
  564. else
  565. {
  566. llinfos << "good intersection at " <<  (objectp->getPositionGlobal() - point_global) << llendl;
  567. }
  568. return intersect;
  569. }
  570. void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent)
  571. {
  572. if (gNoRender)
  573. {
  574. return;
  575. }
  576. BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
  577. if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
  578. {
  579. // build mode allows interaction with all transparent objects
  580. // "Show Debug Alpha" means no object actually transparent
  581. pick_transparent = TRUE;
  582. }
  583. LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, TRUE, callback);
  584. schedulePick(pick_info);
  585. }
  586. void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
  587. {
  588. if (mPicks.size() >= 1024 || mWindow->getMinimized())
  589. { //something went wrong, picks are being scheduled but not processed
  590. if (pick_info.mPickCallback)
  591. {
  592. pick_info.mPickCallback(pick_info);
  593. }
  594. return;
  595. }
  596. mPicks.push_back(pick_info);
  597. // delay further event processing until we receive results of pick
  598. // only do this for async picks so that handleMouseUp won't be called
  599. // until the pick triggered in handleMouseDown has been processed, for example
  600. mWindow->delayInputProcessing();
  601. }
  602. void LLViewerWindow::performPick()
  603. {
  604. if (gNoRender)
  605. {
  606. return;
  607. }
  608. if (!mPicks.empty())
  609. {
  610. std::vector<LLPickInfo>::iterator pick_it;
  611. for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
  612. {
  613. pick_it->fetchResults();
  614. }
  615. mLastPick = mPicks.back();
  616. mPicks.clear();
  617. }
  618. }
  619. void LLViewerWindow::returnEmptyPicks()
  620. {
  621. std::vector<LLPickInfo>::iterator pick_it;
  622. for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
  623. {
  624. mLastPick = *pick_it;
  625. // just trigger callback with empty results
  626. if (pick_it->mPickCallback)
  627. {
  628. pick_it->mPickCallback(*pick_it);
  629. }
  630. }
  631. mPicks.clear();
  632. }
  633. // Performs the GL object/land pick.
  634. LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot,  BOOL pick_transparent)
  635. {
  636. if (gNoRender)
  637. {
  638. return LLPickInfo();
  639. }
  640. BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
  641. if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
  642. {
  643. // build mode allows interaction with all transparent objects
  644. // "Show Debug Alpha" means no object actually transparent
  645. pick_transparent = TRUE;
  646. }
  647. // shortcut queueing in mPicks and just update mLastPick in place
  648. mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), gKeyboard->currentMask(TRUE), pick_transparent, TRUE, NULL);
  649. mLastPick.fetchResults();
  650. return mLastPick;
  651. }
  652. LLHUDIcon* LLViewerWindow::cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
  653.    LLVector3* intersection)
  654. {
  655. S32 x = mouse_x;
  656. S32 y = mouse_y;
  657. if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
  658. {
  659. x = getCurrentMouseX();
  660. y = getCurrentMouseY();
  661. }
  662. // world coordinates of mouse
  663. LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
  664. LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
  665. LLVector3 mouse_world_start = mouse_point_global;
  666. LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
  667. return LLHUDIcon::lineSegmentIntersectAll(mouse_world_start, mouse_world_end, intersection);
  668. }
  669. LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth,
  670. LLViewerObject *this_object,
  671. S32 this_face,
  672. BOOL pick_transparent,
  673. S32* face_hit,
  674. LLVector3 *intersection,
  675. LLVector2 *uv,
  676. LLVector3 *normal,
  677. LLVector3 *binormal)
  678. {
  679. S32 x = mouse_x;
  680. S32 y = mouse_y;
  681. if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
  682. {
  683. x = getCurrentMouseX();
  684. y = getCurrentMouseY();
  685. }
  686. // HUD coordinates of mouse
  687. LLVector3 mouse_point_hud = mousePointHUD(x, y);
  688. LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0);
  689. LLVector3 mouse_hud_end   = mouse_point_hud + LLVector3(depth, 0, 0);
  690. // world coordinates of mouse
  691. LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
  692. LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
  693. //get near clip plane
  694. LLVector3 n = LLViewerCamera::getInstance()->getAtAxis();
  695. LLVector3 p = mouse_point_global + n * LLViewerCamera::getInstance()->getNear();
  696. //project mouse point onto plane
  697. LLVector3 pos;
  698. line_plane(mouse_point_global, mouse_direction_global, p, n, pos);
  699. mouse_point_global = pos;
  700. LLVector3 mouse_world_start = mouse_point_global;
  701. LLVector3 mouse_world_end   = mouse_point_global + mouse_direction_global * depth;
  702. LLViewerObject* found = NULL;
  703. if (this_object)  // check only this object
  704. {
  705. if (this_object->isHUDAttachment()) // is a HUD object?
  706. {
  707. if (this_object->lineSegmentIntersect(mouse_hud_start, mouse_hud_end, this_face, pick_transparent,
  708.   face_hit, intersection, uv, normal, binormal))
  709. {
  710. found = this_object;
  711. }
  712. }
  713. else // is a world object
  714. {
  715. if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face, pick_transparent,
  716.   face_hit, intersection, uv, normal, binormal))
  717. {
  718. found = this_object;
  719. }
  720. }
  721. }
  722. else // check ALL objects
  723. {
  724. found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end, pick_transparent,
  725. face_hit, intersection, uv, normal, binormal);
  726. if (!found) // if not found in HUD, look in world:
  727. {
  728. found = gPipeline.lineSegmentIntersectInWorld(mouse_world_start, mouse_world_end, pick_transparent,
  729.   face_hit, intersection, uv, normal, binormal);
  730. }
  731. }
  732. return found;
  733. }
  734. // Returns unit vector relative to camera
  735. // indicating direction of point on screen x,y
  736. LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
  737. {
  738. // find vertical field of view
  739. F32 fov = LLViewerCamera::getInstance()->getView();
  740. // find world view center in scaled ui coordinates
  741. F32 center_x = getWorldViewRectScaled().getCenterX();
  742. F32 center_y = getWorldViewRectScaled().getCenterY();
  743. // calculate pixel distance to screen
  744. F32 distance = ((F32)getWorldViewHeightScaled() * 0.5f) / (tan(fov / 2.f));
  745. // calculate click point relative to middle of screen
  746. F32 click_x = x - center_x;
  747. F32 click_y = y - center_y;
  748. // compute mouse vector
  749. LLVector3 mouse_vector = distance * LLViewerCamera::getInstance()->getAtAxis()
  750. - click_x * LLViewerCamera::getInstance()->getLeftAxis()
  751. + click_y * LLViewerCamera::getInstance()->getUpAxis();
  752. mouse_vector.normVec();
  753. return mouse_vector;
  754. }
  755. LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const
  756. {
  757. // find screen resolution
  758. S32 height = getWorldViewHeightScaled();
  759. // find world view center
  760. F32 center_x = getWorldViewRectScaled().getCenterX();
  761. F32 center_y = getWorldViewRectScaled().getCenterY();
  762. // remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5
  763. F32 hud_x = -((F32)x - center_x)  / height;
  764. F32 hud_y = ((F32)y - center_y) / height;
  765. return LLVector3(0.f, hud_x/gAgent.mHUDCurZoom, hud_y/gAgent.mHUDCurZoom);
  766. }
  767. // Returns unit vector relative to camera in camera space
  768. // indicating direction of point on screen x,y
  769. LLVector3 LLViewerWindow::mouseDirectionCamera(const S32 x, const S32 y) const
  770. {
  771. // find vertical field of view
  772. F32 fov_height = LLViewerCamera::getInstance()->getView();
  773. F32 fov_width = fov_height * LLViewerCamera::getInstance()->getAspect();
  774. // find screen resolution
  775. S32 height = getWorldViewHeightScaled();
  776. S32 width = getWorldViewWidthScaled();
  777. // find world view center
  778. F32 center_x = getWorldViewRectScaled().getCenterX();
  779. F32 center_y = getWorldViewRectScaled().getCenterY();
  780. // calculate click point relative to middle of screen
  781. F32 click_x = (((F32)x - center_x) / (F32)width) * fov_width * -1.f;
  782. F32 click_y = (((F32)y - center_y) / (F32)height) * fov_height;
  783. // compute mouse vector
  784. LLVector3 mouse_vector = LLVector3(0.f, 0.f, -1.f);
  785. LLQuaternion mouse_rotate;
  786. mouse_rotate.setQuat(click_y, click_x, 0.f);
  787. mouse_vector = mouse_vector * mouse_rotate;
  788. // project to z = -1 plane;
  789. mouse_vector = mouse_vector * (-1.f / mouse_vector.mV[VZ]);
  790. return mouse_vector;
  791. }
  792. BOOL LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, 
  793. const LLVector3d &plane_point_global, 
  794. const LLVector3 &plane_normal_global)
  795. {
  796. LLVector3d mouse_direction_global_d;
  797. mouse_direction_global_d.setVec(mouseDirectionGlobal(x,y));
  798. LLVector3d plane_normal_global_d;
  799. plane_normal_global_d.setVec(plane_normal_global);
  800. F64 plane_mouse_dot = (plane_normal_global_d * mouse_direction_global_d);
  801. LLVector3d plane_origin_camera_rel = plane_point_global - gAgent.getCameraPositionGlobal();
  802. F64 mouse_look_at_scale = (plane_normal_global_d * plane_origin_camera_rel)
  803. / plane_mouse_dot;
  804. if (llabs(plane_mouse_dot) < 0.00001)
  805. {
  806. // if mouse is parallel to plane, return closest point on line through plane origin
  807. // that is parallel to camera plane by scaling mouse direction vector
  808. // by distance to plane origin, modulated by deviation of mouse direction from plane origin
  809. LLVector3d plane_origin_dir = plane_origin_camera_rel;
  810. plane_origin_dir.normVec();
  811. mouse_look_at_scale = plane_origin_camera_rel.magVec() / (plane_origin_dir * mouse_direction_global_d);
  812. }
  813. point = gAgent.getCameraPositionGlobal() + mouse_look_at_scale * mouse_direction_global_d;
  814. return mouse_look_at_scale > 0.0;
  815. }
  816. // Returns global position
  817. BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_position_global)
  818. {
  819. LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
  820. F32 mouse_dir_scale;
  821. BOOL hit_land = FALSE;
  822. LLViewerRegion *regionp;
  823. F32 land_z;
  824. const F32 FIRST_PASS_STEP = 1.0f; // meters
  825. const F32 SECOND_PASS_STEP = 0.1f; // meters
  826. LLVector3d camera_pos_global;
  827. camera_pos_global = gAgent.getCameraPositionGlobal();
  828. LLVector3d probe_point_global;
  829. LLVector3 probe_point_region;
  830. // walk forwards to find the point
  831. for (mouse_dir_scale = FIRST_PASS_STEP; mouse_dir_scale < gAgent.mDrawDistance; mouse_dir_scale += FIRST_PASS_STEP)
  832. {
  833. LLVector3d mouse_direction_global_d;
  834. mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
  835. probe_point_global = camera_pos_global + mouse_direction_global_d;
  836. regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
  837. if (!regionp)
  838. {
  839. // ...we're outside the world somehow
  840. continue;
  841. }
  842. S32 i = (S32) (probe_point_region.mV[VX]/regionp->getLand().getMetersPerGrid());
  843. S32 j = (S32) (probe_point_region.mV[VY]/regionp->getLand().getMetersPerGrid());
  844. S32 grids_per_edge = (S32) regionp->getLand().mGridsPerEdge;
  845. if ((i >= grids_per_edge) || (j >= grids_per_edge))
  846. {
  847. //llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
  848. continue;
  849. }
  850. land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
  851. //llinfos << "mousePointOnLand initial z " << land_z << llendl;
  852. if (probe_point_region.mV[VZ] < land_z)
  853. {
  854. // ...just went under land
  855. // cout << "under land at " << probe_point << " scale " << mouse_vec_scale << endl;
  856. hit_land = TRUE;
  857. break;
  858. }
  859. }
  860. if (hit_land)
  861. {
  862. // Don't go more than one step beyond where we stopped above.
  863. // This can't just be "mouse_vec_scale" because floating point error
  864. // will stop the loop before the last increment.... X - 1.0 + 0.1 + 0.1 + ... + 0.1 != X
  865. F32 stop_mouse_dir_scale = mouse_dir_scale + FIRST_PASS_STEP;
  866. // take a step backwards, then walk forwards again to refine position
  867. for ( mouse_dir_scale -= FIRST_PASS_STEP; mouse_dir_scale <= stop_mouse_dir_scale; mouse_dir_scale += SECOND_PASS_STEP)
  868. {
  869. LLVector3d mouse_direction_global_d;
  870. mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
  871. probe_point_global = camera_pos_global + mouse_direction_global_d;
  872. regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
  873. if (!regionp)
  874. {
  875. // ...we're outside the world somehow
  876. continue;
  877. }
  878. /*
  879. i = (S32) (local_probe_point.mV[VX]/regionp->getLand().getMetersPerGrid());
  880. j = (S32) (local_probe_point.mV[VY]/regionp->getLand().getMetersPerGrid());
  881. if ((i >= regionp->getLand().mGridsPerEdge) || (j >= regionp->getLand().mGridsPerEdge))
  882. {
  883. // llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
  884. continue;
  885. }
  886. land_z = regionp->getLand().mSurfaceZ[ i + j * (regionp->getLand().mGridsPerEdge) ];
  887. */
  888. land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
  889. //llinfos << "mousePointOnLand refine z " << land_z << llendl;
  890. if (probe_point_region.mV[VZ] < land_z)
  891. {
  892. // ...just went under land again
  893. *land_position_global = probe_point_global;
  894. return TRUE;
  895. }
  896. }
  897. }
  898. return FALSE;
  899. }
  900. // Saves an image to the harddrive as "SnapshotX" where X >= 1.
  901. BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image)
  902. {
  903. if (!image)
  904. {
  905. return FALSE;
  906. }
  907. LLFilePicker::ESaveFilter pick_type;
  908. std::string extension("." + image->getExtension());
  909. if (extension == ".j2c")
  910. pick_type = LLFilePicker::FFSAVE_J2C;
  911. else if (extension == ".bmp")
  912. pick_type = LLFilePicker::FFSAVE_BMP;
  913. else if (extension == ".jpg")
  914. pick_type = LLFilePicker::FFSAVE_JPEG;
  915. else if (extension == ".png")
  916. pick_type = LLFilePicker::FFSAVE_PNG;
  917. else if (extension == ".tga")
  918. pick_type = LLFilePicker::FFSAVE_TGA;
  919. else
  920. pick_type = LLFilePicker::FFSAVE_ALL; // ???
  921. // Get a base file location if needed.
  922. if ( ! isSnapshotLocSet())
  923. {
  924. std::string proposed_name( sSnapshotBaseName );
  925. // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in.
  926. // pick a directory in which to save
  927. LLFilePicker& picker = LLFilePicker::instance();
  928. if (!picker.getSaveFile(pick_type, proposed_name))
  929. {
  930. // Clicked cancel
  931. return FALSE;
  932. }
  933. // Copy the directory + file name
  934. std::string filepath = picker.getFirstFile();
  935. LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true);
  936. LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath);
  937. }
  938. // Look for an unused file name
  939. std::string filepath;
  940. S32 i = 1;
  941. S32 err = 0;
  942. do
  943. {
  944. filepath = sSnapshotDir;
  945. filepath += gDirUtilp->getDirDelimiter();
  946. filepath += sSnapshotBaseName;
  947. filepath += llformat("_%.3d",i);
  948. filepath += extension;
  949. llstat stat_info;
  950. err = LLFile::stat( filepath, &stat_info );
  951. i++;
  952. }
  953. while( -1 != err );  // search until the file is not found (i.e., stat() gives an error).
  954. return image->save(filepath);
  955. }
  956. void LLViewerWindow::resetSnapshotLoc()
  957. {
  958. sSnapshotDir.clear();
  959. }
  960. static S32 BORDERHEIGHT = 0;
  961. static S32 BORDERWIDTH = 0;
  962. // static
  963. void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
  964. {
  965. LLCoordScreen size;
  966. gViewerWindow->mWindow->getSize(&size);
  967. if (  (size.mX != new_width + BORDERWIDTH)
  968. ||(size.mY != new_height + BORDERHEIGHT))
  969. {
  970. // use actual display dimensions, not virtual UI dimensions
  971. S32 x = gViewerWindow->getWindowWidthRaw();
  972. S32 y = gViewerWindow->getWindowHeightRaw();
  973. BORDERWIDTH = size.mX - x;
  974. BORDERHEIGHT = size.mY- y;
  975. LLCoordScreen new_size(new_width + BORDERWIDTH, 
  976.    new_height + BORDERHEIGHT);
  977. BOOL disable_sync = gSavedSettings.getBOOL("DisableVerticalSync");
  978. if (gViewerWindow->mWindow->getFullscreen())
  979. {
  980. gViewerWindow->changeDisplaySettings(FALSE, 
  981. new_size, 
  982. disable_sync, 
  983. TRUE);
  984. }
  985. else
  986. {
  987. gViewerWindow->mWindow->setSize(new_size);
  988. }
  989. }
  990. }
  991. BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
  992. {
  993. llinfos << "Saving snapshot to: " << filepath << llendl;
  994. LLPointer<LLImageRaw> raw = new LLImageRaw;
  995. BOOL success = rawSnapshot(raw, image_width, image_height, TRUE, FALSE, show_ui, do_rebuild);
  996. if (success)
  997. {
  998. LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
  999. success = bmp_image->encode(raw, 0.0f);
  1000. if( success )
  1001. {
  1002. success = bmp_image->save(filepath);
  1003. }
  1004. else
  1005. {
  1006. llwarns << "Unable to encode bmp snapshot" << llendl;
  1007. }
  1008. }
  1009. else
  1010. {
  1011. llwarns << "Unable to capture raw snapshot" << llendl;
  1012. }
  1013. return success;
  1014. }
  1015. void LLViewerWindow::playSnapshotAnimAndSound()
  1016. {
  1017. if (gSavedSettings.getBOOL("QuietSnapshotsToDisk"))
  1018. {
  1019. return;
  1020. }
  1021. gAgent.sendAnimationRequest(ANIM_AGENT_SNAPSHOT, ANIM_REQUEST_START);
  1022. send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);
  1023. }
  1024. BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
  1025. {
  1026. return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);
  1027. // *TODO below code was broken in deferred pipeline
  1028. /*
  1029. if ((!raw) || preview_width < 10 || preview_height < 10)
  1030. {
  1031. return FALSE;
  1032. }
  1033. if(gResizeScreenTexture) //the window is resizing
  1034. {
  1035. return FALSE ;
  1036. }
  1037. setCursor(UI_CURSOR_WAIT);
  1038. // Hide all the UI widgets first and draw a frame
  1039. BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
  1040. if ( prev_draw_ui != show_ui)
  1041. {
  1042. LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
  1043. }
  1044. BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
  1045. if (hide_hud)
  1046. {
  1047. LLPipeline::sShowHUDAttachments = FALSE;
  1048. }
  1049. S32 render_name = gSavedSettings.getS32("RenderName");
  1050. gSavedSettings.setS32("RenderName", 0);
  1051. LLVOAvatar::updateFreezeCounter(1) ; //pause avatar updating for one frame
  1052. S32 w = preview_width ;
  1053. S32 h = preview_height ;
  1054. LLVector2 display_scale = mDisplayScale ;
  1055. mDisplayScale.setVec((F32)w / mWindowRectRaw.getWidth(), (F32)h / mWindowRectRaw.getHeight()) ;
  1056. LLRect window_rect = mWindowRectRaw;
  1057. mWindowRectRaw.set(0, h, w, 0);
  1058. gDisplaySwapBuffers = FALSE;
  1059. gDepthDirty = TRUE;
  1060. glClearColor(0.f, 0.f, 0.f, 0.f);
  1061. glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  1062. setup3DRender();
  1063. LLFontGL::setFontDisplay(FALSE) ;
  1064. LLHUDText::setDisplayText(FALSE) ;
  1065. if (type == SNAPSHOT_TYPE_OBJECT_ID)
  1066. {
  1067. gObjectList.renderPickList(gViewerWindow->getWindowRectScaled(), FALSE, FALSE);
  1068. }
  1069. else
  1070. {
  1071. display(do_rebuild, 1.0f, 0, TRUE);
  1072. render_ui();
  1073. }
  1074. S32 glformat, gltype, glpixel_length ;
  1075. if(SNAPSHOT_TYPE_DEPTH == type)
  1076. {
  1077. glpixel_length = 4 ;
  1078. glformat = GL_DEPTH_COMPONENT ; 
  1079. gltype = GL_FLOAT ;
  1080. }
  1081. else
  1082. {
  1083. glpixel_length = 3 ;
  1084. glformat = GL_RGB ;
  1085. gltype = GL_UNSIGNED_BYTE ;
  1086. }
  1087. raw->resize(w, h, glpixel_length);
  1088. glReadPixels(0, 0, w, h, glformat, gltype, raw->getData());
  1089. if(SNAPSHOT_TYPE_DEPTH == type)
  1090. {
  1091. LLViewerCamera* camerap = LLViewerCamera::getInstance();
  1092. F32 depth_conversion_factor_1 = (camerap->getFar() + camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear());
  1093. F32 depth_conversion_factor_2 = (camerap->getFar() - camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear());
  1094. //calculate the depth 
  1095. for (S32 y = 0 ; y < h ; y++)
  1096. {
  1097. for(S32 x = 0 ; x < w ; x++)
  1098. {
  1099. S32 i = (w * y + x) << 2 ;
  1100. F32 depth_float_i = *(F32*)(raw->getData() + i);
  1101. F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float_i * depth_conversion_factor_2));
  1102. U8 depth_byte = F32_to_U8(linear_depth_float, camerap->getNear(), camerap->getFar());
  1103. *(raw->getData() + i + 0) = depth_byte;
  1104. *(raw->getData() + i + 1) = depth_byte;
  1105. *(raw->getData() + i + 2) = depth_byte;
  1106. *(raw->getData() + i + 3) = 255;
  1107. }
  1108. }
  1109. }
  1110. LLFontGL::setFontDisplay(TRUE) ;
  1111. LLHUDText::setDisplayText(TRUE) ;
  1112. mDisplayScale.setVec(display_scale) ;
  1113. mWindowRectRaw = window_rect;
  1114. setup3DRender();
  1115. gDisplaySwapBuffers = FALSE;
  1116. gDepthDirty = TRUE;
  1117. // POST SNAPSHOT
  1118. if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
  1119. {
  1120. LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
  1121. }
  1122. if (hide_hud)
  1123. {
  1124. LLPipeline::sShowHUDAttachments = TRUE;
  1125. }
  1126. setCursor(UI_CURSOR_ARROW);
  1127. if (do_rebuild)
  1128. {
  1129. // If we had to do a rebuild, that means that the lists of drawables to be rendered
  1130. // was empty before we started.
  1131. // Need to reset these, otherwise we call state sort on it again when render gets called the next time
  1132. // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
  1133. // objects on them.
  1134. gPipeline.resetDrawOrders();
  1135. }
  1136. gSavedSettings.setS32("RenderName", render_name);
  1137. return TRUE;*/
  1138. }
  1139. // Saves the image from the screen to the specified filename and path.
  1140. BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, 
  1141.  BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size)
  1142. {
  1143. if (!raw)
  1144. {
  1145. return FALSE;
  1146. }
  1147. // PRE SNAPSHOT
  1148. gDisplaySwapBuffers = FALSE;
  1149. // if not showing ui, use full window to render world view
  1150. updateWorldViewRect(!show_ui);
  1151. glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  1152. setCursor(UI_CURSOR_WAIT);
  1153. // Hide all the UI widgets first and draw a frame
  1154. BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
  1155. if ( prev_draw_ui != show_ui)
  1156. {
  1157. LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
  1158. }
  1159. BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
  1160. if (hide_hud)
  1161. {
  1162. LLPipeline::sShowHUDAttachments = FALSE;
  1163. }
  1164. // Copy screen to a buffer
  1165. // crop sides or top and bottom, if taking a snapshot of different aspect ratio
  1166. // from window
  1167. S32 snapshot_width = mWindowRectRaw.getWidth();
  1168. S32 snapshot_height =  mWindowRectRaw.getHeight();
  1169. // SNAPSHOT
  1170. S32 window_width = mWindowRectRaw.getWidth();
  1171. S32 window_height = mWindowRectRaw.getHeight();
  1172. LLRect window_rect = mWindowRectRaw;
  1173. BOOL use_fbo = FALSE;
  1174. LLRenderTarget target;
  1175. F32 scale_factor = 1.0f ;
  1176. if(!keep_window_aspect) //image cropping
  1177. {
  1178. F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
  1179. snapshot_width = (S32)(ratio * image_width) ;
  1180. snapshot_height = (S32)(ratio * image_height) ;
  1181. scale_factor = llmax(1.0f, 1.0f / ratio) ;
  1182. }
  1183. else //the scene(window) proportion needs to be maintained.
  1184. {
  1185. if(image_width > window_width || image_height > window_height) //need to enlarge the scene
  1186. {
  1187. if (!LLPipeline::sRenderDeferred && gGLManager.mHasFramebufferObject && !show_ui)
  1188. {
  1189. GLint max_size = 0;
  1190. glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &max_size);
  1191. if (image_width <= max_size && image_height <= max_size) //re-project the scene
  1192. {
  1193. use_fbo = TRUE;
  1194. snapshot_width = image_width;
  1195. snapshot_height = image_height;
  1196. target.allocate(snapshot_width, snapshot_height, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, TRUE);
  1197. window_width = snapshot_width;
  1198. window_height = snapshot_height;
  1199. scale_factor = 1.f;
  1200. mWindowRectRaw.set(0, snapshot_height, snapshot_width, 0);
  1201. target.bindTarget();
  1202. }
  1203. }
  1204. if(!use_fbo) //no re-projection, so tiling the scene
  1205. {
  1206. F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
  1207. snapshot_width = (S32)(ratio * image_width) ;
  1208. snapshot_height = (S32)(ratio * image_height) ;
  1209. scale_factor = llmax(1.0f, 1.0f / ratio) ;
  1210. }
  1211. }
  1212. //else: keep the current scene scale, re-scale it if necessary after reading out.
  1213. }
  1214. S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f);
  1215. S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f);
  1216. S32 image_buffer_x = llfloor(snapshot_width*scale_factor) ;
  1217. S32 image_buffer_y = llfloor(snapshot_height *scale_factor) ;
  1218. if(image_buffer_x > max_size || image_buffer_y > max_size) //boundary check to avoid memory overflow
  1219. {
  1220. scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ;
  1221. image_buffer_x = llfloor(snapshot_width*scale_factor) ;
  1222. image_buffer_y = llfloor(snapshot_height *scale_factor) ;
  1223. }
  1224. raw->resize(image_buffer_x, image_buffer_y, 3);
  1225. if(raw->isBufferInvalid())
  1226. {
  1227. return FALSE ;
  1228. }
  1229. BOOL high_res = scale_factor >= 2.f; // Font scaling is slow, only do so if rez is much higher
  1230. if (high_res)
  1231. {
  1232. send_agent_pause();
  1233. //rescale fonts
  1234. initFonts(scale_factor);
  1235. LLHUDText::reshape();
  1236. }
  1237. S32 output_buffer_offset_y = 0;
  1238. F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
  1239. F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
  1240. gObjectList.generatePickList(*LLViewerCamera::getInstance());
  1241. for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
  1242. {
  1243. S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);;
  1244. // handle fractional columns
  1245. U32 read_height = llmax(0, (window_height - subimage_y_offset) -
  1246. llmax(0, (window_height * (subimage_y + 1)) - (buffer_y_offset + raw->getHeight())));
  1247. S32 output_buffer_offset_x = 0;
  1248. for (int subimage_x = 0; subimage_x < scale_factor; ++subimage_x)
  1249. {
  1250. gDisplaySwapBuffers = FALSE;
  1251. gDepthDirty = TRUE;
  1252. if (type == SNAPSHOT_TYPE_OBJECT_ID)
  1253. {
  1254. glClearColor(0.f, 0.f, 0.f, 0.f);
  1255. glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  1256. LLViewerCamera::getInstance()->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor)));
  1257. setup3DRender();
  1258. gObjectList.renderPickList(gViewerWindow->getWindowRectScaled(), FALSE, FALSE);
  1259. }
  1260. else
  1261. {
  1262. const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor));
  1263. if (LLPipeline::sRenderDeferred)
  1264. {
  1265. display(do_rebuild, scale_factor, subfield, FALSE);
  1266. }
  1267. else
  1268. {
  1269. display(do_rebuild, scale_factor, subfield, TRUE);
  1270. // Required for showing the GUI in snapshots?  See DEV-16350 for details. JC
  1271. render_ui(scale_factor, subfield);
  1272. }
  1273. }
  1274. S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width);
  1275. // handle fractional rows
  1276. U32 read_width = llmax(0, (window_width - subimage_x_offset) -
  1277. llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth())));
  1278. for(U32 out_y = 0; out_y < read_height ; out_y++)
  1279. {
  1280. S32 output_buffer_offset = ( 
  1281. (out_y * (raw->getWidth())) // ...plus iterated y...
  1282. + (window_width * subimage_x) // ...plus subimage start in x...
  1283. + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y...
  1284. - output_buffer_offset_x // ...minus buffer padding x...
  1285. - (output_buffer_offset_y * (raw->getWidth()))  // ...minus buffer padding y...
  1286. ) * raw->getComponents();
  1287. // Ping the wathdog thread every 100 lines to keep us alive (arbitrary number, feel free to change)
  1288. if (out_y % 100 == 0)
  1289. {
  1290. LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot");
  1291. }
  1292. if (type == SNAPSHOT_TYPE_OBJECT_ID || type == SNAPSHOT_TYPE_COLOR)
  1293. {
  1294. glReadPixels(
  1295. subimage_x_offset, out_y + subimage_y_offset,
  1296. read_width, 1,
  1297. GL_RGB, GL_UNSIGNED_BYTE,
  1298. raw->getData() + output_buffer_offset
  1299. );
  1300. }
  1301. else // SNAPSHOT_TYPE_DEPTH
  1302. {
  1303. LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values
  1304. glReadPixels(
  1305. subimage_x_offset, out_y + subimage_y_offset,
  1306. read_width, 1,
  1307. GL_DEPTH_COMPONENT, GL_FLOAT,
  1308. depth_line_buffer->getData()// current output pixel is beginning of buffer...
  1309. );
  1310. for (S32 i = 0; i < (S32)read_width; i++)
  1311. {
  1312. F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32)));
  1313. F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2));
  1314. U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar());
  1315. //write converted scanline out to result image
  1316. for(S32 j = 0; j < raw->getComponents(); j++)
  1317. {
  1318. *(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte;
  1319. }
  1320. }
  1321. }
  1322. }
  1323. output_buffer_offset_x += subimage_x_offset;
  1324. stop_glerror();
  1325. }
  1326. output_buffer_offset_y += subimage_y_offset;
  1327. }
  1328. if (use_fbo)
  1329. {
  1330. mWindowRectRaw = window_rect;
  1331. target.flush();
  1332. glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
  1333. }
  1334. gDisplaySwapBuffers = FALSE;
  1335. gDepthDirty = TRUE;
  1336. // POST SNAPSHOT
  1337. if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
  1338. {
  1339. LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
  1340. }
  1341. if (hide_hud)
  1342. {
  1343. LLPipeline::sShowHUDAttachments = TRUE;
  1344. }
  1345. if (high_res)
  1346. {
  1347. initFonts(1.f);
  1348. LLHUDText::reshape();
  1349. }
  1350. // Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
  1351. // Note: this formula depends on the number of components being 3.  Not obvious, but it's correct.
  1352. image_width += (image_width * 3) % 4;
  1353. BOOL ret = TRUE ;
  1354. // Resize image
  1355. if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4)
  1356. {
  1357. ret = raw->scale( image_width, image_height );  
  1358. }
  1359. else if(image_width != image_buffer_x || image_height != image_buffer_y)
  1360. {
  1361. ret = raw->scale( image_width, image_height, FALSE );  
  1362. }
  1363. setCursor(UI_CURSOR_ARROW);
  1364. if (do_rebuild)
  1365. {
  1366. // If we had to do a rebuild, that means that the lists of drawables to be rendered
  1367. // was empty before we started.
  1368. // Need to reset these, otherwise we call state sort on it again when render gets called the next time
  1369. // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
  1370. // objects on them.
  1371. gPipeline.resetDrawOrders();
  1372. }
  1373. if (high_res)
  1374. {
  1375. send_agent_resume();
  1376. }
  1377. return ret;
  1378. }
  1379. void LLViewerWindow::destroyWindow()
  1380. {
  1381. if (mWindow)
  1382. {
  1383. LLWindowManager::destroyWindow(mWindow);
  1384. }
  1385. mWindow = NULL;
  1386. }
  1387. void LLViewerWindow::drawMouselookInstructions()
  1388. {
  1389. // Draw instructions for mouselook ("Press ESC to return to World View" partially transparent at the bottom of the screen.)
  1390. const std::string instructions = LLTrans::getString("LeaveMouselook");
  1391. const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Large", LLFontGL::BOLD));
  1392. //to be on top of Bottom bar when it is opened
  1393. const S32 INSTRUCTIONS_PAD = 50;
  1394. font->renderUTF8( 
  1395. instructions, 0,
  1396. getWorldViewRectScaled().getCenterX(),
  1397. getWorldViewRectScaled().mBottom + INSTRUCTIONS_PAD,
  1398. LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ),
  1399. LLFontGL::HCENTER, LLFontGL::TOP,
  1400. LLFontGL::NORMAL,LLFontGL::DROP_SHADOW);
  1401. }
  1402. void* LLViewerWindow::getPlatformWindow() const
  1403. {
  1404. return mWindow->getPlatformWindow();
  1405. }
  1406. void* LLViewerWindow::getMediaWindow()  const
  1407. {
  1408. return mWindow->getMediaWindow();
  1409. }
  1410. void LLViewerWindow::focusClient() const
  1411. {
  1412. return mWindow->focusClient();
  1413. }
  1414. LLRootView* LLViewerWindow::getRootView() const
  1415. {
  1416. return mRootView;
  1417. }
  1418. LLRect LLViewerWindow::getWorldViewRectScaled() const
  1419. {
  1420. return mWorldViewRectScaled;
  1421. }
  1422. S32 LLViewerWindow::getWorldViewHeightScaled() const
  1423. {
  1424. return mWorldViewRectScaled.getHeight();
  1425. }
  1426. S32 LLViewerWindow::getWorldViewWidthScaled() const
  1427. {
  1428. return mWorldViewRectScaled.getWidth();
  1429. }
  1430. S32 LLViewerWindow::getWorldViewHeightRaw() const
  1431. {
  1432. return mWorldViewRectRaw.getHeight(); 
  1433. }
  1434. S32 LLViewerWindow::getWorldViewWidthRaw() const
  1435. {
  1436. return mWorldViewRectRaw.getWidth(); 
  1437. }
  1438. S32 LLViewerWindow::getWindowHeightScaled() const 
  1439. return mWindowRectScaled.getHeight(); 
  1440. }
  1441. S32 LLViewerWindow::getWindowWidthScaled() const 
  1442. return mWindowRectScaled.getWidth(); 
  1443. }
  1444. S32 LLViewerWindow::getWindowHeightRaw() const 
  1445. return mWindowRectRaw.getHeight(); 
  1446. }
  1447. S32 LLViewerWindow::getWindowWidthRaw() const 
  1448. return mWindowRectRaw.getWidth(); 
  1449. }
  1450. void LLViewerWindow::setup2DRender()
  1451. {
  1452. // setup ortho camera
  1453. gl_state_for_2d(mWindowRectRaw.getWidth(), mWindowRectRaw.getHeight());
  1454. setup2DViewport();
  1455. }
  1456. void LLViewerWindow::setup2DViewport(S32 x_offset, S32 y_offset)
  1457. {
  1458. gGLViewport[0] = mWindowRectRaw.mLeft + x_offset;
  1459. gGLViewport[1] = mWindowRectRaw.mBottom + y_offset;
  1460. gGLViewport[2] = mWindowRectRaw.getWidth();
  1461. gGLViewport[3] = mWindowRectRaw.getHeight();
  1462. glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
  1463. }
  1464. void LLViewerWindow::setup3DRender()
  1465. {
  1466. // setup perspective camera
  1467. LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, mWorldViewRectRaw.mLeft, mWorldViewRectRaw.mBottom,  mWorldViewRectRaw.getWidth(), mWorldViewRectRaw.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f);
  1468. setup3DViewport();
  1469. }
  1470. void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset)
  1471. {
  1472. if (LLRenderTarget::getCurrentBoundTarget() != NULL)
  1473. {
  1474. // don't use translation component of mWorldViewRectRaw, as we are already in a properly sized render target
  1475. gGLViewport[0] = x_offset;
  1476. gGLViewport[1] = y_offset;
  1477. }
  1478. else
  1479. {
  1480. gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset;
  1481. gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset;
  1482. }
  1483. gGLViewport[2] = mWorldViewRectRaw.getWidth();
  1484. gGLViewport[3] = mWorldViewRectRaw.getHeight();
  1485. glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
  1486. }
  1487. void LLViewerWindow::setShowProgress(const BOOL show)
  1488. {
  1489. if (mProgressView)
  1490. {
  1491. mProgressView->setVisible(show);
  1492. }
  1493. }
  1494. BOOL LLViewerWindow::getShowProgress() const
  1495. {
  1496. return (mProgressView && mProgressView->getVisible());
  1497. }
  1498. void LLViewerWindow::moveProgressViewToFront()
  1499. {
  1500. if( mProgressView && mRootView )
  1501. {
  1502. mRootView->sendChildToFront(mProgressView);
  1503. }
  1504. }
  1505. void LLViewerWindow::setProgressString(const std::string& string)
  1506. {
  1507. if (mProgressView)
  1508. {
  1509. mProgressView->setText(string);
  1510. }
  1511. }
  1512. void LLViewerWindow::setProgressMessage(const std::string& msg)
  1513. {
  1514. if(mProgressView)
  1515. {
  1516. mProgressView->setMessage(msg);
  1517. }
  1518. }
  1519. void LLViewerWindow::setProgressPercent(const F32 percent)
  1520. {
  1521. if (mProgressView)
  1522. {
  1523. mProgressView->setPercent(percent);
  1524. }
  1525. }
  1526. void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string& label )
  1527. {
  1528. if (mProgressView)
  1529. {
  1530. mProgressView->setCancelButtonVisible( b, label );
  1531. }
  1532. }
  1533. LLProgressView *LLViewerWindow::getProgressView() const
  1534. {
  1535. return mProgressView;
  1536. }
  1537. void LLViewerWindow::dumpState()
  1538. {
  1539. llinfos << "LLViewerWindow Active " << S32(mActive) << llendl;
  1540. llinfos << "mWindow visible " << S32(mWindow->getVisible())
  1541. << " minimized " << S32(mWindow->getMinimized())
  1542. << llendl;
  1543. }
  1544. void LLViewerWindow::stopGL(BOOL save_state)
  1545. {
  1546. //Note: --bao
  1547. //if not necessary, do not change the order of the function calls in this function.
  1548. //if change something, make sure it will not break anything.
  1549. //especially be careful to put anything behind gTextureList.destroyGL(save_state);
  1550. if (!gGLManager.mIsDisabled)
  1551. {
  1552. llinfos << "Shutting down GL..." << llendl;
  1553. // Pause texture decode threads (will get unpaused during main loop)
  1554. LLAppViewer::getTextureCache()->pause();
  1555. LLAppViewer::getImageDecodeThread()->pause();
  1556. LLAppViewer::getTextureFetch()->pause();
  1557. gSky.destroyGL();
  1558. stop_glerror();
  1559. LLManipTranslate::destroyGL() ;
  1560. stop_glerror();
  1561. gBumpImageList.destroyGL();
  1562. stop_glerror();
  1563. LLFontGL::destroyAllGL();
  1564. stop_glerror();
  1565. LLVOAvatar::destroyGL();
  1566. stop_glerror();
  1567. LLViewerDynamicTexture::destroyGL();
  1568. stop_glerror();
  1569. if (gPipeline.isInit())
  1570. {
  1571. gPipeline.destroyGL();
  1572. }
  1573. gCone.cleanupGL();
  1574. gBox.cleanupGL();
  1575. gSphere.cleanupGL();
  1576. gCylinder.cleanupGL();
  1577. if(gPostProcess)
  1578. {
  1579. gPostProcess->invalidate();
  1580. }
  1581. gTextureList.destroyGL(save_state);
  1582. stop_glerror();
  1583. gGLManager.mIsDisabled = TRUE;
  1584. stop_glerror();
  1585. llinfos << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemoryInBytes << " bytes" << llendl;
  1586. }
  1587. }
  1588. void LLViewerWindow::restoreGL(const std::string& progress_message)
  1589. {
  1590. //Note: --bao
  1591. //if not necessary, do not change the order of the function calls in this function.
  1592. //if change something, make sure it will not break anything. 
  1593. //especially, be careful to put something before gTextureList.restoreGL();
  1594. if (gGLManager.mIsDisabled)
  1595. {
  1596. llinfos << "Restoring GL..." << llendl;
  1597. gGLManager.mIsDisabled = FALSE;
  1598. initGLDefaults();
  1599. LLGLState::restoreGL();
  1600. gTextureList.restoreGL();
  1601. // for future support of non-square pixels, and fonts that are properly stretched
  1602. //LLFontGL::destroyDefaultFonts();
  1603. initFonts();
  1604. gSky.restoreGL();
  1605. gPipeline.restoreGL();
  1606. LLDrawPoolWater::restoreGL();
  1607. LLManipTranslate::restoreGL();
  1608. gBumpImageList.restoreGL();
  1609. LLViewerDynamicTexture::restoreGL();
  1610. LLVOAvatar::restoreGL();
  1611. gResizeScreenTexture = TRUE;
  1612. if (gFloaterCustomize && gFloaterCustomize->getVisible())
  1613. {
  1614. LLVisualParamHint::requestHintUpdates();
  1615. }
  1616. if (!progress_message.empty())
  1617. {
  1618. gRestoreGLTimer.reset();
  1619. gRestoreGL = TRUE;
  1620. setShowProgress(TRUE);
  1621. setProgressString(progress_message);
  1622. }
  1623. llinfos << "...Restoring GL done" << llendl;
  1624. if(!LLAppViewer::instance()->restoreErrorTrap())
  1625. {
  1626. llwarns << " Someone took over my signal/exception handler (post restoreGL)!" << llendl;
  1627. }
  1628. }
  1629. }
  1630. void LLViewerWindow::initFonts(F32 zoom_factor)
  1631. {
  1632. LLFontGL::destroyAllGL();
  1633. // Initialize with possibly different zoom factor
  1634. LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
  1635. mDisplayScale.mV[VX] * zoom_factor,
  1636. mDisplayScale.mV[VY] * zoom_factor,
  1637. gDirUtilp->getAppRODataDir(),
  1638. LLUI::getXUIPaths());
  1639. // Force font reloads, which can be very slow
  1640. LLFontGL::loadDefaultFonts();
  1641. }
  1642. void LLViewerWindow::toggleFullscreen(BOOL show_progress)
  1643. {
  1644. if (mWindow)
  1645. {
  1646. mWantFullscreen = mWindow->getFullscreen() ? FALSE : TRUE;
  1647. mIsFullscreenChecked =  mWindow->getFullscreen() ? FALSE : TRUE;
  1648. mShowFullscreenProgress = show_progress;
  1649. }
  1650. }
  1651. void LLViewerWindow::getTargetWindow(BOOL& fullscreen, S32& width, S32& height) const
  1652. {
  1653. fullscreen = mWantFullscreen;
  1654. if (mWindow
  1655. &&  mWindow->getFullscreen() == mWantFullscreen)
  1656. {
  1657. width = getWindowWidthRaw();
  1658. height = getWindowHeightRaw();
  1659. }
  1660. else if (mWantFullscreen)
  1661. {
  1662. width = gSavedSettings.getS32("FullScreenWidth");
  1663. height = gSavedSettings.getS32("FullScreenHeight");
  1664. }
  1665. else
  1666. {
  1667. width = gSavedSettings.getS32("WindowWidth");
  1668. height = gSavedSettings.getS32("WindowHeight");
  1669. }
  1670. }
  1671. void LLViewerWindow::requestResolutionUpdate()
  1672. {
  1673. mResDirty = true;
  1674. }
  1675. void LLViewerWindow::requestResolutionUpdate(bool fullscreen_checked)
  1676. {
  1677. mResDirty = true;
  1678. mWantFullscreen = fullscreen_checked;
  1679. mIsFullscreenChecked = fullscreen_checked;
  1680. }
  1681. BOOL LLViewerWindow::checkSettings()
  1682. {
  1683. if (mStatesDirty)
  1684. {
  1685. gGL.refreshState();
  1686. LLViewerShaderMgr::instance()->setShaders();
  1687. mStatesDirty = false;
  1688. }
  1689. // We want to update the resolution AFTER the states getting refreshed not before.
  1690. if (mResDirty)
  1691. {
  1692. if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio"))
  1693. {
  1694. getWindow()->setNativeAspectRatio(0.f);
  1695. }
  1696. else
  1697. {
  1698. getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio"));
  1699. }
  1700. reshape(getWindowWidthRaw(), getWindowHeightRaw());
  1701. // force aspect ratio
  1702. if (mIsFullscreenChecked)
  1703. {
  1704. LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
  1705. }
  1706. mResDirty = false;
  1707. }
  1708. BOOL is_fullscreen = mWindow->getFullscreen();
  1709. if(mWantFullscreen)
  1710. {
  1711. LLCoordScreen screen_size;
  1712. LLCoordScreen desired_screen_size(gSavedSettings.getS32("FullScreenWidth"),
  1713.    gSavedSettings.getS32("FullScreenHeight"));
  1714. getWindow()->getSize(&screen_size);
  1715. if(!is_fullscreen || 
  1716.     screen_size.mX != desired_screen_size.mX 
  1717. || screen_size.mY != desired_screen_size.mY)
  1718. {
  1719. if (!LLStartUp::canGoFullscreen())
  1720. {
  1721. return FALSE;
  1722. }
  1723. LLGLState::checkStates();
  1724. LLGLState::checkTextureChannels();
  1725. changeDisplaySettings(TRUE, 
  1726.   desired_screen_size,
  1727.   gSavedSettings.getBOOL("DisableVerticalSync"),
  1728.   mShowFullscreenProgress);
  1729. LLGLState::checkStates();
  1730. LLGLState::checkTextureChannels();
  1731. mStatesDirty = true;
  1732. return TRUE;
  1733. }
  1734. }
  1735. else
  1736. {
  1737. if(is_fullscreen)
  1738. {
  1739. // Changing to windowed mode.
  1740. changeDisplaySettings(FALSE, 
  1741.   LLCoordScreen(gSavedSettings.getS32("WindowWidth"),
  1742. gSavedSettings.getS32("WindowHeight")),
  1743.   TRUE,
  1744.   mShowFullscreenProgress);
  1745. mStatesDirty = true;
  1746. return TRUE;
  1747. }
  1748. }
  1749. return FALSE;
  1750. }
  1751. void LLViewerWindow::restartDisplay(BOOL show_progress_bar)
  1752. {
  1753. llinfos << "Restaring GL" << llendl;
  1754. stopGL();
  1755. if (show_progress_bar)
  1756. {
  1757. restoreGL("Changing Resolution...");
  1758. }
  1759. else
  1760. {
  1761. restoreGL();
  1762. }
  1763. }
  1764. BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar)
  1765. {
  1766. BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized");
  1767. mWantFullscreen = fullscreen;
  1768. mShowFullscreenProgress = show_progress_bar;
  1769. gSavedSettings.setBOOL("WindowFullScreen", mWantFullscreen);
  1770. //gResizeScreenTexture = TRUE;
  1771. BOOL old_fullscreen = mWindow->getFullscreen();
  1772. if (!old_fullscreen && fullscreen && !LLStartUp::canGoFullscreen())
  1773. {
  1774. // Not allowed to switch to fullscreen now, so exit early.
  1775. // *NOTE: This case should never be reached, but just-in-case.
  1776. return TRUE;
  1777. }
  1778. U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
  1779. U32 old_fsaa = mWindow->getFSAASamples();
  1780. // going from windowed to windowed
  1781. if (!old_fullscreen && !fullscreen)
  1782. {
  1783. // if not maximized, use the request size
  1784. if (!mWindow->getMaximized())
  1785. {
  1786. mWindow->setSize(size);
  1787. }
  1788. if (fsaa == old_fsaa)
  1789. {
  1790. return TRUE;
  1791. }
  1792. }
  1793. // Close floaters that don't handle settings change
  1794. LLFloaterReg::hideInstance("snapshot");
  1795. BOOL result_first_try = FALSE;
  1796. BOOL result_second_try = FALSE;
  1797. LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
  1798. send_agent_pause();
  1799. llinfos << "Stopping GL during changeDisplaySettings" << llendl;
  1800. stopGL();
  1801. mIgnoreActivate = TRUE;
  1802. LLCoordScreen old_size;
  1803. LLCoordScreen old_pos;
  1804. mWindow->getSize(&old_size);
  1805. BOOL got_position = mWindow->getPosition(&old_pos);
  1806. if (!old_fullscreen && fullscreen && got_position)
  1807. {
  1808. // switching from windowed to fullscreen, so save window position
  1809. gSavedSettings.setS32("WindowX", old_pos.mX);
  1810. gSavedSettings.setS32("WindowY", old_pos.mY);
  1811. }
  1812. mWindow->setFSAASamples(fsaa);
  1813. result_first_try = mWindow->switchContext(fullscreen, size, disable_vsync);
  1814. if (!result_first_try)
  1815. {
  1816. // try to switch back
  1817. mWindow->setFSAASamples(old_fsaa);
  1818. result_second_try = mWindow->switchContext(old_fullscreen, old_size, disable_vsync);
  1819. if (!result_second_try)
  1820. {
  1821. // we are stuck...try once again with a minimal resolution?
  1822. send_agent_resume();
  1823. mIgnoreActivate = FALSE;
  1824. return FALSE;
  1825. }
  1826. }
  1827. send_agent_resume();
  1828. llinfos << "Restoring GL during resolution change" << llendl;
  1829. if (show_progress_bar)
  1830. {
  1831. restoreGL("Changing Resolution...");
  1832. }
  1833. else
  1834. {
  1835. restoreGL();
  1836. }
  1837. if (!result_first_try)
  1838. {
  1839. LLSD args;
  1840. args["RESX"] = llformat("%d",size.mX);
  1841. args["RESY"] = llformat("%d",size.mY);
  1842. LLNotificationsUtil::add("ResolutionSwitchFail", args);
  1843. size = old_size; // for reshape below
  1844. }
  1845. BOOL success = result_first_try || result_second_try;
  1846. if (success)
  1847. {
  1848. #if LL_WINDOWS
  1849. // Only trigger a reshape after switching to fullscreen; otherwise rely on the windows callback
  1850. // (otherwise size is wrong; this is the entire window size, reshape wants the visible window size)
  1851. if (fullscreen && result_first_try)
  1852. #endif
  1853. {
  1854. reshape(size.mX, size.mY);
  1855. }
  1856. }
  1857. if (!mWindow->getFullscreen() && success)
  1858. {
  1859. // maximize window if was maximized, else reposition
  1860. if (was_maximized)
  1861. {
  1862. mWindow->maximize();
  1863. }
  1864. else
  1865. {
  1866. S32 windowX = gSavedSettings.getS32("WindowX");
  1867. S32 windowY = gSavedSettings.getS32("WindowY");
  1868. mWindow->setPosition(LLCoordScreen ( windowX, windowY ) );
  1869. }
  1870. }
  1871. mIgnoreActivate = FALSE;
  1872. gFocusMgr.setKeyboardFocus(keyboard_focus);
  1873. mWantFullscreen = mWindow->getFullscreen();
  1874. mShowFullscreenProgress = FALSE;
  1875. return success;
  1876. }
  1877. F32 LLViewerWindow::getDisplayAspectRatio() const
  1878. {
  1879. if (mWindow->getFullscreen())
  1880. {
  1881. if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio"))
  1882. {
  1883. return mWindow->getNativeAspectRatio();
  1884. }
  1885. else
  1886. {
  1887. return gSavedSettings.getF32("FullScreenAspectRatio");
  1888. }
  1889. }
  1890. else
  1891. {
  1892. return mWindow->getNativeAspectRatio();
  1893. }
  1894. }
  1895. F32 LLViewerWindow::getWorldViewAspectRatio() const
  1896. {
  1897. F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight();
  1898. //F32 window_aspect = (F32)mWindowRectRaw.getWidth() / (F32)mWindowRectRaw.getHeight();
  1899. if (mWindow->getFullscreen())
  1900. {
  1901. return world_aspect * mWindow->getPixelAspectRatio();
  1902. }
  1903. else
  1904. {
  1905. return world_aspect;
  1906. }
  1907. }
  1908. void LLViewerWindow::calcDisplayScale()
  1909. {
  1910. F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
  1911. LLVector2 display_scale;
  1912. display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
  1913. F32 height_normalization = gSavedSettings.getBOOL("UIAutoScale") ? ((F32)mWindowRectRaw.getHeight() / display_scale.mV[VY]) / 768.f : 1.f;
  1914. if(mWindow->getFullscreen())
  1915. {
  1916. display_scale *= (ui_scale_factor * height_normalization);
  1917. }
  1918. else
  1919. {
  1920. display_scale *= ui_scale_factor;
  1921. }
  1922. // limit minimum display scale
  1923. if (display_scale.mV[VX] < MIN_DISPLAY_SCALE || display_scale.mV[VY] < MIN_DISPLAY_SCALE)
  1924. {
  1925. display_scale *= MIN_DISPLAY_SCALE / llmin(display_scale.mV[VX], display_scale.mV[VY]);
  1926. }
  1927. if (mWindow->getFullscreen())
  1928. {
  1929. display_scale.mV[0] = llround(display_scale.mV[0], 2.0f/(F32) mWindowRectRaw.getWidth());
  1930. display_scale.mV[1] = llround(display_scale.mV[1], 2.0f/(F32) mWindowRectRaw.getHeight());
  1931. }
  1932. if (display_scale != mDisplayScale)
  1933. {
  1934. llinfos << "Setting display scale to " << display_scale << llendl;
  1935. mDisplayScale = display_scale;
  1936. // Init default fonts
  1937. initFonts();
  1938. }
  1939. }
  1940. //static
  1941. LLRect  LLViewerWindow::calcScaledRect(const LLRect & rect, const LLVector2& display_scale)
  1942. {
  1943. LLRect res = rect;
  1944. res.mLeft = llround((F32)res.mLeft / display_scale.mV[VX]);
  1945. res.mRight = llround((F32)res.mRight / display_scale.mV[VX]);
  1946. res.mBottom = llround((F32)res.mBottom / display_scale.mV[VY]);
  1947. res.mTop = llround((F32)res.mTop / display_scale.mV[VY]);
  1948. return res;
  1949. }
  1950. S32 LLViewerWindow::getChatConsoleBottomPad()
  1951. {
  1952. S32 offset = 0;
  1953. if(LLBottomTray::instanceExists())
  1954. offset += LLBottomTray::getInstance()->getRect().getHeight();
  1955. return offset;
  1956. }
  1957. LLRect LLViewerWindow::getChatConsoleRect()
  1958. {
  1959. LLRect full_window(0, getWindowHeightScaled(), getWindowWidthScaled(), 0);
  1960. LLRect console_rect = full_window;
  1961. const S32 CONSOLE_PADDING_TOP = 24;
  1962. const S32 CONSOLE_PADDING_LEFT = 24;
  1963. const S32 CONSOLE_PADDING_RIGHT = 10;
  1964. console_rect.mTop    -= CONSOLE_PADDING_TOP;
  1965. console_rect.mBottom += getChatConsoleBottomPad();
  1966. console_rect.mLeft   += CONSOLE_PADDING_LEFT; 
  1967. static const BOOL CHAT_FULL_WIDTH = gSavedSettings.getBOOL("ChatFullWidth");
  1968. if (CHAT_FULL_WIDTH)
  1969. {
  1970. console_rect.mRight -= CONSOLE_PADDING_RIGHT;
  1971. }
  1972. else
  1973. {
  1974. // Make console rect somewhat narrow so having inventory open is
  1975. // less of a problem.
  1976. console_rect.mRight  = console_rect.mLeft + 2 * getWindowWidthScaled() / 3;
  1977. }
  1978. return console_rect;
  1979. }
  1980. //----------------------------------------------------------------------------
  1981. //static 
  1982. bool LLViewerWindow::onAlert(const LLSD& notify)
  1983. {
  1984. LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
  1985. if (gNoRender)
  1986. {
  1987. llinfos << "Alert: " << notification->getName() << llendl;
  1988. notification->respond(LLSD::emptyMap());
  1989. LLNotifications::instance().cancel(notification);
  1990. return false;
  1991. }
  1992. // If we're in mouselook, the mouse is hidden and so the user can't click 
  1993. // the dialog buttons.  In that case, change to First Person instead.
  1994. if( gAgent.cameraMouselook() )
  1995. {
  1996. gAgent.changeCameraToDefault();
  1997. }
  1998. return false;
  1999. }
  2000. ////////////////////////////////////////////////////////////////////////////
  2001. //
  2002. // LLPickInfo
  2003. //
  2004. LLPickInfo::LLPickInfo()
  2005. : mKeyMask(MASK_NONE),
  2006.   mPickCallback(NULL),
  2007.   mPickType(PICK_INVALID),
  2008.   mWantSurfaceInfo(FALSE),
  2009.   mObjectFace(-1),
  2010.   mUVCoords(-1.f, -1.f),
  2011.   mSTCoords(-1.f, -1.f),
  2012.   mXYCoords(-1, -1),
  2013.   mIntersection(),
  2014.   mNormal(),
  2015.   mBinormal(),
  2016.   mHUDIcon(NULL),
  2017.   mPickTransparent(FALSE)
  2018. {
  2019. }
  2020. LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, 
  2021.        MASK keyboard_mask, 
  2022.        BOOL pick_transparent,
  2023.        BOOL pick_uv_coords,
  2024.        void (*pick_callback)(const LLPickInfo& pick_info))
  2025. : mMousePt(mouse_pos),
  2026.   mKeyMask(keyboard_mask),
  2027.   mPickCallback(pick_callback),
  2028.   mPickType(PICK_INVALID),
  2029.   mWantSurfaceInfo(pick_uv_coords),
  2030.   mObjectFace(-1),
  2031.   mUVCoords(-1.f, -1.f),
  2032.   mSTCoords(-1.f, -1.f),
  2033.   mXYCoords(-1, -1),
  2034.   mNormal(),
  2035.   mBinormal(),
  2036.   mHUDIcon(NULL),
  2037.   mPickTransparent(pick_transparent)
  2038. {
  2039. }
  2040. void LLPickInfo::fetchResults()
  2041. {
  2042. S32 face_hit = -1;
  2043. LLVector3 intersection, normal, binormal;
  2044. LLVector2 uv;
  2045. LLHUDIcon* hit_icon = gViewerWindow->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f, &intersection);
  2046. F32 icon_dist = 0.f;
  2047. if (hit_icon)
  2048. {
  2049. icon_dist = (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec();
  2050. }
  2051. LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f,
  2052. NULL, -1, mPickTransparent, &face_hit,
  2053. &intersection, &uv, &normal, &binormal);
  2054. mPickPt = mMousePt;
  2055. U32 te_offset = face_hit > -1 ? face_hit : 0;
  2056. //unproject relative clicked coordinate from window coordinate using GL
  2057. LLViewerObject* objectp = hit_object;
  2058. if (hit_icon && 
  2059. (!objectp || 
  2060. icon_dist < (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec()))
  2061. {
  2062. // was this name referring to a hud icon?
  2063. mHUDIcon = hit_icon;
  2064. mPickType = PICK_ICON;
  2065. mPosGlobal = mHUDIcon->getPositionGlobal();
  2066. }
  2067. else if (objectp)
  2068. {
  2069. if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
  2070. {
  2071. // Hit land
  2072. mPickType = PICK_LAND;
  2073. mObjectID.setNull(); // land has no id
  2074. // put global position into land_pos
  2075. LLVector3d land_pos;
  2076. if (!gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos))
  2077. {
  2078. // The selected point is beyond the draw distance or is otherwise 
  2079. // not selectable. Return before calling mPickCallback().
  2080. return;
  2081. }
  2082. // Fudge the land focus a little bit above ground.
  2083. mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f;
  2084. }
  2085. else
  2086. {
  2087. if(isFlora(objectp))
  2088. {
  2089. mPickType = PICK_FLORA;
  2090. }
  2091. else
  2092. {
  2093. mPickType = PICK_OBJECT;
  2094. }
  2095. mObjectOffset = gAgent.calcFocusOffset(objectp, intersection, mPickPt.mX, mPickPt.mY);
  2096. mObjectID = objectp->mID;
  2097. mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset;
  2098. mPosGlobal = gAgent.getPosGlobalFromAgent(intersection);
  2099. if (mWantSurfaceInfo)
  2100. {
  2101. getSurfaceInfo();
  2102. }
  2103. }
  2104. }
  2105. if (mPickCallback)
  2106. {
  2107. mPickCallback(*this);
  2108. }
  2109. }
  2110. LLPointer<LLViewerObject> LLPickInfo::getObject() const
  2111. {
  2112. return gObjectList.findObject( mObjectID );
  2113. }
  2114. void LLPickInfo::updateXYCoords()
  2115. {
  2116. if (mObjectFace > -1)
  2117. {
  2118. const LLTextureEntry* tep = getObject()->getTE(mObjectFace);
  2119. LLPointer<LLViewerTexture> imagep = LLViewerTextureManager::getFetchedTexture(tep->getID());
  2120. if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull())
  2121. {
  2122. mXYCoords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth());
  2123. mXYCoords.mY = llround((1.f - mUVCoords.mV[VY]) * (F32)imagep->getHeight());
  2124. }
  2125. }
  2126. }
  2127. void LLPickInfo::getSurfaceInfo()
  2128. {
  2129. // set values to uninitialized - this is what we return if no intersection is found
  2130. mObjectFace   = -1;
  2131. mUVCoords     = LLVector2(-1, -1);
  2132. mSTCoords     = LLVector2(-1, -1);
  2133. mXYCoords   = LLCoordScreen(-1, -1);
  2134. mIntersection = LLVector3(0,0,0);
  2135. mNormal       = LLVector3(0,0,0);
  2136. mBinormal     = LLVector3(0,0,0);
  2137. LLViewerObject* objectp = getObject();
  2138. if (objectp)
  2139. {
  2140. if (gViewerWindow->cursorIntersect(llround((F32)mMousePt.mX), llround((F32)mMousePt.mY), 1024.f,
  2141.    objectp, -1, mPickTransparent,
  2142.    &mObjectFace,
  2143.    &mIntersection,
  2144.    &mSTCoords,
  2145.    &mNormal,
  2146.    &mBinormal))
  2147. {
  2148. // if we succeeded with the intersect above, compute the texture coordinates:
  2149. if (objectp->mDrawable.notNull() && mObjectFace > -1)
  2150. {
  2151. LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
  2152. mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal);
  2153. }
  2154. // and XY coords:
  2155. updateXYCoords();
  2156. }
  2157. }
  2158. }
  2159. /* code to get UV via a special UV render - removed in lieu of raycast method
  2160. LLVector2 LLPickInfo::pickUV()
  2161. {
  2162. LLVector2 result(-1.f, -1.f);
  2163. LLViewerObject* objectp = getObject();
  2164. if (!objectp)
  2165. {
  2166. return result;
  2167. }
  2168. if (mObjectFace > -1 &&
  2169. objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME &&
  2170. mObjectFace < objectp->mDrawable->getNumFaces())
  2171. {
  2172. S32 scaled_x = llround((F32)mPickPt.mX * gViewerWindow->getDisplayScale().mV[VX]);
  2173. S32 scaled_y = llround((F32)mPickPt.mY * gViewerWindow->getDisplayScale().mV[VY]);
  2174. const S32 UV_PICK_WIDTH = 5;
  2175. const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
  2176. U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
  2177. LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
  2178. if (facep)
  2179. {
  2180. LLGLState scissor_state(GL_SCISSOR_TEST);
  2181. scissor_state.enable();
  2182. LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
  2183. //glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
  2184. glScissor(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
  2185. glClear(GL_DEPTH_BUFFER_BIT);
  2186. facep->renderSelectedUV();
  2187. 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);
  2188. U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)];
  2189. result.mV[VX] = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f;
  2190. result.mV[VY] = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f;
  2191. }
  2192. }
  2193. return result;
  2194. } */
  2195. //static 
  2196. bool LLPickInfo::isFlora(LLViewerObject* object)
  2197. {
  2198. if (!object) return false;
  2199. LLPCode pcode = object->getPCode();
  2200. if( (LL_PCODE_LEGACY_GRASS == pcode) 
  2201. || (LL_PCODE_LEGACY_TREE == pcode) 
  2202. || (LL_PCODE_TREE_NEW == pcode))
  2203. {
  2204. return true;
  2205. }
  2206. return false;
  2207. }