diff --git a/doc/contributions.txt b/doc/contributions.txt index c33562839103a525883f27a82f7d4fd7a2d79cf6..bebe715e87b258b308377d72ddd85084c92f718c 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1188,6 +1188,7 @@ PanteraPolnocy SL-18891 SL-18904 SL-18937 + SL-19681 Parvati Silverweb Patric Mills VWR-2645 @@ -1413,6 +1414,7 @@ Sovereign Engineer SL-18525 SL-18534 SL-19690 + SL-19336 SpacedOut Frye VWR-34 VWR-45 diff --git a/indra/deps/CMakeLists.txt b/indra/deps/CMakeLists.txt index 1f361f7475fa24cc3fa9f2978a28932d38e412bc..59fc2851117e7208fb76522602d4eac9afbfe76a 100644 --- a/indra/deps/CMakeLists.txt +++ b/indra/deps/CMakeLists.txt @@ -37,7 +37,7 @@ FetchContent_Declare( FetchContent_Declare( fmt GIT_REPOSITORY https://github.com/fmtlib/fmt.git - GIT_TAG 9.1.0 + GIT_TAG 10.0.0 GIT_SHALLOW TRUE GIT_PROGRESS TRUE ) @@ -79,7 +79,7 @@ if(USE_NFD) FetchContent_Declare( nfd GIT_REPOSITORY https://github.com/btzy/nativefiledialog-extended.git - GIT_TAG v1.0.3 + GIT_TAG v1.1.0 ) set(NFD_PORTAL ON) diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index 76925160e06a4ad1b2f9e0909118b0e3dd78127f..f4ab12fe2304bddb3c3870e41741c51b59f790bf 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -1145,6 +1145,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo // get number of joint motions //------------------------------------------------------------------------- U32 num_motions = 0; + S32 rotation_dupplicates = 0; + S32 position_dupplicates = 0; if (!dp.unpackU32(num_motions, "num_joints")) { LL_WARNS() << "can't read number of joints" @@ -1376,6 +1378,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo std::sort(rCurve->mKeys.begin(), rCurve->mKeys.end(), [](const auto& a, const auto& b) { return a.first < b.first; }); + if (joint_motion->mRotationCurve.mNumKeys > joint_motion->mRotationCurve.mKeys.size()) + { + rotation_dupplicates++; + LL_INFOS() << "Motion: " << asset_id << " had dupplicate rotation keys that were removed" << LL_ENDL; + } + //--------------------------------------------------------------------- // scan position curve header //--------------------------------------------------------------------- @@ -1480,9 +1488,24 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo std::sort(pCurve->mKeys.begin(), pCurve->mKeys.end(), [](const auto& a, const auto& b) { return a.first < b.first; }); + if (joint_motion->mPositionCurve.mNumKeys > joint_motion->mPositionCurve.mKeys.size()) + { + position_dupplicates++; + } + joint_motion->mUsage = joint_state->getUsage(); } + if (rotation_dupplicates > 0) + { + LL_INFOS() << "Motion: " << asset_id << " had " << rotation_dupplicates << " dupplicate rotation keys that were removed" << LL_ENDL; + } + + if (position_dupplicates > 0) + { + LL_INFOS() << "Motion: " << asset_id << " had " << position_dupplicates << " dupplicate position keys that were removed" << LL_ENDL; + } + //------------------------------------------------------------------------- // get number of constraints //------------------------------------------------------------------------- @@ -1762,10 +1785,13 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const JointMotion* joint_motionp = mJointMotionList->getJointMotion(i); success &= dp.packString(joint_motionp->mJointName, "joint_name"); success &= dp.packS32(joint_motionp->mPriority, "joint_priority"); - success &= dp.packS32(joint_motionp->mRotationCurve.mNumKeys, "num_rot_keys"); + success &= dp.packS32(joint_motionp->mRotationCurve.mKeys.size(), "num_rot_keys"); - LL_DEBUGS("BVH") << "Joint " << joint_motionp->mJointName << LL_ENDL; - for (RotationCurve::key_map_t::value_type& rot_pair : joint_motionp->mRotationCurve.mKeys) + LL_DEBUGS("BVH") << "Joint " << i + << " name: " << joint_motionp->mJointName + << " Rotation keys: " << joint_motionp->mRotationCurve.mKeys.size() + << " Position keys: " << joint_motionp->mPositionCurve.mKeys.size() << LL_ENDL; + for (RotationCurve::key_map_t::value_type& rot_pair : joint_motionp->mRotationCurve.mKeys) { RotationKey& rot_key = rot_pair.second; U16 time_short = F32_to_U16(rot_key.mTime, 0.f, mJointMotionList->mDuration); @@ -1785,7 +1811,7 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const LL_DEBUGS("BVH") << " rot: t " << rot_key.mTime << " angles " << rot_angles.mV[VX] <<","<< rot_angles.mV[VY] <<","<< rot_angles.mV[VZ] << LL_ENDL; } - success &= dp.packS32(joint_motionp->mPositionCurve.mNumKeys, "num_pos_keys"); + success &= dp.packS32(joint_motionp->mPositionCurve.mKeys.size(), "num_pos_keys"); for (PositionCurve::key_map_t::value_type& pos_pair : joint_motionp->mPositionCurve.mKeys) { PositionKey& pos_key = pos_pair.second; diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index c90d8f24c810b64561dde49c9b120eb76dcec679..c7e34b83f05e805c460d0d4c7f8aa8611729af88 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -42,7 +42,6 @@ set(llcommon_SOURCE_FILES lldependencies.cpp lldictionary.cpp llerror.cpp - llerrorthread.cpp llevent.cpp lleventapi.cpp lleventcoro.cpp @@ -154,7 +153,6 @@ set(llcommon_HEADER_FILES llendianswizzle.h llerror.h llerrorcontrol.h - llerrorthread.h llevent.h lleventapi.h lleventcoro.h diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index dee10cadf9514999ba989a76452a6f3f6c3ca097..b4da4a437d685ef65eed4ecb8cbdf5a8a4d6d653 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -39,7 +39,6 @@ #include "llcommon.h" #include "llapr.h" #include "llerrorcontrol.h" -#include "llerrorthread.h" #include "llframetimer.h" #include "lllivefile.h" #include "llmemory.h" @@ -100,12 +99,7 @@ LLAppErrorHandler LLApp::sErrorHandler = NULL; BOOL LLApp::sErrorThreadRunning = FALSE; -LLApp::LLApp() : mThreadErrorp(NULL) -{ - commonCtor(); -} - -void LLApp::commonCtor() +LLApp::LLApp() { assert_main_thread(); // Make sure we record the main thread on_main_thread(); // Make sure we record the main thread @@ -133,12 +127,6 @@ void LLApp::commonCtor() sApplication = this; } -LLApp::LLApp(LLErrorThread *error_thread) : - mThreadErrorp(error_thread) -{ - commonCtor(); -} - LLApp::~LLApp() { @@ -148,13 +136,6 @@ LLApp::~LLApp() mLiveFiles.clear(); setStopped(); - // HACK: wait for the error thread to clean itself - ms_sleep(20); - if (mThreadErrorp) - { - delete mThreadErrorp; - mThreadErrorp = NULL; - } SUBSYSTEM_CLEANUP_DBG(LLCommon); } @@ -374,43 +355,17 @@ void LLApp::setupErrorHandling(bool second_instance) #if defined(LL_WINDOWS) -#if LL_SEND_CRASH_REPORTS && ! defined(AL_SENTRY) - EnableCrashingOnCrashes(); - - // This sets a callback to handle w32 signals to the console window. - // The viewer shouldn't be affected, sicne its a windowed app. - SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE); -#endif // LL_SEND_CRASH_REPORTS && ! defined(AL_SENTRY) #else // ! LL_WINDOWS // +#if ! defined(AL_SENTRY) // Start up signal handling. // // There are two different classes of signals. Synchronous signals are delivered to a specific // thread, asynchronous signals can be delivered to any thread (in theory) // setup_signals(); +#endif // ! AL_SENTRY #endif // ! LL_WINDOWS - -#if defined(AL_SENTRY) - // do not start our own error thread -#else // ! AL_SENTRY - startErrorThread(); -#endif -} - -void LLApp::startErrorThread() -{ - // - // Start the error handling thread, which is responsible for taking action - // when the app goes into the APP_STATUS_ERROR state - // - if(!mThreadErrorp) - { - LL_INFOS() << "Starting error thread" << LL_ENDL; - mThreadErrorp = new LLErrorThread(); - mThreadErrorp->setUserData((void *) this); - mThreadErrorp->start(); - } } void LLApp::setErrorHandler(LLAppErrorHandler handler) @@ -473,7 +428,7 @@ void LLApp::setStatus(EAppStatus status) // static void LLApp::setError() { - // set app status to ERROR so that the LLErrorThread notices + // set app status to ERROR setStatus(APP_STATUS_ERROR); } diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 80288e1d82d8ea9b15fa57b7578497f4f9e43240..8d426b9abc20f01d458fb526d304137b9d5a5f76 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -34,7 +34,6 @@ #include <atomic> #include <chrono> // Forward declarations -class LLErrorThread; class LLLiveFile; #if LL_LINUX #include <signal.h> @@ -53,7 +52,6 @@ void clear_signals(); class LL_COMMON_API LLApp { - friend class LLErrorThread; public: typedef enum e_app_status { @@ -67,11 +65,6 @@ class LL_COMMON_API LLApp LLApp(); virtual ~LLApp(); -protected: - LLApp(LLErrorThread* error_thread); - void commonCtor(); -public: - /** * @brief Return the static app instance if one was created. */ @@ -257,14 +250,14 @@ class LL_COMMON_API LLApp void setupErrorHandling(bool mSecondInstance=false); void setErrorHandler(LLAppErrorHandler handler); - static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. + static void runErrorHandler(); // run shortly after we detect an error //@} - + // the maximum length of the minidump filename returned by getMiniDumpFilename() static const U32 MAX_MINDUMP_PATH_LENGTH = 256; // change the directory where Breakpad minidump files are written to - void setDebugFileNames(const std::string &path); + void setDebugFileNames(const std::string &path); // Return the Google Breakpad minidump filename after a crash. std::string* getStaticDebugFile() { return &mStaticDebugFileName; } @@ -300,10 +293,8 @@ class LL_COMMON_API LLApp void stepFrame(); private: - void startErrorThread(); - - std::string mStaticDebugFileName; - std::string mDynamicDebugFileName; + std::string mStaticDebugFileName; + std::string mDynamicDebugFileName; // *NOTE: On Windows, we need a routine to reset the structured // exception handler when some evil driver has taken it over for @@ -311,9 +302,6 @@ class LL_COMMON_API LLApp typedef int(*signal_handler_func)(int signum); static LLAppErrorHandler sErrorHandler; - // Default application threads - LLErrorThread* mThreadErrorp; // Waits for app to go to status ERROR, then runs the error callback - // This is the application level runnable scheduler. LLRunner mRunner; diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index fcfa569ccf193339485fd5aa97946c1734e44a21..4342d2a695e9ad5b63b677311facc76ba04f02f6 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -276,7 +276,6 @@ namespace LLError // used to indicate no class info known for logging //LLCallStacks keeps track of call stacks and output the call stacks to log file - //when LLAppViewer::handleViewerCrash() is triggered. // //Note: to be simple, efficient and necessary to keep track of correct call stacks, //LLCallStacks is designed not to be thread-safe. diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp deleted file mode 100644 index a20253bf45c5c28f8727f1291199a1c3e4ba37a2..0000000000000000000000000000000000000000 --- a/indra/llcommon/llerrorthread.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @file llerrorthread.cpp - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llerrorthread.h" - -#include "llapp.h" -#include "lltimer.h" // ms_sleep() - -LLErrorThread::LLErrorThread() - : LLThread("Error"), - mUserDatap(NULL) -{ -} - -void LLErrorThread::setUserData(void* user_data) -{ - mUserDatap = user_data; -} - - -void* LLErrorThread::getUserData() const -{ - return mUserDatap; -} - -#if !LL_WINDOWS -// -// Various signal/error handling functions that can't be put into the class -// -void get_child_status(const int waitpid_status, int &process_status, bool &exited, bool do_logging) -{ - exited = false; - process_status = -1; - // The child process exited. Call its callback, and then clean it up - if (WIFEXITED(waitpid_status)) - { - process_status = WEXITSTATUS(waitpid_status); - exited = true; - if (do_logging) - { - LL_INFOS() << "get_child_status - Child exited cleanly with return of " << process_status << LL_ENDL; - } - return; - } - else if (WIFSIGNALED(waitpid_status)) - { - process_status = WTERMSIG(waitpid_status); - exited = true; - if (do_logging) - { - LL_INFOS() << "get_child_status - Child died because of uncaught signal " << process_status << LL_ENDL; -#ifdef WCOREDUMP - if (WCOREDUMP(waitpid_status)) - { - LL_INFOS() << "get_child_status - Child dumped core" << LL_ENDL; - } - else - { - LL_INFOS() << "get_child_status - Child didn't dump core" << LL_ENDL; - } -#endif - } - return; - } - else if (do_logging) - { - // This is weird. I just dump the waitpid status into the status code, - // not that there's any way of telling what it is... - LL_INFOS() << "get_child_status - Got SIGCHILD but child didn't exit" << LL_ENDL; - process_status = waitpid_status; - } - -} -#endif - -void LLErrorThread::run() -{ - LLApp::sErrorThreadRunning = TRUE; - // This thread sits and waits for the sole purpose - // of waiting for the signal/exception handlers to flag the - // application state as APP_STATUS_ERROR. - //LL_INFOS() << "thread_error - Waiting for an error" << LL_ENDL; - - while (! (LLApp::isError() || LLApp::isStopped())) - { - ms_sleep(10); - } - if (LLApp::isError()) - { - // The app is in an error state, run the application's error handler. - //LL_INFOS() << "thread_error - An error has occurred, running error callback!" << LL_ENDL; - // Run the error handling callback - LLApp::runErrorHandler(); - } - else - { - // Everything is okay, a clean exit. - //LL_INFOS() << "thread_error - Application exited cleanly" << LL_ENDL; - } - - //LL_INFOS() << "thread_error - Exiting" << LL_ENDL; - LLApp::sErrorThreadRunning = FALSE; -} - diff --git a/indra/llcommon/llerrorthread.h b/indra/llcommon/llerrorthread.h deleted file mode 100644 index 037fce7e3f7975516ce9e3c9f62e34d5173dafdc..0000000000000000000000000000000000000000 --- a/indra/llcommon/llerrorthread.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file llerrorthread.h - * @brief Specialized thread to handle runtime errors. - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLERRORTHREAD_H -#define LL_LLERRORTHREAD_H - -#include "llthread.h" - -class LL_COMMON_API LLErrorThread final : public LLThread -{ -public: - LLErrorThread(); - ~LLErrorThread() = default; - - /*virtual*/ void run(void); - void setUserData(void *user_data); - void *getUserData() const; - -protected: - void* mUserDatap; // User data associated with this thread -}; - -#endif // LL_LLERRORTHREAD_H diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 536e66de24270f82e34bb2e06456c0d6f38317db..366ce79381411c0b3e1331a39345ed6c066b4142 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -553,7 +553,9 @@ std::string LLCacheName::buildUsername(const std::string& full_name) // if the input wasn't a correctly formatted legacy name, just return it // cleaned up from a potential terminal "Resident" - return cleanFullName(full_name); + std::string clean_name = cleanFullName(full_name); + LLStringUtil::toLower(clean_name); + return clean_name; } //static diff --git a/indra/llprimitive/llmaterial.cpp b/indra/llprimitive/llmaterial.cpp index ac968fe496e82c39a1b45b2862067c74ab2fcb3a..7de38af7d0bd51183f11c1ea21b5d35b8fbd54f0 100644 --- a/indra/llprimitive/llmaterial.cpp +++ b/indra/llprimitive/llmaterial.cpp @@ -438,18 +438,18 @@ bool LLMaterial::operator != (const LLMaterial& rhs) const } -U32 LLMaterial::getShaderMask(U32 alpha_mode) +U32 LLMaterial::getShaderMask(U32 alpha_mode, BOOL is_alpha) { //NEVER incorporate this value into the message system -- this function will vary depending on viewer implementation - U32 ret = 0; - //two least significant bits are "diffuse alpha mode" - if (alpha_mode != DIFFUSE_ALPHA_MODE_DEFAULT) + //two least significant bits are "diffuse alpha mode" + U32 ret = alpha_mode; + if (ret == DIFFUSE_ALPHA_MODE_DEFAULT) { - ret = alpha_mode; - } - else - { - ret = getDiffuseAlphaMode(); + ret = getDiffuseAlphaMode(); + if (ret == DIFFUSE_ALPHA_MODE_BLEND && !is_alpha) + { + ret = DIFFUSE_ALPHA_MODE_NONE; + } } llassert(ret < SHADER_COUNT); diff --git a/indra/llprimitive/llmaterial.h b/indra/llprimitive/llmaterial.h index 5d3f4abf2793ab6477e7ef7ceb37430fe90440e3..0adaa6b62c1cee1ed8eec19d473eeca750b5621d 100644 --- a/indra/llprimitive/llmaterial.h +++ b/indra/llprimitive/llmaterial.h @@ -124,7 +124,7 @@ class LLMaterial final : public LLRefCount bool operator == (const LLMaterial& rhs) const; bool operator != (const LLMaterial& rhs) const; - U32 getShaderMask(U32 alpha_mode = DIFFUSE_ALPHA_MODE_DEFAULT); + U32 getShaderMask(U32 alpha_mode, BOOL is_alpha); LLUUID getHash() const; protected: diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 78a6fab0cb91bda8c593ef53dab30dccad0fe3ad..d7e9ed10dd0e56f7eaa82541239799e05bbfe4bf 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -491,7 +491,7 @@ F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max return getWidthF32(wtext.c_str(), begin_offset, max_chars); } -F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars) const +F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars, bool no_padding) const { const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL; @@ -514,12 +514,15 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars F32 advance = mFontFreetype->getXAdvance(fgi); - // for the last character we want to measure the greater of its width and xadvance values - // so keep track of the difference between these values for the each character we measure - // so we can fix things up at the end - width_padding = llmax( 0.f, // always use positive padding amount - width_padding - advance, // previous padding left over after advance of current character - (F32)(fgi->mWidth + fgi->mXBearing) - advance); // difference between width of this character and advance to next character + if (!no_padding) + { + // for the last character we want to measure the greater of its width and xadvance values + // so keep track of the difference between these values for the each character we measure + // so we can fix things up at the end + width_padding = llmax(0.f, // always use positive padding amount + width_padding - advance, // previous padding left over after advance of current character + (F32)(fgi->mWidth + fgi->mXBearing) - advance); // difference between width of this character and advance to next character + } cur_x += advance; llwchar next_char = wchars[i+1]; @@ -536,8 +539,11 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars cur_x = (F32)ll_round(cur_x); } - // add in extra pixels for last character's width past its xadvance - cur_x += width_padding; + if (!no_padding) + { + // add in extra pixels for last character's width past its xadvance + cur_x += width_padding; + } return cur_x / sScaleX; } diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index f7461af3dfbb6c7afeccb731c8b50de5f2323649..7d815bf9b56510b891838dd6fe1c6e90236c1d31 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -138,7 +138,7 @@ class LLFontGL F32 getWidthF32(const std::string& utf8text) const; F32 getWidthF32(const llwchar* wchars) const; F32 getWidthF32(const std::string& text, S32 offset, S32 max_chars ) const; - F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars) const; + F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars, bool no_padding = false) const; // The following are called often, frequently with large buffers, so do not use a string interface diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index af9360cf08d8b88cd540047fa43cd6dac4d73cf7..1df1e48d6a8f8d98e1f344ccbb426777c370ef21 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -903,10 +903,17 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32 { stop_glerror(); - if (prev_mip_data != cur_mip_data) - delete[] prev_mip_data; + if (prev_mip_data) + { + if (prev_mip_data != cur_mip_data) + delete[] prev_mip_data; + prev_mip_data = nullptr; + } if (cur_mip_data) + { delete[] cur_mip_data; + cur_mip_data = nullptr; + } mGLTextureCreated = false; return FALSE; diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index dad94168f1d3aeca23c7b9938601609018b772e7..3b476c683132e25ba0e1ab652797b98ee48af471 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -283,6 +283,17 @@ void LLLayoutStack::draw() } } +void LLLayoutStack::deleteAllChildren() +{ + mPanels.clear(); + LLView::deleteAllChildren(); + + // Not really needed since nothing is left to + // display, but for the sake of consistency + updateFractionalSizes(); + mNeedsLayout = true; +} + void LLLayoutStack::removeChild(LLView* view) { LLLayoutPanel* embedded_panelp = findEmbeddedPanel(dynamic_cast<LLPanel*>(view)); @@ -290,12 +301,14 @@ void LLLayoutStack::removeChild(LLView* view) if (embedded_panelp) { mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp)); - delete embedded_panelp; + LLView::removeChild(view); updateFractionalSizes(); mNeedsLayout = true; } - - LLView::removeChild(view); + else + { + LLView::removeChild(view); + } } BOOL LLLayoutStack::postBuild() diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 1227acd0339980801dfd13017f3ab5ea001565e0..b0b06059e1ad0d1df88886c91583b8b36e964238 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -67,6 +67,7 @@ class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack> virtual ~LLLayoutStack(); /*virtual*/ void draw(); + /*virtual*/ void deleteAllChildren(); /*virtual*/ void removeChild(LLView*); /*virtual*/ BOOL postBuild(); /*virtual*/ bool addChild(LLView* child, S32 tab_group = 0); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index c6eb6b12d1be30adfb21e05e654beae11511d4f5..423adea3b916c9019aadca044020fcde1066a6b0 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1903,6 +1903,13 @@ bool LLMenuGL::addContextChild(LLView* view, S32 tab_group) return false; } + +void LLMenuGL::deleteAllChildren() +{ + mItems.clear(); + LLUICtrl::deleteAllChildren(); +} + void LLMenuGL::removeChild( LLView* ctrl) { // previously a dynamic_cast with if statement to check validity diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 43c1d218a0a5ff3120082456f887a2a5db4fa5ae..2a81bacd31846a8f9748dff5a7327fa182d8fb30 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -451,6 +451,7 @@ class LLMenuGL /*virtual*/ void drawBackground(LLMenuItemGL* itemp, F32 alpha); /*virtual*/ void setVisible(BOOL visible); /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); + /*virtual*/ void deleteAllChildren(); /*virtual*/ void removeChild( LLView* ctrl); /*virtual*/ BOOL postBuild(); diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index 3e026b7d752bfb4d64185cadc917c865c7bce466..474fa687a782f78bbba6b37427851611978aa5f4 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -128,6 +128,7 @@ class LLPanel : public LLUICtrl, public LLBadgeHolder virtual void clearCtrls(); // overridden in LLPanelObject and LLPanelVolume // Border controls + const LLViewBorder* getBorder() const { return mBorder; } void addBorder( LLViewBorder::Params p); void addBorder(); void removeBorder(); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 071ceb39395d78ebb0d0db5b84eaf5b6ffadf69d..b5214eef7108f1391ab6792ae6beb7009d4ef43f 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -378,7 +378,7 @@ void LLTextBase::onValueChange(S32 start, S32 end) { } -std::vector<LLRect> LLTextBase::getSelctionRects(const highlight_list_t& highlights) +std::vector<LLRect> LLTextBase::getSelectionRects(const highlight_list_t& highlights) { // Nor supposed to be called without selection llassert(hasSelection()); @@ -518,7 +518,7 @@ void LLTextBase::drawHighlightsBackground(const highlight_list_t& highlights, co if (!mLineInfoList.empty()) // [/SL:KB] { - std::vector<LLRect> selection_rects = getSelctionRects(highlights); + std::vector<LLRect> selection_rects = getSelectionRects(highlights); // Draw the selection box (we're using a box instead of reversing the colors on the selected text). gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -3674,7 +3674,7 @@ bool LLNormalTextSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& w height = mFontHeight; const LLWString &text = getWText(); // if last character is a newline, then return true, forcing line break - width = mStyle->getFont()->getWidthF32(text.c_str(), mStart + first_char, num_chars); + width = mStyle->getFont()->getWidthF32(text.c_str(), mStart + first_char, num_chars, true); } return false; } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index a064ea64e277343fc7087367abf4ccb0598969f4..6e66192c3ad70eb89c2c2f9393ca66f9e3db93f1 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -680,7 +680,7 @@ class LLTextBase public: bool hasSelection() const { return (mSelectionStart !=mSelectionEnd); } - std::vector<LLRect> getSelctionRects(const highlight_list_t& highlights); + std::vector<LLRect> getSelectionRects(const highlight_list_t& highlights); protected: // text segmentation and flow diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 4fede1ed02502d43d68478e31a36a868547a2a18..584825d4e920f30f6d0146156323fe673a985910 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -174,7 +174,8 @@ void LLTextBox::reshapeToFitText(BOOL called_from_parent) S32 width = getTextPixelWidth(); S32 height = getTextPixelHeight(); - reshape( width + 2 * mHPad, height + 2 * mVPad, called_from_parent ); + //consider investigating reflow() to find missing width pixel (see SL-17045 changes) + reshape( width + 2 * mHPad + 1, height + 2 * mVPad, called_from_parent ); } diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp index dfff572dbac37ee12ed5f991910d13850d02193d..87d76e84cec0406a430d092f44d6edfe11190b4f 100644 --- a/indra/llui/lluicolortable.cpp +++ b/indra/llui/lluicolortable.cpp @@ -199,7 +199,6 @@ LLUIColor LLUIColorTable::getColor(std::string_view name, const LLColor4& defaul void LLUIColorTable::setColor(std::string_view name, const LLColor4& color) { setColor(name, color, mUserSetColors); - setColor(name, color, mLoadedColors); } bool LLUIColorTable::loadFromSettings() @@ -226,6 +225,11 @@ void LLUIColorTable::saveUserSettings(const bool scrub /* = false */) const for (const auto& color_pair : mUserSetColors) { + // Compare user color value with the default value, skip if equal + string_color_map_t::const_iterator itd = mLoadedColors.find(color_pair.first); + if(itd != mLoadedColors.end() && itd->second == color_pair.second) + continue; + if (!scrub || color_pair.first.find("ColorPaletteEntry") != std::string::npos) { ColorEntryParams color_entry; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index a53c95242eb680967214c7ef11d8996439cc9cee..7bb6432153883c331a6aacb87a5409d1826e846b 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -576,8 +576,10 @@ void LLView::deleteAllChildren() while (!mChildList.empty()) { - LLView* viewp = mChildList.front(); - delete viewp; // will remove the child from mChildList + LLView* viewp = mChildList.front(); + viewp->mParentView = NULL; + delete viewp; + mChildList.pop_front(); } } diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index a079a92227bc330a928a660c391e932781387040..eae43221b514247e3fe69613bcd0f0c07098fd50 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -118,7 +118,8 @@ class LLWindow : public LLInstanceTracker<LLWindow> // Sets cursor, may set to arrow+hourglass virtual void setCursor(ECursorType cursor) { mNextCursor = cursor; }; - virtual ECursorType getCursor() const; + virtual ECursorType getCursor() const; + virtual ECursorType getNextCursor() const { return mNextCursor; }; virtual void updateCursor() = 0; virtual void captureMouse() = 0; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index fb4dbc2cc0b413a8b4417bdad9a62f590805d450..611b0bee49db39b47915bf76b7784ec0869ba8c0 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13659,13 +13659,13 @@ <key>TranslationService</key> <map> <key>Comment</key> - <string>Translation API to use. (google|bing)</string> + <string>Translation API to use. (google|azure)</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>String</string> <key>Value</key> - <string>bing</string> + <string>azure</string> </map> <key>GoogleTranslateAPIKey</key> <map> @@ -13681,7 +13681,7 @@ <key>BingTranslateAPIKey</key> <map> <key>Comment</key> - <string>Bing AppID to use with the Microsoft Translator API</string> + <string>(Deprecated) Bing AppID to use with the Microsoft Translator API</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -13689,6 +13689,28 @@ <key>Value</key> <string></string> </map> + <key>AzureTranslateAPIKey</key> + <map> + <key>Comment</key> + <string>Azure Translation service data to use with the MS Azure Translator API</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>LLSD</string> + <key>Value</key> + <string></string> + </map> + <key>DeepLTranslateAPIKey</key> + <map> + <key>Comment</key> + <string>DeepL Translation service data to use with the DeepL Translator API</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>LLSD</string> + <key>Value</key> + <string></string> + </map> <key>TutorialURL</key> <map> <key>Comment</key> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 1003008ba2a21bef2c5bc1c7ce6f4afa9c578bca..c2293e66aa1878034869cc0ee61559ec41132824 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3607,149 +3607,6 @@ void LLAppViewer::writeSystemInfo() writeDebugInfo(); // Save out debug_info.log early, in case of crash. } -void LLAppViewer::handleViewerCrash() -{ - LL_INFOS("CRASHREPORT") << "Handle viewer crash entry." << LL_ENDL; - - LL_INFOS("CRASHREPORT") << "Last render pool type: " << LLPipeline::sCurRenderPoolType << LL_ENDL ; - - LLMemory::logMemoryInfo(true) ; - - //print out recorded call stacks if there are any. - LLError::LLCallStacks::print(); - - LLAppViewer* pApp = LLAppViewer::instance(); - if (pApp->beingDebugged()) - { - // This will drop us into the debugger. - abort(); - } - - if (LLApp::isCrashloggerDisabled()) - { - abort(); - } - - // Returns whether a dialog was shown. - // Only do the logic in here once - if (pApp->mReportedCrash) - { - return; - } - pApp->mReportedCrash = TRUE; - - // Insert crash host url (url to post crash log to) if configured. - std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl"); - if(crashHostUrl != "") - { - gDebugInfo["Dynamic"]["CrashHostUrl"] = crashHostUrl; - } - - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if ( parcel && parcel->getMusicURL()[0]) - { - gDebugInfo["Dynamic"]["ParcelMusicURL"] = parcel->getMusicURL(); - } - if ( parcel && parcel->getMediaURL()[0]) - { - gDebugInfo["Dynamic"]["ParcelMediaURL"] = parcel->getMediaURL(); - } - - gDebugInfo["Dynamic"]["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds()); - gDebugInfo["Dynamic"]["RAMInfo"]["Allocated"] = LLSD::Integer(LLMemory::getCurrentRSS() / 1024); - - if(gLogoutInProgress) - { - gDebugInfo["Dynamic"]["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH; - } - else - { - gDebugInfo["Dynamic"]["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH; - } - - if(gAgent.getRegion()) - { - gDebugInfo["Dynamic"]["CurrentSimHost"] = gAgent.getRegion()->getSimHostName(); - gDebugInfo["Dynamic"]["CurrentRegion"] = gAgent.getRegion()->getName(); - - const LLVector3& loc = gAgent.getPositionAgent(); - gDebugInfo["Dynamic"]["CurrentLocationX"] = loc.mV[0]; - gDebugInfo["Dynamic"]["CurrentLocationY"] = loc.mV[1]; - gDebugInfo["Dynamic"]["CurrentLocationZ"] = loc.mV[2]; - } - - if(LLAppViewer::instance()->mMainloopTimeout) - { - gDebugInfo["Dynamic"]["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState(); - } - - // The crash is being handled here so set this value to false. - // Otherwise the crash logger will think this crash was a freeze. - gDebugInfo["Dynamic"]["CrashNotHandled"] = LLSD::Boolean(false); - - //Write out the crash status file - //Use marker file style setup, as that's the simplest, especially since - //we're already in a crash situation - if (gDirUtilp) - { - std::string crash_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, - gLLErrorActivated - ? LLERROR_MARKER_FILE_NAME - : ERROR_MARKER_FILE_NAME); - LLAPRFile crash_marker_file ; - crash_marker_file.open(crash_marker_file_name, LL_APR_WB); - if (crash_marker_file.getFileHandle()) - { - LL_INFOS("MarkerFile") << "Created crash marker file " << crash_marker_file_name << LL_ENDL; - recordMarkerVersion(crash_marker_file); - } - else - { - LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_marker_file_name << LL_ENDL; - } - } - else - { - LL_WARNS("MarkerFile") << "No gDirUtilp with which to create error marker file name" << LL_ENDL; - } - -#ifdef LL_WINDOWS - Sleep(200); -#endif - - gDebugInfo["Dynamic"]["CrashType"]="crash"; - - if (gMessageSystem && gDirUtilp) - { - std::string filename; - filename = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "stats.log"); - LL_DEBUGS("CRASHREPORT") << "recording stats " << filename << LL_ENDL; - llofstream file(filename.c_str(), std::ios_base::binary); - if(file.good()) - { - gMessageSystem->summarizeLogs(file); - file.close(); - } - else - { - LL_WARNS("CRASHREPORT") << "problem recording stats" << LL_ENDL; - } - } - - if (gMessageSystem) - { - gMessageSystem->getCircuitInfo(gDebugInfo["CircuitInfo"]); - gMessageSystem->stopLogging(); - } - - if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]); - - gDebugInfo["FatalMessage"] = LLError::getFatalMessage(); - - // Close the debug file - pApp->writeDebugInfo(false); //false answers the isStatic question with the least overhead. -} - // static void LLAppViewer::recordMarkerVersion(LLAPRFile& marker_file) { diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 03a783d7e59cc4e2a0a8da8433b69cc5b620dd02..4cb7439198560343051479c6a8b14caeac7fbc3a 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -115,7 +115,6 @@ class LLAppViewer : public LLApp virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism. // return false if the error trap needed restoration. virtual void initCrashReporting(bool reportFreeze = false) = 0; // What to do with crash report? - static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon. void checkForCrash(); // Thread accessors diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 510f5bcc095f6aab5da1803e0273ec98abb16772..8dc9f533ef8767cc15a1ede6fb986aa953e4490b 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -85,8 +85,6 @@ int main( int argc, char **argv ) // install unexpected exception handler gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler); - // install crash handlers - viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); bool ok = viewer_app_ptr->init(); if(!ok) diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index d367395d5d3a22fb053a73db1fa2e36efd9ca7e3..dc0bad04bcab06fbdc91633d6bb55e98419fd3ad 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -78,8 +78,6 @@ void constructViewer() } gViewerAppPtr = new LLAppViewerMacOSX(); - - gViewerAppPtr->setErrorHandler(LLAppViewer::handleViewerCrash); } bool initViewer() diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 747b72fbba50623f0f6629cf6306ead9eaff753f..8c496e4095bd4652d908f9349ddbcdf8369d41cd 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -354,8 +354,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler); - viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); - // Set a debug info flag to indicate if multiple instances are running. bool found_other_instance = !create_app_mutex(); gDebugInfo["FoundOtherInstanceAtStartup"] = LLSD::Boolean(found_other_instance); diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index a6de5e333dc3c892373125c50940aea45b963ebb..2722112b8f033d8566440bc82c85a257c2327bef 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -74,6 +74,7 @@ struct LLAvatarData std::string profile_url; U8 caption_index; std::string caption_text; + std::string customer_type; U32 flags; BOOL allow_publish; }; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 875ea8c492fee8c86a5ff9bafca04ae13c82151c..39e9f2e4d2cb7723812bbf72651d8c947a231aa7 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -282,6 +282,7 @@ void LLDrawPoolAlpha::renderDebugAlpha() gGL.diffuseColor4f(1, 0, 0, 1); gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::getSmokeImage()); + renderAlphaHighlight(); pushUntexturedBatches(LLRenderPass::PASS_ALPHA_MASK); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 5f66d64285ab6d2974b5a25122aa38d039d0c5a9..6c99f648dec5ed3074e914bfb90d6576b2d1eb3d 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1776,7 +1776,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } *dst++ = tc; - if (do_bump) + if ((!mat && !gltf_mat) && do_bump) { bump_tc.push_back(tc); } diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 73312f9890a304abea62b789be87d608f39b2a4b..4d7d6a4d4a6ce97c7e850d85a8f5d1a3e481e36c 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -608,11 +608,11 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) mOFN.lpstrFilter = ANIM_FILTER \ L"\0"; break; - case FFLOAD_GLTF: - mOFN.lpstrFilter = GLTF_FILTER \ - L"\0"; - break; - case FFLOAD_COLLADA: + case FFLOAD_GLTF: + mOFN.lpstrFilter = GLTF_FILTER \ + L"\0"; + break; + case FFLOAD_COLLADA: mOFN.lpstrFilter = COLLADA_FILTER \ L"\0"; break; @@ -1213,7 +1213,6 @@ void set_nav_save_data(LLFilePicker::ESaveFilter filter, std::string &extension, case LLFilePicker::FFSAVE_ANIM: extension = "xaf"; break; - case LLFilePicker::FFSAVE_GLTF: extension = "glb"; break; diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 87279b6970a14565d1da68af50bdace055399848..10c42b2844bfda0f5919dc41133ab2f1f5b7e69d 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -117,6 +117,8 @@ LLFloaterIMNearbyChat::LLFloaterIMNearbyChat(const LLSD& llsd) mEnableCallbackRegistrar.add("Avatar.EnableGearItem", boost::bind(&cb_do_nothing)); mCommitCallbackRegistrar.add("Avatar.GearDoToSelected", boost::bind(&cb_do_nothing)); mEnableCallbackRegistrar.add("Avatar.CheckGearItem", boost::bind(&cb_do_nothing)); + + mMinFloaterHeight = EXPANDED_MIN_HEIGHT; } //static diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 1550cf94a26eb4c9b56db364223abca0b60c3785..e6222c8b56e00bf124ee8c639c32a87ba7cca049 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -92,6 +92,8 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLFloaterIMSessionTab::enableContextMenuItem, this, _2)); mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLFloaterIMSessionTab::doToSelected, this, _2)); mCommitCallbackRegistrar.add("Group.DoToSelected", boost::bind(&cb_group_do_nothing)); + + mMinFloaterHeight = getMinHeight(); } LLFloaterIMSessionTab::~LLFloaterIMSessionTab() @@ -939,10 +941,13 @@ void LLFloaterIMSessionTab::reshapeFloater(bool collapse) S32 height = mContentPanel->getRect().getHeight() + mToolbarPanel->getRect().getHeight() + mChatLayoutPanel->getRect().getHeight() - mChatLayoutPanelHeight + 2; floater_rect.mTop -= height; + + setResizeLimits(getMinWidth(), floater_rect.getHeight()); } else { floater_rect.mTop = floater_rect.mBottom + mFloaterHeight; + setResizeLimits(getMinWidth(), mMinFloaterHeight); } enableResizeCtrls(true, true, !collapse); @@ -967,6 +972,7 @@ void LLFloaterIMSessionTab::restoreFloater() setShape(floater_rect, true); mBodyStack->updateLayout(); mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon")); + setResizeLimits(getMinWidth(), mMinFloaterHeight); setMessagePaneExpanded(true); saveCollapsedState(); mInputEditor->enableSingleLineMode(false); diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index e14e5c88dac19765a59f2f5f57f220147e7dfcc9..183c194afcdc1f38bc7bbc90f7107f57e22bbef6 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -155,6 +155,7 @@ class LLFloaterIMSessionTab bool mMessagePaneExpanded; bool mIsParticipantListExpanded; + S32 mMinFloaterHeight; LLIMModel::LLIMSession* mSession; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index cbdab11ca72daa930569f74d168d9fd9349a782c..01e41a055583283395084b6f5ef38f89f8640d1a 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -316,7 +316,6 @@ void LLFloaterRegionInfo::onOpen(const LLSD& key) } refreshFromRegion(gAgent.getRegion()); requestRegionInfo(); - requestMeshRezInfo(); if (!mGodLevelChangeSlot.connected()) { @@ -1005,19 +1004,6 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L return false; } -void LLFloaterRegionInfo::requestMeshRezInfo() -{ - std::string sim_console_url = gAgent.getRegionCapability("SimConsoleAsync"); - - if (!sim_console_url.empty()) - { - std::string request_str = "get mesh_rez_enabled"; - - LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(sim_console_url, LLSD(request_str), - "Requested mesh_rez_enabled", "Error requesting mesh_rez_enabled"); - } -} - // setregioninfo // strings[0] = 'Y' - block terraform, 'N' - not // strings[1] = 'Y' - block fly, 'N' - not diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index cf38c0458c119f7dc67382d00fd435f5682e8276..a1b11faafa955327cb566dcdde1abd256c696fd4 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -102,7 +102,6 @@ class LLFloaterRegionInfo final : public LLFloater void onRegionChanged(); void requestRegionInfo(); - void requestMeshRezInfo(); void enableTopButtons(); void disableTopButtons(); diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 082bb888b1fa444003fba5901002131bc84cba64..d29ecbbf956f47824975b337c89325898167f287 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -45,15 +45,9 @@ LLFloaterTranslationSettings::LLFloaterTranslationSettings(const LLSD& key) : LLFloater(key) , mMachineTranslationCB(NULL) -, mLanguageCombo(NULL) -, mTranslationServiceRadioGroup(NULL) -, mBingAPIKeyEditor(NULL) -, mGoogleAPIKeyEditor(NULL) -, mBingVerifyBtn(NULL) -, mGoogleVerifyBtn(NULL) -, mOKBtn(NULL) -, mBingKeyVerified(false) +, mAzureKeyVerified(false) , mGoogleKeyVerified(false) +, mDeepLKeyVerified(false) { } @@ -63,24 +57,54 @@ BOOL LLFloaterTranslationSettings::postBuild() mMachineTranslationCB = getChild<LLCheckBoxCtrl>("translate_chat_checkbox"); mLanguageCombo = getChild<LLComboBox>("translate_language_combo"); mTranslationServiceRadioGroup = getChild<LLRadioGroup>("translation_service_rg"); - mBingAPIKeyEditor = getChild<LLLineEditor>("bing_api_key"); + mAzureAPIEndpointEditor = getChild<LLComboBox>("azure_api_endpoint_combo"); + mAzureAPIKeyEditor = getChild<LLLineEditor>("azure_api_key"); + mAzureAPIRegionEditor = getChild<LLLineEditor>("azure_api_region"); mGoogleAPIKeyEditor = getChild<LLLineEditor>("google_api_key"); - mBingVerifyBtn = getChild<LLButton>("verify_bing_api_key_btn"); + mDeepLAPIDomainCombo = getChild<LLComboBox>("deepl_api_domain_combo"); + mDeepLAPIKeyEditor = getChild<LLLineEditor>("deepl_api_key"); + mAzureVerifyBtn = getChild<LLButton>("verify_azure_api_key_btn"); mGoogleVerifyBtn = getChild<LLButton>("verify_google_api_key_btn"); + mDeepLVerifyBtn = getChild<LLButton>("verify_deepl_api_key_btn"); mOKBtn = getChild<LLButton>("ok_btn"); mMachineTranslationCB->setCommitCallback(boost::bind(&LLFloaterTranslationSettings::updateControlsEnabledState, this)); mTranslationServiceRadioGroup->setCommitCallback(boost::bind(&LLFloaterTranslationSettings::updateControlsEnabledState, this)); mOKBtn->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnOK, this)); getChild<LLButton>("cancel_btn")->setClickedCallback(boost::bind(&LLFloater::closeFloater, this, false)); - mBingVerifyBtn->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnBingVerify, this)); + mAzureVerifyBtn->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnAzureVerify, this)); mGoogleVerifyBtn->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnGoogleVerify, this)); + mDeepLVerifyBtn->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnDeepLVerify, this)); + + mAzureAPIKeyEditor->setFocusReceivedCallback(boost::bind(&LLFloaterTranslationSettings::onEditorFocused, this, _1)); + mAzureAPIKeyEditor->setKeystrokeCallback(boost::bind(&LLFloaterTranslationSettings::onAzureKeyEdited, this), NULL); + mAzureAPIRegionEditor->setFocusReceivedCallback(boost::bind(&LLFloaterTranslationSettings::onEditorFocused, this, _1)); + mAzureAPIRegionEditor->setKeystrokeCallback(boost::bind(&LLFloaterTranslationSettings::onAzureKeyEdited, this), NULL); + + mAzureAPIEndpointEditor->setFocusLostCallback([this](LLFocusableElement*) + { + setAzureVerified(false, false, 0); + }); + mAzureAPIEndpointEditor->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) + { + setAzureVerified(false, false, 0); + }); - mBingAPIKeyEditor->setFocusReceivedCallback(boost::bind(&LLFloaterTranslationSettings::onEditorFocused, this, _1)); - mBingAPIKeyEditor->setKeystrokeCallback(boost::bind(&LLFloaterTranslationSettings::onBingKeyEdited, this), NULL); mGoogleAPIKeyEditor->setFocusReceivedCallback(boost::bind(&LLFloaterTranslationSettings::onEditorFocused, this, _1)); mGoogleAPIKeyEditor->setKeystrokeCallback(boost::bind(&LLFloaterTranslationSettings::onGoogleKeyEdited, this), NULL); + mDeepLAPIKeyEditor->setFocusReceivedCallback(boost::bind(&LLFloaterTranslationSettings::onEditorFocused, this, _1)); + mDeepLAPIKeyEditor->setKeystrokeCallback(boost::bind(&LLFloaterTranslationSettings::onDeepLKeyEdited, this), NULL); + + mDeepLAPIDomainCombo->setFocusLostCallback([this](LLFocusableElement*) + { + setDeepLVerified(false, false, 0); + }); + mDeepLAPIDomainCombo->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) + { + setDeepLVerified(false, false, 0); + }); + center(); return TRUE; } @@ -92,17 +116,28 @@ void LLFloaterTranslationSettings::onOpen(const LLSD& key) mLanguageCombo->setSelectedByValue(gSavedSettings.getString("TranslateLanguage"), TRUE); mTranslationServiceRadioGroup->setSelectedByValue(gSavedSettings.getString("TranslationService"), TRUE); - std::string bing_key = gSavedSettings.getString("BingTranslateAPIKey"); - if (!bing_key.empty()) + LLSD azure_key = gSavedSettings.getLLSD("AzureTranslateAPIKey"); + if (azure_key.isMap() && !azure_key["id"].asString().empty()) { - mBingAPIKeyEditor->setText(bing_key); - mBingAPIKeyEditor->setTentative(FALSE); - verifyKey(LLTranslate::SERVICE_BING, bing_key, false); + mAzureAPIKeyEditor->setText(azure_key["id"].asString()); + mAzureAPIKeyEditor->setTentative(false); + if (azure_key.has("region") && !azure_key["region"].asString().empty()) + { + mAzureAPIRegionEditor->setText(azure_key["region"].asString()); + mAzureAPIRegionEditor->setTentative(false); + } + else + { + mAzureAPIRegionEditor->setTentative(true); + } + mAzureAPIEndpointEditor->setValue(azure_key["endpoint"]); + verifyKey(LLTranslate::SERVICE_AZURE, azure_key, false); } else { - mBingAPIKeyEditor->setTentative(TRUE); - mBingKeyVerified = FALSE; + mAzureAPIKeyEditor->setTentative(TRUE); + mAzureAPIRegionEditor->setTentative(true); + mAzureKeyVerified = FALSE; } std::string google_key = gSavedSettings.getString("GoogleTranslateAPIKey"); @@ -118,39 +153,74 @@ void LLFloaterTranslationSettings::onOpen(const LLSD& key) mGoogleKeyVerified = FALSE; } + LLSD deepl_key = gSavedSettings.getLLSD("DeepLTranslateAPIKey"); + if (deepl_key.isMap() && !deepl_key["id"].asString().empty()) + { + mDeepLAPIKeyEditor->setText(deepl_key["id"].asString()); + mDeepLAPIKeyEditor->setTentative(false); + mDeepLAPIDomainCombo->setValue(deepl_key["domain"]); + verifyKey(LLTranslate::SERVICE_DEEPL, deepl_key, false); + } + else + { + mDeepLAPIKeyEditor->setTentative(TRUE); + mDeepLKeyVerified = FALSE; + } + updateControlsEnabledState(); } -void LLFloaterTranslationSettings::setBingVerified(bool ok, bool alert) +void LLFloaterTranslationSettings::setAzureVerified(bool ok, bool alert, S32 status) { if (alert) { - showAlert(ok ? "bing_api_key_verified" : "bing_api_key_not_verified"); + showAlert(ok ? "azure_api_key_verified" : "azure_api_key_not_verified", status); } - mBingKeyVerified = ok; + mAzureKeyVerified = ok; updateControlsEnabledState(); } -void LLFloaterTranslationSettings::setGoogleVerified(bool ok, bool alert) +void LLFloaterTranslationSettings::setGoogleVerified(bool ok, bool alert, S32 status) { if (alert) { - showAlert(ok ? "google_api_key_verified" : "google_api_key_not_verified"); + showAlert(ok ? "google_api_key_verified" : "google_api_key_not_verified", status); } mGoogleKeyVerified = ok; updateControlsEnabledState(); } +void LLFloaterTranslationSettings::setDeepLVerified(bool ok, bool alert, S32 status) +{ + if (alert) + { + showAlert(ok ? "deepl_api_key_verified" : "deepl_api_key_not_verified", status); + } + + mDeepLKeyVerified = ok; + updateControlsEnabledState(); +} + std::string LLFloaterTranslationSettings::getSelectedService() const { return mTranslationServiceRadioGroup->getSelectedValue().asString(); } -std::string LLFloaterTranslationSettings::getEnteredBingKey() const +LLSD LLFloaterTranslationSettings::getEnteredAzureKey() const { - return mBingAPIKeyEditor->getTentative() ? LLStringUtil::null : mBingAPIKeyEditor->getText(); + LLSD key; + if (!mAzureAPIKeyEditor->getTentative()) + { + key["endpoint"] = mAzureAPIEndpointEditor->getValue(); + key["id"] = mAzureAPIKeyEditor->getText(); + if (!mAzureAPIRegionEditor->getTentative()) + { + key["region"] = mAzureAPIRegionEditor->getText(); + } + } + return key; } std::string LLFloaterTranslationSettings::getEnteredGoogleKey() const @@ -158,10 +228,26 @@ std::string LLFloaterTranslationSettings::getEnteredGoogleKey() const return mGoogleAPIKeyEditor->getTentative() ? LLStringUtil::null : mGoogleAPIKeyEditor->getText(); } -void LLFloaterTranslationSettings::showAlert(const std::string& msg_name) const +LLSD LLFloaterTranslationSettings::getEnteredDeepLKey() const +{ + LLSD key; + if (!mDeepLAPIKeyEditor->getTentative()) + { + key["domain"] = mDeepLAPIDomainCombo->getValue(); + key["id"] = mDeepLAPIKeyEditor->getText(); + } + return key; +} + +void LLFloaterTranslationSettings::showAlert(const std::string& msg_name, S32 status) const { + LLStringUtil::format_map_t string_args; + // For now just show an http error code, whole 'reason' string might be added later + string_args["[STATUS]"] = llformat("%d", status); + std::string message = getString(msg_name, string_args); + LLSD args; - args["MESSAGE"] = getString(msg_name); + args["MESSAGE"] = message; LLNotificationsUtil::add("GenericAlert", args); } @@ -170,34 +256,51 @@ void LLFloaterTranslationSettings::updateControlsEnabledState() // Enable/disable controls based on the checkbox value. bool on = mMachineTranslationCB->getValue().asBoolean(); std::string service = getSelectedService(); - bool bing_selected = service == "bing"; + bool azure_selected = service == "azure"; bool google_selected = service == "google"; + bool deepl_selected = service == "deepl"; mTranslationServiceRadioGroup->setEnabled(on); mLanguageCombo->setEnabled(on); - getChild<LLTextBox>("bing_api_key_label")->setEnabled(on); - mBingAPIKeyEditor->setEnabled(on); + // MS Azure + getChild<LLTextBox>("azure_api_endoint_label")->setEnabled(on); + mAzureAPIEndpointEditor->setEnabled(on && azure_selected); + getChild<LLTextBox>("azure_api_key_label")->setEnabled(on); + mAzureAPIKeyEditor->setEnabled(on && azure_selected); + getChild<LLTextBox>("azure_api_region_label")->setEnabled(on); + mAzureAPIRegionEditor->setEnabled(on && azure_selected); - getChild<LLTextBox>("google_api_key_label")->setEnabled(on); - mGoogleAPIKeyEditor->setEnabled(on); + mAzureVerifyBtn->setEnabled(on && azure_selected && + !mAzureKeyVerified && getEnteredAzureKey().isMap()); - mBingAPIKeyEditor->setEnabled(on && bing_selected); - mGoogleAPIKeyEditor->setEnabled(on && google_selected); + // Google + getChild<LLTextBox>("google_api_key_label")->setEnabled(on); + mGoogleAPIKeyEditor->setEnabled(on && google_selected); - mBingVerifyBtn->setEnabled(on && bing_selected && - !mBingKeyVerified && !getEnteredBingKey().empty()); mGoogleVerifyBtn->setEnabled(on && google_selected && !mGoogleKeyVerified && !getEnteredGoogleKey().empty()); - bool service_verified = (bing_selected && mBingKeyVerified) || (google_selected && mGoogleKeyVerified); + // DeepL + getChild<LLTextBox>("deepl_api_domain_label")->setEnabled(on); + mDeepLAPIDomainCombo->setEnabled(on && deepl_selected); + getChild<LLTextBox>("deepl_api_key_label")->setEnabled(on); + mDeepLAPIKeyEditor->setEnabled(on && deepl_selected); + + mDeepLVerifyBtn->setEnabled(on && deepl_selected && + !mDeepLKeyVerified && getEnteredDeepLKey().isMap()); + + bool service_verified = + (azure_selected && mAzureKeyVerified) + || (google_selected && mGoogleKeyVerified) + || (deepl_selected && mDeepLKeyVerified); gSavedPerAccountSettings.setBOOL("TranslatingEnabled", service_verified); mOKBtn->setEnabled(!on || service_verified); } /*static*/ -void LLFloaterTranslationSettings::setVerificationStatus(int service, bool ok, bool alert) +void LLFloaterTranslationSettings::setVerificationStatus(int service, bool ok, bool alert, S32 status) { LLFloaterTranslationSettings* floater = LLFloaterReg::getTypedInstance<LLFloaterTranslationSettings>("prefs_translation"); @@ -210,20 +313,23 @@ void LLFloaterTranslationSettings::setVerificationStatus(int service, bool ok, b switch (service) { - case LLTranslate::SERVICE_BING: - floater->setBingVerified(ok, alert); + case LLTranslate::SERVICE_AZURE: + floater->setAzureVerified(ok, alert, status); break; case LLTranslate::SERVICE_GOOGLE: - floater->setGoogleVerified(ok, alert); + floater->setGoogleVerified(ok, alert, status); + break; + case LLTranslate::SERVICE_DEEPL: + floater->setDeepLVerified(ok, alert, status); break; } } -void LLFloaterTranslationSettings::verifyKey(int service, const std::string& key, bool alert) +void LLFloaterTranslationSettings::verifyKey(int service, const LLSD& key, bool alert) { LLTranslate::verifyKey(static_cast<LLTranslate::EService>(service), key, - boost::bind(&LLFloaterTranslationSettings::setVerificationStatus, _1, _2, alert)); + boost::bind(&LLFloaterTranslationSettings::setVerificationStatus, _1, _2, alert, _3)); } void LLFloaterTranslationSettings::onEditorFocused(LLFocusableElement* control) @@ -239,11 +345,13 @@ void LLFloaterTranslationSettings::onEditorFocused(LLFocusableElement* control) } } -void LLFloaterTranslationSettings::onBingKeyEdited() +void LLFloaterTranslationSettings::onAzureKeyEdited() { - if (mBingAPIKeyEditor->isDirty()) + if (mAzureAPIKeyEditor->isDirty() + || mAzureAPIRegionEditor->isDirty()) { - setBingVerified(false, false); + // todo: verify mAzureAPIEndpointEditor url + setAzureVerified(false, false, 0); } } @@ -251,16 +359,24 @@ void LLFloaterTranslationSettings::onGoogleKeyEdited() { if (mGoogleAPIKeyEditor->isDirty()) { - setGoogleVerified(false, false); + setGoogleVerified(false, false, 0); } } -void LLFloaterTranslationSettings::onBtnBingVerify() +void LLFloaterTranslationSettings::onDeepLKeyEdited() { - std::string key = getEnteredBingKey(); - if (!key.empty()) + if (mDeepLAPIKeyEditor->isDirty()) + { + setDeepLVerified(false, false, 0); + } +} + +void LLFloaterTranslationSettings::onBtnAzureVerify() +{ + LLSD key = getEnteredAzureKey(); + if (key.isMap()) { - verifyKey(LLTranslate::SERVICE_BING, key); + verifyKey(LLTranslate::SERVICE_AZURE, key); } } @@ -269,26 +385,40 @@ void LLFloaterTranslationSettings::onBtnGoogleVerify() std::string key = getEnteredGoogleKey(); if (!key.empty()) { - verifyKey(LLTranslate::SERVICE_GOOGLE, key); + verifyKey(LLTranslate::SERVICE_GOOGLE, LLSD(key)); } } + +void LLFloaterTranslationSettings::onBtnDeepLVerify() +{ + LLSD key = getEnteredDeepLKey(); + if (key.isMap()) + { + verifyKey(LLTranslate::SERVICE_DEEPL, key); + } +} + void LLFloaterTranslationSettings::onClose(bool app_quitting) { std::string service = gSavedSettings.getString("TranslationService"); - bool bing_selected = service == "bing"; + bool azure_selected = service == "azure"; bool google_selected = service == "google"; + bool deepl_selected = service == "deepl"; - bool service_verified = (bing_selected && mBingKeyVerified) || (google_selected && mGoogleKeyVerified); - gSavedPerAccountSettings.setBOOL("TranslatingEnabled", service_verified); - + bool service_verified = + (azure_selected && mAzureKeyVerified) + || (google_selected && mGoogleKeyVerified) + || (deepl_selected && mDeepLKeyVerified); + gSavedPerAccountSettings.setBOOL("TranslatingEnabled", service_verified); } void LLFloaterTranslationSettings::onBtnOK() { gSavedSettings.setBOOL("TranslateChat", mMachineTranslationCB->getValue().asBoolean()); gSavedSettings.setString("TranslateLanguage", mLanguageCombo->getSelectedValue().asString()); gSavedSettings.setString("TranslationService", getSelectedService()); - gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey()); + gSavedSettings.setLLSD("AzureTranslateAPIKey", getEnteredAzureKey()); gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); + gSavedSettings.setLLSD("DeepLTranslateAPIKey", getEnteredDeepLKey()); closeFloater(false); } diff --git a/indra/newview/llfloatertranslationsettings.h b/indra/newview/llfloatertranslationsettings.h index ff7ad9c50e462af22330b86192ef36ae4200c981..670734f152dec85a88fe79c3d94ff1d8081e0556 100644 --- a/indra/newview/llfloatertranslationsettings.h +++ b/indra/newview/llfloatertranslationsettings.h @@ -42,38 +42,48 @@ class LLFloaterTranslationSettings final : public LLFloater /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); - void setBingVerified(bool ok, bool alert); - void setGoogleVerified(bool ok, bool alert); + void setAzureVerified(bool ok, bool alert, S32 status); + void setGoogleVerified(bool ok, bool alert, S32 status); + void setDeepLVerified(bool ok, bool alert, S32 status); void onClose(bool app_quitting); private: std::string getSelectedService() const; - std::string getEnteredBingKey() const; + LLSD getEnteredAzureKey() const; std::string getEnteredGoogleKey() const; - void showAlert(const std::string& msg_name) const; + LLSD getEnteredDeepLKey() const; + void showAlert(const std::string& msg_name, S32 status) const; void updateControlsEnabledState(); - void verifyKey(int service, const std::string& key, bool alert = true); + void verifyKey(int service, const LLSD& key, bool alert = true); void onEditorFocused(LLFocusableElement* control); - void onBingKeyEdited(); + void onAzureKeyEdited(); void onGoogleKeyEdited(); - void onBtnBingVerify(); + void onDeepLKeyEdited(); + void onBtnAzureVerify(); void onBtnGoogleVerify(); + void onBtnDeepLVerify(); void onBtnOK(); - static void setVerificationStatus(int service, bool alert, bool ok); + static void setVerificationStatus(int service, bool alert, bool ok, S32 status); LLCheckBoxCtrl* mMachineTranslationCB; LLComboBox* mLanguageCombo; - LLLineEditor* mBingAPIKeyEditor; + LLComboBox* mAzureAPIEndpointEditor; + LLLineEditor* mAzureAPIKeyEditor; + LLLineEditor* mAzureAPIRegionEditor; LLLineEditor* mGoogleAPIKeyEditor; + LLComboBox* mDeepLAPIDomainCombo; + LLLineEditor* mDeepLAPIKeyEditor; LLRadioGroup* mTranslationServiceRadioGroup; - LLButton* mBingVerifyBtn; + LLButton* mAzureVerifyBtn; LLButton* mGoogleVerifyBtn; + LLButton* mDeepLVerifyBtn; LLButton* mOKBtn; - bool mBingKeyVerified; + bool mAzureKeyVerified; bool mGoogleKeyVerified; + bool mDeepLKeyVerified; }; #endif // LL_LLFLOATERTRANSLATIONSETTINGS_H diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp index 68801b08951b622e828d6c731d9f303b56b0157c..6f93a78ca67f2054951d285ca59e81a128e1ba28 100644 --- a/indra/newview/llinspecttoast.cpp +++ b/indra/newview/llinspecttoast.cpp @@ -47,6 +47,7 @@ class LLInspectToast: public LLInspect /*virtual*/ void onOpen(const LLSD& notification_id); /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask); + /*virtual*/ void deleteAllChildren(); /*virtual*/ void removeChild(LLView* child); private: void onToastDestroy(LLToast * toast); @@ -122,6 +123,12 @@ BOOL LLInspectToast::handleToolTip(S32 x, S32 y, MASK mask) return LLFloater::handleToolTip(x, y, mask); } +void LLInspectToast::deleteAllChildren() +{ + mPanel = NULL; + LLInspect::deleteAllChildren(); +} + // virtual void LLInspectToast::removeChild(LLView* child) { diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 970278a7a426e7fd6051b1baf3c840a5cd48effc..607dc8b6d05137ed2822f827020cd7af63d848df 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -616,7 +616,11 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot( } } - if(rv.isNull() && create_folder && root_id.notNull()) + if(rv.isNull() + && root_id.notNull() + && create_folder + && preferred_type != LLFolderType::FT_MARKETPLACE_LISTINGS + && preferred_type != LLFolderType::FT_OUTBOX) { if (isInventoryUsable()) diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index c9b4cbfa743461c38ad6abe797526a13188b89c3..c944edd4d6d9dce6cf8e649580e60c764ee192af 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -30,8 +30,10 @@ #include "llagent.h" #include "llappviewer.h" #include "llcallbacklist.h" -#include "llinventorypanel.h" #include "llinventorymodel.h" +#include "llinventorypanel.h" +#include "llnotificationsutil.h" +#include "llstartup.h" #include "llviewercontrol.h" #include "llviewerinventory.h" #include "llviewermessage.h" @@ -576,6 +578,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() // *TODO: Think I'd like to get a shared pointer to this and share it // among all the folder requests. uuid_vec_t recursive_cats; + uuid_vec_t all_cats; // dupplicate avoidance LLSD folder_request_body; LLSD folder_request_body_lib; @@ -606,7 +609,8 @@ void LLInventoryModelBackgroundFetch::bulkFetch() if (cat) { - if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) + if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion() + && std::find(all_cats.begin(), all_cats.end(), cat_id) == all_cats.end()) { LLSD folder_sd; folder_sd["folder_id"] = cat->getUUID(); @@ -645,6 +649,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() { recursive_cats.push_back(cat_id); } + all_cats.push_back(cat_id); } else { @@ -963,6 +968,63 @@ void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::Http << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL; // Could use a 404 test here to try to detect revoked caps... + + if(status == LLCore::HttpStatus(HTTP_FORBIDDEN)) + { + // Too large, split into two if possible + if (gDisconnected || LLApp::isExiting()) + { + return; + } + + const std::string url(gAgent.getRegionCapability("FetchInventoryDescendents2")); + if (url.empty()) + { + LL_WARNS(LOG_INV) << "Failed to get AIS2 cap" << LL_ENDL; + return; + } + + S32 size = mRequestSD["folders"].size(); + + if (size > 1) + { + // Can split, assume that this isn't the library + LLSD folders; + uuid_vec_t recursive_cats; + LLSD::array_iterator iter = mRequestSD["folders"].beginArray(); + LLSD::array_iterator end = mRequestSD["folders"].endArray(); + while (iter != end) + { + folders.append(*iter); + LLUUID fodler_id = iter->get("folder_id").asUUID(); + if (std::find(mRecursiveCatUUIDs.begin(), mRecursiveCatUUIDs.end(), fodler_id) != mRecursiveCatUUIDs.end()) + { + recursive_cats.push_back(fodler_id); + } + if (folders.size() == (S32)(size / 2)) + { + LLSD request_body; + request_body["folders"] = folders; + LLCore::HttpHandler::ptr_t handler(new BGFolderHttpHandler(request_body, recursive_cats)); + gInventory.requestPost(false, url, request_body, handler, "Inventory Folder"); + recursive_cats.clear(); + folders.clear(); + } + iter++; + } + + LLSD request_body; + request_body["folders"] = folders; + LLCore::HttpHandler::ptr_t handler(new BGFolderHttpHandler(request_body, recursive_cats)); + gInventory.requestPost(false, url, request_body, handler, "Inventory Folder"); + return; + } + else + { + // Can't split + LLNotificationsUtil::add("InventoryLimitReachedAIS"); + } + } // This was originally the request retry logic for the inventory // request which tested on HTTP_INTERNAL_ERROR status. This diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 6b29dbadf908e0e609c0eeea4b3560cc2876f9f2..38b828c123004aae02a113b7774d38ccf2535557 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1272,8 +1272,10 @@ BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask) { BOOL handled = LLView::handleHover(x, y, mask); if(handled) - { - ECursorType cursor = getWindow()->getCursor(); + { + // getCursor gets current cursor, setCursor sets next cursor + // check that children didn't set own 'next' cursor + ECursorType cursor = getWindow()->getNextCursor(); if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() && cursor == UI_CURSOR_ARROW) { // replace arrow cursor with arrow and hourglass cursor diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 115f773c52845267c381c3300b24fd20579c8500..99619faa343842be8167cc4497c613c9f521457a 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -99,6 +99,7 @@ class LLMuteList final : public LLSingleton<LLMuteList> BOOL isMuted(const LLUUID& id, const std::string& name = LLStringUtil::null, U32 flags = 0) const; // Workaround for username-based mute search, a lot of string conversions so use cautiously + // Expects lower case username BOOL isMuted(const std::string& username, U32 flags = 0) const; // Alternate (convenience) form for places we don't need to pass the name, but do need flags diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 3dcdb4bb7b05e9a895784fe1cd9affb2191bd5a2..8bbff470e01382918fbb711375d4fd97c7ea6c0f 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -957,7 +957,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) { //set state of UI to match state of texture entry(ies) (calls setEnabled, setValue, etc, but NOT setVisible) LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - if( objectp + if (objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify()) { @@ -987,7 +987,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) mComboMatMedia->setEnabled(editable); - LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type"); + LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type"); if (radio_mat_type->getSelectedIndex() < MATTYPE_DIFFUSE) { radio_mat_type->selectNthItem(MATTYPE_DIFFUSE); @@ -1011,7 +1011,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) // *NOTE: The "identical" variable is currently only used to decide if // the texgen control should be tentative - this is not used by GLTF // materials. -Cosmic;2022-11-09 - bool identical = true; // true because it is anded below + bool identical = true; // true because it is anded below bool identical_diffuse = false; bool identical_norm = false; bool identical_spec = false; @@ -1028,12 +1028,12 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) { getChildView("color label")->setEnabled(editable); } - LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("colorswatch"); + LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("colorswatch"); - LLColor4 color = LLColor4::white; - bool identical_color = false; + LLColor4 color = LLColor4::white; + bool identical_color = false; - if(color_swatch) + if (color_swatch) { LLSelectedTE::getColor(color, identical_color); LLColor4 prev_color = color_swatch->get(); @@ -1067,7 +1067,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) LLCtrlSelectionInterface* combobox_shininess = mComboShininess->getSelectionInterface(); if (combobox_shininess) - { + { combobox_shininess->selectNthItem((S32)shiny); } @@ -1104,18 +1104,18 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) bumpy = norm_map_id.isNull() ? bumpy : BUMPY_TEXTURE; if (combobox_bumpiness) - { + { combobox_bumpiness->selectNthItem((S32)bumpy); - } + } else - { + { LL_WARNS() << "failed childGetSelectionInterface for 'combobox bumpiness'" << LL_ENDL; - } + } getChildView("combobox bumpiness")->setEnabled(editable); getChild<LLUICtrl>("combobox bumpiness")->setTentative(!identical_bumpy); getChildView("label bumpiness")->setEnabled(editable); - } + } // Texture { @@ -1129,25 +1129,25 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) bool identical_image_format = false; LLSelectedTE::getImageFormat(image_format, identical_image_format); - mIsAlpha = FALSE; - switch (image_format) - { - case GL_RGBA: - case GL_ALPHA: - { - mIsAlpha = TRUE; - } - break; - - case GL_RGB: break; - default: - { - LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL; - } - break; + mIsAlpha = FALSE; + switch (image_format) + { + case GL_RGBA: + case GL_ALPHA: + { + mIsAlpha = TRUE; + } + break; + + case GL_RGB: break; + default: + { + LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL; } + break; + } - if(LLViewerMedia::getInstance()->textureHasMedia(id)) + if (LLViewerMedia::getInstance()->textureHasMedia(id)) { getChildView("button align")->setEnabled(editable); } @@ -1199,7 +1199,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } else if (id.isNull()) { - // None selected + // None selected texture_ctrl->setTentative(FALSE); texture_ctrl->setEnabled(FALSE); texture_ctrl->setImageAssetID(LLUUID::null); @@ -1212,7 +1212,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } else { - // Tentative: multiple selected with different textures + // Tentative: multiple selected with different textures texture_ctrl->setTentative(TRUE); texture_ctrl->setEnabled(editable && !has_pbr_material); texture_ctrl->setImageAssetID(id); @@ -1223,7 +1223,6 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) texture_ctrl->setBakeTextureEnabled(TRUE); } - } if (shinytexture_ctrl) @@ -1509,7 +1508,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) LLComboBox* mComboTexGen = getChild<LLComboBox>("combobox texgen"); if (mComboTexGen) - { + { S32 index = mComboTexGen ? mComboTexGen->getCurrentIndex() : 0; bool enabled = editable && (index != 1); bool identical_repeats = true; @@ -1604,14 +1603,14 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) if (!mIsAlpha) { // ... unless there is no alpha channel in the texture, in which case alpha mode MUST ebe none alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE; - } + } combobox_alphamode->selectNthItem(alpha_mode); - } - else - { + } + else + { LL_WARNS() << "failed childGetSelectionInterface for 'combobox alphamode'" << LL_ENDL; - } + } mSpinMaskCutoff->setValue(material->getAlphaMaskCutoff()); updateAlphaControls(); @@ -1622,15 +1621,15 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) mShinyTextureCtrl->setImageAssetID(material->getSpecularID()); if (!material->getSpecularID().isNull() && (shiny == SHINY_TEXTURE)) - { + { material->getSpecularOffset(offset_x,offset_y); material->getSpecularRepeat(repeat_x,repeat_y); if (identical_planar_texgen) - { + { repeat_x *= 2.0f; repeat_y *= 2.0f; - } + } rot = material->getSpecularRotation(); getChild<LLUICtrl>("shinyScaleU")->setValue(repeat_x); @@ -1642,7 +1641,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) mSpinEnvironment->setValue(material->getEnvironmentIntensity()); updateShinyControls(!material->getSpecularID().isNull(), true); - } + } // Assert desired colorswatch color to match material AFTER updateShinyControls // to avoid getting overwritten with the default on some UI state changes. @@ -1708,14 +1707,14 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) pbr_ctrl->setEnabled(FALSE); } LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("texture control"); - if(texture_ctrl) + if (texture_ctrl) { texture_ctrl->setImageAssetID( LLUUID::null ); texture_ctrl->setEnabled( FALSE ); // this is a LLUICtrl, but we don't want it to have keyboard focus so we add it as a child, not a ctrl. // texture_ctrl->setValid(FALSE); } LLColorSwatchCtrl* mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch"); - if(mColorSwatch) + if (mColorSwatch) { mColorSwatch->setEnabled( FALSE ); mColorSwatch->setFallbackImage(LLUI::getUIImage("locked_image.j2c") ); @@ -1827,7 +1826,6 @@ void LLPanelFace::updateCopyTexButton() && (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)); std::string tooltip = (objectp && objectp->isInventoryPending()) ? LLTrans::getString("LoadingContents") : getString("paste_options"); mMenuClipboardTexture->setToolTip(tooltip); - } void LLPanelFace::refresh() diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index ef07be5a16bb9f8baa218f311107872b7397bbc7..b6d77b237416c84b393695b9e1226af1df478fd4 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -139,7 +139,7 @@ class LLPanelFace : public LLPanel void sendTexGen(); // applies and sends bump map void sendShiny(U32 shininess); // applies and sends shininess void sendFullbright(); // applies and sends full bright - void sendGlow(); + void sendGlow(); void alignTestureLayer(); void updateCopyTexButton(); @@ -284,7 +284,6 @@ class LLPanelFace : public LLPanel LLSpinCtrl* mSpinMaskCutoff = nullptr; private: - bool isAlpha() { return mIsAlpha; } // Convenience funcs to keep the visual flack to a minimum @@ -293,10 +292,10 @@ class LLPanelFace : public LLPanel LLUUID getCurrentSpecularMap(); U32 getCurrentShininess(); U32 getCurrentBumpiness(); - U8 getCurrentDiffuseAlphaMode(); - U8 getCurrentAlphaMaskCutoff(); - U8 getCurrentEnvIntensity(); - U8 getCurrentGlossiness(); + U8 getCurrentDiffuseAlphaMode(); + U8 getCurrentAlphaMaskCutoff(); + U8 getCurrentEnvIntensity(); + U8 getCurrentGlossiness(); F32 getCurrentBumpyRot(); F32 getCurrentBumpyScaleU(); F32 getCurrentBumpyScaleV(); @@ -372,7 +371,7 @@ class LLPanelFace : public LLPanel U32 new_alpha_mode = new_material->getDiffuseAlphaMode(); LLUUID new_normal_map_id = new_material->getNormalID(); - LLUUID new_spec_map_id = new_material->getSpecularID(); + LLUUID new_spec_map_id = new_material->getSpecularID(); if ((new_alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND) && !is_alpha_face) { @@ -617,7 +616,6 @@ class LLPanelFace : public LLPanel class LLSelectedTE { public: - static void getFace(class LLFace*& face_to_return, bool& identical_face); static void getImageFormat(LLGLenum& image_format_to_return, bool& identical_face); static void getTexId(LLUUID& id, bool& identical); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 7254cbe49bfb0ef3356b715800f047b63bc3b164..af1d0a544a58f7386026cc77c2015886ca0282c3 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1633,7 +1633,8 @@ void LLPanelObjectInventory::reset() LLEditMenuHandler::gEditMenuHandler = mFolders; } - LLRect scroller_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + int offset = hasBorder() ? getBorder()->getBorderWidth() << 1 : 0; + LLRect scroller_rect(0, getRect().getHeight() - offset, getRect().getWidth() - offset, 0); LLScrollContainer::Params scroll_p; scroll_p.name("task inventory scroller"); scroll_p.rect(scroller_rect); diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 743195bfda9c713c8da1232cd4b214bdea84e6e9..cfa5543cdc8b13b8dc05713d00f4dbbd7d8557a0 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -161,6 +161,7 @@ void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id) avatar_data->fl_about_text = result["fl_about_text"].asString(); avatar_data->born_on = result["member_since"].asDate(); avatar_data->profile_url = getProfileURL(agent_id.asString()); + avatar_data->customer_type = result["customer_type"].asString(); avatar_data->flags = 0; @@ -758,6 +759,8 @@ void LLPanelProfileSecondLife::resetData() mCantEditObjectsIcon->setEnabled(false); childSetVisible("partner_layout", FALSE); + childSetVisible("badge_layout", FALSE); + childSetVisible("partner_spacer_layout", TRUE); } void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) @@ -965,6 +968,73 @@ void LLPanelProfileSecondLife::fillAccountStatus(const LLAvatarData* avatar_data std::string caption_text = getString("CaptionTextAcctInfo", args); getChild<LLUICtrl>("account_info")->setValue(caption_text); + + const S32 LINDEN_EMPLOYEE_INDEX = 3; + LLDate sl_release; + sl_release.fromYMDHMS(2003, 6, 23, 0, 0, 0); + std::string customer_lower = avatar_data->customer_type; + LLStringUtil::toLower(customer_lower); + if (avatar_data->caption_index == LINDEN_EMPLOYEE_INDEX) + { + getChild<LLUICtrl>("badge_icon")->setValue("Profile_Badge_Linden"); + getChild<LLUICtrl>("badge_text")->setValue(getString("BadgeLinden")); + childSetVisible("badge_layout", TRUE); + childSetVisible("partner_spacer_layout", FALSE); + } + else if (avatar_data->born_on < sl_release) + { + getChild<LLUICtrl>("badge_icon")->setValue("Profile_Badge_Beta"); + getChild<LLUICtrl>("badge_text")->setValue(getString("BadgeBeta")); + childSetVisible("badge_layout", TRUE); + childSetVisible("partner_spacer_layout", FALSE); + } + else if (customer_lower == "beta_lifetime") + { + getChild<LLUICtrl>("badge_icon")->setValue("Profile_Badge_Beta_Lifetime"); + getChild<LLUICtrl>("badge_text")->setValue(getString("BadgeBetaLifetime")); + childSetVisible("badge_layout", TRUE); + childSetVisible("partner_spacer_layout", FALSE); + } + else if (customer_lower == "lifetime") + { + getChild<LLUICtrl>("badge_icon")->setValue("Profile_Badge_Lifetime"); + getChild<LLUICtrl>("badge_text")->setValue(getString("BadgeLifetime")); + childSetVisible("badge_layout", TRUE); + childSetVisible("partner_spacer_layout", FALSE); + } + else if (customer_lower == "secondlifetime_premium") + { + getChild<LLUICtrl>("badge_icon")->setValue("Profile_Badge_Premium_Lifetime"); + getChild<LLUICtrl>("badge_text")->setValue(getString("BadgePremiumLifetime")); + childSetVisible("badge_layout", TRUE); + childSetVisible("partner_spacer_layout", FALSE); + } + else if (customer_lower == "secondlifetime_premium_plus") + { + getChild<LLUICtrl>("badge_icon")->setValue("Profile_Badge_Pplus_Lifetime"); + getChild<LLUICtrl>("badge_text")->setValue(getString("BadgePremiumPlusLifetime")); + childSetVisible("badge_layout", TRUE); + childSetVisible("partner_spacer_layout", FALSE); + } + else if (customer_lower == "monthly" || customer_lower == "quarterly" || customer_lower == "annual") + { + getChild<LLUICtrl>("badge_icon")->setValue("AccountLevel_Premium"); + getChild<LLUICtrl>("badge_text")->setValue(getString("BadgePremium")); + childSetVisible("badge_layout", TRUE); + childSetVisible("partner_spacer_layout", FALSE); + } + else if (customer_lower.find("premium_plus") != std::string::npos) + { + getChild<LLUICtrl>("badge_icon")->setValue("AccountLevel_Plus"); + getChild<LLUICtrl>("badge_text")->setValue(getString("BadgePremiumPlus")); + childSetVisible("badge_layout", TRUE); + childSetVisible("partner_spacer_layout", FALSE); + } + else + { + childSetVisible("badge_layout", FALSE); + childSetVisible("partner_spacer_layout", TRUE); + } } void LLPanelProfileSecondLife::fillRightsData() @@ -1119,7 +1189,7 @@ void LLPanelProfileSecondLife::updateOnlineStatus() } else { - childSetVisible("frind_layout", false); + childSetVisible("friend_layout", false); childSetVisible("online_layout", false); childSetVisible("offline_layout", false); } @@ -1127,7 +1197,7 @@ void LLPanelProfileSecondLife::updateOnlineStatus() void LLPanelProfileSecondLife::processOnlineStatus(bool is_friend, bool show_online, bool online) { - childSetVisible("frind_layout", is_friend); + childSetVisible("friend_layout", is_friend); childSetVisible("online_layout", online && show_online); childSetVisible("offline_layout", !online && show_online); } diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp index 8a6f3f77742f2f6267f0bde68b447ffe3849731a..1623884af4b337468a0409b1127e3179d05d69d1 100644 --- a/indra/newview/llpanelprofilepicks.cpp +++ b/indra/newview/llpanelprofilepicks.cpp @@ -539,6 +539,7 @@ void LLPanelProfilePick::setAvatarId(const LLUUID& avatar_id) pick_name = parcel->getName(); pick_desc = parcel->getDesc(); snapshot_id = parcel->getSnapshotID(); + mPickDescription->setParseHTML(false); } LLViewerRegion* region = gAgent.getRegion(); diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index 64bdc473bd9520c9415d896f811cff75ada3a38b..042ff74b6ad16714899449f6f9dab2611b9f9d2a 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -598,7 +598,7 @@ void LLPanelWearing::onRemoveAttachment() { LLSelectMgr::getInstance()->deselectAll(); LLSelectMgr::getInstance()->selectObjectAndFamily(mAttachmentsMap[item->getUUID()]); - LLSelectMgr::getInstance()->sendDropAttachment(); + LLSelectMgr::getInstance()->sendDetach(); } } diff --git a/indra/newview/llscripteditor.cpp b/indra/newview/llscripteditor.cpp index de247592ab8ea9f812a0c75f6ffd527325102a10..da08aa87a8b7c93190136d695780a7f53fce5fe3 100644 --- a/indra/newview/llscripteditor.cpp +++ b/indra/newview/llscripteditor.cpp @@ -194,7 +194,7 @@ void LLScriptEditor::drawSelectionBackground() { highlight_list_t highlights; highlights.push_back(range_pair_t(llmin(mSelectionStart, mSelectionEnd), llmax(mSelectionStart, mSelectionEnd))); - std::vector<LLRect> selection_rects = getSelctionRects(highlights); + std::vector<LLRect> selection_rects = getSelectionRects(highlights); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); const LLColor4& color = mReadOnly ? mReadOnlyFgColor : mFgColor; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 73d638deed02241317f0a248b7f85beb794e88ac..8166d44f5597da470dc2b54ba6f4ecebcd5edf9a 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1454,8 +1454,16 @@ bool idle_startup() } else if (regionp->capabilitiesError()) { - // Try to connect despite capabilities' error state - LLStartUp::setStartupState(STATE_SEED_CAP_GRANTED); + LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL; + if (gRememberPassword) + { + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + } + else + { + LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); + } + reset_login(); } else { @@ -1975,6 +1983,7 @@ bool idle_startup() LLNotificationsUtil::add("InventoryUnusable"); } + LLInventoryModelBackgroundFetch::instance().start(); gInventory.createCommonSystemCategories(); // It's debatable whether this flag is a good idea - sets all diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 1ff165eee45c97eb80874565e06423b4feface46..f5b06c59fe7662f4e97ead8624cb251dcbeb00ca 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1102,12 +1102,16 @@ void LLToolDragAndDrop::dropMaterialOneFace(LLViewerObject* hit_obj, LL_WARNS() << "LLToolDragAndDrop::dropTextureOneFace no material item." << LL_ENDL; return; } + + // SL-20013 must save asset_id before handleDropMaterialProtections since our item instance + // may be deleted if it is moved into task inventory + LLUUID asset_id = item->getAssetUUID(); BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id); if (!success) { return; } - LLUUID asset_id = item->getAssetUUID(); + if (asset_id.isNull()) { // use blank material @@ -1133,13 +1137,17 @@ void LLToolDragAndDrop::dropMaterialAllFaces(LLViewerObject* hit_obj, LL_WARNS() << "LLToolDragAndDrop::dropTextureAllFaces no material item." << LL_ENDL; return; } + + // SL-20013 must save asset_id before handleDropMaterialProtections since our item instance + // may be deleted if it is moved into task inventory + LLUUID asset_id = item->getAssetUUID(); BOOL success = handleDropMaterialProtections(hit_obj, item, source, src_id); + if (!success) { return; } - LLUUID asset_id = item->getAssetUUID(); if (asset_id.isNull()) { // use blank material diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index 84601da4c1d1d37176fb5482ead58352f4991355..3916a69808010d02431da7528cac1e9fb3eec621 100644 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -41,8 +41,8 @@ #include <nlohmann/json.hpp> -static const std::string BING_NOTRANSLATE_OPENING_TAG("<div class=\"notranslate\">"); -static const std::string BING_NOTRANSLATE_CLOSING_TAG("</div>"); +static const std::string AZURE_NOTRANSLATE_OPENING_TAG("<div translate=\"no\">"); +static const std::string AZURE_NOTRANSLATE_CLOSING_TAG("</div>"); /** * Handler of an HTTP machine translation service. @@ -80,7 +80,18 @@ class LLTranslationAPIHandler * @param[in] key Key to verify. */ virtual std::string getKeyVerificationURL( - const std::string &key) const = 0; + const LLSD &key) const = 0; + + /** + * Check API verification response. + * + * @param[out] bool true if valid. + * @param[in] response + * @param[in] status + */ + virtual bool checkVerificationResponse( + const LLSD &response, + int status) const = 0; /** * Parse translation response. @@ -92,6 +103,7 @@ class LLTranslationAPIHandler * @param[out] err_msg Error message (in case of error). */ virtual bool parseResponse( + const LLSD& http_response, int& status, const std::string& body, std::string& translation, @@ -105,14 +117,30 @@ class LLTranslationAPIHandler virtual LLTranslate::EService getCurrentService() = 0; - virtual void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc) = 0; + virtual void verifyKey(const LLSD &key, LLTranslate::KeyVerificationResult_fn fnc) = 0; virtual void translateMessage(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure); virtual ~LLTranslationAPIHandler() {} - void verifyKeyCoro(LLTranslate::EService service, std::string key, LLTranslate::KeyVerificationResult_fn fnc); + void verifyKeyCoro(LLTranslate::EService service, LLSD key, LLTranslate::KeyVerificationResult_fn fnc); void translateMessageCoro(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure); + + virtual void initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent) const = 0; + virtual void initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent, const LLSD &key) const = 0; + virtual LLSD sendMessageAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string & url, + const std::string & msg, + const std::string& from_lang, + const std::string& to_lang) const = 0; + virtual LLSD verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string & url) const = 0; }; void LLTranslationAPIHandler::translateMessage(LanguagePair_t fromTo, std::string msg, LLTranslate::TranslationSuccess_fn success, LLTranslate::TranslationFailure_fn failure) @@ -122,8 +150,7 @@ void LLTranslationAPIHandler::translateMessage(LanguagePair_t fromTo, std::strin } - -void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, std::string key, LLTranslate::KeyVerificationResult_fn fnc) +void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, LLSD key, LLTranslate::KeyVerificationResult_fn fnc) { LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t @@ -140,8 +167,7 @@ void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, std:: LLVersionInfo::instance().getPatch(), LLVersionInfo::instance().getBuild()); - httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN); - httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent); + initHttpHeader(httpHeaders, user_agent, key); httpOpts->setFollowRedirects(true); httpOpts->setSSLVerifyPeer(false); @@ -153,17 +179,29 @@ void LLTranslationAPIHandler::verifyKeyCoro(LLTranslate::EService service, std:: return; } - LLSD result = httpAdapter->getAndSuspend(httpRequest, url, httpOpts, httpHeaders); + std::string::size_type delim_pos = url.find("://"); + if (delim_pos == std::string::npos) + { + LL_INFOS("Translate") << "URL is missing a scheme" << LL_ENDL; + return; + } + + LLSD result = verifyAndSuspend(httpAdapter, httpRequest, httpOpts, httpHeaders, url); LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); bool bOk = true; - if (!status) + int parseResult = status.getType(); + if (!checkVerificationResponse(httpResults, parseResult)) + { bOk = false; + } if (!fnc.empty()) - fnc(service, bOk); + { + fnc(service, bOk, parseResult); + } } void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::string msg, @@ -184,8 +222,7 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s LLVersionInfo::instance().getPatch(), LLVersionInfo::instance().getBuild()); - httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN); - httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent); + initHttpHeader(httpHeaders, user_agent); httpOpts->setSSLVerifyPeer(false); std::string url = this->getTranslateURL(fromTo.first, fromTo.second, msg); @@ -195,7 +232,7 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s return; } - LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts, httpHeaders); + LLSD result = sendMessageAndSuspend(httpAdapter, httpRequest, httpOpts, httpHeaders, url, msg, fromTo.first, fromTo.second); if (LLApp::isQuitting()) { @@ -216,7 +253,7 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s try { - res = this->parseResponse(parseResult, body, translation, detected_lang, err_msg); + res = this->parseResponse(httpResults, parseResult, body, translation, detected_lang, err_msg); } catch (std::out_of_range&) { @@ -242,6 +279,11 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s } else { + if (err_msg.empty() && httpResults.has("error_body")) + { + err_msg = httpResults["error_body"].asString(); + } + if (err_msg.empty()) { err_msg = LLTrans::getString("TranslationResponseParseError"); @@ -262,23 +304,44 @@ class LLGoogleTranslationHandler : public LLTranslationAPIHandler LOG_CLASS(LLGoogleTranslationHandler); public: - /*virtual*/ std::string getTranslateURL( + std::string getTranslateURL( const std::string &from_lang, const std::string &to_lang, - const std::string &text) const; - /*virtual*/ std::string getKeyVerificationURL( - const std::string &key) const; - /*virtual*/ bool parseResponse( + const std::string &text) const override; + std::string getKeyVerificationURL( + const LLSD &key) const override; + bool checkVerificationResponse( + const LLSD &response, + int status) const override; + bool parseResponse( + const LLSD& http_response, int& status, const std::string& body, std::string& translation, std::string& detected_lang, - std::string& err_msg) const; - /*virtual*/ bool isConfigured() const; - - /*virtual*/ LLTranslate::EService getCurrentService() { return LLTranslate::EService::SERVICE_GOOGLE; } - - /*virtual*/ void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc); + std::string& err_msg) const override; + bool isConfigured() const override; + + LLTranslate::EService getCurrentService() override { return LLTranslate::EService::SERVICE_GOOGLE; } + + void verifyKey(const LLSD &key, LLTranslate::KeyVerificationResult_fn fnc) override; + + void initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent) const override; + void initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent, const LLSD &key) const override; + LLSD sendMessageAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string & url, + const std::string & msg, + const std::string& from_lang, + const std::string& to_lang) const override; + + LLSD verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string & url) const override; private: static void parseErrorResponse( @@ -311,15 +374,24 @@ std::string LLGoogleTranslationHandler::getTranslateURL( // virtual std::string LLGoogleTranslationHandler::getKeyVerificationURL( - const std::string& key) const + const LLSD& key) const { - std::string url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=") - + key + "&target=en"; + std::string url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=") + + key.asString() +"&target=en"; return url; } +//virtual +bool LLGoogleTranslationHandler::checkVerificationResponse( + const LLSD &response, + int status) const +{ + return status == HTTP_OK; +} + // virtual bool LLGoogleTranslationHandler::parseResponse( + const LLSD& http_response, int& status, const std::string& body, std::string& translation, @@ -410,75 +482,199 @@ bool LLGoogleTranslationHandler::parseTranslation( // static std::string LLGoogleTranslationHandler::getAPIKey() { - return gSavedSettings.getString("GoogleTranslateAPIKey"); + static LLCachedControl<std::string> google_key(gSavedSettings, "GoogleTranslateAPIKey"); + return google_key; } /*virtual*/ -void LLGoogleTranslationHandler::verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc) +void LLGoogleTranslationHandler::verifyKey(const LLSD &key, LLTranslate::KeyVerificationResult_fn fnc) { LLCoros::instance().launch("Google /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro, this, LLTranslate::SERVICE_GOOGLE, key, fnc)); } +/*virtual*/ +void LLGoogleTranslationHandler::initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent) const +{ + headers->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN); + headers->append(HTTP_OUT_HEADER_USER_AGENT, user_agent); +} + +/*virtual*/ +void LLGoogleTranslationHandler::initHttpHeader( + LLCore::HttpHeaders::ptr_t headers, + const std::string& user_agent, + const LLSD &key) const +{ + headers->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_TEXT_PLAIN); + headers->append(HTTP_OUT_HEADER_USER_AGENT, user_agent); +} + +LLSD LLGoogleTranslationHandler::sendMessageAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string & url, + const std::string & msg, + const std::string& from_lang, + const std::string& to_lang) const +{ + return adapter->getRawAndSuspend(request, url, options, headers); +} + +LLSD LLGoogleTranslationHandler::verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string & url) const +{ + return adapter->getAndSuspend(request, url, options, headers); +} //========================================================================= /// Microsoft Translator v2 API handler. -class LLBingTranslationHandler : public LLTranslationAPIHandler +class LLAzureTranslationHandler : public LLTranslationAPIHandler { - LOG_CLASS(LLBingTranslationHandler); + LOG_CLASS(LLAzureTranslationHandler); public: - /*virtual*/ std::string getTranslateURL( + std::string getTranslateURL( const std::string &from_lang, const std::string &to_lang, - const std::string &text) const; - /*virtual*/ std::string getKeyVerificationURL( - const std::string &key) const; - /*virtual*/ bool parseResponse( + const std::string &text) const override; + std::string getKeyVerificationURL( + const LLSD &key) const override; + bool checkVerificationResponse( + const LLSD &response, + int status) const override; + bool parseResponse( + const LLSD& http_response, int& status, const std::string& body, std::string& translation, std::string& detected_lang, - std::string& err_msg) const; - /*virtual*/ bool isConfigured() const; - - /*virtual*/ LLTranslate::EService getCurrentService() { return LLTranslate::EService::SERVICE_BING; } - - /*virtual*/ void verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc); + std::string& err_msg) const override; + bool isConfigured() const override; + + LLTranslate::EService getCurrentService() override { return LLTranslate::EService::SERVICE_AZURE; } + + void verifyKey(const LLSD &key, LLTranslate::KeyVerificationResult_fn fnc) override; + + void initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent) const override; + void initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent, const LLSD &key) const override; + LLSD sendMessageAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string & url, + const std::string & msg, + const std::string& from_lang, + const std::string& to_lang) const override; + + LLSD verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string & url) const override; private: - static std::string getAPIKey(); + static std::string parseErrorResponse( + const std::string& body); + static LLSD getAPIKey(); static std::string getAPILanguageCode(const std::string& lang); }; //------------------------------------------------------------------------- // virtual -std::string LLBingTranslationHandler::getTranslateURL( +std::string LLAzureTranslationHandler::getTranslateURL( const std::string &from_lang, const std::string &to_lang, const std::string &text) const { - std::string url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=") - + getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + getAPILanguageCode(to_lang); - if (!from_lang.empty()) - { - url += "&from=" + getAPILanguageCode(from_lang); - } + std::string url; + LLSD key = getAPIKey(); + if (key.isMap()) + { + std::string endpoint = key["endpoint"].asString(); + + if (*endpoint.rbegin() != '/') + { + endpoint += "/"; + } + url = endpoint + std::string("translate?api-version=3.0&to=") + + getAPILanguageCode(to_lang); + } return url; } // virtual -std::string LLBingTranslationHandler::getKeyVerificationURL( - const std::string& key) const +std::string LLAzureTranslationHandler::getKeyVerificationURL( + const LLSD& key) const { - std::string url = std::string("http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate?appId=") - + key; + std::string url; + if (key.isMap()) + { + std::string endpoint = key["endpoint"].asString(); + if (*endpoint.rbegin() != '/') + { + endpoint += "/"; + } + url = endpoint + std::string("translate?api-version=3.0&to=en"); + } return url; } +//virtual +bool LLAzureTranslationHandler::checkVerificationResponse( + const LLSD &response, + int status) const +{ + if (status == HTTP_UNAUTHORIZED) + { + LL_DEBUGS("Translate") << "Key unathorised" << LL_ENDL; + return false; + } + + if (status == HTTP_NOT_FOUND) + { + LL_DEBUGS("Translate") << "Either endpoint doesn't have requested resource" << LL_ENDL; + return false; + } + + if (status != HTTP_BAD_REQUEST) + { + LL_DEBUGS("Translate") << "Unexpected error code" << LL_ENDL; + return false; + } + + if (!response.has("error_body")) + { + LL_DEBUGS("Translate") << "Unexpected response, no error returned" << LL_ENDL; + return false; + } + + // Expected: "{\"error\":{\"code\":400000,\"message\":\"One of the request inputs is not valid.\"}}" + // But for now just verify response is a valid json + + std::stringstream stream(response["error_body"].asString()); + nlohmann::json root; + try + { + stream >> root; + } + catch(nlohmann::json::exception &e) + { + LL_DEBUGS("Translate") << "Failed to parse error_body:" << e.what() << LL_ENDL; + return false; + } + + return true; +} + // virtual -bool LLBingTranslationHandler::parseResponse( +bool LLAzureTranslationHandler::parseResponse( + const LLSD& http_response, int& status, const std::string& body, std::string& translation, @@ -487,65 +683,450 @@ bool LLBingTranslationHandler::parseResponse( { if (status != HTTP_OK) { - static const std::string MSG_BEGIN_MARKER = "Message: "; - size_t begin = body.find(MSG_BEGIN_MARKER); - if (begin != std::string::npos) - { - begin += MSG_BEGIN_MARKER.size(); - } - else - { - begin = 0; - err_msg.clear(); - } - size_t end = body.find("</p>", begin); - err_msg = body.substr(begin, end-begin); - LLStringUtil::replaceString(err_msg, "
", ""); // strip CR + if (http_response.has("error_body")) + err_msg = parseErrorResponse(http_response["error_body"].asString()); return false; } - // Sample response: <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hola</string> - size_t begin = body.find(">"); - if (begin == std::string::npos || begin >= (body.size() - 1)) + //Example: + // "[{\"detectedLanguage\":{\"language\":\"en\",\"score\":1.0},\"translations\":[{\"text\":\"Hello, what is your name?\",\"to\":\"en\"}]}]" + + nlohmann::json root; + try + { + root = nlohmann::json::parse(body); + } + catch(nlohmann::json::exception &e) { - begin = 0; + err_msg = e.what(); + return false; } - else + + if (!root.is_object() || !root.is_array()) // empty response? should not happen + { + return false; + } + + // Request succeeded, extract translation from the response. + + const nlohmann::json& data = root[0U]; + if (!data.is_object() + || data.find("detectedLanguage") == data.end() + || data.find("translations") == data.end()) + { + return false; + } + + const nlohmann::json& detectedLanguage = data["detectedLanguage"]; + if (!detectedLanguage.is_object() || detectedLanguage.find("language") == detectedLanguage.end()) + { + return false; + } + detected_lang = detectedLanguage["language"].get<std::string>(); + + const nlohmann::json& translations = data["translations"]; + if (!translations.is_array() || translations.size() == 0) + { + return false; + } + + const nlohmann::json& first = translations[0U]; + if (!first.is_object() || first.find("text") == first.end()) + { + return false; + } + + translation = first["text"].get<std::string>(); + + return true; +} + +// virtual +bool LLAzureTranslationHandler::isConfigured() const +{ + return getAPIKey().isMap(); +} + +//static +std::string LLAzureTranslationHandler::parseErrorResponse( + const std::string& body) +{ + // Expected: "{\"error\":{\"code\":400000,\"message\":\"One of the request inputs is not valid.\"}}" + // But for now just verify response is a valid json with an error + + nlohmann::json root; + try + { + root = nlohmann::json::parse(body); + } + catch(const nlohmann::json::exception&) { - ++begin; + return std::string(); } - size_t end = body.find("</string>", begin); + if (!root.is_object() || root.find("error") == root.end()) + { + return std::string(); + } - detected_lang.clear(); // unsupported by this API - translation = body.substr(begin, end-begin); - LLStringUtil::replaceString(translation, "
", ""); // strip CR - return true; + const nlohmann::json& error_map = root["error"]; + + if (!error_map.is_object() || error_map.find("message") == error_map.end()) + { + return std::string(); + } + + return error_map["message"].get<std::string>(); } +// static +LLSD LLAzureTranslationHandler::getAPIKey() +{ + static LLCachedControl<LLSD> azure_key(gSavedSettings, "AzureTranslateAPIKey"); + return azure_key; +} + +// static +std::string LLAzureTranslationHandler::getAPILanguageCode(const std::string& lang) +{ + return lang == "zh" ? "zh-CHT" : lang; // treat Chinese as Traditional Chinese +} + +/*virtual*/ +void LLAzureTranslationHandler::verifyKey(const LLSD &key, LLTranslate::KeyVerificationResult_fn fnc) +{ + LLCoros::instance().launch("Azure /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro, + this, LLTranslate::SERVICE_AZURE, key, fnc)); +} +/*virtual*/ +void LLAzureTranslationHandler::initHttpHeader( + LLCore::HttpHeaders::ptr_t headers, + const std::string& user_agent) const +{ + initHttpHeader(headers, user_agent, getAPIKey()); +} + +/*virtual*/ +void LLAzureTranslationHandler::initHttpHeader( + LLCore::HttpHeaders::ptr_t headers, + const std::string& user_agent, + const LLSD &key) const +{ + headers->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_JSON); + headers->append(HTTP_OUT_HEADER_USER_AGENT, user_agent); + + if (key.has("id")) + { + // Token based autorization + headers->append("Ocp-Apim-Subscription-Key", key["id"].asString()); + } + if (key.has("region")) + { + // ex: "westeurope" + headers->append("Ocp-Apim-Subscription-Region", key["region"].asString()); + } +} + +LLSD LLAzureTranslationHandler::sendMessageAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string & url, + const std::string & msg, + const std::string& from_lang, + const std::string& to_lang) const +{ + LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray); + LLCore::BufferArrayStream outs(rawbody.get()); + outs << "[{\"text\":\""; + outs << msg; + outs << "\"}]"; + + return adapter->postRawAndSuspend(request, url, rawbody, options, headers); +} + +LLSD LLAzureTranslationHandler::verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string & url) const +{ + LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray); + LLCore::BufferArrayStream outs(rawbody.get()); + outs << "[{\"intentionally_invalid_400\"}]"; + + return adapter->postRawAndSuspend(request, url, rawbody, options, headers); +} + +//========================================================================= +/// DeepL Translator API handler. +class LLDeepLTranslationHandler: public LLTranslationAPIHandler +{ + LOG_CLASS(LLDeepLTranslationHandler); + +public: + std::string getTranslateURL( + const std::string& from_lang, + const std::string& to_lang, + const std::string& text) const override; + std::string getKeyVerificationURL( + const LLSD& key) const override; + bool checkVerificationResponse( + const LLSD& response, + int status) const override; + bool parseResponse( + const LLSD& http_response, + int& status, + const std::string& body, + std::string& translation, + std::string& detected_lang, + std::string& err_msg) const override; + bool isConfigured() const override; + + LLTranslate::EService getCurrentService() override + { + return LLTranslate::EService::SERVICE_DEEPL; + } + + void verifyKey(const LLSD& key, LLTranslate::KeyVerificationResult_fn fnc) override; + + void initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent) const override; + void initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent, const LLSD& key) const override; + LLSD sendMessageAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string& url, + const std::string& msg, + const std::string& from_lang, + const std::string& to_lang) const override; + + LLSD verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string& url) const override; +private: + static std::string parseErrorResponse( + const std::string& body); + static LLSD getAPIKey(); + static std::string getAPILanguageCode(const std::string& lang); +}; + +//------------------------------------------------------------------------- // virtual -bool LLBingTranslationHandler::isConfigured() const +std::string LLDeepLTranslationHandler::getTranslateURL( + const std::string& from_lang, + const std::string& to_lang, + const std::string& text) const { - return !getAPIKey().empty(); + std::string url; + LLSD key = getAPIKey(); + if (key.isMap()) + { + url = key["domain"].asString(); + + if (*url.rbegin() != '/') + { + url += "/"; + } + url += std::string("v2/translate"); + } + return url; +} + + +// virtual +std::string LLDeepLTranslationHandler::getKeyVerificationURL( + const LLSD& key) const +{ + std::string url; + if (key.isMap()) + { + url = key["domain"].asString(); + + if (*url.rbegin() != '/') + { + url += "/"; + } + url += std::string("v2/translate"); + } + return url; +} + +//virtual +bool LLDeepLTranslationHandler::checkVerificationResponse( + const LLSD& response, + int status) const +{ + // Might need to parse body to make sure we got + // a valid response and not a message + return status == HTTP_OK; +} + +// virtual +bool LLDeepLTranslationHandler::parseResponse( + const LLSD& http_response, + int& status, + const std::string& body, + std::string& translation, + std::string& detected_lang, + std::string& err_msg) const +{ + if (status != HTTP_OK) + { + if (http_response.has("error_body")) + err_msg = parseErrorResponse(http_response["error_body"].asString()); + return false; + } + + //Example: + // "{\"translations\":[{\"detected_source_language\":\"EN\",\"text\":\"test\"}]}" + + nlohmann::json root; + try + { + root = nlohmann::json::parse(body); + } + catch(nlohmann::json::exception &e) + { + err_msg = e.what(); + return false; + } + + if (!root.is_object() + || root.find("translations") == root.end()) // empty response? should not happen + { + return false; + } + + // Request succeeded, extract translation from the response. + const nlohmann::json& translations = root["translations"]; + if (!translations.is_array() || translations.size() == 0) + { + return false; + } + + const nlohmann::json& data= translations[0U]; + if (!data.is_object() + || data.find("detected_source_language") == root.end() + || data.find("text") == root.end()) + { + return false; + } + + detected_lang = data["detected_source_language"].get<std::string>(); + LLStringUtil::toLower(detected_lang); + translation = data["text"].get<std::string>(); + + return true; +} + +// virtual +bool LLDeepLTranslationHandler::isConfigured() const +{ + return getAPIKey().isMap(); +} + +//static +std::string LLDeepLTranslationHandler::parseErrorResponse( + const std::string& body) +{ + // Example: "{\"message\":\"One of the request inputs is not valid.\"}" + nlohmann::json root; + try + { + root = nlohmann::json::parse(body); + } + catch(const nlohmann::json::exception &) + { + return {}; + } + + if (!root.is_object() || root.find("message") == root.end()) + { + return std::string(); + } + + return root["message"].get<std::string>(); } // static -std::string LLBingTranslationHandler::getAPIKey() +LLSD LLDeepLTranslationHandler::getAPIKey() { - return gSavedSettings.getString("BingTranslateAPIKey"); + static LLCachedControl<LLSD> deepl_key(gSavedSettings, "DeepLTranslateAPIKey"); + return deepl_key; } // static -std::string LLBingTranslationHandler::getAPILanguageCode(const std::string& lang) +std::string LLDeepLTranslationHandler::getAPILanguageCode(const std::string& lang) { - return lang == "zh" ? "zh-CHT" : lang; // treat Chinese as Traditional Chinese + return lang == "zh" ? "zh-CHT" : lang; // treat Chinese as Traditional Chinese +} + +/*virtual*/ +void LLDeepLTranslationHandler::verifyKey(const LLSD& key, LLTranslate::KeyVerificationResult_fn fnc) +{ + LLCoros::instance().launch("DeepL /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro, + this, LLTranslate::SERVICE_DEEPL, key, fnc)); +} +/*virtual*/ +void LLDeepLTranslationHandler::initHttpHeader( + LLCore::HttpHeaders::ptr_t headers, + const std::string& user_agent) const +{ + initHttpHeader(headers, user_agent, getAPIKey()); } /*virtual*/ -void LLBingTranslationHandler::verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc) +void LLDeepLTranslationHandler::initHttpHeader( + LLCore::HttpHeaders::ptr_t headers, + const std::string& user_agent, + const LLSD& key) const +{ + headers->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/x-www-form-urlencoded"); + headers->append(HTTP_OUT_HEADER_USER_AGENT, user_agent); + + if (key.has("id")) + { + std::string authkey = "DeepL-Auth-Key " + key["id"].asString(); + headers->append(HTTP_OUT_HEADER_AUTHORIZATION, authkey); + } +} + +LLSD LLDeepLTranslationHandler::sendMessageAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string& url, + const std::string& msg, + const std::string& from_lang, + const std::string& to_lang) const { - LLCoros::instance().launch("Bing /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro, - this, LLTranslate::SERVICE_BING, key, fnc)); + LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray); + LLCore::BufferArrayStream outs(rawbody.get()); + outs << "text="; + std::string escaped_string = LLURI::escape(msg); + outs << escaped_string; + outs << "&target_lang="; + std::string lang = to_lang; + LLStringUtil::toUpper(lang); + outs << lang; + + return adapter->postRawAndSuspend(request, url, rawbody, options, headers); +} + +LLSD LLDeepLTranslationHandler::verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter, + LLCore::HttpRequest::ptr_t request, + LLCore::HttpOptions::ptr_t options, + LLCore::HttpHeaders::ptr_t headers, + const std::string& url) const +{ + LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray); + LLCore::BufferArrayStream outs(rawbody.get()); + outs << "text=&target_lang=EN"; + + return adapter->postRawAndSuspend(request, url, rawbody, options, headers); } //========================================================================= @@ -572,58 +1153,78 @@ void LLTranslate::translateMessage(const std::string &from_lang, const std::stri std::string LLTranslate::addNoTranslateTags(std::string mesg) { - if (getPreferredHandler().getCurrentService() != SERVICE_BING) + if (getPreferredHandler().getCurrentService() == SERVICE_GOOGLE) + { + return mesg; + } + + if (getPreferredHandler().getCurrentService() == SERVICE_DEEPL) { return mesg; } - std::string upd_msg(mesg); - LLUrlMatch match; - S32 dif = 0; - //surround all links (including SLURLs) with 'no-translate' tags to prevent unnecessary translation - while (LLUrlRegistry::instance().findUrl(mesg, match)) + if (getPreferredHandler().getCurrentService() == SERVICE_AZURE) { - upd_msg.insert(dif + match.getStart(), BING_NOTRANSLATE_OPENING_TAG); - upd_msg.insert(dif + BING_NOTRANSLATE_OPENING_TAG.size() + match.getEnd() + 1, BING_NOTRANSLATE_CLOSING_TAG); - mesg.erase(match.getStart(), match.getEnd() - match.getStart()); - dif += match.getEnd() - match.getStart() + BING_NOTRANSLATE_OPENING_TAG.size() + BING_NOTRANSLATE_CLOSING_TAG.size(); + // https://learn.microsoft.com/en-us/azure/cognitive-services/translator/prevent-translation + std::string upd_msg(mesg); + LLUrlMatch match; + S32 dif = 0; + //surround all links (including SLURLs) with 'no-translate' tags to prevent unnecessary translation + while (LLUrlRegistry::instance().findUrl(mesg, match)) + { + upd_msg.insert(dif + match.getStart(), AZURE_NOTRANSLATE_OPENING_TAG); + upd_msg.insert(dif + AZURE_NOTRANSLATE_OPENING_TAG.size() + match.getEnd() + 1, AZURE_NOTRANSLATE_CLOSING_TAG); + mesg.erase(match.getStart(), match.getEnd() - match.getStart()); + dif += match.getEnd() - match.getStart() + AZURE_NOTRANSLATE_OPENING_TAG.size() + AZURE_NOTRANSLATE_CLOSING_TAG.size(); + } + return upd_msg; } - return upd_msg; + return mesg; } std::string LLTranslate::removeNoTranslateTags(std::string mesg) { - if (getPreferredHandler().getCurrentService() != SERVICE_BING) + if (getPreferredHandler().getCurrentService() == SERVICE_GOOGLE) { return mesg; } - std::string upd_msg(mesg); - LLUrlMatch match; - S32 opening_tag_size = BING_NOTRANSLATE_OPENING_TAG.size(); - S32 closing_tag_size = BING_NOTRANSLATE_CLOSING_TAG.size(); - S32 dif = 0; - //remove 'no-translate' tags we added to the links before - while (LLUrlRegistry::instance().findUrl(mesg, match)) + if (getPreferredHandler().getCurrentService() == SERVICE_DEEPL) { - if (upd_msg.substr(dif + match.getStart() - opening_tag_size, opening_tag_size) == BING_NOTRANSLATE_OPENING_TAG) - { - upd_msg.erase(dif + match.getStart() - opening_tag_size, opening_tag_size); - dif -= opening_tag_size; + return mesg; + } - if (upd_msg.substr(dif + match.getEnd() + 1, closing_tag_size) == BING_NOTRANSLATE_CLOSING_TAG) + if (getPreferredHandler().getCurrentService() == SERVICE_AZURE) + { + std::string upd_msg(mesg); + LLUrlMatch match; + S32 opening_tag_size = AZURE_NOTRANSLATE_OPENING_TAG.size(); + S32 closing_tag_size = AZURE_NOTRANSLATE_CLOSING_TAG.size(); + S32 dif = 0; + //remove 'no-translate' tags we added to the links before + while (LLUrlRegistry::instance().findUrl(mesg, match)) + { + if (upd_msg.substr(dif + match.getStart() - opening_tag_size, opening_tag_size) == AZURE_NOTRANSLATE_OPENING_TAG) { - upd_msg.replace(dif + match.getEnd() + 1, closing_tag_size, " "); - dif -= closing_tag_size - 1; + upd_msg.erase(dif + match.getStart() - opening_tag_size, opening_tag_size); + dif -= opening_tag_size; + + if (upd_msg.substr(dif + match.getEnd() + 1, closing_tag_size) == AZURE_NOTRANSLATE_CLOSING_TAG) + { + upd_msg.replace(dif + match.getEnd() + 1, closing_tag_size, " "); + dif -= closing_tag_size - 1; + } } + mesg.erase(match.getStart(), match.getUrl().size()); + dif += match.getUrl().size(); } - mesg.erase(match.getStart(), match.getUrl().size()); - dif += match.getUrl().size(); + return upd_msg; } - return upd_msg; + + return mesg; } /*static*/ -void LLTranslate::verifyKey(EService service, const std::string &key, KeyVerificationResult_fn fnc) +void LLTranslate::verifyKey(EService service, const LLSD &key, KeyVerificationResult_fn fnc) { LLTranslationAPIHandler& handler = getHandler(service); @@ -689,13 +1290,21 @@ LLSD LLTranslate::asLLSD() const // static LLTranslationAPIHandler& LLTranslate::getPreferredHandler() { - EService service = SERVICE_BING; + EService service = SERVICE_AZURE; std::string service_str = gSavedSettings.getString("TranslationService"); if (service_str == "google") { service = SERVICE_GOOGLE; } + if (service_str == "azure") + { + service = SERVICE_AZURE; + } + if (service_str == "deepl") + { + service = SERVICE_DEEPL; + } return getHandler(service); } @@ -704,12 +1313,19 @@ LLTranslationAPIHandler& LLTranslate::getPreferredHandler() LLTranslationAPIHandler& LLTranslate::getHandler(EService service) { static LLGoogleTranslationHandler google; - static LLBingTranslationHandler bing; + static LLAzureTranslationHandler azure; + static LLDeepLTranslationHandler deepl; - if (service == SERVICE_GOOGLE) - { - return google; - } + switch (service) + { + case SERVICE_AZURE: + return azure; + case SERVICE_GOOGLE: + return google; + case SERVICE_DEEPL: + return deepl; + } + + return azure; - return bing; } diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index 58707e2d3620e1c0f8b59d24be16f2f7a546b9b3..4a5d80737c022542ad02b9be1c913676a2f7dab2 100644 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -59,11 +59,12 @@ class LLTranslate: public LLSingleton<LLTranslate> public : typedef enum e_service { - SERVICE_BING, + SERVICE_AZURE, SERVICE_GOOGLE, + SERVICE_DEEPL, } EService; - typedef boost::function<void(EService, bool)> KeyVerificationResult_fn; + typedef boost::function<void(EService, bool, S32)> KeyVerificationResult_fn; typedef boost::function<void(std::string , std::string )> TranslationSuccess_fn; typedef boost::function<void(int, std::string)> TranslationFailure_fn; @@ -78,12 +79,12 @@ public : static void translateMessage(const std::string &from_lang, const std::string &to_lang, const std::string &mesg, TranslationSuccess_fn success, TranslationFailure_fn failure); /** - * Verify given API key of a translation service. - * - * @param receiver Object to pass verification result to. - * @param key Key to verify. - */ - static void verifyKey(EService service, const std::string &key, KeyVerificationResult_fn fnc); + * Verify given API key of a translation service. + * + * @param receiver Object to pass verification result to. + * @param key Key to verify. + */ + static void verifyKey(EService service, const LLSD &key, KeyVerificationResult_fn fnc); /** * @return translation target language diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 07577992a5d7c904510feb06bee6204948b86b66..efd820c5b4f265370bab98ff0c6d997bb9e4ed13 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1673,7 +1673,8 @@ bool LLViewerInput::scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) BOOL LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down) { - BOOL handled = gViewerWindow->handleAnyMouseClick(window_impl, pos, mask, clicktype, down); + bool is_toolmgr_action = false; + BOOL handled = gViewerWindow->handleAnyMouseClick(window_impl, pos, mask, clicktype, down, is_toolmgr_action); if (clicktype != CLICK_NONE) { @@ -1692,7 +1693,7 @@ BOOL LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, // If the first LMB click is handled by the menu, skip the following double click static bool skip_double_click = false; - if (clicktype == CLICK_LEFT && down ) + if (clicktype == CLICK_LEFT && down && !is_toolmgr_action) { skip_double_click = handled; } diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index a20b31b578cfa3ead8e7b2ac58f5ed0ada572e51..5bff3e17ff294db1a7723f14218c139b3105fa12 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -170,7 +170,7 @@ SimMeasurement<> SIM_TIME_DILATION("simtimedilation", "Simulator time scale", SIM_MAIN_AGENTS("simmainagents", "Number of avatars in current region", LL_SIM_STAT_NUMAGENTMAIN), SIM_CHILD_AGENTS("simchildagents", "Number of avatars in neighboring regions", LL_SIM_STAT_NUMAGENTCHILD), SIM_OBJECTS("simobjects", "", LL_SIM_STAT_NUMTASKS), - SIM_ACTIVE_OBJECTS("simactiveobjects", "Number of scripted and/or mocing objects", LL_SIM_STAT_NUMTASKSACTIVE), + SIM_ACTIVE_OBJECTS("simactiveobjects", "Number of scripted and/or moving objects", LL_SIM_STAT_NUMTASKSACTIVE), SIM_ACTIVE_SCRIPTS("simactivescripts", "Number of scripted objects", LL_SIM_STAT_NUMSCRIPTSACTIVE), SIM_IN_PACKETS_PER_SEC("siminpps", "", LL_SIM_STAT_INPPS), SIM_OUT_PACKETS_PER_SEC("simoutpps", "", LL_SIM_STAT_OUTPPS), diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 0783497d9b013d4d21fffd8e380c26fcc2616dd9..d47dd8ca29b4c52fd5ec92190e7fefd9e626555d 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -232,6 +232,8 @@ void LLViewerTextureList::doPrefetchImages() LLViewerTextureManager::getFetchedTexture(IMG_SHOT); LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF); + LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + LLViewerFetchedTexture::sSmokeImagep->setNoDelete(); LLStandardBumpmap::addstandard(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 2b494df9fb134d1ac390acc075eabd10eed66d97..cf4a51b292c9f9cbfed6d56f4598bbad15f774a1 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1061,7 +1061,7 @@ void LLViewerWindow::handlePieMenu(S32 x, S32 y, MASK mask) } } -BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down) +BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down, bool& is_toolmgr_action) { const char* buttonname = ""; const char* buttonstatestr = ""; @@ -1223,6 +1223,7 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK m LLViewerEventRecorder::instance().clear_xui(); } #endif + is_toolmgr_action = true; return TRUE; } diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 7f8107d81564c67a38d3308ee4317fe64b6340bc..6bd2c6a6eae85f142369e5136dbbf32977e27fca 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -180,7 +180,7 @@ class LLViewerWindow final : public LLWindowCallbacks void reshapeStatusBarContainer(); - BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down); + BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down, bool &is_toolmgr_action); // // LLWindowCallback interface implementation diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index bde67d6e03887f2d2d57eb73953cb230102ceeb0..3b04122393d40d335d8f8f5a2365f561d7dea389 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -276,13 +276,13 @@ static void killGateway() /////////////////////////////////////////////////////////////////////////////////////////////// bool LLVivoxVoiceClient::sShuttingDown = false; +bool LLVivoxVoiceClient::sConnected = false; +LLPumpIO *LLVivoxVoiceClient::sPump = nullptr; LLVivoxVoiceClient::LLVivoxVoiceClient() : mSessionTerminateRequested(false), mRelogRequested(false), - mConnected(false), mTerminateDaemon(false), - mPump(NULL), mSpatialJoiningNum(0), mTuningMode(false), @@ -351,7 +351,11 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() : mIsProcessingChannels(false), mIsCoroutineActive(false), mVivoxPump("vivoxClientPump") -{ +{ + sShuttingDown = false; + sConnected = false; + sPump = nullptr; + mSpeakerVolume = scale_speaker_volume(0); mVoiceVersion.serverVersion = ""; @@ -397,7 +401,7 @@ LLVivoxVoiceClient::~LLVivoxVoiceClient() void LLVivoxVoiceClient::init(LLPumpIO *pump) { // constructor will set up LLVoiceClient::getInstance() - mPump = pump; + sPump = pump; // LLCoros::instance().launch("LLVivoxVoiceClient::voiceControlCoro", // boost::bind(&LLVivoxVoiceClient::voiceControlCoro, LLVivoxVoiceClient::getInstance())); @@ -418,10 +422,10 @@ void LLVivoxVoiceClient::terminate() logoutOfVivox(false); } - if(mConnected) + if(sConnected) { breakVoiceConnection(false); - mConnected = false; + sConnected = false; } else { @@ -430,7 +434,7 @@ void LLVivoxVoiceClient::terminate() } sShuttingDown = true; - mPump = NULL; + sPump = NULL; } //--------------------------------------------------- @@ -476,7 +480,7 @@ bool LLVivoxVoiceClient::writeString(const std::string &str) bool result = false; LL_DEBUGS("LowVoice") << "sending:\n" << str << LL_ENDL; - if(mConnected) + if(sConnected) { apr_status_t err; apr_size_t size = (apr_size_t)str.size(); @@ -1113,7 +1117,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() int retryCount(0); LLVoiceVivoxStats::getInstance()->reset(); - while (!mConnected && !sShuttingDown && retryCount++ <= DAEMON_CONNECT_RETRY_MAX) + while (!sConnected && !sShuttingDown && retryCount++ <= DAEMON_CONNECT_RETRY_MAX) { LLVoiceVivoxStats::getInstance()->connectionAttemptStart(); LL_DEBUGS("Voice") << "Attempting to connect to vivox daemon: " << mDaemonHost << LL_ENDL; @@ -1123,23 +1127,23 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); } - mConnected = mSocket->blockingConnect(mDaemonHost); - LLVoiceVivoxStats::getInstance()->connectionAttemptEnd(mConnected); - if (!mConnected) + sConnected = mSocket->blockingConnect(mDaemonHost); + LLVoiceVivoxStats::getInstance()->connectionAttemptEnd(sConnected); + if (!sConnected) { llcoro::suspendUntilTimeout(DAEMON_CONNECT_THROTTLE_SECONDS); } } //--------------------------------------------------------------------- - if (sShuttingDown && !mConnected) + if (sShuttingDown && !sConnected) { return false; } llcoro::suspendUntilTimeout(UPDATE_THROTTLE_SECONDS); - while (!mPump && !sShuttingDown) + while (!sPump && !sShuttingDown) { // Can't use the pump until we have it available. llcoro::suspend(); } @@ -1161,7 +1165,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() readChain.push_back(LLIOPipe::ptr_t(new LLVivoxProtocolParser())); - mPump->addChain(readChain, NEVER_CHAIN_EXPIRY_SECS); + sPump->addChain(readChain, NEVER_CHAIN_EXPIRY_SECS); //--------------------------------------------------------------------- @@ -1383,9 +1387,9 @@ bool LLVivoxVoiceClient::breakVoiceConnection(bool corowait) // the message, yet we need to receive "connector shutdown response". // Either wait a bit and emulate it or check gMessageSystem for specific message _sleep(1000); - if (mConnected) + if (sConnected) { - mConnected = false; + sConnected = false; LLSD vivoxevent(LLSDMap("connector", LLSD::Boolean(false))); mVivoxPump.post(vivoxevent); } @@ -1397,7 +1401,7 @@ bool LLVivoxVoiceClient::breakVoiceConnection(bool corowait) LL_DEBUGS("Voice") << "closing SLVoice socket" << LL_ENDL; closeSocket(); // Need to do this now -- bad things happen if the destructor does it later. cleanUp(); - mConnected = false; + sConnected = false; return retval; } @@ -2576,7 +2580,7 @@ bool LLVivoxVoiceClient::performMicTuning() void LLVivoxVoiceClient::closeSocket(void) { mSocket.reset(); - mConnected = false; + sConnected = false; mConnectorEstablished = false; mAccountLoggedIn = false; } @@ -3084,7 +3088,7 @@ bool LLVivoxVoiceClient::deviceSettingsAvailable() { bool result = true; - if(!mConnected) + if(!sConnected) result = false; if(mRenderDevices.empty()) @@ -3904,7 +3908,7 @@ void LLVivoxVoiceClient::connectorShutdownResponse(int statusCode, std::string & // Should this ever fail? do we care if it does? } - mConnected = false; + sConnected = false; mShutdownComplete = true; LLSD vivoxevent(LLSDMap("connector", LLSD::Boolean(false))); @@ -7486,7 +7490,7 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl( LL_DEBUGS("VivoxProtocolParser") << "at end, mInput is: " << mInput << LL_ENDL; #endif - if(!LLVivoxVoiceClient::getInstance()->mConnected) + if(!LLVivoxVoiceClient::sConnected) { // If voice has been disabled, we just want to close the socket. This does so. LL_INFOS("Voice") << "returning STATUS_STOP" << LL_ENDL; diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 7b4c71bedae6a46924a6aa5c7b0e84ab49fcaec9..e635ef3889a79a6336c06c84df378e059d97b79e 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -672,12 +672,10 @@ class LLVivoxVoiceClient final : public LLSingleton<LLVivoxVoiceClient>, LLHost mDaemonHost; LLSocket::ptr_t mSocket; - bool mConnected; // We should kill the voice daemon in case of connection alert bool mTerminateDaemon; - LLPumpIO *mPump; friend class LLVivoxProtocolParser; std::string mAccountName; @@ -922,7 +920,10 @@ class LLVivoxVoiceClient final : public LLSingleton<LLVivoxVoiceClient>, bool mIsProcessingChannels; bool mIsCoroutineActive; - static bool sShuttingDown; // corutines can last longer than vivox so we need a static variable as a shutdown flag + // This variables can last longer than vivox in coroutines so we need them as static + static bool sShuttingDown; + static bool sConnected; + static LLPumpIO* sPump; LLEventMailDrop mVivoxPump; }; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index cca0c75c3ff023180fef816d7fdb5bb67e2f4d6f..18a6c2f06777c6a93878fa7dc51c41326d5e6c0f 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5338,13 +5338,14 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, if (mat) { + BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) || (facep->getTextureEntry()->getColor().mV[3] < 0.999f) ? TRUE : FALSE; if (type == LLRenderPass::PASS_ALPHA) { - shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND); + shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND, is_alpha); } else { - shader_mask = mat->getShaderMask(); + shader_mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_DEFAULT, is_alpha); } } @@ -5833,15 +5834,20 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } else { - if (te->getColor().mV[3] > 0.f || te->getGlow() > 0.f) - { //only treat as alpha in the pipeline if < 100% transparent - drawablep->setState(LLDrawable::HAS_ALPHA); - add_face(sAlphaFaces, alpha_count, facep); - } - else if (LLDrawPoolAlpha::sShowDebugAlpha) - { - add_face(sAlphaFaces, alpha_count, facep); - } + if (te->getColor().mV[3] > 0.f || te->getGlow() > 0.f) + { //only treat as alpha in the pipeline if < 100% transparent + drawablep->setState(LLDrawable::HAS_ALPHA); + add_face(sAlphaFaces, alpha_count, facep); + } + else if (LLDrawPoolAlpha::sShowDebugAlpha || + (gPipeline.sRenderHighlight && !drawablep->getParent() && + //only root objects are highlighted with red color in this case + drawablep->getVObj() && drawablep->getVObj()->flagScripted() && + (LLPipeline::getRenderScriptedBeacons() || + (LLPipeline::getRenderScriptedTouchBeacons() && drawablep->getVObj()->flagHandleTouch())))) + { //draw the transparent face for debugging purposes using a custom texture + add_face(sAlphaFaces, alpha_count, facep); + } } } else @@ -6595,7 +6601,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { // HACK - this should never happen, but sometimes we get a material that thinks it has alpha blending when it ought not alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE; } - U32 mask = mat->getShaderMask(alpha_mode); + U32 mask = mat->getShaderMask(alpha_mode, is_alpha); U32 vb_mask = facep->getVertexBuffer()->getTypeMask(); diff --git a/indra/newview/skins/default/textures/icons/profile_badge_beta.png b/indra/newview/skins/default/textures/icons/profile_badge_beta.png new file mode 100644 index 0000000000000000000000000000000000000000..7c8a723c47f4f0e2cb981a36e90be707d0e53af8 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/profile_badge_beta.png differ diff --git a/indra/newview/skins/default/textures/icons/profile_badge_beta_lifetime.png b/indra/newview/skins/default/textures/icons/profile_badge_beta_lifetime.png new file mode 100644 index 0000000000000000000000000000000000000000..7c38e9e2aee25fa181401e38ac6138ac135f9a4e Binary files /dev/null and b/indra/newview/skins/default/textures/icons/profile_badge_beta_lifetime.png differ diff --git a/indra/newview/skins/default/textures/icons/profile_badge_lifetime.png b/indra/newview/skins/default/textures/icons/profile_badge_lifetime.png new file mode 100644 index 0000000000000000000000000000000000000000..475edd080ef5037f7dd43f1b2978d379e9506aff Binary files /dev/null and b/indra/newview/skins/default/textures/icons/profile_badge_lifetime.png differ diff --git a/indra/newview/skins/default/textures/icons/profile_badge_linden.png b/indra/newview/skins/default/textures/icons/profile_badge_linden.png new file mode 100644 index 0000000000000000000000000000000000000000..1b6ac03e868b7d05a674cb4ccda822833165ed24 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/profile_badge_linden.png differ diff --git a/indra/newview/skins/default/textures/icons/profile_badge_pplus_lifetime.png b/indra/newview/skins/default/textures/icons/profile_badge_pplus_lifetime.png new file mode 100644 index 0000000000000000000000000000000000000000..42869952020c8a952b5c2d2b18fab9c4fd3aecda Binary files /dev/null and b/indra/newview/skins/default/textures/icons/profile_badge_pplus_lifetime.png differ diff --git a/indra/newview/skins/default/textures/icons/profile_badge_premium_lifetime.png b/indra/newview/skins/default/textures/icons/profile_badge_premium_lifetime.png new file mode 100644 index 0000000000000000000000000000000000000000..47e93c4fac777f2b4422a892694d1560ba9248bd Binary files /dev/null and b/indra/newview/skins/default/textures/icons/profile_badge_premium_lifetime.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 348b0cd118e88b7d705b9cea25a1de47624eae44..9372ec897d7715b1b17e7ce0fdb784967bedbfbb 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -535,7 +535,13 @@ with the same filename but different name <texture name="Play_Off" file_name="icons/Play_Off.png" preload="false" /> <texture name="Play_Over" file_name="icons/Play_Over.png" preload="false" /> <texture name="Play_Press" file_name="icons/Play_Press.png" preload="false" /> - + + <texture name="Profile_Badge_Beta" file_name="icons/profile_badge_beta.png" preload="true"/> + <texture name="Profile_Badge_Beta_Lifetime" file_name="icons/profile_badge_beta_lifetime.png" preload="true"/> + <texture name="Profile_Badge_Lifetime" file_name="icons/profile_badge_lifetime.png" preload="true"/> + <texture name="Profile_Badge_Linden" file_name="icons/profile_badge_linden.png" preload="true"/> + <texture name="Profile_Badge_Pplus_Lifetime" file_name="icons/profile_badge_pplus_lifetime.png" preload="true"/> + <texture name="Profile_Badge_Premium_Lifetime" file_name="icons/profile_badge_premium_lifetime.png" preload="true"/> <texture name="Profile_Group_Visibility_Off" file_name="icons/profile_group_visibility_eye_off.png" preload="true"/> <texture name="Profile_Group_Visibility_Off_Pressed" file_name="icons/profile_group_visibility_eye_off_pressed.png" preload="true"/> <texture name="Profile_Group_Visibility_On" file_name="icons/profile_group_visibility_eye_on.png" preload="true"/> diff --git a/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml b/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml index 37efbe654e6a80e69658a94ea1bd4e6f6fab01e8..b757f4eab80863313f1c2ec18c21273b56e055a7 100644 --- a/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml @@ -414,7 +414,7 @@ name="frame_stats" label="Frame breakdown" show_label="true"> - <stat_bar name="packet_loss" + <stat_bar name="scenery_frame_pct" label="Scenery" orientation="horizontal" unit_label=" %" @@ -422,7 +422,7 @@ bar_max="100" tick_spacing="0.5" show_bar="false"/> - <stat_bar name="packet_loss" + <stat_bar name="avatar_frame_pct" label="Avatar" orientation="horizontal" unit_label=" %" @@ -430,7 +430,7 @@ bar_max="100" tick_spacing="0.5" show_bar="false"/> - <stat_bar name="packet_loss" + <stat_bar name="ui_frame_pct" label="UI" orientation="horizontal" unit_label=" %" @@ -438,7 +438,7 @@ bar_max="100" tick_spacing="0.5" show_bar="false"/> - <stat_bar name="packet_loss" + <stat_bar name="huds_frame_pct" label="HUDs" orientation="horizontal" unit_label=" %" @@ -446,7 +446,7 @@ bar_max="100" tick_spacing="0.5" show_bar="false"/> - <stat_bar name="packet_loss" + <stat_bar name="swap_frame_pct" label="Swap" orientation="horizontal" unit_label=" %" @@ -454,7 +454,7 @@ bar_max="100" tick_spacing="0.5" show_bar="false"/> - <stat_bar name="packet_loss" + <stat_bar name="idle_frame_pct" label="Tasks" orientation="horizontal" unit_label=" %" diff --git a/indra/newview/skins/default/xui/en/floater_translation_settings.xml b/indra/newview/skins/default/xui/en/floater_translation_settings.xml index a212ce78891f66412ca0a2af19aac111f03dfdac..3f3331b468af6cf720fa25f6ca39ff31d63bac2a 100644 --- a/indra/newview/skins/default/xui/en/floater_translation_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_translation_settings.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" - height="310" + height="470" layout="topleft" name="floater_translation_settings" help_topic="translation_settings" @@ -9,11 +9,13 @@ title="CHAT TRANSLATION SETTINGS" width="485"> - <string name="bing_api_key_not_verified">Bing appID not verified. Please try again.</string> - <string name="google_api_key_not_verified">Google API key not verified. Please try again.</string> + <string name="azure_api_key_not_verified">Azure service identifier not verified. Status: [STATUS]. Please check your settings and try again.</string> + <string name="google_api_key_not_verified">Google API key not verified. Status: [STATUS]. Please check your key and try again.</string> + <string name="deepl_api_key_not_verified">DeepL Auth Key key not verified. Status: [STATUS]. Please check your key and try again.</string> - <string name="bing_api_key_verified">Bing appID verified.</string> + <string name="azure_api_key_verified">Azure service identifier verified.</string> <string name="google_api_key_verified">Google API key verified.</string> + <string name="deepl_api_key_verified">DeepL API key verified.</string> <check_box height="16" @@ -128,25 +130,86 @@ <radio_group follows="top|left" - height="80" + height="260" layout="topleft" left_delta="10" name="translation_service_rg" top_pad="20" width="320"> <radio_item - initial_value="bing" - label="Bing Translator" + initial_value="azure" + label="Azure Translator" layout="topleft" - name="bing" /> + name="azure" /> <radio_item initial_value="google" label="Google Translate" layout="topleft" name="google" - top_pad="55" /> + top_pad="115" /> + <radio_item + initial_value="deepl" + label="DeepL Translator" + layout="topleft" + name="deepl" + top_pad="61" /> </radio_group> + <text + follows="top|right" + height="20" + layout="topleft" + left="185" + length="1" + name="google_links_text" + top_pad="-262" + type="string" + width="100"> + [https://learn.microsoft.com/en-us/azure/cognitive-services/translator/create-translator-resource Setup] + </text> + + <text + type="string" + length="1" + follows="top|right" + height="20" + layout="topleft" + left="70" + name="azure_api_endoint_label" + top_pad="8" + width="85"> + Endpoint: + </text> + + <combo_box + allow_text_entry="true" + follows="left|top" + name="azure_api_endpoint_combo" + height="23" + left_pad="10" + right="-10" + top_delta="-4" + max_chars="512" + value="https://api.cognitive.microsofttranslator.com" + combo_button.scale_image="true"> + <combo_box.item + label="https://api.cognitive.microsofttranslator.com" + name="global" + value="https://api.cognitive.microsofttranslator.com" /> + <combo_box.item + label="https://api-apc.cognitive.microsofttranslator.com" + name="api-apc" + value="https://api-apc.cognitive.microsofttranslator.com" /> + <combo_box.item + label="https://api-eur.cognitive.microsofttranslator.com" + name="api-eur" + value="https://api-eur.cognitive.microsofttranslator.com" /> + <combo_box.item + label="https://api-nam.cognitive.microsofttranslator.com" + name="api-nam" + value="https://api-nam.cognitive.microsofttranslator.com" /> + </combo_box> + <text type="string" length="1" @@ -154,30 +217,52 @@ height="20" layout="topleft" left="70" - name="bing_api_key_label" - top_pad="-55" + name="azure_api_key_label" + top_pad="10" width="85"> - Bing [http://www.bing.com/developers/createapp.aspx AppID]: + Azure Key: </text> <line_editor - default_text="Enter Bing AppID and click "Verify"" + default_text="Enter Translator Key and click "Verify"" follows="top|left" height="20" layout="topleft" left_pad="10" max_length_chars="50" top_delta="-4" - name="bing_api_key" + name="azure_api_key" width="210" /> - <button - follows="left|top" - height="23" - label="Verify" - layout="topleft" - left_pad="10" - name="verify_bing_api_key_btn" - top_delta="-2" - width="90" /> + <text + type="string" + length="1" + follows="top|right" + height="20" + layout="topleft" + left="70" + name="azure_api_region_label" + top_pad="11" + width="85"> + Region: + </text> + <line_editor + default_text="Can be left empty for global services" + follows="top|left" + height="20" + layout="topleft" + left_pad="10" + max_length_chars="50" + top_delta="-4" + name="azure_api_region" + width="210" /> + <button + follows="left|top" + height="23" + label="Verify" + layout="topleft" + left_pad="10" + name="verify_azure_api_key_btn" + top_delta="-2" + width="90" /> <text follows="top|right" @@ -186,7 +271,7 @@ left="70" length="1" name="google_api_key_label" - top_pad="50" + top_pad="53" type="string" width="85"> Google [http://code.google.com/apis/language/translate/v2/getting_started.html#auth API key]: @@ -209,7 +294,7 @@ left_pad="10" name="verify_google_api_key_btn" top_delta="-2" - width="90" /> + width="90" /> <text follows="top|right" @@ -224,6 +309,87 @@ [http://code.google.com/apis/language/translate/v2/pricing.html Pricing] | [https://code.google.com/apis/console Stats] </text> + <text + type="string" + length="1" + follows="top|right" + height="20" + layout="topleft" + left="70" + name="deepl_api_domain_label" + top_pad="80" + width="85"> + Endpoint: + </text> + + <combo_box + allow_text_entry="false" + follows="left|top" + name="deepl_api_domain_combo" + height="23" + left_pad="10" + width="140" + top_delta="-4" + max_chars="512" + value="https://api-free.deepl.com" + combo_button.scale_image="true"> + <combo_box.item + label="DeepL Free" + name="global" + value="https://api-free.deepl.com" /> + <combo_box.item + label="DeepL Pro" + name="api-apc" + value="https://api.deepl.com" /> + </combo_box> + + <text + follows="top|right" + height="20" + layout="topleft" + left="70" + length="1" + name="deepl_api_key_label" + top_pad="11" + type="string" + width="85"> + DeepL API key: + </text> + + <line_editor + default_text="Enter DeepL API key and click "Verify"" + follows="top|left" + height="20" + layout="topleft" + left_pad="10" + max_length_chars="50" + top_delta="-4" + name="deepl_api_key" + width="210" /> + + <button + follows="left|top" + height="23" + label="Verify" + layout="topleft" + left_pad="10" + name="verify_deepl_api_key_btn" + top_delta="-2" + width="90" /> + + <text + follows="top|right" + height="20" + layout="topleft" + left="185" + length="1" + name="deepl_links_text" + top_delta="-53" + type="string" + width="100"> + [https://www.deepl.com/pro/select-country?cta=header-prices Pricing] + </text> + <button follows="left|top" height="23" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 53a0bc4515617690adbcd770177347e9b794067f..7b833e2cf1a0b252e510b9d450b7f0b11a9216c1 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -192,7 +192,7 @@ No tutorial is currently available. icon="alertmodal.tga" name="BadInstallation" type="alertmodal"> - An error occurred while updating [APP_NAME]. Please [https://www.alchemyviewer.org/pages/downloads.html download the latest version] of the Viewer. + An error occurred while updating [APP_NAME]. Please [https://www.alchemyviewer.org/downloads download the latest version] of the Viewer. <tag>fail</tag> <usetemplate name="okbutton" @@ -4322,7 +4322,7 @@ Finished download of raw terrain file to: name="RequiredUpdate" type="alertmodal"> Version [VERSION] is required for login. -Please download from https://www.alchemyviewer.org/pages/downloads.html +Please download from https://www.alchemyviewer.org/downloads <tag>confirm</tag> <usetemplate name="okbutton" @@ -6517,6 +6517,14 @@ Your trash is overflowing. This may cause problems logging in. yestext="Check trash folder"/> </notification> + <notification + icon="notifytip.tga" + name="InventoryLimitReachedAIS" + type="notifytip"> +Your inventory is experiencing issues. Please, contact support. + <tag>fail</tag> + </notification> + <notification icon="alertmodal.tga" name="ConfirmClearBrowserCache" diff --git a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml index 777b37d66675dcae63d5b23bd6906c3a43574810..cb6c1aec4d50a0e9830fde2008c57ffffd197c20 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml @@ -27,7 +27,33 @@ Account: [ACCTTYPE] [PAYMENTINFO] </string> - + + <!--Badges--> + <string + name="BadgeBeta" + value="Original Beta Tester" /> + <string + name="BadgeBetaLifetime" + value="Beta Lifetime member" /> + <string + name="BadgeLifetime" + value="Lifetime member" /> + <string + name="BadgeLinden" + value="Linden Lab employee" /> + <string + name="BadgePremiumLifetime" + value="Premium lifetime" /> + <string + name="BadgePremiumPlusLifetime" + value="Premium Plus lifetime" /> + <string + name="BadgePremium" + value="Premium" /> + <string + name="BadgePremiumPlus" + value="Premium Plus" /> + <layout_stack name="image_stack" top="8" @@ -156,9 +182,39 @@ Account: [ACCTTYPE] user_resize="false" visible="true"> </layout_panel> - + + <layout_panel + name="badge_layout" + follows="all" + layout="topleft" + height="40" + auto_resize="false" + user_resize="false" + visible="false"> + <icon + name="badge_icon" + image_name="Beta_Tester" + layout="topleft" + follows="left|top" + top="10" + left="5" + height="18" + width="18"/> + <text + name="badge_text" + value="Badge Tester" + top="13" + left_pad="3" + right="-1" + height="16" + follows="left|top|right" + layout="topleft" + translate="false" + visible="true"/> + </layout_panel> + <layout_panel - name="frind_layout" + name="friend_layout" follows="all" layout="topleft" height="16" @@ -166,7 +222,7 @@ Account: [ACCTTYPE] user_resize="false" visible="false"> <text - name="frind_text" + name="friend_text" value="You are friends" text_color="ConversationFriendColor" top="0" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index eae7dcb5590fc65c8741a2febec9d05299101a53..9df960a5a98a2ef53ee90913ca5217ea5a4dfee3 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -144,10 +144,9 @@ Voice Server Version: [VOICE_VERSION] <string name="AgniGridLabel">Second Life Main Grid (Agni)</string> <string name="AditiGridLabel">Second Life Beta Test Grid (Aditi)</string> - <string name="ViewerDownloadURL">https://www.alchemyviewer.org/pages/downloads.html</string> + <string name="ViewerDownloadURL">https://www.alchemyviewer.org/downloads</string> <string name="LoginFailedViewerNotPermitted"> - The viewer you are using can no longer access [CURRENT_GRID]. Please visit the following page to download a new viewer: -https://www.alchemyviewer.org/pages/downloads.html</string> + The viewer you are using can no longer access [CURRENT_GRID]. Please visit the following page to download a new viewer: https://www.alchemyviewer.org/downloads</string> <string name="LoginFailed">"Login process did not complete due to system issues. Try again in a few minutes. If you feel this is an error, please contact support.</string> <string name="LoginIntermediateOptionalUpdateAvailable">Optional viewer update available: [VERSION]</string> diff --git a/indra/newview/skins/default/xui/pt/panel_edit_hair.xml b/indra/newview/skins/default/xui/pt/panel_edit_hair.xml index 13f1f892f99811ab1d462a0656063695d63ab278..e9750a1c2e14690b13310473bdc458ed26e4a8ad 100644 --- a/indra/newview/skins/default/xui/pt/panel_edit_hair.xml +++ b/indra/newview/skins/default/xui/pt/panel_edit_hair.xml @@ -7,7 +7,7 @@ <accordion name="wearable_accordion"> <accordion_tab name="hair_color_tab" title="Cor"/> <accordion_tab name="hair_style_tab" title="Estilo"/> - <accordion_tab name="hair_eyebrows_tab" title="Sombrancelhas"/> + <accordion_tab name="hair_eyebrows_tab" title="Sobrancelhas"/> <accordion_tab name="hair_facial_tab" title="Faciais"/> </accordion> </panel>