From 99a9258d5217565d9c4e4753a5697857b6b339b7 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 25 Sep 2024 18:03:57 -0700 Subject: Issue #2687: Honor flag sent by server indicating server side autopilot is engaged. When flag is set allow sever to update local avatar rotation. --- indra/llprimitive/object_flags.h | 12 ++++++------ indra/newview/llviewerobject.cpp | 6 ++++++ 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llprimitive/object_flags.h b/indra/llprimitive/object_flags.h index e2cdba072a..06e216ba49 100644 --- a/indra/llprimitive/object_flags.h +++ b/indra/llprimitive/object_flags.h @@ -57,16 +57,16 @@ const U32 FLAGS_CAMERA_SOURCE = (1U << 22); //const U32 FLAGS_UNUSED_001 = (1U << 23); // was FLAGS_CAST_SHADOWS -//const U32 FLAGS_UNUSED_002 = (1U << 24); -//const U32 FLAGS_UNUSED_003 = (1U << 25); -//const U32 FLAGS_UNUSED_004 = (1U << 26); -//const U32 FLAGS_UNUSED_005 = (1U << 27); +const U32 FLAGS_SERVER_AUTOPILOT = (1U << 24); // Update was for an agent AND that agent is being autopiloted from the server +//const U32 FLAGS_UNUSED_002 = (1U << 25); +//const U32 FLAGS_UNUSED_003 = (1U << 26); +//const U32 FLAGS_UNUSED_004 = (1U << 27); const U32 FLAGS_OBJECT_OWNER_MODIFY = (1U << 28); const U32 FLAGS_TEMPORARY_ON_REZ = (1U << 29); -//const U32 FLAGS_UNUSED_006 = (1U << 30); // was FLAGS_TEMPORARY -//const U32 FLAGS_UNUSED_007 = (1U << 31); // was FLAGS_ZLIB_COMPRESSED +//const U32 FLAGS_UNUSED_005 = (1U << 30); // was FLAGS_TEMPORARY +//const U32 FLAGS_UNUSED_006 = (1U << 31); // was FLAGS_ZLIB_COMPRESSED const U32 FLAGS_LOCAL = FLAGS_ANIM_SOURCE | FLAGS_CAMERA_SOURCE; const U32 FLAGS_WORLD = FLAGS_USE_PHYSICS | FLAGS_PHANTOM | FLAGS_TEMPORARY_ON_REZ; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 86440fca48..b87b17e3cf 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2325,6 +2325,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Set the rotation of the object followed by adjusting for the accumulated angular velocity (llSetTargetOmega) setRotation(new_rot * mAngularVelocityRot); + if ((mFlags & FLAGS_SERVER_AUTOPILOT) && asAvatar() && asAvatar()->isSelf()) + { + gAgent.resetAxes(); + gAgent.rotate(new_rot); + gAgentCamera.resetView(); + } setChanged(ROTATED | SILHOUETTE); } -- cgit v1.3 From 81df0476b5194ca50b7b473e9fb1a33c0831c28a Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Mon, 14 Oct 2024 12:49:43 -0700 Subject: Private Issue #297: Accept new flags in ScriptTeleportRequest message. Flags indicate if the world map should be opened and focused. --- indra/llcommon/indra_constants.h | 2 ++ indra/llui/llfloater.h | 6 ++++-- indra/newview/llfloaterworldmap.cpp | 7 +++++-- indra/newview/llviewermessage.cpp | 18 ++++++++++++++++-- scripts/messages/message_template.msg | 20 ++++++++++++-------- scripts/messages/message_template.msg.sha1 | 2 +- 6 files changed, 40 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index d2de88ff0a..c6bdab007f 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -355,5 +355,7 @@ const U8 CLICK_ACTION_DISABLED = 8; const U8 CLICK_ACTION_IGNORE = 9; // DO NOT CHANGE THE SEQUENCE OF THIS LIST!! +constexpr U32 BEACON_SHOW_MAP = 0x0001; +constexpr U32 BEACON_FOCUS_MAP = 0x0002; #endif diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 9be2240f6f..eae2435117 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -377,6 +377,10 @@ public: void enableResizeCtrls(bool enable, bool width = true, bool height = true); bool isPositioning(LLFloaterEnums::EOpenPositioning p) const { return (p == mPositioning); } + + void setAutoFocus(bool focus) { mAutoFocus = focus; } // whether to automatically take focus when opened + bool getAutoFocus() const { return mAutoFocus; } + protected: void applyControlsAndPosition(LLFloater* other); @@ -401,8 +405,6 @@ protected: void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized const LLRect& getExpandedRect() const { return mExpandedRect; } - void setAutoFocus(bool focus) { mAutoFocus = focus; } // whether to automatically take focus when opened - bool getAutoFocus() const { return mAutoFocus; } LLDragHandle* getDragHandle() const { return mDragHandle; } void destroy(); // Don't call this directly. You probably want to call closeFloater() diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 30ed723db6..a798ba31ee 100755 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -486,8 +486,11 @@ void LLFloaterWorldMap::onOpen(const LLSD& key) const LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); LLInventoryModelBackgroundFetch::instance().start(landmark_folder_id); - mLocationEditor->setFocus( true); - gFocusMgr.triggerFocusFlash(); + if (hasFocus()) + { + mLocationEditor->setFocus( true); + gFocusMgr.triggerFocusFlash(); + } buildAvatarIDList(); buildLandmarkIDLists(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 1d4828fd33..fe6de38dd7 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6610,7 +6610,6 @@ void process_initiate_download(LLMessageSystem* msg, void**) (void**)new std::string(viewer_filename)); } - void process_script_teleport_request(LLMessageSystem* msg, void**) { if (!gSavedSettings.getBOOL("ScriptsCanShowUI")) return; @@ -6624,6 +6623,11 @@ void process_script_teleport_request(LLMessageSystem* msg, void**) msg->getString("Data", "SimName", sim_name); msg->getVector3("Data", "SimPosition", pos); msg->getVector3("Data", "LookAt", look_at); + U32 flags = (BEACON_SHOW_MAP | BEACON_FOCUS_MAP); + if (msg->has("Options")) + { + msg->getU32("Options", "Flags", flags); + } LLFloaterWorldMap* instance = LLFloaterWorldMap::getInstance(); if(instance) @@ -6634,7 +6638,17 @@ void process_script_teleport_request(LLMessageSystem* msg, void**) << LL_ENDL; instance->trackURL(sim_name, (S32)pos.mV[VX], (S32)pos.mV[VY], (S32)pos.mV[VZ]); - LLFloaterReg::showInstance("world_map", "center"); + if (flags & BEACON_SHOW_MAP) + { + bool old_auto_focus = instance->getAutoFocus(); + instance->setAutoFocus(false); + instance->openFloater("center"); + if (flags & BEACON_FOCUS_MAP) + { + instance->setFocus(true); + } + instance->setAutoFocus(old_auto_focus); + } } // remove above two lines and replace with below line diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index 1450c111c2..70c2bdf53a 100755 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -4370,14 +4370,18 @@ version 2.0 // ScriptTeleportRequest // reliable { - ScriptTeleportRequest Low 195 Trusted Unencoded - { - Data Single - { ObjectName Variable 1 } - { SimName Variable 1 } - { SimPosition LLVector3 } - { LookAt LLVector3 } - } + ScriptTeleportRequest Low 195 Trusted Unencoded + { + Data Single + { ObjectName Variable 1 } + { SimName Variable 1 } + { SimPosition LLVector3 } + { LookAt LLVector3 } + } + { + Options Variable + { Flags U32 } + } } diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1 index efa5f3cf48..eb436d0627 100755 --- a/scripts/messages/message_template.msg.sha1 +++ b/scripts/messages/message_template.msg.sha1 @@ -1 +1 @@ -d7915d67467e59287857630bd89bf9529d065199 \ No newline at end of file +b98fc0af5fa88601f5afa4f3c83f08188316e9a8 \ No newline at end of file -- cgit v1.3 From 3dc945c1df2a8961363528df0e383519c9d63d1f Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Mon, 14 Oct 2024 15:45:04 -0700 Subject: Private Issue #297: Code review feedback. --- indra/newview/llviewermessage.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index fe6de38dd7..e52a40ef85 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6641,12 +6641,8 @@ void process_script_teleport_request(LLMessageSystem* msg, void**) if (flags & BEACON_SHOW_MAP) { bool old_auto_focus = instance->getAutoFocus(); - instance->setAutoFocus(false); + instance->setAutoFocus(flags & BEACON_FOCUS_MAP); instance->openFloater("center"); - if (flags & BEACON_FOCUS_MAP) - { - instance->setFocus(true); - } instance->setAutoFocus(old_auto_focus); } } -- cgit v1.3 From 09af45daa3e63bc6a5df064e1cc40e3ec4e18e70 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 8 Nov 2024 16:49:34 -0800 Subject: Server Issue #1493: New notification message for llTransferOwnership. --- indra/newview/skins/default/xui/en/notifications.xml | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index b5f742e5fb..36d6ef8dbf 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10326,6 +10326,14 @@ You are now the owner of object [OBJECT_NAME] + fail +You are now the owner of object [OBJECT_NAME] and it has been placed in your inventory. + + + fail -- cgit v1.3 From bb5e05e98608c42b91fd3aca6f035e43d752ce52 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Wed, 12 Mar 2025 19:33:29 +0200 Subject: #3685 Add two new slapps to support wearing contents of folders - Add and Remove --- indra/newview/llappearancemgr.cpp | 116 +++++++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 28 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4e0c5d7df0..58fb5b71af 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4724,46 +4724,64 @@ void wear_multiple(const uuid_vec_t& ids, bool replace) // SLapp for easy-wearing of a stock (library) avatar // +bool wear_library_category(const LLSD& query_map, bool append) +{ + LLUUID folder_uuid; + + if (query_map.has("folder_name")) + { + std::string outfit_folder_name = query_map["folder_name"]; + folder_uuid = findDescendentCategoryIDByName(gInventory.getLibraryRootFolderID(), outfit_folder_name); + if (folder_uuid.isNull()) + LL_WARNS() << "Couldn't find " << std::quoted(outfit_folder_name) << " in the Library" << LL_ENDL; + } + if (folder_uuid.isNull() && query_map.has("folder_id")) + { + folder_uuid = query_map["folder_id"].asUUID(); + } + + if (folder_uuid.notNull()) + { + if (LLViewerInventoryCategory* cat = gInventory.getCategory(folder_uuid)) + { + if (bool is_library = gInventory.isObjectDescendentOf(folder_uuid, gInventory.getRootFolderID())) + { + LLPointer new_category = new LLInventoryCategory(folder_uuid, LLUUID::null, LLFolderType::FT_CLOTHING, "Quick Appearance"); + LLAppearanceMgr::getInstance()->wearInventoryCategory(new_category, true, append); + } + else + { + LLAppearanceMgr::getInstance()->wearInventoryCategory(cat, true, append); + } + return true; + } + else + { + LL_WARNS() << "Couldn't find folder id" << folder_uuid << " in Inventory" << LL_ENDL; + } + } + + return false; +} + class LLWearFolderHandler : public LLCommandHandler { public: // not allowed from outside the app - LLWearFolderHandler() : LLCommandHandler("wear_folder", UNTRUSTED_BLOCK) { } + LLWearFolderHandler() : LLCommandHandler("wear_folder", UNTRUSTED_BLOCK) {} bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { - LLSD::UUID folder_uuid; - - if (folder_uuid.isNull() && query_map.has("folder_name")) - { - std::string outfit_folder_name = query_map["folder_name"]; - folder_uuid = findDescendentCategoryIDByName( - gInventory.getLibraryRootFolderID(), - outfit_folder_name); - } - if (folder_uuid.isNull() && query_map.has("folder_id")) + if (wear_library_category(query_map, false)) { - folder_uuid = query_map["folder_id"].asUUID(); - } + // Assume this is coming from the predefined avatars web floater + LLUIUsage::instance().logCommand("Avatar.WearPredefinedAppearance"); - if (folder_uuid.notNull()) - { - LLPointer category = new LLInventoryCategory(folder_uuid, - LLUUID::null, - LLFolderType::FT_CLOTHING, - "Quick Appearance"); - if ( gInventory.getCategory( folder_uuid ) != NULL ) - { - // Assume this is coming from the predefined avatars web floater - LLUIUsage::instance().logCommand("Avatar.WearPredefinedAppearance"); - LLAppearanceMgr::getInstance()->wearInventoryCategory(category, true, false); - - // *TODOw: This may not be necessary if initial outfit is chosen already -- josh - gAgent.setOutfitChosen(true); - } + // *TODOw: This may not be necessary if initial outfit is chosen already -- josh + gAgent.setOutfitChosen(true); } // release avatar picker keyboard focus @@ -4773,4 +4791,46 @@ public: } }; +class LLAddFolderHandler : public LLCommandHandler +{ +public: + // not allowed from outside the app + LLAddFolderHandler() : LLCommandHandler("add_folder", UNTRUSTED_BLOCK) {} + + bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) + { + wear_library_category(query_map, true); + + return true; + } +}; + +class LLRemoveFolderHandler : public LLCommandHandler +{ +public: + LLRemoveFolderHandler() : LLCommandHandler("remove_folder", UNTRUSTED_BLOCK) {} + + bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) + { + if (query_map.has("folder_id")) + { + LLUUID folder_id = query_map["folder_id"].asUUID(); + if (folder_id.notNull()) + { + if (LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id)) + { + LLAppearanceMgr::instance().takeOffOutfit(cat->getLinkedUUID()); + } + else + { + LL_WARNS() << "Couldn't find folder id" << folder_id << " in Inventory" << LL_ENDL; + } + } + } + return true; + } +}; + LLWearFolderHandler gWearFolderHandler; +LLAddFolderHandler gAddFolderHandler; +LLRemoveFolderHandler gRemoveFolderHandler; -- cgit v1.3 From 506b0d02dd19372d4270bd3d73f2d6dde8a528ae Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 13 Mar 2025 14:36:28 +0200 Subject: #2711 Remove ALM text from About SL for JP and CN --- indra/newview/skins/default/xui/ja/strings.xml | 1 - indra/newview/skins/default/xui/zh/strings.xml | 1 - 2 files changed, 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index fa6c329fe7..71f7c1a034 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -66,7 +66,6 @@ SLURL:<nolink>[SLURL]</nolink> 帯域幅:[NET_BANDWITH]kbit/秒 LOD係数:[LOD_FACTOR] 描画の質:[RENDER_QUALITY] -高度な光源モデル:[GPU_SHADERS] テクスチャメモリ:[TEXTURE_MEMORY]㎆ diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml index bdb16c9bf1..d053d2b30d 100644 --- a/indra/newview/skins/default/xui/zh/strings.xml +++ b/indra/newview/skins/default/xui/zh/strings.xml @@ -69,7 +69,6 @@ 頻寬:[NET_BANDWITH]千位元/秒 細節層次率:[LOD_FACTOR] 呈像品質:[RENDER_QUALITY] -進階照明模型:[GPU_SHADERS] 材質記憶體:[TEXTURE_MEMORY]MB -- cgit v1.3 From d6fb10de86957a2ff41f3e5262fb0314c8bdf1db Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 13 Mar 2025 16:39:12 +0200 Subject: #3685 clean up --- indra/newview/llappearancemgr.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 58fb5b71af..101aca3823 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4722,9 +4722,7 @@ void wear_multiple(const uuid_vec_t& ids, bool replace) LLAppearanceMgr::instance().wearItemsOnAvatar(ids, true, replace, cb); } -// SLapp for easy-wearing of a stock (library) avatar -// -bool wear_library_category(const LLSD& query_map, bool append) +bool wear_category(const LLSD& query_map, bool append) { LLUUID folder_uuid; @@ -4775,7 +4773,7 @@ public: const std::string& grid, LLMediaCtrl* web) { - if (wear_library_category(query_map, false)) + if (wear_category(query_map, false)) { // Assume this is coming from the predefined avatars web floater LLUIUsage::instance().logCommand("Avatar.WearPredefinedAppearance"); @@ -4799,7 +4797,7 @@ public: bool handle(const LLSD& tokens, const LLSD& query_map, const std::string& grid, LLMediaCtrl* web) { - wear_library_category(query_map, true); + wear_category(query_map, true); return true; } -- cgit v1.3 From 14dc1a11b812a4f3817b0eedf09d72669e0cacfc Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 14 Mar 2025 00:12:47 +0200 Subject: #3741 fix for mac crash on exit --- indra/newview/llpanelprofileclassifieds.cpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelprofileclassifieds.cpp b/indra/newview/llpanelprofileclassifieds.cpp index 3920dd82c8..62829b0745 100644 --- a/indra/newview/llpanelprofileclassifieds.cpp +++ b/indra/newview/llpanelprofileclassifieds.cpp @@ -78,13 +78,6 @@ class LLClassifiedHandler : public LLCommandHandler, public LLAvatarPropertiesOb public: // throttle calls from untrusted browsers LLClassifiedHandler() : LLCommandHandler("classified", UNTRUSTED_THROTTLE) {} - virtual ~LLClassifiedHandler() - { - if (LLAvatarPropertiesProcessor::instanceExists()) - { - LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); - } - } std::set mClassifiedIds; std::string mRequestVerb; -- cgit v1.3 From 17fbbef67b2ee853b6ea424fcc617089d848d4a7 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 14 Mar 2025 20:40:12 +0200 Subject: #3745 fix for showing system notification on login --- indra/newview/llcallingcard.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 549c7ed0e4..829b6380cd 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -42,6 +42,7 @@ #include "llinventorymodel.h" #include "llnotifications.h" #include "llslurl.h" +#include "llstartup.h" #include "llimview.h" #include "lltrans.h" #include "llviewercontrol.h" @@ -743,7 +744,11 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online) mModifyMask |= LLFriendObserver::ONLINE; instance().notifyObservers(); - gInventory.notifyObservers(); + // Skip if we had received the friends list before the inventory callbacks were properly initialized + if (LLStartUp::getStartupState() > STATE_INVENTORY_CALLBACKS) + { + gInventory.notifyObservers(); + } } } -- cgit v1.3 From 895a6739d3d02e11750e9ada72b730d02998d4c0 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 14 Mar 2025 20:46:13 +0200 Subject: #3750 Crash at isSaveTextureEnabled --- indra/newview/llpanelmaininventory.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 5bd2a53e7c..d964fa9170 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -1582,7 +1582,7 @@ void LLPanelMainInventory::initInventoryViews() void LLPanelMainInventory::toggleViewMode() { - if(mSingleFolderMode && isCombinationViewMode()) + if(mSingleFolderMode && isCombinationViewMode() && mCombinationGalleryPanel->getRootFolder().notNull()) { mCombinationInventoryPanel->getRootFolder()->setForceArrange(false); } @@ -2047,7 +2047,8 @@ bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata) } else { - LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); + LLFolderView* root_folder = getActivePanel() ? getActivePanel()->getRootFolder() : nullptr; + LLFolderViewItem* current_item = root_folder ? root_folder->getCurSelectedItem() : nullptr; if (current_item) { inv_item = dynamic_cast(static_cast(current_item->getViewModelItem())->getInventoryObject()); @@ -2443,8 +2444,6 @@ void LLPanelMainInventory::updateCombinationVisibility() mCombinationGalleryPanel->handleModifiedFilter(); } - getActivePanel()->getRootFolder(); - if (mReshapeInvLayout && show_inv_pane && (mCombinationGalleryPanel->hasVisibleItems() || mCombinationGalleryPanel->areViewsInitialized()) @@ -2501,8 +2500,12 @@ void LLPanelMainInventory::updateCombinationVisibility() && mCombinationInventoryPanel->areViewsInitialized()) { mCombinationInventoryPanel->setSelectionByID(mCombInvUUIDNeedsRename, true); - mCombinationInventoryPanel->getRootFolder()->scrollToShowSelection(); - mCombinationInventoryPanel->getRootFolder()->setNeedsAutoRename(true); + LLFolderView* root = mCombinationInventoryPanel->getRootFolder(); + if (root) + { + root->scrollToShowSelection(); + root->setNeedsAutoRename(true); + } mCombInvUUIDNeedsRename.setNull(); } } -- cgit v1.3 From 4e5dce794923736ff7c32d55f1e75361e89a9d31 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 18 Mar 2025 17:04:08 +0200 Subject: #3736 LLExperienceCache shutdown crash --- indra/llmessage/llexperiencecache.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index b5d0c93376..83a070df32 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -94,6 +94,8 @@ LLExperienceCache::LLExperienceCache() LLExperienceCache::~LLExperienceCache() { + // can exit without cleanup() + sShutdown = true; } void LLExperienceCache::initSingleton() -- cgit v1.3 From d3d0728bac31099785fea1bf87f11b7c29d2425d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 18 Mar 2025 19:29:30 +0200 Subject: #3547 Further reduce ParcelInfoRequest calls --- indra/newview/llpanelprofilepicks.cpp | 4 ++-- indra/newview/llremoteparcelrequest.cpp | 19 ++++++++++++++++++- indra/newview/llremoteparcelrequest.h | 2 ++ 3 files changed, 22 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp index 09b8011ce4..a87ef4f0f9 100644 --- a/indra/newview/llpanelprofilepicks.cpp +++ b/indra/newview/llpanelprofilepicks.cpp @@ -55,7 +55,7 @@ static LLPanelInjector t_panel_profile_picks("panel_profile_picks"); static LLPanelInjector t_panel_profile_pick("panel_profile_pick"); -constexpr F32 REQUEST_TIMOUT = 60; +constexpr F32 REQUEST_TIMEOUT = 60; constexpr F32 LOCATION_CACHE_TIMOUT = 900; class LLPickHandler : public LLCommandHandler @@ -842,7 +842,7 @@ std::string LLPanelProfilePick::getLocationNotice() void LLPanelProfilePick::sendParcelInfoRequest() { - if (mParcelId != mRequestedId || mLastRequestTimer.getElapsedTimeF32() > REQUEST_TIMOUT) + if (mParcelId != mRequestedId || mLastRequestTimer.getElapsedTimeF32() > REQUEST_TIMEOUT) { if (mRequestedId.notNull()) { diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp index 7b80e8c27f..d0aa1af2f3 100644 --- a/indra/newview/llremoteparcelrequest.cpp +++ b/indra/newview/llremoteparcelrequest.cpp @@ -102,7 +102,15 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v msg->getS32 ("Data", "SalePrice", parcel_data.sale_price); msg->getS32 ("Data", "AuctionID", parcel_data.auction_id); - LLRemoteParcelInfoProcessor::observer_multimap_t & observers = LLRemoteParcelInfoProcessor::getInstance()->mObservers; + LLRemoteParcelInfoProcessor* inst = LLRemoteParcelInfoProcessor::getInstance(); + + requests_map_t::const_iterator found = inst->mPendingParcelRequests.find(parcel_data.parcel_id); + if (found != inst->mPendingParcelRequests.end()) + { + inst->mPendingParcelRequests.erase(found); + } + + LLRemoteParcelInfoProcessor::observer_multimap_t & observers = inst->mObservers; typedef std::vector deadlist_t; deadlist_t dead_iters; @@ -151,6 +159,15 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v void LLRemoteParcelInfoProcessor::sendParcelInfoRequest(const LLUUID& parcel_id) { + constexpr F32 DUPPLICATE_TIMEOUT = 0.5f; + requests_map_t::const_iterator found = mPendingParcelRequests.find(parcel_id); + if (found != mPendingParcelRequests.end() && found->second.getElapsedTimeF32() < DUPPLICATE_TIMEOUT) + { + // recently requested + return; + } + mPendingParcelRequests[parcel_id].reset(); + LLMessageSystem *msg = gMessageSystem; msg->newMessage("ParcelInfoRequest"); diff --git a/indra/newview/llremoteparcelrequest.h b/indra/newview/llremoteparcelrequest.h index 1420b4032e..7059e14bec 100644 --- a/indra/newview/llremoteparcelrequest.h +++ b/indra/newview/llremoteparcelrequest.h @@ -91,6 +91,8 @@ public: private: typedef std::multimap > observer_multimap_t; observer_multimap_t mObservers; + typedef std::map requests_map_t; + requests_map_t mPendingParcelRequests; // Dupplicate request avoidance void regionParcelInfoCoro(std::string url, LLUUID regionId, LLVector3 posRegion, LLVector3d posGlobal, LLHandle observerHandle); }; -- cgit v1.3 From c99e3167ed8549bc13d7df03b1e12dc15b0a080f Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 13 Mar 2025 23:55:38 +0200 Subject: #3644 Adjust throttle based of how busy buffer is --- indra/llmessage/llpacketring.cpp | 6 ++++++ indra/llmessage/llpacketring.h | 1 + indra/llmessage/message.h | 4 +--- indra/newview/llappviewer.cpp | 1 + indra/newview/llviewerthrottle.cpp | 14 +++++++++++--- indra/newview/llviewerthrottle.h | 3 +++ 6 files changed, 23 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index da3c502e9d..eb6650c6c5 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -344,6 +344,12 @@ bool LLPacketRing::expandRing() return true; } +F32 LLPacketRing::getBufferLoadRate() const +{ + // goes up to MAX_BUFFER_RING_SIZE + return (F32)mNumBufferedPackets / (F32)DEFAULT_BUFFER_RING_SIZE; +} + void LLPacketRing::dumpPacketRingStats() { mNumDroppedPacketsTotal += mNumDroppedPackets; diff --git a/indra/llmessage/llpacketring.h b/indra/llmessage/llpacketring.h index 237efc12e0..572dcbd271 100644 --- a/indra/llmessage/llpacketring.h +++ b/indra/llmessage/llpacketring.h @@ -64,6 +64,7 @@ public: S32 getNumBufferedBytes() const { return mNumBufferedBytes; } S32 getNumDroppedPackets() const { return mNumDroppedPacketsTotal + mNumDroppedPackets; } + F32 getBufferLoadRate() const; // from 0 to 4 (0 - empty, 1 - default size is full) void dumpPacketRingStats(); protected: // returns 'true' if we should intentionally drop a packet diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index 1844d5e7cd..30945cac51 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -538,7 +538,6 @@ public: //void buildMessage(); - S32 zeroCode(U8 **data, S32 *data_size); S32 zeroCodeExpand(U8 **data, S32 *data_size); S32 zeroCodeAdjustCurrentSendTotal(); @@ -755,6 +754,7 @@ public: S32 getReceiveBytes() const; S32 getUnackedListSize() const { return mUnackedListSize; } + F32 getBufferLoadRate() const { return mPacketRing.getBufferLoadRate(); } //const char* getCurrentSMessageName() const { return mCurrentSMessageName; } //const char* getCurrentSBlockName() const { return mCurrentSBlockName; } @@ -842,12 +842,10 @@ private: LLUUID mSessionID; void addTemplate(LLMessageTemplate *templatep); - bool decodeTemplate( const U8* buffer, S32 buffer_size, LLMessageTemplate** msg_template ); void logMsgFromInvalidCircuit( const LLHost& sender, bool recv_reliable ); void logTrustedMsgFromUntrustedCircuit( const LLHost& sender ); void logValidMsg(LLCircuitData *cdp, const LLHost& sender, bool recv_reliable, bool recv_resent, bool recv_acks ); - void logRanOffEndOfPacket( const LLHost& sender ); class LLMessageCountInfo { diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a05c2376a0..4cf651de33 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5443,6 +5443,7 @@ void LLAppViewer::idleNetwork() // Retransmit unacknowledged packets. gXferManager->retransmitUnackedPackets(); gAssetStorage->checkForTimeouts(); + gViewerThrottle.setBufferLoadRate(gMessageSystem->getBufferLoadRate()); gViewerThrottle.updateDynamicThrottle(); // Check that the circuit between the viewer and the agent's current diff --git a/indra/newview/llviewerthrottle.cpp b/indra/newview/llviewerthrottle.cpp index b0a00c29a4..8d935e4243 100644 --- a/indra/newview/llviewerthrottle.cpp +++ b/indra/newview/llviewerthrottle.cpp @@ -48,6 +48,8 @@ const F32 MIN_FRACTIONAL = 0.2f; const F32 MIN_BANDWIDTH = 50.f; const F32 MAX_BANDWIDTH = 6000.f; const F32 STEP_FRACTIONAL = 0.1f; +const F32 HIGH_BUFFER_LOAD_TRESHOLD = 1.f; +const F32 LOW_BUFFER_LOAD_TRESHOLD = 0.8f; const LLUnit TIGHTEN_THROTTLE_THRESHOLD(3.0f); // packet loss % per s const LLUnit EASE_THROTTLE_THRESHOLD(0.5f); // packet loss % per s const F32 DYNAMIC_UPDATE_DURATION = 5.0f; // seconds @@ -146,7 +148,7 @@ LLViewerThrottleGroup LLViewerThrottleGroup::operator-(const LLViewerThrottleGro void LLViewerThrottleGroup::sendToSim() const { - LL_INFOS() << "Sending throttle settings, total BW " << mThrottleTotal << LL_ENDL; + LL_DEBUGS("Throttle") << "Sending throttle settings, total BW " << mThrottleTotal << LL_ENDL; LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_AgentThrottle); @@ -305,7 +307,10 @@ void LLViewerThrottle::updateDynamicThrottle() mUpdateTimer.reset(); LLUnit mean_packets_lost = LLViewerStats::instance().getRecording().getMean(LLStatViewer::PACKETS_LOST_PERCENT); - if (mean_packets_lost > TIGHTEN_THROTTLE_THRESHOLD) + if ( + mean_packets_lost > TIGHTEN_THROTTLE_THRESHOLD // already losing packets + || mBufferLoadRate >= HIGH_BUFFER_LOAD_TRESHOLD // let viewer sort through the backlog before it starts dropping packets + ) { if (mThrottleFrac <= MIN_FRACTIONAL || mCurrentBandwidth / 1024.0f <= MIN_BANDWIDTH) { @@ -318,7 +323,8 @@ void LLViewerThrottle::updateDynamicThrottle() mCurrent.sendToSim(); LL_INFOS() << "Tightening network throttle to " << mCurrentBandwidth << LL_ENDL; } - else if (mean_packets_lost <= EASE_THROTTLE_THRESHOLD) + else if (mean_packets_lost <= EASE_THROTTLE_THRESHOLD + && mBufferLoadRate < LOW_BUFFER_LOAD_TRESHOLD) { if (mThrottleFrac >= MAX_FRACTIONAL || mCurrentBandwidth / 1024.0f >= MAX_BANDWIDTH) { @@ -331,4 +337,6 @@ void LLViewerThrottle::updateDynamicThrottle() mCurrent.sendToSim(); LL_INFOS() << "Easing network throttle to " << mCurrentBandwidth << LL_ENDL; } + + mBufferLoadRate = 0; } diff --git a/indra/newview/llviewerthrottle.h b/indra/newview/llviewerthrottle.h index 28a24d04fc..9973c88549 100644 --- a/indra/newview/llviewerthrottle.h +++ b/indra/newview/llviewerthrottle.h @@ -70,12 +70,15 @@ public: void updateDynamicThrottle(); void resetDynamicThrottle(); + void setBufferLoadRate(F32 rate) { mBufferLoadRate = llmax(mBufferLoadRate, rate); } + LLViewerThrottleGroup getThrottleGroup(const F32 bandwidth_kbps); static const std::string sNames[TC_EOF]; protected: F32 mMaxBandwidth; F32 mCurrentBandwidth; + F32 mBufferLoadRate = 0; LLViewerThrottleGroup mCurrent; -- cgit v1.3 From 53c3176121f585eed4f2efff02c3694217604221 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 18 Mar 2025 23:40:02 +0200 Subject: #3661 Clamp water blur multiplier --- indra/newview/skins/default/xui/en/panel_settings_water.xml | 2 +- indra/newview/skins/default/xui/ja/panel_settings_water.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_settings_water.xml b/indra/newview/skins/default/xui/en/panel_settings_water.xml index 5e65b0e8a2..e062f1710b 100644 --- a/indra/newview/skins/default/xui/en/panel_settings_water.xml +++ b/indra/newview/skins/default/xui/en/panel_settings_water.xml @@ -378,7 +378,7 @@ initial_value="0" layout="topleft" left_delta="5" - min_val="-0.5" + min_val="0" max_val="0.5" name="water_blur_multip" top_pad="5" diff --git a/indra/newview/skins/default/xui/ja/panel_settings_water.xml b/indra/newview/skins/default/xui/ja/panel_settings_water.xml index ead1ca9b2f..2510523897 100644 --- a/indra/newview/skins/default/xui/ja/panel_settings_water.xml +++ b/indra/newview/skins/default/xui/ja/panel_settings_water.xml @@ -63,7 +63,7 @@ ブラー乗数 - + -- cgit v1.3 From f04992676d5ab17cc34b310e06ce7d838c5232b9 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 19 Mar 2025 00:50:18 +0200 Subject: #3685 add test floater for new slapps --- indra/newview/CMakeLists.txt | 2 + indra/newview/app_settings/settings.xml | 11 ++ indra/newview/llfloaterslapptest.cpp | 51 +++++++++ indra/newview/llfloaterslapptest.h | 42 +++++++ indra/newview/llinventorybridge.cpp | 15 +++ indra/newview/llviewerfloaterreg.cpp | 5 +- .../skins/default/xui/en/floater_test_slapp.xml | 123 +++++++++++++++++++++ .../skins/default/xui/en/menu_inventory.xml | 8 ++ indra/newview/skins/default/xui/en/menu_viewer.xml | 7 ++ 9 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 indra/newview/llfloaterslapptest.cpp create mode 100644 indra/newview/llfloaterslapptest.h create mode 100644 indra/newview/skins/default/xui/en/floater_test_slapp.xml (limited to 'indra') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3210b76649..ed29911a43 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -291,6 +291,7 @@ set(viewer_SOURCE_FILES llfloatersettingscolor.cpp llfloatersettingsdebug.cpp llfloatersidepanelcontainer.cpp + llfloaterslapptest.cpp llfloatersnapshot.cpp llfloatersounddevices.cpp llfloaterspellchecksettings.cpp @@ -962,6 +963,7 @@ set(viewer_HEADER_FILES llfloatersettingscolor.h llfloatersettingsdebug.h llfloatersidepanelcontainer.h + llfloaterslapptest.h llfloatersnapshot.h llfloatersounddevices.h llfloaterspellchecksettings.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0c83355a81..4ce7e0f729 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3676,6 +3676,17 @@ Value 5000 + InventoryExposeFolderID + + Comment + Allows copying folder id from context menu + Persist + 0 + Type + Boolean + Value + 0 + MarketplaceListingsSortOrder Comment diff --git a/indra/newview/llfloaterslapptest.cpp b/indra/newview/llfloaterslapptest.cpp new file mode 100644 index 0000000000..0075379529 --- /dev/null +++ b/indra/newview/llfloaterslapptest.cpp @@ -0,0 +1,51 @@ +/** + * @file llfloaterslapptest.cpp + * + * $LicenseInfo:firstyear=2025&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2025, 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 "llfloaterslapptest.h" +#include "lluictrlfactory.h" + +#include "lllineeditor.h" +#include "lltextbox.h" + +LLFloaterSLappTest::LLFloaterSLappTest(const LLSD& key) + : LLFloater("floater_test_slapp") +{ +} + +LLFloaterSLappTest::~LLFloaterSLappTest() +{} + +bool LLFloaterSLappTest::postBuild() +{ + getChild("remove_folder_id")->setKeystrokeCallback([this](LLLineEditor* editor, void*) + { + std::string slapp(getString("remove_folder_slapp")); + getChild("remove_folder_txt")->setValue(slapp + editor->getValue().asString()); + }, NULL); + + return true; +} diff --git a/indra/newview/llfloaterslapptest.h b/indra/newview/llfloaterslapptest.h new file mode 100644 index 0000000000..ec727cb629 --- /dev/null +++ b/indra/newview/llfloaterslapptest.h @@ -0,0 +1,42 @@ +/** + * @file llfloaterslapptest.h + * + * $LicenseInfo:firstyear=2025&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2025, 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$ + */ + +#ifndef LL_LLFLOATERSLAPPTEST_H +#define LL_LLFLOATERSLAPPTEST_H + +#include "llfloater.h" + +class LLFloaterSLappTest: + public LLFloater +{ + friend class LLFloaterReg; + virtual bool postBuild() override; + +private: + LLFloaterSLappTest(const LLSD& key); + ~LLFloaterSLappTest(); +}; + +#endif diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 479b7c19ac..ce91f9a1f3 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3599,6 +3599,13 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("move_to_marketplace_listings" != action), (("copy_or_move_to_marketplace_listings" == action))); } + else if ("copy_folder_uuid" == action) + { + LLInventoryCategory* cat = gInventory.getCategory(mUUID); + if (!cat) return; + gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(mUUID.asString())); + return; + } } void LLFolderBridge::gatherMessage(std::string& message, S32 depth, LLError::ELevel log_level) @@ -4466,6 +4473,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items { disabled_items.push_back(std::string("Delete System Folder")); } + else + { + static LLCachedControl show_copy_id(gSavedSettings, "InventoryExposeFolderID", false); + if (show_copy_id()) + { + items.push_back(std::string("Copy UUID")); + } + } if (isAgentInventory() && !isMarketplaceListingsFolder()) { diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index ef68609182..95c2a77ba8 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -137,6 +137,7 @@ #include "llfloatersettingscolor.h" #include "llfloatersettingsdebug.h" #include "llfloatersidepanelcontainer.h" +#include "llfloaterslapptest.h" #include "llfloatersnapshot.h" #include "llfloatersounddevices.h" #include "llfloaterspellchecksettings.h" @@ -278,7 +279,8 @@ public: "upload_model", "upload_script", "upload_sound", - "bulk_upload" + "bulk_upload", + "slapp_test" }; return std::find(blacklist_untrusted.begin(), blacklist_untrusted.end(), fl_name) == blacklist_untrusted.end(); } @@ -499,6 +501,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("slapp_test", "floater_test_slapp.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/skins/default/xui/en/floater_test_slapp.xml b/indra/newview/skins/default/xui/en/floater_test_slapp.xml new file mode 100644 index 0000000000..dd2720816a --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_test_slapp.xml @@ -0,0 +1,123 @@ + + + + secondlife://app/remove_folder/?folder_id= + + + Trusted source + + + /wear_folder + + + secondlife://app/wear_folder/?folder_name=Daisy + + + /add_folder + + + secondlife://app/add_folder/?folder_name=Cardboard%20Boxbot + + + secondlife://app/add_folder/?folder_id=59219db2-c260-87d3-213d-bb3bc298a3d8 + + + /remove_folder + + + Folder ID: + + + + secondlife://app/remove_folder/?folder_id= + + diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index d8aac71dd5..e57e3b0750 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -370,6 +370,14 @@ function="Inventory.DoToSelected" parameter="copy_uuid" /> + + + + + + -- cgit v1.3 From e92e79038fdb00318e65452f12ba000646dd22a2 Mon Sep 17 00:00:00 2001 From: nerodevo <100370411+nerodevo@users.noreply.github.com> Date: Mon, 22 Apr 2024 15:21:38 -0500 Subject: Remove invalid text color parameter from panel_login_first.xml Follow-up to previous commit 4a07fd3. This will resolve the warning showing up when loading the viewer for the first time. --- indra/newview/skins/default/xui/en/panel_login_first.xml | 1 - 1 file changed, 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_login_first.xml b/indra/newview/skins/default/xui/en/panel_login_first.xml index c906e2f96c..d6ac71db94 100644 --- a/indra/newview/skins/default/xui/en/panel_login_first.xml +++ b/indra/newview/skins/default/xui/en/panel_login_first.xml @@ -179,7 +179,6 @@ control_name="RememberPassword" follows="left|top" font="SansSerifLarge" - text_color="EmphasisColor" height="24" left="262" bottom_delta="0" -- cgit v1.3 From d8f0faf128a12ff6c7406df966521471c219eeac Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 27 Mar 2024 00:28:04 +0200 Subject: viewer-private#131 landmark panel closes after a rename if destination was changed --- indra/newview/llfloatercreatelandmark.cpp | 4 ++-- indra/newview/llfloatercreatelandmark.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp index 2ce8a7a212..864a1f0767 100644 --- a/indra/newview/llfloatercreatelandmark.cpp +++ b/indra/newview/llfloatercreatelandmark.cpp @@ -389,6 +389,7 @@ void LLFloaterCreateLandmark::setItem(const uuid_set_t& items) { mItem = item; mAssetID = mItem->getAssetUUID(); + mParentID = mItem->getParentUUID(); setVisibleAndFrontmost(true); break; } @@ -418,8 +419,7 @@ void LLFloaterCreateLandmark::updateItem(const uuid_set_t& items, U32 mask) closeFloater(); } - LLUUID folder_id = mFolderCombo->getValue().asUUID(); - if (folder_id != mItem->getParentUUID()) + if (mParentID != mItem->getParentUUID()) { // user moved landmark in inventory, // assume that we are done all other changes should already be commited diff --git a/indra/newview/llfloatercreatelandmark.h b/indra/newview/llfloatercreatelandmark.h index fa6d001b8e..f97ade2c1b 100644 --- a/indra/newview/llfloatercreatelandmark.h +++ b/indra/newview/llfloatercreatelandmark.h @@ -69,6 +69,7 @@ private: LLTextEditor* mNotesEditor; LLUUID mLandmarksID; LLUUID mAssetID; + LLUUID mParentID; LLLandmarksInventoryObserver* mInventoryObserver; LLPointer mItem; -- cgit v1.3 From a5f1cca07589a53c659c9bea296ff6cae57b36df Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Tue, 18 Jun 2024 11:46:59 +0200 Subject: #1644 On-water property lines persist at water level --- indra/newview/llviewerparceloverlay.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index 2e9b5de72b..19066217b1 100755 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -581,7 +581,7 @@ void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F3 outside_y += dy * (dy - LINE_WIDTH); // Middle part, full width - const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS ); + const S32 GRID_STEP = (S32)PARCEL_GRID_STEP_METERS; for (S32 i = 1; i < GRID_STEP; i++) { inside_z = land.resolveHeightRegion( inside_x, inside_y ); @@ -666,7 +666,9 @@ void LLViewerParcelOverlay::renderPropertyLines() return; LLSurface& land = mRegion->getLand(); - F32 water_z = land.getWaterHeight() + 0.01f; + + bool render_water = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER); + F32 water_z = render_water ? land.getWaterHeight() + 0.01f : 0; LLGLSUIDefault gls_ui; // called from pipeline gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -- cgit v1.3 From b6bf32e00e25de773b6403b716c655f64b6092c9 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 19 Mar 2025 17:57:50 +0200 Subject: #3488 Prelock mutexes Main thread has priority, it shouldn't be relocking on each loadMeshLOD --- indra/newview/llmeshrepository.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index e1fa84b4d8..a8c6f69425 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -4573,6 +4573,8 @@ void LLMeshRepository::notifyLoadedMeshes() std::partial_sort(mPendingRequests.begin(), mPendingRequests.begin() + push_count, mPendingRequests.end(), PendingRequestBase::CompareScoreGreater()); } + LLMutexTrylock lock3(mThread->mHeaderMutex); + LLMutexTrylock lock4(mThread->mPendingMutex); while (!mPendingRequests.empty() && push_count > 0) { std::unique_ptr& req_p = mPendingRequests.front(); -- cgit v1.3 From ed6f939df42fa414e7ab55329c58e9aa2848b34a Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 19 Mar 2025 19:29:32 +0200 Subject: #3771 Fix unresolved HOSTIP parameter --- indra/newview/skins/default/xui/da/floater_about.xml | 2 +- indra/newview/skins/default/xui/de/strings.xml | 2 +- indra/newview/skins/default/xui/es/strings.xml | 2 +- indra/newview/skins/default/xui/fr/strings.xml | 2 +- indra/newview/skins/default/xui/it/strings.xml | 2 +- indra/newview/skins/default/xui/ja/strings.xml | 2 +- indra/newview/skins/default/xui/pt/strings.xml | 2 +- indra/newview/skins/default/xui/ru/strings.xml | 2 +- indra/newview/skins/default/xui/tr/strings.xml | 2 +- indra/newview/skins/default/xui/zh/strings.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml index 604eb7c58f..4ea34975e1 100644 --- a/indra/newview/skins/default/xui/da/floater_about.xml +++ b/indra/newview/skins/default/xui/da/floater_about.xml @@ -5,7 +5,7 @@ [[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] - Du er ved [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] i regionen [REGION] lokaliseret ved <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Du er ved [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] i regionen [REGION] lokaliseret ved <nolink>[HOSTNAME]</nolink> [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index 486d604e9f..3f5fccf57f 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -12,7 +12,7 @@ Grafikinitialisierung fehlgeschlagen. Bitte aktualisieren Sie Ihren Grafiktreiber. [CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([ADDRESS_SIZE]Bit) [[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] Build-Konfiguration [BUILD_CONFIG] - Sie befinden sich an [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] auf <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Sie befinden sich an [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] auf <nolink>[HOSTNAME]</nolink> SLURL: <nolink>[SLURL]</nolink> (globale Koordinaten [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) [SERVER_VERSION] diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index 9fcfc2daa5..ff1200e2b3 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -10,7 +10,7 @@ [CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([ADDRESS_SIZE]bit) [[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] Configuración de constitución [BUILD_CONFIG] - Estás en la posición [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1], de [REGION], alojada en <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Estás en la posición [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1], de [REGION], alojada en <nolink>[HOSTNAME]</nolink> SLURL: <nolink>[SLURL]</nolink> (coordenadas globales [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) [SERVER_VERSION] diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 55f6209fe1..5307c8d561 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -13,7 +13,7 @@ [CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([ADDRESS_SIZE]bit) [[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] Configuration de la construction [BUILD_CONFIG] - Vous êtes à [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] dans [REGION], se trouvant à <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Vous êtes à [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] dans [REGION], se trouvant à <nolink>[HOSTNAME]</nolink> SLURL : <nolink>[SLURL]</nolink> (coordonnées globales [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) [SERVER_VERSION] diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index f77ab1062a..bb22ff788e 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -12,7 +12,7 @@ [CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([ADDRESS_SIZE]bit) [[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] Configurazione struttura [BUILD_CONFIG] - Tu sei a [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] che si trova a <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Tu sei a [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] che si trova a <nolink>[HOSTNAME]</nolink> SLURL: <nolink>[SLURL]</nolink> (coordinate globali [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) [SERVER_VERSION] diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index 71f7c1a034..df19f3678f 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -39,7 +39,7 @@ あなたは、現在[REGION]の[POSITION_LOCAL_0,number,1],[POSITION_LOCAL_1,number,1],[POSITION_LOCAL_2,number,1]にいます。 -位置は、<nolink>[HOSTNAME]</nolink>です。([HOSTIP]) +位置は、<nolink>[HOSTNAME]</nolink>です。 SLURL:<nolink>[SLURL]</nolink> (グローバル座標は、[POSITION_0,number,1],[POSITION_1,number,1],[POSITION_2,number,1]です。) [SERVER_VERSION] diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 4ce1e6d2ec..509b3d72a0 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -10,7 +10,7 @@ [CHANNEL] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2].[VIEWER_VERSION_3] ([ADDRESS_SIZE]bit) [[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]] Configuração do corpo [BUILD_CONFIG] - Você está em [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] em [REGION] localizado em <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Você está em [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] em [REGION] localizado em <nolink>[HOSTNAME]</nolink> SLURL: <nolink>[SLURL]</nolink> (coordenadas globais [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) [SERVER_VERSION] diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml index 0079309ba2..48eb7118aa 100644 --- a/indra/newview/skins/default/xui/ru/strings.xml +++ b/indra/newview/skins/default/xui/ru/strings.xml @@ -42,7 +42,7 @@ Конфигурация построения [BUILD_CONFIG] - Вы в точке [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] в регионе «[REGION]», расположенном на <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Вы в точке [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] в регионе «[REGION]», расположенном на <nolink>[HOSTNAME]</nolink> SLURL: <nolink>[SLURL]</nolink> (глобальные координаты [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) [SERVER_VERSION] diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml index fa2fd3a802..92e5160e97 100644 --- a/indra/newview/skins/default/xui/tr/strings.xml +++ b/indra/newview/skins/default/xui/tr/strings.xml @@ -42,7 +42,7 @@ Yapı Konfigürasyonu [BUILD_CONFIG] - <nolink>[HOSTNAME]</nolink> ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] konumundasınız + <nolink>[HOSTNAME]</nolink> üzerinde bulunan [REGION] içerisinde [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] konumundasınız SLURL: <nolink>[SLURL]</nolink> (küresel koordinatlar [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) [SERVER_VERSION] diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml index d053d2b30d..8fae007429 100644 --- a/indra/newview/skins/default/xui/zh/strings.xml +++ b/indra/newview/skins/default/xui/zh/strings.xml @@ -42,7 +42,7 @@ 建製設置 [BUILD_CONFIG] - 你的方位是 [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1],地區名:[REGION],主機:<nolink>[HOSTNAME]</nolink> ([HOSTIP]) + 你的方位是 [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1],地區名:[REGION],主機:<nolink>[HOSTNAME]</nolink> 第二人生URL:<nolink>[SLURL]</nolink> (全域坐標:[POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) [SERVER_VERSION] -- cgit v1.3 From 28638b31af625e59914e215af1cf7b0ad40b3fb6 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 19 Mar 2025 19:59:00 +0200 Subject: #3762 Remove incorrect resolution specification Looks like it was added by a mistake and does not match real value --- indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml | 2 +- indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml | 2 +- indra/newview/skins/default/xui/es/panel_snapshot_inventory.xml | 2 +- indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml | 2 +- indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml | 2 +- indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml | 2 +- indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml | 2 +- indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml | 2 +- indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml | 2 +- indra/newview/skins/default/xui/zh/panel_snapshot_inventory.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml index 602424821f..09447cbbaf 100644 --- a/indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/de/panel_snapshot_inventory.xml @@ -7,7 +7,7 @@ - + diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml index f8040b9a65..68878baa0d 100644 --- a/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_inventory.xml @@ -60,7 +60,7 @@ name="Large(512x512)" value="[i512,i512]" /> - + diff --git a/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml index 3cf64583d2..a560ff8d5e 100644 --- a/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/fr/panel_snapshot_inventory.xml @@ -7,7 +7,7 @@ L'enregistrement d'une image dans l'inventaire coûte [UPLOAD_COST] L$. Pour enregistrer votre image sous forme de texture, sélectionnez un format carré. - + diff --git a/indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml index 75b5d64660..21b65e8e69 100644 --- a/indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/it/panel_snapshot_inventory.xml @@ -7,7 +7,7 @@ Salvare un'immagine nell'inventario costa L$[UPLOAD_COST]. Per salvare l'immagine come texture, selezionare uno dei formati quadrati. - + diff --git a/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml index c55c11e928..30542378cc 100644 --- a/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/ja/panel_snapshot_inventory.xml @@ -6,7 +6,7 @@ - + diff --git a/indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml index f3357026d5..28a5142baa 100644 --- a/indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/pt/panel_snapshot_inventory.xml @@ -7,7 +7,7 @@ Salvar uma imagem em seu inventário custa L$[UPLOAD_COST]. Para salvar sua imagem como uma textura, selecione um dos formatos quadrados. - + diff --git a/indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml index f07e12e0ed..adc612dfd8 100644 --- a/indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/ru/panel_snapshot_inventory.xml @@ -7,7 +7,7 @@ Сохранение изображения в инвентаре стоит L$[UPLOAD_COST]. Чтобы сохранить его как текстуру, выберите один из квадратных форматов. - + diff --git a/indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml index be5940c4b9..160cba8700 100644 --- a/indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/tr/panel_snapshot_inventory.xml @@ -7,7 +7,7 @@ Bir görüntüyü envanterinize kaydetmenin maliyeti L$[UPLOAD_COST] olur. Görüntünüzü bir doku olarak kaydetmek için kare formatlardan birini seçin. - + diff --git a/indra/newview/skins/default/xui/zh/panel_snapshot_inventory.xml b/indra/newview/skins/default/xui/zh/panel_snapshot_inventory.xml index 094bf019b4..9c45c54a5e 100644 --- a/indra/newview/skins/default/xui/zh/panel_snapshot_inventory.xml +++ b/indra/newview/skins/default/xui/zh/panel_snapshot_inventory.xml @@ -7,7 +7,7 @@ 將圖像儲存到收納區的費用為 L$[UPLOAD_COST]。 若要將圖像存為材質,請選擇一個正方格式。 - + -- cgit v1.3 From 5608c3998df99c9ea075c58f0f45fb23617ec2ed Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 8 Oct 2024 22:10:50 +0300 Subject: viewer#2270 The "More" button does not close the "Choose emoji" floater --- indra/llui/llemojihelper.cpp | 11 +++++++++ indra/llui/llemojihelper.h | 7 ++++++ indra/llui/lltexteditor.cpp | 8 +++++++ indra/llui/lltexteditor.h | 1 + indra/newview/llfloaterimsessiontab.cpp | 42 +++++++++++++++++++++++++++++++-- indra/newview/llfloaterimsessiontab.h | 5 ++++ 6 files changed, 72 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/llemojihelper.cpp b/indra/llui/llemojihelper.cpp index b9441a9c91..b2c59ce775 100644 --- a/indra/llui/llemojihelper.cpp +++ b/indra/llui/llemojihelper.cpp @@ -99,6 +99,7 @@ void LLEmojiHelper::showHelper(LLUICtrl* hostctrl_p, S32 local_x, S32 local_y, c LLFloater* pHelperFloater = LLFloaterReg::getInstance(DEFAULT_EMOJI_HELPER_FLOATER); mHelperHandle = pHelperFloater->getHandle(); mHelperCommitConn = pHelperFloater->setCommitCallback(std::bind([&](const LLSD& sdValue) { onCommitEmoji(utf8str_to_wstring(sdValue.asStringRef())[0]); }, std::placeholders::_2)); + mHelperCloseConn = pHelperFloater->setCloseCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCloseHelper(ctrl, param); }); } setHostCtrl(hostctrl_p); mEmojiCommitCb = cb; @@ -148,6 +149,16 @@ void LLEmojiHelper::onCommitEmoji(llwchar emoji) } } +void LLEmojiHelper::onCloseHelper(LLUICtrl* ctrl, const LLSD& param) +{ + mCloseSignal(ctrl, param); +} + +boost::signals2::connection LLEmojiHelper::setCloseCallback(const commit_signal_t::slot_type& cb) +{ + return mCloseSignal.connect(cb); +} + void LLEmojiHelper::setHostCtrl(LLUICtrl* hostctrl_p) { const LLUICtrl* pCurHostCtrl = mHostHandle.get(); diff --git a/indra/llui/llemojihelper.h b/indra/llui/llemojihelper.h index 2834b06061..26840eef94 100644 --- a/indra/llui/llemojihelper.h +++ b/indra/llui/llemojihelper.h @@ -51,16 +51,23 @@ public: // Eventing bool handleKey(const LLUICtrl* ctrl_p, KEY key, MASK mask); void onCommitEmoji(llwchar emoji); + void onCloseHelper(LLUICtrl* ctrl, const LLSD& param); + + typedef boost::signals2::signal commit_signal_t; + boost::signals2::connection setCloseCallback(const commit_signal_t::slot_type& cb); protected: LLUICtrl* getHostCtrl() const { return mHostHandle.get(); } void setHostCtrl(LLUICtrl* hostctrl_p); private: + commit_signal_t mCloseSignal; + LLHandle mHostHandle; LLHandle mHelperHandle; boost::signals2::connection mHostCtrlFocusLostConn; boost::signals2::connection mHelperCommitConn; + boost::signals2::connection mHelperCloseConn; std::function mEmojiCommitCb; bool mIsHideDisabled; }; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3537c764b9..6c59ed0fd9 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1211,6 +1211,14 @@ void LLTextEditor::showEmojiHelper() LLEmojiHelper::instance().showHelper(this, cursorRect.mLeft, cursorRect.mTop, LLStringUtil::null, cb); } +void LLTextEditor::hideEmojiHelper() +{ + if (mShowEmojiHelper) + { + LLEmojiHelper::instance().hideHelper(this); + } +} + void LLTextEditor::tryToShowEmojiHelper() { if (mReadOnly || !mShowEmojiHelper) diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index e9e7070414..b2b14b01e2 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -207,6 +207,7 @@ public: bool getShowContextMenu() const { return mShowContextMenu; } void showEmojiHelper(); + void hideEmojiHelper(); void setShowEmojiHelper(bool show); bool getShowEmojiHelper() const { return mShowEmojiHelper; } diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 655674357f..50e765c236 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -39,6 +39,7 @@ #include "llchicletbar.h" #include "lldraghandle.h" #include "llemojidictionary.h" +#include "llemojihelper.h" #include "llfloaterreg.h" #include "llfloateremojipicker.h" #include "llfloaterimsession.h" @@ -300,6 +301,8 @@ bool LLFloaterIMSessionTab::postBuild() mEmojiPickerShowBtn = getChild("emoji_picker_show_btn"); mEmojiPickerShowBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerShowBtnClicked(); }); + mEmojiPickerShowBtn->setMouseDownCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerShowBtnDown(); }); + mEmojiCloseConn = LLEmojiHelper::instance().setCloseCallback([this](LLUICtrl*, const LLSD&) { onEmojiPickerClosed(); }); mGearBtn = getChild("gear_btn"); mAddBtn = getChild("add_btn"); @@ -532,8 +535,43 @@ void LLFloaterIMSessionTab::onEmojiRecentPanelToggleBtnClicked() void LLFloaterIMSessionTab::onEmojiPickerShowBtnClicked() { - mInputEditor->setFocus(true); - mInputEditor->showEmojiHelper(); + if (!mEmojiPickerShowBtn->getToggleState()) + { + mInputEditor->hideEmojiHelper(); + mInputEditor->setFocus(true); + mInputEditor->showEmojiHelper(); + mEmojiPickerShowBtn->setToggleState(true); // in case hideEmojiHelper closed a visible instance + } + else + { + mInputEditor->hideEmojiHelper(); + mEmojiPickerShowBtn->setToggleState(false); + } +} + +void LLFloaterIMSessionTab::onEmojiPickerShowBtnDown() +{ + if (mEmojiHelperLastCallbackFrame == LLFrameTimer::getFrameCount()) + { + // Helper gets closed by focus lost event on Down before before onEmojiPickerShowBtnDown + // triggers. + // If this condition is true, user pressed button and it was 'toggled' during press, + // restore 'toggled' state so that button will not reopen helper. + mEmojiPickerShowBtn->setToggleState(true); + } +} + +void LLFloaterIMSessionTab::onEmojiPickerClosed() +{ + if (mEmojiPickerShowBtn->getToggleState()) + { + mEmojiPickerShowBtn->setToggleState(false); + // Helper gets closed by focus lost event on Down before onEmojiPickerShowBtnDown + // triggers. If mEmojiHelperLastCallbackFrame is set and matches Down, means close + // was triggered by user's press. + // A bit hacky, but I can't think of a better way to handle this without rewriting helper. + mEmojiHelperLastCallbackFrame = LLFrameTimer::getFrameCount(); + } } void LLFloaterIMSessionTab::initEmojiRecentPanel() diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index 367d988f26..6d04d622e1 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -235,6 +235,8 @@ private: void onEmojiRecentPanelToggleBtnClicked(); void onEmojiPickerShowBtnClicked(); + void onEmojiPickerShowBtnDown(); + void onEmojiPickerClosed(); void initEmojiRecentPanel(); void onEmojiRecentPanelFocusReceived(); void onEmojiRecentPanelFocusLost(); @@ -249,6 +251,9 @@ private: S32 mInputEditorPad; S32 mChatLayoutPanelHeight; S32 mFloaterHeight; + + boost::signals2::connection mEmojiCloseConn; + U32 mEmojiHelperLastCallbackFrame = { 0 }; }; -- cgit v1.3 From bf0767b0d781202064c58ff7c9f44dfeec6959ac Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 29 Oct 2024 00:54:13 +0200 Subject: viewer#2894 Make PBR scale like Blinn Phong does --- indra/newview/llselectmgr.cpp | 27 +++++++++++++++++++++++++++ indra/newview/llselectmgr.h | 2 ++ 2 files changed, 29 insertions(+) (limited to 'indra') diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index b307de787c..b2f30dd966 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -3138,6 +3138,8 @@ void LLSelectMgr::adjustTexturesByScale(bool send_to_sim, bool stretch) F32 scale_x = 1; F32 scale_y = 1; + F32 offset_x = 0; + F32 offset_y = 0; for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) { @@ -3154,6 +3156,21 @@ void LLSelectMgr::adjustTexturesByScale(bool send_to_sim, bool stretch) scale_y = scale_ratio.mV[t_axis] * object_scale.mV[t_axis]; } material->mTextureTransform[i].mScale.set(scale_x, scale_y); + + LLVector2 scales = selectNode->mGLTFScales[te_num][i]; + LLVector2 offsets = selectNode->mGLTFOffsets[te_num][i]; + F64 int_part = 0; + offset_x = (F32)modf((offsets[VX] + (scales[VX] - scale_x)) / 2, &int_part); + if (offset_x < 0) + { + offset_x++; + } + offset_y = (F32)modf((offsets[VY] + (scales[VY] - scale_y)) / 2, &int_part); + if (offset_y < 0) + { + offset_y++; + } + material->mTextureTransform[i].mOffset.set(offset_x, offset_y); } const LLGLTFMaterial* base_material = tep->getGLTFMaterial(); @@ -6904,6 +6921,8 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query) { mTextureScaleRatios.clear(); mGLTFScaleRatios.clear(); + mGLTFScales.clear(); + mGLTFOffsets.clear(); if (mObject.notNull()) { @@ -6944,6 +6963,8 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query) F32 scale_x = 1; F32 scale_y = 1; std::vector material_v_vec; + std::vector material_scales_vec; + std::vector material_offset_vec; for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i) { if (material) @@ -6951,12 +6972,16 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query) LLGLTFMaterial::TextureTransform& transform = material->mTextureTransform[i]; scale_x = transform.mScale[VX]; scale_y = transform.mScale[VY]; + material_scales_vec.push_back(transform.mScale); + material_offset_vec.push_back(transform.mOffset); } else { // Not having an override doesn't mean that there is no material scale_x = 1; scale_y = 1; + material_scales_vec.emplace_back(scale_x, scale_y); + material_offset_vec.emplace_back(0.f, 0.f); } if (tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR) @@ -6972,6 +6997,8 @@ void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query) material_v_vec.push_back(material_v); } mGLTFScaleRatios.push_back(material_v_vec); + mGLTFScales.push_back(material_scales_vec); + mGLTFOffsets.push_back(material_offset_vec); } } } diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index b70ec3dbea..e4613bb3e7 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -242,6 +242,8 @@ public: gltf_materials_vec_t mSavedGLTFOverrideMaterials; std::vector mTextureScaleRatios; std::vector< std::vector > mGLTFScaleRatios; + std::vector< std::vector > mGLTFScales; + std::vector< std::vector > mGLTFOffsets; std::vector mSilhouetteVertices; // array of vertices to render silhouette of object std::vector mSilhouetteNormals; // array of normals to render silhouette of object bool mSilhouetteExists; // need to generate silhouette? -- cgit v1.3 From dee3257ffd9735f0cdaec643743b9dd8cd1920b3 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 20 Mar 2025 15:15:42 +0200 Subject: #1964 fix for reflection probe doesn't update position when the linkset is moved by the script --- indra/newview/llviewerobject.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'indra') diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 030dfeaa6f..3d88cc5f39 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4820,6 +4820,18 @@ void LLViewerObject::setPositionParent(const LLVector3 &pos_parent, bool damped) else { setPositionRegion(pos_parent, damped); + + // #1964 mark reflection probe in the linkset to update position after moving via script + for (LLViewerObject* child : mChildList) + { + if (child && child->isReflectionProbe()) + { + if (LLDrawable* drawablep = child->mDrawable) + { + gPipeline.markMoved(drawablep); + } + } + } } } -- cgit v1.3 From c695ae285fc14f1cce50a1cf1757b3a6e38308b8 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 20 Mar 2025 21:10:06 +0200 Subject: #3779 reset texture repeats when unchecking the Hide Water option --- indra/newview/llpanelface.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index f491cccaf8..c4f118fed8 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -3077,6 +3077,8 @@ void LLPanelFace::onCommitHideWater() { // reset texture to default plywood LLSelectMgr::getInstance()->selectionSetImage(DEFAULT_OBJECT_TEXTURE); + // reset texture repeats, that might be altered by invisiprim script from wiki + LLSelectMgr::getInstance()->selectionTexScaleAutofit(2.f); } } -- cgit v1.3 From bb914ab5e368aa6265aeb057990074f6f275adbd Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Fri, 21 Mar 2025 00:16:14 +0200 Subject: #1644 Correct render type for on-water property lines --- indra/newview/llviewerparceloverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index 19066217b1..da03d3b015 100755 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -667,7 +667,7 @@ void LLViewerParcelOverlay::renderPropertyLines() LLSurface& land = mRegion->getLand(); - bool render_water = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER); + bool render_water = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER); F32 water_z = render_water ? land.getWaterHeight() + 0.01f : 0; LLGLSUIDefault gls_ui; // called from pipeline -- cgit v1.3 From d2dd881a5c840b5132396d6e8353b38b79d69e23 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 20 Mar 2025 19:37:25 +0200 Subject: #3778 #3654 Split text and background selection colors --- indra/llui/llbutton.cpp | 2 +- indra/llui/llmenugl.cpp | 2 +- indra/llui/llscrolllistctrl.cpp | 2 +- indra/llui/llsearchablecontrol.h | 10 ++++++++-- indra/llui/lltextbase.cpp | 2 +- indra/newview/skins/default/colors.xml | 5 ++++- 6 files changed, 16 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 1bce31edb1..d2534b3939 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -837,7 +837,7 @@ void LLButton::draw() // Highlight if needed if( ll::ui::SearchableControl::getHighlighted() ) - label_color = ll::ui::SearchableControl::getHighlightColor(); + label_color = ll::ui::SearchableControl::getHighlightFontColor(); // overlay with keyboard focus border if (hasFocus()) diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 69ffa9a94f..c11b42a348 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -508,7 +508,7 @@ void LLMenuItemGL::draw( void ) // Highlight if needed if( ll::ui::SearchableControl::getHighlighted() ) - color = ll::ui::SearchableControl::getHighlightColor(); + color = ll::ui::SearchableControl::getHighlightFontColor(); // Draw the text on top. if (mBriefItem) diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 943aff1ca1..245339b107 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -3394,7 +3394,7 @@ bool LLScrollListCtrl::highlightMatchingItems(const std::string& filter_str) bool res = false; - setHighlightedColor(LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red4)); + setHighlightedColor(LLUIColorTable::instance().getColor("SearchableControlHighlightBgColor", LLColor4::red4)); std::string filter_str_lc(filter_str); LLStringUtil::toLower(filter_str_lc); diff --git a/indra/llui/llsearchablecontrol.h b/indra/llui/llsearchablecontrol.h index 7f1421dd19..bae85fe9a5 100644 --- a/indra/llui/llsearchablecontrol.h +++ b/indra/llui/llsearchablecontrol.h @@ -43,9 +43,15 @@ namespace ll virtual ~SearchableControl() { } - const LLColor4& getHighlightColor( ) const + const LLColor4& getHighlightBgColor( ) const { - static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red4); + static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightBgColor", LLColor4::red4); + return highlight_color.get(); + } + + const LLColor4& getHighlightFontColor() const + { + static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightFontColor", LLColor4::red4); return highlight_color.get(); } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index fae22fd248..41e7094163 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1378,7 +1378,7 @@ void LLTextBase::draw() // Draw highlighted if needed if( ll::ui::SearchableControl::getHighlighted() ) { - const LLColor4& bg_color = ll::ui::SearchableControl::getHighlightColor(); + const LLColor4& bg_color = ll::ui::SearchableControl::getHighlightBgColor(); LLRect bg_rect = mVisibleTextRect; if( mScroller ) bg_rect.intersectWith( text_rect ); diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index e17321e698..f0af4acf20 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -759,7 +759,10 @@ name="SelectedOutfitTextColor" reference="EmphasisColor" /> + Date: Wed, 12 Mar 2025 15:59:48 +0200 Subject: #3364 Fix a case of excessive texture updates when bias fluctuates a bit. Make bias' effect a bit more gradual. --- indra/newview/lldrawpooltree.cpp | 5 +++-- indra/newview/llviewertexture.cpp | 15 ++++++++++++--- indra/newview/llviewertexturelist.cpp | 3 ++- 3 files changed, 17 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 6efd503574..26ef190fbb 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -108,8 +108,9 @@ void LLDrawPoolTree::beginShadowPass(S32 pass) { LL_PROFILE_ZONE_SCOPED; - glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"), - gSavedSettings.getF32("RenderDeferredTreeShadowBias")); + static LLCachedControl shadow_offset(gSavedSettings, "RenderDeferredTreeShadowOffset"); + static LLCachedControl shadow_bias(gSavedSettings, "RenderDeferredTreeShadowBias"); + glPolygonOffset(shadow_offset(), shadow_bias()); LLEnvironment& environment = LLEnvironment::instance(); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index a0723db479..0782192858 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -519,7 +519,6 @@ void LLViewerTexture::updateClass() bool is_sys_low = isSystemMemoryLow(); bool is_low = is_sys_low || over_pct > 0.f; - F32 discard_bias = sDesiredDiscardBias; static bool was_low = false; static bool was_sys_low = false; @@ -571,6 +570,7 @@ void LLViewerTexture::updateClass() // set to max discard bias if the window has been backgrounded for a while static F32 last_desired_discard_bias = 1.f; + static F32 last_texture_update_count_bias = 1.f; static bool was_backgrounded = false; static LLFrameTimer backgrounded_timer; static LLCachedControl minimized_discard_time(gSavedSettings, "TextureDiscardMinimizedTime", 1.f); @@ -606,12 +606,21 @@ void LLViewerTexture::updateClass() } sDesiredDiscardBias = llclamp(sDesiredDiscardBias, 1.f, 4.f); - if (discard_bias != sDesiredDiscardBias) + if (last_texture_update_count_bias < sDesiredDiscardBias) { - // bias changed, reset texture update counter to + // bias increased, reset texture update counter to // let updates happen at an increased rate. + last_texture_update_count_bias = sDesiredDiscardBias; sBiasTexturesUpdated = 0; } + else if (last_texture_update_count_bias > sDesiredDiscardBias + 0.1f) + { + // bias decreased, 0.1f is there to filter out small fluctuations + // and not reset sBiasTexturesUpdated too often. + // Bias jumps to 1.5 at low memory, so getting stuck at 1.1 is not + // a problem. + last_texture_update_count_bias = sDesiredDiscardBias; + } LLViewerTexture::sFreezeImageUpdates = false; } diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index ae723b4068..db530a3943 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -958,7 +958,8 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag vsize /= min_scale; // apply bias to offscreen faces all the time, but only to onscreen faces when bias is large - if (!face->mInFrustum || LLViewerTexture::sDesiredDiscardBias > 2.f) + // use mImportanceToCamera to make bias switch a bit more gradual + if (!face->mInFrustum || LLViewerTexture::sDesiredDiscardBias > 1.9f + face->mImportanceToCamera / 2.f) { vsize /= bias; } -- cgit v1.3 From 32c7d3064f04899547ee4dea48969c6ceb8554e9 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Fri, 21 Mar 2025 09:33:23 -0400 Subject: Dynamic Probe Allocation (#3787) * #3788 Support dynamic probe allocation. * #3738 Mitigate probe flashing * #3735 Mitigate realtime probes flashing --- .../class1/windlight/atmosphericsFuncs.glsl | 1 + indra/newview/featuretable.txt | 14 +--- indra/newview/featuretable_mac.txt | 10 --- indra/newview/llreflectionmap.cpp | 3 + indra/newview/llreflectionmapmanager.cpp | 86 ++++++++++++++++------ indra/newview/llreflectionmapmanager.h | 11 ++- indra/newview/lltextureview.cpp | 4 +- indra/newview/llviewertexture.cpp | 7 +- .../en/floater_preferences_graphics_advanced.xml | 17 ----- 9 files changed, 87 insertions(+), 66 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl index 205d4bff6d..5089b9e31e 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl @@ -154,6 +154,7 @@ void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, ou if (classic_mode < 1) { amblit = srgb_to_linear(amblit); + amblit = vec3(dot(amblit, vec3(0.2126, 0.7152, 0.0722))); sunlit = srgb_to_linear(sunlit); } diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 883963d558..443a7ae914 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -86,7 +86,6 @@ RenderTonemapType 1 1 RenderTonemapMix 1 1 RenderDisableVintageMode 1 1 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 256 // // Low Graphics Settings @@ -129,7 +128,6 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 512 -RenderReflectionProbeCount 1 1 // // Medium Low Graphics Settings @@ -172,7 +170,6 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 1024 -RenderReflectionProbeCount 1 16 // // Medium Graphics Settings (standard) @@ -214,7 +211,6 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 32 // // Medium High Graphics Settings @@ -245,7 +241,7 @@ RenderFSAASamples 1 1 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 -RenderReflectionProbeLevel 1 2 +RenderReflectionProbeLevel 1 1 RenderMirrors 1 0 RenderHeroProbeResolution 1 512 RenderHeroProbeDistance 1 6 @@ -256,7 +252,6 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 64 // // High Graphics Settings (SSAO + sun shadows) @@ -287,7 +282,7 @@ RenderFSAASamples 1 2 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 1 RenderScreenSpaceReflections 1 0 -RenderReflectionProbeLevel 1 3 +RenderReflectionProbeLevel 1 2 RenderMirrors 1 0 RenderHeroProbeResolution 1 512 RenderHeroProbeDistance 1 8 @@ -298,7 +293,6 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 128 // // High Ultra Graphics Settings (deferred + SSAO + all shadows) @@ -340,7 +334,6 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 256 // // Ultra graphics (REALLY PURTY!) @@ -382,7 +375,6 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 256 // // Class Unknown Hardware (unknown) @@ -416,7 +408,6 @@ RenderReflectionProbeDetail 0 -1 RenderMirrors 0 0 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 0 0 list Intel RenderAnisotropic 1 0 @@ -438,7 +429,6 @@ RenderMirrors 0 0 RenderGLMultiThreadedTextures 0 0 RenderGLMultiThreadedMedia 0 0 RenderDisableVintageMode 1 0 -RenderReflectionProbeCount 0 0 list TexUnit16orLess RenderTerrainPBRDetail 1 -1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 103d24a26d..dc9473b042 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -86,7 +86,6 @@ RenderTonemapMix 1 1 RenderDisableVintageMode 1 1 RenderDownScaleMethod 1 0 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 256 // // Low Graphics Settings @@ -129,7 +128,6 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 512 -RenderReflectionProbeCount 1 1 // // Medium Low Graphics Settings @@ -172,7 +170,6 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 1024 -RenderReflectionProbeCount 1 16 // // Medium Graphics Settings (standard) @@ -214,7 +211,6 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 32 // // Medium High Graphics Settings @@ -256,7 +252,6 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 64 // // High Graphics Settings (SSAO + sun shadows) @@ -298,7 +293,6 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 128 // // High Ultra Graphics Settings (SSAO + all shadows) @@ -340,7 +334,6 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 256 // // Ultra graphics (REALLY PURTY!) @@ -382,7 +375,6 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 1 256 // // Class Unknown Hardware (unknown) @@ -415,7 +407,6 @@ RenderShadowDetail 0 0 RenderMirrors 0 0 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 2048 -RenderReflectionProbeCount 0 0 list TexUnit8orLess RenderDeferredSSAO 0 0 @@ -456,7 +447,6 @@ RenderReflectionProbeDetail 0 0 RenderReflectionsEnabled 0 0 RenderMirrors 0 0 RenderDisableVintageMode 1 0 -RenderReflectionProbeCount 0 0 list VaryingVectors16orLess RenderTerrainPBRPlanarSampleCount 1 1 diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index f3adb52d5e..910509928d 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -52,6 +52,9 @@ LLReflectionMap::~LLReflectionMap() void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 near_clip, bool useClipPlane, LLPlane clipPlane) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY; + if (!mCubeArray.notNull()) + return; + mLastUpdateTime = gFrameTimeSeconds; llassert(mCubeArray.notNull()); llassert(mCubeIndex != -1); diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 48b73531ea..34c6034e9e 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -144,13 +144,14 @@ static void touch_default_probe(LLReflectionMap* probe) LLReflectionMapManager::LLReflectionMapManager() { + mDynamicProbeCount = LL_MAX_REFLECTION_PROBE_COUNT; initCubeFree(); } void LLReflectionMapManager::initCubeFree() { // start at 1 because index 0 is reserved for mDefaultProbe - for (int i = 1; i < LL_MAX_REFLECTION_PROBE_COUNT; ++i) + for (U32 i = 1; i < mDynamicProbeCount; ++i) { mCubeFree.push_back(i); } @@ -221,15 +222,50 @@ void LLReflectionMapManager::update() resume(); } - static LLCachedControl probe_count(gSavedSettings, "RenderReflectionProbeCount", 256U); - bool countReset = mReflectionProbeCount != probe_count; + static LLCachedControl sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); + static LLCachedControl sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); - if (countReset) + // Once every 20 frames, update the dynamic probe count. + if (gFrameCount % 20) { - mResetFade = -0.5f; + U32 probe_count_temp = mDynamicProbeCount; + if (sLevel == 0) + { + mDynamicProbeCount = 1; + } + else if (sLevel == 1) + { + mDynamicProbeCount = (U32)mProbes.size(); + + } + else if (sLevel == 2) + { + mDynamicProbeCount = llmax((U32)mProbes.size(), 128); + } + else + { + mDynamicProbeCount = 256; + } + + // Round mDynamicProbeCount to the nearest increment of 32 + mDynamicProbeCount = ((mDynamicProbeCount + 16) / 32) * 32; + mDynamicProbeCount = llclamp(mDynamicProbeCount, 1, LL_MAX_REFLECTION_PROBE_COUNT); + + if (mDynamicProbeCount < probe_count_temp * 1.1 && mDynamicProbeCount > probe_count_temp * 0.9) + mDynamicProbeCount = probe_count_temp; + else + mGlobalFadeTarget = 0.f; } - initReflectionMaps(); + if (mGlobalFadeTarget < mResetFade) + mResetFade = llmax(mGlobalFadeTarget, mResetFade - (F32)gFrameIntervalSeconds * 2); + else + mResetFade = llmin(mGlobalFadeTarget, mResetFade + (F32)gFrameIntervalSeconds * 2); + + if (mResetFade == mGlobalFadeTarget) + { + initReflectionMaps(); + } static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); @@ -286,9 +322,6 @@ void LLReflectionMapManager::update() bool did_update = false; - static LLCachedControl sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); - static LLCachedControl sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); - bool realtime = sDetail >= (S32)LLReflectionMapManager::DetailLevel::REALTIME; LLReflectionMap* closestDynamic = nullptr; @@ -343,12 +376,7 @@ void LLReflectionMapManager::update() } } - if (countReset) - { - mResetFade = -0.5f; - } - - mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds), 1.f); + mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f); for (unsigned int i = 0; i < mProbes.size(); ++i) { @@ -520,6 +548,16 @@ LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group) return probe; } +U32 LLReflectionMapManager::probeCount() +{ + return mDynamicProbeCount; +} + +U32 LLReflectionMapManager::probeMemory() +{ + return (mDynamicProbeCount * 6 * (mProbeResolution * mProbeResolution) * 4) / 1024 / 1024 + (mDynamicProbeCount * 6 * (LL_IRRADIANCE_MAP_RESOLUTION * LL_IRRADIANCE_MAP_RESOLUTION) * 4) / 1024 / 1024; +} + struct CompareProbeDepth { bool operator()(const LLReflectionMap* lhs, const LLReflectionMap* rhs) @@ -1058,7 +1096,11 @@ void LLReflectionMapManager::updateUniforms() bool is_ambiance_pass = gCubeSnapshot && !isRadiancePass(); F32 ambscale = is_ambiance_pass ? 0.f : 1.f; + ambscale *= mResetFade; + ambscale = llmax(0, ambscale); F32 radscale = is_ambiance_pass ? 0.5f : 1.f; + radscale *= mResetFade; + radscale = llmax(0, radscale); for (auto* refmap : mReflectionMaps) { @@ -1129,8 +1171,8 @@ void LLReflectionMapManager::updateUniforms() } mProbeData.refParams[count].set( - llmax(minimum_ambiance, refmap->getAmbiance())*ambscale * llmax(mResetFade, 0.f), // ambiance scale - radscale * llmax(mResetFade, 0.f), // radiance scale + llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, // ambiance scale + radscale, // radiance scale refmap->mFadeIn, // fade in weight oa.getF32ptr()[2] - refmap->mRadius); // z near @@ -1365,12 +1407,9 @@ void LLReflectionMapManager::renderDebug() void LLReflectionMapManager::initReflectionMaps() { - static LLCachedControl probe_count(gSavedSettings, "RenderReflectionProbeCount", 256U); - U32 count = probe_count(); - static LLCachedControl ref_probe_res(gSavedSettings, "RenderReflectionProbeResolution", 128U); U32 probe_resolution = nhpo2(llclamp(ref_probe_res(), (U32)64, (U32)512)); - if (mTexture.isNull() || mReflectionProbeCount != count || mProbeResolution != probe_resolution || mReset) + if (mTexture.isNull() || mReflectionProbeCount != mDynamicProbeCount || mProbeResolution != probe_resolution || mReset) { if(mProbeResolution != probe_resolution) { @@ -1379,9 +1418,10 @@ void LLReflectionMapManager::initReflectionMaps() } gEXRImage = nullptr; - + mGlobalFadeTarget = 1.f; + mResetFade = -0.125f; mReset = false; - mReflectionProbeCount = count; + mReflectionProbeCount = mDynamicProbeCount; mProbeResolution = probe_resolution; mMaxProbeLOD = log2f((F32)mProbeResolution) - 1.f; // number of mips - 1 diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h index 9f88776ac2..0719c28134 100644 --- a/indra/newview/llreflectionmapmanager.h +++ b/indra/newview/llreflectionmapmanager.h @@ -38,7 +38,7 @@ class LLViewerObject; #define LL_MAX_REFLECTION_PROBE_COUNT 256 // reflection probe resolution -#define LL_IRRADIANCE_MAP_RESOLUTION 64 +#define LL_IRRADIANCE_MAP_RESOLUTION 16 // reflection probe mininum scale #define LL_REFLECTION_PROBE_MINIMUM_SCALE 1.f; @@ -159,6 +159,9 @@ public: // with false when done. void forceDefaultProbeAndUpdateUniforms(bool force = true); + U32 probeCount(); + U32 probeMemory(); + private: friend class LLPipeline; friend class LLHeroProbeManager; @@ -166,6 +169,9 @@ private: // initialize mCubeFree array to default values void initCubeFree(); + // Just does a bulk clear of all of the cubemaps. + void clearCubeMaps(); + // delete the probe with the given index in mProbes void deleteProbe(U32 i); @@ -240,6 +246,8 @@ private: // number of reflection probes to use for rendering U32 mReflectionProbeCount; + U32 mDynamicProbeCount; + // resolution of reflection probes U32 mProbeResolution = 128; @@ -253,6 +261,7 @@ private: bool mReset = false; float mResetFade = 1.f; + float mGlobalFadeTarget = 1.f; // if true, only update the default probe bool mPaused = false; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 78d930c05c..8560a01c4b 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -559,10 +559,12 @@ void LLGLTexMemBar::draw() gGL.color4f(0.f, 0.f, 0.f, 0.25f); gl_rect_2d(-10, getRect().getHeight() + line_height*2 + 1, getRect().getWidth()+2, getRect().getHeight()+2); - text = llformat("Est. Free: %d MB Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB", + text = llformat("Est. Free: %d MB Sys Free: %d MB FBO: %d MB Probe#: %d Probe Mem: %d MB Bias: %.2f Cache: %.1f/%.1f MB", (S32)LLViewerTexture::sFreeVRAMMegabytes, LLMemory::getAvailableMemKB()/1024, LLRenderTarget::sBytesAllocated/(1024*1024), + gPipeline.mReflectionMapManager.probeCount(), + gPipeline.mReflectionMapManager.probeMemory(), discard_bias, cache_usage, cache_max_usage); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 0782192858..4a9dd1c1b6 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -504,8 +504,11 @@ void LLViewerTexture::updateClass() // NOTE: our metrics miss about half the vram we use, so this biases high but turns out to typically be within 5% of the real number F32 used = (F32)ll_round(texture_bytes_alloc + vertex_bytes_alloc); - F32 budget = max_vram_budget == 0 ? (F32)gGLManager.mVRAM : (F32)max_vram_budget; - budget /= tex_vram_divisor; + // For debugging purposes, it's useful to be able to set the VRAM budget manually. + // But when manual control is not enabled, use the VRAM divisor. + // While we're at it, assume we have 1024 to play with at minimum when the divisor is in use. Works more elegantly with the logic below this. + // -Geenz 2025-03-21 + F32 budget = max_vram_budget == 0 ? llmax(1024, (F32)gGLManager.mVRAM / tex_vram_divisor) : (F32)max_vram_budget; // Try to leave at least half a GB for everyone else and for bias, // but keep at least 768MB for ourselves diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index 34ed3fa80d..78d13293a8 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -858,23 +858,6 @@ value="3"/> - - Date: Fri, 21 Mar 2025 16:22:47 +0200 Subject: #3713 Crash at updateGLTFMaterials --- indra/newview/llfetchedgltfmaterial.cpp | 1 + indra/newview/lllocalbitmaps.cpp | 72 +++++++++++++++++---------------- indra/newview/lllocalbitmaps.h | 2 +- 3 files changed, 39 insertions(+), 36 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index c2821d56d6..558fc92018 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -199,6 +199,7 @@ bool LLFetchedGLTFMaterial::replaceLocalTexture(const LLUUID& tracking_id, const { mTrackingIdToLocalTexture.erase(tracking_id); } + updateLocalTexDataDigest(); return res; } diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 31c9eb8966..f08582e860 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -293,8 +293,9 @@ void LLLocalBitmap::addGLTFMaterial(LLGLTFMaterial* mat) return; } - mat_list_t::iterator end = mGLTFMaterialWithLocalTextures.end(); - for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != end;) + mat->addLocalTextureTracking(getTrackingID(), getWorldID()); + + for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != mGLTFMaterialWithLocalTextures.end();) { if (it->get() == mat) { @@ -304,15 +305,12 @@ void LLLocalBitmap::addGLTFMaterial(LLGLTFMaterial* mat) if ((*it)->getNumRefs() == 1) { it = mGLTFMaterialWithLocalTextures.erase(it); - end = mGLTFMaterialWithLocalTextures.end(); } else { it++; } } - - mat->addLocalTextureTracking(getTrackingID(), getWorldID()); mGLTFMaterialWithLocalTextures.push_back(mat); } @@ -628,16 +626,16 @@ void LLLocalBitmap::updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableTyp void LLLocalBitmap::updateGLTFMaterials(LLUUID old_id, LLUUID new_id) { // Might be a better idea to hold this in LLGLTFMaterialList - mat_list_t::iterator end = mGLTFMaterialWithLocalTextures.end(); - for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != end;) + for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != mGLTFMaterialWithLocalTextures.end();) { if ((*it)->getNumRefs() == 1) { // render and override materials are often recreated, // clean up any remains it = mGLTFMaterialWithLocalTextures.erase(it); - end = mGLTFMaterialWithLocalTextures.end(); } + // Render material consists of base and override materials, make sure replaceLocalTexture + // gets called for base and override before applyOverride else if ((*it)->replaceLocalTexture(mTrackingID, old_id, new_id)) { it++; @@ -647,43 +645,47 @@ void LLLocalBitmap::updateGLTFMaterials(LLUUID old_id, LLUUID new_id) // Matching id not found, no longer in use // material would clean itself, remove from the list it = mGLTFMaterialWithLocalTextures.erase(it); - end = mGLTFMaterialWithLocalTextures.end(); } } - // Render material consists of base and override materials, make sure replaceLocalTexture - // gets called for base and override before applyOverride - end = mGLTFMaterialWithLocalTextures.end(); - for (mat_list_t::iterator it = mGLTFMaterialWithLocalTextures.begin(); it != end;) + // Updating render materials calls updateTextureTracking which can modify + // mGLTFMaterialWithLocalTextures, so precollect all entries that need to be updated + std::set update_entries; + for (LLGLTFMaterial* mat : mGLTFMaterialWithLocalTextures) { - LLFetchedGLTFMaterial* fetched_mat = dynamic_cast((*it).get()); + // mGLTFMaterialWithLocalTextures includes overrides that are not 'fetched' + // and don't have texture entries (they don't need to since render material does). + LLFetchedGLTFMaterial* fetched_mat = dynamic_cast(mat); if (fetched_mat) { for (LLTextureEntry* entry : fetched_mat->mTextureEntires) { - // Normally a change in applied material id is supposed to - // drop overrides thus reset material, but local materials - // currently reuse their existing asset id, and purpose is - // to preview how material will work in-world, overrides - // included, so do an override to render update instead. - LLGLTFMaterial* override_mat = entry->getGLTFMaterialOverride(); - if (override_mat) - { - // do not create a new material, reuse existing pointer - LLFetchedGLTFMaterial* render_mat = dynamic_cast(entry->getGLTFRenderMaterial()); - if (render_mat) - { - *render_mat = *fetched_mat; - render_mat->applyOverride(*override_mat); - } - else - { - LL_WARNS_ONCE() << "Failed to apply local material override, render material not found" << LL_ENDL; - } - } + update_entries.insert(entry); + } + } + } + + + for (LLTextureEntry* entry : update_entries) + { + // Normally a change in applied material id is supposed to + // drop overrides thus reset material, but local materials + // currently reuse their existing asset id, and purpose is + // to preview how material will work in-world, overrides + // included, so do an override to render update instead. + LLGLTFMaterial* override_mat = entry->getGLTFMaterialOverride(); + LLGLTFMaterial* mat = entry->getGLTFMaterial(); + if (override_mat && mat) + { + // do not create a new material, reuse existing pointer + // so that mTextureEntires remains untouched + LLGLTFMaterial* render_mat = entry->getGLTFRenderMaterial(); + if (render_mat) + { + *render_mat = *mat; + render_mat->applyOverride(*override_mat); // can update mGLTFMaterialWithLocalTextures } } - ++it; } } diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index e169f96e70..de2dcb3467 100644 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -106,7 +106,7 @@ class LLLocalBitmap // Store a list of accosiated materials // Might be a better idea to hold this in LLGLTFMaterialList - typedef std::vector > mat_list_t; + typedef std::list > mat_list_t; mat_list_t mGLTFMaterialWithLocalTextures; }; -- cgit v1.3 From ecfe76ac125e484a78f1cba67314f5195d8fdf71 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 21 Mar 2025 21:40:38 +0200 Subject: vp#404 Improve URL filter --- indra/llui/llurlentry.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'indra') diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 3cc0c05ffa..77f132e9d8 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -221,6 +221,16 @@ bool LLUrlEntryBase::isWikiLinkCorrect(const std::string &labeled_url) const }, L'\u002F'); // Solidus + std::replace_if(wlabel.begin(), + wlabel.end(), + [](const llwchar& chr) + { + return // Not a decomposition, but suficiently similar + (chr == L'\u04BA') // "Cyrillic Capital Letter Shha" + || (chr == L'\u04BB'); // "Cyrillic Small Letter Shha" + }, + L'\u0068'); // "Latin Small Letter H" + std::string label = wstring_to_utf8str(wlabel); if ((label.find(".com") != std::string::npos || label.find("www.") != std::string::npos) -- cgit v1.3 From 6b88a2bec27e24debb4eb4fe986850f36f8689a9 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 24 Mar 2025 18:05:06 +0200 Subject: #3780 disable water exclusion if user applies PBR or Media --- indra/newview/llpanelface.cpp | 5 +---- indra/newview/llselectmgr.cpp | 11 ++++++++++- indra/newview/llselectmgr.h | 1 + indra/newview/llviewerobject.cpp | 25 +++++++++++++++++++++++++ indra/newview/llviewerobject.h | 2 ++ 5 files changed, 39 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index c4f118fed8..b7d9df6ea6 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -3075,10 +3075,7 @@ void LLPanelFace::onCommitHideWater() } else { - // reset texture to default plywood - LLSelectMgr::getInstance()->selectionSetImage(DEFAULT_OBJECT_TEXTURE); - // reset texture repeats, that might be altered by invisiprim script from wiki - LLSelectMgr::getInstance()->selectionTexScaleAutofit(2.f); + LLSelectMgr::getInstance()->clearWaterExclusion(); } } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index b307de787c..cc88d31aee 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1995,7 +1995,7 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id) asset_id = BLANK_MATERIAL_ASSET_ID; } } - + objectp->clearTEWaterExclusion(te); // Blank out most override data on the object and send to server objectp->setRenderMaterialID(te, asset_id); @@ -2477,6 +2477,7 @@ void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) } else { // Add/update media + object->clearTEWaterExclusion(te); object->setTEMediaFlags(te, mMediaFlags); LLVOVolume *vo = dynamic_cast(object); llassert(NULL != vo); @@ -7724,6 +7725,14 @@ void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom) gAgentCamera.mHUDCurZoom = current_zoom; } +void LLSelectMgr::clearWaterExclusion() +{ + // reset texture to default plywood + LLSelectMgr::getInstance()->selectionSetImage(DEFAULT_OBJECT_TEXTURE); + // reset texture repeats, that might be altered by invisiprim script from wiki + LLSelectMgr::getInstance()->selectionTexScaleAutofit(2.f); +} + ///////////////////////////////////////////////////////////////////////////// // Object selection iterator helpers ///////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index b70ec3dbea..0dbdc133e3 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -836,6 +836,7 @@ public: void getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const; void updatePointAt(); + void clearWaterExclusion(); // Internal list maintenance functions. TODO: Make these private! void remove(std::vector& objects); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 3d88cc5f39..c5e81dd179 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -7682,6 +7682,31 @@ void LLViewerObject::setGLTFAsset(const LLUUID& id) updateVolume(volume_params); } +void LLViewerObject::clearTEWaterExclusion(const U8 te) +{ + if (permModify()) + { + LLViewerTexture* image = getTEImage(te); + if (image && (IMG_ALPHA_GRAD == image->getID())) + { + // reset texture to default plywood + setTEImage(te, LLViewerTextureManager::getFetchedTexture(DEFAULT_OBJECT_TEXTURE, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + + // reset texture repeats, that might be altered by invisiprim script from wiki + U32 s_axis, t_axis; + if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis)) + { + return; + } + F32 DEFAULT_REPEATS = 2.f; + F32 new_s = getScale().mV[s_axis] * DEFAULT_REPEATS; + F32 new_t = getScale().mV[t_axis] * DEFAULT_REPEATS; + + setTEScale(te, new_s, new_t); + sendTEUpdate(); + } + } +} class ObjectPhysicsProperties : public LLHTTPNode { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 63458e60ea..2b52ea2076 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -405,6 +405,8 @@ public: LLViewerTexture *getTENormalMap(const U8 te) const; LLViewerTexture *getTESpecularMap(const U8 te) const; + void clearTEWaterExclusion(const U8 te); + bool isImageAlphaBlended(const U8 te) const; void fitFaceTexture(const U8 face); -- cgit v1.3 From 7fc9c0baa430875dce44778d5d72b302858f9f4e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 24 Mar 2025 22:20:53 +0200 Subject: #3796 Crash at assetRequestCoro Coroutine doesn't own req pointer, don't use it --- indra/llmessage/llassetstorage.cpp | 22 +++++++++------------- indra/llmessage/llassetstorage.h | 3 ++- indra/newview/llviewerassetstorage.cpp | 14 +++++++------- indra/newview/llviewerassetstorage.h | 3 +-- 4 files changed, 19 insertions(+), 23 deletions(-) (limited to 'indra') diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 2de59c1b6a..10fd56a68e 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -585,7 +585,8 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, // static void LLAssetStorage::removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type, const LLUUID& callback_id, LLAssetType::EType callback_type, - S32 result_code, LLExtStat ext_status) + S32 result_code, LLExtStat ext_status, + S32 bytes_fetched) { // find and callback ALL pending requests for this UUID // SJB: We process the callbacks in reverse order, I do not know if this is important, @@ -598,6 +599,10 @@ void LLAssetStorage::removeAndCallbackPendingDownloads(const LLUUID& file_id, LL LLAssetRequest* tmp = *curiter; if ((tmp->getUUID() == file_id) && (tmp->getType()== file_type)) { + if (bytes_fetched > 0) + { + tmp->mBytesFetched = bytes_fetched; + } requests.push_front(tmp); iter = gAssetStorage->mPendingDownloads.erase(curiter); } @@ -664,6 +669,7 @@ void LLAssetStorage::downloadCompleteCallback( callback_type = req->getType(); } + S32 bytes_fetched = 0; if (LL_ERR_NOERR == result) { // we might have gotten a zero-size file @@ -677,21 +683,11 @@ void LLAssetStorage::downloadCompleteCallback( } else { -#if 1 - for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin(); - iter != gAssetStorage->mPendingDownloads.end(); ++iter ) - { - LLAssetRequest* dlreq = *iter; - if ((dlreq->getUUID() == file_id) && (dlreq->getType()== file_type)) - { - dlreq->mBytesFetched = vfile.getSize(); - } - } -#endif + bytes_fetched = vfile.getSize(); } } - removeAndCallbackPendingDownloads(file_id, file_type, callback_id, callback_type, result, ext_status); + removeAndCallbackPendingDownloads(file_id, file_type, callback_id, callback_type, result, ext_status, bytes_fetched); } void LLAssetStorage::getEstateAsset( diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h index 88fa572092..6d6526757d 100644 --- a/indra/llmessage/llassetstorage.h +++ b/indra/llmessage/llassetstorage.h @@ -324,7 +324,8 @@ public: static void removeAndCallbackPendingDownloads(const LLUUID& file_id, LLAssetType::EType file_type, const LLUUID& callback_id, LLAssetType::EType callback_type, - S32 result_code, LLExtStat ext_status); + S32 result_code, LLExtStat ext_status, + S32 bytes_fetched); // download process callbacks static void downloadCompleteCallback( diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 5ab9f76e47..255cfc998a 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -402,10 +402,10 @@ void LLViewerAssetStorage::queueRequestHttp( manager->enqueueCoprocedure( VIEWER_ASSET_STORAGE_CORO_POOL, "LLViewerAssetStorage::assetRequestCoro", - [this, req, uuid, atype, callback, user_data] + [this, uuid, atype, callback, user_data] (LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t&, const LLUUID&) { - assetRequestCoro(req, uuid, atype, callback, user_data); + assetRequestCoro(uuid, atype, callback, user_data); }); } } @@ -440,7 +440,6 @@ struct LLScopedIncrement }; void LLViewerAssetStorage::assetRequestCoro( - LLViewerAssetRequest *req, const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback callback, @@ -464,7 +463,7 @@ void LLViewerAssetStorage::assetRequestCoro( LL_WARNS_ONCE("ViewerAsset") << "Asset request fails: no region set" << LL_ENDL; result_code = LL_ERR_ASSET_REQUEST_FAILED; ext_status = LLExtStat::NONE; - removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); return; } else if (!gAgent.getRegion()->capabilitiesReceived()) @@ -495,7 +494,7 @@ void LLViewerAssetStorage::assetRequestCoro( LL_WARNS_ONCE("ViewerAsset") << "asset request fails: caps received but no viewer asset cap found" << LL_ENDL; result_code = LL_ERR_ASSET_REQUEST_FAILED; ext_status = LLExtStat::NONE; - removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, 0); return; } std::string url = getAssetURL(mViewerAssetUrl, uuid,atype); @@ -517,6 +516,7 @@ void LLViewerAssetStorage::assetRequestCoro( mCountCompleted++; + S32 bytes_fetched = 0; LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); if (!status) @@ -554,7 +554,7 @@ void LLViewerAssetStorage::assetRequestCoro( LLUUID temp_id; temp_id.generate(); LLFileSystem vf(temp_id, atype, LLFileSystem::WRITE); - req->mBytesFetched = size; + bytes_fetched = size; if (!vf.write(raw.data(),size)) { // TODO asset-http: handle error @@ -583,7 +583,7 @@ void LLViewerAssetStorage::assetRequestCoro( } // Clean up pending downloads and trigger callbacks - removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status); + removeAndCallbackPendingDownloads(uuid, atype, uuid, atype, result_code, ext_status, bytes_fetched); } std::string LLViewerAssetStorage::getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype) diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h index fdb8af7457..42dd9d1dd8 100644 --- a/indra/newview/llviewerassetstorage.h +++ b/indra/newview/llviewerassetstorage.h @@ -82,8 +82,7 @@ protected: void capsRecvForRegion(const LLUUID& region_id, std::string pumpname); - void assetRequestCoro(LLViewerAssetRequest *req, - const LLUUID uuid, + void assetRequestCoro(const LLUUID uuid, LLAssetType::EType atype, LLGetAssetCallback callback, void *user_data); -- cgit v1.3 From 5e5d466628f3576bb48b63f143502ea914f79bca Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Mon, 24 Mar 2025 17:59:13 -0400 Subject: Readd probe count setting (#3793) * Readd max probe count. Disable dynamic probe allocation by default (for now). --- indra/llrender/llcubemaparray.cpp | 32 ++++++++ indra/llrender/llcubemaparray.h | 2 + indra/newview/app_settings/settings.xml | 11 +++ .../shaders/class3/environment/waterF.glsl | 3 +- indra/newview/featuretable.txt | 10 +++ indra/newview/featuretable_mac.txt | 10 +++ indra/newview/llreflectionmapmanager.cpp | 90 +++++++++++++--------- .../en/floater_preferences_graphics_advanced.xml | 45 +++++++++++ 8 files changed, 165 insertions(+), 38 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index d0a97dc2c6..998b57217d 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -105,6 +105,36 @@ LLCubeMapArray::LLCubeMapArray() } +LLCubeMapArray::LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count) : mTextureStage(0) +{ + mWidth = width; + mCount = count; + + // Allocate a new cubemap array with the same criteria as the incoming cubemap array + allocate(mWidth, lhs.mImage->getComponents(), count, lhs.mImage->getUseMipMaps(), lhs.mHDR); + + // Copy each cubemap from the incoming array to the new array + U32 min_count = std::min(count, lhs.mCount); + for (U32 i = 0; i < min_count * 6; ++i) + { + U32 src_resolution = lhs.mWidth; + U32 dst_resolution = mWidth; + { + GLint components = GL_RGB; + if (mImage->getComponents() == 4) + components = GL_RGBA; + GLint format = GL_RGB; + + // Handle different resolutions by scaling the image + LLPointer src_image = new LLImageRaw(lhs.mWidth, lhs.mWidth, lhs.mImage->getComponents()); + glGetTexImage(GL_TEXTURE_CUBE_MAP_ARRAY, 0, components, GL_UNSIGNED_BYTE, src_image->getData()); + + LLPointer scaled_image = src_image->scaled(mWidth, mWidth); + glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, i, mWidth, mWidth, 1, components, GL_UNSIGNED_BYTE, scaled_image->getData()); + } + } +} + LLCubeMapArray::~LLCubeMapArray() { } @@ -115,6 +145,8 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool us mWidth = resolution; mCount = count; + mHDR = hdr; + LLImageGL::generateTextures(1, &texname); mImage = new LLImageGL(resolution, resolution, components, use_mips); diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h index bfc72a321d..6b4288cb23 100644 --- a/indra/llrender/llcubemaparray.h +++ b/indra/llrender/llcubemaparray.h @@ -36,6 +36,7 @@ class LLCubeMapArray : public LLRefCount { public: LLCubeMapArray(); + LLCubeMapArray(LLCubeMapArray& lhs, U32 width, U32 count); static GLenum sTargets[6]; @@ -73,4 +74,5 @@ protected: U32 mWidth = 0; U32 mCount = 0; S32 mTextureStage; + bool mHDR; }; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4ce7e0f729..b7127adc53 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9087,6 +9087,17 @@ Value 1 + RenderReflectionProbeDynamicAllocation + + Comment + Enable dynamic allocation of reflection probes. -1 means no dynamic allocation. Sets a buffer to allocate when a dynamic allocation occurs otherwise. + Persist + 1 + Type + S32 + Value + -1 + RenderReflectionProbeCount Comment diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index 1b7b0c1937..e57aa69731 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -26,6 +26,7 @@ // class3/environment/waterF.glsl #define WATER_MINIMAL 1 +#define SHORELINE_FADE 1 out vec4 frag_color; @@ -264,7 +265,7 @@ void main() // Calculate some distance fade in the water to better assist with refraction blending and reducing the refraction texture's "disconnect". #ifdef SHORELINE_FADE - fade = max(0,min(1, (pos.z - refPos.z) / 10)) + fade = max(0,min(1, (pos.z - refPos.z) / 10)); #else fade = 1 * water_mask; #endif diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 443a7ae914..c0009d24ee 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -86,6 +86,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 1 RenderDisableVintageMode 1 1 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Low Graphics Settings @@ -128,6 +129,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 512 +RenderReflectionProbeCount 1 1 // // Medium Low Graphics Settings @@ -170,6 +172,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 1024 +RenderReflectionProbeCount 1 32 // // Medium Graphics Settings (standard) @@ -211,6 +214,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 64 // // Medium High Graphics Settings @@ -252,6 +256,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 64 // // High Graphics Settings (SSAO + sun shadows) @@ -293,6 +298,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 128 // // High Ultra Graphics Settings (deferred + SSAO + all shadows) @@ -334,6 +340,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Ultra graphics (REALLY PURTY!) @@ -375,6 +382,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Class Unknown Hardware (unknown) @@ -408,6 +416,7 @@ RenderReflectionProbeDetail 0 -1 RenderMirrors 0 0 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 0 0 list Intel RenderAnisotropic 1 0 @@ -429,6 +438,7 @@ RenderMirrors 0 0 RenderGLMultiThreadedTextures 0 0 RenderGLMultiThreadedMedia 0 0 RenderDisableVintageMode 1 0 +RenderReflectionProbeCount 0 0 list TexUnit16orLess RenderTerrainPBRDetail 1 -1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index dc9473b042..5940d1ec12 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -86,6 +86,7 @@ RenderTonemapMix 1 1 RenderDisableVintageMode 1 1 RenderDownScaleMethod 1 0 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Low Graphics Settings @@ -128,6 +129,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 512 +RenderReflectionProbeCount 1 1 // // Medium Low Graphics Settings @@ -170,6 +172,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 1024 +RenderReflectionProbeCount 1 32 // // Medium Graphics Settings (standard) @@ -211,6 +214,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 64 // // Medium High Graphics Settings @@ -252,6 +256,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 64 // // High Graphics Settings (SSAO + sun shadows) @@ -293,6 +298,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 128 // // High Ultra Graphics Settings (SSAO + all shadows) @@ -334,6 +340,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Ultra graphics (REALLY PURTY!) @@ -375,6 +382,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 1 256 // // Class Unknown Hardware (unknown) @@ -407,6 +415,7 @@ RenderShadowDetail 0 0 RenderMirrors 0 0 RenderDisableVintageMode 1 0 RenderMaxTextureResolution 1 2048 +RenderReflectionProbeCount 0 0 list TexUnit8orLess RenderDeferredSSAO 0 0 @@ -447,6 +456,7 @@ RenderReflectionProbeDetail 0 0 RenderReflectionsEnabled 0 0 RenderMirrors 0 0 RenderDisableVintageMode 1 0 +RenderReflectionProbeCount 0 0 list VaryingVectors16orLess RenderTerrainPBRPlanarSampleCount 1 1 diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 34c6034e9e..f2abc7b8b7 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -224,48 +224,54 @@ void LLReflectionMapManager::update() static LLCachedControl sDetail(gSavedSettings, "RenderReflectionProbeDetail", -1); static LLCachedControl sLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); + static LLCachedControl sReflectionProbeCount(gSavedSettings, "RenderReflectionProbeCount", 256U); + static LLCachedControl sProbeDynamicAllocation(gSavedSettings, "RenderReflectionProbeDynamicAllocation", -1); + mResetFade = llmin((F32)(mResetFade + gFrameIntervalSeconds * 2.f), 1.f); - // Once every 20 frames, update the dynamic probe count. - if (gFrameCount % 20) { U32 probe_count_temp = mDynamicProbeCount; - if (sLevel == 0) - { - mDynamicProbeCount = 1; - } - else if (sLevel == 1) + if (sProbeDynamicAllocation > -1) { - mDynamicProbeCount = (U32)mProbes.size(); + if (sLevel == 0) + { + mDynamicProbeCount = 1; + } + else if (sLevel == 1) + { + mDynamicProbeCount = (U32)mProbes.size(); + } + else if (sLevel == 2) + { + mDynamicProbeCount = llmax((U32)mProbes.size(), 128); + } + else + { + mDynamicProbeCount = 256; + } - } - else if (sLevel == 2) - { - mDynamicProbeCount = llmax((U32)mProbes.size(), 128); + if (sProbeDynamicAllocation > 1) + { + // Round mDynamicProbeCount to the nearest increment of 16 + mDynamicProbeCount = ((mDynamicProbeCount + sProbeDynamicAllocation / 2) / sProbeDynamicAllocation) * 16; + mDynamicProbeCount = llclamp(mDynamicProbeCount, 1, sReflectionProbeCount); + } + else + { + mDynamicProbeCount = llclamp(mDynamicProbeCount + sProbeDynamicAllocation, 1, sReflectionProbeCount); + } } else { - mDynamicProbeCount = 256; + mDynamicProbeCount = sReflectionProbeCount; } - // Round mDynamicProbeCount to the nearest increment of 32 - mDynamicProbeCount = ((mDynamicProbeCount + 16) / 32) * 32; - mDynamicProbeCount = llclamp(mDynamicProbeCount, 1, LL_MAX_REFLECTION_PROBE_COUNT); + mDynamicProbeCount = llmin(mDynamicProbeCount, LL_MAX_REFLECTION_PROBE_COUNT); - if (mDynamicProbeCount < probe_count_temp * 1.1 && mDynamicProbeCount > probe_count_temp * 0.9) - mDynamicProbeCount = probe_count_temp; - else - mGlobalFadeTarget = 0.f; + if (mDynamicProbeCount != probe_count_temp) + mResetFade = 1.f; } - if (mGlobalFadeTarget < mResetFade) - mResetFade = llmax(mGlobalFadeTarget, mResetFade - (F32)gFrameIntervalSeconds * 2); - else - mResetFade = llmin(mGlobalFadeTarget, mResetFade + (F32)gFrameIntervalSeconds * 2); - - if (mResetFade == mGlobalFadeTarget) - { - initReflectionMaps(); - } + initReflectionMaps(); static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); @@ -356,6 +362,7 @@ void LLReflectionMapManager::update() probe->mCubeArray = nullptr; probe->mCubeIndex = -1; probe->mComplete = false; + probe->mFadeIn = 0; } } @@ -1418,8 +1425,6 @@ void LLReflectionMapManager::initReflectionMaps() } gEXRImage = nullptr; - mGlobalFadeTarget = 1.f; - mResetFade = -0.125f; mReset = false; mReflectionProbeCount = mDynamicProbeCount; mProbeResolution = probe_resolution; @@ -1429,15 +1434,25 @@ void LLReflectionMapManager::initReflectionMaps() mTexture->getWidth() != mProbeResolution || mReflectionProbeCount + 2 != mTexture->getCount()) { - mTexture = new LLCubeMapArray(); + if (mTexture) + { + mTexture = new LLCubeMapArray(*mTexture, mProbeResolution, mReflectionProbeCount + 2); - static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); + mIrradianceMaps = new LLCubeMapArray(*mIrradianceMaps, LL_IRRADIANCE_MAP_RESOLUTION, mReflectionProbeCount); + } + else + { + mTexture = new LLCubeMapArray(); + + static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); - // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) - mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2, true, render_hdr); + // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation + // source) + mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2, true, render_hdr); - mIrradianceMaps = new LLCubeMapArray(); - mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, false, render_hdr); + mIrradianceMaps = new LLCubeMapArray(); + mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, false, render_hdr); + } } // reset probe state @@ -1457,6 +1472,7 @@ void LLReflectionMapManager::initReflectionMaps() probe->mCubeArray = nullptr; probe->mCubeIndex = -1; probe->mNeighbors.clear(); + probe->mFadeIn = 0; } mCubeFree.clear(); diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index 78d13293a8..6877ce6411 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -858,6 +858,51 @@ value="3"/> + + Max Reflection Probes: + + + + + + + + + + Date: Mon, 24 Mar 2025 23:50:34 +0200 Subject: #3798 Crash at getAvatar() --- indra/newview/llface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 811aacb2ed..373a556f86 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2218,7 +2218,7 @@ bool LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) { LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("calcPixelArea - rigged"); //override with joint volume face joint bounding boxes - LLVOAvatar* avatar = mVObjp->getAvatar(); + LLVOAvatar* avatar = mVObjp.notNull() ? mVObjp->getAvatar() : nullptr; bool hasRiggedExtents = false; if (avatar && avatar->mDrawable) -- cgit v1.3 From d484fff77d73931e70c896b9a88db547c4922dbd Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Mar 2025 14:30:29 +0200 Subject: #3596 Don't supress exceptions in WorkQueue We need those to know about problems. --- indra/llcommon/workqueue.cpp | 83 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp index 6066e74fb5..dace95aaf2 100644 --- a/indra/llcommon/workqueue.cpp +++ b/indra/llcommon/workqueue.cpp @@ -17,6 +17,7 @@ // std headers // external library headers // other Linden headers +#include "llapp.h" #include "llcoros.h" #include LLCOROS_MUTEX_HEADER #include "llerror.h" @@ -102,19 +103,95 @@ std::string LL::WorkQueueBase::makeName(const std::string& name) return STRINGIZE("WorkQueue" << num); } +namespace +{ +#if LL_WINDOWS + + static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific + + U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop) + { + if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop)) + { + // Handled + return EXCEPTION_CONTINUE_SEARCH; + } + else if (code == STATUS_MSC_EXCEPTION) + { + // C++ exception, go on + return EXCEPTION_CONTINUE_SEARCH; + } + else + { + // handle it, convert to std::exception + return EXCEPTION_EXECUTE_HANDLER; + } + + return EXCEPTION_CONTINUE_SEARCH; + } + + void cpphandle(const LL::WorkQueueBase::Work& work) + { + // SE and C++ can not coexists, thus two handlers + try + { + work(); + } + catch (const LLContinueError&) + { + // Any uncaught exception derived from LLContinueError will be caught + // here and logged. This coroutine will terminate but the rest of the + // viewer will carry on. + LOG_UNHANDLED_EXCEPTION(STRINGIZE("LLContinue in work queue")); + } + } + + void sehandle(const LL::WorkQueueBase::Work& work) + { + __try + { + // handle stop and continue exceptions first + cpphandle(work); + } + __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) + { + // convert to C++ styled exception + char integer_string[512]; + sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); + throw std::exception(integer_string); + } + } +#endif // LL_WINDOWS +} // anonymous namespace + void LL::WorkQueueBase::callWork(const Work& work) { LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + +#ifdef LL_WINDOWS + // can not use __try directly, toplevel requires unwinding, thus use of a wrapper + sehandle(work); +#else // LL_WINDOWS try { work(); } - catch (...) + catch (LLContinueError&) { - // No matter what goes wrong with any individual work item, the worker - // thread must go on! Log our own instance name with the exception. LOG_UNHANDLED_EXCEPTION(getKey()); } + catch (...) + { + // Stash any other kind of uncaught exception to be rethrown by main thread. + LL_WARNS("LLCoros") << "Capturing uncaught exception in WorkQueueBase " + << getKey() << LL_ENDL; + + LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); + main_queue->post( + // Bind the current exception rethrow it in main loop. + [exc = std::current_exception()]() { std::rethrow_exception(exc); }); + } +#endif // else LL_WINDOWS } void LL::WorkQueueBase::error(const std::string& msg) -- cgit v1.3 From 8705c16cb2559fc00f907da6ad801b2fae4970fa Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Mar 2025 20:19:25 +0200 Subject: #3643 Make sure attribute names match between OSs On Mac spaces aren't permitted. --- indra/newview/llappviewerwin32.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index b4a2479520..aaf2a7ea3e 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -155,10 +155,10 @@ namespace sBugSplatSender->setAttribute(WCSTR(L"OS"), WCSTR(LLOSInfo::instance().getOSStringSimple())); // In case we ever stop using email for this sBugSplatSender->setAttribute(WCSTR(L"AppState"), WCSTR(LLStartUp::getStartupStateString())); - sBugSplatSender->setAttribute(WCSTR(L"GL Vendor"), WCSTR(gGLManager.mGLVendor)); - sBugSplatSender->setAttribute(WCSTR(L"GL Version"), WCSTR(gGLManager.mGLVersionString)); - sBugSplatSender->setAttribute(WCSTR(L"GPU Version"), WCSTR(gGLManager.mDriverVersionVendorString)); - sBugSplatSender->setAttribute(WCSTR(L"GL Renderer"), WCSTR(gGLManager.mGLRenderer)); + sBugSplatSender->setAttribute(WCSTR(L"GLVendor"), WCSTR(gGLManager.mGLVendor)); + sBugSplatSender->setAttribute(WCSTR(L"GLVersion"), WCSTR(gGLManager.mGLVersionString)); + sBugSplatSender->setAttribute(WCSTR(L"GPUVersion"), WCSTR(gGLManager.mDriverVersionVendorString)); + sBugSplatSender->setAttribute(WCSTR(L"GLRenderer"), WCSTR(gGLManager.mGLRenderer)); sBugSplatSender->setAttribute(WCSTR(L"VRAM"), WCSTR(STRINGIZE(gGLManager.mVRAM))); sBugSplatSender->setAttribute(WCSTR(L"RAM"), WCSTR(STRINGIZE(gSysMemory.getPhysicalMemoryKB().value()))); -- cgit v1.3 From 8eff224c121f8e08514b28326d4c886e4acd35ab Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Mar 2025 22:11:16 +0200 Subject: #3795 Fix macos shutdown crash --- indra/llwindow/llwindowmacosx.cpp | 86 ++++++++++++++++++++++++++++++++++----- indra/newview/llviewerwindow.cpp | 11 +++-- 2 files changed, 82 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 6c3be3eef8..dadbc83f45 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -279,6 +279,10 @@ void callResetKeys() bool callUnicodeCallback(wchar_t character, unsigned int mask) { + if (!gWindowImplementation) + { + return false; + } NativeKeyEventData eventData; memset(&eventData, 0, sizeof(NativeKeyEventData)); @@ -300,7 +304,7 @@ bool callUnicodeCallback(wchar_t character, unsigned int mask) void callFocus() { - if (gWindowImplementation) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); } @@ -308,7 +312,7 @@ void callFocus() void callFocusLost() { - if (gWindowImplementation) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); } @@ -316,6 +320,10 @@ void callFocusLost() void callRightMouseDown(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -329,6 +337,10 @@ void callRightMouseDown(float *pos, MASK mask) void callRightMouseUp(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -342,6 +354,10 @@ void callRightMouseUp(float *pos, MASK mask) void callLeftMouseDown(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -355,6 +371,10 @@ void callLeftMouseDown(float *pos, MASK mask) void callLeftMouseUp(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -369,6 +389,10 @@ void callLeftMouseUp(float *pos, MASK mask) void callDoubleClick(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } if (gWindowImplementation->allowsLanguageInput()) { gWindowImplementation->interruptLanguageTextInput(); @@ -382,7 +406,7 @@ void callDoubleClick(float *pos, MASK mask) void callResize(unsigned int width, unsigned int height) { - if (gWindowImplementation != NULL) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height); } @@ -390,6 +414,10 @@ void callResize(unsigned int width, unsigned int height) void callMouseMoved(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -403,6 +431,10 @@ void callMouseMoved(float *pos, MASK mask) void callMouseDragged(float *pos, MASK mask) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -424,6 +456,10 @@ void callScrollMoved(float deltaX, float deltaY) void callMouseExit() { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation); } @@ -475,11 +511,19 @@ void callWindowDidChangeScreen() void callDeltaUpdate(float *delta, MASK mask) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->updateMouseDeltas(delta); } void callOtherMouseDown(float *pos, MASK mask, int button) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -500,6 +544,10 @@ void callOtherMouseDown(float *pos, MASK mask, int button) void callOtherMouseUp(float *pos, MASK mask, int button) { + if (!gWindowImplementation) + { + return; + } LLCoordGL outCoords; outCoords.mX = ll_round(pos[0]); outCoords.mY = ll_round(pos[1]); @@ -524,27 +572,43 @@ void callModifier(MASK mask) void callHandleDragEntered(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING); } void callHandleDragExited(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING); } void callHandleDragUpdated(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK); } void callHandleDragDropped(std::string url) { + if (!gWindowImplementation) + { + return; + } gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED); } void callQuitHandler() { - if (gWindowImplementation) + if (gWindowImplementation && gWindowImplementation->getCallbacks()) { if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation)) { @@ -555,7 +619,7 @@ void callQuitHandler() void getPreeditSelectionRange(int *position, int *length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->getSelectionRange(position, length); } @@ -563,7 +627,7 @@ void getPreeditSelectionRange(int *position, int *length) void getPreeditMarkedRange(int *position, int *length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->getPreeditRange(position, length); } @@ -571,7 +635,7 @@ void getPreeditMarkedRange(int *position, int *length) void setPreeditMarkedRange(int position, int length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->markAsPreedit(position, length); } @@ -580,7 +644,7 @@ void setPreeditMarkedRange(int position, int length) bool handleUnicodeCharacter(wchar_t c) { bool success = false; - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { success = gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c); } @@ -590,7 +654,7 @@ bool handleUnicodeCharacter(wchar_t c) void resetPreedit() { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { gWindowImplementation->getPreeditor()->resetPreedit(); } @@ -600,7 +664,7 @@ void resetPreedit() // This largely mirrors the old implementation, only sans the carbon parameters. void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); preeditor->resetPreedit(); @@ -623,7 +687,7 @@ void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigne void getPreeditLocation(float *location, unsigned int length) { - if (gWindowImplementation->getPreeditor()) + if (gWindowImplementation && gWindowImplementation->getPreeditor()) { LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); LLCoordGL coord; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 4194dd00e7..70c06af89b 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1450,10 +1450,13 @@ void LLViewerWindow::handleMouseLeave(LLWindow *window) bool LLViewerWindow::handleCloseRequest(LLWindow *window) { - // User has indicated they want to close, but we may need to ask - // about modified documents. - LLAppViewer::instance()->userQuit(); - // Don't quit immediately + if (!LLApp::isExiting()) + { + // User has indicated they want to close, but we may need to ask + // about modified documents. + LLAppViewer::instance()->userQuit(); + // Don't quit immediately + } return false; } -- cgit v1.3 From 74254c9524e66d13a061312a629cc404a6c64a54 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 26 Mar 2025 10:28:01 -0400 Subject: Disable shoreline fade. (#3811) --- indra/newview/app_settings/shaders/class3/environment/waterF.glsl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index e57aa69731..349f3b9a67 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -26,7 +26,6 @@ // class3/environment/waterF.glsl #define WATER_MINIMAL 1 -#define SHORELINE_FADE 1 out vec4 frag_color; @@ -267,9 +266,9 @@ void main() #ifdef SHORELINE_FADE fade = max(0,min(1, (pos.z - refPos.z) / 10)); #else - fade = 1 * water_mask; + fade = 1; #endif - + fade *= water_mask; distort2 = mix(distort, distort2, min(1, fade * 10)); depth = texture(depthMap, distort2).r; -- cgit v1.3 From b976d261edaeb8fa96f3726ab6530b7866755c67 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 26 Mar 2025 20:01:30 +0200 Subject: #3803 Crash at LLTabContainer::setTab --- indra/newview/llfloaterimcontainer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index e55bf50724..e4b14d8df6 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1939,7 +1939,7 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c mConversationEventQueue.erase(uuid); // Don't let the focus fall IW, select and refocus on the first conversation in the list - if (change_focus) + if (change_focus && isInVisibleChain()) { setFocus(true); if (new_selection) @@ -1959,6 +1959,10 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c } } } + else + { + LL_INFOS() << "Conversation widgets: " << (S32)mConversationsWidgets.size() << LL_ENDL; + } return is_widget_selected; } -- cgit v1.3 From 4e80ec7e962dde43c8d7379f0167a242704336ad Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 26 Mar 2025 19:51:59 +0200 Subject: #3814 Out of range exception in TextCmdRemove::execute --- indra/llui/lltexteditor.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3537c764b9..77a4976f6b 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -209,8 +209,15 @@ public: } virtual bool execute( LLTextBase* editor, S32* delta ) { - mWString = editor->getWText().substr(getPosition(), mLen); - *delta = remove(editor, getPosition(), mLen ); + try + { + mWString = editor->getWText().substr(getPosition(), mLen); + *delta = remove(editor, getPosition(), mLen); + } + catch (std::out_of_range&) + { + return false; + } return (*delta != 0); } virtual S32 undo( LLTextBase* editor ) -- cgit v1.3 From 695247539b54dee648d71417295e5ca753eaa74e Mon Sep 17 00:00:00 2001 From: "Jonathan \"Geenz\" Goodman" Date: Wed, 26 Mar 2025 19:01:30 -0400 Subject: Mitigate some of the frame stuttering we're seeing by setting the VRAM divisor to 1. tl;dr - this helps avoid frequent texture reuploads to VRAM in some texture heavy areas. This speaks to some bigger problems we're seeing in our texture streaming system however. You will see similar problems by manually setting the texture VRAM manually. --- indra/newview/app_settings/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b7127adc53..60ae8ac691 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7814,7 +7814,7 @@ Type U32 Value - 2 + 1 RenderMinFreeMainMemoryThreshold -- cgit v1.3 From 7d5a5e939a7427fb0cabc99e10f75d7d99c5f133 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 27 Mar 2025 18:02:19 +0200 Subject: #3820 crash at LLNotificationTemplate --- indra/llui/llnotifications.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 7405413a3d..6fc9b90fb8 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1251,7 +1251,8 @@ LLNotifications::LLNotifications() void LLNotifications::clear() { - mDefaultChannels.clear(); + mDefaultChannels.clear(); + mTemplates.clear(); } // The expiration channel gets all notifications that are cancelled -- cgit v1.3 From d67859e48351a4db498f658030c0eb2866d59e77 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 26 Mar 2025 21:05:36 +0200 Subject: Use LLCachedControl in llviewerwindow and llappviewer Getting from gSavedSettings is expensive to do so often --- indra/llappearance/llwearable.cpp | 13 +++++++------ indra/newview/llappviewer.cpp | 11 +++++++---- indra/newview/llviewerwindow.cpp | 24 ++++++++++++++++-------- 3 files changed, 30 insertions(+), 18 deletions(-) (limited to 'indra') diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index f30c147b91..4acb0ef3d4 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -645,9 +645,10 @@ void LLWearable::addVisualParam(LLVisualParam *param) void LLWearable::setVisualParamWeight(S32 param_index, F32 value) { - if( is_in_map(mVisualParamIndexMap, param_index ) ) + visual_param_index_map_t::iterator found = mVisualParamIndexMap.find(param_index); + if(found != mVisualParamIndexMap.end()) { - LLVisualParam *wearable_param = mVisualParamIndexMap[param_index]; + LLVisualParam *wearable_param = found->second; wearable_param->setWeight(value); } else @@ -658,10 +659,10 @@ void LLWearable::setVisualParamWeight(S32 param_index, F32 value) F32 LLWearable::getVisualParamWeight(S32 param_index) const { - if( is_in_map(mVisualParamIndexMap, param_index ) ) + visual_param_index_map_t::const_iterator found = mVisualParamIndexMap.find(param_index); + if(found != mVisualParamIndexMap.end()) { - const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second; - return wearable_param->getWeight(); + return found->second->getWeight(); } else { @@ -726,7 +727,7 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp) if (!avatarp) return; // Pull params - for( LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) + for( const LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) { // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 4cf651de33..0ffe675a7b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -445,8 +445,8 @@ void idle_afk_check() { // check idle timers F32 current_idle = gAwayTriggerTimer.getElapsedTimeF32(); - F32 afk_timeout = (F32)gSavedSettings.getS32("AFKTimeout"); - if (afk_timeout && (current_idle > afk_timeout) && ! gAgent.getAFK()) + static LLCachedControl afk_timeout(gSavedSettings, "AFKTimeout", 300); + if (afk_timeout() && (current_idle > (F32)afk_timeout()) && !gAgent.getAFK()) { LL_INFOS("IdleAway") << "Idle more than " << afk_timeout << " seconds: automatically changing to Away status" << LL_ENDL; gAgent.setAFK(); @@ -5376,7 +5376,8 @@ void LLAppViewer::idleNetwork() gObjectList.mNumNewObjects = 0; S32 total_decoded = 0; - if (!gSavedSettings.getBOOL("SpeedTest")) + static LLCachedControl speed_test(gSavedSettings, "SpeedTest", false); + if (!speed_test()) { LL_PROFILE_ZONE_NAMED_CATEGORY_NETWORK("idle network"); //LL_RECORD_BLOCK_TIME(FTM_IDLE_NETWORK); // decode @@ -5435,7 +5436,9 @@ void LLAppViewer::idleNetwork() } // Handle per-frame message system processing. - lmc.processAcks(gSavedSettings.getF32("AckCollectTime")); + + static LLCachedControl ack_collection_time(gSavedSettings, "AckCollectTime", 0.1f); + lmc.processAcks(ack_collection_time()); } } add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 70c06af89b..fe5a0667a5 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -489,7 +489,8 @@ public: clearText(); - if (gSavedSettings.getBOOL("DebugShowTime")) + static LLCachedControl debug_show_time(gSavedSettings, "DebugShowTime", false); + if (debug_show_time()) { F32 time = gFrameTimeSeconds; S32 hours = (S32)(time / (60*60)); @@ -498,7 +499,8 @@ public: addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; } - if (gSavedSettings.getBOOL("DebugShowMemory")) + static LLCachedControl debug_show_memory(gSavedSettings, "DebugShowMemory", false); + if (debug_show_memory()) { addText(xpos, ypos, STRINGIZE("Memory: " << (LLMemory::getCurrentRSS() / 1024) << " (KB)")); @@ -591,7 +593,8 @@ public: ypos += y_inc; }*/ - if (gSavedSettings.getBOOL("DebugShowRenderInfo")) + static LLCachedControl debug_show_render_info(gSavedSettings, "DebugShowRenderInfo", false); + if (debug_show_render_info()) { LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording(); @@ -730,7 +733,8 @@ public: gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; } - if (gSavedSettings.getBOOL("DebugShowAvatarRenderInfo")) + static LLCachedControl debug_show_avatar_render_info(gSavedSettings, "DebugShowAvatarRenderInfo", false); + if (debug_show_avatar_render_info()) { std::map sorted_avs; { @@ -763,7 +767,8 @@ public: av_iter++; } } - if (gSavedSettings.getBOOL("DebugShowRenderMatrices")) + static LLCachedControl debug_show_render_matrices(gSavedSettings, "DebugShowRenderMatrices", false); + if (debug_show_render_matrices()) { char camera_lines[8][32]; memset(camera_lines, ' ', sizeof(camera_lines)); @@ -789,7 +794,8 @@ public: ypos += y_inc; } // disable use of glReadPixels which messes up nVidia nSight graphics debugging - if (gSavedSettings.getBOOL("DebugShowColor") && !LLRender::sNsightDebugSupport) + static LLCachedControl debug_show_color(gSavedSettings, "DebugShowColor", false); + if (debug_show_color() && !LLRender::sNsightDebugSupport) { U8 color[4]; LLCoordGL coord = gViewerWindow->getCurrentMouse(); @@ -881,7 +887,8 @@ public: } } - if (gSavedSettings.getBOOL("DebugShowTextureInfo")) + static LLCachedControl debug_show_texture_info(gSavedSettings, "DebugShowTextureInfo", false); + if (debug_show_texture_info()) { LLViewerObject* objectp = NULL ; @@ -1600,7 +1607,8 @@ bool LLViewerWindow::handleActivate(LLWindow *window, bool activated) mActive = false; // if the user has chosen to go Away automatically after some time, then go Away when minimizing - if (gSavedSettings.getS32("AFKTimeout")) + static LLCachedControl afk_time(gSavedSettings, "AFKTimeout", 300); + if (afk_time()) { gAgent.setAFK(); } -- cgit v1.3 From 2b44a97a16dcf5f2a3356f1a4ccf29a47bbe9c87 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 26 Mar 2025 21:07:20 +0200 Subject: Avoid recalculating pixel area when possible --- indra/newview/llviewertexturelist.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index db530a3943..63d5a2d778 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -899,6 +899,9 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag { llassert(!gCubeSnapshot); + constexpr F32 BIAS_TRS_OUT_OF_SCREEN = 1.5f; + constexpr F32 BIAS_TRS_ON_SCREEN = 1.f; + if (imagep->getBoostLevel() < LLViewerFetchedTexture::BOOST_HIGH) // don't bother checking face list for boosted textures { static LLCachedControl texture_scale_min(gSavedSettings, "TextureScaleMinAreaFactor", 0.0095f); @@ -940,7 +943,7 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag F32 vsize = face->getPixelArea(); - on_screen = face->mInFrustum; + on_screen |= face->mInFrustum; // Scale desired texture resolution higher or lower depending on texture scale // @@ -972,14 +975,28 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag } max_vsize = llmax(max_vsize, vsize); + + // addTextureStats limits size to sMaxVirtualSize + if (max_vsize >= LLViewerFetchedTexture::sMaxVirtualSize + && (on_screen || LLViewerTexture::sDesiredDiscardBias <= BIAS_TRS_ON_SCREEN)) + { + break; + } } } + + if (max_vsize >= LLViewerFetchedTexture::sMaxVirtualSize + && (on_screen || LLViewerTexture::sDesiredDiscardBias <= BIAS_TRS_ON_SCREEN)) + { + break; + } } if (face_count > 1024) { // this texture is used in so many places we should just boost it and not bother checking its vsize // this is especially important because the above is not time sliced and can hit multiple ms for a single texture imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_HIGH); + // Do we ever remove it? This also sets texture nodelete! } if (imagep->getType() == LLViewerTexture::LOD_TEXTURE && imagep->getBoostLevel() == LLViewerTexture::BOOST_NONE) @@ -987,8 +1004,8 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag // this is an alternative to decaying mMaxVirtualSize over time // that keeps textures from continously downrezzing and uprezzing in the background - if (LLViewerTexture::sDesiredDiscardBias > 1.5f || - (!on_screen && LLViewerTexture::sDesiredDiscardBias > 1.f)) + if (LLViewerTexture::sDesiredDiscardBias > BIAS_TRS_OUT_OF_SCREEN || + (!on_screen && LLViewerTexture::sDesiredDiscardBias > BIAS_TRS_ON_SCREEN)) { imagep->mMaxVirtualSize = 0.f; } -- cgit v1.3 From 6ac1d4f3e37f2118875a4c9e96b26e3f82e17a1e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 27 Mar 2025 20:47:10 +0200 Subject: #3829 WebRTC crash OnDataReceivedImpl --- indra/newview/llvoicewebrtc.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 93c217a7ba..08fcec86ac 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -3024,7 +3024,7 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b { root["ug"] = user_gain; } - if (root.size() > 0) + if (root.size() > 0 && mWebRTCDataInterface) { std::string json_data = boost::json::serialize(root); mWebRTCDataInterface->sendData(json_data, false); @@ -3067,7 +3067,10 @@ void LLVoiceWebRTCConnection::OnDataChannelReady(llwebrtc::LLWebRTCDataInterface void LLVoiceWebRTCConnection::sendJoin() { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE; - + if (!mWebRTCDataInterface) + { + return; + } boost::json::object root; boost::json::object join_obj; -- cgit v1.3 From b1822e36e531a3c423404f0aa875cbf6949061a0 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 27 Mar 2025 20:04:24 +0200 Subject: #3784 Increase texture scale boundaries --- .../skins/default/xui/en/panel_tools_texture.xml | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml index 9a19d06432..af6a9b94d9 100644 --- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml +++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml @@ -729,8 +729,8 @@ label_width="205" layout="topleft" left="10" - min_val="-100" - max_val="100" + min_val="-10000" + max_val="10000" name="TexScaleU" top_pad="5" width="265" /> @@ -742,8 +742,8 @@ label_width="205" layout="topleft" left="10" - min_val="-100" - max_val="100" + min_val="-10000" + max_val="10000" name="TexScaleV" width="265" /> @@ -818,8 +818,8 @@ label_width="205" layout="topleft" left="10" - min_val="-100" - max_val="100" + min_val="-10000" + max_val="10000" name="bumpyScaleV" width="265" /> @@ -882,8 +882,8 @@ label_width="205" layout="topleft" left="10" - min_val="-100" - max_val="100" + min_val="-10000" + max_val="10000" name="shinyScaleV" width="265" /> Date: Sat, 29 Mar 2025 14:40:33 +0200 Subject: #3836 Fix crash at LLNotificationForm::getNumElements()/LLSD::size() --- indra/llui/llnotifications.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'indra') diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 6fc9b90fb8..634d8f71a2 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -614,6 +614,13 @@ void LLNotification::cancel() LLSD LLNotification::getResponseTemplate(EResponseTemplateType type) { LLSD response = LLSD::emptyMap(); + + if (!mForm) + { + LL_WARNS("Notifications") << "Null form when getting response template for notification " << getName() << LL_ENDL; + return response; + } + for (S32 element_idx = 0; element_idx < mForm->getNumElements(); ++element_idx) @@ -1465,6 +1472,13 @@ bool LLNotifications::templateExists(std::string_view name) void LLNotifications::forceResponse(const LLNotification::Params& params, S32 option) { LLNotificationPtr temp_notify(new LLNotification(params)); + + if (!temp_notify->getForm()) + { + LL_WARNS("Notifications") << "Cannot force response for notification with null form: " << (std::string)params.name << LL_ENDL; + return; + } + LLSD response = temp_notify->getResponseTemplate(); LLSD selected_item = temp_notify->getForm()->getElement(option); -- cgit v1.3 From e671cb54fee9cb7b7da39953eb96eabc9151f687 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 29 Mar 2025 22:40:59 +0200 Subject: #3795 Crash at getVolatileAPRPool() --- indra/llcommon/workqueue.cpp | 4 ++-- indra/llui/llcommandmanager.cpp | 2 ++ indra/llui/llnotifications.cpp | 18 +++++++++++++++++- indra/llui/llnotifications.h | 2 +- indra/newview/llappviewer.cpp | 27 ++++++++++++++++++++------- indra/newview/llviewerwindow.cpp | 2 +- 6 files changed, 43 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp index dace95aaf2..c8ece616b2 100644 --- a/indra/llcommon/workqueue.cpp +++ b/indra/llcommon/workqueue.cpp @@ -183,12 +183,12 @@ void LL::WorkQueueBase::callWork(const Work& work) catch (...) { // Stash any other kind of uncaught exception to be rethrown by main thread. - LL_WARNS("LLCoros") << "Capturing uncaught exception in WorkQueueBase " + LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase " << getKey() << LL_ENDL; LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop"); main_queue->post( - // Bind the current exception rethrow it in main loop. + // Bind the current exception, rethrow it in main loop. [exc = std::current_exception()]() { std::rethrow_exception(exc); }); } #endif // else LL_WINDOWS diff --git a/indra/llui/llcommandmanager.cpp b/indra/llui/llcommandmanager.cpp index 03717da80b..b10ec51f18 100644 --- a/indra/llui/llcommandmanager.cpp +++ b/indra/llui/llcommandmanager.cpp @@ -170,12 +170,14 @@ bool LLCommandManager::load() if (!parser.readXUI(commands_file, commandsParams)) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Unable to load xml file: " << commands_file << LL_ENDL; return false; } if (!commandsParams.validateBlock()) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Invalid commands file: " << commands_file << LL_ENDL; return false; } diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 634d8f71a2..a05feab1d9 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1256,10 +1256,26 @@ LLNotifications::LLNotifications() LLInstanceTracker::instanceCount(); } + +LLNotifications::~LLNotifications() +{ + // Clear explicitly, something in ~LLNotifications() crashes so narrowing down suspects + pHistoryChannel = nullptr; + pExpirationChannel = nullptr; + mGlobalStrings.clear(); + mTemplates.clear(); + mVisibilityRules.clear(); + mUniqueNotifications.clear(); + mListener = nullptr; +} + void LLNotifications::clear() { mDefaultChannels.clear(); - mTemplates.clear(); + // At this point mTemplates still gets used by lingering notifications + // to do responses (ex: group notice will call forceResponse()), but + // since network should be down and everything save, it's questionable + // whether it should stay that way } // The expiration channel gets all notifications that are cancelled diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 46286457cf..138f1969d5 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -887,7 +887,7 @@ class LLNotifications : { LLSINGLETON(LLNotifications); LOG_CLASS(LLNotifications); - virtual ~LLNotifications() {} + virtual ~LLNotifications(); public: diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0ffe675a7b..7653b5ee8e 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5216,15 +5216,28 @@ void LLAppViewer::sendLogoutRequest() gLogoutInProgress = true; if (!mSecondInstance) { - mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME); - - mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB); - if (mLogoutMarkerFile.getFileHandle()) + mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LOGOUT_MARKER_FILE_NAME); + try { - LL_INFOS("MarkerFile") << "Created logout marker file '"<< mLogoutMarkerFileName << "' " << LL_ENDL; - recordMarkerVersion(mLogoutMarkerFile); + if (!mLogoutMarkerFile.getFileHandle()) + { + mLogoutMarkerFile.open(mLogoutMarkerFileName, LL_APR_WB); + if (mLogoutMarkerFile.getFileHandle()) + { + LL_INFOS("MarkerFile") << "Created logout marker file '" << mLogoutMarkerFileName << "' " << LL_ENDL; + recordMarkerVersion(mLogoutMarkerFile); + } + else + { + LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL; + } + } + else + { + LL_WARNS("MarkerFile") << "Atempted to reopen file '" << mLogoutMarkerFileName << "' " << LL_ENDL; + } } - else + catch (...) { LL_WARNS("MarkerFile") << "Cannot create logout marker file " << mLogoutMarkerFileName << LL_ENDL; } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index fe5a0667a5..93ff175967 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1457,7 +1457,7 @@ void LLViewerWindow::handleMouseLeave(LLWindow *window) bool LLViewerWindow::handleCloseRequest(LLWindow *window) { - if (!LLApp::isExiting()) + if (!LLApp::isExiting() && !LLApp::isStopped()) { // User has indicated they want to close, but we may need to ask // about modified documents. -- cgit v1.3 From 8d5dab9f67d54ce20768c0ccda58f27693cb20c9 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 28 Mar 2025 21:49:58 +0200 Subject: #3809 Fix J2C Upload --- indra/llimage/llimagedimensionsinfo.cpp | 20 ++++++++++++++++++++ indra/llimage/llimagedimensionsinfo.h | 1 + indra/newview/llfilepicker.cpp | 6 ++++-- indra/newview/lllocalbitmaps.cpp | 20 ++++++++++++++++++++ indra/newview/lllocalbitmaps.h | 1 + indra/newview/llviewermenufile.cpp | 2 +- indra/newview/llviewertexturelist.cpp | 9 +++++++++ 7 files changed, 56 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp index d4efbcfad2..49a1777fe5 100644 --- a/indra/llimage/llimagedimensionsinfo.cpp +++ b/indra/llimage/llimagedimensionsinfo.cpp @@ -27,6 +27,7 @@ #include "stdtypes.h" #include "llimagejpeg.h" +#include "llimagej2c.h" #include "llimagedimensionsinfo.h" @@ -63,6 +64,8 @@ bool LLImageDimensionsInfo::load(const std::string& src_filename,U32 codec) return getImageDimensionsTga(); case IMG_CODEC_JPEG: return getImageDimensionsJpeg(); + case IMG_CODEC_J2C: + return getImageDimensionsJ2c(); case IMG_CODEC_PNG: return getImageDimensionsPng(); default: @@ -214,6 +217,23 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg() return !sJpegErrorEncountered; } +bool LLImageDimensionsInfo::getImageDimensionsJ2c() +{ + clean(); + + LLPointer jpeg_image = new LLImageJ2C; + if (jpeg_image->load(mSrcFilename)) + { + mWidth = jpeg_image->getWidth(); + mHeight = jpeg_image->getHeight(); + return true; + } + mWarning = "texture_load_format_error"; + LL_WARNS() << "J2C load error: " << LLImage::getLastThreadError() << LL_ENDL; + + return false; +} + bool LLImageDimensionsInfo::checkFileLength(S32 min_len) { // Make sure the file is not shorter than min_len bytes. diff --git a/indra/llimage/llimagedimensionsinfo.h b/indra/llimage/llimagedimensionsinfo.h index 681d66ae4e..820cf33d7e 100644 --- a/indra/llimage/llimagedimensionsinfo.h +++ b/indra/llimage/llimagedimensionsinfo.h @@ -91,6 +91,7 @@ protected: bool getImageDimensionsTga(); bool getImageDimensionsPng(); bool getImageDimensionsJpeg(); + bool getImageDimensionsJ2c(); S32 read_s32() { diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 716e6cd9e3..96ac41a2bf 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -52,7 +52,7 @@ LLFilePicker LLFilePicker::sInstance; #if LL_WINDOWS #define SOUND_FILTER L"Sounds (*.wav)\0*.wav\0" -#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0" +#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.j2c; *.jp2; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.j2c;*.jp2;*.png\0" #define ANIM_FILTER L"Animations (*.bvh; *.anim)\0*.bvh;*.anim\0" #define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0" #define GLTF_FILTER L"glTF (*.gltf; *.glb)\0*.gltf;*.glb\0" @@ -559,7 +559,7 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, } mOFN.lpstrDefExt = L"j2c"; mOFN.lpstrFilter = - L"Compressed Images (*.j2c)\0*.j2c\0" \ + L"Compressed Images (*.j2c *.jp2)\0*.j2c;*.jp2\0" \ L"\0"; break; case FFSAVE_SCRIPT: @@ -649,6 +649,8 @@ std::unique_ptr> LLFilePicker::navOpenFilterProc(ELoadF case FFLOAD_IMAGE: allowedv->push_back("jpg"); allowedv->push_back("jpeg"); + allowedv->push_back("j2c"); + allowedv->push_back("jp2"); allowedv->push_back("bmp"); allowedv->push_back("tga"); allowedv->push_back("bmpf"); diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 31c9eb8966..72a7fe8814 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -38,6 +38,7 @@ /* image compression headers. */ #include "llimagebmp.h" #include "llimagetga.h" +#include "llimagej2c.h" #include "llimagejpeg.h" #include "llimagepng.h" @@ -106,6 +107,10 @@ LLLocalBitmap::LLLocalBitmap(std::string filename) { mExtension = ET_IMG_JPG; } + else if (temp_exten == "j2c" || temp_exten == "jp2") + { + mExtension = ET_IMG_J2C; + } else if (temp_exten == "png") { mExtension = ET_IMG_PNG; @@ -356,6 +361,21 @@ bool LLLocalBitmap::decodeBitmap(LLPointer rawimg) break; } + case ET_IMG_J2C: + { + LLPointer jpeg_image = new LLImageJ2C; + if (jpeg_image->load(mFilename)) + { + jpeg_image->setDiscardLevel(0); + if (jpeg_image->decode(rawimg, 0.0f)) + { + rawimg->biasedScaleToPowerOfTwo(LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT); + decode_successful = true; + } + } + break; + } + case ET_IMG_PNG: { LLPointer png_image = new LLImagePNG; diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index e169f96e70..06770334e4 100644 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -89,6 +89,7 @@ class LLLocalBitmap ET_IMG_BMP, ET_IMG_TGA, ET_IMG_JPG, + ET_IMG_J2C, ET_IMG_PNG }; diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index ce66dbc03f..7a079b267d 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -378,7 +378,7 @@ void LLMediaFilePicker::notify(const std::vector& filenames) #if LL_WINDOWS static std::string SOUND_EXTENSIONS = "wav"; -static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png"; +static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg j2c jp2 png"; static std::string ANIM_EXTENSIONS = "bvh anim"; static std::string XML_EXTENSIONS = "xml"; static std::string SLOBJECT_EXTENSIONS = "slobject"; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index ae723b4068..9f23d39506 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1419,6 +1419,15 @@ bool LLViewerTextureList::createUploadFile(const std::string& filename, image->setLastError("Couldn't load the image to be uploaded."); return false; } + + // calcDataSizeJ2C assumes maximum size is 2048 and for bigger images can + // assign discard to bring imige to needed size, but upload does the scaling + // as needed, so just reset discard. + // Assume file is full and has 'discard' 0 data. + // Todo: probably a better idea to have some setMaxDimentions in J2C + // called when loading from a local file + image->setDiscardLevel(0); + // Decompress or expand it in a raw image structure LLPointer raw_image = new LLImageRaw; if (!image->decode(raw_image, 0.0f)) -- cgit v1.3 From fcc8ffda16ee409e5952e3ca1d872bee786514df Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 31 Mar 2025 14:33:12 +0300 Subject: #3809 Partial revert of "Fix J2C Upload" This partially reverts commit 8d5dab9f67d54ce20768c0ccda58f27693cb20c9. Apparently viewer doesn't support some jp2 variants, so I'm leaving only the fix for bulk upload. --- indra/llimage/llimagedimensionsinfo.cpp | 20 -------------------- indra/llimage/llimagedimensionsinfo.h | 1 - indra/newview/llfilepicker.cpp | 6 ++---- indra/newview/llviewermenufile.cpp | 2 +- 4 files changed, 3 insertions(+), 26 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp index 49a1777fe5..d4efbcfad2 100644 --- a/indra/llimage/llimagedimensionsinfo.cpp +++ b/indra/llimage/llimagedimensionsinfo.cpp @@ -27,7 +27,6 @@ #include "stdtypes.h" #include "llimagejpeg.h" -#include "llimagej2c.h" #include "llimagedimensionsinfo.h" @@ -64,8 +63,6 @@ bool LLImageDimensionsInfo::load(const std::string& src_filename,U32 codec) return getImageDimensionsTga(); case IMG_CODEC_JPEG: return getImageDimensionsJpeg(); - case IMG_CODEC_J2C: - return getImageDimensionsJ2c(); case IMG_CODEC_PNG: return getImageDimensionsPng(); default: @@ -217,23 +214,6 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg() return !sJpegErrorEncountered; } -bool LLImageDimensionsInfo::getImageDimensionsJ2c() -{ - clean(); - - LLPointer jpeg_image = new LLImageJ2C; - if (jpeg_image->load(mSrcFilename)) - { - mWidth = jpeg_image->getWidth(); - mHeight = jpeg_image->getHeight(); - return true; - } - mWarning = "texture_load_format_error"; - LL_WARNS() << "J2C load error: " << LLImage::getLastThreadError() << LL_ENDL; - - return false; -} - bool LLImageDimensionsInfo::checkFileLength(S32 min_len) { // Make sure the file is not shorter than min_len bytes. diff --git a/indra/llimage/llimagedimensionsinfo.h b/indra/llimage/llimagedimensionsinfo.h index 820cf33d7e..681d66ae4e 100644 --- a/indra/llimage/llimagedimensionsinfo.h +++ b/indra/llimage/llimagedimensionsinfo.h @@ -91,7 +91,6 @@ protected: bool getImageDimensionsTga(); bool getImageDimensionsPng(); bool getImageDimensionsJpeg(); - bool getImageDimensionsJ2c(); S32 read_s32() { diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 96ac41a2bf..716e6cd9e3 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -52,7 +52,7 @@ LLFilePicker LLFilePicker::sInstance; #if LL_WINDOWS #define SOUND_FILTER L"Sounds (*.wav)\0*.wav\0" -#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.j2c; *.jp2; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.j2c;*.jp2;*.png\0" +#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0" #define ANIM_FILTER L"Animations (*.bvh; *.anim)\0*.bvh;*.anim\0" #define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0" #define GLTF_FILTER L"glTF (*.gltf; *.glb)\0*.gltf;*.glb\0" @@ -559,7 +559,7 @@ bool LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, } mOFN.lpstrDefExt = L"j2c"; mOFN.lpstrFilter = - L"Compressed Images (*.j2c *.jp2)\0*.j2c;*.jp2\0" \ + L"Compressed Images (*.j2c)\0*.j2c\0" \ L"\0"; break; case FFSAVE_SCRIPT: @@ -649,8 +649,6 @@ std::unique_ptr> LLFilePicker::navOpenFilterProc(ELoadF case FFLOAD_IMAGE: allowedv->push_back("jpg"); allowedv->push_back("jpeg"); - allowedv->push_back("j2c"); - allowedv->push_back("jp2"); allowedv->push_back("bmp"); allowedv->push_back("tga"); allowedv->push_back("bmpf"); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 7a079b267d..ce66dbc03f 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -378,7 +378,7 @@ void LLMediaFilePicker::notify(const std::vector& filenames) #if LL_WINDOWS static std::string SOUND_EXTENSIONS = "wav"; -static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg j2c jp2 png"; +static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png"; static std::string ANIM_EXTENSIONS = "bvh anim"; static std::string XML_EXTENSIONS = "xml"; static std::string SLOBJECT_EXTENSIONS = "slobject"; -- cgit v1.3 From 515c1f15d835f1e8c45828722d8ad91b0604408c Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 31 Mar 2025 19:06:06 +0300 Subject: #3044 Add option to hide L$ balance for Snapshots with Interface showing --- indra/newview/app_settings/settings.xml | 11 ++++++ indra/newview/llappviewer.cpp | 1 + indra/newview/llfloatersnapshot.cpp | 44 ++++++---------------- indra/newview/llfloatersnapshot.h | 3 +- indra/newview/llsnapshotlivepreview.cpp | 2 + indra/newview/llstatusbar.cpp | 4 ++ indra/newview/llstatusbar.h | 2 + indra/newview/llviewermenufile.cpp | 2 + indra/newview/llviewermessage.cpp | 2 + indra/newview/llviewerwindow.cpp | 21 +++++++++-- indra/newview/llviewerwindow.h | 10 +++-- indra/newview/llviewerwindowlistener.cpp | 2 +- .../skins/default/xui/en/floater_snapshot.xml | 14 ++++++- 13 files changed, 74 insertions(+), 44 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0c83355a81..86d36b3f29 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9540,6 +9540,17 @@ Value 0 + RenderBalanceInSnapshot + + Comment + Display L$ balance in snapshot + Persist + 1 + Type + Boolean + Value + 1 + RenderUIBuffer Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 4cf651de33..3f7aaf9557 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4540,6 +4540,7 @@ void LLAppViewer::saveFinalSnapshot() false, gSavedSettings.getBOOL("RenderHUDInSnapshot"), true, + false, LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::SNAPSHOT_FORMAT_PNG); mSavedFinalSnapshot = true; diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 68b9e758a1..faf7ed0d8c 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -60,12 +60,13 @@ LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* { LLSideTrayPanelContainer* panel_container = floater->getChild("panel_container"); LLPanelSnapshot* active_panel = dynamic_cast(panel_container->getCurrentPanel()); - if (!active_panel) - { - LL_WARNS() << "No snapshot active panel, current panel index: " << panel_container->getCurrentPanelIndex() << LL_ENDL; - } + if (!ok_if_not_found) { + if (!active_panel) + { + LL_WARNS() << "No snapshot active panel, current panel index: " << panel_container->getCurrentPanelIndex() << LL_ENDL; + } llassert_always(active_panel != NULL); } return active_panel; @@ -516,34 +517,13 @@ void LLFloaterSnapshotBase::ImplBase::onClickFilter(LLUICtrl *ctrl, void* data) } // static -void LLFloaterSnapshotBase::ImplBase::onClickUICheck(LLUICtrl *ctrl, void* data) +void LLFloaterSnapshotBase::ImplBase::onClickDisplaySetting(LLUICtrl* ctrl, void* data) { - LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; - gSavedSettings.setBOOL( "RenderUIInSnapshot", check->get() ); - - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLFloaterSnapshot* view = (LLFloaterSnapshot*)data; if (view) { LLSnapshotLivePreview* previewp = view->getPreviewView(); - if(previewp) - { - previewp->updateSnapshot(true, true); - } - view->impl->updateControls(view); - } -} - -// static -void LLFloaterSnapshotBase::ImplBase::onClickHUDCheck(LLUICtrl *ctrl, void* data) -{ - LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; - gSavedSettings.setBOOL( "RenderHUDInSnapshot", check->get() ); - - LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; - if (view) - { - LLSnapshotLivePreview* previewp = view->getPreviewView(); - if(previewp) + if (previewp) { previewp->updateSnapshot(true, true); } @@ -1002,11 +982,9 @@ bool LLFloaterSnapshot::postBuild() mSucceessLblPanel = getChild("succeeded_panel"); mFailureLblPanel = getChild("failed_panel"); - childSetCommitCallback("ui_check", ImplBase::onClickUICheck, this); - getChild("ui_check")->setValue(gSavedSettings.getBOOL("RenderUIInSnapshot")); - - childSetCommitCallback("hud_check", ImplBase::onClickHUDCheck, this); - getChild("hud_check")->setValue(gSavedSettings.getBOOL("RenderHUDInSnapshot")); + childSetCommitCallback("ui_check", ImplBase::onClickDisplaySetting, this); + childSetCommitCallback("balance_check", ImplBase::onClickDisplaySetting, this); + childSetCommitCallback("hud_check", ImplBase::onClickDisplaySetting, this); ((Impl*)impl)->setAspectRatioCheckboxValue(this, gSavedSettings.getBOOL("KeepAspectForSnapshot")); diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index 6df851b839..186d9c41cf 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -103,8 +103,7 @@ public: static void onClickAutoSnap(LLUICtrl *ctrl, void* data); static void onClickNoPost(LLUICtrl *ctrl, void* data); static void onClickFilter(LLUICtrl *ctrl, void* data); - static void onClickUICheck(LLUICtrl *ctrl, void* data); - static void onClickHUDCheck(LLUICtrl *ctrl, void* data); + static void onClickDisplaySetting(LLUICtrl *ctrl, void* data); static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data); virtual LLPanelSnapshot* getActivePanel(LLFloaterSnapshotBase* floater, bool ok_if_not_found = true) = 0; diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index ea95d71b27..68b4ab381a 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -694,6 +694,7 @@ bool LLSnapshotLivePreview::onIdle( void* snapshot_preview ) static LLCachedControl freeze_time(gSavedSettings, "FreezeTime", false); static LLCachedControl use_freeze_frame(gSavedSettings, "UseFreezeFrame", false); static LLCachedControl render_ui(gSavedSettings, "RenderUIInSnapshot", false); + static LLCachedControl render_balance(gSavedSettings, "RenderBalanceInSnapshot", false); static LLCachedControl render_hud(gSavedSettings, "RenderHUDInSnapshot", false); static LLCachedControl render_no_post(gSavedSettings, "RenderSnapshotNoPost", false); @@ -750,6 +751,7 @@ bool LLSnapshotLivePreview::onIdle( void* snapshot_preview ) render_hud, false, render_no_post, + render_balance, previewp->mSnapshotBufferType, previewp->getMaxImageSize())) { diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index ecbbc4b2c5..8aa2058ae1 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -738,6 +738,10 @@ void LLStatusBar::updateBalancePanelPosition() balance_bg_view->setShape(balance_bg_rect); } +void LLStatusBar::setBalanceVisible(bool visible) +{ + mBoxBalance->setVisible(visible); +} // Implements secondlife:///app/balance/request to request a L$ balance // update via UDP message system. JC diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 4c9d3e0c08..45cbda0ef1 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -93,6 +93,8 @@ public: S32 getSquareMetersCommitted() const; S32 getSquareMetersLeft() const; + void setBalanceVisible(bool visible); + LLPanelNearByMedia* getNearbyMediaPanel() { return mPanelNearByMedia; } private: diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index ce66dbc03f..9743ec0c59 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -932,6 +932,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t bool render_ui = gSavedSettings.getBOOL("RenderUIInSnapshot"); bool render_hud = gSavedSettings.getBOOL("RenderHUDInSnapshot"); bool render_no_post = gSavedSettings.getBOOL("RenderSnapshotNoPost"); + bool render_balance = gSavedSettings.getBOOL("RenderBalanceInSnapshot"); bool high_res = gSavedSettings.getBOOL("HighResSnapshot"); if (high_res) @@ -952,6 +953,7 @@ class LLFileTakeSnapshotToDisk : public view_listener_t render_hud, false, render_no_post, + render_balance, LLSnapshotModel::SNAPSHOT_TYPE_COLOR, high_res ? S32_MAX : MAX_SNAPSHOT_IMAGE_SIZE)) //per side { diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 7890a571b2..b274ba5abb 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5039,6 +5039,7 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) false, //UI gSavedSettings.getBOOL("RenderHUDInSnapshot"), false, + false, LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::SNAPSHOT_FORMAT_PNG); } @@ -5144,6 +5145,7 @@ static void process_special_alert_messages(const std::string & message) false, gSavedSettings.getBOOL("RenderHUDInSnapshot"), false, + false, LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::SNAPSHOT_FORMAT_PNG); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 4194dd00e7..a133febb85 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4849,12 +4849,12 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height) } } -bool LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, bool show_ui, bool show_hud, bool do_rebuild, LLSnapshotModel::ESnapshotLayerType type, LLSnapshotModel::ESnapshotFormat format) +bool LLViewerWindow::saveSnapshot(const std::string& filepath, S32 image_width, S32 image_height, bool show_ui, bool show_hud, bool do_rebuild, bool show_balance, LLSnapshotModel::ESnapshotLayerType type, LLSnapshotModel::ESnapshotFormat format) { LL_INFOS() << "Saving snapshot to: " << filepath << LL_ENDL; LLPointer raw = new LLImageRaw; - bool success = rawSnapshot(raw, image_width, image_height, true, false, show_ui, show_hud, do_rebuild); + bool success = rawSnapshot(raw, image_width, image_height, true, false, show_ui, show_hud, do_rebuild, show_balance); if (success) { @@ -4915,14 +4915,14 @@ void LLViewerWindow::resetSnapshotLoc() const bool LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, bool show_ui, bool show_hud, bool do_rebuild, bool no_post, LLSnapshotModel::ESnapshotLayerType type) { - return rawSnapshot(raw, preview_width, preview_height, false, false, show_ui, show_hud, do_rebuild, no_post, type); + return rawSnapshot(raw, preview_width, preview_height, false, false, show_ui, show_hud, do_rebuild, no_post, gSavedSettings.getBOOL("RenderBalanceInSnapshot"), type); } // Saves the image from the screen to a raw image // Since the required size might be bigger than the available screen, this method rerenders the scene in parts (called subimages) and copy // the results over to the final raw image. bool LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, - bool keep_window_aspect, bool is_texture, bool show_ui, bool show_hud, bool do_rebuild, bool no_post, LLSnapshotModel::ESnapshotLayerType type, S32 max_size) + bool keep_window_aspect, bool is_texture, bool show_ui, bool show_hud, bool do_rebuild, bool no_post, bool show_balance, LLSnapshotModel::ESnapshotLayerType type, S32 max_size) { if (!raw) { @@ -4980,6 +4980,8 @@ bool LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei // If the user wants the UI, limit the output size to the available screen size image_width = llmin(image_width, window_width); image_height = llmin(image_height, window_height); + + setBalanceVisible(show_balance); } S32 original_width = 0; @@ -5057,11 +5059,13 @@ bool LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei } else { + setBalanceVisible(true); return false; } if (raw->isBufferInvalid()) { + setBalanceVisible(true); return false; } @@ -5237,6 +5241,7 @@ bool LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei { send_agent_resume(); } + setBalanceVisible(true); return ret; } @@ -5702,6 +5707,14 @@ void LLViewerWindow::setProgressCancelButtonVisible( bool b, const std::string& } } +void LLViewerWindow::setBalanceVisible(bool visible) +{ + if (gStatusBar) + { + gStatusBar->setBalanceVisible(visible); + } +} + LLProgressView *LLViewerWindow::getProgressView() const { return mProgressView; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index ac0dfa3fe4..d55c2d3817 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -364,9 +364,11 @@ public: // snapshot functionality. // perhaps some of this should move to llfloatershapshot? -MG - bool saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, bool show_ui = true, bool show_hud = true, bool do_rebuild = false, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::ESnapshotFormat format = LLSnapshotModel::SNAPSHOT_FORMAT_BMP); - bool rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, bool keep_window_aspect = true, bool is_texture = false, - bool show_ui = true, bool show_hud = true, bool do_rebuild = false, bool no_post = false, LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE); + bool saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, bool show_ui = true, bool show_hud = true, bool do_rebuild = false, bool show_balance = true, + LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, LLSnapshotModel::ESnapshotFormat format = LLSnapshotModel::SNAPSHOT_FORMAT_BMP); + bool rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, bool keep_window_aspect = true, bool is_texture = false, + bool show_ui = true, bool show_hud = true, bool do_rebuild = false, bool no_post = false, bool show_balance = true, + LLSnapshotModel::ESnapshotLayerType type = LLSnapshotModel::SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE); bool simpleSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, const int num_render_passes); @@ -462,6 +464,8 @@ public: void calcDisplayScale(); static LLRect calcScaledRect(const LLRect & rect, const LLVector2& display_scale); + void setBalanceVisible(bool visible); + static std::string getLastSnapshotDir(); LLView* getFloaterSnapRegion() { return mFloaterSnapRegion; } diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp index da7e18af5c..3119c31613 100644 --- a/indra/newview/llviewerwindowlistener.cpp +++ b/indra/newview/llviewerwindowlistener.cpp @@ -100,7 +100,7 @@ void LLViewerWindowListener::saveSnapshot(const LLSD& event) const } type = found->second; } - bool ok = mViewerWindow->saveSnapshot(event["filename"], width, height, showui, showhud, rebuild, type); + bool ok = mViewerWindow->saveSnapshot(event["filename"], width, height, showui, showhud, rebuild, true /*L$ Balance*/, type); sendReply(LLSDMap("ok", ok), event); } diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index e6b780728c..acdccdc03a 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -167,8 +167,19 @@ left="30" height="16" top_pad="8" - width="180" + width="80" + control_name="RenderUIInSnapshot" name="ui_check" /> + Date: Mon, 31 Mar 2025 21:59:41 +0300 Subject: #3814 More bad_alloc handling warn user and error --- indra/llmath/llvolume.cpp | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 44b6e7923b..76e5e3aae9 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5586,14 +5586,22 @@ struct MikktData { U32 count = face->mNumIndices; - p.resize(count); - n.resize(count); - tc.resize(count); - t.resize(count); + try + { + p.resize(count); + n.resize(count); + tc.resize(count); + t.resize(count); - if (face->mWeights) + if (face->mWeights) + { + w.resize(count); + } + } + catch (std::bad_alloc&) { - w.resize(count); + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLCoros") << "Bad memory allocation in MikktData, elements count: " << count << LL_ENDL; } @@ -5665,7 +5673,16 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) // and is executed on a background thread MikktData data(this); mikk::Mikktspace ctx(data); - ctx.genTangSpace(); + try + { + ctx.genTangSpace(); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLCoros") << "Bad memory allocation in MikktData::genTangSpace" << LL_ENDL; + } + //re-weld meshopt_Stream mos[] = @@ -5678,7 +5695,15 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents) }; std::vector remap; - remap.resize(data.p.size()); + try + { + remap.resize(data.p.size()); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLCoros") << "Failed to allocate memory for remap: " << (S32)data.p.size() << LL_ENDL; + } U32 stream_count = data.w.empty() ? 4 : 5; -- cgit v1.3 From c609a45c26dae083cedc8d06566564cb55d2e72e Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Wed, 17 Apr 2024 16:58:48 +0200 Subject: secondlife/viewer#912 BugSplat Crash 1412267 (missed refactoring for FindModel) # Conflicts: # indra/newview/llmodelpreview.cpp --- indra/newview/llmodelpreview.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 29ab4e38c0..4ac3abd747 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -132,7 +132,7 @@ std::string getLodSuffix(S32 lod) return suffix; } -void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut) +static bool FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut) { for (auto scene_iter = scene.begin(); scene_iter != scene.end(); scene_iter++) { @@ -142,10 +142,11 @@ void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LL { baseModelOut = model_iter->mModel; matOut = scene_iter->first; - return; + return true; } } } + return false; } //----------------------------------------------------------------------------- @@ -319,10 +320,8 @@ void LLModelPreview::rebuildUploadData() mat *= scale_mat; - for (auto model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) - { // for each instance with said transform applied - LLModelInstance instance = *model_iter; - + for (LLModelInstance& instance : iter->second) + { //for each instance with said transform applied LLModel* base_model = instance.mModel; if (base_model && !requested_name.empty()) @@ -354,7 +353,7 @@ void LLModelPreview::rebuildUploadData() } else { - //Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for + // Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for extensionLOD = mPhysicsSearchLOD; } @@ -365,9 +364,9 @@ void LLModelPreview::rebuildUploadData() name_to_match += toAdd; } - FindModel(mScene[i], name_to_match, lod_model, transform); + bool found = FindModel(mScene[i], name_to_match, lod_model, transform); - if (!lod_model && i != LLModel::LOD_PHYSICS) + if (!found && i != LLModel::LOD_PHYSICS) { if (mImporterDebug) { @@ -380,7 +379,7 @@ void LLModelPreview::rebuildUploadData() } int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i; - while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model) + for (; searchLOD <= LLModel::LOD_HIGH; ++searchLOD) { std::string name_to_match = instance.mLabel; llassert(!name_to_match.empty()); @@ -394,8 +393,8 @@ void LLModelPreview::rebuildUploadData() // See if we can find an appropriately named model in LOD 'searchLOD' // - FindModel(mScene[searchLOD], name_to_match, lod_model, transform); - searchLOD++; + if (FindModel(mScene[searchLOD], name_to_match, lod_model, transform)) + break; } } } @@ -1174,8 +1173,7 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod) LLModel* found_model = NULL; LLMatrix4 transform; - FindModel(mBaseScene, loaded_name, found_model, transform); - if (found_model) + if (FindModel(mBaseScene, loaded_name, found_model, transform)) { // don't rename correctly named models (even if they are placed in a wrong order) name_based = true; } -- cgit v1.3 From 497c309a5b148fd86a0e1429343092f0a6ca2e0d Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Tue, 1 Apr 2025 15:02:24 +0300 Subject: #912 Refactor FindModel() --- indra/newview/llmodelpreview.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 4ac3abd747..5a8fd299bf 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -132,16 +132,16 @@ std::string getLodSuffix(S32 lod) return suffix; } -static bool FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut) +static bool FindModel(const LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut) { - for (auto scene_iter = scene.begin(); scene_iter != scene.end(); scene_iter++) + for (const auto& scene_pair : scene) { - for (auto model_iter = scene_iter->second.begin(); model_iter != scene_iter->second.end(); model_iter++) + for (const auto& model_iter : scene_pair.second) { - if (model_iter->mModel && (model_iter->mModel->mLabel == name_to_match)) + if (model_iter.mModel && (model_iter.mModel->mLabel == name_to_match)) { - baseModelOut = model_iter->mModel; - matOut = scene_iter->first; + baseModelOut = model_iter.mModel; + matOut = scene_pair.first; return true; } } -- cgit v1.3 From 3a03c5f8fe00ae23a33c823625052f39fb42501e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 1 Apr 2025 16:30:21 +0300 Subject: #3846 Crash at updateGLTFMaterials --- indra/newview/lllocalbitmaps.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 75c77e9301..e31fbb188a 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -700,11 +700,15 @@ void LLLocalBitmap::updateGLTFMaterials(LLUUID old_id, LLUUID new_id) // do not create a new material, reuse existing pointer // so that mTextureEntires remains untouched LLGLTFMaterial* render_mat = entry->getGLTFRenderMaterial(); - if (render_mat) + if (render_mat && render_mat != mat) { *render_mat = *mat; render_mat->applyOverride(*override_mat); // can update mGLTFMaterialWithLocalTextures } + else + { + LL_WARNS() << "A TE had an override, but no render material" << LL_ENDL; + } } } } -- cgit v1.3 From 8c20662ff77a9672917aa127f80a2fa9efda7119 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 1 Apr 2025 20:35:52 +0300 Subject: #3712 CMakeFindFrameworks deprecation --- indra/cmake/Linking.cmake | 1 - indra/llwindow/CMakeLists.txt | 1 - 2 files changed, 2 deletions(-) (limited to 'indra') diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index 1d757abeff..1093fc7f71 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -67,7 +67,6 @@ elseif (WINDOWS) legacy_stdio_definitions ) else() - include(CMakeFindFrameworks) find_library(COREFOUNDATION_LIBRARY CoreFoundation) find_library(CARBON_LIBRARY Carbon) find_library(COCOA_LIBRARY Cocoa) diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 2996f58fe0..5bfac34ca5 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -182,7 +182,6 @@ endif (SDL_FOUND) target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) if (DARWIN) - include(CMakeFindFrameworks) find_library(CARBON_LIBRARY Carbon) target_link_libraries(llwindow ${CARBON_LIBRARY}) endif (DARWIN) -- cgit v1.3 From 939817d560434cdc2888ef478b965f5625a381b7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 1 Apr 2025 21:16:38 +0300 Subject: #3849 Crash at LLSelectMgr::updatePointAt --- indra/newview/llselectmgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 3d17446186..be1e64ce54 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -7513,7 +7513,7 @@ void LLSelectMgr::updatePointAt() LLVector3 select_offset; const LLPickInfo& pick = gViewerWindow->getLastPick(); LLViewerObject *click_object = pick.getObject(); - bool was_hud = pick.mPickHUD && !click_object->isHUDAttachment(); + bool was_hud = pick.mPickHUD && click_object && !click_object->isHUDAttachment(); if (click_object && click_object->isSelected() && !was_hud) { // clicked on another object in our selection group, use that as target -- cgit v1.3 From d77954ef50f300846eb14034a8dde3e4d7064dcf Mon Sep 17 00:00:00 2001 From: Andrey Lihatskiy Date: Wed, 2 Apr 2025 01:50:21 +0300 Subject: #3597 Improve error handling at LLGLSLShader::disableTexture() --- indra/llrender/llglslshader.cpp | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index b3f32fdc83..50e40a3eb6 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -1247,23 +1247,40 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) llassert(false); return -1; } + S32 index = mTexture[uniform]; - if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE) + if (index < 0) + { + // Invalid texture index - nothing to disable + return index; + } + + LLTexUnit* tex_unit = gGL.getTexUnit(index); + if (!tex_unit) { - if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) + // Invalid texture unit + LL_WARNS_ONCE("Shader") << "Invalid texture unit at index: " << index << LL_ENDL; + return index; + } + + LLTexUnit::eTextureType curr_type = tex_unit->getCurrType(); + if (curr_type != LLTexUnit::TT_NONE) + { + if (gDebugGL && curr_type != mode) { if (gDebugSession) { - gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl; + gFailLog << "Texture channel " << index << " texture type corrupted. Expected: " << mode << ", Found: " << curr_type << std::endl; ll_fail("LLGLSLShader::disableTexture failed"); } else { - LL_ERRS() << "Texture channel " << index << " texture type corrupted." << LL_ENDL; + LL_ERRS() << "Texture channel " << index << " texture type corrupted. Expected: " << mode << ", Found: " << curr_type << LL_ENDL; } } - gGL.getTexUnit(index)->disable(); + tex_unit->disable(); } + return index; } -- cgit v1.3 From db2c45ba23a10d34d89f556533f80a8b42600bf6 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Wed, 2 Apr 2025 17:22:17 +0300 Subject: #3857 pick new and updated LEAP functions from develop branch --- indra/newview/llagentlistener.cpp | 387 ++++++++++++++++++++---- indra/newview/llagentlistener.h | 17 +- indra/newview/llfloaterimnearbychat.cpp | 3 + indra/newview/llfloaterimnearbychatlistener.cpp | 34 +-- indra/newview/llfloaterimnearbychatlistener.h | 6 +- 5 files changed, 371 insertions(+), 76 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp index 0c120ae01d..5ddb87558a 100644 --- a/indra/newview/llagentlistener.cpp +++ b/indra/newview/llagentlistener.cpp @@ -31,19 +31,25 @@ #include "llagentlistener.h" #include "llagent.h" +#include "llagentcamera.h" +#include "llavatarname.h" +#include "llavatarnamecache.h" #include "llvoavatar.h" #include "llcommandhandler.h" +#include "llinventorymodel.h" #include "llslurl.h" #include "llurldispatcher.h" +#include "llviewercontrol.h" #include "llviewernetwork.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" +#include "llvoavatarself.h" #include "llsdutil.h" #include "llsdutil_math.h" #include "lltoolgrab.h" #include "llhudeffectlookat.h" -#include "llagentcamera.h" +#include "llviewercamera.h" LLAgentListener::LLAgentListener(LLAgent &agent) : LLEventAPI("LLAgent", @@ -69,13 +75,6 @@ LLAgentListener::LLAgentListener(LLAgent &agent) add("resetAxes", "Set the agent to a fixed orientation (optionally specify [\"lookat\"] = array of [x, y, z])", &LLAgentListener::resetAxes); - add("getAxes", - "Obsolete - use getPosition instead\n" - "Send information about the agent's orientation on [\"reply\"]:\n" - "[\"euler\"]: map of {roll, pitch, yaw}\n" - "[\"quat\"]: array of [x, y, z, w] quaternion values", - &LLAgentListener::getAxes, - LLSDMap("reply", LLSD())); add("getPosition", "Send information about the agent's position and orientation on [\"reply\"]:\n" "[\"region\"]: array of region {x, y, z} position\n" @@ -87,33 +86,34 @@ LLAgentListener::LLAgentListener(LLAgent &agent) add("startAutoPilot", "Start the autopilot system using the following parameters:\n" "[\"target_global\"]: array of target global {x, y, z} position\n" - "[\"stop_distance\"]: target maxiumum distance from target [default: autopilot guess]\n" + "[\"stop_distance\"]: maximum stop distance from target [default: autopilot guess]\n" "[\"target_rotation\"]: array of [x, y, z, w] quaternion values [default: no target]\n" "[\"rotation_threshold\"]: target maximum angle from target facing rotation [default: 0.03 radians]\n" - "[\"behavior_name\"]: name of the autopilot behavior [default: \"\"]" - "[\"allow_flying\"]: allow flying during autopilot [default: True]", - //"[\"callback_pump\"]: pump to send success/failure and callback data to [default: none]\n" - //"[\"callback_data\"]: data to send back during a callback [default: none]", - &LLAgentListener::startAutoPilot); + "[\"behavior_name\"]: name of the autopilot behavior [default: \"\"]\n" + "[\"allow_flying\"]: allow flying during autopilot [default: True]\n" + "event with [\"success\"] flag is sent to 'LLAutopilot' event pump, when auto pilot is terminated", + &LLAgentListener::startAutoPilot, + llsd::map("target_global", LLSD())); add("getAutoPilot", "Send information about current state of the autopilot system to [\"reply\"]:\n" "[\"enabled\"]: boolean indicating whether or not autopilot is enabled\n" "[\"target_global\"]: array of target global {x, y, z} position\n" "[\"leader_id\"]: uuid of target autopilot is following\n" - "[\"stop_distance\"]: target maximum distance from target\n" + "[\"stop_distance\"]: maximum stop distance from target\n" "[\"target_distance\"]: last known distance from target\n" "[\"use_rotation\"]: boolean indicating if autopilot has a target facing rotation\n" "[\"target_facing\"]: array of {x, y} target direction to face\n" "[\"rotation_threshold\"]: target maximum angle from target facing rotation\n" "[\"behavior_name\"]: name of the autopilot behavior", &LLAgentListener::getAutoPilot, - LLSDMap("reply", LLSD())); + llsd::map("reply", LLSD())); add("startFollowPilot", "[\"leader_id\"]: uuid of target to follow using the autopilot system (optional with avatar_name)\n" "[\"avatar_name\"]: avatar name to follow using the autopilot system (optional with leader_id)\n" "[\"allow_flying\"]: allow flying during autopilot [default: True]\n" - "[\"stop_distance\"]: target maxiumum distance from target [default: autopilot guess]", - &LLAgentListener::startFollowPilot); + "[\"stop_distance\"]: maximum stop distance from target [default: autopilot guess]", + &LLAgentListener::startFollowPilot, + llsd::map("reply", LLSD())); add("setAutoPilotTarget", "Update target for currently running autopilot:\n" "[\"target_global\"]: array of target global {x, y, z} position", @@ -138,6 +138,69 @@ LLAgentListener::LLAgentListener(LLAgent &agent) "[\"contrib\"]: user's land contribution to this group\n", &LLAgentListener::getGroups, LLSDMap("reply", LLSD())); + //camera params are similar to LSL, see https://wiki.secondlife.com/wiki/LlSetCameraParams + add("setCameraParams", + "Set Follow camera params, and then activate it:\n" + "[\"camera_pos\"]: vector3, camera position in region coordinates\n" + "[\"focus_pos\"]: vector3, what the camera is aimed at (in region coordinates)\n" + "[\"focus_offset\"]: vector3, adjusts the camera focus position relative to the target, default is (1, 0, 0)\n" + "[\"distance\"]: float (meters), distance the camera wants to be from its target, default is 3\n" + "[\"focus_threshold\"]: float (meters), sets the radius of a sphere around the camera's target position within which its focus is not affected by target motion, default is 1\n" + "[\"camera_threshold\"]: float (meters), sets the radius of a sphere around the camera's ideal position within which it is not affected by target motion, default is 1\n" + "[\"focus_lag\"]: float (seconds), how much the camera lags as it tries to aim towards the target, default is 0.1\n" + "[\"camera_lag\"]: float (seconds), how much the camera lags as it tries to move towards its 'ideal' position, default is 0.1\n" + "[\"camera_pitch\"]: float (degrees), adjusts the angular amount that the camera aims straight ahead vs. straight down, maintaining the same distance, default is 0\n" + "[\"behindness_angle\"]: float (degrees), sets the angle in degrees within which the camera is not constrained by changes in target rotation, default is 10\n" + "[\"behindness_lag\"]: float (seconds), sets how strongly the camera is forced to stay behind the target if outside of behindness angle, default is 0\n" + "[\"camera_locked\"]: bool, locks the camera position so it will not move\n" + "[\"focus_locked\"]: bool, locks the camera focus so it will not move", + &LLAgentListener::setFollowCamParams); + add("setFollowCamActive", + "Turns on or off scripted control of the camera using boolean [\"active\"]", + &LLAgentListener::setFollowCamActive, + llsd::map("active", LLSD())); + add("removeCameraParams", + "Reset Follow camera params", + &LLAgentListener::removeFollowCamParams); + + add("playAnimation", + "Play [\"item_id\"] animation locally (by default) or [\"inworld\"] (when set to true)", + &LLAgentListener::playAnimation, + llsd::map("item_id", LLSD(), "reply", LLSD())); + add("stopAnimation", + "Stop playing [\"item_id\"] animation", + &LLAgentListener::stopAnimation, + llsd::map("item_id", LLSD(), "reply", LLSD())); + add("getAnimationInfo", + "Return information about [\"item_id\"] animation", + &LLAgentListener::getAnimationInfo, + llsd::map("item_id", LLSD(), "reply", LLSD())); + + add("getID", + "Return your own avatar ID", + &LLAgentListener::getID, + llsd::map("reply", LLSD())); + + add("getNearbyAvatarsList", + "Return result set key [\"result\"] for nearby avatars in a range of [\"dist\"]\n" + "if [\"dist\"] is not specified, 'RenderFarClip' setting is used\n" + "reply contains \"result\" table with \"id\", \"name\", \"global_pos\", \"region_pos\", \"region_id\" fields", + &LLAgentListener::getNearbyAvatarsList, + llsd::map("reply", LLSD())); + + add("getNearbyObjectsList", + "Return result set key [\"result\"] for nearby objects in a range of [\"dist\"]\n" + "if [\"dist\"] is not specified, 'RenderFarClip' setting is used\n" + "reply contains \"result\" table with \"id\", \"global_pos\", \"region_pos\", \"region_id\" fields", + &LLAgentListener::getNearbyObjectsList, + llsd::map("reply", LLSD())); + + add("getAgentScreenPos", + "Return screen position of the [\"avatar_id\"] avatar or own avatar if not specified\n" + "reply contains \"x\", \"y\" coordinates and \"onscreen\" flag to indicate if it's actually in within the current window\n" + "avatar render position is used as the point", + &LLAgentListener::getAgentScreenPos, + llsd::map("reply", LLSD())); } void LLAgentListener::requestTeleport(LLSD const & event_data) const @@ -168,7 +231,7 @@ void LLAgentListener::requestSit(LLSD const & event_data) const //mAgent.getAvatarObject()->sitOnObject(); // shamelessly ripped from llviewermenu.cpp:handle_sit_or_stand() // *TODO - find a permanent place to share this code properly. - + Response response(LLSD(), event_data); LLViewerObject *object = NULL; if (event_data.has("obj_uuid")) { @@ -177,7 +240,13 @@ void LLAgentListener::requestSit(LLSD const & event_data) const else if (event_data.has("position")) { LLVector3 target_position = ll_vector3_from_sd(event_data["position"]); - object = findObjectClosestTo(target_position); + object = findObjectClosestTo(target_position, true); + } + else + { + //just sit on the ground + mAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); + return; } if (object && object->getPCode() == LL_PCODE_VOLUME) @@ -194,8 +263,7 @@ void LLAgentListener::requestSit(LLSD const & event_data) const } else { - LL_WARNS() << "LLAgent requestSit could not find the sit target: " - << event_data << LL_ENDL; + response.error("requestSit could not find the sit target"); } } @@ -205,7 +273,7 @@ void LLAgentListener::requestStand(LLSD const & event_data) const } -LLViewerObject * LLAgentListener::findObjectClosestTo( const LLVector3 & position ) const +LLViewerObject * LLAgentListener::findObjectClosestTo(const LLVector3 & position, bool sit_target) const { LLViewerObject *object = NULL; @@ -216,8 +284,13 @@ LLViewerObject * LLAgentListener::findObjectClosestTo( const LLVector3 & positio while (cur_index < num_objects) { LLViewerObject * cur_object = gObjectList.getObject(cur_index++); - if (cur_object) - { // Calculate distance from the target position + if (cur_object && !cur_object->isAttachment()) + { + if(sit_target && (cur_object->getPCode() != LL_PCODE_VOLUME)) + { + continue; + } + // Calculate distance from the target position LLVector3 target_diff = cur_object->getPositionRegion() - position; F32 distance_to_target = target_diff.length(); if (distance_to_target < min_distance) @@ -296,22 +369,6 @@ void LLAgentListener::resetAxes(const LLSD& event_data) const } } -void LLAgentListener::getAxes(const LLSD& event_data) const -{ - LLQuaternion quat(mAgent.getQuat()); - F32 roll, pitch, yaw; - quat.getEulerAngles(&roll, &pitch, &yaw); - // The official query API for LLQuaternion's [x, y, z, w] values is its - // public member mQ... - LLSD reply = LLSD::emptyMap(); - reply["quat"] = llsd_copy_array(boost::begin(quat.mQ), boost::end(quat.mQ)); - reply["euler"] = LLSD::emptyMap(); - reply["euler"]["roll"] = roll; - reply["euler"]["pitch"] = pitch; - reply["euler"]["yaw"] = yaw; - sendReply(reply, event_data); -} - void LLAgentListener::getPosition(const LLSD& event_data) const { F32 roll, pitch, yaw; @@ -333,14 +390,13 @@ void LLAgentListener::getPosition(const LLSD& event_data) const void LLAgentListener::startAutoPilot(LLSD const & event_data) { - LLQuaternion target_rotation_value; LLQuaternion* target_rotation = NULL; if (event_data.has("target_rotation")) { - target_rotation_value = ll_quaternion_from_sd(event_data["target_rotation"]); + LLQuaternion target_rotation_value = ll_quaternion_from_sd(event_data["target_rotation"]); target_rotation = &target_rotation_value; } - // *TODO: Use callback_pump and callback_data + F32 rotation_threshold = 0.03f; if (event_data.has("rotation_threshold")) { @@ -360,13 +416,24 @@ void LLAgentListener::startAutoPilot(LLSD const & event_data) stop_distance = (F32)event_data["stop_distance"].asReal(); } + std::string behavior_name = LLCoros::getName(); + if (event_data.has("behavior_name")) + { + behavior_name = event_data["behavior_name"].asString(); + } + // Clear follow target, this is doing a path mFollowTarget.setNull(); + auto finish_cb = [](bool success, void*) + { + LLEventPumps::instance().obtain("LLAutopilot").post(llsd::map("success", success)); + }; + mAgent.startAutoPilotGlobal(ll_vector3d_from_sd(event_data["target_global"]), - event_data["behavior_name"], + behavior_name, target_rotation, - NULL, NULL, + finish_cb, NULL, stop_distance, rotation_threshold, allow_flying); @@ -374,7 +441,7 @@ void LLAgentListener::startAutoPilot(LLSD const & event_data) void LLAgentListener::getAutoPilot(const LLSD& event_data) const { - LLSD reply = LLSD::emptyMap(); + Response reply(LLSD(), event_data); LLSD::Boolean enabled = mAgent.getAutoPilot(); reply["enabled"] = enabled; @@ -403,12 +470,11 @@ void LLAgentListener::getAutoPilot(const LLSD& event_data) const reply["rotation_threshold"] = mAgent.getAutoPilotRotationThreshold(); reply["behavior_name"] = mAgent.getAutoPilotBehaviorName(); reply["fly"] = (LLSD::Boolean) mAgent.getFlying(); - - sendReply(reply, event_data); } void LLAgentListener::startFollowPilot(LLSD const & event_data) { + Response response(LLSD(), event_data); LLUUID target_id; bool allow_flying = true; @@ -442,6 +508,10 @@ void LLAgentListener::startFollowPilot(LLSD const & event_data) } } } + else + { + return response.error("'leader_id' or 'avatar_name' should be specified"); + } F32 stop_distance = 0.f; if (event_data.has("stop_distance")) @@ -449,13 +519,16 @@ void LLAgentListener::startFollowPilot(LLSD const & event_data) stop_distance = (F32)event_data["stop_distance"].asReal(); } - if (target_id.notNull()) + if (!gObjectList.findObject(target_id)) { - mAgent.setFlying(allow_flying); - mFollowTarget = target_id; // Save follow target so we can report distance later - - mAgent.startFollowPilot(target_id, allow_flying, stop_distance); + std::string target_info = event_data.has("leader_id") ? event_data["leader_id"] : event_data["avatar_name"]; + return response.error(stringize("Target ", std::quoted(target_info), " was not found")); } + + mAgent.setFlying(allow_flying); + mFollowTarget = target_id; // Save follow target so we can report distance later + + mAgent.startFollowPilot(target_id, allow_flying, stop_distance); } void LLAgentListener::setAutoPilotTarget(LLSD const & event_data) const @@ -519,3 +592,209 @@ void LLAgentListener::getGroups(const LLSD& event) const } sendReply(LLSDMap("groups", reply), event); } + +/*----------------------------- camera control -----------------------------*/ +// specialize LLSDParam to support (const LLVector3&) arguments -- this +// wouldn't even be necessary except that the relevant LLVector3 constructor +// is explicitly explicit +template <> +class LLSDParam: public LLSDParamBase +{ +public: + LLSDParam(const LLSD& value): value(LLVector3(value)) {} + + operator const LLVector3&() const { return value; } + +private: + LLVector3 value; +}; + +// accept any of a number of similar LLFollowCamMgr methods with different +// argument types, and return a wrapper lambda that accepts LLSD and converts +// to the target argument type +template +auto wrap(void (LLFollowCamMgr::*method)(const LLUUID& source, T arg)) +{ + return [method](LLFollowCamMgr& followcam, const LLUUID& source, const LLSD& arg) + { (followcam.*method)(source, LLSDParam(arg)); }; +} + +// table of supported LLFollowCamMgr methods, +// with the corresponding setFollowCamParams() argument keys +static std::pair> +cam_params[] = +{ + { "camera_pos", wrap(&LLFollowCamMgr::setPosition) }, + { "focus_pos", wrap(&LLFollowCamMgr::setFocus) }, + { "focus_offset", wrap(&LLFollowCamMgr::setFocusOffset) }, + { "camera_locked", wrap(&LLFollowCamMgr::setPositionLocked) }, + { "focus_locked", wrap(&LLFollowCamMgr::setFocusLocked) }, + { "distance", wrap(&LLFollowCamMgr::setDistance) }, + { "focus_threshold", wrap(&LLFollowCamMgr::setFocusThreshold) }, + { "camera_threshold", wrap(&LLFollowCamMgr::setPositionThreshold) }, + { "focus_lag", wrap(&LLFollowCamMgr::setFocusLag) }, + { "camera_lag", wrap(&LLFollowCamMgr::setPositionLag) }, + { "camera_pitch", wrap(&LLFollowCamMgr::setPitch) }, + { "behindness_lag", wrap(&LLFollowCamMgr::setBehindnessLag) }, + { "behindness_angle", wrap(&LLFollowCamMgr::setBehindnessAngle) }, +}; + +void LLAgentListener::setFollowCamParams(const LLSD& event) const +{ + auto& followcam{ LLFollowCamMgr::instance() }; + for (const auto& pair : cam_params) + { + if (event.has(pair.first)) + { + pair.second(followcam, gAgentID, event[pair.first]); + } + } + followcam.setCameraActive(gAgentID, true); +} + +void LLAgentListener::setFollowCamActive(LLSD const & event) const +{ + LLFollowCamMgr::getInstance()->setCameraActive(gAgentID, event["active"]); +} + +void LLAgentListener::removeFollowCamParams(LLSD const & event) const +{ + LLFollowCamMgr::getInstance()->removeFollowCamParams(gAgentID); +} + +LLViewerInventoryItem* get_anim_item(LLEventAPI::Response &response, const LLSD &event_data) +{ + LLViewerInventoryItem* item = gInventory.getItem(event_data["item_id"].asUUID()); + if (!item || (item->getInventoryType() != LLInventoryType::IT_ANIMATION)) + { + response.error(stringize("Animation item ", std::quoted(event_data["item_id"].asString()), " was not found")); + return NULL; + } + return item; +} + +void LLAgentListener::playAnimation(LLSD const &event_data) +{ + Response response(LLSD(), event_data); + if (LLViewerInventoryItem* item = get_anim_item(response, event_data)) + { + if (event_data["inworld"].asBoolean()) + { + mAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_START); + } + else + { + gAgentAvatarp->startMotion(item->getAssetUUID()); + } + } +} + +void LLAgentListener::stopAnimation(LLSD const &event_data) +{ + Response response(LLSD(), event_data); + if (LLViewerInventoryItem* item = get_anim_item(response, event_data)) + { + gAgentAvatarp->stopMotion(item->getAssetUUID()); + mAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_STOP); + } +} + +void LLAgentListener::getAnimationInfo(LLSD const &event_data) +{ + Response response(LLSD(), event_data); + if (LLViewerInventoryItem* item = get_anim_item(response, event_data)) + { + // if motion exists, will return existing one + LLMotion* motion = gAgentAvatarp->createMotion(item->getAssetUUID()); + response["anim_info"] = llsd::map("duration", motion->getDuration(), + "is_loop", motion->getLoop(), + "num_joints", motion->getNumJointMotions(), + "asset_id", item->getAssetUUID(), + "priority", motion->getPriority()); + } +} + +void LLAgentListener::getID(LLSD const& event_data) +{ + Response response(llsd::map("id", gAgentID), event_data); +} + +F32 get_search_radius(LLSD const& event_data) +{ + static LLCachedControl render_far_clip(gSavedSettings, "RenderFarClip", 64); + F32 dist = render_far_clip; + if (event_data.has("dist")) + { + dist = llclamp((F32)event_data["dist"].asReal(), 1, 512); + } + return dist * dist; +} + +void LLAgentListener::getNearbyAvatarsList(LLSD const& event_data) +{ + Response response(LLSD(), event_data); + F32 radius = get_search_radius(event_data); + LLVector3d agent_pos = gAgent.getPositionGlobal(); + for (LLCharacter* character : LLCharacter::sInstances) + { + LLVOAvatar* avatar = (LLVOAvatar*)character; + if (avatar && !avatar->isDead() && !avatar->isControlAvatar() && !avatar->isSelf()) + { + if ((dist_vec_squared(avatar->getPositionGlobal(), agent_pos) <= radius)) + { + LLAvatarName av_name; + LLAvatarNameCache::get(avatar->getID(), &av_name); + LLVector3 region_pos = avatar->getCharacterPosition(); + response["result"].append(llsd::map("id", avatar->getID(), "global_pos", ll_sd_from_vector3d(avatar->getPosGlobalFromAgent(region_pos)), + "region_pos", ll_sd_from_vector3(region_pos), "name", av_name.getUserName(), "region_id", avatar->getRegion()->getRegionID())); + } + } + } +} + +void LLAgentListener::getNearbyObjectsList(LLSD const& event_data) +{ + Response response(LLSD(), event_data); + F32 radius = get_search_radius(event_data); + S32 num_objects = gObjectList.getNumObjects(); + LLVector3d agent_pos = gAgent.getPositionGlobal(); + for (S32 i = 0; i < num_objects; ++i) + { + LLViewerObject* object = gObjectList.getObject(i); + if (object && object->getVolume() && !object->isAttachment()) + { + if ((dist_vec_squared(object->getPositionGlobal(), agent_pos) <= radius)) + { + response["result"].append(llsd::map("id", object->getID(), "global_pos", ll_sd_from_vector3d(object->getPositionGlobal()), "region_pos", + ll_sd_from_vector3(object->getPositionRegion()), "region_id", object->getRegion()->getRegionID())); + } + } + } +} + +void LLAgentListener::getAgentScreenPos(LLSD const& event_data) +{ + Response response(LLSD(), event_data); + LLVector3 render_pos; + if (event_data.has("avatar_id") && (event_data["avatar_id"].asUUID() != gAgentID)) + { + LLUUID avatar_id(event_data["avatar_id"]); + for (LLCharacter* character : LLCharacter::sInstances) + { + LLVOAvatar* avatar = (LLVOAvatar*)character; + if (!avatar->isDead() && (avatar->getID() == avatar_id)) + { + render_pos = avatar->getRenderPosition(); + break; + } + } + } + else if (gAgentAvatarp.notNull() && gAgentAvatarp->isValid()) + { + render_pos = gAgentAvatarp->getRenderPosition(); + } + LLCoordGL screen_pos; + response["onscreen"] = LLViewerCamera::getInstance()->projectPosAgentToScreen(render_pos, screen_pos, false); + response["x"] = screen_pos.mX; + response["y"] = screen_pos.mY; +} diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h index c544d089ce..31f50a653f 100644 --- a/indra/newview/llagentlistener.h +++ b/indra/newview/llagentlistener.h @@ -48,7 +48,6 @@ private: void requestStand(LLSD const & event_data) const; void requestTouch(LLSD const & event_data) const; void resetAxes(const LLSD& event_data) const; - void getAxes(const LLSD& event_data) const; void getGroups(const LLSD& event) const; void getPosition(const LLSD& event_data) const; void startAutoPilot(const LLSD& event_data); @@ -58,7 +57,21 @@ private: void stopAutoPilot(const LLSD& event_data) const; void lookAt(LLSD const & event_data) const; - LLViewerObject * findObjectClosestTo( const LLVector3 & position ) const; + void setFollowCamParams(LLSD const & event_data) const; + void setFollowCamActive(LLSD const & event_data) const; + void removeFollowCamParams(LLSD const & event_data) const; + + void playAnimation(LLSD const &event_data); + void playAnimation_(const LLUUID& asset_id, const bool inworld); + void stopAnimation(LLSD const &event_data); + void getAnimationInfo(LLSD const &event_data); + + void getID(LLSD const& event_data); + void getNearbyAvatarsList(LLSD const& event_data); + void getNearbyObjectsList(LLSD const& event_data); + void getAgentScreenPos(LLSD const& event_data); + + LLViewerObject * findObjectClosestTo( const LLVector3 & position, bool sit_target = false ) const; private: LLAgent & mAgent; diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 28c651f0cd..db6f9ac22a 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -52,6 +52,7 @@ #include "llfirstuse.h" #include "llfloaterimnearbychat.h" +#include "llfloaterimnearbychatlistener.h" #include "llagent.h" // gAgent #include "llgesturemgr.h" #include "llmultigesture.h" @@ -71,6 +72,8 @@ S32 LLFloaterIMNearbyChat::sLastSpecialChatChannel = 0; +static LLFloaterIMNearbyChatListener sChatListener; + constexpr S32 EXPANDED_HEIGHT = 266; constexpr S32 COLLAPSED_HEIGHT = 60; constexpr S32 EXPANDED_MIN_HEIGHT = 150; diff --git a/indra/newview/llfloaterimnearbychatlistener.cpp b/indra/newview/llfloaterimnearbychatlistener.cpp index 43173d3680..b15a32ce40 100644 --- a/indra/newview/llfloaterimnearbychatlistener.cpp +++ b/indra/newview/llfloaterimnearbychatlistener.cpp @@ -34,12 +34,12 @@ #include "llagent.h" #include "llchat.h" #include "llviewercontrol.h" +#include "stringize.h" +static const F32 CHAT_THROTTLE_PERIOD = 1.f; -LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar) - : LLEventAPI("LLChatBar", - "LLChatBar listener to (e.g.) sendChat, etc."), - mChatbar(chatbar) +LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener() : + LLEventAPI("LLChatBar", "LLChatBar listener to (e.g.) sendChat, etc.") { add("sendChat", "Send chat to the simulator:\n" @@ -49,10 +49,18 @@ LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyCh &LLFloaterIMNearbyChatListener::sendChat); } - // "sendChat" command -void LLFloaterIMNearbyChatListener::sendChat(LLSD const & chat_data) const +void LLFloaterIMNearbyChatListener::sendChat(LLSD const& chat_data) { + F64 cur_time = LLTimer::getElapsedSeconds(); + + if (cur_time < mLastThrottleTime + CHAT_THROTTLE_PERIOD) + { + LL_WARNS("LLFloaterIMNearbyChatListener") << "'sendChat' was throttled" << LL_ENDL; + return; + } + mLastThrottleTime = cur_time; + // Extract the data std::string chat_text = chat_data["message"].asString(); @@ -81,20 +89,12 @@ void LLFloaterIMNearbyChatListener::sendChat(LLSD const & chat_data) const } // Have to prepend /42 style channel numbers - std::string chat_to_send; - if (channel == 0) - { - chat_to_send = chat_text; - } - else + if (channel) { - chat_to_send += "/"; - chat_to_send += chat_data["channel"].asString(); - chat_to_send += " "; - chat_to_send += chat_text; + chat_text = stringize("/", chat_data["channel"].asString(), " ", chat_text); } // Send it as if it was typed in - mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, ((bool)(channel == 0)) && gSavedSettings.getBOOL("PlayChatAnim")); + LLFloaterIMNearbyChat::sendChatFromViewer(chat_text, type_o_chat, (channel == 0) && gSavedSettings.getBOOL("PlayChatAnim")); } diff --git a/indra/newview/llfloaterimnearbychatlistener.h b/indra/newview/llfloaterimnearbychatlistener.h index 96184d95b3..71eba53a9a 100644 --- a/indra/newview/llfloaterimnearbychatlistener.h +++ b/indra/newview/llfloaterimnearbychatlistener.h @@ -38,12 +38,12 @@ class LLFloaterIMNearbyChat; class LLFloaterIMNearbyChatListener : public LLEventAPI { public: - LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar); + LLFloaterIMNearbyChatListener(); private: - void sendChat(LLSD const & chat_data) const; + void sendChat(LLSD const & chat_data); - LLFloaterIMNearbyChat & mChatbar; + F64 mLastThrottleTime{0}; }; #endif // LL_LLFLOATERIMNEARBYCHATLISTENER_H -- cgit v1.3 From 498b244070b47a9f9f14b5b0f026a14274942459 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 2 Apr 2025 22:05:49 +0300 Subject: # 3826 Physics Material Type does not update for linked objects --- indra/newview/llpanelvolume.cpp | 44 ++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 951dc45a78..2fbdbeaf59 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -576,32 +576,48 @@ void LLPanelVolume::getState( ) return object->getMaterial(); } } func; - bool material_same = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_code ); + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + bool material_same = selection->getSelectedTEValue( &func, material_code ); std::string LEGACY_FULLBRIGHT_DESC = LLTrans::getString("Fullbright"); - if (editable && single_volume && material_same) + + bool enable_material = editable && single_volume && material_same; + LLCachedControl edit_linked(gSavedSettings, "EditLinkedParts", false); + if (!enable_material && !edit_linked()) { - mComboMaterial->setEnabled( true ); - if (material_code == LL_MCODE_LIGHT) + LLViewerObject* root = selection->getPrimaryObject(); + while (root && !root->isAvatar() && root->getParent()) { - if (mComboMaterial->getItemCount() == mComboMaterialItemCount) + LLViewerObject* parent = (LLViewerObject*)root->getParent(); + if (parent->isAvatar()) { - mComboMaterial->add(LEGACY_FULLBRIGHT_DESC); + break; } - mComboMaterial->setSimple(LEGACY_FULLBRIGHT_DESC); + root = parent; } - else + if (root) { - if (mComboMaterial->getItemCount() != mComboMaterialItemCount) - { - mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC); - } + material_code = root->getMaterial(); + } + } - mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code))); + mComboMaterial->setEnabled(enable_material); + + if (material_code == LL_MCODE_LIGHT) + { + if (mComboMaterial->getItemCount() == mComboMaterialItemCount) + { + mComboMaterial->add(LEGACY_FULLBRIGHT_DESC); } + mComboMaterial->setSimple(LEGACY_FULLBRIGHT_DESC); } else { - mComboMaterial->setEnabled( false ); + if (mComboMaterial->getItemCount() != mComboMaterialItemCount) + { + mComboMaterial->remove(LEGACY_FULLBRIGHT_DESC); + } + + mComboMaterial->setSimple(std::string(LLMaterialTable::basic.getName(material_code))); } // Physics properties -- cgit v1.3 From 46fca6f5bbafcdb2942114ccccdadc1e769955e4 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 3 Apr 2025 12:34:51 +0300 Subject: #3857 second batch of new or updated LEAP functions --- indra/llcommon/llsdutil.h | 55 ++++++++++++ indra/newview/CMakeLists.txt | 2 + indra/newview/groupchatlistener.cpp | 84 ++++++++++++------ indra/newview/groupchatlistener.h | 15 ++-- indra/newview/llagentlistener.h | 1 - indra/newview/llappearancelistener.cpp | 158 +++++++++++++++++++++++++++++++++ indra/newview/llappearancelistener.h | 46 ++++++++++ indra/newview/llappearancemgr.cpp | 8 ++ indra/newview/llappearancemgr.h | 1 + indra/newview/llgroupactions.cpp | 2 +- indra/newview/llwearableitemslist.cpp | 10 --- indra/newview/llwearableitemslist.h | 9 ++ 12 files changed, 345 insertions(+), 46 deletions(-) create mode 100644 indra/newview/llappearancelistener.cpp create mode 100644 indra/newview/llappearancelistener.h (limited to 'indra') diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index 38bbe19ddd..c31030c5ea 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -553,6 +553,61 @@ LLSD shallow(LLSD value, LLSD filter=LLSD()) { return llsd_shallow(value, filter } // namespace llsd +/***************************************************************************** + * toArray(), toMap() + *****************************************************************************/ +namespace llsd +{ + +// For some T convertible to LLSD, given std::vector myVec, +// toArray(myVec) returns an LLSD array whose entries correspond to the +// items in myVec. +// For some U convertible to LLSD, given function U xform(const T&), +// toArray(myVec, xform) returns an LLSD array whose every entry is +// xform(item) of the corresponding item in myVec. +// toArray() actually works with any container usable with range +// 'for', not just std::vector. +// (Once we get C++20 we can use std::identity instead of this default lambda.) +template +LLSD toArray(const C& container, FUNC&& func = [](const auto& arg) { return arg; }) +{ + LLSD array; + for (const auto& item : container) + { + array.append(std::forward(func)(item)); + } + return array; +} + +// For some T convertible to LLSD, given std::map myMap, +// toMap(myMap) returns an LLSD map whose entries correspond to the +// (key, value) pairs in myMap. +// For some U convertible to LLSD, given function +// std::pair xform(const std::pair&), +// toMap(myMap, xform) returns an LLSD map whose every entry is +// xform(pair) of the corresponding (key, value) pair in myMap. +// toMap() actually works with any container usable with range 'for', not +// just std::map. It need not even be an associative container, as long as +// you pass an xform function that returns std::pair. +// (Once we get C++20 we can use std::identity instead of this default lambda.) +template +LLSD toMap(const C& container, FUNC&& func = [](const auto& arg) { return arg; }) +{ + LLSD map; + for (const auto& pair : container) + { + const auto& [key, value] = std::forward(func)(pair); + map[key] = value; + } + return map; +} + +} // namespace llsd + +/***************************************************************************** + * boost::hash + *****************************************************************************/ + // Specialization for generating a hash value from an LLSD block. namespace boost { diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ed29911a43..fff1597fd9 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -92,6 +92,7 @@ set(viewer_SOURCE_FILES llagentwearables.cpp llanimstatelabels.cpp llappcorehttp.cpp + llappearancelistener.cpp llappearancemgr.cpp llappviewer.cpp llappviewerlistener.cpp @@ -761,6 +762,7 @@ set(viewer_HEADER_FILES llanimstatelabels.h llappcorehttp.h llappearance.h + llappearancelistener.h llappearancemgr.h llappviewer.h llappviewerlistener.h diff --git a/indra/newview/groupchatlistener.cpp b/indra/newview/groupchatlistener.cpp index 43507f13e9..ed9e34d1bf 100644 --- a/indra/newview/groupchatlistener.cpp +++ b/indra/newview/groupchatlistener.cpp @@ -2,11 +2,11 @@ * @file groupchatlistener.cpp * @author Nat Goodspeed * @date 2011-04-11 - * @brief Implementation for groupchatlistener. + * @brief Implementation for LLGroupChatListener. * - * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2011, Linden Research, Inc. + * Copyright (C) 2024, 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 @@ -34,43 +34,69 @@ // std headers // external library headers // other Linden headers +#include "llchat.h" #include "llgroupactions.h" #include "llimview.h" +LLGroupChatListener::LLGroupChatListener(): + LLEventAPI("GroupChat", + "API to enter, leave, send and intercept group chat messages") +{ + add("startGroupChat", + "Enter a group chat in group with UUID [\"group_id\"]\n" + "Assumes the logged-in agent is already a member of this group.", + &LLGroupChatListener::startGroupChat, + llsd::map("group_id", LLSD())); + add("leaveGroupChat", + "Leave a group chat in group with UUID [\"group_id\"]\n" + "Assumes a prior successful startIM request.", + &LLGroupChatListener::leaveGroupChat, + llsd::map("group_id", LLSD())); + add("sendGroupIM", + "send a [\"message\"] to group with UUID [\"group_id\"]", + &LLGroupChatListener::sendGroupIM, + llsd::map("message", LLSD(), "group_id", LLSD())); +} -namespace { - void startIm_wrapper(LLSD const & event) +bool is_in_group(LLEventAPI::Response &response, const LLSD &data) +{ + if (!LLGroupActions::isInGroup(data["group_id"])) { - LLUUID session_id = LLGroupActions::startIM(event["id"].asUUID()); - sendReply(LLSDMap("session_id", LLSD(session_id)), event); + response.error(stringize("You are not the member of the group:", std::quoted(data["group_id"].asString()))); + return false; } + return true; +} - void send_message_wrapper(const std::string& text, const LLUUID& session_id, const LLUUID& group_id) +void LLGroupChatListener::startGroupChat(LLSD const &data) +{ + Response response(LLSD(), data); + if (!is_in_group(response, data)) + { + return; + } + if (LLGroupActions::startIM(data["group_id"]).isNull()) { - LLIMModel::sendMessage(text, session_id, group_id, IM_SESSION_GROUP_START); + return response.error(stringize("Failed to start group chat session ", std::quoted(data["group_id"].asString()))); } } +void LLGroupChatListener::leaveGroupChat(LLSD const &data) +{ + Response response(LLSD(), data); + if (is_in_group(response, data)) + { + LLGroupActions::endIM(data["group_id"].asUUID()); + } +} -GroupChatListener::GroupChatListener(): - LLEventAPI("GroupChat", - "API to enter, leave, send and intercept group chat messages") +void LLGroupChatListener::sendGroupIM(LLSD const &data) { - add("startIM", - "Enter a group chat in group with UUID [\"id\"]\n" - "Assumes the logged-in agent is already a member of this group.", - &startIm_wrapper); - add("endIM", - "Leave a group chat in group with UUID [\"id\"]\n" - "Assumes a prior successful startIM request.", - &LLGroupActions::endIM, - llsd::array("id")); - add("sendIM", - "send a groupchat IM", - &send_message_wrapper, - llsd::array("text", "session_id", "group_id")); + Response response(LLSD(), data); + if (!is_in_group(response, data)) + { + return; + } + LLUUID group_id(data["group_id"]); + LLIMModel::sendMessage(data["message"], gIMMgr->computeSessionID(IM_SESSION_GROUP_START, group_id), group_id, IM_SESSION_SEND); } -/* - static void sendMessage(const std::string& utf8_text, const LLUUID& im_session_id, - const LLUUID& other_participant_id, EInstantMessage dialog); -*/ diff --git a/indra/newview/groupchatlistener.h b/indra/newview/groupchatlistener.h index 3819ac59b7..14cd7266a3 100644 --- a/indra/newview/groupchatlistener.h +++ b/indra/newview/groupchatlistener.h @@ -26,15 +26,20 @@ * $/LicenseInfo$ */ -#if ! defined(LL_GROUPCHATLISTENER_H) -#define LL_GROUPCHATLISTENER_H +#if ! defined(LL_LLGROUPCHATLISTENER_H) +#define LL_LLGROUPCHATLISTENER_H #include "lleventapi.h" -class GroupChatListener: public LLEventAPI +class LLGroupChatListener: public LLEventAPI { public: - GroupChatListener(); + LLGroupChatListener(); + +private: + void startGroupChat(LLSD const &data); + void leaveGroupChat(LLSD const &data); + void sendGroupIM(LLSD const &data); }; -#endif /* ! defined(LL_GROUPCHATLISTENER_H) */ +#endif /* ! defined(LL_LLGROUPCHATLISTENER_H) */ diff --git a/indra/newview/llagentlistener.h b/indra/newview/llagentlistener.h index 31f50a653f..b5bea8c0bd 100644 --- a/indra/newview/llagentlistener.h +++ b/indra/newview/llagentlistener.h @@ -62,7 +62,6 @@ private: void removeFollowCamParams(LLSD const & event_data) const; void playAnimation(LLSD const &event_data); - void playAnimation_(const LLUUID& asset_id, const bool inworld); void stopAnimation(LLSD const &event_data); void getAnimationInfo(LLSD const &event_data); diff --git a/indra/newview/llappearancelistener.cpp b/indra/newview/llappearancelistener.cpp new file mode 100644 index 0000000000..65cdf2e11b --- /dev/null +++ b/indra/newview/llappearancelistener.cpp @@ -0,0 +1,158 @@ +/** + * @file llappearancelistener.cpp + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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 "llappearancelistener.h" + +#include "llappearancemgr.h" +#include "llinventoryfunctions.h" +#include "lltransutil.h" +#include "llwearableitemslist.h" +#include "stringize.h" + +LLAppearanceListener::LLAppearanceListener() + : LLEventAPI("LLAppearance", + "API to wear a specified outfit and wear/remove individual items") +{ + add("wearOutfit", + "Wear outfit by folder id: [\"folder_id\"] OR by folder name: [\"folder_name\"]\n" + "When [\"append\"] is true, outfit will be added to COF\n" + "otherwise it will replace current oufit", + &LLAppearanceListener::wearOutfit); + + add("wearItems", + "Wear items by id: [items_id]", + &LLAppearanceListener::wearItems, + llsd::map("items_id", LLSD(), "replace", LLSD())); + + add("detachItems", + "Detach items by id: [items_id]", + &LLAppearanceListener::detachItems, + llsd::map("items_id", LLSD())); + + add("getOutfitsList", + "Return the table with Outfits info(id and name)", + &LLAppearanceListener::getOutfitsList); + + add("getOutfitItems", + "Return the table of items with info(id : name, wearable_type, is_worn) inside specified outfit folder", + &LLAppearanceListener::getOutfitItems); +} + + +void LLAppearanceListener::wearOutfit(LLSD const &data) +{ + Response response(LLSD(), data); + if (!data.has("folder_id") && !data.has("folder_name")) + { + return response.error("Either [folder_id] or [folder_name] is required"); + } + + bool append = data.has("append") ? data["append"].asBoolean() : false; + if (!LLAppearanceMgr::instance().wearOutfit(data, append)) + { + response.error("Failed to wear outfit"); + } +} + +void LLAppearanceListener::wearItems(LLSD const &data) +{ + const LLSD& items_id{ data["items_id"] }; + uuid_vec_t ids; + if (!items_id.isArray()) + { + ids.push_back(items_id.asUUID()); + } + else // array + { + for (const auto& id : llsd::inArray(items_id)) + { + ids.push_back(id); + } + } + LLAppearanceMgr::instance().wearItemsOnAvatar(ids, true, data["replace"].asBoolean()); +} + +void LLAppearanceListener::detachItems(LLSD const &data) +{ + const LLSD& items_id{ data["items_id"] }; + uuid_vec_t ids; + if (!items_id.isArray()) + { + ids.push_back(items_id.asUUID()); + } + else // array + { + for (const auto& id : llsd::inArray(items_id)) + { + ids.push_back(id); + } + } + LLAppearanceMgr::instance().removeItemsFromAvatar(ids); +} + +void LLAppearanceListener::getOutfitsList(LLSD const &data) +{ + Response response(LLSD(), data); + const LLUUID outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + + LLIsType is_category(LLAssetType::AT_CATEGORY); + gInventory.collectDescendentsIf(outfits_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, is_category); + + response["outfits"] = llsd::toMap(cat_array, + [](const LLPointer &cat) + { return std::make_pair(cat->getUUID().asString(), cat->getName()); }); +} + +void LLAppearanceListener::getOutfitItems(LLSD const &data) +{ + Response response(LLSD(), data); + LLUUID outfit_id(data["outfit_id"].asUUID()); + LLViewerInventoryCategory *cat = gInventory.getCategory(outfit_id); + if (!cat || cat->getPreferredType() != LLFolderType::FT_OUTFIT) + { + return response.error(stringize(LLTrans::getString("OutfitNotFound"), outfit_id.asString())); + } + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + + LLFindOutfitItems collector = LLFindOutfitItems(); + gInventory.collectDescendentsIf(outfit_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, collector); + + response["items"] = llsd::toMap(item_array, + [](const LLPointer &it) + { + return std::make_pair( + it->getUUID().asString(), + llsd::map( + "name", it->getName(), + "wearable_type", LLWearableType::getInstance()->getTypeName(it->isWearableType() ? it->getWearableType() : LLWearableType::WT_NONE), + "is_worn", get_is_item_worn(it))); + }); +} diff --git a/indra/newview/llappearancelistener.h b/indra/newview/llappearancelistener.h new file mode 100644 index 0000000000..04c5eac2eb --- /dev/null +++ b/indra/newview/llappearancelistener.h @@ -0,0 +1,46 @@ +/** + * @file llappearancelistener.h + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, 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$ + */ + + +#ifndef LL_LLAPPEARANCELISTENER_H +#define LL_LLAPPEARANCELISTENER_H + +#include "lleventapi.h" + +class LLAppearanceListener : public LLEventAPI +{ +public: + LLAppearanceListener(); + +private: + void wearOutfit(LLSD const &data); + void wearItems(LLSD const &data); + void detachItems(LLSD const &data); + void getOutfitsList(LLSD const &data); + void getOutfitItems(LLSD const &data); +}; + +#endif // LL_LLAPPEARANCELISTENER_H + diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 101aca3823..e9d455ae53 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -31,6 +31,7 @@ #include "llagent.h" #include "llagentcamera.h" #include "llagentwearables.h" +#include "llappearancelistener.h" #include "llappearancemgr.h" #include "llattachmentsmgr.h" #include "llcommandhandler.h" @@ -66,6 +67,8 @@ #include "llavatarpropertiesprocessor.h" +LLAppearanceListener sAppearanceListener; + namespace { const S32 BAKE_RETRY_MAX_COUNT = 5; @@ -4762,6 +4765,11 @@ bool wear_category(const LLSD& query_map, bool append) return false; } +bool LLAppearanceMgr::wearOutfit(const LLSD& query_map, bool append) +{ + return wear_category(query_map, append); +} + class LLWearFolderHandler : public LLCommandHandler { public: diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 6c45a32856..bc7dc9506b 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -60,6 +60,7 @@ public: void wearInventoryCategoryOnAvatar(LLInventoryCategory* category, bool append); void wearCategoryFinal(const LLUUID& cat_id, bool copy_items, bool append); void wearOutfitByName(const std::string& name); + bool wearOutfit(const LLSD& query_map, bool append = false); void changeOutfit(bool proceed, const LLUUID& category, bool append); void replaceCurrentOutfit(const LLUUID& new_outfit); void renameOutfit(const LLUUID& outfit_id); diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index ba9c9fa13f..34d96aa024 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -46,7 +46,7 @@ // // Globals // -static GroupChatListener sGroupChatListener; +static LLGroupChatListener sGroupChatListener; class LLGroupHandler : public LLCommandHandler { diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 8ce1a745c3..c708e804b2 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -33,7 +33,6 @@ #include "llagentwearables.h" #include "llappearancemgr.h" -#include "llinventoryfunctions.h" #include "llinventoryicon.h" #include "llgesturemgr.h" #include "lltransutil.h" @@ -41,15 +40,6 @@ #include "llviewermenu.h" #include "llvoavatarself.h" -class LLFindOutfitItems : public LLInventoryCollectFunctor -{ -public: - LLFindOutfitItems() {} - virtual ~LLFindOutfitItems() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item); -}; - bool LLFindOutfitItems::operator()(LLInventoryCategory* cat, LLInventoryItem* item) { diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index 3fe1059176..7a5f29020e 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -32,6 +32,7 @@ #include "llsingleton.h" // newview +#include "llinventoryfunctions.h" #include "llinventoryitemslist.h" #include "llinventorylistitem.h" #include "lllistcontextmenu.h" @@ -507,4 +508,12 @@ protected: LLWearableType::EType mMenuWearableType; }; +class LLFindOutfitItems : public LLInventoryCollectFunctor +{ +public: + LLFindOutfitItems() {} + virtual ~LLFindOutfitItems() {} + virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item); +}; + #endif //LL_LLWEARABLEITEMSLIST_H -- cgit v1.3 From dead3c1fca14e8097fdc707fb94572eee6b23dc3 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 3 Apr 2025 15:11:51 +0300 Subject: #3857 teleport finished/failed event --- indra/newview/llappearancelistener.cpp | 2 +- indra/newview/llviewerparcelmgr.cpp | 24 ++++++++++++++++++++++++ indra/newview/llviewerparcelmgr.h | 4 ++++ 3 files changed, 29 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llappearancelistener.cpp b/indra/newview/llappearancelistener.cpp index 65cdf2e11b..a6d6e76e02 100644 --- a/indra/newview/llappearancelistener.cpp +++ b/indra/newview/llappearancelistener.cpp @@ -137,7 +137,7 @@ void LLAppearanceListener::getOutfitItems(LLSD const &data) LLViewerInventoryCategory *cat = gInventory.getCategory(outfit_id); if (!cat || cat->getPreferredType() != LLFolderType::FT_OUTFIT) { - return response.error(stringize(LLTrans::getString("OutfitNotFound"), outfit_id.asString())); + return response.error(stringize("Couldn't find outfit ", outfit_id.asString())); } LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 8e6657b4b9..66a19d3601 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -42,6 +42,7 @@ // Viewer includes #include "llagent.h" #include "llagentaccess.h" +#include "llcallbacklist.h" #include "llviewerparcelaskplay.h" #include "llviewerwindow.h" #include "llviewercontrol.h" @@ -1750,6 +1751,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use { instance->mTeleportFinishedSignal(instance->mTeleportInProgressPosition, false); } + instance->postTeleportFinished(instance->mTeleportWithinRegion); + instance->mTeleportWithinRegion = false; } parcel->setParcelEnvironmentVersion(parcel_environment_version); LL_DEBUGS("ENVIRONMENT") << "Parcel environment version is " << parcel->getParcelEnvironmentVersion() << LL_ENDL; @@ -2719,6 +2722,8 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos // Local teleport. We already have the agent parcel data. // Emit the signal immediately. getInstance()->mTeleportFinishedSignal(new_pos, local); + + postTeleportFinished(true); } else { @@ -2727,12 +2732,14 @@ void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos // Let's wait for the update and then emit the signal. mTeleportInProgressPosition = new_pos; mTeleportInProgress = true; + mTeleportWithinRegion = local; } } void LLViewerParcelMgr::onTeleportFailed() { mTeleportFailedSignal(); + LLEventPumps::instance().obtain("LLTeleport").post(llsd::map("success", false)); } bool LLViewerParcelMgr::getTeleportInProgress() @@ -2740,3 +2747,20 @@ bool LLViewerParcelMgr::getTeleportInProgress() return mTeleportInProgress // case where parcel data arrives after teleport || gAgent.getTeleportState() > LLAgent::TELEPORT_NONE; // For LOCAL, no mTeleportInProgress } + +void LLViewerParcelMgr::postTeleportFinished(bool local) +{ + auto post = []() + { + LLEventPumps::instance().obtain("LLTeleport").post(llsd::map("success", true)); + }; + if (local) + { + static LLCachedControl teleport_local_delay(gSavedSettings, "TeleportLocalDelay"); + doAfterInterval(post, teleport_local_delay + 0.5f); + } + else + { + post(); + } +} diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index 974ea39359..95d693662e 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -295,6 +295,8 @@ public: void onTeleportFailed(); bool getTeleportInProgress(); + void postTeleportFinished(bool local); + static bool isParcelOwnedByAgent(const LLParcel* parcelp, U64 group_proxy_power); static bool isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power); @@ -344,7 +346,9 @@ private: std::vector mObservers; + // Used to communicate between onTeleportFinished() and processParcelProperties() bool mTeleportInProgress; + bool mTeleportWithinRegion{ false }; LLVector3d mTeleportInProgressPosition; teleport_finished_signal_t mTeleportFinishedSignal; teleport_failed_signal_t mTeleportFailedSignal; -- cgit v1.3 From f2e7e30cffca1de0a1ee9287753156f8a312b7dd Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 3 Apr 2025 20:27:28 +0300 Subject: #3868 Crash in updateHoveredState according to bugsplat mWrapperPanel is null. --- indra/newview/lltoast.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra') diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 84503e66a5..84854a79d4 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -436,6 +436,14 @@ void LLToast::setVisible(bool show) void LLToast::updateHoveredState() { + if (!mWrapperPanel) + { + // Shouldn't be happening. + // mWrapperPanel should have been inited in the constructor + // This needs to be figured out and fixed + llassert(false); + return; + } S32 x, y; LLUI::getInstance()->getMousePositionScreen(&x, &y); -- cgit v1.3 From f795ad6d6298a5a2e13a9cf9117f9c1d39475a4f Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 3 Apr 2025 21:15:57 +0300 Subject: #3870 Crash at LLVOAvatarSelf::getJoint() A long standing one --- indra/newview/llvoavatar.h | 2 +- indra/newview/llvoavatarself.cpp | 9 +++++++++ indra/newview/llvoavatarself.h | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 263c3dadf6..a2232d21a2 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -547,7 +547,7 @@ public: U32 renderTransparent(bool first_pass); void renderCollisionVolumes(); void renderBones(const std::string &selected_joint = std::string()); - void renderJoints(); + virtual void renderJoints(); static void deleteCachedImages(bool clearAll=true); static void destroyGL(); static void restoreGL(); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 746ef7cacb..f23af5afa4 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -697,6 +697,7 @@ void LLVOAvatarSelf::idleUpdate(LLAgent &agent, const F64 &time) // virtual LLJoint *LLVOAvatarSelf::getJoint(const std::string &name) { + std::lock_guard lock(mJointMapMutex); LLJoint *jointp = NULL; jointp = LLVOAvatar::getJoint(name); if (!jointp && mScreenp) @@ -714,6 +715,14 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name) return jointp; } + +//virtual +void LLVOAvatarSelf::renderJoints() +{ + std::lock_guard lock(mJointMapMutex); + LLVOAvatar::renderJoints(); +} + // virtual bool LLVOAvatarSelf::setVisualParamWeight(const LLVisualParam *which_param, F32 weight) { diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 051ac791c0..f9bea41b1d 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -92,6 +92,8 @@ public: /*virtual*/ void requestStopMotion(LLMotion* motion); /*virtual*/ LLJoint* getJoint(const std::string &name); + /*virtual*/ void renderJoints(); + /*virtual*/ bool setVisualParamWeight(const LLVisualParam *which_param, F32 weight); /*virtual*/ bool setVisualParamWeight(const char* param_name, F32 weight); /*virtual*/ bool setVisualParamWeight(S32 index, F32 weight); @@ -103,6 +105,8 @@ private: // helper function. Passed in param is assumed to be in avatar's parameter list. bool setParamWeight(const LLViewerVisualParam *param, F32 weight); + std::mutex mJointMapMutex; // getJoint gets used from mesh thread + /******************************************************************************** ** ** ** STATE -- cgit v1.3 From 68f20d542ebbb999d7bebb05c7e4c08ebafdfd89 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 3 Apr 2025 21:55:38 +0300 Subject: #2702 Increase hover height's limit --- indra/newview/llvoavatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 40312b7f4e..de530976ea 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -122,8 +122,8 @@ extern F32 ANIM_SPEED_MAX; extern F32 ANIM_SPEED_MIN; extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG; -const F32 MAX_HOVER_Z = 2.0; -const F32 MIN_HOVER_Z = -2.0; +const F32 MAX_HOVER_Z = 3.0; +const F32 MIN_HOVER_Z = -3.0; const F32 MIN_ATTACHMENT_COMPLEXITY = 0.f; const F32 DEFAULT_MAX_ATTACHMENT_COMPLEXITY = 1.0e6f; -- cgit v1.3 From 2b475ad027285144bbbe46cbfa6db17744acd15b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 4 Apr 2025 21:49:23 +0300 Subject: #3878 Crash at LLPipeline::unlinkDrawable assertInitializedDoError() on shutdown --- indra/newview/lldrawable.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 4921964b35..9d212cfe8b 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -253,7 +253,15 @@ void LLDrawable::cleanupReferences() std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); mFaces.clear(); - gPipeline.unlinkDrawable(this); + if (gPipeline.mInitialized) + { + gPipeline.unlinkDrawable(this); + } + else if (getSpatialGroup()) + { + // Not supposed to happen? + getSpatialGroup()->getSpatialPartition()->remove(this, getSpatialGroup()); + } removeFromOctree(); -- cgit v1.3 From 9aea5bb5e25a3b046c305eb0200fa9e84895c898 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 4 Apr 2025 22:39:37 +0300 Subject: #3876 sendLogoutRequest logging mac's crash logs seem to get mixed with normal logs, hope is this will help confirming the issue. Also needed for automated testing. --- indra/newview/llappviewer.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index dfe4a0c197..edc70030b4 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -5255,6 +5255,8 @@ void LLAppViewer::sendLogoutRequest() msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); gAgent.sendReliableMessage(); + LL_INFOS("Agent") << "Logging out as agent: " << gAgent.getID() << " Session: " << gAgent.getSessionID() << LL_ENDL; + gLogoutTimer.reset(); gLogoutMaxTime = LOGOUT_REQUEST_TIME; mLogoutRequestSent = true; -- cgit v1.3 From 2da46c38305f6002993cd1974a9342935e97f8c6 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 1 Apr 2025 22:59:22 +0300 Subject: #3575 Clean up obsolete VRAM detectin logic --- indra/llrender/llgl.cpp | 19 - indra/llwindow/lldxhardware.cpp | 652 ------------------------- indra/llwindow/lldxhardware.h | 68 --- indra/newview/llappviewerwin32.cpp | 60 +-- indra/newview/skins/default/xui/en/strings.xml | 1 - 5 files changed, 1 insertion(+), 799 deletions(-) (limited to 'indra') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 1966e48f2e..0be27b8975 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -1228,28 +1228,9 @@ bool LLGLManager::initGL() } #endif -#if LL_WINDOWS - if (mVRAM < 256) - { - // Something likely went wrong using the above extensions - // try WMI first and fall back to old method (from dxdiag) if all else fails - // Function will check all GPUs WMI knows of and will pick up the one with most - // memory. We need to check all GPUs because system can switch active GPU to - // weaker one, to preserve power when not under load. - U32 mem = LLDXHardware::getMBVideoMemoryViaWMI(); - if (mem != 0) - { - mVRAM = mem; - LL_WARNS("RenderInit") << "VRAM Detected (WMI):" << mVRAM<< LL_ENDL; - } - } -#endif - if (mVRAM < 256 && old_vram > 0) { // fall back to old method - // Note: on Windows value will be from LLDXHardware. - // Either received via dxdiag or via WMI by id from dxdiag. mVRAM = old_vram; } diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp index 4bc069c5a4..387982dfc2 100644 --- a/indra/llwindow/lldxhardware.cpp +++ b/indra/llwindow/lldxhardware.cpp @@ -47,7 +47,6 @@ #include "llstl.h" #include "lltimer.h" -void (*gWriteDebug)(const char* msg) = NULL; LLDXHardware gDXHardware; //----------------------------------------------------------------------------- @@ -61,170 +60,6 @@ typedef BOOL ( WINAPI* PfnCoSetProxyBlanket )( IUnknown* pProxy, DWORD dwAuthnSv OLECHAR* pServerPrincName, DWORD dwAuthnLevel, DWORD dwImpLevel, RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities ); -HRESULT GetVideoMemoryViaWMI(WCHAR* strInputDeviceID, DWORD* pdwAdapterRam) -{ - HRESULT hr; - bool bGotMemory = false; - IWbemLocator* pIWbemLocator = nullptr; - IWbemServices* pIWbemServices = nullptr; - BSTR pNamespace = nullptr; - - *pdwAdapterRam = 0; - CoInitializeEx(0, COINIT_APARTMENTTHREADED); - - hr = CoCreateInstance( CLSID_WbemLocator, - nullptr, - CLSCTX_INPROC_SERVER, - IID_IWbemLocator, - ( LPVOID* )&pIWbemLocator ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) wprintf( L"WMI: CoCreateInstance failed: 0x%0.8x\n", hr ); -#endif - - if( SUCCEEDED( hr ) && pIWbemLocator ) - { - // Using the locator, connect to WMI in the given namespace. - pNamespace = SysAllocString( L"\\\\.\\root\\cimv2" ); - - hr = pIWbemLocator->ConnectServer( pNamespace, nullptr, nullptr, 0L, - 0L, nullptr, nullptr, &pIWbemServices ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) wprintf( L"WMI: pIWbemLocator->ConnectServer failed: 0x%0.8x\n", hr ); -#endif - if( SUCCEEDED( hr ) && pIWbemServices != 0 ) - { - HINSTANCE hinstOle32 = nullptr; - - hinstOle32 = LoadLibraryW( L"ole32.dll" ); - if( hinstOle32 ) - { - PfnCoSetProxyBlanket pfnCoSetProxyBlanket = nullptr; - - pfnCoSetProxyBlanket = ( PfnCoSetProxyBlanket )GetProcAddress( hinstOle32, "CoSetProxyBlanket" ); - if( pfnCoSetProxyBlanket != 0 ) - { - // Switch security level to IMPERSONATE. - pfnCoSetProxyBlanket( pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, - RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, 0 ); - } - - FreeLibrary( hinstOle32 ); - } - - IEnumWbemClassObject* pEnumVideoControllers = nullptr; - BSTR pClassName = nullptr; - - pClassName = SysAllocString( L"Win32_VideoController" ); - - hr = pIWbemServices->CreateInstanceEnum( pClassName, 0, - nullptr, &pEnumVideoControllers ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) wprintf( L"WMI: pIWbemServices->CreateInstanceEnum failed: 0x%0.8x\n", hr ); -#endif - - if( SUCCEEDED( hr ) && pEnumVideoControllers ) - { - IWbemClassObject* pVideoControllers[10] = {0}; - DWORD uReturned = 0; - BSTR pPropName = nullptr; - - // Get the first one in the list - pEnumVideoControllers->Reset(); - hr = pEnumVideoControllers->Next( 5000, // timeout in 5 seconds - 10, // return the first 10 - pVideoControllers, - &uReturned ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) wprintf( L"WMI: pEnumVideoControllers->Next failed: 0x%0.8x\n", hr ); - if( uReturned == 0 ) wprintf( L"WMI: pEnumVideoControllers uReturned == 0\n" ); -#endif - - VARIANT var; - if( SUCCEEDED( hr ) ) - { - bool bFound = false; - for( UINT iController = 0; iController < uReturned; iController++ ) - { - if ( !pVideoControllers[iController] ) - continue; - - // if strInputDeviceID is set find this specific device and return memory or specific device - // if strInputDeviceID is not set return the best device - if (strInputDeviceID) - { - pPropName = SysAllocString( L"PNPDeviceID" ); - hr = pVideoControllers[iController]->Get( pPropName, 0L, &var, nullptr, nullptr ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) - wprintf( L"WMI: pVideoControllers[iController]->Get PNPDeviceID failed: 0x%0.8x\n", hr ); -#endif - if( SUCCEEDED( hr ) && strInputDeviceID) - { - if( wcsstr( var.bstrVal, strInputDeviceID ) != 0 ) - bFound = true; - } - VariantClear( &var ); - if( pPropName ) SysFreeString( pPropName ); - } - - if( bFound || !strInputDeviceID ) - { - pPropName = SysAllocString( L"AdapterRAM" ); - hr = pVideoControllers[iController]->Get( pPropName, 0L, &var, nullptr, nullptr ); -#ifdef PRINTF_DEBUGGING - if( FAILED( hr ) ) - wprintf( L"WMI: pVideoControllers[iController]->Get AdapterRAM failed: 0x%0.8x\n", - hr ); -#endif - if( SUCCEEDED( hr ) ) - { - bGotMemory = true; - *pdwAdapterRam = llmax(var.ulVal, *pdwAdapterRam); - } - VariantClear( &var ); - if( pPropName ) SysFreeString( pPropName ); - } - - SAFE_RELEASE( pVideoControllers[iController] ); - - if (bFound) - { - break; - } - } - } - } - - if( pClassName ) - SysFreeString( pClassName ); - SAFE_RELEASE( pEnumVideoControllers ); - } - - if( pNamespace ) - SysFreeString( pNamespace ); - SAFE_RELEASE( pIWbemServices ); - } - - SAFE_RELEASE( pIWbemLocator ); - - CoUninitialize(); - - if( bGotMemory ) - return S_OK; - else - return E_FAIL; -} - -//static -U32 LLDXHardware::getMBVideoMemoryViaWMI() -{ - DWORD vram = 0; - if (SUCCEEDED(GetVideoMemoryViaWMI(NULL, &vram))) - { - return vram / (1024 * 1024);; - } - return 0; -} //Getting the version of graphics controller driver via WMI std::string LLDXHardware::getDriverVersionWMI(EGPUVendor vendor) @@ -480,495 +315,14 @@ std::string get_string(IDxDiagContainer *containerp, const WCHAR *wszPropName) return utf16str_to_utf8str(wszPropValue); } - -LLVersion::LLVersion() -{ - mValid = false; - S32 i; - for (i = 0; i < 4; i++) - { - mFields[i] = 0; - } -} - -bool LLVersion::set(const std::string &version_string) -{ - S32 i; - for (i = 0; i < 4; i++) - { - mFields[i] = 0; - } - // Split the version string. - std::string str(version_string); - typedef boost::tokenizer > tokenizer; - boost::char_separator sep(".", "", boost::keep_empty_tokens); - tokenizer tokens(str, sep); - - tokenizer::iterator iter = tokens.begin(); - S32 count = 0; - for (;(iter != tokens.end()) && (count < 4);++iter) - { - mFields[count] = atoi(iter->c_str()); - count++; - } - if (count < 4) - { - //LL_WARNS() << "Potentially bogus version string!" << version_string << LL_ENDL; - for (i = 0; i < 4; i++) - { - mFields[i] = 0; - } - mValid = false; - } - else - { - mValid = true; - } - return mValid; -} - -S32 LLVersion::getField(const S32 field_num) -{ - if (!mValid) - { - return -1; - } - else - { - return mFields[field_num]; - } -} - -std::string LLDXDriverFile::dump() -{ - if (gWriteDebug) - { - gWriteDebug("Filename:"); - gWriteDebug(mName.c_str()); - gWriteDebug("\n"); - gWriteDebug("Ver:"); - gWriteDebug(mVersionString.c_str()); - gWriteDebug("\n"); - gWriteDebug("Date:"); - gWriteDebug(mDateString.c_str()); - gWriteDebug("\n"); - } - LL_INFOS() << mFilepath << LL_ENDL; - LL_INFOS() << mName << LL_ENDL; - LL_INFOS() << mVersionString << LL_ENDL; - LL_INFOS() << mDateString << LL_ENDL; - - return ""; -} - -LLDXDevice::~LLDXDevice() -{ - for_each(mDriverFiles.begin(), mDriverFiles.end(), DeletePairedPointer()); - mDriverFiles.clear(); -} - -std::string LLDXDevice::dump() -{ - if (gWriteDebug) - { - gWriteDebug("StartDevice\n"); - gWriteDebug("DeviceName:"); - gWriteDebug(mName.c_str()); - gWriteDebug("\n"); - gWriteDebug("PCIString:"); - gWriteDebug(mPCIString.c_str()); - gWriteDebug("\n"); - } - LL_INFOS() << LL_ENDL; - LL_INFOS() << "DeviceName:" << mName << LL_ENDL; - LL_INFOS() << "PCIString:" << mPCIString << LL_ENDL; - LL_INFOS() << "Drivers" << LL_ENDL; - LL_INFOS() << "-------" << LL_ENDL; - for (driver_file_map_t::iterator iter = mDriverFiles.begin(), - end = mDriverFiles.end(); - iter != end; iter++) - { - LLDXDriverFile *filep = iter->second; - filep->dump(); - } - if (gWriteDebug) - { - gWriteDebug("EndDevice\n"); - } - - return ""; -} - -LLDXDriverFile *LLDXDevice::findDriver(const std::string &driver) -{ - for (driver_file_map_t::iterator iter = mDriverFiles.begin(), - end = mDriverFiles.end(); - iter != end; iter++) - { - LLDXDriverFile *filep = iter->second; - if (!utf8str_compare_insensitive(filep->mName,driver)) - { - return filep; - } - } - - return NULL; -} - LLDXHardware::LLDXHardware() { - mVRAM = 0; - gWriteDebug = NULL; } void LLDXHardware::cleanup() { - // for_each(mDevices.begin(), mDevices.end(), DeletePairedPointer()); - // mDevices.clear(); -} - -/* -std::string LLDXHardware::dumpDevices() -{ - if (gWriteDebug) - { - gWriteDebug("\n"); - gWriteDebug("StartAllDevices\n"); - } - for (device_map_t::iterator iter = mDevices.begin(), - end = mDevices.end(); - iter != end; iter++) - { - LLDXDevice *devicep = iter->second; - devicep->dump(); - } - if (gWriteDebug) - { - gWriteDebug("EndAllDevices\n\n"); - } - return ""; } -LLDXDevice *LLDXHardware::findDevice(const std::string &vendor, const std::string &devices) -{ - // Iterate through different devices tokenized in devices string - std::string str(devices); - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("|", "", boost::keep_empty_tokens); - tokenizer tokens(str, sep); - - tokenizer::iterator iter = tokens.begin(); - for (;iter != tokens.end();++iter) - { - std::string dev_str = *iter; - for (device_map_t::iterator iter = mDevices.begin(), - end = mDevices.end(); - iter != end; iter++) - { - LLDXDevice *devicep = iter->second; - if ((devicep->mVendorID == vendor) - && (devicep->mDeviceID == dev_str)) - { - return devicep; - } - } - } - - return NULL; -} -*/ - -bool LLDXHardware::getInfo(bool vram_only) -{ - LLTimer hw_timer; - bool ok = false; - HRESULT hr; - - // CLSID_DxDiagProvider does not work with Multithreaded? - CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - - IDxDiagProvider *dx_diag_providerp = NULL; - IDxDiagContainer *dx_diag_rootp = NULL; - IDxDiagContainer *devices_containerp = NULL; - // IDxDiagContainer *system_device_containerp= NULL; - IDxDiagContainer *device_containerp = NULL; - IDxDiagContainer *file_containerp = NULL; - IDxDiagContainer *driver_containerp = NULL; - DWORD dw_device_count; - - mVRAM = 0; - - // CoCreate a IDxDiagProvider* - LL_DEBUGS("AppInit") << "CoCreateInstance IID_IDxDiagProvider" << LL_ENDL; - hr = CoCreateInstance(CLSID_DxDiagProvider, - NULL, - CLSCTX_INPROC_SERVER, - IID_IDxDiagProvider, - (LPVOID*) &dx_diag_providerp); - - if (FAILED(hr)) - { - LL_WARNS("AppInit") << "No DXDiag provider found! DirectX 9 not installed!" << LL_ENDL; - gWriteDebug("No DXDiag provider found! DirectX 9 not installed!\n"); - goto LCleanup; - } - if (SUCCEEDED(hr)) // if FAILED(hr) then dx9 is not installed - { - // Fill out a DXDIAG_INIT_PARAMS struct and pass it to IDxDiagContainer::Initialize - // Passing in TRUE for bAllowWHQLChecks, allows dxdiag to check if drivers are - // digital signed as logo'd by WHQL which may connect via internet to update - // WHQL certificates. - DXDIAG_INIT_PARAMS dx_diag_init_params; - ZeroMemory(&dx_diag_init_params, sizeof(DXDIAG_INIT_PARAMS)); - - dx_diag_init_params.dwSize = sizeof(DXDIAG_INIT_PARAMS); - dx_diag_init_params.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION; - dx_diag_init_params.bAllowWHQLChecks = TRUE; - dx_diag_init_params.pReserved = NULL; - - LL_DEBUGS("AppInit") << "dx_diag_providerp->Initialize" << LL_ENDL; - hr = dx_diag_providerp->Initialize(&dx_diag_init_params); - if(FAILED(hr)) - { - goto LCleanup; - } - - LL_DEBUGS("AppInit") << "dx_diag_providerp->GetRootContainer" << LL_ENDL; - hr = dx_diag_providerp->GetRootContainer( &dx_diag_rootp ); - if(FAILED(hr) || !dx_diag_rootp) - { - goto LCleanup; - } - - HRESULT hr; - - // Get display driver information - LL_DEBUGS("AppInit") << "dx_diag_rootp->GetChildContainer" << LL_ENDL; - hr = dx_diag_rootp->GetChildContainer(L"DxDiag_DisplayDevices", &devices_containerp); - if(FAILED(hr) || !devices_containerp) - { - // do not release 'dirty' devices_containerp at this stage, only dx_diag_rootp - devices_containerp = NULL; - goto LCleanup; - } - - // make sure there is something inside - hr = devices_containerp->GetNumberOfChildContainers(&dw_device_count); - if (FAILED(hr) || dw_device_count == 0) - { - goto LCleanup; - } - - // Get device 0 - // By default 0 device is the primary one, howhever in case of various hybrid graphics - // like itegrated AMD and PCI AMD GPUs system might switch. - LL_DEBUGS("AppInit") << "devices_containerp->GetChildContainer" << LL_ENDL; - hr = devices_containerp->GetChildContainer(L"0", &device_containerp); - if(FAILED(hr) || !device_containerp) - { - goto LCleanup; - } - - DWORD vram = 0; - - WCHAR deviceID[512]; - - get_wstring(device_containerp, L"szDeviceID", deviceID, 512); - // Example: searches id like 1F06 in pnp string (aka VEN_10DE&DEV_1F06) - // doesn't seem to work on some systems since format is unrecognizable - // but in such case keyDeviceID works - if (SUCCEEDED(GetVideoMemoryViaWMI(deviceID, &vram))) - { - mVRAM = vram/(1024*1024); - } - else - { - get_wstring(device_containerp, L"szKeyDeviceID", deviceID, 512); - LL_WARNS() << "szDeviceID" << deviceID << LL_ENDL; - // '+9' to avoid ENUM\\PCI\\ prefix - // Returns string like Enum\\PCI\\VEN_10DE&DEV_1F06&SUBSYS... - // and since GetVideoMemoryViaWMI searches by PNPDeviceID it is sufficient - if (SUCCEEDED(GetVideoMemoryViaWMI(deviceID + 9, &vram))) - { - mVRAM = vram / (1024 * 1024); - } - } - - if (mVRAM == 0) - { // Get the English VRAM string - std::string ram_str = get_string(device_containerp, L"szDisplayMemoryEnglish"); - - // We don't need the device any more - SAFE_RELEASE(device_containerp); - - // Dump the string as an int into the structure - char *stopstring; - mVRAM = strtol(ram_str.c_str(), &stopstring, 10); - LL_INFOS("AppInit") << "VRAM Detected: " << mVRAM << " DX9 string: " << ram_str << LL_ENDL; - } - - if (vram_only) - { - ok = true; - goto LCleanup; - } - - - /* for now, we ONLY do vram_only the rest of this - is commented out, to ensure no-one is tempted - to use it - - // Now let's get device and driver information - // Get the IDxDiagContainer object called "DxDiag_SystemDevices". - // This call may take some time while dxdiag gathers the info. - DWORD num_devices = 0; - WCHAR wszContainer[256]; - LL_DEBUGS("AppInit") << "dx_diag_rootp->GetChildContainer DxDiag_SystemDevices" << LL_ENDL; - hr = dx_diag_rootp->GetChildContainer(L"DxDiag_SystemDevices", &system_device_containerp); - if (FAILED(hr)) - { - goto LCleanup; - } - - hr = system_device_containerp->GetNumberOfChildContainers(&num_devices); - if (FAILED(hr)) - { - goto LCleanup; - } - - LL_DEBUGS("AppInit") << "DX9 iterating over devices" << LL_ENDL; - S32 device_num = 0; - for (device_num = 0; device_num < (S32)num_devices; device_num++) - { - hr = system_device_containerp->EnumChildContainerNames(device_num, wszContainer, 256); - if (FAILED(hr)) - { - goto LCleanup; - } - - hr = system_device_containerp->GetChildContainer(wszContainer, &device_containerp); - if (FAILED(hr) || device_containerp == NULL) - { - goto LCleanup; - } - - std::string device_name = get_string(device_containerp, L"szDescription"); - - std::string device_id = get_string(device_containerp, L"szDeviceID"); - - LLDXDevice *dxdevicep = new LLDXDevice; - dxdevicep->mName = device_name; - dxdevicep->mPCIString = device_id; - mDevices[dxdevicep->mPCIString] = dxdevicep; - - // Split the PCI string based on vendor, device, subsys, rev. - std::string str(device_id); - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("&\\", "", boost::keep_empty_tokens); - tokenizer tokens(str, sep); - - tokenizer::iterator iter = tokens.begin(); - S32 count = 0; - bool valid = true; - for (;(iter != tokens.end()) && (count < 3);++iter) - { - switch (count) - { - case 0: - if (strcmp(iter->c_str(), "PCI")) - { - valid = false; - } - break; - case 1: - dxdevicep->mVendorID = iter->c_str(); - break; - case 2: - dxdevicep->mDeviceID = iter->c_str(); - break; - default: - // Ignore it - break; - } - count++; - } - - - - - // Now, iterate through the related drivers - hr = device_containerp->GetChildContainer(L"Drivers", &driver_containerp); - if (FAILED(hr) || !driver_containerp) - { - goto LCleanup; - } - - DWORD num_files = 0; - hr = driver_containerp->GetNumberOfChildContainers(&num_files); - if (FAILED(hr)) - { - goto LCleanup; - } - - S32 file_num = 0; - for (file_num = 0; file_num < (S32)num_files; file_num++ ) - { - - hr = driver_containerp->EnumChildContainerNames(file_num, wszContainer, 256); - if (FAILED(hr)) - { - goto LCleanup; - } - - hr = driver_containerp->GetChildContainer(wszContainer, &file_containerp); - if (FAILED(hr) || file_containerp == NULL) - { - goto LCleanup; - } - - std::string driver_path = get_string(file_containerp, L"szPath"); - std::string driver_name = get_string(file_containerp, L"szName"); - std::string driver_version = get_string(file_containerp, L"szVersion"); - std::string driver_date = get_string(file_containerp, L"szDatestampEnglish"); - - LLDXDriverFile *dxdriverfilep = new LLDXDriverFile; - dxdriverfilep->mName = driver_name; - dxdriverfilep->mFilepath= driver_path; - dxdriverfilep->mVersionString = driver_version; - dxdriverfilep->mVersion.set(driver_version); - dxdriverfilep->mDateString = driver_date; - - dxdevicep->mDriverFiles[driver_name] = dxdriverfilep; - - SAFE_RELEASE(file_containerp); - } - SAFE_RELEASE(device_containerp); - } - */ - } - - // dumpDevices(); - ok = true; - -LCleanup: - if (!ok) - { - LL_WARNS("AppInit") << "DX9 probe failed" << LL_ENDL; - gWriteDebug("DX9 probe failed\n"); - } - - SAFE_RELEASE(file_containerp); - SAFE_RELEASE(driver_containerp); - SAFE_RELEASE(device_containerp); - SAFE_RELEASE(devices_containerp); - SAFE_RELEASE(dx_diag_rootp); - SAFE_RELEASE(dx_diag_providerp); - - CoUninitialize(); - - return ok; - } - LLSD LLDXHardware::getDisplayInfo() { LLTimer hw_timer; @@ -995,7 +349,6 @@ LLSD LLDXHardware::getDisplayInfo() if (FAILED(hr)) { LL_WARNS() << "No DXDiag provider found! DirectX 9 not installed!" << LL_ENDL; - gWriteDebug("No DXDiag provider found! DirectX 9 not installed!\n"); goto LCleanup; } if (SUCCEEDED(hr)) // if FAILED(hr) then dx9 is not installed @@ -1111,9 +464,4 @@ LCleanup: return ret; } -void LLDXHardware::setWriteDebugFunc(void (*func)(const char*)) -{ - gWriteDebug = func; -} - #endif diff --git a/indra/llwindow/lldxhardware.h b/indra/llwindow/lldxhardware.h index 2b879e021c..8d8a08a4eb 100644 --- a/indra/llwindow/lldxhardware.h +++ b/indra/llwindow/lldxhardware.h @@ -30,64 +30,16 @@ #include #include "stdtypes.h" -#include "llstring.h" #include "llsd.h" -class LLVersion -{ -public: - LLVersion(); - bool set(const std::string &version_string); - S32 getField(const S32 field_num); -protected: - std::string mVersionString; - S32 mFields[4]; - bool mValid; -}; - -class LLDXDriverFile -{ -public: - std::string dump(); - -public: - std::string mFilepath; - std::string mName; - std::string mVersionString; - LLVersion mVersion; - std::string mDateString; -}; - -class LLDXDevice -{ -public: - ~LLDXDevice(); - std::string dump(); - - LLDXDriverFile *findDriver(const std::string &driver); -public: - std::string mName; - std::string mPCIString; - std::string mVendorID; - std::string mDeviceID; - - typedef std::map driver_file_map_t; - driver_file_map_t mDriverFiles; -}; - class LLDXHardware { public: LLDXHardware(); - void setWriteDebugFunc(void (*func)(const char*)); void cleanup(); - // Returns true on success. - // vram_only true does a "light" probe. - bool getInfo(bool vram_only); - // WMI can return multiple GPU drivers // specify which one to output typedef enum { @@ -98,29 +50,9 @@ public: } EGPUVendor; std::string getDriverVersionWMI(EGPUVendor vendor); - S32 getVRAM() const { return mVRAM; } - LLSD getDisplayInfo(); - - // Will get memory of best GPU in MB, return memory on sucsess, 0 on failure - // Note: WMI is not accurate in some cases - static U32 getMBVideoMemoryViaWMI(); - - // Find a particular device that matches the following specs. - // Empty strings indicate that you don't care. - // You can separate multiple devices with '|' chars to indicate you want - // ANY of them to match and return. - // LLDXDevice *findDevice(const std::string &vendor, const std::string &devices); - - // std::string dumpDevices(); -public: - typedef std::map device_map_t; - // device_map_t mDevices; -protected: - S32 mVRAM; }; -extern void (*gWriteDebug)(const char* msg); extern LLDXHardware gDXHardware; #endif // LL_LLDXHARDWARE_H diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index aaf2a7ea3e..4f5fa53312 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -842,69 +842,11 @@ void write_debug_dx(const std::string& str) bool LLAppViewerWin32::initHardwareTest() { - // - // Do driver verification and initialization based on DirectX - // hardware polling and driver versions - // - if (true == gSavedSettings.getBOOL("ProbeHardwareOnStartup") && false == gSavedSettings.getBOOL("NoHardwareProbe")) - { - // per DEV-11631 - disable hardware probing for everything - // but vram. - bool vram_only = true; - - LLSplashScreen::update(LLTrans::getString("StartupDetectingHardware")); - - LL_DEBUGS("AppInit") << "Attempting to poll DirectX for hardware info" << LL_ENDL; - gDXHardware.setWriteDebugFunc(write_debug_dx); - bool probe_ok = gDXHardware.getInfo(vram_only); - - if (!probe_ok - && gWarningSettings.getBOOL("AboutDirectX9")) - { - LL_WARNS("AppInit") << "DirectX probe failed, alerting user." << LL_ENDL; - - // Warn them that runnin without DirectX 9 will - // not allow us to tell them about driver issues - std::ostringstream msg; - msg << LLTrans::getString ("MBNoDirectX"); - S32 button = OSMessageBox( - msg.str(), - LLTrans::getString("MBWarning"), - OSMB_YESNO); - if (OSBTN_NO== button) - { - LL_INFOS("AppInit") << "User quitting after failed DirectX 9 detection" << LL_ENDL; - LLWeb::loadURLExternal("http://secondlife.com/support/", false); - return false; - } - gWarningSettings.setBOOL("AboutDirectX9", false); - } - LL_DEBUGS("AppInit") << "Done polling DirectX for hardware info" << LL_ENDL; - - // Only probe once after installation - gSavedSettings.setBOOL("ProbeHardwareOnStartup", false); - - // Disable so debugger can work - std::string splash_msg; - LLStringUtil::format_map_t args; - args["[APP_NAME]"] = LLAppViewer::instance()->getSecondLifeTitle(); - splash_msg = LLTrans::getString("StartupLoading", args); - - LLSplashScreen::update(splash_msg); - } - if (!restoreErrorTrap()) { - LL_WARNS("AppInit") << " Someone took over my exception handler (post hardware probe)!" << LL_ENDL; + LL_WARNS("AppInit") << " Someone took over my exception handler!" << LL_ENDL; } - if (gGLManager.mVRAM == 0) - { - gGLManager.mVRAM = gDXHardware.getVRAM(); - } - - LL_INFOS("AppInit") << "Detected VRAM: " << gGLManager.mVRAM << LL_ENDL; - return true; } diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index f0a26f9c56..d909a95b83 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -13,7 +13,6 @@ Second Life Support Portal - Detecting hardware... Loading [APP_NAME]... Clearing cache... Initializing texture cache... -- cgit v1.3 From 0c056c77f4eddb13e3e7a2a1d3d4b881dc07ea46 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 1 Apr 2025 23:24:51 +0300 Subject: #3575 Adjust VRAM budget test a bit --- indra/llwindow/llwindowwin32.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 832cf254d1..c190295512 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -4684,9 +4684,18 @@ void LLWindowWin32::LLWindowWin32Thread::checkDXMem() if (phys_mb > 0) { - // Intel uses 'shared' vram, cap it to 25% of total memory - // Todo: consider caping all adapters at least to 50% ram - budget_mb = llmin(budget_mb, (UINT64)(phys_mb * 0.25)); + if (gGLManager.mIsIntel) + { + // Intel uses 'shared' vram, cap it to 25% of total memory + // Todo: consider a way of detecting integrated Intel and AMD + budget_mb = llmin(budget_mb, (UINT64)(phys_mb * 0.25)); + } + else + { + // More budget is generally better, but the way viewer + // utilizes even dedicated VRAM leaves a footprint in RAM + budget_mb = llmin(budget_mb, (UINT64)(phys_mb * 0.75)); + } } else { -- cgit v1.3 From cc54e206c3ea390a3a14829a4ac40ce5d98f5965 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 2 Apr 2025 00:05:57 +0300 Subject: #3575 Shrink draw distance when VRAM is very low --- indra/newview/lldrawpoolavatar.cpp | 2 -- indra/newview/llviewerdisplay.cpp | 6 +++++- indra/newview/llvoavatar.cpp | 6 ++---- indra/newview/llworld.cpp | 4 +--- 4 files changed, 8 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 95f96e85d6..90ee95d424 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -491,7 +491,6 @@ void LLDrawPoolAvatar::beginImpostor() if (!LLPipeline::sReflectionRender) { - LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f); LLVOAvatar::sNumVisibleAvatars = 0; } @@ -547,7 +546,6 @@ void LLDrawPoolAvatar::beginDeferredImpostor() if (!LLPipeline::sReflectionRender) { - LLVOAvatar::sRenderDistance = llclamp(LLVOAvatar::sRenderDistance, 16.f, 256.f); LLVOAvatar::sNumVisibleAvatars = 0; } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 32019f860d..27718782ee 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -215,11 +215,15 @@ void display_update_camera() final_far = gSavedSettings.getF32("RenderReflectionProbeDrawDistance"); } else if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode()) - { final_far *= 0.5f; } + else if (LLViewerTexture::sDesiredDiscardBias > 2.f) + { + final_far = llmax(32.f, final_far / (LLViewerTexture::sDesiredDiscardBias - 1.f)); + } LLViewerCamera::getInstance()->setFar(final_far); + LLVOAvatar::sRenderDistance = llclamp(final_far, 16.f, 256.f); gViewerWindow->setup3DRender(); if (!gCubeSnapshot) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index de530976ea..3306289f51 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -10963,8 +10963,7 @@ void LLVOAvatar::idleUpdateRenderComplexity() bool autotune = LLPerfStats::tunables.userAutoTuneEnabled && !mIsControlAvatar && !isSelf(); if (autotune && !isDead()) { - static LLCachedControl render_far_clip(gSavedSettings, "RenderFarClip", 64); - F32 radius = render_far_clip * render_far_clip; + F32 radius = sRenderDistance * sRenderDistance; bool is_nearby = true; if ((dist_vec_squared(getPositionGlobal(), gAgent.getPositionGlobal()) > radius) && @@ -10996,8 +10995,7 @@ void LLVOAvatar::updateNearbyAvatarCount() if (agent_update_timer.getElapsedTimeF32() > 1.0f) { S32 avs_nearby = 0; - static LLCachedControl render_far_clip(gSavedSettings, "RenderFarClip", 64); - F32 radius = render_far_clip * render_far_clip; + F32 radius = sRenderDistance * sRenderDistance; for (LLCharacter* character : LLCharacter::sInstances) { LLVOAvatar* avatar = (LLVOAvatar*)character; diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 899733ccc3..47e1815bc2 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1372,10 +1372,8 @@ void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector* positi F32 LLWorld::getNearbyAvatarsAndMaxGPUTime(std::vector &valid_nearby_avs) { - static LLCachedControl render_far_clip(gSavedSettings, "RenderFarClip", 64); - F32 nearby_max_complexity = 0; - F32 radius = render_far_clip * render_far_clip; + F32 radius = LLVOAvatar::sRenderDistance * LLVOAvatar::sRenderDistance; for (LLCharacter* character : LLCharacter::sInstances) { -- cgit v1.3 From f6a2dbe6ec3dbe059ca25cfcd2348619aeacb46b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sun, 6 Apr 2025 15:01:28 +0300 Subject: #3627 std::bad_alloc when loading a model --- indra/newview/gltfscenemanager.cpp | 11 +++++++++-- indra/newview/llmaterialeditor.cpp | 11 +++++++++-- indra/newview/skins/default/xui/en/notifications.xml | 10 ++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index c33d15228c..e0cd762776 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -69,9 +69,16 @@ void GLTFSceneManager::load() { return; } - if (filenames.size() > 0) + try + { + if (filenames.size() > 0) + { + GLTFSceneManager::instance().load(filenames[0]); + } + } + catch (std::bad_alloc&) { - GLTFSceneManager::instance().load(filenames[0]); + LLNotificationsUtil::add("CannotOpenFileTooBig"); } }, LLFilePicker::FFLOAD_GLTF, diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp index 1e3a328464..28160177f6 100644 --- a/indra/newview/llmaterialeditor.cpp +++ b/indra/newview/llmaterialeditor.cpp @@ -2857,9 +2857,16 @@ void LLMaterialEditor::importMaterial() { return; } - if (filenames.size() > 0) + try { - LLMaterialEditor::loadMaterialFromFile(filenames[0], -1); + if (filenames.size() > 0) + { + LLMaterialEditor::loadMaterialFromFile(filenames[0], -1); + } + } + catch (std::bad_alloc&) + { + LLNotificationsUtil::add("CannotOpenFileTooBig"); } }, LLFilePicker::FFLOAD_MATERIAL, diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 509a8eec38..1a56d7e3a3 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2408,6 +2408,16 @@ Unable to upload snapshot. File might be too big, try reducing resolution or try again later. fail + + +Unable to open file. + +Viewer run out of memory while opening file. File might be too big. + fail + Date: Mon, 7 Apr 2025 21:30:47 +0300 Subject: #3873 Return back AudioLevelWind Partial revert from d00b6e4216bb308ae075d90dfa871c902d765f8d Our statistics claimed that AudioLevelWind is unused, but it is in use. --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llvieweraudio.cpp | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a2a6744722..1025c9299d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -345,6 +345,17 @@ F32 Value 0.5 + + AudioLevelWind + + Comment + Audio level of wind noise when standing still + Persist + 1 + Type + F32 + Value + 0.5 AudioStreamingMedia diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index b3b4f43e57..404297c58f 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -541,8 +541,8 @@ void audio_update_wind(bool force_update) // whereas steady-state avatar walk velocity is only 3.2 m/s. // Without this the world feels desolate on first login when you are // standing still. - const F32 WIND_LEVEL = 0.5f; - LLVector3 scaled_wind_vec = gWindVec * WIND_LEVEL; + static LLUICachedControl wind_level("AudioLevelWind", 0.5f); + LLVector3 scaled_wind_vec = gWindVec * wind_level; // Mix in the avatar's motion, subtract because when you walk north, // the apparent wind moves south. -- cgit v1.3 From b95b20a1be56ff7baa3ad20e8d0571ec9f07ab12 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 8 Apr 2025 20:28:50 +0300 Subject: #3757 Allow subfolders in "My Outfits" --- indra/newview/llappearancelistener.cpp | 2 +- indra/newview/llinventorybridge.cpp | 45 +++++++++++++++++++-- indra/newview/llinventorybridge.h | 1 + indra/newview/llinventoryfunctions.cpp | 5 +++ indra/newview/llinventoryfunctions.h | 18 +++++++++ indra/newview/llinventorygallery.cpp | 13 ++++++ indra/newview/llinventorygallerymenu.cpp | 1 + indra/newview/lloutfitslist.cpp | 47 +++++++++++++++++++++- .../skins/default/xui/en/menu_inventory.xml | 8 ++++ 9 files changed, 134 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappearancelistener.cpp b/indra/newview/llappearancelistener.cpp index a6d6e76e02..dc7bbc3236 100644 --- a/indra/newview/llappearancelistener.cpp +++ b/indra/newview/llappearancelistener.cpp @@ -122,7 +122,7 @@ void LLAppearanceListener::getOutfitsList(LLSD const &data) LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t item_array; - LLIsType is_category(LLAssetType::AT_CATEGORY); + LLIsFolderType is_category(LLFolderType::FT_OUTFIT); gInventory.collectDescendentsIf(outfits_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, is_category); response["outfits"] = llsd::toMap(cat_array, diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ce91f9a1f3..8d31c4dde7 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2916,6 +2916,10 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, // create a new folder and populate it with links to original objects dropToMyOutfits(inv_cat, cb); } + else if (getCategory() && getCategory()->getParentUUID() == my_outifts_id) + { + dropToMyOutfitsSubfolder(inv_cat, mUUID, cb); + } // if target is current outfit folder we use link else if (move_is_into_current_outfit && (inv_cat->getPreferredType() == LLFolderType::FT_NONE || @@ -4016,7 +4020,14 @@ void LLFolderBridge::perform_pasteFromClipboard() U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit"); if (cat && can_move_to_my_outfits(model, cat, max_items_to_wear)) { - dropToMyOutfits(cat, cb); + if (mUUID == my_outifts_id) + { + dropToMyOutfits(cat, cb); + } + else if (getCategory() && getCategory()->getParentUUID() == mUUID) + { + dropToMyOutfitsSubfolder(cat, mUUID, cb); + } } else { @@ -4256,6 +4267,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items if (outfits_id == mUUID) { + items.push_back(std::string("New Outfit Folder")); items.push_back(std::string("New Outfit")); } @@ -5331,13 +5343,36 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointergetUUID(), _1, cb, mInventoryPanel); - gInventory.createNewCategory(dest_id, + getInventoryModel()->createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); } +void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLPointer cb) +{ + LLViewerInventoryCategory* cat = getInventoryModel()->getCategory(dest_id); + const LLUUID outfits_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + inventory_func_type func = boost::bind(outfitFolderCreatedCallback, inv_cat->getUUID(), _1, cb, mInventoryPanel); + if (cat && cat->getParentUUID() == outfits_id) + { + getInventoryModel()->createNewCategory(dest_id, + LLFolderType::FT_OUTFIT, + inv_cat->getName(), + func, + inv_cat->getThumbnailUUID()); + } + else + { + getInventoryModel()->createNewCategory(outfits_id, + LLFolderType::FT_OUTFIT, + inv_cat->getName(), + func, + inv_cat->getThumbnailUUID()); + } +} + void LLFolderBridge::outfitFolderCreatedCallback(LLUUID cat_source_id, LLUUID cat_dest_id, LLPointer cb, @@ -5441,6 +5476,10 @@ bool LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const bool move_is_into_favorites = (mUUID == favorites_id); const bool move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); const bool move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); + const bool move_is_into_my_outfits_subfolder = move_is_into_my_outfits + && getCategory() + && getCategory()->getParentUUID() == my_outifts_id + && getCategory()->getPreferredType() != LLFolderType::FT_OUTFIT; const bool move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); const bool move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); const bool move_is_from_marketplacelistings = model->isObjectDescendentOf(inv_item->getUUID(), marketplacelistings_id); @@ -5511,7 +5550,7 @@ bool LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } else if (user_confirm && (move_is_into_current_outfit || move_is_into_outfit)) { - accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); + accept = !move_is_into_my_outfits_subfolder && can_move_to_outfit(inv_item, move_is_into_current_outfit); } else if (user_confirm && (move_is_into_favorites || move_is_into_landmarks)) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 3e7f74384b..b7bdef9b21 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -369,6 +369,7 @@ protected: void dropToFavorites(LLInventoryItem* inv_item, LLPointer cb = NULL); void dropToOutfit(LLInventoryItem* inv_item, bool move_is_into_current_outfit, LLPointer cb = NULL); void dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer cb = NULL); + void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest, LLPointer cb = NULL); //-------------------------------------------------------------------- // Messy hacks for handling folder options diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 1ccefa3212..b4299972d9 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2621,6 +2621,11 @@ bool LLInventoryCollectFunctor::itemTransferCommonlyAllowed(const LLInventoryIte return false; } +bool LLIsFolderType::operator()(LLInventoryCategory* cat, LLInventoryItem* item) +{ + return cat && cat->getPreferredType() == mType; +} + bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item) { if(mType == LLAssetType::AT_CATEGORY) diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 13a64f21dc..b379d625a9 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -234,6 +234,24 @@ protected: // the type is the type passed in during construction. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLIsFolderType : public LLInventoryCollectFunctor +{ +public: + LLIsFolderType(LLFolderType::EType type) : mType(type) {} + virtual ~LLIsFolderType() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item); +protected: + LLFolderType::EType mType; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLIsType +// +// Implementation of a LLInventoryCollectFunctor which returns true if +// the type is the type passed in during construction. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + class LLIsType : public LLInventoryCollectFunctor { public: diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index c4f93cee98..6188b812d5 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -64,6 +64,7 @@ const S32 FAST_LOAD_THUMBNAIL_TRSHOLD = 50; // load folders below this value imm bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, bool drop, std::string& tooltip_msg, bool is_link); bool dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, bool drop, std::string& tooltip_msg, bool user_confirm); void dropToMyOutfits(LLInventoryCategory* inv_cat); +void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id); class LLGalleryPanel: public LLPanel { @@ -3898,6 +3899,10 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, // create a new folder and populate it with links to original objects dropToMyOutfits(inv_cat); } + else if (dest_cat && dest_cat->getParentUUID() == my_outifts_id) + { + dropToMyOutfitsSubfolder(inv_cat, dest_id); + } // if target is current outfit folder we use link else if (move_is_into_current_outfit && (inv_cat->getPreferredType() == LLFolderType::FT_NONE || @@ -4041,3 +4046,11 @@ void dropToMyOutfits(LLInventoryCategory* inv_cat) inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1); gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); } + +void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID &dest_id) +{ + // Note: creation will take time, so passing folder id to callback is slightly unreliable, + // but so is collecting and passing descendants' ids + inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1); + gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); +} diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index dbf4821ca1..25b339d51e 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -771,6 +771,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men if(is_outfits && !isRootFolder()) { + items.push_back(std::string("New Outfit Folder")); items.push_back(std::string("New Outfit")); } diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index 6e666b8a4b..cfbfe8f8e0 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -819,6 +819,49 @@ void LLOutfitListBase::observerCallback(const LLUUID& category_id) refreshList(category_id); } +class LLIsOutfitListFolder : public LLInventoryCollectFunctor +{ +public: + LLIsOutfitListFolder() + { + mOutfitsId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + } + virtual ~LLIsOutfitListFolder() {} + + bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override + { + if (cat) + { + if (cat->getPreferredType() == LLFolderType::FT_OUTFIT) + { + return true; + } + if (cat->getPreferredType() == LLFolderType::FT_NONE + && cat->getParentUUID() == mOutfitsId) + { + LLViewerInventoryCategory* inv_cat = dynamic_cast(cat); + if (inv_cat && inv_cat->getDescendentCount() > 3) + { + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items); + if (items->size() > 3) // eyes, skin, hair and shape are required + { + // For now assume this to be an old style outfit, not a subfolder + // but ideally no such 'outfits' should be left in My Outfits + // Todo: stop counting FT_NONE as outfits, + // convert obvious outfits into FT_OUTFIT + return true; + } + } + } + } + return false; + } +protected: + LLUUID mOutfitsId; +}; + void LLOutfitListBase::refreshList(const LLUUID& category_id) { bool wasNull = mRefreshListState.CategoryUUID.isNull(); @@ -828,13 +871,13 @@ void LLOutfitListBase::refreshList(const LLUUID& category_id) LLInventoryModel::item_array_t item_array; // Collect all sub-categories of a given category. - LLIsType is_category(LLAssetType::AT_CATEGORY); + LLIsOutfitListFolder is_outfit; gInventory.collectDescendentsIf( category_id, cat_array, item_array, LLInventoryModel::EXCLUDE_TRASH, - is_category); + is_outfit); // Memorize item names for each UUID std::map names; diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index e57e3b0750..d8c7de0e55 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -151,6 +151,14 @@ function="Inventory.DoCreate" parameter="category" /> + + + Date: Tue, 8 Apr 2025 22:39:41 +0300 Subject: #3757 Menu for subfodlers in outfits --- indra/newview/llinventorybridge.cpp | 199 ++++++++++++++++++++++--------- indra/newview/llinventorybridge.h | 2 +- indra/newview/llinventorygallery.cpp | 57 ++++++++- indra/newview/llinventorygallerymenu.cpp | 8 +- indra/newview/llinventorymodel.cpp | 3 +- indra/newview/lloutfitslist.cpp | 3 +- 6 files changed, 202 insertions(+), 70 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 8d31c4dde7..fd9d08a26d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -105,6 +105,44 @@ static bool check_item(const LLUUID& item_id, // Helper functions + +namespace { + enum EMyOutfitsSubfolderType + { + MY_OUTFITS_NO, + MY_OUTFITS_SUBFOLDER, + MY_OUTFITS_OUTFIT, + }; + + EMyOutfitsSubfolderType myoutfit_object_subfolder_type(LLInventoryModel* model, const LLUUID& obj_id, + const LLUUID& cat_id) + { + if (obj_id == cat_id) return MY_OUTFITS_NO; + + const LLViewerInventoryCategory* test_cat = model->getCategory(obj_id); + while (test_cat) + { + if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT) + { + return MY_OUTFITS_OUTFIT; + } + + const LLUUID& parent_id = test_cat->getParentUUID(); + if (parent_id.isNull()) + { + return MY_OUTFITS_NO; + } + if (parent_id == cat_id) + { + return MY_OUTFITS_SUBFOLDER; + } + test_cat = model->getCategory(parent_id); + } + + return MY_OUTFITS_NO; + } +} + bool isAddAction(const std::string& action) { return ("wear" == action || "attach" == action || "activate" == action); @@ -2912,13 +2950,22 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, if (mUUID == my_outifts_id) { - // Category can contains objects, + // Category can't contains objects, // create a new folder and populate it with links to original objects dropToMyOutfits(inv_cat, cb); } - else if (getCategory() && getCategory()->getParentUUID() == my_outifts_id) + else if (move_is_into_my_outfits) { - dropToMyOutfitsSubfolder(inv_cat, mUUID, cb); + EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); + if (res == MY_OUTFITS_SUBFOLDER) + { + // turn it into outfit + dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_OUTFIT, cb); + } + else + { + dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_NONE, cb); + } } // if target is current outfit folder we use link else if (move_is_into_current_outfit && @@ -4012,6 +4059,7 @@ void LLFolderBridge::perform_pasteFromClipboard() { if (!move_is_into_my_outfits && item && can_move_to_outfit(item, move_is_into_current_outfit)) { + // todo: this is going to create dupplicate folders? dropToOutfit(item, move_is_into_current_outfit, cb); } else if (move_is_into_my_outfits && LLAssetType::AT_CATEGORY == obj->getType()) @@ -4024,9 +4072,18 @@ void LLFolderBridge::perform_pasteFromClipboard() { dropToMyOutfits(cat, cb); } - else if (getCategory() && getCategory()->getParentUUID() == mUUID) + else if (move_is_into_my_outfits) { - dropToMyOutfitsSubfolder(cat, mUUID, cb); + EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); + if (res == MY_OUTFITS_SUBFOLDER) + { + // turn it into outfit + dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_OUTFIT, cb); + } + else + { + dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_NONE, cb); + } } } else @@ -4361,63 +4418,85 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items else if(isAgentInventory()) // do not allow creating in library { LLViewerInventoryCategory *cat = getCategory(); - // BAP removed protected check to re-enable standard ops in untyped folders. - // Not sure what the right thing is to do here. - if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) - { - if (!isInboxFolder() // don't allow creation in inbox - && outfits_id != mUUID) - { - bool menu_items_added = false; - // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. - if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) - { - items.push_back(std::string("New Folder")); - menu_items_added = true; - } - if (!isMarketplaceListingsFolder()) - { - items.push_back(std::string("upload_def")); - items.push_back(std::string("create_new")); - items.push_back(std::string("New Script")); - items.push_back(std::string("New Note")); - items.push_back(std::string("New Gesture")); - items.push_back(std::string("New Material")); - items.push_back(std::string("New Clothes")); - items.push_back(std::string("New Body Parts")); - items.push_back(std::string("New Settings")); - if (!LLEnvironment::instance().isInventoryEnabled()) - { - disabled_items.push_back("New Settings"); - } - } - else - { - items.push_back(std::string("New Listing Folder")); - } - if (menu_items_added) - { - items.push_back(std::string("Create Separator")); - } - } - getClipboardEntries(false, items, disabled_items, flags); - } - else + + if (cat) { - // Want some but not all of the items from getClipboardEntries for outfits. - if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT)) + if (cat->getPreferredType() == LLFolderType::FT_OUTFIT) { + // Want some but not all of the items from getClipboardEntries for outfits. + items.push_back(std::string("New Outfit Folder")); items.push_back(std::string("Rename")); items.push_back(std::string("thumbnail")); addDeleteContextMenuOptions(items, disabled_items); // EXT-4030: disallow deletion of currently worn outfit - const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); + const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory())) { disabled_items.push_back(std::string("Delete")); } } + else if (outfits_id == mUUID) + { + getClipboardEntries(false, items, disabled_items, flags); + } + else if (!isCOFFolder()) + { + EMyOutfitsSubfolderType in_my_outfits = myoutfit_object_subfolder_type(model, mUUID, outfits_id); + if (in_my_outfits != MY_OUTFITS_NO) + { + if (in_my_outfits == MY_OUTFITS_SUBFOLDER) + { + // Not inside an outfit, but inside 'my outfits' + items.push_back(std::string("New Outfit")); + } + + items.push_back(std::string("New Outfit Folder")); + items.push_back(std::string("Rename")); + items.push_back(std::string("thumbnail")); + + addDeleteContextMenuOptions(items, disabled_items); + } + else + { + if (!isInboxFolder() // don't allow creation in inbox + && outfits_id != mUUID) + { + bool menu_items_added = false; + // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. + if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) + { + items.push_back(std::string("New Folder")); + menu_items_added = true; + } + if (!isMarketplaceListingsFolder()) + { + items.push_back(std::string("upload_def")); + items.push_back(std::string("create_new")); + items.push_back(std::string("New Script")); + items.push_back(std::string("New Note")); + items.push_back(std::string("New Gesture")); + items.push_back(std::string("New Material")); + items.push_back(std::string("New Clothes")); + items.push_back(std::string("New Body Parts")); + items.push_back(std::string("New Settings")); + if (!LLEnvironment::instance().isInventoryEnabled()) + { + disabled_items.push_back("New Settings"); + } + } + else + { + items.push_back(std::string("New Listing Folder")); + } + if (menu_items_added) + { + items.push_back(std::string("Create Separator")); + } + } + getClipboardEntries(false, items, disabled_items, flags); + } + } } if (model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT) == mUUID) @@ -4570,7 +4649,11 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren() && (type != LLFolderType::FT_OUTFIT)) { - items.push_back(std::string("Ungroup folder items")); + const LLUUID my_outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + if (!gInventory.isObjectDescendentOf(mUUID, my_outfits)) + { + items.push_back(std::string("Ungroup folder items")); + } } } else @@ -5350,7 +5433,7 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointergetThumbnailUUID()); } -void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLPointer cb) +void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLFolderType::EType preferred_type, LLPointer cb) { LLViewerInventoryCategory* cat = getInventoryModel()->getCategory(dest_id); const LLUUID outfits_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); @@ -5358,7 +5441,7 @@ void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, cons if (cat && cat->getParentUUID() == outfits_id) { getInventoryModel()->createNewCategory(dest_id, - LLFolderType::FT_OUTFIT, + preferred_type, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); @@ -5366,7 +5449,7 @@ void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, cons else { getInventoryModel()->createNewCategory(outfits_id, - LLFolderType::FT_OUTFIT, + preferred_type, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); @@ -5476,10 +5559,6 @@ bool LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const bool move_is_into_favorites = (mUUID == favorites_id); const bool move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); const bool move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - const bool move_is_into_my_outfits_subfolder = move_is_into_my_outfits - && getCategory() - && getCategory()->getParentUUID() == my_outifts_id - && getCategory()->getPreferredType() != LLFolderType::FT_OUTFIT; const bool move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); const bool move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); const bool move_is_from_marketplacelistings = model->isObjectDescendentOf(inv_item->getUUID(), marketplacelistings_id); @@ -5550,7 +5629,9 @@ bool LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } else if (user_confirm && (move_is_into_current_outfit || move_is_into_outfit)) { - accept = !move_is_into_my_outfits_subfolder && can_move_to_outfit(inv_item, move_is_into_current_outfit); + EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); + // don't allow items in my outfits' subfodlers, only in outfits and outfit's subfolders + accept = res != MY_OUTFITS_SUBFOLDER && can_move_to_outfit(inv_item, move_is_into_current_outfit); } else if (user_confirm && (move_is_into_favorites || move_is_into_landmarks)) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index b7bdef9b21..a101c7368a 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -369,7 +369,7 @@ protected: void dropToFavorites(LLInventoryItem* inv_item, LLPointer cb = NULL); void dropToOutfit(LLInventoryItem* inv_item, bool move_is_into_current_outfit, LLPointer cb = NULL); void dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer cb = NULL); - void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest, LLPointer cb = NULL); + void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest, LLFolderType::EType preferred_type, LLPointer cb = NULL); //-------------------------------------------------------------------- // Messy hacks for handling folder options diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 6188b812d5..15bc578c64 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -60,11 +60,49 @@ static LLPanelInjector t_inventory_gallery("inventory_galler const S32 GALLERY_ITEMS_PER_ROW_MIN = 2; const S32 FAST_LOAD_THUMBNAIL_TRSHOLD = 50; // load folders below this value immediately + +namespace { + enum EMyOutfitsSubfolderType + { + MY_OUTFITS_NO, + MY_OUTFITS_SUBFOLDER, + MY_OUTFITS_OUTFIT, + }; + + EMyOutfitsSubfolderType myoutfit_object_subfolder_type(LLInventoryModel* model, const LLUUID& obj_id, + const LLUUID& cat_id) + { + if (obj_id == cat_id) return MY_OUTFITS_NO; + + const LLViewerInventoryCategory* test_cat = model->getCategory(obj_id); + while (test_cat) + { + if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT) + { + return MY_OUTFITS_OUTFIT; + } + + const LLUUID& parent_id = test_cat->getParentUUID(); + if (parent_id.isNull()) + { + return MY_OUTFITS_NO; + } + if (parent_id == cat_id) + { + return MY_OUTFITS_SUBFOLDER; + } + test_cat = model->getCategory(parent_id); + } + + return MY_OUTFITS_NO; + } +} + // Helper dnd functions bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, bool drop, std::string& tooltip_msg, bool is_link); bool dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, bool drop, std::string& tooltip_msg, bool user_confirm); void dropToMyOutfits(LLInventoryCategory* inv_cat); -void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id); +void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLFolderType::EType preferred_type); class LLGalleryPanel: public LLPanel { @@ -3899,9 +3937,18 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, // create a new folder and populate it with links to original objects dropToMyOutfits(inv_cat); } - else if (dest_cat && dest_cat->getParentUUID() == my_outifts_id) + else if (move_is_into_my_outfits) { - dropToMyOutfitsSubfolder(inv_cat, dest_id); + EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, dest_id, my_outifts_id); + if (res == MY_OUTFITS_SUBFOLDER) + { + // turn it into outfit + dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_OUTFIT); + } + else + { + dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_NONE); + } } // if target is current outfit folder we use link else if (move_is_into_current_outfit && @@ -4047,10 +4094,10 @@ void dropToMyOutfits(LLInventoryCategory* inv_cat) gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); } -void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID &dest_id) +void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID &dest_id, LLFolderType::EType preferred_type) { // Note: creation will take time, so passing folder id to callback is slightly unreliable, // but so is collecting and passing descendants' ids inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1); - gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); + gInventory.createNewCategory(dest_id, preferred_type, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); } diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 25b339d51e..3ef5071c97 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -586,7 +586,9 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men bool is_trash = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)); bool is_in_trash = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)); bool is_lost_and_found = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); - bool is_outfits= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS)); + const LLUUID my_outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + bool is_outfits= (selected_id == my_outfits); + bool is_in_outfits = is_outfits || gInventory.isObjectDescendentOf(selected_id, my_outfits); bool is_in_favorites = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)); //bool is_favorites= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)); @@ -725,7 +727,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men } else { - if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits) + if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits && !is_in_outfits) { LLViewerInventoryCategory* category = gInventory.getCategory(selected_id); if (!category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(category)) @@ -778,7 +780,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men items.push_back(std::string("Subfolder Separator")); if (!is_system_folder && !isRootFolder()) { - if(has_children && (folder_type != LLFolderType::FT_OUTFIT)) + if(has_children && (folder_type != LLFolderType::FT_OUTFIT) && !is_in_outfits) { items.push_back(std::string("Ungroup folder items")); } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 9fffe6378e..6f4d2db12e 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1007,7 +1007,8 @@ void LLInventoryModel::createNewCategory(const LLUUID& parent_id, return; } - if (preferred_type != LLFolderType::FT_NONE) + if (preferred_type != LLFolderType::FT_NONE + && preferred_type != LLFolderType::FT_OUTFIT) { // Ultimately this should only be done for non-singleton // types. Requires back-end changes to guarantee that others diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index cfbfe8f8e0..9d8493549d 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -845,7 +845,8 @@ public: LLInventoryModel::cat_array_t* cats; LLInventoryModel::item_array_t* items; gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items); - if (items->size() > 3) // eyes, skin, hair and shape are required + if (cats->empty() // protection against outfits inside + && items->size() > 3) // eyes, skin, hair and shape are required { // For now assume this to be an old style outfit, not a subfolder // but ideally no such 'outfits' should be left in My Outfits -- cgit v1.3 From 1c90421b8873a2228a845ea2f7f4a80758500aa6 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 9 Apr 2025 19:54:50 +0300 Subject: #3596 Faster mesh thread shutdown --- indra/llcommon/lluuid.cpp | 15 --------------- indra/llcommon/lluuid.h | 2 -- indra/newview/llinventorymodel.cpp | 2 +- indra/newview/llmeshrepository.cpp | 29 +++++++++++++++++++++++++++-- indra/newview/llmeshrepository.h | 3 +++ 5 files changed, 31 insertions(+), 20 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index b9bd27aa17..4aae90626e 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -174,14 +174,6 @@ void LLUUID::toString(std::string& out) const (U8)(mData[15])); } -// *TODO: deprecate -void LLUUID::toString(char* out) const -{ - std::string buffer; - toString(buffer); - strcpy(out, buffer.c_str()); /* Flawfinder: ignore */ -} - void LLUUID::toCompressedString(std::string& out) const { char bytes[UUID_BYTES + 1]; @@ -190,13 +182,6 @@ void LLUUID::toCompressedString(std::string& out) const out.assign(bytes, UUID_BYTES); } -// *TODO: deprecate -void LLUUID::toCompressedString(char* out) const -{ - memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */ - out[UUID_BYTES] = '\0'; -} - std::string LLUUID::getString() const { return asString(); diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index bd4edc7993..ca1cf03c4d 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -103,9 +103,7 @@ public: friend LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLUUID &uuid); friend LL_COMMON_API std::istream& operator>>(std::istream& s, LLUUID &uuid); - void toString(char *out) const; // Does not allocate memory, needs 36 characters (including \0) void toString(std::string& out) const; - void toCompressedString(char *out) const; // Does not allocate memory, needs 17 characters (including \0) void toCompressedString(std::string& out) const; std::string asString() const; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 6f4d2db12e..0a2d938bd0 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3526,7 +3526,7 @@ bool LLInventoryModel::saveToFile(const std::string& filename, fileXML.close(); - LL_INFOS(LOG_INV) << "Inventory saved: " << cat_count << " categories, " << it_count << " items." << LL_ENDL; + LL_INFOS(LOG_INV) << "Inventory saved: " << (S32)cat_count << " categories, " << (S32)it_count << " items." << LL_ENDL; } catch (...) { diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index a8c6f69425..48c80842b9 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1210,6 +1210,12 @@ void LLMeshRepoThread::run() LL_WARNS(LOG_MESH) << "Convex decomposition unable to be quit." << LL_ENDL; } } +void LLMeshRepoThread::cleanup() +{ + mShuttingDown = true; + mSignal->broadcast(); + mMeshThreadPool->close(); +} // Mutex: LLMeshRepoThread::mMutex must be held on entry void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id) @@ -1493,6 +1499,11 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) [mesh_id, buffer, size] () { + if (gMeshRepo.mThread->isShuttingDown()) + { + delete[] buffer; + return; + } if (!gMeshRepo.mThread->skinInfoReceived(mesh_id, buffer, size)) { // either header is faulty or something else overwrote the cache @@ -1993,6 +2004,11 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) [params, mesh_id, lod, buffer, size] () { + if (gMeshRepo.mThread->isShuttingDown()) + { + delete[] buffer; + return; + } if (gMeshRepo.mThread->lodReceived(params, lod, buffer, size) == MESH_OK) { LL_DEBUGS(LOG_MESH) << "Mesh/Cache: Mesh body for ID " << mesh_id << " - was retrieved from the cache." << LL_ENDL; @@ -3792,6 +3808,11 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body [shrd_handler, data, data_size] () { + if (gMeshRepo.mThread->isShuttingDown()) + { + delete[] data; + return; + } LLMeshLODHandler* handler = (LLMeshLODHandler * )shrd_handler.get(); handler->processLod(data, data_size); delete[] data; @@ -3905,6 +3926,11 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* [shrd_handler, data, data_size] () { + if (gMeshRepo.mThread->isShuttingDown()) + { + delete[] data; + return; + } LLMeshSkinInfoHandler* handler = (LLMeshSkinInfoHandler*)shrd_handler.get(); handler->processSkin(data, data_size); delete[] data; @@ -4127,8 +4153,7 @@ void LLMeshRepository::shutdown() mUploads[i]->discard() ; //discard the uploading requests. } - mThread->mSignal->broadcast(); - mThread->mMeshThreadPool->close(); + mThread->cleanup(); while (!mThread->isStopped()) { diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 0d9da32e27..b9acb3573f 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -515,6 +515,8 @@ public: ~LLMeshRepoThread(); virtual void run(); + void cleanup(); + bool isShuttingDown() { return mShuttingDown; } void lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod); void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod); @@ -583,6 +585,7 @@ private: U8* getDiskCacheBuffer(S32 size); S32 mDiskCacheBufferSize = 0; U8* mDiskCacheBuffer = nullptr; + bool mShuttingDown = false; }; -- cgit v1.3 From 2371994a88ffeefd07891d00aed18ac226b954a7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 9 Apr 2025 21:35:40 +0300 Subject: #3757 Menu for subfodlers in outfits p2 --- indra/newview/llinventorybridge.cpp | 90 +++++++++----------------- indra/newview/llinventoryfunctions.cpp | 30 +++++++++ indra/newview/llinventoryfunctions.h | 11 ++++ indra/newview/llinventorygallery.cpp | 65 +++++++------------ indra/newview/llinventorygallerymenu.cpp | 16 ++++- indra/newview/skins/default/xui/en/strings.xml | 1 + 6 files changed, 109 insertions(+), 104 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index fd9d08a26d..2c1c6d22a6 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -104,45 +104,6 @@ static bool check_item(const LLUUID& item_id, LLInventoryFilter* filter); // Helper functions - - -namespace { - enum EMyOutfitsSubfolderType - { - MY_OUTFITS_NO, - MY_OUTFITS_SUBFOLDER, - MY_OUTFITS_OUTFIT, - }; - - EMyOutfitsSubfolderType myoutfit_object_subfolder_type(LLInventoryModel* model, const LLUUID& obj_id, - const LLUUID& cat_id) - { - if (obj_id == cat_id) return MY_OUTFITS_NO; - - const LLViewerInventoryCategory* test_cat = model->getCategory(obj_id); - while (test_cat) - { - if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT) - { - return MY_OUTFITS_OUTFIT; - } - - const LLUUID& parent_id = test_cat->getParentUUID(); - if (parent_id.isNull()) - { - return MY_OUTFITS_NO; - } - if (parent_id == cat_id) - { - return MY_OUTFITS_SUBFOLDER; - } - test_cat = model->getCategory(parent_id); - } - - return MY_OUTFITS_NO; - } -} - bool isAddAction(const std::string& action) { return ("wear" == action || "attach" == action || "activate" == action); @@ -2735,7 +2696,12 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit"); if (is_movable && move_is_into_outfit) { - if (mUUID == my_outifts_id) + if ((inv_cat->getPreferredType() != LLFolderType::FT_NONE) && (inv_cat->getPreferredType() != LLFolderType::FT_OUTFIT)) + { + tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); + is_movable = false; + } + else if (mUUID == my_outifts_id) { if (source != LLToolDragAndDrop::SOURCE_AGENT || move_is_from_marketplacelistings) { @@ -2752,13 +2718,28 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, is_movable = false; } } - else if(getCategory() && getCategory()->getPreferredType() == LLFolderType::FT_NONE) + else if (!getCategory()) { - is_movable = ((inv_cat->getPreferredType() == LLFolderType::FT_NONE) || (inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT)); + is_movable = false; + tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); } else { - is_movable = false; + LLFolderType::EType type = getCategory()->getPreferredType(); + if (type == LLFolderType::FT_OUTFIT && inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT) + { + is_movable = false; + tooltip_msg = LLTrans::getString("TooltipCantMoveOutfitIntoOutfit"); + } + else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear)) + { + is_movable = true; + } + else + { + is_movable = false; + tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); + } } } if (is_movable && move_is_into_current_outfit && is_link) @@ -2964,6 +2945,7 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } else { + // or link it? dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_NONE, cb); } } @@ -5435,25 +5417,13 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer cb) { - LLViewerInventoryCategory* cat = getInventoryModel()->getCategory(dest_id); const LLUUID outfits_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); inventory_func_type func = boost::bind(outfitFolderCreatedCallback, inv_cat->getUUID(), _1, cb, mInventoryPanel); - if (cat && cat->getParentUUID() == outfits_id) - { - getInventoryModel()->createNewCategory(dest_id, - preferred_type, - inv_cat->getName(), - func, - inv_cat->getThumbnailUUID()); - } - else - { - getInventoryModel()->createNewCategory(outfits_id, - preferred_type, - inv_cat->getName(), - func, - inv_cat->getThumbnailUUID()); - } + getInventoryModel()->createNewCategory(dest_id, + preferred_type, + inv_cat->getName(), + func, + inv_cat->getThumbnailUUID()); } void LLFolderBridge::outfitFolderCreatedCallback(LLUUID cat_source_id, diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index b4299972d9..dc69e0c92e 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2493,6 +2493,36 @@ bool can_share_item(const LLUUID& item_id) return can_share; } + +EMyOutfitsSubfolderType myoutfit_object_subfolder_type( + LLInventoryModel* model, + const LLUUID& obj_id, + const LLUUID& my_outfits_id) +{ + if (obj_id == my_outfits_id) return MY_OUTFITS_NO; + + const LLViewerInventoryCategory* test_cat = model->getCategory(obj_id); + while (test_cat) + { + if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT) + { + return MY_OUTFITS_OUTFIT; + } + + const LLUUID& parent_id = test_cat->getParentUUID(); + if (parent_id.isNull()) + { + return MY_OUTFITS_NO; + } + if (parent_id == my_outfits_id) + { + return MY_OUTFITS_SUBFOLDER; + } + test_cat = model->getCategory(parent_id); + } + + return MY_OUTFITS_NO; +} ///---------------------------------------------------------------------------- /// LLMarketplaceValidator implementations ///---------------------------------------------------------------------------- diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index b379d625a9..eb3503c5b0 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -121,6 +121,17 @@ std::string get_searchable_creator_name(LLInventoryModel* model, const LLUUID& i std::string get_searchable_UUID(LLInventoryModel* model, const LLUUID& item_id); bool can_share_item(const LLUUID& item_id); +enum EMyOutfitsSubfolderType +{ + MY_OUTFITS_NO, + MY_OUTFITS_SUBFOLDER, + MY_OUTFITS_OUTFIT, +}; +EMyOutfitsSubfolderType myoutfit_object_subfolder_type( + LLInventoryModel* model, + const LLUUID& obj_id, + const LLUUID& my_outfits_id); + /** Miscellaneous global functions ** ** *******************************************************************************/ diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 15bc578c64..d640e04915 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -61,43 +61,6 @@ const S32 GALLERY_ITEMS_PER_ROW_MIN = 2; const S32 FAST_LOAD_THUMBNAIL_TRSHOLD = 50; // load folders below this value immediately -namespace { - enum EMyOutfitsSubfolderType - { - MY_OUTFITS_NO, - MY_OUTFITS_SUBFOLDER, - MY_OUTFITS_OUTFIT, - }; - - EMyOutfitsSubfolderType myoutfit_object_subfolder_type(LLInventoryModel* model, const LLUUID& obj_id, - const LLUUID& cat_id) - { - if (obj_id == cat_id) return MY_OUTFITS_NO; - - const LLViewerInventoryCategory* test_cat = model->getCategory(obj_id); - while (test_cat) - { - if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT) - { - return MY_OUTFITS_OUTFIT; - } - - const LLUUID& parent_id = test_cat->getParentUUID(); - if (parent_id.isNull()) - { - return MY_OUTFITS_NO; - } - if (parent_id == cat_id) - { - return MY_OUTFITS_SUBFOLDER; - } - test_cat = model->getCategory(parent_id); - } - - return MY_OUTFITS_NO; - } -} - // Helper dnd functions bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, bool drop, std::string& tooltip_msg, bool is_link); bool dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, bool drop, std::string& tooltip_msg, bool user_confirm); @@ -3784,7 +3747,12 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit"); if (is_movable && move_is_into_outfit) { - if (dest_id == my_outifts_id) + if ((inv_cat->getPreferredType() != LLFolderType::FT_NONE) && (inv_cat->getPreferredType() != LLFolderType::FT_OUTFIT)) + { + tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); + is_movable = false; + } + else if (dest_id == my_outifts_id) { if (source != LLToolDragAndDrop::SOURCE_AGENT || move_is_from_marketplacelistings) { @@ -3801,13 +3769,28 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, is_movable = false; } } - else if (dest_cat && dest_cat->getPreferredType() == LLFolderType::FT_NONE) + else if (!dest_cat) { - is_movable = ((inv_cat->getPreferredType() == LLFolderType::FT_NONE) || (inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT)); + is_movable = false; + tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); } else { - is_movable = false; + LLFolderType::EType type = dest_cat->getPreferredType(); + if (type == LLFolderType::FT_OUTFIT && inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT) + { + is_movable = false; + tooltip_msg = LLTrans::getString("TooltipCantMoveOutfitIntoOutfit"); + } + else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear)) + { + is_movable = true; + } + else + { + is_movable = false; + tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); + } } } if (is_movable && move_is_into_current_outfit && is_link) diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 3ef5071c97..68af0cb581 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -771,14 +771,24 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men items.push_back(std::string("upload_def")); } - if(is_outfits && !isRootFolder()) + if(is_outfits) { + EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(&gInventory, selected_id, my_outfits); + if (res == MY_OUTFITS_OUTFIT) + { + items.push_back(std::string("New Outfit")); + } items.push_back(std::string("New Outfit Folder")); - items.push_back(std::string("New Outfit")); + items.push_back(std::string("Delete")); + items.push_back(std::string("Rename")); + if (!get_is_category_and_children_removable(&gInventory, selected_id, false)) + { + disabled_items.push_back(std::string("Delete")); + } } items.push_back(std::string("Subfolder Separator")); - if (!is_system_folder && !isRootFolder()) + if (!is_system_folder && !isRootFolder() && !is_outfits) { if(has_children && (folder_type != LLFolderType::FT_OUTFIT) && !is_in_outfits) { diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index d909a95b83..7361ad5245 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -258,6 +258,7 @@ If you feel this is an error, please contact support@secondlife.com All items in a stock folder must have the same type and permission You can only put items or outfits from your personal inventory into "My outfits" One or more items can't be used inside "My outfits" + Can not move an outfit into another outfit You can't move a folder into its child You can't move a folder into itself -- cgit v1.3 From 7dce74fcfb9ca9e6c152eaf33392ff79412ff555 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 10 Apr 2025 22:39:04 +0300 Subject: #3757 Move for subfodlers --- indra/newview/llinventorybridge.cpp | 93 +++++++++++++++++++++++++++----- indra/newview/llinventoryfunctions.cpp | 6 ++- indra/newview/llinventoryfunctions.h | 1 + indra/newview/llinventorygallery.cpp | 85 ++++++++++++++++++++++++----- indra/newview/llinventorygallerymenu.cpp | 2 +- 5 files changed, 158 insertions(+), 29 deletions(-) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 2c1c6d22a6..5bd17d4d5b 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2725,12 +2725,23 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } else { - LLFolderType::EType type = getCategory()->getPreferredType(); - if (type == LLFolderType::FT_OUTFIT && inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT) + EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); + EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id); + if ((dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) && inv_res == MY_OUTFITS_OUTFIT) { is_movable = false; tooltip_msg = LLTrans::getString("TooltipCantMoveOutfitIntoOutfit"); } + else if ((dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) && inv_res == MY_OUTFITS_SUBFOLDER) + { + is_movable = false; + tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); + } + else if (dest_res == MY_OUTFITS_SUBFOLDER && inv_res == MY_OUTFITS_SUBOUTFIT) + { + is_movable = false; + tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); + } else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear)) { is_movable = true; @@ -2931,22 +2942,76 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, if (mUUID == my_outifts_id) { - // Category can't contains objects, - // create a new folder and populate it with links to original objects - dropToMyOutfits(inv_cat, cb); - } - else if (move_is_into_my_outfits) - { - EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); - if (res == MY_OUTFITS_SUBFOLDER) + EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id); + if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT) { - // turn it into outfit - dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_OUTFIT, cb); + LLInvFVBridge::changeCategoryParent( + model, + (LLViewerInventoryCategory*)inv_cat, + mUUID, + false); + if (cb) cb->fire(inv_cat->getUUID()); } else { - // or link it? - dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_NONE, cb); + // Moving from inventory + // create a new folder and populate it with links to original objects + dropToMyOutfits(inv_cat, cb); + } + } + else if (move_is_into_my_outfits) + { + EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); + EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id); + switch (inv_res) + { + case MY_OUTFITS_NO: + // Moning from outside outfits into outfits + if (dest_res == MY_OUTFITS_SUBFOLDER) + { + // turn it into outfit + dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_OUTFIT, cb); + } + else + { + // or link it? + dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_NONE, cb); + } + break; + case MY_OUTFITS_SUBFOLDER: + case MY_OUTFITS_OUTFIT: + // only permit moving subfodlers and outfits into other subfolders + if (dest_res == MY_OUTFITS_SUBFOLDER) + { + LLInvFVBridge::changeCategoryParent( + model, + (LLViewerInventoryCategory*)inv_cat, + mUUID, + false); + if (cb) cb->fire(inv_cat->getUUID()); + } + else + { + assert(false); // mot permitted, shouldn't have accepted + } + break; + case MY_OUTFITS_SUBOUTFIT: + if (dest_res == MY_OUTFITS_SUBOUTFIT || dest_res == MY_OUTFITS_OUTFIT) + { + LLInvFVBridge::changeCategoryParent( + model, + (LLViewerInventoryCategory*)inv_cat, + mUUID, + false); + if (cb) cb->fire(inv_cat->getUUID()); + } + else + { + assert(false); // mot permitted, shouldn't have accepted + } + break; + default: + break; } } // if target is current outfit folder we use link diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index dc69e0c92e..7fff88fba7 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2502,11 +2502,15 @@ EMyOutfitsSubfolderType myoutfit_object_subfolder_type( if (obj_id == my_outfits_id) return MY_OUTFITS_NO; const LLViewerInventoryCategory* test_cat = model->getCategory(obj_id); + if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT) + { + return MY_OUTFITS_OUTFIT; + } while (test_cat) { if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT) { - return MY_OUTFITS_OUTFIT; + return MY_OUTFITS_SUBOUTFIT; } const LLUUID& parent_id = test_cat->getParentUUID(); diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index eb3503c5b0..0ab045f2a0 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -126,6 +126,7 @@ enum EMyOutfitsSubfolderType MY_OUTFITS_NO, MY_OUTFITS_SUBFOLDER, MY_OUTFITS_OUTFIT, + MY_OUTFITS_SUBOUTFIT, }; EMyOutfitsSubfolderType myoutfit_object_subfolder_type( LLInventoryModel* model, diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index d640e04915..713d87787e 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -3776,12 +3776,23 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, } else { - LLFolderType::EType type = dest_cat->getPreferredType(); - if (type == LLFolderType::FT_OUTFIT && inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT) + EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, dest_id, my_outifts_id); + EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id); + if ((dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) && inv_res == MY_OUTFITS_OUTFIT) { is_movable = false; tooltip_msg = LLTrans::getString("TooltipCantMoveOutfitIntoOutfit"); } + else if ((dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) && inv_res == MY_OUTFITS_SUBFOLDER) + { + is_movable = false; + tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); + } + else if (dest_res == MY_OUTFITS_SUBFOLDER && inv_res == MY_OUTFITS_SUBOUTFIT) + { + is_movable = false; + tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); + } else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear)) { is_movable = true; @@ -3916,21 +3927,69 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, if (dest_id == my_outifts_id) { - // Category can contains objects, - // create a new folder and populate it with links to original objects - dropToMyOutfits(inv_cat); - } - else if (move_is_into_my_outfits) - { - EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, dest_id, my_outifts_id); - if (res == MY_OUTFITS_SUBFOLDER) + EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id); + if (inv_res == MY_OUTFITS_SUBFOLDER || inv_res == MY_OUTFITS_OUTFIT) { - // turn it into outfit - dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_OUTFIT); + gInventory.changeCategoryParent( + (LLViewerInventoryCategory*)inv_cat, + dest_id, + move_is_into_trash); } else { - dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_NONE); + // Category can contains objects, + // create a new folder and populate it with links to original objects + dropToMyOutfits(inv_cat); + } + } + else if (move_is_into_my_outfits) + { + EMyOutfitsSubfolderType dest_res = myoutfit_object_subfolder_type(model, dest_id, my_outifts_id); + EMyOutfitsSubfolderType inv_res = myoutfit_object_subfolder_type(model, cat_id, my_outifts_id); + switch (inv_res) + { + case MY_OUTFITS_NO: + // Moning from outside outfits into outfits + if (dest_res == MY_OUTFITS_SUBFOLDER) + { + // turn it into outfit + dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_OUTFIT); + } + else + { + dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_NONE); + } + break; + case MY_OUTFITS_SUBFOLDER: + case MY_OUTFITS_OUTFIT: + // only permit moving subfodlers and outfits into other subfolders + if (dest_res == MY_OUTFITS_SUBFOLDER) + { + gInventory.changeCategoryParent( + (LLViewerInventoryCategory*)inv_cat, + dest_id, + move_is_into_trash); + } + else + { + assert(false); // mot permitted, shouldn't have accepted + } + break; + case MY_OUTFITS_SUBOUTFIT: + if (dest_res == MY_OUTFITS_SUBOUTFIT || dest_res == MY_OUTFITS_OUTFIT) + { + gInventory.changeCategoryParent( + (LLViewerInventoryCategory*)inv_cat, + dest_id, + move_is_into_trash); + } + else + { + assert(false); // mot permitted, shouldn't have accepted + } + break; + default: + break; } } // if target is current outfit folder we use link diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 68af0cb581..7acd3b90a2 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -774,7 +774,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men if(is_outfits) { EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(&gInventory, selected_id, my_outfits); - if (res == MY_OUTFITS_OUTFIT) + if (res != MY_OUTFITS_OUTFIT && res != MY_OUTFITS_SUBOUTFIT) { items.push_back(std::string("New Outfit")); } -- cgit v1.3 From e43baa755d9b91c029e7b5166317e76468baf896 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 11 Apr 2025 19:21:25 +0300 Subject: #1754 Restore land owners overlay --- indra/newview/lldrawpoolterrain.h | 1 + indra/newview/llsurfacepatch.cpp | 9 ++++++- indra/newview/llsurfacepatch.h | 2 +- indra/newview/llterrainpaintmap.cpp | 3 ++- indra/newview/llvosurfacepatch.cpp | 51 +++++++++++++++++++++++++++---------- indra/newview/llvosurfacepatch.h | 4 +++ 6 files changed, 53 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 5380463d01..23cf253b6a 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -38,6 +38,7 @@ public: VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TANGENT | // Only PBR terrain uses this currently + LLVertexBuffer::MAP_TEXCOORD0 | // Ownership overlay LLVertexBuffer::MAP_TEXCOORD1 }; diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 4315c4c6b0..6f99da5957 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -201,7 +201,7 @@ LLVector2 LLSurfacePatch::getTexCoords(const U32 x, const U32 y) const void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 *vertex, LLVector3 *normal, - LLVector2 *tex1) const + LLVector2* tex0, LLVector2 *tex1) const { if (!mSurfacep || !mSurfacep->getRegion() || !mSurfacep->getGridsPerEdge() || !mVObjp) { @@ -210,6 +210,7 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 llassert_always(vertex && normal && tex1); U32 surface_stride = mSurfacep->getGridsPerEdge(); + U32 texture_stride = mSurfacep->getGridsPerEdge() - 1; U32 point_offset = x + y*surface_stride; *normal = getNormal(x, y); @@ -220,6 +221,12 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 pos_agent.mV[VZ] = *(mDataZ + point_offset); *vertex = pos_agent-mVObjp->getRegion()->getOriginAgent(); + // tex0 is used for ownership overlay + LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent(); + LLVector3 tex_pos = rel_pos * (1.f / (texture_stride * mSurfacep->getMetersPerGrid())); + tex0->mV[0] = tex_pos.mV[0]; + tex0->mV[1] = tex_pos.mV[1]; + tex1->mV[0] = mSurfacep->getRegion()->getCompositionXY(llfloor(mOriginRegion.mV[0])+x, llfloor(mOriginRegion.mV[1])+y); const F32 xyScale = 4.9215f*7.f; //0.93284f; diff --git a/indra/newview/llsurfacepatch.h b/indra/newview/llsurfacepatch.h index f4831487c1..505fc8c24c 100644 --- a/indra/newview/llsurfacepatch.h +++ b/indra/newview/llsurfacepatch.h @@ -116,7 +116,7 @@ public: void calcNormalFlat(LLVector3& normal_out, const U32 x, const U32 y, const U32 index /* 0 or 1 */); void eval(const U32 x, const U32 y, const U32 stride, - LLVector3 *vertex, LLVector3 *normal, LLVector2 *tex1) const; + LLVector3 *vertex, LLVector3 *normal, LLVector2* tex0, LLVector2 *tex1) const; diff --git a/indra/newview/llterrainpaintmap.cpp b/indra/newview/llterrainpaintmap.cpp index 8ccde74c93..c7a82013e4 100644 --- a/indra/newview/llterrainpaintmap.cpp +++ b/indra/newview/llterrainpaintmap.cpp @@ -204,8 +204,9 @@ bool LLTerrainPaintMap::bakeHeightNoiseIntoPBRPaintMapRGB(const LLViewerRegion& { LLVector3 scratch3; LLVector3 pos3; + LLVector2 tex0_temp; LLVector2 tex1_temp; - patch->eval(i, j, stride, &pos3, &scratch3, &tex1_temp); + patch->eval(i, j, stride, &pos3, &scratch3, &tex0_temp, &tex1_temp); (*pos++).set(pos3.mV[VX], pos3.mV[VY], pos3.mV[VZ]); *tex1++ = tex1_temp; vertex_total++; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 294d36b0a9..bc326a74a8 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -245,6 +245,7 @@ bool LLVOSurfacePatch::updateLOD() void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, LLStrider &normalsp, + LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp) { @@ -259,18 +260,21 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, updateMainGeometry(facep, verticesp, normalsp, + texCoords0p, texCoords1p, indicesp, index_offset); updateNorthGeometry(facep, verticesp, normalsp, + texCoords0p, texCoords1p, indicesp, index_offset); updateEastGeometry(facep, verticesp, normalsp, + texCoords0p, texCoords1p, indicesp, index_offset); @@ -279,6 +283,7 @@ void LLVOSurfacePatch::getTerrainGeometry(LLStrider &verticesp, void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, + LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, U32 &index_offset) @@ -317,9 +322,10 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, { x = i * render_stride; y = j * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } } @@ -381,6 +387,7 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, + LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, U32 &index_offset) @@ -414,9 +421,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } @@ -425,9 +433,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, { x = i * render_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } @@ -460,9 +469,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } @@ -472,9 +482,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * render_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } @@ -514,9 +525,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * north_stride; y = 16 - render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } @@ -526,9 +538,10 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, x = i * north_stride; y = 16; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } @@ -564,6 +577,7 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, + LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, U32 &index_offset) @@ -592,9 +606,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } @@ -603,9 +618,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, { x = 16; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } @@ -638,9 +654,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } // Iterate through the east patch's points @@ -649,9 +666,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16; y = i * render_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } @@ -690,9 +708,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16 - render_stride; y = i * east_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } // Iterate through the east patch's points @@ -701,9 +720,10 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, x = 16; y = i * east_stride; - mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords1p.get()); + mPatchp->eval(x, y, render_stride, verticesp.get(), normalsp.get(), texCoords0p.get(), texCoords1p.get()); verticesp++; normalsp++; + texCoords0p++; texCoords1p++; } @@ -1022,12 +1042,14 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) LLStrider vertices_start; LLStrider normals_start; LLStrider tangents_start; + LLStrider texcoords0_start; // ownership overlay LLStrider texcoords2_start; LLStrider indices_start; llassert_always(buffer->getVertexStrider(vertices_start)); llassert_always(buffer->getNormalStrider(normals_start)); llassert_always(buffer->getTangentStrider(tangents_start)); + llassert_always(buffer->getTexCoord0Strider(texcoords0_start)); llassert_always(buffer->getTexCoord1Strider(texcoords2_start)); llassert_always(buffer->getIndexStrider(indices_start)); @@ -1037,6 +1059,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) { LLStrider vertices = vertices_start; LLStrider normals = normals_start; + LLStrider texcoords0 = texcoords0_start; LLStrider texcoords2 = texcoords2_start; LLStrider indices = indices_start; @@ -1049,7 +1072,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) facep->setVertexBuffer(buffer); LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject(); - patchp->getTerrainGeometry(vertices, normals, texcoords2, indices); + patchp->getTerrainGeometry(vertices, normals, texcoords0, texcoords2, indices); indices_index += facep->getIndicesCount(); index_offset += facep->getGeomCount(); diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index af5f05774b..c93a58d2d9 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -57,6 +57,7 @@ public: /*virtual*/ void updateFaceSize(S32 idx); void getTerrainGeometry(LLStrider &verticesp, LLStrider &normalsp, + LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp); @@ -109,18 +110,21 @@ protected: void updateMainGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, + LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, U32 &index_offset); void updateNorthGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, + LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, U32 &index_offset); void updateEastGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, + LLStrider &texCoords0p, LLStrider &texCoords1p, LLStrider &indicesp, U32 &index_offset); -- cgit v1.3