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/newview/llviewerobject.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/newview') 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.2.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/newview/llfloaterworldmap.cpp | 7 +++++-- indra/newview/llviewermessage.cpp | 18 ++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'indra/newview') 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 -- cgit v1.2.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/newview') 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.2.3 From 7cd50ceaceaf3fa83c37ab6d7cf85e3e22609d9c Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Mon, 21 Oct 2024 16:35:23 -0700 Subject: Issue #2907: Process metadata sent along with chats of type IM_NOTHING_SPECIAL, The metadata can contain information about the bot status of the sender. It may also contain a system-injected notification that is displayed to the agent as part of the 1:1 chat window. --- indra/newview/llimprocessing.cpp | 47 ++++++++++++++++++++++++-- indra/newview/llimprocessing.h | 1 + indra/newview/llimview.cpp | 2 +- indra/newview/llviewermessage.cpp | 18 +++++++++- indra/newview/skins/default/xui/da/strings.xml | 4 +++ indra/newview/skins/default/xui/de/strings.xml | 4 +++ indra/newview/skins/default/xui/en/strings.xml | 4 +++ indra/newview/skins/default/xui/es/strings.xml | 4 +++ indra/newview/skins/default/xui/fr/strings.xml | 4 +++ indra/newview/skins/default/xui/it/strings.xml | 4 +++ indra/newview/skins/default/xui/ja/strings.xml | 4 +++ indra/newview/skins/default/xui/pl/strings.xml | 4 +++ indra/newview/skins/default/xui/pt/strings.xml | 4 +++ indra/newview/skins/default/xui/ru/strings.xml | 4 +++ indra/newview/skins/default/xui/tr/strings.xml | 4 +++ indra/newview/skins/default/xui/zh/strings.xml | 4 +++ 16 files changed, 111 insertions(+), 5 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index 590cd09a31..5d1317f00f 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -422,6 +422,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, U8 *binary_bucket, S32 binary_bucket_size, LLHost &sender, + LLSD metadata, LLUUID aux_id) { LLChat chat; @@ -451,6 +452,30 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, bool is_linden = chat.mSourceType != CHAT_SOURCE_OBJECT && LLMuteList::isLinden(name); + /*** + * The simulator has flagged this sender as a bot, if the viewer would like to display + * the chat text in a different color or font, the below code is how the viewer can + * tell if the sender is a bot. + *----------------------------------------------------- + bool is_bot = false; + if (metadata.has("sender")) + { // The server has identified this sender as a bot. + is_bot = metadata["sender"]["bot"].asBoolean(); + } + *----------------------------------------------------- + */ + + bool is_system_notice = false; + std::string notice_id; + LLSD notice_args; + if (metadata.has("notice")) + { // The server has injected a notice into the IM conversation. + // These will be things like bot notifications, etc. + is_system_notice = true; + notice_id = metadata["notice"]["id"].asString(); + notice_args = metadata["notice"]["data"]; + } + chat.mMuted = is_muted; chat.mFromID = from_id; chat.mFromName = name; @@ -544,7 +569,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, } else { - // standard message, not from system + // standard message, server may have injected a notice into the conversation. std::string saved; if (offline == IM_OFFLINE) { @@ -579,8 +604,16 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, region_message = true; } } - gIMMgr->addMessage( - session_id, + + if (is_system_notice) + { // The simulator has injected some sort of notice into the conversation. + // findString will only replace the contents of buffer if the notice_id is found. + LLTrans::findString(buffer, notice_id, notice_args); + name = SYSTEM_FROM; + from_id = LLUUID::null; + } + + gIMMgr->addMessage(session_id, from_id, name, buffer, @@ -592,6 +625,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, position, region_message, timestamp); + } else { @@ -1627,6 +1661,12 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url) from_group = message_data["from_group"].asString() == "Y"; } + LLSD metadata; + if (message_data.has("metadata")) + { + metadata = message_data["metadata"]; + } + EInstantMessage dialog = static_cast(message_data["dialog"].asInteger()); LLUUID session_id = message_data["transaction-id"].asUUID(); if (session_id.isNull() && dialog == IM_FROM_TASK) @@ -1654,6 +1694,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url) local_bin_bucket.data(), S32(local_bin_bucket.size()), local_sender, + metadata, message_data["asset_id"].asUUID()); }); diff --git a/indra/newview/llimprocessing.h b/indra/newview/llimprocessing.h index 030d28b198..66ffc59ae0 100644 --- a/indra/newview/llimprocessing.h +++ b/indra/newview/llimprocessing.h @@ -48,6 +48,7 @@ public: U8 *binary_bucket, S32 binary_bucket_size, LLHost &sender, + LLSD metadata, LLUUID aux_id = LLUUID::null); // Either receives list of offline messages from 'ReadOfflineMsgs' capability diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 34a4b5b230..7a2f1486ae 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -3142,7 +3142,7 @@ void LLIMMgr::addMessage( const LLUUID& region_id, const LLVector3& position, bool is_region_msg, - U32 timestamp) // May be zero + U32 timestamp) // May be zero { LLUUID other_participant_id = target_id; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 1d4828fd33..f2335319a8 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2137,6 +2137,21 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) EInstantMessage dialog = (EInstantMessage)d; LLHost sender = msg->getSender(); + LLSD metadata; + if (msg->getNumberOfBlocksFast(_PREHASH_MetaData) > 0) + { + S32 metadata_size = msg->getSizeFast(_PREHASH_MetaData, 0, _PREHASH_Data); + std::string metadata_buffer; + metadata_buffer.resize(metadata_size, 0); + + msg->getBinaryDataFast(_PREHASH_MetaData, _PREHASH_Data, &metadata_buffer[0], metadata_size, 0, metadata_size ); + std::stringstream metadata_stream(metadata_buffer); + if (LLSDSerialize::fromBinary(metadata, metadata_stream, metadata_size) == LLSDParser::PARSE_FAILURE) + { + metadata.clear(); + } + } + LLIMProcessing::processNewMessage(from_id, from_group, to_id, @@ -2151,7 +2166,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) position, binary_bucket, binary_bucket_size, - sender); + sender, + metadata); } void send_do_not_disturb_message (LLMessageSystem* msg, const LLUUID& from_id, const LLUUID& session_id) diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml index e4f99d14e9..c4275d43f7 100644 --- a/indra/newview/skins/default/xui/da/strings.xml +++ b/indra/newview/skins/default/xui/da/strings.xml @@ -3723,6 +3723,10 @@ Hvis du bliver ved med at modtage denne besked, kontakt venligst [SUPPORT_SITE]. Konference med [AGENT_NAME] + +Du chatter med en bot, [NAME]. Del ikke personlige oplysninger. +Læs mere på https://second.life/scripted-agents. + (IM session eksisterer ikke) diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index a9e7626dc5..44355940c4 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -1614,6 +1614,10 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich bitte an [SUPPORT_ Konferenz mit [AGENT_NAME] Inventarobjekt „[ITEM_NAME]“ angeboten Inventarordner „[ITEM_NAME]“ angeboten + + Sie chatten mit einem Bot, [NAME]. Geben Sie keine persönlichen Informationen weiter. +Erfahren Sie mehr unter https://second.life/scripted-agents. + Objekte aus dem Inventar hier her ziehen Sie haben auf Facebook gepostet. Sie haben auf Flickr gepostet. diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index f0a26f9c56..9102a30e1d 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3717,6 +3717,10 @@ Please reinstall viewer from https://secondlife.com/support/downloads/ and cont Inventory folder '[ITEM_NAME]' offered + + You are chatting with a bot, [NAME]. Do not share any personal information. +Learn more at https://second.life/scripted-agents. + Drag items from inventory here diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index cd8e7687ae..f23f6e1c07 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -1585,6 +1585,10 @@ Si sigues recibiendo este mensaje, contacta con [SUPPORT_SITE]. Conferencia con [AGENT_NAME] Ítem del inventario '[ITEM_NAME]' ofrecido Carpeta del inventario '[ITEM_NAME]' ofrecida + +Estás conversando con un bot, [NAME]. No compartas información personal. +Más información en https://second.life/scripted-agents. + Arrastra los ítems desde el invenbtario hasta aquí Has publicado en Facebook. Has publicado en Flickr. diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 0a3fbeb603..cfa6cb5001 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -1615,6 +1615,10 @@ Si ce message persiste, veuillez aller sur la page [SUPPORT_SITE]. Conférence avec [AGENT_NAME] Objet de l’inventaire [ITEM_NAME] offert Dossier de l’inventaire [ITEM_NAME] offert + +Vous discutez avec un bot, [NAME]. Ne partagez pas d’informations personnelles. +En savoir plus sur https://second.life/scripted-agents. + Faire glisser les objets de l'inventaire ici Vous avez publié sur Facebook. Vous avez publié sur Flickr. diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index 178bb90ca6..2a430ad840 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -1587,6 +1587,10 @@ Se il messaggio persiste, contatta [SUPPORT_SITE]. Chiamata in conferenza con [AGENT_NAME] Offerto oggetto di inventario "[ITEM_NAME]" Offerta cartella di inventario "[ITEM_NAME]" + +Stai parlando con un bot, [NAME]. Non condividere informazioni personali. +Scopri di più su https://second.life/scripted-agents. + Hai pubblicato su Facebook. Hai pubblicato su Flickr. Hai pubblicato su Twitter. diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index fa6c329fe7..ff3b1a53a2 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -6150,6 +6150,10 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ フォルダ「[ITEM_NAME]」がインベントリに送られてきました。 + +[NAME]とチャットしています。個人情報を共有しないでください。 +詳細は https://second.life/scripted-agents をご覧ください。 + インベントリからここにアイテムをドラッグします。 diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml index 26ec6cc9dc..d26272ca54 100644 --- a/indra/newview/skins/default/xui/pl/strings.xml +++ b/indra/newview/skins/default/xui/pl/strings.xml @@ -4413,6 +4413,10 @@ Jeżeli nadal otrzymujesz ten komunikat, skontaktuj się z [SUPPORT_SITE]. Zaoferowano folder: '[ITEM_NAME]' + +Rozmawiasz z botem [NAME]. Nie udostępniaj żadnych danych osobowych. +Dowiedz się więcej na https://second.life/scripted-agents. + Przeciągaj tutaj rzeczy z Szafy diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 6db5da2e89..4ce5694c01 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -1550,6 +1550,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. Conversa com [AGENT_NAME] Item do inventário '[ITEM_NAME]' oferecido Pasta do inventário '[ITEM_NAME]' oferecida + +Você está conversando com um bot, [NAME]. Não compartilhe informações pessoais. +Saiba mais em https://second.life/scripted-agents. + Você publicou no Facebook. Você publicou no Flickr. Você publicou no Twitter. diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml index 61d836a2d1..9a26accdde 100644 --- a/indra/newview/skins/default/xui/ru/strings.xml +++ b/indra/newview/skins/default/xui/ru/strings.xml @@ -4577,6 +4577,10 @@ support@secondlife.com. Предложена папка инвентаря «[ITEM_NAME]» + +Вы общаетесь с ботом [NAME]. Не передавайте личные данные. +Подробнее на https://second.life/scripted-agents. + Перетаскивайте вещи из инвентаря сюда diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml index e709a4c5d6..157b48c32a 100644 --- a/indra/newview/skins/default/xui/tr/strings.xml +++ b/indra/newview/skins/default/xui/tr/strings.xml @@ -4580,6 +4580,10 @@ Bu iletiyi almaya devam ederseniz, lütfen [SUPPORT_SITE] bölümüne başvurun. "[ITEM_NAME]" envanter klasörü sunuldu + +Bir bot ile sohbet ediyorsunuz, [NAME]. Kişisel bilgilerinizi paylaşmayın. +Daha fazla bilgi için: https://second.life/scripted-agents. + Envanterinizden buraya öğeler sürükleyin diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml index bdb16c9bf1..a3a9915dc4 100644 --- a/indra/newview/skins/default/xui/zh/strings.xml +++ b/indra/newview/skins/default/xui/zh/strings.xml @@ -4573,6 +4573,10 @@ http://secondlife.com/support 求助解決問題。 收納區資料夾'[ITEM_NAME]'已向人提供 + +您正在与人工智能机器人 [NAME] 聊天。请勿分享任何个人信息。 +了解更多:https://second.life/scripted-agents。 + 將收納區物品拖曳到這裡 -- cgit v1.2.3 From a097f887282f6ddb20ed8a7d50f506554216a0a2 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 23 Oct 2024 11:31:29 -0700 Subject: Issue #2907: Code review comments. --- indra/newview/llimprocessing.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index 5d1317f00f..f5b149335b 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -453,7 +453,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, LLMuteList::isLinden(name); /*** - * The simulator has flagged this sender as a bot, if the viewer would like to display + * The simulator may have flagged this sender as a bot, if the viewer would like to display * the chat text in a different color or font, the below code is how the viewer can * tell if the sender is a bot. *----------------------------------------------------- @@ -465,14 +465,12 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, *----------------------------------------------------- */ - bool is_system_notice = false; - std::string notice_id; + std::string notice_name; LLSD notice_args; if (metadata.has("notice")) { // The server has injected a notice into the IM conversation. // These will be things like bot notifications, etc. - is_system_notice = true; - notice_id = metadata["notice"]["id"].asString(); + notice_name = metadata["notice"]["id"].asString(); notice_args = metadata["notice"]["data"]; } @@ -605,10 +603,10 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, } } - if (is_system_notice) + if (!notice_name.empty()) { // The simulator has injected some sort of notice into the conversation. // findString will only replace the contents of buffer if the notice_id is found. - LLTrans::findString(buffer, notice_id, notice_args); + LLTrans::findString(buffer, notice_name, notice_args); name = SYSTEM_FROM; from_id = LLUUID::null; } -- cgit v1.2.3 From 48ccb0f75b078670ced1f8fe8d4942abe0a6f293 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 25 Oct 2024 15:52:10 -0700 Subject: Issue #2907: When passing the injected notification message into addMessage on behalf of the system, optionally specify the agent id and name that should be used. (cherry picked from commit 7ff297ec3fc5f878cc9a916678987c0033b7eb8a) --- indra/newview/llimprocessing.cpp | 10 ++++++---- indra/newview/llimview.cpp | 13 ++++++++++--- indra/newview/llimview.h | 4 +++- 3 files changed, 19 insertions(+), 8 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index f5b149335b..e050fb77e0 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -603,12 +603,13 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, } } + std::string real_name; + if (!notice_name.empty()) { // The simulator has injected some sort of notice into the conversation. // findString will only replace the contents of buffer if the notice_id is found. LLTrans::findString(buffer, notice_name, notice_args); - name = SYSTEM_FROM; - from_id = LLUUID::null; + real_name = SYSTEM_FROM; } gIMMgr->addMessage(session_id, @@ -622,8 +623,9 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, region_id, position, region_message, - timestamp); - + timestamp, + LLUUID::null, + real_name); } else { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 7a2f1486ae..21c255f226 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -3142,9 +3142,16 @@ void LLIMMgr::addMessage( const LLUUID& region_id, const LLVector3& position, bool is_region_msg, - U32 timestamp) // May be zero + U32 timestamp, // May be zero + LLUUID display_id, + std::string_view display_name) { LLUUID other_participant_id = target_id; + std::string message_display_name = (display_name.empty()) ? from : std::string(display_name); + if (display_id.isNull() && (display_name.empty())) + { + display_id = other_participant_id; + } LLUUID new_session_id = session_id; if (new_session_id.isNull()) @@ -3240,7 +3247,7 @@ void LLIMMgr::addMessage( } //Play sound for new conversations - if (!skip_message & !gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation"))) + if (!skip_message && !gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNewConversation"))) { make_ui_sound("UISndNewIncomingIMSession"); } @@ -3254,7 +3261,7 @@ void LLIMMgr::addMessage( if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message) { - LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg, true, is_region_msg, timestamp); + LLIMModel::instance().addMessage(new_session_id, message_display_name, display_id, msg, true, is_region_msg, timestamp); } // Open conversation floater if offline messages are present diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 61776860e3..23f90ca795 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -368,7 +368,9 @@ public: const LLUUID& region_id = LLUUID::null, const LLVector3& position = LLVector3::zero, bool is_region_msg = false, - U32 timestamp = 0); + U32 timestamp = 0, + LLUUID display_id = LLUUID::null, + std::string_view display_name = ""); void addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args); -- cgit v1.2.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/newview') 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.2.3 From 942527ddf39925e3e77d5c4e30a0fdc245156ada Mon Sep 17 00:00:00 2001 From: William Weaver Date: Tue, 11 Mar 2025 21:34:45 +0300 Subject: **fix: Correctly update shadows on RenderShadowResolutionScale change** MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shadows were not updating correctly after a shader change occurred in-session and then the RenderShadowResolutionScale setting was adjusted. This issue is present in Second Life Release 7.1.12.1355088671 (64-bit) and Second Life Test 7.1.12.250701803 (64-bit). **Specifically, after any shader-related setting is changed in-session (such as toggling Advanced Graphics options like SSAO, HDR, Depth of Field, SSR, Antialiasing, or changing the Graphics Quality preset), subsequent adjustments to `RenderShadowResolutionScale` via Debug Settings result in broken shadow rendering.** The shadows become corrupted or disappear entirely and do not reflect the new resolution scale. Correct shadow rendering is only restored by toggling a shader or restarting the viewer. This behavior is inconsistent with other render settings that update immediately after modification and degrades the user experience when dynamically adjusting shadow quality. This commit changes the signal listener for "RenderShadowResolutionScale" in **llviewercontrol.cpp** from `handleShadowsResized` to `handleSetShaderChanged`. `handleSetShaderChanged` ensures a full shader update, which is necessary for this setting to take effect immediately—similar to other render settings like RenderDeferredSSAO. This change ensures that shadows update correctly and immediately when the resolution scale is changed in Debug Settings, even after prior shader changes in the session, without requiring additional shader toggling or viewer restarts. This provides a smoother and more responsive experience for advanced users adjusting shadow quality in various rendering scenarios. --- **Steps to Reproduce (Bug)** _Verified in Second Life Release 7.1.12.1355088671 (64-bit) and Second Life Test 7.1.12.250701803 (64-bit):_ 1. **Fresh Install Preparation:** Ensure a clean Second Life installation state. Ideally, uninstall and reinstall the viewer or clear/rename all folders in `AppData\Local\Second Life` and `AppData\Roaming\Second Life` before launching. 2. Launch the Second Life Viewer and log in. 3. Enable the Debug Menu: Open Preferences (Ctrl+P), go to the "Advanced" tab, and check "Show Advanced Settings". 4. Open Debug Settings: Click the "Advanced" menu in the menu bar and select "Debug Settings." 5. Locate the `RenderShadowResolutionScale` setting (which should be set to 1.0 on a clean install). 6. Initially, changing `RenderShadowResolutionScale` at this point may not exhibit the bug. Proceed to the next steps to reliably trigger it. 7. **Trigger the Bug:** Open Preferences (Ctrl+P) again and go to the "Graphics" tab. 8. Click the "Advanced Settings" button. 9. **Toggle *any* of the following Advanced Graphics options:** - Screen Space Ambient Occlusion - HDR and Emissive Rendering - Depth of Field - Screen Space Reflections - Antialiasing - *Alternatively*, change the "Graphics Quality" preset slider (e.g., Low to Ultra or any other change). 10. Return to the Debug Settings floater. 11. Change the value of `RenderShadowResolutionScale` to a different value (e.g., from 1.0 to 0.5 or 2.0). 12. **Observe the Bug:** Notice that shadow rendering does not update correctly—shadows become corrupted or disappear. 13. **Workaround (in buggy version):** To restore correct shadow rendering without the fix, either: - Toggle a different shader (e.g., change graphics presets in Preferences, or toggle SSAO, SSR, etc.), or - Restart the viewer. **Steps to Verify (Fix):** 1. Build the viewer with this commit applied. 2. Launch the viewer and log in. 3. Repeat steps 1–9 from "Steps to Reproduce (Bug)" to ensure an Advanced Graphics setting is toggled before proceeding. 4. Open Debug Settings and locate `RenderShadowResolutionScale`. 5. Change the value of `RenderShadowResolutionScale` (e.g., from 1.0 to 0.5 or 2.0). 6. **Verify the Fix:** Confirm that shadow rendering updates immediately and correctly—even after toggling Advanced Graphics settings—with the shadows visibly changing resolution in real time. No shader toggling or viewer restart is required. --- - No specific regression testing is required for this targeted fix. However, standard viewer functionality should be verified after building to ensure no unintended side effects have been introduced. Pay particular attention to shadow rendering in various environments and lighting conditions to confirm the fix has not negatively impacted other shadow-related features. --- - No documentation changes are needed as this is a bug fix for an existing debug setting. --- indra/newview/llviewercontrol.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 598ad89907..1f5ac61040 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -809,7 +809,9 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "RenderSpecularResY", handleLUTBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderSpecularExponent", handleLUTBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderAnisotropic", handleAnisotropicChanged); - setting_setup_signal_listener(gSavedSettings, "RenderShadowResolutionScale", handleShadowsResized); + // Ensure shader update on shadow resolution scale change for correct shadow rendering. + // setting_setup_signal_listener(gSavedSettings, "RenderShadowResolutionScale", handleShadowsResized); // Original line commented out + setting_setup_signal_listener(gSavedSettings, "RenderShadowResolutionScale", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleReleaseGLBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "RenderGlowResolutionPow", handleReleaseGLBufferChanged); -- cgit v1.2.3 From 76db64e0c8c7dd40ce2a85ef19183c3c245f1dc8 Mon Sep 17 00:00:00 2001 From: William Weaver Date: Wed, 12 Mar 2025 19:52:56 +0300 Subject: Fixes: Add guard to prevent shadow texture resize with invalid mRT dimensions after shader changes; **Replaces forced shader refresh with lightweight guard** MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces a guard in `LLPipeline::resizeShadowTexture()` to prevent shadow texture resizing when the shadow render target (mRT) has invalid (zero) dimensions. **This replaces a previous, less efficient approach of forcing a full shader recompile whenever `RenderShadowResolutionScale` was changed in-session.** **Background and Problem:** Previously, the code forced a full shader recompile whenever `RenderShadowResolutionScale` changed in-session (after toggling advanced graphics settings like SSAO or HDR). While this “sledgehammer” approach did fix broken shadow rendering, it unnecessarily thrashed the shader cache and reset many pipeline states. **Solution:** This commit removes the forced shader recompile in favor of a guard check in `LLPipeline::resizeShadowTexture()`. The guard ensures mRT (the shadow render target) has non-zero dimensions before resizing. If mRT is zero for that frame, the resize operation is skipped, and a warning is logged. Once mRT becomes valid (usually in the next frame), the shadow texture is resized successfully without requiring a full shader refresh. **Detailed changes:** - Reverted the binding of `RenderShadowResolutionScale` to `handleSetShaderChanged`. - Restored the original `handleShadowsResized` listener for `RenderShadowResolutionScale` in `llviewercontrol.cpp`. - Added guard checks in `LLPipeline::resizeShadowTexture()` to skip resizing when `mRT->width` or `mRT->height` is zero. - Added logging statements to track how many frames are skipped. **Benefits:** - Prevents shader thrashing while still avoiding shadow corruption. - Shadows now update correctly as soon as mRT dimensions are valid. - Maintains a detailed record of frames skipped. - **Lightweight and targeted interim solution, much less disruptive than a full shader recompile.** Testing: 1. Reproduce the bug as described in the bug report (toggle SSAO, then change RenderShadowResolutionScale). 2. Verify that shadows are no longer broken after these steps. 3. Check the logs for the warning message indicating skipped frames when the bug is triggered. 4. Confirm that under normal operation (without shader changes causing mRT issues), shadow resizing works as expected without excessive warnings. Documentation: No user-facing documentation changes are needed for this interim fix. However, internal developer documentation should note this guard and the ongoing investigation into the root cause. Further Development: This guard is a temporary fix. The root cause of why mRT becomes invalid after shader changes needs to be investigated and resolved. See the bug report for detailed next steps for investigation. --- indra/newview/llviewercontrol.cpp | 4 +--- indra/newview/pipeline.cpp | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 1f5ac61040..598ad89907 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -809,9 +809,7 @@ void settings_setup_listeners() setting_setup_signal_listener(gSavedSettings, "RenderSpecularResY", handleLUTBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderSpecularExponent", handleLUTBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderAnisotropic", handleAnisotropicChanged); - // Ensure shader update on shadow resolution scale change for correct shadow rendering. - // setting_setup_signal_listener(gSavedSettings, "RenderShadowResolutionScale", handleShadowsResized); // Original line commented out - setting_setup_signal_listener(gSavedSettings, "RenderShadowResolutionScale", handleSetShaderChanged); + setting_setup_signal_listener(gSavedSettings, "RenderShadowResolutionScale", handleShadowsResized); setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleReleaseGLBufferChanged); setting_setup_signal_listener(gSavedSettings, "RenderGlow", handleSetShaderChanged); setting_setup_signal_listener(gSavedSettings, "RenderGlowResolutionPow", handleReleaseGLBufferChanged); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 18dd694246..691d155a3c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -121,7 +121,7 @@ #include "SMAAAreaTex.h" #include "SMAASearchTex.h" - +#include "llerror.h" #ifndef LL_WINDOWS #define A_GCC 1 #pragma GCC diagnostic ignored "-Wunused-function" @@ -727,6 +727,29 @@ void LLPipeline::requestResizeShadowTexture() void LLPipeline::resizeShadowTexture() { + // A static counter to keep track of skipped frames + static int sSkippedFrameCount = 0; + + if (!mRT || mRT->width == 0 || mRT->height == 0) + { + sSkippedFrameCount++; + LL_WARNS("Render") << "Shadow texture resizing aborted: render target dimensions invalid. Skipped " + << sSkippedFrameCount << " frame(s) so far." << LL_ENDL; + return; + } + + // If there were skipped frames before mRT became valid, log that information. + if (sSkippedFrameCount > 0) + { + LL_INFOS("Render") << "Render target now valid after " + << sSkippedFrameCount << " skipped frame(s)." << LL_ENDL; + sSkippedFrameCount = 0; + } + + LL_WARNS() << "LLPipeline::resizeShadowTexture() called." << LL_ENDL; + LL_INFOS() << "Resizing shadow texture. mRT->width = " + << mRT->width << " mRT->height = " << mRT->height << LL_ENDL; + releaseSunShadowTargets(); releaseSpotShadowTargets(); allocateShadowBuffer(mRT->width, mRT->height); -- cgit v1.2.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/newview') 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.2.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/newview') 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.2.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/newview') 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.2.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/newview/llfloaterimsessiontab.cpp | 42 +++++++++++++++++++++++++++++++-- indra/newview/llfloaterimsessiontab.h | 5 ++++ 2 files changed, 45 insertions(+), 2 deletions(-) (limited to 'indra/newview') 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.2.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/newview') 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.2.3 From 423df2ba4b731417796478c449e3e8f3d166ef21 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 21 Mar 2025 07:18:13 -0700 Subject: prevent erroneous edit of wrong parcel (#3759) * prevent erroneous edit of wrong parcel Fixes jira-archive-internal/issues/70771 [SL-20409] Erroneous Local Parcel Twins - Parcel Updates Across Region Borders - unrequested updateDatabaseParcel changes * remove unused argument in sendParcelPropertiesUpdate() --- indra/newview/llviewerparcelmgr.cpp | 12 +++++++++--- indra/newview/llviewerparcelmgr.h | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 8e6657b4b9..1a5c40064a 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1327,12 +1327,12 @@ const S32 LLViewerParcelMgr::getAgentParcelId() const return INVALID_PARCEL_ID; } -void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_agent_region) +void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel) { if(!parcel) return; - LLViewerRegion *region = use_agent_region ? gAgent.getRegion() : LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth ); + LLViewerRegion *region = LLWorld::getInstance()->getRegionFromID(parcel->getRegionID()); if (!region) return; @@ -1676,10 +1676,16 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use // Actually extract the data. if (parcel) { + // store region_id in the parcel so we can find it again later + LLViewerRegion* parcel_region = LLWorld::getInstance()->getRegion(msg->getSender()); + if (parcel_region) + { + parcel->setRegionID(parcel_region->getRegionID()); + } + if (local_id == parcel_mgr.mAgentParcel->getLocalID()) { // Parcels in different regions can have same ids. - LLViewerRegion* parcel_region = LLWorld::getInstance()->getRegion(msg->getSender()); LLViewerRegion* agent_region = gAgent.getRegion(); if (parcel_region && agent_region && parcel_region->getRegionID() == agent_region->getRegionID()) { diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index 974ea39359..086bca4878 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -219,7 +219,7 @@ public: // containing the southwest corner of the selection. // If want_reply_to_update, simulator will send back a ParcelProperties // message. - void sendParcelPropertiesUpdate(LLParcel* parcel, bool use_agent_region = false); + void sendParcelPropertiesUpdate(LLParcel* parcel); // Takes an Access List flag, like AL_ACCESS or AL_BAN void sendParcelAccessListUpdate(U32 which); -- cgit v1.2.3 From e1ebb33ab2966a20b63741dd84a0826e82b6a807 Mon Sep 17 00:00:00 2001 From: William Weaver Date: Fri, 28 Mar 2025 04:28:36 +0300 Subject: fix(pipeline): Remove incorrect zeroing of mRT dimensions in createGLBuffers Resolves the root cause of shadow rendering failures when changing RenderShadowResolutionScale immediately after modifying other graphics settings (e.g., SSAO, HDR). Investigation revealed that LLPipeline::createGLBuffers, which is called during certain graphics setting changes that require full buffer recreation, contained lines that incorrectly set mRT->width and mRT->height to zero *after* the call to allocateScreenBuffer had already established the correct dimensions. This created a state inconsistency. If RenderShadowResolutionScale was changed immediately following the graphics setting change, the subsequent call to LLPipeline::resizeShadowTexture (triggered via handleShadowsResized) would read these incorrect zero dimensions from mRT. This led to failed shadow buffer allocation (allocateShadowBuffer(0, 0)) and resulted in corrupted or missing shadows. This commit removes the erroneous mRT->width = 0 and mRT->height = 0 lines from the end of createGLBuffers. This ensures that the render target dimensions remain valid after buffer recreation. With this fix, resizeShadowTexture now correctly reads the valid screen dimensions immediately following a graphics setting change and successfully resizes the shadow buffers without delay or error. This eliminates the need for previous workarounds like guard conditions or forced shader recompiles. Ref: #3719 --- indra/newview/pipeline.cpp | 30 +++++------------------------- 1 file changed, 5 insertions(+), 25 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 691d155a3c..6adf203ea1 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -727,29 +727,6 @@ void LLPipeline::requestResizeShadowTexture() void LLPipeline::resizeShadowTexture() { - // A static counter to keep track of skipped frames - static int sSkippedFrameCount = 0; - - if (!mRT || mRT->width == 0 || mRT->height == 0) - { - sSkippedFrameCount++; - LL_WARNS("Render") << "Shadow texture resizing aborted: render target dimensions invalid. Skipped " - << sSkippedFrameCount << " frame(s) so far." << LL_ENDL; - return; - } - - // If there were skipped frames before mRT became valid, log that information. - if (sSkippedFrameCount > 0) - { - LL_INFOS("Render") << "Render target now valid after " - << sSkippedFrameCount << " skipped frame(s)." << LL_ENDL; - sSkippedFrameCount = 0; - } - - LL_WARNS() << "LLPipeline::resizeShadowTexture() called." << LL_ENDL; - LL_INFOS() << "Resizing shadow texture. mRT->width = " - << mRT->width << " mRT->height = " << mRT->height << LL_ENDL; - releaseSunShadowTargets(); releaseSpotShadowTargets(); allocateShadowBuffer(mRT->width, mRT->height); @@ -1309,8 +1286,11 @@ void LLPipeline::createGLBuffers() } allocateScreenBuffer(resX, resY); - mRT->width = 0; - mRT->height = 0; + // Do not zero out mRT dimensions here. allocateScreenBuffer() above + // already sets the correct dimensions. Zeroing them caused resizeShadowTexture() + // to fail if called immediately after createGLBuffers (e.g., post graphics change). + // mRT->width = 0; + // mRT->height = 0; if (!mNoiseMap) -- cgit v1.2.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/newview') 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: Fri, 28 Mar 2025 21:49:58 +0200 Subject: #3809 Fix J2C Upload --- 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 +++++++++ 5 files changed, 35 insertions(+), 3 deletions(-) (limited to 'indra/newview') 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.2.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/newview/llfilepicker.cpp | 6 ++---- indra/newview/llviewermenufile.cpp | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'indra/newview') 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.2.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/newview') 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: 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/newview') 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.2.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/newview') 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.2.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/newview') 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.2.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/newview') 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.2.3 From 04af0424359d55ddb8056dc1693c078eadaee239 Mon Sep 17 00:00:00 2001 From: William Weaver Date: Wed, 2 Apr 2025 02:13:01 +0300 Subject: Fix(EnvAdjust): Ensure cloud texture selection updates the sky Problem: When selecting a new cloud texture in the Personal Lighting floater (LLFloaterEnvironmentAdjust) using the cloud map texture picker, the sky rendering did not update to reflect the selected texture. The callback only updated the internal mLiveSky object and its subsequent call to mLiveSky->update() was insufficient to trigger a live render update. Cause: The onCloudMapChanged callback modified the mLiveSky settings object directly and called its update() method. However, in the context of live environment adjustments, changes require propagation through the central LLEnvironment singleton to correctly update the active environment layer (ENV_LOCAL) and signal the renderer. Relying solely on the settings object's update() method bypassed this necessary mechanism. Solution: This commit refactors onCloudMapChanged to correctly handle the update: 1. Uses the LLEnvironment singleton to manage the state change: - Explicitly targets the local environment layer (ENV_LOCAL) via setSelectedEnvironment(). - Clones the mLiveSky settings object. - Uses LLEnvironment::setEnvironment() to apply the modified clone to the ENV_LOCAL layer. - Uses LLEnvironment::updateEnvironment() to trigger the render update. 2. Synchronizes the UI preview: - Calls picker_ctrl->setValue() on the LLTextureCtrl widget after the environment update to ensure the UI preview matches the applied texture. Result: Selecting a cloud texture in the Environment Settings floater now correctly updates both the sky rendering and the UI preview widget simultaneously. Testing: - Open World -> Environment Editor -> Environment Settings. - Go to the Clouds tab. - Click the cloud texture preview to open the texture picker. - Select a new cloud texture and click OK. - Verify the sky updates immediately to use the selected texture. - Verify the texture preview in the floater also updates immediately. - Repeat with several different textures to confirm consistent behavior. --- indra/newview/llfloaterenvironmentadjust.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloaterenvironmentadjust.cpp b/indra/newview/llfloaterenvironmentadjust.cpp index 35f8340997..b137d71c22 100644 --- a/indra/newview/llfloaterenvironmentadjust.cpp +++ b/indra/newview/llfloaterenvironmentadjust.cpp @@ -456,8 +456,26 @@ void LLFloaterEnvironmentAdjust::onCloudMapChanged() { if (!mLiveSky) return; - mLiveSky->setCloudNoiseTextureId(getChild(FIELD_SKY_CLOUD_MAP)->getValue().asUUID()); + + // Get the texture picker control + LLTextureCtrl* picker_ctrl = getChild(FIELD_SKY_CLOUD_MAP); + if (!picker_ctrl) + { + // Optional: Log an error if the control isn't found, though unlikely + return; + } + + // Get the new texture ID selected by the user + LLUUID new_texture_id = picker_ctrl->getValue().asUUID(); + + // Update the internal sky settings object + mLiveSky->setCloudNoiseTextureId(new_texture_id); + + // Trigger the update for the sky rendering mLiveSky->update(); + + // Explicitly refresh the UI picker control to match the applied change + picker_ctrl->setValue(new_texture_id); } void LLFloaterEnvironmentAdjust::onWaterMapChanged() -- cgit v1.2.3 From 61ba4b0d7705ca12b606d238d48a0b1bc370bf31 Mon Sep 17 00:00:00 2001 From: William Weaver Date: Wed, 2 Apr 2025 03:45:54 +0300 Subject: Fix(XUI): Remove unrecognized user_resize attribute from sun_moon_trackball Problem: A warning "Failed to parse parameter 'user_resize.'" appeared in the logs during UI loading, originating from sun_moon_trackball.xml. Cause: The 'user_resize' attribute is not a recognized or utilized parameter for the 'sun_moon_trackball' widget type, as defined in the corresponding C++ (LLVirtualTrackball). Solution: Removed the extraneous 'user_resize="false"' line from the sun_moon_trackball.xml widget definition. Result: Eliminates the parsing warning from the logs upon viewer startup or UI reload. Testing: - Launch viewer. - Check logs for the absence of the "Failed to parse parameter 'user_resize.'" warning. --- indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml | 1 - 1 file changed, 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml b/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml index cdeff6ab05..f246ff764a 100644 --- a/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml +++ b/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml @@ -3,7 +3,6 @@ name="virtualtrackball" width="150" height="150" - user_resize="false" increment_angle_mouse="1.5f" increment_angle_btn="1.0f" image_sphere="VirtualTrackball_Sphere" -- cgit v1.2.3 From be595b440321dcad842be5d982d20fd601bb8b4c Mon Sep 17 00:00:00 2001 From: William Weaver Date: Wed, 2 Apr 2025 04:09:00 +0300 Subject: Fix(XUI): Resolve parsing warnings for Fixed Environment editor widgets Problem: Opening the Fixed Environment floater generated three distinct XUI parsing warnings in the logs: - Failed to parse parameter "decimal_digits." in xy_vector.xml - Failed to parse parameter "user_resize." in xy_vector.xml - Failed to parse parameter "logarithmic." in panel_settings_sky_clouds.xml Cause: These attributes were either not recognized/utilized by the underlying C++ widget implementations ('decimal_digits', 'user_resize' in LLXYVector) or were using an incorrect value ('logarithmic="1"' instead of a boolean 'true'/'false' in LLSliderCtrl). Solution: This commit addresses these three warnings: - Removed the extraneous 'decimal_digits' and 'user_resize' attributes from the definition of the 'xyvector' widget in xy_vector.xml. - Corrected the 'logarithmic' attribute value from "1" to "true" for the 'cloud_scroll_xy' slider in panel_settings_sky_clouds.xml. Result: Eliminates these specific parsing warnings from the logs when the Fixed Environment floater is opened. Testing: - Launch viewer. - Open World -> Environment Editor -> My Environments. - Select a sky setting and click Edit (or create a New one). - Observe the logs upon the Fixed Environment floater opening. - Verify the absence of the 'decimal_digits', 'user_resize' (from xy_vector.xml), and 'logarithmic' (from panel_settings_sky_clouds.xml) parsing warnings. --- indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml | 2 +- indra/newview/skins/default/xui/en/widgets/xy_vector.xml | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml index 7687f7cd96..23bbf45e88 100644 --- a/indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml +++ b/indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml @@ -139,7 +139,7 @@ max_val_x="30" min_val_y="-30" max_val_y="30" - logarithmic="1"/> + logarithmic="true"/> + edit_bar_height="18"> -- cgit v1.2.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/newview') 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.2.3 From 2bb4de97e43a32589434a35b617a36c2dfda22ee Mon Sep 17 00:00:00 2001 From: Hecklezz Date: Wed, 2 Apr 2025 18:18:17 +1000 Subject: Fix normal and specular repeats per meter scaling --- indra/newview/llpanelface.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index c080d72580..5a2a8ce128 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -3592,7 +3592,7 @@ void LLPanelFace::onCommitRepeatsPerMeter() bool identical_scale_t = false; LLSelectedTE::getObjectScaleS(obj_scale_s, identical_scale_s); - LLSelectedTE::getObjectScaleS(obj_scale_t, identical_scale_t); + LLSelectedTE::getObjectScaleT(obj_scale_t, identical_scale_t); if (gSavedSettings.getBOOL("SyncMaterialSettings")) { @@ -5086,6 +5086,7 @@ void LLPanelFace::LLSelectedTEMaterial::getMaxSpecularRepeats(F32& repeats, bool LLMaterial* mat = object->getTE(face)->getMaterialParams().get(); U32 s_axis = VX; U32 t_axis = VY; + LLPrimitive::getTESTAxes(face, &s_axis, &t_axis); F32 repeats_s = 1.0f; F32 repeats_t = 1.0f; if (mat) @@ -5110,6 +5111,7 @@ void LLPanelFace::LLSelectedTEMaterial::getMaxNormalRepeats(F32& repeats, bool& LLMaterial* mat = object->getTE(face)->getMaterialParams().get(); U32 s_axis = VX; U32 t_axis = VY; + LLPrimitive::getTESTAxes(face, &s_axis, &t_axis); F32 repeats_s = 1.0f; F32 repeats_t = 1.0f; if (mat) -- cgit v1.2.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/newview') 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.2.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/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 ++ 11 files changed, 290 insertions(+), 46 deletions(-) create mode 100644 indra/newview/llappearancelistener.cpp create mode 100644 indra/newview/llappearancelistener.h (limited to 'indra/newview') 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.2.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/newview') 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.2.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/newview') 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.2.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/newview') 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.2.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/newview') 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.2.3 From 1fcabcdd324305ccfafb59b9c9ef5e04ef859a4d Mon Sep 17 00:00:00 2001 From: William Weaver Date: Fri, 4 Apr 2025 16:02:08 +0300 Subject: Fix(EnvAdjust): Properly update sky after cloud texture selection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: When selecting a new cloud texture in the Personal Lighting floater (LLFloaterEnvironmentAdjust), the sky did not visually update. The code previously only updated LiveSky->setCloudNoiseTextureId() and called mLiveSky->update(), which failed to notify the global LLEnvironment mechanism or the renderer about the new texture. Cause: Relying solely on mLiveSky for environment changes is insufficient. To update the live environment layer (ENV_LOCAL) and trigger a render refresh, calls to LLEnvironment::setEnvironment() and LLEnvironment::updateEnvironment() are required. Solution: 1. Remove an unnecessary null-check for getChild, as getChild() never returns null. 2. Clone the current sky settings (mLiveSky->buildClone()) to avoid modifying a shared environment object directly. 3. Apply the new cloud texture ID to the clone. 4. Use LLEnvironment::setEnvironment(ENV_LOCAL, sky_to_set) to apply the updated settings to the user's local environment override. 5. Call LLEnvironment::updateEnvironment(LLEnvironment::TRANSITION_INSTANT, true) to ensure the renderer recognizes and displays the updated texture immediately. 6. Reset the picker control’s value to match the newly applied texture for UI consistency. Additional Note: A partial implementation was inadvertently committed earlier (commit`04af042`) due to a local staging error. This commit supersedes that incomplete change by correctly implementing the intended fix. Result: Selecting a new cloud texture from LLFloaterEnvironmentAdjust now immediately updates both the in-world sky rendering and the texture preview UI, ensuring consistency and clarity for users. Testing: - Open the Personal Lighting floater and select various cloud textures. - Verify that the sky updates immediately for each new selection. - Confirm that the texture picker also updates to reflect the selected texture. --- indra/newview/llfloaterenvironmentadjust.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloaterenvironmentadjust.cpp b/indra/newview/llfloaterenvironmentadjust.cpp index b137d71c22..58616995d3 100644 --- a/indra/newview/llfloaterenvironmentadjust.cpp +++ b/indra/newview/llfloaterenvironmentadjust.cpp @@ -455,26 +455,28 @@ void LLFloaterEnvironmentAdjust::onMoonAzimElevChanged() void LLFloaterEnvironmentAdjust::onCloudMapChanged() { if (!mLiveSky) + { return; + } - // Get the texture picker control LLTextureCtrl* picker_ctrl = getChild(FIELD_SKY_CLOUD_MAP); - if (!picker_ctrl) + + LLUUID new_texture_id = picker_ctrl->getValue().asUUID(); + + LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); + + LLSettingsSky::ptr_t sky_to_set = mLiveSky->buildClone(); + if (!sky_to_set) { - // Optional: Log an error if the control isn't found, though unlikely - return; + return; } - // Get the new texture ID selected by the user - LLUUID new_texture_id = picker_ctrl->getValue().asUUID(); + sky_to_set->setCloudNoiseTextureId(new_texture_id); - // Update the internal sky settings object - mLiveSky->setCloudNoiseTextureId(new_texture_id); + LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, sky_to_set); - // Trigger the update for the sky rendering - mLiveSky->update(); + LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT, true); - // Explicitly refresh the UI picker control to match the applied change picker_ctrl->setValue(new_texture_id); } -- cgit v1.2.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/newview') 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.2.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/newview') 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.2.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/newview/llappviewerwin32.cpp | 60 +------------------------- indra/newview/skins/default/xui/en/strings.xml | 1 - 2 files changed, 1 insertion(+), 60 deletions(-) (limited to 'indra/newview') 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.2.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/newview') 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.2.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/newview') 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 16:57:12 +0300 Subject: Fix: Remove potentially redundant RenderAutoHideSurfaceAreaLimit setting registration This commit removes a seemingly duplicated `connectRefreshCachedSettingsSafe` call in `LLPipeline::init()` for the `RenderAutoHideSurfaceAreaLimit` setting. A duplicated registration for this setting was identified during a review of `LLPipeline::init()`. Double registration can lead to unexpected behavior, including potential CPU overhead. The duplication *may* have been introduced with commit 440c7b2 (Added CollectFontVertexBuffers feature), though this requires further confirmation. Testing Performed: After removing the duplicate registration, the `RenderAutoHideSurfaceAreaLimit` functionality was validated by ensuring the following behavior (consistent with the existing code): * A value of 0 (zero) causes all objects to appear regardless of size. * Values slightly above zero result in only small objects appearing, with all others hidden. * Increasing the value causes objects of increasing size to appear, while smaller objects remain visible. This change merits careful review to ensure it has no unintended side effects, and to confirm the accuracy of these observations from other developers. --- indra/newview/pipeline.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 6adf203ea1..aa82b28bf7 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -599,7 +599,6 @@ void LLPipeline::init() connectRefreshCachedSettingsSafe("RenderMirrors"); connectRefreshCachedSettingsSafe("RenderHeroProbeUpdateRate"); connectRefreshCachedSettingsSafe("RenderHeroProbeConservativeUpdateMultiplier"); - connectRefreshCachedSettingsSafe("RenderAutoHideSurfaceAreaLimit"); LLPointer cntrl_ptr = gSavedSettings.getControl("CollectFontVertexBuffers"); if (cntrl_ptr.notNull()) -- cgit v1.2.3 From a7f3785cd6856eeba7eb454625e8cf874eb20e8e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev 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/newview') 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.2.3 From c07817c3d26095de569e9193ade2b9040b7be8c0 Mon Sep 17 00:00:00 2001 From: William Weaver Date: Fri, 11 Apr 2025 02:23:52 +0300 Subject: Fix(Tonemap): Correct blend logic to preserve HDR detail The blending operation for the `tonemap_mix` uniform in `postDeferredTonemap.glsl` incorrectly used a prematurely clamped color value as the source for the linear mix target. Specifically, the exposed HDR input color was clamped to the [0, 1] LDR range before being used in the `mix()` function when `tonemap_mix < 1.0`. This premature clamping resulted in the loss of High Dynamic Range (HDR) detail in highlights during the blend operation. As `tonemap_mix` was reduced, instead of smoothly blending towards the linear scene representation, clipped highlights were incorrectly reintroduced. This commit modifies the `toneMap` and `toneMapNoExposure` functions to correct this logic: 1. The original linear input color is preserved before exposure/processing. 2. The appropriate exposure factor is calculated and applied separately. 3. The chosen tone mapping operator is applied to the exposed color, storing the result. 4. The `mix()` function now correctly blends between the appropriately scaled, *unclamped* linear input color and the fully tone-mapped result. 5. The final clamp to the [0, 1] LDR range is applied *after* the blend operation. This change ensures that HDR information is preserved throughout the blending process, resulting in a smoother, more perceptually correct visual transition as `tonemap_mix` is adjusted. While the effect is nuanced, it is noticeable in bright highlights; with the legacy code, these highlights appeared visibly clipped and less intense during the blend, whereas the corrected code allows them to retain their peak brightness and detail more accurately. This makes the `tonemap_mix` control more intuitive, behaving as a true intensity blend for the tone mapping effect without introducing clipping artifacts. The computational cost is negligible. --- .../shaders/class1/deferred/tonemapUtilF.glsl | 37 ++++++++++++++-------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl index a63b8d7c2b..774ccb6baf 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl @@ -117,27 +117,34 @@ uniform float exposure; uniform float tonemap_mix; uniform int tonemap_type; + vec3 toneMap(vec3 color) { #ifndef NO_POST - float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; - - color *= exposure * exp_scale; + vec3 linear_input_color = color; - vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0)); + float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; + float final_exposure = exposure * exp_scale; + vec3 exposed_color = color * final_exposure; + vec3 tonemapped_color = exposed_color; switch(tonemap_type) { case 0: - color = PBRNeutralToneMapping(color); + tonemapped_color = PBRNeutralToneMapping(exposed_color); break; case 1: - color = toneMapACES_Hill(color); + tonemapped_color = toneMapACES_Hill(exposed_color); break; } - // mix tonemapped and linear here to provide adjustment - color = mix(clamped_color, color, tonemap_mix); + vec3 exposed_linear_input = linear_input_color * final_exposure; + color = mix(exposed_linear_input, tonemapped_color, tonemap_mix); + + color = clamp(color, 0.0, 1.0); +#else + color *= exposure * texture(exposureMap, vec2(0.5,0.5)).r; + color = clamp(color, 0.0, 1.0); #endif return color; @@ -147,20 +154,24 @@ vec3 toneMap(vec3 color) vec3 toneMapNoExposure(vec3 color) { #ifndef NO_POST - vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0)); + vec3 linear_input_color = color; + vec3 tonemapped_color = color; switch(tonemap_type) { case 0: - color = PBRNeutralToneMapping(color); + tonemapped_color = PBRNeutralToneMapping(color); break; case 1: - color = toneMapACES_Hill(color); + tonemapped_color = toneMapACES_Hill(color); break; } - // mix tonemapped and linear here to provide adjustment - color = mix(clamped_color, color, tonemap_mix); + color = mix(linear_input_color, tonemapped_color, tonemap_mix); + + color = clamp(color, 0.0, 1.0); +#else + color = clamp(color, 0.0, 1.0); #endif return color; -- cgit v1.2.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/newview') 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/newview') 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.2.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/newview/llinventorymodel.cpp | 2 +- indra/newview/llmeshrepository.cpp | 29 +++++++++++++++++++++++++++-- indra/newview/llmeshrepository.h | 3 +++ 3 files changed, 31 insertions(+), 3 deletions(-) (limited to 'indra/newview') 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.2.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/newview') 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.2.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/newview') 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.2.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/newview') 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.2.3 From 7d36e7103e4260c8d79d2022bfaacdcebafb75d3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 14 Apr 2025 22:07:11 +0300 Subject: #3757 Disable ability to create folders in individual outfits This part needs a recheck --- indra/newview/llinventorybridge.cpp | 6 ++---- indra/newview/llinventorygallery.cpp | 2 +- indra/newview/llinventorygallerymenu.cpp | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 5bd17d4d5b..4018a89c5a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2732,7 +2732,7 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, 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) + else if (dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) { is_movable = false; tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); @@ -4471,7 +4471,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items 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")); @@ -4496,9 +4495,8 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items { // 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("New Outfit Folder")); items.push_back(std::string("Rename")); items.push_back(std::string("thumbnail")); diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 713d87787e..eb47af85fd 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -3783,7 +3783,7 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, 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) + else if (dest_res == MY_OUTFITS_OUTFIT || dest_res == MY_OUTFITS_SUBOUTFIT) { is_movable = false; tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 7acd3b90a2..ec3e03ee2d 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -777,8 +777,8 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men if (res != MY_OUTFITS_OUTFIT && res != MY_OUTFITS_SUBOUTFIT) { items.push_back(std::string("New Outfit")); + items.push_back(std::string("New Outfit Folder")); } - items.push_back(std::string("New Outfit Folder")); items.push_back(std::string("Delete")); items.push_back(std::string("Rename")); if (!get_is_category_and_children_removable(&gInventory, selected_id, false)) -- cgit v1.2.3 From a99c1e36de575c008ea6f16c74cbcdb99ea29c5b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 15 Apr 2025 20:43:36 +0300 Subject: #3887 Fix clouds not updating setSelectedEnvironment for a default transition was conflicting with updateEnvironment for an instant transition. setSelectedEnvironment already has updateEnvironment, so remove the update and fix time --- indra/newview/llenvironment.cpp | 1 - indra/newview/llfloatereditextdaycycle.cpp | 2 -- indra/newview/llfloaterenvironmentadjust.cpp | 5 +---- 3 files changed, 1 insertion(+), 7 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 0017a724ea..875dac103c 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -2563,7 +2563,6 @@ void LLEnvironment::setSharedEnvironment() { clearEnvironment(LLEnvironment::ENV_LOCAL); setSelectedEnvironment(LLEnvironment::ENV_LOCAL); - updateEnvironment(); } void LLEnvironment::setExperienceEnvironment(LLUUID experience_id, LLUUID asset_id, F32 transition_time) diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp index 42307dd3f8..0a8b8d321d 100644 --- a/indra/newview/llfloatereditextdaycycle.cpp +++ b/indra/newview/llfloatereditextdaycycle.cpp @@ -495,7 +495,6 @@ void LLFloaterEditExtDayCycle::setEditDayCycle(const LLSettingsDay::ptr_t &pday) updateEditEnvironment(); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_INSTANT); - LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT); synchronizeTabs(); updateTabs(); refresh(); @@ -824,7 +823,6 @@ void LLFloaterEditExtDayCycle::onClearTrack() updateEditEnvironment(); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_INSTANT); - LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT); synchronizeTabs(); updateTabs(); refresh(); diff --git a/indra/newview/llfloaterenvironmentadjust.cpp b/indra/newview/llfloaterenvironmentadjust.cpp index 35f8340997..aa548a3f42 100644 --- a/indra/newview/llfloaterenvironmentadjust.cpp +++ b/indra/newview/llfloaterenvironmentadjust.cpp @@ -242,9 +242,7 @@ void LLFloaterEnvironmentAdjust::captureCurrentEnvironment() environment.setEnvironment(LLEnvironment::ENV_LOCAL, mLiveSky, FLOATER_ENVIRONMENT_UPDATE); environment.setEnvironment(LLEnvironment::ENV_LOCAL, mLiveWater, FLOATER_ENVIRONMENT_UPDATE); } - environment.setSelectedEnvironment(LLEnvironment::ENV_LOCAL); - environment.updateEnvironment(LLEnvironment::TRANSITION_INSTANT); - + environment.setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_INSTANT); } void LLFloaterEnvironmentAdjust::onButtonReset() @@ -258,7 +256,6 @@ void LLFloaterEnvironmentAdjust::onButtonReset() this->closeFloater(); LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL); LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL); - LLEnvironment::instance().updateEnvironment(); } }); -- cgit v1.2.3 From 2e4d2ddae15428002d289ea6d097cc3300d16559 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 16 Apr 2025 22:48:25 +0300 Subject: #3627 Crash on texture cache init I'm not sure if I should be crashing and logging this data to bugsplat or if I should let it be in case cache file is unreasonably big. --- indra/newview/lltexturecache.cpp | 44 +++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index be7653c011..442c627d07 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -1347,27 +1347,39 @@ U32 LLTextureCache::openAndReadEntries(std::vector& entries) } for (U32 idx=0; idxread((void*)(&entry), (S32)sizeof(Entry)); - if (bytes_read < sizeof(Entry)) + try + { + Entry entry; + S32 bytes_read = aprfile->read((void*)(&entry), (S32)sizeof(Entry)); + if (bytes_read < sizeof(Entry)) + { + LL_WARNS() << "Corrupted header entries, failed at " << idx << " / " << num_entries << LL_ENDL; + return 0; + } + entries.push_back(entry); + // LL_INFOS() << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << LL_ENDL; + if (entry.mImageSize > entry.mBodySize) + { + mHeaderIDMap[entry.mID] = idx; + mTexturesSizeMap[entry.mID] = entry.mBodySize; + mTexturesSizeTotal += entry.mBodySize; + } + else + { + mFreeList.insert(idx); + } + } + catch (std::bad_alloc&) { - LL_WARNS() << "Corrupted header entries, failed at " << idx << " / " << num_entries << LL_ENDL; + // Too little ram yet very large cache? + // Should this actually crash viewer? + entries.clear(); + LL_WARNS() << "Bad alloc trying to read texture entries from cache, mFreeList: " << (S32)mFreeList.size() + << ", added entries: " << idx << ", total entries: " << num_entries << LL_ENDL; closeHeaderEntriesFile(); purgeAllTextures(false); return 0; } - entries.push_back(entry); -// LL_INFOS() << "ENTRY: " << entry.mTime << " TEX: " << entry.mID << " IDX: " << idx << " Size: " << entry.mImageSize << LL_ENDL; - if(entry.mImageSize > entry.mBodySize) - { - mHeaderIDMap[entry.mID] = idx; - mTexturesSizeMap[entry.mID] = entry.mBodySize; - mTexturesSizeTotal += entry.mBodySize; - } - else - { - mFreeList.insert(idx); - } } closeHeaderEntriesFile(); return num_entries; -- cgit v1.2.3 From d65de99052d5ff08c7c4290a1f1b8e396105b8af Mon Sep 17 00:00:00 2001 From: Ansariel Date: Thu, 17 Apr 2025 18:44:09 +0200 Subject: Use standard library functions for llisnan and replace obvious NaN checks that don't work using /fp:fast floating point behavior under MSVC --- indra/newview/llphysicsmotion.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index 86291708b0..e5c84728fe 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -646,18 +646,17 @@ bool LLPhysicsMotion::onUpdate(F32 time) velocity_new_local = 0; } - // Check for NaN values. A NaN value is detected if the variables doesn't equal itself. - // If NaN, then reset everything. - if ((mPosition_local != mPosition_local) || - (mVelocity_local != mVelocity_local) || - (position_new_local != position_new_local)) + // Check for NaN values. If NaN, then reset everything. + if (llisnan(mPosition_local) || + llisnan(mVelocity_local) || + llisnan(position_new_local)) { - position_new_local = 0; - mVelocity_local = 0; - mVelocityJoint_local = 0; - mAccelerationJoint_local = 0; - mPosition_local = 0; - mPosition_world = LLVector3(0,0,0); + position_new_local = 0.f; + mVelocity_local = 0.f; + mVelocityJoint_local = 0.f; + mAccelerationJoint_local = 0.f; + mPosition_local = 0.f; + mPosition_world = LLVector3(0.f,0.f,0.f); } const F32 position_new_local_clamped = llclamp(position_new_local, -- cgit v1.2.3 From 441c844ec8319f4c15d59de5a5a8ae46be7912f1 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Thu, 17 Apr 2025 18:55:08 +0200 Subject: Fix lerp issues on newer GCC versions --- indra/newview/llpanelprimmediacontrols.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index b00b9d1ad1..b1c8b5f36a 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -777,7 +777,7 @@ void LLPanelPrimMediaControls::draw() else if(mFadeTimer.getStarted()) { F32 time = mFadeTimer.getElapsedTimeF32(); - alpha *= llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f); + alpha *= llmax(lerp(1.f, 0.f, time / mControlFadeTime), 0.0f); if(time >= mControlFadeTime) { -- cgit v1.2.3 From 698a3017a0de2efbf06e4e0c906494f9f6ef172f Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 25 Sep 2024 22:14:39 +0200 Subject: Remove orphaned LLPanelOutfitSnapshotInventory # Conflicts: # indra/newview/llpanelsnapshotinventory.cpp --- indra/newview/llpanelsnapshotinventory.cpp | 106 ++++------------------------- indra/newview/llpanelsnapshotlocal.cpp | 20 +++--- indra/newview/llpanelsnapshotoptions.cpp | 4 +- indra/newview/llpanelsnapshotpostcard.cpp | 20 +++--- indra/newview/llpanelsnapshotprofile.cpp | 18 ++--- 5 files changed, 45 insertions(+), 123 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp index 96b17acc40..74dadce960 100644 --- a/indra/newview/llpanelsnapshotinventory.cpp +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -42,77 +42,33 @@ /** * The panel provides UI for saving snapshot as an inventory texture. */ -class LLPanelSnapshotInventoryBase - : public LLPanelSnapshot -{ - LOG_CLASS(LLPanelSnapshotInventoryBase); - -public: - LLPanelSnapshotInventoryBase(); - - /*virtual*/ bool postBuild(); -protected: - void onSend(); - /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType(); -}; - class LLPanelSnapshotInventory - : public LLPanelSnapshotInventoryBase + : public LLPanelSnapshot { LOG_CLASS(LLPanelSnapshotInventory); public: LLPanelSnapshotInventory(); - /*virtual*/ bool postBuild(); - /*virtual*/ void onOpen(const LLSD& key); + bool postBuild() override; + void onOpen(const LLSD& key) override; void onResolutionCommit(LLUICtrl* ctrl); private: - /*virtual*/ std::string getWidthSpinnerName() const { return "inventory_snapshot_width"; } - /*virtual*/ std::string getHeightSpinnerName() const { return "inventory_snapshot_height"; } - /*virtual*/ std::string getAspectRatioCBName() const { return "inventory_keep_aspect_check"; } - /*virtual*/ std::string getImageSizeComboName() const { return "texture_size_combo"; } - /*virtual*/ std::string getImageSizePanelName() const { return LLStringUtil::null; } - /*virtual*/ void updateControls(const LLSD& info); - -}; - -class LLPanelOutfitSnapshotInventory - : public LLPanelSnapshotInventoryBase -{ - LOG_CLASS(LLPanelOutfitSnapshotInventory); + std::string getWidthSpinnerName() const override { return "inventory_snapshot_width"; } + std::string getHeightSpinnerName() const override { return "inventory_snapshot_height"; } + std::string getAspectRatioCBName() const override { return "inventory_keep_aspect_check"; } + std::string getImageSizeComboName() const override { return "texture_size_combo"; } + std::string getImageSizePanelName() const override { return LLStringUtil::null; } + LLSnapshotModel::ESnapshotType getSnapshotType() override; + void updateControls(const LLSD& info) override; -public: - LLPanelOutfitSnapshotInventory(); - /*virtual*/ bool postBuild(); - /*virtual*/ void onOpen(const LLSD& key); - -private: - /*virtual*/ std::string getWidthSpinnerName() const { return ""; } - /*virtual*/ std::string getHeightSpinnerName() const { return ""; } - /*virtual*/ std::string getAspectRatioCBName() const { return ""; } - /*virtual*/ std::string getImageSizeComboName() const { return "texture_size_combo"; } - /*virtual*/ std::string getImageSizePanelName() const { return LLStringUtil::null; } - /*virtual*/ void updateControls(const LLSD& info); - - /*virtual*/ void cancel(); + void onSend(); }; static LLPanelInjector panel_class1("llpanelsnapshotinventory"); -static LLPanelInjector panel_class2("llpaneloutfitsnapshotinventory"); - -LLPanelSnapshotInventoryBase::LLPanelSnapshotInventoryBase() -{ -} - -bool LLPanelSnapshotInventoryBase::postBuild() -{ - return LLPanelSnapshot::postBuild(); -} - -LLSnapshotModel::ESnapshotType LLPanelSnapshotInventoryBase::getSnapshotType() +LLSnapshotModel::ESnapshotType LLPanelSnapshotInventory::getSnapshotType() { return LLSnapshotModel::SNAPSHOT_TEXTURE; } @@ -130,7 +86,7 @@ bool LLPanelSnapshotInventory::postBuild() getChild(getHeightSpinnerName())->setAllowEdit(false); getChild(getImageSizeComboName())->setCommitCallback(boost::bind(&LLPanelSnapshotInventory::onResolutionCommit, this, _1)); - return LLPanelSnapshotInventoryBase::postBuild(); + return LLPanelSnapshot::postBuild(); } // virtual @@ -153,7 +109,7 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl) getChild(getHeightSpinnerName())->setVisible(!current_window_selected); } -void LLPanelSnapshotInventoryBase::onSend() +void LLPanelSnapshotInventory::onSend() { S32 w = 0; S32 h = 0; @@ -187,37 +143,3 @@ void LLPanelSnapshotInventoryBase::onSend() } } } - -LLPanelOutfitSnapshotInventory::LLPanelOutfitSnapshotInventory() -{ - mCommitCallbackRegistrar.add("Inventory.SaveOutfitPhoto", boost::bind(&LLPanelOutfitSnapshotInventory::onSend, this)); - mCommitCallbackRegistrar.add("Inventory.SaveOutfitCancel", boost::bind(&LLPanelOutfitSnapshotInventory::cancel, this)); -} - -// virtual -bool LLPanelOutfitSnapshotInventory::postBuild() -{ - return LLPanelSnapshotInventoryBase::postBuild(); -} - -// virtual -void LLPanelOutfitSnapshotInventory::onOpen(const LLSD& key) -{ - getChild("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", LLAgentBenefitsMgr::current().getTextureUploadCost())); - LLPanelSnapshot::onOpen(key); -} - -// virtual -void LLPanelOutfitSnapshotInventory::updateControls(const LLSD& info) -{ - const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true; - getChild("save_btn")->setEnabled(have_snapshot); -} - -void LLPanelOutfitSnapshotInventory::cancel() -{ - if (mSnapshotFloater) - { - mSnapshotFloater->closeFloater(); - } -} diff --git a/indra/newview/llpanelsnapshotlocal.cpp b/indra/newview/llpanelsnapshotlocal.cpp index 366030c0fa..57759fbcaa 100644 --- a/indra/newview/llpanelsnapshotlocal.cpp +++ b/indra/newview/llpanelsnapshotlocal.cpp @@ -47,18 +47,18 @@ class LLPanelSnapshotLocal public: LLPanelSnapshotLocal(); - /*virtual*/ bool postBuild(); - /*virtual*/ void onOpen(const LLSD& key); + bool postBuild() override; + void onOpen(const LLSD& key) override; private: - /*virtual*/ std::string getWidthSpinnerName() const { return "local_snapshot_width"; } - /*virtual*/ std::string getHeightSpinnerName() const { return "local_snapshot_height"; } - /*virtual*/ std::string getAspectRatioCBName() const { return "local_keep_aspect_check"; } - /*virtual*/ std::string getImageSizeComboName() const { return "local_size_combo"; } - /*virtual*/ std::string getImageSizePanelName() const { return "local_image_size_lp"; } - /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const; - /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType(); - /*virtual*/ void updateControls(const LLSD& info); + std::string getWidthSpinnerName() const override { return "local_snapshot_width"; } + std::string getHeightSpinnerName() const override { return "local_snapshot_height"; } + std::string getAspectRatioCBName() const override { return "local_keep_aspect_check"; } + std::string getImageSizeComboName() const override { return "local_size_combo"; } + std::string getImageSizePanelName() const override { return "local_image_size_lp"; } + LLSnapshotModel::ESnapshotFormat getImageFormat() const override; + LLSnapshotModel::ESnapshotType getSnapshotType() override; + void updateControls(const LLSD& info) override; S32 mLocalFormat; diff --git a/indra/newview/llpanelsnapshotoptions.cpp b/indra/newview/llpanelsnapshotoptions.cpp index 962d3bba16..63dd50996a 100644 --- a/indra/newview/llpanelsnapshotoptions.cpp +++ b/indra/newview/llpanelsnapshotoptions.cpp @@ -47,8 +47,8 @@ class LLPanelSnapshotOptions public: LLPanelSnapshotOptions(); ~LLPanelSnapshotOptions(); - /*virtual*/ bool postBuild(); - /*virtual*/ void onOpen(const LLSD& key); + bool postBuild() override; + void onOpen(const LLSD& key) override; private: void updateUploadCost(); diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp index 23e8789e3f..f3dfdc9250 100644 --- a/indra/newview/llpanelsnapshotpostcard.cpp +++ b/indra/newview/llpanelsnapshotpostcard.cpp @@ -56,18 +56,18 @@ class LLPanelSnapshotPostcard public: LLPanelSnapshotPostcard(); - /*virtual*/ bool postBuild(); - /*virtual*/ void onOpen(const LLSD& key); + bool postBuild() override; + void onOpen(const LLSD& key) override; private: - /*virtual*/ std::string getWidthSpinnerName() const { return "postcard_snapshot_width"; } - /*virtual*/ std::string getHeightSpinnerName() const { return "postcard_snapshot_height"; } - /*virtual*/ std::string getAspectRatioCBName() const { return "postcard_keep_aspect_check"; } - /*virtual*/ std::string getImageSizeComboName() const { return "postcard_size_combo"; } - /*virtual*/ std::string getImageSizePanelName() const { return "postcard_image_size_lp"; } - /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG; } - /*virtual*/ LLSnapshotModel::ESnapshotType getSnapshotType(); - /*virtual*/ void updateControls(const LLSD& info); + std::string getWidthSpinnerName() const override { return "postcard_snapshot_width"; } + std::string getHeightSpinnerName() const override { return "postcard_snapshot_height"; } + std::string getAspectRatioCBName() const override { return "postcard_keep_aspect_check"; } + std::string getImageSizeComboName() const override { return "postcard_size_combo"; } + std::string getImageSizePanelName() const override { return "postcard_image_size_lp"; } + LLSnapshotModel::ESnapshotFormat getImageFormat() const override { return LLSnapshotModel::SNAPSHOT_FORMAT_JPEG; } + LLSnapshotModel::ESnapshotType getSnapshotType() override; + void updateControls(const LLSD& info) override; bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response); static void sendPostcardFinished(LLSD result); diff --git a/indra/newview/llpanelsnapshotprofile.cpp b/indra/newview/llpanelsnapshotprofile.cpp index aa257dea9e..b533d7bbbc 100644 --- a/indra/newview/llpanelsnapshotprofile.cpp +++ b/indra/newview/llpanelsnapshotprofile.cpp @@ -49,17 +49,17 @@ class LLPanelSnapshotProfile public: LLPanelSnapshotProfile(); - /*virtual*/ bool postBuild(); - /*virtual*/ void onOpen(const LLSD& key); + bool postBuild() override; + void onOpen(const LLSD& key) override; private: - /*virtual*/ std::string getWidthSpinnerName() const { return "profile_snapshot_width"; } - /*virtual*/ std::string getHeightSpinnerName() const { return "profile_snapshot_height"; } - /*virtual*/ std::string getAspectRatioCBName() const { return "profile_keep_aspect_check"; } - /*virtual*/ std::string getImageSizeComboName() const { return "profile_size_combo"; } - /*virtual*/ std::string getImageSizePanelName() const { return "profile_image_size_lp"; } - /*virtual*/ LLSnapshotModel::ESnapshotFormat getImageFormat() const { return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; } - /*virtual*/ void updateControls(const LLSD& info); + std::string getWidthSpinnerName() const override { return "profile_snapshot_width"; } + std::string getHeightSpinnerName() const override { return "profile_snapshot_height"; } + std::string getAspectRatioCBName() const override { return "profile_keep_aspect_check"; } + std::string getImageSizeComboName() const override { return "profile_size_combo"; } + std::string getImageSizePanelName() const override { return "profile_image_size_lp"; } + LLSnapshotModel::ESnapshotFormat getImageFormat() const override { return LLSnapshotModel::SNAPSHOT_FORMAT_PNG; } + void updateControls(const LLSD& info) override; void onSend(); }; -- cgit v1.2.3 From 0c380ebc085df0f7edce3bac51c57c150dd1e999 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 25 Sep 2024 23:05:44 +0200 Subject: Fix upload cost calculation for snapshots to inventory based on encoded image size and display upload cost to user --- indra/newview/llpanelsnapshotinventory.cpp | 42 +++++++++++++++------- .../default/xui/de/panel_snapshot_inventory.xml | 2 +- .../default/xui/en/panel_snapshot_inventory.xml | 4 ++- .../default/xui/es/panel_snapshot_inventory.xml | 2 +- .../default/xui/fr/panel_snapshot_inventory.xml | 2 +- .../default/xui/it/panel_snapshot_inventory.xml | 2 +- .../default/xui/ja/panel_snapshot_inventory.xml | 2 +- .../default/xui/pt/panel_snapshot_inventory.xml | 2 +- .../default/xui/ru/panel_snapshot_inventory.xml | 2 +- .../default/xui/tr/panel_snapshot_inventory.xml | 2 +- .../default/xui/zh/panel_snapshot_inventory.xml | 2 +- 11 files changed, 41 insertions(+), 23 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llpanelsnapshotinventory.cpp b/indra/newview/llpanelsnapshotinventory.cpp index 74dadce960..b81b891685 100644 --- a/indra/newview/llpanelsnapshotinventory.cpp +++ b/indra/newview/llpanelsnapshotinventory.cpp @@ -64,6 +64,8 @@ private: void updateControls(const LLSD& info) override; void onSend(); + void updateUploadCost(); + S32 calculateUploadCost(); }; static LLPanelInjector panel_class1("llpanelsnapshotinventory"); @@ -92,6 +94,8 @@ bool LLPanelSnapshotInventory::postBuild() // virtual void LLPanelSnapshotInventory::onOpen(const LLSD& key) { + updateUploadCost(); + LLPanelSnapshot::onOpen(key); } @@ -100,6 +104,8 @@ void LLPanelSnapshotInventory::updateControls(const LLSD& info) { const bool have_snapshot = info.has("have-snapshot") ? info["have-snapshot"].asBoolean() : true; getChild("save_btn")->setEnabled(have_snapshot); + + updateUploadCost(); } void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl) @@ -111,19 +117,7 @@ void LLPanelSnapshotInventory::onResolutionCommit(LLUICtrl* ctrl) void LLPanelSnapshotInventory::onSend() { - S32 w = 0; - S32 h = 0; - - if( mSnapshotFloater ) - { - LLSnapshotLivePreview* preview = mSnapshotFloater->getPreviewView(); - if( preview ) - { - preview->getSize(w, h); - } - } - - S32 expected_upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost(w, h); + S32 expected_upload_cost = calculateUploadCost(); if (can_afford_transaction(expected_upload_cost)) { if (mSnapshotFloater) @@ -143,3 +137,25 @@ void LLPanelSnapshotInventory::onSend() } } } + +void LLPanelSnapshotInventory::updateUploadCost() +{ + getChild("hint_lbl")->setTextArg("[UPLOAD_COST]", llformat("%d", calculateUploadCost())); +} + +S32 LLPanelSnapshotInventory::calculateUploadCost() +{ + S32 w = 0; + S32 h = 0; + + if (mSnapshotFloater) + { + if (LLSnapshotLivePreview* preview = mSnapshotFloater->getPreviewView()) + { + w = preview->getEncodedImageWidth(); + h = preview->getEncodedImageHeight(); + } + } + + return LLAgentBenefitsMgr::current().getTextureUploadCost(w, h); +} 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..0cac1b410f 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]" /> To save your image as a texture select one of the square formats. + +Upload cost: L$[UPLOAD_COST]