diff --git a/indra/llcommon/llbase64.cpp b/indra/llcommon/llbase64.cpp index 4e82cf7f209b2edfba28601135a294405f0003de..6683ef7fc72ff5132661d484c7bf8b7165da0036 100644 --- a/indra/llcommon/llbase64.cpp +++ b/indra/llcommon/llbase64.cpp @@ -28,34 +28,77 @@ #include "linden_common.h" #include "llbase64.h" +#include <openssl/evp.h> -#include <string> - -#include "apr_base64.h" +// static +std::string LLBase64::encode(const U8* input, size_t input_size) +{ + if (!(input && input_size > 0)) return LLStringUtil::null; + + BIO *b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + BIO *bio = BIO_new(BIO_s_mem()); + BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); + bio = BIO_push(b64, bio); + BIO_write(bio, input, input_size); + + (void)BIO_flush(bio); + + char *new_data; + size_t bytes_written = BIO_get_mem_data(bio, &new_data); + std::string result(new_data, bytes_written); + BIO_free_all(bio); + + return result; +} +// static +std::string LLBase64::encode(const std::string& in_str) +{ + size_t data_size = in_str.size(); + std::vector<U8> data; + data.resize(data_size); + memcpy(&data[0], in_str.c_str(), data_size); + return encode(&data[0], data_size); +} // static -std::string LLBase64::encode(const U8* input, size_t input_size) +size_t LLBase64::decode(const std::string& input, U8 * buffer, size_t buffer_size) +{ + if (input.empty()) return 0; + + BIO *b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + // BIO_new_mem_buf is not const aware, but it doesn't modify the buffer + BIO *bio = BIO_new_mem_buf(const_cast<char*>(input.c_str()), input.length()); + bio = BIO_push(b64, bio); + size_t bytes_written = BIO_read(bio, buffer, buffer_size); + BIO_free_all(bio); + + return bytes_written; +} + +std::string LLBase64::decode(const std::string& input) { - std::string output; - if (input - && input_size > 0) - { - // Yes, it returns int. - int b64_buffer_length = apr_base64_encode_len(input_size); - char* b64_buffer = new char[b64_buffer_length]; - - // This is faster than apr_base64_encode() if you know - // you're not on an EBCDIC machine. Also, the output is - // null terminated, even though the documentation doesn't - // specify. See apr_base64.c for details. JC - b64_buffer_length = apr_base64_encode_binary( - b64_buffer, - input, - input_size); - output.assign(b64_buffer); - delete[] b64_buffer; - } - return output; + U32 buffer_len = LLBase64::requiredDecryptionSpace(input); + std::vector<U8> buffer(buffer_len); + buffer_len = LLBase64::decode(input, &buffer[0], buffer_len); + buffer.resize(buffer_len); + return std::string(reinterpret_cast<const char*>(&buffer[0]), buffer_len); } +// static +size_t LLBase64::requiredDecryptionSpace(const std::string& str) +{ + size_t len = str.length(); + U32 padding = 0; + + if (str[len - 1] == '=' && str[len - 2] == '=') //last two chars are = + padding = 2; + else if (str[len - 1] == '=') //last char is = + padding = 1; + + return len * 0.75 - padding; +} diff --git a/indra/llcommon/llbase64.h b/indra/llcommon/llbase64.h index 16d2c217d0cd04927fdaf1c14979c6ec22d5279b..064da10a1f4d348fdd1873e383eaa4f9e45ee53f 100644 --- a/indra/llcommon/llbase64.h +++ b/indra/llcommon/llbase64.h @@ -31,7 +31,11 @@ class LL_COMMON_API LLBase64 { public: + static std::string encode(const std::string& in_str); static std::string encode(const U8* input, size_t input_size); + static size_t decode(const std::string& input, U8 * buffer, size_t buffer_size); + static std::string decode(const std::string& input); + static size_t requiredDecryptionSpace(const std::string& str); }; #endif diff --git a/indra/llcommon/tests/llbase64_test.cpp b/indra/llcommon/tests/llbase64_test.cpp index d0394150fa2ae63b2d82d8f266dfa55f3a281090..afb942f01bf1974a8953377d8da503cc90481c97 100644 --- a/indra/llcommon/tests/llbase64_test.cpp +++ b/indra/llcommon/tests/llbase64_test.cpp @@ -73,5 +73,24 @@ namespace tut ensure("encode 40 bytes", (result == "c9+s/4xGMX3smy3HZRGkg+YTUEBwNYdi7QwaSH4OkY92xAuxhKnDhg==") ); } - + + template<> template<> + void base64_object::test<3>() + { + std::string result; + + result = LLBase64::encode(LLStringExplicit("Hands full of bananas.")); + ensure("encode string", + (result == "SGFuZHMgZnVsbCBvZiBiYW5hbmFzLg==")); + } + + template<> template<> + void base64_object::test<4>() + { + std::string result; + + result = LLBase64::decode(LLStringExplicit("SGFuZHMgZnVsbCBvZiBiYW5hbmFzLg==")); + ensure("decode string", + (result == "Hands full of bananas.")); + } } diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 2500e2251c7d2b29b9306eefbf092b36d7ed8996..50864430d60a89cd87664b1954f843b0c03366bc 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -29,6 +29,7 @@ include_directories( ) set(llmessage_SOURCE_FILES + llaescipher.cpp llassetstorage.cpp llavatarname.cpp llavatarnamecache.cpp @@ -106,6 +107,7 @@ set(llmessage_SOURCE_FILES set(llmessage_HEADER_FILES CMakeLists.txt + llaescipher.h llassetstorage.h llavatarname.h llavatarnamecache.h diff --git a/indra/llmessage/llaescipher.cpp b/indra/llmessage/llaescipher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6e08c7810bdaf457198ab126e324fca451f5affb --- /dev/null +++ b/indra/llmessage/llaescipher.cpp @@ -0,0 +1,154 @@ +/* + * @file llaescipher.cpp + * @brief AES wrapper + * + * Copyright (c) 2014, Cinder Roxley <cinder@sdf.org> + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "linden_common.h" +#include "llaescipher.h" +#include <openssl/evp.h> +#include <openssl/aes.h> + +LLAESCipher::LLAESCipher(const U8* secret, size_t secret_size, const U8* iv, size_t iv_size) +: LLCipher() +{ + llassert(secret); + + mSecretSize = secret_size; + mSecret = new U8[mSecretSize]; + memcpy(mSecret, secret, mSecretSize); + + mInitialVectorSize = iv_size; + mInitialVector = new U8[mInitialVectorSize]; + memcpy(mInitialVector, iv, mInitialVectorSize); +} + +LLAESCipher::~LLAESCipher() +{ + delete [] mSecret; + mSecret = nullptr; + + delete [] mInitialVector; + mInitialVector = nullptr; +} + +// virtual +U32 LLAESCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) +{ + if (!src || !src_len || !dst || !dst_len) return 0; + if (src_len > dst_len) return 0; + + // OpenSSL uses "cipher contexts" to hold encryption parameters. + EVP_CIPHER_CTX* context = EVP_CIPHER_CTX_new(); + + EVP_EncryptInit_ex(context, EVP_aes_256_ofb(), nullptr, nullptr, nullptr); + EVP_CIPHER_CTX_set_key_length(context, (int)mSecretSize); + + EVP_EncryptInit_ex(context, nullptr, nullptr, mSecret, mInitialVector); + + int blocksize = EVP_CIPHER_CTX_block_size(context); + int keylen = EVP_CIPHER_CTX_key_length(context); + int iv_length = EVP_CIPHER_CTX_iv_length(context); + LL_DEBUGS("Crypto") << "Blocksize " << blocksize << " keylen " << keylen << " iv_len " << iv_length << LL_ENDL; + + int output_len = 0; + int temp_len = 0; + if (!EVP_EncryptUpdate(context, + dst, + &output_len, + src, + src_len)) + { + LL_WARNS("Crypto") << "EVP_EncryptUpdate failure" << LL_ENDL; + goto AES_ERROR; + } + + // There may be some final data left to encrypt if the input is + // not an exact multiple of the block size. + if (!EVP_EncryptFinal_ex(context, (unsigned char*)(dst + output_len), &temp_len)) + { + LL_WARNS("Crypto") << "EVP_EncryptFinal failure" << LL_ENDL; + goto AES_ERROR; + } + output_len += temp_len; + + EVP_CIPHER_CTX_free(context); + return output_len; + +AES_ERROR: + EVP_CIPHER_CTX_free(context); + return 0; +} + +// virtual +U32 LLAESCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) +{ + if (!src || !src_len || !dst || !dst_len) return 0; + if (src_len > dst_len) return 0; + + EVP_CIPHER_CTX* context = EVP_CIPHER_CTX_new(); + + EVP_DecryptInit_ex(context, EVP_aes_256_ofb(), nullptr, nullptr, nullptr); + EVP_CIPHER_CTX_set_key_length(context, (int)mSecretSize); + + EVP_DecryptInit_ex(context, nullptr, nullptr, mSecret, mInitialVector); + + int blocksize = EVP_CIPHER_CTX_block_size(context); + int keylen = EVP_CIPHER_CTX_key_length(context); + int iv_length = EVP_CIPHER_CTX_iv_length(context); + LL_DEBUGS("AES") << "Blocksize " << blocksize << " keylen " << keylen << " iv_len " << iv_length << LL_ENDL; + + int out_len = 0; + int tmp_len = 0; + if (!EVP_DecryptUpdate(context, dst, &out_len, src, src_len)) + { + LL_WARNS("AES") << "EVP_DecryptUpdate failure" << LL_ENDL; + goto AES_ERROR; + } + if (!EVP_DecryptFinal_ex(context, dst + out_len, &tmp_len)) + { + LL_WARNS("AES") << "EVP_DecryptFinal failure" << LL_ENDL; + goto AES_ERROR; + } + + out_len += tmp_len; + + EVP_CIPHER_CTX_free(context); + return out_len; + +AES_ERROR: + EVP_CIPHER_CTX_free(context); + return 0; +} + +// virtual +U32 LLAESCipher::requiredEncryptionSpace(U32 len) const +{ + len += AES_BLOCK_SIZE; + len -= (len % AES_BLOCK_SIZE); + return len; +} diff --git a/indra/llmessage/llaescipher.h b/indra/llmessage/llaescipher.h new file mode 100644 index 0000000000000000000000000000000000000000..5fca5f739866705cd01ec57e36fee9c70fe32c0e --- /dev/null +++ b/indra/llmessage/llaescipher.h @@ -0,0 +1,53 @@ +/* + * @file llaescipher.h + * @brief AES wrapper + * + * Copyright (c) 2014, Cinder Roxley <cinder@sdf.org> + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef LL_AESCIPHER_H +#define LL_AESCIPHER_H + +#include "llcipher.h" + +class LLAESCipher : public LLCipher +{ +public: + LLAESCipher(const U8* secret, size_t secret_size, const U8* iv, size_t iv_size); + virtual ~LLAESCipher(); + + /*virtual*/ U32 encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) override; + /*virtual*/ U32 decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len) override; + /*virtual*/ U32 requiredEncryptionSpace(U32 src_len) const override; + +private: + U8* mSecret; + size_t mSecretSize; + U8* mInitialVector; + size_t mInitialVectorSize; +}; + +#endif // LL_AESCIPHER_H diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4e57a359e8300e2aaa194b8b26fd91fbdafe36a7..08954bbb8ece0507e7a6bd1d42fb800ee638d75f 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -333,6 +333,7 @@ set(viewer_SOURCE_FILES llfloaterpreference.cpp llfloaterpreferenceviewadvanced.cpp llfloaterpreviewtrash.cpp + llfloaterprogressview.cpp llfloaterproperties.cpp llfloaterregiondebugconsole.cpp llfloaterregioninfo.cpp @@ -1026,6 +1027,7 @@ set(viewer_HEADER_FILES llfloaterpreference.h llfloaterpreferenceviewadvanced.h llfloaterpreviewtrash.h + llfloaterprogressview.h llfloaterproperties.h llfloaterregiondebugconsole.h llfloaterregioninfo.h diff --git a/indra/newview/alpanelradaralert.cpp b/indra/newview/alpanelradaralert.cpp index aef3e383cc16fc7444546a482b24460ca5202200..283a2913b2d10a99829a7d841cda4a9affabc38c 100644 --- a/indra/newview/alpanelradaralert.cpp +++ b/indra/newview/alpanelradaralert.cpp @@ -6,7 +6,6 @@ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * Copyright (C) 2014, Cinder Roxley - * Copyright (C) 2022, Rye Mutt <rye@alchemyviewer.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/indra/newview/alpanelradaralert.h b/indra/newview/alpanelradaralert.h index ad83cd8922c940b2ff146b85a144ebd2e548373e..db41806f0bb61f71e649f8a88fffbe171fa4e026 100644 --- a/indra/newview/alpanelradaralert.h +++ b/indra/newview/alpanelradaralert.h @@ -6,7 +6,6 @@ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * COpyright (C) 2014, Cinder Roxley - * Copyright (C) 2022, Rye Mutt <rye@alchemyviewer.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 3eb270aff2d5e04157350053dbca15e40803e5a0..a7266e49248161614672ed725b29f0f63d939c7f 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -121,10 +121,13 @@ BOOL LLAvatarListItem::postBuild() mIconPermissionEditTheirs = getChild<LLIconCtrl>("permission_edit_theirs_icon"); mIconPermissionMapTheirs = getChild<LLIconCtrl>("permission_map_theirs_icon"); + mIconPermissionOnlineTheirs = getChild<LLIconCtrl>("permission_online_theirs_icon"); + mIconPermissionOnline->setVisible(false); mIconPermissionMap->setVisible(false); mIconPermissionEditMine->setVisible(false); mIconPermissionEditTheirs->setVisible(false); + mIconPermissionOnlineTheirs->setVisible(false); mIconPermissionMapTheirs->setVisible(false); mIconHovered = getChild<LLIconCtrl>("hovered_icon"); @@ -156,7 +159,9 @@ BOOL LLAvatarListItem::postBuild() mIconPermissionMap->setEnabled(SP_NEVER != mShowPermissions); mIconPermissionEditMine->setEnabled(SP_NEVER != mShowPermissions); mIconPermissionEditTheirs->setEnabled(SP_NEVER != mShowPermissions); + mIconPermissionOnlineTheirs->setEnabled(SP_NEVER != mShowPermissions); mIconPermissionMapTheirs->setEnabled(SP_NEVER != mShowPermissions); + return TRUE; } @@ -331,6 +336,7 @@ void LLAvatarListItem::setShowPermissions(EShowPermissionType spType) mIconPermissionMap->setEnabled(SP_NEVER != mShowPermissions); mIconPermissionEditMine->setEnabled(SP_NEVER != mShowPermissions); mIconPermissionEditTheirs->setEnabled(SP_NEVER != mShowPermissions); + mIconPermissionOnlineTheirs->setEnabled(SP_NEVER != mShowPermissions); mIconPermissionMapTheirs->setEnabled(SP_NEVER != mShowPermissions); refreshPermissions(); @@ -675,6 +681,7 @@ void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item) S32 permission_edit_theirs_width = avatar_item->mIconPermissionEditMine->getRect().mLeft - avatar_item->mIconPermissionEditTheirs->getRect().mLeft; S32 permission_map_theirs_width = avatar_item->mIconPermissionEditTheirs->getRect().mLeft - avatar_item->mIconPermissionMapTheirs->getRect().mLeft; + S32 permission_online_theirs_width = avatar_item->mIconPermissionMapTheirs->getRect().mLeft - avatar_item->mIconPermissionOnlineTheirs->getRect().mLeft; // avatar icon width + padding @@ -685,6 +692,7 @@ void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item) S32 index = ALIC_COUNT; sChildrenWidths[--index] = icon_width; sChildrenWidths[--index] = 0; // for avatar name we don't need its width, it will be calculated as "left available space" + sChildrenWidths[--index] = permission_online_theirs_width; sChildrenWidths[--index] = permission_map_theirs_width; sChildrenWidths[--index] = permission_edit_theirs_width; sChildrenWidths[--index] = permission_edit_mine_width; @@ -794,6 +802,7 @@ bool LLAvatarListItem::refreshPermissions() mIconPermissionEditMine->setImageOverlay( (fGrantedEditMine) ? "" : strUngrantedOverlay); mIconPermissionEditTheirs->setVisible(relation->isRightGrantedFrom(LLRelationship::GRANT_MODIFY_OBJECTS)); + mIconPermissionOnlineTheirs->setVisible(relation->isRightGrantedFrom(LLRelationship::GRANT_ONLINE_STATUS)); mIconPermissionMapTheirs->setVisible(relation->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)); } else @@ -802,6 +811,7 @@ bool LLAvatarListItem::refreshPermissions() mIconPermissionMap->setVisible(false); mIconPermissionEditMine->setVisible(false); mIconPermissionEditTheirs->setVisible(false); + mIconPermissionOnlineTheirs->setVisible(false); mIconPermissionMapTheirs->setVisible(false); } @@ -841,6 +851,9 @@ LLView* LLAvatarListItem::getItemChildView(EAvatarListItemChildIndex child_view_ case ALIC_PERMISSION_MAP_THEIRS: child_view = mIconPermissionMapTheirs; break; + case ALIC_PERMISSION_ONLINE_THEIRS: + child_view = mIconPermissionOnlineTheirs; + break; case ALIC_INFO_BUTTON: child_view = mInfoBtn; break; diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 4e487e5c6eb3be3ca8783c18e509b8b625c9b169..d0c330f7c6449161665d5bd4999d159b96c74da0 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -151,6 +151,8 @@ class LLAvatarListItem final : public LLPanel, public LLFriendObserver LLIconCtrl* mIconPermissionEditTheirs = nullptr; /// Indicator for permission to show their position on the map. LLIconCtrl* mIconPermissionMapTheirs = nullptr; + /// Indicator for permission to see their online status. + LLIconCtrl* mIconPermissionOnlineTheirs = nullptr; LLIconCtrl* mIconHovered = nullptr; @@ -179,6 +181,7 @@ class LLAvatarListItem final : public LLPanel, public LLFriendObserver ALIC_PERMISSION_EDIT_MINE, ALIC_PERMISSION_EDIT_THEIRS, ALIC_PERMISSION_MAP_THEIRS, + ALIC_PERMISSION_ONLINE_THEIRS, ALIC_NAME, ALIC_ICON, ALIC_COUNT, diff --git a/indra/newview/llfloaterevent.cpp b/indra/newview/llfloaterevent.cpp index a6640cc073e672c14845b9ffa1687e083dc30324..8156f673158b45e8b93093e64ca2343d25479a1e 100644 --- a/indra/newview/llfloaterevent.cpp +++ b/indra/newview/llfloaterevent.cpp @@ -3,8 +3,9 @@ * @brief Display for events in the finder * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code + * Alchemy Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2014, Cinder Roxley @ Second Life * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,92 +28,20 @@ #include "llviewerprecompiledheaders.h" #include "llfloaterevent.h" - -#include "message.h" -#include "llnotificationsutil.h" -#include "llui.h" - -#include "llagent.h" -#include "llviewerwindow.h" -#include "llbutton.h" -#include "llcachename.h" -#include "llcommandhandler.h" // secondlife:///app/chat/ support -#include "lleventflags.h" -#include "llmediactrl.h" -#include "llexpandabletextbox.h" -#include "llfloater.h" -#include "llfloaterreg.h" -#include "llmediactrl.h" -#include "llfloaterworldmap.h" -#include "llinventorymodel.h" -#include "llslurl.h" -#include "lltextbox.h" -#include "lltexteditor.h" -#include "lluiconstants.h" -#include "llviewercontrol.h" -#include "llweb.h" -#include "llworldmap.h" -#include "llworldmapmessage.h" -#include "lluictrlfactory.h" -#include "lltrans.h" +#include "llpaneleventinfo.h" LLFloaterEvent::LLFloaterEvent(const LLSD& key) - : LLFloater(key), - LLViewerMediaObserver(), - mBrowser(NULL), - mEventID(0) -{ -} - - -LLFloaterEvent::~LLFloaterEvent() +: LLFloater(key) +, mEventId(0) { -} - - -BOOL LLFloaterEvent::postBuild() -{ - mBrowser = getChild<LLMediaCtrl>("browser"); - if (mBrowser) - { - mBrowser->addObserver(this); - } - - return TRUE; -} - -void LLFloaterEvent::handleMediaEvent(LLPluginClassMedia *self, EMediaEvent event) -{ - switch (event) - { - case MEDIA_EVENT_NAVIGATE_BEGIN: - getChild<LLUICtrl>("status_text")->setValue(getString("loading_text")); - break; - - case MEDIA_EVENT_NAVIGATE_COMPLETE: - getChild<LLUICtrl>("status_text")->setValue(getString("done_text")); - break; - - default: - break; - } + } void LLFloaterEvent::setEventID(const U32 event_id) { - mEventID = event_id; - - if (event_id != 0) - { - LLSD subs; - subs["EVENT_ID"] = (S32)event_id; - // get the search URL and expand all of the substitutions - // (also adds things like [LANGUAGE], [VERSION], [OS], etc.) - std::ostringstream url; - url << gSavedSettings.getString("EventURL") << event_id << std::endl; - // and load the URL in the web view - mBrowser->navigateTo(url.str()); - - } + mEventId = event_id; + if (event_id == 0) closeFloater(); + + getChild<LLPanel>("event_panel")->onOpen(mEventId); } diff --git a/indra/newview/llfloaterevent.h b/indra/newview/llfloaterevent.h index 1698e62a912edaa47a94fd0d7981203798e32caf..918e34d285803274f35f63d282f8d5b8817663c0 100644 --- a/indra/newview/llfloaterevent.h +++ b/indra/newview/llfloaterevent.h @@ -3,8 +3,9 @@ * @brief Display for events in the finder * * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code + * Alchemy Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2014, Cinder Roxley @ Second Life * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,35 +29,17 @@ #define LL_LLFLOATEREVENT_H #include "llfloater.h" -#include "llviewermediaobserver.h" - -class LLMediaCtrl; -class LLButton; - -class LLFloaterEvent final : public LLFloater, - public LLViewerMediaObserver +class LLFloaterEvent final : public LLFloater { public: LLFloaterEvent(const LLSD& key); - /*virtual*/ ~LLFloaterEvent(); - - /*virtual*/ BOOL postBuild(); - + /*virtual*/ ~LLFloaterEvent() = default; void setEventID(const U32 event_id); - - U32 getEventID() { return mEventID; } - - - -protected: - /*virtual*/ void handleMediaEvent(LLPluginClassMedia *self, EMediaEvent event); - U32 mEventID; - - LLMediaCtrl* mBrowser; - +private: + S32 mEventId; }; #endif // LL_LLFLOATEREVENT_H diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index ff0b79d3c75609c575ad9ffb6f3e8594f4556041..060d0b2b66ca4f079a9cd27b05ad1bf33f39b2dc 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -488,7 +488,10 @@ void LLFloaterIMNearbyChat::onChatBoxKeystroke() S32 length = raw_text.length(); - if( (length > 0) && (raw_text[0] != '/') ) // forward slash is used for escape (eg. emote) sequences + if( (length > 0) + && (raw_text[0] != '/') // forward slash is used for escape (eg. emote) sequences + && (raw_text[0] != ':') // colon is used in for MUD poses + ) { gAgent.startTyping(); } @@ -613,6 +616,8 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type ) std::string utf8_revised_text; if (0 == channel) { + applyMUPose(utf8text); + // discard returned "found" boolean if(!LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text)) { diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index ce8b67aef1dd67e4ac408baaeb7d1586135a1398..04a3c7e7f13ef64906a832cac86d1bdb40830648 100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -321,7 +321,7 @@ void LLFloaterIMSession::sendMsgFromInputEditor() { // Truncate and convert to UTF8 for transport std::string utf8_text = wstring_to_utf8str(text); - + applyMUPose(utf8_text); sendMsg(utf8_text); mInputEditor->setText(LLStringUtil::null); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 4ecc87e57a28326d88b0d728e68f81646770f416..30f1efa562e220f6ec2c3302748d3494bab69cc7 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -1181,6 +1181,30 @@ LLView* LLFloaterIMSessionTab::getChatHistory() return mChatHistory; } +// virtual +void LLFloaterIMSessionTab::applyMUPose(std::string& text) +{ + static LLCachedControl<bool> useMUPose(gSavedSettings, "AlchemyChatMUPose", false); + if (!useMUPose) + return; + + if (text.at(0) == ':' + && text.length() > 3) + { + if (text.find(":'") == 0) + { + text.replace(0, 1, "/me"); + } + // Account for emotes and smilies + else if (!isdigit(text.at(1)) + && !ispunct(text.at(1)) + && !isspace(text.at(1))) + { + text.replace(0, 1, "/me "); + } + } +} + BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask ) { BOOL handled = FALSE; diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index ba5a372df4a909ee0c5f9e27442f64e3ad973e9e..484b921021df22888edf87fced731b0fceae5710 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -146,6 +146,8 @@ class LLFloaterIMSessionTab std::string appendTime(); void assignResizeLimits(); + + virtual void applyMUPose(std::string& text); S32 mFloaterExtraWidth; diff --git a/indra/newview/llfloaterprogressview.cpp b/indra/newview/llfloaterprogressview.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50b37e748cfe2567ceb95c619937369af6e1558e --- /dev/null +++ b/indra/newview/llfloaterprogressview.cpp @@ -0,0 +1,98 @@ +/** + * @file llfloaterprogressview.cpp + * @brief Progress floater + * + * Copyright (c) 2014, Cinder Roxley <cinder@sdf.org> + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "llviewerprecompiledheaders.h" +#include "llfloaterprogressview.h" + +#include "llfloaterreg.h" +#include "llprogressbar.h" +#include "lltextbase.h" +#include "lltrans.h" + +#include "llagent.h" + +LLFloaterProgressView::LLFloaterProgressView(const LLSD& key) +: LLFloater(key) +, mProgressBar(nullptr) +, mProgressText(nullptr) +, mLocationText(nullptr) +, mCancelBtn(nullptr) +{ + mCommitCallbackRegistrar.add("cancel", boost::bind(&LLFloaterProgressView::onCommitCancel, this, _1)); +} + +LLFloaterProgressView::~LLFloaterProgressView() +{ +} + +BOOL LLFloaterProgressView::postBuild() +{ + mProgressBar = getChild<LLProgressBar>("progress_bar"); + mProgressText = getChild<LLTextBase>("progress_text"); + mLocationText = getChild<LLTextBase>("location"); + mCancelBtn = getChild<LLButton>("cancel_btn"); + return TRUE; +} + +void LLFloaterProgressView::setRegion(const std::string& region) +{ + if (region.empty()) + mLocationText->setText(getString("teleporting")); + else + { + LLStringUtil::format_map_t arg; + arg["REGION"] = region; + mLocationText->setText(getString("loc_fmt", arg)); + } +} + +void LLFloaterProgressView::setProgressText(const std::string& text) +{ + mProgressText->setValue(text); +} + +void LLFloaterProgressView::setProgressPercent(const F32 percent) +{ + mProgressBar->setValue(percent); +} + +void LLFloaterProgressView::setProgressCancelButtonVisible(BOOL visible, const std::string& label) +{ + mCancelBtn->setVisible(visible); + mCancelBtn->setEnabled(visible); + mCancelBtn->setLabelSelected(label); + mCancelBtn->setLabelUnselected(label); +} + +void LLFloaterProgressView::onCommitCancel(LLUICtrl* ctrl) +{ + gAgent.teleportCancel(); + ctrl->setEnabled(FALSE); +} diff --git a/indra/newview/llfloaterprogressview.h b/indra/newview/llfloaterprogressview.h new file mode 100644 index 0000000000000000000000000000000000000000..84ffd0ef8075343fe7522a7902fb958102a7cd44 --- /dev/null +++ b/indra/newview/llfloaterprogressview.h @@ -0,0 +1,60 @@ +/** + * @file llfloaterprogressview.h + * @brief Progress floater + * + * Copyright (c) 2014, Cinder Roxley <cinder@sdf.org> + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef LL_FLOATERPROGRESSVIEW_H +#define LL_FLOATERPROGRESSVIEW_H + +#include "llfloater.h" + +class LLButton; +class LLProgressBar; +class LLTextBase; + +class LLFloaterProgressView final : public LLFloater +{ +public: + LLFloaterProgressView(const LLSD& key); + BOOL postBuild() override; + void setProgressCancelButtonVisible(BOOL visible, const std::string& label = LLStringUtil::null); + void setProgressText(const std::string& text); + void setProgressPercent(const F32 percent); + void setRegion(const std::string& region = LLStringUtil::null); + +private: + ~LLFloaterProgressView(); + void onCommitCancel(LLUICtrl* ctrl); + + LLProgressBar* mProgressBar; + LLTextBase* mProgressText; + LLTextBase* mLocationText; + LLButton* mCancelBtn; +}; + +#endif // LL_FLOATERPROGRESSVIEW_H diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 771b8f7886bc626645203ad26282811b9e36effb..0555eb8730acf12b5d993ae45c7fc36c969a9330 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -50,6 +50,7 @@ #include "llnotificationsutil.h" #include "llcolorswatch.h" +#include "llfilepicker.h" #include "lltexturectrl.h" #include "lltextureentry.h" #include "llviewercontrol.h" // gSavedSettings @@ -720,6 +721,9 @@ BOOL LLPanelEditWearable::postBuild() mBtnBack->setClickedCallback(boost::bind(&LLPanelEditWearable::onBackButtonClicked, this)); + getChild<LLButton>("import_btn")->setClickedCallback(boost::bind(&LLPanelEditWearable::onClickedImportBtn, this)); + + mNameEditor = getChild<LLLineEditor>("description"); mPanelTitle = getChild<LLTextBox>("edit_wearable_title"); @@ -1657,6 +1661,84 @@ void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLAvatarAppearanceDefine } } +void LLPanelEditWearable::onClickedImportBtn() +{ + LLFilePicker& file_picker = LLFilePicker::instance(); + if(!file_picker.getOpenFile(LLFilePicker::FFLOAD_XML)) + { + LL_INFOS("ShapeImport") << "User closed the filepicker. Aborting!" << LL_ENDL; + return; + } + + const std::string filename = file_picker.getFirstFile(); + LLXmlTree tree; + if (!tree.parseFile(filename, FALSE)) + { + LL_WARNS("ShapeImport") << "Parsing " << filename << "failed miserably." << LL_ENDL; + LLNotificationsUtil::add("ShapeImportGenericFail", LLSD().with("FILENAME", filename)); + return; + } + LLXmlTreeNode* root = tree.getRoot(); + if (!root || !root->hasName("linden_genepool")) + { + LL_WARNS("ShapeImport") << filename << " has an invaid root node (not linden_genepool). Are you sure this is an avatar file?" << LL_ENDL; + LLNotificationsUtil::add("ShapeImportVersionFail", LLSD().with("FILENAME", filename)); + return; + } + std::string version; + static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); + if(!root->getFastAttributeString(version_string, version) || (version != "1.0") ) + { + LL_WARNS("ShapeImport") << "Invalid avatar file version: " << version << " in file: " << filename << LL_ENDL; + LLNotificationsUtil::add("ShapeImportVersionFail", LLSD().with("FILENAME", filename)); + return; + } + LLXmlTreeNode* archetype = root->getChildByName("archetype"); + if (archetype) + { + static const LLStdStringHandle id_handle = LLXmlTree::addAttributeString("id"); + static const LLStdStringHandle value_handle = LLXmlTree::addAttributeString("value"); + U32 parse_errors = 0; + + for (LLXmlTreeNode* child = archetype->getFirstChild(); child != nullptr; child = archetype->getNextChild()) + { + if (!child->hasName("param")) continue; + S32 id; + F32 value; + if (child->getFastAttributeS32(id_handle, id) + && child->getFastAttributeF32(value_handle, value)) + { + LLVisualParam* visual_param = getWearable()->getVisualParam(id); + if (visual_param) + visual_param->setWeight(value, FALSE); + } + else + { + LL_WARNS("ShapeImport") << "Failed to parse parameters in " << filename << LL_ENDL; + ++parse_errors; + } + } + if (parse_errors) + { + LLNotificationsUtil::add("ShapeImportGenericFail", LLSD().with("FILENAME", filename)); + } + if (isAgentAvatarValid()) + { + getWearable()->writeToAvatar(gAgentAvatarp); + gAgentAvatarp->updateVisualParams(); + updateScrollingPanelUI(); + LL_INFOS("ShapeImport") << "Shape import has finished with great success!" << LL_ENDL; + } + else + LL_WARNS("ShapeImport") << "Agent is not valid. Can't apply shape import changes" << LL_ENDL; + } + else + { + LL_WARNS("ShapeImport") << filename << " is missing the archetype." << LL_ENDL; + LLNotificationsUtil::add("ShapeImportGenericFail"); + } +} + // handle secondlife:///app/metricsystem class LLMetricSystemHandler : public LLCommandHandler { diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 43d6a3595fdc7eaca0e2f6934cf1b771c35b33fe..1e5d8c23f1ade5d1de6e35c8253dbc6d87bf270b 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -88,6 +88,8 @@ class LLPanelEditWearable : public LLPanel void buildParamList(LLScrollingPanelList *panel_list, value_map_t &sorted_params, LLAccordionCtrlTab *tab, LLJoint* jointp); // update bottom bar buttons ("Save", "Revert", etc) void updateVerbs(); + + void onClickedImportBtn(); void onColorSwatchCommit(const LLUICtrl*); void onTexturePickerCommit(const LLUICtrl*); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 860bf853a6578ac66f5c2788f35bdd1f5495030a..7b6d60f654c83d513e11362eaaccfdc625c64ba5 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -42,6 +42,8 @@ #include "lldrawpoolalpha.h" #include "llfeaturemanager.h" //#include "llfirstuse.h" +#include "llfloaterprogressview.h" +#include "llfloaterreg.h" #include "llhudmanager.h" #include "llimagepng.h" #include "llmemory.h" @@ -465,48 +467,49 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) gAgent.setTeleportMessage(LLStringUtil::null); } + LLFloaterProgressView* pProgFloater = LLFloaterReg::getTypedInstance<LLFloaterProgressView>("progress_view"); + const std::string& message = gAgent.getTeleportMessage(); switch( gAgent.getTeleportState() ) { case LLAgent::TELEPORT_PENDING: gTeleportDisplayTimer.reset(); - gViewerWindow->setShowProgress(TRUE); - gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); + pProgFloater->setVisible(TRUE); + pProgFloater->setProgressPercent(llmin(teleport_percent, 0.f)); gAgent.setTeleportMessage(LLAgent::sTeleportProgressMessages["pending"]); - gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["pending"]); + pProgFloater->setProgressText(LLAgent::sTeleportProgressMessages["pending"]); break; case LLAgent::TELEPORT_START: // Transition to REQUESTED. Viewer has sent some kind // of TeleportRequest to the source simulator gTeleportDisplayTimer.reset(); - gViewerWindow->setShowProgress(TRUE); - gViewerWindow->setProgressPercent(llmin(teleport_percent, 0.0f)); + pProgFloater->setVisible(TRUE); + pProgFloater->setProgressPercent(llmin(teleport_percent, 0.f)); LL_INFOS("Teleport") << "A teleport request has been sent, setting state to TELEPORT_REQUESTED" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_REQUESTED ); gAgent.setTeleportMessage( LLAgent::sTeleportProgressMessages["requesting"]); - gViewerWindow->setProgressString(LLAgent::sTeleportProgressMessages["requesting"]); - gViewerWindow->setProgressMessage(gAgent.mMOTD); + pProgFloater->setProgressText(LLAgent::sTeleportProgressMessages["requesting"]); break; case LLAgent::TELEPORT_REQUESTED: // Waiting for source simulator to respond - gViewerWindow->setProgressPercent( llmin(teleport_percent, 37.5f) ); - gViewerWindow->setProgressString(message); + pProgFloater->setProgressPercent(llmin(teleport_percent, 37.5f)); + pProgFloater->setProgressText(message); break; case LLAgent::TELEPORT_MOVING: // Viewer has received destination location from source simulator - gViewerWindow->setProgressPercent( llmin(teleport_percent, 75.f) ); - gViewerWindow->setProgressString(message); + pProgFloater->setProgressPercent(llmin(teleport_percent, 75.f)); + pProgFloater->setProgressText(message); break; case LLAgent::TELEPORT_START_ARRIVAL: // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator gTeleportArrivalTimer.reset(); - gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); - gViewerWindow->setProgressPercent(75.f); +pProgFloater->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); + pProgFloater->setProgressPercent(75.f); LL_INFOS("Teleport") << "Changing state to TELEPORT_ARRIVING" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_ARRIVING ); gAgent.setTeleportMessage( @@ -528,9 +531,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LL_INFOS("Teleport") << "arrival_fraction is " << arrival_fraction << " changing state to TELEPORT_NONE" << LL_ENDL; gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); } - gViewerWindow->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); - gViewerWindow->setProgressPercent( arrival_fraction * 25.f + 75.f); - gViewerWindow->setProgressString(message); + pProgFloater->setProgressCancelButtonVisible(FALSE, LLTrans::getString("Cancel")); + pProgFloater->setProgressPercent(arrival_fraction * 25.f + 75.f); + pProgFloater->setProgressText(message); } break; @@ -552,7 +555,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) case LLAgent::TELEPORT_NONE: // No teleport in progress - gViewerWindow->setShowProgress(FALSE); + pProgFloater->setVisible(FALSE); gTeleportDisplay = FALSE; // [SL:KB] - Patch: Appearance-TeleportAttachKill | Checked: Catznip-4.0 LLViewerParcelMgr::getInstance()->onTeleportDone(); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index af7b2fa5754811b301f5be1762863136ceeac3fc..b5fc22e9ab4b96cb76bf56ff176e07511c37021a 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -126,6 +126,7 @@ #include "llfloaterpreferenceviewadvanced.h" #include "llfloaterpreviewtrash.h" #include "llfloaterprofile.h" +#include "llfloaterprogressview.h" #include "llfloaterproperties.h" #include "llfloaterregiondebugconsole.h" #include "llfloaterregioninfo.h" @@ -424,6 +425,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("lightbox", "floater_lightbox_settings.xml", (LLFloaterBuildFunc) &LLFloaterReg::build<ALFloaterLightBox>); LLFloaterReg::add("music_ticker", "floater_music_ticker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>); LLFloaterReg::add("particle_editor", "floater_particle_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<ALFloaterParticleEditor>); + LLFloaterReg::add("progress_view", "floater_progress_view.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProgressView>); LLFloaterReg::add("quick_settings", "floater_quick_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>); LLFloaterReg::add("region_tracker", "floater_region_tracker.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<ALFloaterRegionTracker>); LLFloaterReg::add("search", "floater_directory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDirectory>); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 73fc07a77e2d61132e8bdf11e6ab7f167127e48c..b127f3edee6951a829532441b2f03f7c35ce60b1 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -56,6 +56,7 @@ #include "llpolyskeletaldistortion.h" #include "lleditingmotion.h" #include "llemote.h" +#include "llfilepicker.h" #include "llfloatertools.h" #include "llheadrotmotion.h" #include "llhudeffecttrail.h" @@ -10045,10 +10046,17 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara outprefix = std::string("new_archetype"); } std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml"); + + LLFilePicker& file_picker = LLFilePicker::instance(); + if (!file_picker.getSaveFile(LLFilePicker::FFSAVE_XML, outfilename)) + { + LL_INFOS("DumpArchetypeXML") << "User closed the filepicker" << LL_ENDL; + return; + } LLAPRFile outfile; LLWearableType *wr_inst = LLWearableType::getInstanceFast(); - std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename); + std::string fullpath = file_picker.getFirstFile(); if (APR_SUCCESS == outfile.open(fullpath, LL_APR_WB )) { apr_file_t* file = outfile.getFileHandle(); @@ -10271,6 +10279,8 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara LLNotificationsUtil::add("AppearanceToXMLFailed"); } // File will close when handle goes out of scope + LL_INFOS("DumpArchetypeXML") << "Archetype xml written successfully!" << LL_ENDL; + LLNotificationsUtil::add("DumpArchetypeSuccess", LLSD().with("FILE_PATH", fullpath)); } diff --git a/indra/newview/skins/default/xui/en/floater_event.xml b/indra/newview/skins/default/xui/en/floater_event.xml index cf61b7d24d4409b1f0db01787af31438a212681f..e12b10df3a0d0de5f99845516c227bae830c35b8 100644 --- a/indra/newview/skins/default/xui/en/floater_event.xml +++ b/indra/newview/skins/default/xui/en/floater_event.xml @@ -1,39 +1,23 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - height="400" + height="590" can_resize="true" help_topic="event_details" label="Event" layout="topleft" name="Event" - save_rect="true" save_visibility="false" - title="EVENT DETAILS" - width="600"> - <floater.string - name="loading_text"> - Loading... - </floater.string> - <floater.string - name="done_text"> - Done - </floater.string> - <web_browser - trusted_content="true" - follows="left|right|top|bottom" - layout="topleft" - left="10" - name="browser" - height="365" - width="580" - top="0"/> - <text - follows="bottom|left" - height="16" - layout="topleft" - left_delta="0" - name="status_text" - top_pad="10" - width="150" /> + title="EVENT DETAILS" + max_width="320" + width="313"> + <panel + follows="all" + name="event_panel" + top="0" + bottom="590" + left="0" + right="313" + class="panel_event_info" + filename="panel_event_info.xml" /> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_progress_view.xml b/indra/newview/skins/default/xui/en/floater_progress_view.xml new file mode 100644 index 0000000000000000000000000000000000000000..ddbb235e2688f61b1fb9e3a434e8b86374c3764f --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_progress_view.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + positioning="centered" + header_height="0" + height="90" + layout="topleft" + name="progress_view" + chrome="false" + can_resize="false" + can_close="false" + can_minimize="false" + single_instance="true" + width="420"> + <floater.string + name="loc_fmt"> +Teleporting to [REGION]... + </floater.string> + <floater.string + name="teleporting"> +Teleporting... + </floater.string> + <text + height="26" + use_ellipses="true" + type="string" + text_color="LabelTextColor" + font="SansSerifHugeBold" + length="1" + follows="top|left" + layout="topleft" + name="location" + top="6" + left="6" + right="-6" + value="[APP_NAME]" /> + <text + height="20" + use_ellipses="true" + font="SanSerifHuge" + type="string" + length="1" + follows="top|right" + layout="topleft" + name="progress_text" + top_pad="10" + left="6" + width="334" /> + <button + height="24" + label="Cancel" + left_pad="4" + name="cancel_btn" + top_delta="-4" + width="70"> + <button.commit_callback + function="cancel" /> + </button> + <progress_bar + height="16" + follows="top|left" + layout="topleft" + name="progress_bar" + top_pad="4" + left="6" + right="-6" + tool_tip="progress bar" + color_bar="EmphasisColor"/> +</floater> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index c74532d8c7c906fc4028e2eba14ea7da56f92515..473f25204526509c2353cd112e4a1add84ca99b4 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -12073,6 +12073,13 @@ Unpacking: [UNPACK_TIME]s [USIZE]KB Dice Roll: [RESULT] </notification> + <notification + icon="notify.tga" + name="DumpArchetypeSuccess" + type="notify"> + Successfully saved appearance to [FILE_PATH]. + </notification> + <notification icon="alertmodal.tga" name="InvalidGrid" @@ -12516,15 +12523,30 @@ Are you sure you wish to continue? notext="Cancel" yestext="OK"/> </notification> - - <notification - icon="notifytip.tga" - name="AlwaysRunEnabled" - persist="true" - log_to_chat="true" - type="notifytip"> + + <notification + icon="notifytip.tga" + name="ShapeImportGenericFail" + type="notifytip"> + <tag>fail</tag> + There was a problem importing [FILENAME]. Please see the log for more details. + </notification> + <notification + icon="notifytip.tga" + name="ShapeImportVersionFail" + type="notifytip"> + <tag>fail</tag> + Shape import failed. Are you sure [FILENAME] is an avatar genepool file? + </notification> + + <notification + icon="notifytip.tga" + name="AlwaysRunEnabled" + persist="true" + log_to_chat="true" + type="notifytip"> Always Run enabled. - </notification> + </notification> <notification icon="notifytip.tga" name="AlwaysRunDisabled" diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index 1bd984652aa445ab1d616ba16d5d2f689e2e1a8e..7428b8d5412a733e0b8da1cbdbd0a70a38bba776 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -65,6 +65,18 @@ use_ellipses="true" value="(loading)" width="180" /> + <icon + enabled="false" + height="16" + follows="right" + image_name="Permission_Visible_Them_Online" + layout="topleft" + left_pad="3" + right="-215" + name="permission_online_theirs_icon" + tool_tip="You can see when this friend is online" + top="4" + width="16" /> <icon enabled="false" height="16" diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index 078b9c1384861e6e823248184360bbf78df6f3c0..add76c9c27ddb5b9aea3f627848fb4da12001681 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -471,7 +471,7 @@ mouse_opaque="false" name="save_as_btn_lp" auto_resize="true" - width="154"> + width="151"> <button follows="bottom|left|right" height="23" @@ -480,17 +480,17 @@ left="1" name="save_as_button" top="0" - width="153" /> + width="148" /> </layout_panel> <layout_panel follows="bottom|left|right" height="23" layout="bottomleft" - left_pad="3" + left="0" mouse_opaque="false" name="revert_btn_lp" auto_resize="true" - width="152"> + width="151"> <button follows="bottom|left|right" height="23" @@ -501,6 +501,25 @@ top="0" width="148" /> </layout_panel> + <layout_panel + follows="bottom|left|right" + height="23" + layout="bottomleft" + left="0" + mouse_opaque="false" + name="import_btn_lp" + auto_resize="true" + width="151"> + <button + follows="bottom|left|right" + height="23" + label="Import" + layout="topleft" + left="1" + name="import_btn" + top="0" + width="148" /> + </layout_panel> </layout_stack> </panel> </panel>