diff options
131 files changed, 2474 insertions, 1180 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index 7509245ac3..e764e89e35 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1187,6 +1187,7 @@ PanteraPolnocy SL-18891 SL-18904 SL-18937 + SL-19681 Parvati Silverweb Patric Mills VWR-2645 @@ -1411,6 +1412,7 @@ Sovereign Engineer SL-18497 SL-18525 SL-18534 + SL-19336 SpacedOut Frye VWR-34 VWR-45 diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index 6720f902bd..3cef382bbf 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -1391,6 +1391,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" @@ -1621,6 +1623,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo rCurve->mKeys[time] = rot_key; } + 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 //--------------------------------------------------------------------- @@ -1723,9 +1731,24 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo } } + 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 //------------------------------------------------------------------------- @@ -2005,10 +2028,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); @@ -2028,7 +2054,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 54020a4231..ef4899978e 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -39,7 +39,6 @@ set(llcommon_SOURCE_FILES lldependencies.cpp lldictionary.cpp llerror.cpp - llerrorthread.cpp llevent.cpp lleventapi.cpp lleventcoro.cpp @@ -151,7 +150,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 d839b19c99..90d0c28eb1 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" @@ -105,15 +104,9 @@ BOOL LLApp::sLogInSignal = FALSE; // Keeps track of application status LLScalarCond<LLApp::EAppStatus> LLApp::sStatus{LLApp::APP_STATUS_STOPPED}; LLAppErrorHandler LLApp::sErrorHandler = NULL; -BOOL LLApp::sErrorThreadRunning = FALSE; -LLApp::LLApp() : mThreadErrorp(NULL) -{ - commonCtor(); -} - -void LLApp::commonCtor() +LLApp::LLApp() { // Set our status to running setStatus(APP_STATUS_RUNNING); @@ -143,12 +136,6 @@ void LLApp::commonCtor() mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe"; } -LLApp::LLApp(LLErrorThread *error_thread) : - mThreadErrorp(error_thread) -{ - commonCtor(); -} - LLApp::~LLApp() { @@ -158,13 +145,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); } @@ -393,27 +373,6 @@ void LLApp::setupErrorHandling(bool second_instance) #endif // ! LL_BUGSPLAT #endif // ! LL_WINDOWS - -#ifdef LL_BUGSPLAT - // do not start our own error thread -#else // ! LL_BUGSPLAT - 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) @@ -476,7 +435,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); } @@ -827,13 +786,8 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) return; } - // Flag status to ERROR, so thread_error does its work. + // Flag status to ERROR LLApp::setError(); - // Block in the signal handler until somebody says that we're done. - while (LLApp::sErrorThreadRunning && !LLApp::isStopped()) - { - ms_sleep(10); - } if (LLApp::sLogInSignal) { diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index c65fe21c9c..a892bfeb1e 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 @@ public: 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 @@ public: 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. char *getMiniDumpFilename() { return mMinidumpPath; } @@ -298,7 +291,6 @@ protected: static void setStatus(EAppStatus status); // Use this to change the application status. static LLScalarCond<EAppStatus> sStatus; // Reflects current application status - static BOOL sErrorThreadRunning; // Set while the error thread is running static BOOL sDisableCrashlogger; // Let the OS handle crashes for us. std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting. @@ -310,13 +302,11 @@ protected: void stepFrame(); private: - void startErrorThread(); - // Contains the filename of the minidump file after a crash. char mMinidumpPath[MAX_MINDUMP_PATH_LENGTH]; - 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 @@ -324,9 +314,6 @@ private: 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 d06c0e2132..020f05e8f5 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -274,7 +274,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 4f8f0a88ad..0000000000 --- a/indra/llcommon/llerrorthread.cpp +++ /dev/null @@ -1,131 +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) -{ -} - -LLErrorThread::~LLErrorThread() -{ -} - -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 474cef3a50..0000000000 --- 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 : public LLThread -{ -public: - LLErrorThread(); - ~LLErrorThread(); - - /*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/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index d5adf11264..22bbff4478 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -21,11 +21,12 @@ #include "llevents.h" #include "stringize.h" -LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity): +LL::ThreadPool::ThreadPool(const std::string& name, size_t threads, size_t capacity, bool auto_shutdown): super(name), mQueue(name, capacity), mName("ThreadPool:" + name), - mThreadCount(threads) + mThreadCount(threads), + mAutomaticShutdown(auto_shutdown) {} void LL::ThreadPool::start() @@ -39,6 +40,13 @@ void LL::ThreadPool::start() run(tname); }); } + + // Some threads might need to run longer than LLEventPumps + if (!mAutomaticShutdown) + { + return; + } + // Listen on "LLApp", and when the app is shutting down, close the queue // and join the workers. LLEventPumps::instance().obtain("LLApp").listen( diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h index f8eec3b457..22c875edb9 100644 --- a/indra/llcommon/threadpool.h +++ b/indra/llcommon/threadpool.h @@ -31,7 +31,7 @@ namespace LL * Pass ThreadPool a string name. This can be used to look up the * relevant WorkQueue. */ - ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024); + ThreadPool(const std::string& name, size_t threads=1, size_t capacity=1024, bool auto_shutdown = true); virtual ~ThreadPool(); /** @@ -66,6 +66,7 @@ namespace LL std::string mName; size_t mThreadCount; std::vector<std::pair<std::string, std::thread>> mThreads; + bool mAutomaticShutdown; }; } // namespace LL diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 66bd85f4e6..a2e85cf6c2 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -552,7 +552,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 a219ac1450..fa22145972 100644 --- a/indra/llprimitive/llmaterial.cpp +++ b/indra/llprimitive/llmaterial.cpp @@ -426,18 +426,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 d58b7ee812..d92ef1dfba 100644 --- a/indra/llprimitive/llmaterial.h +++ b/indra/llprimitive/llmaterial.h @@ -126,7 +126,7 @@ public: 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); protected: LLUUID mNormalID; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 1bf061bc8d..6f4f2ec62c 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -494,7 +494,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; @@ -517,12 +517,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]; @@ -539,8 +542,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 3b58a37d33..93c6b78ce8 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -138,7 +138,7 @@ public: 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 9dc140b5b9..465f30a343 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -859,9 +859,16 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32 stop_glerror(); if (prev_mip_data) - delete[] 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/llcontainerview.cpp b/indra/llui/llcontainerview.cpp index 727fbe850e..1c33088e8d 100644 --- a/indra/llui/llcontainerview.cpp +++ b/indra/llui/llcontainerview.cpp @@ -288,7 +288,7 @@ void LLContainerView::setLabel(const std::string& label) mLabel = label; } -void LLContainerView::setDisplayChildren(const BOOL displayChildren) +void LLContainerView::setDisplayChildren(BOOL displayChildren) { mDisplayChildren = displayChildren; for (child_list_const_iter_t child_iter = getChildList()->begin(); diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h index 99267d978a..8e75aaef6e 100644 --- a/indra/llui/llcontainerview.h +++ b/indra/llui/llcontainerview.h @@ -78,7 +78,7 @@ public: void setLabel(const std::string& label); void showLabel(BOOL show) { mShowLabel = show; } - void setDisplayChildren(const BOOL displayChildren); + void setDisplayChildren(BOOL displayChildren); BOOL getDisplayChildren() { return mDisplayChildren; } void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;} diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index eba93beed9..e2b5279aab 100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -395,7 +395,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height ) // it is purely visual, so it is fine to do at our laisure refreshSuffix(); } - mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight; + mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + mLabelPaddingRight; mLabelWidthDirty = false; } diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index e01aba402e..2791377a5e 100644 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -37,6 +37,8 @@ #include "lluiimage.h" #include "llwindow.h" +#include "llgltexture.h" + static LLDefaultChildRegistry::Register<LLIconCtrl> r("icon"); LLIconCtrl::Params::Params() @@ -94,6 +96,22 @@ BOOL LLIconCtrl::handleHover(S32 x, S32 y, MASK mask) return LLUICtrl::handleHover(x, y, mask); } +void LLIconCtrl::onVisibilityChange(BOOL new_visibility) +{ + LLUICtrl::onVisibilityChange(new_visibility); + if (mPriority == LLGLTexture::BOOST_ICON) + { + if (new_visibility) + { + loadImage(getValue(), mPriority); + } + else + { + mImagep = nullptr; + } + } +} + // virtual // value might be a string or a UUID void LLIconCtrl::setValue(const LLSD& value) @@ -110,6 +128,14 @@ void LLIconCtrl::setValue(const LLSD& value, S32 priority) tvalue = LLSD(LLUUID(value.asString())); } LLUICtrl::setValue(tvalue); + + loadImage(tvalue, priority); +} + +void LLIconCtrl::loadImage(const LLSD& tvalue, S32 priority) +{ + if(mPriority == LLGLTexture::BOOST_ICON && !getVisible()) return; + if (tvalue.isUUID()) { mImagep = LLUI::getUIImageByID(tvalue.asUUID(), priority); diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h index 9c3b517bca..5d6c544571 100644 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -72,6 +72,7 @@ public: virtual BOOL handleHover(S32 x, S32 y, MASK mask); // lluictrl overrides + void onVisibilityChange(BOOL new_visibility); virtual void setValue(const LLSD& value ); std::string getImageName() const; @@ -95,6 +96,8 @@ protected: bool mInteractable; private: + void loadImage(const LLSD& value, S32 priority); + LLUIColor mColor; LLPointer<LLUIImage> mImagep; }; diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 69e338ddb9..341ddb83f3 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -479,7 +479,7 @@ LLTrace::BlockTimerStatHandle FTM_SYNTAX_COLORING("Syntax Coloring"); // Walk through a string, applying the rules specified by the keyword token list and // create a list of color segments. -void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLWString& wtext, const LLColor4 &defaultColor, LLTextEditor& editor) +void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLWString& wtext, LLTextEditor& editor, LLStyleConstSP style) { LL_RECORD_BLOCK_TIME(FTM_SYNTAX_COLORING); seg_list->clear(); @@ -491,7 +491,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW S32 text_len = wtext.size() + 1; - seg_list->push_back( new LLNormalTextSegment( defaultColor, 0, text_len, editor ) ); + seg_list->push_back( new LLNormalTextSegment( style, 0, text_len, editor ) ); const llwchar* base = wtext.c_str(); const llwchar* cur = base; @@ -501,9 +501,9 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW { if( *cur == '\n' ) { - LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(cur-base); + LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, cur-base); text_segment->setToken( 0 ); - insertSegment( *seg_list, text_segment, text_len, defaultColor, editor); + insertSegment( *seg_list, text_segment, text_len, style, editor); cur++; if( !*cur || *cur == '\n' ) { @@ -541,7 +541,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW S32 seg_end = cur - base; //create segments from seg_start to seg_end - insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor); + insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, style, editor); line_done = TRUE; // to break out of second loop. break; } @@ -648,7 +648,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead(); } - insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, defaultColor, editor); + insertSegments(wtext, *seg_list,cur_delimiter, text_len, seg_start, seg_end, style, editor); /* LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_delimiter->getColor(), seg_start, seg_end, editor ); text_segment->setToken( cur_delimiter ); @@ -682,7 +682,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW // LL_INFOS("SyntaxLSL") << "Seg: [" << word.c_str() << "]" << LL_ENDL; - insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, defaultColor, editor); + insertSegments(wtext, *seg_list,cur_token, text_len, seg_start, seg_end, style, editor); } cur += seg_len; continue; @@ -697,30 +697,32 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW } } -void LLKeywords::insertSegments(const LLWString& wtext, std::vector<LLTextSegmentPtr>& seg_list, LLKeywordToken* cur_token, S32 text_len, S32 seg_start, S32 seg_end, const LLColor4 &defaultColor, LLTextEditor& editor ) +void LLKeywords::insertSegments(const LLWString& wtext, std::vector<LLTextSegmentPtr>& seg_list, LLKeywordToken* cur_token, S32 text_len, S32 seg_start, S32 seg_end, LLStyleConstSP style, LLTextEditor& editor ) { std::string::size_type pos = wtext.find('\n',seg_start); + + LLStyleConstSP cur_token_style = new LLStyle(LLStyle::Params().font(style->getFont()).color(cur_token->getColor())); while (pos!=-1 && pos < (std::string::size_type)seg_end) { if (pos!=seg_start) { - LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, pos, editor ); + LLTextSegmentPtr text_segment = new LLNormalTextSegment(cur_token_style, seg_start, pos, editor); text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + insertSegment( seg_list, text_segment, text_len, style, editor); } - LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(pos); + LLTextSegmentPtr text_segment = new LLLineBreakTextSegment(style, pos); text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + insertSegment( seg_list, text_segment, text_len, style, editor); seg_start = pos+1; pos = wtext.find('\n',seg_start); } - LLTextSegmentPtr text_segment = new LLNormalTextSegment( cur_token->getColor(), seg_start, seg_end, editor ); + LLTextSegmentPtr text_segment = new LLNormalTextSegment(cur_token_style, seg_start, seg_end, editor); text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor, editor); + insertSegment( seg_list, text_segment, text_len, style, editor); } void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor, LLTextEditor& editor ) @@ -744,6 +746,27 @@ void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSe } } +void LLKeywords::insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, LLStyleConstSP style, LLTextEditor& editor ) +{ + LLTextSegmentPtr last = seg_list.back(); + S32 new_seg_end = new_segment->getEnd(); + + if( new_segment->getStart() == last->getStart() ) + { + seg_list.pop_back(); + } + else + { + last->setEnd( new_segment->getStart() ); + } + seg_list.push_back( new_segment ); + + if( new_seg_end < text_len ) + { + seg_list.push_back( new LLNormalTextSegment( style, new_seg_end, text_len, editor ) ); + } +} + #ifdef _DEBUG void LLKeywords::dump() { diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index 18e2ed06c5..2410fe7d5a 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -29,6 +29,7 @@ #include "lldir.h" +#include "llstyle.h" #include "llstring.h" #include "v3color.h" #include "v4color.h" @@ -115,8 +116,8 @@ public: void findSegments(std::vector<LLTextSegmentPtr> *seg_list, const LLWString& text, - const LLColor4 &defaultColor, - class LLTextEditor& editor); + class LLTextEditor& editor, + LLStyleConstSP style); void initialize(LLSD SyntaxXML); void processTokens(); @@ -181,9 +182,11 @@ protected: S32 text_len, S32 seg_start, S32 seg_end, - const LLColor4 &defaultColor, + LLStyleConstSP style, LLTextEditor& editor); + void insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, LLStyleConstSP style, LLTextEditor& editor ); + bool mLoaded; LLSD mSyntax; word_token_map_t mWordTokenMap; diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 77938edf27..ae9dba5945 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -282,6 +282,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)); @@ -289,12 +300,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 f772dbc6b4..22f11eb20f 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -67,6 +67,7 @@ public: 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 d29781cf33..73ac72ac56 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1774,7 +1774,8 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p) mNeedsArrange(FALSE), mAlwaysShowMenu(FALSE), mResetScrollPositionOnShow(true), - mShortcutPad(p.shortcut_pad) + mShortcutPad(p.shortcut_pad), + mFont(p.font) { typedef boost::tokenizer<boost::char_separator<char> > tokenizer; boost::char_separator<char> sep("_"); @@ -1879,6 +1880,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 @@ -3626,6 +3634,7 @@ BOOL LLMenuBarGL::appendMenu( LLMenuGL* menu ) p.disabled_color=LLUIColorTable::instance().getColor("MenuItemDisabledColor"); p.highlight_bg_color=LLUIColorTable::instance().getColor("MenuItemHighlightBgColor"); p.highlight_fg_color=LLUIColorTable::instance().getColor("MenuItemHighlightFgColor"); + p.font = menu->getFont(); LLMenuItemBranchDownGL* branch = LLUICtrlFactory::create<LLMenuItemBranchDownGL>(p); success &= branch->addToAcceleratorList(&mAccelerators); diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index f84c4d41eb..8194501f79 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -442,6 +442,7 @@ public: /*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(); @@ -554,7 +555,9 @@ public: // add a context menu branch BOOL appendContextSubMenu(LLMenuGL *menu); -protected: + const LLFontGL *getFont() const { return mFont; } + + protected: void createSpilloverBranch(); void cleanupSpilloverBranch(); // Add the menu item to this menu. @@ -586,6 +589,9 @@ protected: BOOL mKeepFixedSize; BOOL mNeedsArrange; + // Font for top menu items only + const LLFontGL* mFont; + private: diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index b8f47ef6ba..8018365d3e 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -127,6 +127,7 @@ public: 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/llstatview.cpp b/indra/llui/llstatview.cpp index bb4969c81f..03f2fb7cc0 100644 --- a/indra/llui/llstatview.cpp +++ b/indra/llui/llstatview.cpp @@ -58,10 +58,7 @@ LLStatView::~LLStatView() } } - static StatViewRegistry::Register<LLStatBar> r1("stat_bar"); static StatViewRegistry::Register<LLStatView> r2("stat_view"); // stat_view can be a child of panels/etc. static LLDefaultChildRegistry::Register<LLStatView> r3("stat_view"); - - diff --git a/indra/llui/llstatview.h b/indra/llui/llstatview.h index af4db7d7ea..044f0a8679 100644 --- a/indra/llui/llstatview.h +++ b/indra/llui/llstatview.h @@ -63,7 +63,7 @@ protected: friend class LLUICtrlFactory; protected: - std::string mSetting; - + const std::string mSetting; }; + #endif // LL_STATVIEW_ diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 82a3c01c6d..26a38bd541 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -361,7 +361,7 @@ void LLTextBase::onValueChange(S32 start, S32 end) { } -std::vector<LLRect> LLTextBase::getSelctionRects() +std::vector<LLRect> LLTextBase::getSelectionRects() { // Nor supposed to be called without selection llassert(hasSelection()); @@ -458,7 +458,7 @@ void LLTextBase::drawSelectionBackground() // Draw selection even if we don't have keyboard focus for search/replace if (hasSelection() && !mLineInfoList.empty()) { - std::vector<LLRect> selection_rects = getSelctionRects(); + std::vector<LLRect> selection_rects = getSelectionRects(); // 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); @@ -1356,9 +1356,9 @@ void LLTextBase::draw() drawCursor(); } - mDocumentView->setVisible(FALSE); + mDocumentView->setVisibleDirect(FALSE); LLUICtrl::draw(); - mDocumentView->setVisible(TRUE); + mDocumentView->setVisibleDirect(TRUE); } @@ -3431,7 +3431,7 @@ BOOL LLNormalTextSegment::handleToolTip(S32 x, S32 y, MASK mask) if (mToken && !mToken->getToolTip().empty()) { const LLWString& wmsg = mToken->getToolTip(); - LLToolTipMgr::instance().show(wstring_to_utf8str(wmsg)); + LLToolTipMgr::instance().show(wstring_to_utf8str(wmsg), (mToken->getType() == LLKeywordToken::TT_FUNCTION)); return TRUE; } // or do we have an explicitly set tooltip (e.g., for Urls) @@ -3464,7 +3464,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 e3cf56a5ee..3611ab0499 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -638,7 +638,7 @@ protected: return mLabel.getString() + getToolTip(); } - std::vector<LLRect> getSelctionRects(); + std::vector<LLRect> getSelectionRects(); protected: // text segmentation and flow diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index c567451973..521dabf9d4 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -171,7 +171,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/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3d2a426913..c83ed4c3e1 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1779,7 +1779,8 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask ) else { if (mEnableTooltipPaste && - LLToolTipMgr::instance().toolTipVisible() && + LLToolTipMgr::instance().toolTipVisible() && + LLToolTipMgr::instance().isTooltipPastable() && KEY_TAB == key) { // Paste the first line of a tooltip into the editor std::string message; diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 2f56a8b1d0..c4b132317f 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -154,7 +154,8 @@ LLToolTip::Params::Params() text_color("text_color"), time_based_media("time_based_media", false), web_based_media("web_based_media", false), - media_playing("media_playing", false) + media_playing("media_playing", false), + allow_paste_tooltip("allow_paste_tooltip", false) { changeDefault(chrome, true); } @@ -166,7 +167,8 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p) mTextBox(NULL), mInfoButton(NULL), mPlayMediaButton(NULL), - mHomePageButton(NULL) + mHomePageButton(NULL), + mIsTooltipPastable(p.allow_paste_tooltip) { LLTextBox::Params params; params.name = params.initial_value().asString(); @@ -308,6 +310,8 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p) mTextBox->reshape(mTextBox->getRect().getWidth(), llmax(mTextBox->getRect().getHeight(), tooltip_rect.getHeight() - 2 * mPadding)); setShape(tooltip_rect); + + mIsTooltipPastable = p.allow_paste_tooltip; } void LLToolTip::setVisible(BOOL visible) @@ -469,9 +473,9 @@ void LLToolTipMgr::createToolTip(const LLToolTip::Params& params) } -void LLToolTipMgr::show(const std::string& msg) +void LLToolTipMgr::show(const std::string& msg, bool allow_paste_tooltip) { - show(LLToolTip::Params().message(msg)); + show(LLToolTip::Params().message(msg).allow_paste_tooltip(allow_paste_tooltip)); } void LLToolTipMgr::show(const LLToolTip::Params& params) @@ -612,5 +616,13 @@ void LLToolTipMgr::getToolTipMessage(std::string & message) } } +bool LLToolTipMgr::isTooltipPastable() +{ + if (toolTipVisible()) + { + return mToolTip->isTooltipPastable(); + } + return false; + } // EOF diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h index 0b1fbe5367..6ff7c0671a 100644 --- a/indra/llui/lltooltip.h +++ b/indra/llui/lltooltip.h @@ -91,6 +91,8 @@ public: padding; Optional<bool> wrap; + Optional<bool> allow_paste_tooltip; + Params(); }; /*virtual*/ void draw(); @@ -106,6 +108,7 @@ public: void initFromParams(const LLToolTip::Params& params); void getToolTipMessage(std::string & message); + bool isTooltipPastable() { return mIsTooltipPastable; } private: class LLTextBox* mTextBox; @@ -117,6 +120,8 @@ private: LLFrameTimer mVisibleTimer; bool mHasClickCallback; S32 mPadding; // pixels + + bool mIsTooltipPastable; }; // used for the inspector tooltips which need different background images etc. @@ -134,7 +139,7 @@ class LLToolTipMgr : public LLSingleton<LLToolTipMgr> public: void show(const LLToolTip::Params& params); - void show(const std::string& message); + void show(const std::string& message, bool allow_paste_tooltip = false); void unblockToolTips(); void blockToolTips(); @@ -146,6 +151,7 @@ public: void updateToolTipVisibility(); void getToolTipMessage(std::string & message); + bool isTooltipPastable(); private: void createToolTip(const LLToolTip::Params& params); diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp index 244f0c6f00..096336045c 100644 --- a/indra/llui/lluicolortable.cpp +++ b/indra/llui/lluicolortable.cpp @@ -200,7 +200,6 @@ LLUIColor LLUIColorTable::getColor(const std::string& name, const LLColor4& defa void LLUIColorTable::setColor(const std::string& name, const LLColor4& color) { setColor(name, color, mUserSetColors); - setColor(name, color, mLoadedColors); } bool LLUIColorTable::loadFromSettings() @@ -229,6 +228,11 @@ void LLUIColorTable::saveUserSettings() const it != mUserSetColors.end(); ++it) { + // Compare user color value with the default value, skip if equal + string_color_map_t::const_iterator itd = mLoadedColors.find(it->first); + if(itd != mLoadedColors.end() && itd->second == it->second) + continue; + ColorEntryParams color_entry; color_entry.name = it->first; color_entry.color.value = it->second; diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 9ba71913d0..3344300635 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/llui/llview.h b/indra/llui/llview.h index bec45df78a..8aa97aac39 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -287,6 +287,7 @@ public: void setAllChildrenEnabled(BOOL b); virtual void setVisible(BOOL visible); + void setVisibleDirect(BOOL visible) { mVisible = visible; } const BOOL& getVisible() const { return mVisible; } virtual void setEnabled(BOOL enabled); BOOL getEnabled() const { return mEnabled; } diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 4380bbdb73..ac4848579f 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -118,7 +118,8 @@ public: // 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/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 2e560ddb0a..01e38fcc9d 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -828,6 +828,7 @@ void LLWindowWin32::close() // Is window is already closed? if (!mWindowHandle) { + mWindowThread->close(); return; } @@ -4590,7 +4591,7 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList() #endif // LL_WINDOWS inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread() - : ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE) + : ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, false) { ThreadPool::start(); } diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 97154f804c..e9d5f8c17f 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.6.13 +6.6.14 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index af486653a5..23e97ebad1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5420,6 +5420,17 @@ <key>Value</key> <string>http://wiki.secondlife.com/wiki/[LSL_STRING]</string> </map> + <key>LSLFontSizeName</key> + <map> + <key>Comment</key> + <string>Text font size in LSL editor</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>Monospace</string> + </map> <key>GridStatusRSS</key> <map> <key>Comment</key> @@ -7474,10 +7485,21 @@ <key>Value</key> <integer>1</integer> </map> + <key>OpenDebugStatBasic</key> + <map> + <key>Comment</key> + <string>Expand Basic performance stats display</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>OpenDebugStatAdvanced</key> <map> <key>Comment</key> - <string>Expand advanced performance stats display</string> + <string>Expand Advanced performance stats display</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -7485,10 +7507,10 @@ <key>Value</key> <integer>0</integer> </map> - <key>OpenDebugStatBasic</key> + <key>OpenDebugStatRender</key> <map> <key>Comment</key> - <string>Expand basic performance stats display</string> + <string>Expand Render performance stats display</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -7496,10 +7518,21 @@ <key>Value</key> <integer>1</integer> </map> - <key>OpenDebugStatNet</key> + <key>OpenDebugStatTexture</key> <map> <key>Comment</key> - <string>Expand network stats display</string> + <string>Expand Texture performance stats display</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>OpenDebugStatMemory</key> + <map> + <key>Comment</key> + <string>Expand Memory Usage stats display</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -7507,10 +7540,10 @@ <key>Value</key> <integer>1</integer> </map> - <key>OpenDebugStatRender</key> + <key>OpenDebugStatNet</key> <map> <key>Comment</key> - <string>Expand render stats display</string> + <string>Expand Network performance stats display</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -7521,7 +7554,7 @@ <key>OpenDebugStatSim</key> <map> <key>Comment</key> - <string>Expand simulator performance stats display</string> + <string>Expand Simulator performance stats display</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -7529,10 +7562,10 @@ <key>Value</key> <integer>1</integer> </map> - <key>OpenDebugStatTexture</key> + <key>OpenDebugStatPhysicsDetails</key> <map> <key>Comment</key> - <string>Expand Texture performance stats display</string> + <string>Expand Physics Details performance stats display</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -7540,10 +7573,10 @@ <key>Value</key> <integer>0</integer> </map> - <key>OpenDebugStatPhysicsDetails</key> + <key>OpenDebugStatPathfinding</key> <map> <key>Comment</key> - <string>Expand Physics Details performance stats display</string> + <string>Expand Pathfinding performance stats display</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -12973,13 +13006,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> @@ -12995,7 +13028,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> @@ -13003,6 +13036,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 8235e4466c..e9ba0550b0 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2945,13 +2945,14 @@ bool LLAppViewer::initConfiguration() if (mSecondInstance) { - // This is the second instance of SL. Turn off voice support, + // This is the second instance of SL. Mute voice, // but make sure the setting is *not* persisted. - LLControlVariable* disable_voice = gSavedSettings.getControl("CmdLineDisableVoice"); - if(disable_voice) + // Also see LLVivoxVoiceClient::voiceEnabled() + LLControlVariable* enable_voice = gSavedSettings.getControl("EnableVoiceChat"); + if(enable_voice) { const BOOL DO_NOT_PERSIST = FALSE; - disable_voice->setValue(LLSD(TRUE), DO_NOT_PERSIST); + enable_voice->setValue(LLSD(FALSE), DO_NOT_PERSIST); } } @@ -3582,8 +3583,6 @@ void LLAppViewer::writeSystemInfo() // "CrashNotHandled" is set here, while things are running well, // in case of a freeze. If there is a freeze, the crash logger will be launched // and can read this value from the debug_info.log. - // If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze, - // then the value of "CrashNotHandled" will be set to true. gDebugInfo["CrashNotHandled"] = LLSD::Boolean(true); #else // LL_BUGSPLAT // "CrashNotHandled" is obsolete; it used (not very successsfully) @@ -3675,163 +3674,6 @@ void getFileList() } #endif -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 - - char *minidump_file = pApp->getMiniDumpFilename(); - LL_DEBUGS("CRASHREPORT") << "minidump file name " << minidump_file << LL_ENDL; - if(minidump_file && minidump_file[0] != 0) - { - gDebugInfo["Dynamic"]["MinidumpPath"] = minidump_file; - } - else - { -#ifdef LL_WINDOWS - getFileList(); -#else - LL_WARNS("CRASHREPORT") << "no minidump file?" << LL_ENDL; -#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 f28a90c703..bc4dec6bec 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -119,7 +119,6 @@ public: virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism. // return false if the error trap needed restoration. - 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 dc487967fc..9f58f90326 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -80,8 +80,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 cb5cac6f2d..8b313a321b 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -83,8 +83,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 d22fb7a4e6..298d841934 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -428,8 +428,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 f778634d25..10cde35f9c 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -85,6 +85,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/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 594cfe513d..3fd15d36df 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -402,7 +402,7 @@ void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL t if(pparams->mFace) { LLViewerObject* vobj = pparams->mFace->getViewerObject(); - if(vobj->isAttachment()) + if(vobj && vobj->isAttachment()) { trackAttachments(vobj, false, &ratPtr); } @@ -429,7 +429,7 @@ void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, U32 mask, if(pparams->mFace) { LLViewerObject* vobj = pparams->mFace->getViewerObject(); - if(vobj->isAttachment()) + if(vobj && vobj->isAttachment()) { trackAttachments( vobj, true ,&ratPtr); } @@ -459,7 +459,7 @@ void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_text if(pparams->mFace) { LLViewerObject* vobj = pparams->mFace->getViewerObject(); - if(vobj->isAttachment()) + if(vobj && vobj->isAttachment()) { trackAttachments( vobj, false, &ratPtr); } @@ -484,7 +484,7 @@ void LLRenderPass::pushRiggedBatches(U32 type, U32 mask, BOOL texture, BOOL batc if(pparams->mFace) { LLViewerObject* vobj = pparams->mFace->getViewerObject(); - if(vobj->isAttachment()) + if(vobj && vobj->isAttachment()) { trackAttachments( vobj, true, &ratPtr); } @@ -514,7 +514,7 @@ void LLRenderPass::pushMaskBatches(U32 type, U32 mask, BOOL texture, BOOL batch_ if((*pparams).mFace) { LLViewerObject* vobj = (*pparams).mFace->getViewerObject(); - if(vobj->isAttachment()) + if(vobj && vobj->isAttachment()) { trackAttachments( vobj, false, &ratPtr); } @@ -539,7 +539,7 @@ void LLRenderPass::pushRiggedMaskBatches(U32 type, U32 mask, BOOL texture, BOOL if((*pparams).mFace) { LLViewerObject* vobj = (*pparams).mFace->getViewerObject(); - if(vobj->isAttachment()) + if(vobj && vobj->isAttachment()) { trackAttachments( vobj, true, &ratPtr); } diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 5b205d373b..ab1ac7e30c 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -281,6 +281,8 @@ void LLDrawPoolAlpha::renderDebugAlpha() { gHighlightProgram.bind(); gGL.diffuseColor4f(1, 0, 0, 1); + + LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f * 1024.f); gGL.getTexUnit(0)->bindFast(LLViewerFetchedTexture::sSmokeImagep); @@ -347,7 +349,7 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) if(params.mFace) { LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); - if(vobj->isAttachment()) + if(vobj && vobj->isAttachment()) { trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); } @@ -620,7 +622,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) { LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject(); - if(vobj->isAttachment()) + if(vobj && vobj->isAttachment()) { trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr ); } diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index cdce6f7156..c1d8828229 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -320,6 +320,7 @@ public: if (item) { + LLFavoritesBarCtrl::sWaitingForCallabck = 0.f; LLFavoritesOrderStorage::instance().setSortIndex(item, mSortField); item->setComplete(TRUE); @@ -365,6 +366,9 @@ struct LLFavoritesSort } }; + +F64 LLFavoritesBarCtrl::sWaitingForCallabck = 0.f; + LLFavoritesBarCtrl::Params::Params() : image_drag_indication("image_drag_indication"), more_button("more_button"), @@ -381,7 +385,7 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p) mShowDragMarker(FALSE), mLandingTab(NULL), mLastTab(NULL), - mTabsHighlightEnabled(TRUE), + mItemsListDirty(false), mUpdateDropDownItems(true), mRestoreOverflowMenu(false), mGetPrevItems(true), @@ -618,6 +622,9 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con int sortField = 0; LLPointer<LLItemCopiedCallback> cb; + const F64 CALLBACK_WAIT_TIME = 30.f; + sWaitingForCallabck = LLTimer::getTotalSeconds() + CALLBACK_WAIT_TIME; + // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field for (LLInventoryModel::item_array_t::iterator i = mItems.begin(); i != mItems.end(); ++i) { @@ -691,16 +698,22 @@ void LLFavoritesBarCtrl::changed(U32 mask) LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID()); } - updateButtons(); - if (!mItemsChangedTimer.getStarted()) - { - mItemsChangedTimer.start(); - } - else - { - mItemsChangedTimer.reset(); - } - + if (sWaitingForCallabck < LLTimer::getTotalSeconds()) + { + updateButtons(); + if (!mItemsChangedTimer.getStarted()) + { + mItemsChangedTimer.start(); + } + else + { + mItemsChangedTimer.reset(); + } + } + else + { + mItemsListDirty = true; + } } } @@ -754,6 +767,18 @@ void LLFavoritesBarCtrl::draw() mItemsChangedTimer.start(); } + if (mItemsListDirty && sWaitingForCallabck < LLTimer::getTotalSeconds()) + { + updateButtons(); + if (!mItemsChangedTimer.getStarted()) + { + mItemsChangedTimer.start(); + } + else + { + mItemsChangedTimer.reset(); + } + } } const LLButton::Params& LLFavoritesBarCtrl::getButtonParams() @@ -782,6 +807,7 @@ void LLFavoritesBarCtrl::updateButtons(bool force_update) return; } + mItemsListDirty = false; mItems.clear(); if (!collectFavoriteItems(mItems)) diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 3b439b31fd..68a679e27f 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -53,6 +53,7 @@ public: protected: LLFavoritesBarCtrl(const Params&); friend class LLUICtrlFactory; + friend class LLItemCopiedCallback; public: virtual ~LLFavoritesBarCtrl(); @@ -84,7 +85,6 @@ protected: void onButtonRightClick(LLUUID id,LLView* button,S32 x,S32 y,MASK mask); void onButtonMouseDown(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); - void onOverflowMenuItemMouseDown(LLUUID id, LLUICtrl* item, S32 x, S32 y, MASK mask); void onButtonMouseUp(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); void onEndDrag(); @@ -164,7 +164,8 @@ private: BOOL mStartDrag; LLInventoryModel::item_array_t mItems; - BOOL mTabsHighlightEnabled; + static F64 sWaitingForCallabck; + bool mItemsListDirty; S32 mMouseX; S32 mMouseY; diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index b61afcbbc9..f1f156c2e0 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -55,9 +55,6 @@ LLFilePicker LLFilePicker::sInstance; #define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0" #define ANIM_FILTER L"Animations (*.bvh; *.anim)\0*.bvh;*.anim\0" #define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0" -#ifdef _CORY_TESTING -#define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0" -#endif #define XML_FILTER L"XML files (*.xml)\0*.xml\0" #define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0" #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0" @@ -197,12 +194,6 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter) mOFN.lpstrFilter = COLLADA_FILTER \ L"\0"; break; -#ifdef _CORY_TESTING - case FFLOAD_GEOMETRY: - mOFN.lpstrFilter = GEOMETRY_FILTER \ - L"\0"; - break; -#endif case FFLOAD_XML: mOFN.lpstrFilter = XML_FILTER \ L"\0"; @@ -498,18 +489,6 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, L"XAF Anim File (*.xaf)\0*.xaf\0" \ L"\0"; break; -#ifdef _CORY_TESTING - case FFSAVE_GEOMETRY: - if (filename.empty()) - { - wcsncpy( mFilesW,L"untitled.slg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ - } - mOFN.lpstrDefExt = L"slg"; - mOFN.lpstrFilter = - L"SLG SL Geometry File (*.slg)\0*.slg\0" \ - L"\0"; - break; -#endif case FFSAVE_XML: if (filename.empty()) { @@ -652,11 +631,6 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF case FFLOAD_COLLADA: allowedv->push_back("dae"); break; -#ifdef _CORY_TESTING - case FFLOAD_GEOMETRY: - allowedv->push_back("slg"); - break; -#endif case FFLOAD_XML: allowedv->push_back("xml"); break; @@ -771,14 +745,6 @@ void set_nav_save_data(LLFilePicker::ESaveFilter filter, std::string &extension, creator = "\?\?\?\?"; extension = "xaf"; break; - -#ifdef _CORY_TESTING - case LLFilePicker::FFSAVE_GEOMETRY: - type = "\?\?\?\?"; - creator = "\?\?\?\?"; - extension = "slg"; - break; -#endif case LLFilePicker::FFSAVE_XML: type = "\?\?\?\?"; diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 26649e0940..692b908fff 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -77,9 +77,6 @@ public: FFLOAD_WAV = 2, FFLOAD_IMAGE = 3, FFLOAD_ANIM = 4, -#ifdef _CORY_TESTING - FFLOAD_GEOMETRY = 5, -#endif FFLOAD_XML = 6, FFLOAD_SLOBJECT = 7, FFLOAD_RAW = 8, @@ -99,9 +96,6 @@ public: FFSAVE_BMP = 5, FFSAVE_AVI = 6, FFSAVE_ANIM = 7, -#ifdef _CORY_TESTING - FFSAVE_GEOMETRY = 8, -#endif FFSAVE_XML = 9, FFSAVE_COLLADA = 10, FFSAVE_RAW = 11, diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index f1807f1c5b..0d2c6d8e4c 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -108,6 +108,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/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 4cd91c53d8..eb7bd843d3 100644 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -522,6 +522,8 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, // errors in separate window. if (chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG) { + if (LLFloater::isQuitRequested()) return; + if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) return; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 78271369d2..af4e7f5aff 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() @@ -934,10 +936,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); @@ -962,6 +967,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 9f00917647..d478922617 100644 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -152,6 +152,7 @@ protected: bool mMessagePaneExpanded; bool mIsParticipantListExpanded; + S32 mMinFloaterHeight; LLIMModel::LLIMSession* mSession; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 9ea49e935f..42b1c87314 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -114,6 +114,7 @@ #include "llpresetsmanager.h" #include "llviewercontrol.h" #include "llpresetsmanager.h" +#include "llinventoryfunctions.h" #include "llsearchableui.h" #include "llperfstats.h" @@ -1609,25 +1610,6 @@ void LLFloaterPreference::onChangeMaturity() getChild<LLIconCtrl>("rating_icon_adult")->setVisible(sim_access == SIM_ACCESS_ADULT); } -std::string get_category_path(LLUUID cat_id) -{ - LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); - std::string localized_cat_name; - if (!LLTrans::findString(localized_cat_name, "InvFolder " + cat->getName())) - { - localized_cat_name = cat->getName(); - } - - if (cat->getParentUUID().notNull()) - { - return get_category_path(cat->getParentUUID()) + " > " + localized_cat_name; - } - else - { - return localized_cat_name; - } -} - std::string get_category_path(LLFolderType::EType cat_type) { LLUUID cat_id = gInventory.findUserDefinedCategoryUUIDForType(cat_type); diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index da7a4733c7..7f50a2f0cc 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -144,7 +144,7 @@ public: const LLUUID& invoice, const sparam_t& strings); - LLSD getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ); + static LLSD getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ); }; @@ -317,7 +317,6 @@ void LLFloaterRegionInfo::onOpen(const LLSD& key) } refreshFromRegion(gAgent.getRegion()); requestRegionInfo(); - requestMeshRezInfo(); if (!mGodLevelChangeSlot.connected()) { @@ -1006,19 +1005,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 @@ -2464,11 +2450,12 @@ bool LLDispatchSetEstateAccess::operator()( return true; } +// static LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_t::const_iterator end, S32 count ) { LLSD idList = LLSD::emptyArray(); LLUUID id; - while(count--> 0) + while (count-- > 0 && it < end) { memcpy(id.mData, (*(it++)).data(), UUID_BYTES); idList.append(id); @@ -2482,7 +2469,7 @@ LLSD LLDispatchSetEstateExperience::getIDs( sparam_t::const_iterator it, sparam_ // strings[2] = str(num blocked) // strings[3] = str(num trusted) // strings[4] = str(num allowed) -// strings[8] = bin(uuid) ... +// strings[5] = bin(uuid) ... // ... bool LLDispatchSetEstateExperience::operator()( const LLDispatcher* dispatcher, @@ -2491,23 +2478,30 @@ bool LLDispatchSetEstateExperience::operator()( const sparam_t& strings) { LLPanelRegionExperiences* panel = LLFloaterRegionInfo::getPanelExperiences(); - if (!panel) return true; + if (!panel) + return true; + + const sparam_t::size_type MIN_SIZE = 5; + if (strings.size() < MIN_SIZE) + return true; + // Skip 2 parameters sparam_t::const_iterator it = strings.begin(); ++it; // U32 estate_id = strtol((*it).c_str(), NULL, 10); ++it; // U32 send_to_agent_only = strtoul((*(++it)).c_str(), NULL, 10); + // Read 3 parameters LLUUID id; S32 num_blocked = strtol((*(it++)).c_str(), NULL, 10); S32 num_trusted = strtol((*(it++)).c_str(), NULL, 10); S32 num_allowed = strtol((*(it++)).c_str(), NULL, 10); LLSD ids = LLSD::emptyMap() - .with("blocked", getIDs(it, strings.end(), num_blocked)) - .with("trusted", getIDs(it + (num_blocked), strings.end(), num_trusted)) - .with("allowed", getIDs(it + (num_blocked+num_trusted), strings.end(), num_allowed)); + .with("blocked", getIDs(it, strings.end(), num_blocked)) + .with("trusted", getIDs(it + num_blocked, strings.end(), num_trusted)) + .with("allowed", getIDs(it + num_blocked + num_trusted, strings.end(), num_allowed)); - panel->processResponse(ids); + panel->processResponse(ids); return true; } diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index c34dbb62e8..3eb39b250f 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -102,7 +102,6 @@ public: void onRegionChanged(); void requestRegionInfo(); - void requestMeshRezInfo(); void enableTopButtons(); void disableTopButtons(); diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 082bb888b1..d29ecbbf95 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 2a15eacded..eff0803fdd 100644 --- a/indra/newview/llfloatertranslationsettings.h +++ b/indra/newview/llfloatertranslationsettings.h @@ -42,38 +42,48 @@ public: /*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/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index ab6a64157c..a45246eedc 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -898,6 +898,15 @@ void LLHUDNameTag::shift(const LLVector3& offset) mPositionAgent += offset; } +F32 LLHUDNameTag::getWorldHeight() const +{ + const LLViewerCamera* camera = LLViewerCamera::getInstance(); + F32 height_meters = mLastDistance * (F32)tan(camera->getView() / 2.f); + F32 height_pixels = camera->getViewHeightInPixels() / 2.f; + F32 meters_per_pixel = height_meters / height_pixels; + return mHeight * meters_per_pixel * gViewerWindow->getDisplayScale().mV[VY]; +} + //static void LLHUDNameTag::addPickable(std::set<LLViewerObject*> &pick_list) { diff --git a/indra/newview/llhudnametag.h b/indra/newview/llhudnametag.h index 361e4d4f4b..592ab5518f 100644 --- a/indra/newview/llhudnametag.h +++ b/indra/newview/llhudnametag.h @@ -127,11 +127,12 @@ public: /*virtual*/ void markDead(); friend class LLHUDObject; /*virtual*/ F32 getDistance() const { return mLastDistance; } - S32 getLOD() { return mLOD; } - BOOL getVisible() { return mVisible; } + S32 getLOD() const { return mLOD; } + BOOL getVisible() const { return mVisible; } BOOL getHidden() const { return mHidden; } void setHidden( BOOL hide ) { mHidden = hide; } void shift(const LLVector3& offset); + F32 getWorldHeight() const; BOOL lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, LLVector4a& intersection, BOOL debug_render = FALSE); diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp index 68801b0895..6f93a78ca6 100644 --- a/indra/newview/llinspecttoast.cpp +++ b/indra/newview/llinspecttoast.cpp @@ -47,6 +47,7 @@ public: /*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/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 67240ac7e7..004f0425fd 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1967,6 +1967,24 @@ void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::st } +std::string get_category_path(LLUUID cat_id) +{ + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + std::string localized_cat_name; + if (!LLTrans::findString(localized_cat_name, "InvFolder " + cat->getName())) + { + localized_cat_name = cat->getName(); + } + + if (cat->getParentUUID().notNull()) + { + return get_category_path(cat->getParentUUID()) + " > " + localized_cat_name; + } + else + { + return localized_cat_name; + } +} ///---------------------------------------------------------------------------- /// LLInventoryCollectFunctor implementations ///---------------------------------------------------------------------------- diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 56ad6f6496..873bd7233c 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -97,6 +97,7 @@ void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::st void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected_uuids); bool is_only_cats_selected(const uuid_vec_t& selected_uuids); bool is_only_items_selected(const uuid_vec_t& selected_uuids); +std::string get_category_path(LLUUID cat_id); /** Miscellaneous global functions ** ** diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 0bbf201dc6..b4727de77f 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -594,7 +594,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 4a9b471a47..f544b318d6 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" @@ -408,6 +410,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; @@ -438,7 +441,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(); @@ -477,6 +481,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() { recursive_cats.push_back(cat_id); } + all_cats.push_back(cat_id); } else { @@ -796,6 +801,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 8029486d6f..2799cb4cdf 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1268,8 +1268,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 2c45014321..14840f1b2e 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -99,6 +99,7 @@ public: 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 178aba11a3..cbb87f63bb 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -831,7 +831,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()) { @@ -854,7 +854,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type"); - if(radio_mat_type) + if (radio_mat_type) { if (radio_mat_type->getSelectedIndex() < MATTYPE_DIFFUSE) { @@ -871,10 +871,10 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) childSetValue("checkbox_sync_settings", gSavedSettings.getBOOL("SyncMaterialSettings")); updateVisibility(); - bool identical = true; // true because it is anded below - bool identical_diffuse = false; - bool identical_norm = false; - bool identical_spec = false; + bool identical = true; // true because it is anded below + bool identical_diffuse = false; + bool identical_norm = false; + bool identical_spec = false; LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("texture control"); LLTextureCtrl* shinytexture_ctrl = getChild<LLTextureCtrl>("shinytexture control"); @@ -888,12 +888,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(); @@ -927,7 +927,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) LLCtrlSelectionInterface* combobox_shininess = childGetSelectionInterface("combobox shininess"); if (combobox_shininess) - { + { combobox_shininess->selectNthItem((S32)shiny); } @@ -947,8 +947,8 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) getChild<LLUICtrl>("shinycolorswatch")->setTentative(!identical_spec); LLColorSwatchCtrl* mShinyColorSwatch = getChild<LLColorSwatchCtrl>("shinycolorswatch"); - if(mShinyColorSwatch) - { + if (mShinyColorSwatch) + { mShinyColorSwatch->setValid(editable); mShinyColorSwatch->setEnabled( editable ); mShinyColorSwatch->setCanApplyImmediately( editable ); @@ -956,7 +956,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) U8 bumpy = 0; // Bumpy - { + { bool identical_bumpy = false; LLSelectedTE::getBumpmap(bumpy,identical_bumpy); @@ -966,18 +966,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 { @@ -991,25 +991,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); } @@ -1046,7 +1046,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) updateAlphaControls(); if (texture_ctrl) - { + { if (identical_diffuse) { texture_ctrl->setTentative(FALSE); @@ -1060,8 +1060,8 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) texture_ctrl->setBakeTextureEnabled(TRUE); } else if (id.isNull()) - { - // None selected + { + // None selected texture_ctrl->setTentative(FALSE); texture_ctrl->setEnabled(FALSE); texture_ctrl->setImageAssetID(LLUUID::null); @@ -1071,10 +1071,10 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) getChildView("label maskcutoff")->setEnabled(FALSE); texture_ctrl->setBakeTextureEnabled(false); - } - else - { - // Tentative: multiple selected with different textures + } + else + { + // Tentative: multiple selected with different textures texture_ctrl->setTentative(TRUE); texture_ctrl->setEnabled(editable); texture_ctrl->setImageAssetID(id); @@ -1085,7 +1085,6 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) texture_ctrl->setBakeTextureEnabled(TRUE); } - } if (shinytexture_ctrl) @@ -1343,15 +1342,14 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) combobox_texgen->selectNthItem(((S32)selected_texgen) >> 1); } else - { + { LL_WARNS() << "failed childGetSelectionInterface for 'combobox texgen'" << LL_ENDL; - } + } getChildView("combobox texgen")->setEnabled(editable); getChild<LLUICtrl>("combobox texgen")->setTentative(!identical); getChildView("tex gen")->setEnabled(editable); - - } + } { U8 fullbright_flag = 0; @@ -1380,7 +1378,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; @@ -1390,26 +1388,26 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) LLSelectMgr::getInstance()->setTextureChannel(LLRender::eTexIndex(material_type)); switch (material_type) - { + { default: case MATTYPE_DIFFUSE: - { + { enabled = editable && !id.isNull(); identical_repeats = identical_diff_repeats; repeats = repeats_diff; - } + } break; case MATTYPE_SPECULAR: - { + { enabled = (editable && ((shiny == SHINY_TEXTURE) && !specmap_id.isNull())); identical_repeats = identical_spec_repeats; repeats = repeats_spec; - } + } break; case MATTYPE_NORMAL: - { + { enabled = (editable && ((bumpy == BUMPY_TEXTURE) && !normmap_id.isNull())); identical_repeats = identical_norm_repeats; repeats = repeats_norm; @@ -1458,14 +1456,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; - } + } getChild<LLUICtrl>("maskcutoff")->setValue(material->getAlphaMaskCutoff()); updateAlphaControls(); @@ -1477,15 +1475,15 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) texture_ctrl->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); @@ -1497,7 +1495,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) getChild<LLUICtrl>("environment")->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. @@ -1559,14 +1557,14 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) // Disable non-UICtrls 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") ); @@ -1609,7 +1607,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 44bc442bbb..aaf8eddaf7 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -134,8 +134,7 @@ protected: 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 sendMedia(); + void sendGlow(); void alignTestureLayer(); void updateCopyTexButton(); @@ -240,7 +239,6 @@ protected: private: - bool isAlpha() { return mIsAlpha; } // Convenience funcs to keep the visual flack to a minimum @@ -249,10 +247,10 @@ private: 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(); @@ -328,7 +326,7 @@ private: 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) { @@ -540,7 +538,6 @@ public: 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 bd40c9dd2b..d935c01eb8 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -960,9 +960,15 @@ void LLTaskLSLBridge::openItem() LLSD floater_key; floater_key["taskid"] = mPanel->getTaskUUID(); floater_key["itemid"] = mUUID; + LLLiveLSLEditor* preview = LLFloaterReg::showTypedInstance<LLLiveLSLEditor>("preview_scriptedit", floater_key, TAKE_FOCUS_YES); if (preview) { + LLSelectNode *node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(NULL, TRUE); + if (node && node->mValid) + { + preview->setObjectName(node->mName); + } preview->setObjectID(mPanel->getTaskUUID()); } } @@ -1368,7 +1374,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 708ff26ced..8ac1efe8e7 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -159,6 +159,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; @@ -1051,6 +1052,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) @@ -1258,6 +1261,59 @@ 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 + { + childSetVisible("badge_layout", FALSE); + childSetVisible("partner_spacer_layout", TRUE); + } } void LLPanelProfileSecondLife::fillRightsData() @@ -1412,7 +1468,7 @@ void LLPanelProfileSecondLife::updateOnlineStatus() } else { - childSetVisible("frind_layout", false); + childSetVisible("friend_layout", false); childSetVisible("online_layout", false); childSetVisible("offline_layout", false); } @@ -1420,7 +1476,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 45d0252e4f..c2a0c16df4 100644 --- a/indra/newview/llpanelprofilepicks.cpp +++ b/indra/newview/llpanelprofilepicks.cpp @@ -529,6 +529,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(); @@ -558,7 +559,6 @@ void LLPanelProfilePick::setAvatarId(const LLUUID& avatar_id) { mPickName->setEnabled(TRUE); mPickDescription->setEnabled(TRUE); - mSetCurrentLocationButton->setVisible(TRUE); } else { @@ -573,7 +573,6 @@ BOOL LLPanelProfilePick::postBuild() mSaveButton = getChild<LLButton>("save_changes_btn"); mCreateButton = getChild<LLButton>("create_changes_btn"); mCancelButton = getChild<LLButton>("cancel_changes_btn"); - mSetCurrentLocationButton = getChild<LLButton>("set_to_curr_location_btn"); mSnapshotCtrl = getChild<LLTextureCtrl>("pick_snapshot"); mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelProfilePick::onSnapshotChanged, this)); @@ -584,7 +583,6 @@ BOOL LLPanelProfilePick::postBuild() mSaveButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this)); mCreateButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this)); mCancelButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickCancel, this)); - mSetCurrentLocationButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSetLocation, this)); mPickName->setKeystrokeCallback(boost::bind(&LLPanelProfilePick::onPickChanged, this, _1), NULL); mPickName->setEnabled(FALSE); @@ -746,32 +744,6 @@ BOOL LLPanelProfilePick::isDirty() const return FALSE; } -void LLPanelProfilePick::onClickSetLocation() -{ - // Save location for later use. - setPosGlobal(gAgent.getPositionGlobal()); - - std::string parcel_name, region_name; - - LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); - if (parcel) - { - mParcelId = parcel->getID(); - parcel_name = parcel->getName(); - } - - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - region_name = region->getName(); - } - - setPickLocation(createLocationText(getLocationNotice(), parcel_name, region_name, getPosGlobal())); - - mLocationChanged = true; - enableSaveButton(TRUE); -} - void LLPanelProfilePick::onClickSave() { sendUpdate(); diff --git a/indra/newview/llpanelprofilepicks.h b/indra/newview/llpanelprofilepicks.h index f84463cc9b..228dfd5958 100644 --- a/indra/newview/llpanelprofilepicks.h +++ b/indra/newview/llpanelprofilepicks.h @@ -202,11 +202,6 @@ protected: void resetDirty() override; /** - * Callback for "Set Location" button click - */ - void onClickSetLocation(); - - /** * Callback for "Save" and "Create" button click */ void onClickSave(); @@ -228,7 +223,6 @@ protected: LLTextureCtrl* mSnapshotCtrl; LLLineEditor* mPickName; LLTextEditor* mPickDescription; - LLButton* mSetCurrentLocationButton; LLButton* mSaveButton; LLButton* mCreateButton; LLButton* mCancelButton; diff --git a/indra/newview/llpanelvoicedevicesettings.cpp b/indra/newview/llpanelvoicedevicesettings.cpp index 28631e2b7b..af57169f3b 100644 --- a/indra/newview/llpanelvoicedevicesettings.cpp +++ b/indra/newview/llpanelvoicedevicesettings.cpp @@ -32,6 +32,7 @@ // Viewer includes #include "llcombobox.h" #include "llsliderctrl.h" +#include "llstartup.h" #include "llviewercontrol.h" #include "llvoiceclient.h" #include "llvoicechannel.h" @@ -70,11 +71,14 @@ BOOL LLPanelVoiceDeviceSettings::postBuild() mCtrlInputDevices = getChild<LLComboBox>("voice_input_device"); mCtrlOutputDevices = getChild<LLComboBox>("voice_output_device"); + mUnmuteBtn = getChild<LLButton>("unmute_btn"); mCtrlInputDevices->setCommitCallback( boost::bind(&LLPanelVoiceDeviceSettings::onCommitInputDevice, this)); mCtrlOutputDevices->setCommitCallback( boost::bind(&LLPanelVoiceDeviceSettings::onCommitOutputDevice, this)); + mUnmuteBtn->setCommitCallback( + boost::bind(&LLPanelVoiceDeviceSettings::onCommitUnmute, this)); mLocalizedDeviceNames[DEFAULT_DEVICE] = getString("default_text"); mLocalizedDeviceNames["No Device"] = getString("name_no_device"); @@ -108,11 +112,27 @@ void LLPanelVoiceDeviceSettings::draw() // let user know that volume indicator is not yet available bool is_in_tuning_mode = LLVoiceClient::getInstance()->inTuningMode(); - getChildView("wait_text")->setVisible( !is_in_tuning_mode && mUseTuningMode); + bool voice_enabled = LLVoiceClient::getInstance()->voiceEnabled(); + if (voice_enabled) + { + getChildView("wait_text")->setVisible( !is_in_tuning_mode && mUseTuningMode); + getChildView("disabled_text")->setVisible(FALSE); + mUnmuteBtn->setVisible(FALSE); + } + else + { + getChildView("wait_text")->setVisible(FALSE); + + static LLCachedControl<bool> chat_enabled(gSavedSettings, "EnableVoiceChat"); + // If voice isn't enabled, it is either disabled or muted + bool voice_disabled = chat_enabled() || LLStartUp::getStartupState() <= STATE_LOGIN_WAIT; + getChildView("disabled_text")->setVisible(voice_disabled); + mUnmuteBtn->setVisible(!voice_disabled); + } LLPanel::draw(); - if (is_in_tuning_mode) + if (is_in_tuning_mode && voice_enabled) { const S32 num_bars = 5; F32 voice_power = LLVoiceClient::getInstance()->tuningGetEnergy() / LLVoiceClient::OVERDRIVEN_POWER_LEVEL; @@ -339,3 +359,8 @@ void LLPanelVoiceDeviceSettings::onInputDevicesClicked() { LLVoiceClient::getInstance()->refreshDeviceLists(false); // fill in the pop up menus again if needed. } + +void LLPanelVoiceDeviceSettings::onCommitUnmute() +{ + gSavedSettings.setBOOL("EnableVoiceChat", TRUE); +} diff --git a/indra/newview/llpanelvoicedevicesettings.h b/indra/newview/llpanelvoicedevicesettings.h index 355bc02b05..e704394d4a 100644 --- a/indra/newview/llpanelvoicedevicesettings.h +++ b/indra/newview/llpanelvoicedevicesettings.h @@ -55,12 +55,14 @@ protected: void onCommitOutputDevice(); void onOutputDevicesClicked(); void onInputDevicesClicked(); + void onCommitUnmute(); F32 mMicVolume; std::string mInputDevice; std::string mOutputDevice; class LLComboBox *mCtrlInputDevices; class LLComboBox *mCtrlOutputDevices; + class LLButton *mUnmuteBtn; BOOL mDevicesUpdated; bool mUseTuningMode; std::map<std::string, std::string> mLocalizedDeviceNames; diff --git a/indra/newview/llpanelvolumepulldown.cpp b/indra/newview/llpanelvolumepulldown.cpp index 6f11e76a72..09038ac95a 100644 --- a/indra/newview/llpanelvolumepulldown.cpp +++ b/indra/newview/llpanelvolumepulldown.cpp @@ -50,7 +50,7 @@ LLPanelVolumePulldown::LLPanelVolumePulldown() { mCommitCallbackRegistrar.add("Vol.setControlFalse", boost::bind(&LLPanelVolumePulldown::setControlFalse, this, _2)); mCommitCallbackRegistrar.add("Vol.SetSounds", boost::bind(&LLPanelVolumePulldown::onClickSetSounds, this)); - mCommitCallbackRegistrar.add("Vol.updateMediaAutoPlayCheckbox", boost::bind(&LLPanelVolumePulldown::updateMediaAutoPlayCheckbox, this, _1)); + mCommitCallbackRegistrar.add("Vol.updateCheckbox", boost::bind(&LLPanelVolumePulldown::updateCheckbox, this, _1, _2)); mCommitCallbackRegistrar.add("Vol.GoAudioPrefs", boost::bind(&LLPanelVolumePulldown::onAdvancedButtonClick, this, _2)); buildFromFile( "panel_volume_pulldown.xml"); } @@ -90,19 +90,23 @@ void LLPanelVolumePulldown::setControlFalse(const LLSD& user_data) control->set(LLSD(FALSE)); } -void LLPanelVolumePulldown::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl) +void LLPanelVolumePulldown::updateCheckbox(LLUICtrl* ctrl, const LLSD& user_data) { - std::string name = ctrl->getName(); + std::string control_name = user_data.asString(); + if (control_name == "MediaAutoPlay") + { + std::string name = ctrl->getName(); - // Disable "Allow Media to auto play" only when both - // "Streaming Music" and "Media" are unchecked. STORM-513. - if ((name == "enable_music") || (name == "enable_media")) - { - bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get(); - bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get(); + // Disable "Allow Media to auto play" only when both + // "Streaming Music" and "Media" are unchecked. STORM-513. + if ((name == "enable_music") || (name == "enable_media")) + { + bool music_enabled = getChild<LLCheckBoxCtrl>("enable_music")->get(); + bool media_enabled = getChild<LLCheckBoxCtrl>("enable_media")->get(); - getChild<LLCheckBoxCtrl>("media_auto_play_combo")->setEnabled(music_enabled || media_enabled); - } + getChild<LLCheckBoxCtrl>("media_auto_play_combo")->setEnabled(music_enabled || media_enabled); + } + } } void LLPanelVolumePulldown::onClickSetSounds() diff --git a/indra/newview/llpanelvolumepulldown.h b/indra/newview/llpanelvolumepulldown.h index e907bb0c78..3243d2e968 100644 --- a/indra/newview/llpanelvolumepulldown.h +++ b/indra/newview/llpanelvolumepulldown.h @@ -43,7 +43,7 @@ class LLPanelVolumePulldown : public LLPanelPulldown void onClickSetSounds(); // Disables "Allow Media to auto play" check box only when both // "Streaming Music" and "Media" are unchecked. Otherwise enables it. - void updateMediaAutoPlayCheckbox(LLUICtrl* ctrl); + void updateCheckbox(LLUICtrl* ctrl, const LLSD& user_data); void onAdvancedButtonClick(const LLSD& user_data); }; diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp index 3347c40687..bc9f0cef83 100644 --- a/indra/newview/llpanelwearing.cpp +++ b/indra/newview/llpanelwearing.cpp @@ -566,7 +566,7 @@ void LLPanelWearing::onRemoveAttachment() { LLSelectMgr::getInstance()->deselectAll(); LLSelectMgr::getInstance()->selectObjectAndFamily(mAttachmentsMap[item->getUUID()]); - LLSelectMgr::getInstance()->sendDropAttachment(); + LLSelectMgr::getInstance()->sendDetach(); } } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index d677a996c1..dc79abcdeb 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -86,6 +86,9 @@ #include "llexperiencecache.h" #include "llfloaterexperienceprofile.h" #include "llviewerassetupload.h" +#include "lltoggleablemenu.h" +#include "llmenubutton.h" +#include "llinventoryfunctions.h" const std::string HELLO_LSL = "default\n" @@ -322,6 +325,38 @@ void LLFloaterScriptSearch::onSearchBoxCommit() } /// --------------------------------------------------------------------------- + +class LLScriptMovedObserver : public LLInventoryObserver +{ + public: + LLScriptMovedObserver(LLPreviewLSL *floater) : mPreview(floater) { gInventory.addObserver(this); } + virtual ~LLScriptMovedObserver() { gInventory.removeObserver(this); } + virtual void changed(U32 mask); + + private: + LLPreviewLSL *mPreview; +}; + +void LLScriptMovedObserver::changed(U32 mask) +{ + const std::set<LLUUID> &mChangedItemIDs = gInventory.getChangedIDs(); + std::set<LLUUID>::const_iterator it; + + const LLUUID &item_id = mPreview->getScriptID(); + + for (it = mChangedItemIDs.begin(); it != mChangedItemIDs.end(); it++) + { + if (*it == item_id) + { + if ((mask & (LLInventoryObserver::STRUCTURE)) != 0) + { + mPreview->setDirty(); + } + } + } +} + +/// --------------------------------------------------------------------------- /// LLScriptEdCore /// --------------------------------------------------------------------------- @@ -459,6 +494,13 @@ BOOL LLScriptEdCore::postBuild() LLSyntaxIdLSL::getInstance()->initialize(); processKeywords(); + mCommitCallbackRegistrar.add("FontSize.Set", boost::bind(&LLScriptEdCore::onChangeFontSize, this, _2)); + mEnableCallbackRegistrar.add("FontSize.Check", boost::bind(&LLScriptEdCore::isFontSizeChecked, this, _2)); + + LLToggleableMenu *context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>( + "menu_lsl_font_size.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + getChild<LLMenuButton>("font_btn")->setMenu(context_menu, LLMenuButton::MP_BOTTOM_LEFT, true); + return TRUE; } @@ -787,7 +829,7 @@ void LLScriptEdCore::setHelpPage(const std::string& help_string) LLUIString url_string = gSavedSettings.getString("LSLHelpURL"); - url_string.setArg("[LSL_STRING]", help_string); + url_string.setArg("[LSL_STRING]", help_string.empty() ? HELP_LSL_PORTAL_TOPIC : help_string); addHelpItemToHistory(help_string); @@ -1287,7 +1329,21 @@ LLUUID LLScriptEdCore::getAssociatedExperience()const return mAssociatedExperience; } -void LLLiveLSLEditor::setExperienceIds( const LLSD& experience_ids ) +void LLScriptEdCore::onChangeFontSize(const LLSD &userdata) +{ + const std::string font_name = userdata.asString(); + gSavedSettings.setString("LSLFontSizeName", font_name); +} + +bool LLScriptEdCore::isFontSizeChecked(const LLSD &userdata) +{ + const std::string current_size_name = LLScriptEditor::getScriptFontSize(); + const std::string size_name = userdata.asString(); + + return (size_name == current_size_name); +} + + void LLLiveLSLEditor::setExperienceIds( const LLSD& experience_ids ) { mExperienceIds=experience_ids; updateExperiencePanel(); @@ -1475,7 +1531,21 @@ bool LLScriptEdContainer::onExternalChange(const std::string& filename) return true; } -/// --------------------------------------------------------------------------- +BOOL LLScriptEdContainer::handleKeyHere(KEY key, MASK mask) +{ + if (('A' == key) && (MASK_CONTROL == (mask & MASK_MODIFIERS))) + { + mScriptEd->selectAll(); + return TRUE; + } + + if (!LLPreview::handleKeyHere(key, mask)) + { + return mScriptEd->handleKeyHere(key, mask); + } + return TRUE; +} + /// --------------------------------------------------------------------------- /// LLPreviewLSL /// --------------------------------------------------------------------------- @@ -1516,6 +1586,14 @@ LLPreviewLSL::LLPreviewLSL(const LLSD& key ) mPendingUploads(0) { mFactoryMap["script panel"] = LLCallbackMap(LLPreviewLSL::createScriptEdPanel, this); + + mItemObserver = new LLScriptMovedObserver(this); +} + +LLPreviewLSL::~LLPreviewLSL() +{ + delete mItemObserver; + mItemObserver = NULL; } // virtual @@ -1527,10 +1605,14 @@ BOOL LLPreviewLSL::postBuild() if (item) { getChild<LLUICtrl>("desc")->setValue(item->getDescription()); + + std::string item_path = get_category_path(item->getParentUUID()); + getChild<LLUICtrl>("path_txt")->setValue(item_path); + getChild<LLUICtrl>("path_txt")->setToolTip(item_path); } childSetCommitCallback("desc", LLPreview::onText, this); getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); - + return LLPreview::postBuild(); } @@ -1542,7 +1624,12 @@ void LLPreviewLSL::draw() setTitle(LLTrans::getString("ScriptWasDeleted")); mScriptEd->setItemRemoved(TRUE); } - + else if (mDirty) + { + std::string item_path = get_category_path(item->getParentUUID()); + getChild<LLUICtrl>("path_txt")->setValue(item_path); + getChild<LLUICtrl>("path_txt")->setToolTip(item_path); + } LLPreview::draw(); } // virtual @@ -1828,7 +1915,8 @@ LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) : mPendingUploads(0), mIsModifiable(FALSE), mIsNew(false), - mIsSaving(FALSE) + mIsSaving(FALSE), + mObjectName("") { mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this); } @@ -1965,6 +2053,7 @@ void LLLiveLSLEditor::loadAsset() } refreshFromItem(); + getChild<LLUICtrl>("obj_name")->setValue(mObjectName); // This is commented out, because we don't completely // handle script exports yet. /* diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index f851ff6f3f..36e5253fb6 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -36,6 +36,7 @@ #include "llfloatergotoline.h" #include "lllivefile.h" #include "llsyntaxid.h" +#include "llscripteditor.h" class LLLiveLSLFile; class LLMessageSystem; @@ -52,6 +53,7 @@ class LLViewerInventoryItem; class LLScriptEdContainer; class LLFloaterGotoLine; class LLFloaterExperienceProfile; +class LLScriptMovedObserver; class LLLiveLSLFile : public LLLiveFile { @@ -145,7 +147,13 @@ public: void setAssetID( const LLUUID& asset_id){ mAssetID = asset_id; }; LLUUID getAssetID() { return mAssetID; } -private: + bool isFontSizeChecked(const LLSD &userdata); + void onChangeFontSize(const LLSD &size_name); + + virtual BOOL handleKeyHere(KEY key, MASK mask); + void selectAll() { mEditor->selectAll(); } + + private: void onBtnDynamicHelp(); void onBtnUndoChanges(); @@ -153,8 +161,6 @@ private: void selectFirstError(); - virtual BOOL handleKeyHere(KEY key, MASK mask); - void enableSave(BOOL b) {mEnableSave = b;} protected: @@ -207,6 +213,8 @@ public: LLScriptEdContainer(const LLSD& key); LLScriptEdContainer(const LLSD& key, const bool live); + BOOL handleKeyHere(KEY key, MASK mask); + protected: std::string getTmpFileName(const std::string& script_name); bool onExternalChange(const std::string& filename); @@ -220,6 +228,12 @@ class LLPreviewLSL : public LLScriptEdContainer { public: LLPreviewLSL(const LLSD& key ); + ~LLPreviewLSL(); + + LLUUID getScriptID() { return mItemUUID; } + + void setDirty() { mDirty = true; } + virtual void callbackLSLCompileSucceeded(); virtual void callbackLSLCompileFailed(const LLSD& compile_errors); @@ -250,6 +264,8 @@ protected: // Can safely close only after both text and bytecode are uploaded S32 mPendingUploads; + LLScriptMovedObserver* mItemObserver; + }; @@ -282,6 +298,8 @@ public: void requestExperiences(); void experienceChanged(); void addAssociatedExperience(const LLSD& experience); + + void setObjectName(std::string name) { mObjectName = name; } private: virtual BOOL canClose(); @@ -340,6 +358,7 @@ private: LLSD mExperienceIds; LLHandle<LLFloater> mExperienceProfile; + std::string mObjectName; }; #endif // LL_LLPREVIEWSCRIPT_H diff --git a/indra/newview/llscripteditor.cpp b/indra/newview/llscripteditor.cpp index 140cbbedbe..693491e7e7 100644 --- a/indra/newview/llscripteditor.cpp +++ b/indra/newview/llscripteditor.cpp @@ -30,19 +30,22 @@ #include "llsyntaxid.h" #include "lllocalcliprect.h" +#include "llviewercontrol.h" const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 32; static LLDefaultChildRegistry::Register<LLScriptEditor> r("script_editor"); LLScriptEditor::Params::Params() -: show_line_numbers("show_line_numbers", true) +: show_line_numbers("show_line_numbers", true), + default_font_size("default_font_size", false) {} LLScriptEditor::LLScriptEditor(const Params& p) : LLTextEditor(p) -, mShowLineNumbers(p.show_line_numbers) +, mShowLineNumbers(p.show_line_numbers), + mUseDefaultFontSize(p.default_font_size) { if (mShowLineNumbers) { @@ -51,6 +54,12 @@ LLScriptEditor::LLScriptEditor(const Params& p) } } +BOOL LLScriptEditor::postBuild() +{ + gSavedSettings.getControl("LSLFontSizeName")->getCommitSignal()->connect(boost::bind(&LLScriptEditor::onFontSizeChange, this)); + return LLTextEditor::postBuild(); +} + void LLScriptEditor::draw() { { @@ -110,12 +119,11 @@ void LLScriptEditor::drawLineNumbers() // draw the line numbers if(line.mLineNum != last_line_num && line.mRect.mTop <= scrolled_view_rect.mTop) { - const LLFontGL *num_font = LLFontGL::getFontMonospace(); const LLWString ltext = utf8str_to_wstring(llformat("%d", line.mLineNum )); BOOL is_cur_line = cursor_line == line.mLineNum; const U8 style = is_cur_line ? LLFontGL::BOLD : LLFontGL::NORMAL; const LLColor4 fg_color = is_cur_line ? mCursorColor : mReadOnlyFgColor; - num_font->render( + getScriptFont()->render( ltext, // string to draw 0, // begin offset UI_TEXTEDITOR_LINE_NUMBER_MARGIN - 2, // x @@ -143,8 +151,10 @@ void LLScriptEditor::loadKeywords() LL_PROFILE_ZONE_SCOPED; mKeywords.processTokens(); + LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getScriptFont()).color(mDefaultColor.get())); + segment_vec_t segment_list; - mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); + mKeywords.findSegments(&segment_list, getWText(), *this, style); mSegments.clear(); segment_set_t::iterator insert_it = mSegments.begin(); @@ -159,9 +169,12 @@ void LLScriptEditor::updateSegments() if (mReflowIndex < S32_MAX && mKeywords.isLoaded() && mParseOnTheFly) { LL_PROFILE_ZONE_SCOPED; + + LLStyleConstSP style = new LLStyle(LLStyle::Params().font(getScriptFont()).color(mDefaultColor.get())); + // HACK: No non-ascii keywords for now segment_vec_t segment_list; - mKeywords.findSegments(&segment_list, getWText(), mDefaultColor.get(), *this); + mKeywords.findSegments(&segment_list, getWText(), *this, style); clearSegments(); for (segment_vec_t::iterator list_it = segment_list.begin(); list_it != segment_list.end(); ++list_it) @@ -187,7 +200,7 @@ void LLScriptEditor::drawSelectionBackground() // Draw selection even if we don't have keyboard focus for search/replace if( hasSelection() && !mLineInfoList.empty()) { - std::vector<LLRect> selection_rects = getSelctionRects(); + std::vector<LLRect> selection_rects = getSelectionRects(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); const LLColor4& color = mReadOnly ? mReadOnlyFgColor : mFgColor; @@ -211,3 +224,23 @@ void LLScriptEditor::drawSelectionBackground() } } } + +std::string LLScriptEditor::getScriptFontSize() +{ + static LLCachedControl<std::string> size_name(gSavedSettings, "LSLFontSizeName", "Monospace"); + return size_name; +} + +LLFontGL* LLScriptEditor::getScriptFont() +{ + std::string font_size_name = mUseDefaultFontSize ? "Monospace" : getScriptFontSize(); + return LLFontGL::getFont(LLFontDescriptor("Monospace", font_size_name, 0)); +} + +void LLScriptEditor::onFontSizeChange() +{ + if (!mUseDefaultFontSize) + { + needsReflow(); + } +} diff --git a/indra/newview/llscripteditor.h b/indra/newview/llscripteditor.h index f458203a39..ef941f552a 100644 --- a/indra/newview/llscripteditor.h +++ b/indra/newview/llscripteditor.h @@ -37,7 +37,7 @@ public: struct Params : public LLInitParam::Block<Params, LLTextEditor::Params> { Optional<bool> show_line_numbers; - + Optional<bool> default_font_size; Params(); }; @@ -45,6 +45,7 @@ public: // LLView override virtual void draw(); + BOOL postBuild(); void initKeywords(); void loadKeywords(); @@ -52,7 +53,11 @@ public: LLKeywords::keyword_iterator_t keywordsBegin() { return mKeywords.begin(); } LLKeywords::keyword_iterator_t keywordsEnd() { return mKeywords.end(); } -protected: + static std::string getScriptFontSize(); + LLFontGL* getScriptFont(); + void onFontSizeChange(); + + protected: friend class LLUICtrlFactory; LLScriptEditor(const Params& p); @@ -65,6 +70,7 @@ private: LLKeywords mKeywords; bool mShowLineNumbers; + bool mUseDefaultFontSize; }; #endif // LL_SCRIPTEDITOR_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 57f91b4147..22c6e8bf2a 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1395,8 +1395,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 { @@ -1902,6 +1910,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/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 0a87b14e17..836a4327bf 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -190,6 +190,13 @@ BOOL LLStatusBar::postBuild() LLHints::getInstance()->registerHintTarget("linden_balance", getChild<LLView>("balance_bg")->getHandle()); gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&LLStatusBar::onVolumeChanged, this, _2)); + gSavedSettings.getControl("EnableVoiceChat")->getSignal()->connect(boost::bind(&LLStatusBar::onVoiceChanged, this, _2)); + + if (!gSavedSettings.getBOOL("EnableVoiceChat") && LLAppViewer::instance()->isSecondInstance()) + { + // Indicate that second instance started without sound + mBtnVolume->setImageUnselected(LLUI::getUIImage("VoiceMute_Off")); + } // Adding Net Stat Graph S32 x = getRect().getWidth() - 2; @@ -640,6 +647,16 @@ void LLStatusBar::onVolumeChanged(const LLSD& newvalue) refresh(); } +void LLStatusBar::onVoiceChanged(const LLSD& newvalue) +{ + if (newvalue.asBoolean()) + { + // Second instance starts with "VoiceMute_Off" icon, fix it + mBtnVolume->setImageUnselected(LLUI::getUIImage("Audio_Off")); + } + refresh(); +} + void LLStatusBar::onUpdateFilterTerm() { LLWString searchValue = utf8str_to_wstring( mFilterEdit->getValue() ); diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 3002b91c10..3e9190652d 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -99,12 +99,12 @@ private: void onClickBuyCurrency(); void onVolumeChanged(const LLSD& newvalue); + void onVoiceChanged(const LLSD& newvalue); void onMouseEnterPresetsCamera(); void onMouseEnterPresets(); void onMouseEnterVolume(); void onMouseEnterNearbyMedia(); - void onClickScreen(S32 x, S32 y); static void onClickMediaToggle(void* data); static void onClickBalance(void* data); diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index 34d3ed8bb1..6182c96597 100644 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -41,8 +41,8 @@ #include "llurlregistry.h" -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 @@ public: * @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 @@ public: * @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 @@ public: 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 = 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"); @@ -251,8 +293,6 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s if (!failure.empty()) failure(status, err_msg); } - - } //========================================================================= @@ -262,23 +302,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( @@ -290,7 +351,6 @@ private: std::string& translation, std::string& detected_lang); static std::string getAPIKey(); - }; //------------------------------------------------------------------------- @@ -311,44 +371,54 @@ 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, std::string& detected_lang, std::string& err_msg) const { + const std::string& text = !body.empty() ? body : http_response["error_body"].asStringRef(); + Json::Value root; Json::Reader reader; - if (!reader.parse(body, root)) + if (reader.parse(text, root)) { - err_msg = reader.getFormatedErrorMessages(); - return false; - } + if (root.isObject()) + { + // Request succeeded, extract translation from the XML body. + if (parseTranslation(root, translation, detected_lang)) + return true; - if (!root.isObject()) // empty response? should not happen - { - return false; + // Request failed. Extract error message from the XML body. + parseErrorResponse(root, status, err_msg); + } } - - if (status != HTTP_OK) + else { - // Request failed. Extract error message from the response. - parseErrorResponse(root, status, err_msg); - return false; + // XML parsing failed. Extract error message from the XML parser. + err_msg = reader.getFormatedErrorMessages(); } - // Request succeeded, extract translation from the response. - return parseTranslation(root, translation, detected_lang); + return false; } // virtual @@ -407,75 +477,195 @@ 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_JSON); + 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 +{ + initHttpHeader(headers, 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 + + Json::Value root; + Json::Reader reader; + + if (!reader.parse(response["error_body"].asString(), root)) + { + LL_DEBUGS("Translate") << "Failed to parse error_body:" << reader.getFormatedErrorMessages() << 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, @@ -484,65 +674,448 @@ 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)) - { - begin = 0; - } - else - { - ++begin; - } + //Example: + // "[{\"detectedLanguage\":{\"language\":\"en\",\"score\":1.0},\"translations\":[{\"text\":\"Hello, what is your name?\",\"to\":\"en\"}]}]" - size_t end = body.find("</string>", begin); + Json::Value root; + Json::Reader reader; - detected_lang = ""; // unsupported by this API - translation = body.substr(begin, end-begin); - LLStringUtil::replaceString(translation, "
", ""); // strip CR - return true; + if (!reader.parse(body, root)) + { + err_msg = reader.getFormatedErrorMessages(); + return false; + } + + if (!root.isArray()) // empty response? should not happen + { + return false; + } + + // Request succeeded, extract translation from the response. + + const Json::Value& data = root[0U]; + if (!data.isObject() + || !data.isMember("detectedLanguage") + || !data.isMember("translations")) + { + return false; + } + + const Json::Value& detectedLanguage = data["detectedLanguage"]; + if (!detectedLanguage.isObject() || !detectedLanguage.isMember("language")) + { + return false; + } + detected_lang = detectedLanguage["language"].asString(); + + const Json::Value& translations = data["translations"]; + if (!translations.isArray() || translations.size() == 0) + { + return false; + } + + const Json::Value& first = translations[0U]; + if (!first.isObject() || !first.isMember("text")) + { + return false; + } + + translation = LLURI::unescape(first["text"].asString()); + + return true; } // virtual -bool LLBingTranslationHandler::isConfigured() const +bool LLAzureTranslationHandler::isConfigured() const { - return !getAPIKey().empty(); + 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 + + Json::Value root; + Json::Reader reader; + + if (!reader.parse(body, root)) + { + return std::string(); + } + + if (!root.isObject() || !root.isMember("error")) + { + return std::string(); + } + + const Json::Value& error_map = root["error"]; + + if (!error_map.isObject() || !error_map.isMember("message")) + { + return std::string(); + } + + return error_map["message"].asString(); } // static -std::string LLBingTranslationHandler::getAPIKey() +LLSD LLAzureTranslationHandler::getAPIKey() { - return gSavedSettings.getString("BingTranslateAPIKey"); + static LLCachedControl<LLSD> azure_key(gSavedSettings, "AzureTranslateAPIKey"); + return azure_key; } // static -std::string LLBingTranslationHandler::getAPILanguageCode(const std::string& lang) +std::string LLAzureTranslationHandler::getAPILanguageCode(const std::string& lang) { return lang == "zh" ? "zh-CHT" : lang; // treat Chinese as Traditional Chinese } /*virtual*/ -void LLBingTranslationHandler::verifyKey(const std::string &key, LLTranslate::KeyVerificationResult_fn fnc) +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()); + + static const std::string allowed_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz " + "0123456789" + "-._~"; + + outs << "[{\"text\":\""; + outs << LLURI::escape(msg, allowed_chars); + 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 +std::string LLDeepLTranslationHandler::getTranslateURL( + const std::string& from_lang, + const std::string& to_lang, + const std::string& text) const +{ + 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\"}]}" + + Json::Value root; + Json::Reader reader; + + if (!reader.parse(body, root)) + { + err_msg = reader.getFormatedErrorMessages(); + return false; + } + + if (!root.isObject() + || !root.isMember("translations")) // empty response? should not happen + { + return false; + } + + // Request succeeded, extract translation from the response. + const Json::Value& translations = root["translations"]; + if (!translations.isArray() || translations.size() == 0) + { + return false; + } + + const Json::Value& data= translations[0U]; + if (!data.isObject() + || !data.isMember("detected_source_language") + || !data.isMember("text")) + { + return false; + } + + detected_lang = data["detected_source_language"].asString(); + LLStringUtil::toLower(detected_lang); + translation = data["text"].asString(); + + 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.\"}" + + Json::Value root; + Json::Reader reader; + + if (!reader.parse(body, root)) + { + return std::string(); + } + + if (!root.isObject() || !root.isMember("message")) + { + return std::string(); + } + + return root["message"].asString(); +} + +// static +LLSD LLDeepLTranslationHandler::getAPIKey() +{ + static LLCachedControl<LLSD> deepl_key(gSavedSettings, "DeepLTranslateAPIKey"); + return deepl_key; +} + +// static +std::string LLDeepLTranslationHandler::getAPILanguageCode(const std::string& lang) +{ + 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("Bing /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro, - this, LLTranslate::SERVICE_BING, key, 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 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 +{ + 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); } //========================================================================= @@ -569,58 +1142,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; } - 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_DEEPL) { - 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(); + return mesg; } - return upd_msg; + + if (getPreferredHandler().getCurrentService() == SERVICE_AZURE) + { + // 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 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); @@ -686,13 +1279,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); } @@ -701,12 +1302,18 @@ 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 bing; + return azure; } diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index 58707e2d36..4a5d80737c 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 6bab2c2100..226e0a9a56 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1597,7 +1597,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) { @@ -1616,7 +1617,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/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index ea409bc8a7..84396c2c68 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -276,10 +276,6 @@ void handle_object_owner_permissive(void*); void handle_object_lock(void*); void handle_object_asset_ids(void*); void force_take_copy(void*); -#ifdef _CORY_TESTING -void force_export_copy(void*); -void force_import_geometry(void*); -#endif void handle_force_parcel_owner_to_me(void*); void handle_force_parcel_to_content(void*); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 27fe7a7018..2634c8d908 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -355,9 +355,6 @@ void LLMediaFilePicker::notify(const std::vector<std::string>& filenames) static std::string SOUND_EXTENSIONS = "wav"; static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png"; static std::string ANIM_EXTENSIONS = "bvh anim"; -#ifdef _CORY_TESTING -static std::string GEOMETRY_EXTENSIONS = "slg"; -#endif static std::string XML_EXTENSIONS = "xml"; static std::string SLOBJECT_EXTENSIONS = "slobject"; #endif @@ -379,10 +376,6 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter) return SLOBJECT_EXTENSIONS; case LLFilePicker::FFLOAD_MODEL: return MODEL_EXTENSIONS; -#ifdef _CORY_TESTING - case LLFilePicker::FFLOAD_GEOMETRY: - return GEOMETRY_EXTENSIONS; -#endif case LLFilePicker::FFLOAD_XML: return XML_EXTENSIONS; case LLFilePicker::FFLOAD_ALL: diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 519166af63..1607296194 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -124,7 +124,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/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 8a11c5cf8f..97ff5f58e4 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -402,9 +402,6 @@ void LLViewerTextureManager::init() LLViewerFetchedTexture::sDefaultImagep->dontDiscard(); LLViewerFetchedTexture::sDefaultImagep->setCategory(LLGLTexture::OTHER); - LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); - LLViewerFetchedTexture::sSmokeImagep->setNoDelete(); - image_raw = new LLImageRaw(32,32,3); data = image_raw->getData(); @@ -2368,7 +2365,8 @@ bool LLViewerFetchedTexture::updateFetch() } } - llassert_always(mRawImage.notNull() || (!mNeedsCreateTexture && !mIsRawImageValid)); + llassert_always(mRawImage.notNull() || !mIsRawImageValid); + llassert_always(mRawImage.notNull() || !mNeedsCreateTexture); return mIsFetching ? true : false; } diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 0a20c864dd..e6d4b0d026 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -228,6 +228,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 b9fcc25310..e8fd74b37b 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1050,7 +1050,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 = ""; @@ -1199,6 +1199,7 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK m if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) ) { LLViewerEventRecorder::instance().clear_xui(); + is_toolmgr_action = true; return TRUE; } diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 1927e01ddb..92905ef21a 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -179,7 +179,7 @@ public: 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/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 305c489cc8..250366dbea 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -3612,7 +3612,6 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) local_camera_up.normalize(); local_camera_up = local_camera_up * inv_root_rot; - // position is based on head position, does not require mAvatarOffset here. - Nyx LLVector3 avatar_ellipsoid(mBodySize.mV[VX] * 0.4f, mBodySize.mV[VY] * 0.4f, @@ -3634,6 +3633,25 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av)); name_position += pixel_up_vec * NAMETAG_VERTICAL_SCREEN_OFFSET; + const F32 water_height = getRegion()->getWaterHeight(); + static const F32 WATER_HEIGHT_DELTA = 0.25f; + if (name_position[VZ] < water_height + WATER_HEIGHT_DELTA) + { + if (LLViewerCamera::getInstance()->getOrigin()[VZ] >= water_height) + { + name_position[VZ] = water_height; + } + else // both camera and HUD are below watermark + { + F32 name_world_height = mNameText->getWorldHeight(); + F32 max_z_position = water_height - name_world_height; + if (name_position[VZ] > max_z_position) + { + name_position[VZ] = max_z_position; + } + } + } + mNameText->setPositionAgent(name_position); } diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index c73f96da2d..1b9aef193c 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), @@ -350,7 +350,11 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() : mIsProcessingChannels(false), mIsCoroutineActive(false), mVivoxPump("vivoxClientPump") -{ +{ + sShuttingDown = false; + sConnected = false; + sPump = nullptr; + mSpeakerVolume = scale_speaker_volume(0); mVoiceVersion.serverVersion = ""; @@ -392,7 +396,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())); @@ -413,10 +417,10 @@ void LLVivoxVoiceClient::terminate() logoutOfVivox(false); } - if(mConnected) + if(sConnected) { breakVoiceConnection(false); - mConnected = false; + sConnected = false; } else { @@ -425,7 +429,7 @@ void LLVivoxVoiceClient::terminate() } sShuttingDown = true; - mPump = NULL; + sPump = NULL; } //--------------------------------------------------- @@ -471,7 +475,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(); @@ -947,32 +951,52 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() // cause SLVoice's bind() call to fail with EADDRINUSE. We expect // that eventually the OS will time out previous ports, which is // why we cycle instead of incrementing indefinitely. - U32 portbase = gSavedSettings.getU32("VivoxVoicePort"); - static U32 portoffset = 0; + + static LLCachedControl<U32> portbase(gSavedSettings, "VivoxVoicePort"); + static LLCachedControl<std::string> host(gSavedSettings, "VivoxVoiceHost"); + static LLCachedControl<std::string> loglevel(gSavedSettings, "VivoxDebugLevel"); + static LLCachedControl<std::string> log_folder(gSavedSettings, "VivoxLogDirectory"); + static LLCachedControl<std::string> shutdown_timeout(gSavedSettings, "VivoxShutdownTimeout"); static const U32 portrange = 100; - std::string host(gSavedSettings.getString("VivoxVoiceHost")); - U32 port = portbase + portoffset; + static U32 portoffset = 0; + U32 port = 0; + + if (LLAppViewer::instance()->isSecondInstance()) + { + // Ideally need to know amount of instances and + // to increment instance_offset on EADDRINUSE. + // But for now just use rand + static U32 instance_offset = portrange * ll_rand(20); + port = portbase + portoffset + instance_offset; + } + else + { + // leave main thread with exclusive port set + port = portbase + portoffset; + } portoffset = (portoffset + 1) % portrange; params.args.add("-i"); - params.args.add(STRINGIZE(host << ':' << port)); + params.args.add(STRINGIZE(host() << ':' << port)); - std::string loglevel = gSavedSettings.getString("VivoxDebugLevel"); - if (loglevel.empty()) + params.args.add("-ll"); + if (loglevel().empty()) { - loglevel = "0"; + params.args.add("0"); } - params.args.add("-ll"); - params.args.add(loglevel); - - std::string log_folder = gSavedSettings.getString("VivoxLogDirectory"); - - if (log_folder.empty()) + else { - log_folder = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + params.args.add(loglevel); } params.args.add("-lf"); - params.args.add(log_folder); + if (log_folder().empty()) + { + params.args.add(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "")); + } + else + { + params.args.add(log_folder); + } // set log file basename and .log params.args.add("-lp"); @@ -988,8 +1012,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() LLFile::rename(new_log, old_log); } - std::string shutdown_timeout = gSavedSettings.getString("VivoxShutdownTimeout"); - if (!shutdown_timeout.empty()) + if (!shutdown_timeout().empty()) { params.args.add("-st"); params.args.add(shutdown_timeout); @@ -1012,7 +1035,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() sGatewayPtr = LLProcess::create(params); - mDaemonHost = LLHost(host.c_str(), port); + mDaemonHost = LLHost(host().c_str(), port); } else { @@ -1051,7 +1074,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; @@ -1061,23 +1084,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(); } @@ -1099,7 +1122,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); //--------------------------------------------------------------------- @@ -1321,9 +1344,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); } @@ -1335,7 +1358,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; } @@ -2516,7 +2539,7 @@ bool LLVivoxVoiceClient::performMicTuning() void LLVivoxVoiceClient::closeSocket(void) { mSocket.reset(); - mConnected = false; + sConnected = false; mConnectorEstablished = false; mAccountLoggedIn = false; } @@ -3017,7 +3040,7 @@ bool LLVivoxVoiceClient::deviceSettingsAvailable() { bool result = true; - if(!mConnected) + if(!sConnected) result = false; if(mRenderDevices.empty()) @@ -3816,7 +3839,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))); @@ -7389,7 +7412,7 @@ LLIOPipe::EStatus LLVivoxProtocolParser::process_impl( LL_DEBUGS("VivoxProtocolParser") << "at end, mInput is: " << mInput << LL_ENDL; - 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 0a785401c1..e3ab99c675 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -666,12 +666,10 @@ private: 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; @@ -916,7 +914,10 @@ private: 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 e9a1724639..c7054102fd 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5296,13 +5296,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); } } @@ -5857,15 +5858,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 @@ -6681,7 +6687,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace LLRenderPass::PASS_NORMSPEC_EMISSIVE, }; - U32 mask = mat->getShaderMask(); + U32 mask = mat->getShaderMask(LLMaterial::DIFFUSE_ALPHA_MODE_DEFAULT, is_alpha); llassert(mask < sizeof(pass)/sizeof(U32)); diff --git a/indra/newview/skins/default/textures/icons/Icon_Color_Palette.png b/indra/newview/skins/default/textures/icons/Icon_Color_Palette.png Binary files differnew file mode 100644 index 0000000000..28906001ea --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Icon_Color_Palette.png diff --git a/indra/newview/skins/default/textures/icons/Icon_Font_Size.png b/indra/newview/skins/default/textures/icons/Icon_Font_Size.png Binary files differnew file mode 100644 index 0000000000..37bdde69aa --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Icon_Font_Size.png diff --git a/indra/newview/skins/default/textures/icons/VoiceMute_Off.png b/indra/newview/skins/default/textures/icons/VoiceMute_Off.png Binary files differnew file mode 100644 index 0000000000..425ba267a5 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/VoiceMute_Off.png diff --git a/indra/newview/skins/default/textures/icons/profile_badge_beta.png b/indra/newview/skins/default/textures/icons/profile_badge_beta.png Binary files differnew file mode 100644 index 0000000000..7c8a723c47 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_badge_beta.png 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 Binary files differnew file mode 100644 index 0000000000..7c38e9e2ae --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_badge_beta_lifetime.png diff --git a/indra/newview/skins/default/textures/icons/profile_badge_lifetime.png b/indra/newview/skins/default/textures/icons/profile_badge_lifetime.png Binary files differnew file mode 100644 index 0000000000..475edd080e --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_badge_lifetime.png diff --git a/indra/newview/skins/default/textures/icons/profile_badge_linden.png b/indra/newview/skins/default/textures/icons/profile_badge_linden.png Binary files differnew file mode 100644 index 0000000000..1b6ac03e86 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_badge_linden.png 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 Binary files differnew file mode 100644 index 0000000000..4286995202 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_badge_pplus_lifetime.png 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 Binary files differnew file mode 100644 index 0000000000..47e93c4fac --- /dev/null +++ b/indra/newview/skins/default/textures/icons/profile_badge_premium_lifetime.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 72c8f03017..d237ddd518 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -63,6 +63,7 @@ with the same filename but different name <texture name="AudioMute_Off" file_name="icons/AudioMute_Off.png" preload="false" /> <texture name="AudioMute_Over" file_name="icons/AudioMute_Over.png" preload="false" /> + <texture name="VoiceMute_Off" file_name="icons/VoiceMute_Off.png" preload="false" /> <texture name="Audio_Off" file_name="icons/Audio_Off.png" preload="false" /> <texture name="Audio_Press" file_name="icons/Audio_Press.png" preload="false" /> @@ -511,7 +512,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"/> @@ -875,4 +882,7 @@ with the same filename but different name <texture name="System_Notification" file_name="icons/SL_Logo.png" preload="true"/> <texture name="Icon_Attachment_Small" file_name="icons/Icon_Attachment_Small.png" preload="true"/> <texture name="Icon_Attachment_Large" file_name="icons/Icon_Attachment_Large.png" preload="true"/> + + <texture name="Icon_Color_Palette" file_name="icons/Icon_Color_Palette.png" preload="false"/> + <texture name="Icon_Font_Size" file_name="icons/Icon_Font_Size.png" preload="false"/> </textures> diff --git a/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml b/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml index e8826034f6..88173e68fa 100644 --- a/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml +++ b/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml @@ -4,7 +4,7 @@ bevel_style="none" border_style="line" can_resize="true" - height="582" + height="607" layout="topleft" min_height="271" min_width="328" @@ -45,6 +45,21 @@ name="loading"> Loading... </floater.string> + <text + type="string" + length="1" + follows="left|top|right" + width="490" + use_ellipses="true" + font="SansSerif" + height="18" + layout="topleft" + left="13" + name="obj_name" + text_color="white" + top="21"> + Object name + </text> <panel bevel_style="none" @@ -54,7 +69,7 @@ layout="topleft" left="10" name="script ed panel" - top="16" + top_pad="2" width="501" /> <button follows="left|bottom" 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 37efbe654e..b757f4eab8 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_script_ed_prefs.xml b/indra/newview/skins/default/xui/en/floater_script_ed_prefs.xml index 8e4bcb3eb0..8ae1e74d52 100644 --- a/indra/newview/skins/default/xui/en/floater_script_ed_prefs.xml +++ b/indra/newview/skins/default/xui/en/floater_script_ed_prefs.xml @@ -335,6 +335,7 @@ layout="topleft" max_length="300" name="Script Preview" + default_font_size="true" text_color="ScriptText" default_color="ScriptText" bg_writeable_color="ScriptBackground" diff --git a/indra/newview/skins/default/xui/en/floater_script_preview.xml b/indra/newview/skins/default/xui/en/floater_script_preview.xml index 91a9e67e4c..91c18035db 100644 --- a/indra/newview/skins/default/xui/en/floater_script_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_script_preview.xml @@ -2,10 +2,10 @@ <floater legacy_header_height="18" can_resize="true" - height="570" + height="593" layout="topleft" min_height="271" - min_width="290" + min_width="320" name="preview lsl text" help_topic="preview_lsl_text" save_rect="true" @@ -21,7 +21,7 @@ layout="topleft" left="10" name="script panel" - top="42" + top="65" width="497" /> <icon follows="top|right" @@ -36,13 +36,28 @@ <text type="string" length="1" + follows="left|top|right" + width="490" + use_ellipses="true" + font="SansSerif" + height="18" + layout="topleft" + left="13" + name="path_txt" + text_color="white" + top="21"> + File path + </text> + <text + type="string" + length="1" follows="left|top" font="SansSerif" height="19" layout="topleft" left="13" name="desc txt" - top="19" + top_pad="5" width="80"> Description: </text> diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml index b9ca0108b6..0fde6a329a 100644 --- a/indra/newview/skins/default/xui/en/floater_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_stats.xml @@ -25,7 +25,7 @@ name="statistics_view" top="20" width="250" > - <stat_view name="basic" + <stat_view name="basic" label="Basic" setting="OpenDebugStatBasic"> <stat_bar name="fps" @@ -54,7 +54,7 @@ label="jitter" decimal_digits="1" stat="frametimejitter"/> - <stat_bar name="bandwidth" + <stat_bar name="bandwidth" label="UDP Data Received" stat="activemessagedatareceived" decimal_digits="0" @@ -68,7 +68,7 @@ stat="simpingstat"/> </stat_view> - <stat_view name="advanced" + <stat_view name="advanced" label="Advanced" setting="OpenDebugStatAdvanced"> <stat_view name="render" @@ -84,28 +84,29 @@ <stat_bar name="totalobjs" label="Total Objects" stat="numobjectsstat"/> - <stat_bar name="cachedobjs" + <stat_bar name="cachedobjs" label="Cached Objects" stat="numactivecachedobjects"/> - <stat_bar name="newobjs" + <stat_bar name="newobjs" label="New Objects" stat="numnewobjectsstat"/> <stat_bar name="object_cache_hits" label="Object Cache Hit Rate" stat="object_cache_hits" show_history="true"/> - <stat_bar name="occlusion_queries" - label="Occlusion Queries Performed" - stat="occlusion_queries"/> - <stat_bar name="occluded" - label="Objects Occluded" - stat="occluded_objects"/> - <stat_bar name="unoccluded" - label="Object Unoccluded" - stat="unoccluded_objects"/> - </stat_view> + <stat_bar name="occlusion_queries" + label="Occlusion Queries Performed" + stat="occlusion_queries"/> + <stat_bar name="occluded" + label="Objects Occluded" + stat="occluded_objects"/> + <stat_bar name="unoccluded" + label="Object Unoccluded" + stat="unoccluded_objects"/> + </stat_view> <stat_view name="texture" - label="Texture"> + label="Texture" + setting="OpenDebugStatTexture"> <stat_bar name="texture_cache_hits" label="Cache Hit Rate" stat="texture_cache_hits" @@ -133,54 +134,55 @@ label="Bound Mem" stat="glboundmemstat"/> </stat_view> - <stat_view name="memory" - label="Memory Usage"> - <stat_bar name="LLTrace" + <stat_view name="memory" + label="Memory Usage" + setting="OpenDebugStatMemory"> + <stat_bar name="LLTrace" label="LLTrace" stat="LLTrace"/> - <stat_bar name="LLView" + <stat_bar name="LLView" label="UI" stat="LLView"/> - <stat_bar name="LLFontFreetype" + <stat_bar name="LLFontFreetype" label="Fonts" stat="LLFontFreetype"/> - <stat_bar name="LLInventoryObject" + <stat_bar name="LLInventoryObject" label="Inventory" stat="LLInventoryObject"/> - <stat_bar name="LLViewerObject" + <stat_bar name="LLViewerObject" label="Viewer Objects" stat="LLViewerObject"/> - <stat_bar name="LLViewerOctreeGroup" - label="Octree Group Data" - stat="LLViewerOctreeGroup"/> - <stat_bar name="LLViewerOctreeEntry" - label="Octree Data" - stat="LLViewerOctreeEntry"/> - <stat_bar name="LLVOCacheEntry" + <stat_bar name="LLViewerOctreeGroup" + label="Octree Group Data" + stat="LLViewerOctreeGroup"/> + <stat_bar name="LLViewerOctreeEntry" + label="Octree Data" + stat="LLViewerOctreeEntry"/> + <stat_bar name="LLVOCacheEntry" label="Viewer Object Cache" stat="LLVOCacheEntry"/> - <stat_bar name="LLDrawable" + <stat_bar name="LLDrawable" label="Drawables" stat="LLDrawable"/> - <stat_bar name="LLFace" - label="Face Data" - stat="LLFace"/> + <stat_bar name="LLFace" + label="Face Data" + stat="LLFace"/> <stat_bar name="LLDrawInfo" - label="Draw Info" - stat="LLDrawInfo"/> + label="Draw Info" + stat="LLDrawInfo"/> <stat_bar name="LLTexture" - label="Texture Data" - stat="LLTexture"/> - <stat_bar name="LLImage" + label="Texture Data" + stat="LLTexture"/> + <stat_bar name="LLImage" label="Image Data" stat="LLImage"/> - <stat_bar name="LLImageGL" + <stat_bar name="LLImageGL" label="GL Image Data" stat="LLImageGL"/> - <stat_bar name="LLVertexBuffer" + <stat_bar name="LLVertexBuffer" label="Vertex Buffers" stat="LLVertexBuffer"/> - </stat_view> + </stat_view> <stat_view name="network" label="Network" setting="OpenDebugStatNet"> @@ -237,7 +239,8 @@ decimal_digits="1" bar_max="45" /> <stat_view name="physicsdetail" - label="Physics Details"> + label="Physics Details" + setting="OpenDebugStatPhysicsDetails"> <stat_bar name="physicspinnedtasks" label="Pinned Objects" stat="physicspinnedtasks"/> @@ -276,7 +279,8 @@ stat="simscripteps" unit_label="eps"/> <stat_view name="simpathfinding" - label="Pathfinding"> + label="Pathfinding" + setting="OpenDebugStatPathfinding"> <stat_bar name="simsimaistepmsec" label="AI Step Time" stat="simsimaistepmsec"/> @@ -309,7 +313,8 @@ stat="simtotalunackedbytes" decimal_digits="1"/> <stat_view name="simperf" - label="Time"> + label="Time" + setting="OpenDebugStatSimTime"> <stat_bar name="simframemsec" label="Total Frame Time" stat="simframemsec"/> @@ -335,7 +340,8 @@ label="Spare Time" stat="simsparemsec"/> <stat_view name="timedetails" - label="Time Details"> + label="Time Details" + setting="OpenDebugStatSimTimeDetails"> <stat_bar name="simsimphysicsstepmsec" label="Physics Step" stat="simsimphysicsstepmsec"/> 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 a212ce7889..3f3331b468 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/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml index d88c267a95..3c3eb6b66f 100644 --- a/indra/newview/skins/default/xui/en/fonts.xml +++ b/indra/newview/skins/default/xui/en/fonts.xml @@ -170,4 +170,12 @@ comment="Size of small font (points, or 1/72 of an inch)" size="7.6" /> + <font_size name="SmallLSL" + comment="Size of small font for LSL editor (points, or 1/72 of an inch)" + size="7" + /> + <font_size name="HugeLSL" + comment="Size of huge font for LSL editor (points, or 1/72 of an inch)" + size="12" + /> </fonts> diff --git a/indra/newview/skins/default/xui/en/menu_lsl_font_size.xml b/indra/newview/skins/default/xui/en/menu_lsl_font_size.xml new file mode 100644 index 0000000000..39a2bc511c --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_lsl_font_size.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + bottom="806" + layout="topleft" + left="0" + mouse_opaque="false" + name="menu_font_size" + visible="false"> + <menu_item_check + label="Small" + layout="topleft" + name="font_small"> + <on_click + function="FontSize.Set" + parameter="SmallLSL" /> + <on_check + function="FontSize.Check" + parameter="SmallLSL" /> + </menu_item_check> + <menu_item_check + label="Default" + layout="topleft" + name="font_monospace"> + <on_click + function="FontSize.Set" + parameter="Monospace" /> + <on_check + function="FontSize.Check" + parameter="Monospace" /> + </menu_item_check> + <menu_item_check + label="Medium" + layout="topleft" + name="font_medium"> + <on_click + function="FontSize.Set" + parameter="Medium" /> + <on_check + function="FontSize.Check" + parameter="Medium" /> + </menu_item_check> + <menu_item_check + label="Large" + layout="topleft" + name="font_large"> + <on_click + function="FontSize.Set" + parameter="Large" /> + <on_check + function="FontSize.Check" + parameter="Large" /> + </menu_item_check> + <menu_item_check + label="Huge" + layout="topleft" + name="font_huge"> + <on_click + function="FontSize.Set" + parameter="HugeLSL" /> + <on_check + function="FontSize.Check" + parameter="HugeLSL" /> + </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index f9211600ea..a216ef7c0d 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6370,6 +6370,14 @@ Your trash is overflowing. This may cause problems logging in. </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" type="alertmodal"> diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml b/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml index b72af7221e..8e2a241661 100644 --- a/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml +++ b/indra/newview/skins/default/xui/en/panel_group_list_item_short.xml @@ -71,7 +71,6 @@ name="visibility_show_btn" tool_tip="Show group on my profile" top_delta="0" - right_delta="0" height="20" width="20" follows="right" 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 777b37d666..07cdd6d71e 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml @@ -27,6 +27,26 @@ 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" /> <layout_stack name="image_stack" @@ -156,9 +176,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 +216,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/panel_script_ed.xml b/indra/newview/skins/default/xui/en/panel_script_ed.xml index 545c01935b..4ea4a4f38d 100644 --- a/indra/newview/skins/default/xui/en/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/en/panel_script_ed.xml @@ -44,10 +44,12 @@ layout="topleft" left="0" mouse_opaque="false" + font="SansSerif" name="File" width="138"> <menu_item_call label="Save" + shortcut="control|S" layout="topleft" name="Save" /> <menu_item_separator @@ -66,16 +68,6 @@ label="Save to file..." layout="topleft" name="SaveToFile" /> - <menu_item_separator - layout="topleft" /> - <menu_item_call - label="Colors..." - layout="topleft" - name="Colors"> - <menu_item_call.on_click - function="Floater.Toggle" - parameter="script_colors"/> - </menu_item_call> </menu> <menu top="0" @@ -83,6 +75,7 @@ label="Edit" layout="topleft" mouse_opaque="false" + font="SansSerif" name="Edit" width="139"> <menu_item_call @@ -117,6 +110,7 @@ name="separator2" /> <menu_item_call label="Select All" + shortcut="control|A" layout="topleft" name="Select All" /> <menu_item_call @@ -142,6 +136,7 @@ label="Help" layout="topleft" mouse_opaque="false" + font="SansSerif" name="Help" width="112"> <menu_item_call @@ -150,12 +145,34 @@ name="Keyword Help..." /> </menu> </menu_bar> + <menu_button + follows="right|top" + height="24" + image_overlay="Icon_Font_Size" + layout="topleft" + top_delta="-2" + right="453" + name="font_btn" + width="32" /> + <button + follows="right|top" + height="24" + image_overlay="Icon_Color_Palette" + layout="topleft" + top_delta="0" + right="487" + name="color_btn" + width="32"> + <button.commit_callback + function="Floater.Toggle" + parameter="script_colors"/> + </button> <script_editor left="0" type="string" length="1" follows="left|top|right|bottom" - font="Monospace" + height="376" ignore_tab="false" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_sound_devices.xml b/indra/newview/skins/default/xui/en/panel_sound_devices.xml index 3dbb7fb7fc..a1ce99c8be 100644 --- a/indra/newview/skins/default/xui/en/panel_sound_devices.xml +++ b/indra/newview/skins/default/xui/en/panel_sound_devices.xml @@ -122,7 +122,7 @@ layout="topleft" left_pad="5" name="wait_text" - top_delta="-1" + top_delta="2" width="110"> Please wait </text> @@ -132,7 +132,7 @@ layout="topleft" left_delta="0" name="bar0" - top_delta="-2" + top_delta="-5" width="20" /> <locate follows="right|top" @@ -166,4 +166,26 @@ name="bar4" top_delta="0" width="20" /> + <text + type="string" + name="disabled_text" + text_color="EmphasisColor" + length="1" + follows="right|top" + height="18" + layout="topleft" + left_delta="-100" + top_delta="5" + width="110"> + Disabled + </text> + <button + follows="right|top" + height="23" + layout="topleft" + left_delta="0" + name="unmute_btn" + label="Unmute" + top_delta="-6" + width="110" /> </panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml index b4eb1ade94..3c466022d8 100644 --- a/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml +++ b/indra/newview/skins/default/xui/en/panel_volume_pulldown.xml @@ -199,7 +199,8 @@ top_delta="2" width="350"> <check_box.commit_callback - function="Vol.updateMediaAutoPlayCheckbox"/> + function="Vol.updateCheckbox" + parameter="MediaAutoPlay"/> </check_box> <slider control_name="AudioLevelMedia" @@ -246,7 +247,8 @@ name="enable_media" width="110"> <check_box.commit_callback - function="Vol.updateMediaAutoPlayCheckbox"/> + function="Vol.updateCheckbox" + parameter="MediaAutoPlay"/> </check_box> <slider control_name="AudioLevelVoice" @@ -292,5 +294,6 @@ top_delta="2" left_pad="5" name="enable_voice_check" - width="110"/> + width="110" + /> </panel> diff --git a/indra/newview/skins/default/xui/en/widgets/menu.xml b/indra/newview/skins/default/xui/en/widgets/menu.xml index 13ac84beb2..0e2b478aa5 100644 --- a/indra/newview/skins/default/xui/en/widgets/menu.xml +++ b/indra/newview/skins/default/xui/en/widgets/menu.xml @@ -4,5 +4,6 @@ bg_visible="true" drop_shadow="true" tear_off="false" + font="SansSerifSmall" shortcut_pad="15"> </menu> 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 13f1f892f9..e9750a1c2e 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> |