llviewerwindow.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:146k
- viewp->onMouseEnter(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
- }
- }
- // call onMouseLeave() on all views which no longer contain the mouse cursor
- view_handle_list_t mouse_leave_views;
- std::set_difference(mMouseHoverViews.begin(), mMouseHoverViews.end(),
- mouse_hover_set.begin(), mouse_hover_set.end(),
- std::back_inserter(mouse_leave_views));
- for (view_handle_list_t::iterator it = mouse_leave_views.begin();
- it != mouse_leave_views.end();
- ++it)
- {
- LLView* viewp = it->get();
- if (viewp)
- {
- LLRect view_screen_rect = viewp->calcScreenRect();
- viewp->onMouseLeave(x - view_screen_rect.mLeft, y - view_screen_rect.mBottom, mask);
- }
- }
- // store resulting hover set for next frame
- swap(mMouseHoverViews, mouse_hover_set);
- if( mouse_captor )
- {
- // Pass hover events to object capturing mouse events.
- S32 local_x;
- S32 local_y;
- mouse_captor->screenPointToLocal( x, y, &local_x, &local_y );
- handled = mouse_captor->handleHover(local_x, local_y, mask);
- if (LLView::sDebugMouseHandling)
- {
- llinfos << "Hover handled by captor " << mouse_captor->getName() << llendl;
- }
- if( !handled )
- {
- lldebugst(LLERR_USER_INPUT) << "hover not handled by mouse captor" << llendl;
- }
- }
- else
- {
- if (top_ctrl)
- {
- S32 local_x, local_y;
- top_ctrl->screenPointToLocal( x, y, &local_x, &local_y );
- handled = top_ctrl->pointInView(local_x, local_y) && top_ctrl->handleHover(local_x, local_y, mask);
- handled_by_top_ctrl = TRUE;
- }
- if ( !handled )
- {
- // x and y are from last time mouse was in window
- // mMouseInWindow tracks *actual* mouse location
- if (mMouseInWindow && mRootView->handleHover(x, y, mask) )
- {
- if (LLView::sDebugMouseHandling && LLView::sMouseHandlerMessage != last_handle_msg)
- {
- last_handle_msg = LLView::sMouseHandlerMessage;
- llinfos << "Hover" << LLView::sMouseHandlerMessage << llendl;
- }
- handled = TRUE;
- }
- else if (LLView::sDebugMouseHandling)
- {
- if (last_handle_msg != LLStringUtil::null)
- {
- last_handle_msg.clear();
- llinfos << "Hover not handled by view" << llendl;
- }
- }
- }
- if (!handled)
- {
- LLTool *tool = LLToolMgr::getInstance()->getCurrentTool();
- if(mMouseInWindow && tool)
- {
- handled = tool->handleHover(x, y, mask);
- }
- }
- }
- // Show a new tool tip (or update one that is already shown)
- BOOL tool_tip_handled = FALSE;
- std::string tool_tip_msg;
- if( handled
- && !mWindow->isCursorHidden())
- {
- LLRect screen_sticky_rect = mRootView->getLocalRect();
- S32 local_x, local_y;
- if (gSavedSettings.getBOOL("DebugShowXUINames"))
- {
- LLToolTip::Params params;
- LLView* tooltip_view = mRootView;
- LLView::tree_iterator_t end_it = mRootView->endTreeDFS();
- for (LLView::tree_iterator_t it = mRootView->beginTreeDFS(); it != end_it; ++it)
- {
- LLView* viewp = *it;
- LLRect screen_rect;
- viewp->localRectToScreen(viewp->getLocalRect(), &screen_rect);
- if (!(viewp->getVisible()
- && screen_rect.pointInRect(x, y)))
- {
- it.skipDescendants();
- }
- // only report xui names for LLUICtrls,
- // and blacklist the various containers we don't care about
- else if (dynamic_cast<LLUICtrl*>(viewp)
- && viewp != gMenuHolder
- && viewp != gFloaterView
- && viewp != gConsole)
- {
- if (dynamic_cast<LLFloater*>(viewp))
- {
- // constrain search to descendants of this (frontmost) floater
- // by resetting iterator
- it = viewp->beginTreeDFS();
- }
- // if we are in a new part of the tree (not a descendent of current tooltip_view)
- // then push the results for tooltip_view and start with a new potential view
- // NOTE: this emulates visiting only the leaf nodes that meet our criteria
- if (!viewp->hasAncestor(tooltip_view))
- {
- append_xui_tooltip(tooltip_view, params);
- screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
- }
- tooltip_view = viewp;
- }
- }
- append_xui_tooltip(tooltip_view, params);
- screen_sticky_rect.intersectWith(tooltip_view->calcScreenRect());
-
- params.sticky_rect = screen_sticky_rect;
- params.max_width = 400;
- LLToolTipMgr::instance().show(params);
- }
- // if there is a mouse captor, nothing else gets a tooltip
- else if (mouse_captor)
- {
- mouse_captor->screenPointToLocal(x, y, &local_x, &local_y);
- tool_tip_handled = mouse_captor->handleToolTip(local_x, local_y, mask);
- }
- else
- {
- // next is top_ctrl
- if (!tool_tip_handled && top_ctrl)
- {
- top_ctrl->screenPointToLocal(x, y, &local_x, &local_y);
- tool_tip_handled = top_ctrl->handleToolTip(local_x, local_y, mask );
- }
-
- if (!tool_tip_handled)
- {
- local_x = x; local_y = y;
- tool_tip_handled = mRootView->handleToolTip(local_x, local_y, mask );
- }
- LLTool* current_tool = LLToolMgr::getInstance()->getCurrentTool();
- if (!tool_tip_handled && current_tool)
- {
- current_tool->screenPointToLocal(x, y, &local_x, &local_y);
- tool_tip_handled = current_tool->handleToolTip(local_x, local_y, mask );
- }
- }
- }
-
- updateLayout();
- mLastMousePoint = mCurrentMousePoint;
- // cleanup unused selections when no modal dialogs are open
- if (LLModalDialog::activeCount() == 0)
- {
- LLViewerParcelMgr::getInstance()->deselectUnused();
- }
- if (LLModalDialog::activeCount() == 0)
- {
- LLSelectMgr::getInstance()->deselectUnused();
- }
- }
- void LLViewerWindow::updateLayout()
- {
- LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
- if (gFloaterTools != NULL
- && tool != NULL
- && tool != gToolNull
- && tool != LLToolCompInspect::getInstance()
- && tool != LLToolDragAndDrop::getInstance()
- && !gSavedSettings.getBOOL("FreezeTime"))
- {
- // Suppress the toolbox view if our source tool was the pie tool,
- // and we've overridden to something else.
- bool suppress_toolbox =
- (LLToolMgr::getInstance()->getBaseTool() == LLToolPie::getInstance()) &&
- (LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance());
- LLMouseHandler *captor = gFocusMgr.getMouseCapture();
- // With the null, inspect, or drag and drop tool, don't muck
- // with visibility.
- if (gFloaterTools->isMinimized()
- || (tool != LLToolPie::getInstance() // not default tool
- && tool != LLToolCompGun::getInstance() // not coming out of mouselook
- && !suppress_toolbox // not override in third person
- && LLToolMgr::getInstance()->getCurrentToolset() != gFaceEditToolset // not special mode
- && LLToolMgr::getInstance()->getCurrentToolset() != gMouselookToolset
- && (!captor || dynamic_cast<LLView*>(captor) != NULL))) // not dragging
- {
- // Force floater tools to be visible (unless minimized)
- if (!gFloaterTools->getVisible())
- {
- gFloaterTools->openFloater();
- }
- // Update the location of the blue box tool popup
- LLCoordGL select_center_screen;
- gFloaterTools->updatePopup( select_center_screen, gKeyboard->currentMask(TRUE) );
- }
- else
- {
- gFloaterTools->setVisible(FALSE);
- }
- //gMenuBarView->setItemVisible("BuildTools", gFloaterTools->getVisible());
- }
- // Always update console
- if(gConsole)
- {
- LLRect console_rect = getChatConsoleRect();
- gConsole->reshape(console_rect.getWidth(), console_rect.getHeight());
- gConsole->setRect(console_rect);
- }
- }
- void LLViewerWindow::updateMouseDelta()
- {
- S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]);
- S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]);
- //RN: fix for asynchronous notification of mouse leaving window not working
- LLCoordWindow mouse_pos;
- mWindow->getCursorPosition(&mouse_pos);
- if (mouse_pos.mX < 0 ||
- mouse_pos.mY < 0 ||
- mouse_pos.mX > mWindowRectRaw.getWidth() ||
- mouse_pos.mY > mWindowRectRaw.getHeight())
- {
- mMouseInWindow = FALSE;
- }
- else
- {
- mMouseInWindow = TRUE;
- }
- LLVector2 mouse_vel;
- if (gSavedSettings.getBOOL("MouseSmooth"))
- {
- static F32 fdx = 0.f;
- static F32 fdy = 0.f;
- F32 amount = 16.f;
- fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f);
- fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f);
- mCurrentMouseDelta.set(llround(fdx), llround(fdy));
- mouse_vel.setVec(fdx,fdy);
- }
- else
- {
- mCurrentMouseDelta.set(dx, dy);
- mouse_vel.setVec((F32) dx, (F32) dy);
- }
-
- mMouseVelocityStat.addValue(mouse_vel.magVec());
- }
- void LLViewerWindow::updateKeyboardFocus()
- {
- // clean up current focus
- LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
- if (cur_focus)
- {
- if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain())
- {
- // don't release focus, just reassign so that if being given
- // to a sibling won't call onFocusLost on all the ancestors
- // gFocusMgr.releaseFocusIfNeeded(cur_focus);
- LLUICtrl* parent = cur_focus->getParentUICtrl();
- const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot();
- while(parent)
- {
- if (parent->isCtrl() &&
- (parent->hasTabStop() || parent == focus_root) &&
- !parent->getIsChrome() &&
- parent->isInVisibleChain() &&
- parent->isInEnabledChain())
- {
- if (!parent->focusFirstItem())
- {
- parent->setFocus(TRUE);
- }
- break;
- }
- parent = parent->getParentUICtrl();
- }
- // if we didn't find a better place to put focus, just release it
- // hasFocus() will return true if and only if we didn't touch focus since we
- // are only moving focus higher in the hierarchy
- if (cur_focus->hasFocus())
- {
- cur_focus->setFocus(FALSE);
- }
- }
- else if (cur_focus->isFocusRoot())
- {
- // focus roots keep trying to delegate focus to their first valid descendant
- // this assumes that focus roots are not valid focus holders on their own
- cur_focus->focusFirstItem();
- }
- }
- // last ditch force of edit menu to selection manager
- if (LLEditMenuHandler::gEditMenuHandler == NULL && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
- {
- LLEditMenuHandler::gEditMenuHandler = LLSelectMgr::getInstance();
- }
- if (gFloaterView->getCycleMode())
- {
- // sync all floaters with their focus state
- gFloaterView->highlightFocusedFloater();
- gSnapshotFloaterView->highlightFocusedFloater();
- if ((gKeyboard->currentMask(TRUE) & MASK_CONTROL) == 0)
- {
- // control key no longer held down, finish cycle mode
- gFloaterView->setCycleMode(FALSE);
- gFloaterView->syncFloaterTabOrder();
- }
- else
- {
- // user holding down CTRL, don't update tab order of floaters
- }
- }
- else
- {
- // update focused floater
- gFloaterView->highlightFocusedFloater();
- gSnapshotFloaterView->highlightFocusedFloater();
- // make sure floater visible order is in sync with tab order
- gFloaterView->syncFloaterTabOrder();
- }
- if(LLSideTray::instanceCreated())//just getInstance will create sidetray. we don't want this
- LLSideTray::getInstance()->highlightFocused();
- }
- static LLFastTimer::DeclareTimer FTM_UPDATE_WORLD_VIEW("Update World View");
- void LLViewerWindow::updateWorldViewRect(bool use_full_window)
- {
- LLFastTimer ft(FTM_UPDATE_WORLD_VIEW);
- // start off using whole window to render world
- LLRect new_world_rect = mWindowRectRaw;
- if (use_full_window == false && mWorldViewPlaceholder.get())
- {
- new_world_rect = mWorldViewPlaceholder.get()->calcScreenRect();
- // clamp to at least a 1x1 rect so we don't try to allocate zero width gl buffers
- new_world_rect.mTop = llmax(new_world_rect.mTop, new_world_rect.mBottom + 1);
- new_world_rect.mRight = llmax(new_world_rect.mRight, new_world_rect.mLeft + 1);
- new_world_rect.mLeft = llround((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]);
- new_world_rect.mRight = llround((F32)new_world_rect.mRight * mDisplayScale.mV[VX]);
- new_world_rect.mBottom = llround((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]);
- new_world_rect.mTop = llround((F32)new_world_rect.mTop * mDisplayScale.mV[VY]);
- }
- if (mWorldViewRectRaw != new_world_rect)
- {
- LLRect old_world_rect = mWorldViewRectRaw;
- mWorldViewRectRaw = new_world_rect;
- gResizeScreenTexture = TRUE;
- LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() );
- LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
- mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale);
- // sending a signal with a new WorldView rect
- old_world_rect = calcScaledRect(old_world_rect, mDisplayScale);
- mOnWorldViewRectUpdated(old_world_rect, mWorldViewRectScaled);
- }
- }
- void LLViewerWindow::saveLastMouse(const LLCoordGL &point)
- {
- // Store last mouse location.
- // If mouse leaves window, pretend last point was on edge of window
- if (point.mX < 0)
- {
- mCurrentMousePoint.mX = 0;
- }
- else if (point.mX > getWindowWidthScaled())
- {
- mCurrentMousePoint.mX = getWindowWidthScaled();
- }
- else
- {
- mCurrentMousePoint.mX = point.mX;
- }
- if (point.mY < 0)
- {
- mCurrentMousePoint.mY = 0;
- }
- else if (point.mY > getWindowHeightScaled() )
- {
- mCurrentMousePoint.mY = getWindowHeightScaled();
- }
- else
- {
- mCurrentMousePoint.mY = point.mY;
- }
- }
- // Draws the selection outlines for the currently selected objects
- // Must be called after displayObjects is called, which sets the mGLName parameter
- // NOTE: This function gets called 3 times:
- // render_ui_3d: FALSE, FALSE, TRUE
- // renderObjectsForSelect: TRUE, pick_parcel_wall, FALSE
- // render_hud_elements: FALSE, FALSE, FALSE
- void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud )
- {
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- if (!for_hud && !for_gl_pick)
- {
- // Call this once and only once
- LLSelectMgr::getInstance()->updateSilhouettes();
- }
-
- // Draw fence around land selections
- if (for_gl_pick)
- {
- if (pick_parcel_walls)
- {
- LLViewerParcelMgr::getInstance()->renderParcelCollision();
- }
- }
- else if (( for_hud && selection->getSelectType() == SELECT_TYPE_HUD) ||
- (!for_hud && selection->getSelectType() != SELECT_TYPE_HUD))
- {
- LLSelectMgr::getInstance()->renderSilhouettes(for_hud);
-
- stop_glerror();
- // setup HUD render
- if (selection->getSelectType() == SELECT_TYPE_HUD && LLSelectMgr::getInstance()->getSelection()->getObjectCount())
- {
- LLBBox hud_bbox = gAgent.getAvatarObject()->getHUDBBox();
- // set up transform to encompass bounding box of HUD
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
- glOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth);
-
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame
- glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f);
- }
- // Render light for editing
- if (LLSelectMgr::sRenderLightRadius && LLToolMgr::getInstance()->inEdit())
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- LLGLEnable gls_blend(GL_BLEND);
- LLGLEnable gls_cull(GL_CULL_FACE);
- LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- if (selection->getSelectType() == SELECT_TYPE_HUD)
- {
- F32 zoom = gAgent.mHUDCurZoom;
- glScalef(zoom, zoom, zoom);
- }
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* object)
- {
- LLDrawable* drawable = object->mDrawable;
- if (drawable && drawable->isLight())
- {
- LLVOVolume* vovolume = drawable->getVOVolume();
- glPushMatrix();
- LLVector3 center = drawable->getPositionAgent();
- glTranslatef(center[0], center[1], center[2]);
- F32 scale = vovolume->getLightRadius();
- glScalef(scale, scale, scale);
- LLColor4 color(vovolume->getLightColor(), .5f);
- glColor4fv(color.mV);
-
- F32 pixel_area = 100000.f;
- // Render Outside
- gSphere.render(pixel_area);
- // Render Inside
- glCullFace(GL_FRONT);
- gSphere.render(pixel_area);
- glCullFace(GL_BACK);
-
- glPopMatrix();
- }
- return true;
- }
- } func;
- LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func);
-
- glPopMatrix();
- }
-
- // NOTE: The average position for the axis arrows of the selected objects should
- // not be recalculated at this time. If they are, then group rotations will break.
- // Draw arrows at average center of all selected objects
- LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
- if (tool)
- {
- if(tool->isAlwaysRendered())
- {
- tool->render();
- }
- else
- {
- if( !LLSelectMgr::getInstance()->getSelection()->isEmpty() )
- {
- BOOL moveable_object_selected = FALSE;
- BOOL all_selected_objects_move = TRUE;
- BOOL all_selected_objects_modify = TRUE;
- BOOL selecting_linked_set = !gSavedSettings.getBOOL("EditLinkedParts");
- for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
- iter != LLSelectMgr::getInstance()->getSelection()->end(); iter++)
- {
- LLSelectNode* nodep = *iter;
- LLViewerObject* object = nodep->getObject();
- BOOL this_object_movable = FALSE;
- if (object->permMove() && (object->permModify() || selecting_linked_set))
- {
- moveable_object_selected = TRUE;
- this_object_movable = TRUE;
- }
- all_selected_objects_move = all_selected_objects_move && this_object_movable;
- all_selected_objects_modify = all_selected_objects_modify && object->permModify();
- }
- BOOL draw_handles = TRUE;
- if (tool == LLToolCompTranslate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
- {
- draw_handles = FALSE;
- }
- if (tool == LLToolCompRotate::getInstance() && (!moveable_object_selected || !all_selected_objects_move))
- {
- draw_handles = FALSE;
- }
- if ( !all_selected_objects_modify && tool == LLToolCompScale::getInstance() )
- {
- draw_handles = FALSE;
- }
-
- if( draw_handles )
- {
- tool->render();
- }
- }
- }
- if (selection->getSelectType() == SELECT_TYPE_HUD && selection->getObjectCount())
- {
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- stop_glerror();
- }
- }
- }
- }
- // Return a point near the clicked object representative of the place the object was clicked.
- LLVector3d LLViewerWindow::clickPointInWorldGlobal(S32 x, S32 y_from_bot, LLViewerObject* clicked_object) const
- {
- // create a normalized vector pointing from the camera center into the
- // world at the location of the mouse click
- LLVector3 mouse_direction_global = mouseDirectionGlobal( x, y_from_bot );
- LLVector3d relative_object = clicked_object->getPositionGlobal() - gAgent.getCameraPositionGlobal();
- // make mouse vector as long as object vector, so it touchs a point near
- // where the user clicked on the object
- mouse_direction_global *= (F32) relative_object.magVec();
- LLVector3d new_pos;
- new_pos.setVec(mouse_direction_global);
- // transform mouse vector back to world coords
- new_pos += gAgent.getCameraPositionGlobal();
- return new_pos;
- }
- BOOL LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const
- {
- BOOL intersect = FALSE;
- // U8 shape = objectp->mPrimitiveCode & LL_PCODE_BASE_MASK;
- if (!intersect)
- {
- point_global = clickPointInWorldGlobal(x, y, objectp);
- llinfos << "approx intersection at " << (objectp->getPositionGlobal() - point_global) << llendl;
- }
- else
- {
- llinfos << "good intersection at " << (objectp->getPositionGlobal() - point_global) << llendl;
- }
- return intersect;
- }
- void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback)(const LLPickInfo& info), BOOL pick_transparent)
- {
- if (gNoRender)
- {
- return;
- }
-
- BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
- if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
- {
- // build mode allows interaction with all transparent objects
- // "Show Debug Alpha" means no object actually transparent
- pick_transparent = TRUE;
- }
- LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, TRUE, callback);
- schedulePick(pick_info);
- }
- void LLViewerWindow::schedulePick(LLPickInfo& pick_info)
- {
- if (mPicks.size() >= 1024 || mWindow->getMinimized())
- { //something went wrong, picks are being scheduled but not processed
-
- if (pick_info.mPickCallback)
- {
- pick_info.mPickCallback(pick_info);
- }
-
- return;
- }
- mPicks.push_back(pick_info);
-
- // delay further event processing until we receive results of pick
- // only do this for async picks so that handleMouseUp won't be called
- // until the pick triggered in handleMouseDown has been processed, for example
- mWindow->delayInputProcessing();
- }
- void LLViewerWindow::performPick()
- {
- if (gNoRender)
- {
- return;
- }
- if (!mPicks.empty())
- {
- std::vector<LLPickInfo>::iterator pick_it;
- for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
- {
- pick_it->fetchResults();
- }
- mLastPick = mPicks.back();
- mPicks.clear();
- }
- }
- void LLViewerWindow::returnEmptyPicks()
- {
- std::vector<LLPickInfo>::iterator pick_it;
- for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it)
- {
- mLastPick = *pick_it;
- // just trigger callback with empty results
- if (pick_it->mPickCallback)
- {
- pick_it->mPickCallback(*pick_it);
- }
- }
- mPicks.clear();
- }
- // Performs the GL object/land pick.
- LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_transparent)
- {
- if (gNoRender)
- {
- return LLPickInfo();
- }
- BOOL in_build_mode = LLFloaterReg::instanceVisible("build");
- if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha)
- {
- // build mode allows interaction with all transparent objects
- // "Show Debug Alpha" means no object actually transparent
- pick_transparent = TRUE;
- }
- // shortcut queueing in mPicks and just update mLastPick in place
- mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), gKeyboard->currentMask(TRUE), pick_transparent, TRUE, NULL);
- mLastPick.fetchResults();
- return mLastPick;
- }
- LLHUDIcon* LLViewerWindow::cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth,
- LLVector3* intersection)
- {
- S32 x = mouse_x;
- S32 y = mouse_y;
- if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
- {
- x = getCurrentMouseX();
- y = getCurrentMouseY();
- }
- // world coordinates of mouse
- LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
- LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
- LLVector3 mouse_world_start = mouse_point_global;
- LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth;
- return LLHUDIcon::lineSegmentIntersectAll(mouse_world_start, mouse_world_end, intersection);
-
- }
- LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth,
- LLViewerObject *this_object,
- S32 this_face,
- BOOL pick_transparent,
- S32* face_hit,
- LLVector3 *intersection,
- LLVector2 *uv,
- LLVector3 *normal,
- LLVector3 *binormal)
- {
- S32 x = mouse_x;
- S32 y = mouse_y;
- if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position
- {
- x = getCurrentMouseX();
- y = getCurrentMouseY();
- }
- // HUD coordinates of mouse
- LLVector3 mouse_point_hud = mousePointHUD(x, y);
- LLVector3 mouse_hud_start = mouse_point_hud - LLVector3(depth, 0, 0);
- LLVector3 mouse_hud_end = mouse_point_hud + LLVector3(depth, 0, 0);
-
- // world coordinates of mouse
- LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
- LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin();
-
- //get near clip plane
- LLVector3 n = LLViewerCamera::getInstance()->getAtAxis();
- LLVector3 p = mouse_point_global + n * LLViewerCamera::getInstance()->getNear();
- //project mouse point onto plane
- LLVector3 pos;
- line_plane(mouse_point_global, mouse_direction_global, p, n, pos);
- mouse_point_global = pos;
- LLVector3 mouse_world_start = mouse_point_global;
- LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth;
-
- LLViewerObject* found = NULL;
- if (this_object) // check only this object
- {
- if (this_object->isHUDAttachment()) // is a HUD object?
- {
- if (this_object->lineSegmentIntersect(mouse_hud_start, mouse_hud_end, this_face, pick_transparent,
- face_hit, intersection, uv, normal, binormal))
- {
- found = this_object;
- }
- }
-
- else // is a world object
- {
- if (this_object->lineSegmentIntersect(mouse_world_start, mouse_world_end, this_face, pick_transparent,
- face_hit, intersection, uv, normal, binormal))
- {
- found = this_object;
- }
- }
- }
- else // check ALL objects
- {
- found = gPipeline.lineSegmentIntersectInHUD(mouse_hud_start, mouse_hud_end, pick_transparent,
- face_hit, intersection, uv, normal, binormal);
- if (!found) // if not found in HUD, look in world:
- {
- found = gPipeline.lineSegmentIntersectInWorld(mouse_world_start, mouse_world_end, pick_transparent,
- face_hit, intersection, uv, normal, binormal);
- }
- }
- return found;
- }
- // Returns unit vector relative to camera
- // indicating direction of point on screen x,y
- LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const
- {
- // find vertical field of view
- F32 fov = LLViewerCamera::getInstance()->getView();
- // find world view center in scaled ui coordinates
- F32 center_x = getWorldViewRectScaled().getCenterX();
- F32 center_y = getWorldViewRectScaled().getCenterY();
- // calculate pixel distance to screen
- F32 distance = ((F32)getWorldViewHeightScaled() * 0.5f) / (tan(fov / 2.f));
- // calculate click point relative to middle of screen
- F32 click_x = x - center_x;
- F32 click_y = y - center_y;
- // compute mouse vector
- LLVector3 mouse_vector = distance * LLViewerCamera::getInstance()->getAtAxis()
- - click_x * LLViewerCamera::getInstance()->getLeftAxis()
- + click_y * LLViewerCamera::getInstance()->getUpAxis();
- mouse_vector.normVec();
- return mouse_vector;
- }
- LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const
- {
- // find screen resolution
- S32 height = getWorldViewHeightScaled();
- // find world view center
- F32 center_x = getWorldViewRectScaled().getCenterX();
- F32 center_y = getWorldViewRectScaled().getCenterY();
- // remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5
- F32 hud_x = -((F32)x - center_x) / height;
- F32 hud_y = ((F32)y - center_y) / height;
- return LLVector3(0.f, hud_x/gAgent.mHUDCurZoom, hud_y/gAgent.mHUDCurZoom);
- }
- // Returns unit vector relative to camera in camera space
- // indicating direction of point on screen x,y
- LLVector3 LLViewerWindow::mouseDirectionCamera(const S32 x, const S32 y) const
- {
- // find vertical field of view
- F32 fov_height = LLViewerCamera::getInstance()->getView();
- F32 fov_width = fov_height * LLViewerCamera::getInstance()->getAspect();
- // find screen resolution
- S32 height = getWorldViewHeightScaled();
- S32 width = getWorldViewWidthScaled();
- // find world view center
- F32 center_x = getWorldViewRectScaled().getCenterX();
- F32 center_y = getWorldViewRectScaled().getCenterY();
- // calculate click point relative to middle of screen
- F32 click_x = (((F32)x - center_x) / (F32)width) * fov_width * -1.f;
- F32 click_y = (((F32)y - center_y) / (F32)height) * fov_height;
- // compute mouse vector
- LLVector3 mouse_vector = LLVector3(0.f, 0.f, -1.f);
- LLQuaternion mouse_rotate;
- mouse_rotate.setQuat(click_y, click_x, 0.f);
- mouse_vector = mouse_vector * mouse_rotate;
- // project to z = -1 plane;
- mouse_vector = mouse_vector * (-1.f / mouse_vector.mV[VZ]);
- return mouse_vector;
- }
- BOOL LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y,
- const LLVector3d &plane_point_global,
- const LLVector3 &plane_normal_global)
- {
- LLVector3d mouse_direction_global_d;
- mouse_direction_global_d.setVec(mouseDirectionGlobal(x,y));
- LLVector3d plane_normal_global_d;
- plane_normal_global_d.setVec(plane_normal_global);
- F64 plane_mouse_dot = (plane_normal_global_d * mouse_direction_global_d);
- LLVector3d plane_origin_camera_rel = plane_point_global - gAgent.getCameraPositionGlobal();
- F64 mouse_look_at_scale = (plane_normal_global_d * plane_origin_camera_rel)
- / plane_mouse_dot;
- if (llabs(plane_mouse_dot) < 0.00001)
- {
- // if mouse is parallel to plane, return closest point on line through plane origin
- // that is parallel to camera plane by scaling mouse direction vector
- // by distance to plane origin, modulated by deviation of mouse direction from plane origin
- LLVector3d plane_origin_dir = plane_origin_camera_rel;
- plane_origin_dir.normVec();
-
- mouse_look_at_scale = plane_origin_camera_rel.magVec() / (plane_origin_dir * mouse_direction_global_d);
- }
- point = gAgent.getCameraPositionGlobal() + mouse_look_at_scale * mouse_direction_global_d;
- return mouse_look_at_scale > 0.0;
- }
- // Returns global position
- BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_position_global)
- {
- LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y);
- F32 mouse_dir_scale;
- BOOL hit_land = FALSE;
- LLViewerRegion *regionp;
- F32 land_z;
- const F32 FIRST_PASS_STEP = 1.0f; // meters
- const F32 SECOND_PASS_STEP = 0.1f; // meters
- LLVector3d camera_pos_global;
- camera_pos_global = gAgent.getCameraPositionGlobal();
- LLVector3d probe_point_global;
- LLVector3 probe_point_region;
- // walk forwards to find the point
- for (mouse_dir_scale = FIRST_PASS_STEP; mouse_dir_scale < gAgent.mDrawDistance; mouse_dir_scale += FIRST_PASS_STEP)
- {
- LLVector3d mouse_direction_global_d;
- mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
- probe_point_global = camera_pos_global + mouse_direction_global_d;
- regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
- if (!regionp)
- {
- // ...we're outside the world somehow
- continue;
- }
- S32 i = (S32) (probe_point_region.mV[VX]/regionp->getLand().getMetersPerGrid());
- S32 j = (S32) (probe_point_region.mV[VY]/regionp->getLand().getMetersPerGrid());
- S32 grids_per_edge = (S32) regionp->getLand().mGridsPerEdge;
- if ((i >= grids_per_edge) || (j >= grids_per_edge))
- {
- //llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
- continue;
- }
- land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
- //llinfos << "mousePointOnLand initial z " << land_z << llendl;
- if (probe_point_region.mV[VZ] < land_z)
- {
- // ...just went under land
- // cout << "under land at " << probe_point << " scale " << mouse_vec_scale << endl;
- hit_land = TRUE;
- break;
- }
- }
- if (hit_land)
- {
- // Don't go more than one step beyond where we stopped above.
- // This can't just be "mouse_vec_scale" because floating point error
- // will stop the loop before the last increment.... X - 1.0 + 0.1 + 0.1 + ... + 0.1 != X
- F32 stop_mouse_dir_scale = mouse_dir_scale + FIRST_PASS_STEP;
- // take a step backwards, then walk forwards again to refine position
- for ( mouse_dir_scale -= FIRST_PASS_STEP; mouse_dir_scale <= stop_mouse_dir_scale; mouse_dir_scale += SECOND_PASS_STEP)
- {
- LLVector3d mouse_direction_global_d;
- mouse_direction_global_d.setVec(mouse_direction_global * mouse_dir_scale);
- probe_point_global = camera_pos_global + mouse_direction_global_d;
- regionp = LLWorld::getInstance()->resolveRegionGlobal(probe_point_region, probe_point_global);
- if (!regionp)
- {
- // ...we're outside the world somehow
- continue;
- }
- /*
- i = (S32) (local_probe_point.mV[VX]/regionp->getLand().getMetersPerGrid());
- j = (S32) (local_probe_point.mV[VY]/regionp->getLand().getMetersPerGrid());
- if ((i >= regionp->getLand().mGridsPerEdge) || (j >= regionp->getLand().mGridsPerEdge))
- {
- // llinfos << "LLViewerWindow::mousePointOnLand probe_point is out of region" << llendl;
- continue;
- }
- land_z = regionp->getLand().mSurfaceZ[ i + j * (regionp->getLand().mGridsPerEdge) ];
- */
- land_z = regionp->getLand().resolveHeightRegion(probe_point_region);
- //llinfos << "mousePointOnLand refine z " << land_z << llendl;
- if (probe_point_region.mV[VZ] < land_z)
- {
- // ...just went under land again
- *land_position_global = probe_point_global;
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- // Saves an image to the harddrive as "SnapshotX" where X >= 1.
- BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image)
- {
- if (!image)
- {
- return FALSE;
- }
- LLFilePicker::ESaveFilter pick_type;
- std::string extension("." + image->getExtension());
- if (extension == ".j2c")
- pick_type = LLFilePicker::FFSAVE_J2C;
- else if (extension == ".bmp")
- pick_type = LLFilePicker::FFSAVE_BMP;
- else if (extension == ".jpg")
- pick_type = LLFilePicker::FFSAVE_JPEG;
- else if (extension == ".png")
- pick_type = LLFilePicker::FFSAVE_PNG;
- else if (extension == ".tga")
- pick_type = LLFilePicker::FFSAVE_TGA;
- else
- pick_type = LLFilePicker::FFSAVE_ALL; // ???
-
- // Get a base file location if needed.
- if ( ! isSnapshotLocSet())
- {
- std::string proposed_name( sSnapshotBaseName );
- // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in.
- // pick a directory in which to save
- LLFilePicker& picker = LLFilePicker::instance();
- if (!picker.getSaveFile(pick_type, proposed_name))
- {
- // Clicked cancel
- return FALSE;
- }
- // Copy the directory + file name
- std::string filepath = picker.getFirstFile();
- LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true);
- LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath);
- }
- // Look for an unused file name
- std::string filepath;
- S32 i = 1;
- S32 err = 0;
- do
- {
- filepath = sSnapshotDir;
- filepath += gDirUtilp->getDirDelimiter();
- filepath += sSnapshotBaseName;
- filepath += llformat("_%.3d",i);
- filepath += extension;
- llstat stat_info;
- err = LLFile::stat( filepath, &stat_info );
- i++;
- }
- while( -1 != err ); // search until the file is not found (i.e., stat() gives an error).
- return image->save(filepath);
- }
- void LLViewerWindow::resetSnapshotLoc()
- {
- sSnapshotDir.clear();
- }
- static S32 BORDERHEIGHT = 0;
- static S32 BORDERWIDTH = 0;
- // static
- void LLViewerWindow::movieSize(S32 new_width, S32 new_height)
- {
- LLCoordScreen size;
- gViewerWindow->mWindow->getSize(&size);
- if ( (size.mX != new_width + BORDERWIDTH)
- ||(size.mY != new_height + BORDERHEIGHT))
- {
- // use actual display dimensions, not virtual UI dimensions
- S32 x = gViewerWindow->getWindowWidthRaw();
- S32 y = gViewerWindow->getWindowHeightRaw();
- BORDERWIDTH = size.mX - x;
- BORDERHEIGHT = size.mY- y;
- LLCoordScreen new_size(new_width + BORDERWIDTH,
- new_height + BORDERHEIGHT);
- BOOL disable_sync = gSavedSettings.getBOOL("DisableVerticalSync");
- if (gViewerWindow->mWindow->getFullscreen())
- {
- gViewerWindow->changeDisplaySettings(FALSE,
- new_size,
- disable_sync,
- TRUE);
- }
- else
- {
- gViewerWindow->mWindow->setSize(new_size);
- }
- }
- }
- BOOL LLViewerWindow::saveSnapshot( const std::string& filepath, S32 image_width, S32 image_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
- {
- llinfos << "Saving snapshot to: " << filepath << llendl;
- LLPointer<LLImageRaw> raw = new LLImageRaw;
- BOOL success = rawSnapshot(raw, image_width, image_height, TRUE, FALSE, show_ui, do_rebuild);
- if (success)
- {
- LLPointer<LLImageBMP> bmp_image = new LLImageBMP;
- success = bmp_image->encode(raw, 0.0f);
- if( success )
- {
- success = bmp_image->save(filepath);
- }
- else
- {
- llwarns << "Unable to encode bmp snapshot" << llendl;
- }
- }
- else
- {
- llwarns << "Unable to capture raw snapshot" << llendl;
- }
- return success;
- }
- void LLViewerWindow::playSnapshotAnimAndSound()
- {
- if (gSavedSettings.getBOOL("QuietSnapshotsToDisk"))
- {
- return;
- }
- gAgent.sendAnimationRequest(ANIM_AGENT_SNAPSHOT, ANIM_REQUEST_START);
- send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);
- }
- BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
- {
- return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);
-
- // *TODO below code was broken in deferred pipeline
- /*
- if ((!raw) || preview_width < 10 || preview_height < 10)
- {
- return FALSE;
- }
- if(gResizeScreenTexture) //the window is resizing
- {
- return FALSE ;
- }
- setCursor(UI_CURSOR_WAIT);
- // Hide all the UI widgets first and draw a frame
- BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
- if ( prev_draw_ui != show_ui)
- {
- LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
- BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
- if (hide_hud)
- {
- LLPipeline::sShowHUDAttachments = FALSE;
- }
- S32 render_name = gSavedSettings.getS32("RenderName");
- gSavedSettings.setS32("RenderName", 0);
- LLVOAvatar::updateFreezeCounter(1) ; //pause avatar updating for one frame
-
- S32 w = preview_width ;
- S32 h = preview_height ;
- LLVector2 display_scale = mDisplayScale ;
- mDisplayScale.setVec((F32)w / mWindowRectRaw.getWidth(), (F32)h / mWindowRectRaw.getHeight()) ;
- LLRect window_rect = mWindowRectRaw;
- mWindowRectRaw.set(0, h, w, 0);
-
- gDisplaySwapBuffers = FALSE;
- gDepthDirty = TRUE;
- glClearColor(0.f, 0.f, 0.f, 0.f);
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- setup3DRender();
- LLFontGL::setFontDisplay(FALSE) ;
- LLHUDText::setDisplayText(FALSE) ;
- if (type == SNAPSHOT_TYPE_OBJECT_ID)
- {
- gObjectList.renderPickList(gViewerWindow->getWindowRectScaled(), FALSE, FALSE);
- }
- else
- {
- display(do_rebuild, 1.0f, 0, TRUE);
- render_ui();
- }
- S32 glformat, gltype, glpixel_length ;
- if(SNAPSHOT_TYPE_DEPTH == type)
- {
- glpixel_length = 4 ;
- glformat = GL_DEPTH_COMPONENT ;
- gltype = GL_FLOAT ;
- }
- else
- {
- glpixel_length = 3 ;
- glformat = GL_RGB ;
- gltype = GL_UNSIGNED_BYTE ;
- }
- raw->resize(w, h, glpixel_length);
- glReadPixels(0, 0, w, h, glformat, gltype, raw->getData());
- if(SNAPSHOT_TYPE_DEPTH == type)
- {
- LLViewerCamera* camerap = LLViewerCamera::getInstance();
- F32 depth_conversion_factor_1 = (camerap->getFar() + camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear());
- F32 depth_conversion_factor_2 = (camerap->getFar() - camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear());
- //calculate the depth
- for (S32 y = 0 ; y < h ; y++)
- {
- for(S32 x = 0 ; x < w ; x++)
- {
- S32 i = (w * y + x) << 2 ;
-
- F32 depth_float_i = *(F32*)(raw->getData() + i);
-
- F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float_i * depth_conversion_factor_2));
- U8 depth_byte = F32_to_U8(linear_depth_float, camerap->getNear(), camerap->getFar());
- *(raw->getData() + i + 0) = depth_byte;
- *(raw->getData() + i + 1) = depth_byte;
- *(raw->getData() + i + 2) = depth_byte;
- *(raw->getData() + i + 3) = 255;
- }
- }
- }
- LLFontGL::setFontDisplay(TRUE) ;
- LLHUDText::setDisplayText(TRUE) ;
- mDisplayScale.setVec(display_scale) ;
- mWindowRectRaw = window_rect;
- setup3DRender();
- gDisplaySwapBuffers = FALSE;
- gDepthDirty = TRUE;
- // POST SNAPSHOT
- if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
- if (hide_hud)
- {
- LLPipeline::sShowHUDAttachments = TRUE;
- }
- setCursor(UI_CURSOR_ARROW);
- if (do_rebuild)
- {
- // If we had to do a rebuild, that means that the lists of drawables to be rendered
- // was empty before we started.
- // Need to reset these, otherwise we call state sort on it again when render gets called the next time
- // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
- // objects on them.
- gPipeline.resetDrawOrders();
- }
-
- gSavedSettings.setS32("RenderName", render_name);
-
- return TRUE;*/
- }
- // Saves the image from the screen to the specified filename and path.
- BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height,
- BOOL keep_window_aspect, BOOL is_texture, BOOL show_ui, BOOL do_rebuild, ESnapshotType type, S32 max_size)
- {
- if (!raw)
- {
- return FALSE;
- }
- // PRE SNAPSHOT
- gDisplaySwapBuffers = FALSE;
-
- // if not showing ui, use full window to render world view
- updateWorldViewRect(!show_ui);
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- setCursor(UI_CURSOR_WAIT);
- // Hide all the UI widgets first and draw a frame
- BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
- if ( prev_draw_ui != show_ui)
- {
- LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
- BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
- if (hide_hud)
- {
- LLPipeline::sShowHUDAttachments = FALSE;
- }
- // Copy screen to a buffer
- // crop sides or top and bottom, if taking a snapshot of different aspect ratio
- // from window
- S32 snapshot_width = mWindowRectRaw.getWidth();
- S32 snapshot_height = mWindowRectRaw.getHeight();
- // SNAPSHOT
- S32 window_width = mWindowRectRaw.getWidth();
- S32 window_height = mWindowRectRaw.getHeight();
- LLRect window_rect = mWindowRectRaw;
- BOOL use_fbo = FALSE;
- LLRenderTarget target;
- F32 scale_factor = 1.0f ;
- if(!keep_window_aspect) //image cropping
- {
- F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
- snapshot_width = (S32)(ratio * image_width) ;
- snapshot_height = (S32)(ratio * image_height) ;
- scale_factor = llmax(1.0f, 1.0f / ratio) ;
- }
- else //the scene(window) proportion needs to be maintained.
- {
- if(image_width > window_width || image_height > window_height) //need to enlarge the scene
- {
- if (!LLPipeline::sRenderDeferred && gGLManager.mHasFramebufferObject && !show_ui)
- {
- GLint max_size = 0;
- glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &max_size);
-
- if (image_width <= max_size && image_height <= max_size) //re-project the scene
- {
- use_fbo = TRUE;
-
- snapshot_width = image_width;
- snapshot_height = image_height;
- target.allocate(snapshot_width, snapshot_height, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, TRUE);
- window_width = snapshot_width;
- window_height = snapshot_height;
- scale_factor = 1.f;
- mWindowRectRaw.set(0, snapshot_height, snapshot_width, 0);
- target.bindTarget();
- }
- }
- if(!use_fbo) //no re-projection, so tiling the scene
- {
- F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
- snapshot_width = (S32)(ratio * image_width) ;
- snapshot_height = (S32)(ratio * image_height) ;
- scale_factor = llmax(1.0f, 1.0f / ratio) ;
- }
- }
- //else: keep the current scene scale, re-scale it if necessary after reading out.
- }
-
- S32 buffer_x_offset = llfloor(((window_width - snapshot_width) * scale_factor) / 2.f);
- S32 buffer_y_offset = llfloor(((window_height - snapshot_height) * scale_factor) / 2.f);
- S32 image_buffer_x = llfloor(snapshot_width*scale_factor) ;
- S32 image_buffer_y = llfloor(snapshot_height *scale_factor) ;
- if(image_buffer_x > max_size || image_buffer_y > max_size) //boundary check to avoid memory overflow
- {
- scale_factor *= llmin((F32)max_size / image_buffer_x, (F32)max_size / image_buffer_y) ;
- image_buffer_x = llfloor(snapshot_width*scale_factor) ;
- image_buffer_y = llfloor(snapshot_height *scale_factor) ;
- }
- raw->resize(image_buffer_x, image_buffer_y, 3);
- if(raw->isBufferInvalid())
- {
- return FALSE ;
- }
- BOOL high_res = scale_factor >= 2.f; // Font scaling is slow, only do so if rez is much higher
- if (high_res)
- {
- send_agent_pause();
- //rescale fonts
- initFonts(scale_factor);
- LLHUDText::reshape();
- }
- S32 output_buffer_offset_y = 0;
- F32 depth_conversion_factor_1 = (LLViewerCamera::getInstance()->getFar() + LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
- F32 depth_conversion_factor_2 = (LLViewerCamera::getInstance()->getFar() - LLViewerCamera::getInstance()->getNear()) / (2.f * LLViewerCamera::getInstance()->getFar() * LLViewerCamera::getInstance()->getNear());
- gObjectList.generatePickList(*LLViewerCamera::getInstance());
- for (int subimage_y = 0; subimage_y < scale_factor; ++subimage_y)
- {
- S32 subimage_y_offset = llclamp(buffer_y_offset - (subimage_y * window_height), 0, window_height);;
- // handle fractional columns
- U32 read_height = llmax(0, (window_height - subimage_y_offset) -
- llmax(0, (window_height * (subimage_y + 1)) - (buffer_y_offset + raw->getHeight())));
- S32 output_buffer_offset_x = 0;
- for (int subimage_x = 0; subimage_x < scale_factor; ++subimage_x)
- {
- gDisplaySwapBuffers = FALSE;
- gDepthDirty = TRUE;
- if (type == SNAPSHOT_TYPE_OBJECT_ID)
- {
- glClearColor(0.f, 0.f, 0.f, 0.f);
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- LLViewerCamera::getInstance()->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor)));
- setup3DRender();
- gObjectList.renderPickList(gViewerWindow->getWindowRectScaled(), FALSE, FALSE);
- }
- else
- {
- const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor));
- if (LLPipeline::sRenderDeferred)
- {
- display(do_rebuild, scale_factor, subfield, FALSE);
- }
- else
- {
- display(do_rebuild, scale_factor, subfield, TRUE);
- // Required for showing the GUI in snapshots? See DEV-16350 for details. JC
- render_ui(scale_factor, subfield);
- }
- }
- S32 subimage_x_offset = llclamp(buffer_x_offset - (subimage_x * window_width), 0, window_width);
- // handle fractional rows
- U32 read_width = llmax(0, (window_width - subimage_x_offset) -
- llmax(0, (window_width * (subimage_x + 1)) - (buffer_x_offset + raw->getWidth())));
- for(U32 out_y = 0; out_y < read_height ; out_y++)
- {
- S32 output_buffer_offset = (
- (out_y * (raw->getWidth())) // ...plus iterated y...
- + (window_width * subimage_x) // ...plus subimage start in x...
- + (raw->getWidth() * window_height * subimage_y) // ...plus subimage start in y...
- - output_buffer_offset_x // ...minus buffer padding x...
- - (output_buffer_offset_y * (raw->getWidth())) // ...minus buffer padding y...
- ) * raw->getComponents();
-
- // Ping the wathdog thread every 100 lines to keep us alive (arbitrary number, feel free to change)
- if (out_y % 100 == 0)
- {
- LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot");
- }
-
- if (type == SNAPSHOT_TYPE_OBJECT_ID || type == SNAPSHOT_TYPE_COLOR)
- {
- glReadPixels(
- subimage_x_offset, out_y + subimage_y_offset,
- read_width, 1,
- GL_RGB, GL_UNSIGNED_BYTE,
- raw->getData() + output_buffer_offset
- );
- }
- else // SNAPSHOT_TYPE_DEPTH
- {
- LLPointer<LLImageRaw> depth_line_buffer = new LLImageRaw(read_width, 1, sizeof(GL_FLOAT)); // need to store floating point values
- glReadPixels(
- subimage_x_offset, out_y + subimage_y_offset,
- read_width, 1,
- GL_DEPTH_COMPONENT, GL_FLOAT,
- depth_line_buffer->getData()// current output pixel is beginning of buffer...
- );
- for (S32 i = 0; i < (S32)read_width; i++)
- {
- F32 depth_float = *(F32*)(depth_line_buffer->getData() + (i * sizeof(F32)));
-
- F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float * depth_conversion_factor_2));
- U8 depth_byte = F32_to_U8(linear_depth_float, LLViewerCamera::getInstance()->getNear(), LLViewerCamera::getInstance()->getFar());
- //write converted scanline out to result image
- for(S32 j = 0; j < raw->getComponents(); j++)
- {
- *(raw->getData() + output_buffer_offset + (i * raw->getComponents()) + j) = depth_byte;
- }
- }
- }
- }
- output_buffer_offset_x += subimage_x_offset;
- stop_glerror();
- }
- output_buffer_offset_y += subimage_y_offset;
- }
- if (use_fbo)
- {
- mWindowRectRaw = window_rect;
- target.flush();
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- }
- gDisplaySwapBuffers = FALSE;
- gDepthDirty = TRUE;
- // POST SNAPSHOT
- if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
- if (hide_hud)
- {
- LLPipeline::sShowHUDAttachments = TRUE;
- }
- if (high_res)
- {
- initFonts(1.f);
- LLHUDText::reshape();
- }
- // Pre-pad image to number of pixels such that the line length is a multiple of 4 bytes (for BMP encoding)
- // Note: this formula depends on the number of components being 3. Not obvious, but it's correct.
- image_width += (image_width * 3) % 4;
- BOOL ret = TRUE ;
- // Resize image
- if(llabs(image_width - image_buffer_x) > 4 || llabs(image_height - image_buffer_y) > 4)
- {
- ret = raw->scale( image_width, image_height );
- }
- else if(image_width != image_buffer_x || image_height != image_buffer_y)
- {
- ret = raw->scale( image_width, image_height, FALSE );
- }
-
- setCursor(UI_CURSOR_ARROW);
- if (do_rebuild)
- {
- // If we had to do a rebuild, that means that the lists of drawables to be rendered
- // was empty before we started.
- // Need to reset these, otherwise we call state sort on it again when render gets called the next time
- // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
- // objects on them.
- gPipeline.resetDrawOrders();
- }
- if (high_res)
- {
- send_agent_resume();
- }
- return ret;
- }
- void LLViewerWindow::destroyWindow()
- {
- if (mWindow)
- {
- LLWindowManager::destroyWindow(mWindow);
- }
- mWindow = NULL;
- }
- void LLViewerWindow::drawMouselookInstructions()
- {
- // Draw instructions for mouselook ("Press ESC to return to World View" partially transparent at the bottom of the screen.)
- const std::string instructions = LLTrans::getString("LeaveMouselook");
- const LLFontGL* font = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Large", LLFontGL::BOLD));
-
- //to be on top of Bottom bar when it is opened
- const S32 INSTRUCTIONS_PAD = 50;
- font->renderUTF8(
- instructions, 0,
- getWorldViewRectScaled().getCenterX(),
- getWorldViewRectScaled().mBottom + INSTRUCTIONS_PAD,
- LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ),
- LLFontGL::HCENTER, LLFontGL::TOP,
- LLFontGL::NORMAL,LLFontGL::DROP_SHADOW);
- }
- void* LLViewerWindow::getPlatformWindow() const
- {
- return mWindow->getPlatformWindow();
- }
- void* LLViewerWindow::getMediaWindow() const
- {
- return mWindow->getMediaWindow();
- }
- void LLViewerWindow::focusClient() const
- {
- return mWindow->focusClient();
- }
- LLRootView* LLViewerWindow::getRootView() const
- {
- return mRootView;
- }
- LLRect LLViewerWindow::getWorldViewRectScaled() const
- {
- return mWorldViewRectScaled;
- }
- S32 LLViewerWindow::getWorldViewHeightScaled() const
- {
- return mWorldViewRectScaled.getHeight();
- }
- S32 LLViewerWindow::getWorldViewWidthScaled() const
- {
- return mWorldViewRectScaled.getWidth();
- }
- S32 LLViewerWindow::getWorldViewHeightRaw() const
- {
- return mWorldViewRectRaw.getHeight();
- }
- S32 LLViewerWindow::getWorldViewWidthRaw() const
- {
- return mWorldViewRectRaw.getWidth();
- }
- S32 LLViewerWindow::getWindowHeightScaled() const
- {
- return mWindowRectScaled.getHeight();
- }
- S32 LLViewerWindow::getWindowWidthScaled() const
- {
- return mWindowRectScaled.getWidth();
- }
- S32 LLViewerWindow::getWindowHeightRaw() const
- {
- return mWindowRectRaw.getHeight();
- }
- S32 LLViewerWindow::getWindowWidthRaw() const
- {
- return mWindowRectRaw.getWidth();
- }
- void LLViewerWindow::setup2DRender()
- {
- // setup ortho camera
- gl_state_for_2d(mWindowRectRaw.getWidth(), mWindowRectRaw.getHeight());
- setup2DViewport();
- }
- void LLViewerWindow::setup2DViewport(S32 x_offset, S32 y_offset)
- {
- gGLViewport[0] = mWindowRectRaw.mLeft + x_offset;
- gGLViewport[1] = mWindowRectRaw.mBottom + y_offset;
- gGLViewport[2] = mWindowRectRaw.getWidth();
- gGLViewport[3] = mWindowRectRaw.getHeight();
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- }
- void LLViewerWindow::setup3DRender()
- {
- // setup perspective camera
- LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, mWorldViewRectRaw.mLeft, mWorldViewRectRaw.mBottom, mWorldViewRectRaw.getWidth(), mWorldViewRectRaw.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f);
- setup3DViewport();
- }
- void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset)
- {
- if (LLRenderTarget::getCurrentBoundTarget() != NULL)
- {
- // don't use translation component of mWorldViewRectRaw, as we are already in a properly sized render target
- gGLViewport[0] = x_offset;
- gGLViewport[1] = y_offset;
- }
- else
- {
- gGLViewport[0] = mWorldViewRectRaw.mLeft + x_offset;
- gGLViewport[1] = mWorldViewRectRaw.mBottom + y_offset;
- }
- gGLViewport[2] = mWorldViewRectRaw.getWidth();
- gGLViewport[3] = mWorldViewRectRaw.getHeight();
- glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
- }
- void LLViewerWindow::setShowProgress(const BOOL show)
- {
- if (mProgressView)
- {
- mProgressView->setVisible(show);
- }
- }
- BOOL LLViewerWindow::getShowProgress() const
- {
- return (mProgressView && mProgressView->getVisible());
- }
- void LLViewerWindow::moveProgressViewToFront()
- {
- if( mProgressView && mRootView )
- {
- mRootView->sendChildToFront(mProgressView);
- }
- }
- void LLViewerWindow::setProgressString(const std::string& string)
- {
- if (mProgressView)
- {
- mProgressView->setText(string);
- }
- }
- void LLViewerWindow::setProgressMessage(const std::string& msg)
- {
- if(mProgressView)
- {
- mProgressView->setMessage(msg);
- }
- }
- void LLViewerWindow::setProgressPercent(const F32 percent)
- {
- if (mProgressView)
- {
- mProgressView->setPercent(percent);
- }
- }
- void LLViewerWindow::setProgressCancelButtonVisible( BOOL b, const std::string& label )
- {
- if (mProgressView)
- {
- mProgressView->setCancelButtonVisible( b, label );
- }
- }
- LLProgressView *LLViewerWindow::getProgressView() const
- {
- return mProgressView;
- }
- void LLViewerWindow::dumpState()
- {
- llinfos << "LLViewerWindow Active " << S32(mActive) << llendl;
- llinfos << "mWindow visible " << S32(mWindow->getVisible())
- << " minimized " << S32(mWindow->getMinimized())
- << llendl;
- }
- void LLViewerWindow::stopGL(BOOL save_state)
- {
- //Note: --bao
- //if not necessary, do not change the order of the function calls in this function.
- //if change something, make sure it will not break anything.
- //especially be careful to put anything behind gTextureList.destroyGL(save_state);
- if (!gGLManager.mIsDisabled)
- {
- llinfos << "Shutting down GL..." << llendl;
- // Pause texture decode threads (will get unpaused during main loop)
- LLAppViewer::getTextureCache()->pause();
- LLAppViewer::getImageDecodeThread()->pause();
- LLAppViewer::getTextureFetch()->pause();
-
- gSky.destroyGL();
- stop_glerror();
- LLManipTranslate::destroyGL() ;
- stop_glerror();
- gBumpImageList.destroyGL();
- stop_glerror();
- LLFontGL::destroyAllGL();
- stop_glerror();
- LLVOAvatar::destroyGL();
- stop_glerror();
- LLViewerDynamicTexture::destroyGL();
- stop_glerror();
- if (gPipeline.isInit())
- {
- gPipeline.destroyGL();
- }
-
- gCone.cleanupGL();
- gBox.cleanupGL();
- gSphere.cleanupGL();
- gCylinder.cleanupGL();
-
- if(gPostProcess)
- {
- gPostProcess->invalidate();
- }
- gTextureList.destroyGL(save_state);
- stop_glerror();
-
- gGLManager.mIsDisabled = TRUE;
- stop_glerror();
-
- llinfos << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemoryInBytes << " bytes" << llendl;
- }
- }
- void LLViewerWindow::restoreGL(const std::string& progress_message)
- {
- //Note: --bao
- //if not necessary, do not change the order of the function calls in this function.
- //if change something, make sure it will not break anything.
- //especially, be careful to put something before gTextureList.restoreGL();
- if (gGLManager.mIsDisabled)
- {
- llinfos << "Restoring GL..." << llendl;
- gGLManager.mIsDisabled = FALSE;
-
- initGLDefaults();
- LLGLState::restoreGL();
-
- gTextureList.restoreGL();
-
- // for future support of non-square pixels, and fonts that are properly stretched
- //LLFontGL::destroyDefaultFonts();
- initFonts();
-
- gSky.restoreGL();
- gPipeline.restoreGL();
- LLDrawPoolWater::restoreGL();
- LLManipTranslate::restoreGL();
-
- gBumpImageList.restoreGL();
- LLViewerDynamicTexture::restoreGL();
- LLVOAvatar::restoreGL();
-
- gResizeScreenTexture = TRUE;
- if (gFloaterCustomize && gFloaterCustomize->getVisible())
- {
- LLVisualParamHint::requestHintUpdates();
- }
- if (!progress_message.empty())
- {
- gRestoreGLTimer.reset();
- gRestoreGL = TRUE;
- setShowProgress(TRUE);
- setProgressString(progress_message);
- }
- llinfos << "...Restoring GL done" << llendl;
- if(!LLAppViewer::instance()->restoreErrorTrap())
- {
- llwarns << " Someone took over my signal/exception handler (post restoreGL)!" << llendl;
- }
- }
- }
- void LLViewerWindow::initFonts(F32 zoom_factor)
- {
- LLFontGL::destroyAllGL();
- // Initialize with possibly different zoom factor
- LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"),
- mDisplayScale.mV[VX] * zoom_factor,
- mDisplayScale.mV[VY] * zoom_factor,
- gDirUtilp->getAppRODataDir(),
- LLUI::getXUIPaths());
- // Force font reloads, which can be very slow
- LLFontGL::loadDefaultFonts();
- }
- void LLViewerWindow::toggleFullscreen(BOOL show_progress)
- {
- if (mWindow)
- {
- mWantFullscreen = mWindow->getFullscreen() ? FALSE : TRUE;
- mIsFullscreenChecked = mWindow->getFullscreen() ? FALSE : TRUE;
- mShowFullscreenProgress = show_progress;
- }
- }
- void LLViewerWindow::getTargetWindow(BOOL& fullscreen, S32& width, S32& height) const
- {
- fullscreen = mWantFullscreen;
-
- if (mWindow
- && mWindow->getFullscreen() == mWantFullscreen)
- {
- width = getWindowWidthRaw();
- height = getWindowHeightRaw();
- }
- else if (mWantFullscreen)
- {
- width = gSavedSettings.getS32("FullScreenWidth");
- height = gSavedSettings.getS32("FullScreenHeight");
- }
- else
- {
- width = gSavedSettings.getS32("WindowWidth");
- height = gSavedSettings.getS32("WindowHeight");
- }
- }
- void LLViewerWindow::requestResolutionUpdate()
- {
- mResDirty = true;
- }
- void LLViewerWindow::requestResolutionUpdate(bool fullscreen_checked)
- {
- mResDirty = true;
- mWantFullscreen = fullscreen_checked;
- mIsFullscreenChecked = fullscreen_checked;
- }
- BOOL LLViewerWindow::checkSettings()
- {
- if (mStatesDirty)
- {
- gGL.refreshState();
- LLViewerShaderMgr::instance()->setShaders();
- mStatesDirty = false;
- }
-
- // We want to update the resolution AFTER the states getting refreshed not before.
- if (mResDirty)
- {
- if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio"))
- {
- getWindow()->setNativeAspectRatio(0.f);
- }
- else
- {
- getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio"));
- }
-
- reshape(getWindowWidthRaw(), getWindowHeightRaw());
- // force aspect ratio
- if (mIsFullscreenChecked)
- {
- LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() );
- }
- mResDirty = false;
- }
-
- BOOL is_fullscreen = mWindow->getFullscreen();
- if(mWantFullscreen)
- {
- LLCoordScreen screen_size;
- LLCoordScreen desired_screen_size(gSavedSettings.getS32("FullScreenWidth"),
- gSavedSettings.getS32("FullScreenHeight"));
- getWindow()->getSize(&screen_size);
- if(!is_fullscreen ||
- screen_size.mX != desired_screen_size.mX
- || screen_size.mY != desired_screen_size.mY)
- {
- if (!LLStartUp::canGoFullscreen())
- {
- return FALSE;
- }
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- changeDisplaySettings(TRUE,
- desired_screen_size,
- gSavedSettings.getBOOL("DisableVerticalSync"),
- mShowFullscreenProgress);
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- mStatesDirty = true;
- return TRUE;
- }
- }
- else
- {
- if(is_fullscreen)
- {
- // Changing to windowed mode.
- changeDisplaySettings(FALSE,
- LLCoordScreen(gSavedSettings.getS32("WindowWidth"),
- gSavedSettings.getS32("WindowHeight")),
- TRUE,
- mShowFullscreenProgress);
- mStatesDirty = true;
- return TRUE;
- }
- }
- return FALSE;
- }
- void LLViewerWindow::restartDisplay(BOOL show_progress_bar)
- {
- llinfos << "Restaring GL" << llendl;
- stopGL();
- if (show_progress_bar)
- {
- restoreGL("Changing Resolution...");
- }
- else
- {
- restoreGL();
- }
- }
- BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar)
- {
- BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized");
- mWantFullscreen = fullscreen;
- mShowFullscreenProgress = show_progress_bar;
- gSavedSettings.setBOOL("WindowFullScreen", mWantFullscreen);
- //gResizeScreenTexture = TRUE;
- BOOL old_fullscreen = mWindow->getFullscreen();
- if (!old_fullscreen && fullscreen && !LLStartUp::canGoFullscreen())
- {
- // Not allowed to switch to fullscreen now, so exit early.
- // *NOTE: This case should never be reached, but just-in-case.
- return TRUE;
- }
- U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
- U32 old_fsaa = mWindow->getFSAASamples();
- // going from windowed to windowed
- if (!old_fullscreen && !fullscreen)
- {
- // if not maximized, use the request size
- if (!mWindow->getMaximized())
- {
- mWindow->setSize(size);
- }
- if (fsaa == old_fsaa)
- {
- return TRUE;
- }
- }
- // Close floaters that don't handle settings change
- LLFloaterReg::hideInstance("snapshot");
-
- BOOL result_first_try = FALSE;
- BOOL result_second_try = FALSE;
- LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
- send_agent_pause();
- llinfos << "Stopping GL during changeDisplaySettings" << llendl;
- stopGL();
- mIgnoreActivate = TRUE;
- LLCoordScreen old_size;
- LLCoordScreen old_pos;
- mWindow->getSize(&old_size);
- BOOL got_position = mWindow->getPosition(&old_pos);
- if (!old_fullscreen && fullscreen && got_position)
- {
- // switching from windowed to fullscreen, so save window position
- gSavedSettings.setS32("WindowX", old_pos.mX);
- gSavedSettings.setS32("WindowY", old_pos.mY);
- }
-
- mWindow->setFSAASamples(fsaa);
- result_first_try = mWindow->switchContext(fullscreen, size, disable_vsync);
- if (!result_first_try)
- {
- // try to switch back
- mWindow->setFSAASamples(old_fsaa);
- result_second_try = mWindow->switchContext(old_fullscreen, old_size, disable_vsync);
- if (!result_second_try)
- {
- // we are stuck...try once again with a minimal resolution?
- send_agent_resume();
- mIgnoreActivate = FALSE;
- return FALSE;
- }
- }
- send_agent_resume();
- llinfos << "Restoring GL during resolution change" << llendl;
- if (show_progress_bar)
- {
- restoreGL("Changing Resolution...");
- }
- else
- {
- restoreGL();
- }
- if (!result_first_try)
- {
- LLSD args;
- args["RESX"] = llformat("%d",size.mX);
- args["RESY"] = llformat("%d",size.mY);
- LLNotificationsUtil::add("ResolutionSwitchFail", args);
- size = old_size; // for reshape below
- }
- BOOL success = result_first_try || result_second_try;
- if (success)
- {
- #if LL_WINDOWS
- // Only trigger a reshape after switching to fullscreen; otherwise rely on the windows callback
- // (otherwise size is wrong; this is the entire window size, reshape wants the visible window size)
- if (fullscreen && result_first_try)
- #endif
- {
- reshape(size.mX, size.mY);
- }
- }
- if (!mWindow->getFullscreen() && success)
- {
- // maximize window if was maximized, else reposition
- if (was_maximized)
- {
- mWindow->maximize();
- }
- else
- {
- S32 windowX = gSavedSettings.getS32("WindowX");
- S32 windowY = gSavedSettings.getS32("WindowY");
- mWindow->setPosition(LLCoordScreen ( windowX, windowY ) );
- }
- }
- mIgnoreActivate = FALSE;
- gFocusMgr.setKeyboardFocus(keyboard_focus);
- mWantFullscreen = mWindow->getFullscreen();
- mShowFullscreenProgress = FALSE;
-
- return success;
- }
- F32 LLViewerWindow::getDisplayAspectRatio() const
- {
- if (mWindow->getFullscreen())
- {
- if (gSavedSettings.getBOOL("FullScreenAutoDetectAspectRatio"))
- {
- return mWindow->getNativeAspectRatio();
- }
- else
- {
- return gSavedSettings.getF32("FullScreenAspectRatio");
- }
- }
- else
- {
- return mWindow->getNativeAspectRatio();
- }
- }
- F32 LLViewerWindow::getWorldViewAspectRatio() const
- {
- F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight();
- //F32 window_aspect = (F32)mWindowRectRaw.getWidth() / (F32)mWindowRectRaw.getHeight();
- if (mWindow->getFullscreen())
- {
- return world_aspect * mWindow->getPixelAspectRatio();
- }
- else
- {
- return world_aspect;
- }
- }
- void LLViewerWindow::calcDisplayScale()
- {
- F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor");
- LLVector2 display_scale;
- display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
- F32 height_normalization = gSavedSettings.getBOOL("UIAutoScale") ? ((F32)mWindowRectRaw.getHeight() / display_scale.mV[VY]) / 768.f : 1.f;
- if(mWindow->getFullscreen())
- {
- display_scale *= (ui_scale_factor * height_normalization);
- }
- else
- {
- display_scale *= ui_scale_factor;
- }
- // limit minimum display scale
- if (display_scale.mV[VX] < MIN_DISPLAY_SCALE || display_scale.mV[VY] < MIN_DISPLAY_SCALE)
- {
- display_scale *= MIN_DISPLAY_SCALE / llmin(display_scale.mV[VX], display_scale.mV[VY]);
- }
- if (mWindow->getFullscreen())
- {
- display_scale.mV[0] = llround(display_scale.mV[0], 2.0f/(F32) mWindowRectRaw.getWidth());
- display_scale.mV[1] = llround(display_scale.mV[1], 2.0f/(F32) mWindowRectRaw.getHeight());
- }
-
- if (display_scale != mDisplayScale)
- {
- llinfos << "Setting display scale to " << display_scale << llendl;
- mDisplayScale = display_scale;
- // Init default fonts
- initFonts();
- }
- }
- //static
- LLRect LLViewerWindow::calcScaledRect(const LLRect & rect, const LLVector2& display_scale)
- {
- LLRect res = rect;
- res.mLeft = llround((F32)res.mLeft / display_scale.mV[VX]);
- res.mRight = llround((F32)res.mRight / display_scale.mV[VX]);
- res.mBottom = llround((F32)res.mBottom / display_scale.mV[VY]);
- res.mTop = llround((F32)res.mTop / display_scale.mV[VY]);
- return res;
- }
- S32 LLViewerWindow::getChatConsoleBottomPad()
- {
- S32 offset = 0;
- if(LLBottomTray::instanceExists())
- offset += LLBottomTray::getInstance()->getRect().getHeight();
- return offset;
- }
- LLRect LLViewerWindow::getChatConsoleRect()
- {
- LLRect full_window(0, getWindowHeightScaled(), getWindowWidthScaled(), 0);
- LLRect console_rect = full_window;
- const S32 CONSOLE_PADDING_TOP = 24;
- const S32 CONSOLE_PADDING_LEFT = 24;
- const S32 CONSOLE_PADDING_RIGHT = 10;
- console_rect.mTop -= CONSOLE_PADDING_TOP;
- console_rect.mBottom += getChatConsoleBottomPad();
- console_rect.mLeft += CONSOLE_PADDING_LEFT;
- static const BOOL CHAT_FULL_WIDTH = gSavedSettings.getBOOL("ChatFullWidth");
- if (CHAT_FULL_WIDTH)
- {
- console_rect.mRight -= CONSOLE_PADDING_RIGHT;
- }
- else
- {
- // Make console rect somewhat narrow so having inventory open is
- // less of a problem.
- console_rect.mRight = console_rect.mLeft + 2 * getWindowWidthScaled() / 3;
- }
- return console_rect;
- }
- //----------------------------------------------------------------------------
- //static
- bool LLViewerWindow::onAlert(const LLSD& notify)
- {
- LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
- if (gNoRender)
- {
- llinfos << "Alert: " << notification->getName() << llendl;
- notification->respond(LLSD::emptyMap());
- LLNotifications::instance().cancel(notification);
- return false;
- }
- // If we're in mouselook, the mouse is hidden and so the user can't click
- // the dialog buttons. In that case, change to First Person instead.
- if( gAgent.cameraMouselook() )
- {
- gAgent.changeCameraToDefault();
- }
- return false;
- }
- ////////////////////////////////////////////////////////////////////////////
- //
- // LLPickInfo
- //
- LLPickInfo::LLPickInfo()
- : mKeyMask(MASK_NONE),
- mPickCallback(NULL),
- mPickType(PICK_INVALID),
- mWantSurfaceInfo(FALSE),
- mObjectFace(-1),
- mUVCoords(-1.f, -1.f),
- mSTCoords(-1.f, -1.f),
- mXYCoords(-1, -1),
- mIntersection(),
- mNormal(),
- mBinormal(),
- mHUDIcon(NULL),
- mPickTransparent(FALSE)
- {
- }
- LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos,
- MASK keyboard_mask,
- BOOL pick_transparent,
- BOOL pick_uv_coords,
- void (*pick_callback)(const LLPickInfo& pick_info))
- : mMousePt(mouse_pos),
- mKeyMask(keyboard_mask),
- mPickCallback(pick_callback),
- mPickType(PICK_INVALID),
- mWantSurfaceInfo(pick_uv_coords),
- mObjectFace(-1),
- mUVCoords(-1.f, -1.f),
- mSTCoords(-1.f, -1.f),
- mXYCoords(-1, -1),
- mNormal(),
- mBinormal(),
- mHUDIcon(NULL),
- mPickTransparent(pick_transparent)
- {
- }
- void LLPickInfo::fetchResults()
- {
- S32 face_hit = -1;
- LLVector3 intersection, normal, binormal;
- LLVector2 uv;
- LLHUDIcon* hit_icon = gViewerWindow->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f, &intersection);
-
- F32 icon_dist = 0.f;
- if (hit_icon)
- {
- icon_dist = (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec();
- }
- LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f,
- NULL, -1, mPickTransparent, &face_hit,
- &intersection, &uv, &normal, &binormal);
-
- mPickPt = mMousePt;
- U32 te_offset = face_hit > -1 ? face_hit : 0;
- //unproject relative clicked coordinate from window coordinate using GL
-
- LLViewerObject* objectp = hit_object;
- if (hit_icon &&
- (!objectp ||
- icon_dist < (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec()))
- {
- // was this name referring to a hud icon?
- mHUDIcon = hit_icon;
- mPickType = PICK_ICON;
- mPosGlobal = mHUDIcon->getPositionGlobal();
- }
- else if (objectp)
- {
- if( objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH )
- {
- // Hit land
- mPickType = PICK_LAND;
- mObjectID.setNull(); // land has no id
- // put global position into land_pos
- LLVector3d land_pos;
- if (!gViewerWindow->mousePointOnLandGlobal(mPickPt.mX, mPickPt.mY, &land_pos))
- {
- // The selected point is beyond the draw distance or is otherwise
- // not selectable. Return before calling mPickCallback().
- return;
- }
- // Fudge the land focus a little bit above ground.
- mPosGlobal = land_pos + LLVector3d::z_axis * 0.1f;
- }
- else
- {
- if(isFlora(objectp))
- {
- mPickType = PICK_FLORA;
- }
- else
- {
- mPickType = PICK_OBJECT;
- }
- mObjectOffset = gAgent.calcFocusOffset(objectp, intersection, mPickPt.mX, mPickPt.mY);
- mObjectID = objectp->mID;
- mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset;
- mPosGlobal = gAgent.getPosGlobalFromAgent(intersection);
-
- if (mWantSurfaceInfo)
- {
- getSurfaceInfo();
- }
- }
- }
-
- if (mPickCallback)
- {
- mPickCallback(*this);
- }
- }
- LLPointer<LLViewerObject> LLPickInfo::getObject() const
- {
- return gObjectList.findObject( mObjectID );
- }
- void LLPickInfo::updateXYCoords()
- {
- if (mObjectFace > -1)
- {
- const LLTextureEntry* tep = getObject()->getTE(mObjectFace);
- LLPointer<LLViewerTexture> imagep = LLViewerTextureManager::getFetchedTexture(tep->getID());
- if(mUVCoords.mV[VX] >= 0.f && mUVCoords.mV[VY] >= 0.f && imagep.notNull())
- {
- mXYCoords.mX = llround(mUVCoords.mV[VX] * (F32)imagep->getWidth());
- mXYCoords.mY = llround((1.f - mUVCoords.mV[VY]) * (F32)imagep->getHeight());
- }
- }
- }
- void LLPickInfo::getSurfaceInfo()
- {
- // set values to uninitialized - this is what we return if no intersection is found
- mObjectFace = -1;
- mUVCoords = LLVector2(-1, -1);
- mSTCoords = LLVector2(-1, -1);
- mXYCoords = LLCoordScreen(-1, -1);
- mIntersection = LLVector3(0,0,0);
- mNormal = LLVector3(0,0,0);
- mBinormal = LLVector3(0,0,0);
-
- LLViewerObject* objectp = getObject();
- if (objectp)
- {
- if (gViewerWindow->cursorIntersect(llround((F32)mMousePt.mX), llround((F32)mMousePt.mY), 1024.f,
- objectp, -1, mPickTransparent,
- &mObjectFace,
- &mIntersection,
- &mSTCoords,
- &mNormal,
- &mBinormal))
- {
- // if we succeeded with the intersect above, compute the texture coordinates:
- if (objectp->mDrawable.notNull() && mObjectFace > -1)
- {
- LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
- mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal);
- }
- // and XY coords:
- updateXYCoords();
-
- }
- }
- }
- /* code to get UV via a special UV render - removed in lieu of raycast method
- LLVector2 LLPickInfo::pickUV()
- {
- LLVector2 result(-1.f, -1.f);
- LLViewerObject* objectp = getObject();
- if (!objectp)
- {
- return result;
- }
- if (mObjectFace > -1 &&
- objectp->mDrawable.notNull() && objectp->getPCode() == LL_PCODE_VOLUME &&
- mObjectFace < objectp->mDrawable->getNumFaces())
- {
- S32 scaled_x = llround((F32)mPickPt.mX * gViewerWindow->getDisplayScale().mV[VX]);
- S32 scaled_y = llround((F32)mPickPt.mY * gViewerWindow->getDisplayScale().mV[VY]);
- const S32 UV_PICK_WIDTH = 5;
- const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2;
- U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4];
- LLFace* facep = objectp->mDrawable->getFace(mObjectFace);
- if (facep)
- {
- LLGLState scissor_state(GL_SCISSOR_TEST);
- scissor_state.enable();
- LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE);
- //glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
- glScissor(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH);
- glClear(GL_DEPTH_BUFFER_BIT);
- facep->renderSelectedUV();
- 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);
- U8* center_pixel = &uv_pick_buffer[4 * ((UV_PICK_WIDTH * UV_PICK_HALF_WIDTH) + UV_PICK_HALF_WIDTH + 1)];
- result.mV[VX] = (F32)((center_pixel[VGREEN] & 0xf) + (16.f * center_pixel[VRED])) / 4095.f;
- result.mV[VY] = (F32)((center_pixel[VGREEN] >> 4) + (16.f * center_pixel[VBLUE])) / 4095.f;
- }
- }
- return result;
- } */
- //static
- bool LLPickInfo::isFlora(LLViewerObject* object)
- {
- if (!object) return false;
- LLPCode pcode = object->getPCode();
- if( (LL_PCODE_LEGACY_GRASS == pcode)
- || (LL_PCODE_LEGACY_TREE == pcode)
- || (LL_PCODE_TREE_NEW == pcode))
- {
- return true;
- }
- return false;
- }