diff options
author | Loren Shih <seraph@lindenlab.com> | 2010-11-08 12:57:26 -0500 |
---|---|---|
committer | Loren Shih <seraph@lindenlab.com> | 2010-11-08 12:57:26 -0500 |
commit | a5e63b1dc0ce6c706de46dfea10784838e2d0257 (patch) | |
tree | 15c7d26720fe56bfc6adf796b20af4e3a5e94110 /indra/newview | |
parent | b3ab10923d74e64e543b15d773639a856f9989e7 (diff) | |
parent | 124a59263184391b0b4ec418c532b7a715e9b5a3 (diff) |
Merge
Diffstat (limited to 'indra/newview')
91 files changed, 2863 insertions, 2152 deletions
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 00d69f805e..ba3b6a42a4 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -391,5 +391,13 @@ <string>CrashOnStartup</string> </map> + <key>disablecrashlogger</key> + <map> + <key>desc</key> + <string>Disables the crash logger and lets the OS handle crashes</string> + <key>map-to</key> + <string>DisableCrashLogger</string> + </map> + </map> </llsd> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 5ac076ae1b..5cc8c34cd5 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -24,6 +24,17 @@ <key>Value</key> <real>300</real> </map> + <key>AdminMenu</key> + <map> + <key>Comment</key> + <string>Enable the debug admin menu from the main menu. Note: This will just allow the menu to be shown; this does not grant admin privileges.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>AdvanceSnapshot</key> <map> <key>Comment</key> @@ -2578,6 +2589,28 @@ <key>Value</key> <integer>1</integer> </map> + <key>EnableGroupChatPopups</key> + <map> + <key>Comment</key> + <string>Enable Incoming Group Chat Popups</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>EnableIMChatPopups</key> + <map> + <key>Comment</key> + <string>Enable Incoming IM Chat Popups</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>DisplayAvatarAgentTarget</key> <map> <key>Comment</key> @@ -4592,6 +4625,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>LogTextureNetworkTraffic</key> + <map> + <key>Comment</key> + <string>Log network traffic for textures</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>LoginAsGod</key> <map> <key>Comment</key> @@ -5915,6 +5959,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>ObjectCacheEnabled</key> + <map> + <key>Comment</key> + <string>Enable the object cache.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>OpenDebugStatAdvanced</key> <map> <key>Comment</key> @@ -8413,7 +8468,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>0</integer> </map> <key>RenderUIBuffer</key> <map> @@ -11330,6 +11385,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>SpeakerParticipantDefaultOrder</key> + <map> + <key>Comment</key> + <string>Order for displaying speakers in voice controls. 0 = alphabetical. 1 = recent.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>1</integer> + </map> <key>SpeakerParticipantRemoveDelay</key> <map> <key>Comment</key> diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index 1d7576d8a6..1114104d84 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -143,7 +143,7 @@ WLSkyDetail 1 48 RenderDeferred 1 0 RenderDeferredSSAO 1 0 RenderShadowDetail 1 0 -RenderUseFBO 1 1 +RenderUseFBO 1 0 // // Ultra graphics (REALLY PURTY!) @@ -170,7 +170,7 @@ WLSkyDetail 1 128 RenderDeferred 1 1 RenderDeferredSSAO 1 1 RenderShadowDetail 1 2 -RenderUseFBO 1 1 +RenderUseFBO 1 0 // // Class Unknown Hardware (unknown) diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 1f3465472c..2fa47c38d5 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -140,7 +140,7 @@ RenderWaterReflections 1 0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 48 -RenderUseFBO 1 1 +RenderUseFBO 1 0 // // Ultra graphics (REALLY PURTY!) @@ -166,7 +166,7 @@ RenderWaterReflections 1 1 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 -RenderUseFBO 1 1 +RenderUseFBO 1 0 // // Class Unknown Hardware (unknown) diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 8168adb0fb..29d26a117f 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -296,8 +296,11 @@ void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera) LLSelectMgr::getInstance()->deselectAll(); } - // Hide all popup menus - gMenuHolder->hideMenus(); + if (gMenuHolder != NULL) + { + // Hide all popup menus + gMenuHolder->hideMenus(); + } } if (change_camera && !gSavedSettings.getBOOL("FreezeTime")) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index ed5e8ceee3..62074ddcd5 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2204,12 +2204,11 @@ void LLAppearanceMgr::updateIsDirty() base_outfit = catp->getUUID(); } - if(base_outfit.isNull()) - { - // no outfit link found, display "unsaved outfit" - mOutfitIsDirty = true; - } - else + // Set dirty to "false" if no base outfit found to disable "Save" + // and leave only "Save As" enabled in My Outfits. + mOutfitIsDirty = false; + + if (base_outfit.notNull()) { LLIsOfAssetType collector = LLIsOfAssetType(LLAssetType::AT_LINK); @@ -2248,8 +2247,6 @@ void LLAppearanceMgr::updateIsDirty() return; } } - - mOutfitIsDirty = false; } } @@ -2635,6 +2632,7 @@ void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items, LLAppearanceMgr::LLAppearanceMgr(): mAttachmentInvLinkEnabled(false), mOutfitIsDirty(false), + mOutfitLocked(false), mIsInUpdateAppearanceFromCOF(false) { LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 08ab82acec..4f80ba3aeb 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -988,6 +988,7 @@ bool LLAppViewer::mainLoop() LLVoiceClient::getInstance()->init(gServicePump); LLTimer frameTimer,idleTimer; LLTimer debugTime; + LLFrameTimer memCheckTimer; LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); joystick->setNeedsReset(true); @@ -998,11 +999,29 @@ bool LLAppViewer::mainLoop() // point of posting. LLSD newFrame; + const F32 memory_check_interval = 1.0f ; //second + // Handle messages while (!LLApp::isExiting()) { LLFastTimer::nextFrame(); // Should be outside of any timer instances + //clear call stack records + llclearcallstacks; + + //check memory availability information + { + if(memory_check_interval < memCheckTimer.getElapsedTimeF32()) + { + memCheckTimer.reset() ; + + //update the availability of memory + LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; + } + llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ; + llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ; + } + try { pingMainloopTimeout("Main:MiscNativeWindowEvents"); @@ -1229,11 +1248,20 @@ bool LLAppViewer::mainLoop() resumeMainloopTimeout(); pingMainloopTimeout("Main:End"); - } - + } } catch(std::bad_alloc) { + { + llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ; + llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ; + + LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; + + llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ; + llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ; + } + //stop memory leaking simulation LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); @@ -2037,6 +2065,15 @@ bool LLAppViewer::initConfiguration() // - apply command line settings clp.notify(); + // Register the core crash option as soon as we can + // if we want gdb post-mortem on cores we need to be up and running + // ASAP or we might miss init issue etc. + if(clp.hasOption("disablecrashlogger")) + { + llwarns << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << llendl; + LLAppViewer::instance()->disableCrashlogger(); + } + // Handle initialization from settings. // Start up the debugging console before handling other options. if (gSavedSettings.getBOOL("ShowConsoleWindow")) @@ -2614,6 +2651,11 @@ void LLAppViewer::handleViewerCrash() abort(); } + if (LLApp::isCrashloggerDisabled()) + { + abort(); + } + // Returns whether a dialog was shown. // Only do the logic in here once if (pApp->mReportedCrash) diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index fdc3b9ef9e..a40cd83182 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -260,6 +260,8 @@ private: std::set<struct apr_dso_handle_t*> mPlugins; + U32 mAvailPhysicalMemInKB ; + U32 mAvailVirtualMemInKB ; public: //some information for updater typedef struct diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index a56dc129d4..30eecfe323 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -41,7 +41,7 @@ bool LLAvatarListItem::sStaticInitialized = false; S32 LLAvatarListItem::sLeftPadding = 0; -S32 LLAvatarListItem::sRightNamePadding = 0; +S32 LLAvatarListItem::sNameRightPadding = 0; S32 LLAvatarListItem::sChildrenWidths[LLAvatarListItem::ALIC_COUNT]; static LLWidgetNameRegistry::StaticRegistrar sRegisterAvatarListItemParams(&typeid(LLAvatarListItem::Params), "avatar_list_item"); @@ -52,7 +52,8 @@ LLAvatarListItem::Params::Params() voice_call_joined_style("voice_call_joined_style"), voice_call_left_style("voice_call_left_style"), online_style("online_style"), - offline_style("offline_style") + offline_style("offline_style"), + name_right_pad("name_right_pad", 0) {}; @@ -119,6 +120,9 @@ BOOL LLAvatarListItem::postBuild() // so that we can hide and show them again later. initChildrenWidths(this); + // Right padding between avatar name text box and nearest visible child. + sNameRightPadding = LLUICtrlFactory::getDefaultParams<LLAvatarListItem>().name_right_pad; + sStaticInitialized = true; } @@ -486,7 +490,6 @@ void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item) S32 icon_width = avatar_item->mAvatarName->getRect().mLeft - avatar_item->mAvatarIcon->getRect().mLeft; sLeftPadding = avatar_item->mAvatarIcon->getRect().mLeft; - sRightNamePadding = avatar_item->mLastInteractionTime->getRect().mLeft - avatar_item->mAvatarName->getRect().mRight; S32 index = ALIC_COUNT; sChildrenWidths[--index] = icon_width; @@ -565,7 +568,7 @@ void LLAvatarListItem::updateChildren() // apply paddings name_new_width -= sLeftPadding; - name_new_width -= sRightNamePadding; + name_new_width -= sNameRightPadding; name_view_rect.setLeftTopAndSize( name_new_left, diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index a069838ac3..c95ac39696 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -51,6 +51,8 @@ public: online_style, offline_style; + Optional<S32> name_right_pad; + Params(); }; @@ -215,7 +217,7 @@ private: static bool sStaticInitialized; // this variable is introduced to improve code readability static S32 sLeftPadding; // padding to first left visible child (icon or name) - static S32 sRightNamePadding; // right padding from name to next visible child + static S32 sNameRightPadding; // right padding from name to next visible child /** * Contains widths of each child specified by EAvatarListItemChildIndex diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 078bd73379..b2e9564f7d 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -45,6 +45,7 @@ #include "llspeakers.h" #include "lltextutil.h" #include "lltransientfloatermgr.h" +#include "llviewercontrol.h" #include "llviewerdisplayname.h" #include "llviewerwindow.h" #include "llvoicechannel.h" @@ -335,8 +336,9 @@ void LLCallFloater::refreshParticipantList() { mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT, false); mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1)); - mParticipants->setSortOrder(LLParticipantList::E_SORT_BY_RECENT_SPEAKERS); - + const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); + mParticipants->setSortOrder(LLParticipantList::EParticipantSortOrder(speaker_sort_order)); + if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager) { mAvatarList->setNoItemsCommentText(getString("no_one_near")); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index cb5cf4a61d..3dc6e786d3 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -790,8 +790,9 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // (don't let object names with hyperlinks override our objectim Url) LLStyle::Params link_params(style_params); link_params.color.control = "HTMLLinkColor"; + link_params.is_link = true; link_params.link_href = url; - mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, + mEditor->appendText(chat.mFromName + delimiter, false, link_params); } else if ( chat.mFromName != SYSTEM_FROM && chat.mFromID.notNull() && !message_from_log) @@ -804,7 +805,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL } else { - mEditor->appendText(chat.mFromName + delimiter, false, style_params); + mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, false, style_params); } } } diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index dc573e1433..1e91710552 100644 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -104,6 +104,8 @@ void LLFloaterHardwareSettings::refreshEnabledState() getChildView("(brightness, lower is brighter)")->setEnabled(!gPipeline.canUseWindLightShaders()); getChildView("fog")->setEnabled(!gPipeline.canUseWindLightShaders()); getChildView("fsaa")->setEnabled(gPipeline.canUseAntiAliasing()); + getChildView("antialiasing restart")->setVisible(!gSavedSettings.getBOOL("RenderUseFBO")); + /* Enable to reset fsaa value to disabled when feature is not available. if (!gPipeline.canUseAntiAliasing()) { diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp index a1d291fea6..351b9ac5da 100644 --- a/indra/newview/llfloatermap.cpp +++ b/indra/newview/llfloatermap.cpp @@ -43,6 +43,8 @@ #include "lldraghandle.h" #include "lltextbox.h" #include "llviewermenu.h" +#include "llfloaterworldmap.h" +#include "llagent.h" // // Constants @@ -122,11 +124,36 @@ BOOL LLFloaterMap::postBuild() return TRUE; } -BOOL LLFloaterMap::handleDoubleClick( S32 x, S32 y, MASK mask ) +BOOL LLFloaterMap::handleDoubleClick(S32 x, S32 y, MASK mask) { // If floater is minimized, minimap should be shown on doubleclick (STORM-299) - std::string floater_to_show = this->isMinimized() ? "mini_map" : "world_map"; - LLFloaterReg::showInstance(floater_to_show); + if (isMinimized()) + { + setMinimized(FALSE); + return TRUE; + } + + LLVector3d pos_global = mMap->viewPosToGlobal(x, y); + + // If we're not tracking a beacon already, double-click will set one + if (!LLTracker::isTracking(NULL)) + { + LLFloaterWorldMap* world_map = LLFloaterWorldMap::getInstance(); + if (world_map) + { + world_map->trackLocation(pos_global); + } + } + + if (gSavedSettings.getBOOL("DoubleClickTeleport")) + { + // If DoubleClickTeleport is on, double clicking the minimap will teleport there + gAgent.teleportViaLocationLookAt(pos_global); + } + else + { + LLFloaterReg::showInstance("world_map"); + } return TRUE; } diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index c38cd4d090..62ba746a02 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -2429,6 +2429,7 @@ S32 LLFolderView::notify(const LLSD& info) { setFocus(true); selectFirstItem(); + scrollToShowSelection(); return 1; } @@ -2436,6 +2437,7 @@ S32 LLFolderView::notify(const LLSD& info) { setFocus(true); selectLastItem(); + scrollToShowSelection(); return 1; } } diff --git a/indra/newview/llhints.cpp b/indra/newview/llhints.cpp index 7f6df627e0..3f0deb98cd 100644 --- a/indra/newview/llhints.cpp +++ b/indra/newview/llhints.cpp @@ -109,7 +109,14 @@ public: /*virtual*/ BOOL postBuild(); - void onClickClose() { hide(); LLNotifications::instance().cancel(mNotification); } + void onClickClose() + { + if (!mHidden) + { + hide(); + LLNotifications::instance().cancel(mNotification); + } + } void draw(); void hide() { if(!mHidden) {mHidden = true; mFadeTimer.reset();} } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 914e7a3df0..857c27be63 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -131,6 +131,20 @@ void toast_callback(const LLSD& msg){ return; } + // *NOTE Skip toasting if the user disable it in preferences/debug settings ~Alexandrea + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession( + msg["session_id"]); + if (!gSavedSettings.getBOOL("EnableGroupChatPopups") + && session->isGroupSessionType()) + { + return; + } + if (!gSavedSettings.getBOOL("EnableIMChatPopups") + && !session->isGroupSessionType()) + { + return; + } + // Skip toasting if we have open window of IM with this session id LLIMFloater* open_im_floater = LLIMFloater::findInstance(msg["session_id"]); if (open_im_floater && open_im_floater->getVisible()) @@ -257,21 +271,17 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& // history files have consistent (English) names in different locales. if (isAdHocSessionType() && IM_SESSION_INVITE == type) { - // Name here has a form of "<Avatar's name> Conference" - // Lets update it to localize the "Conference" word. See EXT-8429. - S32 separator_index = mName.rfind(" "); - std::string name = mName.substr(0, separator_index); - ++separator_index; - std::string conference_word = mName.substr(separator_index, mName.length()); + LLAvatarNameCache::get(mOtherParticipantID, + boost::bind(&LLIMModel::LLIMSession::onAdHocNameCache, + this, _2)); + } +} - // additional check that session name is what we expected - if ("Conference" == conference_word) - { +void LLIMModel::LLIMSession::onAdHocNameCache(const LLAvatarName& av_name) +{ LLStringUtil::format_map_t args; - args["[AGENT_NAME]"] = name; + args["[AGENT_NAME]"] = av_name.getCompleteName(); LLTrans::findString(mName, "conference-title-incoming", args); - } - } } void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction) diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 3da4465862..650d329e18 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -100,6 +100,8 @@ public: void onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name); + void onAdHocNameCache(const LLAvatarName& av_name);
+ //*TODO make private static std::string generateHash(const std::set<LLUUID>& sorted_uuids); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index d09a41b358..43cd7b3466 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1651,16 +1651,19 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) && (LLToolDragAndDrop::SOURCE_AGENT == source); + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + BOOL accept = FALSE; if (is_agent_inventory) { const LLUUID &cat_id = inv_cat->getUUID(); const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); const BOOL move_is_into_outfit = getCategory() && (getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT); - const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); //-------------------------------------------------------------------------------- // Determine if folder can be moved. @@ -1698,6 +1701,21 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } } + if (move_is_into_landmarks) + { + for (S32 i=0; i < descendent_items.count(); ++i) + { + LLViewerInventoryItem* item = descendent_items[i]; + + // Don't move anything except landmarks and categories into Landmarks folder. + // We use getType() instead of getActua;Type() to allow links to landmarks and folders. + if (LLAssetType::AT_LANDMARK != item->getType() && LLAssetType::AT_CATEGORY != item->getType()) + { + is_movable = FALSE; + break; // It's generally movable, but not into Landmarks. + } + } + } // //-------------------------------------------------------------------------------- @@ -1785,6 +1803,17 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, LLUUID category_id = mUUID; accept = move_inv_category_world_to_agent(object_id, category_id, drop); } + else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) + { + // Accept folders that contain complete outfits. + accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(inv_cat->getUUID()); + + if (accept && drop) + { + LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, true, false); + } + } + return accept; } @@ -2672,6 +2701,8 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data) { + LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; + //llinfos << "LLFolderBridge::dragOrDrop()" << llendl; BOOL accept = FALSE; switch(cargo_type) @@ -2687,10 +2718,24 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, case DAD_BODYPART: case DAD_ANIMATION: case DAD_GESTURE: + accept = dragItemIntoFolder(inv_item, drop); + break; case DAD_LINK: - case DAD_MESH: - accept = dragItemIntoFolder((LLInventoryItem*)cargo_data, - drop); + // DAD_LINK type might mean one of two asset types: AT_LINK or AT_LINK_FOLDER. + // If we have an item of AT_LINK_FOLDER type we should process the linked + // category being dragged or dropped into folder. + if (inv_item && LLAssetType::AT_LINK_FOLDER == inv_item->getActualType()) + { + LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID()); + if (linked_category) + { + accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop); + } + } + else + { + accept = dragItemIntoFolder(inv_item, drop); + } break; case DAD_CATEGORY: if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID)) @@ -2874,6 +2919,7 @@ static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_curr { if ((inv_item->getInventoryType() != LLInventoryType::IT_WEARABLE) && (inv_item->getInventoryType() != LLInventoryType::IT_GESTURE) && + (inv_item->getInventoryType() != LLInventoryType::IT_ATTACHMENT) && (inv_item->getInventoryType() != LLInventoryType::IT_OBJECT)) { return FALSE; @@ -2887,6 +2933,24 @@ static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_curr return TRUE; } +// Returns TRUE if item is a landmark or a link to a landmark +// and can be moved to Favorites or Landmarks folder. +static BOOL can_move_to_landmarks(LLInventoryItem* inv_item) +{ + // Need to get the linked item to know its type because LLInventoryItem::getType() + // returns actual type AT_LINK for links, not the asset type of a linked item. + if (LLAssetType::AT_LINK == inv_item->getType()) + { + LLInventoryItem* linked_item = gInventory.getItem(inv_item->getLinkedUUID()); + if (linked_item) + { + return LLAssetType::AT_LANDMARK == linked_item->getType(); + } + } + + return LLAssetType::AT_LANDMARK == inv_item->getType(); +} + void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item) { // use callback to rearrange favorite landmarks after adding @@ -2943,9 +3007,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); + const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + const BOOL move_is_into_favorites = (mUUID == favorites_id); const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); BOOL accept = FALSE; @@ -2956,7 +3023,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); const BOOL move_is_outof_current_outfit = LLAppearanceMgr::instance().getIsInCOF(inv_item->getUUID()); - const BOOL folder_allows_reorder = (mUUID == favorites_id); //-------------------------------------------------------------------------------- // Determine if item can be moved. @@ -3002,12 +3068,16 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, if (!is_movable) accept = FALSE; - if ((mUUID == inv_item->getParentUUID()) && !folder_allows_reorder) + if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites) accept = FALSE; if (move_is_into_current_outfit || move_is_into_outfit) { accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); } + else if (move_is_into_favorites || move_is_into_landmarks) + { + accept = can_move_to_landmarks(inv_item); + } if(accept && drop) { @@ -3033,8 +3103,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // // REORDER - // (only reorder the item) - if ((mUUID == inv_item->getParentUUID()) && folder_allows_reorder) + // (only reorder the item in Favorites folder) + if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites) { LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; @@ -3048,7 +3118,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // FAVORITES folder // (copy the item) - else if (favorites_id == mUUID) + else if (move_is_into_favorites) { dropToFavorites(inv_item); } @@ -3113,6 +3183,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { accept = FALSE; } + // Don't allow to move a single item to Favorites or Landmarks + // if it is not a landmark or a link to a landmark. + else if ((move_is_into_favorites || move_is_into_landmarks) + && !can_move_to_landmarks(inv_item)) + { + accept = FALSE; + } if(drop && accept) { @@ -3158,12 +3235,18 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); } + // Don't allow to move a single item to Favorites or Landmarks + // if it is not a landmark or a link to a landmark. + else if (move_is_into_favorites || move_is_into_landmarks) + { + accept = can_move_to_landmarks(inv_item); + } if (accept && drop) { // FAVORITES folder // (copy the item) - if (favorites_id == mUUID) + if (move_is_into_favorites) { dropToFavorites(inv_item); } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 50adae09c0..0870b5b8dd 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -290,7 +290,10 @@ void LLInventoryPanel::modelChanged(U32 mask) const LLUUID& item_id = (*items_iter); const LLInventoryObject* model_item = model->getObject(item_id); LLFolderViewItem* view_item = mFolderRoot->getItemByID(item_id); - LLFolderViewFolder* view_folder = mFolderRoot->getFolderByID(item_id); + + // LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item + // to folder is the fast way to get a folder without searching through folders tree. + LLFolderViewFolder* view_folder = dynamic_cast<LLFolderViewFolder*>(view_item); ////////////////////////////// // LABEL Operation diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 47d32e57fb..d2ad78f140 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -64,6 +64,18 @@ public: LLNearbyChatScreenChannel(const LLUUID& id):LLScreenChannelBase(id) { mStopProcessing = false; + + LLControlVariable* ctrl = gSavedSettings.getControl("NearbyToastLifeTime").get(); + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLNearbyChatScreenChannel::updateToastsLifetime, this)); + } + + ctrl = gSavedSettings.getControl("NearbyToastFadingTime").get(); + if (ctrl) + { + ctrl->getSignal()->connect(boost::bind(&LLNearbyChatScreenChannel::updateToastFadingTime, this)); + } } void addNotification (LLSD& notification); @@ -109,13 +121,26 @@ protected: if (!toast) return; LL_DEBUGS("NearbyChat") << "Pooling toast" << llendl; toast->setVisible(FALSE); - toast->stopTimer(); + toast->stopFading(); toast->setIsHidden(true); + + // Nearby chat toasts that are hidden, not destroyed. They are collected to the toast pool, so that + // they can be used next time, this is done for performance. But if the toast lifetime was changed + // (from preferences floater (STORY-36)) while it was shown (at this moment toast isn't in the pool yet) + // changes don't take affect. + // So toast's lifetime should be updated each time it's added to the pool. Otherwise viewer would have + // to be restarted so that changes take effect. + toast->setLifetime(gSavedSettings.getS32("NearbyToastLifeTime")); + toast->setFadingTime(gSavedSettings.getS32("NearbyToastFadingTime")); m_toast_pool.push_back(toast->getHandle()); } void createOverflowToast(S32 bottom, F32 timer); + void updateToastsLifetime(); + + void updateToastFadingTime(); + create_toast_panel_callback_t m_create_toast_panel_callback_t; bool createPoolToast(); @@ -205,6 +230,27 @@ void LLNearbyChatScreenChannel::onToastFade(LLToast* toast) arrangeToasts(); } +void LLNearbyChatScreenChannel::updateToastsLifetime() +{ + S32 seconds = gSavedSettings.getS32("NearbyToastLifeTime"); + toast_list_t::iterator it; + + for(it = m_toast_pool.begin(); it != m_toast_pool.end(); ++it) + { + (*it).get()->setLifetime(seconds); + } +} + +void LLNearbyChatScreenChannel::updateToastFadingTime() +{ + S32 seconds = gSavedSettings.getS32("NearbyToastFadingTime"); + toast_list_t::iterator it; + + for(it = m_toast_pool.begin(); it != m_toast_pool.end(); ++it) + { + (*it).get()->setFadingTime(seconds); + } +} bool LLNearbyChatScreenChannel::createPoolToast() { @@ -250,7 +296,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) { panel->addMessage(notification); toast->reshapeToPanel(); - toast->resetTimer(); + toast->startFading(); arrangeToasts(); return; @@ -295,7 +341,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) panel->init(notification); toast->reshapeToPanel(); - toast->resetTimer(); + toast->startFading(); m_active_toasts.push_back(toast->getHandle()); @@ -325,9 +371,9 @@ void LLNearbyChatScreenChannel::arrangeToasts() int sort_toasts_predicate(LLHandle<LLToast> first, LLHandle<LLToast> second) { - F32 v1 = first.get()->getTimer()->getEventTimer().getElapsedTimeF32(); - F32 v2 = second.get()->getTimer()->getEventTimer().getElapsedTimeF32(); - return v1 < v2; + F32 v1 = first.get()->getTimeLeftToLive(); + F32 v2 = second.get()->getTimeLeftToLive(); + return v1 > v2; } void LLNearbyChatScreenChannel::showToastsBottom() diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index 650bce0da4..e053b1c177 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -38,6 +38,7 @@ class LLColor4U; class LLCoordGL; class LLImageRaw; class LLViewerTexture; +class LLFloaterMap; class LLNetMap : public LLUICtrl { @@ -55,6 +56,7 @@ public: protected: LLNetMap (const Params & p); friend class LLUICtrlFactory; + friend class LLFloaterMap; public: virtual ~LLNetMap(); diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 70295259b3..6435126fc0 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -115,7 +115,7 @@ public: registrar.add("Gear.Wear", boost::bind(&LLOutfitListGearMenu::onWear, this)); registrar.add("Gear.TakeOff", boost::bind(&LLOutfitListGearMenu::onTakeOff, this)); registrar.add("Gear.Rename", boost::bind(&LLOutfitListGearMenu::onRename, this)); - registrar.add("Gear.Delete", boost::bind(&LLOutfitListGearMenu::onDelete, this)); + registrar.add("Gear.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList)); registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenu::onCreate, this, _2)); registrar.add("Gear.WearAdd", boost::bind(&LLOutfitListGearMenu::onAdd, this)); @@ -197,15 +197,6 @@ private: } } - void onDelete() - { - const LLUUID& selected_outfit_id = getSelectedOutfitID(); - if (selected_outfit_id.notNull()) - { - remove_category(&gInventory, selected_outfit_id); - } - } - void onCreate(const LLSD& data) { LLWearableType::EType type = LLWearableType::typeNameToType(data.asString()); @@ -260,6 +251,12 @@ private: class LLOutfitContextMenu : public LLListContextMenu { +public: + + LLOutfitContextMenu(LLOutfitsList* outfit_list) + : LLListContextMenu(), + mOutfitList(outfit_list) + {} protected: /* virtual */ LLContextMenu* createMenu() { @@ -275,7 +272,7 @@ protected: boost::bind(&LLAppearanceMgr::takeOffOutfit, &LLAppearanceMgr::instance(), selected_id)); registrar.add("Outfit.Edit", boost::bind(editOutfit)); registrar.add("Outfit.Rename", boost::bind(renameOutfit, selected_id)); - registrar.add("Outfit.Delete", boost::bind(deleteOutfit, selected_id)); + registrar.add("Outfit.Delete", boost::bind(&LLOutfitsList::removeSelected, mOutfitList)); enable_registrar.add("Outfit.OnEnable", boost::bind(&LLOutfitContextMenu::onEnable, this, _2)); enable_registrar.add("Outfit.OnVisible", boost::bind(&LLOutfitContextMenu::onVisible, this, _2)); @@ -338,10 +335,8 @@ protected: LLAppearanceMgr::instance().renameOutfit(outfit_cat_id); } - static void deleteOutfit(const LLUUID& outfit_cat_id) - { - remove_category(&gInventory, outfit_cat_id); - } +private: + LLOutfitsList* mOutfitList; }; ////////////////////////////////////////////////////////////////////////// @@ -358,7 +353,7 @@ LLOutfitsList::LLOutfitsList() mCategoriesObserver = new LLInventoryCategoriesObserver(); mGearMenu = new LLOutfitListGearMenu(this); - mOutfitMenu = new LLOutfitContextMenu(); + mOutfitMenu = new LLOutfitContextMenu(this); } LLOutfitsList::~LLOutfitsList() @@ -635,6 +630,14 @@ void LLOutfitsList::performAction(std::string action) void LLOutfitsList::removeSelected() { + LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLOutfitsList::onOutfitsRemovalConfirmation, this, _1, _2)); +} + +void LLOutfitsList::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return; // canceled + if (mSelectedOutfitUUID.notNull()) { remove_category(&gInventory, mSelectedOutfitUUID); diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index 5fecbb83e7..a0598737f1 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -110,6 +110,8 @@ public: private: + void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response); + /** * Wrapper for LLCommonUtils::computeDifference. @see LLCommonUtils::computeDifference */ diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 80df420a4e..ec340dc258 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -692,7 +692,8 @@ void LLPanelGroupGeneral::updateMembers() LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); if (!mListVisibleMembers || !gdatap - || !gdatap->isMemberDataComplete()) + || !gdatap->isMemberDataComplete() + || gdatap->mMembers.empty()) { return; } diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 0d1d96eae6..d1362d7922 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -1576,6 +1576,7 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc) void LLPanelGroupMembersSubTab::addMemberToList(LLUUID id, LLGroupMemberData* data) { + if (!data) return; LLUIString donated = getString("donation_area"); donated.setArg("[AREA]", llformat("%d", data->getContribution())); @@ -1616,9 +1617,12 @@ void LLPanelGroupMembersSubTab::onNameCache(const LLUUID& update_id, const LLUUI std::string fullname; gCacheName->getFullName(id, fullname); - if (matchesSearchFilter(fullname)) + + LLGroupMemberData* data; + // trying to avoid unnecessary hash lookups + if (matchesSearchFilter(fullname) && ((data = gdatap->mMembers[id]) != NULL)) { - addMemberToList(id, gdatap->mMembers[id]); + addMemberToList(id, data); if(!mMembersList->getEnabled()) { mMembersList->setEnabled(TRUE); diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 4f2cfa2bbc..a90f864ae2 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -258,17 +258,7 @@ void LLPanelOutfitsInventory::updateListCommands() void LLPanelOutfitsInventory::onTrashButtonClick() { - LLNotificationsUtil::add("DeleteOutfits", LLSD(), LLSD(), boost::bind(&LLPanelOutfitsInventory::onOutfitsRemovalConfirmation, this, _1, _2)); -} - -void LLPanelOutfitsInventory::onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - if (option != 0) return; // canceled - mMyOutfitsPanel->removeSelected(); - updateListCommands(); - updateVerbs(); } bool LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index f1ca1dbfeb..a7917b457c 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -89,7 +89,6 @@ protected: void onWearButtonClick(); void showGearMenu(); void onTrashButtonClick(); - void onOutfitsRemovalConfirmation(const LLSD& notification, const LLSD& response); bool isActionEnabled(const LLSD& userdata); void setWearablesLoading(bool val); void onWearablesLoaded(); diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 01b3b5572e..54053cf89f 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -197,17 +197,20 @@ private: uuid_set_t mAvalineCallers; }; -LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/, - bool exclude_agent /*= true*/, bool can_toggle_icons /*= true*/): +LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, + LLAvatarList* avatar_list, + bool use_context_menu/* = true*/, + bool exclude_agent /*= true*/, + bool can_toggle_icons /*= true*/) : mSpeakerMgr(data_source), mAvatarList(avatar_list), - mSortOrder(E_SORT_BY_NAME) -, mParticipantListMenu(NULL) -, mExcludeAgent(exclude_agent) -, mValidateSpeakerCallback(NULL) + mParticipantListMenu(NULL), + mExcludeAgent(exclude_agent), + mValidateSpeakerCallback(NULL) { + mAvalineUpdater = new LLAvalineUpdater(boost::bind(&LLParticipantList::onAvalineCallerFound, this, _1), - boost::bind(&LLParticipantList::onAvalineCallerRemoved, this, _1)); + boost::bind(&LLParticipantList::onAvalineCallerRemoved, this, _1)); mSpeakerAddListener = new SpeakerAddListener(*this); mSpeakerRemoveListener = new SpeakerRemoveListener(*this); @@ -393,15 +396,15 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) } /* -Seems this method is not necessary after onAvalineCallerRemoved was implemented; + Seems this method is not necessary after onAvalineCallerRemoved was implemented; -It does nothing because list item is always created with correct class type for Avaline caller. -For now Avaline Caller is removed from the LLSpeakerMgr List when it is removed from the Voice Client -session. -This happens in two cases: if Avaline Caller ends call itself or if Resident ends group call. + It does nothing because list item is always created with correct class type for Avaline caller. + For now Avaline Caller is removed from the LLSpeakerMgr List when it is removed from the Voice Client + session. + This happens in two cases: if Avaline Caller ends call itself or if Resident ends group call. -Probably Avaline caller should be removed from the LLSpeakerMgr list ONLY if it ends call itself. -Asked in EXT-4301. + Probably Avaline caller should be removed from the LLSpeakerMgr list ONLY if it ends call itself. + Asked in EXT-4301. */ void LLParticipantList::onAvalineCallerFound(const LLUUID& participant_id) { @@ -443,16 +446,19 @@ void LLParticipantList::onAvalineCallerRemoved(const LLUUID& participant_id) void LLParticipantList::setSortOrder(EParticipantSortOrder order) { - if ( mSortOrder != order ) + const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); + + if ( speaker_sort_order != order ) { - mSortOrder = order; + gSavedSettings.setU32("SpeakerParticipantDefaultOrder", (U32)order); sort(); } } -LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder() +const LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder() const { - return mSortOrder; + const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); + return EParticipantSortOrder(speaker_sort_order); } void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t cb) @@ -551,28 +557,29 @@ void LLParticipantList::sort() if ( !mAvatarList ) return; - switch ( mSortOrder ) { - case E_SORT_BY_NAME : - // if mExcludeAgent == true , then no need to keep agent on top of the list - if(mExcludeAgent) - { - mAvatarList->sortByName(); - } - else - { - mAvatarList->setComparator(&AGENT_ON_TOP_NAME_COMPARATOR); + switch ( getSortOrder() ) + { + case E_SORT_BY_NAME : + // if mExcludeAgent == true , then no need to keep agent on top of the list + if(mExcludeAgent) + { + mAvatarList->sortByName(); + } + else + { + mAvatarList->setComparator(&AGENT_ON_TOP_NAME_COMPARATOR); + mAvatarList->sort(); + } + break; + case E_SORT_BY_RECENT_SPEAKERS: + if (mSortByRecentSpeakers.isNull()) + mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this); + mAvatarList->setComparator(mSortByRecentSpeakers.get()); mAvatarList->sort(); - } - break; - case E_SORT_BY_RECENT_SPEAKERS: - if (mSortByRecentSpeakers.isNull()) - mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this); - mAvatarList->setComparator(mSortByRecentSpeakers.get()); - mAvatarList->sort(); - break; - default : - llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl; - return; + break; + default : + llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl; + return; } } @@ -645,7 +652,7 @@ bool LLParticipantList::SpeakerClearListener::handleEvent(LLPointer<LLOldEvents: // bool LLParticipantList::SpeakerModeratorUpdateListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { - return mParent.onModeratorUpdateEvent(event, userdata); + return mParent.onModeratorUpdateEvent(event, userdata); } bool LLParticipantList::SpeakerMuteListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) @@ -867,7 +874,7 @@ void LLParticipantList::LLParticipantListMenu::confirmMuteAllCallback(const LLSD const LLUUID& session_id = payload["session_id"]; LLIMSpeakerMgr * speaker_manager = dynamic_cast<LLIMSpeakerMgr*> ( - LLIMModel::getInstance()->getSpeakerManager(session_id)); + LLIMModel::getInstance()->getSpeakerManager(session_id)); if (speaker_manager) { speaker_manager->moderateVoiceAllParticipants(false); @@ -925,9 +932,9 @@ bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& } /* -Processed menu items with such parameters: - can_allow_text_chat - can_moderate_voice + Processed menu items with such parameters: + can_allow_text_chat + can_moderate_voice */ bool LLParticipantList::LLParticipantListMenu::enableModerateContextMenuItem(const LLSD& userdata) { @@ -978,11 +985,11 @@ bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD& } else if(item == "is_sorted_by_name") { - return E_SORT_BY_NAME == mParent.mSortOrder; + return E_SORT_BY_NAME == mParent.getSortOrder(); } else if(item == "is_sorted_by_recent_speakers") { - return E_SORT_BY_RECENT_SPEAKERS == mParent.mSortOrder; + return E_SORT_BY_RECENT_SPEAKERS == mParent.getSortOrder(); } return false; diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 722a749d19..e0b3d42c25 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -24,6 +24,9 @@ * $/LicenseInfo$ */ +#ifndef LL_PARTICIPANTLIST_H +#define LL_PARTICIPANTLIST_H + #include "llviewerprecompiledheaders.h" #include "llevent.h" #include "llavatarlist.h" // for LLAvatarItemRecentSpeakerComparator @@ -37,239 +40,247 @@ class LLAvalineUpdater; class LLParticipantList { LOG_CLASS(LLParticipantList); +public: + + typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t; + + LLParticipantList(LLSpeakerMgr* data_source, + LLAvatarList* avatar_list, + bool use_context_menu = true, + bool exclude_agent = true, + bool can_toggle_icons = true); + ~LLParticipantList(); + void setSpeakingIndicatorsVisible(BOOL visible); + + enum EParticipantSortOrder + { + E_SORT_BY_NAME = 0, + E_SORT_BY_RECENT_SPEAKERS = 1, + }; + + /** + * Adds specified avatar ID to the existing list if it is not Agent's ID + * + * @param[in] avatar_id - Avatar UUID to be added into the list + */ + void addAvatarIDExceptAgent(const LLUUID& avatar_id); + + /** + * Set and sort Avatarlist by given order + */ + void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME); + const EParticipantSortOrder getSortOrder() const; + + /** + * Refreshes the participant list if it's in sort by recent speaker order. + */ + void updateRecentSpeakersOrder(); + + /** + * Set a callback to be called before adding a speaker. Invalid speakers will not be added. + * + * If the callback is unset all speakers are considered as valid. + * + * @see onAddItemEvent() + */ + void setValidateSpeakerCallback(validate_speaker_callback_t cb); + +protected: + /** + * LLSpeakerMgr event handlers + */ + bool onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + bool onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + + /** + * Sorts the Avatarlist by stored order + */ + void sort(); + + /** + * List of listeners implementing LLOldEvents::LLSimpleListener. + * There is no way to handle all the events in one listener as LLSpeakerMgr registers + * listeners in such a way that one listener can handle only one type of event + **/ + class BaseSpeakerListener : public LLOldEvents::LLSimpleListener + { public: + BaseSpeakerListener(LLParticipantList& parent) : mParent(parent) {} + protected: + LLParticipantList& mParent; + }; - typedef boost::function<bool (const LLUUID& speaker_id)> validate_speaker_callback_t; - - LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true, bool exclude_agent = true, bool can_toggle_icons = true); - ~LLParticipantList(); - void setSpeakingIndicatorsVisible(BOOL visible); - - typedef enum e_participant_sort_oder { - E_SORT_BY_NAME = 0, - E_SORT_BY_RECENT_SPEAKERS = 1, - } EParticipantSortOrder; + class SpeakerAddListener : public BaseSpeakerListener + { + public: + SpeakerAddListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + }; - /** - * Adds specified avatar ID to the existing list if it is not Agent's ID - * - * @param[in] avatar_id - Avatar UUID to be added into the list - */ - void addAvatarIDExceptAgent(const LLUUID& avatar_id); + class SpeakerRemoveListener : public BaseSpeakerListener + { + public: + SpeakerRemoveListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + }; - /** - * Set and sort Avatarlist by given order - */ - void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME); - EParticipantSortOrder getSortOrder(); + class SpeakerClearListener : public BaseSpeakerListener + { + public: + SpeakerClearListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + }; - /** - * Refreshes the participant list if it's in sort by recent speaker order. - */ - void updateRecentSpeakersOrder(); + class SpeakerModeratorUpdateListener : public BaseSpeakerListener + { + public: + SpeakerModeratorUpdateListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} + /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + }; + + class SpeakerMuteListener : public BaseSpeakerListener + { + public: + SpeakerMuteListener(LLParticipantList& parent) : BaseSpeakerListener(parent) {} - /** - * Set a callback to be called before adding a speaker. Invalid speakers will not be added. - * - * If the callback is unset all speakers are considered as valid. - * - * @see onAddItemEvent() - */ - void setValidateSpeakerCallback(validate_speaker_callback_t cb); + /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + }; + /** + * Menu used in the participant list. + */ + class LLParticipantListMenu : public LLListContextMenu + { + public: + LLParticipantListMenu(LLParticipantList& parent):mParent(parent){}; + /*virtual*/ LLContextMenu* createMenu(); + /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); protected: + LLParticipantList& mParent; + private: + bool enableContextMenuItem(const LLSD& userdata); + bool enableModerateContextMenuItem(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + + void sortParticipantList(const LLSD& userdata); + void toggleAllowTextChat(const LLSD& userdata); + void toggleMute(const LLSD& userdata, U32 flags); + void toggleMuteText(const LLSD& userdata); + void toggleMuteVoice(const LLSD& userdata); + /** - * LLSpeakerMgr event handlers + * Return true if Agent is group moderator(and moderator of group call). */ - bool onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); - bool onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); - bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); - bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); - bool onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + bool isGroupModerator(); + // Voice moderation support /** - * Sorts the Avatarlist by stored order + * Check whether specified by argument avatar is muted for group chat or not. */ - void sort(); - - //List of listeners implementing LLOldEvents::LLSimpleListener. - //There is no way to handle all the events in one listener as LLSpeakerMgr registers listeners in such a way - //that one listener can handle only one type of event - class BaseSpeakerListner : public LLOldEvents::LLSimpleListener - { - public: - BaseSpeakerListner(LLParticipantList& parent) : mParent(parent) {} - protected: - LLParticipantList& mParent; - }; - - class SpeakerAddListener : public BaseSpeakerListner - { - public: - SpeakerAddListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {} - /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); - }; - - class SpeakerRemoveListener : public BaseSpeakerListner - { - public: - SpeakerRemoveListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {} - /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); - }; - - class SpeakerClearListener : public BaseSpeakerListner - { - public: - SpeakerClearListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {} - /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); - }; - - class SpeakerModeratorUpdateListener : public BaseSpeakerListner - { - public: - SpeakerModeratorUpdateListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {} - /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); - }; - - class SpeakerMuteListener : public BaseSpeakerListner - { - public: - SpeakerMuteListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {} - - /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); - }; + bool isMuted(const LLUUID& avatar_id); /** - * Menu used in the participant list. + * Processes Voice moderation menu items. + * + * It calls either moderateVoiceParticipant() or moderateVoiceParticipant() depend on + * passed parameter. + * + * @param userdata can be "selected" or "others". + * + * @see moderateVoiceParticipant() + * @see moderateVoiceAllParticipants() */ - class LLParticipantListMenu : public LLListContextMenu - { - public: - LLParticipantListMenu(LLParticipantList& parent):mParent(parent){}; - /*virtual*/ LLContextMenu* createMenu(); - /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); - protected: - LLParticipantList& mParent; - private: - bool enableContextMenuItem(const LLSD& userdata); - bool enableModerateContextMenuItem(const LLSD& userdata); - bool checkContextMenuItem(const LLSD& userdata); - - void sortParticipantList(const LLSD& userdata); - void toggleAllowTextChat(const LLSD& userdata); - void toggleMute(const LLSD& userdata, U32 flags); - void toggleMuteText(const LLSD& userdata); - void toggleMuteVoice(const LLSD& userdata); - - /** - * Return true if Agent is group moderator(and moderator of group call). - */ - bool isGroupModerator(); - - // Voice moderation support - /** - * Check whether specified by argument avatar is muted for group chat or not. - */ - bool isMuted(const LLUUID& avatar_id); - - /** - * Processes Voice moderation menu items. - * - * It calls either moderateVoiceParticipant() or moderateVoiceParticipant() depend on - * passed parameter. - * - * @param userdata can be "selected" or "others". - * - * @see moderateVoiceParticipant() - * @see moderateVoiceAllParticipants() - */ - void moderateVoice(const LLSD& userdata); - - /** - * Mutes/Unmutes avatar for current group voice chat. - * - * It only marks avatar as muted for session and does not use local Agent's Block list. - * It does not mute Agent itself. - * - * @param[in] avatar_id UUID of avatar to be processed - * @param[in] unmute if true - specified avatar will be muted, otherwise - unmuted. - * - * @see moderateVoiceAllParticipants() - */ - void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); - - /** - * Mutes/Unmutes all avatars for current group voice chat. - * - * It only marks avatars as muted for session and does not use local Agent's Block list. - * - * @param[in] unmute if true - avatars will be muted, otherwise - unmuted. - * - * @see moderateVoiceParticipant() - */ - void moderateVoiceAllParticipants(bool unmute); - - static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response); - }; + void moderateVoice(const LLSD& userdata); /** - * Comparator for comparing avatar items by last spoken time + * Mutes/Unmutes avatar for current group voice chat. + * + * It only marks avatar as muted for session and does not use local Agent's Block list. + * It does not mute Agent itself. + * + * @param[in] avatar_id UUID of avatar to be processed + * @param[in] unmute if true - specified avatar will be muted, otherwise - unmuted. + * + * @see moderateVoiceAllParticipants() */ - class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator, public LLRefCount - { - LOG_CLASS(LLAvatarItemRecentSpeakerComparator); - public: - LLAvatarItemRecentSpeakerComparator(LLParticipantList& parent):mParent(parent){}; - virtual ~LLAvatarItemRecentSpeakerComparator() {}; - protected: - virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const; - private: - LLParticipantList& mParent; - }; - - private: - void onAvatarListDoubleClicked(LLUICtrl* ctrl); - void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); - - void onAvalineCallerFound(const LLUUID& participant_id); - void onAvalineCallerRemoved(const LLUUID& participant_id); + void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); /** - * Adjusts passed participant to work properly. + * Mutes/Unmutes all avatars for current group voice chat. * - * Adds SpeakerMuteListener to process moderation actions. - */ - void adjustParticipant(const LLUUID& speaker_id); - - LLSpeakerMgr* mSpeakerMgr; - LLAvatarList* mAvatarList; - - std::set<LLUUID> mModeratorList; - std::set<LLUUID> mModeratorToRemoveList; - - LLPointer<SpeakerAddListener> mSpeakerAddListener; - LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener; - LLPointer<SpeakerClearListener> mSpeakerClearListener; - LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener; - LLPointer<SpeakerMuteListener> mSpeakerMuteListener; - - LLParticipantListMenu* mParticipantListMenu; - - EParticipantSortOrder mSortOrder; - /* - * This field manages an adding a new avatar_id in the mAvatarList - * If true, then agent_id wont be added into mAvatarList - * Also by default this field is controlling a sort procedure, @c sort() + * It only marks avatars as muted for session and does not use local Agent's Block list. + * + * @param[in] unmute if true - avatars will be muted, otherwise - unmuted. + * + * @see moderateVoiceParticipant() */ - bool mExcludeAgent; + void moderateVoiceAllParticipants(bool unmute); - // boost::connections - boost::signals2::connection mAvatarListDoubleClickConnection; - boost::signals2::connection mAvatarListRefreshConnection; - boost::signals2::connection mAvatarListReturnConnection; - boost::signals2::connection mAvatarListToggleIconsConnection; + static void confirmMuteAllCallback(const LLSD& notification, const LLSD& response); + }; - LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers; - validate_speaker_callback_t mValidateSpeakerCallback; - LLAvalineUpdater* mAvalineUpdater; + /** + * Comparator for comparing avatar items by last spoken time + */ + class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator, public LLRefCount + { + LOG_CLASS(LLAvatarItemRecentSpeakerComparator); + public: + LLAvatarItemRecentSpeakerComparator(LLParticipantList& parent):mParent(parent){}; + virtual ~LLAvatarItemRecentSpeakerComparator() {}; + protected: + virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const; + private: + LLParticipantList& mParent; + }; + +private: + void onAvatarListDoubleClicked(LLUICtrl* ctrl); + void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); + + void onAvalineCallerFound(const LLUUID& participant_id); + void onAvalineCallerRemoved(const LLUUID& participant_id); + + /** + * Adjusts passed participant to work properly. + * + * Adds SpeakerMuteListener to process moderation actions. + */ + void adjustParticipant(const LLUUID& speaker_id); + + LLSpeakerMgr* mSpeakerMgr; + LLAvatarList* mAvatarList; + + std::set<LLUUID> mModeratorList; + std::set<LLUUID> mModeratorToRemoveList; + + LLPointer<SpeakerAddListener> mSpeakerAddListener; + LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener; + LLPointer<SpeakerClearListener> mSpeakerClearListener; + LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener; + LLPointer<SpeakerMuteListener> mSpeakerMuteListener; + + LLParticipantListMenu* mParticipantListMenu; + + /** + * This field manages an adding a new avatar_id in the mAvatarList + * If true, then agent_id wont be added into mAvatarList + * Also by default this field is controlling a sort procedure, @c sort() + */ + bool mExcludeAgent; + + // boost::connections + boost::signals2::connection mAvatarListDoubleClickConnection; + boost::signals2::connection mAvatarListRefreshConnection; + boost::signals2::connection mAvatarListReturnConnection; + boost::signals2::connection mAvatarListToggleIconsConnection; + + LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers; + validate_speaker_callback_t mValidateSpeakerCallback; + LLAvalineUpdater* mAvalineUpdater; }; + +#endif // LL_PARTICIPANTLIST_H diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index 408270a1a0..29e262199e 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -205,24 +205,6 @@ BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask) return LLFolderView::handleRightMouseDown(x, y, mask); } -BOOL LLPlacesFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - // Don't accept anything except landmarks and folders to be dropped - // in places folder view. See STORM-296. - if (cargo_type != DAD_LANDMARK && cargo_type != DAD_CATEGORY) - { - *accept = ACCEPT_NO; - return FALSE; - } - - return LLFolderView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, - accept, tooltip_msg); -} - void LLPlacesFolderView::setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle) { mMenuHandlesByInventoryType[asset_type] = menu_handle; diff --git a/indra/newview/llplacesinventorypanel.h b/indra/newview/llplacesinventorypanel.h index a44776d18b..6641871a0b 100644 --- a/indra/newview/llplacesinventorypanel.h +++ b/indra/newview/llplacesinventorypanel.h @@ -70,12 +70,6 @@ public: */ /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - void setupMenuHandle(LLInventoryType::EType asset_type, LLHandle<LLView> menu_handle); void setParentLandmarksPanel(LLLandmarksPanel* panel) diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 18c9ac28c1..61f4897ed0 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -369,7 +369,7 @@ void LLScreenChannel::loadStoredToastsToChannel() for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it) { (*it).toast->setIsHidden(false); - (*it).toast->resetTimer(); + (*it).toast->startFading(); mToastList.push_back((*it)); } @@ -394,7 +394,7 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id) } toast->setIsHidden(false); - toast->resetTimer(); + toast->startFading(); mToastList.push_back((*it)); redrawToasts(); @@ -477,7 +477,7 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel) toast->removeChild(old_panel); delete old_panel; toast->insertPanel(panel); - toast->resetTimer(); + toast->startFading(); redrawToasts(); } } @@ -588,7 +588,7 @@ void LLScreenChannel::showToastsBottom() mHiddenToastsNum = 0; for(; it != mToastList.rend(); it++) { - (*it).toast->stopTimer(); + (*it).toast->stopFading(); (*it).toast->setVisible(FALSE); mHiddenToastsNum++; } diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp index f9c0fd398e..be797ea937 100644 --- a/indra/newview/llsidepaneliteminfo.cpp +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -68,10 +68,22 @@ private: void LLItemPropertiesObserver::changed(U32 mask) { - // if there's a change we're interested in. - if((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0) + const std::set<LLUUID>& mChangedItemIDs = gInventory.getChangedIDs(); + std::set<LLUUID>::const_iterator it; + + const LLUUID& object_id = mFloater->getObjectID(); + + for (it = mChangedItemIDs.begin(); it != mChangedItemIDs.end(); it++) { - mFloater->dirty(); + // set dirty for 'item profile panel' only if changed item is the item for which 'item profile panel' is shown (STORM-288) + if (*it == object_id) + { + // if there's a change we're interested in. + if((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0) + { + mFloater->dirty(); + } + } } } @@ -179,6 +191,11 @@ void LLSidepanelItemInfo::setItemID(const LLUUID& item_id) mItemID = item_id; } +const LLUUID& LLSidepanelItemInfo::getObjectID() const +{ + return mObjectID; +} + void LLSidepanelItemInfo::reset() { LLSidepanelInventorySubpanel::reset(); diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h index 10e93dd7de..6416e2cfe4 100644 --- a/indra/newview/llsidepaneliteminfo.h +++ b/indra/newview/llsidepaneliteminfo.h @@ -54,6 +54,8 @@ public: void setItemID(const LLUUID& item_id); void setEditMode(BOOL edit); + const LLUUID& getObjectID() const; + protected: /*virtual*/ void refresh(); /*virtual*/ void save(); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index fafef84aa2..d6d38de225 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -299,6 +299,7 @@ public: { static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog"); static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator"); + static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; if (log_to_viewer_log || log_to_sim) { @@ -332,6 +333,16 @@ public: } S32 data_size = worker->callbackHttpGet(channels, buffer, partial, success); + + if(log_texture_traffic && data_size > 0) + { + LLViewerTexture* tex = LLViewerTextureManager::findTexture(mID) ; + if(tex) + { + gTotalTextureBytesPerBoostLevel[tex->getBoostLevel()] += data_size ; + } + } + mFetcher->removeFromHTTPQueue(mID, data_size); } else diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index c87aff022f..b9a15fd1f4 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -514,7 +514,8 @@ void LLGLTexMemBar::draw() F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ; S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); S32 v_offset = (S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f); - S32 total_downloaded = BYTES_TO_MEGA_BYTES(gTotalTextureBytes); + F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024); + F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024); //---------------------------------------------------------------------------- LLGLSUIDefault gls_ui; LLColor4 text_color(1.f, 1.f, 1.f, 0.75f); @@ -525,13 +526,13 @@ void LLGLTexMemBar::draw() LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*6, text_color, LLFontGL::LEFT, LLFontGL::TOP); - text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot: %d MB", + text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot Tex: %.1f MB Tot Obj: %.1f MB", total_mem, max_total_mem, bound_mem, max_bound_mem, LLImageRaw::sGlobalRawMemory >> 20, discard_bias, - cache_usage, cache_max_usage, total_downloaded); + cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded); //, cache_entries, cache_max_entries LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3, diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index c3090cb1fc..8176b8c1f9 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -35,6 +35,13 @@ using namespace LLNotificationsUI; +//-------------------------------------------------------------------------- +LLToastLifeTimer::LLToastLifeTimer(LLToast* toast, F32 period) + : mToast(toast), + LLEventTimer(period) +{ +} + /*virtual*/ BOOL LLToastLifeTimer::tick() { @@ -45,6 +52,38 @@ BOOL LLToastLifeTimer::tick() return FALSE; } +void LLToastLifeTimer::stop() +{ + mEventTimer.stop(); +} + +void LLToastLifeTimer::start() +{ + mEventTimer.start(); +} + +void LLToastLifeTimer::restart() +{ + mEventTimer.reset(); +} + +BOOL LLToastLifeTimer::getStarted() +{ + return mEventTimer.getStarted(); +} + +void LLToastLifeTimer::setPeriod(F32 period) +{ + mPeriod = period; +} + +F32 LLToastLifeTimer::getRemainingTimeF32() +{ + F32 et = mEventTimer.getElapsedTimeF32(); + if (!getStarted() || et > mPeriod) return 0.0f; + return mPeriod - et; +} + //-------------------------------------------------------------------------- LLToast::Params::Params() : can_fade("can_fade", true), @@ -73,7 +112,8 @@ LLToast::LLToast(const LLToast::Params& p) mIsHidden(false), mHideBtnPressed(false), mIsTip(p.is_tip), - mWrapperPanel(NULL) + mWrapperPanel(NULL), + mIsTransparent(false) { mTimer.reset(new LLToastLifeTimer(this, p.lifetime_secs)); @@ -143,6 +183,7 @@ LLToast::~LLToast() void LLToast::hide() { setVisible(FALSE); + setTransparentState(false); mTimer->stop(); mIsHidden = true; mOnFadeSignal(this); @@ -166,6 +207,16 @@ void LLToast::onFocusReceived() } } +void LLToast::setLifetime(S32 seconds) +{ + mToastLifetime = seconds; +} + +void LLToast::setFadingTime(S32 seconds) +{ + mToastFadingTime = seconds; +} + S32 LLToast::getTopPad() { if(mWrapperPanel) @@ -195,13 +246,46 @@ void LLToast::setCanFade(bool can_fade) //-------------------------------------------------------------------------- void LLToast::expire() { - // if toast has fade property - hide it - if(mCanFade) + if (mCanFade) { - hide(); + if (mIsTransparent) + { + hide(); + } + else + { + setTransparentState(true); + mTimer->restart(); + } } } +void LLToast::setTransparentState(bool transparent) +{ + setBackgroundOpaque(!transparent); + mIsTransparent = transparent; + + if (transparent) + { + mTimer->setPeriod(mToastFadingTime); + } + else + { + mTimer->setPeriod(mToastLifetime); + } +} + +F32 LLToast::getTimeLeftToLive() +{ + F32 time_to_live = mTimer->getRemainingTimeF32(); + + if (!mIsTransparent) + { + time_to_live += mToastFadingTime; + } + + return time_to_live; +} //-------------------------------------------------------------------------- void LLToast::reshapeToPanel() @@ -245,13 +329,6 @@ void LLToast::draw() drawChild(mHideBtn); } } - - // if timer started and remaining time <= fading time - if (mTimer->getStarted() && (mToastLifetime - - mTimer->getEventTimer().getElapsedTimeF32()) <= mToastFadingTime) - { - setBackgroundOpaque(FALSE); - } } //-------------------------------------------------------------------------- @@ -267,6 +344,11 @@ void LLToast::setVisible(BOOL show) return; } + if (show && getVisible()) + { + return; + } + if(show) { setBackgroundOpaque(TRUE); @@ -372,7 +454,8 @@ void LLNotificationsUI::LLToast::stopFading() { if(mCanFade) { - stopTimer(); + setTransparentState(false); + mTimer->stop(); } } @@ -380,7 +463,8 @@ void LLNotificationsUI::LLToast::startFading() { if(mCanFade) { - resetTimer(); + setTransparentState(false); + mTimer->start(); } } diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 0a96c092a0..fb534561c9 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -49,14 +49,16 @@ class LLToast; class LLToastLifeTimer: public LLEventTimer { public: - LLToastLifeTimer(LLToast* toast, F32 period) : mToast(toast), LLEventTimer(period){} + LLToastLifeTimer(LLToast* toast, F32 period); /*virtual*/ BOOL tick(); - void stop() { mEventTimer.stop(); } - void start() { mEventTimer.start(); } - void restart() {mEventTimer.reset(); } - BOOL getStarted() { return mEventTimer.getStarted(); } + void stop(); + void start(); + void restart(); + BOOL getStarted(); + void setPeriod(F32 period); + F32 getRemainingTimeF32(); LLTimer& getEventTimer() { return mEventTimer;} private : @@ -80,8 +82,14 @@ public: Optional<LLUUID> notif_id, //notification ID session_id; //im session ID Optional<LLNotificationPtr> notification; - Optional<F32> lifetime_secs, - fading_time_secs; // Number of seconds while a toast is fading + + //NOTE: Life time of a toast (i.e. period of time from the moment toast was shown + //till the moment when toast was hidden) is the sum of lifetime_secs and fading_time_secs. + + Optional<F32> lifetime_secs, // Number of seconds while a toast is non-transparent + fading_time_secs; // Number of seconds while a toast is transparent + + Optional<toast_callback_t> on_delete_toast, on_mouse_enter; Optional<bool> can_fade, @@ -125,10 +133,8 @@ public: LLPanel* getPanel() { return mPanel; } // enable/disable Toast's Hide button void setHideButtonEnabled(bool enabled); - // - void resetTimer() { mTimer->start(); } // - void stopTimer() { mTimer->stop(); } + F32 getTimeLeftToLive(); // LLToastLifeTimer* getTimer() { return mTimer.get();} // @@ -144,6 +150,10 @@ public: /*virtual*/ void onFocusReceived(); + void setLifetime(S32 seconds); + + void setFadingTime(S32 seconds); + /** * Returns padding between floater top and wrapper_panel top. * This padding should be taken into account when positioning or reshaping toasts @@ -196,7 +206,9 @@ private: void onToastMouseLeave(); - void expire(); + void expire(); + + void setTransparentState(bool transparent); LLUUID mNotificationID; LLUUID mSessionID; @@ -222,6 +234,7 @@ private: bool mHideBtnPressed; bool mIsHidden; // this flag is TRUE when a toast has faded or was hidden with (x) button (EXT-1849) bool mIsTip; + bool mIsTransparent; commit_signal_t mToastMouseEnterSignal; commit_signal_t mToastMouseLeaveSignal; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 88bf2006f9..6d59b687f3 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1,1498 +1,1510 @@ -/** - * @file llviewerdisplay.cpp - * @brief LLViewerDisplay class implementation - * - * $LicenseInfo:firstyear=2004&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$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llviewerdisplay.h" - -#include "llgl.h" -#include "llrender.h" -#include "llglheaders.h" -#include "llagent.h" -#include "llagentcamera.h" -#include "llviewercontrol.h" -#include "llcoord.h" -#include "llcriticaldamp.h" -#include "lldir.h" -#include "lldynamictexture.h" -#include "lldrawpoolalpha.h" -#include "llfeaturemanager.h" -//#include "llfirstuse.h" -#include "llhudmanager.h" -#include "llimagebmp.h" -#include "llmemory.h" -#include "llselectmgr.h" -#include "llsky.h" -#include "llstartup.h" -#include "lltoolfocus.h" -#include "lltoolmgr.h" -#include "lltooldraganddrop.h" -#include "lltoolpie.h" -#include "lltracker.h" -#include "lltrans.h" -#include "llui.h" -#include "llviewercamera.h" -#include "llviewerobjectlist.h" -#include "llviewerparcelmgr.h" -#include "llviewerwindow.h" -#include "llvoavatarself.h" -#include "llvograss.h" -#include "llworld.h" -#include "pipeline.h" -#include "llspatialpartition.h" -#include "llappviewer.h" -#include "llstartup.h" -#include "llviewershadermgr.h" -#include "llfasttimer.h" -#include "llfloatertools.h" -#include "llviewertexturelist.h" -#include "llfocusmgr.h" -#include "llcubemap.h" -#include "llviewerregion.h" -#include "lldrawpoolwater.h" -#include "lldrawpoolbump.h" -#include "llwlparammanager.h" -#include "llwaterparammanager.h" -#include "llpostprocess.h" - -extern LLPointer<LLViewerTexture> gStartTexture; - -LLPointer<LLViewerTexture> gDisconnectedImagep = NULL; - -// used to toggle renderer back on after teleport -const F32 TELEPORT_RENDER_DELAY = 20.f; // Max time a teleport is allowed to take before we raise the curtain -const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. -const F32 TELEPORT_LOCAL_DELAY = 1.0f; // Delay to prevent teleports after starting an in-sim teleport. -BOOL gTeleportDisplay = FALSE; -LLFrameTimer gTeleportDisplayTimer; -LLFrameTimer gTeleportArrivalTimer; -const F32 RESTORE_GL_TIME = 5.f; // Wait this long while reloading textures before we raise the curtain - -BOOL gForceRenderLandFence = FALSE; -BOOL gDisplaySwapBuffers = FALSE; -BOOL gDepthDirty = FALSE; -BOOL gResizeScreenTexture = FALSE; -BOOL gSnapshot = FALSE; - -U32 gRecentFrameCount = 0; // number of 'recent' frames -LLFrameTimer gRecentFPSTime; -LLFrameTimer gRecentMemoryTime; - -// Rendering stuff -void pre_show_depth_buffer(); -void post_show_depth_buffer(); -void render_ui(F32 zoom_factor = 1.f, int subfield = 0); -void render_hud_attachments(); -void render_ui_3d(); -void render_ui_2d(); -void render_disconnected_background(); - -void display_startup() -{ - if ( !gViewerWindow->getActive() - || !gViewerWindow->mWindow->getVisible() - || gViewerWindow->mWindow->getMinimized() - || gNoRender ) - { - return; - } - - gPipeline.updateGL(); - - // Update images? - //gImageList.updateImages(0.01f); - - LLGLSDefault gls_default; - - // Required for HTML update in login screen - static S32 frame_count = 0; - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - - if (frame_count++ > 1) // make sure we have rendered a frame first - { - LLViewerDynamicTexture::updateAllInstances(); - } - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - LLGLSUIDefault gls_ui; - gPipeline.disableLights(); - - gViewerWindow->setup2DRender(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - - gGL.color4f(1,1,1,1); - gViewerWindow->draw(); - gGL.flush(); - - LLVertexBuffer::unbind(); - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - - gViewerWindow->mWindow->swapBuffers(); - glClear(GL_DEPTH_BUFFER_BIT); -} - -void display_update_camera() -{ - LLMemType mt_uc(LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA); - // TODO: cut draw distance down if customizing avatar? - // TODO: cut draw distance on per-parcel basis? - - // Cut draw distance in half when customizing avatar, - // but on the viewer only. - F32 final_far = gAgentCamera.mDrawDistance; - if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode()) - { - final_far *= 0.5f; - } - LLViewerCamera::getInstance()->setFar(final_far); - gViewerWindow->setup3DRender(); - - // update all the sky/atmospheric/water settings - LLWLParamManager::instance()->update(LLViewerCamera::getInstance()); - LLWaterParamManager::instance()->update(LLViewerCamera::getInstance()); - - // Update land visibility too - LLWorld::getInstance()->setLandFarClip(final_far); -} - -// Write some stats to llinfos -void display_stats() -{ - F32 fps_log_freq = gSavedSettings.getF32("FPSLogFrequency"); - if (fps_log_freq > 0.f && gRecentFPSTime.getElapsedTimeF32() >= fps_log_freq) - { - F32 fps = gRecentFrameCount / fps_log_freq; - llinfos << llformat("FPS: %.02f", fps) << llendl; - gRecentFrameCount = 0; - gRecentFPSTime.reset(); - } - F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency"); - if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq) - { - gMemoryAllocated = LLMemory::getCurrentRSS(); - U32 memory = (U32)(gMemoryAllocated / (1024*1024)); - llinfos << llformat("MEMORY: %d MB", memory) << llendl; - gRecentMemoryTime.reset(); - } -} - -static LLFastTimer::DeclareTimer FTM_PICK("Picking"); -static LLFastTimer::DeclareTimer FTM_RENDER("Render", true); -static LLFastTimer::DeclareTimer FTM_UPDATE_SKY("Update Sky"); -static LLFastTimer::DeclareTimer FTM_UPDATE_TEXTURES("Update Textures"); -static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE("Update Images"); - -// Paint the display! -void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) -{ - LLMemType mt_render(LLMemType::MTYPE_RENDER); - LLFastTimer t(FTM_RENDER); - - if (gResizeScreenTexture) - { //skip render on frames where screen texture is resizing - gGL.flush(); - glClear(GL_COLOR_BUFFER_BIT); - gViewerWindow->mWindow->swapBuffers(); - gResizeScreenTexture = FALSE; - gPipeline.resizeScreenTexture(); - return; - } - - if (LLPipeline::sRenderFrameTest) - { - send_agent_pause(); - } - - gSnapshot = for_snapshot; - - LLGLSDefault gls_default; - LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL); - - LLVertexBuffer::unbind(); - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - - stop_glerror(); - - gPipeline.disableLights(); - - stop_glerror(); - - // Don't draw if the window is hidden or minimized. - // In fact, must explicitly check the minimized state before drawing. - // Attempting to draw into a minimized window causes a GL error. JC - if ( !gViewerWindow->getActive() - || !gViewerWindow->mWindow->getVisible() - || gViewerWindow->mWindow->getMinimized() ) - { - // Clean up memory the pools may have allocated - if (rebuild) - { - stop_glerror(); - gPipeline.rebuildPools(); - stop_glerror(); - } - - stop_glerror(); - gViewerWindow->returnEmptyPicks(); - stop_glerror(); - return; - } - - gViewerWindow->checkSettings(); - - { - LLFastTimer ftm(FTM_PICK); - LLAppViewer::instance()->pingMainloopTimeout("Display:Pick"); - gViewerWindow->performPick(); - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates"); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - - ////////////////////////////////////////////////////////// - // - // Logic for forcing window updates if we're in drone mode. - // - - if (gNoRender) - { -#if LL_WINDOWS - static F32 last_update_time = 0.f; - if ((gFrameTimeSeconds - last_update_time) > 1.f) - { - InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE); - last_update_time = gFrameTimeSeconds; - } -#elif LL_DARWIN - // MBW -- Do something clever here. -#endif - // Not actually rendering, don't bother. - return; - } - - - // - // Bail out if we're in the startup state and don't want to try to - // render the world. - // - if (LLStartUp::getStartupState() < STATE_STARTED) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:Startup"); - display_startup(); - return; - } - - //LLGLState::verify(FALSE); - - ///////////////////////////////////////////////// - // - // Update GL Texture statistics (used for discard logic?) - // - - LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats"); - stop_glerror(); - - LLImageGL::updateStats(gFrameTimeSeconds); - - LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode"); - LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode")); - - gPipeline.mBackfaceCull = TRUE; - gFrameCount++; - gRecentFrameCount++; - if (gFocusMgr.getAppHasFocus()) - { - gForegroundFrameCount++; - } - - ////////////////////////////////////////////////////////// - // - // Display start screen if we're teleporting, and skip render - // - - if (gTeleportDisplay) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport"); - const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. - - S32 attach_count = 0; - if (isAgentAvatarValid()) - { - attach_count = gAgentAvatarp->getAttachmentCount(); - } - F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count; - F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32(); - F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time); - if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) ) - { - // Give up. Don't keep the UI locked forever. - gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); - gAgent.setTeleportMessage(std::string()); - } - - const std::string& message = gAgent.getTeleportMessage(); - switch( gAgent.getTeleportState() ) - { - case LLAgent::TELEPORT_START: - // Transition to REQUESTED. Viewer has sent some kind - // of TeleportRequest to the source simulator - gTeleportDisplayTimer.reset(); - gViewerWindow->setShowProgress(TRUE); - gViewerWindow->setProgressPercent(0); - gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); - gAgent.setTeleportMessage( - LLAgent::sTeleportProgressMessages["requesting"]); - break; - - case LLAgent::TELEPORT_REQUESTED: - // Waiting for source simulator to respond - gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) ); - gViewerWindow->setProgressString(message); - break; - - case LLAgent::TELEPORT_MOVING: - // Viewer has received destination location from source simulator - gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) ); - gViewerWindow->setProgressString(message); - break; - - case LLAgent::TELEPORT_START_ARRIVAL: - // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator - gTeleportArrivalTimer.reset(); - gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); - gViewerWindow->setProgressPercent(75.f); - gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING ); - gAgent.setTeleportMessage( - LLAgent::sTeleportProgressMessages["arriving"]); - gTextureList.mForceResetTextureStats = TRUE; - gAgentCamera.resetView(TRUE, TRUE); - break; - - case LLAgent::TELEPORT_ARRIVING: - // Make the user wait while content "pre-caches" - { - F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY); - if( arrival_fraction > 1.f ) - { - arrival_fraction = 1.f; - //LLFirstUse::useTeleport(); - gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); - } - gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); - gViewerWindow->setProgressPercent( arrival_fraction * 25.f + 75.f); - gViewerWindow->setProgressString(message); - } - break; - - case LLAgent::TELEPORT_LOCAL: - // Short delay when teleporting in the same sim (progress screen active but not shown - did not - // fall-through from TELEPORT_START) - { - if( gTeleportDisplayTimer.getElapsedTimeF32() > TELEPORT_LOCAL_DELAY ) - { - //LLFirstUse::useTeleport(); - gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); - } - } - break; - - case LLAgent::TELEPORT_NONE: - // No teleport in progress - gViewerWindow->setShowProgress(FALSE); - gTeleportDisplay = FALSE; - break; - } - } - else if(LLAppViewer::instance()->logoutRequestSent()) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:Logout"); - F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime; - if (percent_done > 100.f) - { - percent_done = 100.f; - } - - if( LLApp::isExiting() ) - { - percent_done = 100.f; - } - - gViewerWindow->setProgressPercent( percent_done ); - } - else - if (gRestoreGL) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL"); - F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME; - if( percent_done > 100.f ) - { - gViewerWindow->setShowProgress(FALSE); - gRestoreGL = FALSE; - } - else - { - - if( LLApp::isExiting() ) - { - percent_done = 100.f; - } - - gViewerWindow->setProgressPercent( percent_done ); - } - } - - ////////////////////////// - // - // Prepare for the next frame - // - - ///////////////////////////// - // - // Update the camera - // - // - - LLAppViewer::instance()->pingMainloopTimeout("Display:Camera"); - LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield); - LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE); - - ////////////////////////// - // - // clear the next buffer - // (must follow dynamic texture writing since that uses the frame buffer) - // - - if (gDisconnected) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected"); - render_ui(); - } - - ////////////////////////// - // - // Set rendering options - // - // - LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup"); - stop_glerror(); - - /////////////////////////////////////// - // - // Slam lighting parameters back to our defaults. - // Note that these are not the same as GL defaults... - - stop_glerror(); - F32 one[4] = {1.f, 1.f, 1.f, 1.f}; - glLightModelfv (GL_LIGHT_MODEL_AMBIENT,one); - stop_glerror(); - - ///////////////////////////////////// - // - // Render - // - // Actually push all of our triangles to the screen. - // - - // do render-to-texture stuff here - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES)) - { - LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures"); - LLFastTimer t(FTM_UPDATE_TEXTURES); - if (LLViewerDynamicTexture::updateAllInstances()) - { - gGL.setColorMask(true, true); - glClear(GL_DEPTH_BUFFER_BIT); - } - } - - gViewerWindow->setup3DViewport(); - - gPipeline.resetFrameStats(); // Reset per-frame statistics. - - if (!gDisconnected) - { - LLMemType mt_du(LLMemType::MTYPE_DISPLAY_UPDATE); - LLAppViewer::instance()->pingMainloopTimeout("Display:Update"); - if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) - { //don't draw hud objects in this frame - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); - } - - if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES)) - { //don't draw hud particles in this frame - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); - } - - //upkeep gl name pools - LLGLNamePool::upkeepPools(); - - stop_glerror(); - display_update_camera(); - stop_glerror(); - - // *TODO: merge these two methods - { - LLMemType mt_uh(LLMemType::MTYPE_DISPLAY_UPDATE_HUD); - LLHUDManager::getInstance()->updateEffects(); - LLHUDObject::updateAll(); - stop_glerror(); - } - - { - LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM); - const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time - gPipeline.createObjects(max_geom_update_time); - gPipeline.updateGeom(max_geom_update_time); - stop_glerror(); - } - - gPipeline.updateGL(); - stop_glerror(); - - S32 water_clip = 0; - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) && - (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) || - gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER))) - { - if (LLViewerCamera::getInstance()->cameraUnderWater()) - { - water_clip = -1; - } - else - { - water_clip = 1; - } - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:Cull"); - - //Increment drawable frame counter - LLDrawable::incrementVisible(); - - LLSpatialGroup::sNoDelete = TRUE; - LLPipeline::sUseOcclusion = - (!gUseWireframe - && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") - && gSavedSettings.getBOOL("UseOcclusion") - && gGLManager.mHasOcclusionQuery) ? 2 : 0; - - if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) - { //force occlusion on for all render types if doing deferred render - LLPipeline::sUseOcclusion = 3; - } - - LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred"); - LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred"); - LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); - LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible"); - LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate"); - - S32 occlusion = LLPipeline::sUseOcclusion; - if (gDepthDirty) - { //depth buffer is invalid, don't overwrite occlusion state - LLPipeline::sUseOcclusion = llmin(occlusion, 1); - } - gDepthDirty = FALSE; - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - - static LLCullResult result; - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip); - stop_glerror(); - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - - BOOL to_texture = !for_snapshot && - gPipeline.canUseVertexShaders() && - LLPipeline::sRenderGlow; - - LLAppViewer::instance()->pingMainloopTimeout("Display:Swap"); - - { - LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SWAP); - { - LLFastTimer ftm(FTM_CLIENT_COPY); - LLVertexBuffer::clientCopy(0.016); - } - - //if (gResizeScreenTexture) - //{ - // gResizeScreenTexture = FALSE; - // gPipeline.resizeScreenTexture(); - //} - - gGL.setColorMask(true, true); - glClearColor(0,0,0,0); - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - - if (!for_snapshot) - { - if (gFrameCount > 1) - { //for some reason, ATI 4800 series will error out if you - //try to generate a shadow before the first frame is through - gPipeline.generateSunShadow(*LLViewerCamera::getInstance()); - } - - LLVertexBuffer::unbind(); - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - - glh::matrix4f proj = glh_get_current_projection(); - glh::matrix4f mod = glh_get_current_modelview(); - glViewport(0,0,512,512); - LLVOAvatar::updateFreezeCounter() ; - LLVOAvatar::updateImpostors(); - - glh_set_current_projection(proj); - glh_set_current_modelview(mod); - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(proj.m); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(mod.m); - gViewerWindow->setup3DViewport(); - - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - - } - glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - } - - if (!for_snapshot) - { - LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION); - LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery"); - gPipeline.generateWaterReflection(*LLViewerCamera::getInstance()); - gPipeline.generateHighlight(*LLViewerCamera::getInstance()); - } - - ////////////////////////////////////// - // - // Update images, using the image stats generated during object update/culling - // - // Can put objects onto the retextured list. - // - // Doing this here gives hardware occlusion queries extra time to complete - LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages"); - LLError::LLCallStacks::clear() ; - - { - LLMemType mt_iu(LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE); - LLFastTimer t(FTM_IMAGE_UPDATE); - - LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(), - LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean()); - - gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first. - - F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time - max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame) - gTextureList.updateImages(max_image_decode_time); - - //remove dead textures from GL - LLImageGL::deleteDeadTextures(); - stop_glerror(); - } - /////////////////////////////////// - // - // StateSort - // - // Responsible for taking visible objects, and adding them to the appropriate draw orders. - // In the case of alpha objects, z-sorts them first. - // Also creates special lists for outlines and selected face rendering. - // - LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort"); - { - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - LLMemType mt_ss(LLMemType::MTYPE_DISPLAY_STATE_SORT); - gPipeline.sAllowRebuildPriorityGroup = TRUE ; - gPipeline.stateSort(*LLViewerCamera::getInstance(), result); - stop_glerror(); - - if (rebuild) - { - ////////////////////////////////////// - // - // rebuildPools - // - // - gPipeline.rebuildPools(); - stop_glerror(); - } - } - - LLPipeline::sUseOcclusion = occlusion; - - { - LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SKY); - LLAppViewer::instance()->pingMainloopTimeout("Display:Sky"); - LLFastTimer t(FTM_UPDATE_SKY); - gSky.updateSky(); - } - - if(gUseWireframe) - { - glClearColor(0.5f, 0.5f, 0.5f, 0.f); - glClear(GL_COLOR_BUFFER_BIT); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart"); - - //// render frontmost floater opaque for occlusion culling purposes - //LLFloater* frontmost_floaterp = gFloaterView->getFrontmost(); - //// assumes frontmost floater with focus is opaque - //if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp)) - //{ - // glMatrixMode(GL_MODELVIEW); - // glPushMatrix(); - // { - // gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - // glLoadIdentity(); - - // LLRect floater_rect = frontmost_floaterp->calcScreenRect(); - // // deflate by one pixel so rounding errors don't occlude outside of floater extents - // floater_rect.stretch(-1); - // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidthScaled(), - // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeightScaled(), - // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidthScaled(), - // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeightScaled()); - // floater_3d_rect.translate(-0.5f, -0.5f); - // glTranslatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear()); - // glScalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f); - // gGL.color4fv(LLColor4::white.mV); - // gGL.begin(LLVertexBuffer::QUADS); - // { - // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f); - // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f); - // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f); - // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f); - // } - // gGL.end(); - // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - // } - // glPopMatrix(); - //} - - LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; - LLPipeline::updateRenderDeferred(); - - stop_glerror(); - - if (to_texture) - { - gGL.setColorMask(true, true); - - if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) - { - gPipeline.mDeferredScreen.bindTarget(); - glClearColor(0,0,0,0); - gPipeline.mDeferredScreen.clear(); - } - else - { - gPipeline.mScreen.bindTarget(); - gPipeline.mScreen.clear(); - } - - gGL.setColorMask(true, false); - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom"); - - if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot()) - && !gRestoreGL) - { - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - LLMemType mt_rg(LLMemType::MTYPE_DISPLAY_RENDER_GEOM); - gGL.setColorMask(true, false); - if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) - { - gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance()); - } - else - { - gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE); - } - - gGL.setColorMask(true, true); - - //store this frame's modelview matrix for use - //when rendering next frame's occlusion queries - for (U32 i = 0; i < 16; i++) - { - gGLLastModelView[i] = gGLModelView[i]; - gGLLastProjection[i] = gGLProjection[i]; - } - stop_glerror(); - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush"); - - if (to_texture) - { - LLMemType mt_rf(LLMemType::MTYPE_DISPLAY_RENDER_FLUSH); - if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) - { - gPipeline.mDeferredScreen.flush(); - if(LLRenderTarget::sUseFBO) - { - LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), - gPipeline.mDeferredScreen.getHeight(), 0, 0, - gPipeline.mDeferredScreen.getWidth(), - gPipeline.mDeferredScreen.getHeight(), - GL_DEPTH_BUFFER_BIT, GL_NEAREST); - } - } - else - { - gPipeline.mScreen.flush(); - if(LLRenderTarget::sUseFBO) - { - LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(), - gPipeline.mScreen.getHeight(), 0, 0, - gPipeline.mScreen.getWidth(), - gPipeline.mScreen.getHeight(), - GL_DEPTH_BUFFER_BIT, GL_NEAREST); - } - } - } - - if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) - { - gPipeline.renderDeferredLighting(); - } - - LLPipeline::sUnderWaterRender = FALSE; - - LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); - if (!for_snapshot) - { - LLFastTimer t(FTM_RENDER_UI); - render_ui(); - } - - - LLSpatialGroup::sNoDelete = FALSE; - gPipeline.clearReferences(); - - gPipeline.rebuildGroups(); - } - - LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats"); - - stop_glerror(); - - if (LLPipeline::sRenderFrameTest) - { - send_agent_resume(); - LLPipeline::sRenderFrameTest = FALSE; - } - - display_stats(); - - LLAppViewer::instance()->pingMainloopTimeout("Display:Done"); -} - -void render_hud_attachments() -{ - LLMemType mt_ra(LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - glh::matrix4f current_proj = glh_get_current_projection(); - glh::matrix4f current_mod = glh_get_current_modelview(); - - // clamp target zoom level to reasonable values - gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f); - // smoothly interpolate current zoom level - gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f)); - - if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices()) - { - LLCamera hud_cam = *LLViewerCamera::getInstance(); - LLVector3 origin = hud_cam.getOrigin(); - hud_cam.setOrigin(-1.f,0,0); - hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1)); - LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE); - - bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles"); - - //only render hud objects - gPipeline.pushRenderTypeMask(); - - // turn off everything - gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES); - // turn on HUD - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); - // turn on HUD particles - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); - - // if particles are off, turn off hud-particles as well - if (!render_particles) - { - // turn back off HUD particles - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES); - } - - bool has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); - if (has_ui) - { - gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - - S32 use_occlusion = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 0; - LLPipeline::sDisableShaders = TRUE; - - //cull, sort, and render hud objects - static LLCullResult result; - LLSpatialGroup::sNoDelete = TRUE; - - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - gPipeline.updateCull(hud_cam, result); - - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE); - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY); - - gPipeline.stateSort(hud_cam, result); - - gPipeline.renderGeom(hud_cam); - - LLSpatialGroup::sNoDelete = FALSE; - gPipeline.clearReferences(); - - render_hud_elements(); - - //restore type mask - gPipeline.popRenderTypeMask(); - - if (has_ui) - { - gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); - } - LLPipeline::sUseOcclusion = use_occlusion; - LLPipeline::sDisableShaders = FALSE; - } - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glh_set_current_projection(current_proj); - glh_set_current_modelview(current_mod); -} - -LLRect get_whole_screen_region() -{ - LLRect whole_screen = gViewerWindow->getWorldViewRectScaled(); - - // 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) - { - S32 num_horizontal_tiles = llceil(zoom_factor); - S32 tile_width = llround((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor); - S32 tile_height = llround((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor); - int tile_y = sub_region / num_horizontal_tiles; - int tile_x = sub_region - (tile_y * num_horizontal_tiles); - glh::matrix4f mat; - - whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height); - } - return whole_screen; -} - -bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model) -{ - if (isAgentAvatarValid() && gAgentAvatarp->hasHUDAttachment()) - { - F32 zoom_level = gAgentCamera.mHUDCurZoom; - LLBBox hud_bbox = gAgentAvatarp->getHUDBBox(); - - F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); - proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth); - proj.element(2,2) = -0.01f; - - F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect(); - - glh::matrix4f mat; - F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth(); - F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight(); - mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f)); - mat.set_translate( - glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio), - clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y), - 0.f)); - proj *= mat; - - glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION); - - mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level)); - mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f)); - - tmp_model *= mat; - model = tmp_model; - return TRUE; - } - else - { - return FALSE; - } -} - -bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model) -{ - LLRect whole_screen = get_whole_screen_region(); - return get_hud_matrices(whole_screen, proj, model); -} - -BOOL setup_hud_matrices() -{ - LLRect whole_screen = get_whole_screen_region(); - return setup_hud_matrices(whole_screen); -} - -BOOL setup_hud_matrices(const LLRect& screen_region) -{ - glh::matrix4f proj, model; - bool result = get_hud_matrices(screen_region, proj, model); - if (!result) return result; - - // set up transform to keep HUD objects in front of camera - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(proj.m); - glh_set_current_projection(proj); - - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(model.m); - glh_set_current_modelview(model); - return TRUE; -} - -static LLFastTimer::DeclareTimer FTM_SWAP("Swap"); - -void render_ui(F32 zoom_factor, int subfield) -{ - LLMemType mt_ru(LLMemType::MTYPE_DISPLAY_RENDER_UI); - LLGLState::checkStates(); - - glPushMatrix(); - glLoadMatrixd(gGLLastModelView); - glh::matrix4f saved_view = glh_get_current_modelview(); - glh_set_current_modelview(glh_copy_matrix(gGLLastModelView)); - - { - BOOL to_texture = gPipeline.canUseVertexShaders() && - LLPipeline::sRenderGlow; - - if (to_texture) - { - gPipeline.renderBloom(gSnapshot, zoom_factor, subfield); - } - - render_hud_elements(); - render_hud_attachments(); - } - - LLGLSDefault gls_default; - LLGLSUIDefault gls_ui; - { - gPipeline.disableLights(); - } - - { - gGL.color4f(1,1,1,1); - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - LLFastTimer t(FTM_RENDER_UI); - - if (!gDisconnected) - { - render_ui_3d(); - LLGLState::checkStates(); - } - else - { - render_disconnected_background(); - } - - render_ui_2d(); - LLGLState::checkStates(); - } - gGL.flush(); - - { - gViewerWindow->setup2DRender(); - gViewerWindow->updateDebugText(); - gViewerWindow->drawDebugText(); - } - - LLVertexBuffer::unbind(); - } - - glh_set_current_modelview(saved_view); - glPopMatrix(); - - if (gDisplaySwapBuffers) - { - LLFastTimer t(FTM_SWAP); - gViewerWindow->mWindow->swapBuffers(); - } - gDisplaySwapBuffers = TRUE; -} - -void renderCoordinateAxes() -{ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.begin(LLRender::LINES); - gGL.color3f(1.0f, 0.0f, 0.0f); // i direction = X-Axis = red - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(2.0f, 0.0f, 0.0f); - gGL.vertex3f(3.0f, 0.0f, 0.0f); - gGL.vertex3f(5.0f, 0.0f, 0.0f); - gGL.vertex3f(6.0f, 0.0f, 0.0f); - gGL.vertex3f(8.0f, 0.0f, 0.0f); - // Make an X - gGL.vertex3f(11.0f, 1.0f, 1.0f); - gGL.vertex3f(11.0f, -1.0f, -1.0f); - gGL.vertex3f(11.0f, 1.0f, -1.0f); - gGL.vertex3f(11.0f, -1.0f, 1.0f); - - gGL.color3f(0.0f, 1.0f, 0.0f); // j direction = Y-Axis = green - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(0.0f, 2.0f, 0.0f); - gGL.vertex3f(0.0f, 3.0f, 0.0f); - gGL.vertex3f(0.0f, 5.0f, 0.0f); - gGL.vertex3f(0.0f, 6.0f, 0.0f); - gGL.vertex3f(0.0f, 8.0f, 0.0f); - // Make a Y - gGL.vertex3f(1.0f, 11.0f, 1.0f); - gGL.vertex3f(0.0f, 11.0f, 0.0f); - gGL.vertex3f(-1.0f, 11.0f, 1.0f); - gGL.vertex3f(0.0f, 11.0f, 0.0f); - gGL.vertex3f(0.0f, 11.0f, 0.0f); - gGL.vertex3f(0.0f, 11.0f, -1.0f); - - gGL.color3f(0.0f, 0.0f, 1.0f); // Z-Axis = blue - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(0.0f, 0.0f, 2.0f); - gGL.vertex3f(0.0f, 0.0f, 3.0f); - gGL.vertex3f(0.0f, 0.0f, 5.0f); - gGL.vertex3f(0.0f, 0.0f, 6.0f); - gGL.vertex3f(0.0f, 0.0f, 8.0f); - // Make a Z - gGL.vertex3f(-1.0f, 1.0f, 11.0f); - gGL.vertex3f(1.0f, 1.0f, 11.0f); - gGL.vertex3f(1.0f, 1.0f, 11.0f); - gGL.vertex3f(-1.0f, -1.0f, 11.0f); - gGL.vertex3f(-1.0f, -1.0f, 11.0f); - gGL.vertex3f(1.0f, -1.0f, 11.0f); - gGL.end(); -} - - -void draw_axes() -{ - LLGLSUIDefault gls_ui; - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - // A vertical white line at origin - LLVector3 v = gAgent.getPositionAgent(); - gGL.begin(LLRender::LINES); - gGL.color3f(1.0f, 1.0f, 1.0f); - gGL.vertex3f(0.0f, 0.0f, 0.0f); - gGL.vertex3f(0.0f, 0.0f, 40.0f); - gGL.end(); - // Some coordinate axes - glPushMatrix(); - glTranslatef( v.mV[VX], v.mV[VY], v.mV[VZ] ); - renderCoordinateAxes(); - glPopMatrix(); -} - -void render_ui_3d() -{ - LLGLSPipeline gls_pipeline; - - ////////////////////////////////////// - // - // Render 3D UI elements - // NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD, - // so 3d elements requiring Z buffer are moved to LLDrawPoolHUD - // - - ///////////////////////////////////////////////////////////// - // - // Render 2.5D elements (2D elements in the world) - // Stuff without z writes - // - - // Debugging stuff goes before the UI. - - // Coordinate axes - if (gSavedSettings.getBOOL("ShowAxes")) - { - draw_axes(); - } - - stop_glerror(); - - gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements - stop_glerror(); -} - -void render_ui_2d() -{ - LLGLSUIDefault gls_ui; - - ///////////////////////////////////////////////////////////// - // - // Render 2D UI elements that overlay the world (no z compare) - - // Disable wireframe mode below here, as this is HUD/menus - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - - // Menu overlays, HUD, etc - gViewerWindow->setup2DRender(); - - 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 - LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidthScaled() * (F32)pos_x / zoom_factor); - LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeightScaled() * (F32)pos_y / zoom_factor); - } - - stop_glerror(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - - // render outline for HUD - if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f) - { - glPushMatrix(); - S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2); - S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2); - glScalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f); - glTranslatef((F32)half_width, (F32)half_height, 0.f); - F32 zoom = gAgentCamera.mHUDCurZoom; - glScalef(zoom,zoom,1.f); - gGL.color4fv(LLColor4::white.mV); - gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE); - glPopMatrix(); - stop_glerror(); - } - - - if (gSavedSettings.getBOOL("RenderUIBuffer")) - { - if (LLUI::sDirty) - { - LLUI::sDirty = FALSE; - LLRect t_rect; - - gPipeline.mUIScreen.bindTarget(); - gGL.setColorMask(true, true); - { - static const S32 pad = 8; - - LLUI::sDirtyRect.mLeft -= pad; - LLUI::sDirtyRect.mRight += pad; - LLUI::sDirtyRect.mBottom -= pad; - LLUI::sDirtyRect.mTop += pad; - - LLGLEnable scissor(GL_SCISSOR_TEST); - static LLRect last_rect = LLUI::sDirtyRect; - - //union with last rect to avoid mouse poop - last_rect.unionWith(LLUI::sDirtyRect); - - t_rect = LLUI::sDirtyRect; - LLUI::sDirtyRect = last_rect; - last_rect = t_rect; - - last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]); - last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]); - last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]); - last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]); - - LLRect clip_rect(last_rect); - - glClear(GL_COLOR_BUFFER_BIT); - - gViewerWindow->draw(); - } - - gPipeline.mUIScreen.flush(); - gGL.setColorMask(true, false); - - LLUI::sDirtyRect = t_rect; - - } - - LLGLDisable cull(GL_CULL_FACE); - LLGLDisable blend(GL_BLEND); - S32 width = gViewerWindow->getWindowWidthScaled(); - S32 height = gViewerWindow->getWindowHeightScaled(); - gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen); - gGL.begin(LLRender::TRIANGLE_STRIP); - gGL.color4f(1,1,1,1); - gGL.texCoord2f(0, 0); gGL.vertex2i(0, 0); - gGL.texCoord2f(width, 0); gGL.vertex2i(width, 0); - gGL.texCoord2f(0, height); gGL.vertex2i(0, height); - gGL.texCoord2f(width, height); gGL.vertex2i(width, height); - gGL.end(); - } - else - { - gViewerWindow->draw(); - } - - - - // reset current origin for font rendering, in case of tiling render - LLFontGL::sCurOrigin.set(0, 0); -} - -void render_disconnected_background() -{ - gGL.color4f(1,1,1,1); - if (!gDisconnectedImagep && gDisconnected) - { - llinfos << "Loading last bitmap..." << llendl; - - std::string temp_str; - temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_LAST_FILENAME; - - LLPointer<LLImageBMP> image_bmp = new LLImageBMP; - if( !image_bmp->load(temp_str) ) - { - //llinfos << "Bitmap load failed" << llendl; - return; - } - - LLPointer<LLImageRaw> raw = new LLImageRaw; - if (!image_bmp->decode(raw, 0.0f)) - { - llinfos << "Bitmap decode failed" << llendl; - gDisconnectedImagep = NULL; - return; - } - - U8 *rawp = raw->getData(); - S32 npixels = (S32)image_bmp->getWidth()*(S32)image_bmp->getHeight(); - for (S32 i = 0; i < npixels; i++) - { - S32 sum = 0; - sum = *rawp + *(rawp+1) + *(rawp+2); - sum /= 3; - *rawp = ((S32)sum*6 + *rawp)/7; - rawp++; - *rawp = ((S32)sum*6 + *rawp)/7; - rawp++; - *rawp = ((S32)sum*6 + *rawp)/7; - rawp++; - } - - - raw->expandToPowerOfTwo(); - gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE ); - gStartTexture = gDisconnectedImagep; - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - - // Make sure the progress view always fills the entire window. - S32 width = gViewerWindow->getWindowWidthScaled(); - S32 height = gViewerWindow->getWindowHeightScaled(); - - if (gDisconnectedImagep) - { - LLGLSUIDefault gls_ui; - gViewerWindow->setup2DRender(); - glPushMatrix(); - { - // scale ui to reflect UIScaleFactor - // this can't be done in setup2DRender because it requires a - // pushMatrix/popMatrix pair - const LLVector2& display_scale = gViewerWindow->getDisplayScale(); - glScalef(display_scale.mV[VX], display_scale.mV[VY], 1.f); - - gGL.getTexUnit(0)->bind(gDisconnectedImagep); - gGL.color4f(1.f, 1.f, 1.f, 1.f); - gl_rect_2d_simple_tex(width, height); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } - glPopMatrix(); - } - gGL.flush(); -} - -void display_cleanup() -{ - gDisconnectedImagep = NULL; -} +/**
+ * @file llviewerdisplay.cpp
+ * @brief LLViewerDisplay class implementation
+ *
+ * $LicenseInfo:firstyear=2004&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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewerdisplay.h"
+
+#include "llgl.h"
+#include "llrender.h"
+#include "llglheaders.h"
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llviewercontrol.h"
+#include "llcoord.h"
+#include "llcriticaldamp.h"
+#include "lldir.h"
+#include "lldynamictexture.h"
+#include "lldrawpoolalpha.h"
+#include "llfeaturemanager.h"
+//#include "llfirstuse.h"
+#include "llhudmanager.h"
+#include "llimagebmp.h"
+#include "llmemory.h"
+#include "llselectmgr.h"
+#include "llsky.h"
+#include "llstartup.h"
+#include "lltoolfocus.h"
+#include "lltoolmgr.h"
+#include "lltooldraganddrop.h"
+#include "lltoolpie.h"
+#include "lltracker.h"
+#include "lltrans.h"
+#include "llui.h"
+#include "llviewercamera.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerwindow.h"
+#include "llvoavatarself.h"
+#include "llvograss.h"
+#include "llworld.h"
+#include "pipeline.h"
+#include "llspatialpartition.h"
+#include "llappviewer.h"
+#include "llstartup.h"
+#include "llviewershadermgr.h"
+#include "llfasttimer.h"
+#include "llfloatertools.h"
+#include "llviewertexturelist.h"
+#include "llfocusmgr.h"
+#include "llcubemap.h"
+#include "llviewerregion.h"
+#include "lldrawpoolwater.h"
+#include "lldrawpoolbump.h"
+#include "llwlparammanager.h"
+#include "llwaterparammanager.h"
+#include "llpostprocess.h"
+
+extern LLPointer<LLViewerTexture> gStartTexture;
+
+LLPointer<LLViewerTexture> gDisconnectedImagep = NULL;
+
+// used to toggle renderer back on after teleport
+const F32 TELEPORT_RENDER_DELAY = 20.f; // Max time a teleport is allowed to take before we raise the curtain
+const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
+const F32 TELEPORT_LOCAL_DELAY = 1.0f; // Delay to prevent teleports after starting an in-sim teleport.
+BOOL gTeleportDisplay = FALSE;
+LLFrameTimer gTeleportDisplayTimer;
+LLFrameTimer gTeleportArrivalTimer;
+const F32 RESTORE_GL_TIME = 5.f; // Wait this long while reloading textures before we raise the curtain
+
+BOOL gForceRenderLandFence = FALSE;
+BOOL gDisplaySwapBuffers = FALSE;
+BOOL gDepthDirty = FALSE;
+BOOL gResizeScreenTexture = FALSE;
+BOOL gSnapshot = FALSE;
+
+U32 gRecentFrameCount = 0; // number of 'recent' frames
+LLFrameTimer gRecentFPSTime;
+LLFrameTimer gRecentMemoryTime;
+
+// Rendering stuff
+void pre_show_depth_buffer();
+void post_show_depth_buffer();
+void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
+void render_hud_attachments();
+void render_ui_3d();
+void render_ui_2d();
+void render_disconnected_background();
+
+void display_startup()
+{
+ if ( !gViewerWindow->getActive()
+ || !gViewerWindow->mWindow->getVisible()
+ || gViewerWindow->mWindow->getMinimized()
+ || gNoRender )
+ {
+ return;
+ }
+
+ gPipeline.updateGL();
+
+ // Update images?
+ //gImageList.updateImages(0.01f);
+
+ LLGLSDefault gls_default;
+
+ // Required for HTML update in login screen
+ static S32 frame_count = 0;
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+ if (frame_count++ > 1) // make sure we have rendered a frame first
+ {
+ LLViewerDynamicTexture::updateAllInstances();
+ }
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ LLGLSUIDefault gls_ui;
+ gPipeline.disableLights();
+
+ gViewerWindow->setup2DRender();
+ gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+ gGL.color4f(1,1,1,1);
+ gViewerWindow->draw();
+ gGL.flush();
+
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+ gViewerWindow->mWindow->swapBuffers();
+ glClear(GL_DEPTH_BUFFER_BIT);
+}
+
+void display_update_camera()
+{
+ LLMemType mt_uc(LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA);
+ // TODO: cut draw distance down if customizing avatar?
+ // TODO: cut draw distance on per-parcel basis?
+
+ // Cut draw distance in half when customizing avatar,
+ // but on the viewer only.
+ F32 final_far = gAgentCamera.mDrawDistance;
+ if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
+ {
+ final_far *= 0.5f;
+ }
+ LLViewerCamera::getInstance()->setFar(final_far);
+ gViewerWindow->setup3DRender();
+
+ // update all the sky/atmospheric/water settings
+ LLWLParamManager::instance()->update(LLViewerCamera::getInstance());
+ LLWaterParamManager::instance()->update(LLViewerCamera::getInstance());
+
+ // Update land visibility too
+ LLWorld::getInstance()->setLandFarClip(final_far);
+}
+
+// Write some stats to llinfos
+void display_stats()
+{
+ F32 fps_log_freq = gSavedSettings.getF32("FPSLogFrequency");
+ if (fps_log_freq > 0.f && gRecentFPSTime.getElapsedTimeF32() >= fps_log_freq)
+ {
+ F32 fps = gRecentFrameCount / fps_log_freq;
+ llinfos << llformat("FPS: %.02f", fps) << llendl;
+ gRecentFrameCount = 0;
+ gRecentFPSTime.reset();
+ }
+ F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
+ if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
+ {
+ gMemoryAllocated = LLMemory::getCurrentRSS();
+ U32 memory = (U32)(gMemoryAllocated / (1024*1024));
+ llinfos << llformat("MEMORY: %d MB", memory) << llendl;
+ gRecentMemoryTime.reset();
+ }
+}
+
+static LLFastTimer::DeclareTimer FTM_PICK("Picking");
+static LLFastTimer::DeclareTimer FTM_RENDER("Render", true);
+static LLFastTimer::DeclareTimer FTM_UPDATE_SKY("Update Sky");
+static LLFastTimer::DeclareTimer FTM_UPDATE_TEXTURES("Update Textures");
+static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE("Update Images");
+
+// Paint the display!
+void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
+{
+ LLMemType mt_render(LLMemType::MTYPE_RENDER);
+ LLFastTimer t(FTM_RENDER);
+
+ if (gResizeScreenTexture)
+ { //skip render on frames where screen texture is resizing
+ gGL.flush();
+ if (!for_snapshot)
+ {
+ glClear(GL_COLOR_BUFFER_BIT);
+ gViewerWindow->mWindow->swapBuffers();
+ }
+
+ gResizeScreenTexture = FALSE;
+ gPipeline.resizeScreenTexture();
+
+ if (!for_snapshot)
+ {
+ return;
+ }
+ }
+
+ if (LLPipeline::sRenderDeferred)
+ { //hack to make sky show up in deferred snapshots
+ for_snapshot = FALSE;
+ }
+
+ if (LLPipeline::sRenderFrameTest)
+ {
+ send_agent_pause();
+ }
+
+ gSnapshot = for_snapshot;
+
+ LLGLSDefault gls_default;
+ LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE, GL_LEQUAL);
+
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+ stop_glerror();
+
+ gPipeline.disableLights();
+
+ stop_glerror();
+
+ // Don't draw if the window is hidden or minimized.
+ // In fact, must explicitly check the minimized state before drawing.
+ // Attempting to draw into a minimized window causes a GL error. JC
+ if ( !gViewerWindow->getActive()
+ || !gViewerWindow->mWindow->getVisible()
+ || gViewerWindow->mWindow->getMinimized() )
+ {
+ // Clean up memory the pools may have allocated
+ if (rebuild)
+ {
+ stop_glerror();
+ gPipeline.rebuildPools();
+ stop_glerror();
+ }
+
+ stop_glerror();
+ gViewerWindow->returnEmptyPicks();
+ stop_glerror();
+ return;
+ }
+
+ gViewerWindow->checkSettings();
+
+ {
+ LLFastTimer ftm(FTM_PICK);
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Pick");
+ gViewerWindow->performPick();
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:CheckStates");
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+
+ //////////////////////////////////////////////////////////
+ //
+ // Logic for forcing window updates if we're in drone mode.
+ //
+
+ if (gNoRender)
+ {
+#if LL_WINDOWS
+ static F32 last_update_time = 0.f;
+ if ((gFrameTimeSeconds - last_update_time) > 1.f)
+ {
+ InvalidateRect((HWND)gViewerWindow->getPlatformWindow(), NULL, FALSE);
+ last_update_time = gFrameTimeSeconds;
+ }
+#elif LL_DARWIN
+ // MBW -- Do something clever here.
+#endif
+ // Not actually rendering, don't bother.
+ return;
+ }
+
+
+ //
+ // Bail out if we're in the startup state and don't want to try to
+ // render the world.
+ //
+ if (LLStartUp::getStartupState() < STATE_STARTED)
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Startup");
+ display_startup();
+ return;
+ }
+
+ //LLGLState::verify(FALSE);
+
+ /////////////////////////////////////////////////
+ //
+ // Update GL Texture statistics (used for discard logic?)
+ //
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:TextureStats");
+ stop_glerror();
+
+ LLImageGL::updateStats(gFrameTimeSeconds);
+
+ LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode");
+ LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode"));
+
+ gPipeline.mBackfaceCull = TRUE;
+ gFrameCount++;
+ gRecentFrameCount++;
+ if (gFocusMgr.getAppHasFocus())
+ {
+ gForegroundFrameCount++;
+ }
+
+ //////////////////////////////////////////////////////////
+ //
+ // Display start screen if we're teleporting, and skip render
+ //
+
+ if (gTeleportDisplay)
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport");
+ const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived.
+
+ S32 attach_count = 0;
+ if (isAgentAvatarValid())
+ {
+ attach_count = gAgentAvatarp->getAttachmentCount();
+ }
+ F32 teleport_save_time = TELEPORT_EXPIRY + TELEPORT_EXPIRY_PER_ATTACHMENT * attach_count;
+ F32 teleport_elapsed = gTeleportDisplayTimer.getElapsedTimeF32();
+ F32 teleport_percent = teleport_elapsed * (100.f / teleport_save_time);
+ if( (gAgent.getTeleportState() != LLAgent::TELEPORT_START) && (teleport_percent > 100.f) )
+ {
+ // Give up. Don't keep the UI locked forever.
+ gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+ gAgent.setTeleportMessage(std::string());
+ }
+
+ const std::string& message = gAgent.getTeleportMessage();
+ switch( gAgent.getTeleportState() )
+ {
+ case LLAgent::TELEPORT_START:
+ // Transition to REQUESTED. Viewer has sent some kind
+ // of TeleportRequest to the source simulator
+ gTeleportDisplayTimer.reset();
+ gViewerWindow->setShowProgress(TRUE);
+ gViewerWindow->setProgressPercent(0);
+ gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED );
+ gAgent.setTeleportMessage(
+ LLAgent::sTeleportProgressMessages["requesting"]);
+ break;
+
+ case LLAgent::TELEPORT_REQUESTED:
+ // Waiting for source simulator to respond
+ gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) );
+ gViewerWindow->setProgressString(message);
+ break;
+
+ case LLAgent::TELEPORT_MOVING:
+ // Viewer has received destination location from source simulator
+ gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) );
+ gViewerWindow->setProgressString(message);
+ break;
+
+ case LLAgent::TELEPORT_START_ARRIVAL:
+ // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator
+ gTeleportArrivalTimer.reset();
+ gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
+ gViewerWindow->setProgressPercent(75.f);
+ gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING );
+ gAgent.setTeleportMessage(
+ LLAgent::sTeleportProgressMessages["arriving"]);
+ gTextureList.mForceResetTextureStats = TRUE;
+ gAgentCamera.resetView(TRUE, TRUE);
+ break;
+
+ case LLAgent::TELEPORT_ARRIVING:
+ // Make the user wait while content "pre-caches"
+ {
+ F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY);
+ if( arrival_fraction > 1.f )
+ {
+ arrival_fraction = 1.f;
+ //LLFirstUse::useTeleport();
+ gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+ }
+ gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel"));
+ gViewerWindow->setProgressPercent( arrival_fraction * 25.f + 75.f);
+ gViewerWindow->setProgressString(message);
+ }
+ break;
+
+ case LLAgent::TELEPORT_LOCAL:
+ // Short delay when teleporting in the same sim (progress screen active but not shown - did not
+ // fall-through from TELEPORT_START)
+ {
+ if( gTeleportDisplayTimer.getElapsedTimeF32() > TELEPORT_LOCAL_DELAY )
+ {
+ //LLFirstUse::useTeleport();
+ gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+ }
+ }
+ break;
+
+ case LLAgent::TELEPORT_NONE:
+ // No teleport in progress
+ gViewerWindow->setShowProgress(FALSE);
+ gTeleportDisplay = FALSE;
+ break;
+ }
+ }
+ else if(LLAppViewer::instance()->logoutRequestSent())
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Logout");
+ F32 percent_done = gLogoutTimer.getElapsedTimeF32() * 100.f / gLogoutMaxTime;
+ if (percent_done > 100.f)
+ {
+ percent_done = 100.f;
+ }
+
+ if( LLApp::isExiting() )
+ {
+ percent_done = 100.f;
+ }
+
+ gViewerWindow->setProgressPercent( percent_done );
+ }
+ else
+ if (gRestoreGL)
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RestoreGL");
+ F32 percent_done = gRestoreGLTimer.getElapsedTimeF32() * 100.f / RESTORE_GL_TIME;
+ if( percent_done > 100.f )
+ {
+ gViewerWindow->setShowProgress(FALSE);
+ gRestoreGL = FALSE;
+ }
+ else
+ {
+
+ if( LLApp::isExiting() )
+ {
+ percent_done = 100.f;
+ }
+
+ gViewerWindow->setProgressPercent( percent_done );
+ }
+ }
+
+ //////////////////////////
+ //
+ // Prepare for the next frame
+ //
+
+ /////////////////////////////
+ //
+ // Update the camera
+ //
+ //
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Camera");
+ LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield);
+ LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE);
+
+ //////////////////////////
+ //
+ // clear the next buffer
+ // (must follow dynamic texture writing since that uses the frame buffer)
+ //
+
+ if (gDisconnected)
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected");
+ render_ui();
+ }
+
+ //////////////////////////
+ //
+ // Set rendering options
+ //
+ //
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderSetup");
+ stop_glerror();
+
+ ///////////////////////////////////////
+ //
+ // Slam lighting parameters back to our defaults.
+ // Note that these are not the same as GL defaults...
+
+ stop_glerror();
+ F32 one[4] = {1.f, 1.f, 1.f, 1.f};
+ glLightModelfv (GL_LIGHT_MODEL_AMBIENT,one);
+ stop_glerror();
+
+ /////////////////////////////////////
+ //
+ // Render
+ //
+ // Actually push all of our triangles to the screen.
+ //
+
+ // do render-to-texture stuff here
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES))
+ {
+ LLAppViewer::instance()->pingMainloopTimeout("Display:DynamicTextures");
+ LLFastTimer t(FTM_UPDATE_TEXTURES);
+ if (LLViewerDynamicTexture::updateAllInstances())
+ {
+ gGL.setColorMask(true, true);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+ }
+
+ gViewerWindow->setup3DViewport();
+
+ gPipeline.resetFrameStats(); // Reset per-frame statistics.
+
+ if (!gDisconnected)
+ {
+ LLMemType mt_du(LLMemType::MTYPE_DISPLAY_UPDATE);
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Update");
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ { //don't draw hud objects in this frame
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
+
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES))
+ { //don't draw hud particles in this frame
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+ }
+
+ //upkeep gl name pools
+ LLGLNamePool::upkeepPools();
+
+ stop_glerror();
+ display_update_camera();
+ stop_glerror();
+
+ // *TODO: merge these two methods
+ {
+ LLMemType mt_uh(LLMemType::MTYPE_DISPLAY_UPDATE_HUD);
+ LLHUDManager::getInstance()->updateEffects();
+ LLHUDObject::updateAll();
+ stop_glerror();
+ }
+
+ {
+ LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM);
+ const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time
+ gPipeline.createObjects(max_geom_update_time);
+ gPipeline.updateGeom(max_geom_update_time);
+ stop_glerror();
+ }
+
+ gPipeline.updateGL();
+ stop_glerror();
+
+ S32 water_clip = 0;
+ if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
+ (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) ||
+ gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER)))
+ {
+ if (LLViewerCamera::getInstance()->cameraUnderWater())
+ {
+ water_clip = -1;
+ }
+ else
+ {
+ water_clip = 1;
+ }
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Cull");
+
+ //Increment drawable frame counter
+ LLDrawable::incrementVisible();
+
+ LLSpatialGroup::sNoDelete = TRUE;
+ LLPipeline::sUseOcclusion =
+ (!gUseWireframe
+ && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion")
+ && gSavedSettings.getBOOL("UseOcclusion")
+ && gGLManager.mHasOcclusionQuery) ? 2 : 0;
+
+ if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred)
+ { //force occlusion on for all render types if doing deferred render
+ LLPipeline::sUseOcclusion = 3;
+ }
+
+ LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
+ LLPipeline::sAutoMaskAlphaNonDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaNonDeferred");
+ LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip");
+ LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible");
+ LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate");
+
+ S32 occlusion = LLPipeline::sUseOcclusion;
+ if (gDepthDirty)
+ { //depth buffer is invalid, don't overwrite occlusion state
+ LLPipeline::sUseOcclusion = llmin(occlusion, 1);
+ }
+ gDepthDirty = FALSE;
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ static LLCullResult result;
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ gPipeline.updateCull(*LLViewerCamera::getInstance(), result, water_clip);
+ stop_glerror();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ BOOL to_texture = !for_snapshot &&
+ gPipeline.canUseVertexShaders() &&
+ LLPipeline::sRenderGlow;
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Swap");
+
+ {
+ LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SWAP);
+ {
+ LLFastTimer ftm(FTM_CLIENT_COPY);
+ LLVertexBuffer::clientCopy(0.016);
+ }
+
+ //if (gResizeScreenTexture)
+ //{
+ // gResizeScreenTexture = FALSE;
+ // gPipeline.resizeScreenTexture();
+ //}
+
+ gGL.setColorMask(true, true);
+ glClearColor(0,0,0,0);
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ if (!for_snapshot)
+ {
+ if (gFrameCount > 1)
+ { //for some reason, ATI 4800 series will error out if you
+ //try to generate a shadow before the first frame is through
+ gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
+ }
+
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ glh::matrix4f proj = glh_get_current_projection();
+ glh::matrix4f mod = glh_get_current_modelview();
+ glViewport(0,0,512,512);
+ LLVOAvatar::updateFreezeCounter() ;
+ LLVOAvatar::updateImpostors();
+
+ glh_set_current_projection(proj);
+ glh_set_current_modelview(mod);
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(proj.m);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(mod.m);
+ gViewerWindow->setup3DViewport();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ }
+ glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ }
+
+ if (!for_snapshot)
+ {
+ LLMemType mt_gw(LLMemType::MTYPE_DISPLAY_GEN_REFLECTION);
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery");
+ gPipeline.generateWaterReflection(*LLViewerCamera::getInstance());
+ gPipeline.generateHighlight(*LLViewerCamera::getInstance());
+ }
+
+ //////////////////////////////////////
+ //
+ // Update images, using the image stats generated during object update/culling
+ //
+ // Can put objects onto the retextured list.
+ //
+ // Doing this here gives hardware occlusion queries extra time to complete
+ LLAppViewer::instance()->pingMainloopTimeout("Display:UpdateImages");
+
+ {
+ LLMemType mt_iu(LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE);
+ LLFastTimer t(FTM_IMAGE_UPDATE);
+
+ LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(),
+ LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean());
+
+ gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first.
+
+ F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time
+ max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame)
+ gTextureList.updateImages(max_image_decode_time);
+
+ //remove dead textures from GL
+ LLImageGL::deleteDeadTextures();
+ stop_glerror();
+ }
+ ///////////////////////////////////
+ //
+ // StateSort
+ //
+ // Responsible for taking visible objects, and adding them to the appropriate draw orders.
+ // In the case of alpha objects, z-sorts them first.
+ // Also creates special lists for outlines and selected face rendering.
+ //
+ LLAppViewer::instance()->pingMainloopTimeout("Display:StateSort");
+ {
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ LLMemType mt_ss(LLMemType::MTYPE_DISPLAY_STATE_SORT);
+ gPipeline.sAllowRebuildPriorityGroup = TRUE ;
+ gPipeline.stateSort(*LLViewerCamera::getInstance(), result);
+ stop_glerror();
+
+ if (rebuild)
+ {
+ //////////////////////////////////////
+ //
+ // rebuildPools
+ //
+ //
+ gPipeline.rebuildPools();
+ stop_glerror();
+ }
+ }
+
+ LLPipeline::sUseOcclusion = occlusion;
+
+ {
+ LLMemType mt_ds(LLMemType::MTYPE_DISPLAY_SKY);
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Sky");
+ LLFastTimer t(FTM_UPDATE_SKY);
+ gSky.updateSky();
+ }
+
+ if(gUseWireframe)
+ {
+ glClearColor(0.5f, 0.5f, 0.5f, 0.f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderStart");
+
+ //// render frontmost floater opaque for occlusion culling purposes
+ //LLFloater* frontmost_floaterp = gFloaterView->getFrontmost();
+ //// assumes frontmost floater with focus is opaque
+ //if (frontmost_floaterp && gFocusMgr.childHasKeyboardFocus(frontmost_floaterp))
+ //{
+ // glMatrixMode(GL_MODELVIEW);
+ // glPushMatrix();
+ // {
+ // gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ // glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+ // glLoadIdentity();
+
+ // LLRect floater_rect = frontmost_floaterp->calcScreenRect();
+ // // deflate by one pixel so rounding errors don't occlude outside of floater extents
+ // floater_rect.stretch(-1);
+ // LLRectf floater_3d_rect((F32)floater_rect.mLeft / (F32)gViewerWindow->getWindowWidthScaled(),
+ // (F32)floater_rect.mTop / (F32)gViewerWindow->getWindowHeightScaled(),
+ // (F32)floater_rect.mRight / (F32)gViewerWindow->getWindowWidthScaled(),
+ // (F32)floater_rect.mBottom / (F32)gViewerWindow->getWindowHeightScaled());
+ // floater_3d_rect.translate(-0.5f, -0.5f);
+ // glTranslatef(0.f, 0.f, -LLViewerCamera::getInstance()->getNear());
+ // glScalef(LLViewerCamera::getInstance()->getNear() * LLViewerCamera::getInstance()->getAspect() / sinf(LLViewerCamera::getInstance()->getView()), LLViewerCamera::getInstance()->getNear() / sinf(LLViewerCamera::getInstance()->getView()), 1.f);
+ // gGL.color4fv(LLColor4::white.mV);
+ // gGL.begin(LLVertexBuffer::QUADS);
+ // {
+ // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mBottom, 0.f);
+ // gGL.vertex3f(floater_3d_rect.mLeft, floater_3d_rect.mTop, 0.f);
+ // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mTop, 0.f);
+ // gGL.vertex3f(floater_3d_rect.mRight, floater_3d_rect.mBottom, 0.f);
+ // }
+ // gGL.end();
+ // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ // }
+ // glPopMatrix();
+ //}
+
+ LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
+ LLPipeline::updateRenderDeferred();
+
+ stop_glerror();
+
+ if (to_texture)
+ {
+ gGL.setColorMask(true, true);
+
+ if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+ {
+ gPipeline.mDeferredScreen.bindTarget();
+ glClearColor(0,0,0,0);
+ gPipeline.mDeferredScreen.clear();
+ }
+ else
+ {
+ gPipeline.mScreen.bindTarget();
+ gPipeline.mScreen.clear();
+ }
+
+ gGL.setColorMask(true, false);
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom");
+
+ if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot())
+ && !gRestoreGL)
+ {
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ LLMemType mt_rg(LLMemType::MTYPE_DISPLAY_RENDER_GEOM);
+ gGL.setColorMask(true, false);
+ if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+ {
+ gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance());
+ }
+ else
+ {
+ gPipeline.renderGeom(*LLViewerCamera::getInstance(), TRUE);
+ }
+
+ gGL.setColorMask(true, true);
+
+ //store this frame's modelview matrix for use
+ //when rendering next frame's occlusion queries
+ for (U32 i = 0; i < 16; i++)
+ {
+ gGLLastModelView[i] = gGLModelView[i];
+ gGLLastProjection[i] = gGLProjection[i];
+ }
+ stop_glerror();
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");
+
+ if (to_texture)
+ {
+ LLMemType mt_rf(LLMemType::MTYPE_DISPLAY_RENDER_FLUSH);
+ if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+ {
+ gPipeline.mDeferredScreen.flush();
+ if(LLRenderTarget::sUseFBO)
+ {
+ LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(),
+ gPipeline.mDeferredScreen.getHeight(), 0, 0,
+ gPipeline.mDeferredScreen.getWidth(),
+ gPipeline.mDeferredScreen.getHeight(),
+ GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
+ }
+ else
+ {
+ gPipeline.mScreen.flush();
+ if(LLRenderTarget::sUseFBO)
+ {
+ LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(),
+ gPipeline.mScreen.getHeight(), 0, 0,
+ gPipeline.mScreen.getWidth(),
+ gPipeline.mScreen.getHeight(),
+ GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
+ }
+ }
+
+ if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
+ {
+ gPipeline.renderDeferredLighting();
+ }
+
+ LLPipeline::sUnderWaterRender = FALSE;
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI");
+ if (!for_snapshot)
+ {
+ LLFastTimer t(FTM_RENDER_UI);
+ render_ui();
+ }
+
+
+ LLSpatialGroup::sNoDelete = FALSE;
+ gPipeline.clearReferences();
+
+ gPipeline.rebuildGroups();
+ }
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats");
+
+ stop_glerror();
+
+ if (LLPipeline::sRenderFrameTest)
+ {
+ send_agent_resume();
+ LLPipeline::sRenderFrameTest = FALSE;
+ }
+
+ display_stats();
+
+ LLAppViewer::instance()->pingMainloopTimeout("Display:Done");
+}
+
+void render_hud_attachments()
+{
+ LLMemType mt_ra(LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS);
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+ glh::matrix4f current_proj = glh_get_current_projection();
+ glh::matrix4f current_mod = glh_get_current_modelview();
+
+ // clamp target zoom level to reasonable values
+ gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f);
+ // smoothly interpolate current zoom level
+ gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f));
+
+ if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices())
+ {
+ LLCamera hud_cam = *LLViewerCamera::getInstance();
+ LLVector3 origin = hud_cam.getOrigin();
+ hud_cam.setOrigin(-1.f,0,0);
+ hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1));
+ LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE);
+
+ bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles");
+
+ //only render hud objects
+ gPipeline.pushRenderTypeMask();
+
+ // turn off everything
+ gPipeline.andRenderTypeMask(LLPipeline::END_RENDER_TYPES);
+ // turn on HUD
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ // turn on HUD particles
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+
+ // if particles are off, turn off hud-particles as well
+ if (!render_particles)
+ {
+ // turn back off HUD particles
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD_PARTICLES);
+ }
+
+ bool has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ if (has_ui)
+ {
+ gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+
+ S32 use_occlusion = LLPipeline::sUseOcclusion;
+ LLPipeline::sUseOcclusion = 0;
+ LLPipeline::sDisableShaders = TRUE;
+
+ //cull, sort, and render hud objects
+ static LLCullResult result;
+ LLSpatialGroup::sNoDelete = TRUE;
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+ gPipeline.updateCull(hud_cam, result);
+
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_ALPHA);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_FULLBRIGHT);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_SHINY);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISIBLE);
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY);
+
+ gPipeline.stateSort(hud_cam, result);
+
+ gPipeline.renderGeom(hud_cam);
+
+ LLSpatialGroup::sNoDelete = FALSE;
+ gPipeline.clearReferences();
+
+ render_hud_elements();
+
+ //restore type mask
+ gPipeline.popRenderTypeMask();
+
+ if (has_ui)
+ {
+ gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+ LLPipeline::sUseOcclusion = use_occlusion;
+ LLPipeline::sDisableShaders = FALSE;
+ }
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ glh_set_current_projection(current_proj);
+ glh_set_current_modelview(current_mod);
+}
+
+LLRect get_whole_screen_region()
+{
+ LLRect whole_screen = gViewerWindow->getWorldViewRectScaled();
+
+ // 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)
+ {
+ S32 num_horizontal_tiles = llceil(zoom_factor);
+ S32 tile_width = llround((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor);
+ S32 tile_height = llround((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor);
+ int tile_y = sub_region / num_horizontal_tiles;
+ int tile_x = sub_region - (tile_y * num_horizontal_tiles);
+ glh::matrix4f mat;
+
+ whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height);
+ }
+ return whole_screen;
+}
+
+bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model)
+{
+ if (isAgentAvatarValid() && gAgentAvatarp->hasHUDAttachment())
+ {
+ F32 zoom_level = gAgentCamera.mHUDCurZoom;
+ LLBBox hud_bbox = gAgentAvatarp->getHUDBBox();
+
+ F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
+ proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
+ proj.element(2,2) = -0.01f;
+
+ F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect();
+
+ glh::matrix4f mat;
+ F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth();
+ F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight();
+ mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f));
+ mat.set_translate(
+ glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio),
+ clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y),
+ 0.f));
+ proj *= mat;
+
+ glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION);
+
+ mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level));
+ mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f));
+
+ tmp_model *= mat;
+ model = tmp_model;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model)
+{
+ LLRect whole_screen = get_whole_screen_region();
+ return get_hud_matrices(whole_screen, proj, model);
+}
+
+BOOL setup_hud_matrices()
+{
+ LLRect whole_screen = get_whole_screen_region();
+ return setup_hud_matrices(whole_screen);
+}
+
+BOOL setup_hud_matrices(const LLRect& screen_region)
+{
+ glh::matrix4f proj, model;
+ bool result = get_hud_matrices(screen_region, proj, model);
+ if (!result) return result;
+
+ // set up transform to keep HUD objects in front of camera
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(proj.m);
+ glh_set_current_projection(proj);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(model.m);
+ glh_set_current_modelview(model);
+ return TRUE;
+}
+
+static LLFastTimer::DeclareTimer FTM_SWAP("Swap");
+
+void render_ui(F32 zoom_factor, int subfield)
+{
+ LLMemType mt_ru(LLMemType::MTYPE_DISPLAY_RENDER_UI);
+ LLGLState::checkStates();
+
+ glPushMatrix();
+ glLoadMatrixd(gGLLastModelView);
+ glh::matrix4f saved_view = glh_get_current_modelview();
+ glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
+
+ {
+ BOOL to_texture = gPipeline.canUseVertexShaders() &&
+ LLPipeline::sRenderGlow;
+
+ if (to_texture)
+ {
+ gPipeline.renderBloom(gSnapshot, zoom_factor, subfield);
+ }
+
+ render_hud_elements();
+ render_hud_attachments();
+ }
+
+ LLGLSDefault gls_default;
+ LLGLSUIDefault gls_ui;
+ {
+ gPipeline.disableLights();
+ }
+
+ {
+ gGL.color4f(1,1,1,1);
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ LLFastTimer t(FTM_RENDER_UI);
+
+ if (!gDisconnected)
+ {
+ render_ui_3d();
+ LLGLState::checkStates();
+ }
+ else
+ {
+ render_disconnected_background();
+ }
+
+ render_ui_2d();
+ LLGLState::checkStates();
+ }
+ gGL.flush();
+
+ {
+ gViewerWindow->setup2DRender();
+ gViewerWindow->updateDebugText();
+ gViewerWindow->drawDebugText();
+ }
+
+ LLVertexBuffer::unbind();
+ }
+
+ glh_set_current_modelview(saved_view);
+ glPopMatrix();
+
+ if (gDisplaySwapBuffers)
+ {
+ LLFastTimer t(FTM_SWAP);
+ gViewerWindow->mWindow->swapBuffers();
+ }
+ gDisplaySwapBuffers = TRUE;
+}
+
+void renderCoordinateAxes()
+{
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.begin(LLRender::LINES);
+ gGL.color3f(1.0f, 0.0f, 0.0f); // i direction = X-Axis = red
+ gGL.vertex3f(0.0f, 0.0f, 0.0f);
+ gGL.vertex3f(2.0f, 0.0f, 0.0f);
+ gGL.vertex3f(3.0f, 0.0f, 0.0f);
+ gGL.vertex3f(5.0f, 0.0f, 0.0f);
+ gGL.vertex3f(6.0f, 0.0f, 0.0f);
+ gGL.vertex3f(8.0f, 0.0f, 0.0f);
+ // Make an X
+ gGL.vertex3f(11.0f, 1.0f, 1.0f);
+ gGL.vertex3f(11.0f, -1.0f, -1.0f);
+ gGL.vertex3f(11.0f, 1.0f, -1.0f);
+ gGL.vertex3f(11.0f, -1.0f, 1.0f);
+
+ gGL.color3f(0.0f, 1.0f, 0.0f); // j direction = Y-Axis = green
+ gGL.vertex3f(0.0f, 0.0f, 0.0f);
+ gGL.vertex3f(0.0f, 2.0f, 0.0f);
+ gGL.vertex3f(0.0f, 3.0f, 0.0f);
+ gGL.vertex3f(0.0f, 5.0f, 0.0f);
+ gGL.vertex3f(0.0f, 6.0f, 0.0f);
+ gGL.vertex3f(0.0f, 8.0f, 0.0f);
+ // Make a Y
+ gGL.vertex3f(1.0f, 11.0f, 1.0f);
+ gGL.vertex3f(0.0f, 11.0f, 0.0f);
+ gGL.vertex3f(-1.0f, 11.0f, 1.0f);
+ gGL.vertex3f(0.0f, 11.0f, 0.0f);
+ gGL.vertex3f(0.0f, 11.0f, 0.0f);
+ gGL.vertex3f(0.0f, 11.0f, -1.0f);
+
+ gGL.color3f(0.0f, 0.0f, 1.0f); // Z-Axis = blue
+ gGL.vertex3f(0.0f, 0.0f, 0.0f);
+ gGL.vertex3f(0.0f, 0.0f, 2.0f);
+ gGL.vertex3f(0.0f, 0.0f, 3.0f);
+ gGL.vertex3f(0.0f, 0.0f, 5.0f);
+ gGL.vertex3f(0.0f, 0.0f, 6.0f);
+ gGL.vertex3f(0.0f, 0.0f, 8.0f);
+ // Make a Z
+ gGL.vertex3f(-1.0f, 1.0f, 11.0f);
+ gGL.vertex3f(1.0f, 1.0f, 11.0f);
+ gGL.vertex3f(1.0f, 1.0f, 11.0f);
+ gGL.vertex3f(-1.0f, -1.0f, 11.0f);
+ gGL.vertex3f(-1.0f, -1.0f, 11.0f);
+ gGL.vertex3f(1.0f, -1.0f, 11.0f);
+ gGL.end();
+}
+
+
+void draw_axes()
+{
+ LLGLSUIDefault gls_ui;
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ // A vertical white line at origin
+ LLVector3 v = gAgent.getPositionAgent();
+ gGL.begin(LLRender::LINES);
+ gGL.color3f(1.0f, 1.0f, 1.0f);
+ gGL.vertex3f(0.0f, 0.0f, 0.0f);
+ gGL.vertex3f(0.0f, 0.0f, 40.0f);
+ gGL.end();
+ // Some coordinate axes
+ glPushMatrix();
+ glTranslatef( v.mV[VX], v.mV[VY], v.mV[VZ] );
+ renderCoordinateAxes();
+ glPopMatrix();
+}
+
+void render_ui_3d()
+{
+ LLGLSPipeline gls_pipeline;
+
+ //////////////////////////////////////
+ //
+ // Render 3D UI elements
+ // NOTE: zbuffer is cleared before we get here by LLDrawPoolHUD,
+ // so 3d elements requiring Z buffer are moved to LLDrawPoolHUD
+ //
+
+ /////////////////////////////////////////////////////////////
+ //
+ // Render 2.5D elements (2D elements in the world)
+ // Stuff without z writes
+ //
+
+ // Debugging stuff goes before the UI.
+
+ // Coordinate axes
+ if (gSavedSettings.getBOOL("ShowAxes"))
+ {
+ draw_axes();
+ }
+
+ stop_glerror();
+
+ gViewerWindow->renderSelections(FALSE, FALSE, TRUE); // Non HUD call in render_hud_elements
+ stop_glerror();
+}
+
+void render_ui_2d()
+{
+ LLGLSUIDefault gls_ui;
+
+ /////////////////////////////////////////////////////////////
+ //
+ // Render 2D UI elements that overlay the world (no z compare)
+
+ // Disable wireframe mode below here, as this is HUD/menus
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+ // Menu overlays, HUD, etc
+ gViewerWindow->setup2DRender();
+
+ 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
+ LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidthScaled() * (F32)pos_x / zoom_factor);
+ LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeightScaled() * (F32)pos_y / zoom_factor);
+ }
+
+ stop_glerror();
+ gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+ // render outline for HUD
+ if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f)
+ {
+ glPushMatrix();
+ S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2);
+ S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2);
+ glScalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f);
+ glTranslatef((F32)half_width, (F32)half_height, 0.f);
+ F32 zoom = gAgentCamera.mHUDCurZoom;
+ glScalef(zoom,zoom,1.f);
+ gGL.color4fv(LLColor4::white.mV);
+ gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE);
+ glPopMatrix();
+ stop_glerror();
+ }
+
+
+ if (gSavedSettings.getBOOL("RenderUIBuffer"))
+ {
+ if (LLUI::sDirty)
+ {
+ LLUI::sDirty = FALSE;
+ LLRect t_rect;
+
+ gPipeline.mUIScreen.bindTarget();
+ gGL.setColorMask(true, true);
+ {
+ static const S32 pad = 8;
+
+ LLUI::sDirtyRect.mLeft -= pad;
+ LLUI::sDirtyRect.mRight += pad;
+ LLUI::sDirtyRect.mBottom -= pad;
+ LLUI::sDirtyRect.mTop += pad;
+
+ LLGLEnable scissor(GL_SCISSOR_TEST);
+ static LLRect last_rect = LLUI::sDirtyRect;
+
+ //union with last rect to avoid mouse poop
+ last_rect.unionWith(LLUI::sDirtyRect);
+
+ t_rect = LLUI::sDirtyRect;
+ LLUI::sDirtyRect = last_rect;
+ last_rect = t_rect;
+
+ last_rect.mLeft = LLRect::tCoordType(last_rect.mLeft / LLUI::sGLScaleFactor.mV[0]);
+ last_rect.mRight = LLRect::tCoordType(last_rect.mRight / LLUI::sGLScaleFactor.mV[0]);
+ last_rect.mTop = LLRect::tCoordType(last_rect.mTop / LLUI::sGLScaleFactor.mV[1]);
+ last_rect.mBottom = LLRect::tCoordType(last_rect.mBottom / LLUI::sGLScaleFactor.mV[1]);
+
+ LLRect clip_rect(last_rect);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ gViewerWindow->draw();
+ }
+
+ gPipeline.mUIScreen.flush();
+ gGL.setColorMask(true, false);
+
+ LLUI::sDirtyRect = t_rect;
+
+ }
+
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+ S32 width = gViewerWindow->getWindowWidthScaled();
+ S32 height = gViewerWindow->getWindowHeightScaled();
+ gGL.getTexUnit(0)->bind(&gPipeline.mUIScreen);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.color4f(1,1,1,1);
+ gGL.texCoord2f(0, 0); gGL.vertex2i(0, 0);
+ gGL.texCoord2f(width, 0); gGL.vertex2i(width, 0);
+ gGL.texCoord2f(0, height); gGL.vertex2i(0, height);
+ gGL.texCoord2f(width, height); gGL.vertex2i(width, height);
+ gGL.end();
+ }
+ else
+ {
+ gViewerWindow->draw();
+ }
+
+
+
+ // reset current origin for font rendering, in case of tiling render
+ LLFontGL::sCurOrigin.set(0, 0);
+}
+
+void render_disconnected_background()
+{
+ gGL.color4f(1,1,1,1);
+ if (!gDisconnectedImagep && gDisconnected)
+ {
+ llinfos << "Loading last bitmap..." << llendl;
+
+ std::string temp_str;
+ temp_str = gDirUtilp->getLindenUserDir() + gDirUtilp->getDirDelimiter() + SCREEN_LAST_FILENAME;
+
+ LLPointer<LLImageBMP> image_bmp = new LLImageBMP;
+ if( !image_bmp->load(temp_str) )
+ {
+ //llinfos << "Bitmap load failed" << llendl;
+ return;
+ }
+
+ LLPointer<LLImageRaw> raw = new LLImageRaw;
+ if (!image_bmp->decode(raw, 0.0f))
+ {
+ llinfos << "Bitmap decode failed" << llendl;
+ gDisconnectedImagep = NULL;
+ return;
+ }
+
+ U8 *rawp = raw->getData();
+ S32 npixels = (S32)image_bmp->getWidth()*(S32)image_bmp->getHeight();
+ for (S32 i = 0; i < npixels; i++)
+ {
+ S32 sum = 0;
+ sum = *rawp + *(rawp+1) + *(rawp+2);
+ sum /= 3;
+ *rawp = ((S32)sum*6 + *rawp)/7;
+ rawp++;
+ *rawp = ((S32)sum*6 + *rawp)/7;
+ rawp++;
+ *rawp = ((S32)sum*6 + *rawp)/7;
+ rawp++;
+ }
+
+
+ raw->expandToPowerOfTwo();
+ gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE );
+ gStartTexture = gDisconnectedImagep;
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
+
+ // Make sure the progress view always fills the entire window.
+ S32 width = gViewerWindow->getWindowWidthScaled();
+ S32 height = gViewerWindow->getWindowHeightScaled();
+
+ if (gDisconnectedImagep)
+ {
+ LLGLSUIDefault gls_ui;
+ gViewerWindow->setup2DRender();
+ glPushMatrix();
+ {
+ // scale ui to reflect UIScaleFactor
+ // this can't be done in setup2DRender because it requires a
+ // pushMatrix/popMatrix pair
+ const LLVector2& display_scale = gViewerWindow->getDisplayScale();
+ glScalef(display_scale.mV[VX], display_scale.mV[VY], 1.f);
+
+ gGL.getTexUnit(0)->bind(gDisconnectedImagep);
+ gGL.color4f(1.f, 1.f, 1.f, 1.f);
+ gl_rect_2d_simple_tex(width, height);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ }
+ glPopMatrix();
+ }
+ gGL.flush();
+}
+
+void display_cleanup()
+{
+ gDisconnectedImagep = NULL;
+}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 3c850c8b13..1fa99b4a8a 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1968,6 +1968,16 @@ class LLAdvancedShowDebugSettings : public view_listener_t // VIEW ADMIN OPTIONS // //////////////////////// +class LLAdvancedEnableViewAdminOptions : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + // Don't enable in god mode since the admin menu is shown anyway. + // Only enable if the user has set the appropriate debug setting. + bool new_value = !gAgent.getAgentAccess().isGodlikeWithoutAdminMenuFakery() && gSavedSettings.getBOOL("AdminMenu"); + return new_value; + } +}; class LLAdvancedToggleViewAdminOptions : public view_listener_t { @@ -1982,7 +1992,7 @@ class LLAdvancedCheckViewAdminOptions : public view_listener_t { bool handleEvent(const LLSD& userdata) { - bool new_value = check_admin_override(NULL); + bool new_value = check_admin_override(NULL) || gAgent.isGodlike(); return new_value; } }; @@ -8007,6 +8017,7 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedCheckShowObjectUpdates(), "Advanced.CheckShowObjectUpdates"); view_listener_t::addMenu(new LLAdvancedCompressImage(), "Advanced.CompressImage"); view_listener_t::addMenu(new LLAdvancedShowDebugSettings(), "Advanced.ShowDebugSettings"); + view_listener_t::addMenu(new LLAdvancedEnableViewAdminOptions(), "Advanced.EnableViewAdminOptions"); view_listener_t::addMenu(new LLAdvancedToggleViewAdminOptions(), "Advanced.ToggleViewAdminOptions"); view_listener_t::addMenu(new LLAdvancedCheckViewAdminOptions(), "Advanced.CheckViewAdminOptions"); view_listener_t::addMenu(new LLAdvancedRequestAdminStatus(), "Advanced.RequestAdminStatus"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 727a5aa09c..7827e1a5bd 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1199,7 +1199,6 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam const BOOL auto_open = gSavedSettings.getBOOL("ShowInInventory") && // don't open if showininventory is false !(asset_type == LLAssetType::AT_CALLINGCARD) && // don't open if it's a calling card - !(item && (item->getInventoryType() == LLInventoryType::IT_ATTACHMENT)) && // don't open if it's an item that's an attachment !from_name.empty(); // don't open if it's not from anyone. LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(auto_open); if(active_panel) @@ -1511,7 +1510,12 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& // MUTE falls through to decline case IOR_DECLINE: { - log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +"."; + { + LLStringUtil::format_map_t log_message_args; + log_message_args["DESC"] = mDesc; + log_message_args["NAME"] = mFromName; + log_message = LLTrans::getString("InvOfferDecline", log_message_args); + } chat.mText = log_message; if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) ) // muting for SL-42269 { @@ -1710,8 +1714,12 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE); // send the message msg->sendReliable(mHost); - - log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +"."; + { + LLStringUtil::format_map_t log_message_args; + log_message_args["DESC"] = mDesc; + log_message_args["NAME"] = mFromName; + log_message = LLTrans::getString("InvOfferDecline", log_message_args); + } LLSD args; args["MESSAGE"] = log_message; LLNotificationsUtil::add("SystemMessage", args); diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 0b64b204ee..bf3d4d0107 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -166,6 +166,11 @@ BOOL LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject &object) { U32 local_id = object.mLocalID; LLHost region_host = object.getRegion()->getHost(); + if(!region_host.isOk()) + { + return FALSE ; + } + U32 ip = region_host.getAddress(); U32 port = region_host.getPort(); U64 ipport = (((U64)ip) << 32) | (U64)port; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index c1d670442c..93450303ea 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -559,7 +559,7 @@ F32 gWorstLandCompression = 0.f, gWorstWaterCompression = 0.f; U32 gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0; U32 gObjectBits = 0; F32 gAvgSimPing = 0.f; - +U32 gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0}; extern U32 gVisCompared; extern U32 gVisTested; diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index af65fe0488..f91a1241fe 100755 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -293,4 +293,6 @@ void send_stats(); extern std::map<S32,LLFrameTimer> gDebugTimers; extern std::map<S32,std::string> gDebugTimerLabel; extern U32 gTotalTextureBytes; +extern U32 gTotalObjectBytes; +extern U32 gTotalTextureBytesPerBoostLevel[] ; #endif // LL_LLVIEWERSTATS_H diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index ef0bcbb38f..9173ea4176 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1130,7 +1130,7 @@ void LLViewerFetchedTexture::init(bool firstinit) // does not contain this image. mIsMissingAsset = FALSE; - mLoadedCallbackDesiredDiscardLevel = 0; + mLoadedCallbackDesiredDiscardLevel = S8_MAX; mPauseLoadedCallBacks = TRUE ; mNeedsCreateTexture = FALSE; @@ -1155,9 +1155,11 @@ void LLViewerFetchedTexture::init(bool firstinit) mSavedRawImage = NULL ; mForceToSaveRawImage = FALSE ; + mSaveRawImage = FALSE ; mSavedRawDiscardLevel = -1 ; mDesiredSavedRawDiscardLevel = -1 ; mLastReferencedSavedRawImageTime = 0.0f ; + mLastCallBackActiveTime = 0.f; } LLViewerFetchedTexture::~LLViewerFetchedTexture() @@ -1490,56 +1492,57 @@ void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height) //virtual void LLViewerFetchedTexture::processTextureStats() { + static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); + if(mFullyLoaded) - { - if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more + { + if(needsToSaveRawImage())//needs to reload { - mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ; mFullyLoaded = FALSE ; } - } - else - { - updateVirtualSize() ; - - static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); - - if (textures_fullres) + else { - mDesiredDiscardLevel = 0; + return ; } - else if(!mFullWidth || !mFullHeight) + } + + //updateVirtualSize() ; + + if (textures_fullres) + { + mDesiredDiscardLevel = 0; + } + else if(!mFullWidth || !mFullHeight) + { + mDesiredDiscardLevel = llmin(getMaxDiscardLevel(), (S32)mLoadedCallbackDesiredDiscardLevel) ; + } + else + { + if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight) { - mDesiredDiscardLevel = getMaxDiscardLevel() ; - } - else - { - if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight) + if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) { - if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) - { - mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 - } - else - { - mDesiredDiscardLevel = 0; - } - } - else if(mKnownDrawSizeChanged)//known draw size is set - { - mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, - log((F32)mFullHeight / mKnownDrawHeight) / log_2) ; - mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ; - mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ; + mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 } - mKnownDrawSizeChanged = FALSE ; - - if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel)) + else { - mFullyLoaded = TRUE ; + mDesiredDiscardLevel = 0; } } - } + else if(mKnownDrawSizeChanged)//known draw size is set + { + mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, + log((F32)mFullHeight / mKnownDrawHeight) / log_2) ; + mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ; + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ; + } + mKnownDrawSizeChanged = FALSE ; + + if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel)) + { + mFullyLoaded = TRUE ; + } + } if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) //force to refetch the texture. { @@ -2081,13 +2084,14 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call mNeedsAux |= needs_aux; if(keep_imageraw) { - forceToSaveRawImage(discard_level, true) ; + mSaveRawImage = TRUE ; } if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0) { // We need aux data, but we've already loaded the image, and it didn't have any llwarns << "No aux data available for callback for image:" << getID() << llendl; } + mLastCallBackActiveTime = sCurrentTime ; } void LLViewerFetchedTexture::clearCallbackEntryList() @@ -2110,9 +2114,8 @@ void LLViewerFetchedTexture::clearCallbackEntryList() } gTextureList.mCallbackList.erase(this); - mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; mLoadedCallbackDesiredDiscardLevel = S8_MAX ; - if(mForceToSaveRawImage) + if(needsToSaveRawImage()) { destroySavedRawImage() ; } @@ -2158,14 +2161,13 @@ void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::so { // If we have no callbacks, take us off of the image callback list. gTextureList.mCallbackList.erase(this); - mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; - - if(mForceToSaveRawImage) + + if(needsToSaveRawImage()) { destroySavedRawImage() ; } } - else if(mForceToSaveRawImage && mBoostLevel != LLViewerTexture::BOOST_PREVIEW) + else if(needsToSaveRawImage() && mBoostLevel != LLViewerTexture::BOOST_PREVIEW) { if(desired_raw_discard != INVALID_DISCARD_LEVEL) { @@ -2203,7 +2205,7 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry: mPauseLoadedCallBacks = FALSE ; if(need_raw) { - mForceToSaveRawImage = TRUE ; + mSaveRawImage = TRUE ; } } @@ -2234,16 +2236,23 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s { mPauseLoadedCallBacks = TRUE ;//when set, loaded callback is paused. resetTextureStats(); - mForceToSaveRawImage = FALSE ; + mSaveRawImage = FALSE ; } } bool LLViewerFetchedTexture::doLoadedCallbacks() { + static const F32 MAX_INACTIVE_TIME = 120.f ; //seconds + if (mNeedsCreateTexture) { return false; } + if(sCurrentTime - mLastCallBackActiveTime > MAX_INACTIVE_TIME) + { + clearCallbackEntryList() ; //remove all callbacks. + return false ; + } bool res = false; @@ -2309,13 +2318,11 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() bool run_raw_callbacks = false; bool need_readback = false; - mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) { LLLoadedCallbackEntry *entryp = *iter++; - mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)entryp->mDesiredDiscard) ; - + if (entryp->mNeedsImageRaw) { if (mNeedsAux) @@ -2389,7 +2396,8 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() // to satisfy the interested party, then this is the last time that // we're going to call them. - llassert_always(mRawImage.notNull()); + mLastCallBackActiveTime = sCurrentTime ; + //llassert_always(mRawImage.notNull()); if(mNeedsAux && mAuxRawImage.isNull()) { llwarns << "Raw Image with no Aux Data for callback" << llendl; @@ -2424,6 +2432,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() LLLoadedCallbackEntry *entryp = *curiter; if (!entryp->mNeedsImageRaw && (entryp->mLastUsedDiscard > gl_discard)) { + mLastCallBackActiveTime = sCurrentTime ; BOOL final = gl_discard <= entryp->mDesiredDiscard ? TRUE : FALSE; entryp->mLastUsedDiscard = gl_discard; entryp->mCallback(TRUE, this, NULL, NULL, gl_discard, final, entryp->mUserData); @@ -2443,7 +2452,6 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() if (mLoadedCallbackList.empty()) { gTextureList.mCallbackList.erase(this); - mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; } // Done with any raw image data at this point (will be re-created if we still have callbacks) @@ -2523,6 +2531,11 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level) return mRawImage; } +bool LLViewerFetchedTexture::needsToSaveRawImage() +{ + return mForceToSaveRawImage || mSaveRawImage ; +} + void LLViewerFetchedTexture::destroyRawImage() { if (mAuxRawImage.notNull()) sAuxCount--; @@ -2533,7 +2546,7 @@ void LLViewerFetchedTexture::destroyRawImage() if(mIsRawImageValid) { - if(mForceToSaveRawImage) + if(needsToSaveRawImage()) { saveRawImage() ; } @@ -2665,7 +2678,7 @@ void LLViewerFetchedTexture::saveRawImage() mSavedRawDiscardLevel = mRawDiscardLevel ; mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()) ; - if(mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel) + if(mForceToSaveRawImage && mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel) { mForceToSaveRawImage = FALSE ; } @@ -2698,13 +2711,10 @@ void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, bool from_ void LLViewerFetchedTexture::destroySavedRawImage() { clearCallbackEntryList() ; - //if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0 && mDesiredSavedRawDiscardLevel < getDiscardLevel()) - //{ - // return ; //can not destroy the saved raw image before it is fully fetched, otherwise causing callbacks hanging there. - //} - + mSavedRawImage = NULL ; mForceToSaveRawImage = FALSE ; + mSaveRawImage = FALSE ; mSavedRawDiscardLevel = -1 ; mDesiredSavedRawDiscardLevel = -1 ; mLastReferencedSavedRawImageTime = 0.0f ; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 7cb8bea4c8..b779396293 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -441,6 +441,7 @@ public: LLImageRaw* reloadRawImage(S8 discard_level) ; void destroyRawImage(); + bool needsToSaveRawImage(); const std::string& getUrl() const {return mUrl;} //--------------- @@ -532,6 +533,7 @@ protected: S8 mLoadedCallbackDesiredDiscardLevel; BOOL mPauseLoadedCallBacks; callback_list_t mLoadedCallbackList; + F32 mLastCallBackActiveTime; LLPointer<LLImageRaw> mRawImage; S32 mRawDiscardLevel; @@ -543,6 +545,7 @@ protected: //keep a copy of mRawImage for some special purposes //when mForceToSaveRawImage is set. BOOL mForceToSaveRawImage ; + BOOL mSaveRawImage; LLPointer<LLImageRaw> mSavedRawImage; S32 mSavedRawDiscardLevel; S32 mDesiredSavedRawDiscardLevel; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index bbf7c8e60e..275dfaa996 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1161,6 +1161,8 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem) // static void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_data) { + static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; + LLFastTimer t(FTM_PROCESS_IMAGES); // Receive image header, copy into image object and decompresses @@ -1171,14 +1173,16 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d char ip_string[256]; u32_to_ip_string(msg->getSenderIP(),ip_string); + U32 received_size ; if (msg->getReceiveCompressedSize()) { - gTextureList.sTextureBits += msg->getReceiveCompressedSize() * 8; + received_size = msg->getReceiveCompressedSize() ; } else { - gTextureList.sTextureBits += msg->getReceiveSize() * 8; + received_size = msg->getReceiveSize() ; } + gTextureList.sTextureBits += received_size * 8; gTextureList.sTexturePackets++; U8 codec; @@ -1213,6 +1217,11 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d delete [] data; return; } + if(log_texture_traffic) + { + gTotalTextureBytesPerBoostLevel[image->getBoostLevel()] += received_size ; + } + //image->getLastPacketTimer()->reset(); bool res = LLAppViewer::getTextureFetch()->receiveImageHeader(msg->getSender(), id, codec, packets, totalbytes, data_size, data); if (!res) @@ -1224,6 +1233,8 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d // static void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_data) { + static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; + LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); LLFastTimer t(FTM_PROCESS_IMAGES); @@ -1236,14 +1247,16 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d char ip_string[256]; u32_to_ip_string(msg->getSenderIP(),ip_string); + U32 received_size ; if (msg->getReceiveCompressedSize()) { - gTextureList.sTextureBits += msg->getReceiveCompressedSize() * 8; + received_size = msg->getReceiveCompressedSize() ; } else { - gTextureList.sTextureBits += msg->getReceiveSize() * 8; + received_size = msg->getReceiveSize() ; } + gTextureList.sTextureBits += received_size * 8; gTextureList.sTexturePackets++; //llprintline("Start decode, image header..."); @@ -1277,6 +1290,11 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d delete [] data; return; } + if(log_texture_traffic) + { + gTotalTextureBytesPerBoostLevel[image->getBoostLevel()] += received_size ; + } + //image->getLastPacketTimer()->reset(); bool res = LLAppViewer::getTextureFetch()->receiveImagePacket(msg->getSender(), id, packet_num, data_size, data); if (!res) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index d7291c3688..399397eab2 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -308,6 +308,8 @@ public: void update() { + static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; + std::string wind_vel_text; std::string wind_vector_text; std::string rwind_vel_text; @@ -649,6 +651,7 @@ public: ypos += y_inc; } + } } void draw() @@ -1408,7 +1411,7 @@ LLViewerWindow::LLViewerWindow( gSavedSettings.getBOOL("DisableVerticalSync"), !gNoRender, ignore_pixel_depth, - 0); //gSavedSettings.getU32("RenderFSAASamples")); + gSavedSettings.getBOOL("RenderUseFBO") ? 0 : gSavedSettings.getU32("RenderFSAASamples")); //don't use window level anti-aliasing if FBOs are enabled if (!LLAppViewer::instance()->restoreErrorTrap()) { @@ -3945,7 +3948,9 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei 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); + BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI) ? TRUE : FALSE; + + show_ui = show_ui ? TRUE : FALSE; if ( prev_draw_ui != show_ui) { @@ -4083,12 +4088,13 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei if (LLPipeline::sRenderDeferred) { - display(do_rebuild, scale_factor, subfield, FALSE); + display(do_rebuild, scale_factor, subfield, TRUE); } else { display(do_rebuild, scale_factor, subfield, TRUE); - // Required for showing the GUI in snapshots? See DEV-16350 for details. JC + // Required for showing the GUI in snapshots and performing bloom composite overlay + // Call even if show_ui is FALSE render_ui(scale_factor, subfield); } } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index fdf44c6e70..86f53a6fbb 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -33,6 +33,8 @@ #include <string> #include <vector> +#include <boost/signals2.hpp> + #include "imageids.h" // IMG_INVISIBLE #include "llchat.h" #include "lldrawpoolalpha.h" @@ -71,7 +73,8 @@ class LLVOAvatarSkeletonInfo; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLVOAvatar : public LLViewerObject, - public LLCharacter + public LLCharacter, + public boost::signals2::trackable { public: friend class LLVOAvatarSelf; diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 8bdb8e069e..1cb3962daa 100644 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -28,6 +28,7 @@ #include "llvocache.h" #include "llerror.h" #include "llregionhandle.h" +#include "llviewercontrol.h" BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) { @@ -232,11 +233,11 @@ LLVOCache* LLVOCache::sInstance = NULL; //static LLVOCache* LLVOCache::getInstance() -{ +{ if(!sInstance) { sInstance = new LLVOCache() ; -} + } return sInstance ; } @@ -262,13 +263,17 @@ LLVOCache::LLVOCache(): mNumEntries(0), mCacheSize(1) { + mEnabled = gSavedSettings.getBOOL("ObjectCacheEnabled"); mLocalAPRFilePoolp = new LLVolatileAPRPool() ; } LLVOCache::~LLVOCache() { - writeCacheHeader(); - clearCacheInMemory(); + if(mEnabled) + { + writeCacheHeader(); + clearCacheInMemory(); + } delete mLocalAPRFilePoolp; } @@ -282,7 +287,7 @@ void LLVOCache::setDirNames(ELLPath location) void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) { - if(mInitialized) + if(mInitialized || !mEnabled) { return ; } @@ -409,6 +414,11 @@ BOOL LLVOCache::checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes) void LLVOCache::readCacheHeader() { + if(!mEnabled) + { + return ; + } + //clear stale info. clearCacheInMemory(); @@ -453,7 +463,7 @@ void LLVOCache::readCacheHeader() void LLVOCache::writeCacheHeader() { - if(mReadOnly) + if(mReadOnly || !mEnabled) { return ; } @@ -504,6 +514,10 @@ BOOL LLVOCache::updateEntry(const HeaderEntryInfo* entry) void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) { + if(!mEnabled) + { + return ; + } llassert_always(mInitialized); handle_entry_map_t::iterator iter = mHandleEntryMap.find(handle) ; @@ -573,6 +587,10 @@ void LLVOCache::purgeEntries() void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) { + if(!mEnabled) + { + return ; + } llassert_always(mInitialized); if(mReadOnly) diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index ccdff5e96c..ed2bc8bafe 100644 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -129,6 +129,7 @@ private: BOOL checkWrite(LLAPRFile* apr_file, void* src, S32 n_bytes) ; private: + BOOL mEnabled; BOOL mInitialized ; BOOL mReadOnly ; HeaderMetaInfo mMetaInfo; @@ -143,7 +144,7 @@ private: static LLVOCache* sInstance ; public: static LLVOCache* getInstance() ; - static BOOL hasInstance() ; + static BOOL hasInstance() ; static void destroyClass() ; }; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 1bd3aea1e0..70997f7be6 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -126,7 +126,10 @@ void LLWorld::destroyClass() LLViewerRegion* region_to_delete = *region_it++; removeRegion(region_to_delete->getHost()); } - LLVOCache::getInstance()->destroyClass() ; + if(LLVOCache::hasInstance()) + { + LLVOCache::getInstance()->destroyClass() ; + } LLViewerPartSim::getInstance()->destroyClass(); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c154fe7b75..d1a4575880 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -561,7 +561,8 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) mScreenWidth = resX; mScreenHeight = resY; - U32 samples = gSavedSettings.getU32("RenderFSAASamples"); + //never use more than 4 samples for render targets + U32 samples = llmin(gSavedSettings.getU32("RenderFSAASamples"), (U32) 4); U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor"); if (res_mod > 1 && res_mod < resX && res_mod < resY) @@ -587,8 +588,6 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); addDeferredAttachments(mDeferredScreen); - // always set viewport to desired size, since allocate resets the viewport - mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); @@ -694,7 +693,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) } - if (gGLManager.mHasFramebufferMultisample && samples > 1) + if (LLRenderTarget::sUseFBO && gGLManager.mHasFramebufferMultisample && samples > 1) { mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); if (LLPipeline::sRenderDeferred) @@ -979,7 +978,7 @@ BOOL LLPipeline::canUseWindLightShadersOnObjects() const BOOL LLPipeline::canUseAntiAliasing() const { - return (gSavedSettings.getBOOL("RenderUseFBO")); + return TRUE; //(gSavedSettings.getBOOL("RenderUseFBO")); } void LLPipeline::unloadShaders() diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 0a27cc7bc9..3dd6c60095 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -255,7 +255,6 @@ </text> <!--TODO: HOOK UP GROUP ICON--> <text - enabled="false" follows="left|top" height="16" left_pad="2" diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml index 457142f11c..4e0cfb0cd4 100644 --- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml @@ -7,7 +7,7 @@ name="floaterbulkperms" help_topic="floaterbulkperms" title="EDIT CONTENT PERMISSIONS" - width="300"> + width="410"> <floater.string name="nothing_to_modify_text"> Selection contains no editable contents. @@ -71,7 +71,7 @@ control_name="BulkChangeIncludeGestures" height="16" name="check_gesture" - left="65" + left="95" width="16" top="25" /> <icon @@ -87,7 +87,7 @@ height="16" layout="topleft" name="check_notecard" - left="65" + left="95" width="16" top_pad="5" /> <icon @@ -102,7 +102,7 @@ control_name="BulkChangeIncludeObjects" height="16" name="check_object" - left="65" + left="95" top_pad="5" width="16" /> <icon @@ -117,7 +117,7 @@ height="16" name="check_script" top="25" - left="120" + left="180" width="16" /> <icon @@ -133,7 +133,7 @@ height="16" name="check_sound" top_pad="5" - left="120" + left="180" width="16" /> <icon height="16" @@ -147,7 +147,7 @@ height="16" name="check_texture" top_pad="5" - left="120" + left="180" width="16" /> <icon height="16" @@ -162,7 +162,7 @@ layout="topleft" name="check_all" label="√ All" - left="180" + left="290" top="26" width="115"> <button.commit_callback @@ -221,7 +221,7 @@ height="28" layout="topleft" name="AnyoneLabel" - left="104" + left="124" top="110" width="92" word_wrap="true"> @@ -243,7 +243,7 @@ layout="topleft" name="NextOwnerLabel" top="110" - left="189" + left="275" width="92" word_wrap="true"> Next owner: @@ -292,7 +292,7 @@ height="23" label="OK" layout="topleft" - left="95" + left="205" name="apply" top_pad="10" width="90"> diff --git a/indra/newview/skins/default/xui/en/floater_display_name.xml b/indra/newview/skins/default/xui/en/floater_display_name.xml index 7a3fb9334a..9a9fd32a77 100644 --- a/indra/newview/skins/default/xui/en/floater_display_name.xml +++ b/indra/newview/skins/default/xui/en/floater_display_name.xml @@ -63,7 +63,7 @@ width="300" height="20" font="SansSerif" - name="set_name_label"> + name="name_confirm_label"> Type your new name again to confirm: </text> <line_editor diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml index 27f8b4bb39..0ea42f9757 100644 --- a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml @@ -71,6 +71,18 @@ name="16x" value="16" /> </combo_box> + <text + type="string" + length="1" + follows="left|top" + height="12" + layout="topleft" + left_pad="10" + name="antialiasing restart" + top_delta="0" + width="188"> + (requires viewer restart) + </text> <spinner control_name="RenderGamma" decimal_digits="2" diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 49f7080662..f6f74f2ebd 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1021,7 +1021,7 @@ top_pad="10" left="10" name="label click action" - width="98"> + width="118"> Click to: </text> <combo_box @@ -1029,7 +1029,7 @@ height="23" layout="topleft" name="clickaction" - width="168" + width="148" left_pad="0"> <combo_box.item label="Touch (default)" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 47006f34f1..7bb4c93766 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3128,15 +3128,6 @@ <menu_item_separator/> - <menu_item_check - label="Show Admin Menu" - name="View Admin Options"> - <menu_item_check.on_check - function="Advanced.CheckViewAdminOptions" - parameter="ViewAdminOptions" /> - <menu_item_check.on_click - function="Advanced.ToggleViewAdminOptions" /> - </menu_item_check> <menu_item_call label="Request Admin Status" name="Request Admin Options" @@ -3161,6 +3152,17 @@ <menu_item_call.on_enable function="File.EnableUploadModel" /> </menu_item_call> + <menu_item_check + label="Show Admin Menu" + name="View Admin Options"> + <menu_item_check.on_enable + function="Advanced.EnableViewAdminOptions" /> + <menu_item_check.on_check + function="Advanced.CheckViewAdminOptions" + parameter="ViewAdminOptions" /> + <menu_item_check.on_click + function="Advanced.ToggleViewAdminOptions" /> + </menu_item_check> </menu> <menu create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 3279deb595..5248128819 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6358,7 +6358,6 @@ You sent out an update of your appearance after [TIME] seconds. [STATUS] </notification> - <notification icon="notifytip.tga" name="AvatarRezCloudNotification" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index d34c0c29a8..68c423d7dd 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -307,7 +307,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M image_unselected="Toolbar_Right_Off" left="0" layout="topleft" - name="trash_btn" + name="del_btn" tool_tip="Remove selected person from your Friends list" top="0" width="31"/> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index 31e160ec33..85824c2576 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -308,6 +308,38 @@ width="95"> URLs </text> + <spinner + control_name="NearbyToastLifeTime" + decimal_digits="0" + follows="left|top" + height="23" + increment="1" + initial_value="23" + label="Nearby chat toasts life time:" + label_width="190" + layout="topleft" + left="290" + max_val="60" + min_val="1" + name="nearby_toasts_lifetime" + top_pad="33" + width="210" /> + <spinner + control_name="NearbyToastFadingTime" + decimal_digits="0" + follows="left|top" + height="23" + increment="1" + initial_value="3" + label="Nearby chat toasts fading time:" + label_width="190" + layout="topleft" + left_delta="00" + max_val="60" + min_val="0" + name="nearby_toasts_fadingtime" + top_pad="15" + width="210" /> <check_box control_name="PlayTypingAnim" height="16" @@ -316,7 +348,7 @@ layout="topleft" left="30" name="play_typing_animation" - top_pad="32" + top="205" width="400" /> <check_box enabled="false" @@ -343,7 +375,7 @@ left="30" height="20" width="170" - top_pad="14"> + top_pad="7"> Show IMs in: </text> <text @@ -359,14 +391,14 @@ (requires restart) </text> <radio_group + follows="left|top" height="30" - layout="topleft" left="40" control_name="ChatWindow" name="chat_window" top_pad="0" tool_tip="Show your Instant Messages in separate floaters, or in one floater with many tabs (Requires restart)" - width="331"> + width="150"> <radio_item height="16" label="Separate windows" @@ -386,6 +418,36 @@ top_pad="5" width="150" /> </radio_group> + <text + name="disable_toast_label" + follows="left|top" + layout="topleft" + top_delta="-22" + left="280" + height="10" + width="180"> + Enable Incoming Chat popups: + </text> + <check_box + control_name="EnableGroupChatPopups" + name="EnableGroupChatPopups" + label="Group Chats" + layout="topleft" + top_delta="18" + left="295" + height="20" + tool_tip="Check to see popups when a Group Chat message arrives" + width="400" /> + <check_box + control_name="EnableIMChatPopups" + name="EnableIMChatPopups" + label="IM Chats" + layout="topleft" + top_delta="22" + left="295" + height="20" + tool_tip="Check to see popups when an instant message arrives" + width="400" /> <check_box control_name="TranslateChat" enabled="true" @@ -488,4 +550,4 @@ name="Korean" value="ko" /> </combo_box> -</panel> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_script_ed.xml b/indra/newview/skins/default/xui/en/panel_script_ed.xml index c5c66c04d5..1e332a40c2 100644 --- a/indra/newview/skins/default/xui/en/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/en/panel_script_ed.xml @@ -141,6 +141,7 @@ layout="topleft" max_length="65536" name="Script Editor" + text_readonly_color="DkGray" width="487" show_line_numbers="true" word_wrap="true"> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 43af1fb958..10a7124182 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2244,8 +2244,7 @@ Clears (deletes) the media and all params from the given face. <string name="InvOfferOwnedBy">owned by</string> <string name="InvOfferOwnedByUnknownUser">owned by an unknown user</string> <string name="InvOfferGaveYou">gave you</string> - <string name="InvOfferYouDecline">You decline</string> - <string name="InvOfferFrom">from</string> + <string name="InvOfferDecline">You decline [DESC] from <nolink>[NAME]</nolink>.</string> <!-- group money --> <string name="GroupMoneyTotal">Total</string> diff --git a/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml b/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml index ed8df69bf4..1bb3188cc8 100644 --- a/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <avatar_list_item + name_right_pad="5" height="0" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/es/floater_avatar_picker.xml b/indra/newview/skins/default/xui/es/floater_avatar_picker.xml index c83dd3ef3e..49fce5d4ec 100644 --- a/indra/newview/skins/default/xui/es/floater_avatar_picker.xml +++ b/indra/newview/skins/default/xui/es/floater_avatar_picker.xml @@ -24,6 +24,10 @@ Escribe parte del nombre de la persona: </text> <button label="Ir" label_selected="Ir" name="Find"/> + <scroll_list name="SearchResults"> + <columns label="Nombre" name="name"/> + <columns label="Nombre de usuario" name="username"/> + </scroll_list> </panel> <panel label="Amigos" name="FriendsPanel"> <text name="InstructSelectFriend"> @@ -39,7 +43,10 @@ Metros </text> <button font="SansSerifSmall" label="Actualizar la lista" label_selected="Actualizar la lista" left_delta="1" name="Refresh" width="115"/> - <scroll_list bottom_delta="-169" height="159" name="NearMe"/> + <scroll_list bottom_delta="-169" height="159" name="NearMe"> + <columns label="Nombre" name="name"/> + <columns label="Nombre de usuario" name="username"/> + </scroll_list> </panel> </tab_container> <button label="OK" label_selected="OK" name="ok_btn"/> diff --git a/indra/newview/skins/default/xui/es/floater_bumps.xml b/indra/newview/skins/default/xui/es/floater_bumps.xml index 6a9c6b1f22..6d4196ca7c 100644 --- a/indra/newview/skins/default/xui/es/floater_bumps.xml +++ b/indra/newview/skins/default/xui/es/floater_bumps.xml @@ -4,19 +4,19 @@ No se han detectado </floater.string> <floater.string name="bump"> - [TIME] [FIRST] [LAST] ha chocado con usted + [TIME] [NAME] ha chocado contigo </floater.string> <floater.string name="llpushobject"> - [TIME] [FIRST] [LAST] le ha empujado con un script + [TIME] [NAME] te ha empujado con un script </floater.string> <floater.string name="selected_object_collide"> - [TIME] [FIRST] [LAST] ha hecho que un objeto impacte con usted + [TIME] [NAME] te ha golpeado con un script </floater.string> <floater.string name="scripted_object_collide"> - [TIME] [FIRST] [LAST] ha hecho que un objeto con script impacte con usted + [TIME] [NAME] te ha golpeado con un objeto con script </floater.string> <floater.string name="physical_object_collide"> - [TIME] [FIRST] [LAST] ha hecho que un objeto material impacte con usted + [TIME] [NAME] te ha golpeado con un objeto físico </floater.string> <floater.string name="timeStr"> [[hour,datetime,slt]:[min,datetime,slt]] diff --git a/indra/newview/skins/default/xui/es/floater_buy_object.xml b/indra/newview/skins/default/xui/es/floater_buy_object.xml index 117d29777f..a774bc6d05 100644 --- a/indra/newview/skins/default/xui/es/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/es/floater_buy_object.xml @@ -1,26 +1,29 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="contents" title="COMPRAR UNA COPIA DEL OBJETO"> + <floater.string name="title_buy_text"> + Comprar + </floater.string> + <floater.string name="title_buy_copy_text"> + Comprar una copia de + </floater.string> + <floater.string name="no_copy_text"> + (no copiable) + </floater.string> + <floater.string name="no_modify_text"> + (no modificable) + </floater.string> + <floater.string name="no_transfer_text"> + (no transferible) + </floater.string> <text name="contents_text"> Contenidos: </text> <text name="buy_text"> - ¿Comprarlo por [AMOUNT] L$ a [NAME]? + ¿Comprar por [AMOUNT] L$ a: + </text> + <text name="buy_name_text"> + [NAME]? </text> - <button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/> <button label="Comprar" label_selected="Comprar" name="buy_btn"/> - <string name="title_buy_text"> - Comprar - </string> - <string name="title_buy_copy_text"> - Comprar una copia de - </string> - <string name="no_copy_text"> - (no copiable) - </string> - <string name="no_modify_text"> - (no modificable) - </string> - <string name="no_transfer_text"> - (no transferible) - </string> + <button label="Cancelar" label_selected="Cancelar" name="cancel_btn"/> </floater> diff --git a/indra/newview/skins/default/xui/es/floater_display_name.xml b/indra/newview/skins/default/xui/es/floater_display_name.xml new file mode 100644 index 0000000000..f1a31a6776 --- /dev/null +++ b/indra/newview/skins/default/xui/es/floater_display_name.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="Display Name" title="CAMBIAR EL NOMBRE MOSTRADO"> + <text name="info_text"> + El nombre que le has dado a tu avatar se denomina Nombre mostrado. Puedes cambiarlo una vez a la semana. + </text> + <text name="lockout_text"> + No puedes cambiar el nombre mostrado hasta: [TIME]. + </text> + <text name="set_name_label"> + Nuevo nombre mostrado: + </text> + <text name="name_confirm_label"> + Vuelve a escribir tu nombre nuevo para confirmarlo: + </text> + <button label="Guardar" name="save_btn" tool_tip="Guarda tu nombre nuevo"/> + <button label="Reconfigurar" name="reset_btn" tool_tip="Hacer que el nombre mostrado y el nombre de usuario coincidan"/> + <button label="Cancelar" name="cancel_btn"/> +</floater> diff --git a/indra/newview/skins/default/xui/es/floater_event.xml b/indra/newview/skins/default/xui/es/floater_event.xml index 8bca7783ab..d2724bf8b0 100644 --- a/indra/newview/skins/default/xui/es/floater_event.xml +++ b/indra/newview/skins/default/xui/es/floater_event.xml @@ -1,40 +1,11 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - follows="all" - height="400" - can_resize="true" - help_topic="event_details" - label="Event" - layout="topleft" - name="Event" - save_rect="true" - save_visibility="false" - title="EVENT DETAILS" - width="600"> - <floater.string - name="loading_text"> +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater can_resize="true" follows="all" height="400" help_topic="event_details" label="Event" layout="topleft" name="Event" save_rect="true" save_visibility="false" title="EVENT DETAILS" width="600"> + <floater.string name="loading_text"> Cargando... </floater.string> - <floater.string - name="done_text"> - Done - </floater.string> - <web_browser - trusted_content="true" - follows="left|right|top|bottom" - layout="topleft" - left="10" - name="browser" - height="365" - width="580" - top="0"/> - <text - follows="bottom|left" - height="16" - layout="topleft" - left_delta="0" - name="status_text" - top_pad="10" - width="150" /> + <floater.string name="done_text"> + Hecho + </floater.string> + <web_browser follows="left|right|top|bottom" height="365" layout="topleft" left="10" name="browser" top="0" trusted_content="true" width="580"/> + <text follows="bottom|left" height="16" layout="topleft" left_delta="0" name="status_text" top_pad="10" width="150"/> </floater> - diff --git a/indra/newview/skins/default/xui/es/floater_incoming_call.xml b/indra/newview/skins/default/xui/es/floater_incoming_call.xml index 88cfc9575a..b5b756abb6 100644 --- a/indra/newview/skins/default/xui/es/floater_incoming_call.xml +++ b/indra/newview/skins/default/xui/es/floater_incoming_call.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="incoming call" title="ESTÁ LLAMANDO ALGUIEN DESCONOCIDO"> +<floater name="incoming call" title="Llamada entrante"> <floater.string name="lifetime"> 5 </floater.string> diff --git a/indra/newview/skins/default/xui/es/floater_pay.xml b/indra/newview/skins/default/xui/es/floater_pay.xml index d4a4e81310..ad9a43ad71 100644 --- a/indra/newview/skins/default/xui/es/floater_pay.xml +++ b/indra/newview/skins/default/xui/es/floater_pay.xml @@ -11,7 +11,7 @@ </text> <icon name="icon_person" tool_tip="Persona"/> <text left="115" name="payee_name"> - [FIRST] [LAST] + Nombre de prueba demasiado largo para comprobar la función de recorte </text> <button label="1 L$" label_selected="1 L$" name="fastpay 1"/> <button label="5 L$" label_selected="5 L$" name="fastpay 5"/> diff --git a/indra/newview/skins/default/xui/es/floater_pay_object.xml b/indra/newview/skins/default/xui/es/floater_pay_object.xml index f29745ea9b..4767f4dfa0 100644 --- a/indra/newview/skins/default/xui/es/floater_pay_object.xml +++ b/indra/newview/skins/default/xui/es/floater_pay_object.xml @@ -8,7 +8,7 @@ </string> <icon name="icon_person" tool_tip="Persona"/> <text left="120" name="payee_name" width="180"> - [FIRST] [LAST] + Ericacita Moostopolison </text> <text left="5" name="object_name_label" width="110"> A través del objeto: diff --git a/indra/newview/skins/default/xui/es/floater_tools.xml b/indra/newview/skins/default/xui/es/floater_tools.xml index 9867f1b575..d85b43b7e8 100644 --- a/indra/newview/skins/default/xui/es/floater_tools.xml +++ b/indra/newview/skins/default/xui/es/floater_tools.xml @@ -171,13 +171,13 @@ Creador: </text> <text name="Creator Name"> - Thrax Linden + Dª Esbee Linden (esbee.linden) </text> <text name="Owner:"> Propietario: </text> <text name="Owner Name"> - Thrax Linden + Dª Erica "Moose" Linden (erica.linden) </text> <text name="Group:"> Grupo: @@ -186,10 +186,10 @@ <button label="Configurar..." label_selected="Configurar..." name="button set group" tool_tip="Elige un grupo con el que compartir los permisos de este objeto"/> <check_box label="Compartir" name="checkbox share with group" tool_tip="Permite que todos los miembros del grupo compartan tus permisos de modificación en este objeto. Debes transferirlo para activar las restricciones según los roles."/> <button label="Transferir" label_selected="Transferir" name="button deed" tool_tip="La transferencia entrega este objeto con los permisos del próximo propietario. Los objetos compartidos por el grupo pueden ser transferidos por un oficial del grupo."/> - <text name="label click action" width="180"> + <text name="label click action"> Al tocarlo: </text> - <combo_box name="clickaction" width="192"> + <combo_box name="clickaction"> <combo_box.item label="Tocarlo (por defecto)" name="Touch/grab(default)"/> <combo_box.item label="Sentarse en el objeto" name="Sitonobject"/> <combo_box.item label="Comprar el objeto" name="Buyobject"/> diff --git a/indra/newview/skins/default/xui/es/floater_voice_controls.xml b/indra/newview/skins/default/xui/es/floater_voice_controls.xml index 6f4782417d..f02855123c 100644 --- a/indra/newview/skins/default/xui/es/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/es/floater_voice_controls.xml @@ -19,7 +19,7 @@ <layout_panel name="my_panel"> <text name="user_text" value="Mi avatar:"/> </layout_panel> - <layout_panel name="leave_call_panel"> + <layout_panel name="leave_call_panel"> <layout_stack name="voice_effect_and_leave_call_stack"> <layout_panel name="leave_call_btn_panel"> <button label="Colgar" name="leave_call_btn"/> diff --git a/indra/newview/skins/default/xui/es/inspect_avatar.xml b/indra/newview/skins/default/xui/es/inspect_avatar.xml index bff10d9292..119f252db2 100644 --- a/indra/newview/skins/default/xui/es/inspect_avatar.xml +++ b/indra/newview/skins/default/xui/es/inspect_avatar.xml @@ -10,6 +10,11 @@ <string name="Details"> [SL_PROFILE] </string> + <text name="user_name_small" value="Grumpity ProductEngine con un nombre demasiado largo"/> + <text name="user_slid" value="james.linden"/> + <text name="user_details"> + Ésta es mi descripción de Second Life que, por cierto, me encanta. Pero, por lo que sea, me he enrollado más de la cuenta y la descripción es larguísima. + </text> <slider name="volume_slider" tool_tip="Volumen de la voz" value="0.5"/> <button label="Añadir como amigo" name="add_friend_btn"/> <button label="MI" name="im_btn"/> diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml index 4ad631ac10..649c0c2043 100644 --- a/indra/newview/skins/default/xui/es/menu_viewer.xml +++ b/indra/newview/skins/default/xui/es/menu_viewer.xml @@ -85,6 +85,7 @@ <menu_item_call label="Coger una copia" name="Take Copy"/> <menu_item_call label="Guardar una copia en mi inventario" name="Save Object Back to My Inventory"/> <menu_item_call label="Guardar una copia del objeto en los contenidos de donde salió" name="Save Object Back to Object Contents"/> + <menu_item_call label="Devolver objeto" name="Return Object back to Owner"/> </menu> <menu label="Scripts" name="Scripts"> <menu_item_call label="Recompilar los scripts (Mono)" name="Mono"/> @@ -98,6 +99,7 @@ <menu_item_check label="Seleccionar sólo mis objetos" name="Select Only My Objects"/> <menu_item_check label="Seleccionar sólo los objetos movibles" name="Select Only Movable Objects"/> <menu_item_check label="Seleccionar marcando los alrededores" name="Select By Surrounding"/> + <menu_item_check label="Mostrar detalles de la selección" name="Show Selection Outlines"/> <menu_item_check label="Al seleccionar, mostrar lo oculto" name="Show Hidden Selection"/> <menu_item_check label="Al seleccionar, mostrar el radio de la luz" name="Show Light Radius for Selection"/> <menu_item_check label="Mostrar el rayo indicador" name="Show Selection Beam"/> @@ -118,6 +120,7 @@ <menu_item_call label="Denunciar una infracción" name="Report Abuse"/> <menu_item_call label="Informar de un fallo" name="Report Bug"/> <menu_item_call label="Acerca de [APP_NAME]" name="About Second Life"/> + <menu_item_check label="Permitir consejos" name="Enable Hints"/> </menu> <menu label="Avanzado" name="Advanced"> <menu_item_call label="Parar mis animaciones" name="Stop Animating My Avatar"/> @@ -264,7 +267,7 @@ <menu_item_call label="Web Browser Test" name="Web Browser Test"/> <menu_item_call label="Print Selected Object Info" name="Print Selected Object Info"/> <menu_item_call label="Memory Stats" name="Memory Stats"/> - <menu_item_check label="Double-Click Auto-Pilot" name="Double-Click Auto-Pilot"/> + <menu_item_check label="Haz doble clic en Piloto automático" name="Double-ClickAuto-Pilot"/> <menu_item_check label="Teleportar mediante doble clic" name="DoubleClick Teleport"/> <menu_item_check label="Debug Clicks" name="Debug Clicks"/> <menu_item_check label="Debug Mouse Events" name="Debug Mouse Events"/> @@ -276,6 +279,7 @@ <menu_item_call label="Save to XML" name="Save to XML"/> <menu_item_check label="Show XUI Names" name="Show XUI Names"/> <menu_item_call label="Send Test IMs" name="Send Test IMs"/> + <menu_item_call label="Eliminar registros de nombres en caché" name="Flush Names Caches"/> </menu> <menu label="Avatar" name="Character"> <menu label="Grab Baked Texture" name="Grab Baked Texture"> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 6379722553..286af718e3 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -110,7 +110,7 @@ Asegúrate de que tu conexión a Internet está funcionando adecuadamente. </notification> <notification name="GrantModifyRights"> Al conceder permisos de modificación a otro Residente, le estás permitiendo cambiar, borrar o tomar CUALQUIER objeto que tengas en el mundo. Sé MUY cuidadoso al conceder este permiso. -¿Quieres conceder permisos de modificación a [FIRST_NAME] [LAST_NAME]? +¿Quieres conceder permisos de modificación a [NAME]? <usetemplate name="okcancelbuttons" notext="No" yestext="Sí"/> </notification> <notification name="GrantModifyRightsMultiple"> @@ -119,7 +119,7 @@ Asegúrate de que tu conexión a Internet está funcionando adecuadamente. <usetemplate name="okcancelbuttons" notext="No" yestext="Sí"/> </notification> <notification name="RevokeModifyRights"> - ¿Quieres revocar los derechos de modificación a [FIRST_NAME] [LAST_NAME]? + ¿Quieres retirar los permisos de modificación a [NAME]? <usetemplate name="okcancelbuttons" notext="No" yestext="Sí"/> </notification> <notification name="RevokeModifyRightsMultiple"> @@ -314,17 +314,17 @@ Se ha superado el límite máximo de [MAX_ATTACHMENTS] objetos. Por favor, quít No puedes vestirte este ítem porque aún no se ha cargado. Por favor, inténtalo de nuevo en un minuto. </notification> <notification name="MustHaveAccountToLogIn"> - ¡Vaya! Algo se quedó en blanco. -Debes escribir tanto el nombre como el apellido de tu avatar, los dos. + Lo sentimos. Se ha quedado algún espacio en blanco. +Tienes que volver a introducir el nombre de usuario de tu avatar. -Necesitas una cuenta para entrar en [SECOND_LIFE]. ¿Quieres crear una ahora? +Necesitas una cuenta para acceder a [SECOND_LIFE]. ¿Te gustaría crear una ahora? <url name="url"> https://join.secondlife.com/index.php?lang=es-ES </url> <usetemplate name="okcancelbuttons" notext="Volver a intentarlo" yestext="Crear una cuenta nueva"/> </notification> <notification name="InvalidCredentialFormat"> - Escribe el nombre y apellido de tu avatar en el campo Nombre de usuario e inicia sesión otra vez. + Escribe el nombre de usuario o el nombre y el apellido de tu avatar en el campo Nombre de usuario e inicia sesión otra vez. </notification> <notification name="AddClassified"> Los anuncios clasificados aparecen durante una semana en la sección 'Clasificados' de la búsqueda y en [http://secondlife.com/community/classifieds secondlife.com]. @@ -921,12 +921,6 @@ Generalmente, esto es un fallo pasajero. Por favor, personaliza y guarda el íte No se ha podido comprar terreno para el grupo: no tienes el permiso de comprar terreno para el grupo que tienes activado actualmente. </notification> - <notification label="Añadir como amigo" name="AddFriend"> - Los amigos pueden darse permiso para localizarse en el mapa y para saber si el otro está conectado. - -¿Ofrecer a [NAME] que sea tu amigo? - <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> - </notification> <notification label="Añadir como amigo" name="AddFriendWithMessage"> Los amigos pueden darse permiso para localizarse en el mapa y para saber si el otro está conectado. @@ -970,7 +964,7 @@ no tienes el permiso de comprar terreno para el grupo que tienes activado actual </form> </notification> <notification name="RemoveFromFriends"> - ¿Quieres quitar a [FIRST_NAME] [LAST_NAME] de tu lista de amigos? + ¿Quieres eliminar a [NAME] de tu lista de amigos? <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> </notification> <notification name="RemoveMultipleFromFriends"> @@ -1093,12 +1087,11 @@ Si se vende una parcela transferida, el precio de venta se dividirá a partes ig <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> </notification> <notification name="DeedLandToGroupWithContribution"> - Al transferir esta parcela, se requerirá al grupo que tenga y mantenga el crédito suficiente para uso de terreno. -La tranferencia incluirá, a la vez, una contribucíon de terreno al grupo de '[FIRST_NAME] [LAST_NAME]'. -El precio de compra de la parcela no se reembolsa al propietario. -Si se vende una parcela transferida, el precio de venta se dividirá a partes iguales entre los miembros del grupo. + Al transferir esta parcela, el grupo deberá poseer y mantener el número suficiente de créditos de uso de terreno. +El traspaso incluirá una contribución simultánea de terreno al grupo de "[NAME]". +El precio de compra del terreno no se le devolverá al propietario. Si se vende una parcela transferida, el precio de venta se dividirá en partes iguales entre los miembros del grupo. -¿Transferir estos [AREA] m² de terreno al grupo '[GROUP_NAME]'? +¿Transferir este terreno de [AREA] m² al grupo '[GROUP_NAME]'? <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> </notification> <notification name="DisplaySetToSafe"> @@ -1471,6 +1464,46 @@ Se ocultará el chat y los mensajes instantáneos (éstos recibirán tu Respue <button name="Cancel" text="Cancelar"/> </form> </notification> + <notification name="SetDisplayNameSuccess"> + ¡Hola, [DISPLAY_NAME]! + +Al igual que en la vida real, normalmente se tarda algún tiempo en aprender nombres nuevos. Te recomendamos que esperes varios días antes de [http://wiki.secondlife.com/wiki/Setting_your_display_name your name to update] en objetos, scripts, búsquedas, etc. + </notification> + <notification name="SetDisplayNameBlocked"> + Lo sentimos. No puedes cambiar tu nombre mostrado. Si crees que se trata de un error, ponte en contacto con soporte. + </notification> + <notification name="SetDisplayNameFailedLength"> + Lo sentimos. El nombre es demasiado largo. Los nombres mostrados pueden tener un máximo de [LENGTH] caracteres. + +Prueba con un nombre más corto. + </notification> + <notification name="SetDisplayNameFailedGeneric"> + Lo sentimos. No hemos podido configurar tu nombre mostrado. Vuelve a intentarlo más tarde. + </notification> + <notification name="SetDisplayNameMismatch"> + Los nombres mostrados introducidos no coinciden. Vuelve a introducirlos. + </notification> + <notification name="AgentDisplayNameUpdateThresholdExceeded"> + Lo sentimos. Tendrás que esperar para poder cambiar tu nombre mostrado. + +Consulta http://wiki.secondlife.com/wiki/Setting_your_display_name + +Vuelve a intentarlo más tarde. + </notification> + <notification name="AgentDisplayNameSetBlocked"> + Lo sentimos. No he mos podido configurar el nombre que has solicitado porque contiene una palabra prohibida. + + Prueba con un nombre distinto. + </notification> + <notification name="AgentDisplayNameSetInvalidUnicode"> + El nombre mostrado que deseas configurar contiene caracteres no válidos. + </notification> + <notification name="AgentDisplayNameSetOnlyPunctuation"> + Tu nombre mostrado debe contener letras y no debe incluir signos de puntuación. + </notification> + <notification name="DisplayNameUpdate"> + A [OLD_NAME] ([SLID]) se le conoce ahora como [NEW_NAME]. + </notification> <notification name="OfferTeleport"> ¿Ofrecer teleporte a tu posición con este mensaje? <form name="form"> @@ -2038,10 +2071,10 @@ Publícala en una página web para que otros puedan acceder fácilmente a esta p Asunto: [SUBJECT], Mensaje: [MESSAGE] </notification> <notification name="FriendOnline"> - [FIRST] [LAST] está conectado + [NAME] está conectado </notification> <notification name="FriendOffline"> - [FIRST] [LAST] no está conectado + [NAME] está desconectado </notification> <notification name="AddSelfFriend"> Aunque eres muy agradable, no puedes añadirte como amigo a ti mismo. @@ -2108,9 +2141,6 @@ Esto puede influir en tu contraseña. <notification name="CannotRemoveProtectedCategories"> No puedes quitar categorías que están protegidas. </notification> - <notification name="OfferedCard"> - Has ofrecido una tarjeta de visita a [FIRST] [LAST] - </notification> <notification name="UnableToBuyWhileDownloading"> No se puede comprar un objeto mientras se descargan los datos. Por favor, vuelve a intentarlo. @@ -2181,7 +2211,10 @@ Inténtalo seleccionando un trozo más pequeño de terreno. <notification name="SystemMessage"> [MESSAGE] </notification> - <notification name="PaymentRecived"> + <notification name="PaymentReceived"> + [MESSAGE] + </notification> + <notification name="PaymentSent"> [MESSAGE] </notification> <notification name="EventNotification"> @@ -2226,7 +2259,7 @@ Por favor, reinstala el plugin o contacta con el vendedor si sigues teniendo pro Se han devuelto a tu inventario los objetos de los que eras propietario en la parcela seleccionada. </notification> <notification name="OtherObjectsReturned"> - Se han devuelto a tu inventario los objetos de los que eras propietario en la parcela propiedad de [FIRST] [LAST]. + Se han devuelto a su inventario los objetos en la parcela de terreno seleccionada propiedad de [NAME]. </notification> <notification name="OtherObjectsReturned2"> Se han devuelto a su propietario los objetos seleccionados en la parcela de terreno propiedad de '[NAME]'. @@ -2350,7 +2383,7 @@ Por favor, vuelve a intentarlo en unos momentos. No se ha podido encontrar una parcela válida. </notification> <notification name="ObjectGiveItem"> - Un objeto de nombre [OBJECTFROMNAME], propiedad de [NAME_SLURL], te ha dado este [OBJECTTYPE]: + Un objeto de nombre <nolink>[OBJECTFROMNAME]</nolink>, propiedad de [NAME_SLURL], te ha dado este [OBJECTTYPE]: [ITEM_SLURL] <form name="form"> <button name="Keep" text="Guardar"/> @@ -2415,9 +2448,9 @@ Por favor, vuelve a intentarlo en unos momentos. Has ofrecido amistad a [TO_NAME] </notification> <notification name="OfferFriendshipNoMessage"> - [NAME] te está ofreciendo amistad. + [NAME_SLURL] está ofreciendo amistad. -(Por defecto, podrás ver si están conectados los demás). +(De manera predeterminada, podrás ver si están conectados los demás.) <form name="form"> <button name="Accept" text="Aceptar"/> <button name="Decline" text="Rehusar"/> @@ -2452,11 +2485,11 @@ Si permaneces en esta región serás desconectado. Si permaneces en esta región serás desconectado. </notification> <notification name="LoadWebPage"> - ¿Cargar la página web [URL]? + ¿Cargar página web [URL]? [MESSAGE] -Del objeto: [OBJECTNAME]; propiedad de: [NAME]? +Del objeto: <nolink>[OBJECTNAME]</nolink>, propietario: [NAME]? <form name="form"> <button name="Gotopage" text="Cargar"/> <button name="Cancel" text="Cancelar"/> @@ -2472,10 +2505,10 @@ Del objeto: [OBJECTNAME]; propiedad de: [NAME]? El ítem que quieres vestirte tiene una característica que tu visor no puede leer. Por favor, actualiza tu versión de [APP_NAME] para ponerte este ítem. </notification> <notification name="ScriptQuestion"> - '[OBJECTNAME]', un objeto propiedad de '[NAME]', querría: + <nolink>[OBJECTNAME]</nolink>, un objeto propiedad de '[NAME]', quiere: [QUESTIONS] -¿Estás de acuerdo? +¿Es correcto? <form name="form"> <button name="Yes" text="Sí"/> <button name="No" text="No"/> @@ -2483,7 +2516,7 @@ Del objeto: [OBJECTNAME]; propiedad de: [NAME]? </form> </notification> <notification name="ScriptQuestionCaution"> - Un objeto de nombre '[OBJECTNAME]', propiedad de '[NAME]', quiere: + Un objeto de nombre '<nolink>[OBJECTNAME]</nolink>', propiedad de '[NAME]', quiere: [QUESTIONS] Si no confias en este objeto y en su creador, deberías rehusar esta petición. @@ -2496,14 +2529,14 @@ Si no confias en este objeto y en su creador, deberías rehusar esta petición. </form> </notification> <notification name="ScriptDialog"> - '[TITLE]' de [FIRST] [LAST] + '<nolink>[TITLE]</nolink>' de [NAME] [MESSAGE] <form name="form"> <button name="Ignore" text="Ignorar"/> </form> </notification> <notification name="ScriptDialogGroup"> - '[TITLE]' de [GROUPNAME]' + '<nolink>[TITLE]</nolink>' de [GROUPNAME] [MESSAGE] <form name="form"> <button name="Ignore" text="Ignorar"/> @@ -2539,13 +2572,13 @@ Pulsa Aceptar o Rehusar para coger o no la llamada. Pulsa Ignorar para ignorar a </form> </notification> <notification name="AutoUnmuteByIM"> - [FIRST] [LAST] ha dejado automáticamente de estar ignorado al enviarle un mensaje instantáneo. + [NAME] ha dejado automáticamente de estar ignorado al enviarle un mensaje instantáneo. </notification> <notification name="AutoUnmuteByMoney"> - [FIRST] [LAST] ha dejado automáticamente de estar ignorado al darle dinero. + [NAME] ha dejado automáticamente de estar ignorado al darle dinero. </notification> <notification name="AutoUnmuteByInventory"> - [FIRST] [LAST] ha dejado automáticamente de estar ignorado al ofrecerle algo del inventario. + [NAME] ha dejado automáticamente de estar ignorado al ofrecerle inventario. </notification> <notification name="VoiceInviteGroup"> [NAME] ha empezado un chat de voz con el grupo [GROUP]. @@ -2771,6 +2804,37 @@ Si lo haces, todos los residentes que se unan posteriormente a la llamada tambi ¿Deseas silenciar a todos? <usetemplate ignoretext="Confirma que deseas silenciar a todos los participantes en una multiconferencia." name="okcancelignore" notext="Cancelar" yestext="OK"/> </notification> + <notification label="Chat" name="HintChat"> + Para unirte a la conversación, escribe en el campo de chat que aparece a continuación. + </notification> + <notification label="Levantarme" name="HintSit"> + Para levantarte y salir de la posición de sentado, haz clic en el botón Levantarme. + </notification> + <notification label="Explora el mundo" name="HintDestinationGuide"> + La Guía de destinos contiene miles de nuevos lugares por descubrir. Selecciona una ubicación y elige Teleportarme para iniciar la exploración. + </notification> + <notification label="Panel lateral" name="HintSidePanel"> + Accede de manera rápida a tu inventario, así como a tu ropa, los perfiles y el resto de la información disponible en el panel lateral. + </notification> + <notification label="Mover" name="HintMove"> + Si deseas caminar o correr, abre el panel Mover y utiliza las flechas de dirección para navegar. También puedes utilizar las flechas de dirección del teclado. + </notification> + <notification label="Nombre mostrado" name="HintDisplayName"> + Configura y personaliza aquí tu nombre mostrado. Esto se añadirá a tu nombre de usuario personal, que no puedes modificar. Puedes cambiar la manera en que ves los nombres de otras personas en tus preferencias. + </notification> + <notification label="Inventario" name="HintInventory"> + Accede a tu inventario para buscar ítems. Los ítems más recientes se pueden encontrar fácilmente en la pestaña Recientes. + </notification> + <notification label="¡Tienes dólares Linden!" name="HintLindenDollar"> + Éste es tu saldo actual de L$. Haz clic en Comprar L$ para comprar más dólares Linden. + </notification> + <notification name="PopupAttempt"> + Se ha impedido que se abriera una ventana emergente. + <form name="form"> + <ignore name="ignore" text="Permitir todas las ventanas emergentes"/> + <button name="open" text="Abrir ventana emergente"/> + </form> + </notification> <global name="UnsupportedCPU"> - La velocidad de tu CPU no cumple los requerimientos mínimos. </global> diff --git a/indra/newview/skins/default/xui/es/panel_edit_profile.xml b/indra/newview/skins/default/xui/es/panel_edit_profile.xml index 8da8a9771b..56d03dccc2 100644 --- a/indra/newview/skins/default/xui/es/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/es/panel_edit_profile.xml @@ -22,6 +22,14 @@ <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> <panel name="data_panel"> + <text name="display_name_label" value="Nombre mostrado:"/> + <text name="solo_username_label" value="Nombre de usuario:"/> + <button name="set_name" tool_tip="Configurar nombre mostrado"/> + <text name="solo_user_name" value="Hamilton Hitchings"/> + <text name="user_name" value="Hamilton Hitchings"/> + <text name="user_name_small" value="Hamilton Hitchings"/> + <text name="user_label" value="Nombre de usuario:"/> + <text name="user_slid" value="hamilton.linden"/> <panel name="lifes_images_panel"> <icon label="" name="2nd_life_edit_icon" tool_tip="Pulsa para elegir una imagen"/> </panel> @@ -38,7 +46,7 @@ <text name="my_account_link" value="[[URL] Ir a mi Panel de Control]"/> <text name="title_partner_text" value="Mi compañero/a:"/> <panel name="partner_data_panel"> - <name_box initial_value="(obteniendo)" name="partner_text"/> + <text initial_value="(obteniendo)" name="partner_text"/> </panel> <text name="partner_edit_link" value="[[URL] Editar]"/> </panel> diff --git a/indra/newview/skins/default/xui/es/panel_group_land_money.xml b/indra/newview/skins/default/xui/es/panel_group_land_money.xml index f307126b03..3afb0f5665 100644 --- a/indra/newview/skins/default/xui/es/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/es/panel_group_land_money.xml @@ -24,6 +24,7 @@ <scroll_list.columns label="Región" name="location"/> <scroll_list.columns label="Tipo" name="type"/> <scroll_list.columns label="Área" name="area"/> + <scroll_list.columns label="Oculto" name="hidden"/> </scroll_list> <text name="total_contributed_land_label"> Contribución total: diff --git a/indra/newview/skins/default/xui/es/panel_login.xml b/indra/newview/skins/default/xui/es/panel_login.xml index 4b45a6f7b8..49d4881737 100644 --- a/indra/newview/skins/default/xui/es/panel_login.xml +++ b/indra/newview/skins/default/xui/es/panel_login.xml @@ -11,7 +11,7 @@ <text name="username_text"> Nombre de usuario: </text> - <line_editor label="Nombre de usuario" name="username_edit" tool_tip="Nombre de usuario de [SECOND_LIFE]"/> + <line_editor label="bobsmith12 o Steller Sunshine" name="username_edit" tool_tip="El nombre de usuario que elegiste al registrarte, como bobsmith12 o Steller Sunshine"/> <text name="password_text"> Contraseña: </text> @@ -30,7 +30,7 @@ Registrarme </text> <text name="forgot_password_text"> - ¿Olvidaste el nombre o la contraseña? + ¿Olvidaste el nombre de usuario o la contraseña? </text> <text name="login_help"> ¿Necesitas ayuda para conectarte? diff --git a/indra/newview/skins/default/xui/es/panel_place_profile.xml b/indra/newview/skins/default/xui/es/panel_place_profile.xml index 6fe7895d45..524ba2253b 100644 --- a/indra/newview/skins/default/xui/es/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/es/panel_place_profile.xml @@ -76,7 +76,7 @@ <text name="region_rating_label" value="Calificación:"/> <text name="region_rating" value="Adulto"/> <text name="region_owner_label" value="Propietario:"/> - <text name="region_owner" value="moose Van Moose"/> + <text name="region_owner" value="Moose Van Moose: nombre demasiado largo"/> <text name="region_group_label" value="Grupo:"/> <text name="region_group"> The Mighty Moose of mooseville soundvillemoose @@ -89,6 +89,7 @@ <text name="estate_name_label" value="Estado:"/> <text name="estate_rating_label" value="Calificación:"/> <text name="estate_owner_label" value="Propietario:"/> + <text name="estate_owner" value="Comprobación de la longitud del nombre de un propietario con nombre largo"/> <text name="covenant_label" value="Contrato:"/> </panel> </accordion_tab> diff --git a/indra/newview/skins/default/xui/es/panel_preferences_general.xml b/indra/newview/skins/default/xui/es/panel_preferences_general.xml index c609cb74ba..5b8cb77173 100644 --- a/indra/newview/skins/default/xui/es/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/es/panel_preferences_general.xml @@ -44,9 +44,10 @@ <radio_item label="On" name="radio2" value="1"/> <radio_item label="Mostrar brevemente" name="radio3" value="2"/> </radio_group> - <check_box label="Ver yo mi nombre" name="show_my_name_checkbox1"/> - <check_box initial_value="true" label="Etiquetas de los avatares en pequeño" name="small_avatar_names_checkbox"/> - <check_box label="Mostrar las etiquetas de grupo" name="show_all_title_checkbox1"/> + <check_box label="Mi nombre" name="show_my_name_checkbox1"/> + <check_box label="Nombre de usuario" name="show_slids" tool_tip="Mostrar el nombre de usuario, como bobsmith123"/> + <check_box label="Títulos de grupos" name="show_all_title_checkbox1" tool_tip="Mostrar títulos de grupos, como Jefe o Miembro"/> + <check_box label="Realzar amigos" name="show_friends" tool_tip="Realzar las etiquetas de los nombres de tus amigos"/> <text name="effects_color_textbox"> Mis efectos: </text> @@ -61,6 +62,7 @@ <combo_box.item label="30 minutos" name="item3"/> <combo_box.item label="nunca" name="item4"/> </combo_box> + <check_box label="Ver nombres mostrados" name="display_names_check" tool_tip="Comprobar para utilizar nombres mostrados en chat, MI, etiquetas de nombres, etc."/> <text name="text_box3"> Respuesta cuando estoy en modo ocupado: </text> diff --git a/indra/newview/skins/default/xui/es/panel_preferences_setup.xml b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml index 88f5ba42b5..100951a51e 100644 --- a/indra/newview/skins/default/xui/es/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/es/panel_preferences_setup.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="Configurar" name="Input panel"> - <button bottom_delta="-40" label="Otros dispositivos" name="joystick_setup_button"/> <text name="Mouselook:"> Vista subjetiva: </text> @@ -37,10 +36,11 @@ <radio_item label="Usar mi navegador (IE, Firefox, Safari)" name="external" tool_tip="Usa tu navegador por defecto para ayuda, enlaces web, etc. No es aconsejable si estás a pantalla completa." value="1"/> <radio_item label="Usar el navegador incorporado" name="internal" tool_tip="Usa el navegador incorporado para ayuda, enlaces web, etc. Este navegador se abre en una nueva ventana dentro de [APP_NAME]." value=""/> </radio_group> - <check_box label="Activar plugins" name="browser_plugins_enabled"/> - <check_box label="Aceptar las 'cookies'" name="cookies_enabled"/> - <check_box label="Activar Javascript" name="browser_javascript_enabled"/> - <check_box label="Activar web proxy" name="web_proxy_enabled"/> + <check_box initial_value="true" label="Activar plugins" name="browser_plugins_enabled"/> + <check_box initial_value="true" label="Aceptar las 'cookies'" name="cookies_enabled"/> + <check_box initial_value="true" label="Activar Javascript" name="browser_javascript_enabled"/> + <check_box initial_value="falso" label="Permitir ventanas emergentes de navegadores de medios" name="media_popup_enabled"/> + <check_box initial_value="false" label="Activar web proxy" name="web_proxy_enabled"/> <text name="Proxy location"> Localización del proxy: </text> diff --git a/indra/newview/skins/default/xui/es/panel_profile_view.xml b/indra/newview/skins/default/xui/es/panel_profile_view.xml index b556346051..a11fc31607 100644 --- a/indra/newview/skins/default/xui/es/panel_profile_view.xml +++ b/indra/newview/skins/default/xui/es/panel_profile_view.xml @@ -6,8 +6,14 @@ <string name="status_offline"> Desconectado/a </string> - <text_editor name="user_name" value="(Cargando...)"/> + <text name="display_name_label" value="Nombre mostrado:"/> + <text name="solo_username_label" value="Nombre de usuario:"/> <text name="status" value="Conectado/a"/> + <text name="user_name_small" value="Jack, ¿has visto esto? Es un nombre larguísimo."/> + <text name="user_name" value="Jack Linden"/> + <button name="copy_to_clipboard" tool_tip="Copiar al portapapeles"/> + <text name="user_label" value="Nombre de usuario:"/> + <text name="user_slid" value="jack.linden"/> <tab_container name="tabs"> <panel label="PERFIL" name="panel_profile"/> <panel label="DESTACADOS" name="panel_picks"/> diff --git a/indra/newview/skins/default/xui/es/role_actions.xml b/indra/newview/skins/default/xui/es/role_actions.xml index 14df3d67ca..660293b02c 100644 --- a/indra/newview/skins/default/xui/es/role_actions.xml +++ b/indra/newview/skins/default/xui/es/role_actions.xml @@ -39,6 +39,7 @@ <action description="Permitir siempre 'Crear objetos'" longdescription="Quien tenga un rol con esta capacidad puede crear objetos en una parcela perteneciente al grupo aunque eso esté desactivado en Acerca del terreno > pestaña Opciones." name="land allow create" value="25"/> <action description="Permitir siempre 'Crear hitos'" longdescription="Quien tenga un rol con esta capacidad puede crear un hito en una parcela perteneciente al grupo aunque eso esté desactivado en Acerca del terreno > pestaña Opciones." name="land allow landmark" value="26"/> <action description="Permitir 'Fijar mi Base aquí' en el terreno del grupo" longdescription="Los miembros que tengan un rol con esta capacidad pueden usar el menú Mundo > Hitos > Fijar aquí mi Base en una parcela transferida al grupo." name="land allow set home" value="28"/> + <action description="Permitir "Organización de eventos" en un terreno de grupo" longdescription="Los miembros con un rol que tenga esta capacidad pueden seleccionar parcelas propiedad de un grupo como sede de la organización de eventos." name="land allow host event" value="41"/> </action_set> <action_set description="Estas capacidades incluyen poderes para permitir o restringir el acceso a parcelas pertenecientes al grupo, incluyendo el congelar y expulsar a residentes." name="Parcel Access"> <action description="Administrar las listas de acceso a la parcela" longdescription="Administre las listas de acceso a la parcela en Acerca del terreno > pestaña Acceso." name="land manage allowed" value="29"/> @@ -64,10 +65,6 @@ <action description="Enviar aviso" longdescription="Los miembros con un rol que tenga esta capacidad pueden enviar avisos a través de la sección Grupo > Avisos." name="notices send" value="42"/> <action description="Recibir avisos nuevos y ver los anteriores" longdescription="Los miembros con un rol que tenga esta capacidad pueden recibir Avisos y ver los ya enviados en la sección Grupo > Avisos." name="notices receive" value="43"/> </action_set> - <action_set description="Estas habilidades incluyen poderes para permitir a los miembros crear propuestas, votarlas, y ver el historial de votaciones." name="Proposals"> - <action description="Hacer una propuesta" longdescription="Quien tenga un rol con esta capacidad puede crear propuestas para que sean votadas en Información del grupo > pestaña Propuestas." name="proposal start" value="44"/> - <action description="Votar en propuestas" longdescription="Quien tenga un rol con esta capacidad puede votar las propuestas en Información del grupo > pestaña Propuestas." name="proposal vote" value="45"/> - </action_set> <action_set description="Estas capacidades incluyen poderes para permitir o no el aceso a las sesiones de chat del grupo y al chat de voz del mismo." name="Chat"> <action description="Abrir chat de grupo" longdescription="Quien tenga un rol con esta capacidad puede abrir sesiones de chat del grupo, tanto de texto como de voz." name="join group chat" value="16"/> <action description="Abrir chat de voz del grupo" longdescription="Quien tenga un rol con esta capacidad puede abrir sesiones de chat de voz del grupo. NOTA: para acceder al chat de voz debe tenerse la capacidad 'Abrir chat de grupo'." name="join voice chat" value="27"/> diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index 5fa3d54de2..0be827f5f7 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -194,6 +194,9 @@ <string name="TooltipAgentUrl"> Pulsa para ver el perfil del Residente </string> + <string name="TooltipAgentInspect"> + Obtén más información acerca de este residente. + </string> <string name="TooltipAgentMute"> Pulsa para silenciar a este Residente </string> @@ -741,6 +744,12 @@ <string name="Estate / Full Region"> Estado /Región completa </string> + <string name="Estate / Homestead"> + Estado / Homestead + </string> + <string name="Mainland / Homestead"> + Continente / Homestead + </string> <string name="Mainland / Full Region"> Continente / Región completa </string> @@ -3472,7 +3481,7 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE]. Usted es el único usuario en esta sesión. </string> <string name="offline_message"> - [FIRST] [LAST] no está conectado. + [NAME] está desconectado. </string> <string name="invite_message"> Pulse el botón [BUTTON NAME] para aceptar/conectar este chat de voz. @@ -3541,7 +3550,10 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE]. http://secondlife.com/landing/voicemorphing </string> <string name="paid_you_ldollars"> - [NAME] te ha pagado [AMOUNT] L$ + [NAME] te ha pagado [AMOUNT] L$ [REASON]. + </string> + <string name="paid_you_ldollars_no_reason"> + [NAME] te ha pagado [AMOUNT] L$. </string> <string name="you_paid_ldollars"> Has pagado [AMOUNT] L$ a [NAME] por [REASON]. @@ -3555,6 +3567,9 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE]. <string name="you_paid_ldollars_no_name"> Has pagado [AMOUNT] L$ por [REASON]. </string> + <string name="for item"> + para [ITEM] + </string> <string name="for a parcel of land"> para una parcela de terreno </string> @@ -3573,6 +3588,9 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE]. <string name="to upload"> to upload </string> + <string name="to publish a classified ad"> + para publicar un anuncio clasificado + </string> <string name="giving"> Dando [AMOUNT] L$ </string> diff --git a/indra/newview/skins/default/xui/fr/floater_tools.xml b/indra/newview/skins/default/xui/fr/floater_tools.xml index 666aaa8147..8a128c0308 100644 --- a/indra/newview/skins/default/xui/fr/floater_tools.xml +++ b/indra/newview/skins/default/xui/fr/floater_tools.xml @@ -189,7 +189,7 @@ <text name="label click action"> Cliquer pour : </text> - <combo_box name="clickaction" width="178"> + <combo_box name="clickaction"> <combo_box.item label="Toucher (par défaut)" name="Touch/grab(default)"/> <combo_box.item label="S'asseoir sur l'objet" name="Sitonobject"/> <combo_box.item label="Acheter l'objet" name="Buyobject"/> diff --git a/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml b/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml index be24960c6e..d8d0164618 100644 --- a/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml @@ -43,7 +43,7 @@ 全員: </text> <check_box label="コピー" name="everyone_copy"/> - <text name="NextOwnerLabel" left="160"> + <text name="NextOwnerLabel"> 次の所有者: </text> <check_box label="修正" name="next_owner_modify"/> diff --git a/indra/newview/skins/default/xui/nl/floater_tools.xml b/indra/newview/skins/default/xui/nl/floater_tools.xml index 212cac0a5b..b72e4d4681 100644 --- a/indra/newview/skins/default/xui/nl/floater_tools.xml +++ b/indra/newview/skins/default/xui/nl/floater_tools.xml @@ -144,7 +144,7 @@ <text name="label click action"> Wanneer links-geklikt: </text> - <combo_box name="clickaction" width="178"> + <combo_box name="clickaction"> <combo_box.item name="Touch/grab(default)" label="Aanraken/pakken (standaard)" /> <combo_box.item name="Sitonobject" label="Zit op object" |