diff options
author | Brad Linden <brad@lindenlab.com> | 2024-05-23 11:31:19 -0700 |
---|---|---|
committer | Brad Linden <brad@lindenlab.com> | 2024-05-23 11:31:19 -0700 |
commit | a1f49564d670a2c41bfa25c833bba2564b9b7f48 (patch) | |
tree | 1d205e51bc37621916a17d459ad83782fe41f975 /indra/newview/llviewerwindow.cpp | |
parent | 6af5db09faf5ea33a2d4c47b64e76f42edae178a (diff) | |
parent | 6377610f6587989c126b00f490dfc8d527a1c2ce (diff) |
Merge remote-tracking branch 'origin/DRTVWR-600-maint-A' into brad/merge-maint-a-to-dev
Diffstat (limited to 'indra/newview/llviewerwindow.cpp')
-rw-r--r-- | indra/newview/llviewerwindow.cpp | 8809 |
1 files changed, 4411 insertions, 4398 deletions
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 275164b698..3218b94aca 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1,25 +1,25 @@ -/** +/** * @file llviewerwindow.cpp * @brief Implementation of the LLViewerWindow class. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -62,7 +62,7 @@ // // linden library includes -#include "llaudioengine.h" // mute on minimize +#include "llaudioengine.h" // mute on minimize #include "llchatentry.h" #include "indra_constants.h" #include "llassetstorage.h" @@ -166,7 +166,7 @@ #include "lltoolselectland.h" #include "lltrans.h" #include "lluictrlfactory.h" -#include "llurldispatcher.h" // SLURL from other app instance +#include "llurldispatcher.h" // SLURL from other app instance #include "llversioninfo.h" #include "llvieweraudio.h" #include "llviewercamera.h" @@ -231,31 +231,31 @@ extern bool gResizeScreenTexture; extern bool gCubeSnapshot; extern bool gSnapshotNoPost; -LLViewerWindow *gViewerWindow = NULL; +LLViewerWindow *gViewerWindow = NULL; -LLFrameTimer gAwayTimer; -LLFrameTimer gAwayTriggerTimer; +LLFrameTimer gAwayTimer; +LLFrameTimer gAwayTriggerTimer; -bool gShowOverlayTitle = false; +bool gShowOverlayTitle = false; LLViewerObject* gDebugRaycastObject = NULL; LLVOPartGroup* gDebugRaycastParticle = NULL; LLVector4a gDebugRaycastIntersection; -LLVector4a gDebugRaycastParticleIntersection; +LLVector4a gDebugRaycastParticleIntersection; LLVector2 gDebugRaycastTexCoord; LLVector4a gDebugRaycastNormal; LLVector4a gDebugRaycastTangent; -S32 gDebugRaycastFaceHit; +S32 gDebugRaycastFaceHit; S32 gDebugRaycastGLTFNodeHit; S32 gDebugRaycastGLTFPrimitiveHit; -LLVector4a gDebugRaycastStart; -LLVector4a gDebugRaycastEnd; +LLVector4a gDebugRaycastStart; +LLVector4a gDebugRaycastEnd; // HUD display lines in lower right -bool gDisplayWindInfo = false; -bool gDisplayCameraPos = false; -bool gDisplayFOV = false; -bool gDisplayBadge = false; +bool gDisplayWindInfo = false; +bool gDisplayCameraPos = false; +bool gDisplayFOV = false; +bool gDisplayBadge = false; static const U8 NO_FACE = 255; bool gQuietSnapshot = false; @@ -269,8 +269,8 @@ static const F32 MIN_DISPLAY_SCALE = 0.75f; static const char KEY_MOUSELOOK = 'M'; -static LLCachedControl<std::string> sSnapshotBaseName(LLCachedControl<std::string>(gSavedPerAccountSettings, "SnapshotBaseName", "Snapshot")); -static LLCachedControl<std::string> sSnapshotDir(LLCachedControl<std::string>(gSavedPerAccountSettings, "SnapshotBaseDir", "")); +static LLCachedControl<std::string> sSnapshotBaseName(LLCachedControl<std::string>(gSavedPerAccountSettings, "SnapshotBaseName", "Snapshot")); +static LLCachedControl<std::string> sSnapshotDir(LLCachedControl<std::string>(gSavedPerAccountSettings, "SnapshotBaseDir", "")); LLTrace::SampleStatHandle<> LLViewerWindow::sMouseVelocityStat("Mouse Velocity"); @@ -278,40 +278,40 @@ LLTrace::SampleStatHandle<> LLViewerWindow::sMouseVelocityStat("Mouse Velocity") class RecordToChatConsoleRecorder : public LLError::Recorder { public: - virtual void recordMessage(LLError::ELevel level, - const std::string& message) - { - //FIXME: this is NOT thread safe, and will do bad things when a warning is issued from a non-UI thread - - // only log warnings to chat console - //if (level == LLError::LEVEL_WARN) - //{ - //LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance<LLFloaterChat>("chat"); - //if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat")) - //{ - // LLChat chat; - // chat.mText = message; - // chat.mSourceType = CHAT_SOURCE_SYSTEM; - - // chat_floater->addChat(chat, false, false); - //} - //} - } + virtual void recordMessage(LLError::ELevel level, + const std::string& message) + { + //FIXME: this is NOT thread safe, and will do bad things when a warning is issued from a non-UI thread + + // only log warnings to chat console + //if (level == LLError::LEVEL_WARN) + //{ + //LLFloaterChat* chat_floater = LLFloaterReg::findTypedInstance<LLFloaterChat>("chat"); + //if (chat_floater && gSavedSettings.getBOOL("WarningsAsChat")) + //{ + // LLChat chat; + // chat.mText = message; + // chat.mSourceType = CHAT_SOURCE_SYSTEM; + + // chat_floater->addChat(chat, false, false); + //} + //} + } }; class RecordToChatConsole : public LLSingleton<RecordToChatConsole> { - LLSINGLETON(RecordToChatConsole); + LLSINGLETON(RecordToChatConsole); public: - void startRecorder() { LLError::addRecorder(mRecorder); } - void stopRecorder() { LLError::removeRecorder(mRecorder); } + void startRecorder() { LLError::addRecorder(mRecorder); } + void stopRecorder() { LLError::removeRecorder(mRecorder); } private: - LLError::RecorderPtr mRecorder; + LLError::RecorderPtr mRecorder; }; RecordToChatConsole::RecordToChatConsole(): - mRecorder(new RecordToChatConsoleRecorder()) + mRecorder(new RecordToChatConsoleRecorder()) { mRecorder->showTags(false); mRecorder->showLocation(false); @@ -421,214 +421,214 @@ static LLTrace::BlockTimerStatHandle FTM_DISPLAY_DEBUG_TEXT("Display Debug Text" class LLDebugText { private: - struct Line - { - Line(const std::string& in_text, S32 in_x, S32 in_y) : text(in_text), x(in_x), y(in_y) {} - std::string text; - S32 x,y; - }; - - LLViewerWindow *mWindow; - - typedef std::vector<Line> line_list_t; - line_list_t mLineList; - LLColor4 mTextColor; - - LLColor4 mBackColor; - LLRect mBackRectCamera1; - LLRect mBackRectCamera2; - - void addText(S32 x, S32 y, const std::string &text) - { - mLineList.push_back(Line(text, x, y)); - } - - void clearText() { mLineList.clear(); } - + struct Line + { + Line(const std::string& in_text, S32 in_x, S32 in_y) : text(in_text), x(in_x), y(in_y) {} + std::string text; + S32 x,y; + }; + + LLViewerWindow *mWindow; + + typedef std::vector<Line> line_list_t; + line_list_t mLineList; + LLColor4 mTextColor; + + LLColor4 mBackColor; + LLRect mBackRectCamera1; + LLRect mBackRectCamera2; + + void addText(S32 x, S32 y, const std::string &text) + { + mLineList.push_back(Line(text, x, y)); + } + + void clearText() { mLineList.clear(); } + public: - LLDebugText(LLViewerWindow* window) : mWindow(window) {} - - void update() - { - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - clearText(); - return; - } - - static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ; - - std::string wind_vel_text; - std::string wind_vector_text; - std::string rwind_vel_text; - std::string rwind_vector_text; - std::string audio_text; - - static const std::string beacon_particle = LLTrans::getString("BeaconParticle"); - static const std::string beacon_physical = LLTrans::getString("BeaconPhysical"); - static const std::string beacon_scripted = LLTrans::getString("BeaconScripted"); - static const std::string beacon_scripted_touch = LLTrans::getString("BeaconScriptedTouch"); - static const std::string beacon_sound = LLTrans::getString("BeaconSound"); - static const std::string beacon_media = LLTrans::getString("BeaconMedia"); - static const std::string beacon_sun = LLTrans::getString("BeaconSun"); - static const std::string beacon_moon = LLTrans::getString("BeaconMoon"); - static const std::string particle_hiding = LLTrans::getString("ParticleHiding"); - - // Draw the statistics in a light gray - // and in a thin font - mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f ); - - // Draw stuff growing up from right lower corner of screen - S32 x_right = mWindow->getWorldViewWidthScaled(); - S32 xpos = x_right - 400; - xpos = llmax(xpos, 0); - S32 ypos = 64; - const S32 y_inc = 20; - - // Camera matrix text is hard to see again a white background - // Add a dark background underneath the matrices for readability (contrast) - mBackRectCamera1.mLeft = xpos; - mBackRectCamera1.mRight = x_right; - mBackRectCamera1.mTop = -1; - mBackRectCamera1.mBottom = -1; - mBackRectCamera2 = mBackRectCamera1; - - mBackColor = LLUIColorTable::instance().getColor( "MenuDefaultBgColor" ); - - clearText(); - - if (gSavedSettings.getBOOL("DebugShowTime")) - { - F32 time = gFrameTimeSeconds; - S32 hours = (S32)(time / (60*60)); - S32 mins = (S32)((time - hours*(60*60)) / 60); - S32 secs = (S32)((time - hours*(60*60) - mins*60)); - addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; - } - - if (gSavedSettings.getBOOL("DebugShowMemory")) - { - addText(xpos, ypos, - STRINGIZE("Memory: " << (LLMemory::getCurrentRSS() / 1024) << " (KB)")); - ypos += y_inc; - } - - if (gDisplayCameraPos) - { - std::string camera_view_text; - std::string camera_center_text; - std::string agent_view_text; - std::string agent_left_text; - std::string agent_center_text; - std::string agent_root_center_text; - - LLVector3d tvector; // Temporary vector to hold data for printing. - - // Update camera center, camera view, wind info every other frame - tvector = gAgent.getPositionGlobal(); - agent_center_text = llformat("AgentCenter %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - - if (isAgentAvatarValid()) - { - tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition()); - agent_root_center_text = llformat("AgentRootCenter %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - } - else - { - agent_root_center_text = "---"; - } - - - tvector = LLVector4(gAgent.getFrameAgent().getAtAxis()); - agent_view_text = llformat("AgentAtAxis %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - - tvector = LLVector4(gAgent.getFrameAgent().getLeftAxis()); - agent_left_text = llformat("AgentLeftAxis %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - - tvector = gAgentCamera.getCameraPositionGlobal(); - camera_center_text = llformat("CameraCenter %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - - tvector = LLVector4(LLViewerCamera::getInstance()->getAtAxis()); - camera_view_text = llformat("CameraAtAxis %f %f %f", - (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); - - addText(xpos, ypos, agent_center_text); ypos += y_inc; - addText(xpos, ypos, agent_root_center_text); ypos += y_inc; - addText(xpos, ypos, agent_view_text); ypos += y_inc; - addText(xpos, ypos, agent_left_text); ypos += y_inc; - addText(xpos, ypos, camera_center_text); ypos += y_inc; - addText(xpos, ypos, camera_view_text); ypos += y_inc; - } - - if (gDisplayWindInfo) - { - wind_vel_text = llformat("Wind velocity %.2f m/s", gWindVec.magVec()); - wind_vector_text = llformat("Wind vector %.2f %.2f %.2f", gWindVec.mV[0], gWindVec.mV[1], gWindVec.mV[2]); - rwind_vel_text = llformat("RWind vel %.2f m/s", gRelativeWindVec.magVec()); - rwind_vector_text = llformat("RWind vec %.2f %.2f %.2f", gRelativeWindVec.mV[0], gRelativeWindVec.mV[1], gRelativeWindVec.mV[2]); - - addText(xpos, ypos, wind_vel_text); ypos += y_inc; - addText(xpos, ypos, wind_vector_text); ypos += y_inc; - addText(xpos, ypos, rwind_vel_text); ypos += y_inc; - addText(xpos, ypos, rwind_vector_text); ypos += y_inc; - } - if (gDisplayWindInfo) - { - audio_text = llformat("Audio for wind: %d", gAudiop ? gAudiop->isWindEnabled() : -1); - addText(xpos, ypos, audio_text); ypos += y_inc; - } - if (gDisplayFOV) - { - addText(xpos, ypos, llformat("FOV: %2.1f deg", RAD_TO_DEG * LLViewerCamera::getInstance()->getView())); - ypos += y_inc; - } - if (gDisplayBadge) - { - addText(xpos, ypos+(y_inc/2), llformat("Hippos!", RAD_TO_DEG * LLViewerCamera::getInstance()->getView())); - ypos += y_inc * 2; - } - - /*if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - addText(xpos + 200, ypos, llformat("Flycam")); - ypos += y_inc; - }*/ - - if (gSavedSettings.getBOOL("DebugShowRenderInfo")) - { - LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording(); - - //show streaming cost/triangle count of known prims in current region OR selection - { - F32 cost = 0.f; - S32 count = 0; - S32 vcount = 0; - S32 object_count = 0; - S32 total_bytes = 0; - S32 visible_bytes = 0; - - const char* label = "Region"; - if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 0) - { //region - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - for (U32 i = 0; i < gObjectList.getNumObjects(); ++i) - { - LLViewerObject* object = gObjectList.getObject(i); - if (object && - object->getRegion() == region && - object->getVolume()) - { - object_count++; - S32 bytes = 0; - S32 visible = 0; - cost += object->getStreamingCost(); + LLDebugText(LLViewerWindow* window) : mWindow(window) {} + + void update() + { + if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + clearText(); + return; + } + + static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic", false) ; + + std::string wind_vel_text; + std::string wind_vector_text; + std::string rwind_vel_text; + std::string rwind_vector_text; + std::string audio_text; + + static const std::string beacon_particle = LLTrans::getString("BeaconParticle"); + static const std::string beacon_physical = LLTrans::getString("BeaconPhysical"); + static const std::string beacon_scripted = LLTrans::getString("BeaconScripted"); + static const std::string beacon_scripted_touch = LLTrans::getString("BeaconScriptedTouch"); + static const std::string beacon_sound = LLTrans::getString("BeaconSound"); + static const std::string beacon_media = LLTrans::getString("BeaconMedia"); + static const std::string beacon_sun = LLTrans::getString("BeaconSun"); + static const std::string beacon_moon = LLTrans::getString("BeaconMoon"); + static const std::string particle_hiding = LLTrans::getString("ParticleHiding"); + + // Draw the statistics in a light gray + // and in a thin font + mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f ); + + // Draw stuff growing up from right lower corner of screen + S32 x_right = mWindow->getWorldViewWidthScaled(); + S32 xpos = x_right - 400; + xpos = llmax(xpos, 0); + S32 ypos = 64; + const S32 y_inc = 20; + + // Camera matrix text is hard to see again a white background + // Add a dark background underneath the matrices for readability (contrast) + mBackRectCamera1.mLeft = xpos; + mBackRectCamera1.mRight = x_right; + mBackRectCamera1.mTop = -1; + mBackRectCamera1.mBottom = -1; + mBackRectCamera2 = mBackRectCamera1; + + mBackColor = LLUIColorTable::instance().getColor( "MenuDefaultBgColor" ); + + clearText(); + + if (gSavedSettings.getBOOL("DebugShowTime")) + { + F32 time = gFrameTimeSeconds; + S32 hours = (S32)(time / (60*60)); + S32 mins = (S32)((time - hours*(60*60)) / 60); + S32 secs = (S32)((time - hours*(60*60) - mins*60)); + addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; + } + + if (gSavedSettings.getBOOL("DebugShowMemory")) + { + addText(xpos, ypos, + STRINGIZE("Memory: " << (LLMemory::getCurrentRSS() / 1024) << " (KB)")); + ypos += y_inc; + } + + if (gDisplayCameraPos) + { + std::string camera_view_text; + std::string camera_center_text; + std::string agent_view_text; + std::string agent_left_text; + std::string agent_center_text; + std::string agent_root_center_text; + + LLVector3d tvector; // Temporary vector to hold data for printing. + + // Update camera center, camera view, wind info every other frame + tvector = gAgent.getPositionGlobal(); + agent_center_text = llformat("AgentCenter %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + + if (isAgentAvatarValid()) + { + tvector = gAgent.getPosGlobalFromAgent(gAgentAvatarp->mRoot->getWorldPosition()); + agent_root_center_text = llformat("AgentRootCenter %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + } + else + { + agent_root_center_text = "---"; + } + + + tvector = LLVector4(gAgent.getFrameAgent().getAtAxis()); + agent_view_text = llformat("AgentAtAxis %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + + tvector = LLVector4(gAgent.getFrameAgent().getLeftAxis()); + agent_left_text = llformat("AgentLeftAxis %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + + tvector = gAgentCamera.getCameraPositionGlobal(); + camera_center_text = llformat("CameraCenter %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + + tvector = LLVector4(LLViewerCamera::getInstance()->getAtAxis()); + camera_view_text = llformat("CameraAtAxis %f %f %f", + (F32)(tvector.mdV[VX]), (F32)(tvector.mdV[VY]), (F32)(tvector.mdV[VZ])); + + addText(xpos, ypos, agent_center_text); ypos += y_inc; + addText(xpos, ypos, agent_root_center_text); ypos += y_inc; + addText(xpos, ypos, agent_view_text); ypos += y_inc; + addText(xpos, ypos, agent_left_text); ypos += y_inc; + addText(xpos, ypos, camera_center_text); ypos += y_inc; + addText(xpos, ypos, camera_view_text); ypos += y_inc; + } + + if (gDisplayWindInfo) + { + wind_vel_text = llformat("Wind velocity %.2f m/s", gWindVec.magVec()); + wind_vector_text = llformat("Wind vector %.2f %.2f %.2f", gWindVec.mV[0], gWindVec.mV[1], gWindVec.mV[2]); + rwind_vel_text = llformat("RWind vel %.2f m/s", gRelativeWindVec.magVec()); + rwind_vector_text = llformat("RWind vec %.2f %.2f %.2f", gRelativeWindVec.mV[0], gRelativeWindVec.mV[1], gRelativeWindVec.mV[2]); + + addText(xpos, ypos, wind_vel_text); ypos += y_inc; + addText(xpos, ypos, wind_vector_text); ypos += y_inc; + addText(xpos, ypos, rwind_vel_text); ypos += y_inc; + addText(xpos, ypos, rwind_vector_text); ypos += y_inc; + } + if (gDisplayWindInfo) + { + audio_text = llformat("Audio for wind: %d", gAudiop ? gAudiop->isWindEnabled() : -1); + addText(xpos, ypos, audio_text); ypos += y_inc; + } + if (gDisplayFOV) + { + addText(xpos, ypos, llformat("FOV: %2.1f deg", RAD_TO_DEG * LLViewerCamera::getInstance()->getView())); + ypos += y_inc; + } + if (gDisplayBadge) + { + addText(xpos, ypos+(y_inc/2), llformat("Hippos!", RAD_TO_DEG * LLViewerCamera::getInstance()->getView())); + ypos += y_inc * 2; + } + + /*if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + addText(xpos + 200, ypos, llformat("Flycam")); + ypos += y_inc; + }*/ + + if (gSavedSettings.getBOOL("DebugShowRenderInfo")) + { + LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording(); + + //show streaming cost/triangle count of known prims in current region OR selection + { + F32 cost = 0.f; + S32 count = 0; + S32 vcount = 0; + S32 object_count = 0; + S32 total_bytes = 0; + S32 visible_bytes = 0; + + const char* label = "Region"; + if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 0) + { //region + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + for (U32 i = 0; i < gObjectList.getNumObjects(); ++i) + { + LLViewerObject* object = gObjectList.getObject(i); + if (object && + object->getRegion() == region && + object->getVolume()) + { + object_count++; + S32 bytes = 0; + S32 visible = 0; + cost += object->getStreamingCost(); LLMeshCostData costs; if (object->getCostData(costs)) { @@ -636,96 +636,96 @@ public: visible = costs.getSizeByLOD(object->getLOD()); } - S32 vt = 0; - count += object->getTriangleCount(&vt); - vcount += vt; - total_bytes += bytes; - visible_bytes += visible; - } - } - } - } - else - { - label = "Selection"; - cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectStreamingCost(&total_bytes, &visible_bytes); - count = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectTriangleCount(&vcount); - object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - } - - addText(xpos,ypos, llformat("%s streaming cost: %.1f", label, cost)); - ypos += y_inc; - - addText(xpos, ypos, llformat(" %.3f KTris, %.3f KVerts, %.1f/%.1f KB, %d objects", - count/1000.f, vcount/1000.f, visible_bytes/1024.f, total_bytes/1024.f, object_count)); - ypos += y_inc; - - } - - addText(xpos, ypos, llformat("%d Texture Binds", LLImageGL::sBindCount)); - ypos += y_inc; - - addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount)); - ypos += y_inc; - - addText(xpos, ypos, llformat("%d Render Calls", (U32)last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize))); + S32 vt = 0; + count += object->getTriangleCount(&vt); + vcount += vt; + total_bytes += bytes; + visible_bytes += visible; + } + } + } + } + else + { + label = "Selection"; + cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectStreamingCost(&total_bytes, &visible_bytes); + count = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectTriangleCount(&vcount); + object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + } + + addText(xpos,ypos, llformat("%s streaming cost: %.1f", label, cost)); + ypos += y_inc; + + addText(xpos, ypos, llformat(" %.3f KTris, %.3f KVerts, %.1f/%.1f KB, %d objects", + count/1000.f, vcount/1000.f, visible_bytes/1024.f, total_bytes/1024.f, object_count)); + ypos += y_inc; + + } + + addText(xpos, ypos, llformat("%d Texture Binds", LLImageGL::sBindCount)); ypos += y_inc; - addText(xpos, ypos, llformat("%d/%d Objects Active", gObjectList.getNumActiveObjects(), gObjectList.getNumObjects())); - ypos += y_inc; + addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount)); + ypos += y_inc; + + addText(xpos, ypos, llformat("%d Render Calls", (U32)last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize))); + ypos += y_inc; - addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount)); - ypos += y_inc; + addText(xpos, ypos, llformat("%d/%d Objects Active", gObjectList.getNumActiveObjects(), gObjectList.getNumObjects())); + ypos += y_inc; + + addText(xpos, ypos, llformat("%d Matrix Ops", gPipeline.mMatrixOpCount)); + ypos += y_inc; - addText(xpos, ypos, llformat("%d Texture Matrix Ops", gPipeline.mTextureMatrixOps)); - ypos += y_inc; + addText(xpos, ypos, llformat("%d Texture Matrix Ops", gPipeline.mTextureMatrixOps)); + ypos += y_inc; - gPipeline.mTextureMatrixOps = 0; - gPipeline.mMatrixOpCount = 0; + gPipeline.mTextureMatrixOps = 0; + gPipeline.mMatrixOpCount = 0; - if (last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize) > 0) - { + if (last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize) > 0) + { addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", (U32)last_frame_recording.getMin(LLPipeline::sStatBatchSize), (U32)last_frame_recording.getMax(LLPipeline::sStatBatchSize), (U32)last_frame_recording.getMean(LLPipeline::sStatBatchSize))); - } + } ypos += y_inc; - addText(xpos, ypos, llformat("UI Verts/Calls: %d/%d", LLRender::sUIVerts, LLRender::sUICalls)); - LLRender::sUICalls = LLRender::sUIVerts = 0; - ypos += y_inc; + addText(xpos, ypos, llformat("UI Verts/Calls: %d/%d", LLRender::sUIVerts, LLRender::sUICalls)); + LLRender::sUICalls = LLRender::sUIVerts = 0; + ypos += y_inc; - addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount)); - - ypos += y_inc; + addText(xpos,ypos, llformat("%d/%d Nodes visible", gPipeline.mNumVisibleNodes, LLSpatialGroup::sNodeCount)); - if (!LLOcclusionCullingGroup::sPendingQueries.empty()) - { - addText(xpos,ypos, llformat("%d Queries pending", LLOcclusionCullingGroup::sPendingQueries.size())); - ypos += y_inc; - } + ypos += y_inc; + if (!LLOcclusionCullingGroup::sPendingQueries.empty()) + { + addText(xpos,ypos, llformat("%d Queries pending", LLOcclusionCullingGroup::sPendingQueries.size())); + ypos += y_inc; + } + + + addText(xpos,ypos, llformat("%d Avatars visible", LLVOAvatar::sNumVisibleAvatars)); + + ypos += y_inc; - addText(xpos,ypos, llformat("%d Avatars visible", LLVOAvatar::sNumVisibleAvatars)); - - ypos += y_inc; + addText(xpos,ypos, llformat("%d Lights visible", LLPipeline::sVisibleLightCount)); - addText(xpos,ypos, llformat("%d Lights visible", LLPipeline::sVisibleLightCount)); - - ypos += y_inc; + ypos += y_inc; + + if (gMeshRepo.meshRezEnabled()) + { + addText(xpos, ypos, llformat("%.3f MB Mesh Data Received", LLMeshRepository::sBytesReceived/(1024.f*1024.f))); + + ypos += y_inc; - if (gMeshRepo.meshRezEnabled()) - { - addText(xpos, ypos, llformat("%.3f MB Mesh Data Received", LLMeshRepository::sBytesReceived/(1024.f*1024.f))); - - ypos += y_inc; - - addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount, - LLMeshRepository::sHTTPRetryCount)); - ypos += y_inc; + addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount, + LLMeshRepository::sHTTPRetryCount)); + ypos += y_inc; - addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing)); - ypos += y_inc; + addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing)); + ypos += y_inc; - addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f))); + addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f))); ypos += y_inc; addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Skins/Decompositions Memory", LLMeshRepository::sCacheBytesSkins / (1024.f*1024.f), LLMeshRepository::sCacheBytesDecomps / (1024.f*1024.f))); @@ -733,72 +733,72 @@ public: addText(xpos, ypos, llformat("%.3f MB Mesh Headers Memory", LLMeshRepository::sCacheBytesHeaders / (1024.f*1024.f))); - ypos += y_inc; - } + ypos += y_inc; + } gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; - } - if (gSavedSettings.getBOOL("DebugShowAvatarRenderInfo")) - { - std::map<std::string, LLVOAvatar*> sorted_avs; - - std::vector<LLCharacter*>::iterator sort_iter = LLCharacter::sInstances.begin(); - while (sort_iter != LLCharacter::sInstances.end()) - { - LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*sort_iter); - if (avatar && - !avatar->isDead()) // Not dead yet - { - // Stuff into a sorted map so the display is ordered - sorted_avs[avatar->getFullname()] = avatar; - } - sort_iter++; - } - - std::string trunc_name; - std::map<std::string, LLVOAvatar*>::reverse_iterator av_iter = sorted_avs.rbegin(); // Put "A" at the top - while (av_iter != sorted_avs.rend()) - { - LLVOAvatar* avatar = av_iter->second; - - avatar->calculateUpdateRenderComplexity(); // Make sure the numbers are up-to-date - - trunc_name = utf8str_truncate(avatar->getFullname(), 16); - addText(xpos, ypos, llformat("%s : %s, complexity %d, area %.2f", - trunc_name.c_str(), + } + if (gSavedSettings.getBOOL("DebugShowAvatarRenderInfo")) + { + std::map<std::string, LLVOAvatar*> sorted_avs; + + std::vector<LLCharacter*>::iterator sort_iter = LLCharacter::sInstances.begin(); + while (sort_iter != LLCharacter::sInstances.end()) + { + LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*sort_iter); + if (avatar && + !avatar->isDead()) // Not dead yet + { + // Stuff into a sorted map so the display is ordered + sorted_avs[avatar->getFullname()] = avatar; + } + sort_iter++; + } + + std::string trunc_name; + std::map<std::string, LLVOAvatar*>::reverse_iterator av_iter = sorted_avs.rbegin(); // Put "A" at the top + while (av_iter != sorted_avs.rend()) + { + LLVOAvatar* avatar = av_iter->second; + + avatar->calculateUpdateRenderComplexity(); // Make sure the numbers are up-to-date + + trunc_name = utf8str_truncate(avatar->getFullname(), 16); + addText(xpos, ypos, llformat("%s : %s, complexity %d, area %.2f", + trunc_name.c_str(), LLVOAvatar::rezStatusToString(avatar->getRezzedStatus()).c_str(), - avatar->getVisualComplexity(), - avatar->getAttachmentSurfaceArea())); - ypos += y_inc; - av_iter++; - } - } - if (gSavedSettings.getBOOL("DebugShowRenderMatrices")) - { - char camera_lines[8][32]; - memset(camera_lines, ' ', sizeof(camera_lines)); - - // Projection last column is always <0,0,-1.0001,0> - // Projection last row is always <0,0,-0.2> - mBackRectCamera1.mBottom = ypos - y_inc + 2; - MATRIX_ROW_N32_TO_STR(gGLProjection, 12,camera_lines[7]); addText(xpos, ypos, std::string(camera_lines[7])); ypos += y_inc; - MATRIX_ROW_N32_TO_STR(gGLProjection, 8,camera_lines[6]); addText(xpos, ypos, std::string(camera_lines[6])); ypos += y_inc; - MATRIX_ROW_N32_TO_STR(gGLProjection, 4,camera_lines[5]); addText(xpos, ypos, std::string(camera_lines[5])); ypos += y_inc; mBackRectCamera1.mTop = ypos + 2; - MATRIX_ROW_N32_TO_STR(gGLProjection, 0,camera_lines[4]); addText(xpos, ypos, std::string(camera_lines[4])); ypos += y_inc; mBackRectCamera2.mBottom = ypos + 2; - - addText(xpos, ypos, "Projection Matrix"); - ypos += y_inc; - - // View last column is always <0,0,0,1> - MATRIX_ROW_F32_TO_STR(gGLModelView, 12,camera_lines[3]); addText(xpos, ypos, std::string(camera_lines[3])); ypos += y_inc; - MATRIX_ROW_N32_TO_STR(gGLModelView, 8,camera_lines[2]); addText(xpos, ypos, std::string(camera_lines[2])); ypos += y_inc; - MATRIX_ROW_N32_TO_STR(gGLModelView, 4,camera_lines[1]); addText(xpos, ypos, std::string(camera_lines[1])); ypos += y_inc; mBackRectCamera2.mTop = ypos + 2; - MATRIX_ROW_N32_TO_STR(gGLModelView, 0,camera_lines[0]); addText(xpos, ypos, std::string(camera_lines[0])); ypos += y_inc; - - addText(xpos, ypos, "View Matrix"); - ypos += y_inc; - } - // disable use of glReadPixels which messes up nVidia nSight graphics debugging + avatar->getVisualComplexity(), + avatar->getAttachmentSurfaceArea())); + ypos += y_inc; + av_iter++; + } + } + if (gSavedSettings.getBOOL("DebugShowRenderMatrices")) + { + char camera_lines[8][32]; + memset(camera_lines, ' ', sizeof(camera_lines)); + + // Projection last column is always <0,0,-1.0001,0> + // Projection last row is always <0,0,-0.2> + mBackRectCamera1.mBottom = ypos - y_inc + 2; + MATRIX_ROW_N32_TO_STR(gGLProjection, 12,camera_lines[7]); addText(xpos, ypos, std::string(camera_lines[7])); ypos += y_inc; + MATRIX_ROW_N32_TO_STR(gGLProjection, 8,camera_lines[6]); addText(xpos, ypos, std::string(camera_lines[6])); ypos += y_inc; + MATRIX_ROW_N32_TO_STR(gGLProjection, 4,camera_lines[5]); addText(xpos, ypos, std::string(camera_lines[5])); ypos += y_inc; mBackRectCamera1.mTop = ypos + 2; + MATRIX_ROW_N32_TO_STR(gGLProjection, 0,camera_lines[4]); addText(xpos, ypos, std::string(camera_lines[4])); ypos += y_inc; mBackRectCamera2.mBottom = ypos + 2; + + addText(xpos, ypos, "Projection Matrix"); + ypos += y_inc; + + // View last column is always <0,0,0,1> + MATRIX_ROW_F32_TO_STR(gGLModelView, 12,camera_lines[3]); addText(xpos, ypos, std::string(camera_lines[3])); ypos += y_inc; + MATRIX_ROW_N32_TO_STR(gGLModelView, 8,camera_lines[2]); addText(xpos, ypos, std::string(camera_lines[2])); ypos += y_inc; + MATRIX_ROW_N32_TO_STR(gGLModelView, 4,camera_lines[1]); addText(xpos, ypos, std::string(camera_lines[1])); ypos += y_inc; mBackRectCamera2.mTop = ypos + 2; + MATRIX_ROW_N32_TO_STR(gGLModelView, 0,camera_lines[0]); addText(xpos, ypos, std::string(camera_lines[0])); ypos += y_inc; + + addText(xpos, ypos, "View Matrix"); + ypos += y_inc; + } + // disable use of glReadPixels which messes up nVidia nSight graphics debugging if (gSavedSettings.getBOOL("DebugShowColor") && !LLRender::sNsightDebugSupport) { U8 color[4]; @@ -807,165 +807,165 @@ public: // Convert x,y to raw pixel coords S32 x_raw = llround(coord.mX * gViewerWindow->getWindowWidthRaw() / (F32) gViewerWindow->getWindowWidthScaled()); S32 y_raw = llround(coord.mY * gViewerWindow->getWindowHeightRaw() / (F32) gViewerWindow->getWindowHeightScaled()); - + glReadPixels(x_raw, y_raw, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color); addText(xpos, ypos, llformat("Pixel <%1d, %1d> R:%1d G:%1d B:%1d A:%1d", x_raw, y_raw, color[0], color[1], color[2], color[3])); ypos += y_inc; } // only display these messages if we are actually rendering beacons at this moment - if (LLPipeline::getRenderBeacons() && LLFloaterReg::instanceVisible("beacons")) - { - if (LLPipeline::getRenderMOAPBeacons()) - { - addText(xpos, ypos, "Viewing media beacons (white)"); - ypos += y_inc; - } - - if (LLPipeline::toggleRenderTypeControlNegated(LLPipeline::RENDER_TYPE_PARTICLES)) - { - addText(xpos, ypos, particle_hiding); - ypos += y_inc; - } - - if (LLPipeline::getRenderParticleBeacons()) - { - addText(xpos, ypos, "Viewing particle beacons (blue)"); - ypos += y_inc; - } - - if (LLPipeline::getRenderSoundBeacons()) - { - addText(xpos, ypos, "Viewing sound beacons (yellow)"); - ypos += y_inc; - } - - if (LLPipeline::getRenderScriptedBeacons()) - { - addText(xpos, ypos, beacon_scripted); - ypos += y_inc; - } - else - if (LLPipeline::getRenderScriptedTouchBeacons()) - { - addText(xpos, ypos, beacon_scripted_touch); - ypos += y_inc; - } - - if (LLPipeline::getRenderPhysicalBeacons()) - { - addText(xpos, ypos, "Viewing physical object beacons (green)"); - ypos += y_inc; - } - } - - static LLUICachedControl<bool> show_sun_beacon("sunbeacon", false); - static LLUICachedControl<bool> show_moon_beacon("moonbeacon", false); - - if (show_sun_beacon) - { - addText(xpos, ypos, beacon_sun); - ypos += y_inc; - } - if (show_moon_beacon) - { - addText(xpos, ypos, beacon_moon); - ypos += y_inc; - } - - if(log_texture_traffic) - { - U32 old_y = ypos ; - for(S32 i = LLViewerTexture::BOOST_NONE; i < LLViewerTexture::MAX_GL_IMAGE_CATEGORY; i++) - { - if(gTotalTextureBytesPerBoostLevel[i] > (S32Bytes)0) - { - addText(xpos, ypos, llformat("Boost_Level %d: %.3f MB", i, F32Megabytes(gTotalTextureBytesPerBoostLevel[i]).value())); - ypos += y_inc; - } - } - if(ypos != old_y) - { - addText(xpos, ypos, "Network traffic for textures:"); - ypos += y_inc; - } - } - - if (gSavedSettings.getBOOL("DebugShowTextureInfo")) - { - LLViewerObject* objectp = NULL ; - - LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode(); - if (nodep) - { - objectp = nodep->getObject(); - } - - if (objectp && !objectp->isDead()) - { - S32 num_faces = objectp->mDrawable->getNumFaces() ; - std::set<LLViewerFetchedTexture*> tex_list; - - for(S32 i = 0 ; i < num_faces; i++) - { - LLFace* facep = objectp->mDrawable->getFace(i) ; - if(facep) - { - LLViewerFetchedTexture* tex = dynamic_cast<LLViewerFetchedTexture*>(facep->getTexture()) ; - if(tex) - { - if(tex_list.find(tex) != tex_list.end()) - { - continue ; //already displayed. - } - tex_list.insert(tex); - - std::string uuid_str; - tex->getID().toString(uuid_str); - uuid_str = uuid_str.substr(0,7); - - addText(xpos, ypos, llformat("ID: %s v_size: %.3f", uuid_str.c_str(), tex->getMaxVirtualSize())); - ypos += y_inc; - - addText(xpos, ypos, llformat("discard level: %d desired level: %d Missing: %s", tex->getDiscardLevel(), - tex->getDesiredDiscardLevel(), tex->isMissingAsset() ? "Y" : "N")); - ypos += y_inc; - } - } - } - } - } - } - - void draw() - { - LL_RECORD_BLOCK_TIME(FTM_DISPLAY_DEBUG_TEXT); - - // Camera matrix text is hard to see again a white background - // Add a dark background underneath the matrices for readability (contrast) - if (mBackRectCamera1.mTop >= 0) - { - mBackColor.setAlpha( 0.75f ); - gl_rect_2d(mBackRectCamera1, mBackColor, true); - - mBackColor.setAlpha( 0.66f ); - gl_rect_2d(mBackRectCamera2, mBackColor, true); - } - - for (line_list_t::iterator iter = mLineList.begin(); - iter != mLineList.end(); ++iter) - { - const Line& line = *iter; - LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor, - LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); - } - } + if (LLPipeline::getRenderBeacons() && LLFloaterReg::instanceVisible("beacons")) + { + if (LLPipeline::getRenderMOAPBeacons()) + { + addText(xpos, ypos, "Viewing media beacons (white)"); + ypos += y_inc; + } + + if (LLPipeline::toggleRenderTypeControlNegated(LLPipeline::RENDER_TYPE_PARTICLES)) + { + addText(xpos, ypos, particle_hiding); + ypos += y_inc; + } + + if (LLPipeline::getRenderParticleBeacons()) + { + addText(xpos, ypos, "Viewing particle beacons (blue)"); + ypos += y_inc; + } + + if (LLPipeline::getRenderSoundBeacons()) + { + addText(xpos, ypos, "Viewing sound beacons (yellow)"); + ypos += y_inc; + } + + if (LLPipeline::getRenderScriptedBeacons()) + { + addText(xpos, ypos, beacon_scripted); + ypos += y_inc; + } + else + if (LLPipeline::getRenderScriptedTouchBeacons()) + { + addText(xpos, ypos, beacon_scripted_touch); + ypos += y_inc; + } + + if (LLPipeline::getRenderPhysicalBeacons()) + { + addText(xpos, ypos, "Viewing physical object beacons (green)"); + ypos += y_inc; + } + } + + static LLUICachedControl<bool> show_sun_beacon("sunbeacon", false); + static LLUICachedControl<bool> show_moon_beacon("moonbeacon", false); + + if (show_sun_beacon) + { + addText(xpos, ypos, beacon_sun); + ypos += y_inc; + } + if (show_moon_beacon) + { + addText(xpos, ypos, beacon_moon); + ypos += y_inc; + } + + if(log_texture_traffic) + { + U32 old_y = ypos ; + for(S32 i = LLViewerTexture::BOOST_NONE; i < LLViewerTexture::MAX_GL_IMAGE_CATEGORY; i++) + { + if(gTotalTextureBytesPerBoostLevel[i] > (S32Bytes)0) + { + addText(xpos, ypos, llformat("Boost_Level %d: %.3f MB", i, F32Megabytes(gTotalTextureBytesPerBoostLevel[i]).value())); + ypos += y_inc; + } + } + if(ypos != old_y) + { + addText(xpos, ypos, "Network traffic for textures:"); + ypos += y_inc; + } + } + + if (gSavedSettings.getBOOL("DebugShowTextureInfo")) + { + LLViewerObject* objectp = NULL ; + + LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode(); + if (nodep) + { + objectp = nodep->getObject(); + } + + if (objectp && !objectp->isDead()) + { + S32 num_faces = objectp->mDrawable->getNumFaces() ; + std::set<LLViewerFetchedTexture*> tex_list; + + for(S32 i = 0 ; i < num_faces; i++) + { + LLFace* facep = objectp->mDrawable->getFace(i) ; + if(facep) + { + LLViewerFetchedTexture* tex = dynamic_cast<LLViewerFetchedTexture*>(facep->getTexture()) ; + if(tex) + { + if(tex_list.find(tex) != tex_list.end()) + { + continue ; //already displayed. + } + tex_list.insert(tex); + + std::string uuid_str; + tex->getID().toString(uuid_str); + uuid_str = uuid_str.substr(0,7); + + addText(xpos, ypos, llformat("ID: %s v_size: %.3f", uuid_str.c_str(), tex->getMaxVirtualSize())); + ypos += y_inc; + + addText(xpos, ypos, llformat("discard level: %d desired level: %d Missing: %s", tex->getDiscardLevel(), + tex->getDesiredDiscardLevel(), tex->isMissingAsset() ? "Y" : "N")); + ypos += y_inc; + } + } + } + } + } + } + + void draw() + { + LL_RECORD_BLOCK_TIME(FTM_DISPLAY_DEBUG_TEXT); + + // Camera matrix text is hard to see again a white background + // Add a dark background underneath the matrices for readability (contrast) + if (mBackRectCamera1.mTop >= 0) + { + mBackColor.setAlpha( 0.75f ); + gl_rect_2d(mBackRectCamera1, mBackColor, true); + + mBackColor.setAlpha( 0.66f ); + gl_rect_2d(mBackRectCamera2, mBackColor, true); + } + + for (line_list_t::iterator iter = mLineList.begin(); + iter != mLineList.end(); ++iter) + { + const Line& line = *iter; + LLFontGL::getFontMonospace()->renderUTF8(line.text, 0, (F32)line.x, (F32)line.y, mTextColor, + LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW); + } + } }; void LLViewerWindow::updateDebugText() { - mDebugText->update(); + mDebugText->update(); } //////////////////////////////////////////////////////////////////////////// @@ -974,16 +974,16 @@ void LLViewerWindow::updateDebugText() // LLViewerWindow::Params::Params() -: title("title"), - name("name"), - x("x"), - y("y"), - width("width"), - height("height"), - min_width("min_width"), - min_height("min_height"), - fullscreen("fullscreen", false), - ignore_pixel_depth("ignore_pixel_depth", false) +: title("title"), + name("name"), + x("x"), + y("y"), + width("width"), + height("height"), + min_width("min_width"), + min_height("min_height"), + fullscreen("fullscreen", false), + ignore_pixel_depth("ignore_pixel_depth", false) {} @@ -1000,167 +1000,167 @@ void LLViewerWindow::handlePieMenu(S32 x, S32 y, MASK mask) bool LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, bool down, bool& is_toolmgr_action) { - const char* buttonname = ""; - const char* buttonstatestr = ""; - S32 x = pos.mX; - S32 y = pos.mY; - x = ll_round((F32)x / mDisplayScale.mV[VX]); - y = ll_round((F32)y / mDisplayScale.mV[VY]); + const char* buttonname = ""; + const char* buttonstatestr = ""; + S32 x = pos.mX; + S32 y = pos.mY; + x = ll_round((F32)x / mDisplayScale.mV[VX]); + y = ll_round((F32)y / mDisplayScale.mV[VY]); - // Handle non-consuming global keybindings, like voice + // Handle non-consuming global keybindings, like voice gViewerInput.handleGlobalBindsMouse(clicktype, mask, down); - // only send mouse clicks to UI if UI is visible - if(gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - - if (down) - { - buttonstatestr = "down" ; - } - else - { - buttonstatestr = "up" ; - } - - switch (clicktype) - { - case CLICK_LEFT: - mLeftMouseDown = down; - buttonname = "Left"; - break; - case CLICK_RIGHT: - mRightMouseDown = down; - buttonname = "Right"; - break; - case CLICK_MIDDLE: - mMiddleMouseDown = down; - buttonname = "Middle"; - break; - case CLICK_DOUBLELEFT: - mLeftMouseDown = down; - buttonname = "Left Double Click"; - break; - case CLICK_BUTTON4: - buttonname = "Button 4"; - break; - case CLICK_BUTTON5: - buttonname = "Button 5"; - break; - default: - break; // COUNT and NONE - } - - LLView::sMouseHandlerMessage.clear(); - - if (gMenuBarView) - { - // stop ALT-key access to menu - gMenuBarView->resetMenuTrigger(); - } - - if (gDebugClicks) - { - LL_INFOS() << "ViewerWindow " << buttonname << " mouse " << buttonstatestr << " at " << x << "," << y << LL_ENDL; - } - - // Make sure we get a corresponding mouseup event, even if the mouse leaves the window - if (down) - mWindow->captureMouse(); - else - mWindow->releaseMouse(); - - // Indicate mouse was active - LLUI::getInstance()->resetMouseIdleTimer(); - - // Don't let the user move the mouse out of the window until mouse up. - if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() ) - { - mWindow->setMouseClipping(down); - } - - LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); - if( mouse_captor ) - { - S32 local_x; - S32 local_y; - mouse_captor->screenPointToLocal( x, y, &local_x, &local_y ); - if (LLView::sDebugMouseHandling) - { - LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << LL_ENDL; - } - - bool r = mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down); - if (r) { - - LL_DEBUGS() << "LLViewerWindow::handleAnyMouseClick viewer with mousecaptor calling updatemouseeventinfo - local_x|global x "<< local_x << " " << x << "local/global y " << local_y << " " << y << LL_ENDL; - - LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); - LLViewerEventRecorder::instance().logMouseEvent(std::string(buttonstatestr),std::string(buttonname)); - - } - else if (down && clicktype == CLICK_RIGHT) - { - handlePieMenu(x, y, mask); - r = true; - } - return r; - } - - // Mark the click as handled and return if we aren't within the root view to avoid spurious bugs - if( !mRootView->pointInView(x, y) ) - { - return true; - } - // Give the UI views a chance to process the click - - bool r= mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) ; - if (r) - { - - LL_DEBUGS() << "LLViewerWindow::handleAnyMouseClick calling updatemouseeventinfo - global x "<< " " << x << "global y " << y << "buttonstate: " << buttonstatestr << " buttonname " << buttonname << LL_ENDL; - - LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); - - // Clear local coords - this was a click on root window so these are not needed - // By not including them, this allows the test skeleton generation tool to be smarter when generating code - // the code generator can be smarter because when local coords are present it can try the xui path with local coords - // and fallback to global coordinates only if needed. - // The drawback to this approach is sometimes a valid xui path will appear to work fine, but NOT interact with the UI element - // (VITA support not implemented yet or not visible to VITA due to widget further up xui path not being visible to VITA) - // For this reason it's best to provide hints where possible here by leaving out local coordinates - LLViewerEventRecorder::instance().setMouseLocalCoords(-1,-1); - LLViewerEventRecorder::instance().logMouseEvent(buttonstatestr,buttonname); - - if (LLView::sDebugMouseHandling) - { - LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " " << LLViewerEventRecorder::instance().get_xui() << LL_ENDL; - } - return true; - } else if (LLView::sDebugMouseHandling) - { - LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " not handled by view" << LL_ENDL; - } - } - - // Do not allow tool manager to handle mouseclicks if we have disconnected - if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) ) - { - LLViewerEventRecorder::instance().clear_xui(); + // only send mouse clicks to UI if UI is visible + if(gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + + if (down) + { + buttonstatestr = "down" ; + } + else + { + buttonstatestr = "up" ; + } + + switch (clicktype) + { + case CLICK_LEFT: + mLeftMouseDown = down; + buttonname = "Left"; + break; + case CLICK_RIGHT: + mRightMouseDown = down; + buttonname = "Right"; + break; + case CLICK_MIDDLE: + mMiddleMouseDown = down; + buttonname = "Middle"; + break; + case CLICK_DOUBLELEFT: + mLeftMouseDown = down; + buttonname = "Left Double Click"; + break; + case CLICK_BUTTON4: + buttonname = "Button 4"; + break; + case CLICK_BUTTON5: + buttonname = "Button 5"; + break; + default: + break; // COUNT and NONE + } + + LLView::sMouseHandlerMessage.clear(); + + if (gMenuBarView) + { + // stop ALT-key access to menu + gMenuBarView->resetMenuTrigger(); + } + + if (gDebugClicks) + { + LL_INFOS() << "ViewerWindow " << buttonname << " mouse " << buttonstatestr << " at " << x << "," << y << LL_ENDL; + } + + // Make sure we get a corresponding mouseup event, even if the mouse leaves the window + if (down) + mWindow->captureMouse(); + else + mWindow->releaseMouse(); + + // Indicate mouse was active + LLUI::getInstance()->resetMouseIdleTimer(); + + // Don't let the user move the mouse out of the window until mouse up. + if( LLToolMgr::getInstance()->getCurrentTool()->clipMouseWhenDown() ) + { + mWindow->setMouseClipping(down); + } + + LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); + if( mouse_captor ) + { + S32 local_x; + S32 local_y; + mouse_captor->screenPointToLocal( x, y, &local_x, &local_y ); + if (LLView::sDebugMouseHandling) + { + LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << LL_ENDL; + } + + bool r = mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down); + if (r) { + + LL_DEBUGS() << "LLViewerWindow::handleAnyMouseClick viewer with mousecaptor calling updatemouseeventinfo - local_x|global x "<< local_x << " " << x << "local/global y " << local_y << " " << y << LL_ENDL; + + LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); + LLViewerEventRecorder::instance().logMouseEvent(std::string(buttonstatestr),std::string(buttonname)); + + } + else if (down && clicktype == CLICK_RIGHT) + { + handlePieMenu(x, y, mask); + r = true; + } + return r; + } + + // Mark the click as handled and return if we aren't within the root view to avoid spurious bugs + if( !mRootView->pointInView(x, y) ) + { + return true; + } + // Give the UI views a chance to process the click + + bool r= mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) ; + if (r) + { + + LL_DEBUGS() << "LLViewerWindow::handleAnyMouseClick calling updatemouseeventinfo - global x "<< " " << x << "global y " << y << "buttonstate: " << buttonstatestr << " buttonname " << buttonname << LL_ENDL; + + LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); + + // Clear local coords - this was a click on root window so these are not needed + // By not including them, this allows the test skeleton generation tool to be smarter when generating code + // the code generator can be smarter because when local coords are present it can try the xui path with local coords + // and fallback to global coordinates only if needed. + // The drawback to this approach is sometimes a valid xui path will appear to work fine, but NOT interact with the UI element + // (VITA support not implemented yet or not visible to VITA due to widget further up xui path not being visible to VITA) + // For this reason it's best to provide hints where possible here by leaving out local coordinates + LLViewerEventRecorder::instance().setMouseLocalCoords(-1,-1); + LLViewerEventRecorder::instance().logMouseEvent(buttonstatestr,buttonname); + + if (LLView::sDebugMouseHandling) + { + LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " " << LLViewerEventRecorder::instance().get_xui() << LL_ENDL; + } + return true; + } else if (LLView::sDebugMouseHandling) + { + LL_INFOS() << buttonname << " Mouse " << buttonstatestr << " not handled by view" << LL_ENDL; + } + } + + // Do not allow tool manager to handle mouseclicks if we have disconnected + if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) ) + { + LLViewerEventRecorder::instance().clear_xui(); is_toolmgr_action = true; - return true; - } + return true; + } - if (down && clicktype == CLICK_RIGHT) - { - handlePieMenu(x, y, mask); - return true; - } + if (down && clicktype == CLICK_RIGHT) + { + handlePieMenu(x, y, mask); + return true; + } - // If we got this far on a down-click, it wasn't handled. - // Up-clicks, though, are always handled as far as the OS is concerned. - bool default_rtn = !down; - return default_rtn; + // If we got this far on a down-click, it wasn't handled. + // Up-clicks, though, are always handled as far as the OS is concerned. + bool default_rtn = !down; + return default_rtn; } bool LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask) @@ -1173,7 +1173,7 @@ bool LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask else { mMouseDownTimer.reset(); - } + } bool down = true; //handleMouse() loops back to LLViewerWindow::handleAnyMouseClick return gViewerInput.handleMouse(window, pos, mask, CLICK_LEFT, down); @@ -1181,14 +1181,14 @@ bool LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask bool LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask) { - // try handling as a double-click first, then a single-click if that - // wasn't handled. - bool down = true; - if (gViewerInput.handleMouse(window, pos, mask, CLICK_DOUBLELEFT, down)) - { - return true; - } - return handleMouseDown(window, pos, mask); + // try handling as a double-click first, then a single-click if that + // wasn't handled. + bool down = true; + if (gViewerInput.handleMouse(window, pos, mask, CLICK_DOUBLELEFT, down)) + { + return true; + } + return handleMouseDown(window, pos, mask); } bool LLViewerWindow::handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) @@ -1202,177 +1202,177 @@ bool LLViewerWindow::handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) } bool LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask) { - bool down = true; - return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down); + bool down = true; + return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down); } bool LLViewerWindow::handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) { - bool down = false; - return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down); + bool down = false; + return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down); } bool LLViewerWindow::handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask) { - bool down = true; - gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down); - - // Always handled as far as the OS is concerned. - return true; + bool down = true; + gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down); + + // Always handled as far as the OS is concerned. + return true; } LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data) { - LLWindowCallbacks::DragNDropResult result = LLWindowCallbacks::DND_NONE; - - const bool prim_media_dnd_enabled = gSavedSettings.getBOOL("PrimMediaDragNDrop"); - const bool slurl_dnd_enabled = gSavedSettings.getBOOL("SLURLDragNDrop"); - - if ( prim_media_dnd_enabled || slurl_dnd_enabled ) - { - switch(action) - { - // Much of the handling for these two cases is the same. - case LLWindowCallbacks::DNDA_TRACK: - case LLWindowCallbacks::DNDA_DROPPED: - case LLWindowCallbacks::DNDA_START_TRACKING: - { - bool drop = (LLWindowCallbacks::DNDA_DROPPED == action); - - if (slurl_dnd_enabled) - { - LLSLURL dropped_slurl(data); - if(dropped_slurl.isSpatial()) - { - if (drop) - { - LLURLDispatcher::dispatch( dropped_slurl.getSLURLString(), LLCommandHandler::NAV_TYPE_CLICKED, NULL, true ); - return LLWindowCallbacks::DND_MOVE; - } - return LLWindowCallbacks::DND_COPY; - } - } - - if (prim_media_dnd_enabled) - { - LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY, - true /* pick_transparent */, + LLWindowCallbacks::DragNDropResult result = LLWindowCallbacks::DND_NONE; + + const bool prim_media_dnd_enabled = gSavedSettings.getBOOL("PrimMediaDragNDrop"); + const bool slurl_dnd_enabled = gSavedSettings.getBOOL("SLURLDragNDrop"); + + if ( prim_media_dnd_enabled || slurl_dnd_enabled ) + { + switch(action) + { + // Much of the handling for these two cases is the same. + case LLWindowCallbacks::DNDA_TRACK: + case LLWindowCallbacks::DNDA_DROPPED: + case LLWindowCallbacks::DNDA_START_TRACKING: + { + bool drop = (LLWindowCallbacks::DNDA_DROPPED == action); + + if (slurl_dnd_enabled) + { + LLSLURL dropped_slurl(data); + if(dropped_slurl.isSpatial()) + { + if (drop) + { + LLURLDispatcher::dispatch( dropped_slurl.getSLURLString(), LLCommandHandler::NAV_TYPE_CLICKED, NULL, true ); + return LLWindowCallbacks::DND_MOVE; + } + return LLWindowCallbacks::DND_COPY; + } + } + + if (prim_media_dnd_enabled) + { + LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY, + true /* pick_transparent */, false /* pick_rigged */); - S32 object_face = pick_info.mObjectFace; - std::string url = data; - - LL_DEBUGS() << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << LL_ENDL; - - LLVOVolume *obj = dynamic_cast<LLVOVolume*>(static_cast<LLViewerObject*>(pick_info.getObject())); - - if (obj && !obj->getRegion()->getCapability("ObjectMedia").empty()) - { - LLTextureEntry *te = obj->getTE(object_face); - - // can modify URL if we can modify the object or we have navigate permissions - bool allow_modify_url = obj->permModify() || obj->hasMediaPermission( te->getMediaData(), LLVOVolume::MEDIA_PERM_INTERACT ); - - if (te && allow_modify_url ) - { - if (drop) - { - // object does NOT have media already - if ( ! te->hasMedia() ) - { - // we are allowed to modify the object - if ( obj->permModify() ) - { - // Create new media entry - LLSD media_data; - // XXX Should we really do Home URL too? - media_data[LLMediaEntry::HOME_URL_KEY] = url; - media_data[LLMediaEntry::CURRENT_URL_KEY] = url; - media_data[LLMediaEntry::AUTO_PLAY_KEY] = true; - obj->syncMediaData(object_face, media_data, true, true); - // XXX This shouldn't be necessary, should it ?!? - if (obj->getMediaImpl(object_face)) - obj->getMediaImpl(object_face)->navigateReload(); - obj->sendMediaDataUpdate(); - - result = LLWindowCallbacks::DND_COPY; - } - } - else - // object HAS media already - { - // URL passes the whitelist - if (te->getMediaData()->checkCandidateUrl( url ) ) - { - // just navigate to the URL - if (obj->getMediaImpl(object_face)) - { - obj->getMediaImpl(object_face)->navigateTo(url); - } - else - { - // This is very strange. Navigation should - // happen via the Impl, but we don't have one. - // This sends it to the server, which /should/ - // trigger us getting it. Hopefully. - LLSD media_data; - media_data[LLMediaEntry::CURRENT_URL_KEY] = url; - obj->syncMediaData(object_face, media_data, true, true); - obj->sendMediaDataUpdate(); - } - result = LLWindowCallbacks::DND_LINK; - - } - } - LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); - mDragHoveredObject = NULL; - - } - else - { - // Check the whitelist, if there's media (otherwise just show it) - if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url)) - { - if ( obj != mDragHoveredObject) - { - // Highlight the dragged object - LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); - mDragHoveredObject = obj; - LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject); - } - result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK; - - } - } - } - } - } - } - break; - - case LLWindowCallbacks::DNDA_STOP_TRACKING: - // The cleanup case below will make sure things are unhilighted if necessary. - break; - } - - if (prim_media_dnd_enabled && - result == LLWindowCallbacks::DND_NONE && !mDragHoveredObject.isNull()) - { - LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); - mDragHoveredObject = NULL; - } - } - - return result; + S32 object_face = pick_info.mObjectFace; + std::string url = data; + + LL_DEBUGS() << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << LL_ENDL; + + LLVOVolume *obj = dynamic_cast<LLVOVolume*>(static_cast<LLViewerObject*>(pick_info.getObject())); + + if (obj && !obj->getRegion()->getCapability("ObjectMedia").empty()) + { + LLTextureEntry *te = obj->getTE(object_face); + + // can modify URL if we can modify the object or we have navigate permissions + bool allow_modify_url = obj->permModify() || obj->hasMediaPermission( te->getMediaData(), LLVOVolume::MEDIA_PERM_INTERACT ); + + if (te && allow_modify_url ) + { + if (drop) + { + // object does NOT have media already + if ( ! te->hasMedia() ) + { + // we are allowed to modify the object + if ( obj->permModify() ) + { + // Create new media entry + LLSD media_data; + // XXX Should we really do Home URL too? + media_data[LLMediaEntry::HOME_URL_KEY] = url; + media_data[LLMediaEntry::CURRENT_URL_KEY] = url; + media_data[LLMediaEntry::AUTO_PLAY_KEY] = true; + obj->syncMediaData(object_face, media_data, true, true); + // XXX This shouldn't be necessary, should it ?!? + if (obj->getMediaImpl(object_face)) + obj->getMediaImpl(object_face)->navigateReload(); + obj->sendMediaDataUpdate(); + + result = LLWindowCallbacks::DND_COPY; + } + } + else + // object HAS media already + { + // URL passes the whitelist + if (te->getMediaData()->checkCandidateUrl( url ) ) + { + // just navigate to the URL + if (obj->getMediaImpl(object_face)) + { + obj->getMediaImpl(object_face)->navigateTo(url); + } + else + { + // This is very strange. Navigation should + // happen via the Impl, but we don't have one. + // This sends it to the server, which /should/ + // trigger us getting it. Hopefully. + LLSD media_data; + media_data[LLMediaEntry::CURRENT_URL_KEY] = url; + obj->syncMediaData(object_face, media_data, true, true); + obj->sendMediaDataUpdate(); + } + result = LLWindowCallbacks::DND_LINK; + + } + } + LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); + mDragHoveredObject = NULL; + + } + else + { + // Check the whitelist, if there's media (otherwise just show it) + if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url)) + { + if ( obj != mDragHoveredObject) + { + // Highlight the dragged object + LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); + mDragHoveredObject = obj; + LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject); + } + result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK; + + } + } + } + } + } + } + break; + + case LLWindowCallbacks::DNDA_STOP_TRACKING: + // The cleanup case below will make sure things are unhilighted if necessary. + break; + } + + if (prim_media_dnd_enabled && + result == LLWindowCallbacks::DND_NONE && !mDragHoveredObject.isNull()) + { + LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); + mDragHoveredObject = NULL; + } + } + + return result; } bool LLViewerWindow::handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) { - bool down = false; - gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down); - - // Always handled as far as the OS is concerned. - return true; + bool down = false; + gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down); + + // Always handled as far as the OS is concerned. + return true; } bool LLViewerWindow::handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask, S32 button, bool down) @@ -1406,32 +1406,32 @@ bool LLViewerWindow::handleOtherMouseUp(LLWindow *window, LLCoordGL pos, MASK ma // WARNING: this is potentially called multiple times per frame void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask) { - S32 x = pos.mX; - S32 y = pos.mY; + S32 x = pos.mX; + S32 y = pos.mY; - x = ll_round((F32)x / mDisplayScale.mV[VX]); - y = ll_round((F32)y / mDisplayScale.mV[VY]); + x = ll_round((F32)x / mDisplayScale.mV[VX]); + y = ll_round((F32)y / mDisplayScale.mV[VY]); - mMouseInWindow = true; + mMouseInWindow = true; - // Save mouse point for access during idle() and display() + // Save mouse point for access during idle() and display() - LLCoordGL mouse_point(x, y); + LLCoordGL mouse_point(x, y); - if (mouse_point != mCurrentMousePoint) - { - LLUI::getInstance()->resetMouseIdleTimer(); - } + if (mouse_point != mCurrentMousePoint) + { + LLUI::getInstance()->resetMouseIdleTimer(); + } - saveLastMouse(mouse_point); + saveLastMouse(mouse_point); - mWindow->showCursorFromMouseMove(); + mWindow->showCursorFromMouseMove(); - if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME - && !gDisconnected) - { - gAgent.clearAFK(); - } + if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME + && !gDisconnected) + { + gAgent.clearAFK(); + } } void LLViewerWindow::handleMouseDragged(LLWindow *window, LLCoordGL pos, MASK mask) @@ -1452,114 +1452,114 @@ void LLViewerWindow::handleMouseDragged(LLWindow *window, LLCoordGL pos, MASK m void LLViewerWindow::handleMouseLeave(LLWindow *window) { - // Note: we won't get this if we have captured the mouse. - llassert( gFocusMgr.getMouseCapture() == NULL ); - mMouseInWindow = false; - LLToolTipMgr::instance().blockToolTips(); + // Note: we won't get this if we have captured the mouse. + llassert( gFocusMgr.getMouseCapture() == NULL ); + mMouseInWindow = false; + LLToolTipMgr::instance().blockToolTips(); } bool LLViewerWindow::handleCloseRequest(LLWindow *window) { - // User has indicated they want to close, but we may need to ask - // about modified documents. - LLAppViewer::instance()->userQuit(); - // Don't quit immediately - return false; + // User has indicated they want to close, but we may need to ask + // about modified documents. + LLAppViewer::instance()->userQuit(); + // Don't quit immediately + return false; } void LLViewerWindow::handleQuit(LLWindow *window) { - if (gNonInteractive) - { - LLAppViewer::instance()->requestQuit(); - } - else - { - LL_INFOS() << "Window forced quit" << LL_ENDL; - LLAppViewer::instance()->forceQuit(); - } + if (gNonInteractive) + { + LLAppViewer::instance()->requestQuit(); + } + else + { + LL_INFOS() << "Window forced quit" << LL_ENDL; + LLAppViewer::instance()->forceQuit(); + } } void LLViewerWindow::handleResize(LLWindow *window, S32 width, S32 height) { - reshape(width, height); - mResDirty = true; + reshape(width, height); + mResDirty = true; } // The top-level window has gained focus (e.g. via ALT-TAB) void LLViewerWindow::handleFocus(LLWindow *window) { - gFocusMgr.setAppHasFocus(true); - LLModalDialog::onAppFocusGained(); + gFocusMgr.setAppHasFocus(true); + LLModalDialog::onAppFocusGained(); - gAgent.onAppFocusGained(); - LLToolMgr::getInstance()->onAppFocusGained(); + gAgent.onAppFocusGained(); + LLToolMgr::getInstance()->onAppFocusGained(); - // See if we're coming in with modifier keys held down - if (gKeyboard) - { - gKeyboard->resetMaskKeys(); - } + // See if we're coming in with modifier keys held down + if (gKeyboard) + { + gKeyboard->resetMaskKeys(); + } - // resume foreground running timer - // since we artifically limit framerate when not frontmost - gForegroundTime.unpause(); + // resume foreground running timer + // since we artifically limit framerate when not frontmost + gForegroundTime.unpause(); } // The top-level window has lost focus (e.g. via ALT-TAB) void LLViewerWindow::handleFocusLost(LLWindow *window) { - gFocusMgr.setAppHasFocus(false); - //LLModalDialog::onAppFocusLost(); - LLToolMgr::getInstance()->onAppFocusLost(); - gFocusMgr.setMouseCapture( NULL ); + gFocusMgr.setAppHasFocus(false); + //LLModalDialog::onAppFocusLost(); + LLToolMgr::getInstance()->onAppFocusLost(); + gFocusMgr.setMouseCapture( NULL ); - if (gMenuBarView) - { - // stop ALT-key access to menu - gMenuBarView->resetMenuTrigger(); - } + if (gMenuBarView) + { + // stop ALT-key access to menu + gMenuBarView->resetMenuTrigger(); + } - // restore mouse cursor - showCursor(); - getWindow()->setMouseClipping(false); + // restore mouse cursor + showCursor(); + getWindow()->setMouseClipping(false); - // If losing focus while keys are down, handle them as + // If losing focus while keys are down, handle them as // an 'up' to correctly release states, then reset states - if (gKeyboard) - { + if (gKeyboard) + { gKeyboard->resetKeyDownAndHandle(); - gKeyboard->resetKeys(); - } + gKeyboard->resetKeys(); + } - // pause timer that tracks total foreground running time - gForegroundTime.pause(); + // pause timer that tracks total foreground running time + gForegroundTime.pause(); } bool LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, bool repeated) { - // Handle non-consuming global keybindings, like voice + // Handle non-consuming global keybindings, like voice // Never affects event processing. gViewerInput.handleGlobalBindsKeyDown(key, mask); - if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME) - { - gAgent.clearAFK(); - } - - // *NOTE: We want to interpret KEY_RETURN later when it arrives as - // a Unicode char, not as a keydown. Otherwise when client frame - // rate is really low, hitting return sends your chat text before - // it's all entered/processed. - if (key == KEY_RETURN && mask == MASK_NONE) - { + if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME) + { + gAgent.clearAFK(); + } + + // *NOTE: We want to interpret KEY_RETURN later when it arrives as + // a Unicode char, not as a keydown. Otherwise when client frame + // rate is really low, hitting return sends your chat text before + // it's all entered/processed. + if (key == KEY_RETURN && mask == MASK_NONE) + { // RIDER: although, at times some of the controlls (in particular the CEF viewer // would like to know about the KEYDOWN for an enter key... so ask and pass it along. LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); if (keyboard_focus && !keyboard_focus->wantsReturnKey()) - return false; - } + return false; + } // remaps, handles ignored cases and returns back to viewer window. return gViewerInput.handleKey(key, mask, repeated); @@ -1567,25 +1567,25 @@ bool LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, bool repeated) bool LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask) { - // Handle non-consuming global keybindings, like voice + // Handle non-consuming global keybindings, like voice // Never affects event processing. gViewerInput.handleGlobalBindsKeyUp(key, mask); - // Let the inspect tool code check for ALT key to set LLToolSelectRect active instead LLToolCamera - LLToolCompInspect * tool_inspectp = LLToolCompInspect::getInstance(); - if (LLToolMgr::getInstance()->getCurrentTool() == tool_inspectp) - { - tool_inspectp->keyUp(key, mask); - } + // Let the inspect tool code check for ALT key to set LLToolSelectRect active instead LLToolCamera + LLToolCompInspect * tool_inspectp = LLToolCompInspect::getInstance(); + if (LLToolMgr::getInstance()->getCurrentTool() == tool_inspectp) + { + tool_inspectp->keyUp(key, mask); + } - return gViewerInput.handleKeyUp(key, mask); + return gViewerInput.handleKeyUp(key, mask); } void LLViewerWindow::handleScanKey(KEY key, bool key_down, bool key_up, bool key_level) { - LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); - gViewerInput.scanKey(key, key_down, key_up, key_level); - return; // Be clear this function returns nothing + LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); + gViewerInput.scanKey(key, key_down, key_up, key_level); + return; // Be clear this function returns nothing } @@ -1593,45 +1593,45 @@ void LLViewerWindow::handleScanKey(KEY key, bool key_down, bool key_up, bool key bool LLViewerWindow::handleActivate(LLWindow *window, bool activated) { - if (activated) - { - mActive = true; - send_agent_resume(); - gAgent.clearAFK(); - - // Unmute audio - audio_update_volume(); - } - else - { - mActive = false; - - // if the user has chosen to go Away automatically after some time, then go Away when minimizing - if (gSavedSettings.getS32("AFKTimeout")) - { - gAgent.setAFK(); - } - - // SL-53351: Make sure we're not in mouselook when minimised, to prevent control issues - if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) - { - gAgentCamera.changeCameraToDefault(); - } - - send_agent_pause(); - - // Mute audio - audio_update_volume(); - } - return true; + if (activated) + { + mActive = true; + send_agent_resume(); + gAgent.clearAFK(); + + // Unmute audio + audio_update_volume(); + } + else + { + mActive = false; + + // if the user has chosen to go Away automatically after some time, then go Away when minimizing + if (gSavedSettings.getS32("AFKTimeout")) + { + gAgent.setAFK(); + } + + // SL-53351: Make sure we're not in mouselook when minimised, to prevent control issues + if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) + { + gAgentCamera.changeCameraToDefault(); + } + + send_agent_pause(); + + // Mute audio + audio_update_volume(); + } + return true; } bool LLViewerWindow::handleActivateApp(LLWindow *window, bool activating) { - //if (!activating) gAgentCamera.changeCameraToDefault(); + //if (!activating) gAgentCamera.changeCameraToDefault(); - LLViewerJoystick::getInstance()->setNeedsReset(true); - return false; + LLViewerJoystick::getInstance()->setNeedsReset(true); + return false; } @@ -1642,108 +1642,108 @@ void LLViewerWindow::handleMenuSelect(LLWindow *window, S32 menu_item) bool LLViewerWindow::handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height) { - // *TODO: Enable similar information output for other platforms? DK 2011-02-18 + // *TODO: Enable similar information output for other platforms? DK 2011-02-18 #if LL_WINDOWS - if (gHeadlessClient) - { - HWND window_handle = (HWND)window->getPlatformWindow(); - PAINTSTRUCT ps; - HDC hdc; - - RECT wnd_rect; - wnd_rect.left = 0; - wnd_rect.top = 0; - wnd_rect.bottom = 200; - wnd_rect.right = 500; - - hdc = BeginPaint(window_handle, &ps); - //SetBKColor(hdc, RGB(255, 255, 255)); - FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255))); - - std::string temp_str; - LLTrace::Recording& recording = LLViewerStats::instance().getRecording(); - temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */ - recording.getPerSec(LLStatViewer::FPS), //mFPSStat.getMeanPerSec(), - recording.getLastValue(LLStatViewer::SIM_PHYSICS_FPS), - recording.getLastValue(LLStatViewer::SIM_TIME_DILATION)); - S32 len = temp_str.length(); - TextOutA(hdc, 0, 0, temp_str.c_str(), len); - - - LLVector3d pos_global = gAgent.getPositionGlobal(); - temp_str = llformat( "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]); - len = temp_str.length(); - TextOutA(hdc, 0, 25, temp_str.c_str(), len); - - TextOutA(hdc, 0, 50, "Set \"HeadlessClient FALSE\" in settings.ini file to reenable", 61); - EndPaint(window_handle, &ps); - return true; - } + if (gHeadlessClient) + { + HWND window_handle = (HWND)window->getPlatformWindow(); + PAINTSTRUCT ps; + HDC hdc; + + RECT wnd_rect; + wnd_rect.left = 0; + wnd_rect.top = 0; + wnd_rect.bottom = 200; + wnd_rect.right = 500; + + hdc = BeginPaint(window_handle, &ps); + //SetBKColor(hdc, RGB(255, 255, 255)); + FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255))); + + std::string temp_str; + LLTrace::Recording& recording = LLViewerStats::instance().getRecording(); + temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */ + recording.getPerSec(LLStatViewer::FPS), //mFPSStat.getMeanPerSec(), + recording.getLastValue(LLStatViewer::SIM_PHYSICS_FPS), + recording.getLastValue(LLStatViewer::SIM_TIME_DILATION)); + S32 len = temp_str.length(); + TextOutA(hdc, 0, 0, temp_str.c_str(), len); + + + LLVector3d pos_global = gAgent.getPositionGlobal(); + temp_str = llformat( "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]); + len = temp_str.length(); + TextOutA(hdc, 0, 25, temp_str.c_str(), len); + + TextOutA(hdc, 0, 50, "Set \"HeadlessClient FALSE\" in settings.ini file to reenable", 61); + EndPaint(window_handle, &ps); + return true; + } #endif - return false; + return false; } void LLViewerWindow::handleScrollWheel(LLWindow *window, S32 clicks) { - handleScrollWheel( clicks ); + handleScrollWheel( clicks ); } void LLViewerWindow::handleScrollHWheel(LLWindow *window, S32 clicks) { - handleScrollHWheel(clicks); + handleScrollHWheel(clicks); } void LLViewerWindow::handleWindowBlock(LLWindow *window) { - send_agent_pause(); + send_agent_pause(); } void LLViewerWindow::handleWindowUnblock(LLWindow *window) { - send_agent_resume(); + send_agent_resume(); } void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data) { - const S32 SLURL_MESSAGE_TYPE = 0; - switch (data_type) - { - case SLURL_MESSAGE_TYPE: - // received URL - std::string url = (const char*)data; - LLMediaCtrl* web = NULL; - const bool trusted_browser = false; - // don't treat slapps coming from external browsers as "clicks" as this would bypass throttling - if (LLURLDispatcher::dispatch(url, LLCommandHandler::NAV_TYPE_EXTERNAL, web, trusted_browser)) - { - // bring window to foreground, as it has just been "launched" from a URL - mWindow->bringToFront(); - } - break; - } + const S32 SLURL_MESSAGE_TYPE = 0; + switch (data_type) + { + case SLURL_MESSAGE_TYPE: + // received URL + std::string url = (const char*)data; + LLMediaCtrl* web = NULL; + const bool trusted_browser = false; + // don't treat slapps coming from external browsers as "clicks" as this would bypass throttling + if (LLURLDispatcher::dispatch(url, LLCommandHandler::NAV_TYPE_EXTERNAL, web, trusted_browser)) + { + // bring window to foreground, as it has just been "launched" from a URL + mWindow->bringToFront(); + } + break; + } } bool LLViewerWindow::handleTimerEvent(LLWindow *window) { //TODO: just call this every frame from gatherInput instead of using a convoluted 30fps timer callback - if (LLViewerJoystick::getInstance()->getOverrideCamera()) - { - LLViewerJoystick::getInstance()->updateStatus(); - return true; - } - return false; + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { + LLViewerJoystick::getInstance()->updateStatus(); + return true; + } + return false; } bool LLViewerWindow::handleDeviceChange(LLWindow *window) { - // give a chance to use a joystick after startup (hot-plugging) - if (!LLViewerJoystick::getInstance()->isJoystickInitialized() ) - { - LLViewerJoystick::getInstance()->init(true); - return true; - } - return false; + // give a chance to use a joystick after startup (hot-plugging) + if (!LLViewerJoystick::getInstance()->isJoystickInitialized() ) + { + LLViewerJoystick::getInstance()->init(true); + return true; + } + return false; } bool LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height) @@ -1763,106 +1763,106 @@ bool LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 bool LLViewerWindow::handleWindowDidChangeScreen(LLWindow *window) { - LLCoordScreen window_rect; - mWindow->getSize(&window_rect); - reshape(window_rect.mX, window_rect.mY); - return true; + LLCoordScreen window_rect; + mWindow->getSize(&window_rect); + reshape(window_rect.mX, window_rect.mY); + return true; } void LLViewerWindow::handlePingWatchdog(LLWindow *window, const char * msg) { - LLAppViewer::instance()->pingMainloopTimeout(msg); + LLAppViewer::instance()->pingMainloopTimeout(msg); } void LLViewerWindow::handleResumeWatchdog(LLWindow *window) { - LLAppViewer::instance()->resumeMainloopTimeout(); + LLAppViewer::instance()->resumeMainloopTimeout(); } void LLViewerWindow::handlePauseWatchdog(LLWindow *window) { - LLAppViewer::instance()->pauseMainloopTimeout(); + LLAppViewer::instance()->pauseMainloopTimeout(); } //virtual std::string LLViewerWindow::translateString(const char* tag) { - return LLTrans::getString( std::string(tag) ); + return LLTrans::getString( std::string(tag) ); } //virtual std::string LLViewerWindow::translateString(const char* tag, - const std::map<std::string, std::string>& args) -{ - // LLTrans uses a special subclass of std::string for format maps, - // but we must use std::map<> in these callbacks, otherwise we create - // a dependency between LLWindow and LLFormatMapString. So copy the data. - LLStringUtil::format_map_t args_copy; - std::map<std::string,std::string>::const_iterator it = args.begin(); - for ( ; it != args.end(); ++it) - { - args_copy[it->first] = it->second; - } - return LLTrans::getString( std::string(tag), args_copy); + const std::map<std::string, std::string>& args) +{ + // LLTrans uses a special subclass of std::string for format maps, + // but we must use std::map<> in these callbacks, otherwise we create + // a dependency between LLWindow and LLFormatMapString. So copy the data. + LLStringUtil::format_map_t args_copy; + std::map<std::string,std::string>::const_iterator it = args.begin(); + for ( ; it != args.end(); ++it) + { + args_copy[it->first] = it->second; + } + return LLTrans::getString( std::string(tag), args_copy); } // // Classes // LLViewerWindow::LLViewerWindow(const Params& p) -: mWindow(NULL), - mActive(true), - mUIVisible(true), - mWindowRectRaw(0, p.height, p.width, 0), - mWindowRectScaled(0, p.height, p.width, 0), - mWorldViewRectRaw(0, p.height, p.width, 0), - mLeftMouseDown(false), - mMiddleMouseDown(false), - mRightMouseDown(false), - mMouseInWindow( false ), +: mWindow(NULL), + mActive(true), + mUIVisible(true), + mWindowRectRaw(0, p.height, p.width, 0), + mWindowRectScaled(0, p.height, p.width, 0), + mWorldViewRectRaw(0, p.height, p.width, 0), + mLeftMouseDown(false), + mMiddleMouseDown(false), + mRightMouseDown(false), + mMouseInWindow( false ), mAllowMouseDragging(true), mMouseDownTimer(), - mLastMask( MASK_NONE ), - mToolStored( NULL ), - mHideCursorPermanent( false ), - mCursorHidden(false), - mIgnoreActivate( false ), - mResDirty(false), - mStatesDirty(false), - mCurrResolutionIndex(0), - mProgressView(NULL) -{ - // gKeyboard is still NULL, so it doesn't do LLWindowListener any good to - // pass its value right now. Instead, pass it a nullary function that - // will, when we later need it, return the value of gKeyboard. - // boost::lambda::var() constructs such a functor on the fly. - mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard))); - mViewerWindowListener.reset(new LLViewerWindowListener(this)); - - mSystemChannel.reset(new LLNotificationChannel("System", "Visible", LLNotificationFilters::includeEverything)); - mCommunicationChannel.reset(new LLCommunicationChannel("Communication", "Visible")); - mAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alerts", "alert")); - mModalAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alertmodal", "alertmodal")); - - bool ignore = gSavedSettings.getBOOL("IgnoreAllNotifications"); - LLNotifications::instance().setIgnoreAllNotifications(ignore); - if (ignore) - { - LL_INFOS() << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << LL_ENDL; - } - - - /* - LLWindowCallbacks* callbacks, - const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, - bool fullscreen, - bool clearBg, - bool disable_vsync, - bool ignore_pixel_depth, - U32 fsaa_samples) - */ - // create window + mLastMask( MASK_NONE ), + mToolStored( NULL ), + mHideCursorPermanent( false ), + mCursorHidden(false), + mIgnoreActivate( false ), + mResDirty(false), + mStatesDirty(false), + mCurrResolutionIndex(0), + mProgressView(NULL) +{ + // gKeyboard is still NULL, so it doesn't do LLWindowListener any good to + // pass its value right now. Instead, pass it a nullary function that + // will, when we later need it, return the value of gKeyboard. + // boost::lambda::var() constructs such a functor on the fly. + mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard))); + mViewerWindowListener.reset(new LLViewerWindowListener(this)); + + mSystemChannel.reset(new LLNotificationChannel("System", "Visible", LLNotificationFilters::includeEverything)); + mCommunicationChannel.reset(new LLCommunicationChannel("Communication", "Visible")); + mAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alerts", "alert")); + mModalAlertsChannel.reset(new LLNotificationsUI::LLViewerAlertHandler("VW_alertmodal", "alertmodal")); + + bool ignore = gSavedSettings.getBOOL("IgnoreAllNotifications"); + LLNotifications::instance().setIgnoreAllNotifications(ignore); + if (ignore) + { + LL_INFOS() << "NOTE: ALL NOTIFICATIONS THAT OCCUR WILL GET ADDED TO IGNORE LIST FOR LATER RUNS." << LL_ENDL; + } + + + /* + LLWindowCallbacks* callbacks, + const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, + bool fullscreen, + bool clearBg, + bool disable_vsync, + bool ignore_pixel_depth, + U32 fsaa_samples) + */ + // create window U32 max_core_count = gSavedSettings.getU32("EmulateCoreCount"); F32 max_gl_version = gSavedSettings.getF32("RenderMaxOpenGLVersion"); @@ -1875,53 +1875,53 @@ LLViewerWindow::LLViewerWindow(const Params& p) if (mWindow) mWindow->setMaxVRAMMegabytes(new_val.asInteger()); }); - - mWindow = LLWindowManager::createWindow(this, - p.title, p.name, p.x, p.y, p.width, p.height, 0, - p.fullscreen, - gHeadlessClient, - gSavedSettings.getBOOL("RenderVSyncEnable"), - !gHeadlessClient, - p.ignore_pixel_depth, - 0, + + mWindow = LLWindowManager::createWindow(this, + p.title, p.name, p.x, p.y, p.width, p.height, 0, + p.fullscreen, + gHeadlessClient, + gSavedSettings.getBOOL("RenderVSyncEnable"), + !gHeadlessClient, + p.ignore_pixel_depth, + 0, max_core_count, max_vram, max_gl_version); //don't use window level anti-aliasing - if (NULL == mWindow) - { - LLSplashScreen::update(LLTrans::getString("StartupRequireDriverUpdate")); - - LL_WARNS("Window") << "Failed to create window, to be shutting Down, be sure your graphics driver is updated." << LL_ENDL ; + if (NULL == mWindow) + { + LLSplashScreen::update(LLTrans::getString("StartupRequireDriverUpdate")); + + LL_WARNS("Window") << "Failed to create window, to be shutting Down, be sure your graphics driver is updated." << LL_ENDL ; - ms_sleep(5000) ; //wait for 5 seconds. + ms_sleep(5000) ; //wait for 5 seconds. - LLSplashScreen::update(LLTrans::getString("ShuttingDown")); + LLSplashScreen::update(LLTrans::getString("ShuttingDown")); #if LL_LINUX - LL_WARNS() << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly. See README-linux.txt for further information." - << LL_ENDL; + LL_WARNS() << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly. See README-linux.txt for further information." + << LL_ENDL; #else - LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings" - << LL_ENDL; + LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings" + << LL_ENDL; #endif LLAppViewer::instance()->fastQuit(1); - } + } else if (!LLViewerShaderMgr::sInitialized) { //immediately initialize shaders LLViewerShaderMgr::sInitialized = true; LLViewerShaderMgr::instance()->setShaders(); } - - if (!LLAppViewer::instance()->restoreErrorTrap()) - { + + if (!LLAppViewer::instance()->restoreErrorTrap()) + { // this always happens, so downgrading it to INFO - LL_INFOS("Window") << " Someone took over my signal/exception handler (post createWindow; normal)" << LL_ENDL; - } + LL_INFOS("Window") << " Someone took over my signal/exception handler (post createWindow; normal)" << LL_ENDL; + } - const bool do_not_enforce = false; - mWindow->setMinSize(p.min_width, p.min_height, do_not_enforce); // root view not set - LLCoordScreen scr; + const bool do_not_enforce = false; + mWindow->setMinSize(p.min_width, p.min_height, do_not_enforce); // root view not set + LLCoordScreen scr; mWindow->getSize(&scr); // Reset UI scale factor on first run if OS's display scaling is not 100% @@ -1934,90 +1934,90 @@ LLViewerWindow::LLViewerWindow(const Params& p) gSavedSettings.setBOOL("ResetUIScaleOnFirstRun", false); } - // Get the real window rect the window was created with (since there are various OS-dependent reasons why - // the size of a window or fullscreen context may have been adjusted slightly...) - F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor") * mWindow->getSystemUISize(), MIN_UI_SCALE, MAX_UI_SCALE); - - mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); - mDisplayScale *= ui_scale_factor; - LLUI::setScaleFactor(mDisplayScale); - - { - LLCoordWindow size; - mWindow->getSize(&size); - mWindowRectRaw.set(0, size.mY, size.mX, 0); - mWindowRectScaled.set(0, ll_round((F32)size.mY / mDisplayScale.mV[VY]), ll_round((F32)size.mX / mDisplayScale.mV[VX]), 0); - } - - LLFontManager::initClass(); - // Init font system, load default fonts and generate basic glyphs - // currently it takes aprox. 0.5 sec and we would load these fonts anyway - // before login screen. - LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), - mDisplayScale.mV[VX], - mDisplayScale.mV[VY], - gDirUtilp->getAppRODataDir()); - - // - // We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off - // stuff like AGP if we think that it'll crash the viewer. - // - LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL; - - // Initialize OpenGL Renderer - LLVertexBuffer::initClass(mWindow); - LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ; - if (!gGL.init(true)) + // Get the real window rect the window was created with (since there are various OS-dependent reasons why + // the size of a window or fullscreen context may have been adjusted slightly...) + F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor") * mWindow->getSystemUISize(), MIN_UI_SCALE, MAX_UI_SCALE); + + mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); + mDisplayScale *= ui_scale_factor; + LLUI::setScaleFactor(mDisplayScale); + + { + LLCoordWindow size; + mWindow->getSize(&size); + mWindowRectRaw.set(0, size.mY, size.mX, 0); + mWindowRectScaled.set(0, ll_round((F32)size.mY / mDisplayScale.mV[VY]), ll_round((F32)size.mX / mDisplayScale.mV[VX]), 0); + } + + LLFontManager::initClass(); + // Init font system, load default fonts and generate basic glyphs + // currently it takes aprox. 0.5 sec and we would load these fonts anyway + // before login screen. + LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), + mDisplayScale.mV[VX], + mDisplayScale.mV[VY], + gDirUtilp->getAppRODataDir()); + + // + // We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off + // stuff like AGP if we think that it'll crash the viewer. + // + LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL; + + // Initialize OpenGL Renderer + LLVertexBuffer::initClass(mWindow); + LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ; + if (!gGL.init(true)) { LLError::LLUserWarningMsg::show(LLTrans::getString("MBVideoDrvErr")); LL_ERRS() << "gGL not initialized" << LL_ENDL; } - if (LLFeatureManager::getInstance()->isSafe() - || (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion()) - || (gSavedSettings.getString("LastGPUString") != LLFeatureManager::getInstance()->getGPUString()) - || (gSavedSettings.getBOOL("ProbeHardwareOnStartup"))) - { - LLFeatureManager::getInstance()->applyRecommendedSettings(); - gSavedSettings.setBOOL("ProbeHardwareOnStartup", false); - } - - // If we crashed while initializng GL stuff last time, disable certain features - if (gSavedSettings.getBOOL("RenderInitError")) - { - mInitAlert = "DisplaySettingsNoShaders"; - LLFeatureManager::getInstance()->setGraphicsLevel(0, false); - gSavedSettings.setU32("RenderQualityPerformance", 0); - } - - // Init the image list. Must happen after GL is initialized and before the images that - // LLViewerWindow needs are requested, as well as before LLViewerMedia starts updating images. + if (LLFeatureManager::getInstance()->isSafe() + || (gSavedSettings.getS32("LastFeatureVersion") != LLFeatureManager::getInstance()->getVersion()) + || (gSavedSettings.getString("LastGPUString") != LLFeatureManager::getInstance()->getGPUString()) + || (gSavedSettings.getBOOL("ProbeHardwareOnStartup"))) + { + LLFeatureManager::getInstance()->applyRecommendedSettings(); + gSavedSettings.setBOOL("ProbeHardwareOnStartup", false); + } + + // If we crashed while initializng GL stuff last time, disable certain features + if (gSavedSettings.getBOOL("RenderInitError")) + { + mInitAlert = "DisplaySettingsNoShaders"; + LLFeatureManager::getInstance()->setGraphicsLevel(0, false); + gSavedSettings.setU32("RenderQualityPerformance", 0); + } + + // Init the image list. Must happen after GL is initialized and before the images that + // LLViewerWindow needs are requested, as well as before LLViewerMedia starts updating images. LLImageGL::initClass(mWindow, LLViewerTexture::MAX_GL_IMAGE_CATEGORY, false, gSavedSettings.getBOOL("RenderGLMultiThreadedTextures"), gSavedSettings.getBOOL("RenderGLMultiThreadedMedia")); - gTextureList.init(); - LLViewerTextureManager::init() ; - gBumpImageList.init(); - + gTextureList.init(); + LLViewerTextureManager::init() ; + gBumpImageList.init(); + // Create container for all sub-views - LLView::Params rvp; - rvp.name("root"); - rvp.rect(mWindowRectScaled); - rvp.mouse_opaque(false); - rvp.follows.flags(FOLLOWS_NONE); - mRootView = LLUICtrlFactory::create<LLRootView>(rvp); - LLUI::getInstance()->setRootView(mRootView); + LLView::Params rvp; + rvp.name("root"); + rvp.rect(mWindowRectScaled); + rvp.mouse_opaque(false); + rvp.follows.flags(FOLLOWS_NONE); + mRootView = LLUICtrlFactory::create<LLRootView>(rvp); + LLUI::getInstance()->setRootView(mRootView); - // Make avatar head look forward at start - mCurrentMousePoint.mX = getWindowWidthScaled() / 2; - mCurrentMousePoint.mY = getWindowHeightScaled() / 2; + // Make avatar head look forward at start + mCurrentMousePoint.mX = getWindowWidthScaled() / 2; + mCurrentMousePoint.mY = getWindowHeightScaled() / 2; - gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle"); - mOverlayTitle = gSavedSettings.getString("OverlayTitle"); - // Can't have spaces in settings.ini strings, so use underscores instead and convert them. - LLStringUtil::replaceChar(mOverlayTitle, '_', ' '); + gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle"); + mOverlayTitle = gSavedSettings.getString("OverlayTitle"); + // Can't have spaces in settings.ini strings, so use underscores instead and convert them. + LLStringUtil::replaceChar(mOverlayTitle, '_', ' '); - mDebugText = new LLDebugText(this); + mDebugText = new LLDebugText(this); - mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); + mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); } std::string LLViewerWindow::getLastSnapshotDir() @@ -2027,8 +2027,8 @@ std::string LLViewerWindow::getLastSnapshotDir() void LLViewerWindow::initGLDefaults() { - // RN: Need this for translation and stretch manip. - gBox.prerender(); + // RN: Need this for translation and stretch manip. + gBox.prerender(); } struct MainPanel : public LLPanel @@ -2037,161 +2037,163 @@ struct MainPanel : public LLPanel void LLViewerWindow::initBase() { - S32 height = getWindowHeightScaled(); - S32 width = getWindowWidthScaled(); + S32 height = getWindowHeightScaled(); + S32 width = getWindowWidthScaled(); - LLRect full_window(0, height, width, 0); + LLRect full_window(0, height, width, 0); - //////////////////// - // - // Set the gamma - // + //////////////////// + // + // Set the gamma + // - F32 gamma = gSavedSettings.getF32("RenderGamma"); - if (gamma != 0.0f) - { - getWindow()->setGamma(gamma); - } + F32 gamma = gSavedSettings.getF32("RenderGamma"); + if (gamma != 0.0f) + { + getWindow()->setGamma(gamma); + } - // Create global views + // Create global views - // Login screen and main_view.xml need edit menus for preferences and browser - LL_DEBUGS("AppInit") << "initializing edit menu" << LL_ENDL; - initialize_edit_menu(); + // Login screen and main_view.xml need edit menus for preferences and browser + LL_DEBUGS("AppInit") << "initializing edit menu" << LL_ENDL; + initialize_edit_menu(); LLFontGL::loadCommonFonts(); - // Create the floater view at the start so that other views can add children to it. - // (But wait to add it as a child of the root view so that it will be in front of the - // other views.) - MainPanel* main_view = new MainPanel(); - if (!main_view->buildFromFile("main_view.xml")) - { - LL_ERRS() << "Failed to initialize viewer: Viewer couldn't process file main_view.xml, " - << "if this problem happens again, please validate your installation." << LL_ENDL; - } - main_view->setShape(full_window); - getRootView()->addChild(main_view); - - // placeholder widget that controls where "world" is rendered - mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle(); - mPopupView = main_view->getChild<LLPopupView>("popup_holder"); - mHintHolder = main_view->getChild<LLView>("hint_holder")->getHandle(); - mLoginPanelHolder = main_view->getChild<LLView>("login_panel_holder")->getHandle(); - - // Create the toolbar view - // Get a pointer to the toolbar view holder - LLPanel* panel_holder = main_view->getChild<LLPanel>("toolbar_view_holder"); - // Load the toolbar view from file - gToolBarView = LLUICtrlFactory::getInstance()->createFromFile<LLToolBarView>("panel_toolbar_view.xml", panel_holder, LLDefaultChildRegistry::instance()); - if (!gToolBarView) - { - LL_ERRS() << "Failed to initialize viewer: Viewer couldn't process file panel_toolbar_view.xml, " - << "if this problem happens again, please validate your installation." << LL_ENDL; - } - gToolBarView->setShape(panel_holder->getLocalRect()); - // Hide the toolbars for the moment: we'll make them visible after logging in world (see LLViewerWindow::initWorldUI()) - gToolBarView->setVisible(false); - - // Constrain floaters to inside the menu and status bar regions. - gFloaterView = main_view->getChild<LLFloaterView>("Floater View"); - for (S32 i = 0; i < LLToolBarEnums::TOOLBAR_COUNT; ++i) - { - LLToolBar * toolbarp = gToolBarView->getToolbar((LLToolBarEnums::EToolBarLocation)i); - if (toolbarp) - { - toolbarp->getCenterLayoutPanel()->setReshapeCallback(boost::bind(&LLFloaterView::setToolbarRect, gFloaterView, _1, _2)); - } - } - gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle()); - gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View"); - - // Console - llassert( !gConsole ); - LLConsole::Params cp; - cp.name("console"); - cp.max_lines(gSavedSettings.getS32("ConsoleBufferSize")); - cp.rect(getChatConsoleRect()); - cp.persist_time(gSavedSettings.getF32("ChatPersistTime")); - cp.font_size_index(gSavedSettings.getS32("ChatFontSize")); - cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); - gConsole = LLUICtrlFactory::create<LLConsole>(cp); - getRootView()->addChild(gConsole); - - // optionally forward warnings to chat console/chat floater - // for qa runs and dev builds + // Create the floater view at the start so that other views can add children to it. + // (But wait to add it as a child of the root view so that it will be in front of the + // other views.) + MainPanel* main_view = new MainPanel(); + if (!main_view->buildFromFile("main_view.xml")) + { + LL_ERRS() << "Failed to initialize viewer: Viewer couldn't process file main_view.xml, " + << "if this problem happens again, please validate your installation." << LL_ENDL; + } + main_view->setShape(full_window); + getRootView()->addChild(main_view); + + // placeholder widget that controls where "world" is rendered + mWorldViewPlaceholder = main_view->getChildView("world_view_rect")->getHandle(); + mPopupView = main_view->getChild<LLPopupView>("popup_holder"); + mHintHolder = main_view->getChild<LLView>("hint_holder")->getHandle(); + mLoginPanelHolder = main_view->getChild<LLView>("login_panel_holder")->getHandle(); + + // Create the toolbar view + // Get a pointer to the toolbar view holder + LLPanel* panel_holder = main_view->getChild<LLPanel>("toolbar_view_holder"); + // Load the toolbar view from file + gToolBarView = LLUICtrlFactory::getInstance()->createFromFile<LLToolBarView>("panel_toolbar_view.xml", panel_holder, LLDefaultChildRegistry::instance()); + if (!gToolBarView) + { + LL_ERRS() << "Failed to initialize viewer: Viewer couldn't process file panel_toolbar_view.xml, " + << "if this problem happens again, please validate your installation." << LL_ENDL; + } + gToolBarView->setShape(panel_holder->getLocalRect()); + // Hide the toolbars for the moment: we'll make them visible after logging in world (see LLViewerWindow::initWorldUI()) + gToolBarView->setVisible(false); + + // Constrain floaters to inside the menu and status bar regions. + gFloaterView = main_view->getChild<LLFloaterView>("Floater View"); + for (S32 i = 0; i < LLToolBarEnums::TOOLBAR_COUNT; ++i) + { + LLToolBar * toolbarp = gToolBarView->getToolbar((LLToolBarEnums::EToolBarLocation)i); + if (toolbarp) + { + toolbarp->getCenterLayoutPanel()->setReshapeCallback(boost::bind(&LLFloaterView::setToolbarRect, gFloaterView, _1, _2)); + } + } + gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle()); + gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View"); + + const F32 CHAT_PERSIST_TIME = 20.f; + + // Console + llassert( !gConsole ); + LLConsole::Params cp; + cp.name("console"); + cp.max_lines(gSavedSettings.getS32("ConsoleBufferSize")); + cp.rect(getChatConsoleRect()); + cp.persist_time(CHAT_PERSIST_TIME); + cp.font_size_index(gSavedSettings.getS32("ChatFontSize")); + cp.follows.flags(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM); + gConsole = LLUICtrlFactory::create<LLConsole>(cp); + getRootView()->addChild(gConsole); + + // optionally forward warnings to chat console/chat floater + // for qa runs and dev builds #if !LL_RELEASE_FOR_DOWNLOAD - RecordToChatConsole::getInstance()->startRecorder(); + RecordToChatConsole::getInstance()->startRecorder(); #else - if(gSavedSettings.getBOOL("QAMode")) - { - RecordToChatConsole::getInstance()->startRecorder(); - } + if(gSavedSettings.getBOOL("QAMode")) + { + RecordToChatConsole::getInstance()->startRecorder(); + } #endif - gDebugView = getRootView()->getChild<LLDebugView>("DebugView"); - gDebugView->init(); - gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view"); + gDebugView = getRootView()->getChild<LLDebugView>("DebugView"); + gDebugView->init(); + gToolTipView = getRootView()->getChild<LLToolTipView>("tooltip view"); - // Initialize do not disturb response message when logged in - LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initDoNotDisturbResponse)); + // Initialize do not disturb response message when logged in + LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLFloaterPreference::initDoNotDisturbResponse)); - // Add the progress bar view (startup view), which overrides everything - mProgressView = getRootView()->findChild<LLProgressView>("progress_view"); - setShowProgress(false); - setProgressCancelButtonVisible(false); + // Add the progress bar view (startup view), which overrides everything + mProgressView = getRootView()->findChild<LLProgressView>("progress_view"); + setShowProgress(false); + setProgressCancelButtonVisible(false); - gMenuHolder = getRootView()->getChild<LLViewerMenuHolderGL>("Menu Holder"); - LLMenuGL::sMenuContainer = gMenuHolder; + gMenuHolder = getRootView()->getChild<LLViewerMenuHolderGL>("Menu Holder"); + LLMenuGL::sMenuContainer = gMenuHolder; } void LLViewerWindow::initWorldUI() { - if (gNonInteractive) - { - gIMMgr = LLIMMgr::getInstance(); - LLNavigationBar::getInstance(); - gFloaterView->pushVisibleAll(false); - return; - } - - S32 height = mRootView->getRect().getHeight(); - S32 width = mRootView->getRect().getWidth(); - LLRect full_window(0, height, width, 0); - - - gIMMgr = LLIMMgr::getInstance(); - - //getRootView()->sendChildToFront(gFloaterView); - //getRootView()->sendChildToFront(gSnapshotFloaterView); - - if (!gNonInteractive) - { - LLPanel* chiclet_container = getRootView()->getChild<LLPanel>("chiclet_container"); - LLChicletBar* chiclet_bar = LLChicletBar::getInstance(); - chiclet_bar->setShape(chiclet_container->getLocalRect()); - chiclet_bar->setFollowsAll(); - chiclet_container->addChild(chiclet_bar); - chiclet_container->setVisible(true); - } - - LLRect morph_view_rect = full_window; - morph_view_rect.stretch( -STATUS_BAR_HEIGHT ); - morph_view_rect.mTop = full_window.mTop - 32; - LLMorphView::Params mvp; - mvp.name("MorphView"); - mvp.rect(morph_view_rect); - mvp.visible(false); - gMorphView = LLUICtrlFactory::create<LLMorphView>(mvp); - getRootView()->addChild(gMorphView); - - LLWorldMapView::initClass(); - - // Force gFloaterWorldMap to initialize - LLFloaterReg::getInstance("world_map"); - - // Force gFloaterTools to initialize - LLFloaterReg::getInstance("build"); + if (gNonInteractive) + { + gIMMgr = LLIMMgr::getInstance(); + LLNavigationBar::getInstance(); + gFloaterView->pushVisibleAll(false); + return; + } + + S32 height = mRootView->getRect().getHeight(); + S32 width = mRootView->getRect().getWidth(); + LLRect full_window(0, height, width, 0); + + + gIMMgr = LLIMMgr::getInstance(); + + //getRootView()->sendChildToFront(gFloaterView); + //getRootView()->sendChildToFront(gSnapshotFloaterView); + + if (!gNonInteractive) + { + LLPanel* chiclet_container = getRootView()->getChild<LLPanel>("chiclet_container"); + LLChicletBar* chiclet_bar = LLChicletBar::getInstance(); + chiclet_bar->setShape(chiclet_container->getLocalRect()); + chiclet_bar->setFollowsAll(); + chiclet_container->addChild(chiclet_bar); + chiclet_container->setVisible(true); + } + + LLRect morph_view_rect = full_window; + morph_view_rect.stretch( -STATUS_BAR_HEIGHT ); + morph_view_rect.mTop = full_window.mTop - 32; + LLMorphView::Params mvp; + mvp.name("MorphView"); + mvp.rect(morph_view_rect); + mvp.visible(false); + gMorphView = LLUICtrlFactory::create<LLMorphView>(mvp); + getRootView()->addChild(gMorphView); + + LLWorldMapView::initClass(); + + // Force gFloaterWorldMap to initialize + LLFloaterReg::getInstance("world_map"); + + // Force gFloaterTools to initialize + LLFloaterReg::getInstance("build"); LLNavigationBar* navbar = LLNavigationBar::getInstance(); if (!gStatusBar) @@ -2233,207 +2235,207 @@ void LLViewerWindow::initWorldUI() } - // Top Info bar - LLPanel* topinfo_bar_container = getRootView()->getChild<LLPanel>("topinfo_bar_container"); - LLPanelTopInfoBar* topinfo_bar = LLPanelTopInfoBar::getInstance(); - - topinfo_bar->setShape(topinfo_bar_container->getLocalRect()); - - topinfo_bar_container->addChild(topinfo_bar); - topinfo_bar_container->setVisible(true); - - if (!gSavedSettings.getBOOL("ShowMiniLocationPanel")) - { - topinfo_bar->setVisible(false); - } - - if ( gHUDView == NULL ) - { - LLRect hud_rect = full_window; - hud_rect.mBottom += 50; - if (gMenuBarView && gMenuBarView->isInVisibleChain()) - { - hud_rect.mTop -= gMenuBarView->getRect().getHeight(); - } - gHUDView = new LLHUDView(hud_rect); - getRootView()->addChild(gHUDView); - getRootView()->sendChildToBack(gHUDView); - } - - LLPanel* panel_ssf_container = getRootView()->getChild<LLPanel>("state_management_buttons_container"); - - LLPanelStandStopFlying* panel_stand_stop_flying = LLPanelStandStopFlying::getInstance(); - panel_ssf_container->addChild(panel_stand_stop_flying); - - LLPanelHideBeacon* panel_hide_beacon = LLPanelHideBeacon::getInstance(); - panel_ssf_container->addChild(panel_hide_beacon); - - panel_ssf_container->setVisible(true); - - LLMenuOptionPathfindingRebakeNavmesh::getInstance()->initialize(); - - // Load and make the toolbars visible - // Note: we need to load the toolbars only *after* the user is logged in and IW - if (gToolBarView) - { - gToolBarView->loadToolbars(); - gToolBarView->setVisible(true); - } - - if (!gNonInteractive) - { - LLMediaCtrl* destinations = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents"); - if (destinations) - { - destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - std::string url = gSavedSettings.getString("DestinationGuideURL"); - url = LLWeb::expandURLSubstitutions(url, LLSD()); - destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); - } - LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents"); - if (avatar_picker) - { - avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); - std::string url = gSavedSettings.getString("AvatarPickerURL"); - url = LLWeb::expandURLSubstitutions(url, LLSD()); - avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML); - } - } + // Top Info bar + LLPanel* topinfo_bar_container = getRootView()->getChild<LLPanel>("topinfo_bar_container"); + LLPanelTopInfoBar* topinfo_bar = LLPanelTopInfoBar::getInstance(); + + topinfo_bar->setShape(topinfo_bar_container->getLocalRect()); + + topinfo_bar_container->addChild(topinfo_bar); + topinfo_bar_container->setVisible(true); + + if (!gSavedSettings.getBOOL("ShowMiniLocationPanel")) + { + topinfo_bar->setVisible(false); + } + + if ( gHUDView == NULL ) + { + LLRect hud_rect = full_window; + hud_rect.mBottom += 50; + if (gMenuBarView && gMenuBarView->isInVisibleChain()) + { + hud_rect.mTop -= gMenuBarView->getRect().getHeight(); + } + gHUDView = new LLHUDView(hud_rect); + getRootView()->addChild(gHUDView); + getRootView()->sendChildToBack(gHUDView); + } + + LLPanel* panel_ssf_container = getRootView()->getChild<LLPanel>("state_management_buttons_container"); + + LLPanelStandStopFlying* panel_stand_stop_flying = LLPanelStandStopFlying::getInstance(); + panel_ssf_container->addChild(panel_stand_stop_flying); + + LLPanelHideBeacon* panel_hide_beacon = LLPanelHideBeacon::getInstance(); + panel_ssf_container->addChild(panel_hide_beacon); + + panel_ssf_container->setVisible(true); + + LLMenuOptionPathfindingRebakeNavmesh::getInstance()->initialize(); + + // Load and make the toolbars visible + // Note: we need to load the toolbars only *after* the user is logged in and IW + if (gToolBarView) + { + gToolBarView->loadToolbars(); + gToolBarView->setVisible(true); + } + + if (!gNonInteractive) + { + LLMediaCtrl* destinations = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents"); + if (destinations) + { + destinations->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); + std::string url = gSavedSettings.getString("DestinationGuideURL"); + url = LLWeb::expandURLSubstitutions(url, LLSD()); + destinations->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + } + LLMediaCtrl* avatar_picker = LLFloaterReg::getInstance("avatar")->findChild<LLMediaCtrl>("avatar_picker_contents"); + if (avatar_picker) + { + avatar_picker->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL")); + std::string url = gSavedSettings.getString("AvatarPickerURL"); + url = LLWeb::expandURLSubstitutions(url, LLSD()); + avatar_picker->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + } + } } // Destroy the UI void LLViewerWindow::shutdownViews() { - // clean up warning logger - RecordToChatConsole::getInstance()->stopRecorder(); - LL_INFOS() << "Warning logger is cleaned." << LL_ENDL ; - - gFocusMgr.unlockFocus(); - gFocusMgr.setMouseCapture(NULL); - gFocusMgr.setKeyboardFocus(NULL); - gFocusMgr.setTopCtrl(NULL); - if (mWindow) - { - mWindow->allowLanguageTextInput(NULL, false); - } - - delete mDebugText; - mDebugText = NULL; - - LL_INFOS() << "DebugText deleted." << LL_ENDL ; - - // Cleanup global views - if (gMorphView) - { - gMorphView->setVisible(false); - } - LL_INFOS() << "Global views cleaned." << LL_ENDL ; - - LLNotificationsUI::LLToast::cleanupToasts(); - LL_INFOS() << "Leftover toast cleaned up." << LL_ENDL; - - // DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open - // will crump with LL_ERRS. - LLModalDialog::shutdownModals(); - LL_INFOS() << "LLModalDialog shut down." << LL_ENDL; - - // destroy the nav bar, not currently part of gViewerWindow - // *TODO: Make LLNavigationBar part of gViewerWindow - LLNavigationBar::deleteSingleton(); - LL_INFOS() << "LLNavigationBar destroyed." << LL_ENDL ; - - // destroy menus after instantiating navbar above, as it needs - // access to gMenuHolder - cleanup_menus(); - LL_INFOS() << "menus destroyed." << LL_ENDL ; - - view_listener_t::cleanup(); - LL_INFOS() << "view listeners destroyed." << LL_ENDL ; - - // Clean up pointers that are going to be invalid. (todo: check sMenuContainer) - mProgressView = NULL; - mPopupView = NULL; - - // Delete all child views. - delete mRootView; - mRootView = NULL; - LL_INFOS() << "RootView deleted." << LL_ENDL ; - - LLMenuOptionPathfindingRebakeNavmesh::getInstance()->quit(); - - // Automatically deleted as children of mRootView. Fix the globals. - gStatusBar = NULL; - gIMMgr = NULL; - gToolTipView = NULL; - - gToolBarView = NULL; - gFloaterView = NULL; - gMorphView = NULL; - - gHUDView = NULL; + // clean up warning logger + RecordToChatConsole::getInstance()->stopRecorder(); + LL_INFOS() << "Warning logger is cleaned." << LL_ENDL ; + + gFocusMgr.unlockFocus(); + gFocusMgr.setMouseCapture(NULL); + gFocusMgr.setKeyboardFocus(NULL); + gFocusMgr.setTopCtrl(NULL); + if (mWindow) + { + mWindow->allowLanguageTextInput(NULL, false); + } + + delete mDebugText; + mDebugText = NULL; + + LL_INFOS() << "DebugText deleted." << LL_ENDL ; + + // Cleanup global views + if (gMorphView) + { + gMorphView->setVisible(false); + } + LL_INFOS() << "Global views cleaned." << LL_ENDL ; + + LLNotificationsUI::LLToast::cleanupToasts(); + LL_INFOS() << "Leftover toast cleaned up." << LL_ENDL; + + // DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open + // will crump with LL_ERRS. + LLModalDialog::shutdownModals(); + LL_INFOS() << "LLModalDialog shut down." << LL_ENDL; + + // destroy the nav bar, not currently part of gViewerWindow + // *TODO: Make LLNavigationBar part of gViewerWindow + LLNavigationBar::deleteSingleton(); + LL_INFOS() << "LLNavigationBar destroyed." << LL_ENDL ; + + // destroy menus after instantiating navbar above, as it needs + // access to gMenuHolder + cleanup_menus(); + LL_INFOS() << "menus destroyed." << LL_ENDL ; + + view_listener_t::cleanup(); + LL_INFOS() << "view listeners destroyed." << LL_ENDL ; + + // Clean up pointers that are going to be invalid. (todo: check sMenuContainer) + mProgressView = NULL; + mPopupView = NULL; + + // Delete all child views. + delete mRootView; + mRootView = NULL; + LL_INFOS() << "RootView deleted." << LL_ENDL ; + + LLMenuOptionPathfindingRebakeNavmesh::getInstance()->quit(); + + // Automatically deleted as children of mRootView. Fix the globals. + gStatusBar = NULL; + gIMMgr = NULL; + gToolTipView = NULL; + + gToolBarView = NULL; + gFloaterView = NULL; + gMorphView = NULL; + + gHUDView = NULL; } void LLViewerWindow::shutdownGL() { - //-------------------------------------------------------- - // Shutdown GL cleanly. Order is very important here. - //-------------------------------------------------------- - LLFontGL::destroyDefaultFonts(); - SUBSYSTEM_CLEANUP(LLFontManager); - stop_glerror(); + //-------------------------------------------------------- + // Shutdown GL cleanly. Order is very important here. + //-------------------------------------------------------- + LLFontGL::destroyDefaultFonts(); + SUBSYSTEM_CLEANUP(LLFontManager); + stop_glerror(); + + gSky.cleanup(); + stop_glerror(); - gSky.cleanup(); - stop_glerror(); + LL_INFOS() << "Cleaning up pipeline" << LL_ENDL; + gPipeline.cleanup(); + stop_glerror(); - LL_INFOS() << "Cleaning up pipeline" << LL_ENDL; - gPipeline.cleanup(); - stop_glerror(); + //MUST clean up pipeline before cleaning up wearables + LL_INFOS() << "Cleaning up wearables" << LL_ENDL; + LLWearableList::instance().cleanup() ; - //MUST clean up pipeline before cleaning up wearables - LL_INFOS() << "Cleaning up wearables" << LL_ENDL; - LLWearableList::instance().cleanup() ; + gTextureList.shutdown(); + stop_glerror(); - gTextureList.shutdown(); - stop_glerror(); + gBumpImageList.shutdown(); + stop_glerror(); - gBumpImageList.shutdown(); - stop_glerror(); + LLWorldMapView::cleanupTextures(); - LLWorldMapView::cleanupTextures(); + LLViewerTextureManager::cleanup() ; + SUBSYSTEM_CLEANUP(LLImageGL) ; - LLViewerTextureManager::cleanup() ; - SUBSYSTEM_CLEANUP(LLImageGL) ; - - LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ; + LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ; - LL_INFOS() << "Cleaning up select manager" << LL_ENDL; - LLSelectMgr::getInstance()->cleanup(); + LL_INFOS() << "Cleaning up select manager" << LL_ENDL; + LLSelectMgr::getInstance()->cleanup(); - LL_INFOS() << "Stopping GL during shutdown" << LL_ENDL; - stopGL(false); - stop_glerror(); + LL_INFOS() << "Stopping GL during shutdown" << LL_ENDL; + stopGL(false); + stop_glerror(); - gGL.shutdown(); + gGL.shutdown(); - SUBSYSTEM_CLEANUP(LLVertexBuffer); + SUBSYSTEM_CLEANUP(LLVertexBuffer); - LL_INFOS() << "LLVertexBuffer cleaned." << LL_ENDL ; + LL_INFOS() << "LLVertexBuffer cleaned." << LL_ENDL ; } // shutdownViews() and shutdownGL() need to be called first LLViewerWindow::~LLViewerWindow() { - LL_INFOS() << "Destroying Window" << LL_ENDL; - destroyWindow(); + LL_INFOS() << "Destroying Window" << LL_ENDL; + destroyWindow(); - delete mDebugText; - mDebugText = NULL; + delete mDebugText; + mDebugText = NULL; - if (LLViewerShaderMgr::sInitialized) - { - LLViewerShaderMgr::releaseInstance(); - LLViewerShaderMgr::sInitialized = false; - } + if (LLViewerShaderMgr::sInitialized) + { + LLViewerShaderMgr::releaseInstance(); + LLViewerShaderMgr::sInitialized = false; + } mMaxVRAMControlConnection.disconnect(); } @@ -2441,157 +2443,157 @@ LLViewerWindow::~LLViewerWindow() void LLViewerWindow::setCursor( ECursorType c ) { - mWindow->setCursor( c ); + mWindow->setCursor( c ); } void LLViewerWindow::showCursor() { - mWindow->showCursor(); - - mCursorHidden = false; + mWindow->showCursor(); + + mCursorHidden = false; } void LLViewerWindow::hideCursor() { - // And hide the cursor - mWindow->hideCursor(); + // And hide the cursor + mWindow->hideCursor(); - mCursorHidden = true; + mCursorHidden = true; } void LLViewerWindow::sendShapeToSim() { - LLMessageSystem* msg = gMessageSystem; - if(!msg) return; - msg->newMessageFast(_PREHASH_AgentHeightWidth); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode); - msg->nextBlockFast(_PREHASH_HeightWidthBlock); - msg->addU32Fast(_PREHASH_GenCounter, 0); - U16 height16 = (U16) mWorldViewRectRaw.getHeight(); - U16 width16 = (U16) mWorldViewRectRaw.getWidth(); - msg->addU16Fast(_PREHASH_Height, height16); - msg->addU16Fast(_PREHASH_Width, width16); - gAgent.sendReliableMessage(); + LLMessageSystem* msg = gMessageSystem; + if(!msg) return; + msg->newMessageFast(_PREHASH_AgentHeightWidth); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode); + msg->nextBlockFast(_PREHASH_HeightWidthBlock); + msg->addU32Fast(_PREHASH_GenCounter, 0); + U16 height16 = (U16) mWorldViewRectRaw.getHeight(); + U16 width16 = (U16) mWorldViewRectRaw.getWidth(); + msg->addU16Fast(_PREHASH_Height, height16); + msg->addU16Fast(_PREHASH_Width, width16); + gAgent.sendReliableMessage(); } // Must be called after window is created to set up agent // camera variables and UI variables. void LLViewerWindow::reshape(S32 width, S32 height) { - // Destroying the window at quit time generates spurious - // reshape messages. We don't care about these, and we - // don't want to send messages because the message system - // may have been destructed. - if (!LLApp::isExiting()) - { - gWindowResized = true; + // Destroying the window at quit time generates spurious + // reshape messages. We don't care about these, and we + // don't want to send messages because the message system + // may have been destructed. + if (!LLApp::isExiting()) + { + gWindowResized = true; - // update our window rectangle - mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width; - mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height; + // update our window rectangle + mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width; + mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height; - //glViewport(0, 0, width, height ); + //glViewport(0, 0, width, height ); LLViewerCamera * camera = LLViewerCamera::getInstance(); // simpleton, might not exist - if (height > 0 && camera) - { + if (height > 0 && camera) + { camera->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); camera->setAspect( getWorldViewAspectRatio() ); - } + } + + calcDisplayScale(); - calcDisplayScale(); - - bool display_scale_changed = mDisplayScale != LLUI::getScaleFactor(); - LLUI::setScaleFactor(mDisplayScale); + bool display_scale_changed = mDisplayScale != LLUI::getScaleFactor(); + LLUI::setScaleFactor(mDisplayScale); - // update our window rectangle - mWindowRectScaled.mRight = mWindowRectScaled.mLeft + ll_round((F32)width / mDisplayScale.mV[VX]); - mWindowRectScaled.mTop = mWindowRectScaled.mBottom + ll_round((F32)height / mDisplayScale.mV[VY]); + // update our window rectangle + mWindowRectScaled.mRight = mWindowRectScaled.mLeft + ll_round((F32)width / mDisplayScale.mV[VX]); + mWindowRectScaled.mTop = mWindowRectScaled.mBottom + ll_round((F32)height / mDisplayScale.mV[VY]); - setup2DViewport(); + setup2DViewport(); - // Inform lower views of the change - // round up when converting coordinates to make sure there are no gaps at edge of window - LLView::sForceReshape = display_scale_changed; - mRootView->reshape(llceil((F32)width / mDisplayScale.mV[VX]), llceil((F32)height / mDisplayScale.mV[VY])); + // Inform lower views of the change + // round up when converting coordinates to make sure there are no gaps at edge of window + LLView::sForceReshape = display_scale_changed; + mRootView->reshape(llceil((F32)width / mDisplayScale.mV[VX]), llceil((F32)height / mDisplayScale.mV[VY])); if (display_scale_changed) { // Needs only a 'scale change' update, everything else gets handled by LLLayoutStack::updateClass() LLPanelLogin::reshapePanel(); } - LLView::sForceReshape = false; + LLView::sForceReshape = false; - // clear font width caches - if (display_scale_changed) - { - LLHUDObject::reshapeAll(); - } + // clear font width caches + if (display_scale_changed) + { + LLHUDObject::reshapeAll(); + } - sendShapeToSim(); + sendShapeToSim(); - // store new settings for the mode we are in, regardless - bool maximized = mWindow->getMaximized(); - gSavedSettings.setBOOL("WindowMaximized", maximized); + // store new settings for the mode we are in, regardless + bool maximized = mWindow->getMaximized(); + gSavedSettings.setBOOL("WindowMaximized", maximized); - if (!maximized) - { - U32 min_window_width=gSavedSettings.getU32("MinWindowWidth"); - U32 min_window_height=gSavedSettings.getU32("MinWindowHeight"); - // tell the OS specific window code about min window size - mWindow->setMinSize(min_window_width, min_window_height); + if (!maximized) + { + U32 min_window_width=gSavedSettings.getU32("MinWindowWidth"); + U32 min_window_height=gSavedSettings.getU32("MinWindowHeight"); + // tell the OS specific window code about min window size + mWindow->setMinSize(min_window_width, min_window_height); - LLCoordScreen window_rect; - if (!gNonInteractive && mWindow->getSize(&window_rect)) - { - // Only save size if not maximized - gSavedSettings.setU32("WindowWidth", window_rect.mX); - gSavedSettings.setU32("WindowHeight", window_rect.mY); - } - } + LLCoordScreen window_rect; + if (!gNonInteractive && mWindow->getSize(&window_rect)) + { + // Only save size if not maximized + gSavedSettings.setU32("WindowWidth", window_rect.mX); + gSavedSettings.setU32("WindowHeight", window_rect.mY); + } + } - sample(LLStatViewer::WINDOW_WIDTH, width); - sample(LLStatViewer::WINDOW_HEIGHT, height); + sample(LLStatViewer::WINDOW_WIDTH, width); + sample(LLStatViewer::WINDOW_HEIGHT, height); - LLLayoutStack::updateClass(); - } + LLLayoutStack::updateClass(); + } } // Hide normal UI when a logon fails void LLViewerWindow::setNormalControlsVisible( bool visible ) { - if(LLChicletBar::instanceExists()) - { - LLChicletBar::getInstance()->setVisible(visible); - LLChicletBar::getInstance()->setEnabled(visible); - } - - if ( gMenuBarView ) - { - gMenuBarView->setVisible( visible ); - gMenuBarView->setEnabled( visible ); - - // ...and set the menu color appropriately. - setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, - LLGridManager::getInstance()->isInProductionGrid()); - } - - if ( gStatusBar ) - { - gStatusBar->setVisible( visible ); - gStatusBar->setEnabled( visible ); - } - - LLNavigationBar* navbarp = LLUI::getInstance()->getRootView()->findChild<LLNavigationBar>("navigation_bar"); - if (navbarp) - { - // when it's time to show navigation bar we need to ensure that the user wants to see it - // i.e. ShowNavbarNavigationPanel option is true - navbarp->setVisible( visible && gSavedSettings.getBOOL("ShowNavbarNavigationPanel") ); - } + if(LLChicletBar::instanceExists()) + { + LLChicletBar::getInstance()->setVisible(visible); + LLChicletBar::getInstance()->setEnabled(visible); + } + + if ( gMenuBarView ) + { + gMenuBarView->setVisible( visible ); + gMenuBarView->setEnabled( visible ); + + // ...and set the menu color appropriately. + setMenuBackgroundColor(gAgent.getGodLevel() > GOD_NOT, + LLGridManager::getInstance()->isInProductionGrid()); + } + + if ( gStatusBar ) + { + gStatusBar->setVisible( visible ); + gStatusBar->setEnabled( visible ); + } + + LLNavigationBar* navbarp = LLUI::getInstance()->getRootView()->findChild<LLNavigationBar>("navigation_bar"); + if (navbarp) + { + // when it's time to show navigation bar we need to ensure that the user wants to see it + // i.e. ShowNavbarNavigationPanel option is true + navbarp->setVisible( visible && gSavedSettings.getBOOL("ShowNavbarNavigationPanel") ); + } } void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) @@ -2599,17 +2601,17 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) LLSD args; LLColor4 new_bg_color; - // god more important than project, proj more important than grid - if ( god_mode ) + // god more important than project, proj more important than grid + if ( god_mode ) { - if ( LLGridManager::getInstance()->isInProductionGrid() ) - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" ); - } - else - { - new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" ); - } + if ( LLGridManager::getInstance()->isInProductionGrid() ) + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuBarGodBgColor" ); + } + else + { + new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionGodBgColor" ); + } } else { @@ -2622,24 +2624,24 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) case LLVersionInfo::PROJECT_VIEWER: new_bg_color = LLUIColorTable::instance().getColor( "MenuBarProjectBgColor" ); break; - + case LLVersionInfo::BETA_VIEWER: new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBetaBgColor" ); break; - + case LLVersionInfo::RELEASE_VIEWER: if(!LLGridManager::getInstance()->isInProductionGrid()) { new_bg_color = LLUIColorTable::instance().getColor( "MenuNonProductionBgColor" ); } - else + else { new_bg_color = LLUIColorTable::instance().getColor( "MenuBarBgColor" ); } break; } } - + if(gMenuBarView) { gMenuBarView->setBackgroundColor( new_bg_color ); @@ -2654,144 +2656,144 @@ void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid) void LLViewerWindow::drawDebugText() { gUIProgram.bind(); - gGL.color4f(1,1,1,1); - gGL.pushMatrix(); - gGL.pushUIMatrix(); - { - // scale view by UI global scale factor and aspect ratio correction factor - gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); - mDebugText->draw(); - } - gGL.popUIMatrix(); - gGL.popMatrix(); + gGL.color4f(1,1,1,1); + gGL.pushMatrix(); + gGL.pushUIMatrix(); + { + // scale view by UI global scale factor and aspect ratio correction factor + gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); + mDebugText->draw(); + } + gGL.popUIMatrix(); + gGL.popMatrix(); - gGL.flush(); - gUIProgram.unbind(); + gGL.flush(); + gUIProgram.unbind(); } void LLViewerWindow::draw() { - + //#if LL_DEBUG - LLView::sIsDrawing = true; + LLView::sIsDrawing = true; //#endif - stop_glerror(); - - LLUI::setLineWidth(1.f); - - LLUI::setLineWidth(1.f); - // Reset any left-over transforms - gGL.matrixMode(LLRender::MM_MODELVIEW); - - gGL.loadIdentity(); - - //S32 screen_x, screen_y; - - if (!gSavedSettings.getBOOL("RenderUIBuffer")) - { - LLView::sDirtyRect = getWindowRectScaled(); - } - - // HACK for timecode debugging - if (gSavedSettings.getBOOL("DisplayTimecode")) - { - // draw timecode block - std::string text; - - gGL.loadIdentity(); - - microsecondsToTimecodeString(gFrameTime,text); - const LLFontGL* font = LLFontGL::getFontSansSerif(); - font->renderUTF8(text, 0, - ll_round((getWindowWidthScaled()/2)-100.f), - ll_round((getWindowHeightScaled()-60.f)), - LLColor4( 1.f, 1.f, 1.f, 1.f ), - LLFontGL::LEFT, LLFontGL::TOP); - } - - // Draw all nested UI views. - // No translation needed, this view is glued to 0,0 - - gUIProgram.bind(); + stop_glerror(); + + LLUI::setLineWidth(1.f); + + LLUI::setLineWidth(1.f); + // Reset any left-over transforms + gGL.matrixMode(LLRender::MM_MODELVIEW); + + gGL.loadIdentity(); + + //S32 screen_x, screen_y; + + if (!gSavedSettings.getBOOL("RenderUIBuffer")) + { + LLView::sDirtyRect = getWindowRectScaled(); + } + + // HACK for timecode debugging + if (gSavedSettings.getBOOL("DisplayTimecode")) + { + // draw timecode block + std::string text; + + gGL.loadIdentity(); + + microsecondsToTimecodeString(gFrameTime,text); + const LLFontGL* font = LLFontGL::getFontSansSerif(); + font->renderUTF8(text, 0, + ll_round((getWindowWidthScaled()/2)-100.f), + ll_round((getWindowHeightScaled()-60.f)), + LLColor4( 1.f, 1.f, 1.f, 1.f ), + LLFontGL::LEFT, LLFontGL::TOP); + } + + // Draw all nested UI views. + // No translation needed, this view is glued to 0,0 + + gUIProgram.bind(); gGL.color4f(1, 1, 1, 1); - gGL.pushMatrix(); - LLUI::pushMatrix(); - { - - // scale view by UI global scale factor and aspect ratio correction factor - gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); - - LLVector2 old_scale_factor = LLUI::getScaleFactor(); - // apply camera zoom transform (for high res screenshots) - F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); - S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); - if (zoom_factor > 1.f) - { - //decompose subregion number to x and y values - int pos_y = sub_region / llceil(zoom_factor); - int pos_x = sub_region - (pos_y*llceil(zoom_factor)); - // offset for this tile - gGL.translatef((F32)getWindowWidthScaled() * -(F32)pos_x, - (F32)getWindowHeightScaled() * -(F32)pos_y, - 0.f); - gGL.scalef(zoom_factor, zoom_factor, 1.f); - LLUI::getScaleFactor() *= zoom_factor; - } - - // Draw tool specific overlay on world - LLToolMgr::getInstance()->getCurrentTool()->draw(); - - if( gAgentCamera.cameraMouselook() || LLFloaterCamera::inFreeCameraMode() ) - { - drawMouselookInstructions(); - stop_glerror(); - } - - // Draw all nested UI views. - // No translation needed, this view is glued to 0,0 - mRootView->draw(); - - if (LLView::sDebugRects) - { - gToolTipView->drawStickyRect(); - } - - // Draw optional on-top-of-everyone view - LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); - if (top_ctrl && top_ctrl->getVisible()) - { - S32 screen_x, screen_y; - top_ctrl->localPointToScreen(0, 0, &screen_x, &screen_y); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - LLUI::pushMatrix(); - LLUI::translate( (F32) screen_x, (F32) screen_y); - top_ctrl->draw(); - LLUI::popMatrix(); - } - - - if( gShowOverlayTitle && !mOverlayTitle.empty() ) - { - // Used for special titles such as "Second Life - Special E3 2003 Beta" - const S32 DIST_FROM_TOP = 20; - LLFontGL::getFontSansSerifBig()->renderUTF8( - mOverlayTitle, 0, - ll_round( getWindowWidthScaled() * 0.5f), - getWindowHeightScaled() - DIST_FROM_TOP, - LLColor4(1, 1, 1, 0.4f), - LLFontGL::HCENTER, LLFontGL::TOP); - } - - LLUI::setScaleFactor(old_scale_factor); - } - LLUI::popMatrix(); - gGL.popMatrix(); - - gUIProgram.unbind(); - - LLView::sIsDrawing = false; + gGL.pushMatrix(); + LLUI::pushMatrix(); + { + + // scale view by UI global scale factor and aspect ratio correction factor + gGL.scaleUI(mDisplayScale.mV[VX], mDisplayScale.mV[VY], 1.f); + + LLVector2 old_scale_factor = LLUI::getScaleFactor(); + // apply camera zoom transform (for high res screenshots) + F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); + S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); + if (zoom_factor > 1.f) + { + //decompose subregion number to x and y values + int pos_y = sub_region / llceil(zoom_factor); + int pos_x = sub_region - (pos_y*llceil(zoom_factor)); + // offset for this tile + gGL.translatef((F32)getWindowWidthScaled() * -(F32)pos_x, + (F32)getWindowHeightScaled() * -(F32)pos_y, + 0.f); + gGL.scalef(zoom_factor, zoom_factor, 1.f); + LLUI::getScaleFactor() *= zoom_factor; + } + + // Draw tool specific overlay on world + LLToolMgr::getInstance()->getCurrentTool()->draw(); + + if( gAgentCamera.cameraMouselook() || LLFloaterCamera::inFreeCameraMode() ) + { + drawMouselookInstructions(); + stop_glerror(); + } + + // Draw all nested UI views. + // No translation needed, this view is glued to 0,0 + mRootView->draw(); + + if (LLView::sDebugRects) + { + gToolTipView->drawStickyRect(); + } + + // Draw optional on-top-of-everyone view + LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); + if (top_ctrl && top_ctrl->getVisible()) + { + S32 screen_x, screen_y; + top_ctrl->localPointToScreen(0, 0, &screen_x, &screen_y); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + LLUI::pushMatrix(); + LLUI::translate( (F32) screen_x, (F32) screen_y); + top_ctrl->draw(); + LLUI::popMatrix(); + } + + + if( gShowOverlayTitle && !mOverlayTitle.empty() ) + { + // Used for special titles such as "Second Life - Special E3 2003 Beta" + const S32 DIST_FROM_TOP = 20; + LLFontGL::getFontSansSerifBig()->renderUTF8( + mOverlayTitle, 0, + ll_round( getWindowWidthScaled() * 0.5f), + getWindowHeightScaled() - DIST_FROM_TOP, + LLColor4(1, 1, 1, 0.4f), + LLFontGL::HCENTER, LLFontGL::TOP); + } + + LLUI::setScaleFactor(old_scale_factor); + } + LLUI::popMatrix(); + gGL.popMatrix(); + + gUIProgram.unbind(); + + LLView::sIsDrawing = false; } // Takes a single keyup event, usually when UI is visible @@ -2807,45 +2809,54 @@ bool LLViewerWindow::handleKeyUp(KEY key, MASK mask) LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); if (keyboard_focus - && !(mask & (MASK_CONTROL | MASK_ALT)) - && !gFocusMgr.getKeystrokesOnly()) - { - // We have keyboard focus, and it's not an accelerator + && !(mask & (MASK_CONTROL | MASK_ALT)) + && !gFocusMgr.getKeystrokesOnly()) + { + // We have keyboard focus, and it's not an accelerator if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown()) { return keyboard_focus->handleKeyUp(key, mask, false); } else if (key < 0x80) - { - // Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first. - return (gFocusMgr.getKeyboardFocus() != NULL); - } - } - - if (keyboard_focus) - { - if (keyboard_focus->handleKeyUp(key, mask, false)) - { - LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned true" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key, mask); - return true; - } - else { - LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned false" << LL_ENDL; - } - } - - // don't pass keys on to world when something in ui has focus - return gFocusMgr.childHasKeyboardFocus(mRootView) - || LLMenuGL::getKeyboardMode() - || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive()); + { + // Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first. + return (gFocusMgr.getKeyboardFocus() != NULL); + } + } + + if (keyboard_focus) + { + if (keyboard_focus->handleKeyUp(key, mask, false)) + { + LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned true" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key, mask); + return true; + } + else { + LL_DEBUGS() << "LLviewerWindow::handleKeyUp - in 'traverse up' - no loops seen... just called keyboard_focus->handleKeyUp an it returned false" << LL_ENDL; + } + } + + // Try for a new-format gesture + if (LLGestureMgr::instance().triggerGestureRelease(key, mask)) + { + LL_DEBUGS() << "LLviewerWindow::handleKey new gesture release feature" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return true; + } + //Old format gestures do not support this, so no need to implement it. + + // don't pass keys on to world when something in ui has focus + return gFocusMgr.childHasKeyboardFocus(mRootView) + || LLMenuGL::getKeyboardMode() + || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive()); } // Takes a single keydown event, usually when UI is visible bool LLViewerWindow::handleKey(KEY key, MASK mask) { - // hide tooltips on keypress - LLToolTipMgr::instance().blockToolTips(); + // hide tooltips on keypress + LLToolTipMgr::instance().blockToolTips(); // Menus get handled on key down instead of key up // so keybindings have to be recorded before that @@ -2857,7 +2868,7 @@ bool LLViewerWindow::handleKey(KEY key, MASK mask) } LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); - + if (keyboard_focus && !gFocusMgr.getKeystrokesOnly()) { @@ -2930,279 +2941,279 @@ bool LLViewerWindow::handleKey(KEY key, MASK mask) } } - // let menus handle navigation keys for navigation - if ((gMenuBarView && gMenuBarView->handleKey(key, mask, true)) - ||(gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, true)) - ||(gMenuHolder && gMenuHolder->handleKey(key, mask, true))) - { - LL_DEBUGS() << "LLviewerWindow::handleKey handle nav keys for nav" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return true; - } - - - // give menus a chance to handle modified (Ctrl, Alt) shortcut keys before current focus - // as long as focus isn't locked - if (mask & (MASK_CONTROL | MASK_ALT) && !gFocusMgr.focusLocked()) - { - // Check the current floater's menu first, if it has one. - if (gFocusMgr.keyboardFocusHasAccelerators() - && keyboard_focus - && keyboard_focus->handleKey(key,mask,false)) - { - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return true; - } - - if (gAgent.isInitialized() - && (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE || gAgent.getTeleportState() == LLAgent::TELEPORT_LOCAL) - && gMenuBarView - && gMenuBarView->handleAcceleratorKey(key, mask)) - { - LLViewerEventRecorder::instance().logKeyEvent(key, mask); - return true; - } - - if (gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)) - { - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return true; - } - } - - // give floaters first chance to handle TAB key - // so frontmost floater gets focus - // if nothing has focus, go to first or last UI element as appropriate + // let menus handle navigation keys for navigation + if ((gMenuBarView && gMenuBarView->handleKey(key, mask, true)) + ||(gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, true)) + ||(gMenuHolder && gMenuHolder->handleKey(key, mask, true))) + { + LL_DEBUGS() << "LLviewerWindow::handleKey handle nav keys for nav" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return true; + } + + + // give menus a chance to handle modified (Ctrl, Alt) shortcut keys before current focus + // as long as focus isn't locked + if (mask & (MASK_CONTROL | MASK_ALT) && !gFocusMgr.focusLocked()) + { + // Check the current floater's menu first, if it has one. + if (gFocusMgr.keyboardFocusHasAccelerators() + && keyboard_focus + && keyboard_focus->handleKey(key,mask,false)) + { + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return true; + } + + if (gAgent.isInitialized() + && (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE || gAgent.getTeleportState() == LLAgent::TELEPORT_LOCAL) + && gMenuBarView + && gMenuBarView->handleAcceleratorKey(key, mask)) + { + LLViewerEventRecorder::instance().logKeyEvent(key, mask); + return true; + } + + if (gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)) + { + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return true; + } + } + + // give floaters first chance to handle TAB key + // so frontmost floater gets focus + // if nothing has focus, go to first or last UI element as appropriate if (key == KEY_TAB && (mask & MASK_CONTROL || keyboard_focus == NULL)) - { - LL_WARNS() << "LLviewerWindow::handleKey give floaters first chance at tab key " << LL_ENDL; - if (gMenuHolder) gMenuHolder->hideMenus(); - - // if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode - gFloaterView->setCycleMode((mask & MASK_CONTROL) != 0); - - // do CTRL-TAB and CTRL-SHIFT-TAB logic - if (mask & MASK_SHIFT) - { - mRootView->focusPrevRoot(); - } - else - { - mRootView->focusNextRoot(); - } - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return true; - } - // hidden edit menu for cut/copy/paste - if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask)) - { - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return true; - } - - LLFloater* focused_floaterp = gFloaterView->getFocusedFloater(); - std::string focusedFloaterName = (focused_floaterp ? focused_floaterp->getInstanceName() : ""); - - if( keyboard_focus ) - { - if ((focusedFloaterName == "nearby_chat") || (focusedFloaterName == "im_container") || (focusedFloaterName == "impanel")) - { - if (gSavedSettings.getBOOL("ArrowKeysAlwaysMove")) - { - // let Control-Up and Control-Down through for chat line history, - if (!(key == KEY_UP && mask == MASK_CONTROL) - && !(key == KEY_DOWN && mask == MASK_CONTROL) - && !(key == KEY_UP && mask == MASK_ALT) - && !(key == KEY_DOWN && mask == MASK_ALT)) - { - switch(key) - { - case KEY_LEFT: - case KEY_RIGHT: - case KEY_UP: - case KEY_DOWN: - case KEY_PAGE_UP: - case KEY_PAGE_DOWN: - case KEY_HOME: - case KEY_END: - // when chatbar is empty or ArrowKeysAlwaysMove set, - // pass arrow keys on to avatar... - return false; - default: - break; - } - } - } - } - - if (keyboard_focus->handleKey(key, mask, false)) - { - - LL_DEBUGS() << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned true" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return true; - } else { - LL_DEBUGS() << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned false" << LL_ENDL; - } - } - - if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) ) - { - LL_DEBUGS() << "LLviewerWindow::handleKey toolbar handling?" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return true; - } - - // Try for a new-format gesture - if (LLGestureMgr::instance().triggerGesture(key, mask)) - { - LL_DEBUGS() << "LLviewerWindow::handleKey new gesture feature" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return true; - } - - // See if this is a gesture trigger. If so, eat the key and - // don't pass it down to the menus. - if (gGestureList.trigger(key, mask)) - { - LL_DEBUGS() << "LLviewerWindow::handleKey check gesture trigger" << LL_ENDL; - LLViewerEventRecorder::instance().logKeyEvent(key,mask); - return true; - } - - // If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, - // no view has keyboard focus, this is a printable character key (and no modifier key is - // pressed except shift), then give focus to nearby chat (STORM-560) - if ( LLStartUp::getStartupState() >= STATE_STARTED && - gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && - !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) - { - // Initialize nearby chat if it's missing - LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); - if (!nearby_chat) - { - LLSD name("im_container"); - LLFloaterReg::toggleInstanceOrBringToFront(name); - } - - LLChatEntry* chat_editor = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")->getChatBox(); - if (chat_editor) - { - // passing NULL here, character will be added later when it is handled by character handler. - nearby_chat->startChat(NULL); - return true; - } - } - - // give menus a chance to handle unmodified accelerator keys - if (gAgent.isInitialized() - && (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE || gAgent.getTeleportState() == LLAgent::TELEPORT_LOCAL) - && gMenuBarView - && gMenuBarView->handleAcceleratorKey(key, mask)) - { - LLViewerEventRecorder::instance().logKeyEvent(key, mask); - return true; - } - - if (gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)) - { - return true; - } - - // don't pass keys on to world when something in ui has focus - return gFocusMgr.childHasKeyboardFocus(mRootView) - || LLMenuGL::getKeyboardMode() - || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive()); + { + LL_WARNS() << "LLviewerWindow::handleKey give floaters first chance at tab key " << LL_ENDL; + if (gMenuHolder) gMenuHolder->hideMenus(); + + // if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode + gFloaterView->setCycleMode((mask & MASK_CONTROL) != 0); + + // do CTRL-TAB and CTRL-SHIFT-TAB logic + if (mask & MASK_SHIFT) + { + mRootView->focusPrevRoot(); + } + else + { + mRootView->focusNextRoot(); + } + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return true; + } + // hidden edit menu for cut/copy/paste + if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask)) + { + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return true; + } + + LLFloater* focused_floaterp = gFloaterView->getFocusedFloater(); + std::string focusedFloaterName = (focused_floaterp ? focused_floaterp->getInstanceName() : ""); + + if( keyboard_focus ) + { + if ((focusedFloaterName == "nearby_chat") || (focusedFloaterName == "im_container") || (focusedFloaterName == "impanel")) + { + if (gSavedSettings.getBOOL("ArrowKeysAlwaysMove")) + { + // let Control-Up and Control-Down through for chat line history, + if (!(key == KEY_UP && mask == MASK_CONTROL) + && !(key == KEY_DOWN && mask == MASK_CONTROL) + && !(key == KEY_UP && mask == MASK_ALT) + && !(key == KEY_DOWN && mask == MASK_ALT)) + { + switch(key) + { + case KEY_LEFT: + case KEY_RIGHT: + case KEY_UP: + case KEY_DOWN: + case KEY_PAGE_UP: + case KEY_PAGE_DOWN: + case KEY_HOME: + case KEY_END: + // when chatbar is empty or ArrowKeysAlwaysMove set, + // pass arrow keys on to avatar... + return false; + default: + break; + } + } + } + } + + if (keyboard_focus->handleKey(key, mask, false)) + { + + LL_DEBUGS() << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned true" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return true; + } else { + LL_DEBUGS() << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned false" << LL_ENDL; + } + } + + if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) ) + { + LL_DEBUGS() << "LLviewerWindow::handleKey toolbar handling?" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return true; + } + + // Try for a new-format gesture + if (LLGestureMgr::instance().triggerGesture(key, mask)) + { + LL_DEBUGS() << "LLviewerWindow::handleKey new gesture feature" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return true; + } + + // See if this is a gesture trigger. If so, eat the key and + // don't pass it down to the menus. + if (gGestureList.trigger(key, mask)) + { + LL_DEBUGS() << "LLviewerWindow::handleKey check gesture trigger" << LL_ENDL; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); + return true; + } + + // If "Pressing letter keys starts local chat" option is selected, we are not in mouselook, + // no view has keyboard focus, this is a printable character key (and no modifier key is + // pressed except shift), then give focus to nearby chat (STORM-560) + if ( LLStartUp::getStartupState() >= STATE_STARTED && + gSavedSettings.getS32("LetterKeysFocusChatBar") && !gAgentCamera.cameraMouselook() && + !keyboard_focus && key < 0x80 && (mask == MASK_NONE || mask == MASK_SHIFT) ) + { + // Initialize nearby chat if it's missing + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); + if (!nearby_chat) + { + LLSD name("im_container"); + LLFloaterReg::toggleInstanceOrBringToFront(name); + } + + LLChatEntry* chat_editor = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")->getChatBox(); + if (chat_editor) + { + // passing NULL here, character will be added later when it is handled by character handler. + nearby_chat->startChat(NULL); + return true; + } + } + + // give menus a chance to handle unmodified accelerator keys + if (gAgent.isInitialized() + && (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE || gAgent.getTeleportState() == LLAgent::TELEPORT_LOCAL) + && gMenuBarView + && gMenuBarView->handleAcceleratorKey(key, mask)) + { + LLViewerEventRecorder::instance().logKeyEvent(key, mask); + return true; + } + + if (gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask)) + { + return true; + } + + // don't pass keys on to world when something in ui has focus + return gFocusMgr.childHasKeyboardFocus(mRootView) + || LLMenuGL::getKeyboardMode() + || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive()); } bool LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask) { - // HACK: We delay processing of return keys until they arrive as a Unicode char, - // so that if you're typing chat text at low frame rate, we don't send the chat - // until all keystrokes have been entered. JC - // HACK: Numeric keypad <enter> on Mac is Unicode 3 - // HACK: Control-M on Windows is Unicode 13 - if ((uni_char == 13 && mask != MASK_CONTROL) - || (uni_char == 3 && mask == MASK_NONE) ) - { - if (mask != MASK_ALT) - { - // remaps, handles ignored cases and returns back to viewer window. - return gViewerInput.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN)); - } - } - - // let menus handle navigation (jump) keys - if (gMenuBarView && gMenuBarView->handleUnicodeChar(uni_char, true)) - { - return true; - } - - // Traverses up the hierarchy - LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); - if( keyboard_focus ) - { - if (keyboard_focus->handleUnicodeChar(uni_char, false)) - { - return true; - } + // HACK: We delay processing of return keys until they arrive as a Unicode char, + // so that if you're typing chat text at low frame rate, we don't send the chat + // until all keystrokes have been entered. JC + // HACK: Numeric keypad <enter> on Mac is Unicode 3 + // HACK: Control-M on Windows is Unicode 13 + if ((uni_char == 13 && mask != MASK_CONTROL) + || (uni_char == 3 && mask == MASK_NONE) ) + { + if (mask != MASK_ALT) + { + // remaps, handles ignored cases and returns back to viewer window. + return gViewerInput.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN)); + } + } + // let menus handle navigation (jump) keys + if (gMenuBarView && gMenuBarView->handleUnicodeChar(uni_char, true)) + { return true; - } + } - return false; + // Traverses up the hierarchy + LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus(); + if( keyboard_focus ) + { + if (keyboard_focus->handleUnicodeChar(uni_char, false)) + { + return true; + } + + return true; + } + + return false; } void LLViewerWindow::handleScrollWheel(S32 clicks) { - LLUI::getInstance()->resetMouseIdleTimer(); - - LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); - if( mouse_captor ) - { - S32 local_x; - S32 local_y; - mouse_captor->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y ); - mouse_captor->handleScrollWheel(local_x, local_y, clicks); - if (LLView::sDebugMouseHandling) - { - LL_INFOS() << "Scroll Wheel handled by captor " << mouse_captor->getName() << LL_ENDL; - } - return; - } - - LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); - if (top_ctrl) - { - S32 local_x; - S32 local_y; - top_ctrl->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y ); - if (top_ctrl->handleScrollWheel(local_x, local_y, clicks)) return; - } - - if (mRootView->handleScrollWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks) ) - { - if (LLView::sDebugMouseHandling) - { - LL_INFOS() << "Scroll Wheel" << LLView::sMouseHandlerMessage << LL_ENDL; - } - return; - } - else if (LLView::sDebugMouseHandling) - { - LL_INFOS() << "Scroll Wheel not handled by view" << LL_ENDL; - } - - // Zoom the camera in and out behavior - - if(top_ctrl == 0 - && getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) - && gAgentCamera.isInitialized()) - gAgentCamera.handleScrollWheel(clicks); - - return; + LLUI::getInstance()->resetMouseIdleTimer(); + + LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); + if( mouse_captor ) + { + S32 local_x; + S32 local_y; + mouse_captor->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y ); + mouse_captor->handleScrollWheel(local_x, local_y, clicks); + if (LLView::sDebugMouseHandling) + { + LL_INFOS() << "Scroll Wheel handled by captor " << mouse_captor->getName() << LL_ENDL; + } + return; + } + + LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); + if (top_ctrl) + { + S32 local_x; + S32 local_y; + top_ctrl->screenPointToLocal( mCurrentMousePoint.mX, mCurrentMousePoint.mY, &local_x, &local_y ); + if (top_ctrl->handleScrollWheel(local_x, local_y, clicks)) return; + } + + if (mRootView->handleScrollWheel(mCurrentMousePoint.mX, mCurrentMousePoint.mY, clicks) ) + { + if (LLView::sDebugMouseHandling) + { + LL_INFOS() << "Scroll Wheel" << LLView::sMouseHandlerMessage << LL_ENDL; + } + return; + } + else if (LLView::sDebugMouseHandling) + { + LL_INFOS() << "Scroll Wheel not handled by view" << LL_ENDL; + } + + // Zoom the camera in and out behavior + + if(top_ctrl == 0 + && getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) + && gAgentCamera.isInitialized()) + gAgentCamera.handleScrollWheel(clicks); + + return; } void LLViewerWindow::handleScrollHWheel(S32 clicks) @@ -3211,7 +3222,7 @@ void LLViewerWindow::handleScrollHWheel(S32 clicks) { return; } - + LLUI::getInstance()->resetMouseIdleTimer(); LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); @@ -3255,42 +3266,42 @@ void LLViewerWindow::handleScrollHWheel(S32 clicks) void LLViewerWindow::addPopup(LLView* popup) { - if (mPopupView) - { - mPopupView->addPopup(popup); - } + if (mPopupView) + { + mPopupView->addPopup(popup); + } } void LLViewerWindow::removePopup(LLView* popup) { - if (mPopupView) - { - mPopupView->removePopup(popup); - } + if (mPopupView) + { + mPopupView->removePopup(popup); + } } void LLViewerWindow::clearPopups() { - if (mPopupView) - { - mPopupView->clearPopups(); - } + if (mPopupView) + { + mPopupView->clearPopups(); + } } void LLViewerWindow::moveCursorToCenter() { - if (! gSavedSettings.getBOOL("DisableMouseWarp")) - { - S32 x = getWorldViewWidthScaled() / 2; - S32 y = getWorldViewHeightScaled() / 2; - - LLUI::getInstance()->setMousePositionScreen(x, y); - - //on a forced move, all deltas get zeroed out to prevent jumping - mCurrentMousePoint.set(x,y); - mLastMousePoint.set(x,y); - mCurrentMouseDelta.set(0,0); - } + if (! gSavedSettings.getBOOL("DisableMouseWarp")) + { + S32 x = getWorldViewWidthScaled() / 2; + S32 y = getWorldViewHeightScaled() / 2; + + LLUI::getInstance()->setMousePositionScreen(x, y); + + //on a forced move, all deltas get zeroed out to prevent jumping + mCurrentMousePoint.set(x,y); + mLastMousePoint.set(x,y); + mCurrentMouseDelta.set(0,0); + } } @@ -3301,32 +3312,32 @@ void LLViewerWindow::moveCursorToCenter() void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params) { - if (viewp) - { - if (!params.styled_message.empty()) - { - params.styled_message.add().text("\n---------\n"); - } - LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView(); - // NOTE: we skip "root" since it is assumed - for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView(); - tooltip_it != end_tooltip_it; - ++tooltip_it) - { - LLView* viewp = *tooltip_it; - - params.styled_message.add().text(viewp->getName()); - - LLPanel* panelp = dynamic_cast<LLPanel*>(viewp); - if (panelp && !panelp->getXMLFilename().empty()) - { - params.styled_message.add() - .text("(" + panelp->getXMLFilename() + ")") - .style.color(LLColor4(0.7f, 0.7f, 1.f, 1.f)); - } - params.styled_message.add().text("/"); - } - } + if (viewp) + { + if (!params.styled_message.empty()) + { + params.styled_message.add().text("\n---------\n"); + } + LLView::root_to_view_iterator_t end_tooltip_it = viewp->endRootToView(); + // NOTE: we skip "root" since it is assumed + for (LLView::root_to_view_iterator_t tooltip_it = ++viewp->beginRootToView(); + tooltip_it != end_tooltip_it; + ++tooltip_it) + { + LLView* viewp = *tooltip_it; + + params.styled_message.add().text(viewp->getName()); + + LLPanel* panelp = dynamic_cast<LLPanel*>(viewp); + if (panelp && !panelp->getXMLFilename().empty()) + { + params.styled_message.add() + .text("(" + panelp->getXMLFilename() + ")") + .style.color(LLColor4(0.7f, 0.7f, 1.f, 1.f)); + } + params.styled_message.add().text("/"); + } + } } static LLTrace::BlockTimerStatHandle ftm("Update UI"); @@ -3335,922 +3346,924 @@ static LLTrace::BlockTimerStatHandle ftm("Update UI"); // event processing. void LLViewerWindow::updateUI() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(ftm); + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(ftm); - static std::string last_handle_msg; + static std::string last_handle_msg; - if (gLoggedInTime.getStarted()) - { - if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("DestinationGuideHintTimeout")) - { - LLFirstUse::notUsingDestinationGuide(); - } - if (gLoggedInTime.getElapsedTimeF32() > gSavedSettings.getF32("SidePanelHintTimeout")) - { - LLFirstUse::notUsingSidePanel(); - } - } + if (gLoggedInTime.getStarted()) + { + const F32 DESTINATION_GUIDE_HINT_TIMEOUT = 1200.f; + const F32 SIDE_PANEL_HINT_TIMEOUT = 300.f; + if (gLoggedInTime.getElapsedTimeF32() > DESTINATION_GUIDE_HINT_TIMEOUT) + { + LLFirstUse::notUsingDestinationGuide(); + } + if (gLoggedInTime.getElapsedTimeF32() > SIDE_PANEL_HINT_TIMEOUT) + { + LLFirstUse::notUsingSidePanel(); + } + } - LLConsole::updateClass(); + LLConsole::updateClass(); - // animate layout stacks so we have up to date rect for world view - LLLayoutStack::updateClass(); + // animate layout stacks so we have up to date rect for world view + LLLayoutStack::updateClass(); - // use full window for world view when not rendering UI - bool world_view_uses_full_window = gAgentCamera.cameraMouselook() || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); - updateWorldViewRect(world_view_uses_full_window); + // use full window for world view when not rendering UI + bool world_view_uses_full_window = gAgentCamera.cameraMouselook() || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); + updateWorldViewRect(world_view_uses_full_window); - LLView::sMouseHandlerMessage.clear(); + LLView::sMouseHandlerMessage.clear(); - S32 x = mCurrentMousePoint.mX; - S32 y = mCurrentMousePoint.mY; + S32 x = mCurrentMousePoint.mX; + S32 y = mCurrentMousePoint.mY; - MASK mask = gKeyboard->currentMask(true); + MASK mask = gKeyboard->currentMask(true); - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) - { - gDebugRaycastFaceHit = gDebugRaycastGLTFNodeHit = gDebugRaycastGLTFPrimitiveHit = -1; - gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, false, false, true, false, - &gDebugRaycastFaceHit, + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) + { + gDebugRaycastFaceHit = gDebugRaycastGLTFNodeHit = gDebugRaycastGLTFPrimitiveHit = -1; + gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, false, false, true, false, + &gDebugRaycastFaceHit, &gDebugRaycastGLTFNodeHit, &gDebugRaycastGLTFPrimitiveHit, - &gDebugRaycastIntersection, - &gDebugRaycastTexCoord, - &gDebugRaycastNormal, - &gDebugRaycastTangent, - &gDebugRaycastStart, - &gDebugRaycastEnd); - - gDebugRaycastParticle = gPipeline.lineSegmentIntersectParticle(gDebugRaycastStart, gDebugRaycastEnd, &gDebugRaycastParticleIntersection, NULL); - } - - updateMouseDelta(); - updateKeyboardFocus(); - - bool handled = false; - - LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); - LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); - LLView* captor_view = dynamic_cast<LLView*>(mouse_captor); - - //FIXME: only include captor and captor's ancestors if mouse is truly over them --RN - - //build set of views containing mouse cursor by traversing UI hierarchy and testing - //screen rect against mouse cursor - view_handle_set_t mouse_hover_set; - - // constraint mouse enter events to children of mouse captor - LLView* root_view = captor_view; - - // if mouse captor doesn't exist or isn't a LLView - // then allow mouse enter events on entire UI hierarchy - if (!root_view) - { - root_view = mRootView; - } - - static LLCachedControl<bool> dump_menu_holder(gSavedSettings, "DumpMenuHolderSize", false); - if (dump_menu_holder) - { - static bool init = false; - static LLFrameTimer child_count_timer; - static std::vector <std::string> child_vec; - if (!init) - { - child_count_timer.resetWithExpiry(5.f); - init = true; - } - if (child_count_timer.hasExpired()) - { - LL_INFOS() << "gMenuHolder child count: " << gMenuHolder->getChildCount() << LL_ENDL; - std::vector<std::string> local_child_vec; - LLView::child_list_t child_list = *gMenuHolder->getChildList(); - for (auto child : child_list) - { - local_child_vec.emplace_back(child->getName()); - } - if (!local_child_vec.empty() && local_child_vec != child_vec) - { - std::vector<std::string> out_vec; - std::sort(local_child_vec.begin(), local_child_vec.end()); - std::sort(child_vec.begin(), child_vec.end()); - std::set_difference(child_vec.begin(), child_vec.end(), local_child_vec.begin(), local_child_vec.end(), std::inserter(out_vec, out_vec.begin())); - if (!out_vec.empty()) - { - LL_INFOS() << "gMenuHolder removal diff size: '"<<out_vec.size() <<"' begin_child_diff"; - for (auto str : out_vec) - { - LL_CONT << " : " << str; - } - LL_CONT << " : end_child_diff" << LL_ENDL; - } - - out_vec.clear(); - std::set_difference(local_child_vec.begin(), local_child_vec.end(), child_vec.begin(), child_vec.end(), std::inserter(out_vec, out_vec.begin())); - if (!out_vec.empty()) - { - LL_INFOS() << "gMenuHolder addition diff size: '" << out_vec.size() << "' begin_child_diff"; - for (auto str : out_vec) - { - LL_CONT << " : " << str; - } - LL_CONT << " : end_child_diff" << LL_ENDL; - } - child_vec.swap(local_child_vec); - } - child_count_timer.resetWithExpiry(5.f); - } - } - - // only update mouse hover set when UI is visible (since we shouldn't send hover events to invisible UI - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - // include all ancestors of captor_view as automatically having mouse - if (captor_view) - { - LLView* captor_parent_view = captor_view->getParent(); - while(captor_parent_view) - { - mouse_hover_set.insert(captor_parent_view->getHandle()); - captor_parent_view = captor_parent_view->getParent(); - } - } - - // aggregate visible views that contain mouse cursor in display order - LLPopupView::popup_list_t popups = mPopupView->getCurrentPopups(); - - for(LLPopupView::popup_list_t::iterator popup_it = popups.begin(); popup_it != popups.end(); ++popup_it) - { - LLView* popup = popup_it->get(); - if (popup && popup->calcScreenBoundingRect().pointInRect(x, y)) - { - // iterator over contents of top_ctrl, and throw into mouse_hover_set - for (LLView::tree_iterator_t it = popup->beginTreeDFS(); - it != popup->endTreeDFS(); - ++it) - { - LLView* viewp = *it; - if (viewp->getVisible() - && viewp->calcScreenBoundingRect().pointInRect(x, y)) - { - // we have a view that contains the mouse, add it to the set - mouse_hover_set.insert(viewp->getHandle()); - } - else - { - // skip this view and all of its children - it.skipDescendants(); - } - } - } - } - - // while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events - if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y)) - { - // iterator over contents of top_ctrl, and throw into mouse_hover_set - for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS(); - it != top_ctrl->endTreeDFS(); - ++it) - { - LLView* viewp = *it; - if (viewp->getVisible() - && viewp->calcScreenBoundingRect().pointInRect(x, y)) - { - // we have a view that contains the mouse, add it to the set - mouse_hover_set.insert(viewp->getHandle()); - } - else - { - // skip this view and all of its children - it.skipDescendants(); - } - } - } - else - { - // walk UI tree in depth-first order - for (LLView::tree_iterator_t it = root_view->beginTreeDFS(); - it != root_view->endTreeDFS(); - ++it) - { - LLView* viewp = *it; - // calculating the screen rect involves traversing the parent, so this is less than optimal - if (viewp->getVisible() - && viewp->calcScreenBoundingRect().pointInRect(x, y)) - { - - // if this view is mouse opaque, nothing behind it should be in mouse_hover_set - if (viewp->getMouseOpaque()) - { - // constrain further iteration to children of this widget - it = viewp->beginTreeDFS(); - } - - // we have a view that contains the mouse, add it to the set - mouse_hover_set.insert(viewp->getHandle()); - } - else - { - // skip this view and all of its children - it.skipDescendants(); - } - } - } - } - - typedef std::vector<LLHandle<LLView> > view_handle_list_t; - - // call onMouseEnter() on all views which contain the mouse cursor but did not before - view_handle_list_t mouse_enter_views; - std::set_difference(mouse_hover_set.begin(), mouse_hover_set.end(), - mMouseHoverViews.begin(), mMouseHoverViews.end(), - std::back_inserter(mouse_enter_views)); - for (view_handle_list_t::iterator it = mouse_enter_views.begin(); - it != mouse_enter_views.end(); - ++it) - { - LLView* viewp = it->get(); - if (viewp) - { - LLRect view_screen_rect = viewp->calcScreenRect(); - 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); - - // only handle hover events when UI is enabled - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - - 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) - { - LL_INFOS() << "Hover handled by captor " << mouse_captor->getName() << LL_ENDL; - } - - if( !handled ) - { - LL_DEBUGS("UserInput") << "hover not handled by mouse captor" << LL_ENDL; - } - } - 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); - } - - 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; - LL_INFOS() << "Hover" << LLView::sMouseHandlerMessage << LL_ENDL; - } - handled = true; - } - else if (LLView::sDebugMouseHandling) - { - if (last_handle_msg != LLStringUtil::null) - { - last_handle_msg.clear(); - LL_INFOS() << "Hover not handled by view" << LL_ENDL; - } - } - } - - 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; - - static LLCachedControl<bool> debug_show_xui_names(gSavedSettings, "DebugShowXUINames", 0); - if (debug_show_xui_names) - { - 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); - params.styled_message.add().text("\n"); - - 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 ); - } - } - } - } - else - { // just have tools handle hover when UI is turned off - LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); - - if(mMouseInWindow && tool) - { - handled = tool->handleHover(x, 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(); - } + &gDebugRaycastIntersection, + &gDebugRaycastTexCoord, + &gDebugRaycastNormal, + &gDebugRaycastTangent, + &gDebugRaycastStart, + &gDebugRaycastEnd); + + gDebugRaycastParticle = gPipeline.lineSegmentIntersectParticle(gDebugRaycastStart, gDebugRaycastEnd, &gDebugRaycastParticleIntersection, NULL); + } + + updateMouseDelta(); + updateKeyboardFocus(); + + bool handled = false; + + LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); + LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); + LLView* captor_view = dynamic_cast<LLView*>(mouse_captor); + + //FIXME: only include captor and captor's ancestors if mouse is truly over them --RN + + //build set of views containing mouse cursor by traversing UI hierarchy and testing + //screen rect against mouse cursor + view_handle_set_t mouse_hover_set; + + // constraint mouse enter events to children of mouse captor + LLView* root_view = captor_view; + + // if mouse captor doesn't exist or isn't a LLView + // then allow mouse enter events on entire UI hierarchy + if (!root_view) + { + root_view = mRootView; + } + + static LLCachedControl<bool> dump_menu_holder(gSavedSettings, "DumpMenuHolderSize", false); + if (dump_menu_holder) + { + static bool init = false; + static LLFrameTimer child_count_timer; + static std::vector <std::string> child_vec; + if (!init) + { + child_count_timer.resetWithExpiry(5.f); + init = true; + } + if (child_count_timer.hasExpired()) + { + LL_INFOS() << "gMenuHolder child count: " << gMenuHolder->getChildCount() << LL_ENDL; + std::vector<std::string> local_child_vec; + LLView::child_list_t child_list = *gMenuHolder->getChildList(); + for (auto child : child_list) + { + local_child_vec.emplace_back(child->getName()); + } + if (!local_child_vec.empty() && local_child_vec != child_vec) + { + std::vector<std::string> out_vec; + std::sort(local_child_vec.begin(), local_child_vec.end()); + std::sort(child_vec.begin(), child_vec.end()); + std::set_difference(child_vec.begin(), child_vec.end(), local_child_vec.begin(), local_child_vec.end(), std::inserter(out_vec, out_vec.begin())); + if (!out_vec.empty()) + { + LL_INFOS() << "gMenuHolder removal diff size: '"<<out_vec.size() <<"' begin_child_diff"; + for (auto str : out_vec) + { + LL_CONT << " : " << str; + } + LL_CONT << " : end_child_diff" << LL_ENDL; + } + + out_vec.clear(); + std::set_difference(local_child_vec.begin(), local_child_vec.end(), child_vec.begin(), child_vec.end(), std::inserter(out_vec, out_vec.begin())); + if (!out_vec.empty()) + { + LL_INFOS() << "gMenuHolder addition diff size: '" << out_vec.size() << "' begin_child_diff"; + for (auto str : out_vec) + { + LL_CONT << " : " << str; + } + LL_CONT << " : end_child_diff" << LL_ENDL; + } + child_vec.swap(local_child_vec); + } + child_count_timer.resetWithExpiry(5.f); + } + } + + // only update mouse hover set when UI is visible (since we shouldn't send hover events to invisible UI + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + // include all ancestors of captor_view as automatically having mouse + if (captor_view) + { + LLView* captor_parent_view = captor_view->getParent(); + while(captor_parent_view) + { + mouse_hover_set.insert(captor_parent_view->getHandle()); + captor_parent_view = captor_parent_view->getParent(); + } + } + + // aggregate visible views that contain mouse cursor in display order + LLPopupView::popup_list_t popups = mPopupView->getCurrentPopups(); + + for(LLPopupView::popup_list_t::iterator popup_it = popups.begin(); popup_it != popups.end(); ++popup_it) + { + LLView* popup = popup_it->get(); + if (popup && popup->calcScreenBoundingRect().pointInRect(x, y)) + { + // iterator over contents of top_ctrl, and throw into mouse_hover_set + for (LLView::tree_iterator_t it = popup->beginTreeDFS(); + it != popup->endTreeDFS(); + ++it) + { + LLView* viewp = *it; + if (viewp->getVisible() + && viewp->calcScreenBoundingRect().pointInRect(x, y)) + { + // we have a view that contains the mouse, add it to the set + mouse_hover_set.insert(viewp->getHandle()); + } + else + { + // skip this view and all of its children + it.skipDescendants(); + } + } + } + } + + // while the top_ctrl contains the mouse cursor, only it and its descendants will receive onMouseEnter events + if (top_ctrl && top_ctrl->calcScreenBoundingRect().pointInRect(x, y)) + { + // iterator over contents of top_ctrl, and throw into mouse_hover_set + for (LLView::tree_iterator_t it = top_ctrl->beginTreeDFS(); + it != top_ctrl->endTreeDFS(); + ++it) + { + LLView* viewp = *it; + if (viewp->getVisible() + && viewp->calcScreenBoundingRect().pointInRect(x, y)) + { + // we have a view that contains the mouse, add it to the set + mouse_hover_set.insert(viewp->getHandle()); + } + else + { + // skip this view and all of its children + it.skipDescendants(); + } + } + } + else + { + // walk UI tree in depth-first order + for (LLView::tree_iterator_t it = root_view->beginTreeDFS(); + it != root_view->endTreeDFS(); + ++it) + { + LLView* viewp = *it; + // calculating the screen rect involves traversing the parent, so this is less than optimal + if (viewp->getVisible() + && viewp->calcScreenBoundingRect().pointInRect(x, y)) + { + + // if this view is mouse opaque, nothing behind it should be in mouse_hover_set + if (viewp->getMouseOpaque()) + { + // constrain further iteration to children of this widget + it = viewp->beginTreeDFS(); + } + + // we have a view that contains the mouse, add it to the set + mouse_hover_set.insert(viewp->getHandle()); + } + else + { + // skip this view and all of its children + it.skipDescendants(); + } + } + } + } + + typedef std::vector<LLHandle<LLView> > view_handle_list_t; + + // call onMouseEnter() on all views which contain the mouse cursor but did not before + view_handle_list_t mouse_enter_views; + std::set_difference(mouse_hover_set.begin(), mouse_hover_set.end(), + mMouseHoverViews.begin(), mMouseHoverViews.end(), + std::back_inserter(mouse_enter_views)); + for (view_handle_list_t::iterator it = mouse_enter_views.begin(); + it != mouse_enter_views.end(); + ++it) + { + LLView* viewp = it->get(); + if (viewp) + { + LLRect view_screen_rect = viewp->calcScreenRect(); + 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); + + // only handle hover events when UI is enabled + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + + 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) + { + LL_INFOS() << "Hover handled by captor " << mouse_captor->getName() << LL_ENDL; + } + + if( !handled ) + { + LL_DEBUGS("UserInput") << "hover not handled by mouse captor" << LL_ENDL; + } + } + 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); + } + + 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; + LL_INFOS() << "Hover" << LLView::sMouseHandlerMessage << LL_ENDL; + } + handled = true; + } + else if (LLView::sDebugMouseHandling) + { + if (last_handle_msg != LLStringUtil::null) + { + last_handle_msg.clear(); + LL_INFOS() << "Hover not handled by view" << LL_ENDL; + } + } + } + + 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; + + static LLCachedControl<bool> debug_show_xui_names(gSavedSettings, "DebugShowXUINames", 0); + if (debug_show_xui_names) + { + 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); + params.styled_message.add().text("\n"); + + 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 ); + } + } + } + } + else + { // just have tools handle hover when UI is turned off + LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); + + if(mMouseInWindow && tool) + { + handled = tool->handleHover(x, 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()->isShowFloaterTools() - && (!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; - MASK mask = gKeyboard->currentMask(true); - gFloaterTools->updatePopup( select_center_screen, mask ); - } - 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); - } + 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()->isShowFloaterTools() + && (!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; + MASK mask = gKeyboard->currentMask(true); + gFloaterTools->updatePopup( select_center_screen, mask ); + } + 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() { #if LL_WINDOWS - LLCoordCommon delta; + LLCoordCommon delta; mWindow->getCursorDelta(&delta); S32 dx = delta.mX; S32 dy = delta.mY; #else - S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::getScaleFactor().mV[VX]); - S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::getScaleFactor().mV[VY]); + S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::getScaleFactor().mV[VX]); + S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::getScaleFactor().mV[VY]); #endif - //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.value()*amount,1.f); - fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds.value()*amount,1.f); - - mCurrentMouseDelta.set(ll_round(fdx), ll_round(fdy)); - mouse_vel.setVec(fdx,fdy); - } - else - { - mCurrentMouseDelta.set(dx, dy); - mouse_vel.setVec((F32) dx, (F32) dy); - } - - sample(sMouseVelocityStat, mouse_vel.magVec()); + //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.value()*amount,1.f); + fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds.value()*amount,1.f); + + mCurrentMouseDelta.set(ll_round(fdx), ll_round(fdy)); + mouse_vel.setVec(fdx,fdy); + } + else + { + mCurrentMouseDelta.set(dx, dy); + mouse_vel.setVec((F32) dx, (F32) dy); + } + + sample(sMouseVelocityStat, mouse_vel.magVec()); } void LLViewerWindow::updateKeyboardFocus() { - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - gFocusMgr.setKeyboardFocus(NULL); - } - - // clean up current focus - LLUICtrl* cur_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); - if (cur_focus) - { - if (!cur_focus->isInVisibleChain() || !cur_focus->isInEnabledChain()) - { + if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + gFocusMgr.setKeyboardFocus(NULL); + } + + // 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(); - bool new_focus_found = false; - while(parent) - { - if (parent->isCtrl() - && (parent->hasTabStop() || parent == focus_root) - && !parent->getIsChrome() - && parent->isInVisibleChain() - && parent->isInEnabledChain()) - { - if (!parent->focusFirstItem()) - { - parent->setFocus(true); - } - new_focus_found = 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 (!new_focus_found) - { - 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(); - MASK mask = gKeyboard->currentMask(true); - if ((mask & 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(); - } + // gFocusMgr.releaseFocusIfNeeded(cur_focus); + + LLUICtrl* parent = cur_focus->getParentUICtrl(); + const LLUICtrl* focus_root = cur_focus->findRootMostFocusRoot(); + bool new_focus_found = false; + while(parent) + { + if (parent->isCtrl() + && (parent->hasTabStop() || parent == focus_root) + && !parent->getIsChrome() + && parent->isInVisibleChain() + && parent->isInEnabledChain()) + { + if (!parent->focusFirstItem()) + { + parent->setFocus(true); + } + new_focus_found = 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 (!new_focus_found) + { + 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(); + MASK mask = gKeyboard->currentMask(true); + if ((mask & 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(); + } } static LLTrace::BlockTimerStatHandle FTM_UPDATE_WORLD_VIEW("Update World View"); void LLViewerWindow::updateWorldViewRect(bool use_full_window) { - LL_RECORD_BLOCK_TIME(FTM_UPDATE_WORLD_VIEW); - - // start off using whole window to render world - LLRect new_world_rect = mWindowRectRaw; + LL_RECORD_BLOCK_TIME(FTM_UPDATE_WORLD_VIEW); - if (!use_full_window && 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); + // start off using whole window to render world + LLRect new_world_rect = mWindowRectRaw; - new_world_rect.mLeft = ll_round((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]); - new_world_rect.mRight = ll_round((F32)new_world_rect.mRight * mDisplayScale.mV[VX]); - new_world_rect.mBottom = ll_round((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]); - new_world_rect.mTop = ll_round((F32)new_world_rect.mTop * mDisplayScale.mV[VY]); - } + if (!use_full_window && 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 = ll_round((F32)new_world_rect.mLeft * mDisplayScale.mV[VX]); + new_world_rect.mRight = ll_round((F32)new_world_rect.mRight * mDisplayScale.mV[VX]); + new_world_rect.mBottom = ll_round((F32)new_world_rect.mBottom * mDisplayScale.mV[VY]); + new_world_rect.mTop = ll_round((F32)new_world_rect.mTop * mDisplayScale.mV[VY]); + } - if (mWorldViewRectRaw != new_world_rect) - { - mWorldViewRectRaw = new_world_rect; - gResizeScreenTexture = true; - LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); - LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); + if (mWorldViewRectRaw != new_world_rect) + { + mWorldViewRectRaw = new_world_rect; + gResizeScreenTexture = true; + LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); + LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); - LLRect old_world_rect_scaled = mWorldViewRectScaled; - mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); + LLRect old_world_rect_scaled = mWorldViewRectScaled; + mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); - // sending a signal with a new WorldView rect - mOnWorldViewRectUpdated(old_world_rect_scaled, mWorldViewRectScaled); - } + // sending a signal with a new WorldView rect + mOnWorldViewRectUpdated(old_world_rect_scaled, 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; - } + // 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 -// render_hud_elements: false, false, false +// render_ui_3d: false, false, true +// 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 = gAgentAvatarp->getHUDBBox(); - - // set up transform to encompass bounding box of HUD - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.pushMatrix(); - gGL.loadIdentity(); - F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); - gGL.ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - gGL.loadIdentity(); - gGL.loadMatrix(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame - gGL.translatef(-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); - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.pushMatrix(); - if (selection->getSelectType() == SELECT_TYPE_HUD) - { - F32 zoom = gAgentCamera.mHUDCurZoom; - gGL.scalef(zoom, zoom, zoom); - } - - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - LLDrawable* drawable = object->mDrawable; - if (drawable && drawable->isLight()) - { - LLVOVolume* vovolume = drawable->getVOVolume(); - gGL.pushMatrix(); - - LLVector3 center = drawable->getPositionAgent(); - gGL.translatef(center[0], center[1], center[2]); - F32 scale = vovolume->getLightRadius(); - gGL.scalef(scale, scale, scale); - - LLColor4 color(vovolume->getLightSRGBColor(), .5f); - gGL.color4fv(color.mV); - - //F32 pixel_area = 100000.f; - // Render Outside - gSphere.render(); - - // Render Inside - glCullFace(GL_FRONT); - gSphere.render(); - glCullFace(GL_BACK); - - gGL.popMatrix(); - } - return true; - } - } func; - LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func); - - gGL.popMatrix(); - } - - // 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 all_selected_objects_move; - bool all_selected_objects_modify; - // Note: This might be costly to do on each frame and when a lot of objects are selected - // we might be better off with some kind of memory for selection and/or states, consider - // optimizing, perhaps even some kind of selection generation at level of LLSelectMgr to - // make whole viewer benefit. - LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(all_selected_objects_move, all_selected_objects_modify); - - bool draw_handles = true; - - if (tool == LLToolCompTranslate::getInstance() && !all_selected_objects_move && !LLSelectMgr::getInstance()->isMovableAvatarSelected()) - { - draw_handles = false; - } - - if (tool == LLToolCompRotate::getInstance() && !all_selected_objects_move && !LLSelectMgr::getInstance()->isMovableAvatarSelected()) - { - 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()) - { - gGL.matrixMode(LLRender::MM_PROJECTION); - gGL.popMatrix(); - - gGL.matrixMode(LLRender::MM_MODELVIEW); - gGL.popMatrix(); - stop_glerror(); - } - } - } + 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 = gAgentAvatarp->getHUDBBox(); + + // set up transform to encompass bounding box of HUD + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.pushMatrix(); + gGL.loadIdentity(); + F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); + gGL.ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + gGL.loadIdentity(); + gGL.loadMatrix(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame + gGL.translatef(-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); + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.pushMatrix(); + if (selection->getSelectType() == SELECT_TYPE_HUD) + { + F32 zoom = gAgentCamera.mHUDCurZoom; + gGL.scalef(zoom, zoom, zoom); + } + + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + LLDrawable* drawable = object->mDrawable; + if (drawable && drawable->isLight()) + { + LLVOVolume* vovolume = drawable->getVOVolume(); + gGL.pushMatrix(); + + LLVector3 center = drawable->getPositionAgent(); + gGL.translatef(center[0], center[1], center[2]); + F32 scale = vovolume->getLightRadius(); + gGL.scalef(scale, scale, scale); + + LLColor4 color(vovolume->getLightSRGBColor(), .5f); + gGL.color4fv(color.mV); + + //F32 pixel_area = 100000.f; + // Render Outside + gSphere.render(); + + // Render Inside + glCullFace(GL_FRONT); + gSphere.render(); + glCullFace(GL_BACK); + + gGL.popMatrix(); + } + return true; + } + } func; + LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func); + + gGL.popMatrix(); + } + + // 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 all_selected_objects_move; + bool all_selected_objects_modify; + // Note: This might be costly to do on each frame and when a lot of objects are selected + // we might be better off with some kind of memory for selection and/or states, consider + // optimizing, perhaps even some kind of selection generation at level of LLSelectMgr to + // make whole viewer benefit. + LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(all_selected_objects_move, all_selected_objects_modify); + + bool draw_handles = true; + + if (tool == LLToolCompTranslate::getInstance() && !all_selected_objects_move && !LLSelectMgr::getInstance()->isMovableAvatarSelected()) + { + draw_handles = false; + } + + if (tool == LLToolCompRotate::getInstance() && !all_selected_objects_move && !LLSelectMgr::getInstance()->isMovableAvatarSelected()) + { + 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()) + { + gGL.matrixMode(LLRender::MM_PROJECTION); + gGL.popMatrix(); + + gGL.matrixMode(LLRender::MM_MODELVIEW); + gGL.popMatrix(); + 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 ); + // 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() - gAgentCamera.getCameraPositionGlobal(); + LLVector3d relative_object = clicked_object->getPositionGlobal() - gAgentCamera.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(); + // 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 += gAgentCamera.getCameraPositionGlobal(); + LLVector3d new_pos; + new_pos.setVec(mouse_direction_global); + // transform mouse vector back to world coords + new_pos += gAgentCamera.getCameraPositionGlobal(); - return new_pos; + return new_pos; } bool LLViewerWindow::clickPointOnSurfaceGlobal(const S32 x, const S32 y, LLViewerObject *objectp, LLVector3d &point_global) const { - bool intersect = false; + bool intersect = false; -// U8 shape = objectp->mPrimitiveCode & LL_PCODE_BASE_MASK; - if (!intersect) - { - point_global = clickPointInWorldGlobal(x, y, objectp); - LL_INFOS() << "approx intersection at " << (objectp->getPositionGlobal() - point_global) << LL_ENDL; - } - else - { - LL_INFOS() << "good intersection at " << (objectp->getPositionGlobal() - point_global) << LL_ENDL; - } +// U8 shape = objectp->mPrimitiveCode & LL_PCODE_BASE_MASK; + if (!intersect) + { + point_global = clickPointInWorldGlobal(x, y, objectp); + LL_INFOS() << "approx intersection at " << (objectp->getPositionGlobal() - point_global) << LL_ENDL; + } + else + { + LL_INFOS() << "good intersection at " << (objectp->getPositionGlobal() - point_global) << LL_ENDL; + } - return intersect; + return intersect; } void LLViewerWindow::pickAsync( S32 x, - S32 y_from_bot, - MASK mask, - void (*callback)(const LLPickInfo& info), - bool pick_transparent, - bool pick_rigged, - bool pick_unselectable, + S32 y_from_bot, + MASK mask, + void (*callback)(const LLPickInfo& info), + bool pick_transparent, + bool pick_rigged, + bool pick_unselectable, bool pick_reflection_probes) { - // "Show Debug Alpha" means no object actually transparent + // "Show Debug Alpha" means no object actually transparent bool in_build_mode = LLFloaterReg::instanceVisible("build"); if (LLDrawPoolAlpha::sShowDebugAlpha || (in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects"))) @@ -4258,587 +4271,587 @@ void LLViewerWindow::pickAsync( S32 x, pick_transparent = true; } - LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, false, pick_reflection_probes, pick_unselectable, true, callback); - schedulePick(pick_info); + LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, false, pick_reflection_probes, pick_unselectable, 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(); + 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 (!mPicks.empty()) - { - std::vector<LLPickInfo>::iterator pick_it; - for (pick_it = mPicks.begin(); pick_it != mPicks.end(); ++pick_it) - { - pick_it->fetchResults(); - } + 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(); - } + 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(); + 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, bool pick_rigged, bool pick_particle, bool pick_unselectable, bool pick_reflection_probe) { - bool in_build_mode = LLFloaterReg::instanceVisible("build"); - if ((in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects")) || 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 - MASK key_mask = gKeyboard->currentMask(true); - mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, pick_rigged, pick_particle, pick_reflection_probe, true, false, NULL); - mLastPick.fetchResults(); + bool in_build_mode = LLFloaterReg::instanceVisible("build"); + if ((in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects")) || 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 + MASK key_mask = gKeyboard->currentMask(true); + mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, pick_rigged, pick_particle, pick_reflection_probe, true, false, NULL); + mLastPick.fetchResults(); - return mLastPick; + return mLastPick; } LLHUDIcon* LLViewerWindow::cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth, - LLVector4a* intersection) + LLVector4a* intersection) { - S32 x = mouse_x; - S32 y = mouse_y; + S32 x = mouse_x; + S32 y = mouse_y; - if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position - { - x = getCurrentMouseX(); - y = getCurrentMouseY(); - } + if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position + { + x = getCurrentMouseX(); + y = getCurrentMouseY(); + } + + // world coordinates of mouse + // VECTORIZE THIS + 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; - // world coordinates of mouse - // VECTORIZE THIS - 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; + LLVector4a start, end; + start.load3(mouse_world_start.mV); + end.load3(mouse_world_end.mV); - LLVector4a start, end; - start.load3(mouse_world_start.mV); - end.load3(mouse_world_end.mV); - - return LLHUDIcon::lineSegmentIntersectAll(start, end, intersection); + return LLHUDIcon::lineSegmentIntersectAll(start, end, intersection); } LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth, - LLViewerObject *this_object, - S32 this_face, - bool pick_transparent, - bool pick_rigged, + LLViewerObject *this_object, + S32 this_face, + bool pick_transparent, + bool pick_rigged, bool pick_unselectable, bool pick_reflection_probe, - S32* face_hit, + S32* face_hit, S32* gltf_node_hit, S32* gltf_primitive_hit, - LLVector4a *intersection, - LLVector2 *uv, - LLVector4a *normal, - LLVector4a *tangent, - LLVector4a* start, - LLVector4a* end) -{ - 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; - - if (!LLViewerJoystick::getInstance()->getOverrideCamera()) - { //always set raycast intersection to mouse_world_end unless - //flycam is on (for DoF effect) - gDebugRaycastIntersection.load3(mouse_world_end.mV); - } - - LLVector4a mw_start; - mw_start.load3(mouse_world_start.mV); - LLVector4a mw_end; - mw_end.load3(mouse_world_end.mV); - - LLVector4a mh_start; - mh_start.load3(mouse_hud_start.mV); - LLVector4a mh_end; - mh_end.load3(mouse_hud_end.mV); - - if (start) - { - *start = mw_start; - } - - if (end) - { - *end = mw_end; - } - - LLViewerObject* found = NULL; - - if (this_object) // check only this object - { - if (this_object->isHUDAttachment()) // is a HUD object? - { - if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, pick_rigged, pick_unselectable, - face_hit, intersection, uv, normal, tangent)) - { - found = this_object; - } - } - else // is a world object - { + LLVector4a *intersection, + LLVector2 *uv, + LLVector4a *normal, + LLVector4a *tangent, + LLVector4a* start, + LLVector4a* end) +{ + 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; + + if (!LLViewerJoystick::getInstance()->getOverrideCamera()) + { //always set raycast intersection to mouse_world_end unless + //flycam is on (for DoF effect) + gDebugRaycastIntersection.load3(mouse_world_end.mV); + } + + LLVector4a mw_start; + mw_start.load3(mouse_world_start.mV); + LLVector4a mw_end; + mw_end.load3(mouse_world_end.mV); + + LLVector4a mh_start; + mh_start.load3(mouse_hud_start.mV); + LLVector4a mh_end; + mh_end.load3(mouse_hud_end.mV); + + if (start) + { + *start = mw_start; + } + + if (end) + { + *end = mw_end; + } + + LLViewerObject* found = NULL; + + if (this_object) // check only this object + { + if (this_object->isHUDAttachment()) // is a HUD object? + { + if (this_object->lineSegmentIntersect(mh_start, mh_end, this_face, pick_transparent, pick_rigged, pick_unselectable, + face_hit, intersection, uv, normal, tangent)) + { + found = this_object; + } + } + else // is a world object + { if ((pick_reflection_probe || !this_object->isReflectionProbe()) && this_object->lineSegmentIntersect(mw_start, mw_end, this_face, pick_transparent, pick_rigged, pick_unselectable, - face_hit, intersection, uv, normal, tangent)) - { - found = this_object; - } - } - } - else // check ALL objects - { - found = gPipeline.lineSegmentIntersectInHUD(mh_start, mh_end, pick_transparent, - face_hit, intersection, uv, normal, tangent); - - if (!found) // if not found in HUD, look in world: - { - found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, - face_hit, gltf_node_hit, gltf_primitive_hit, intersection, uv, normal, tangent); - if (found && !pick_transparent) - { - gDebugRaycastIntersection = *intersection; - } - } - } - - return found; + face_hit, intersection, uv, normal, tangent)) + { + found = this_object; + } + } + } + else // check ALL objects + { + found = gPipeline.lineSegmentIntersectInHUD(mh_start, mh_end, pick_transparent, + face_hit, intersection, uv, normal, tangent); + + if (!found) // if not found in HUD, look in world: + { + found = gPipeline.lineSegmentIntersectInWorld(mw_start, mw_end, pick_transparent, pick_rigged, pick_unselectable, pick_reflection_probe, + face_hit, gltf_node_hit, gltf_primitive_hit, intersection, uv, normal, tangent); + if (found && !pick_transparent) + { + gDebugRaycastIntersection = *intersection; + } + } + } + + 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 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(); + // 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 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; + // 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(); + // compute mouse vector + LLVector3 mouse_vector = distance * LLViewerCamera::getInstance()->getAtAxis() + - click_x * LLViewerCamera::getInstance()->getLeftAxis() + + click_y * LLViewerCamera::getInstance()->getUpAxis(); - mouse_vector.normVec(); + mouse_vector.normVec(); - return mouse_vector; + return mouse_vector; } LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const { - // find screen resolution - S32 height = getWorldViewHeightScaled(); + // find screen resolution + S32 height = getWorldViewHeightScaled(); - // find world view center - F32 center_x = getWorldViewRectScaled().getCenterX(); - F32 center_y = getWorldViewRectScaled().getCenterY(); + // 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; + // 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/gAgentCamera.mHUDCurZoom, hud_y/gAgentCamera.mHUDCurZoom); + return LLVector3(0.f, hud_x/gAgentCamera.mHUDCurZoom, hud_y/gAgentCamera.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 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 screen resolution + S32 height = getWorldViewHeightScaled(); + S32 width = getWorldViewWidthScaled(); - // find world view center - F32 center_x = getWorldViewRectScaled().getCenterX(); - F32 center_y = getWorldViewRectScaled().getCenterY(); + // 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; + // 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); + // 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]); + mouse_vector = mouse_vector * mouse_rotate; + // project to z = -1 plane; + mouse_vector = mouse_vector * (-1.f / mouse_vector.mV[VZ]); - return mouse_vector; + return mouse_vector; } -bool LLViewerWindow::mousePointOnPlaneGlobal(LLVector3d& point, const S32 x, const S32 y, - const LLVector3d &plane_point_global, - const LLVector3 &plane_normal_global) +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; + 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 - gAgentCamera.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); - } + 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 - gAgentCamera.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 = gAgentCamera.getCameraPositionGlobal() + mouse_look_at_scale * mouse_direction_global_d; + point = gAgentCamera.getCameraPositionGlobal() + mouse_look_at_scale * mouse_direction_global_d; - return mouse_look_at_scale > 0.0; + return mouse_look_at_scale > 0.0; } // Returns global position bool LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d *land_position_global, bool ignore_distance) { - 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 - const F32 draw_distance = ignore_distance ? MAX_FAR_CLIP : gAgentCamera.mDrawDistance; - LLVector3d camera_pos_global; - - camera_pos_global = gAgentCamera.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 < draw_distance; 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)) - { - //LL_INFOS() << "LLViewerWindow::mousePointOnLand probe_point is out of region" << LL_ENDL; - continue; - } - - land_z = regionp->getLand().resolveHeightRegion(probe_point_region); - - //LL_INFOS() << "mousePointOnLand initial z " << land_z << LL_ENDL; - - 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)) - { - // LL_INFOS() << "LLViewerWindow::mousePointOnLand probe_point is out of region" << LL_ENDL; - continue; - } - land_z = regionp->getLand().mSurfaceZ[ i + j * (regionp->getLand().mGridsPerEdge) ]; - */ - - land_z = regionp->getLand().resolveHeightRegion(probe_point_region); - - //LL_INFOS() << "mousePointOnLand refine z " << land_z << LL_ENDL; - - if (probe_point_region.mV[VZ] < land_z) - { - // ...just went under land again - - *land_position_global = probe_point_global; - return true; - } - } - } - - return false; + 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 + const F32 draw_distance = ignore_distance ? MAX_FAR_CLIP : gAgentCamera.mDrawDistance; + LLVector3d camera_pos_global; + + camera_pos_global = gAgentCamera.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 < draw_distance; 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)) + { + //LL_INFOS() << "LLViewerWindow::mousePointOnLand probe_point is out of region" << LL_ENDL; + continue; + } + + land_z = regionp->getLand().resolveHeightRegion(probe_point_region); + + //LL_INFOS() << "mousePointOnLand initial z " << land_z << LL_ENDL; + + 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)) + { + // LL_INFOS() << "LLViewerWindow::mousePointOnLand probe_point is out of region" << LL_ENDL; + continue; + } + land_z = regionp->getLand().mSurfaceZ[ i + j * (regionp->getLand().mGridsPerEdge) ]; + */ + + land_z = regionp->getLand().resolveHeightRegion(probe_point_region); + + //LL_INFOS() << "mousePointOnLand refine z " << land_z << LL_ENDL; + + 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. void LLViewerWindow::saveImageNumbered(LLImageFormatted *image, bool force_picker, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { - if (!image) - { - LL_WARNS() << "No image to save" << LL_ENDL; - return; - } - std::string extension("." + image->getExtension()); - LLImageFormatted* formatted_image = image; - // Get a base file location if needed. - if (force_picker || !isSnapshotLocSet()) - { - std::string proposed_name(sSnapshotBaseName); - - // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in. - LLFilePicker::ESaveFilter pick_type; - - 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; - - LLFilePickerReplyThread::startPicker(boost::bind(&LLViewerWindow::onDirectorySelected, this, _1, formatted_image, success_cb, failure_cb), pick_type, proposed_name, - boost::bind(&LLViewerWindow::onSelectionFailure, this, failure_cb)); - } - else - { - saveImageLocal(formatted_image, success_cb, failure_cb); - } + if (!image) + { + LL_WARNS() << "No image to save" << LL_ENDL; + return; + } + std::string extension("." + image->getExtension()); + LLImageFormatted* formatted_image = image; + // Get a base file location if needed. + if (force_picker || !isSnapshotLocSet()) + { + std::string proposed_name(sSnapshotBaseName); + + // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in. + LLFilePicker::ESaveFilter pick_type; + + 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; + + LLFilePickerReplyThread::startPicker(boost::bind(&LLViewerWindow::onDirectorySelected, this, _1, formatted_image, success_cb, failure_cb), pick_type, proposed_name, + boost::bind(&LLViewerWindow::onSelectionFailure, this, failure_cb)); + } + else + { + saveImageLocal(formatted_image, success_cb, failure_cb); + } } void LLViewerWindow::onDirectorySelected(const std::vector<std::string>& filenames, LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { - // Copy the directory + file name - std::string filepath = filenames[0]; + // Copy the directory + file name + std::string filepath = filenames[0]; - gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filepath, true)); - gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filepath)); - saveImageLocal(image, success_cb, failure_cb); + gSavedPerAccountSettings.setString("SnapshotBaseName", gDirUtilp->getBaseFileName(filepath, true)); + gSavedPerAccountSettings.setString("SnapshotBaseDir", gDirUtilp->getDirName(filepath)); + saveImageLocal(image, success_cb, failure_cb); } void LLViewerWindow::onSelectionFailure(const snapshot_saved_signal_t::slot_type& failure_cb) { - failure_cb(); + failure_cb(); } void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_saved_signal_t::slot_type& success_cb, const snapshot_saved_signal_t::slot_type& failure_cb) { - std::string lastSnapshotDir = LLViewerWindow::getLastSnapshotDir(); - if (lastSnapshotDir.empty()) - { - failure_cb(); - return; - } + std::string lastSnapshotDir = LLViewerWindow::getLastSnapshotDir(); + if (lastSnapshotDir.empty()) + { + failure_cb(); + return; + } // Check if there is enough free space to save snapshot #ifdef LL_WINDOWS - boost::filesystem::path b_path(utf8str_to_utf16str(lastSnapshotDir)); + boost::filesystem::path b_path(utf8str_to_utf16str(lastSnapshotDir)); #else - boost::filesystem::path b_path(lastSnapshotDir); + boost::filesystem::path b_path(lastSnapshotDir); #endif - if (!boost::filesystem::is_directory(b_path)) - { - LLSD args; - args["PATH"] = lastSnapshotDir; - LLNotificationsUtil::add("SnapshotToLocalDirNotExist", args); - resetSnapshotLoc(); - failure_cb(); - return; - } - boost::filesystem::space_info b_space = boost::filesystem::space(b_path); - if (b_space.free < image->getDataSize()) - { - LLSD args; - args["PATH"] = lastSnapshotDir; - - std::string needM_bytes_string; - LLResMgr::getInstance()->getIntegerString(needM_bytes_string, (image->getDataSize()) >> 10); - args["NEED_MEMORY"] = needM_bytes_string; - - std::string freeM_bytes_string; - LLResMgr::getInstance()->getIntegerString(freeM_bytes_string, (b_space.free) >> 10); - args["FREE_MEMORY"] = freeM_bytes_string; - - LLNotificationsUtil::add("SnapshotToComputerFailed", args); - - failure_cb(); - } - - // Look for an unused file name - bool is_snapshot_name_loc_set = isSnapshotLocSet(); - std::string filepath; - S32 i = 1; - S32 err = 0; - std::string extension("." + image->getExtension()); - do - { - filepath = sSnapshotDir; - filepath += gDirUtilp->getDirDelimiter(); - filepath += sSnapshotBaseName; - - if (is_snapshot_name_loc_set) - { - 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). - && is_snapshot_name_loc_set); // Or stop if we are rewriting. - - LL_INFOS() << "Saving snapshot to " << filepath << LL_ENDL; - if (image->save(filepath)) - { - playSnapshotAnimAndSound(); - success_cb(); - } - else - { - failure_cb(); - } + if (!boost::filesystem::is_directory(b_path)) + { + LLSD args; + args["PATH"] = lastSnapshotDir; + LLNotificationsUtil::add("SnapshotToLocalDirNotExist", args); + resetSnapshotLoc(); + failure_cb(); + return; + } + boost::filesystem::space_info b_space = boost::filesystem::space(b_path); + if (b_space.free < image->getDataSize()) + { + LLSD args; + args["PATH"] = lastSnapshotDir; + + std::string needM_bytes_string; + LLResMgr::getInstance()->getIntegerString(needM_bytes_string, (image->getDataSize()) >> 10); + args["NEED_MEMORY"] = needM_bytes_string; + + std::string freeM_bytes_string; + LLResMgr::getInstance()->getIntegerString(freeM_bytes_string, (b_space.free) >> 10); + args["FREE_MEMORY"] = freeM_bytes_string; + + LLNotificationsUtil::add("SnapshotToComputerFailed", args); + + failure_cb(); + } + + // Look for an unused file name + bool is_snapshot_name_loc_set = isSnapshotLocSet(); + std::string filepath; + S32 i = 1; + S32 err = 0; + std::string extension("." + image->getExtension()); + do + { + filepath = sSnapshotDir; + filepath += gDirUtilp->getDirDelimiter(); + filepath += sSnapshotBaseName; + + if (is_snapshot_name_loc_set) + { + 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). + && is_snapshot_name_loc_set); // Or stop if we are rewriting. + + LL_INFOS() << "Saving snapshot to " << filepath << LL_ENDL; + if (image->save(filepath)) + { + playSnapshotAnimAndSound(); + success_cb(); + } + else + { + failure_cb(); + } } void LLViewerWindow::resetSnapshotLoc() { - gSavedPerAccountSettings.setString("SnapshotBaseDir", std::string()); + gSavedPerAccountSettings.setString("SnapshotBaseDir", std::string()); } // static void LLViewerWindow::movieSize(S32 new_width, S32 new_height) { - LLCoordWindow size; - LLCoordWindow new_size(new_width, new_height); - gViewerWindow->getWindow()->getSize(&size); - if ( size != new_size ) - { - gViewerWindow->getWindow()->setSize(new_size); - } + LLCoordWindow size; + LLCoordWindow new_size(new_width, new_height); + gViewerWindow->getWindow()->getSize(&size); + if ( size != new_size ) + { + gViewerWindow->getWindow()->setSize(new_size); + } } bool LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, bool show_ui, bool show_hud, bool do_rebuild, LLSnapshotModel::ESnapshotLayerType type, LLSnapshotModel::ESnapshotFormat format) @@ -4886,351 +4899,351 @@ bool LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, 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); + if (gSavedSettings.getBOOL("QuietSnapshotsToDisk")) + { + return; + } + gAgent.sendAnimationRequest(ANIM_AGENT_SNAPSHOT, ANIM_REQUEST_START); + send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f); } bool LLViewerWindow::isSnapshotLocSet() const { - std::string snapshot_dir = sSnapshotDir; - return !snapshot_dir.empty(); + std::string snapshot_dir = sSnapshotDir; + return !snapshot_dir.empty(); } void LLViewerWindow::resetSnapshotLoc() const { - gSavedPerAccountSettings.setString("SnapshotBaseDir", std::string()); + gSavedPerAccountSettings.setString("SnapshotBaseDir", std::string()); } bool LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, bool show_ui, bool show_hud, bool do_rebuild, bool no_post, LLSnapshotModel::ESnapshotLayerType type) { - return rawSnapshot(raw, preview_width, preview_height, false, false, show_ui, show_hud, do_rebuild, no_post, type); + return rawSnapshot(raw, preview_width, preview_height, false, false, show_ui, show_hud, do_rebuild, no_post, type); } // Saves the image from the screen to a raw image // Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy // the results over to the final raw image. -bool LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, +bool LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, bool keep_window_aspect, bool is_texture, bool show_ui, bool show_hud, bool do_rebuild, bool no_post, LLSnapshotModel::ESnapshotLayerType type, S32 max_size) { - if (!raw) - { - return false; - } - - //check if there is enough memory for the snapshot image - if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K - { - if(!LLMemory::tryToAlloc(NULL, image_width * image_height * 3)) - { - LL_WARNS() << "No enough memory to take the snapshot with size (w : h): " << image_width << " : " << image_height << LL_ENDL ; - return false ; //there is no enough memory for taking this snapshot. - } - } - - // PRE SNAPSHOT - gSnapshotNoPost = no_post; - gDisplaySwapBuffers = false; - + if (!raw) + { + return false; + } + + //check if there is enough memory for the snapshot image + if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K + { + if(!LLMemory::tryToAlloc(NULL, image_width * image_height * 3)) + { + LL_WARNS() << "No enough memory to take the snapshot with size (w : h): " << image_width << " : " << image_height << LL_ENDL ; + return false ; //there is no enough memory for taking this snapshot. + } + } + + // PRE SNAPSHOT + gSnapshotNoPost = no_post; + gDisplaySwapBuffers = false; + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT); - setCursor(UI_CURSOR_WAIT); + 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); + // 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(LLPipeline::RENDER_DEBUG_FEATURE_UI); - } + if ( prev_draw_ui != show_ui) + { + LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); + } bool hide_hud = !show_hud && LLPipeline::sShowHUDAttachments; - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = false; - } - - // if not showing ui, use full window to render world view - updateWorldViewRect(!show_ui); - - // Copy screen to a buffer - // crop sides or top and bottom, if taking a snapshot of different aspect ratio - // from window - LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); - - S32 snapshot_width = window_rect.getWidth(); - S32 snapshot_height = window_rect.getHeight(); - // SNAPSHOT - S32 window_width = snapshot_width; - S32 window_height = snapshot_height; - - // Note: Scaling of the UI is currently *not* supported so we limit the output size if UI is requested - if (show_ui) - { - // If the user wants the UI, limit the output size to the available screen size - image_width = llmin(image_width, window_width); - image_height = llmin(image_height, window_height); - } - - S32 original_width = 0; - S32 original_height = 0; - bool reset_deferred = false; - - LLRenderTarget scratch_space; - - F32 scale_factor = 1.0f ; - if (!keep_window_aspect || (image_width > window_width) || (image_height > window_height)) - { - if ((image_width <= gGLManager.mGLMaxTextureSize && image_height <= gGLManager.mGLMaxTextureSize) && - (image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui) - { - U32 color_fmt = type == LLSnapshotModel::SNAPSHOT_TYPE_DEPTH ? GL_DEPTH_COMPONENT : GL_RGBA; - if (scratch_space.allocate(image_width, image_height, color_fmt, true)) - { - original_width = gPipeline.mRT->deferredScreen.getWidth(); - original_height = gPipeline.mRT->deferredScreen.getHeight(); - - if (gPipeline.allocateScreenBuffer(image_width, image_height)) - { - window_width = image_width; - window_height = image_height; - snapshot_width = image_width; - snapshot_height = image_height; - reset_deferred = true; - mWorldViewRectRaw.set(0, image_height, image_width, 0); - LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); - LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); - scratch_space.bindTarget(); - } - else - { - scratch_space.release(); - gPipeline.allocateScreenBuffer(original_width, original_height); - } - } - } - - if (!reset_deferred) - { - // if image cropping or need to enlarge the scene, compute a scale_factor - 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) ; - } - } - - if (show_ui && scale_factor > 1.f) - { - // Note: we should never get there... - LL_WARNS() << "over scaling UI not supported." << LL_ENDL; - } - - 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) ; - } - - LLImageDataLock lock(raw); - - if ((image_buffer_x > 0) && (image_buffer_y > 0)) - { - raw->resize(image_buffer_x, image_buffer_y, 3); - } - else - { - return false; - } - - 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 && show_ui) - { - // Note: we should never get there... - LL_WARNS() << "High res UI snapshot not supported. " << LL_ENDL; - /*send_agent_pause(); - //rescale fonts - initFonts(scale_factor); - LLHUDObject::reshapeAll();*/ - } - - 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()); - - // Subimages are in fact partial rendering of the final view. This happens when the final view is bigger than the screen. - // In most common cases, scale_factor is 1 and there's no more than 1 iteration on x and y - 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; - - 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()))); - - // Skip rendering and sampling altogether if either width or height is degenerated to 0 (common in cropping cases) - if (read_width && read_height) - { - const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor)); - display(do_rebuild, scale_factor, subfield, true); - - if (!LLPipeline::sRenderDeferred) - { - // Required for showing the GUI in snapshots and performing bloom composite overlay - // Call even if show_ui is false - render_ui(scale_factor, subfield); - swap(); - } - - 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 watchdog thread every 100 lines to keep us alive (arbitrary number, feel free to change) - if (out_y % 100 == 0) - { - LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot"); - } - // disable use of glReadPixels when doing nVidia nSight graphics debugging - if (!LLRender::sNsightDebugSupport) - { - if (type == LLSnapshotModel::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 // LLSnapshotModel::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; - } - - gDisplaySwapBuffers = false; - gSnapshotNoPost = false; - gDepthDirty = true; - - // POST SNAPSHOT - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = true; - } - - /*if (high_res) - { - initFonts(1.f); - LLHUDObject::reshapeAll(); - }*/ - - // 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 (reset_deferred) - { - mWorldViewRectRaw = window_rect; - LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); - LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); - scratch_space.flush(); - scratch_space.release(); - gPipeline.allocateScreenBuffer(original_width, original_height); - - } - - if (high_res) - { - send_agent_resume(); - } - - return ret; + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = false; + } + + // if not showing ui, use full window to render world view + updateWorldViewRect(!show_ui); + + // Copy screen to a buffer + // crop sides or top and bottom, if taking a snapshot of different aspect ratio + // from window + LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); + + S32 snapshot_width = window_rect.getWidth(); + S32 snapshot_height = window_rect.getHeight(); + // SNAPSHOT + S32 window_width = snapshot_width; + S32 window_height = snapshot_height; + + // Note: Scaling of the UI is currently *not* supported so we limit the output size if UI is requested + if (show_ui) + { + // If the user wants the UI, limit the output size to the available screen size + image_width = llmin(image_width, window_width); + image_height = llmin(image_height, window_height); + } + + S32 original_width = 0; + S32 original_height = 0; + bool reset_deferred = false; + + LLRenderTarget scratch_space; + + F32 scale_factor = 1.0f ; + if (!keep_window_aspect || (image_width > window_width) || (image_height > window_height)) + { + if ((image_width <= gGLManager.mGLMaxTextureSize && image_height <= gGLManager.mGLMaxTextureSize) && + (image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui) + { + U32 color_fmt = type == LLSnapshotModel::SNAPSHOT_TYPE_DEPTH ? GL_DEPTH_COMPONENT : GL_RGBA; + if (scratch_space.allocate(image_width, image_height, color_fmt, true)) + { + original_width = gPipeline.mRT->deferredScreen.getWidth(); + original_height = gPipeline.mRT->deferredScreen.getHeight(); + + if (gPipeline.allocateScreenBuffer(image_width, image_height)) + { + window_width = image_width; + window_height = image_height; + snapshot_width = image_width; + snapshot_height = image_height; + reset_deferred = true; + mWorldViewRectRaw.set(0, image_height, image_width, 0); + LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); + LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); + scratch_space.bindTarget(); + } + else + { + scratch_space.release(); + gPipeline.allocateScreenBuffer(original_width, original_height); + } + } + } + + if (!reset_deferred) + { + // if image cropping or need to enlarge the scene, compute a scale_factor + 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) ; + } + } + + if (show_ui && scale_factor > 1.f) + { + // Note: we should never get there... + LL_WARNS() << "over scaling UI not supported." << LL_ENDL; + } + + 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) ; + } + + LLImageDataLock lock(raw); + + if ((image_buffer_x > 0) && (image_buffer_y > 0)) + { + raw->resize(image_buffer_x, image_buffer_y, 3); + } + else + { + return false; + } + + 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 && show_ui) + { + // Note: we should never get there... + LL_WARNS() << "High res UI snapshot not supported. " << LL_ENDL; + /*send_agent_pause(); + //rescale fonts + initFonts(scale_factor); + LLHUDObject::reshapeAll();*/ + } + + 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()); + + // Subimages are in fact partial rendering of the final view. This happens when the final view is bigger than the screen. + // In most common cases, scale_factor is 1 and there's no more than 1 iteration on x and y + 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; + + 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()))); + + // Skip rendering and sampling altogether if either width or height is degenerated to 0 (common in cropping cases) + if (read_width && read_height) + { + const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor)); + display(do_rebuild, scale_factor, subfield, true); + + if (!LLPipeline::sRenderDeferred) + { + // Required for showing the GUI in snapshots and performing bloom composite overlay + // Call even if show_ui is false + render_ui(scale_factor, subfield); + swap(); + } + + 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 watchdog thread every 100 lines to keep us alive (arbitrary number, feel free to change) + if (out_y % 100 == 0) + { + LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot"); + } + // disable use of glReadPixels when doing nVidia nSight graphics debugging + if (!LLRender::sNsightDebugSupport) + { + if (type == LLSnapshotModel::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 // LLSnapshotModel::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; + } + + gDisplaySwapBuffers = false; + gSnapshotNoPost = false; + gDepthDirty = true; + + // POST SNAPSHOT + if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + LLPipeline::toggleRenderDebugFeature(LLPipeline::RENDER_DEBUG_FEATURE_UI); + } + + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = true; + } + + /*if (high_res) + { + initFonts(1.f); + LLHUDObject::reshapeAll(); + }*/ + + // 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 (reset_deferred) + { + mWorldViewRectRaw = window_rect; + LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRectRaw.getHeight() ); + LLViewerCamera::getInstance()->setAspect( getWorldViewAspectRatio() ); + scratch_space.flush(); + scratch_space.release(); + gPipeline.allocateScreenBuffer(original_width, original_height); + + } + + if (high_res) + { + send_agent_resume(); + } + + return ret; } bool LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_height, const int num_render_passes) @@ -5248,10 +5261,10 @@ bool LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ } bool hide_hud = LLPipeline::sShowHUDAttachments; - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = false; - } + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = false; + } LLRect window_rect = getWorldViewRectRaw(); @@ -5276,8 +5289,8 @@ bool LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ } // we render the scene more than once since this helps - // greatly with the objects not being drawn in the - // snapshot when they are drawn in the scene. This is + // greatly with the objects not being drawn in the + // snapshot when they are drawn in the scene. This is // evident when you set this value via the debug setting // called 360CaptureNumRenderPasses to 1. The theory is // that the missing objects are caused by the sUseOcclusion @@ -5324,10 +5337,10 @@ bool LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_ } } - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = true; - } + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = true; + } setCursor(UI_CURSOR_ARROW); @@ -5373,16 +5386,16 @@ bool LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea camera->setOrigin(origin); camera->setNear(near_clip); - LLPlane previousClipPlane; + LLPlane previousClipPlane; - if (useCustomClipPlane) - { + if (useCustomClipPlane) + { previousClipPlane = camera->getUserClipPlane(); camera->setUserClipPlane(clipPlane); - } + } glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // stencil buffer is deprecated | GL_STENCIL_BUFFER_BIT); - + U32 dynamic_render_types[] = { LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::RENDER_TYPE_CONTROL_AV, @@ -5411,10 +5424,10 @@ bool LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea } bool hide_hud = LLPipeline::sShowHUDAttachments; - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = false; - } + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = false; + } LLRect window_rect = getWorldViewRectRaw(); mWorldViewRectRaw.set(0, res, res, 0); @@ -5480,19 +5493,19 @@ bool LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea } } - if (hide_hud) - { - LLPipeline::sShowHUDAttachments = true; - } + if (hide_hud) + { + LLPipeline::sShowHUDAttachments = true; + } gPipeline.resetDrawOrders(); mWorldViewRectRaw = window_rect; - if (useCustomClipPlane) - { + if (useCustomClipPlane) + { camera->setUserClipPlane(previousClipPlane); - } - + } + // restore original view/camera/avatar settings settings *camera = saved_camera; set_current_modelview(saved_mod); @@ -5506,138 +5519,138 @@ bool LLViewerWindow::cubeSnapshot(const LLVector3& origin, LLCubeMapArray* cubea void LLViewerWindow::destroyWindow() { - if (mWindow) - { - LLWindowManager::destroyWindow(mWindow); - } - mWindow = NULL; + 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; + // 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); + 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(); + return mWindow->getPlatformWindow(); } -void* LLViewerWindow::getMediaWindow() const +void* LLViewerWindow::getMediaWindow() const { - return mWindow->getMediaWindow(); + return mWindow->getMediaWindow(); } -void LLViewerWindow::focusClient() const +void LLViewerWindow::focusClient() const { - return mWindow->focusClient(); + return mWindow->focusClient(); } -LLRootView* LLViewerWindow::getRootView() const +LLRootView* LLViewerWindow::getRootView() const { - return mRootView; + return mRootView; } LLRect LLViewerWindow::getWorldViewRectScaled() const { - return mWorldViewRectScaled; + return mWorldViewRectScaled; } S32 LLViewerWindow::getWorldViewHeightScaled() const { - return mWorldViewRectScaled.getHeight(); + return mWorldViewRectScaled.getHeight(); } S32 LLViewerWindow::getWorldViewWidthScaled() const { - return mWorldViewRectScaled.getWidth(); + return mWorldViewRectScaled.getWidth(); } S32 LLViewerWindow::getWorldViewHeightRaw() const { - return mWorldViewRectRaw.getHeight(); + return mWorldViewRectRaw.getHeight(); } S32 LLViewerWindow::getWorldViewWidthRaw() const { - return mWorldViewRectRaw.getWidth(); + return mWorldViewRectRaw.getWidth(); } -S32 LLViewerWindow::getWindowHeightScaled() const -{ - return mWindowRectScaled.getHeight(); +S32 LLViewerWindow::getWindowHeightScaled() const +{ + return mWindowRectScaled.getHeight(); } -S32 LLViewerWindow::getWindowWidthScaled() const -{ - return mWindowRectScaled.getWidth(); +S32 LLViewerWindow::getWindowWidthScaled() const +{ + return mWindowRectScaled.getWidth(); } -S32 LLViewerWindow::getWindowHeightRaw() const -{ - return mWindowRectRaw.getHeight(); +S32 LLViewerWindow::getWindowHeightRaw() const +{ + return mWindowRectRaw.getHeight(); } -S32 LLViewerWindow::getWindowWidthRaw() const -{ - return mWindowRectRaw.getWidth(); +S32 LLViewerWindow::getWindowWidthRaw() const +{ + return mWindowRectRaw.getWidth(); } void LLViewerWindow::setup2DRender() { - // setup ortho camera - gl_state_for_2d(mWindowRectRaw.getWidth(), mWindowRectRaw.getHeight()); - setup2DViewport(); + // 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]); + 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(); + // 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) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI - 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]); + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI + 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::revealIntroPanel() { - if (mProgressView) - { - mProgressView->revealIntroPanel(); - } + if (mProgressView) + { + mProgressView->revealIntroPanel(); + } } void LLViewerWindow::initTextures(S32 location_id) @@ -5650,417 +5663,417 @@ void LLViewerWindow::initTextures(S32 location_id) void LLViewerWindow::setShowProgress(const bool show) { - if (mProgressView) - { - mProgressView->setVisible(show); - } + if (mProgressView) + { + mProgressView->setVisible(show); + } } void LLViewerWindow::setStartupComplete() { - if (mProgressView) - { - mProgressView->setStartupComplete(); - } + if (mProgressView) + { + mProgressView->setStartupComplete(); + } } bool LLViewerWindow::getShowProgress() const { - return (mProgressView && mProgressView->getVisible()); + return (mProgressView && mProgressView->getVisible()); } void LLViewerWindow::setProgressString(const std::string& string) { - if (mProgressView) - { - mProgressView->setText(string); - } + if (mProgressView) + { + mProgressView->setText(string); + } } void LLViewerWindow::setProgressMessage(const std::string& msg) { - if(mProgressView) - { - mProgressView->setMessage(msg); - } + if(mProgressView) + { + mProgressView->setMessage(msg); + } } void LLViewerWindow::setProgressPercent(const F32 percent) { - if (mProgressView) - { - mProgressView->setPercent(percent); - } + if (mProgressView) + { + mProgressView->setPercent(percent); + } } void LLViewerWindow::setProgressCancelButtonVisible( bool b, const std::string& label ) { - if (mProgressView) - { - mProgressView->setCancelButtonVisible( b, label ); - } + if (mProgressView) + { + mProgressView->setCancelButtonVisible( b, label ); + } } LLProgressView *LLViewerWindow::getProgressView() const { - return mProgressView; + return mProgressView; } void LLViewerWindow::dumpState() { - LL_INFOS() << "LLViewerWindow Active " << S32(mActive) << LL_ENDL; - LL_INFOS() << "mWindow visible " << S32(mWindow->getVisible()) - << " minimized " << S32(mWindow->getMinimized()) - << LL_ENDL; + LL_INFOS() << "LLViewerWindow Active " << S32(mActive) << LL_ENDL; + LL_INFOS() << "mWindow visible " << S32(mWindow->getVisible()) + << " minimized " << S32(mWindow->getMinimized()) + << LL_ENDL; } 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) - { - LL_INFOS() << "Shutting down GL..." << LL_ENDL; - - // Pause texture decode threads (will get unpaused during main loop) - LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getTextureFetch()->pause(); - - gSky.destroyGL(); - stop_glerror(); - - LLManipTranslate::destroyGL() ; - stop_glerror(); - - gBumpImageList.destroyGL(); - stop_glerror(); - - LLFontGL::destroyAllGL(); - stop_glerror(); - - LLVOAvatar::destroyGL(); - stop_glerror(); - - LLVOPartGroup::destroyGL(); - - LLViewerDynamicTexture::destroyGL(); - stop_glerror(); - - if (gPipeline.isInit()) - { - gPipeline.destroyGL(); - } - - gBox.cleanupGL(); - - if(gPostProcess) - { - gPostProcess->invalidate(); - } - - gTextureList.destroyGL(save_state); - stop_glerror(); - - gGLManager.mIsDisabled = true; - stop_glerror(); - - //unload shader's - while (LLGLSLShader::sInstances.size()) - { - LLGLSLShader* shader = *(LLGLSLShader::sInstances.begin()); - shader->unload(); - } - } + //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) + { + LL_INFOS() << "Shutting down GL..." << LL_ENDL; + + // Pause texture decode threads (will get unpaused during main loop) + LLAppViewer::getTextureCache()->pause(); + LLAppViewer::getTextureFetch()->pause(); + + gSky.destroyGL(); + stop_glerror(); + + LLManipTranslate::destroyGL() ; + stop_glerror(); + + gBumpImageList.destroyGL(); + stop_glerror(); + + LLFontGL::destroyAllGL(); + stop_glerror(); + + LLVOAvatar::destroyGL(); + stop_glerror(); + + LLVOPartGroup::destroyGL(); + + LLViewerDynamicTexture::destroyGL(); + stop_glerror(); + + if (gPipeline.isInit()) + { + gPipeline.destroyGL(); + } + + gBox.cleanupGL(); + + if(gPostProcess) + { + gPostProcess->invalidate(); + } + + gTextureList.destroyGL(save_state); + stop_glerror(); + + gGLManager.mIsDisabled = true; + stop_glerror(); + + //unload shader's + while (LLGLSLShader::sInstances.size()) + { + LLGLSLShader* shader = *(LLGLSLShader::sInstances.begin()); + shader->unload(); + } + } } 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) - { - LL_INFOS() << "Restoring GL..." << LL_ENDL; - 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(); - LLManipTranslate::restoreGL(); - - gBumpImageList.restoreGL(); - LLViewerDynamicTexture::restoreGL(); - LLVOAvatar::restoreGL(); - LLVOPartGroup::restoreGL(); - - gResizeScreenTexture = true; - gWindowResized = true; - - if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance()) - { - LLVisualParamHint::requestHintUpdates(); - } - - if (!progress_message.empty()) - { - gRestoreGLTimer.reset(); - gRestoreGL = true; - setShowProgress(true); - setProgressString(progress_message); - } - LL_INFOS() << "...Restoring GL done" << LL_ENDL; - if(!LLAppViewer::instance()->restoreErrorTrap()) - { - LL_WARNS() << " Someone took over my signal/exception handler (post restoreGL)!" << LL_ENDL; - } - - } + //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) + { + LL_INFOS() << "Restoring GL..." << LL_ENDL; + 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(); + LLManipTranslate::restoreGL(); + + gBumpImageList.restoreGL(); + LLViewerDynamicTexture::restoreGL(); + LLVOAvatar::restoreGL(); + LLVOPartGroup::restoreGL(); + + gResizeScreenTexture = true; + gWindowResized = true; + + if (isAgentAvatarValid() && gAgentAvatarp->isEditingAppearance()) + { + LLVisualParamHint::requestHintUpdates(); + } + + if (!progress_message.empty()) + { + gRestoreGLTimer.reset(); + gRestoreGL = true; + setShowProgress(true); + setProgressString(progress_message); + } + LL_INFOS() << "...Restoring GL done" << LL_ENDL; + if(!LLAppViewer::instance()->restoreErrorTrap()) + { + LL_WARNS() << " Someone took over my signal/exception handler (post restoreGL)!" << LL_ENDL; + } + + } } void LLViewerWindow::initFonts(F32 zoom_factor) { - LLFontGL::destroyAllGL(); - // Initialize with possibly different zoom factor + LLFontGL::destroyAllGL(); + // Initialize with possibly different zoom factor - LLFontManager::initClass(); + LLFontManager::initClass(); - LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), - mDisplayScale.mV[VX] * zoom_factor, - mDisplayScale.mV[VY] * zoom_factor, - gDirUtilp->getAppRODataDir()); + LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), + mDisplayScale.mV[VX] * zoom_factor, + mDisplayScale.mV[VY] * zoom_factor, + gDirUtilp->getAppRODataDir()); } void LLViewerWindow::requestResolutionUpdate() { - mResDirty = true; + mResDirty = true; } static LLTrace::BlockTimerStatHandle FTM_WINDOW_CHECK_SETTINGS("Window Settings"); void LLViewerWindow::checkSettings() { - LL_RECORD_BLOCK_TIME(FTM_WINDOW_CHECK_SETTINGS); - if (mStatesDirty) - { - gGL.refreshState(); - LLViewerShaderMgr::instance()->setShaders(); - mStatesDirty = false; - } - - // We want to update the resolution AFTER the states getting refreshed not before. - if (mResDirty) - { - reshape(getWindowWidthRaw(), getWindowHeightRaw()); - mResDirty = false; - } + LL_RECORD_BLOCK_TIME(FTM_WINDOW_CHECK_SETTINGS); + if (mStatesDirty) + { + gGL.refreshState(); + LLViewerShaderMgr::instance()->setShaders(); + mStatesDirty = false; + } + + // We want to update the resolution AFTER the states getting refreshed not before. + if (mResDirty) + { + reshape(getWindowWidthRaw(), getWindowHeightRaw()); + mResDirty = false; + } } void LLViewerWindow::restartDisplay(bool show_progress_bar) { - LL_INFOS() << "Restaring GL" << LL_ENDL; - stopGL(); - if (show_progress_bar) - { - restoreGL(LLTrans::getString("ProgressChangingResolution")); - } - else - { - restoreGL(); - } + LL_INFOS() << "Restaring GL" << LL_ENDL; + stopGL(); + if (show_progress_bar) + { + restoreGL(LLTrans::getString("ProgressChangingResolution")); + } + else + { + restoreGL(); + } } bool LLViewerWindow::changeDisplaySettings(LLCoordScreen size, bool enable_vsync, bool show_progress_bar) { - //bool was_maximized = gSavedSettings.getBOOL("WindowMaximized"); + //bool was_maximized = gSavedSettings.getBOOL("WindowMaximized"); - //gResizeScreenTexture = true; + //gResizeScreenTexture = true; - //U32 fsaa = gSavedSettings.getU32("RenderFSAASamples"); - //U32 old_fsaa = mWindow->getFSAASamples(); + //U32 fsaa = gSavedSettings.getU32("RenderFSAASamples"); + //U32 old_fsaa = mWindow->getFSAASamples(); - // if not maximized, use the request size - if (!mWindow->getMaximized()) - { - mWindow->setSize(size); - } + // if not maximized, use the request size + if (!mWindow->getMaximized()) + { + mWindow->setSize(size); + } - //if (fsaa == old_fsaa) - { - return true; - } + //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(); - LL_INFOS() << "Stopping GL during changeDisplaySettings" << LL_ENDL; - stopGL(); - mIgnoreActivate = true; - LLCoordScreen old_size; - LLCoordScreen old_pos; - mWindow->getSize(&old_size); - - //mWindow->setFSAASamples(fsaa); - - result_first_try = mWindow->switchContext(false, size, disable_vsync); - if (!result_first_try) - { - // try to switch back - //mWindow->setFSAASamples(old_fsaa); - result_second_try = mWindow->switchContext(false, 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(); - - LL_INFOS() << "Restoring GL during resolution change" << LL_ENDL; - if (show_progress_bar) - { - restoreGL(LLTrans::getString("ProgressChangingResolution")); - } - 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) - { - // 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); - - return success; - - */ -} - -F32 LLViewerWindow::getWorldViewAspectRatio() const -{ - F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight(); - return world_aspect; + // 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(); + LL_INFOS() << "Stopping GL during changeDisplaySettings" << LL_ENDL; + stopGL(); + mIgnoreActivate = true; + LLCoordScreen old_size; + LLCoordScreen old_pos; + mWindow->getSize(&old_size); + + //mWindow->setFSAASamples(fsaa); + + result_first_try = mWindow->switchContext(false, size, disable_vsync); + if (!result_first_try) + { + // try to switch back + //mWindow->setFSAASamples(old_fsaa); + result_second_try = mWindow->switchContext(false, 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(); + + LL_INFOS() << "Restoring GL during resolution change" << LL_ENDL; + if (show_progress_bar) + { + restoreGL(LLTrans::getString("ProgressChangingResolution")); + } + 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) + { + // 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); + + return success; + + */ +} + +F32 LLViewerWindow::getWorldViewAspectRatio() const +{ + F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight(); + return world_aspect; } void LLViewerWindow::calcDisplayScale() { - F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor") * mWindow->getSystemUISize(), MIN_UI_SCALE, MAX_UI_SCALE); - LLVector2 display_scale; - display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); - display_scale *= ui_scale_factor; + F32 ui_scale_factor = llclamp(gSavedSettings.getF32("UIScaleFactor") * mWindow->getSystemUISize(), MIN_UI_SCALE, MAX_UI_SCALE); + LLVector2 display_scale; + display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); + 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 (display_scale != mDisplayScale) - { - LL_INFOS() << "Setting display scale to " << display_scale << " for ui scale: " << ui_scale_factor << LL_ENDL; + // 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]); + } - mDisplayScale = display_scale; - // Init default fonts - initFonts(); - } + if (display_scale != mDisplayScale) + { + LL_INFOS() << "Setting display scale to " << display_scale << " for ui scale: " << ui_scale_factor << LL_ENDL; + + mDisplayScale = display_scale; + // Init default fonts + initFonts(); + } } //static -LLRect LLViewerWindow::calcScaledRect(const LLRect & rect, const LLVector2& display_scale) +LLRect LLViewerWindow::calcScaledRect(const LLRect & rect, const LLVector2& display_scale) { - LLRect res = rect; - res.mLeft = ll_round((F32)res.mLeft / display_scale.mV[VX]); - res.mRight = ll_round((F32)res.mRight / display_scale.mV[VX]); - res.mBottom = ll_round((F32)res.mBottom / display_scale.mV[VY]); - res.mTop = ll_round((F32)res.mTop / display_scale.mV[VY]); + LLRect res = rect; + res.mLeft = ll_round((F32)res.mLeft / display_scale.mV[VX]); + res.mRight = ll_round((F32)res.mRight / display_scale.mV[VX]); + res.mBottom = ll_round((F32)res.mBottom / display_scale.mV[VY]); + res.mTop = ll_round((F32)res.mTop / display_scale.mV[VY]); - return res; + return res; } S32 LLViewerWindow::getChatConsoleBottomPad() { - S32 offset = 0; + S32 offset = 0; - if(gToolBarView) - offset += gToolBarView->getBottomToolbar()->getRect().getHeight(); + if(gToolBarView) + offset += gToolBarView->getBottomToolbar()->getRect().getHeight(); - return offset; + return offset; } LLRect LLViewerWindow::getChatConsoleRect() { - LLRect full_window(0, getWindowHeightScaled(), getWindowWidthScaled(), 0); - LLRect console_rect = full_window; + 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; + 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.mTop -= CONSOLE_PADDING_TOP; + console_rect.mBottom += getChatConsoleBottomPad(); - console_rect.mLeft += CONSOLE_PADDING_LEFT; + console_rect.mLeft += CONSOLE_PADDING_LEFT; - static const bool CHAT_FULL_WIDTH = gSavedSettings.getBOOL("ChatFullWidth"); + 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; - } + 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; + return console_rect; } void LLViewerWindow::reshapeStatusBarContainer() @@ -6103,31 +6116,31 @@ void LLViewerWindow::resetStatusBarContainer() void LLViewerWindow::setUIVisibility(bool visible) { - mUIVisible = visible; + mUIVisible = visible; - if (!visible) - { - gAgentCamera.changeCameraToThirdPerson(false); - gFloaterView->hideAllFloaters(); - } - else - { - gFloaterView->showHiddenFloaters(); - } + if (!visible) + { + gAgentCamera.changeCameraToThirdPerson(false); + gFloaterView->hideAllFloaters(); + } + else + { + gFloaterView->showHiddenFloaters(); + } - if (gToolBarView) - { - gToolBarView->setToolBarsVisible(visible); - } + if (gToolBarView) + { + gToolBarView->setToolBarsVisible(visible); + } - LLNavigationBar::getInstance()->setVisible(visible ? gSavedSettings.getBOOL("ShowNavbarNavigationPanel") : false); - LLPanelTopInfoBar::getInstance()->setVisible(visible? gSavedSettings.getBOOL("ShowMiniLocationPanel") : false); - mRootView->getChildView("status_bar_container")->setVisible(visible); + LLNavigationBar::getInstance()->setVisible(visible ? gSavedSettings.getBOOL("ShowNavbarNavigationPanel") : false); + LLPanelTopInfoBar::getInstance()->setVisible(visible? gSavedSettings.getBOOL("ShowMiniLocationPanel") : false); + mRootView->getChildView("status_bar_container")->setVisible(visible); } bool LLViewerWindow::getUIVisibility() { - return mUIVisible; + return mUIVisible; } //////////////////////////////////////////////////////////////////////////// @@ -6135,22 +6148,22 @@ bool LLViewerWindow::getUIVisibility() // 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(), - mTangent(), - mBinormal(), - mHUDIcon(NULL), - mPickTransparent(false), - mPickRigged(false), - mPickParticle(false) + : 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(), + mTangent(), + mBinormal(), + mHUDIcon(NULL), + mPickTransparent(false), + mPickRigged(false), + mPickParticle(false) { } @@ -6180,236 +6193,236 @@ LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, mPickRigged(pick_rigged), mPickParticle(pick_particle), mPickReflectionProbe(pick_reflection_probe), - mPickUnselectable(pick_unselectable) + mPickUnselectable(pick_unselectable) { } void LLPickInfo::fetchResults() { - S32 face_hit = -1; + S32 face_hit = -1; + + LLVector4a intersection, normal; + LLVector4a tangent; - LLVector4a intersection, normal; - LLVector4a tangent; + LLVector2 uv; - LLVector2 uv; + LLHUDIcon* hit_icon = gViewerWindow->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f, &intersection); - LLHUDIcon* hit_icon = gViewerWindow->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f, &intersection); - - LLVector4a origin; - origin.load3(LLViewerCamera::getInstance()->getOrigin().mV); - F32 icon_dist = 0.f; - LLVector4a start; - LLVector4a end; - LLVector4a particle_end; + LLVector4a origin; + origin.load3(LLViewerCamera::getInstance()->getOrigin().mV); + F32 icon_dist = 0.f; + LLVector4a start; + LLVector4a end; + LLVector4a particle_end; - if (hit_icon) - { - LLVector4a delta; - delta.setSub(intersection, origin); - icon_dist = delta.getLength3().getF32(); - } + if (hit_icon) + { + LLVector4a delta; + delta.setSub(intersection, origin); + icon_dist = delta.getLength3().getF32(); + } - LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f, - nullptr, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, &face_hit, &mGLTFNodeIndex, &mGLTFPrimitiveIndex, + LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f, + nullptr, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, &face_hit, &mGLTFNodeIndex, &mGLTFPrimitiveIndex, &intersection, &uv, &normal, &tangent, &start, &end); - - mPickPt = mMousePt; - - U32 te_offset = face_hit > -1 ? face_hit : 0; - - if (mPickParticle) - { //get the end point of line segement to use for particle raycast - if (hit_object) - { - particle_end = intersection; - } - else - { - particle_end = end; - } - } - - LLViewerObject* objectp = hit_object; - - - LLVector4a delta; - delta.setSub(origin, intersection); - - if (hit_icon && - (!objectp || - icon_dist < delta.getLength3().getF32())) - { - // 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, mPickUnselectable)) - { - // 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; - } - - LLVector3 v_intersection(intersection.getF32ptr()); - - mObjectOffset = gAgentCamera.calcFocusOffset(objectp, v_intersection, mPickPt.mX, mPickPt.mY); - mObjectID = objectp->mID; - mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset; - - - - mPosGlobal = gAgent.getPosGlobalFromAgent(v_intersection); - - if (mWantSurfaceInfo) - { - getSurfaceInfo(); - } - } - } - - if (mPickParticle) - { //search for closest particle to click origin out to intersection point - S32 part_face = -1; - - LLVOPartGroup* group = gPipeline.lineSegmentIntersectParticle(start, particle_end, NULL, &part_face); - if (group) - { - mParticleOwnerID = group->getPartOwner(part_face); - mParticleSourceID = group->getPartSource(part_face); - } - } - - if (mPickCallback) - { - mPickCallback(*this); - } + + mPickPt = mMousePt; + + U32 te_offset = face_hit > -1 ? face_hit : 0; + + if (mPickParticle) + { //get the end point of line segement to use for particle raycast + if (hit_object) + { + particle_end = intersection; + } + else + { + particle_end = end; + } + } + + LLViewerObject* objectp = hit_object; + + + LLVector4a delta; + delta.setSub(origin, intersection); + + if (hit_icon && + (!objectp || + icon_dist < delta.getLength3().getF32())) + { + // 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, mPickUnselectable)) + { + // 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; + } + + LLVector3 v_intersection(intersection.getF32ptr()); + + mObjectOffset = gAgentCamera.calcFocusOffset(objectp, v_intersection, mPickPt.mX, mPickPt.mY); + mObjectID = objectp->mID; + mObjectFace = (te_offset == NO_FACE) ? -1 : (S32)te_offset; + + + + mPosGlobal = gAgent.getPosGlobalFromAgent(v_intersection); + + if (mWantSurfaceInfo) + { + getSurfaceInfo(); + } + } + } + + if (mPickParticle) + { //search for closest particle to click origin out to intersection point + S32 part_face = -1; + + LLVOPartGroup* group = gPipeline.lineSegmentIntersectParticle(start, particle_end, NULL, &part_face); + if (group) + { + mParticleOwnerID = group->getPartOwner(part_face); + mParticleSourceID = group->getPartSource(part_face); + } + } + + if (mPickCallback) + { + mPickCallback(*this); + } } LLPointer<LLViewerObject> LLPickInfo::getObject() const { - return gObjectList.findObject( mObjectID ); + 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 = ll_round(mUVCoords.mV[VX] * (F32)imagep->getWidth()); - mXYCoords.mY = ll_round((1.f - mUVCoords.mV[VY]) * (F32)imagep->getHeight()); - } - } + 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 = ll_round(mUVCoords.mV[VX] * (F32)imagep->getWidth()); + mXYCoords.mY = ll_round((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); - mTangent = LLVector4(0,0,0,0); - - LLVector4a tangent; - LLVector4a intersection; - LLVector4a normal; - - tangent.clear(); - normal.clear(); - intersection.clear(); - - LLViewerObject* objectp = getObject(); - - if (objectp) - { - if (gViewerWindow->cursorIntersect(ll_round((F32)mMousePt.mX), ll_round((F32)mMousePt.mY), 1024.f, - objectp, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, - &mObjectFace, + // 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); + mTangent = LLVector4(0,0,0,0); + + LLVector4a tangent; + LLVector4a intersection; + LLVector4a normal; + + tangent.clear(); + normal.clear(); + intersection.clear(); + + LLViewerObject* objectp = getObject(); + + if (objectp) + { + if (gViewerWindow->cursorIntersect(ll_round((F32)mMousePt.mX), ll_round((F32)mMousePt.mY), 1024.f, + objectp, -1, mPickTransparent, mPickRigged, mPickUnselectable, mPickReflectionProbe, + &mObjectFace, &mGLTFNodeIndex, &mGLTFPrimitiveIndex, - &intersection, - &mSTCoords, - &normal, - &tangent)) - { - // if we succeeded with the intersect above, compute the texture coordinates: - - if (objectp->mDrawable.notNull() && mObjectFace > -1) - { - LLFace* facep = objectp->mDrawable->getFace(mObjectFace); - if (facep) - { - mUVCoords = facep->surfaceToTexture(mSTCoords, intersection, normal); - } - } - - mIntersection.set(intersection.getF32ptr()); - mNormal.set(normal.getF32ptr()); - mTangent.set(tangent.getF32ptr()); - - //extrapoloate binormal from normal and tangent - - LLVector4a binormal; - binormal.setCross3(normal, tangent); - binormal.mul(tangent.getF32ptr()[3]); - - mBinormal.set(binormal.getF32ptr()); - - mBinormal.normalize(); - mNormal.normalize(); - mTangent.normalize(); - - // and XY coords: - updateXYCoords(); - - } - } -} - -//static + &intersection, + &mSTCoords, + &normal, + &tangent)) + { + // if we succeeded with the intersect above, compute the texture coordinates: + + if (objectp->mDrawable.notNull() && mObjectFace > -1) + { + LLFace* facep = objectp->mDrawable->getFace(mObjectFace); + if (facep) + { + mUVCoords = facep->surfaceToTexture(mSTCoords, intersection, normal); + } + } + + mIntersection.set(intersection.getF32ptr()); + mNormal.set(normal.getF32ptr()); + mTangent.set(tangent.getF32ptr()); + + //extrapoloate binormal from normal and tangent + + LLVector4a binormal; + binormal.setCross3(normal, tangent); + binormal.mul(tangent.getF32ptr()[3]); + + mBinormal.set(binormal.getF32ptr()); + + mBinormal.normalize(); + mNormal.normalize(); + mTangent.normalize(); + + // and XY coords: + updateXYCoords(); + + } + } +} + +//static bool LLPickInfo::isFlora(LLViewerObject* object) { - if (!object) return false; + if (!object) return false; - LLPCode pcode = object->getPCode(); + LLPCode pcode = object->getPCode(); - if( (LL_PCODE_LEGACY_GRASS == pcode) - || (LL_PCODE_LEGACY_TREE == pcode) - || (LL_PCODE_TREE_NEW == pcode)) - { - return true; - } - return false; + if( (LL_PCODE_LEGACY_GRASS == pcode) + || (LL_PCODE_LEGACY_TREE == pcode) + || (LL_PCODE_TREE_NEW == pcode)) + { + return true; + } + return false; } |