diff options
| author | Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> | 2026-01-07 19:24:11 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-07 19:24:11 +0200 |
| commit | 1cf375c89adfae557b18dadfb267659b6fb0a8ce (patch) | |
| tree | 77c9f59277aad29cf00dd2de00d97c1909f9f59e /indra | |
| parent | 516bd5e832a91e1f837b5b1b621cfac5fe71c08f (diff) | |
| parent | cab31f8bfed507425a09b266d47823f6acddfa94 (diff) | |
Merge pull request #5227 from RyeMutt/rye/devmerge
Sync develop-linux with develop
Diffstat (limited to 'indra')
92 files changed, 1247 insertions, 1904 deletions
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index 1bdaa814b7..5a02dfe716 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -1449,6 +1449,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC size_t mem_size = pixels * bytes_per_pixel; alpha_data = (U8*)ll_aligned_malloc_32(mem_size); + if (!alpha_data) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate memory for morph texture: " << (S32)(mem_size) << LL_ENDL; + return; + } bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels @@ -1458,6 +1464,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC { // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO // returning only the alpha portion without locking up downstream U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA + if (!temp) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate temporary memory for morph texture readback: " << (S32)(mem_size << 2) << LL_ENDL; + return; + } if (bound_target) { @@ -1494,6 +1506,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // We just want GL_ALPHA, but that isn't supported in OGL core profile 4. static const size_t TEMP_BYTES_PER_PIXEL = 4; U8* temp_data = (U8*)ll_aligned_malloc_32(mem_size * TEMP_BYTES_PER_PIXEL); + if (!temp_data) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate temporary memory for morph texture: " << (S32)(mem_size * TEMP_BYTES_PER_PIXEL) << LL_ENDL; + return; + } glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, temp_data); for (size_t pixel = 0; pixel < pixels; pixel++) { alpha_data[pixel] = temp_data[(pixel * TEMP_BYTES_PER_PIXEL) + 3]; diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt index 0d7802279a..9dbbddde8a 100644 --- a/indra/llcharacter/CMakeLists.txt +++ b/indra/llcharacter/CMakeLists.txt @@ -17,14 +17,12 @@ set(llcharacter_SOURCE_FILES lljointsolverrp3.cpp llkeyframefallmotion.cpp llkeyframemotion.cpp - llkeyframemotionparam.cpp llkeyframestandmotion.cpp llkeyframewalkmotion.cpp llmotioncontroller.cpp llmotion.cpp llmultigesture.cpp llpose.cpp - llstatemachine.cpp lltargetingmotion.cpp llvisualparam.cpp ) @@ -45,14 +43,12 @@ set(llcharacter_HEADER_FILES lljointstate.h llkeyframefallmotion.h llkeyframemotion.h - llkeyframemotionparam.h llkeyframestandmotion.h llkeyframewalkmotion.h llmotion.h llmotioncontroller.h llmultigesture.h llpose.h - llstatemachine.h lltargetingmotion.h llvisualparam.h ) diff --git a/indra/llcharacter/llkeyframemotionparam.cpp b/indra/llcharacter/llkeyframemotionparam.cpp deleted file mode 100644 index e4552b96c9..0000000000 --- a/indra/llcharacter/llkeyframemotionparam.cpp +++ /dev/null @@ -1,436 +0,0 @@ -/** - * @file llkeyframemotionparam.cpp - * @brief Implementation of LLKeyframeMotion class. - * - * $LicenseInfo:firstyear=2001&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$ - */ - -//----------------------------------------------------------------------------- -// Header Files -//----------------------------------------------------------------------------- -#include "linden_common.h" - -#include "llkeyframemotionparam.h" -#include "llcharacter.h" -#include "llmath.h" -#include "m3math.h" -#include "lldir.h" -#include "llanimationstates.h" - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam class -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam() -// Class Constructor -//----------------------------------------------------------------------------- -LLKeyframeMotionParam::LLKeyframeMotionParam( const LLUUID &id) : LLMotion(id) -{ - mDefaultKeyframeMotion = NULL; - mCharacter = NULL; - - mEaseInDuration = 0.f; - mEaseOutDuration = 0.f; - mDuration = 0.f; - mPriority = LLJoint::LOW_PRIORITY; -} - - -//----------------------------------------------------------------------------- -// ~LLKeyframeMotionParam() -// Class Destructor -//----------------------------------------------------------------------------- -LLKeyframeMotionParam::~LLKeyframeMotionParam() -{ - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - delete paramMotion.mMotion; - } - motionList.clear(); - } - mParameterizedMotions.clear(); -} - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::onInitialize(LLCharacter *character) -//----------------------------------------------------------------------------- -LLMotion::LLMotionInitStatus LLKeyframeMotionParam::onInitialize(LLCharacter *character) -{ - mCharacter = character; - - if (!loadMotions()) - { - return STATUS_FAILURE; - } - - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - LLMotion* motion = paramMotion.mMotion; - motion->onInitialize(character); - - if (motion->getDuration() > mEaseInDuration) - { - mEaseInDuration = motion->getEaseInDuration(); - } - - if (motion->getEaseOutDuration() > mEaseOutDuration) - { - mEaseOutDuration = motion->getEaseOutDuration(); - } - - if (motion->getDuration() > mDuration) - { - mDuration = motion->getDuration(); - } - - if (motion->getPriority() > mPriority) - { - mPriority = motion->getPriority(); - } - - LLPose *pose = motion->getPose(); - - mPoseBlender.addMotion(motion); - for (LLJointState *jsp = pose->getFirstJointState(); jsp; jsp = pose->getNextJointState()) - { - LLPose *blendedPose = mPoseBlender.getBlendedPose(); - blendedPose->addJointState(jsp); - } - } - } - - return STATUS_SUCCESS; -} - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::onActivate() -//----------------------------------------------------------------------------- -bool LLKeyframeMotionParam::onActivate() -{ - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - paramMotion.mMotion->activate(mActivationTimestamp); - } - } - return true; -} - - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::onUpdate() -//----------------------------------------------------------------------------- -bool LLKeyframeMotionParam::onUpdate(F32 time, U8* joint_mask) -{ - LL_PROFILE_ZONE_SCOPED; - F32 weightFactor = 1.f / (F32)mParameterizedMotions.size(); - - // zero out all pose weights - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { -// LL_INFOS() << "Weight for pose " << paramMotion.mMotion->getName() << " is " << paramMotion.mMotion->getPose()->getWeight() << LL_ENDL; - paramMotion.mMotion->getPose()->setWeight(0.f); - } - } - - - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - const std::string& paramName = motion_pair.first; - F32* paramValue = (F32 *)mCharacter->getAnimationData(paramName); - if (NULL == paramValue) // unexpected, but... - { - LL_WARNS() << "paramValue == NULL" << LL_ENDL; - continue; - } - - // DANGER! Do not modify mParameterizedMotions while using these pointers! - const ParameterizedMotion* firstMotion = NULL; - const ParameterizedMotion* secondMotion = NULL; - - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - paramMotion.mMotion->onUpdate(time, joint_mask); - - F32 distToParam = paramMotion.mParam - *paramValue; - - if ( distToParam <= 0.f) - { - // keep track of the motion closest to the parameter value - firstMotion = ¶mMotion; - } - else - { - // we've passed the parameter value - // so store the first motion we find as the second one we want to blend... - if (firstMotion && !secondMotion ) - { - secondMotion = ¶mMotion; - } - //...or, if we've seen no other motion so far, make sure we blend to this only - else if (!firstMotion) - { - firstMotion = ¶mMotion; - secondMotion = ¶mMotion; - } - } - } - - LLPose *firstPose; - LLPose *secondPose; - - if (firstMotion) - firstPose = firstMotion->mMotion->getPose(); - else - firstPose = NULL; - - if (secondMotion) - secondPose = secondMotion->mMotion->getPose(); - else - secondPose = NULL; - - // now modify weight of the subanim (only if we are blending between two motions) - if (firstMotion && secondMotion) - { - if (firstMotion == secondMotion) - { - firstPose->setWeight(weightFactor); - } - else if (firstMotion->mParam == secondMotion->mParam) - { - firstPose->setWeight(0.5f * weightFactor); - secondPose->setWeight(0.5f * weightFactor); - } - else - { - F32 first_weight = 1.f - - ((llclamp(*paramValue - firstMotion->mParam, 0.f, (secondMotion->mParam - firstMotion->mParam))) / - (secondMotion->mParam - firstMotion->mParam)); - first_weight = llclamp(first_weight, 0.f, 1.f); - - F32 second_weight = 1.f - first_weight; - - firstPose->setWeight(first_weight * weightFactor); - secondPose->setWeight(second_weight * weightFactor); - -// LL_INFOS() << "Parameter " << *paramName << ": " << *paramValue << LL_ENDL; -// LL_INFOS() << "Weights " << firstPose->getWeight() << " " << secondPose->getWeight() << LL_ENDL; - } - } - else if (firstMotion && !secondMotion) - { - firstPose->setWeight(weightFactor); - } - } - - // blend poses - mPoseBlender.blendAndApply(); - - LL_INFOS() << "Param Motion weight " << mPoseBlender.getBlendedPose()->getWeight() << LL_ENDL; - - return true; -} - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::onDeactivate() -//----------------------------------------------------------------------------- -void LLKeyframeMotionParam::onDeactivate() -{ - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - paramMotion.mMotion->onDeactivate(); - } - } -} - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::addKeyframeMotion() -//----------------------------------------------------------------------------- -bool LLKeyframeMotionParam::addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value) -{ - LLMotion *newMotion = mCharacter->createMotion( id ); - - if (!newMotion) - { - return false; - } - - newMotion->setName(name); - - // now add motion to this list - mParameterizedMotions[param].insert(ParameterizedMotion(newMotion, value)); - - return true; -} - - -//----------------------------------------------------------------------------- -// LLKeyframeMotionParam::setDefaultKeyframeMotion() -//----------------------------------------------------------------------------- -void LLKeyframeMotionParam::setDefaultKeyframeMotion(char *name) -{ - for (motion_map_t::value_type& motion_pair : mParameterizedMotions) - { - motion_list_t& motionList = motion_pair.second; - for (const ParameterizedMotion& paramMotion : motionList) - { - if (paramMotion.mMotion->getName() == name) - { - mDefaultKeyframeMotion = paramMotion.mMotion; - } - } - } -} - -//----------------------------------------------------------------------------- -// loadMotions() -//----------------------------------------------------------------------------- -bool LLKeyframeMotionParam::loadMotions() -{ - //------------------------------------------------------------------------- - // Load named file by concatenating the character prefix with the motion name. - // Load data into a buffer to be parsed. - //------------------------------------------------------------------------- - //std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix()) - // + "_" + getName() + ".llp"; - //RN: deprecated unused reference to "motion" directory - std::string path; - - - //------------------------------------------------------------------------- - // open the file - //------------------------------------------------------------------------- - S32 fileSize = 0; - LLAPRFile infile ; - infile.open(path, LL_APR_R, NULL, &fileSize); - apr_file_t* fp = infile.getFileHandle() ; - if (!fp || fileSize == 0) - { - LL_INFOS() << "ERROR: can't open: " << path << LL_ENDL; - return false; - } - - // allocate a text buffer - std::vector<char> text(fileSize+1); - - //------------------------------------------------------------------------- - // load data from file into buffer - //------------------------------------------------------------------------- - bool error = false; - char *p = &text[0]; - while ( 1 ) - { - if (apr_file_eof(fp) == APR_EOF) - { - break; - } - if (apr_file_gets(p, 1024, fp) != APR_SUCCESS) - { - error = true; - break; - } - while ( *(++p) ) - ; - } - - //------------------------------------------------------------------------- - // close the file - //------------------------------------------------------------------------- - infile.close(); - - //------------------------------------------------------------------------- - // check for error - //------------------------------------------------------------------------- - llassert( p <= (&text[0] + fileSize) ); - - if ( error ) - { - LL_INFOS() << "ERROR: error while reading from " << path << LL_ENDL; - return false; - } - - LL_INFOS() << "Loading parametric keyframe data for: " << getName() << LL_ENDL; - - //------------------------------------------------------------------------- - // parse the text and build keyframe data structures - //------------------------------------------------------------------------- - p = &text[0]; - S32 num; - char strA[80]; /* Flawfinder: ignore */ - char strB[80]; /* Flawfinder: ignore */ - F32 floatA = 0.0f; - - - //------------------------------------------------------------------------- - // get priority - //------------------------------------------------------------------------- - bool isFirstMotion = true; - num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */ - - while(1) - { - if (num == 0 || num == EOF) break; - if ((num != 3)) - { - LL_INFOS() << "WARNING: can't read parametric motion" << LL_ENDL; - return false; - } - - addKeyframeMotion(strA, gAnimLibrary.stringToAnimState(std::string(strA)), strB, floatA); - if (isFirstMotion) - { - isFirstMotion = false; - setDefaultKeyframeMotion(strA); - } - - p = strstr(p, "\n"); - if (!p) - { - break; - } - - p++; - num = sscanf(p, "%79s %79s %f", strA, strB, &floatA); /* Flawfinder: ignore */ - } - - return true; -} - -// End diff --git a/indra/llcharacter/llkeyframemotionparam.h b/indra/llcharacter/llkeyframemotionparam.h deleted file mode 100644 index 8c57766e9b..0000000000 --- a/indra/llcharacter/llkeyframemotionparam.h +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @file llkeyframemotionparam.h - * @brief Implementation of LLKeframeMotionParam class. - * - * $LicenseInfo:firstyear=2002&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_LLKEYFRAMEMOTIONPARAM_H -#define LL_LLKEYFRAMEMOTIONPARAM_H - -//----------------------------------------------------------------------------- -// Header files -//----------------------------------------------------------------------------- - -#include <string> - -#include "llmotion.h" -#include "lljointstate.h" -#include "v3math.h" -#include "llquaternion.h" -#include "llkeyframemotion.h" - -//----------------------------------------------------------------------------- -// class LLKeyframeMotionParam -//----------------------------------------------------------------------------- -class LLKeyframeMotionParam : - public LLMotion -{ -public: - // Constructor - LLKeyframeMotionParam(const LLUUID &id); - - // Destructor - virtual ~LLKeyframeMotionParam(); - -public: - //------------------------------------------------------------------------- - // functions to support MotionController and MotionRegistry - //------------------------------------------------------------------------- - - // static constructor - // all subclasses must implement such a function and register it - static LLMotion *create(const LLUUID &id) { return new LLKeyframeMotionParam(id); } - -public: - //------------------------------------------------------------------------- - // animation callbacks to be implemented by subclasses - //------------------------------------------------------------------------- - - // motions must specify whether or not they loop - virtual bool getLoop() { - return true; - } - - // motions must report their total duration - virtual F32 getDuration() { - return mDuration; - } - - // motions must report their "ease in" duration - virtual F32 getEaseInDuration() { - return mEaseInDuration; - } - - // motions must report their "ease out" duration. - virtual F32 getEaseOutDuration() { - return mEaseOutDuration; - } - - // motions must report their priority - virtual LLJoint::JointPriority getPriority() { - return mPriority; - } - - virtual LLMotionBlendType getBlendType() { return NORMAL_BLEND; } - - // called to determine when a motion should be activated/deactivated based on avatar pixel coverage - virtual F32 getMinPixelArea() { return MIN_REQUIRED_PIXEL_AREA_KEYFRAME; } - - // run-time (post constructor) initialization, - // called after parameters have been set - // must return true to indicate success and be available for activation - virtual LLMotionInitStatus onInitialize(LLCharacter *character); - - // called when a motion is activated - // must return true to indicate success, or else - // it will be deactivated - virtual bool onActivate(); - - // called per time step - // must return true while it is active, and - // must return false when the motion is completed. - virtual bool onUpdate(F32 time, U8* joint_mask); - - // called when a motion is deactivated - virtual void onDeactivate(); - - virtual LLPose* getPose() { return mPoseBlender.getBlendedPose();} - -protected: - //------------------------------------------------------------------------- - // new functions defined by this subclass - //------------------------------------------------------------------------- - struct ParameterizedMotion - { - ParameterizedMotion(LLMotion* motion, F32 param) : mMotion(motion), mParam(param) {} - LLMotion* mMotion; - F32 mParam; - }; - - // add a motion and associated parameter triplet - bool addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value); - - // set default motion for LOD and retrieving blend constants - void setDefaultKeyframeMotion(char *); - - bool loadMotions(); - -protected: - //------------------------------------------------------------------------- - // Member Data - //------------------------------------------------------------------------- - - struct compare_motions - { - bool operator() (const ParameterizedMotion& a, const ParameterizedMotion& b) const - { - if (a.mParam != b.mParam) - return (a.mParam < b.mParam); - else - return a.mMotion < b.mMotion; - } - }; - - typedef std::set < ParameterizedMotion, compare_motions > motion_list_t; - typedef std::map <std::string, motion_list_t > motion_map_t; - motion_map_t mParameterizedMotions; - LLMotion* mDefaultKeyframeMotion; - LLCharacter* mCharacter; - LLPoseBlender mPoseBlender; - - F32 mEaseInDuration; - F32 mEaseOutDuration; - F32 mDuration; - LLJoint::JointPriority mPriority; - - LLUUID mTransactionID; -}; - -#endif // LL_LLKEYFRAMEMOTIONPARAM_H diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h index 0c262bf24a..c2cb174821 100644 --- a/indra/llcharacter/llmotioncontroller.h +++ b/indra/llcharacter/llmotioncontroller.h @@ -37,7 +37,6 @@ #include "llmotion.h" #include "llpose.h" #include "llframetimer.h" -#include "llstatemachine.h" #include "llstring.h" //----------------------------------------------------------------------------- diff --git a/indra/llcharacter/llstatemachine.cpp b/indra/llcharacter/llstatemachine.cpp deleted file mode 100644 index 38e9ef444c..0000000000 --- a/indra/llcharacter/llstatemachine.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/** - * @file llstatemachine.cpp - * @brief LLStateMachine implementation file. - * - * $LicenseInfo:firstyear=2001&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 "llstatemachine.h" -#include "llapr.h" - -#define FSM_PRINT_STATE_TRANSITIONS (0) - -U32 LLUniqueID::sNextID = 0; - -bool operator==(const LLUniqueID &a, const LLUniqueID &b) -{ - return (a.mId == b.mId); -} - -bool operator!=(const LLUniqueID &a, const LLUniqueID &b) -{ - return (a.mId != b.mId); -} - -//----------------------------------------------------------------------------- -// LLStateDiagram -//----------------------------------------------------------------------------- -LLStateDiagram::LLStateDiagram() -{ - mDefaultState = NULL; - mUseDefaultState = false; -} - -LLStateDiagram::~LLStateDiagram() -{ - -} - -// add a state to the state graph -bool LLStateDiagram::addState(LLFSMState *state) -{ - mStates[state] = Transitions(); - return true; -} - -// add a directed transition between 2 states -bool LLStateDiagram::addTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition) -{ - StateMap::iterator state_it; - state_it = mStates.find(&start_state); - Transitions* state_transitions = NULL; - if (state_it == mStates.end() ) - { - addState(&start_state); - state_transitions = &mStates[&start_state]; - } - else - { - state_transitions = &state_it->second; - } - state_it = mStates.find(&end_state); - if (state_it == mStates.end() ) - { - addState(&end_state); - } - - Transitions::iterator transition_it = state_transitions->find(&transition); - if (transition_it != state_transitions->end()) - { - LL_ERRS() << "LLStateTable::addDirectedTransition() : transition already exists" << LL_ENDL; - return false; // transition already exists - } - - (*state_transitions)[&transition] = &end_state; - return true; -} - -// add an undirected transition between 2 states -bool LLStateDiagram::addUndirectedTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition) -{ - bool result; - result = addTransition(start_state, end_state, transition); - if (result) - { - result = addTransition(end_state, start_state, transition); - } - return result; -} - -// add a transition that exists for every state -void LLStateDiagram::addDefaultTransition(LLFSMState& end_state, LLFSMTransition& transition) -{ - mDefaultTransitions[&transition] = &end_state; -} - -// process a possible transition, and get the resulting state -LLFSMState* LLStateDiagram::processTransition(LLFSMState& start_state, LLFSMTransition& transition) -{ - // look up transition - //LLFSMState** dest_state = (mStates.getValue(&start_state))->getValue(&transition); - LLFSMState* dest_state = NULL; - StateMap::iterator state_it = mStates.find(&start_state); - if (state_it == mStates.end()) - { - return NULL; - } - Transitions::iterator transition_it = state_it->second.find(&transition); - - // try default transitions if state-specific transition not found - if (transition_it == state_it->second.end()) - { - dest_state = mDefaultTransitions[&transition]; - } - else - { - dest_state = transition_it->second; - } - - // if we have a destination state... - if (NULL != dest_state) - { - // ...return it... - return dest_state; - } - // ... otherwise ... - else - { - // ...look for default state... - if (mUseDefaultState) - { - // ...return it if we have it... - return mDefaultState; - } - else - { - // ...or else we're still in the same state. - return &start_state; - } - } -} - -void LLStateDiagram::setDefaultState(LLFSMState& default_state) -{ - mUseDefaultState = true; - mDefaultState = &default_state; -} - -S32 LLStateDiagram::numDeadendStates() -{ - S32 numDeadends = 0; - for (StateMap::value_type& state_pair : mStates) - { - if (state_pair.second.size() == 0) - { - numDeadends++; - } - } - return numDeadends; -} - -bool LLStateDiagram::stateIsValid(LLFSMState& state) -{ - if (mStates.find(&state) != mStates.end()) - { - return true; - } - return false; -} - -LLFSMState* LLStateDiagram::getState(U32 state_id) -{ - for (StateMap::value_type& state_pair : mStates) - { - if (state_pair.first->getID() == state_id) - { - return state_pair.first; - } - } - return NULL; -} - -bool LLStateDiagram::saveDotFile(const std::string& filename) -{ - LLAPRFile outfile ; - outfile.open(filename, LL_APR_W); - apr_file_t* dot_file = outfile.getFileHandle() ; - - if (!dot_file) - { - LL_WARNS() << "LLStateDiagram::saveDotFile() : Couldn't open " << filename << " to save state diagram." << LL_ENDL; - return false; - } - apr_file_printf(dot_file, "digraph StateMachine {\n\tsize=\"100,100\";\n\tfontsize=40;\n\tlabel=\"Finite State Machine\";\n\torientation=landscape\n\tratio=.77\n"); - - for (StateMap::value_type& state_pair : mStates) - { - apr_file_printf(dot_file, "\t\"%s\" [fontsize=28,shape=box]\n", state_pair.first->getName().c_str()); - } - apr_file_printf(dot_file, "\t\"All States\" [fontsize=30,style=bold,shape=box]\n"); - - for (Transitions::value_type& transition_pair : mDefaultTransitions) - { - apr_file_printf(dot_file, "\t\"All States\" -> \"%s\" [label = \"%s\",fontsize=24];\n", transition_pair.second->getName().c_str(), - transition_pair.second->getName().c_str()); - } - - if (mDefaultState) - { - apr_file_printf(dot_file, "\t\"All States\" -> \"%s\";\n", mDefaultState->getName().c_str()); - } - - - for (StateMap::value_type& state_pair : mStates) - { - LLFSMState *state = state_pair.first; - - for (Transitions::value_type& transition_pair : state_pair.second) - { - std::string state_name = state->getName(); - std::string target_name = transition_pair.second->getName(); - std::string transition_name = transition_pair.first->getName(); - apr_file_printf(dot_file, "\t\"%s\" -> \"%s\" [label = \"%s\",fontsize=24];\n", state->getName().c_str(), - target_name.c_str(), - transition_name.c_str()); - } - } - - apr_file_printf(dot_file, "}\n"); - - return true; -} - -std::ostream& operator<<(std::ostream &s, LLStateDiagram &FSM) -{ - if (FSM.mDefaultState) - { - s << "Default State: " << FSM.mDefaultState->getName() << "\n"; - } - - for (LLStateDiagram::Transitions::value_type& transition_pair : FSM.mDefaultTransitions) - { - s << "Any State -- " << transition_pair.first->getName() - << " --> " << transition_pair.second->getName() << "\n"; - } - - for (LLStateDiagram::StateMap::value_type& state_pair : FSM.mStates) - { - for (LLStateDiagram::Transitions::value_type& transition_pair : state_pair.second) - { - s << state_pair.first->getName() << " -- " << transition_pair.first->getName() - << " --> " << transition_pair.second->getName() << "\n"; - } - s << "\n"; - } - - return s; -} - -//----------------------------------------------------------------------------- -// LLStateMachine -//----------------------------------------------------------------------------- - -LLStateMachine::LLStateMachine() -{ - // we haven't received a starting state yet - mCurrentState = NULL; - mLastState = NULL; - mLastTransition = NULL; - mStateDiagram = NULL; -} - -LLStateMachine::~LLStateMachine() -{ - -} - -// returns current state -LLFSMState* LLStateMachine::getCurrentState() const -{ - return mCurrentState; -} - -// executes current state -void LLStateMachine::runCurrentState(void *data) -{ - mCurrentState->execute(data); -} - -// set current state -bool LLStateMachine::setCurrentState(LLFSMState *initial_state, void* user_data, bool skip_entry) -{ - llassert(mStateDiagram); - - if (mStateDiagram->stateIsValid(*initial_state)) - { - mLastState = mCurrentState = initial_state; - if (!skip_entry) - { - initial_state->onEntry(user_data); - } - return true; - } - - return false; -} - -bool LLStateMachine::setCurrentState(U32 state_id, void* user_data, bool skip_entry) -{ - llassert(mStateDiagram); - - LLFSMState* state = mStateDiagram->getState(state_id); - - if (state) - { - mLastState = mCurrentState = state; - if (!skip_entry) - { - state->onEntry(user_data); - } - return true; - } - - return false; -} - -void LLStateMachine::processTransition(LLFSMTransition& transition, void* user_data) -{ - llassert(mStateDiagram); - - if (NULL == mCurrentState) - { - LL_WARNS() << "mCurrentState == NULL; aborting processTransition()" << LL_ENDL; - return; - } - - LLFSMState* new_state = mStateDiagram->processTransition(*mCurrentState, transition); - - if (NULL == new_state) - { - LL_WARNS() << "new_state == NULL; aborting processTransition()" << LL_ENDL; - return; - } - - mLastTransition = &transition; - mLastState = mCurrentState; - - if (*mCurrentState != *new_state) - { - mCurrentState->onExit(user_data); - mCurrentState = new_state; - mCurrentState->onEntry(user_data); -#if FSM_PRINT_STATE_TRANSITIONS - LL_INFOS() << "Entering state " << mCurrentState->getName() << - " on transition " << transition.getName() << " from state " << - mLastState->getName() << LL_ENDL; -#endif - } -} - -void LLStateMachine::setStateDiagram(LLStateDiagram* diagram) -{ - mStateDiagram = diagram; -} diff --git a/indra/llcharacter/llstatemachine.h b/indra/llcharacter/llstatemachine.h deleted file mode 100644 index 9a33798d96..0000000000 --- a/indra/llcharacter/llstatemachine.h +++ /dev/null @@ -1,147 +0,0 @@ -/** - * @file llstatemachine.h - * @brief LLStateMachine class header file. - * - * $LicenseInfo:firstyear=2001&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_LLSTATEMACHINE_H -#define LL_LLSTATEMACHINE_H - -#include <string> - -#include "llerror.h" -#include <map> - -class LLUniqueID -{ - friend bool operator==(const LLUniqueID &a, const LLUniqueID &b); - friend bool operator!=(const LLUniqueID &a, const LLUniqueID &b); -protected: - static U32 sNextID; - U32 mId; -public: - LLUniqueID(){mId = sNextID++;} - virtual ~LLUniqueID(){} - U32 getID() {return mId;} -}; - -class LLFSMTransition : public LLUniqueID -{ -public: - LLFSMTransition() : LLUniqueID(){}; - virtual std::string getName()const { return "unnamed"; } -}; - -class LLFSMState : public LLUniqueID -{ -public: - LLFSMState() : LLUniqueID(){}; - virtual void onEntry(void *){}; - virtual void onExit(void *){}; - virtual void execute(void *){}; - virtual std::string getName() const { return "unnamed"; } -}; - -class LLStateDiagram -{ -typedef std::map<LLFSMTransition*, LLFSMState*> Transitions; - -friend std::ostream& operator<<(std::ostream &s, LLStateDiagram &FSM); -friend class LLStateMachine; - -protected: - typedef std::map<LLFSMState*, Transitions> StateMap; - StateMap mStates; - Transitions mDefaultTransitions; - LLFSMState* mDefaultState; - bool mUseDefaultState; - -public: - LLStateDiagram(); - virtual ~LLStateDiagram(); - -protected: - // add a state to the state graph, executed implicitly when adding transitions - bool addState(LLFSMState *state); - - // add a directed transition between 2 states - bool addTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition); - - // add an undirected transition between 2 states - bool addUndirectedTransition(LLFSMState& start_state, LLFSMState& end_state, LLFSMTransition& transition); - - // add a transition that is taken if none other exist - void addDefaultTransition(LLFSMState& end_state, LLFSMTransition& transition); - - // process a possible transition, and get the resulting state - LLFSMState* processTransition(LLFSMState& start_state, LLFSMTransition& transition); - - // add a transition that exists for every state - void setDefaultState(LLFSMState& default_state); - - // return total number of states with no outgoing transitions - S32 numDeadendStates(); - - // does this state exist in the state diagram? - bool stateIsValid(LLFSMState& state); - - // get a state pointer by ID - LLFSMState* getState(U32 state_id); - -public: - // save the graph in a DOT file for rendering and visualization - bool saveDotFile(const std::string& filename); -}; - -class LLStateMachine -{ -protected: - LLFSMState* mCurrentState; - LLFSMState* mLastState; - LLFSMTransition* mLastTransition; - LLStateDiagram* mStateDiagram; - -public: - LLStateMachine(); - virtual ~LLStateMachine(); - - // set state diagram - void setStateDiagram(LLStateDiagram* diagram); - - // process this transition - void processTransition(LLFSMTransition &transition, void* user_data); - - // returns current state - LLFSMState* getCurrentState() const; - - // execute current state - void runCurrentState(void *data); - - // set state by state pointer - bool setCurrentState(LLFSMState *initial_state, void* user_data, bool skip_entry = true); - - // set state by unique ID - bool setCurrentState(U32 state_id, void* user_data, bool skip_entry = true); -}; - -#endif //_LL_LLSTATEMACHINE_H diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index cb3f0d7842..f2d19854b0 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -67,6 +67,7 @@ set(llcommon_SOURCE_FILES llmetricperformancetester.cpp llmortician.cpp llmutex.cpp + llpointer.cpp llptrto.cpp llpredicate.cpp llprocess.cpp diff --git a/indra/llcommon/llpointer.cpp b/indra/llcommon/llpointer.cpp new file mode 100755 index 0000000000..1bb7055b3a --- /dev/null +++ b/indra/llcommon/llpointer.cpp @@ -0,0 +1,43 @@ +/** + * @file llpointer.cpp + * @author Nat Goodspeed + * @date 2024-09-26 + * @brief Implementation for llpointer. + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llpointer.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llerror.h" + +void LLPointerBase::wild_dtor(std::string_view msg) +{ +// LL_WARNS() << msg << LL_ENDL; + llassert_msg(false, msg); +} diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h index 048547e4cc..d2dcf530e5 100644 --- a/indra/llcommon/llpointer.h +++ b/indra/llcommon/llpointer.h @@ -26,8 +26,9 @@ #ifndef LLPOINTER_H #define LLPOINTER_H -#include "llerror.h" // *TODO: consider eliminating this -#include "llmutex.h" +#include <functional> +#include <string_view> +#include <utility> // std::swap() //---------------------------------------------------------------------------- // RefCount objects should generally only be accessed by way of LLPointer<>'s @@ -42,8 +43,18 @@ //---------------------------------------------------------------------------- +class LLPointerBase +{ +protected: + // alert the coder that a referenced type's destructor did something very + // strange -- this is in a non-template base class so we can hide the + // implementation in llpointer.cpp + static void wild_dtor(std::string_view msg); +}; + // Note: relies on Type having ref() and unref() methods -template <class Type> class LLPointer +template <class Type> +class LLPointer: public LLPointerBase { public: template<typename Subclass> @@ -60,6 +71,13 @@ public: ref(); } + // Even though the template constructors below accepting + // (const LLPointer<Subclass>&) and (LLPointer<Subclass>&&) appear to + // subsume these specific (const LLPointer<Type>&) and (LLPointer<Type>&&) + // constructors, the compiler recognizes these as The Copy Constructor and + // The Move Constructor, respectively. In other words, even in the + // presence of the LLPointer<Subclass> constructors, we still must specify + // the LLPointer<Type> constructors. LLPointer(const LLPointer<Type>& ptr) : mPointer(ptr.mPointer) { @@ -98,39 +116,52 @@ public: const Type& operator*() const { return *mPointer; } Type& operator*() { return *mPointer; } - operator BOOL() const { return (mPointer != nullptr); } operator bool() const { return (mPointer != nullptr); } bool operator!() const { return (mPointer == nullptr); } bool isNull() const { return (mPointer == nullptr); } bool notNull() const { return (mPointer != nullptr); } operator Type*() const { return mPointer; } - bool operator !=(Type* ptr) const { return (mPointer != ptr); } - bool operator ==(Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } + template <typename Type1> + bool operator !=(Type1* ptr) const { return (mPointer != ptr); } + template <typename Type1> + bool operator ==(Type1* ptr) const { return (mPointer == ptr); } + template <typename Type1> + bool operator !=(const LLPointer<Type1>& ptr) const { return (mPointer != ptr.mPointer); } + template <typename Type1> + bool operator ==(const LLPointer<Type1>& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } LLPointer<Type>& operator =(Type* ptr) { - assign(ptr); + // copy-and-swap idiom, see http://gotw.ca/gotw/059.htm + LLPointer temp(ptr); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } + // Even though the template assignment operators below accepting + // (const LLPointer<Subclass>&) and (LLPointer<Subclass>&&) appear to + // subsume these specific (const LLPointer<Type>&) and (LLPointer<Type>&&) + // assignment operators, the compiler recognizes these as Copy Assignment + // and Move Assignment, respectively. In other words, even in the presence + // of the LLPointer<Subclass> assignment operators, we still must specify + // the LLPointer<Type> operators. LLPointer<Type>& operator =(const LLPointer<Type>& ptr) { - assign(ptr); + LLPointer temp(ptr); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } LLPointer<Type>& operator =(LLPointer<Type>&& ptr) { - if (mPointer != ptr.mPointer) - { - unref(); - mPointer = ptr.mPointer; - ptr.mPointer = nullptr; - } + LLPointer temp(std::move(ptr)); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } @@ -138,28 +169,32 @@ public: template<typename Subclass> LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr) { - assign(ptr.get()); + LLPointer temp(ptr); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } template<typename Subclass> LLPointer<Type>& operator =(LLPointer<Subclass>&& ptr) { - if (mPointer != ptr.mPointer) - { - unref(); - mPointer = ptr.mPointer; - ptr.mPointer = nullptr; - } + LLPointer temp(std::move(ptr)); + using std::swap; // per Swappable convention + swap(*this, temp); return *this; } // Just exchange the pointers, which will not change the reference counts. static void swap(LLPointer<Type>& a, LLPointer<Type>& b) { - Type* temp = a.mPointer; - a.mPointer = b.mPointer; - b.mPointer = temp; + using std::swap; // per Swappable convention + swap(a.mPointer, b.mPointer); + } + + // Put swap() overload in the global namespace, per Swappable convention + friend void swap(LLPointer<Type>& a, LLPointer<Type>& b) + { + LLPointer<Type>::swap(a, b); } protected: @@ -184,191 +219,19 @@ protected: temp->unref(); if (mPointer != nullptr) { - LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL; + wild_dtor("Unreference did assignment to non-NULL because of destructor"); unref(); } } } #endif // LL_LIBRARY_INCLUDE - void assign(const LLPointer<Type>& ptr) - { - if (mPointer != ptr.mPointer) - { - unref(); - mPointer = ptr.mPointer; - ref(); - } - } - protected: Type* mPointer; }; -template <class Type> class LLConstPointer -{ - template<typename Subclass> - friend class LLConstPointer; -public: - LLConstPointer() : - mPointer(nullptr) - { - } - - LLConstPointer(const Type* ptr) : - mPointer(ptr) - { - ref(); - } - - LLConstPointer(const LLConstPointer<Type>& ptr) : - mPointer(ptr.mPointer) - { - ref(); - } - - LLConstPointer(LLConstPointer<Type>&& ptr) noexcept - { - mPointer = ptr.mPointer; - ptr.mPointer = nullptr; - } - - // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template<typename Subclass> - LLConstPointer(const LLConstPointer<Subclass>& ptr) : - mPointer(ptr.get()) - { - ref(); - } - - template<typename Subclass> - LLConstPointer(LLConstPointer<Subclass>&& ptr) noexcept : - mPointer(ptr.get()) - { - ptr.mPointer = nullptr; - } - - ~LLConstPointer() - { - unref(); - } - - const Type* get() const { return mPointer; } - const Type* operator->() const { return mPointer; } - const Type& operator*() const { return *mPointer; } - - operator BOOL() const { return (mPointer != nullptr); } - operator bool() const { return (mPointer != nullptr); } - bool operator!() const { return (mPointer == nullptr); } - bool isNull() const { return (mPointer == nullptr); } - bool notNull() const { return (mPointer != nullptr); } - - operator const Type*() const { return mPointer; } - bool operator !=(const Type* ptr) const { return (mPointer != ptr); } - bool operator ==(const Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLConstPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLConstPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLConstPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } - - LLConstPointer<Type>& operator =(const Type* ptr) - { - if( mPointer != ptr ) - { - unref(); - mPointer = ptr; - ref(); - } - - return *this; - } - - LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr) - { - if( mPointer != ptr.mPointer ) - { - unref(); - mPointer = ptr.mPointer; - ref(); - } - return *this; - } - - LLConstPointer<Type>& operator =(LLConstPointer<Type>&& ptr) - { - if (mPointer != ptr.mPointer) - { - unref(); - mPointer = ptr.mPointer; - ptr.mPointer = nullptr; - } - return *this; - } - - // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template<typename Subclass> - LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr) - { - if( mPointer != ptr.get() ) - { - unref(); - mPointer = ptr.get(); - ref(); - } - return *this; - } - - template<typename Subclass> - LLConstPointer<Type>& operator =(LLConstPointer<Subclass>&& ptr) - { - if (mPointer != ptr.mPointer) - { - unref(); - mPointer = ptr.mPointer; - ptr.mPointer = nullptr; - } - return *this; - } - - // Just exchange the pointers, which will not change the reference counts. - static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b) - { - const Type* temp = a.mPointer; - a.mPointer = b.mPointer; - b.mPointer = temp; - } - -protected: -#ifdef LL_LIBRARY_INCLUDE - void ref(); - void unref(); -#else // LL_LIBRARY_INCLUDE - void ref() - { - if (mPointer) - { - mPointer->ref(); - } - } - - void unref() - { - if (mPointer) - { - const Type *temp = mPointer; - mPointer = nullptr; - temp->unref(); - if (mPointer != nullptr) - { - LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL; - unref(); - } - } - } -#endif // LL_LIBRARY_INCLUDE - -protected: - const Type* mPointer; -}; +template <typename Type> +using LLConstPointer = LLPointer<const Type>; template<typename Type> class LLCopyOnWritePointer : public LLPointer<Type> @@ -418,38 +281,26 @@ private: bool mStayUnique; }; -template<typename Type> -bool operator!=(Type* lhs, const LLPointer<Type>& rhs) +template<typename Type0, typename Type1> +bool operator!=(Type0* lhs, const LLPointer<Type1>& rhs) { return (lhs != rhs.get()); } -template<typename Type> -bool operator==(Type* lhs, const LLPointer<Type>& rhs) +template<typename Type0, typename Type1> +bool operator==(Type0* lhs, const LLPointer<Type1>& rhs) { return (lhs == rhs.get()); } -// boost hash adapter -template <class Type> -struct boost::hash<LLPointer<Type>> -{ - typedef LLPointer<Type> argument_type; - typedef std::size_t result_type; - result_type operator()(argument_type const& s) const - { - return (std::size_t) s.get(); - } -}; - -// Adapt boost hash to std hash +// Specialize for std::hash namespace std { template<class Type> struct hash<LLPointer<Type>> { std::size_t operator()(LLPointer<Type> const& s) const noexcept { - return boost::hash<LLPointer<Type>>()(s); + return std::hash<Type*>()(s.get()); } }; } diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp index 7efaebd569..4db44ff2a6 100644 --- a/indra/llcommon/workqueue.cpp +++ b/indra/llcommon/workqueue.cpp @@ -276,12 +276,30 @@ bool LL::WorkQueue::done() bool LL::WorkQueue::post(const Work& callable) { - return mQueue.pushIfOpen(callable); + try + { + return mQueue.pushIfOpen(callable); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLCoros") << "Bad memory allocation in WorkQueue::post" << LL_ENDL; + return false; + } } bool LL::WorkQueue::tryPost(const Work& callable) { - return mQueue.tryPush(callable); + try + { + return mQueue.tryPush(callable); + } + catch (std::bad_alloc&) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS("LLCoros") << "Bad memory allocation in WorkQueue::tryPost" << LL_ENDL; + return false; + } } LL::WorkQueue::Work LL::WorkQueue::pop_() diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 16042e573a..8569c28528 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -27,10 +27,11 @@ #ifndef LL_LLIMAGE_H #define LL_LLIMAGE_H -#include "lluuid.h" -#include "llstring.h" +#include "llmutex.h" #include "llpointer.h" +#include "llstring.h" #include "lltrace.h" +#include "lluuid.h" constexpr S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 constexpr S32 MAX_IMAGE_MIP = 12; // 4096x4096 diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index bb0c94d513..d8f649140f 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -25,6 +25,7 @@ #include "linden_common.h" +#include "llmutex.h" #include "llvolumemgr.h" #include "llvolume.h" diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 196ecdcf7d..0e11dca876 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -155,6 +155,7 @@ class LLVector3 friend const LLVector3& operator*=(LLVector3 &a, const LLVector3 &b); // Returns a * b; friend const LLVector3& operator*=(LLVector3 &a, F32 k); // Return a times scaler k friend const LLVector3& operator/=(LLVector3 &a, F32 k); // Return a divided by scaler k + friend const LLVector3& operator/=(LLVector3& a, const LLVector3& b); friend const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &b); // Returns a * b; friend LLVector3 operator-(const LLVector3 &a); // Return vector -a @@ -460,6 +461,14 @@ inline const LLVector3& operator/=(LLVector3& a, F32 k) return a; } +inline const LLVector3& operator/=(LLVector3& a, const LLVector3& b) +{ + a.mV[VX] /= b.mV[VX]; + a.mV[VY] /= b.mV[VY]; + a.mV[VZ] /= b.mV[VZ]; + return a; +} + inline LLVector3 operator-(const LLVector3& a) { return LLVector3(-a.mV[VX], -a.mV[VY], -a.mV[VZ]); diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 31bc76344c..c3e3e19ee9 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -109,11 +109,12 @@ public: PARAMS_EXTENDED_MESH = 0x70, PARAMS_RENDER_MATERIAL = 0x80, PARAMS_REFLECTION_PROBE = 0x90, + PARAMS_MAX = PARAMS_REFLECTION_PROBE, }; public: U16 mType; - virtual ~LLNetworkData() {}; + virtual ~LLNetworkData() = default; virtual bool pack(LLDataPacker &dp) const = 0; virtual bool unpack(LLDataPacker &dp) = 0; virtual bool operator==(const LLNetworkData& data) const = 0; @@ -319,7 +320,7 @@ public: bool fromLLSD(LLSD& sd); void setSculptTexture(const LLUUID& texture_id, U8 sculpt_type); - LLUUID getSculptTexture() const { return mSculptTexture; } + const LLUUID& getSculptTexture() const { return mSculptTexture; } U8 getSculptType() const { return mSculptType; } }; @@ -340,10 +341,10 @@ public: bool fromLLSD(LLSD& sd); void setLightTexture(const LLUUID& id) { mLightTexture = id; } - LLUUID getLightTexture() const { return mLightTexture; } + const LLUUID& getLightTexture() const { return mLightTexture; } bool isLightSpotlight() const { return mLightTexture.notNull(); } void setParams(const LLVector3& params) { mParams = params; } - LLVector3 getParams() const { return mParams; } + const LLVector3& getParams() const { return mParams; } }; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index ab88e4868e..e26c53bc2e 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1698,25 +1698,64 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) return; } - if (mUIOffset.empty()) + LLVector4a vert(x, y, z); + transform(vert); + mVerticesp[mCount] = vert; + + mCount++; + mVerticesp[mCount] = mVerticesp[mCount-1]; + mColorsp[mCount] = mColorsp[mCount-1]; + mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +} + +void LLRender::transform(LLVector3& vert) +{ + if (!mUIOffset.empty()) { - mVerticesp[mCount].set(x,y,z); + vert += LLVector3(mUIOffset.back().getF32ptr()); + vert *= LLVector3(mUIScale.back().getF32ptr()); } - else +} + +void LLRender::transform(LLVector4a& vert) +{ + if (!mUIOffset.empty()) { - LLVector4a vert(x, y, z); vert.add(mUIOffset.back()); vert.mul(mUIScale.back()); - mVerticesp[mCount] = vert; } +} - mCount++; - mVerticesp[mCount] = mVerticesp[mCount-1]; - mColorsp[mCount] = mColorsp[mCount-1]; - mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +void LLRender::untransform(LLVector3& vert) +{ + if (!mUIOffset.empty()) + { + vert /= LLVector3(mUIScale.back().getF32ptr()); + vert -= LLVector3(mUIOffset.back().getF32ptr()); + } +} + +void LLRender::batchTransform(LLVector4a* verts, U32 vert_count) +{ + if (!mUIOffset.empty()) + { + const LLVector4a& offset = mUIOffset.back(); + const LLVector4a& scale = mUIScale.back(); + + for (U32 i = 0; i < vert_count; ++i) + { + verts[i].add(offset); + verts[i].mul(scale); + } + } +} + +void LLRender::vertexBatchPreTransformed(const std::vector<LLVector4a>& verts) +{ + vertexBatchPreTransformed(verts.data(), narrow(verts.size())); } -void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) +void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -1737,7 +1776,7 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) mVerticesp[mCount] = mVerticesp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count) +void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, S32 vert_count) { if (mCount + vert_count > 4094) { @@ -1761,7 +1800,7 @@ void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 } } -void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) +void LLRender::vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, const LLColor4U* colors, S32 vert_count) { if (mCount + vert_count > 4094) { diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 9c17cf3470..51301c7cac 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -449,9 +449,16 @@ public: void diffuseColor4ubv(const U8* c); void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a); - void vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count); - void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count); - void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U*, S32 vert_count); + void transform(LLVector3& vert); + void transform(LLVector4a& vert); + void untransform(LLVector3& vert); + + void batchTransform(LLVector4a* verts, U32 vert_count); + + void vertexBatchPreTransformed(const std::vector<LLVector4a>& verts); + void vertexBatchPreTransformed(const LLVector4a* verts, S32 vert_count); + void vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, S32 vert_count); + void vertexBatchPreTransformed(const LLVector4a* verts, const LLVector2* uvs, const LLColor4U*, S32 vert_count); void setColorMask(bool writeColor, bool writeAlpha); void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha); diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index b534c8d4e8..ef62666918 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -122,6 +122,7 @@ LLLineEditor::Params::Params() LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) : LLUICtrl(p), + mDefaultText(p.default_text), mMaxLengthBytes(p.max_length.bytes), mMaxLengthChars(p.max_length.chars), mCursorPos( 0 ), diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 3f762822ee..6384bfdc5f 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -202,6 +202,7 @@ public: void setLabel(const LLStringExplicit &new_label) { mLabel = new_label; } const std::string& getLabel() { return mLabel.getString(); } + void setDefaultText() { setText(mDefaultText); } void setText(const LLStringExplicit &new_text); const std::string& getText() const override { return mText.getString(); } @@ -347,6 +348,7 @@ protected: LLFontVertexBuffer mFontBufferSelection; LLFontVertexBuffer mFontBufferPostSelection; LLFontVertexBuffer mFontBufferLabel; + std::string mDefaultText; S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes S32 mMaxLengthChars; // Maximum number of characters in the string S32 mCursorPos; // I-beam is just after the mCursorPos-th character. diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index d56c459560..c7c7435be2 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -93,6 +93,7 @@ #include "llinitparam.h" #include "llinstancetracker.h" #include "llmortician.h" +#include "llmutex.h" #include "llnotificationptr.h" #include "llpointer.h" #include "llrefcount.h" diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index b459c67dad..558ce6a7fd 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -3185,6 +3185,7 @@ LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLS if (cell_p.width.isProvided()) { new_column.width.pixel_width = cell_p.width; + new_column.width.pixel_width.choose(); } addColumn(new_column); columnp = mColumns[column]; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index fcdf3782ae..7689b93374 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -581,7 +581,7 @@ S32 LLTextEditor::indentLine( S32 pos, S32 spaces ) LLWString wtext = getWText(); if (wtext[pos] == ' ') { - delta_spaces += remove( pos, 1, false ); + delta_spaces -= remove( pos, 1, false ); } } } diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index d1bae49784..8e08239ee6 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -814,6 +814,7 @@ LLWebRTCPeerConnectionImpl::~LLWebRTCPeerConnectionImpl() { mSignalingObserverList.clear(); mDataObserverList.clear(); + mPeerConnectionFactory.release(); if (mPendingJobs > 0) { RTC_LOG(LS_ERROR) << __FUNCTION__ << "Destroying a connection that has " << std::to_string(mPendingJobs) << " unfinished jobs that might cause workers to crash"; @@ -877,7 +878,6 @@ void LLWebRTCPeerConnectionImpl::terminate() } mPendingJobs--; }); - mPeerConnectionFactory.release(); } void LLWebRTCPeerConnectionImpl::setSignalingObserver(LLWebRTCSignalingObserver *observer) { mSignalingObserverList.emplace_back(observer); } @@ -1004,6 +1004,7 @@ bool LLWebRTCPeerConnectionImpl::initializeConnection(const LLWebRTCPeerConnecti } webrtc::PeerConnectionInterface::RTCOfferAnswerOptions offerOptions; + this->AddRef(); // CreateOffer will deref this when it's done. Without this, the callbacks never get called. mPeerConnection->CreateOffer(this, offerOptions); mPendingJobs--; }); diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 24d2facc4c..8a95ab2cc2 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -157,9 +157,12 @@ LLControlVariable::LLControlVariable(const std::string& name, eControlType type, { if ((persist != PERSIST_NO) && mComment.empty()) { - // File isn't actually missing, but something is wrong with it - // so the main point is to warn user to reinstall - LLError::LLUserWarningMsg::showMissingFiles(); + std::string error_string = + "Second Life failed to initialize settings. Setting " + mName + " is invalid. " + "Either settings' files were supplied incorrectly or default files were corrupted." + "\n\nPlease reinstall viewer from https://secondlife.com/support/downloads/ and " + "contact https://support.secondlife.com if issue persists after reinstall."; + LLError::LLUserWarningMsg::show(error_string); LL_ERRS() << "Must supply a comment for control " << mName << LL_ENDL; } //Push back versus setValue'ing here, since we don't want to call a signal yet @@ -990,7 +993,7 @@ U32 LLControlGroup::saveToFile(const std::string& filename, bool nondefault_only return num_saved; } -U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_values, bool save_values) +U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_values, bool save_values, bool error_when_no_comment) { LLSD settings; llifstream infile; @@ -1105,10 +1108,26 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v } } + std::string comment = control_map["Comment"].asString(); + if (!error_when_no_comment + && !set_default_values + && comment.empty()) + { + // Only error for default settings that should remind the developer to provide comments + // and otherwise indicate a problem with viewer's files. + // But permit this minor transgression in user's files. + // Otherwise user might have a hard time figuring out source of the error or how to fix it. + // Instead make setting to not persist so that unrecognized invalid settings won't be saved + // for the next run. + persist = LLControlVariable::PERSIST_NO; + comment = "Comment not provided, setting won't persist"; + LL_WARNS() << "Control " << name << " is missing a comment value. Setting will be marked as PERSIST_NO" << LL_ENDL; + } + declareControl(name, typeStringToEnum(control_map["Type"].asString()), control_map["Value"], - control_map["Comment"].asString(), + comment, persist, hidefromsettingseditor ); diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index da7268bf45..c9bd0a8a32 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -278,7 +278,7 @@ public: // as the given type. U32 loadFromFileLegacy(const std::string& filename, bool require_declaration = true, eControlType declare_as = TYPE_STRING); U32 saveToFile(const std::string& filename, bool nondefault_only); - U32 loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true); + U32 loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true, bool error_when_no_comment = true); void resetToDefaults(); void incrCount(std::string_view name); diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 429dc57af3..4703009f54 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -7.2.3 +2026.01.0 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 674f459193..5d82b38c2a 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4591,6 +4591,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>MapShowGridCoords</key> + <map> + <key>Comment</key> + <string>Shows/hides the grid coordinates of each region on the world map.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>MiniMapAutoCenter</key> <map> <key>Comment</key> @@ -7368,7 +7379,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>32.0</real> + <real>48.0</real> </map> <key>RenderCPUBasis</key> <map> diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index b2c66b1bac..d884b32ac0 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -975,6 +975,10 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction) new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); } } + else + { + new_distance = llmin(new_distance, getCameraMaxZoomDistance()); + } mCameraFocusOffsetTarget = new_distance * camera_offset_unit; } @@ -1035,6 +1039,10 @@ void LLAgentCamera::cameraOrbitIn(const F32 meters) new_distance = llclamp(new_distance, APPEARANCE_MIN_ZOOM, APPEARANCE_MAX_ZOOM); } } + else + { + new_distance = llmin(new_distance, getCameraMaxZoomDistance()); + } // Compute new camera offset mCameraFocusOffsetTarget = new_distance * camera_offset_unit; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6058973176..8bf418aa44 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2454,7 +2454,10 @@ bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key, full_settings_path = gDirUtilp->getExpandedFilename((ELLPath)path_index, file.file_name()); } - if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent)) + // Be softer for files in the user's folders, user can't just reinstall those + bool error_when_no_comment = !set_defaults && location_key != "User"; + + if(settings_group->loadFromFile(full_settings_path, set_defaults, file.persistent, error_when_no_comment)) { // success! LL_INFOS("Settings") << "Loaded settings file " << full_settings_path << LL_ENDL; } @@ -4499,7 +4502,19 @@ void LLAppViewer::purgeCacheImmediate() { LL_INFOS("AppCache") << "Purging Object Cache and Texture Cache immediately..." << LL_ENDL; LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE, false); - LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true); + if (LLVOCache::instanceExists()) + { + LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true); + } + else if (!mSecondInstance) + { + // LLVOCache requires parameters to be initialized, if it's not there, try manually + std::string mask = "*"; + std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "objectcache"); + LL_INFOS() << "Removing cache at " << cache_dir << LL_ENDL; + gDirUtilp->deleteFilesInDir(cache_dir, mask); //delete all files + LLFile::remove(cache_dir); + } } std::string LLAppViewer::getSecondLifeTitle() const diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 6f6b89ea81..fb1426a235 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -29,8 +29,6 @@ #include "llavataractions.h" -#include "boost/lambda/lambda.hpp" // for lambda::constant - #include "llavatarnamecache.h" // IDEVO #include "llsd.h" #include "llnotifications.h" diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 322ee90541..da9378ad12 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -723,9 +723,13 @@ F32 LLDrawable::updateXform(bool undamped) mXform.setRotation(target_rot); mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!) mXform.updateMatrix(); - if (isRoot() && mVObjp->isAnimatedObject() && mVObjp->getControlAvatar()) + if (isRoot() && mVObjp->isAnimatedObject()) { - mVObjp->getControlAvatar()->matchVolumeTransform(); + LLControlAvatar* cav = mVObjp->getControlAvatar(); + if (cav) + { + cav->matchVolumeTransform(); + } } if (mSpatialBridge) diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index bc45734e66..9d1b11880b 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -267,7 +267,7 @@ void LLDrawPoolAlpha::forwardRender(bool rigged) gGL.setColorMask(true, false); - if (!rigged) + if (!rigged && getType() == LLDrawPoolAlpha::POOL_ALPHA_POST_WATER) { //render "highlight alpha" on final non-rigged pass // NOTE -- hacky call here protected by !rigged instead of alongside "forwardRender" // so renderDebugAlpha is executed while gls_pipeline_alpha and depth GL state diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 37802fa175..b9c84c10cf 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2372,7 +2372,11 @@ F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius //the above calculation is too expensive //the below is a good estimation: bounding box of the bounding sphere: - F32 alpha = 0.5f * (radius + screen_radius - d) / radius ; + F32 alpha = 1.f; + if (!is_approx_zero(radius)) // radius can be something like -1e-10 + { + alpha = 0.5f * (radius + screen_radius - d) / radius; + } alpha = llclamp(alpha, 0.f, 1.f) ; return alpha * alpha ; } diff --git a/indra/newview/llfloatereditenvironmentbase.cpp b/indra/newview/llfloatereditenvironmentbase.cpp index a42c94f049..bc1f3045bb 100644 --- a/indra/newview/llfloatereditenvironmentbase.cpp +++ b/indra/newview/llfloatereditenvironmentbase.cpp @@ -262,7 +262,7 @@ void LLFloaterEditEnvironmentBase::onSaveAsCommit(const LLSD& notification, cons } else if (mInventoryItem) { - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); LLUUID parent_id = mInventoryItem->getParentUUID(); if (marketplacelistings_id == parent_id || gInventory.isObjectDescendentOf(mInventoryItem->getUUID(), gInventory.getLibraryRootFolderID())) { diff --git a/indra/newview/llfloatermarketplace.cpp b/indra/newview/llfloatermarketplace.cpp index 7316d7617d..2a67e75fec 100644 --- a/indra/newview/llfloatermarketplace.cpp +++ b/indra/newview/llfloatermarketplace.cpp @@ -39,6 +39,26 @@ LLFloaterMarketplace::~LLFloaterMarketplace() { } +void LLFloaterMarketplace::onOpen(const LLSD& key) +{ + Params params(key); + + if (!params.validateBlock()) + { + closeFloater(); + return; + } + + if (params.url().empty()) + { + openMarketplace(); + } + else + { + openMarketplaceURL(params.url); + } +} + // just to override LLFloaterWebContent void LLFloaterMarketplace::onClose(bool app_quitting) { @@ -68,3 +88,18 @@ void LLFloaterMarketplace::openMarketplace() mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); } } + +void LLFloaterMarketplace::openMarketplaceURL(const std::string& url) +{ + if (mCurrentURL != url) + { + mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); + } +} + +// static +bool LLFloaterMarketplace::isMarketplaceURL(const std::string& url) +{ + static LLCachedControl<std::string> marketplace_url(gSavedSettings, "MarketplaceURL", "https://marketplace.secondlife.com/"); + return url.starts_with(marketplace_url()); +} diff --git a/indra/newview/llfloatermarketplace.h b/indra/newview/llfloatermarketplace.h index 9524c94eee..17979dae90 100644 --- a/indra/newview/llfloatermarketplace.h +++ b/indra/newview/llfloatermarketplace.h @@ -36,11 +36,14 @@ class LLFloaterMarketplace: public: void openMarketplace(); + void openMarketplaceURL(const std::string& url); + bool static isMarketplaceURL(const std::string& url); private: LLFloaterMarketplace(const LLSD& key); ~LLFloaterMarketplace(); bool postBuild() override; + void onOpen(const LLSD& key) override; void onClose(bool app_quitting) override; }; diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp index f20fea01c5..dfd023e424 100644 --- a/indra/newview/llfloatermarketplacelistings.cpp +++ b/indra/newview/llfloatermarketplacelistings.cpp @@ -29,6 +29,7 @@ #include "llfloatermarketplacelistings.h" +#include "llcallbacklist.h" #include "llfloaterreg.h" #include "llfiltereditor.h" #include "llfolderview.h" @@ -231,7 +232,7 @@ void LLPanelMarketplaceListings::onTabChange() void LLPanelMarketplaceListings::onAddButtonClicked() { - LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); llassert(marketplacelistings_id.notNull()); LLFolderType::EType preferred_type = LLFolderType::lookup("category"); LLHandle<LLPanel> handle = getHandle(); @@ -351,7 +352,15 @@ public: if (added_category_type == LLFolderType::FT_MARKETPLACE_LISTINGS) { - mMarketplaceListingsFloater->initializeMarketPlace(); + LLHandle<LLFloater> handle = mMarketplaceListingsFloater->getHandle(); + doOnIdleOneTime([handle]() + { + LLFloaterMarketplaceListings* floater = (LLFloaterMarketplaceListings*)handle.get(); + if (floater) + { + floater->initializeMarketPlace(); + } + }); } } } @@ -415,7 +424,7 @@ bool LLFloaterMarketplaceListings::postBuild() // Fetch aggressively so we can interact with listings as soon as possible if (!fetchContents()) { - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); LLInventoryModelBackgroundFetch::instance().start(marketplacelistings_id, true); } @@ -513,8 +522,6 @@ void LLFloaterMarketplaceListings::setRootFolder() return; } - mRootFolderCreating = false; - // No longer need to observe new category creation if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) { @@ -524,6 +531,8 @@ void LLFloaterMarketplaceListings::setRootFolder() } llassert(!mCategoryAddedObserver); + mRootFolderCreating = false; + if (marketplacelistings_id == mRootFolderId) { LL_WARNS("SLM") << "Inventory warning: Marketplace listings folder already set" << LL_ENDL; @@ -566,7 +575,8 @@ void LLFloaterMarketplaceListings::setPanels() void LLFloaterMarketplaceListings::initializeMarketPlace() { - LLMarketplaceData::instance().initializeSLM(boost::bind(&LLFloaterMarketplaceListings::updateView, this)); + if (!mRootFolderCreating) + LLMarketplaceData::instance().initializeSLM(boost::bind(&LLFloaterMarketplaceListings::updateView, this)); } S32 LLFloaterMarketplaceListings::getFolderCount() @@ -909,7 +919,7 @@ void LLFloaterMarketplaceValidation::onOpen(const LLSD& key) LLUUID cat_id(key.asUUID()); if (cat_id.isNull()) { - cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + cat_id = gInventory.getMarketplaceListingsUUID(); } // Validates the folder diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp index fa491a4b27..bd8530abd7 100644 --- a/indra/newview/llfloaterobjectweights.cpp +++ b/indra/newview/llfloaterobjectweights.cpp @@ -208,7 +208,7 @@ void LLFloaterObjectWeights::draw() toggleRenderLoadingIndicators(false); } mTrianglesShown->setText(llformat("%d", total_tris)); - mPixelArea->setText(llformat("%d", pixel_area)); + mPixelArea->setText(llformat("%ld", (S64)pixel_area)); // value capped at 10M } LLFloater::draw(); } diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp index d5e45c09e3..e497fb0914 100644 --- a/indra/newview/llfloaterpay.cpp +++ b/indra/newview/llfloaterpay.cpp @@ -502,7 +502,7 @@ void LLFloaterPay::onGive(give_money_ptr info) amount = atoi(text_field->getValue().asString().c_str()); } - if (amount > PAY_AMOUNT_NOTIFICATION && gStatusBar && gStatusBar->getBalance() > amount) + if (amount > PAY_AMOUNT_NOTIFICATION) { LLUUID payee_id = LLUUID::null; bool is_group = false; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 989dbc0c29..024017ad9b 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -474,7 +474,8 @@ bool LLFloaterPreference::postBuild() getChild<LLUICtrl>("log_path_string")->setEnabled(false); // make it read-only but selectable - getChild<LLComboBox>("language_combobox")->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this)); + mLanguageCombobox = getChild<LLComboBox>("language_combobox"); + mLanguageCombobox->setCommitCallback(boost::bind(&LLFloaterPreference::onLanguageChange, this)); mTimeFormatCombobox = getChild<LLComboBox>("time_format_combobox"); mTimeFormatCombobox->setCommitCallback(boost::bind(&LLFloaterPreference::onTimeFormatChange, this)); @@ -516,18 +517,18 @@ bool LLFloaterPreference::postBuild() std::map<std::string, std::string>::iterator iter = labels.find(system_lang); if (iter != labels.end()) { - getChild<LLComboBox>("language_combobox")->add(iter->second, LLSD("default"), ADD_TOP, true); + mLanguageCombobox->add(iter->second, LLSD("default"), ADD_TOP, true); } else { LL_WARNS() << "Language \"" << system_lang << "\" is not in default_languages.xml" << LL_ENDL; - getChild<LLComboBox>("language_combobox")->add("System default", LLSD("default"), ADD_TOP, true); + mLanguageCombobox->add("System default", LLSD("default"), ADD_TOP, true); } } else { LL_WARNS() << "Failed to load labels from " << user_filename << ". Using default." << LL_ENDL; - getChild<LLComboBox>("language_combobox")->add("System default", LLSD("default"), ADD_TOP, true); + mLanguageCombobox->add("System default", LLSD("default"), ADD_TOP, true); } #ifndef LL_DISCORD @@ -1340,6 +1341,12 @@ void LLFloaterPreference::refresh() updateClickActionViews(); mTimeFormatCombobox->selectByValue(gSavedSettings.getBOOL("Use24HourClock") ? "1" : "0"); + + std::string current_language = gSavedSettings.getString("Language"); + if (current_language != "default" && !current_language.empty()) + { + mLanguageCombobox->selectByValue(LLSD(current_language)); + } } void LLFloaterPreference::onCommitWindowedMode() diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index a2aa3ee8de..3028bec64a 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -237,6 +237,7 @@ private: LLButton* mEnablePopupBtn = nullptr; LLButton* mDisablePopupBtn = nullptr; LLComboBox* mTimeFormatCombobox = nullptr; + LLComboBox* mLanguageCombobox = nullptr; std::unique_ptr< ll::prefs::SearchData > mSearchData; bool mSearchDataDirty; diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 4cb6e7be96..1b5566a32d 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -538,6 +538,18 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) panel->getChildView("access_combo")->setEnabled(gAgent.isGodlike() || (region && region->canManageEstate() && !teen_grid)); panel->setCtrlsEnabled(allow_modify); + panel->getChild<LLLineEditor>("estate_id")->setValue((S32)region_info.mEstateID); + + if (region) + { + panel->getChild<LLLineEditor>("grid_position_x")->setValue((S32)(region->getOriginGlobal()[VX] / 256)); + panel->getChild<LLLineEditor>("grid_position_y")->setValue((S32)(region->getOriginGlobal()[VY] / 256)); + } + else + { + panel->getChild<LLLineEditor>("grid_position_x")->setDefaultText(); + panel->getChild<LLLineEditor>("grid_position_y")->setDefaultText(); + } // DEBUG PANEL panel = tab->getChild<LLPanel>("Debug"); @@ -902,6 +914,9 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region) getChildView("apply_btn")->setEnabled(false); getChildView("access_text")->setEnabled(allow_modify); // getChildView("access_combo")->setEnabled(allow_modify); + getChildView("estate_id")->setEnabled(false); + getChildView("grid_position_x")->setEnabled(false); + getChildView("grid_position_y")->setEnabled(false); // now set in processRegionInfo for teen grid detection getChildView("kick_btn")->setEnabled(allow_modify); getChildView("kick_all_btn")->setEnabled(allow_modify); diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index cb1068943e..41d7d93528 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -901,6 +901,39 @@ private: }; +F32 shader_timer_benchmark(std::vector<LLRenderTarget> & dest, TextureHolder & texHolder, U32 textures_count, LLVertexBuffer * buff, F32 &seconds) +{ + // run GPU timer benchmark + + //number of samples to take + const S32 samples = 64; + + { + ShaderProfileHelper initProfile; + dest[0].bindTarget(); + gBenchmarkProgram.bind(); + for (S32 c = 0; c < samples; ++c) + { + for (U32 i = 0; i < textures_count; ++i) + { + texHolder.bind(i); + buff->setBuffer(); + buff->drawArrays(LLRender::TRIANGLES, 0, 3); + } + } + gBenchmarkProgram.unbind(); + dest[0].flush(); + } + + F32 ms = gBenchmarkProgram.mTimeElapsed / 1000000.f; + seconds = ms / 1000.f; + + F64 samples_drawn = (F64)gBenchmarkProgram.mSamplesDrawn; + F64 gpixels_drawn = samples_drawn / 1000000000.0; + F32 samples_sec = (F32)(gpixels_drawn / seconds); + return samples_sec * 4; // 4 bytes per sample +} + //----------------------------------------------------------------------------- // gpu_benchmark() // returns measured memory bandwidth of GPU in gigabytes per second @@ -942,9 +975,6 @@ F32 gpu_benchmark() //number of textures const U32 count = 32; - //number of samples to take - const S32 samples = 64; - //time limit, allocation operations shouldn't take longer then 30 seconds, same for actual benchmark. const F32 time_limit = 30; @@ -1034,33 +1064,15 @@ F32 gpu_benchmark() LLGLSLShader::unbind(); - // run GPU timer benchmark - { - ShaderProfileHelper initProfile; - dest[0].bindTarget(); - gBenchmarkProgram.bind(); - for (S32 c = 0; c < samples; ++c) - { - for (U32 i = 0; i < count; ++i) - { - texHolder.bind(i); - buff->setBuffer(); - buff->drawArrays(LLRender::TRIANGLES, 0, 3); - } - } - gBenchmarkProgram.unbind(); - dest[0].flush(); - } + // run GPU timer benchmark twice + F32 seconds = 0; + F32 gbps = shader_timer_benchmark(dest, texHolder, count, buff.get(), seconds); - F32 ms = gBenchmarkProgram.mTimeElapsed/1000000.f; - F32 seconds = ms/1000.f; + LL_INFOS("Benchmark") << "Memory bandwidth, 1st run is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL; - F64 samples_drawn = (F64)gBenchmarkProgram.mSamplesDrawn; - F64 gpixels_drawn = samples_drawn / 1000000000.0; - F32 samples_sec = (F32)(gpixels_drawn/seconds); - F32 gbps = samples_sec*4; // 4 bytes per sample + gbps = shader_timer_benchmark(dest, texHolder, count, buff.get(), seconds); - LL_INFOS("Benchmark") << "Memory bandwidth is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL; + LL_INFOS("Benchmark") << "Memory bandwidth, final run is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL; return gbps; } diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 7659e5f082..074cda1683 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -317,7 +317,7 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL // virtual bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) { - // Why is "new group" sufficient? + // "new group" is sufficient because update_group_floaters always calls that on group changes if (event->desc() == "new group") { setDirty(); diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 11f049564a..4327d281e5 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -301,7 +301,7 @@ void LLHUDNameTag::renderText() const S32 label_height = ll_round((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f))); label_top_rect.mBottom = label_top_rect.mTop - label_height; LLColor4 label_top_color = text_color; - label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor; + label_top_color.mV[VALPHA] = bubble_opacity() * alpha_factor; mRoundedRectTopImgp->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 848f28f933..542c0fdfdd 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -336,7 +336,7 @@ bool LLInvFVBridge::cutToClipboard() const LLInventoryObject* obj = gInventory.getObject(mUUID); if (obj && isItemMovable() && isItemRemovable()) { - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); const bool cut_from_marketplacelistings = gInventory.isObjectDescendentOf(mUUID, marketplacelistings_id); if (cut_from_marketplacelistings && (LLMarketplaceData::instance().isInActiveFolder(mUUID) || @@ -1378,7 +1378,7 @@ bool LLInvFVBridge::isInboxFolder() const bool LLInvFVBridge::isMarketplaceListingsFolder() const { - const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID folder_id = gInventory.getMarketplaceListingsUUID(); if (folder_id.isNull()) { @@ -1686,7 +1686,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const { std::string error_msg; LLInventoryModel* model = getInventoryModel(); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &marketplacelistings_id = model->getMarketplaceListingsUUID(); if (marketplacelistings_id.notNull()) { LLViewerInventoryCategory * master_folder = model->getCategory(marketplacelistings_id); @@ -1845,7 +1845,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) { LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); // Note: For a single item, if it's not a copy, then it's a move move_item_to_marketplacelistings(itemp, marketplacelistings_id, ("copy_to_marketplace_listings" == action)); } @@ -2678,7 +2678,7 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const LLUUID &cat_id = inv_cat->getUUID(); const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); const LLUUID from_folder_uuid = inv_cat->getParentUUID(); const bool move_is_into_current_outfit = (mUUID == current_outfit_id); @@ -3758,7 +3758,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) { LLInventoryCategory * cat = gInventory.getCategory(mUUID); if (!cat) return; - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("move_to_marketplace_listings" != action), (("copy_or_move_to_marketplace_listings" == action))); } else if ("copy_folder_uuid" == action) @@ -4012,7 +4012,7 @@ void LLFolderBridge::pasteFromClipboard() LLInventoryModel* model = getInventoryModel(); if (model && isClipboardPasteable()) { - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &marketplacelistings_id = model->getMarketplaceListingsUUID(); const bool paste_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); bool cut_from_marketplacelistings = false; @@ -4074,7 +4074,7 @@ void LLFolderBridge::perform_pasteFromClipboard() if (model && isClipboardPasteable()) { const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); @@ -4371,7 +4371,7 @@ void LLFolderBridge::pasteLinkFromClipboard() if(model) { const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); const bool move_is_into_current_outfit = (mUUID == current_outfit_id); @@ -4471,7 +4471,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); const LLUUID &favorites = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - const LLUUID &marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplace_listings_id = model->getMarketplaceListingsUUID(); const LLUUID &outfits_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); if (outfits_id == mUUID) @@ -5708,7 +5708,7 @@ bool LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); const LLUUID from_folder_uuid = inv_item->getParentUUID(); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 3cc57e851f..458ea24d33 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -405,7 +405,7 @@ void update_all_marketplace_count(const LLUUID& cat_id) void update_all_marketplace_count() { // Get the marketplace root and launch the recursive exploration - const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplace_listings_uuid = gInventory.getMarketplaceListingsUUID(); if (!marketplace_listings_uuid.isNull()) { update_all_marketplace_count(marketplace_listings_uuid); @@ -1050,11 +1050,7 @@ void open_marketplace_listings() S32 depth_nesting_in_marketplace(LLUUID cur_uuid) { - // Get the marketplace listings root, exit with -1 (i.e. not under the marketplace listings root) if none - // Todo: findCategoryUUIDForType is somewhat expensive with large - // flat root folders yet we use depth_nesting_in_marketplace at - // every turn, find a way to correctly cache this id. - const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplace_listings_uuid = gInventory.getMarketplaceListingsUUID(); if (marketplace_listings_uuid.isNull()) { return -1; @@ -3420,7 +3416,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if ("delete" == action) { - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); bool marketplacelistings_item = false; bool has_worn = false; bool needs_replacement = false; @@ -3601,7 +3597,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if (action == "wear" || action == "wear_add") { const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID mp_id = gInventory.getMarketplaceListingsUUID(); std::copy_if(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids), @@ -4011,7 +4007,7 @@ void LLInventoryAction::buildMarketplaceFolders(LLFolderView* root) // target listing *and* the original listing. So we need to keep track of both. // Note: do not however put the marketplace listings root itself in this list or the whole marketplace data will be rebuilt. sMarketplaceFolders.clear(); - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.isNull()) { return; diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index f77088e0b1..24b0866041 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1726,7 +1726,7 @@ bool is_category_removable(const LLUUID& folder_id, bool check_worn) } } - const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID mp_id = gInventory.getMarketplaceListingsUUID(); if (mp_id.notNull() && gInventory.isObjectDescendentOf(folder_id, mp_id)) { return false; @@ -1768,7 +1768,7 @@ void LLInventoryGallery::paste() return; } - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (mSelectedItemIDs.size() == 1 && gInventory.isObjectDescendentOf(*mSelectedItemIDs.begin(), marketplacelistings_id)) { return; @@ -2114,7 +2114,7 @@ void LLInventoryGallery::pasteAsLink() } const LLUUID& current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); const LLUUID& my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); std::vector<LLUUID> objects; @@ -3333,7 +3333,7 @@ bool dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, bool drop, const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); const bool move_is_into_current_outfit = (folder_id == current_outfit_id); @@ -3727,7 +3727,7 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, const LLUUID &cat_id = inv_cat->getUUID(); const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = model->getMarketplaceListingsUUID(); //const LLUUID from_folder_uuid = inv_cat->getParentUUID(); const bool move_is_into_current_outfit = (dest_id == current_outfit_id); const bool move_is_into_marketplacelistings = model->isObjectDescendentOf(dest_id, marketplacelistings_id); diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 2c3909cc79..c0c93f56e0 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -400,7 +400,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata) if (can_copy) { - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (itemp) { move_item_to_marketplacelistings(itemp, marketplacelistings_id, copy_operation); @@ -419,7 +419,7 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata) // option == 0 Move no copy item(s) // option == 1 Don't move no copy item(s) (leave them behind) bool copy_and_move = option == 0; - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); // main inventory only allows one item? LLViewerInventoryItem* itemp = gInventory.getItem(lamdba_list.front()); @@ -535,7 +535,7 @@ bool can_list_on_marketplace(const LLUUID &id) if (can_list) { std::string error_msg; - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.notNull()) { LLViewerInventoryCategory* master_folder = gInventory.getCategory(marketplacelistings_id); @@ -1033,7 +1033,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men // Marketplace bool can_list = false; - const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.notNull() && !is_inbox && !obj->getIsLinkType()) { if (is_folder) diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index c34df48f7d..01ff01e233 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -975,6 +975,15 @@ const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::ETyp return findCategoryUUIDForTypeInRoot(preferred_type, gInventory.getLibraryRootFolderID()); } +const LLUUID LLInventoryModel::getMarketplaceListingsUUID() +{ + if (mMarketplaceListingsUUID.isNull()) + { + mMarketplaceListingsUUID = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + } + return mMarketplaceListingsUUID; +} + // Convenience function to create a new category. You could call // updateCategory() with a newly generated UUID category, but this // version will take care of details like what the name should be @@ -1692,7 +1701,7 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 mask |= LLInventoryObserver::LABEL; } // Under marketplace, category labels are quite complex and need extra upate - const LLUUID marketplace_id = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplace_id = getMarketplaceListingsUUID(); if (marketplace_id.notNull() && isObjectDescendentOf(cat->getUUID(), marketplace_id)) { mask |= LLInventoryObserver::LABEL; diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 2859923df9..9fbabec8f3 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -329,6 +329,8 @@ public: // user specified one or it does not exist, creates default category if it is missing. const LLUUID findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type) const; + const LLUUID getMarketplaceListingsUUID(); + // Get whatever special folder this object is a child of, if any. const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const; @@ -361,6 +363,8 @@ public: private: mutable LLPointer<LLViewerInventoryItem> mLastItem; // cache recent lookups + LLUUID mMarketplaceListingsUUID; + //-------------------------------------------------------------------- // Count //-------------------------------------------------------------------- diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 1e5f771ba7..82eefb50ac 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -828,7 +828,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() // Intent is for marketplace request to happen after // main inventory is done, unless requested by floater mRecursiveMarketplaceFetchStarted = true; - const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.notNull()) { mFetchFolderQueue.emplace_front(marketplacelistings_id, FT_FOLDER_AND_CONTENT); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index cde87ede9b..8d57a4e7bb 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1849,6 +1849,7 @@ void LLInventoryPanel::purgeSelectedItems() { if (!mFolderRoot.get()) return; + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); const std::set<LLFolderViewItem*> inventory_selected = mFolderRoot.get()->getSelectionList(); if (inventory_selected.empty()) return; LLSD args; @@ -1858,12 +1859,17 @@ void LLInventoryPanel::purgeSelectedItems() it != end_it; ++it) { + // Selection allows items outside trash folder, only count the ones inside. LLUUID item_id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID(); - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - gInventory.collectDescendents(item_id, cats, items, LLInventoryModel::INCLUDE_TRASH); - count += items.size() + cats.size(); - selected_items.push_back(item_id); + LLInventoryObject* obj = gInventory.getObject(item_id); + if (obj->getParentUUID() == trash_id) + { + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(item_id, cats, items, LLInventoryModel::INCLUDE_TRASH); + count += items.size() + cats.size(); + selected_items.push_back(item_id); + } } args["COUNT"] = static_cast<S32>(count); LLNotificationsUtil::add("PurgeSelectedItems", args, LLSD(), boost::bind(callbackPurgeSelectedItems, _1, _2, selected_items)); diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index d80d9058e2..3567ca8e4a 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -582,7 +582,7 @@ void LLLocalBitmap::updateUserVolumes(LLUUID old_id, LLUUID new_id, U32 channel) if (object->isSculpted() && object->getVolume() && object->getVolume()->getParams().getSculptID() == old_id) { - LLSculptParams* old_params = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams* old_params = object->getSculptParams(); LLSculptParams new_params(*old_params); new_params.setSculptTexture(new_id, (*old_params).getSculptType()); object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, new_params, true); diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index d1d4641df3..dad04f4eab 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -845,7 +845,7 @@ void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot // Get/Post/Put requests to the SLM Server using the SLM API void LLMarketplaceData::getSLMListings() { - const LLUUID marketplaceFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplaceFolderId = gInventory.getMarketplaceListingsUUID(); setUpdating(marketplaceFolderId, true); LLCoros::instance().launch("getSLMListings", @@ -1752,7 +1752,7 @@ bool LLMarketplaceData::isUpdating(const LLUUID& folder_id, S32 depth) } else { - const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplace_listings_uuid = gInventory.getMarketplaceListingsUUID(); std::set<LLUUID>::iterator it = mPendingUpdateSet.find(marketplace_listings_uuid); if (it != mPendingUpdateSet.end()) { diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 0ed1e01ff8..68739341e9 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -4271,20 +4271,63 @@ S32 LLMeshRepository::update() return static_cast<S32>(size); } -void LLMeshRepository::unregisterMesh(LLVOVolume* vobj) +void LLMeshRepository::unregisterMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail) { - for (auto& lod : mLoadingMeshes) + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + + llassert((mesh_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH); + llassert(mesh_params.getSculptID().notNull()); + auto& lod = mLoadingMeshes[detail]; + auto param_iter = lod.find(mesh_params.getSculptID()); + if (param_iter != lod.end()) { - for (auto& param : lod) + param_iter->second.mVolumes.erase(vobj); + llassert(!param_iter->second.mVolumes.contains(vobj)); + if (param_iter->second.mVolumes.empty()) { - vector_replace_with_last(param.second.mVolumes, vobj); + lod.erase(param_iter); } } +} - for (auto& skin_pair : mLoadingSkins) +void LLMeshRepository::unregisterSkinInfo(const LLUUID& mesh_id, LLVOVolume* vobj) +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + + llassert(mesh_id.notNull()); + auto skin_pair_iter = mLoadingSkins.find(mesh_id); + if (skin_pair_iter != mLoadingSkins.end()) + { + skin_pair_iter->second.mVolumes.erase(vobj); + llassert(!skin_pair_iter->second.mVolumes.contains(vobj)); + if (skin_pair_iter->second.mVolumes.empty()) + { + mLoadingSkins.erase(skin_pair_iter); + } + } +} + +// Lots of dead objects make expensive calls to +// LLMeshRepository::unregisterMesh which may delay shutdown. Avoid this by +// preemptively unregistering all meshes. +// We can also do this safely if all objects are confirmed dead for some other +// reason. +void LLMeshRepository::unregisterAllMeshes() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; + + // The size of mLoadingMeshes and mLoadingSkins may be large and thus + // expensive to iterate over in LLVOVolume::~LLVOVolume. + // This is unnecessary during shutdown, so we ignore the referenced objects in the + // least expensive way which is still safe: by clearing these containers. + // Clear now and not in LLMeshRepository::shutdown because + // LLMeshRepository::notifyLoadedMeshes could (depending on invocation + // order) reference a pointer to an object after it has been deleted. + for (auto& lod : mLoadingMeshes) { - vector_replace_with_last(skin_pair.second.mVolumes, vobj); + lod.clear(); } + mLoadingSkins.clear(); } S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 new_lod, S32 last_lod) @@ -4306,7 +4349,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para mesh_load_map::iterator iter = mLoadingMeshes[new_lod].find(mesh_id); if (iter != mLoadingMeshes[new_lod].end()) { //request pending for this mesh, append volume id to list - auto it = std::find(iter->second.mVolumes.begin(), iter->second.mVolumes.end(), vobj); + auto it = iter->second.mVolumes.find(vobj); if (it == iter->second.mVolumes.end()) { iter->second.addVolume(vobj); } @@ -4804,7 +4847,7 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOV skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); if (iter != mLoadingSkins.end()) { //request pending for this mesh, append volume id to list - auto it = std::find(iter->second.mVolumes.begin(), iter->second.mVolumes.end(), requesting_obj); + auto it = iter->second.mVolumes.find(requesting_obj); if (it == iter->second.mVolumes.end()) { iter->second.addVolume(requesting_obj); } diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 01b51e753e..56ad8297c7 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -290,7 +290,7 @@ private: class MeshLoadData { public: - MeshLoadData() {} + MeshLoadData() = default; ~MeshLoadData() { if (std::shared_ptr<PendingRequestBase> request = mRequest.lock()) @@ -300,19 +300,19 @@ public: } void initData(LLVOVolume* vol, std::shared_ptr<PendingRequestBase>& request) { - mVolumes.push_back(vol); + mVolumes.insert(vol); request->trackData(this); mRequest = request; } void addVolume(LLVOVolume* vol) { - mVolumes.push_back(vol); + mVolumes.insert(vol); if (std::shared_ptr<PendingRequestBase> request = mRequest.lock()) { request->setScoreDirty(); } } - std::vector<LLVOVolume*> mVolumes; + std::unordered_set<LLVOVolume*> mVolumes; private: std::weak_ptr<PendingRequestBase> mRequest; }; @@ -862,10 +862,12 @@ public: LLMeshRepository(); void init(); + void unregisterAllMeshes(); void shutdown(); S32 update(); - void unregisterMesh(LLVOVolume* volume); + void unregisterMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail); + void unregisterSkinInfo(const LLUUID& mesh_id, LLVOVolume* vobj); //mesh management functions S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 new_lod = 0, S32 last_lod = -1); diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index ecb66f9cea..ad65293b98 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -191,6 +191,13 @@ bool LLPanelGroup::postBuild() mButtonJoin->setCommitCallback(boost::bind(&LLPanelGroup::onBtnJoin,this)); mJoinText = panel_general->getChild<LLUICtrl>("join_cost_text"); + + mButtonActivate = panel_general->getChild<LLButton>("btn_activate"); + mButtonActivate->setVisible(false); + mButtonActivate->setEnabled(gAgent.getGroupID() != mID); + mButtonActivate->setCommitCallback(boost::bind(&LLPanelGroup::onBtnActivate, this)); + + gAgent.addListener(this, "new group"); } LLVoiceClient::addObserver(this); @@ -267,6 +274,7 @@ void LLPanelGroup::onBtnJoin() if (LLGroupActions::isInGroup(mID)) { LLGroupActions::leave(mID); + mButtonActivate->setVisible(false); } else { @@ -275,6 +283,12 @@ void LLPanelGroup::onBtnJoin() } } +void LLPanelGroup::onBtnActivate() +{ + LLGroupActions::activate(mID); + mButtonActivate->setEnabled(false); +} + void LLPanelGroup::changed(LLGroupChange gc) { for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it) @@ -312,6 +326,8 @@ void LLPanelGroup::update(LLGroupChange gc) bool join_btn_visible = is_member || gdatap->mOpenEnrollment; mButtonJoin->setVisible(join_btn_visible); + mButtonActivate->setEnabled(gAgent.getGroupID() != mID); + mButtonActivate->setVisible(is_member); mJoinText->setVisible(join_btn_visible); if (is_member) @@ -384,6 +400,8 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) if(mButtonJoin) mButtonJoin->setVisible(false); + if (mButtonActivate) + mButtonActivate->setVisible(false); if(is_null_group_id)//creating new group @@ -598,4 +616,20 @@ void LLPanelGroup::showNotice(const std::string& subject, } +bool LLPanelGroup::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + if (event->desc() == "new group") + { + mButtonActivate->setEnabled(gAgent.getGroupID() != mID); + return true; + } + + if (event->desc() == "value_changed") + { + mButtonActivate->setEnabled(gAgent.getGroupID() != mID); + return true; + } + + return false; +} diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h index b43a93bc40..d3550264a0 100644 --- a/indra/newview/llpanelgroup.h +++ b/indra/newview/llpanelgroup.h @@ -26,6 +26,7 @@ #ifndef LL_LLPANELGROUP_H #define LL_LLPANELGROUP_H +#include "llevent.h" #include "llgroupmgr.h" #include "llpanel.h" #include "lltimer.h" @@ -44,7 +45,8 @@ class LLAgent; class LLPanelGroup : public LLPanel, public LLGroupMgrObserver, - public LLVoiceClientStatusObserver + public LLVoiceClientStatusObserver, + public LLOldEvents::LLSimpleListener { public: LLPanelGroup(); @@ -94,6 +96,7 @@ protected: void onBackBtnClick(); void onBtnJoin(); + void onBtnActivate(); static void onBtnApply(void*); static void onBtnRefresh(void*); @@ -120,11 +123,15 @@ protected: LLUICtrl* mGroupNameCtrl = nullptr; LLButton* mButtonJoin = nullptr; + LLButton* mButtonActivate = nullptr; LLButton* mButtonApply = nullptr; LLButton* mButtonCall = nullptr; LLButton* mButtonChat = nullptr; LLButton* mButtonRefresh = nullptr; LLUICtrl* mJoinText; + +private: + bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // for agent group list changes }; class LLPanelGroupTab : public LLPanel diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index fe9145bf71..00b592d86e 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -188,7 +188,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, mUsernameLength(0), mPasswordLength(0), mLocationLength(0), - mShowFavorites(false) + mShowFavorites(false), + mAlertNotif(false) { setBackgroundVisible(false); setBackgroundOpaque(true); @@ -297,8 +298,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, childSetAction("connect_btn", onClickConnect, this); - LLButton* def_btn = getChild<LLButton>("connect_btn"); - setDefaultBtn(def_btn); + mLoginBtn = getChild<LLButton>("connect_btn"); + setDefaultBtn(mLoginBtn); std::string channel = LLVersionInfo::instance().getChannel(); std::string version = stringize(LLVersionInfo::instance().getShortVersion(), " (", @@ -327,6 +328,8 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, LLCheckBoxCtrl* remember_name = getChild<LLCheckBoxCtrl>("remember_name"); remember_name->setCommitCallback(boost::bind(&LLPanelLogin::onRememberUserCheck, this)); getChild<LLCheckBoxCtrl>("remember_password")->setCommitCallback(boost::bind(&LLPanelLogin::onRememberPasswordCheck, this)); + + mAlertListener = LLNotifications::instance().getChannel("Alerts")->connectChanged([this](const LLSD& notify){ return onUpdateNotification(notify); }); } void LLPanelLogin::addFavoritesToStartLocation() @@ -409,7 +412,7 @@ void LLPanelLogin::addFavoritesToStartLocation() gSavedSettings.setBOOL("RememberPassword", save_password); if (!save_password) { - getChild<LLButton>("connect_btn")->setEnabled(false); + mLoginBtn->setEnabled(false); } update_password_setting = false; } @@ -936,7 +939,7 @@ void LLPanelLogin::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent ev // static void LLPanelLogin::onClickConnect(bool commit_fields) { - if (sInstance && sInstance->mCallback) + if (sInstance && sInstance->mCallback && !sInstance->mAlertNotif) { if (commit_fields) { @@ -1193,9 +1196,7 @@ void LLPanelLogin::updateServer() void LLPanelLogin::updateLoginButtons() { - LLButton* login_btn = getChild<LLButton>("connect_btn"); - - login_btn->setEnabled(mUsernameLength != 0 && mPasswordLength != 0); + mLoginBtn->setEnabled(mUsernameLength != 0 && mPasswordLength != 0 && !mAlertNotif); if (!mFirstLoginThisInstall) { @@ -1367,3 +1368,22 @@ std::string LLPanelLogin::getUserName(LLPointer<LLCredential> &cred) return "unknown"; } +bool LLPanelLogin::onUpdateNotification(const LLSD& notify) +{ + // disable Login button while alert notification is displayed + LLNotificationPtr notifyp = LLNotifications::instance().find(notify["id"].asUUID()); + if (notifyp && notifyp->getName() == "PromptOptionalUpdate") + { + std::string sigtype = notify["sigtype"].asString(); + if (sigtype == "add") + { + mAlertNotif = true; + } + else if (sigtype == "delete") + { + mAlertNotif = false; + } + updateLoginButtons(); + } + return false; +} diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index a1bf25fb05..f527aa53ac 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -105,8 +105,11 @@ private: static void onRememberPasswordCheck(void*); static void onPassKey(LLLineEditor* caller, void* user_data); + bool onUpdateNotification(const LLSD& notify); + private: std::unique_ptr<LLPanelLoginListener> mListener; + LLTempBoundListener mAlertListener; void updateLoginButtons(); void populateUserList(LLPointer<LLCredential> credential); @@ -126,6 +129,9 @@ private: unsigned int mUsernameLength; unsigned int mPasswordLength; unsigned int mLocationLength; + + bool mAlertNotif; + LLButton* mLoginBtn; }; #endif diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 23e6a9fbcf..69be65d9c9 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -625,7 +625,7 @@ void LLPanelObject::getState( ) } - if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + if (objectp->getSculptParams()) { selected_item = MI_SCULPT; //LLFirstUse::useSculptedPrim(); @@ -1078,7 +1078,7 @@ void LLPanelObject::getState( ) LLUUID id; - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = objectp->getSculptParams(); if (sculpt_params) // if we have a legal sculpt param block for this object: @@ -1246,13 +1246,13 @@ void LLPanelObject::onCommitParametric( LLUICtrl* ctrl, void* userdata ) if (selected_type == MI_SCULPT) { self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, true, true); - LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = self->mObject->getSculptParams(); if (sculpt_params) volume_params.setSculptID(sculpt_params->getSculptTexture(), sculpt_params->getSculptType()); } else { - LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = self->mObject->getSculptParams(); if (sculpt_params) self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, false, true); } @@ -2264,24 +2264,21 @@ void LLPanelObject::onCopyParams() mClipboardParams["volume_params"] = params.asLLSD(); // Sculpted Prim - if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + LLSculptParams *sculpt_params = objectp->getSculptParams(); + if (sculpt_params) { - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - if (sculpt_params) + LLUUID texture_id = sculpt_params->getSculptTexture(); + if (get_can_copy_texture(texture_id)) { - LLUUID texture_id = sculpt_params->getSculptTexture(); - if (get_can_copy_texture(texture_id)) - { - LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; - mClipboardParams["sculpt"]["id"] = texture_id; - } - else - { - mClipboardParams["sculpt"]["id"] = SCULPT_DEFAULT_TEXTURE; - } - - mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); + LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; + mClipboardParams["sculpt"]["id"] = texture_id; } + else + { + mClipboardParams["sculpt"]["id"] = SCULPT_DEFAULT_TEXTURE; + } + + mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); } } @@ -2304,7 +2301,7 @@ void LLPanelObject::onPasteParams() } else { - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = objectp->getSculptParams(); if (sculpt_params) { objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, false, true); diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 5916163f60..94864797d5 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -532,7 +532,7 @@ void LLPanelVolume::getState( ) getChildView("FlexForceY")->setEnabled(true); getChildView("FlexForceZ")->setEnabled(true); - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData(); getChild<LLUICtrl>("FlexNumSections")->setValue((F32)attributes->getSimulateLOD()); getChild<LLUICtrl>("FlexGravity")->setValue(attributes->getGravity()); @@ -643,7 +643,7 @@ void LLPanelVolume::getState( ) mComboPhysicsShapeType->add(getString("None"), LLSD(1)); bool isMesh = false; - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = objectp->getSculptParams(); if (sculpt_params) { U8 sculpt_type = sculpt_params->getSculptType(); @@ -1043,7 +1043,7 @@ void LLPanelVolume::onCopyFeatures() // Flexi Prim if (volobjp && volobjp->isFlexible()) { - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData(); if (attributes) { clipboard["flex"]["lod"] = attributes->getSimulateLOD(); @@ -1141,7 +1141,7 @@ void LLPanelVolume::onPasteFeatures() objectp->setClickAction(CLICK_ACTION_NONE); } - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData(); if (attributes) { LLFlexibleObjectData new_attributes; @@ -1568,7 +1568,7 @@ void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata ) return; } - LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData *attributes = objectp->getFlexibleObjectData(); if (attributes) { LLFlexibleObjectData new_attributes; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 2dc2810861..66872b104e 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -135,9 +135,10 @@ void LLSpatialGroup::clearDrawMap() mDrawMap.clear(); } -bool LLSpatialGroup::isHUDGroup() +bool LLSpatialGroup::isHUDGroup() const { - return getSpatialPartition() && getSpatialPartition()->isHUDPartition() ; + LLSpatialPartition* part = (LLSpatialPartition*)mSpatialPartition; + return part && part->isHUDPartition(); } void LLSpatialGroup::validate() diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index dd11099c69..2e918df910 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -265,7 +265,7 @@ public: LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part); - bool isHUDGroup() ; + bool isHUDGroup() const; void clearDrawMap(); void validate(); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index f78ff2226c..5e2d91d31e 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -775,7 +775,7 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, bool drop, if (!handled) { // Disallow drag and drop to 3D from the marketplace - const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.notNull()) { for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++) diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index 5ccda7d4eb..3bd459f5b0 100644 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -55,17 +55,17 @@ LLToolSelect::LLToolSelect( LLToolComposite* composite ) : LLTool( std::string("Select"), composite ), mIgnoreGroup( false ) { - } +} // True if you selected an object. bool LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask) { // do immediate pick query bool pick_rigged = false; //gSavedSettings.getBOOL("AnimatedObjectsAllowLeftClick"); - bool pick_transparent = gSavedSettings.getBOOL("SelectInvisibleObjects"); - bool pick_reflection_probe = gSavedSettings.getBOOL("SelectReflectionProbes"); + static LLCachedControl<bool> select_invisible_objects(gSavedSettings, "SelectInvisibleObjects"); + static LLCachedControl<bool> select_reflection_probes(gSavedSettings, "SelectReflectionProbes"); - mPick = gViewerWindow->pickImmediate(x, y, pick_transparent, pick_rigged, false, true, pick_reflection_probe); + mPick = gViewerWindow->pickImmediate(x, y, select_invisible_objects, pick_rigged, false, true, select_reflection_probes); // Pass mousedown to agent LLTool::handleMouseDown(x, y, mask); @@ -73,7 +73,6 @@ bool LLToolSelect::handleMouseDown(S32 x, S32 y, MASK mask) return mPick.getObject().notNull(); } - // static LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pick, bool ignore_group, bool temp_select, bool select_root) { diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index aa0cbac91f..a7441febd9 100644 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -398,18 +398,12 @@ void init_audio() void audio_update_volume(bool force_update) { - F32 master_volume = gSavedSettings.getF32("AudioLevelMaster"); - bool mute_audio = gSavedSettings.getBOOL("MuteAudio"); - - LLProgressView* progress = gViewerWindow->getProgressView(); - bool progress_view_visible = false; - - if (progress) - { - progress_view_visible = progress->getVisible(); - } + static LLCachedControl<F32> master_volume(gSavedSettings, "AudioLevelMaster"); + static LLCachedControl<bool> mute_audio_setting(gSavedSettings, "MuteAudio"); + static LLCachedControl<bool> mute_when_minimized(gSavedSettings, "MuteWhenMinimized"); + bool mute_audio = mute_audio_setting(); - if (!gViewerWindow->getActive() && gSavedSettings.getBOOL("MuteWhenMinimized")) + if (!gViewerWindow->getActive() && mute_when_minimized()) { mute_audio = true; } @@ -419,7 +413,7 @@ void audio_update_volume(bool force_update) { // Sound Effects - gAudiop->setMasterGain ( master_volume ); + gAudiop->setMasterGain (master_volume()); const F32 AUDIO_LEVEL_DOPPLER = 1.f; gAudiop->setDopplerFactor(AUDIO_LEVEL_DOPPLER); @@ -435,6 +429,7 @@ void audio_update_volume(bool force_update) gAudiop->setRolloffFactor(AUDIO_LEVEL_UNDERWATER_ROLLOFF); } + bool progress_view_visible = gViewerWindow->getShowProgress(); gAudiop->setMuted(mute_audio || progress_view_visible); //Play any deferred sounds when unmuted @@ -448,13 +443,21 @@ void audio_update_volume(bool force_update) audio_update_wind(true); } + static LLCachedControl<bool> mute_sounds(gSavedSettings, "MuteSounds"); + static LLCachedControl<bool> mute_ui(gSavedSettings, "MuteUI"); + static LLCachedControl<bool> mute_ambient(gSavedSettings, "MuteAmbient"); + static LLCachedControl<bool> mute_music(gSavedSettings, "MuteMusic"); + static LLCachedControl<F32> al_sfx(gSavedSettings, "AudioLevelSFX"); + static LLCachedControl<F32> al_ui(gSavedSettings, "AudioLevelUI"); + static LLCachedControl<F32> al_ambient(gSavedSettings, "AudioLevelAmbient"); + static LLCachedControl<F32> al_music(gSavedSettings, "AudioLevelMusic"); // handle secondary gains gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_SFX, - gSavedSettings.getBOOL("MuteSounds") ? 0.f : gSavedSettings.getF32("AudioLevelSFX")); + mute_sounds() ? 0.f : al_sfx()); gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_UI, - gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI")); + mute_ui() ? 0.f : al_ui()); gAudiop->setSecondaryGain(LLAudioEngine::AUDIO_TYPE_AMBIENT, - gSavedSettings.getBOOL("MuteAmbient") ? 0.f : gSavedSettings.getF32("AudioLevelAmbient")); + mute_ambient() ? 0.f : al_ambient()); // Streaming Music @@ -464,31 +467,29 @@ void audio_update_volume(bool force_update) LLViewerAudio::getInstance()->setForcedTeleportFade(false); } - F32 music_volume = gSavedSettings.getF32("AudioLevelMusic"); - bool music_muted = gSavedSettings.getBOOL("MuteMusic"); F32 fade_volume = LLViewerAudio::getInstance()->getFadeVolume(); - music_volume = mute_volume * master_volume * music_volume * fade_volume; - gAudiop->setInternetStreamGain (music_muted ? 0.f : music_volume); + F32 music_volume = mute_volume * master_volume * al_music() * fade_volume; + gAudiop->setInternetStreamGain (mute_music() ? 0.f : music_volume); } // Streaming Media - F32 media_volume = gSavedSettings.getF32("AudioLevelMedia"); - bool media_muted = gSavedSettings.getBOOL("MuteMedia"); - media_volume = mute_volume * master_volume * media_volume; - LLViewerMedia::getInstance()->setVolume( media_muted ? 0.0f : media_volume ); + static LLCachedControl<bool> media_muted(gSavedSettings, "MuteMedia"); + static LLCachedControl<F32> media_volume(gSavedSettings, "AudioLevelMedia"); + LLViewerMedia::getInstance()->setVolume( media_muted() ? 0.0f : (mute_volume * master_volume() * media_volume())); // Voice, this is parametric singleton, it gets initialized when ready if (LLVoiceClient::instanceExists()) { - F32 voice_volume = gSavedSettings.getF32("AudioLevelVoice"); - voice_volume = mute_volume * master_volume * voice_volume; - bool voice_mute = gSavedSettings.getBOOL("MuteVoice"); + static LLCachedControl<bool> voice_mute(gSavedSettings, "MuteVoice"); + static LLCachedControl<F32> voice_volume_setting(gSavedSettings, "AudioLevelVoice"); + static LLCachedControl<F32> voice_mic_setting(gSavedSettings, "AudioLevelMic"); + F32 voice_volume = mute_volume * master_volume() * voice_volume_setting(); LLVoiceClient *voice_inst = LLVoiceClient::getInstance(); - voice_inst->setVoiceVolume(voice_mute ? 0.f : voice_volume); - voice_inst->setMicGain(voice_mute ? 0.f : gSavedSettings.getF32("AudioLevelMic")); + voice_inst->setVoiceVolume(voice_mute() ? 0.f : voice_volume); + voice_inst->setMicGain(voice_mute() ? 0.f : voice_mic_setting()); - if (!gViewerWindow->getActive() && (gSavedSettings.getBOOL("MuteWhenMinimized"))) + if (!gViewerWindow->getActive() && mute_when_minimized()) { voice_inst->setMuteMic(true); } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index a8eaadc426..30b2dafb8f 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -663,9 +663,10 @@ void LLViewerMedia::updateMedia(void *dummy_arg) LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; //LL_RECORD_BLOCK_TIME(FTM_MEDIA_UPDATE); llassert(!gCubeSnapshot); + static LLCachedControl<bool> use_read_thread(gSavedSettings, "PluginUseReadThread", true); // Enable/disable the plugin read thread - LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread")); + LLPluginProcessParent::setUseReadThread(use_read_thread()); // SL-16418 We can't call LLViewerMediaImpl->update() if we are in the state of shutting down. if(LLApp::isExiting()) @@ -2196,16 +2197,19 @@ void LLViewerMediaImpl::updateVolume() if (mProximityCamera > 0) { - if (mProximityCamera > gSavedSettings.getF32("MediaRollOffMax")) + static LLCachedControl<F32> media_rolloff_min(gSavedSettings, "MediaRollOffMin"); + static LLCachedControl<F32> media_rolloff_max(gSavedSettings, "MediaRollOffMax"); + static LLCachedControl<F32> media_rolloff_rate(gSavedSettings, "MediaRollOffRate"); + if (mProximityCamera > media_rolloff_max()) { volume = 0; } - else if (mProximityCamera > gSavedSettings.getF32("MediaRollOffMin")) + else if (mProximityCamera > media_rolloff_min()) { // attenuated_volume = 1 / (roll_off_rate * (d - min))^2 // the +1 is there so that for distance 0 the volume stays the same - F64 adjusted_distance = mProximityCamera - gSavedSettings.getF32("MediaRollOffMin"); - F64 attenuation = 1.0 + (gSavedSettings.getF32("MediaRollOffRate") * adjusted_distance); + F64 adjusted_distance = mProximityCamera - media_rolloff_min(); + F64 attenuation = 1.0 + (media_rolloff_rate() * adjusted_distance); attenuation = 1.0 / (attenuation * attenuation); // the attenuation multiplier should never be more than one since that would increase volume volume = volume * (F32)llmin(1.0, attenuation); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index abaf813530..f29760c824 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -425,7 +425,7 @@ void LLSLMMenuUpdater::setMerchantMenu() LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings"); gToolBarView->enableCommand(command->id(), true); - const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID marketplacelistings_id = gInventory.getMarketplaceListingsUUID(); if (marketplacelistings_id.isNull()) { U32 mkt_status = LLMarketplaceData::instance().getSLMStatus(); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1675c44c5c..0f4cbdd25c 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -310,6 +310,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mAttachmentItemID(LLUUID::null), mLastUpdateType(OUT_UNKNOWN), mLastUpdateCached(false), + mExtraParameterList(LLNetworkData::PARAMS_MAX >> 4), mCachedMuteListUpdateTime(0), mCachedOwnerInMuteList(false), mRiggedAttachedWarned(false) @@ -367,15 +368,6 @@ LLViewerObject::~LLViewerObject() } // Delete memory associated with extra parameters. - std::unordered_map<U16, ExtraParameter*>::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - if(iter->second != NULL) - { - delete iter->second->data; - delete iter->second; - } - } mExtraParameterList.clear(); for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ; @@ -1508,10 +1500,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, unpackParticleSource(block_num, owner_id); // Mark all extra parameters not used - std::unordered_map<U16, ExtraParameter*>::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + for (auto& entry : mExtraParameterList) { - iter->second->in_use = false; + if (entry.in_use) *entry.in_use = false; } // Unpack extra parameters @@ -1543,12 +1534,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, delete[] buffer; } - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + for (size_t i = 0; i < mExtraParameterList.size(); ++i) { - if (!iter->second->in_use) + auto& entry = mExtraParameterList[i]; + if (entry.in_use && !*entry.in_use) { // Send an update message in case it was formerly in use - parameterChanged(iter->first, iter->second->data, false, false); + parameterChanged(((U16)i + 1) << 4, entry.data, false, false); } } @@ -1850,10 +1842,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } // Mark all extra parameters not used - std::unordered_map<U16, ExtraParameter*>::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + for (auto& entry : mExtraParameterList) { - iter->second->in_use = false; + if (entry.in_use) *entry.in_use = false; } // Unpack extra params @@ -1871,12 +1862,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, unpackParameterEntry(param_type, &dp2); } - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) + for (size_t i = 0; i < mExtraParameterList.size(); ++i) { - if (!iter->second->in_use) + auto& entry = mExtraParameterList[i]; + if (entry.in_use && !*entry.in_use) { // Send an update message in case it was formerly in use - parameterChanged(iter->first, iter->second->data, false, false); + parameterChanged(((U16)i + 1) << 4, entry.data, false, false); } } @@ -4183,7 +4175,7 @@ void LLViewerObject::boostTexturePriority(bool boost_children /* = true */) if (isSculpted() && !isMesh()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = getSculptParams(); if (sculpt_params) { LLUUID sculpt_id = sculpt_params->getSculptTexture(); @@ -6494,7 +6486,7 @@ bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp) if (param) { param->data->unpack(*dp); - param->in_use = true; + *param->in_use = true; parameterChanged(param_type, param->data, true, false); return true; } @@ -6506,108 +6498,79 @@ bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp) LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 param_type) { - LLNetworkData* new_block = NULL; + LLNetworkData* new_block = nullptr; + bool* in_use = NULL; switch (param_type) { case LLNetworkData::PARAMS_FLEXIBLE: { - new_block = new LLFlexibleObjectData(); + mFlexibleObjectData = std::make_unique<LLFlexibleObjectData>(); + new_block = mFlexibleObjectData.get(); + in_use = &mFlexibleObjectDataInUse; break; } case LLNetworkData::PARAMS_LIGHT: { - new_block = new LLLightParams(); + mLightParams = std::make_unique<LLLightParams>(); + new_block = mLightParams.get(); + in_use = &mLightParamsInUse; break; } case LLNetworkData::PARAMS_SCULPT: { - new_block = new LLSculptParams(); + mSculptParams = std::make_unique<LLSculptParams>(); + new_block = mSculptParams.get(); + in_use = &mSculptParamsInUse; break; } case LLNetworkData::PARAMS_LIGHT_IMAGE: { - new_block = new LLLightImageParams(); + mLightImageParams = std::make_unique<LLLightImageParams>(); + new_block = mLightImageParams.get(); + in_use = &mLightImageParamsInUse; break; } case LLNetworkData::PARAMS_EXTENDED_MESH: { - new_block = new LLExtendedMeshParams(); + mExtendedMeshParams = std::make_unique<LLExtendedMeshParams>(); + new_block = mExtendedMeshParams.get(); + in_use = &mExtendedMeshParamsInUse; break; } case LLNetworkData::PARAMS_RENDER_MATERIAL: { - new_block = new LLRenderMaterialParams(); + mRenderMaterialParams = std::make_unique<LLRenderMaterialParams>(); + new_block = mRenderMaterialParams.get(); + in_use = &mRenderMaterialParamsInUse; break; } case LLNetworkData::PARAMS_REFLECTION_PROBE: { - new_block = new LLReflectionProbeParams(); + mReflectionProbeParams = std::make_unique<LLReflectionProbeParams>(); + new_block = mReflectionProbeParams.get(); + in_use = &mReflectionProbeParamsInUse; break; } default: { - LL_INFOS_ONCE() << "Unknown param type: " << param_type << LL_ENDL; + LL_INFOS_ONCE() << "Unknown param type. (" << llformat("0x%2x", param_type) << ")" << LL_ENDL; break; } }; + ExtraParameter& entry = mExtraParameterList[U32(param_type >> 4) - 1]; if (new_block) { - ExtraParameter* new_entry = new ExtraParameter; - new_entry->data = new_block; - new_entry->in_use = false; // not in use yet - llassert(mExtraParameterList[param_type] == nullptr); // leak -- redundantly allocated parameter entry - mExtraParameterList[param_type] = new_entry; - return new_entry; - } - return NULL; -} - -LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntry(U16 param_type) const -{ - LL_PROFILE_ZONE_SCOPED_CATEGORY_VIEWER; - std::unordered_map<U16, ExtraParameter*>::const_iterator itor = mExtraParameterList.find(param_type); - if (itor != mExtraParameterList.end()) - { - return itor->second; - } - return NULL; -} - -LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntryCreate(U16 param_type) -{ - ExtraParameter* param = getExtraParameterEntry(param_type); - if (!param) - { - param = createNewParameterEntry(param_type); - } - return param; -} - -LLNetworkData* LLViewerObject::getParameterEntry(U16 param_type) const -{ - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) - { - return param->data; + entry.in_use = in_use; + *entry.in_use = false; // not in use yet + entry.data = new_block; + return &entry; } else { - return NULL; - } -} - -bool LLViewerObject::getParameterEntryInUse(U16 param_type) const -{ - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) - { - return param->in_use; - } - else - { - return false; + entry.is_invalid = true; } + return nullptr; } bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin) @@ -6615,11 +6578,11 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_ ExtraParameter* param = getExtraParameterEntryCreate(param_type); if (param) { - if (param->in_use && new_value == *(param->data)) + if (*(param->in_use) && new_value == *(param->data)) { return false; } - param->in_use = true; + *param->in_use = true; param->data->copy(new_value); parameterChanged(param_type, param->data, true, local_origin); return true; @@ -6635,22 +6598,28 @@ bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_ // Should always return true. bool LLViewerObject::setParameterEntryInUse(U16 param_type, bool in_use, bool local_origin) { - ExtraParameter* param = getExtraParameterEntryCreate(param_type); - if (param && param->in_use != in_use) + if (param_type <= LLNetworkData::PARAMS_MAX) { - param->in_use = in_use; - parameterChanged(param_type, param->data, in_use, local_origin); - return true; + ExtraParameter* param = (in_use ? getExtraParameterEntryCreate(param_type) : &getExtraParameterEntry(param_type)); + if (param && param->data && *param->in_use != in_use) + { + *param->in_use = in_use; + parameterChanged(param_type, param->data, in_use, local_origin); + return true; + } } return false; } void LLViewerObject::parameterChanged(U16 param_type, bool local_origin) { - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) + if (param_type <= LLNetworkData::PARAMS_MAX) { - parameterChanged(param_type, param->data, param->in_use, local_origin); + const ExtraParameter& param = getExtraParameterEntry(param_type); + if (param.data) + { + parameterChanged(param_type, param.data, *param.in_use, local_origin); + } } } @@ -6698,7 +6667,7 @@ void LLViewerObject::parameterChanged(U16 param_type, LLNetworkData* data, bool { if (param_type == LLNetworkData::PARAMS_RENDER_MATERIAL) { - const LLRenderMaterialParams* params = in_use ? (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL) : nullptr; + const LLRenderMaterialParams* params = in_use ? getRenderMaterialParams() : nullptr; setRenderMaterialIDs(params, local_origin); } } @@ -7469,9 +7438,10 @@ const std::string& LLViewerObject::getAttachmentItemName() const LLVOAvatar* LLViewerObject::getAvatar() const { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; - if (getControlAvatar()) + LLControlAvatar* ca = getControlAvatar(); + if (ca) { - return getControlAvatar(); + return ca; } if (isAttachment()) { @@ -7490,7 +7460,7 @@ LLVOAvatar* LLViewerObject::getAvatar() const bool LLViewerObject::hasRenderMaterialParams() const { - return getParameterEntryInUse(LLNetworkData::PARAMS_RENDER_MATERIAL); + return mRenderMaterialParamsInUse; } void LLViewerObject::setHasRenderMaterialParams(bool has_materials) @@ -7512,7 +7482,7 @@ void LLViewerObject::setHasRenderMaterialParams(bool has_materials) const LLUUID& LLViewerObject::getRenderMaterialID(U8 te) const { - LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL); + const LLRenderMaterialParams* param_block = getRenderMaterialParams(); if (param_block) { return param_block->getMaterial(te); @@ -7553,7 +7523,7 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat start_idx = llmax(start_idx, 0); end_idx = llmin(end_idx, (S32) getNumTEs()); - LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL); + LLRenderMaterialParams* param_block = getRenderMaterialParams(); if (!param_block && id.notNull()) { // block doesn't exist, but it will need to param_block = (LLRenderMaterialParams*)createNewParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL)->data; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index a9c2db60e4..cccf59a319 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -126,13 +126,15 @@ class LLViewerObject protected: virtual ~LLViewerObject(); // use unref() +private: // TomY: Provide for a list of extra parameter structures, mapped by structure name struct ExtraParameter { - bool in_use; - LLNetworkData *data; + bool is_invalid = false; + bool* in_use = nullptr; + LLNetworkData* data = nullptr; }; - std::unordered_map<U16, ExtraParameter*> mExtraParameterList; + std::vector<ExtraParameter> mExtraParameterList; public: typedef std::list<LLPointer<LLViewerObject> > child_list_t; @@ -630,10 +632,16 @@ public: void dirtySpatialGroup() const; virtual void dirtyMesh(); - virtual LLNetworkData* getParameterEntry(U16 param_type) const; - virtual bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin); - virtual bool getParameterEntryInUse(U16 param_type) const; - virtual bool setParameterEntryInUse(U16 param_type, bool in_use, bool local_origin); + LLFlexibleObjectData* getFlexibleObjectData() const { return mFlexibleObjectDataInUse ? mFlexibleObjectData.get() : nullptr; } + LLLightParams* getLightParams() const { return mLightParamsInUse ? mLightParams.get() : nullptr; } + LLSculptParams* getSculptParams() const { return mSculptParamsInUse ? mSculptParams.get() : nullptr; } + LLLightImageParams* getLightImageParams() const { return mLightImageParamsInUse ? mLightImageParams.get() : nullptr; } + LLExtendedMeshParams* getExtendedMeshParams() const { return mExtendedMeshParamsInUse ? mExtendedMeshParams.get() : nullptr; } + LLRenderMaterialParams* getRenderMaterialParams() const { return mRenderMaterialParamsInUse ? mRenderMaterialParams.get() : nullptr; } + LLReflectionProbeParams* getReflectionProbeParams() const { return mReflectionProbeParamsInUse ? mReflectionProbeParams.get() : nullptr; } + + bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin); + bool setParameterEntryInUse(U16 param_type, bool in_use, bool local_origin); // Called when a parameter is changed virtual void parameterChanged(U16 param_type, bool local_origin); virtual void parameterChanged(U16 param_type, LLNetworkData* data, bool in_use, bool local_origin); @@ -675,8 +683,31 @@ private: bool isAssetInInventory(LLViewerInventoryItem* item, LLAssetType::EType type); ExtraParameter* createNewParameterEntry(U16 param_type); - ExtraParameter* getExtraParameterEntry(U16 param_type) const; - ExtraParameter* getExtraParameterEntryCreate(U16 param_type); + const ExtraParameter& getExtraParameterEntry(U16 param_type) const + { + return mExtraParameterList[U32(param_type >> 4) - 1]; + } + ExtraParameter& getExtraParameterEntry(U16 param_type) + { + return mExtraParameterList[U32(param_type >> 4) - 1]; + } + ExtraParameter* getExtraParameterEntryCreate(U16 param_type) + { + if (param_type <= LLNetworkData::PARAMS_MAX) + { + ExtraParameter& param = getExtraParameterEntry(param_type); + if (!param.is_invalid) + { + if (!param.data) + { + ExtraParameter* new_entry = createNewParameterEntry(param_type); + return new_entry; + } + return ¶m; + } + } + return nullptr; + } bool unpackParameterEntry(U16 param_type, LLDataPacker *dp); // This function checks to see if the given media URL has changed its version @@ -749,6 +780,21 @@ private: // Grabbed from UPDATE_FLAGS U32 mFlags; + bool mFlexibleObjectDataInUse = false, + mLightParamsInUse = false, + mSculptParamsInUse = false, + mLightImageParamsInUse = false, + mExtendedMeshParamsInUse = false, + mRenderMaterialParamsInUse = false, + mReflectionProbeParamsInUse = false; + std::unique_ptr<LLFlexibleObjectData> mFlexibleObjectData; + std::unique_ptr<LLLightParams> mLightParams; + std::unique_ptr<LLSculptParams> mSculptParams; + std::unique_ptr<LLLightImageParams> mLightImageParams; + std::unique_ptr<LLExtendedMeshParams> mExtendedMeshParams; + std::unique_ptr<LLRenderMaterialParams> mRenderMaterialParams; + std::unique_ptr<LLReflectionProbeParams> mReflectionProbeParams; + static std::map<std::string, U32> sObjectDataMap; public: // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 1b38fed3bb..50edb408c7 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -65,6 +65,7 @@ #include "lltoolmgr.h" #include "lltoolpie.h" #include "llkeyboard.h" +#include "llmeshrepository.h" #include "u64.h" #include "llviewertexturelist.h" #include "lldatapacker.h" @@ -1398,6 +1399,8 @@ void LLViewerObjectList::killAllObjects() llassert((objectp == gAgentAvatarp) || objectp->isDead()); } + gMeshRepo.unregisterAllMeshes(); + cleanDeadObjects(false); if(!mObjects.empty()) diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h index 83b8aa8d03..fb6fa8bac4 100644 --- a/indra/newview/llvieweroctree.h +++ b/indra/newview/llvieweroctree.h @@ -312,7 +312,6 @@ public: //virtual bool isRecentlyVisible() const; - LLViewerOctreePartition* getSpatialPartition()const {return mSpatialPartition;} bool isAnyRecentlyVisible() const; static U32 getNewOcclusionQueryObjectName(); diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 432da2e990..6a029645fb 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -881,7 +881,8 @@ LLParcel* LLViewerParcelMgr::getCollisionParcel() const void LLViewerParcelMgr::render() { - if (mSelected && mRenderSelection && gSavedSettings.getBOOL("RenderParcelSelection") && !gDisconnected) + static LLCachedControl<bool> render_parcel_selection(gSavedSettings, "RenderParcelSelection"); + if (mSelected && mRenderSelection && render_parcel_selection() && !gDisconnected) { // Rendering is done in agent-coordinates, so need to supply // an appropriate offset to the render code. diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index cf92850762..17d2edee4d 100755 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -63,9 +63,9 @@ LLUIColor LLViewerParcelOverlay::sForSaleColor; LLUIColor LLViewerParcelOverlay::sAuctionColor; LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_width_meters) -: mRegion( region ), - mParcelGridsPerEdge( S32( region_width_meters / PARCEL_GRID_STEP_METERS ) ), - mDirty( false ), +: mRegion(region), + mParcelGridsPerEdge(S32(region_width_meters / PARCEL_GRID_STEP_METERS)), + mDirty(false), mTimeSinceLastUpdate(), mOverlayTextureIdx(-1) { @@ -467,9 +467,9 @@ void LLViewerParcelOverlay::updatePropertyLines() { for (S32 col = 0; col < GRIDS_PER_EDGE; col++) { - U8 overlay = mOwnership[row*GRIDS_PER_EDGE+col]; + U8 overlay = mOwnership[row * GRIDS_PER_EDGE + col]; S32 colorIndex = overlay & PARCEL_COLOR_MASK; - switch(colorIndex) + switch (colorIndex) { case PARCEL_SELF: case PARCEL_GROUP: @@ -483,11 +483,11 @@ void LLViewerParcelOverlay::updatePropertyLines() const LLColor4U& color = colors[colorIndex]; - F32 left = col*GRID_STEP; - F32 right = left+GRID_STEP; + F32 left = col * GRID_STEP; + F32 right = left + GRID_STEP; - F32 bottom = row*GRID_STEP; - F32 top = bottom+GRID_STEP; + F32 bottom = row * GRID_STEP; + F32 top = bottom + GRID_STEP; // West edge if (overlay & PARCEL_WEST_LINE) @@ -528,99 +528,121 @@ void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F3 Edge& edge = mEdges.back(); edge.color = color; + // Detailized rendering vertices: + // A B C D E F G + // *-*------*--------*--------*------*-* : 'outside' vertices are placed right on the border + // *------*--------*--------*------* : 'inside' vertices are shifted on LINE_WIDTH inside + + // Simplified rendering vertices: + // A G + // *-----------------------------------* + // *-----------------------------------* + F32 outside_x = start_x; F32 outside_y = start_y; - F32 outside_z = 0.f; - F32 inside_x = start_x + tick_dx; - F32 inside_y = start_y + tick_dy; - F32 inside_z = 0.f; + F32 outside_z = land.resolveHeightRegion(outside_x, outside_y); + F32 inside_x = start_x + tick_dx; + F32 inside_y = start_y + tick_dy; + F32 inside_z = land.resolveHeightRegion(inside_x, inside_y); + + auto move = [&](F32 distance) + { + outside_x += dx * distance; + outside_y += dy * distance; + outside_z = land.resolveHeightRegion(outside_x, outside_y); + inside_x += dx * distance; + inside_y += dy * distance; + inside_z = land.resolveHeightRegion(inside_x, inside_y); + }; - auto split = [&](const LLVector3& start, F32 x, F32 y, F32 z, F32 part) + auto split = [&](U32 lod, const LLVector4a& start, F32 x, F32 y, F32 z, F32 part) { - F32 new_x = start.mV[VX] + (x - start.mV[VX]) * part; - F32 new_y = start.mV[VY] + (y - start.mV[VY]) * part; - F32 new_z = start.mV[VZ] + (z - start.mV[VZ]) * part; - edge.vertices.emplace_back(new_x, new_y, new_z); + F32 new_x = start[VX] + (x - start[VX]) * part; + F32 new_y = start[VY] + (y - start[VY]) * part; + edge.pushVertex(lod, new_x, new_y, water_z, 0); }; - auto checkForSplit = [&]() + auto checkForSplit = [&](U32 lod) { - const LLVector3& last_outside = edge.vertices.back(); - F32 z0 = last_outside.mV[VZ]; + const std::vector<LLVector4a>& vertices = edge.verticesUnderWater[lod]; + const LLVector4a& last_outside = vertices.back(); + F32 z0 = last_outside[VZ]; F32 z1 = outside_z; if ((z0 >= water_z && z1 >= water_z) || (z0 < water_z && z1 < water_z)) return; F32 part = (water_z - z0) / (z1 - z0); - const LLVector3& last_inside = edge.vertices[edge.vertices.size() - 2]; - split(last_inside, inside_x, inside_y, inside_z, part); - split(last_outside, outside_x, outside_y, outside_z, part); + const LLVector4a& last_inside = vertices[vertices.size() - 2]; + split(lod, last_inside, inside_x, inside_y, inside_z, part); + split(lod, last_outside, outside_x, outside_y, outside_z, part); }; - // First part, only one vertex - outside_z = land.resolveHeightRegion( outside_x, outside_y ); - - edge.vertices.emplace_back(outside_x, outside_y, outside_z); - - inside_x += dx * LINE_WIDTH; - inside_y += dy * LINE_WIDTH; - - outside_x += dx * LINE_WIDTH; - outside_y += dy * LINE_WIDTH; - - // Then the "actual edge" - inside_z = land.resolveHeightRegion( inside_x, inside_y ); - outside_z = land.resolveHeightRegion( outside_x, outside_y ); + auto pushTwoVertices = [&](U32 lod) + { + LLVector3 out(outside_x, outside_y, outside_z); + LLVector3 in(inside_x, inside_y, inside_z); + if (fabs(inside_z - outside_z) < LINE_WIDTH / 5) + { + edge.pushVertex(lod, inside_x, inside_y, inside_z, water_z); + } + else + { + // Make the line thinner if heights differ too much + LLVector3 dist(in - out); + F32 coef = dist.length() / LINE_WIDTH; + LLVector3 new_in(out + dist / coef); + edge.pushVertex(lod, new_in[VX], new_in[VY], new_in[VZ], water_z); + } + edge.pushVertex(lod, outside_x, outside_y, outside_z, water_z); + }; - edge.vertices.emplace_back(inside_x, inside_y, inside_z); - edge.vertices.emplace_back(outside_x, outside_y, outside_z); + // Point A simplified (first two vertices) + pushTwoVertices(1); - inside_x += dx * (dx - LINE_WIDTH); - inside_y += dy * (dy - LINE_WIDTH); + // Point A detailized (only one vertex) + edge.pushVertex(0, outside_x, outside_y, outside_z, water_z); - outside_x += dx * (dx - LINE_WIDTH); - outside_y += dy * (dy - LINE_WIDTH); + // Point B (two vertices) + move(LINE_WIDTH); + pushTwoVertices(0); - // Middle part, full width + // Points C, D, E + F32 distance = 1.f - LINE_WIDTH; constexpr S32 GRID_STEP = (S32)PARCEL_GRID_STEP_METERS; - for (S32 i = 1; i < GRID_STEP; i++) + for (U32 i = 1; i < GRID_STEP; ++i) { - inside_z = land.resolveHeightRegion( inside_x, inside_y ); - outside_z = land.resolveHeightRegion( outside_x, outside_y ); - - checkForSplit(); - - edge.vertices.emplace_back(inside_x, inside_y, inside_z); - edge.vertices.emplace_back(outside_x, outside_y, outside_z); - - inside_x += dx; - inside_y += dy; - - outside_x += dx; - outside_y += dy; + move(distance); + checkForSplit(0); + pushTwoVertices(0); + distance = 1.f; } - // Extra buffer for edge - inside_x -= dx * LINE_WIDTH; - inside_y -= dy * LINE_WIDTH; - - outside_x -= dx * LINE_WIDTH; - outside_y -= dy * LINE_WIDTH; - - inside_z = land.resolveHeightRegion( inside_x, inside_y ); - outside_z = land.resolveHeightRegion( outside_x, outside_y ); - - checkForSplit(); + // Point F (two vertices) + move(1.f - LINE_WIDTH); + checkForSplit(0); + pushTwoVertices(0); - edge.vertices.emplace_back(inside_x, inside_y, inside_z); - edge.vertices.emplace_back(outside_x, outside_y, outside_z); + // Point G simplified (last two vertices) + move(LINE_WIDTH); + pushTwoVertices(1); - outside_x += dx * LINE_WIDTH; - outside_y += dy * LINE_WIDTH; + // Point G detailized (only one vertex) + edge.pushVertex(0, outside_x, outside_y, outside_z, water_z); +} - // Last edge is not drawn to the edge - outside_z = land.resolveHeightRegion( outside_x, outside_y ); +void LLViewerParcelOverlay::Edge::pushVertex(U32 lod, F32 x, F32 y, F32 z, F32 water_z) +{ + verticesUnderWater[lod].emplace_back(x, y, z); + gGL.transform(verticesUnderWater[lod].back()); - edge.vertices.emplace_back(outside_x, outside_y, outside_z); + if (z >= water_z) + { + verticesAboveWater[lod].push_back(verticesUnderWater[lod].back()); + } + else + { + verticesAboveWater[lod].emplace_back(x, y, water_z); + gGL.transform(verticesAboveWater[lod].back()); + } } void LLViewerParcelOverlay::setDirty() @@ -665,6 +687,9 @@ void LLViewerParcelOverlay::renderPropertyLines() if (!show) return; + LL_PROFILE_ZONE_SCOPED; + LL_PROFILE_GPU_ZONE("Property Lines"); + LLSurface& land = mRegion->getLand(); bool render_water = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER); @@ -702,6 +727,8 @@ void LLViewerParcelOverlay::renderPropertyLines() // Stomp the camera into two dimensions LLVector3 camera_region = mRegion->getPosRegionFromGlobal( gAgentCamera.getCameraPositionGlobal() ); + bool draw_underwater = camera_region.mV[VZ] < water_z || + !gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER); // Set up a cull plane 2 * PARCEL_GRID_STEP_METERS behind // the camera. The cull plane normal is the camera's at axis. @@ -709,15 +736,23 @@ void LLViewerParcelOverlay::renderPropertyLines() cull_plane_point *= -2.f * PARCEL_GRID_STEP_METERS; cull_plane_point += camera_region; - bool render_hidden = LLSelectMgr::sRenderHiddenSelections && LLFloaterReg::instanceVisible("build"); + bool render_hidden = !draw_underwater && + LLSelectMgr::sRenderHiddenSelections && + LLFloaterReg::instanceVisible("build"); constexpr F32 PROPERTY_LINE_CLIP_DIST_SQUARED = 256.f * 256.f; + const F32 PROPERTY_LINE_LOD0_DIST_SQUARED = PROPERTY_LINE_CLIP_DIST_SQUARED / 25; for (const Edge& edge : mEdges) { - LLVector3 center = edge.vertices[edge.vertices.size() >> 1]; + const std::vector<LLVector4a>& vertices0 = edge.verticesAboveWater[0]; + const F32* first = vertices0.front().getF32ptr(); + const F32* last = vertices0.back().getF32ptr(); + LLVector3 center((first[VX] + last[VX]) / 2, (first[VY] + last[VY]) / 2, (first[VZ] + last[VZ]) / 2); + gGL.untransform(center); - if (dist_vec_squared2D(center, camera_region) > PROPERTY_LINE_CLIP_DIST_SQUARED) + F32 dist_squared = dist_vec_squared(center, camera_region); + if (dist_squared > PROPERTY_LINE_CLIP_DIST_SQUARED) { continue; } @@ -731,43 +766,33 @@ void LLViewerParcelOverlay::renderPropertyLines() continue; } + U32 lod = dist_squared < PROPERTY_LINE_LOD0_DIST_SQUARED ? 0 : 1; + gGL.begin(LLRender::TRIANGLE_STRIP); gGL.color4ubv(edge.color.mV); - for (const LLVector3& vertex : edge.vertices) + if (draw_underwater) { - if (render_hidden || camera_z < water_z || vertex.mV[2] >= water_z) - { - gGL.vertex3fv(vertex.mV); - } - else - { - LLVector3 visible = vertex; - visible.mV[VZ] = water_z; - gGL.vertex3fv(visible.mV); - } + gGL.vertexBatchPreTransformed(edge.verticesUnderWater[lod]); } - - gGL.end(); - - if (render_hidden) + else { - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + gGL.vertexBatchPreTransformed(edge.verticesAboveWater[lod]); - gGL.begin(LLRender::TRIANGLE_STRIP); + if (render_hidden) + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); - LLColor4U color = edge.color; - color.mV[VALPHA] /= 4; - gGL.color4ubv(color.mV); + LLColor4U color = edge.color; + color.mV[VALPHA] /= 4; + gGL.color4ubv(color.mV); - for (const LLVector3& vertex : edge.vertices) - { - gGL.vertex3fv(vertex.mV); + gGL.vertexBatchPreTransformed(edge.verticesUnderWater[lod]); } - - gGL.end(); } + + gGL.end(); } gGL.popMatrix(); diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 50bef02ddf..7271c85701 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -116,7 +116,10 @@ private: struct Edge { - std::vector<LLVector3> vertices; + void pushVertex(U32 lod, F32 x, F32 y, F32 z, F32 water_z); + // LOD: 0 - detailized, 1 - simplified + std::vector<LLVector4a> verticesAboveWater[2]; + std::vector<LLVector4a> verticesUnderWater[2]; LLColor4U color; }; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index c77dd9cc08..a3c241456d 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1332,7 +1332,7 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi // Check the whitelist, if there's media (otherwise just show it) if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url)) { - if ( obj != mDragHoveredObject.get()) + if (obj != mDragHoveredObject) { // Highlight the dragged object LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); @@ -3394,13 +3394,11 @@ void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params) } } -static LLTrace::BlockTimerStatHandle ftm("Update UI"); - // Update UI based on stored mouse position from mouse-move // event processing. void LLViewerWindow::updateUI() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; //LL_RECORD_BLOCK_TIME(ftm); + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; static std::string last_handle_msg; @@ -3418,12 +3416,15 @@ void LLViewerWindow::updateUI() } } - LLConsole::updateClass(); + { + LL_PROFILE_ZONE_NAMED("UI updateClass"); + LLConsole::updateClass(); - // execute postponed arrange calls - LLAccordionCtrl::updateClass(); - // animate layout stacks so we have up to date rect for world view - LLLayoutStack::updateClass(); + // execute postponed arrange calls + LLAccordionCtrl::updateClass(); + // animate layout stacks so we have up to date rect for world view + LLLayoutStack::updateClass(); + } // use full window for world view when not rendering UI bool world_view_uses_full_window = gAgentCamera.cameraMouselook() || !gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); @@ -3852,6 +3853,7 @@ void LLViewerWindow::updateUI() void LLViewerWindow::updateLayout() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; LLTool* tool = LLToolMgr::getInstance()->getCurrentTool(); if (gFloaterTools != NULL && tool != NULL @@ -4331,15 +4333,15 @@ void LLViewerWindow::pickAsync( S32 x, bool pick_unselectable, bool pick_reflection_probes) { + static LLCachedControl<bool> select_invisible_objects(gSavedSettings, "SelectInvisibleObjects"); // "Show Debug Alpha" means no object actually transparent bool in_build_mode = LLFloaterReg::instanceVisible("build"); - if (LLDrawPoolAlpha::sShowDebugAlpha - || (in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects"))) + if (LLDrawPoolAlpha::sShowDebugAlpha || (in_build_mode && select_invisible_objects)) { pick_transparent = true; } - LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, false, pick_reflection_probes, pick_unselectable, true, callback); + LLPickInfo pick_info(LLCoordGL(x, y_from_bot), mask, pick_transparent, pick_rigged, false, pick_reflection_probes, true, pick_unselectable, callback); schedulePick(pick_info); } @@ -4363,7 +4365,6 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info) mWindow->delayInputProcessing(); } - void LLViewerWindow::performPick() { if (!mPicks.empty()) @@ -4397,8 +4398,9 @@ void LLViewerWindow::returnEmptyPicks() // Performs the GL object/land pick. LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, bool pick_transparent, bool pick_rigged, bool pick_particle, bool pick_unselectable, bool pick_reflection_probe) { + static LLCachedControl<bool> select_invisible_objects(gSavedSettings, "SelectInvisibleObjects"); bool in_build_mode = LLFloaterReg::instanceVisible("build"); - if ((in_build_mode && gSavedSettings.getBOOL("SelectInvisibleObjects")) || LLDrawPoolAlpha::sShowDebugAlpha) + if ((in_build_mode && select_invisible_objects) || LLDrawPoolAlpha::sShowDebugAlpha) { // build mode allows interaction with all transparent objects // "Show Debug Alpha" means no object actually transparent @@ -4406,7 +4408,7 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, bool pick_transp } // shortcut queueing in mPicks and just update mLastPick in place - MASK key_mask = gKeyboard->currentMask(true); + MASK key_mask = gKeyboard->currentMask(true); mLastPick = LLPickInfo(LLCoordGL(x, y_from_bot), key_mask, pick_transparent, pick_rigged, pick_particle, pick_reflection_probe, true, false, NULL); mLastPick.fetchResults(); @@ -6131,14 +6133,14 @@ LLPickInfo::LLPickInfo(const LLCoordGL& mouse_pos, bool pick_rigged, bool pick_particle, bool pick_reflection_probe, - bool pick_uv_coords, + bool pick_surface_info, bool pick_unselectable, void (*pick_callback)(const LLPickInfo& pick_info)) : mMousePt(mouse_pos), mKeyMask(keyboard_mask), mPickCallback(pick_callback), mPickType(PICK_INVALID), - mWantSurfaceInfo(pick_uv_coords), + mWantSurfaceInfo(pick_surface_info), mObjectFace(-1), mUVCoords(-1.f, -1.f), mSTCoords(-1.f, -1.f), diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 085e386ec9..d1de2f55da 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -2549,10 +2549,7 @@ void LLVoiceWebRTCConnection::OnRenegotiationNeeded() LL::WorkQueue::postMaybe(mMainQueue, [=, this] { LL_DEBUGS("Voice") << "Voice channel requires renegotiation." << LL_ENDL; - if (!mShutDown) - { - setVoiceConnectionState(VOICE_STATE_SESSION_RETRY); - } + setVoiceConnectionState(VOICE_STATE_SESSION_RETRY); mCurrentStatus = LLVoiceClientStatusObserver::ERROR_UNKNOWN; }); } @@ -2898,9 +2895,10 @@ bool LLVoiceWebRTCConnection::connectionStateMachine() // this connection. // For spatial this connection will come up as muted, but will be set to the appropriate // value later on when we determine the regions we connect to. - if (!isSpatial()) + if (isSpatial()) { - mWebRTCAudioInterface->setMute(mMuted); + // we'll determine primary state later and set mute accordinly + mPrimary = false; } mWebRTCAudioInterface->setReceiveVolume(mSpeakerVolume); LLWebRTCVoiceClient::getInstance()->OnConnectionEstablished(mChannelID, mRegionID); @@ -2924,6 +2922,10 @@ bool LLVoiceWebRTCConnection::connectionStateMachine() LLWebRTCVoiceClient::getInstance()->updatePosition(); LLWebRTCVoiceClient::getInstance()->sendPositionUpdate(true); } + else + { + mWebRTCAudioInterface->setMute(mMuted); + } } break; } diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 9c0f4baf28..b328d3a414 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -250,10 +250,12 @@ LLVOVolume::~LLVOVolume() delete mVolumeImpl; mVolumeImpl = NULL; - gMeshRepo.unregisterMesh(this); + unregisterOldMeshAndSkin(); if(!mMediaImplList.empty()) { + LL_PROFILE_ZONE_NAMED_CATEGORY_MEDIA("delete volume media list"); + for(U32 i = 0 ; i < mMediaImplList.size() ; i++) { if(mMediaImplList[i].notNull()) @@ -351,7 +353,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, U8 sculpt_type = 0; if (isSculpted()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = getSculptParams(); if (sculpt_params) { sculpt_id = sculpt_params->getSculptTexture(); @@ -924,7 +926,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) if (getLightTextureID().notNull()) { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLLightImageParams* params = getLightImageParams(); LLUUID id = params->getLightTexture(); mLightTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE); if (mLightTexture.notNull()) @@ -1048,6 +1050,28 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) return mDrawable; } +// Inverse of gMeshRepo.loadMesh and gMeshRepo.getSkinInfo, combined into one function +// Assume a Collada mesh never changes after being set. +void LLVOVolume::unregisterOldMeshAndSkin() +{ + if (mVolumep) + { + const LLVolumeParams& params = mVolumep->getParams(); + if ((params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { + // object is being deleted, so it will no longer need to request + // meshes. + for (S32 lod = 0; lod != LLVolumeLODGroup::NUM_LODS; ++lod) + { + gMeshRepo.unregisterMesh(this, params, lod); + } + // This volume may or may not have a skin + gMeshRepo.unregisterSkinInfo(params.getSculptID(), this); + } + } +} + + bool LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bool unique_volume) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME; @@ -1082,7 +1106,7 @@ bool LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, true, false); if (!mVolumeImpl) { - LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); + LLFlexibleObjectData* data = getFlexibleObjectData(); mVolumeImpl = new LLVolumeImplFlexible(this, data); } } @@ -1193,7 +1217,7 @@ void LLVOVolume::updateSculptTexture() if (isSculpted() && !isMesh()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLSculptParams *sculpt_params = getSculptParams(); if (sculpt_params) { LLUUID id = sculpt_params->getSculptTexture(); @@ -3053,7 +3077,7 @@ void LLVOVolume::setLightTextureID(LLUUID id) { old_texturep->removeVolume(LLRender::LIGHT_TEX, this); } - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLLightImageParams* param_block = getLightImageParams(); if (param_block && param_block->getLightTexture() != id) { param_block->setLightTexture(id); @@ -3083,7 +3107,7 @@ void LLVOVolume::setLightTextureID(LLUUID id) void LLVOVolume::setSpotLightParams(LLVector3 params) { - LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLLightImageParams* param_block = getLightImageParams(); if (param_block && param_block->getParams() != params) { param_block->setParams(params); @@ -3125,7 +3149,7 @@ void LLVOVolume::setLightSRGBColor(const LLColor3& color) void LLVOVolume::setLightLinearColor(const LLColor3& color) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = getLightParams(); if (param_block) { if (param_block->getLinearColor() != color) @@ -3140,7 +3164,7 @@ void LLVOVolume::setLightLinearColor(const LLColor3& color) void LLVOVolume::setLightIntensity(F32 intensity) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = getLightParams(); if (param_block) { if (param_block->getLinearColor().mV[3] != intensity) @@ -3153,7 +3177,7 @@ void LLVOVolume::setLightIntensity(F32 intensity) void LLVOVolume::setLightRadius(F32 radius) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = getLightParams(); if (param_block) { if (param_block->getRadius() != radius) @@ -3166,7 +3190,7 @@ void LLVOVolume::setLightRadius(F32 radius) void LLVOVolume::setLightFalloff(F32 falloff) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = getLightParams(); if (param_block) { if (param_block->getFalloff() != falloff) @@ -3179,7 +3203,7 @@ void LLVOVolume::setLightFalloff(F32 falloff) void LLVOVolume::setLightCutoff(F32 cutoff) { - LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + LLLightParams *param_block = getLightParams(); if (param_block) { if (param_block->getCutoff() != cutoff) @@ -3194,7 +3218,7 @@ void LLVOVolume::setLightCutoff(F32 cutoff) bool LLVOVolume::getIsLight() const { - mIsLight = getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT); + mIsLight = getLightParams() != nullptr; return mIsLight; } @@ -3210,7 +3234,7 @@ LLColor3 LLVOVolume::getLightSRGBBaseColor() const LLColor3 LLVOVolume::getLightLinearBaseColor() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return LLColor3(param_block->getLinearColor()); @@ -3223,7 +3247,7 @@ LLColor3 LLVOVolume::getLightLinearBaseColor() const LLColor3 LLVOVolume::getLightLinearColor() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return LLColor3(param_block->getLinearColor()) * param_block->getLinearColor().mV[3]; @@ -3241,33 +3265,27 @@ LLColor3 LLVOVolume::getLightSRGBColor() const return ret; } -LLUUID LLVOVolume::getLightTextureID() const +const LLUUID& LLVOVolume::getLightTextureID() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + const LLLightImageParams *param_block = getLightImageParams(); + if (param_block) { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getLightTexture(); - } + return param_block->getLightTexture(); } return LLUUID::null; } -LLVector3 LLVOVolume::getSpotLightParams() const +const LLVector3& LLVOVolume::getSpotLightParams() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + const LLLightImageParams *param_block = getLightImageParams(); + if (param_block) { - const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (param_block) - { - return param_block->getParams(); - } + return param_block->getParams(); } - return LLVector3(); + return LLVector3::zero; } F32 LLVOVolume::getSpotLightPriority() const @@ -3304,8 +3322,8 @@ void LLVOVolume::updateSpotLightPriority() bool LLVOVolume::isLightSpotlight() const { - LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); - if (params && getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + const LLLightImageParams* params = getLightImageParams(); + if (params) { return params->isLightSpotlight(); } @@ -3315,7 +3333,7 @@ bool LLVOVolume::isLightSpotlight() const LLViewerTexture* LLVOVolume::getLightTexture() { - LLUUID id = getLightTextureID(); + const LLUUID& id = getLightTextureID(); if (id.notNull()) { @@ -3326,7 +3344,7 @@ LLViewerTexture* LLVOVolume::getLightTexture() } else { - mLightTexture = NULL; + mLightTexture = nullptr; } return mLightTexture; @@ -3334,7 +3352,7 @@ LLViewerTexture* LLVOVolume::getLightTexture() F32 LLVOVolume::getLightIntensity() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return param_block->getLinearColor().mV[3]; @@ -3347,7 +3365,7 @@ F32 LLVOVolume::getLightIntensity() const F32 LLVOVolume::getLightRadius() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return param_block->getRadius(); @@ -3360,7 +3378,7 @@ F32 LLVOVolume::getLightRadius() const F32 LLVOVolume::getLightFalloff(const F32 fudge_factor) const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return param_block->getFalloff() * fudge_factor; @@ -3373,7 +3391,7 @@ F32 LLVOVolume::getLightFalloff(const F32 fudge_factor) const F32 LLVOVolume::getLightCutoff() const { - const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); + const LLLightParams *param_block = getLightParams(); if (param_block) { return param_block->getCutoff(); @@ -3386,7 +3404,7 @@ F32 LLVOVolume::getLightCutoff() const bool LLVOVolume::isReflectionProbe() const { - return getParameterEntryInUse(LLNetworkData::PARAMS_REFLECTION_PROBE); + return getReflectionProbeParams() != nullptr; } bool LLVOVolume::setIsReflectionProbe(bool is_probe) @@ -3411,7 +3429,7 @@ bool LLVOVolume::setIsReflectionProbe(bool is_probe) bool LLVOVolume::setReflectionProbeAmbiance(F32 ambiance) { - LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { if (param_block->getAmbiance() != ambiance) @@ -3427,7 +3445,7 @@ bool LLVOVolume::setReflectionProbeAmbiance(F32 ambiance) bool LLVOVolume::setReflectionProbeNearClip(F32 near_clip) { - LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { if (param_block->getClipDistance() != near_clip) @@ -3443,7 +3461,7 @@ bool LLVOVolume::setReflectionProbeNearClip(F32 near_clip) bool LLVOVolume::setReflectionProbeIsBox(bool is_box) { - LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { if (param_block->getIsBox() != is_box) @@ -3459,7 +3477,7 @@ bool LLVOVolume::setReflectionProbeIsBox(bool is_box) bool LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic) { - LLReflectionProbeParams* param_block = (LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { if (param_block->getIsDynamic() != is_dynamic) @@ -3475,7 +3493,7 @@ bool LLVOVolume::setReflectionProbeIsDynamic(bool is_dynamic) bool LLVOVolume::setReflectionProbeIsMirror(bool is_mirror) { - LLReflectionProbeParams *param_block = (LLReflectionProbeParams *) getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { if (param_block->getIsMirror() != is_mirror) @@ -3498,7 +3516,7 @@ bool LLVOVolume::setReflectionProbeIsMirror(bool is_mirror) F32 LLVOVolume::getReflectionProbeAmbiance() const { - const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + const LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { return param_block->getAmbiance(); @@ -3511,7 +3529,7 @@ F32 LLVOVolume::getReflectionProbeAmbiance() const F32 LLVOVolume::getReflectionProbeNearClip() const { - const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + const LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { return param_block->getClipDistance(); @@ -3524,7 +3542,7 @@ F32 LLVOVolume::getReflectionProbeNearClip() const bool LLVOVolume::getReflectionProbeIsBox() const { - const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + const LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { return param_block->getIsBox(); @@ -3535,7 +3553,7 @@ bool LLVOVolume::getReflectionProbeIsBox() const bool LLVOVolume::getReflectionProbeIsDynamic() const { - const LLReflectionProbeParams* param_block = (const LLReflectionProbeParams*)getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + const LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { return param_block->getIsDynamic(); @@ -3546,8 +3564,7 @@ bool LLVOVolume::getReflectionProbeIsDynamic() const bool LLVOVolume::getReflectionProbeIsMirror() const { - const LLReflectionProbeParams *param_block = - (const LLReflectionProbeParams *) getParameterEntry(LLNetworkData::PARAMS_REFLECTION_PROBE); + const LLReflectionProbeParams* param_block = getReflectionProbeParams(); if (param_block) { return param_block->getIsMirror(); @@ -3568,7 +3585,7 @@ U32 LLVOVolume::getVolumeInterfaceID() const bool LLVOVolume::isFlexible() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) + if (getFlexibleObjectData()) { LLVolume* volume = getVolume(); if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE) @@ -3587,7 +3604,7 @@ bool LLVOVolume::isFlexible() const bool LLVOVolume::isSculpted() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) + if (getSculptParams()) { return true; } @@ -3599,7 +3616,7 @@ bool LLVOVolume::isMesh() const { if (isSculpted()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + const LLSculptParams *sculpt_params = getSculptParams(); if (sculpt_params) { U8 sculpt_type = sculpt_params->getSculptType(); @@ -3617,7 +3634,7 @@ bool LLVOVolume::isMesh() const bool LLVOVolume::hasLightTexture() const { - if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + if (getLightImageParams()) { return true; } @@ -3737,8 +3754,7 @@ bool LLVOVolume::isRiggedMesh() const //---------------------------------------------------------------------------- U32 LLVOVolume::getExtendedMeshFlags() const { - const LLExtendedMeshParams *param_block = - (const LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); + const LLExtendedMeshParams *param_block = getExtendedMeshParams(); if (param_block) { return param_block->getFlags(); @@ -3783,8 +3799,7 @@ void LLVOVolume::setExtendedMeshFlags(U32 flags) { bool in_use = true; setParameterEntryInUse(LLNetworkData::PARAMS_EXTENDED_MESH, in_use, true); - LLExtendedMeshParams *param_block = - (LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); + LLExtendedMeshParams *param_block = (LLExtendedMeshParams *)getExtendedMeshParams(); if (param_block) { param_block->setFlags(flags); @@ -3842,11 +3857,12 @@ void LLVOVolume::onReparent(LLViewerObject *old_parent, LLViewerObject *new_pare } if (old_volp && old_volp->isAnimatedObject()) { - if (old_volp->getControlAvatar()) + LLControlAvatar* cav = old_volp->getControlAvatar(); + if (cav) { // We have been removed from an animated object, need to do cleanup. - old_volp->getControlAvatar()->updateAttachmentOverrides(); - old_volp->getControlAvatar()->updateAnimations(); + cav->updateAttachmentOverrides(); + cav->updateAnimations(); } } } @@ -5131,7 +5147,7 @@ U32 LLVOVolume::getPartitionType() const { return LLViewerRegion::PARTITION_HUD; } - if (isAnimatedObject() && getControlAvatar()) + if (isAnimatedObjectFast() && getControlAvatar()) { return LLViewerRegion::PARTITION_CONTROL_AV; } @@ -5757,11 +5773,18 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } // Standard rigged mesh attachments: - bool rigged = !vobj->isAnimatedObject() && skinInfo && vobj->isAttachment(); + bool is_animated = vobj->isAnimatedObject(); + bool rigged = !is_animated && skinInfo && vobj->isAttachment(); // Animated objects. Have to check for isRiggedMesh() to // exclude static objects in animated object linksets. - rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() && - vobj->getControlAvatar() && vobj->getControlAvatar()->mPlaying); + if (!rigged && is_animated && vobj->isRiggedMesh()) + { + LLControlAvatar* cav = vobj->getControlAvatar(); + if (cav) + { + rigged = cav->mPlaying; + } + } bool any_rigged_face = false; diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 97a5131260..b6044bc319 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -227,6 +227,7 @@ public: void setTexture(const S32 face); S32 getIndexInTex(U32 ch) const {return mIndexInTex[ch];} + void unregisterOldMeshAndSkin(); /*virtual*/ bool setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false) override; void updateSculptTexture(); void setIndexInTex(U32 ch, S32 index) { mIndexInTex[ch] = index ;} @@ -283,9 +284,9 @@ public: // Get the light color in sRGB color space scaled by intensity. LLColor3 getLightSRGBColor() const; - LLUUID getLightTextureID() const; + const LLUUID& getLightTextureID() const; bool isLightSpotlight() const; - LLVector3 getSpotLightParams() const; + const LLVector3& getSpotLightParams() const; void updateSpotLightPriority(); F32 getSpotLightPriority() const; diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp index 614d1afc2a..072743505f 100644 --- a/indra/newview/llwatchdog.cpp +++ b/indra/newview/llwatchdog.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llwatchdog.h" +#include "llmutex.h" #include "llthread.h" #include "llappviewer.h" diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index a319aa00bc..f603274335 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -34,6 +34,7 @@ #include "llagent.h" #include "llappviewer.h" +#include "llfloatermarketplace.h" #include "llfloaterwebcontent.h" #include "llfloaterreg.h" #include "lllogininstance.h" @@ -74,12 +75,20 @@ void LLWeb::loadURL(const std::string& url, const std::string& target, const std } // static -// Explicitly open a Web URL using the Web content floater +// Explicitly open a Web URL using the Web content floater or Marketplace floater void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid, bool dev_mode) { LLFloaterWebContent::Params p; p.url(url).target(target).id(uuid).dev_mode(dev_mode); - LLFloaterReg::showInstance("web_content", p); + + if (LLFloaterMarketplace::isMarketplaceURL(url)) + { + LLFloaterReg::showInstance("marketplace", p); + } + else + { + LLFloaterReg::showInstance("web_content", p); + } } // static diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 153bee3aef..1db36649fa 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -118,6 +118,7 @@ LLVector3d LLSimInfo::getGlobalOrigin() const { return from_region_handle(mHandle); } + LLVector3 LLSimInfo::getLocalPos(LLVector3d global_pos) const { LLVector3d sim_origin = from_region_handle(mHandle); diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 6b2bd3e6fb..1be6a6cfff 100755 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -517,26 +517,38 @@ void LLWorldMapView::draw() // Draw the region name in the lower left corner if (mMapScale >= DRAW_TEXT_THRESHOLD) { - std::string mesg; + static LLCachedControl<bool> print_coords(gSavedSettings, "MapShowGridCoords"); + static LLFontGL* font = LLFontGL::getFontSansSerifSmallBold(); + + auto print = [&](std::string text, F32 x, F32 y, bool use_ellipses) + { + font->renderUTF8(text, 0, + (F32)llfloor(left + x), (F32)llfloor(bottom + y), + LLColor4::white, + LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, + S32_MAX, //max_chars + (S32)mMapScale, //max_pixels + NULL, + use_ellipses); + }; + + std::string grid_name = info->getName(); if (info->isDown()) { - mesg = llformat( "%s (%s)", info->getName().c_str(), sStringsMap["offline"].c_str()); + grid_name += " (" + sStringsMap["offline"] + ")"; } - else + + if (print_coords) { - mesg = info->getName(); + print(grid_name, 3, 14, true); + // Obtain and print the grid map coordinates + LLVector3d region_pos = info->getGlobalOrigin(); + std::string grid_coords = llformat("[%.0f, %.0f]", region_pos[VX] / 256, region_pos[VY] / 256); + print(grid_coords, 3, 2, false); } - if (!mesg.empty()) + else { - LLFontGL::getFontSansSerifSmallBold()->renderUTF8( - mesg, 0, - (F32)llfloor(left + 3), (F32)llfloor(bottom + 2), - LLColor4::white, - LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, - S32_MAX, //max_chars - (S32)mMapScale, //max_pixels - NULL, - /*use_ellipses*/true); + print(grid_name, 3, 2, true); } } } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4316b850e3..3b72e512da 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -5536,7 +5536,7 @@ static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_ if (light->mDrawable.notNull() && light->mDrawable->isState(LLDrawable::ACTIVE)) { // moving lights get a little higher priority (too much causes artifacts) - dist = llmax(dist - light->getLightRadius()*0.25f, 0.f); + dist = llmax(dist - radius * 0.25f, 0.f); } return dist; } diff --git a/indra/newview/skins/default/xui/en/floater_test_combobox.xml b/indra/newview/skins/default/xui/en/floater_test_combobox.xml index 4211d624ac..0d75685223 100644 --- a/indra/newview/skins/default/xui/en/floater_test_combobox.xml +++ b/indra/newview/skins/default/xui/en/floater_test_combobox.xml @@ -155,4 +155,36 @@ name="item3" value="tx" /> </combo_box> + <text + type="string" + length="1" + height="16" + layout="topleft" + left_delta="0" + top_pad="24" + width="200"> + Multiple columns: + </text> + <combo_box + name="multi_column_combo" + layout="topleft" + height="20" + width="150" + left_delta="0" + top_pad="4"> + <combo_item name="combo_item1" value="0"> + <column width="40" name="label" label="|Abc|" /> + <column name="longtext" label="Match full text" /> + </combo_item> + + <combo_item name="combo_item2" value="1"> + <column name="label" label="*Abc*" /> + <column name="longtext" label="Match substring" /> + </combo_item> + + <combo_item name="combo_item3" value="2"> + <column name="label" label="/ *. /" /> + <column name="longtext" label="Match regular expression" /> + </combo_item> + </combo_box> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index 0ce64b7a83..b0635a2229 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -109,7 +109,7 @@ </panel> <panel follows="right|top" - height="126" + height="150" top_pad="4" width="238" left="1" @@ -285,6 +285,30 @@ by owner </text> + <check_box + name="grid_coords_chk" + control_name="MapShowGridCoords" + layout="topleft" + follows="top|right" + top_pad="2" + left="3" + height="16" + width="22" + /> + <text + name="grid_coords_label" + type="string" + layout="topleft" + follows="top|right" + top_delta="2" + left_pad="3" + height="16" + width="220" + halign="left" + length="1" > + Show grid map coordinates + </text> + <button follows="top|right" height="22" @@ -455,7 +479,7 @@ <panel follows="right|top|bottom" - height="235" + height="220" top_pad="0" width="238" name="layout_panel_4"> @@ -573,7 +597,7 @@ draw_stripes="false" bg_writeable_color="MouseGray" follows="all" - height="145" + height="130" layout="topleft" left="28" name="search_results" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index dbd513afe8..d278bac075 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4425,9 +4425,9 @@ Click OK to install. </notification> <notification - icon="alertmodal.tga" + icon="alert.tga" name="PromptOptionalUpdate" - type="alertmodal"> + type="alert"> Version [VERSION] has been downloaded and is ready to install. Release notes: [URL] diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml index 7290cbb5c6..74bc7736f9 100644 --- a/indra/newview/skins/default/xui/en/panel_group_general.xml +++ b/indra/newview/skins/default/xui/en/panel_group_general.xml @@ -86,6 +86,15 @@ Hover your mouse over the options for more help. name="btn_join" visible="true" width="120" /> + <button + follows="left|top" + left_pad="6" + top_delta="0" + height="23" + label="Activate" + name="btn_activate" + visible="true" + width="120" /> </panel> <text_editor type="string" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index ddddb4855f..aa641a35f7 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -113,7 +113,7 @@ width="70"> <combo_box.item enabled="true" - label="1:00 AM" + label="1:00 PM" name="12H" value="0" /> <combo_box.item diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml index 6ef1b6e44a..47e1e669d1 100644 --- a/indra/newview/skins/default/xui/en/panel_region_general.xml +++ b/indra/newview/skins/default/xui/en/panel_region_general.xml @@ -33,6 +33,28 @@ unknown </text> <text + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + top_delta="0" + right="-100" + name="estate_id_lbl" + width="80"> + Estate ID: + </text> + <line_editor + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + top_delta="0" + name="estate_id" + enabled="false" + right="-10" + initial_value="unknown" + width="85" /> + <text follows="left|top" font="SansSerif" height="20" @@ -55,6 +77,39 @@ unknown </text> <text + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + top_delta="0" + right="-100" + name="grid_position_lbl" + width="80"> + Grid Position: + </text> + <line_editor + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + right="-55" + name="grid_position_x" + enabled="false" + top_delta="0" + default_text="n/a" + width="40" /> + <line_editor + follows="right|top" + font="SansSerif" + height="20" + layout="topleft" + right="-10" + name="grid_position_y" + enabled="false" + top_delta="0" + default_text="n/a" + width="40" /> + <text follows="left|top" font="SansSerif" height="20" |
