summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2025-07-03 21:25:03 +0800
committerErik Kundiman <erik@megapahit.org>2025-07-03 21:25:03 +0800
commit9dee269eacd32c48627d3fcc243104a56f021bbc (patch)
treeb6418c111051e1ccebf0553e7ff667f917ea4c8d /indra
parentfa7a4a38d8e66121116d91d947c4ec807822912e (diff)
parentbca9ba9b7940f9e32fe9dd25fb64fa4f2fb407db (diff)
Merge tag 'Second_Life_Project#bca9ba9b-glTF_Mesh_Import' into gltf_mesh_import
Diffstat (limited to 'indra')
-rw-r--r--indra/cmake/Linking.cmake2
-rw-r--r--indra/llappearance/llavatarappearance.cpp14
-rw-r--r--indra/llappearance/llavatarappearance.h4
-rw-r--r--indra/llappearance/lljointdata.h22
-rw-r--r--indra/llcharacter/llbvhloader.cpp6
-rw-r--r--indra/llcharacter/llbvhloader.h2
-rw-r--r--indra/llcharacter/llcharacter.cpp7
-rw-r--r--indra/llcharacter/llcharacter.h2
-rw-r--r--indra/llcharacter/lljoint.cpp7
-rw-r--r--indra/llcharacter/lljoint.h2
-rw-r--r--indra/llcommon/llthread.h2
-rw-r--r--indra/llfilesystem/lldir.cpp5
-rw-r--r--indra/llimage/llimagedimensionsinfo.cpp20
-rw-r--r--indra/llimage/llimagedimensionsinfo.h4
-rw-r--r--indra/llimage/llimagej2c.cpp9
-rw-r--r--indra/llimagej2coj/llimagej2coj.cpp217
-rw-r--r--indra/llimagej2coj/llimagej2coj.h2
-rw-r--r--indra/llinventory/llparcel.h102
-rw-r--r--indra/llinventory/llsettingsbase.cpp6
-rw-r--r--indra/llinventory/llsettingssky.cpp7
-rw-r--r--indra/llmath/raytrace.cpp1
-rw-r--r--indra/llmessage/patch_code.cpp1
-rw-r--r--indra/llmessage/patch_dct.cpp1
-rw-r--r--indra/llmessage/patch_idct.cpp1
-rw-r--r--indra/llplugin/llpluginprocessparent.cpp2
-rw-r--r--indra/llprimitive/lldaeloader.cpp2
-rw-r--r--indra/llprimitive/lldaeloader.h26
-rw-r--r--indra/llprimitive/llmodelloader.cpp52
-rw-r--r--indra/llprimitive/llmodelloader.h3
-rw-r--r--indra/llui/lllineeditor.cpp3
-rw-r--r--indra/llui/llscrolllistctrl.cpp2
-rw-r--r--indra/llwindow/llopenglview-objc.mm4
-rw-r--r--indra/llwindow/llwindow.cpp1
-rw-r--r--indra/llwindow/llwindow.h1
-rw-r--r--indra/llwindow/llwindowwin32.cpp21
-rw-r--r--indra/llwindow/llwindowwin32.h2
-rw-r--r--indra/newview/app_settings/settings.xml44
-rw-r--r--indra/newview/gltf/llgltfloader.cpp271
-rw-r--r--indra/newview/gltf/llgltfloader.h45
-rw-r--r--indra/newview/llagent.cpp13
-rw-r--r--indra/newview/llagentcamera.cpp10
-rw-r--r--indra/newview/llappviewer.cpp24
-rw-r--r--indra/newview/llappviewer.h6
-rw-r--r--indra/newview/llappviewerwin32.cpp23
-rw-r--r--indra/newview/llappviewerwin32.h1
-rw-r--r--indra/newview/llfloaterbvhpreview.cpp4
-rw-r--r--indra/newview/llfloaterbvhpreview.h2
-rw-r--r--indra/newview/llfloatermodelpreview.cpp2
-rw-r--r--indra/newview/llfloateruipreview.cpp5
-rwxr-xr-xindra/newview/llfloaterworldmap.cpp252
-rw-r--r--indra/newview/llfloaterworldmap.h14
-rw-r--r--indra/newview/llhudtext.cpp4
-rw-r--r--indra/newview/llinventoryfilter.cpp6
-rw-r--r--indra/newview/llinventoryfilter.h2
-rw-r--r--indra/newview/llinventoryfunctions.cpp4
-rw-r--r--indra/newview/llmodelpreview.cpp2
-rw-r--r--indra/newview/llpanelface.cpp284
-rw-r--r--indra/newview/llpanelface.h6
-rw-r--r--indra/newview/llpanelgroupbulk.cpp62
-rw-r--r--indra/newview/llpanelgroupbulkimpl.h4
-rw-r--r--indra/newview/llpanelmaininventory.cpp248
-rw-r--r--indra/newview/llpanelpermissions.cpp1
-rw-r--r--indra/newview/llpanelprofilepicks.cpp42
-rw-r--r--indra/newview/llpanelprofilepicks.h10
-rw-r--r--indra/newview/llsky.h1
-rw-r--r--indra/newview/llsprite.h2
-rw-r--r--indra/newview/llsurface.h1
-rw-r--r--indra/newview/lltoolpie.cpp141
-rw-r--r--indra/newview/lltoolpie.h16
-rw-r--r--indra/newview/llviewerdisplay.cpp63
-rwxr-xr-xindra/newview/llviewerparceloverlay.cpp74
-rw-r--r--indra/newview/llviewerparceloverlay.h13
-rwxr-xr-xindra/newview/llviewerregion.cpp1
-rw-r--r--indra/newview/llviewerstats.cpp87
-rw-r--r--indra/newview/llviewerstats.h7
-rw-r--r--indra/newview/llviewertexturelist.cpp16
-rw-r--r--indra/newview/llviewerwindow.cpp16
-rw-r--r--indra/newview/llvoavatar.cpp8
-rw-r--r--indra/newview/llvoavatar.h2
-rw-r--r--indra/newview/llvoavatarself.cpp6
-rw-r--r--indra/newview/llvoavatarself.h2
-rw-r--r--indra/newview/llvovolume.cpp11
-rw-r--r--indra/newview/llwatchdog.cpp34
-rw-r--r--indra/newview/llwatchdog.h12
-rw-r--r--indra/newview/skins/default/xui/en/floater_model_preview.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_stats.xml32
-rw-r--r--indra/newview/skins/default/xui/en/floater_world_map.xml18
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml236
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile_pick.xml20
-rw-r--r--indra/newview/skins/default/xui/en/panel_tools_texture.xml13
90 files changed, 1867 insertions, 927 deletions
diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake
index a1a24de04b..fab649fed8 100644
--- a/indra/cmake/Linking.cmake
+++ b/indra/cmake/Linking.cmake
@@ -72,7 +72,6 @@ elseif (DARWIN)
find_library(COCOA_LIBRARY Cocoa)
find_library(IOKIT_LIBRARY IOKit)
- find_library(AGL_LIBRARY AGL)
find_library(APPKIT_LIBRARY AppKit)
find_library(COREAUDIO_LIBRARY CoreAudio)
@@ -81,7 +80,6 @@ elseif (DARWIN)
${IOKIT_LIBRARY}
${COREFOUNDATION_LIBRARY}
${CARBON_LIBRARY}
- ${AGL_LIBRARY}
${APPKIT_LIBRARY}
${COREAUDIO_LIBRARY}
)
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 13bea1e5ea..dab18c240d 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -78,6 +78,7 @@ private:
std::string mName;
std::string mSupport;
std::string mAliases;
+ std::string mGroup;
bool mIsJoint;
LLVector3 mPos;
LLVector3 mEnd;
@@ -1606,6 +1607,15 @@ bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
mSupport = "base";
}
+ // Skeleton has 133 bones, but shader only allows 110 (LL_MAX_JOINTS_PER_MESH_OBJECT)
+ // Groups can be used by importer to cut out unused groups of joints
+ static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group");
+ if (!node->getFastAttributeString(group_string, mGroup))
+ {
+ LL_WARNS() << "Bone without group " << mName << LL_ENDL;
+ mGroup = "global";
+ }
+
if (mIsJoint)
{
static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot");
@@ -1683,7 +1693,11 @@ void LLAvatarSkeletonInfo::getJointMatricesAndHierarhy(
{
data.mName = bone_info->mName;
data.mJointMatrix = bone_info->getJointMatrix();
+ data.mScale = glm::vec3(bone_info->mScale[0], bone_info->mScale[1], bone_info->mScale[2]);
+ data.mRotation = bone_info->mRot;
data.mRestMatrix = parent_mat * data.mJointMatrix;
+ data.mIsJoint = bone_info->mIsJoint;
+ data.mGroup = bone_info->mGroup;
for (LLAvatarBoneInfo* child_info : bone_info->mChildren)
{
LLJointData& child_data = data.mChildren.emplace_back();
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index 2748da9a1d..84cb42056a 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -140,7 +140,7 @@ public:
LLVector3 mHeadOffset{}; // current head position
LLAvatarJoint* mRoot{ nullptr };
- typedef std::map<std::string, LLJoint*> joint_map_t;
+ typedef std::map<std::string, LLJoint*, std::less<>> joint_map_t;
joint_map_t mJointMap;
typedef std::map<std::string, LLVector3> joint_state_map_t;
@@ -153,7 +153,7 @@ public:
public:
typedef std::vector<LLAvatarJoint*> avatar_joint_list_t;
const avatar_joint_list_t& getSkeleton() { return mSkeleton; }
- typedef std::map<std::string, std::string> joint_alias_map_t;
+ typedef std::map<std::string, std::string, std::less<>> joint_alias_map_t;
const joint_alias_map_t& getJointAliases();
typedef std::map<std::string, std::string> joint_parent_map_t; // matrix plus parent
typedef std::map<std::string, glm::mat4> joint_rest_map_t;
diff --git a/indra/llappearance/lljointdata.h b/indra/llappearance/lljointdata.h
index 549f4af041..2fc26198ee 100644
--- a/indra/llappearance/lljointdata.h
+++ b/indra/llappearance/lljointdata.h
@@ -34,11 +34,33 @@ class LLJointData
{
public:
std::string mName;
+ std::string mGroup;
glm::mat4 mJointMatrix;
glm::mat4 mRestMatrix;
+ glm::vec3 mScale;
+ LLVector3 mRotation;
typedef std::vector<LLJointData> bones_t;
bones_t mChildren;
+
+ bool mIsJoint; // if not, collision_volume
+ enum SupportCategory
+ {
+ SUPPORT_BASE,
+ SUPPORT_EXTENDED
+ };
+ SupportCategory mSupport;
+ void setSupport(const std::string& support)
+ {
+ if (support == "extended")
+ {
+ mSupport = SUPPORT_EXTENDED;
+ }
+ else
+ {
+ mSupport = SUPPORT_BASE;
+ }
+ }
};
#endif //LL_LLJOINTDATA_H
diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp
index 9dace08e6f..581e9f62d5 100644
--- a/indra/llcharacter/llbvhloader.cpp
+++ b/indra/llcharacter/llbvhloader.cpp
@@ -131,7 +131,7 @@ LLQuaternion::Order bvhStringToOrder( char *str )
// LLBVHLoader()
//-----------------------------------------------------------------------------
-LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string>& joint_alias_map )
+LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string, std::less<>>& joint_alias_map )
{
reset();
errorLine = 0;
@@ -156,9 +156,9 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error
}
// Recognize all names we've been told are legal.
- for (std::map<std::string, std::string>::value_type& alias_pair : joint_alias_map)
+ for (const auto& [alias, joint] : joint_alias_map)
{
- makeTranslation( alias_pair.first , alias_pair.second );
+ makeTranslation(alias, joint);
}
char error_text[128]; /* Flawfinder: ignore */
diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h
index de31f76dd3..ae2e347ba1 100644
--- a/indra/llcharacter/llbvhloader.h
+++ b/indra/llcharacter/llbvhloader.h
@@ -227,7 +227,7 @@ class LLBVHLoader
friend class LLKeyframeMotion;
public:
// Constructor
- LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string>& joint_alias_map );
+ LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string, std::less<>>& joint_alias_map );
~LLBVHLoader();
/*
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index ecbcdb3bf5..8efcd9dd29 100644
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -77,12 +77,11 @@ LLCharacter::~LLCharacter()
//-----------------------------------------------------------------------------
// getJoint()
//-----------------------------------------------------------------------------
-LLJoint *LLCharacter::getJoint( const std::string &name )
+LLJoint* LLCharacter::getJoint(std::string_view name)
{
- LLJoint* joint = NULL;
+ LLJoint* joint = nullptr;
- LLJoint *root = getRootJoint();
- if (root)
+ if (LLJoint* root = getRootJoint())
{
joint = root->findJoint(name);
}
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index 6143ec8cd1..0046c5da7e 100644
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -76,7 +76,7 @@ public:
// get the specified joint
// default implementation does recursive search,
// subclasses may optimize/cache results.
- virtual LLJoint *getJoint( const std::string &name );
+ virtual LLJoint* getJoint(std::string_view name);
// get the position of the character
virtual LLVector3 getCharacterPosition() = 0;
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index f31aa5d4c9..405e62a38b 100644
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -242,21 +242,20 @@ LLJoint *LLJoint::getRoot()
//-----------------------------------------------------------------------------
// findJoint()
//-----------------------------------------------------------------------------
-LLJoint *LLJoint::findJoint( const std::string &name )
+LLJoint* LLJoint::findJoint(std::string_view name)
{
if (name == getName())
return this;
for (LLJoint* joint : mChildren)
{
- LLJoint *found = joint->findJoint(name);
- if (found)
+ if (LLJoint* found = joint->findJoint(name))
{
return found;
}
}
- return NULL;
+ return nullptr;
}
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index 763c1e3865..b58dc797f8 100644
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -222,7 +222,7 @@ public:
LLJoint *getRoot();
// search for child joints by name
- LLJoint *findJoint( const std::string &name );
+ LLJoint* findJoint(std::string_view name);
// add/remove children
void addChild( LLJoint *joint );
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 4194e0014d..21264351e5 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -68,7 +68,7 @@ public:
// Called from MAIN THREAD.
void pause();
void unpause();
- bool isPaused() { return isStopped() || mPaused; }
+ bool isPaused() const { return isStopped() || mPaused; }
// Cause the thread to wake up and check its condition
void wake();
diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp
index d12080aafa..918bb0d117 100644
--- a/indra/llfilesystem/lldir.cpp
+++ b/indra/llfilesystem/lldir.cpp
@@ -110,9 +110,10 @@ std::vector<std::string> LLDir::getFilesInDir(const std::string &dirname)
std::vector<std::string> v;
- if (exists(p))
+ boost::system::error_code ec;
+ if (exists(p, ec) && !ec.failed())
{
- if (is_directory(p))
+ if (is_directory(p, ec) && !ec.failed())
{
boost::filesystem::directory_iterator end_iter;
for (boost::filesystem::directory_iterator dir_itr(p);
diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp
index d4efbcfad2..c896d60c85 100644
--- a/indra/llimage/llimagedimensionsinfo.cpp
+++ b/indra/llimage/llimagedimensionsinfo.cpp
@@ -75,7 +75,7 @@ bool LLImageDimensionsInfo::load(const std::string& src_filename,U32 codec)
bool LLImageDimensionsInfo::getImageDimensionsBmp()
{
// Make sure the file is long enough.
- const S32 DATA_LEN = 26; // BMP header (14) + DIB header size (4) + width (4) + height (4)
+ constexpr S32 DATA_LEN = 26; // BMP header (14) + DIB header size (4) + width (4) + height (4)
if (!checkFileLength(DATA_LEN))
{
LL_WARNS() << "Premature end of file" << LL_ENDL;
@@ -105,7 +105,7 @@ bool LLImageDimensionsInfo::getImageDimensionsBmp()
bool LLImageDimensionsInfo::getImageDimensionsTga()
{
- const S32 TGA_FILE_HEADER_SIZE = 12;
+ constexpr S32 TGA_FILE_HEADER_SIZE = 12;
// Make sure the file is long enough.
if (!checkFileLength(TGA_FILE_HEADER_SIZE + 1 /* width */ + 1 /* height */))
@@ -124,7 +124,7 @@ bool LLImageDimensionsInfo::getImageDimensionsTga()
bool LLImageDimensionsInfo::getImageDimensionsPng()
{
- const S32 PNG_MAGIC_SIZE = 8;
+ constexpr S32 PNG_MAGIC_SIZE = 8;
// Make sure the file is long enough.
if (!checkFileLength(PNG_MAGIC_SIZE + 8 + sizeof(S32) * 2 /* width, height */))
@@ -134,7 +134,7 @@ bool LLImageDimensionsInfo::getImageDimensionsPng()
}
// Read PNG signature.
- const U8 png_magic[PNG_MAGIC_SIZE] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
+ constexpr U8 png_magic[PNG_MAGIC_SIZE] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
U8 signature[PNG_MAGIC_SIZE];
mInfile.read((void*)signature, PNG_MAGIC_SIZE);
@@ -166,34 +166,36 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
{
sJpegErrorEncountered = false;
clean();
- FILE *fp = LLFile::fopen(mSrcFilename, "rb");
- if (fp == NULL)
+ FILE* fp = LLFile::fopen(mSrcFilename, "rb");
+ if (!fp)
{
setLastError("Unable to open file for reading", mSrcFilename);
return false;
}
/* Make sure this is a JPEG file. */
- const size_t JPEG_MAGIC_SIZE = 2;
- const U8 jpeg_magic[JPEG_MAGIC_SIZE] = {0xFF, 0xD8};
+ constexpr size_t JPEG_MAGIC_SIZE = 2;
+ constexpr U8 jpeg_magic[JPEG_MAGIC_SIZE] = {0xFF, 0xD8};
U8 signature[JPEG_MAGIC_SIZE];
if (fread(signature, sizeof(signature), 1, fp) != 1)
{
LL_WARNS() << "Premature end of file" << LL_ENDL;
+ fclose(fp);
return false;
}
if (memcmp(signature, jpeg_magic, JPEG_MAGIC_SIZE) != 0)
{
LL_WARNS() << "Not a JPEG" << LL_ENDL;
mWarning = "texture_load_format_error";
+ fclose(fp);
return false;
}
fseek(fp, 0, SEEK_SET); // go back to start of the file
/* Init jpeg */
jpeg_error_mgr jerr;
- jpeg_decompress_struct cinfo;
+ jpeg_decompress_struct cinfo{};
cinfo.err = jpeg_std_error(&jerr);
// Call our function instead of exit() if Libjpeg encounters an error.
// This is done to avoid crash in this case (STORM-472).
diff --git a/indra/llimage/llimagedimensionsinfo.h b/indra/llimage/llimagedimensionsinfo.h
index 681d66ae4e..4870f2e815 100644
--- a/indra/llimage/llimagedimensionsinfo.h
+++ b/indra/llimage/llimagedimensionsinfo.h
@@ -38,7 +38,7 @@ class LLImageDimensionsInfo
{
public:
LLImageDimensionsInfo():
- mData(NULL)
+ mData(nullptr)
,mHeight(0)
,mWidth(0)
{}
@@ -67,7 +67,7 @@ protected:
{
mInfile.close();
delete[] mData;
- mData = NULL;
+ mData = nullptr;
mWidth = 0;
mHeight = 0;
}
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index aa161709a1..5a941dc958 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -281,10 +281,11 @@ S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 r
S32 height = (h > 0) ? h : 2048;
S32 max_dimension = llmax(width, height); // Find largest dimension
S32 block_area = MAX_BLOCK_SIZE * MAX_BLOCK_SIZE; // Calculated initial block area from established max block size (currently 64)
- block_area *= llmax((max_dimension / MAX_BLOCK_SIZE / max_components), 1); // Adjust initial block area by ratio of largest dimension to block size per component
- S32 totalbytes = (S32) (block_area * max_components * precision); // First block layer computed before loop without compression rate
- S32 block_layers = 1; // Start at layer 1 since first block layer is computed outside loop
- while (block_layers < 6) // Walk five layers for the five discards in JPEG2000
+ S32 max_layers = (S32)llmax(llround(log2f((float)max_dimension) - log2f((float)MAX_BLOCK_SIZE)), 4); // Find number of powers of two between extents and block size to a minimum of 4
+ block_area *= llmax(max_layers, 1); // Adjust initial block area by max number of layers
+ S32 totalbytes = (S32) (MIN_LAYER_SIZE * max_components * precision); // Start estimation with a minimum reasonable size
+ S32 block_layers = 0;
+ while (block_layers <= max_layers) // Walk the layers
{
if (block_layers <= (5 - discard_level)) // Walk backwards from discard 5 to required discard layer.
totalbytes += (S32) (block_area * max_components * precision * rate); // Add each block layer reduced by assumed compression rate
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index 04b527d783..717b0a6e86 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -32,8 +32,6 @@
#include <openjpeg-2.5/event.h>
#include <openjpeg-2.5/cio.h>
-#define MAX_ENCODED_DISCARD_LEVELS 5
-
// Factory function: see declaration in llimagej2c.cpp
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
{
@@ -132,73 +130,96 @@ static void opj_error(const char* msg, void* user_data)
static OPJ_SIZE_T opj_read(void * buffer, OPJ_SIZE_T bytes, void* user_data)
{
- llassert(user_data);
+ llassert(user_data && buffer);
+
JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
- OPJ_SIZE_T remainder = (jpeg_codec->size - jpeg_codec->offset);
- if (remainder <= 0)
+
+ if (jpeg_codec->offset < 0 || static_cast<OPJ_SIZE_T>(jpeg_codec->offset) >= jpeg_codec->size)
{
jpeg_codec->offset = jpeg_codec->size;
- // Indicate end of stream (hacky?)
- return (OPJ_OFF_T)-1;
+ return static_cast<OPJ_SIZE_T>(-1); // Indicate EOF
}
- OPJ_SIZE_T to_read = llclamp(U32(bytes), U32(0), U32(remainder));
+
+ OPJ_SIZE_T remainder = jpeg_codec->size - static_cast<OPJ_SIZE_T>(jpeg_codec->offset);
+ OPJ_SIZE_T to_read = (bytes < remainder) ? bytes : remainder;
+
memcpy(buffer, jpeg_codec->buffer + jpeg_codec->offset, to_read);
jpeg_codec->offset += to_read;
+
return to_read;
}
static OPJ_SIZE_T opj_write(void * buffer, OPJ_SIZE_T bytes, void* user_data)
{
- llassert(user_data);
+ llassert(user_data && buffer);
+
JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
- OPJ_SIZE_T remainder = jpeg_codec->size - jpeg_codec->offset;
- if (remainder < bytes)
+ OPJ_OFF_T required_offset = jpeg_codec->offset + static_cast<OPJ_OFF_T>(bytes);
+
+ // Overflow check
+ if (required_offset < jpeg_codec->offset)
+ return 0; // Overflow detected
+
+ // Resize if needed (exponential growth)
+ if (required_offset > static_cast<OPJ_OFF_T>(jpeg_codec->size))
{
- OPJ_SIZE_T new_size = jpeg_codec->size + (bytes - remainder);
+ OPJ_SIZE_T new_size = jpeg_codec->size ? jpeg_codec->size : 1024;
+ while (required_offset > static_cast<OPJ_OFF_T>(new_size))
+ new_size *= 2;
+
+ const OPJ_SIZE_T MAX_BUFFER_SIZE = 512 * 1024 * 1024; // 512 MB, increase if needed
+ if (new_size > MAX_BUFFER_SIZE) return 0;
+
U8* new_buffer = (U8*)ll_aligned_malloc_16(new_size);
- memcpy(new_buffer, jpeg_codec->buffer, jpeg_codec->offset);
- U8* old_buffer = jpeg_codec->buffer;
+ if (!new_buffer) return 0; // Allocation failed
+
+ if (jpeg_codec->offset > 0)
+ memcpy(new_buffer, jpeg_codec->buffer, static_cast<size_t>(jpeg_codec->offset));
+
+ ll_aligned_free_16(jpeg_codec->buffer);
jpeg_codec->buffer = new_buffer;
- ll_aligned_free_16(old_buffer);
jpeg_codec->size = new_size;
}
- memcpy(jpeg_codec->buffer + jpeg_codec->offset, buffer, bytes);
- jpeg_codec->offset += bytes;
+
+ memcpy(jpeg_codec->buffer + jpeg_codec->offset, buffer, static_cast<size_t>(bytes));
+ jpeg_codec->offset = required_offset;
return bytes;
}
static OPJ_OFF_T opj_skip(OPJ_OFF_T bytes, void* user_data)
{
+ llassert(user_data);
JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
- jpeg_codec->offset += bytes;
- if (jpeg_codec->offset > (OPJ_OFF_T)jpeg_codec->size)
- {
- jpeg_codec->offset = jpeg_codec->size;
- // Indicate end of stream
- return (OPJ_OFF_T)-1;
- }
+ OPJ_OFF_T new_offset = jpeg_codec->offset + bytes;
- if (jpeg_codec->offset < 0)
+ if (new_offset < 0 || new_offset > static_cast<OPJ_OFF_T>(jpeg_codec->size))
{
- // Shouldn't be possible?
- jpeg_codec->offset = 0;
+ // Clamp and indicate EOF or error
+ jpeg_codec->offset = llclamp<OPJ_OFF_T>(new_offset, 0, static_cast<OPJ_OFF_T>(jpeg_codec->size));
return (OPJ_OFF_T)-1;
}
+ jpeg_codec->offset = new_offset;
return bytes;
}
-static OPJ_BOOL opj_seek(OPJ_OFF_T bytes, void * user_data)
+static OPJ_BOOL opj_seek(OPJ_OFF_T offset, void * user_data)
{
+ llassert(user_data);
JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
- jpeg_codec->offset = bytes;
- jpeg_codec->offset = llclamp(U32(jpeg_codec->offset), U32(0), U32(jpeg_codec->size));
+
+ if (offset < 0 || offset > static_cast<OPJ_OFF_T>(jpeg_codec->size))
+ return OPJ_FALSE;
+
+ jpeg_codec->offset = offset;
return OPJ_TRUE;
}
static void opj_free_user_data(void * user_data)
{
+ llassert(user_data);
+
JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
// Don't free, data is managed externally
jpeg_codec->buffer = nullptr;
@@ -208,14 +229,54 @@ static void opj_free_user_data(void * user_data)
static void opj_free_user_data_write(void * user_data)
{
+ llassert(user_data);
+
JPEG2KBase* jpeg_codec = static_cast<JPEG2KBase*>(user_data);
// Free, data was allocated here
- ll_aligned_free_16(jpeg_codec->buffer);
- jpeg_codec->buffer = nullptr;
+ if (jpeg_codec->buffer)
+ {
+ ll_aligned_free_16(jpeg_codec->buffer);
+ jpeg_codec->buffer = nullptr;
+ }
jpeg_codec->size = 0;
jpeg_codec->offset = 0;
}
+/**
+ * Estimates the number of layers necessary depending on the image surface (w x h)
+ */
+static U32 estimate_num_layers(U32 surface)
+{
+ if (surface <= 1024) return 2; // Tiny (≤32×32)
+ else if (surface <= 16384) return 3; // Small (≤128×128)
+ else if (surface <= 262144) return 4; // Medium (≤512×512)
+ else if (surface <= 1048576) return 5; // Up to ~1MP
+ else return 6; // Up to ~1.5–2MP
+}
+
+/**
+ * Sets the parameters.tcp_rates according to the number of layers and a last tcp_rate value (which equals to the final compression ratio).
+ *
+ * Example for 6 layers:
+ *
+ * i = 5, parameters.tcp_rates[6 - 1 - 5] = 8.0f * (1 << (5 << 1)) = 8192 // Layer 5 (lowest quality)
+ * i = 4, parameters.tcp_rates[6 - 1 - 4] = 8.0f * (1 << (4 << 1)) = 2048 // Layer 4
+ * i = 3, parameters.tcp_rates[6 - 1 - 3] = 8.0f * (1 << (3 << 1)) = 512 // Layer 3
+ * i = 2, parameters.tcp_rates[6 - 1 - 2] = 8.0f * (1 << (2 << 1)) = 128 // Layer 2
+ * i = 1, parameters.tcp_rates[6 - 1 - 1] = 8.0f * (1 << (1 << 1)) = 32 // Layer 1
+ * i = 0, parameters.tcp_rates[6 - 1 - 0] = 8.0f * (1 << (0 << 1)) = 8 // Layer 0 (highest quality)
+ *
+ */
+static void set_tcp_rates(opj_cparameters_t* parameters, U32 num_layers = 1, F32 last_tcp_rate = LAST_TCP_RATE)
+{
+ parameters->tcp_numlayers = num_layers;
+
+ for (int i = num_layers - 1; i >= 0; i--)
+ {
+ parameters->tcp_rates[num_layers - 1 - i] = last_tcp_rate * static_cast<F32>(1 << (i << 1));
+ }
+}
+
class JPEG2KDecode : public JPEG2KBase
{
public:
@@ -430,15 +491,16 @@ public:
opj_set_default_encoder_parameters(&parameters);
parameters.cod_format = OPJ_CODEC_J2K;
- parameters.cp_disto_alloc = 1;
+ parameters.prog_order = OPJ_RLCP; // should be the default, but, just in case
+ parameters.cp_disto_alloc = 1; // enable rate allocation by distortion
+ parameters.max_cs_size = 0; // do not cap max size because we're using tcp_rates and also irrelevant with lossless.
if (reversible)
{
- parameters.max_cs_size = 0; // do not limit size for reversible compression
parameters.irreversible = 0; // should be the default, but, just in case
parameters.tcp_numlayers = 1;
/* documentation seems to be wrong, should be 0.0f for lossless, not 1.0f
- see https://github.com/uclouvain/openjpeg/blob/39e8c50a2f9bdcf36810ee3d41bcbf1cc78968ae/src/lib/openjp2/j2k.c#L7755
+ see https://github.com/uclouvain/openjpeg/blob/e7453e398b110891778d8da19209792c69ca7169/src/lib/openjp2/j2k.c#L7817
*/
parameters.tcp_rates[0] = 0.0f;
}
@@ -493,53 +555,22 @@ public:
encoder = opj_create_compress(OPJ_CODEC_J2K);
- parameters.tcp_mct = (image->numcomps >= 3) ? 1 : 0;
- parameters.cod_format = OPJ_CODEC_J2K;
- parameters.prog_order = OPJ_RLCP;
- parameters.cp_disto_alloc = 1;
+ parameters.tcp_mct = (image->numcomps >= 3) ? 1 : 0; // no color transform for RGBA images
+
// if not lossless compression, computes tcp_numlayers and max_cs_size depending on the image dimensions
- if( parameters.irreversible ) {
+ if( parameters.irreversible )
+ {
// computes a number of layers
U32 surface = rawImageIn.getWidth() * rawImageIn.getHeight();
- U32 nb_layers = 1;
- U32 s = 64*64;
- while (surface > s)
- {
- nb_layers++;
- s *= 4;
- }
- nb_layers = llclamp(nb_layers, 1, 6);
- parameters.tcp_numlayers = nb_layers;
- parameters.tcp_rates[nb_layers - 1] = (U32)(1.f / DEFAULT_COMPRESSION_RATE); // 1:8 by default
+ // gets the necessary number of layers
+ U32 nb_layers = estimate_num_layers(surface);
- // for each subsequent layer, computes its rate and adds surface * numcomps * 1/rate to the max_cs_size
- U32 max_cs_size = (U32)(surface * image->numcomps * DEFAULT_COMPRESSION_RATE);
- U32 multiplier;
- for (int i = nb_layers - 2; i >= 0; i--)
- {
- if( i == nb_layers - 2 )
- {
- multiplier = 15;
- }
- else if( i == nb_layers - 3 )
- {
- multiplier = 4;
- }
- else
- {
- multiplier = 2;
- }
- parameters.tcp_rates[i] = parameters.tcp_rates[i + 1] * multiplier;
- max_cs_size += (U32)(surface * image->numcomps * (1 / parameters.tcp_rates[i]));
- }
-
- //ensure that we have at least a minimal size
- max_cs_size = llmax(max_cs_size, (U32)FIRST_PACKET_SIZE);
+ // fills parameters.tcp_rates and updates parameters.tcp_numlayers
+ set_tcp_rates(&parameters, nb_layers, LAST_TCP_RATE);
- parameters.max_cs_size = max_cs_size;
}
if (!opj_setup_encoder(encoder, &parameters, image))
@@ -551,7 +582,20 @@ public:
opj_set_warning_handler(encoder, opj_warn, this);
opj_set_error_handler(encoder, opj_error, this);
- U32 tile_count = (rawImageIn.getWidth() >> 6) * (rawImageIn.getHeight() >> 6);
+ U32 width_tiles = (rawImageIn.getWidth() >> 6);
+ U32 height_tiles = (rawImageIn.getHeight() >> 6);
+
+ // Allow images with a width or height that are MIN_IMAGE_SIZE <= x < 64
+ if (width_tiles == 0 && (rawImageIn.getWidth() >= MIN_IMAGE_SIZE))
+ {
+ width_tiles = 1;
+ }
+ if (height_tiles == 0 && (rawImageIn.getHeight() >= MIN_IMAGE_SIZE))
+ {
+ height_tiles = 1;
+ }
+
+ U32 tile_count = width_tiles * height_tiles;
U32 data_size_guess = tile_count * TILE_SIZE;
// will be freed in opj_free_user_data_write
@@ -566,7 +610,7 @@ public:
opj_stream_destroy(stream);
}
- stream = opj_stream_create(data_size_guess, false);
+ stream = opj_stream_create(data_size_guess, OPJ_FALSE);
if (!stream)
{
return false;
@@ -607,17 +651,15 @@ public:
void setImage(const LLImageRaw& raw)
{
- opj_image_cmptparm_t cmptparm[MAX_ENCODED_DISCARD_LEVELS];
- memset(&cmptparm[0], 0, MAX_ENCODED_DISCARD_LEVELS * sizeof(opj_image_cmptparm_t));
-
S32 numcomps = raw.getComponents();
- S32 width = raw.getWidth();
- S32 height = raw.getHeight();
+ S32 width = raw.getWidth();
+ S32 height = raw.getHeight();
+
+ std::vector<opj_image_cmptparm_t> cmptparm(numcomps);
for (S32 c = 0; c < numcomps; c++)
{
- cmptparm[c].prec = 8;
- cmptparm[c].bpp = 8;
+ cmptparm[c].prec = 8; // replaces .bpp
cmptparm[c].sgnd = 0;
cmptparm[c].dx = parameters.subsampling_dx;
cmptparm[c].dy = parameters.subsampling_dy;
@@ -625,7 +667,7 @@ public:
cmptparm[c].h = height;
}
- image = opj_image_create(numcomps, &cmptparm[0], OPJ_CLRSPC_SRGB);
+ image = opj_image_create(numcomps, cmptparm.data(), OPJ_CLRSPC_SRGB);
image->x1 = width;
image->y1 = height;
@@ -637,7 +679,7 @@ public:
{
for (S32 x = 0; x < width; x++)
{
- const U8 *pixel = src_datap + (y*width + x) * numcomps;
+ const U8 *pixel = src_datap + (y * width + x) * numcomps;
for (S32 c = 0; c < numcomps; c++)
{
image->comps[c].data[i] = *pixel;
@@ -857,12 +899,11 @@ bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con
{
JPEG2KEncode encode(comment_text, reversible);
bool encoded = encode.encode(raw_image, base);
- if (encoded)
+ if (!encoded)
{
- LL_WARNS() << "Openjpeg encoding implementation isn't complete, returning false" << LL_ENDL;
+ LL_WARNS() << "Openjpeg encoding was unsuccessful, returning false" << LL_ENDL;
}
return encoded;
- //return false;
}
bool LLImageJ2COJ::getMetadata(LLImageJ2C &base)
diff --git a/indra/llimagej2coj/llimagej2coj.h b/indra/llimagej2coj/llimagej2coj.h
index 498502451a..da49597302 100644
--- a/indra/llimagej2coj/llimagej2coj.h
+++ b/indra/llimagej2coj/llimagej2coj.h
@@ -29,6 +29,8 @@
#include "llimagej2c.h"
+const F32 LAST_TCP_RATE = 1.f/DEFAULT_COMPRESSION_RATE; // should be 8, giving a 1:8 ratio
+
class LLImageJ2COJ : public LLImageJ2CImpl
{
public:
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index 759638b956..ac50b428bf 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -37,98 +37,98 @@
#include "llsettingsdaycycle.h"
// Grid out of which parcels taken is stepped every 4 meters.
-const F32 PARCEL_GRID_STEP_METERS = 4.f;
+constexpr F32 PARCEL_GRID_STEP_METERS = 4.f;
// Area of one "square" of parcel
-const S32 PARCEL_UNIT_AREA = 16;
+constexpr S32 PARCEL_UNIT_AREA = 16;
// Height _above_ground_ that parcel boundary ends
-const F32 PARCEL_HEIGHT = 50.f;
+constexpr F32 PARCEL_HEIGHT = 50.f;
//Height above ground which parcel boundries exist for explicitly banned avatars
-const F32 BAN_HEIGHT = 5000.f;
+constexpr F32 BAN_HEIGHT = 5000.f;
// Maximum number of entries in an access list
-const S32 PARCEL_MAX_ACCESS_LIST = 300;
+constexpr S32 PARCEL_MAX_ACCESS_LIST = 300;
//Maximum number of entires in an update packet
//for access/ban lists.
-const F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f;
+constexpr F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f;
// Maximum number of experiences
-const S32 PARCEL_MAX_EXPERIENCE_LIST = 24;
+constexpr S32 PARCEL_MAX_EXPERIENCE_LIST = 24;
// Weekly charge for listing a parcel in the directory
-const S32 PARCEL_DIRECTORY_FEE = 30;
+constexpr S32 PARCEL_DIRECTORY_FEE = 30;
-const S32 PARCEL_PASS_PRICE_DEFAULT = 10;
-const F32 PARCEL_PASS_HOURS_DEFAULT = 1.f;
+constexpr S32 PARCEL_PASS_PRICE_DEFAULT = 10;
+constexpr F32 PARCEL_PASS_HOURS_DEFAULT = 1.f;
// Number of "chunks" in which parcel overlay data is sent
// Chunk 0 = southern rows, entire width
-const S32 PARCEL_OVERLAY_CHUNKS = 4;
+constexpr S32 PARCEL_OVERLAY_CHUNKS = 4;
// Bottom three bits are a color index for the land overlay
-const U8 PARCEL_COLOR_MASK = 0x07;
-const U8 PARCEL_PUBLIC = 0x00;
-const U8 PARCEL_OWNED = 0x01;
-const U8 PARCEL_GROUP = 0x02;
-const U8 PARCEL_SELF = 0x03;
-const U8 PARCEL_FOR_SALE = 0x04;
-const U8 PARCEL_AUCTION = 0x05;
+constexpr U8 PARCEL_COLOR_MASK = 0x07;
+constexpr U8 PARCEL_PUBLIC = 0x00;
+constexpr U8 PARCEL_OWNED = 0x01;
+constexpr U8 PARCEL_GROUP = 0x02;
+constexpr U8 PARCEL_SELF = 0x03;
+constexpr U8 PARCEL_FOR_SALE = 0x04;
+constexpr U8 PARCEL_AUCTION = 0x05;
// unused 0x06
// unused 0x07
// flag, unused 0x08
-const U8 PARCEL_HIDDENAVS = 0x10; // avatars not visible outside of parcel. Used for 'see avs' feature, but must be off for compatibility
-const U8 PARCEL_SOUND_LOCAL = 0x20;
-const U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge
-const U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge
+constexpr U8 PARCEL_HIDDENAVS = 0x10; // avatars not visible outside of parcel. Used for 'see avs' feature, but must be off for compatibility
+constexpr U8 PARCEL_SOUND_LOCAL = 0x20;
+constexpr U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge
+constexpr U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge
// Transmission results for parcel properties
-const S32 PARCEL_RESULT_NO_DATA = -1;
-const S32 PARCEL_RESULT_SUCCESS = 0; // got exactly one parcel
-const S32 PARCEL_RESULT_MULTIPLE = 1; // got multiple parcels
-
-const S32 SELECTED_PARCEL_SEQ_ID = -10000;
-const S32 COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID = -20000;
-const S32 COLLISION_BANNED_PARCEL_SEQ_ID = -30000;
-const S32 COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID = -40000;
-const S32 HOVERED_PARCEL_SEQ_ID = -50000;
-
-const U32 RT_NONE = 0x1 << 0;
-const U32 RT_OWNER = 0x1 << 1;
-const U32 RT_GROUP = 0x1 << 2;
-const U32 RT_OTHER = 0x1 << 3;
-const U32 RT_LIST = 0x1 << 4;
-const U32 RT_SELL = 0x1 << 5;
-
-const S32 INVALID_PARCEL_ID = -1;
-
-const S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2;
+constexpr S32 PARCEL_RESULT_NO_DATA = -1;
+constexpr S32 PARCEL_RESULT_SUCCESS = 0; // got exactly one parcel
+constexpr S32 PARCEL_RESULT_MULTIPLE = 1; // got multiple parcels
+
+constexpr S32 SELECTED_PARCEL_SEQ_ID = -10000;
+constexpr S32 COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID = -20000;
+constexpr S32 COLLISION_BANNED_PARCEL_SEQ_ID = -30000;
+constexpr S32 COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID = -40000;
+constexpr S32 HOVERED_PARCEL_SEQ_ID = -50000;
+
+constexpr U32 RT_NONE = 0x1 << 0;
+constexpr U32 RT_OWNER = 0x1 << 1;
+constexpr U32 RT_GROUP = 0x1 << 2;
+constexpr U32 RT_OTHER = 0x1 << 3;
+constexpr U32 RT_LIST = 0x1 << 4;
+constexpr U32 RT_SELL = 0x1 << 5;
+
+constexpr S32 INVALID_PARCEL_ID = -1;
+
+constexpr S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2;
// if Region settings are used, parcel env. version is -1
-const S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1;
+constexpr S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1;
// Timeouts for parcels
// default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
-const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
+constexpr U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
// ***** TESTING is 10 minutes
//const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(600000000);
// group is 60 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 5184000000000
-const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
+constexpr U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
// ***** TESTING is 10 minutes
//const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(600000000);
// default sale timeout is 2 days -> 172800000000
-const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
+constexpr U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
// ***** TESTING is 10 minutes
//const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(600000000);
// more grace period extensions.
-const U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
+constexpr U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
// if more than 100,000s before sale revert, and no extra extension
// has been given, go ahead and extend it more. That's about 1.2 days.
-const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
+constexpr S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
@@ -250,9 +250,9 @@ public:
void setMediaURL(const std::string& url);
void setMediaType(const std::string& type);
void setMediaDesc(const std::string& desc);
- void setMediaID(const LLUUID& id) { mMediaID = id; }
- void setMediaAutoScale ( U8 flagIn ) { mMediaAutoScale = flagIn; }
- void setMediaLoop (U8 loop) { mMediaLoop = loop; }
+ void setMediaID(const LLUUID& id) { mMediaID = id; }
+ void setMediaAutoScale ( U8 flagIn ) { mMediaAutoScale = flagIn; }
+ void setMediaLoop(U8 loop) { mMediaLoop = loop; }
void setMediaWidth(S32 width);
void setMediaHeight(S32 height);
void setMediaCurrentURL(const std::string& url);
diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp
index 97979d64e3..5bd490974b 100644
--- a/indra/llinventory/llsettingsbase.cpp
+++ b/indra/llinventory/llsettingsbase.cpp
@@ -361,14 +361,12 @@ LLSD LLSettingsBase::interpolateSDValue(const std::string& key_name, const LLSD
new_array = q.getValue();
}
else
- { // TODO: We could expand this to inspect the type and do a deep lerp based on type.
- // for now assume a heterogeneous array of reals.
+ {
size_t len = std::max(value.size(), other_value.size());
for (size_t i = 0; i < len; ++i)
{
-
- new_array[i] = lerp((F32)value[i].asReal(), (F32)other_value[i].asReal(), (F32)mix);
+ new_array[i] = interpolateSDValue(key_name, value[i], other_value[i], defaults, mix, skip, slerps);
}
}
diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index ad37b08df7..1e5a2280e3 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -658,15 +658,16 @@ void LLSettingsSky::blend(LLSettingsBase::ptr_t &end, F64 blendf)
mHasLegacyHaze |= lerp_legacy_float(mHazeDensity, mLegacyHazeDensity, other->mHazeDensity, other->mLegacyHazeDensity, 0.7f, (F32)blendf);
mHasLegacyHaze |= lerp_legacy_float(mDistanceMultiplier, mLegacyDistanceMultiplier, other->mDistanceMultiplier, other->mLegacyDistanceMultiplier, 0.8f, (F32)blendf);
mHasLegacyHaze |= lerp_legacy_float(mDensityMultiplier, mLegacyDensityMultiplier, other->mDensityMultiplier, other->mLegacyDensityMultiplier, 0.0001f, (F32)blendf);
+ mHasLegacyHaze |= lerp_legacy_color(mAmbientColor, mLegacyAmbientColor, other->mAmbientColor, other->mLegacyAmbientColor, LLColor3(0.25f, 0.25f, 0.25f), (F32)blendf);
mHasLegacyHaze |= lerp_legacy_color(mBlueHorizon, mLegacyBlueHorizon, other->mBlueHorizon, other->mLegacyBlueHorizon, LLColor3(0.4954f, 0.4954f, 0.6399f), (F32)blendf);
mHasLegacyHaze |= lerp_legacy_color(mBlueDensity, mLegacyBlueDensity, other->mBlueDensity, other->mLegacyBlueDensity, LLColor3(0.2447f, 0.4487f, 0.7599f), (F32)blendf);
parammapping_t defaults = other->getParameterMap();
stringset_t skip = getSkipInterpolateKeys();
stringset_t slerps = getSlerpKeys();
- mAbsorptionConfigs = interpolateSDMap(mAbsorptionConfigs, other->mAbsorptionConfigs, defaults, blendf, skip, slerps);
- mMieConfigs = interpolateSDMap(mMieConfigs, other->mMieConfigs, defaults, blendf, skip, slerps);
- mRayleighConfigs = interpolateSDMap(mRayleighConfigs, other->mRayleighConfigs, defaults, blendf, skip, slerps);
+ mAbsorptionConfigs = interpolateSDValue("absorption_config", mAbsorptionConfigs, other->mAbsorptionConfigs, defaults, blendf, skip, slerps);
+ mMieConfigs = interpolateSDValue("mie_config", mMieConfigs, other->mMieConfigs, defaults, blendf, skip, slerps);
+ mRayleighConfigs = interpolateSDValue("rayleigh_config", mRayleighConfigs, other->mRayleighConfigs, defaults, blendf, skip, slerps);
setDirtyFlag(true);
setReplaced();
diff --git a/indra/llmath/raytrace.cpp b/indra/llmath/raytrace.cpp
index 893bf1fc70..c0b5f48f2d 100644
--- a/indra/llmath/raytrace.cpp
+++ b/indra/llmath/raytrace.cpp
@@ -27,7 +27,6 @@
#include "linden_common.h"
#include "math.h"
-//#include "vmath.h"
#include "v3math.h"
#include "llquaternion.h"
#include "m3math.h"
diff --git a/indra/llmessage/patch_code.cpp b/indra/llmessage/patch_code.cpp
index 489b6ce6a6..9f9f4c852a 100644
--- a/indra/llmessage/patch_code.cpp
+++ b/indra/llmessage/patch_code.cpp
@@ -27,7 +27,6 @@
#include "linden_common.h"
#include "llmath.h"
-//#include "vmath.h"
#include "v3math.h"
#include "patch_dct.h"
#include "patch_code.h"
diff --git a/indra/llmessage/patch_dct.cpp b/indra/llmessage/patch_dct.cpp
index 728fe84537..e74e5fd459 100644
--- a/indra/llmessage/patch_dct.cpp
+++ b/indra/llmessage/patch_dct.cpp
@@ -27,7 +27,6 @@
#include "linden_common.h"
#include "llmath.h"
-//#include "vmath.h"
#include "v3math.h"
#include "patch_dct.h"
diff --git a/indra/llmessage/patch_idct.cpp b/indra/llmessage/patch_idct.cpp
index 5483cf98c0..4bcc439917 100644
--- a/indra/llmessage/patch_idct.cpp
+++ b/indra/llmessage/patch_idct.cpp
@@ -27,7 +27,6 @@
#include "linden_common.h"
#include "llmath.h"
-//#include "vmath.h"
#include "v3math.h"
#include "patch_dct.h"
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index 9e4640d20a..63f1de8d6a 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -578,7 +578,7 @@ void LLPluginProcessParent::idle(void)
params.args.add("-e");
params.args.add("tell application \"Terminal\"");
params.args.add("-e");
- params.args.add(STRINGIZE("set win to do script \"lldb -pid "
+ params.args.add(STRINGIZE("set win to do script \"lldb -p "
<< mProcess->getProcessID() << "\""));
params.args.add("-e");
params.args.add("do script \"continue\" in win");
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 0759447902..eadb052b38 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -880,7 +880,7 @@ LLDAELoader::LLDAELoader(
void* opaque_userdata,
JointTransformMap& jointTransformMap,
JointNameSet& jointsFromNodes,
- std::map<std::string, std::string>& jointAliasMap,
+ std::map<std::string, std::string, std::less<>>& jointAliasMap,
U32 maxJointsPerMesh,
U32 modelLimit,
bool preprocess)
diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h
index 92152fb8b8..b3e4667fd7 100644
--- a/indra/llprimitive/lldaeloader.h
+++ b/indra/llprimitive/lldaeloader.h
@@ -49,19 +49,19 @@ public:
dae_model_map mModelsMap;
LLDAELoader(
- std::string filename,
- S32 lod,
- LLModelLoader::load_callback_t load_cb,
- LLModelLoader::joint_lookup_func_t joint_lookup_func,
- LLModelLoader::texture_load_func_t texture_load_func,
- LLModelLoader::state_callback_t state_cb,
- void* opaque_userdata,
- JointTransformMap& jointTransformMap,
- JointNameSet& jointsFromNodes,
- std::map<std::string, std::string>& jointAliasMap,
- U32 maxJointsPerMesh,
- U32 modelLimit,
- bool preprocess);
+ std::string filename,
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void* opaque_userdata,
+ JointTransformMap& jointTransformMap,
+ JointNameSet& jointsFromNodes,
+ std::map<std::string, std::string, std::less<>>& jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit,
+ bool preprocess);
virtual ~LLDAELoader() ;
virtual bool OpenFile(const std::string& filename);
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp
index dee39175f8..55f1338dab 100644
--- a/indra/llprimitive/llmodelloader.cpp
+++ b/indra/llprimitive/llmodelloader.cpp
@@ -468,6 +468,58 @@ bool LLModelLoader::isRigSuitableForJointPositionUpload( const std::vector<std::
return true;
}
+void LLModelLoader::dumpDebugData()
+{
+ std::string log_file = mFilename + "_importer.txt";
+ LLStringUtil::toLower(log_file);
+ llofstream file;
+ file.open(log_file.c_str());
+ if (!file)
+ {
+ LL_WARNS() << "dumpDebugData failed to open file " << log_file << LL_ENDL;
+ return;
+ }
+ file << "Importing: " << mFilename << "\n";
+
+ std::map<std::string, LLMatrix4a> inv_bind;
+ std::map<std::string, LLMatrix4a> alt_bind;
+ for (LLPointer<LLModel>& mdl : mModelList)
+ {
+
+ file << "Model name: " << mdl->mLabel << "\n";
+ const LLMeshSkinInfo& skin_info = mdl->mSkinInfo;
+ file << "Shape Bind matrix: " << skin_info.mBindShapeMatrix << "\n";
+ file << "Skin Weights count: " << (S32)mdl->mSkinWeights.size() << "\n";
+
+ // some objects might have individual bind matrices,
+ // but for now it isn't accounted for
+ size_t joint_count = skin_info.mJointNames.size();
+ for (size_t i = 0; i< joint_count;i++)
+ {
+ const std::string& joint = skin_info.mJointNames[i];
+ if (skin_info.mInvBindMatrix.size() > i)
+ {
+ inv_bind[joint] = skin_info.mInvBindMatrix[i];
+ }
+ if (skin_info.mAlternateBindMatrix.size() > i)
+ {
+ alt_bind[joint] = skin_info.mAlternateBindMatrix[i];
+ }
+ }
+ }
+
+ file << "Inv Bind matrices.\n";
+ for (auto& bind : inv_bind)
+ {
+ file << "Joint: " << bind.first << " Matrix: " << bind.second << "\n";
+ }
+
+ file << "Alt Bind matrices.\n";
+ for (auto& bind : alt_bind)
+ {
+ file << "Joint: " << bind.first << " Matrix: " << bind.second << "\n";
+ }
+}
//called in the main thread
void LLModelLoader::loadTextures()
diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h
index 73ec0ed1f4..caffa34676 100644
--- a/indra/llprimitive/llmodelloader.h
+++ b/indra/llprimitive/llmodelloader.h
@@ -36,7 +36,7 @@ class LLJoint;
typedef std::map<std::string, LLMatrix4> JointTransformMap;
typedef std::map<std::string, LLMatrix4>::iterator JointTransformMapIt;
-typedef std::map<std::string, std::string> JointMap;
+typedef std::map<std::string, std::string, std::less<>> JointMap;
typedef std::deque<std::string> JointNameSet;
const S32 SLM_SUPPORTED_VERSION = 3;
@@ -198,6 +198,7 @@ public:
const LLSD logOut() const { return mWarningsArray; }
void clearLog() { mWarningsArray.clear(); }
+ void dumpDebugData();
protected:
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 45dab88e87..b534c8d4e8 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -2230,6 +2230,9 @@ void LLLineEditor::clear()
{
mText.clear();
setCursor(0);
+ mFontBufferPreSelection.reset();
+ mFontBufferSelection.reset();
+ mFontBufferPostSelection.reset();
}
//virtual
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 245339b107..ff77b4d482 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -1007,7 +1007,7 @@ void LLScrollListCtrl::deleteItems(const LLSD& sd)
void LLScrollListCtrl::deleteSelectedItems()
{
item_list::iterator iter;
- for (iter = mItemList.begin(); iter < mItemList.end(); )
+ for (iter = mItemList.begin(); iter != mItemList.end(); )
{
LLScrollListItem* itemp = *iter;
if (itemp->getSelected())
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
index 6177eb4873..3cb6686c02 100644
--- a/indra/llwindow/llopenglview-objc.mm
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -657,7 +657,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
};
int string_length = [aString length];
- unichar text[string_length];
+ unichar *text = new unichar[string_length];
attributedStringInfo segments;
// I used 'respondsToSelector:@selector(string)'
// to judge aString is an attributed string or not.
@@ -685,6 +685,8 @@ attributedStringInfo getSegments(NSAttributedString *str)
// we must clear the marked text when aString is null.
[self unmarkText];
}
+
+ delete [] text;
} else {
if (mHasMarkedText)
{
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index bff559591f..935050485f 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -103,7 +103,6 @@ LLWindow::LLWindow(LLWindowCallbacks* callbacks, bool fullscreen, U32 flags)
mFullscreen(fullscreen),
mFullscreenWidth(0),
mFullscreenHeight(0),
- mFullscreenBits(0),
mFullscreenRefresh(0),
mSupportedResolutions(NULL),
mNumSupportedResolutions(0),
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index 37e681c41b..0514f63830 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -223,7 +223,6 @@ protected:
bool mFullscreen;
S32 mFullscreenWidth;
S32 mFullscreenHeight;
- S32 mFullscreenBits;
S32 mFullscreenRefresh;
LLWindowResolution* mSupportedResolutions;
S32 mNumSupportedResolutions;
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 64f20e65ca..3a87d2070c 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -697,8 +697,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
}
if (dev_mode.dmPelsWidth == width &&
- dev_mode.dmPelsHeight == height &&
- dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
+ dev_mode.dmPelsHeight == height)
{
success = true;
if ((dev_mode.dmDisplayFrequency - current_refresh)
@@ -738,7 +737,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
// If we found a good resolution, use it.
if (success)
{
- success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
+ success = setDisplayResolution(width, height, closest_refresh);
}
// Keep a copy of the actual current device mode in case we minimize
@@ -751,7 +750,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mFullscreen = true;
mFullscreenWidth = dev_mode.dmPelsWidth;
mFullscreenHeight = dev_mode.dmPelsHeight;
- mFullscreenBits = dev_mode.dmBitsPerPel;
mFullscreenRefresh = dev_mode.dmDisplayFrequency;
LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
@@ -765,7 +763,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mFullscreen = false;
mFullscreenWidth = -1;
mFullscreenHeight = -1;
- mFullscreenBits = -1;
mFullscreenRefresh = -1;
std::map<std::string,std::string> args;
@@ -1187,7 +1184,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
// If we found a good resolution, use it.
if (success)
{
- success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
+ success = setDisplayResolution(width, height, closest_refresh);
}
// Keep a copy of the actual current device mode in case we minimize
@@ -1199,7 +1196,6 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
mFullscreen = true;
mFullscreenWidth = dev_mode.dmPelsWidth;
mFullscreenHeight = dev_mode.dmPelsHeight;
- mFullscreenBits = dev_mode.dmBitsPerPel;
mFullscreenRefresh = dev_mode.dmDisplayFrequency;
LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
@@ -1225,7 +1221,6 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
mFullscreen = false;
mFullscreenWidth = -1;
mFullscreenHeight = -1;
- mFullscreenBits = -1;
mFullscreenRefresh = -1;
LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL;
@@ -3519,7 +3514,7 @@ F32 LLWindowWin32::getPixelAspectRatio()
// Change display resolution. Returns true if successful.
// protected
-bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh)
+bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 refresh)
{
DEVMODE dev_mode;
::ZeroMemory(&dev_mode, sizeof(DEVMODE));
@@ -3531,7 +3526,6 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
{
if (dev_mode.dmPelsWidth == width &&
dev_mode.dmPelsHeight == height &&
- dev_mode.dmBitsPerPel == bits &&
dev_mode.dmDisplayFrequency == refresh )
{
// ...display mode identical, do nothing
@@ -3543,9 +3537,8 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
dev_mode.dmSize = sizeof(dev_mode);
dev_mode.dmPelsWidth = width;
dev_mode.dmPelsHeight = height;
- dev_mode.dmBitsPerPel = bits;
dev_mode.dmDisplayFrequency = refresh;
- dev_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
+ dev_mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
// CDS_FULLSCREEN indicates that this is a temporary change to the device mode.
LONG cds_result = ChangeDisplaySettings(&dev_mode, CDS_FULLSCREEN);
@@ -3555,7 +3548,7 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
if (!success)
{
LL_WARNS("Window") << "setDisplayResolution failed, "
- << width << "x" << height << "x" << bits << " @ " << refresh << LL_ENDL;
+ << width << "x" << height << " @ " << refresh << LL_ENDL;
}
return success;
@@ -3566,7 +3559,7 @@ bool LLWindowWin32::setFullscreenResolution()
{
if (mFullscreen)
{
- return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenBits, mFullscreenRefresh);
+ return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenRefresh);
}
else
{
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 36e89e4586..561f07d388 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -150,7 +150,7 @@ protected:
virtual LLSD getNativeKeyData();
// Changes display resolution. Returns true if successful
- bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
+ bool setDisplayResolution(S32 width, S32 height, S32 refresh);
// Go back to last fullscreen display resolution.
bool setFullscreenResolution();
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 315018bbee..33c5474d0d 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11631,6 +11631,28 @@
<key>Value</key>
<string>fss.txt</string>
</map>
+ <key>StatsFrametimeSampleSeconds</key>
+ <map>
+ <key>Comment</key>
+ <string>The number of seconds to sample extended frametime data (percentiles, stddev).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>5</integer>
+ </map>
+ <key>StatsFrametimeEventThreshold</key>
+ <map>
+ <key>Comment</key>
+ <string>The percentage that the frametime difference must exceed in order to register a frametime event. 0.1 = 10%, 0.25 = 25%, etc.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.1</real>
+ </map>
<key>SystemLanguage</key>
<map>
<key>Comment</key>
@@ -16683,5 +16705,27 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>MediaAutoPlayHuds</key>
+ <map>
+ <key>Comment</key>
+ <string>Automatically play HUD media</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>MediaFirstClickInteract</key>
+ <map>
+ <key>Comment</key>
+ <string>This setting controls which media (once loaded) does not require a first click to focus before interaction can begin. This allows clicks to be passed directly to media bypassing the focus click requirement. This setting is a bitfield, precomputed values are as follows: Disabled=0; Worn HUDs only=1; Owned objects=3; Friend objects=7; Group objects=15; Landowner objects=31; Any object=31; All MOAP=1073741824. For complete details see lltoolpie.h enum MediaFirstClickTypes.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
</map>
</llsd>
diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp
index 7a1ebf0610..bd3c1a3833 100644
--- a/indra/newview/gltf/llgltfloader.cpp
+++ b/indra/newview/gltf/llgltfloader.cpp
@@ -86,20 +86,20 @@ static const glm::mat4 coord_system_rotationxy(
0.f, 0.f, 0.f, 1.f
);
-LLGLTFLoader::LLGLTFLoader(std::string filename,
- S32 lod,
- LLModelLoader::load_callback_t load_cb,
- LLModelLoader::joint_lookup_func_t joint_lookup_func,
- LLModelLoader::texture_load_func_t texture_load_func,
- LLModelLoader::state_callback_t state_cb,
- void * opaque_userdata,
- JointTransformMap & jointTransformMap,
- JointNameSet & jointsFromNodes,
- std::map<std::string, std::string> &jointAliasMap,
- U32 maxJointsPerMesh,
- U32 modelLimit,
- std::vector<LLJointData> viewer_skeleton) //,
- //bool preprocess)
+LLGLTFLoader::LLGLTFLoader(std::string filename,
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void * opaque_userdata,
+ JointTransformMap & jointTransformMap,
+ JointNameSet & jointsFromNodes,
+ std::map<std::string, std::string, std::less<>> & jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit,
+ std::vector<LLJointData> viewer_skeleton) //,
+ //bool preprocess)
: LLModelLoader( filename,
lod,
load_cb,
@@ -129,6 +129,20 @@ bool LLGLTFLoader::OpenFile(const std::string &filename)
if (!mGltfLoaded)
{
notifyUnsupportedExtension(true);
+
+ for (const auto& buffer : mGLTFAsset.mBuffers)
+ {
+ if (buffer.mByteLength > 0 && buffer.mData.empty())
+ {
+ bool bin_file = buffer.mUri.ends_with(".bin");
+ LLSD args;
+ args["Message"] = bin_file ? "ParsingErrorMissingBufferBin" : "ParsingErrorMissingBuffer";
+ args["BUFFER_NAME"] = buffer.mName;
+ args["BUFFER_URI"] = buffer.mUri;
+ mWarningsArray.append(args);
+ }
+ }
+ setLoadState(ERROR_PARSING);
return false;
}
@@ -258,13 +272,14 @@ bool LLGLTFLoader::parseMeshes()
if (mGLTFAsset.mSkins.size() > 0)
{
checkForXYrotation(mGLTFAsset.mSkins[0]);
+ populateJointGroups();
}
// Populate the joints from skins first.
// There's not many skins - and you can pretty easily iterate through the nodes from that.
for (S32 i = 0; i < mGLTFAsset.mSkins.size(); i++)
{
- populateJointFromSkin(i);
+ populateJointsFromSkin(i);
}
// Track how many times each mesh name has been used
@@ -463,8 +478,29 @@ void LLGLTFLoader::computeCombinedNodeTransform(const LL::GLTF::Asset& asset, S3
}
}
+bool LLGLTFLoader::addJointToModelSkin(LLMeshSkinInfo& skin_info, S32 gltf_skin_idx, size_t gltf_joint_idx) const
+{
+ const std::string& legal_name = mJointNames[gltf_skin_idx][gltf_joint_idx];
+ if (legal_name.empty())
+ {
+ llassert(false); // should have been stopped by gltf_joint_index_use[i] == -1
+ return false;
+ }
+ skin_info.mJointNames.push_back(legal_name);
+ skin_info.mJointNums.push_back(-1);
+
+ // In scope of same skin multiple meshes reuse same bind matrices
+ skin_info.mInvBindMatrix.push_back(mInverseBindMatrices[gltf_skin_idx][gltf_joint_idx]);
+ skin_info.mAlternateBindMatrix.push_back(mAlternateBindMatrices[gltf_skin_idx][gltf_joint_idx]);
+
+ return true;
+}
+
bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh& mesh, const LL::GLTF::Node& nodeno, material_map& mats, S32 instance_count)
{
+ // Set the requested label for the floater display and uploading
+ pModel->mRequestedLabel = gDirUtilp->getBaseFileName(mFilename, true);
+
// Create unique model name
std::string base_name = mesh.mName;
if (base_name.empty())
@@ -516,15 +552,9 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
size_t jointCnt = gltf_skin.mJoints.size();
gltf_joint_index_use.resize(jointCnt);
- S32 replacement_index = 0;
for (size_t i = 0; i < jointCnt; ++i)
{
- // Process joint name and idnex
- S32 joint = gltf_skin.mJoints[i];
- LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[joint];
-
- std::string legal_name(jointNode.mName);
- if (mJointMap.find(legal_name) == mJointMap.end())
+ if (mJointNames[i].empty())
{
// This might need to hold a substitute index
gltf_joint_index_use[i] = -1; // mark as unsupported
@@ -956,65 +986,106 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
// Call normalizeVolumeFacesAndWeights to compute proper extents
pModel->normalizeVolumeFacesAndWeights();
- // Fill joint names, bind matrices and prepare to remap weight indices
+ // Fill joint names, bind matrices and remap weight indices
if (skinIdx >= 0)
{
LL::GLTF::Skin& gltf_skin = mGLTFAsset.mSkins[skinIdx];
LLMeshSkinInfo& skin_info = pModel->mSkinInfo;
S32 valid_joints_count = mValidJointsCount[skinIdx];
+ S32 replacement_index = 0;
std::vector<S32> gltfindex_to_joitindex_map;
size_t jointCnt = gltf_skin.mJoints.size();
gltfindex_to_joitindex_map.resize(jointCnt);
- S32 replacement_index = 0;
- S32 stripped_valid_joints = 0;
- for (size_t i = 0; i < jointCnt; ++i)
+ if (valid_joints_count > LL_MAX_JOINTS_PER_MESH_OBJECT)
{
- // Process joint name and idnex
- S32 joint = gltf_skin.mJoints[i];
- if (gltf_joint_index_use[i] < 0)
+ std::map<std::string, S32> goup_use_count;
+ // Assume that 'Torso' group is always in use since that's what everything else is attached to
+ goup_use_count["Torso"] = 1;
+ // Note that Collisions and Extra groups are all over the place, might want to include them from the start
+ // or add individual when parents are added
+
+ // Check which groups are in use
+ for (size_t i = 0; i < jointCnt; ++i)
{
- // unsupported (-1) joint, drop it
- continue;
+ std::string& joint_name = mJointNames[skinIdx][i];
+ if (!joint_name.empty())
+ {
+ if (gltf_joint_index_use[i] > 0)
+ {
+ const JointGroups &group = mJointGroups[joint_name];
+ // Joint in use, increment it's groups
+ goup_use_count[group.mGroup]++;
+ goup_use_count[group.mParentGroup]++;
+ }
+ }
}
- LL::GLTF::Node& jointNode = mGLTFAsset.mNodes[joint];
- std::string legal_name(jointNode.mName);
- if (mJointMap.find(legal_name) != mJointMap.end())
+ // 1. add joints that are in use directly
+ for (size_t i = 0; i < jointCnt; ++i)
{
- legal_name = mJointMap[legal_name];
- }
- else
- {
- llassert(false); // should have been stopped by gltf_joint_index_use[i] == -1
- continue;
+ // Process joint name and idnex
+ S32 joint = gltf_skin.mJoints[i];
+ if (gltf_joint_index_use[i] <= 0)
+ {
+ // unsupported (-1) joint, drop it
+ // unused (0) joint, drop it
+ continue;
+ }
+
+ if (addJointToModelSkin(skin_info, skinIdx, i))
+ {
+ gltfindex_to_joitindex_map[i] = replacement_index++;
+ }
}
- if (valid_joints_count > LL_MAX_JOINTS_PER_MESH_OBJECT
- && gltf_joint_index_use[i] == 0
- && legal_name != "mPelvis")
+ // 2. add joints from groups that this model's joints belong to
+ // It's perfectly valid to have more joints than is in use
+ // Ex: sandals that make your legs digitigrade despite not skining to
+ // knees or the like.
+ // Todo: sort and add by usecount
+ for (size_t i = 0; i < jointCnt; ++i)
{
- // Unused (0) joint
- // It's perfectly valid to have more joints than is in use
- // Ex: sandals that make your legs digitigrade despite not skining to
- // knees or the like.
- // But if model is over limid, drop extras sans pelvis.
- // Keeping 'pelvis' is a workaround to keep preview whole.
- // Todo: consider improving this, either take as much as possible or
- // ensure common parents/roots are included
- continue;
+ S32 joint = gltf_skin.mJoints[i];
+ if (gltf_joint_index_use[i] != 0)
+ {
+ // this step needs only joints that have zero uses
+ continue;
+ }
+ if (skin_info.mInvBindMatrix.size() > LL_MAX_JOINTS_PER_MESH_OBJECT)
+ {
+ break;
+ }
+ const std::string& legal_name = mJointNames[skinIdx][i];
+ std::string group_name = mJointGroups[legal_name].mGroup;
+ if (goup_use_count[group_name] > 0)
+ {
+ if (addJointToModelSkin(skin_info, skinIdx, i))
+ {
+ gltfindex_to_joitindex_map[i] = replacement_index++;
+ }
+ }
}
+ }
+ else
+ {
+ // Less than 110, just add every valid joint
+ for (size_t i = 0; i < jointCnt; ++i)
+ {
+ // Process joint name and idnex
+ S32 joint = gltf_skin.mJoints[i];
+ if (gltf_joint_index_use[i] < 0)
+ {
+ // unsupported (-1) joint, drop it
+ continue;
+ }
- gltfindex_to_joitindex_map[i] = replacement_index++;
-
- skin_info.mJointNames.push_back(legal_name);
- skin_info.mJointNums.push_back(-1);
-
- // In scope of same skin multiple meshes reuse same bind matrices
- skin_info.mInvBindMatrix.push_back(mInverseBindMatrices[skinIdx][i]);
-
- skin_info.mAlternateBindMatrix.push_back(mAlternateBindMatrices[skinIdx][i]);
+ if (addJointToModelSkin(skin_info, skinIdx, i))
+ {
+ gltfindex_to_joitindex_map[i] = replacement_index++;
+ }
+ }
}
if (skin_info.mInvBindMatrix.size() > LL_MAX_JOINTS_PER_MESH_OBJECT)
@@ -1043,7 +1114,7 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh&
return true;
}
-void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
+void LLGLTFLoader::populateJointsFromSkin(S32 skin_idx)
{
const LL::GLTF::Skin& skin = mGLTFAsset.mSkins[skin_idx];
@@ -1063,6 +1134,7 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
{
mInverseBindMatrices.resize(skin_idx + 1);
mAlternateBindMatrices.resize(skin_idx + 1);
+ mJointNames.resize(skin_idx + 1);
mValidJointsCount.resize(skin_idx + 1, 0);
}
@@ -1119,7 +1191,7 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
glm::mat4 ident(1.0);
for (auto &viewer_data : mViewerJointData)
{
- buildOverrideMatrix(viewer_data, joints_data, names_to_nodes, ident);
+ buildOverrideMatrix(viewer_data, joints_data, names_to_nodes, ident, ident);
}
for (S32 i = 0; i < joint_count; i++)
@@ -1132,6 +1204,11 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
{
legal_name = mJointMap[legal_name];
legal_joint = true;
+ mJointNames[skin_idx].push_back(legal_name);
+ }
+ else
+ {
+ mJointNames[skin_idx].emplace_back();
}
// Compute bind matrices
@@ -1193,6 +1270,15 @@ void LLGLTFLoader::populateJointFromSkin(S32 skin_idx)
}
}
+void LLGLTFLoader::populateJointGroups()
+{
+ std::string parent;
+ for (auto& viewer_data : mViewerJointData)
+ {
+ buildJointGroup(viewer_data, parent);
+ }
+}
+
S32 LLGLTFLoader::findClosestValidJoint(S32 source_joint, const LL::GLTF::Skin& gltf_skin) const
{
@@ -1296,7 +1382,19 @@ S32 LLGLTFLoader::findParentNode(S32 node) const
return -1;
}
-void LLGLTFLoader::buildOverrideMatrix(LLJointData& viewer_data, joints_data_map_t &gltf_nodes, joints_name_to_node_map_t &names_to_nodes, glm::mat4& parent_rest) const
+void LLGLTFLoader::buildJointGroup(LLJointData& viewer_data, const std::string &parent_group)
+{
+ JointGroups& jount_group_data = mJointGroups[viewer_data.mName];
+ jount_group_data.mGroup = viewer_data.mGroup;
+ jount_group_data.mParentGroup = parent_group;
+
+ for (LLJointData& child_data : viewer_data.mChildren)
+ {
+ buildJointGroup(child_data, viewer_data.mGroup);
+ }
+}
+
+void LLGLTFLoader::buildOverrideMatrix(LLJointData& viewer_data, joints_data_map_t &gltf_nodes, joints_name_to_node_map_t &names_to_nodes, glm::mat4& parent_rest, glm::mat4& parent_support_rest) const
{
glm::mat4 new_lefover(1.f);
glm::mat4 rest(1.f);
@@ -1306,26 +1404,42 @@ void LLGLTFLoader::buildOverrideMatrix(LLJointData& viewer_data, joints_data_map
S32 gltf_node_idx = found_node->second;
JointNodeData& node = gltf_nodes[gltf_node_idx];
node.mIsOverrideValid = true;
+ node.mViewerRestMatrix = viewer_data.mRestMatrix;
glm::mat4 gltf_joint_rest_pose = coord_system_rotation * node.mGltfRestMatrix;
if (mApplyXYRotation)
{
gltf_joint_rest_pose = coord_system_rotationxy * gltf_joint_rest_pose;
}
- node.mOverrideMatrix = glm::inverse(parent_rest) * gltf_joint_rest_pose;
- glm::vec3 override;
+ glm::mat4 translated_joint;
+ // Example:
+ // Viewer has pelvis->spine1->spine2->torso.
+ // gltf example model has pelvis->torso
+ // By doing glm::inverse(transalted_rest_spine2) * gltf_rest_torso
+ // We get what torso would have looked like if gltf had a spine2
+ if (viewer_data.mIsJoint)
+ {
+ translated_joint = glm::inverse(parent_rest) * gltf_joint_rest_pose;
+ }
+ else
+ {
+ translated_joint = glm::inverse(parent_support_rest) * gltf_joint_rest_pose;
+ }
+
+ glm::vec3 translation_override;
glm::vec3 skew;
glm::vec3 scale;
glm::vec4 perspective;
glm::quat rotation;
- glm::decompose(node.mOverrideMatrix, scale, rotation, override, skew, perspective);
- glm::vec3 translate;
- glm::decompose(viewer_data.mJointMatrix, scale, rotation, translate, skew, perspective);
- glm::mat4 viewer_joint = glm::recompose(scale, rotation, override, skew, perspective);
+ glm::decompose(translated_joint, scale, rotation, translation_override, skew, perspective);
+
+ node.mOverrideMatrix = glm::recompose(glm::vec3(1, 1, 1), glm::identity<glm::quat>(), translation_override, glm::vec3(0, 0, 0), glm::vec4(0, 0, 0, 1));
+
+ glm::mat4 override_joint = node.mOverrideMatrix;
+ override_joint = glm::scale(override_joint, viewer_data.mScale);
- node.mOverrideMatrix = viewer_joint;
- rest = parent_rest * node.mOverrideMatrix;
+ rest = parent_rest * override_joint;
node.mOverrideRestMatrix = rest;
}
else
@@ -1333,9 +1447,20 @@ void LLGLTFLoader::buildOverrideMatrix(LLJointData& viewer_data, joints_data_map
// No override for this joint
rest = parent_rest * viewer_data.mJointMatrix;
}
+
+ glm::mat4 support_rest(1.f);
+ if (viewer_data.mSupport == LLJointData::SUPPORT_BASE)
+ {
+ support_rest = rest;
+ }
+ else
+ {
+ support_rest = parent_support_rest;
+ }
+
for (LLJointData& child_data : viewer_data.mChildren)
{
- buildOverrideMatrix(child_data, gltf_nodes, names_to_nodes, rest);
+ buildOverrideMatrix(child_data, gltf_nodes, names_to_nodes, rest, support_rest);
}
}
diff --git a/indra/newview/gltf/llgltfloader.h b/indra/newview/gltf/llgltfloader.h
index 19a029d6d4..b53258ab8b 100644
--- a/indra/newview/gltf/llgltfloader.h
+++ b/indra/newview/gltf/llgltfloader.h
@@ -72,19 +72,19 @@ class LLGLTFLoader : public LLModelLoader
typedef std::map <std::string, S32> joints_name_to_node_map_t;
LLGLTFLoader(std::string filename,
- S32 lod,
- LLModelLoader::load_callback_t load_cb,
- LLModelLoader::joint_lookup_func_t joint_lookup_func,
- LLModelLoader::texture_load_func_t texture_load_func,
- LLModelLoader::state_callback_t state_cb,
- void * opaque_userdata,
- JointTransformMap & jointTransformMap,
- JointNameSet & jointsFromNodes,
- std::map<std::string, std::string> &jointAliasMap,
- U32 maxJointsPerMesh,
- U32 modelLimit,
- std::vector<LLJointData> viewer_skeleton); //,
- //bool preprocess );
+ S32 lod,
+ LLModelLoader::load_callback_t load_cb,
+ LLModelLoader::joint_lookup_func_t joint_lookup_func,
+ LLModelLoader::texture_load_func_t texture_load_func,
+ LLModelLoader::state_callback_t state_cb,
+ void * opaque_userdata,
+ JointTransformMap & jointTransformMap,
+ JointNameSet & jointsFromNodes,
+ std::map<std::string, std::string, std::less<>> & jointAliasMap,
+ U32 maxJointsPerMesh,
+ U32 modelLimit,
+ std::vector<LLJointData> viewer_skeleton); //,
+ //bool preprocess );
virtual ~LLGLTFLoader();
virtual bool OpenFile(const std::string &filename);
@@ -112,8 +112,20 @@ protected:
// vector of vectors because of a posibility of having more than one skin
typedef std::vector<LLMeshSkinInfo::matrix_list_t> bind_matrices_t;
+ typedef std::vector<std::vector<std::string> > joint_names_t;
bind_matrices_t mInverseBindMatrices;
bind_matrices_t mAlternateBindMatrices;
+ joint_names_t mJointNames; // empty string when no legal name for a given idx
+
+ // what group a joint belongs to.
+ // For purpose of stripping unused groups when joints are over limit.
+ struct JointGroups
+ {
+ std::string mGroup;
+ std::string mParentGroup;
+ };
+ typedef std::map<std::string, JointGroups> joint_to_group_map_t;
+ joint_to_group_map_t mJointGroups;
// per skin joint count, needs to be tracked for the sake of limits check.
std::vector<S32> mValidJointsCount;
@@ -122,14 +134,17 @@ private:
bool parseMeshes();
void computeCombinedNodeTransform(const LL::GLTF::Asset& asset, S32 node_index, glm::mat4& combined_transform) const;
void processNodeHierarchy(S32 node_idx, std::map<std::string, S32>& mesh_name_counts, U32 submodel_limit, const LLVolumeParams& volume_params);
+ bool addJointToModelSkin(LLMeshSkinInfo& skin_info, S32 gltf_skin_idx, size_t gltf_joint_idx) const;
bool populateModelFromMesh(LLModel* pModel, const LL::GLTF::Mesh &mesh, const LL::GLTF::Node &node, material_map& mats, S32 instance_count);
- void populateJointFromSkin(S32 skin_idx);
+ void populateJointsFromSkin(S32 skin_idx);
+ void populateJointGroups();
void addModelToScene(LLModel* pModel, U32 submodel_limit, const LLMatrix4& transformation, const LLVolumeParams& volume_params, const material_map& mats);
S32 findClosestValidJoint(S32 source_joint, const LL::GLTF::Skin& gltf_skin) const;
S32 findValidRootJointNode(S32 source_joint_node, const LL::GLTF::Skin& gltf_skin) const;
S32 findGLTFRootJointNode(const LL::GLTF::Skin& gltf_skin) const; // if there are multiple roots, gltf stores them under one commor joint
S32 findParentNode(S32 node) const;
- void buildOverrideMatrix(LLJointData& data, joints_data_map_t &gltf_nodes, joints_name_to_node_map_t &names_to_nodes, glm::mat4& parent_rest) const;
+ void buildJointGroup(LLJointData& viewer_data, const std::string& parent_group);
+ void buildOverrideMatrix(LLJointData& data, joints_data_map_t &gltf_nodes, joints_name_to_node_map_t &names_to_nodes, glm::mat4& parent_rest, glm::mat4& support_rest) const;
glm::mat4 buildGltfRestMatrix(S32 joint_node_index, const LL::GLTF::Skin& gltf_skin) const;
glm::mat4 buildGltfRestMatrix(S32 joint_node_index, const joints_data_map_t& joint_data) const;
glm::mat4 computeGltfToViewerSkeletonTransform(const joints_data_map_t& joints_data_map, S32 gltf_node_index, const std::string& joint_name) const;
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index f7b48d25f2..9ce14eb0ab 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -3477,11 +3477,14 @@ void LLAgent::initOriginGlobal(const LLVector3d &origin_global)
bool LLAgent::leftButtonGrabbed() const
{
- const bool camera_mouse_look = gAgentCamera.cameraMouselook();
- return (!camera_mouse_look && mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0)
- || (camera_mouse_look && mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0)
- || (!camera_mouse_look && mControlsTakenPassedOnCount[CONTROL_LBUTTON_DOWN_INDEX] > 0)
- || (camera_mouse_look && mControlsTakenPassedOnCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0);
+ if (gAgentCamera.cameraMouselook())
+ {
+ return mControlsTakenCount[CONTROL_ML_LBUTTON_DOWN_INDEX] > 0;
+ }
+ else
+ {
+ return mControlsTakenCount[CONTROL_LBUTTON_DOWN_INDEX] > 0;
+ }
}
bool LLAgent::rotateGrabbed() const
diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp
index 4856eb1199..3a0d55eeba 100644
--- a/indra/newview/llagentcamera.cpp
+++ b/indra/newview/llagentcamera.cpp
@@ -1990,16 +1990,6 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(bool *hit_limit)
isConstrained = true;
}
}
-
-// JC - Could constrain camera based on parcel stuff here.
-// LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(camera_position_global);
-//
-// if (regionp && !regionp->mParcelOverlay->isBuildCameraAllowed(regionp->getPosRegionFromGlobal(camera_position_global)))
-// {
-// camera_position_global = last_position_global;
-//
-// isConstrained = true;
-// }
}
// Don't let camera go underground
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index d9596164eb..0f9ee93d56 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -5733,9 +5733,9 @@ void LLAppViewer::forceErrorThreadCrash()
thread->start();
}
-void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
+void LLAppViewer::initMainloopTimeout(std::string_view state, F32 secs)
{
- if(!mMainloopTimeout)
+ if (!mMainloopTimeout)
{
mMainloopTimeout = new LLWatchdogTimeout();
resumeMainloopTimeout(state, secs);
@@ -5744,20 +5744,20 @@ void LLAppViewer::initMainloopTimeout(const std::string& state, F32 secs)
void LLAppViewer::destroyMainloopTimeout()
{
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
delete mMainloopTimeout;
- mMainloopTimeout = NULL;
+ mMainloopTimeout = nullptr;
}
}
-void LLAppViewer::resumeMainloopTimeout(const std::string& state, F32 secs)
+void LLAppViewer::resumeMainloopTimeout(std::string_view state, F32 secs)
{
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
- if(secs < 0.0f)
+ if (secs < 0.0f)
{
- static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
+ static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60.f);
secs = mainloop_timeout;
}
@@ -5768,19 +5768,19 @@ void LLAppViewer::resumeMainloopTimeout(const std::string& state, F32 secs)
void LLAppViewer::pauseMainloopTimeout()
{
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
mMainloopTimeout->stop();
}
}
-void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)
+void LLAppViewer::pingMainloopTimeout(std::string_view state, F32 secs)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_APP;
- if(mMainloopTimeout)
+ if (mMainloopTimeout)
{
- if(secs < 0.0f)
+ if (secs < 0.0f)
{
static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
secs = mainloop_timeout;
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 3da0246ccf..b4b8e5bac3 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -197,11 +197,11 @@ public:
// For thread debugging.
// llstartup needs to control init.
// llworld, send_agent_pause() also controls pause/resume.
- void initMainloopTimeout(const std::string& state, F32 secs = -1.0f);
+ void initMainloopTimeout(std::string_view state, F32 secs = -1.0f);
void destroyMainloopTimeout();
void pauseMainloopTimeout();
- void resumeMainloopTimeout(const std::string& state = "", F32 secs = -1.0f);
- void pingMainloopTimeout(const std::string& state, F32 secs = -1.0f);
+ void resumeMainloopTimeout(std::string_view state = "", F32 secs = -1.0f);
+ void pingMainloopTimeout(std::string_view state, F32 secs = -1.0f);
// Handle the 'login completed' event.
// *NOTE:Mani Fix this for login abstraction!!
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 67a44cfb27..f3214e2a20 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -832,6 +832,29 @@ bool LLAppViewerWin32::reportCrashToBugsplat(void* pExcepInfo)
return false;
}
+bool LLAppViewerWin32::initWindow()
+{
+ // This is a workaround/hotfix for a change in Windows 11 24H2 (and possibly later)
+ // Where the window width and height need to correctly reflect an available FullScreen size
+ if (gSavedSettings.getBOOL("FullScreen"))
+ {
+ DEVMODE dev_mode;
+ ::ZeroMemory(&dev_mode, sizeof(DEVMODE));
+ dev_mode.dmSize = sizeof(DEVMODE);
+ if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
+ {
+ gSavedSettings.setU32("WindowWidth", dev_mode.dmPelsWidth);
+ gSavedSettings.setU32("WindowHeight", dev_mode.dmPelsHeight);
+ }
+ else
+ {
+ LL_WARNS("AppInit") << "Unable to set WindowWidth and WindowHeight for FullScreen mode" << LL_ENDL;
+ }
+ }
+
+ return LLAppViewer::initWindow();
+}
+
void LLAppViewerWin32::initLoggingAndGetLastDuration()
{
LLAppViewer::initLoggingAndGetLastDuration();
diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h
index 250e72edf3..3fad53ec72 100644
--- a/indra/newview/llappviewerwin32.h
+++ b/indra/newview/llappviewerwin32.h
@@ -46,6 +46,7 @@ public:
bool reportCrashToBugsplat(void* pExcepInfo) override;
protected:
+ bool initWindow() override; // Override to initialize the viewer's window.
void initLoggingAndGetLastDuration() override; // Override to clean stack_trace info.
void initConsole() override; // Initialize OS level debugging console.
bool initHardwareTest() override; // Win32 uses DX9 to test hardware.
diff --git a/indra/newview/llfloaterbvhpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp
index b94c31ec04..5ee93be061 100644
--- a/indra/newview/llfloaterbvhpreview.cpp
+++ b/indra/newview/llfloaterbvhpreview.cpp
@@ -179,7 +179,7 @@ void LLFloaterBvhPreview::setAnimCallbacks()
getChild<LLUICtrl>("ease_out_time")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateEaseOut, this, _1));
}
-std::map <std::string, std::string> LLFloaterBvhPreview::getJointAliases()
+std::map<std::string, std::string, std::less<>> LLFloaterBvhPreview::getJointAliases()
{
LLPointer<LLVOAvatar> av = (LLVOAvatar*)mAnimPreview->getDummyAvatar();
return av->getJointAliases();
@@ -252,7 +252,7 @@ bool LLFloaterBvhPreview::postBuild()
ELoadStatus load_status = E_ST_OK;
S32 line_number = 0;
- std::map<std::string, std::string> joint_alias_map = getJointAliases();
+ auto joint_alias_map = getJointAliases();
loaderp = new LLBVHLoader(file_buffer, load_status, line_number, joint_alias_map);
std::string status = getString(STATUS[load_status]);
diff --git a/indra/newview/llfloaterbvhpreview.h b/indra/newview/llfloaterbvhpreview.h
index ae64521492..bb69ab65ef 100644
--- a/indra/newview/llfloaterbvhpreview.h
+++ b/indra/newview/llfloaterbvhpreview.h
@@ -108,7 +108,7 @@ public:
S32 status, LLExtStat ext_status);
private:
void setAnimCallbacks() ;
- std::map <std::string, std::string> getJointAliases();
+ std::map<std::string, std::string, std::less<>> getJointAliases();
protected:
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 84b9cb18f8..bd33ab2dbe 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -1487,7 +1487,7 @@ void LLFloaterModelPreview::updateAvatarTab(bool highlight_overrides)
{
// Populate table
- std::map<std::string, std::string> joint_alias_map;
+ std::map<std::string, std::string, std::less<>> joint_alias_map;
mModelPreview->getJointAliases(joint_alias_map);
S32 conflicts = 0;
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index 9bc075d03f..af58c6316d 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -1043,7 +1043,9 @@ void LLFloaterUIPreview::getExecutablePath(const std::vector<std::string>& filen
{
CFStringRef executable_cfstr = (CFStringRef)CFDictionaryGetValue(bundleInfoDict, CFSTR("CFBundleExecutable")); // get the name of the actual executable (e.g. TextEdit or firefox-bin)
int max_file_length = 256; // (max file name length is 255 in OSX)
- char executable_buf[max_file_length];
+
+ // Xcode 26: VLAs are a clang extension. Just create the buffer and delete it after.
+ char *executable_buf = new char [max_file_length];
if(CFStringGetCString(executable_cfstr, executable_buf, max_file_length, kCFStringEncodingMacRoman)) // convert CFStringRef to char*
{
executable_path += std::string("/Contents/MacOS/") + std::string(executable_buf); // append path to executable directory and then executable name to exec path
@@ -1053,6 +1055,7 @@ void LLFloaterUIPreview::getExecutablePath(const std::vector<std::string>& filen
std::string warning = "Unable to get CString from CFString for executable path";
popupAndPrintWarning(warning);
}
+ delete [] executable_buf;
}
else
{
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index a798ba31ee..c70058145a 100755
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -327,9 +327,6 @@ LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key)
mSetToUserPosition(true),
mTrackedLocation(0.0,0.0,0.0),
mTrackedStatus(LLTracker::TRACKING_NOTHING),
- mListFriendCombo(nullptr),
- mListLandmarkCombo(nullptr),
- mListSearchResults(nullptr),
mParcelInfoObserver(nullptr),
mShowParcelInfo(false)
{
@@ -383,32 +380,33 @@ bool LLFloaterWorldMap::postBuild()
mTeleportCoordSpinY = getChild<LLUICtrl>("teleport_coordinate_y");
mTeleportCoordSpinZ = getChild<LLUICtrl>("teleport_coordinate_z");
- LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo");
- avatar_combo->selectFirstItem();
- avatar_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onAvatarComboPrearrange, this) );
- avatar_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
- mListFriendCombo = dynamic_cast<LLCtrlListInterface *>(avatar_combo);
+ mFriendCombo = getChild<LLComboBox>("friend combo");
+ mFriendCombo->selectFirstItem();
+ mFriendCombo->setPrearrangeCallback(boost::bind(&LLFloaterWorldMap::onAvatarComboPrearrange, this));
+ mFriendCombo->setTextChangedCallback(boost::bind(&LLFloaterWorldMap::onComboTextEntry, this));
mLocationEditor = getChild<LLSearchEditor>("location");
mLocationEditor->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1));
- mLocationEditor->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this));
+ mLocationEditor->setTextChangedCallback(boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this));
- getChild<LLScrollListCtrl>("search_results")->setDoubleClickCallback( boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this));
- mListSearchResults = childGetListInterface("search_results");
+ mSearchResults = getChild<LLScrollListCtrl>("search_results");
+ mSearchResults->setDoubleClickCallback(boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this));
- LLComboBox *landmark_combo = getChild<LLComboBox>( "landmark combo");
- landmark_combo->selectFirstItem();
- landmark_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onLandmarkComboPrearrange, this) );
- landmark_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
- mListLandmarkCombo = dynamic_cast<LLCtrlListInterface *>(landmark_combo);
+ mLandmarkCombo = getChild<LLComboBox>("landmark combo");
+ mLandmarkCombo->selectFirstItem();
+ mLandmarkCombo->setPrearrangeCallback(boost::bind(&LLFloaterWorldMap::onLandmarkComboPrearrange, this));
+ mLandmarkCombo->setTextChangedCallback(boost::bind(&LLFloaterWorldMap::onComboTextEntry, this));
mZoomSlider = getChild<LLSliderCtrl>("zoom slider");
F32 slider_zoom = mMapView->getZoom();
mZoomSlider->setValue(slider_zoom);
+ mTrackCtrlsPanel = getChild<LLPanel>("layout_panel_4");
+ mSearchButton = getChild<LLButton>("DoSearch");
+
getChild<LLPanel>("expand_btn_panel")->setMouseDownCallback(boost::bind(&LLFloaterWorldMap::onExpandCollapseBtn, this));
- setDefaultBtn(NULL);
+ mTrackCtrlsPanel->setDefaultBtn(nullptr);
onChangeMaturity();
@@ -608,7 +606,6 @@ void LLFloaterWorldMap::draw()
}
mTeleportButton->setEnabled((bool)tracking_status);
- // getChildView("Clear")->setEnabled((bool)tracking_status);
mShowDestinationButton->setEnabled((bool)tracking_status || LLWorldMap::getInstance()->isTracking());
mCopySlurlButton->setEnabled((mSLURL.isValid()) );
@@ -700,26 +697,24 @@ void LLFloaterWorldMap::requestParcelInfo(const LLVector3d& pos_global, const LL
}
}
-void LLFloaterWorldMap::trackAvatar( const LLUUID& avatar_id, const std::string& name )
+void LLFloaterWorldMap::trackAvatar(const LLUUID& avatar_id, const std::string& name)
{
mShowParcelInfo = false;
- LLCtrlSelectionInterface *iface = childGetSelectionInterface("friend combo");
- if (!iface) return;
buildAvatarIDList();
- if(iface->setCurrentByID(avatar_id) || gAgent.isGodlike())
+ if (mFriendCombo->setCurrentByID(avatar_id) || gAgent.isGodlike())
{
// *HACK: Adjust Z values automatically for liaisons & gods so
// they swoop down when they click on the map. Requested
// convenience.
- if(gAgent.isGodlike())
+ if (gAgent.isGodlike())
{
mTeleportCoordSpinZ->setValue(LLSD(200.f));
}
// Don't re-request info if we already have it or we won't have it in time to teleport
if (mTrackedStatus != LLTracker::TRACKING_AVATAR || avatar_id != mTrackedAvatarID)
{
- mTrackedStatus = LLTracker::TRACKING_AVATAR;
+ mTrackedStatus = LLTracker::TRACKING_AVATAR;
mTrackedAvatarID = avatar_id;
LLTracker::trackAvatar(avatar_id, name);
}
@@ -728,52 +723,45 @@ void LLFloaterWorldMap::trackAvatar( const LLUUID& avatar_id, const std::string&
{
LLTracker::stopTracking(false);
}
- setDefaultBtn("Teleport");
+ mTrackCtrlsPanel->setDefaultBtn(mTeleportButton);
}
-void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id )
+void LLFloaterWorldMap::trackLandmark(const LLUUID& landmark_item_id)
{
mShowParcelInfo = false;
- LLCtrlSelectionInterface *iface = childGetSelectionInterface("landmark combo");
- if (!iface) return;
buildLandmarkIDLists();
bool found = false;
- S32 idx;
+ S32 idx;
for (idx = 0; idx < mLandmarkItemIDList.size(); idx++)
{
- if ( mLandmarkItemIDList.at(idx) == landmark_item_id)
+ if (mLandmarkItemIDList.at(idx) == landmark_item_id)
{
found = true;
break;
}
}
- if (found && iface->setCurrentByID( landmark_item_id ) )
+ if (found && mLandmarkCombo->setCurrentByID(landmark_item_id))
{
- LLUUID asset_id = mLandmarkAssetIDList.at( idx );
- std::string name;
- LLComboBox* combo = getChild<LLComboBox>( "landmark combo");
- if (combo) name = combo->getSimple();
- mTrackedStatus = LLTracker::TRACKING_LANDMARK;
- LLTracker::trackLandmark(mLandmarkAssetIDList.at( idx ), // assetID
- mLandmarkItemIDList.at( idx ), // itemID
- name); // name
+ LLUUID asset_id = mLandmarkAssetIDList.at(idx);
+ std::string name = mLandmarkCombo->getSimple();
+ mTrackedStatus = LLTracker::TRACKING_LANDMARK;
+ LLTracker::trackLandmark(mLandmarkAssetIDList.at(idx), // assetID
+ mLandmarkItemIDList.at(idx), // itemID
+ name); // name
- if( asset_id != sHomeID )
+ if (asset_id != sHomeID)
{
// start the download process
- gLandmarkList.getAsset( asset_id);
+ gLandmarkList.getAsset(asset_id);
}
-
- // We have to download both region info and landmark data, so set busy. JC
- // getWindow()->incBusyCount();
}
else
{
LLTracker::stopTracking(false);
}
- setDefaultBtn("Teleport");
+ mTrackCtrlsPanel->setDefaultBtn(mTeleportButton);
}
@@ -782,7 +770,7 @@ void LLFloaterWorldMap::trackEvent(const LLItemInfo &event_info)
mShowParcelInfo = false;
mTrackedStatus = LLTracker::TRACKING_LOCATION;
LLTracker::trackLocation(event_info.getGlobalPosition(), event_info.getName(), event_info.getToolTip(), LLTracker::LOCATION_EVENT);
- setDefaultBtn("Teleport");
+ mTrackCtrlsPanel->setDefaultBtn(mTeleportButton);
}
void LLFloaterWorldMap::trackGenericItem(const LLItemInfo &item)
@@ -790,7 +778,7 @@ void LLFloaterWorldMap::trackGenericItem(const LLItemInfo &item)
mShowParcelInfo = false;
mTrackedStatus = LLTracker::TRACKING_LOCATION;
LLTracker::trackLocation(item.getGlobalPosition(), item.getName(), item.getToolTip(), LLTracker::LOCATION_ITEM);
- setDefaultBtn("Teleport");
+ mTrackCtrlsPanel->setDefaultBtn(mTeleportButton);
}
void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
@@ -804,7 +792,7 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
S32 world_x = S32(pos_global.mdV[0] / 256);
S32 world_y = S32(pos_global.mdV[1] / 256);
LLWorldMapMessage::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true);
- setDefaultBtn("");
+ mTrackCtrlsPanel->setDefaultBtn(nullptr);
// clicked on a non-region - turn off coord display
enableTeleportCoordsDisplay( false );
@@ -818,7 +806,7 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
LLTracker::stopTracking(false);
LLWorldMap::getInstance()->setTracking(pos_global);
LLWorldMap::getInstance()->setTrackingInvalid();
- setDefaultBtn("");
+ mTrackCtrlsPanel->setDefaultBtn(nullptr);
// clicked on a down region - turn off coord display
enableTeleportCoordsDisplay( false );
@@ -849,7 +837,7 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global)
// we have a valid region - turn on coord display
enableTeleportCoordsDisplay( true );
- setDefaultBtn("Teleport");
+ mTrackCtrlsPanel->setDefaultBtn(mTeleportButton);
}
// enable/disable teleport destination coordinates
@@ -964,7 +952,7 @@ void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S3
local_pos.mV[VZ] = (F32)z_coord;
LLVector3d global_pos = sim_info->getGlobalPos(local_pos);
trackLocation(global_pos);
- setDefaultBtn("Teleport");
+ mTrackCtrlsPanel->setDefaultBtn(mTeleportButton);
}
else
{
@@ -1025,17 +1013,14 @@ void LLFloaterWorldMap::observeFriends()
void LLFloaterWorldMap::friendsChanged()
{
- LLAvatarTracker& t = LLAvatarTracker::instance();
- const LLUUID& avatar_id = t.getAvatarID();
+ LLAvatarTracker& t = LLAvatarTracker::instance();
+ const LLUUID& avatar_id = t.getAvatarID();
buildAvatarIDList();
- if(avatar_id.notNull())
+ if (avatar_id.notNull())
{
- LLCtrlSelectionInterface *iface = childGetSelectionInterface("friend combo");
const LLRelationship* buddy_info = t.getBuddyInfo(avatar_id);
- if(!iface ||
- !iface->setCurrentByID(avatar_id) ||
- (buddy_info && !buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)) ||
- gAgent.isGodlike())
+ if (!mFriendCombo->setCurrentByID(avatar_id) ||
+ (buddy_info && !buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)) || gAgent.isGodlike())
{
LLTracker::stopTracking(false);
}
@@ -1045,15 +1030,12 @@ void LLFloaterWorldMap::friendsChanged()
// No longer really builds a list. Instead, just updates mAvatarCombo.
void LLFloaterWorldMap::buildAvatarIDList()
{
- LLCtrlListInterface *list = mListFriendCombo;
- if (!list) return;
-
// Delete all but the "None" entry
- S32 list_size = list->getItemCount();
+ S32 list_size = mFriendCombo->getItemCount();
if (list_size > 1)
{
- list->selectItemRange(1, -1);
- list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
+ mFriendCombo->selectItemRange(1, -1);
+ mFriendCombo->operateOnSelection(LLCtrlListInterface::OP_DELETE);
}
// Get all of the calling cards for avatar that are currently online
@@ -1061,29 +1043,26 @@ void LLFloaterWorldMap::buildAvatarIDList()
LLAvatarTracker::instance().applyFunctor(collector);
LLCollectMappableBuddies::buddy_map_t::iterator it;
LLCollectMappableBuddies::buddy_map_t::iterator end;
- it = collector.mMappable.begin();
+ it = collector.mMappable.begin();
end = collector.mMappable.end();
- for( ; it != end; ++it)
+ for (; it != end; ++it)
{
- list->addSimpleElement((*it).second, ADD_BOTTOM, (*it).first);
+ mFriendCombo->addSimpleElement((*it).second, ADD_BOTTOM, (*it).first);
}
- list->setCurrentByID( LLAvatarTracker::instance().getAvatarID() );
- list->selectFirstItem();
+ mFriendCombo->setCurrentByID(LLAvatarTracker::instance().getAvatarID());
+ mFriendCombo->selectFirstItem();
}
void LLFloaterWorldMap::buildLandmarkIDLists()
{
- LLCtrlListInterface *list = mListLandmarkCombo;
- if (!list) return;
-
// Delete all but the "None" entry
- S32 list_size = list->getItemCount();
+ S32 list_size = mLandmarkCombo->getItemCount();
if (list_size > 1)
{
- list->selectItemRange(1, -1);
- list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
+ mLandmarkCombo->selectItemRange(1, -1);
+ mLandmarkCombo->operateOnSelection(LLCtrlListInterface::OP_DELETE);
}
mLandmarkItemIDList.clear();
@@ -1115,13 +1094,13 @@ void LLFloaterWorldMap::buildLandmarkIDLists()
{
LLInventoryItem* item = items.at(i);
- list->addSimpleElement(item->getName(), ADD_BOTTOM, item->getUUID());
+ mLandmarkCombo->addSimpleElement(item->getName(), ADD_BOTTOM, item->getUUID());
mLandmarkAssetIDList.push_back( item->getAssetUUID() );
mLandmarkItemIDList.push_back( item->getUUID() );
}
- list->selectFirstItem();
+ mLandmarkCombo->selectFirstItem();
}
@@ -1139,10 +1118,9 @@ F32 LLFloaterWorldMap::getDistanceToDestination(const LLVector3d &destination,
void LLFloaterWorldMap::clearLocationSelection(bool clear_ui, bool dest_reached)
{
- LLCtrlListInterface *list = mListSearchResults;
- if (list && (!dest_reached || (list->getItemCount() == 1)))
+ if (!dest_reached || (mSearchResults->getItemCount() == 1))
{
- list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ mSearchResults->operateOnAll(LLCtrlListInterface::OP_DELETE);
}
LLWorldMap::getInstance()->cancelTracking();
mCompletingRegionName = "";
@@ -1153,11 +1131,7 @@ void LLFloaterWorldMap::clearLandmarkSelection(bool clear_ui)
{
if (clear_ui || !childHasKeyboardFocus("landmark combo"))
{
- LLCtrlListInterface *list = mListLandmarkCombo;
- if (list)
- {
- list->selectByValue( "None" );
- }
+ mLandmarkCombo->selectByValue("None");
}
}
@@ -1167,10 +1141,9 @@ void LLFloaterWorldMap::clearAvatarSelection(bool clear_ui)
if (clear_ui || !childHasKeyboardFocus("friend combo"))
{
mTrackedStatus = LLTracker::TRACKING_NOTHING;
- LLCtrlListInterface *list = mListFriendCombo;
- if (list && list->getSelectedValue().asString() != "None")
+ if (mFriendCombo->getSelectedValue().asString() != "None")
{
- list->selectByValue( "None" );
+ mFriendCombo->selectByValue("None");
}
}
}
@@ -1226,25 +1199,21 @@ void LLFloaterWorldMap::onGoHome()
}
-void LLFloaterWorldMap::onLandmarkComboPrearrange( )
+void LLFloaterWorldMap::onLandmarkComboPrearrange()
{
- if( mIsClosing )
+ if (mIsClosing)
{
return;
}
- LLCtrlListInterface *list = mListLandmarkCombo;
- if (!list) return;
-
- LLUUID current_choice = list->getCurrentID();
+ LLUUID current_choice = mLandmarkCombo->getCurrentID();
buildLandmarkIDLists();
- if( current_choice.isNull() || !list->setCurrentByID( current_choice ) )
+ if (current_choice.isNull() || !mLandmarkCombo->setCurrentByID(current_choice))
{
LLTracker::stopTracking(false);
}
-
}
void LLFloaterWorldMap::onComboTextEntry()
@@ -1264,33 +1233,28 @@ void LLFloaterWorldMap::onSearchTextEntry( )
void LLFloaterWorldMap::onLandmarkComboCommit()
{
- if( mIsClosing )
+ if (mIsClosing)
{
return;
}
- LLCtrlListInterface *list = mListLandmarkCombo;
- if (!list) return;
-
LLUUID asset_id;
- LLUUID item_id = list->getCurrentID();
+ LLUUID item_id = mLandmarkCombo->getCurrentID();
LLTracker::stopTracking(false);
- //RN: stopTracking() clears current combobox selection, need to reassert it here
- list->setCurrentByID(item_id);
+ // RN: stopTracking() clears current combobox selection, need to reassert it here
+ mLandmarkCombo->setCurrentByID(item_id);
- if( item_id.isNull() )
- {
- }
- else if( item_id == sHomeID )
+ if (item_id.isNull()) {}
+ else if (item_id == sHomeID)
{
asset_id = sHomeID;
}
else
{
- LLInventoryItem* item = gInventory.getItem( item_id );
- if( item )
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if (item)
{
asset_id = item->getAssetUUID();
}
@@ -1301,34 +1265,31 @@ void LLFloaterWorldMap::onLandmarkComboCommit()
}
}
- trackLandmark( item_id);
+ trackLandmark(item_id);
onShowTargetBtn();
// Reset to user postion if nothing is tracked
- mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
+ mSetToUserPosition = (LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING);
}
// static
-void LLFloaterWorldMap::onAvatarComboPrearrange( )
+void LLFloaterWorldMap::onAvatarComboPrearrange()
{
- if( mIsClosing )
+ if (mIsClosing)
{
return;
}
- LLCtrlListInterface *list = mListFriendCombo;
- if (!list) return;
-
LLUUID current_choice;
- if( LLAvatarTracker::instance().haveTrackingInfo() )
+ if (LLAvatarTracker::instance().haveTrackingInfo())
{
current_choice = LLAvatarTracker::instance().getAvatarID();
}
buildAvatarIDList();
- if( !list->setCurrentByID( current_choice ) || current_choice.isNull() )
+ if (!mFriendCombo->setCurrentByID(current_choice) || current_choice.isNull())
{
LLTracker::stopTracking(false);
}
@@ -1336,26 +1297,21 @@ void LLFloaterWorldMap::onAvatarComboPrearrange( )
void LLFloaterWorldMap::onAvatarComboCommit()
{
- if( mIsClosing )
+ if (mIsClosing)
{
return;
}
- LLCtrlListInterface *list = mListFriendCombo;
- if (!list) return;
-
- const LLUUID& new_avatar_id = list->getCurrentID();
+ const LLUUID& new_avatar_id = mFriendCombo->getCurrentID();
if (new_avatar_id.notNull())
{
- std::string name;
- LLComboBox* combo = getChild<LLComboBox>("friend combo");
- if (combo) name = combo->getSimple();
+ std::string name = mFriendCombo->getSimple();
trackAvatar(new_avatar_id, name);
onShowTargetBtn();
}
else
- { // Reset to user postion if nothing is tracked
- mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING );
+ { // Reset to user postion if nothing is tracked
+ mSetToUserPosition = (LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING);
}
}
@@ -1375,11 +1331,11 @@ void LLFloaterWorldMap::updateSearchEnabled()
if (childHasKeyboardFocus("location") &&
mLocationEditor->getValue().asString().length() > 0)
{
- setDefaultBtn("DoSearch");
+ mTrackCtrlsPanel->setDefaultBtn(mSearchButton);
}
else
{
- setDefaultBtn(NULL);
+ mTrackCtrlsPanel->setDefaultBtn(nullptr);
}
}
@@ -1487,8 +1443,9 @@ void LLFloaterWorldMap::onExpandCollapseBtn()
std::string image_name = getString(toggle_collapse ? "expand_icon" : "collapse_icon");
std::string tooltip = getString(toggle_collapse ? "expand_tooltip" : "collapse_tooltip");
- getChild<LLIconCtrl>("expand_collapse_icon")->setImage(LLUI::getUIImage(image_name));
- getChild<LLIconCtrl>("expand_collapse_icon")->setToolTip(tooltip);
+ LLIconCtrl* expandCollapseIcon = getChild<LLIconCtrl>("expand_collapse_icon");
+ expandCollapseIcon->setImage(LLUI::getUIImage(image_name));
+ expandCollapseIcon->setToolTip(tooltip);
getChild<LLPanel>("expand_btn_panel")->setToolTip(tooltip);
}
@@ -1680,9 +1637,9 @@ void LLFloaterWorldMap::teleportToAvatar()
void LLFloaterWorldMap::flyToAvatar()
{
- if( LLAvatarTracker::instance().haveTrackingInfo() )
+ if (LLAvatarTracker::instance().haveTrackingInfo())
{
- gAgent.startAutoPilotGlobal( LLAvatarTracker::instance().getGlobalPos() );
+ gAgent.startAutoPilotGlobal(LLAvatarTracker::instance().getGlobalPos());
}
}
@@ -1693,8 +1650,7 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
return;
}
- LLScrollListCtrl *list = getChild<LLScrollListCtrl>("search_results");
- list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ mSearchResults->operateOnAll(LLCtrlListInterface::OP_DELETE);
auto name_length = mCompletingRegionName.length();
@@ -1722,7 +1678,7 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
value["id"] = info->getName();
value["columns"][0]["column"] = "sim_name";
value["columns"][0]["value"] = info->getName();
- list->addElement(value);
+ mSearchResults->addElement(value);
num_results++;
}
}
@@ -1737,21 +1693,21 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
// if match found, highlight it and go
if (!match.isUndefined())
{
- list->selectByValue(match);
+ mSearchResults->selectByValue(match);
}
// else select first found item
else
{
- list->selectFirstItem();
+ mSearchResults->selectFirstItem();
}
- getChild<LLUICtrl>("search_results")->setFocus(true);
+ mSearchResults->setFocus(true);
onCommitSearchResult();
}
else
{
// if we found nothing, say "none"
- list->setCommentText(LLTrans::getString("worldmap_results_none_found"));
- list->operateOnAll(LLCtrlListInterface::OP_DESELECT);
+ mSearchResults->setCommentText(LLTrans::getString("worldmap_results_none_found"));
+ mSearchResults->operateOnAll(LLCtrlListInterface::OP_DESELECT);
}
}
@@ -1765,11 +1721,7 @@ void LLFloaterWorldMap::onTeleportFinished()
void LLFloaterWorldMap::onCommitSearchResult()
{
- LLCtrlListInterface *list = mListSearchResults;
- if (!list) return;
-
- LLSD selected_value = list->getSelectedValue();
- std::string sim_name = selected_value.asString();
+ std::string sim_name = mSearchResults->getSelectedValue().asString();
if (sim_name.empty())
{
return;
@@ -1785,7 +1737,7 @@ void LLFloaterWorldMap::onCommitSearchResult()
{
LLVector3d pos_global = info->getGlobalOrigin();
- const F64 SIM_COORD_DEFAULT = 128.0;
+ constexpr F64 SIM_COORD_DEFAULT = 128.0;
LLVector3 pos_local(SIM_COORD_DEFAULT, SIM_COORD_DEFAULT, 0.0f);
// Did this value come from a trackURL() request?
@@ -1800,7 +1752,7 @@ void LLFloaterWorldMap::onCommitSearchResult()
mLocationEditor->setValue(sim_name);
trackLocation(pos_global);
- setDefaultBtn("Teleport");
+ mTrackCtrlsPanel->setDefaultBtn(mTeleportButton);
break;
}
}
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index 2f2b2b7a0d..bf1650eb7c 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -51,6 +51,8 @@ class LLCheckBoxCtrl;
class LLSliderCtrl;
class LLSpinCtrl;
class LLSearchEditor;
+class LLComboBox;
+class LLScrollListCtrl;
class LLWorldMapParcelInfoObserver : public LLRemoteParcelInfoObserver
{
@@ -218,14 +220,11 @@ private:
LLUUID mTrackedAvatarID;
LLSLURL mSLURL;
- LLCtrlListInterface * mListFriendCombo;
- LLCtrlListInterface * mListLandmarkCombo;
- LLCtrlListInterface * mListSearchResults;
-
LLButton* mTeleportButton = nullptr;
LLButton* mShowDestinationButton = nullptr;
LLButton* mCopySlurlButton = nullptr;
LLButton* mGoHomeButton = nullptr;
+ LLButton* mSearchButton = nullptr;
LLCheckBoxCtrl* mPeopleCheck = nullptr;
LLCheckBoxCtrl* mInfohubCheck = nullptr;
@@ -245,6 +244,13 @@ private:
LLSliderCtrl* mZoomSlider = nullptr;
+ LLComboBox* mLandmarkCombo = nullptr;
+ LLComboBox* mFriendCombo = nullptr;
+
+ LLScrollListCtrl* mSearchResults = nullptr;
+
+ LLPanel* mTrackCtrlsPanel = nullptr;
+
boost::signals2::connection mTeleportFinishConnection;
};
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index fd0d8b696f..c092b4c91a 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -225,10 +225,6 @@ void LLHUDText::renderText()
}
text_color = segment_iter->mColor;
- if (mOnHUDAttachment)
- {
- text_color = linearColor4(text_color);
- }
text_color.mV[VALPHA] *= alpha_factor;
hud_render_text(segment_iter->getText(), render_position, *fontp, style, shadow, x_offset, y_offset, text_color, mOnHUDAttachment);
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 5c0905af3c..01f2c6c525 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -959,7 +959,7 @@ void LLInventoryFilter::setFilterSubString(const std::string& string)
boost::char_separator<char> sep("+");
tokenizer tokens(filter_sub_string_new, sep);
- for (auto token_iter : tokens)
+ for (const auto& token_iter : tokens)
{
mFilterTokens.push_back(token_iter);
}
@@ -1025,7 +1025,7 @@ void LLInventoryFilter::setFilterSubString(const std::string& string)
}
// Cancel out UUID once the search string is modified
- if (mFilterOps.mFilterTypes == FILTERTYPE_UUID)
+ if (mFilterOps.mFilterTypes & FILTERTYPE_UUID)
{
mFilterOps.mFilterTypes &= ~FILTERTYPE_UUID;
mFilterOps.mFilterUUID = LLUUID::null;
@@ -1707,7 +1707,7 @@ std::string LLInventoryFilter::getEmptyLookupMessage(bool is_empty_folder) const
}
}
-bool LLInventoryFilter::areDateLimitsSet()
+bool LLInventoryFilter::areDateLimitsSet() const
{
return mFilterOps.mMinDate != time_min()
|| mFilterOps.mMaxDate != time_max()
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 7e64a03e73..612a161ba2 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -341,7 +341,7 @@ public:
bool checkAgainstFilterThumbnails(const LLUUID& object_id) const;
private:
- bool areDateLimitsSet();
+ bool areDateLimitsSet() const;
bool checkAgainstFilterSubString(const std::string& desc) const;
bool checkAgainstFilterType(const class LLFolderViewModelItemInventory* listener) const;
bool checkAgainstFilterType(const LLInventoryItem* item) const;
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 1077ce74ae..d2ed7168c5 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -2350,9 +2350,9 @@ bool can_move_to_my_outfits_as_outfit(LLInventoryModel* model, LLInventoryCatego
return false;
}
- if (items->size() == 0)
+ if (items->size() == 0 && inv_cat->getPreferredType() != LLFolderType::FT_OUTFIT)
{
- // Nothing to move(create)
+ // Nothing to create an outfit folder from
return false;
}
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index d8373ed0cb..d8b1c3482a 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -781,7 +781,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
mLODFile[lod] = filename;
- std::map<std::string, std::string> joint_alias_map;
+ std::map<std::string, std::string, std::less<>> joint_alias_map;
getJointAliases(joint_alias_map);
LLHandle<LLModelPreview> preview_handle = getHandle();
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 5b059516cd..7ab8549a71 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -162,6 +162,36 @@ void LLPanelFace::updateSelectedGLTFMaterials(std::function<void(LLGLTFMaterial*
LLSelectMgr::getInstance()->getSelection()->applyToTEs(&select_func);
}
+void LLPanelFace::updateSelectedGLTFMaterialsWithScale(std::function<void(LLGLTFMaterial*, const F32, const F32)> func)
+{
+ struct LLSelectedTEGLTFMaterialFunctor : public LLSelectedTEFunctor
+ {
+ LLSelectedTEGLTFMaterialFunctor(std::function<void(LLGLTFMaterial*, const F32, const F32)> func) : mFunc(func) {}
+ virtual ~LLSelectedTEGLTFMaterialFunctor() {};
+ bool apply(LLViewerObject* object, S32 face) override
+ {
+ LLGLTFMaterial new_override;
+ const LLTextureEntry* tep = object->getTE(face);
+ if (tep->getGLTFMaterialOverride())
+ {
+ new_override = *tep->getGLTFMaterialOverride();
+ }
+
+ U32 s_axis = VX;
+ U32 t_axis = VY;
+ LLPrimitive::getTESTAxes(face, &s_axis, &t_axis);
+ mFunc(&new_override, object->getScale().mV[s_axis], object->getScale().mV[t_axis]);
+ LLGLTFMaterialList::queueModify(object, face, &new_override);
+
+ return true;
+ }
+
+ std::function<void(LLGLTFMaterial*, const F32, const F32)> mFunc;
+ } select_func(func);
+
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&select_func);
+}
+
template<typename T>
void readSelectedGLTFMaterial(std::function<T(const LLGLTFMaterial*)> func, T& value, bool& identical, bool has_tolerance, T tolerance)
{
@@ -182,6 +212,36 @@ void readSelectedGLTFMaterial(std::function<T(const LLGLTFMaterial*)> func, T& v
identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&select_func, value, has_tolerance, tolerance);
}
+void getSelectedGLTFMaterialMaxRepeats(LLGLTFMaterial::TextureInfo channel, F32& repeats, bool& identical)
+{
+ // The All channel should read base color values
+ if (channel == LLGLTFMaterial::TextureInfo::GLTF_TEXTURE_INFO_COUNT)
+ channel = LLGLTFMaterial::TextureInfo::GLTF_TEXTURE_INFO_BASE_COLOR;
+
+ struct LLSelectedTEGetGLTFMaterialMaxRepeatsFunctor : public LLSelectedTEGetFunctor<F32>
+ {
+ LLSelectedTEGetGLTFMaterialMaxRepeatsFunctor(LLGLTFMaterial::TextureInfo channel) : mChannel(channel) {}
+ virtual ~LLSelectedTEGetGLTFMaterialMaxRepeatsFunctor() {};
+ F32 get(LLViewerObject* object, S32 face) override
+ {
+ const LLTextureEntry* tep = object->getTE(face);
+ const LLGLTFMaterial* render_material = tep->getGLTFRenderMaterial();
+ if (!render_material)
+ return 0.f;
+
+ U32 s_axis = VX;
+ U32 t_axis = VY;
+ LLPrimitive::getTESTAxes(face, &s_axis, &t_axis);
+ F32 repeats_u = render_material->mTextureTransform[mChannel].mScale[VX] / object->getScale().mV[s_axis];
+ F32 repeats_v = render_material->mTextureTransform[mChannel].mScale[VY] / object->getScale().mV[t_axis];
+ return llmax(repeats_u, repeats_v);
+ }
+
+ LLGLTFMaterial::TextureInfo mChannel;
+ } max_repeats_func(channel);
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&max_repeats_func, repeats);
+}
+
BOOST_STATIC_ASSERT(MATTYPE_DIFFUSE == LLRender::DIFFUSE_MAP && MATTYPE_NORMAL == LLRender::NORMAL_MAP && MATTYPE_SPECULAR == LLRender::SPECULAR_MAP);
//
@@ -322,6 +382,7 @@ bool LLPanelFace::postBuild()
getChildSetCommitCallback(mPBRScaleU, "gltfTextureScaleU", [&](LLUICtrl*, const LLSD&) { onCommitGLTFTextureScaleU(); });
getChildSetCommitCallback(mPBRScaleV, "gltfTextureScaleV", [&](LLUICtrl*, const LLSD&) { onCommitGLTFTextureScaleV(); });
+ getChildSetCommitCallback(mPBRRepeat, "gltfRptctrl", [&](LLUICtrl*, const LLSD&) { onCommitGLTFRepeatsPerMeter(); });
getChildSetCommitCallback(mPBRRotate, "gltfTextureRotation", [&](LLUICtrl*, const LLSD&) { onCommitGLTFRotation(); });
getChildSetCommitCallback(mPBROffsetU, "gltfTextureOffsetU", [&](LLUICtrl*, const LLSD&) { onCommitGLTFTextureOffsetU(); });
getChildSetCommitCallback(mPBROffsetV, "gltfTextureOffsetV", [&](LLUICtrl*, const LLSD&) { onCommitGLTFTextureOffsetV(); });
@@ -1398,9 +1459,18 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
spec_scale_s = editable ? spec_scale_s : 1.0f;
spec_scale_s *= identical_planar_texgen ? 2.0f : 1.0f;
- mTexScaleU->setValue(diff_scale_s);
- mShinyScaleU->setValue(spec_scale_s);
- mBumpyScaleU->setValue(norm_scale_s);
+ if (force_set_values)
+ {
+ mTexScaleU->forceSetValue(diff_scale_s);
+ mShinyScaleU->forceSetValue(spec_scale_s);
+ mBumpyScaleU->forceSetValue(norm_scale_s);
+ }
+ else
+ {
+ mTexScaleU->setValue(diff_scale_s);
+ mShinyScaleU->setValue(spec_scale_s);
+ mBumpyScaleU->setValue(norm_scale_s);
+ }
mTexScaleU->setEnabled(editable && has_material);
mShinyScaleU->setEnabled(editable && has_material && specmap_id.notNull());
@@ -1448,13 +1518,16 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
if (force_set_values)
{
mTexScaleV->forceSetValue(diff_scale_t);
+ mShinyScaleV->forceSetValue(spec_scale_t);
+ mBumpyScaleV->forceSetValue(norm_scale_t);
}
else
{
mTexScaleV->setValue(diff_scale_t);
+ mShinyScaleV->setValue(spec_scale_t);
+ mBumpyScaleV->setValue(norm_scale_t);
}
- mShinyScaleV->setValue(spec_scale_t);
- mBumpyScaleV->setValue(norm_scale_t);
+
mTexScaleV->setTentative(LLSD(diff_scale_tentative));
mShinyScaleV->setTentative(LLSD(spec_scale_tentative));
@@ -1594,36 +1667,57 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
F32 repeats_norm = 1.f;
F32 repeats_spec = 1.f;
+ F32 repeats_pbr_basecolor = 1.f;
+ F32 repeats_pbr_metallic_roughness = 1.f;
+ F32 repeats_pbr_normal = 1.f;
+ F32 repeats_pbr_emissive = 1.f;
+
bool identical_diff_repeats = false;
bool identical_norm_repeats = false;
bool identical_spec_repeats = false;
- LLSelectedTE::getMaxDiffuseRepeats(repeats_diff, identical_diff_repeats);
- LLSelectedTEMaterial::getMaxNormalRepeats(repeats_norm, identical_norm_repeats);
- LLSelectedTEMaterial::getMaxSpecularRepeats(repeats_spec, identical_spec_repeats);
+ bool identical_pbr_basecolor_repeats = false;
+ bool identical_pbr_metallic_roughness_repeats = false;
+ bool identical_pbr_normal_repeats = false;
+ bool identical_pbr_emissive_repeats = false;
{
+ LLSpinCtrl* repeats_spin_ctrl = nullptr;
S32 index = mComboTexGen ? mComboTexGen->getCurrentIndex() : 0;
bool enabled = editable && (index != 1);
bool identical_repeats = true;
S32 material_selection = mComboMatMedia->getCurrentIndex();
F32 repeats = 1.0f;
- U32 material_type = MATTYPE_DIFFUSE;
- if (material_selection == MATMEDIA_MATERIAL)
+ LLRender::eTexIndex material_channel = LLRender::DIFFUSE_MAP;
+ if (material_selection != MATMEDIA_PBR)
{
- material_type = mRadioMaterialType->getSelectedIndex();
+ repeats_spin_ctrl = mTexRepeat;
+ material_channel = getMatTextureChannel();
+ LLSelectedTE::getMaxDiffuseRepeats(repeats_diff, identical_diff_repeats);
+ LLSelectedTEMaterial::getMaxNormalRepeats(repeats_norm, identical_norm_repeats);
+ LLSelectedTEMaterial::getMaxSpecularRepeats(repeats_spec, identical_spec_repeats);
}
else if (material_selection == MATMEDIA_PBR)
{
+ repeats_spin_ctrl = mPBRRepeat;
enabled = editable && has_pbr_material;
- material_type = mRadioPbrType->getSelectedIndex();
+ material_channel = getPBRTextureChannel();
+
+ getSelectedGLTFMaterialMaxRepeats(LLGLTFMaterial::TextureInfo::GLTF_TEXTURE_INFO_BASE_COLOR,
+ repeats_pbr_basecolor, identical_pbr_basecolor_repeats);
+ getSelectedGLTFMaterialMaxRepeats(LLGLTFMaterial::TextureInfo::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS,
+ repeats_pbr_metallic_roughness, identical_pbr_metallic_roughness_repeats);
+ getSelectedGLTFMaterialMaxRepeats(LLGLTFMaterial::TextureInfo::GLTF_TEXTURE_INFO_NORMAL,
+ repeats_pbr_normal, identical_pbr_normal_repeats);
+ getSelectedGLTFMaterialMaxRepeats(LLGLTFMaterial::TextureInfo::GLTF_TEXTURE_INFO_EMISSIVE,
+ repeats_pbr_emissive, identical_pbr_emissive_repeats);
}
- switch (material_type)
+ switch (material_channel)
{
default:
- case MATTYPE_DIFFUSE:
+ case LLRender::DIFFUSE_MAP:
if (material_selection != MATMEDIA_PBR)
{
enabled = editable && !id.isNull();
@@ -1631,7 +1725,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
identical_repeats = identical_diff_repeats;
repeats = repeats_diff;
break;
- case MATTYPE_SPECULAR:
+ case LLRender::SPECULAR_MAP:
if (material_selection != MATMEDIA_PBR)
{
enabled = (editable && ((shiny == SHINY_TEXTURE) && !specmap_id.isNull()));
@@ -1639,7 +1733,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
identical_repeats = identical_spec_repeats;
repeats = repeats_spec;
break;
- case MATTYPE_NORMAL:
+ case LLRender::NORMAL_MAP:
if (material_selection != MATMEDIA_PBR)
{
enabled = (editable && ((bumpy == BUMPY_TEXTURE) && !normmap_id.isNull()));
@@ -1647,6 +1741,23 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
identical_repeats = identical_norm_repeats;
repeats = repeats_norm;
break;
+ case LLRender::NUM_TEXTURE_CHANNELS:
+ case LLRender::BASECOLOR_MAP:
+ identical_repeats = identical_pbr_basecolor_repeats;
+ repeats = repeats_pbr_basecolor;
+ break;
+ case LLRender::METALLIC_ROUGHNESS_MAP:
+ identical_repeats = identical_pbr_metallic_roughness_repeats;
+ repeats = repeats_pbr_metallic_roughness;
+ break;
+ case LLRender::GLTF_NORMAL_MAP:
+ identical_repeats = identical_pbr_normal_repeats;
+ repeats = repeats_pbr_normal;
+ break;
+ case LLRender::EMISSIVE_MAP:
+ identical_repeats = identical_pbr_emissive_repeats;
+ repeats = repeats_pbr_emissive;
+ break;
}
bool repeats_tentative = !identical_repeats;
@@ -1654,14 +1765,14 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
if (force_set_values)
{
// onCommit, previosly edited element updates related ones
- mTexRepeat->forceSetValue(editable ? repeats : 1.0f);
+ repeats_spin_ctrl->forceSetValue(editable ? repeats : 1.0f);
}
else
{
- mTexRepeat->setValue(editable ? repeats : 1.0f);
+ repeats_spin_ctrl->setValue(editable ? repeats : 1.0f);
}
- mTexRepeat->setTentative(LLSD(repeats_tentative));
- mTexRepeat->setEnabled(has_material && !identical_planar_texgen && enabled);
+ repeats_spin_ctrl->setTentative(LLSD(repeats_tentative));
+ repeats_spin_ctrl->setEnabled(!identical_planar_texgen && enabled);
}
}
@@ -1807,6 +1918,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
}
mLabelColorTransp->setEnabled(false);
mTexRepeat->setEnabled(false);
+ mPBRRepeat->setEnabled(false);
mLabelTexGen->setEnabled(false);
mLabelShininess->setEnabled(false);
mLabelBumpiness->setEnabled(false);
@@ -2002,6 +2114,7 @@ void LLPanelFace::updateVisibilityGLTF(LLViewerObject* objectp /*= nullptr */)
mPBRRotate->setVisible(show_pbr);
mPBROffsetU->setVisible(show_pbr);
mPBROffsetV->setVisible(show_pbr);
+ mPBRRepeat->setVisible(show_pbr);
}
void LLPanelFace::updateCopyTexButton()
@@ -3652,18 +3765,8 @@ void LLPanelFace::onCommitRepeatsPerMeter()
if (gSavedSettings.getBOOL("SyncMaterialSettings"))
{
LLSelectMgr::getInstance()->selectionTexScaleAutofit(repeats_per_meter);
-
- mBumpyScaleU->setValue(obj_scale_s * repeats_per_meter);
- mBumpyScaleV->setValue(obj_scale_t * repeats_per_meter);
-
- LLSelectedTEMaterial::setNormalRepeatX(this, obj_scale_s * repeats_per_meter);
- LLSelectedTEMaterial::setNormalRepeatY(this, obj_scale_t * repeats_per_meter);
-
- mShinyScaleU->setValue(obj_scale_s * repeats_per_meter);
- mShinyScaleV->setValue(obj_scale_t * repeats_per_meter);
-
- LLSelectedTEMaterial::setSpecularRepeatX(this, obj_scale_s * repeats_per_meter);
- LLSelectedTEMaterial::setSpecularRepeatY(this, obj_scale_t * repeats_per_meter);
+ LLSelectedTEMaterial::selectionNormalScaleAutofit(this, repeats_per_meter);
+ LLSelectedTEMaterial::selectionSpecularScaleAutofit(this, repeats_per_meter);
}
else
{
@@ -3674,18 +3777,10 @@ void LLPanelFace::onCommitRepeatsPerMeter()
LLSelectMgr::getInstance()->selectionTexScaleAutofit(repeats_per_meter);
break;
case MATTYPE_NORMAL:
- mBumpyScaleU->setValue(obj_scale_s * repeats_per_meter);
- mBumpyScaleV->setValue(obj_scale_t * repeats_per_meter);
-
- LLSelectedTEMaterial::setNormalRepeatX(this, obj_scale_s * repeats_per_meter);
- LLSelectedTEMaterial::setNormalRepeatY(this, obj_scale_t * repeats_per_meter);
+ LLSelectedTEMaterial::selectionNormalScaleAutofit(this, repeats_per_meter);
break;
case MATTYPE_SPECULAR:
- mBumpyScaleU->setValue(obj_scale_s * repeats_per_meter);
- mBumpyScaleV->setValue(obj_scale_t * repeats_per_meter);
-
- LLSelectedTEMaterial::setSpecularRepeatX(this, obj_scale_s * repeats_per_meter);
- LLSelectedTEMaterial::setSpecularRepeatY(this, obj_scale_t * repeats_per_meter);
+ LLSelectedTEMaterial::selectionSpecularScaleAutofit(this, repeats_per_meter);
break;
default:
llassert(false);
@@ -3696,6 +3791,21 @@ void LLPanelFace::onCommitRepeatsPerMeter()
updateUI(true);
}
+// Commit the number of GLTF repeats per meter
+void LLPanelFace::onCommitGLTFRepeatsPerMeter()
+{
+ F32 repeats_per_meter = (F32)mPBRRepeat->getValue().asReal();
+
+ LLGLTFMaterial::TextureInfo material_type = getPBRTextureInfo();
+ updateGLTFTextureTransformWithScale(material_type, [&](LLGLTFMaterial::TextureTransform* new_transform, F32 scale_s, F32 scale_t)
+ {
+ new_transform->mScale.mV[VX] = scale_s * repeats_per_meter;
+ new_transform->mScale.mV[VY] = scale_t * repeats_per_meter;
+ });
+
+ updateUI(true);
+}
+
struct LLPanelFaceSetMediaFunctor : public LLSelectedTEFunctor
{
virtual bool apply(LLViewerObject* object, S32 te)
@@ -4795,6 +4905,29 @@ void LLPanelFace::updateGLTFTextureTransform(std::function<void(LLGLTFMaterial::
}
}
+void LLPanelFace::updateGLTFTextureTransformWithScale(const LLGLTFMaterial::TextureInfo texture_info, std::function<void(LLGLTFMaterial::TextureTransform*, const F32, const F32)> edit)
+{
+ if (texture_info == LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT)
+ {
+ updateSelectedGLTFMaterialsWithScale([&](LLGLTFMaterial* new_override, const F32 scale_s, const F32 scale_t)
+ {
+ for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
+ {
+ LLGLTFMaterial::TextureTransform& new_transform = new_override->mTextureTransform[(LLGLTFMaterial::TextureInfo)i];
+ edit(&new_transform, scale_s, scale_t);
+ }
+ });
+ }
+ else
+ {
+ updateSelectedGLTFMaterialsWithScale([&](LLGLTFMaterial* new_override, const F32 scale_s, const F32 scale_t)
+ {
+ LLGLTFMaterial::TextureTransform& new_transform = new_override->mTextureTransform[texture_info];
+ edit(&new_transform, scale_s, scale_t);
+ });
+ }
+}
+
void LLPanelFace::setMaterialOverridesFromSelection()
{
const LLGLTFMaterial::TextureInfo texture_info = getPBRTextureInfo();
@@ -4870,8 +5003,9 @@ void LLPanelFace::setMaterialOverridesFromSelection()
}
}
- mPBRScaleU->setValue(transform.mScale[VX]);
- mPBRScaleV->setValue(transform.mScale[VY]);
+ // Force set scales just in case they were set by repeats per meter and their spinner is focused
+ mPBRScaleU->forceSetValue(transform.mScale[VX]);
+ mPBRScaleV->forceSetValue(transform.mScale[VY]);
mPBRRotate->setValue(transform.mRotation * RAD_TO_DEG);
mPBROffsetU->setValue(transform.mOffset[VX]);
mPBROffsetV->setValue(transform.mOffset[VY]);
@@ -4881,6 +5015,12 @@ void LLPanelFace::setMaterialOverridesFromSelection()
mPBRRotate->setTentative(!rotation_same);
mPBROffsetU->setTentative(!offset_u_same);
mPBROffsetV->setTentative(!offset_v_same);
+
+ F32 repeats = 1.f;
+ bool identical = false;
+ getSelectedGLTFMaterialMaxRepeats(getPBRDropChannel(), repeats, identical);
+ mPBRRepeat->forceSetValue(repeats);
+ mPBRRepeat->setTentative(!identical || !scale_u_same || !scale_v_same);
}
void LLPanelFace::Selection::connect()
@@ -5374,6 +5514,62 @@ void LLPanelFace::LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(U8& diffuse_a
identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &get_diff_mode, diffuse_alpha_mode);
}
+void LLPanelFace::LLSelectedTEMaterial::selectionNormalScaleAutofit(LLPanelFace* panel_face, F32 repeats_per_meter)
+{
+ struct f : public LLSelectedTEFunctor
+ {
+ LLPanelFace* mFacePanel;
+ F32 mRepeatsPerMeter;
+ f(LLPanelFace* face_panel, const F32& repeats_per_meter) : mFacePanel(face_panel), mRepeatsPerMeter(repeats_per_meter) {}
+ bool apply(LLViewerObject* object, S32 te)
+ {
+ if (object->permModify())
+ {
+ // Compute S,T to axis mapping
+ U32 s_axis, t_axis;
+ if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis))
+ return true;
+
+ F32 new_s = object->getScale().mV[s_axis] * mRepeatsPerMeter;
+ F32 new_t = object->getScale().mV[t_axis] * mRepeatsPerMeter;
+
+ setNormalRepeatX(mFacePanel, new_s, te);
+ setNormalRepeatY(mFacePanel, new_t, te);
+ }
+ return true;
+ }
+ } setfunc(panel_face, repeats_per_meter);
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
+}
+
+void LLPanelFace::LLSelectedTEMaterial::selectionSpecularScaleAutofit(LLPanelFace* panel_face, F32 repeats_per_meter)
+{
+ struct f : public LLSelectedTEFunctor
+ {
+ LLPanelFace* mFacePanel;
+ F32 mRepeatsPerMeter;
+ f(LLPanelFace* face_panel, const F32& repeats_per_meter) : mFacePanel(face_panel), mRepeatsPerMeter(repeats_per_meter) {}
+ bool apply(LLViewerObject* object, S32 te)
+ {
+ if (object->permModify())
+ {
+ // Compute S,T to axis mapping
+ U32 s_axis, t_axis;
+ if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis))
+ return true;
+
+ F32 new_s = object->getScale().mV[s_axis] * mRepeatsPerMeter;
+ F32 new_t = object->getScale().mV[t_axis] * mRepeatsPerMeter;
+
+ setSpecularRepeatX(mFacePanel, new_s, te);
+ setSpecularRepeatY(mFacePanel, new_t, te);
+ }
+ return true;
+ }
+ } setfunc(panel_face, repeats_per_meter);
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
+}
+
void LLPanelFace::LLSelectedTE::getObjectScaleS(F32& scale_s, bool& identical)
{
struct LLSelectedTEGetObjectScaleS : public LLSelectedTEGetFunctor<F32>
diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h
index ce3dd8bdea..0911378582 100644
--- a/indra/newview/llpanelface.h
+++ b/indra/newview/llpanelface.h
@@ -250,6 +250,7 @@ protected:
void onCommitGLTFRotation();
void onCommitGLTFTextureOffsetU();
void onCommitGLTFTextureOffsetV();
+ void onCommitGLTFRepeatsPerMeter();
void onClickAutoFix();
void onAlignTexture();
@@ -361,6 +362,7 @@ private:
LLButton* mDelMedia { nullptr };
LLSpinCtrl* mPBRScaleU { nullptr };
LLSpinCtrl* mPBRScaleV { nullptr };
+ LLSpinCtrl* mPBRRepeat { nullptr };
LLSpinCtrl* mPBRRotate { nullptr };
LLSpinCtrl* mPBROffsetU { nullptr };
LLSpinCtrl* mPBROffsetV { nullptr };
@@ -554,7 +556,9 @@ private:
void updateVisibilityGLTF(LLViewerObject* objectp = nullptr);
void updateSelectedGLTFMaterials(std::function<void(LLGLTFMaterial*)> func);
+ void updateSelectedGLTFMaterialsWithScale(std::function<void(LLGLTFMaterial*, const F32, const F32)> func);
void updateGLTFTextureTransform(std::function<void(LLGLTFMaterial::TextureTransform*)> edit);
+ void updateGLTFTextureTransformWithScale(const LLGLTFMaterial::TextureInfo texture_info, std::function<void(LLGLTFMaterial::TextureTransform*, const F32, const F32)> edit);
void setMaterialOverridesFromSelection();
@@ -649,6 +653,8 @@ public:
static void getMaxSpecularRepeats(F32& repeats, bool& identical);
static void getMaxNormalRepeats(F32& repeats, bool& identical);
static void getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha);
+ static void selectionNormalScaleAutofit(LLPanelFace* panel_face, F32 repeats_per_meter);
+ static void selectionSpecularScaleAutofit(LLPanelFace* panel_face, F32 repeats_per_meter);
DEF_GET_MAT_STATE(LLUUID, const LLUUID&, getNormalID, LLUUID::null, false, LLUUID::null);
DEF_GET_MAT_STATE(LLUUID, const LLUUID&, getSpecularID, LLUUID::null, false, LLUUID::null);
diff --git a/indra/newview/llpanelgroupbulk.cpp b/indra/newview/llpanelgroupbulk.cpp
index 8032e207cd..81c0bd97be 100644
--- a/indra/newview/llpanelgroupbulk.cpp
+++ b/indra/newview/llpanelgroupbulk.cpp
@@ -54,17 +54,16 @@
//////////////////////////////////////////////////////////////////////////
LLPanelGroupBulkImpl::LLPanelGroupBulkImpl(const LLUUID& group_id) :
mGroupID(group_id),
- mBulkAgentList(NULL),
- mOKButton(NULL),
+ mBulkAgentList(nullptr),
+ mOKButton(nullptr),
mAddButton(nullptr),
- mRemoveButton(NULL),
- mGroupName(NULL),
+ mRemoveButton(nullptr),
+ mGroupName(nullptr),
mLoadingText(),
mTooManySelected(),
- mCloseCallback(NULL),
- mCloseCallbackUserData(NULL),
- mAvatarNameCacheConnection(),
- mRoleNames(NULL),
+ mCloseCallback(nullptr),
+ mCloseCallbackUserData(nullptr),
+ mRoleNames(nullptr),
mOwnerWarning(),
mAlreadyInGroup(),
mConfirmedOwnerInvite(false),
@@ -74,10 +73,13 @@ LLPanelGroupBulkImpl::LLPanelGroupBulkImpl(const LLUUID& group_id) :
LLPanelGroupBulkImpl::~LLPanelGroupBulkImpl()
{
- if (mAvatarNameCacheConnection.connected())
+ for (auto& [id, connection] : mAvatarNameCacheConnections)
{
- mAvatarNameCacheConnection.disconnect();
+ if (connection.connected())
+ connection.disconnect();
}
+
+ mAvatarNameCacheConnections.clear();
}
void LLPanelGroupBulkImpl::callbackClickAdd(LLPanelGroupBulk* panelp)
@@ -124,43 +126,42 @@ void LLPanelGroupBulkImpl::callbackSelect(LLUICtrl* ctrl, void* userdata)
void LLPanelGroupBulkImpl::addUsers(const uuid_vec_t& agent_ids)
{
- std::vector<std::string> names;
for (const LLUUID& agent_id : agent_ids)
{
- LLAvatarName av_name;
- if (LLAvatarNameCache::get(agent_id, &av_name))
+ if (LLAvatarName av_name; LLAvatarNameCache::get(agent_id, &av_name))
{
onAvatarNameCache(agent_id, av_name);
}
else
{
- if (mAvatarNameCacheConnection.connected())
+ if (auto found = mAvatarNameCacheConnections.find(agent_id); found != mAvatarNameCacheConnections.end())
{
- mAvatarNameCacheConnection.disconnect();
+ if (found->second.connected())
+ found->second.disconnect();
+
+ mAvatarNameCacheConnections.erase(found);
}
- // *TODO : Add a callback per avatar name being fetched.
- mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_id,
+
+ mAvatarNameCacheConnections.try_emplace(agent_id, LLAvatarNameCache::get(agent_id,
[&](const LLUUID& agent_id, const LLAvatarName& av_name)
{
onAvatarNameCache(agent_id, av_name);
- });
+ }));
}
}
}
void LLPanelGroupBulkImpl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
{
- if (mAvatarNameCacheConnection.connected())
+ if (auto found = mAvatarNameCacheConnections.find(agent_id); found != mAvatarNameCacheConnections.end())
{
- mAvatarNameCacheConnection.disconnect();
- }
+ if (found->second.connected())
+ found->second.disconnect();
- std::vector<std::string> names;
- uuid_vec_t agent_ids;
- agent_ids.push_back(agent_id);
- names.push_back(av_name.getCompleteName());
+ mAvatarNameCacheConnections.erase(found);
+ }
- addUsers(names, agent_ids);
+ addUsers({ av_name.getCompleteName() }, { agent_id });
}
void LLPanelGroupBulkImpl::handleRemove()
@@ -232,7 +233,7 @@ void LLPanelGroupBulkImpl::addUsers(const std::vector<std::string>& names, const
}
}
-void LLPanelGroupBulkImpl::setGroupName(std::string name)
+void LLPanelGroupBulkImpl::setGroupName(const std::string& name)
{
if (mGroupName)
{
@@ -337,12 +338,7 @@ void LLPanelGroupBulk::updateGroupData()
void LLPanelGroupBulk::addUserCallback(const LLUUID& id, const LLAvatarName& av_name)
{
- std::vector<std::string> names;
- uuid_vec_t agent_ids;
- agent_ids.push_back(id);
- names.push_back(av_name.getAccountName());
-
- mImplementation->addUsers(names, agent_ids);
+ mImplementation->addUsers({ av_name.getAccountName() }, { id });
}
void LLPanelGroupBulk::setCloseCallback(void (*close_callback)(void*), void* data)
diff --git a/indra/newview/llpanelgroupbulkimpl.h b/indra/newview/llpanelgroupbulkimpl.h
index 5515bd6d9a..f186ae5373 100644
--- a/indra/newview/llpanelgroupbulkimpl.h
+++ b/indra/newview/llpanelgroupbulkimpl.h
@@ -59,7 +59,7 @@ public:
void handleSelection();
void addUsers(const std::vector<std::string>& names, const uuid_vec_t& agent_ids);
- void setGroupName(std::string name);
+ void setGroupName(const std::string& name);
public:
@@ -84,7 +84,7 @@ public:
void (*mCloseCallback)(void* data);
void* mCloseCallbackUserData;
- boost::signals2::connection mAvatarNameCacheConnection;
+ std::map<LLUUID, boost::signals2::connection> mAvatarNameCacheConnections;
// The following are for the LLPanelGroupInvite subclass only.
// These aren't needed for LLPanelGroupBulkBan, but if we have to add another
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index d964fa9170..44465cbc33 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -78,9 +78,9 @@ static LLPanelInjector<LLPanelMainInventory> t_inventory("panel_main_inventory")
class LLFloaterInventoryFinder : public LLFloater
{
public:
- LLFloaterInventoryFinder( LLPanelMainInventory* inventory_view);
- virtual void draw();
- /*virtual*/ bool postBuild();
+ LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view);
+ void draw();
+ bool postBuild();
void changeFilter(LLInventoryFilter* filter);
void updateElementsFromFilter();
bool getCheckShowEmpty();
@@ -90,17 +90,35 @@ public:
void onCreatorSelfFilterCommit();
void onCreatorOtherFilterCommit();
- static void onTimeAgo(LLUICtrl*, void *);
- static void onCloseBtn(void* user_data);
- static void selectAllTypes(void* user_data);
- static void selectNoTypes(void* user_data);
+ void onTimeAgo();
+ void onCloseBtn();
+ void selectAllTypes();
+ void selectNoTypes();
private:
- LLPanelMainInventory* mPanelMainInventory;
- LLSpinCtrl* mSpinSinceDays;
- LLSpinCtrl* mSpinSinceHours;
- LLCheckBoxCtrl* mCreatorSelf;
- LLCheckBoxCtrl* mCreatorOthers;
- LLInventoryFilter* mFilter;
+ LLPanelMainInventory* mPanelMainInventory{ nullptr };
+ LLSpinCtrl* mSpinSinceDays{ nullptr };
+ LLSpinCtrl* mSpinSinceHours{ nullptr };
+ LLCheckBoxCtrl* mCreatorSelf{ nullptr };
+ LLCheckBoxCtrl* mCreatorOthers{ nullptr };
+ LLInventoryFilter* mFilter{ nullptr };
+
+ LLCheckBoxCtrl* mCheckAnimation{ nullptr };
+ LLCheckBoxCtrl* mCheckCallingCard{ nullptr };
+ LLCheckBoxCtrl* mCheckClothing{ nullptr };
+ LLCheckBoxCtrl* mCheckGesture{ nullptr };
+ LLCheckBoxCtrl* mCheckLandmark{ nullptr };
+ LLCheckBoxCtrl* mCheckMaterial{ nullptr };
+ LLCheckBoxCtrl* mCheckNotecard{ nullptr };
+ LLCheckBoxCtrl* mCheckObject{ nullptr };
+ LLCheckBoxCtrl* mCheckScript{ nullptr };
+ LLCheckBoxCtrl* mCheckSounds{ nullptr };
+ LLCheckBoxCtrl* mCheckTexture{ nullptr };
+ LLCheckBoxCtrl* mCheckSnapshot{ nullptr };
+ LLCheckBoxCtrl* mCheckSettings{ nullptr };
+ LLCheckBoxCtrl* mCheckShowEmpty{ nullptr };
+ LLCheckBoxCtrl* mCheckSinceLogoff{ nullptr };
+
+ LLRadioGroup* mRadioDateSearchDirection{ nullptr };
};
///----------------------------------------------------------------------------
@@ -734,7 +752,6 @@ bool LLPanelMainInventory::filtersVisible(void* user_data)
void LLPanelMainInventory::onClearSearch()
{
bool initially_active = false;
- LLFloater *finder = getFinder();
if (mActivePanel && (getActivePanel() != mWornItemsPanel))
{
initially_active = mActivePanel->getFilter().isNotDefault();
@@ -743,9 +760,9 @@ void LLPanelMainInventory::onClearSearch()
mActivePanel->setFilterLinks(LLInventoryFilter::FILTERLINK_INCLUDE_LINKS);
}
- if (finder)
+ if (LLFloaterInventoryFinder* finder = getFinder())
{
- LLFloaterInventoryFinder::selectAllTypes(finder);
+ finder->selectAllTypes();
}
// re-open folders that were initially open in case filter was active
@@ -1145,36 +1162,53 @@ bool LLFloaterInventoryFinder::postBuild()
const LLRect& viewrect = mPanelMainInventory->getRect();
setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight()));
- childSetAction("All", selectAllTypes, this);
- childSetAction("None", selectNoTypes, this);
+ childSetAction("All", [this](LLUICtrl*, const LLSD&) { selectAllTypes(); });
+ childSetAction("None", [this](LLUICtrl*, const LLSD&) { selectNoTypes(); });
mSpinSinceHours = getChild<LLSpinCtrl>("spin_hours_ago");
- childSetCommitCallback("spin_hours_ago", onTimeAgo, this);
+ mSpinSinceHours->setCommitCallback([this](LLUICtrl*, const LLSD&) { onTimeAgo(); });
mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago");
- childSetCommitCallback("spin_days_ago", onTimeAgo, this);
+ mSpinSinceDays->setCommitCallback([this](LLUICtrl*, const LLSD&) { onTimeAgo(); });
mCreatorSelf = getChild<LLCheckBoxCtrl>("check_created_by_me");
mCreatorOthers = getChild<LLCheckBoxCtrl>("check_created_by_others");
mCreatorSelf->setCommitCallback(boost::bind(&LLFloaterInventoryFinder::onCreatorSelfFilterCommit, this));
mCreatorOthers->setCommitCallback(boost::bind(&LLFloaterInventoryFinder::onCreatorOtherFilterCommit, this));
- childSetAction("Close", onCloseBtn, this);
+ mCheckAnimation = getChild<LLCheckBoxCtrl>("check_animation");
+ mCheckCallingCard = getChild<LLCheckBoxCtrl>("check_calling_card");
+ mCheckClothing = getChild<LLCheckBoxCtrl>("check_clothing");
+ mCheckGesture = getChild<LLCheckBoxCtrl>("check_gesture");
+ mCheckLandmark = getChild<LLCheckBoxCtrl>("check_landmark");
+ mCheckMaterial = getChild<LLCheckBoxCtrl>("check_material");
+ mCheckNotecard = getChild<LLCheckBoxCtrl>("check_notecard");
+ mCheckObject = getChild<LLCheckBoxCtrl>("check_object");
+ mCheckScript = getChild<LLCheckBoxCtrl>("check_script");
+ mCheckSounds = getChild<LLCheckBoxCtrl>("check_sound");
+ mCheckTexture = getChild<LLCheckBoxCtrl>("check_texture");
+ mCheckSnapshot = getChild<LLCheckBoxCtrl>("check_snapshot");
+ mCheckSettings = getChild<LLCheckBoxCtrl>("check_settings");
+ mCheckShowEmpty = getChild<LLCheckBoxCtrl>("check_show_empty");
+ mCheckSinceLogoff = getChild<LLCheckBoxCtrl>("check_since_logoff");
+
+ mRadioDateSearchDirection = getChild<LLRadioGroup>("date_search_direction");
+
+ childSetAction("Close", [this](LLUICtrl*, const LLSD&) { onCloseBtn(); });
updateElementsFromFilter();
+
return true;
}
-void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data)
-{
- LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data;
- if (!self) return;
- if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() )
+void LLFloaterInventoryFinder::onTimeAgo()
+{
+ if (mSpinSinceDays->get() || mSpinSinceHours->get())
{
- self->getChild<LLUICtrl>("check_since_logoff")->setValue(false);
+ mCheckSinceLogoff->setValue(false);
- U32 days = (U32)self->mSpinSinceDays->get();
- U32 hours = (U32)self->mSpinSinceHours->get();
+ U32 days = (U32)mSpinSinceDays->get();
+ U32 hours = (U32)mSpinSinceHours->get();
if (hours >= 24)
{
// Try to handle both cases of spinner clicking and text input in a sensible fashion as best as possible.
@@ -1190,11 +1224,11 @@ void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data)
days = hours / 24;
}
hours = (U32)hours % 24;
- self->mSpinSinceHours->setFocus(false);
- self->mSpinSinceDays->setFocus(false);
- self->mSpinSinceDays->set((F32)days);
- self->mSpinSinceHours->set((F32)hours);
- self->mSpinSinceHours->setFocus(true);
+ mSpinSinceHours->setFocus(false);
+ mSpinSinceDays->setFocus(false);
+ mSpinSinceDays->set((F32)days);
+ mSpinSinceHours->set((F32)hours);
+ mSpinSinceHours->setFocus(true);
}
}
}
@@ -1223,29 +1257,28 @@ void LLFloaterInventoryFinder::updateElementsFromFilter()
// update the ui elements
setTitle(mFilter->getName());
- getChild<LLUICtrl>("check_animation")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION));
-
- getChild<LLUICtrl>("check_calling_card")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD));
- getChild<LLUICtrl>("check_clothing")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE));
- getChild<LLUICtrl>("check_gesture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE));
- getChild<LLUICtrl>("check_landmark")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK));
- getChild<LLUICtrl>("check_material")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_MATERIAL));
- getChild<LLUICtrl>("check_notecard")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD));
- getChild<LLUICtrl>("check_object")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT));
- getChild<LLUICtrl>("check_script")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LSL));
- getChild<LLUICtrl>("check_sound")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND));
- getChild<LLUICtrl>("check_texture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE));
- getChild<LLUICtrl>("check_snapshot")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT));
- getChild<LLUICtrl>("check_settings")->setValue((S32)(filter_types & 0x1 << LLInventoryType::IT_SETTINGS));
- getChild<LLUICtrl>("check_show_empty")->setValue(show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS);
-
- getChild<LLUICtrl>("check_created_by_me")->setValue(show_created_by_me);
- getChild<LLUICtrl>("check_created_by_others")->setValue(show_created_by_others);
-
- getChild<LLUICtrl>("check_since_logoff")->setValue(mFilter->isSinceLogoff());
+ mCheckAnimation->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION));
+ mCheckCallingCard->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD));
+ mCheckClothing->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE));
+ mCheckGesture->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE));
+ mCheckLandmark->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK));
+ mCheckMaterial->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_MATERIAL));
+ mCheckNotecard->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD));
+ mCheckObject->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT));
+ mCheckScript->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_LSL));
+ mCheckSounds->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND));
+ mCheckTexture->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE));
+ mCheckSnapshot->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT));
+ mCheckSettings->setValue((S32)(filter_types & 0x1 << LLInventoryType::IT_SETTINGS));
+ mCheckShowEmpty->setValue(show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS);
+
+ mCreatorSelf->setValue(show_created_by_me);
+ mCreatorOthers->setValue(show_created_by_others);
+
+ mCheckSinceLogoff->setValue(mFilter->isSinceLogoff());
mSpinSinceHours->set((F32)(hours % 24));
mSpinSinceDays->set((F32)(hours / 24));
- getChild<LLRadioGroup>("date_search_direction")->setSelectedIndex(date_search_direction);
+ mRadioDateSearchDirection->setSelectedIndex(date_search_direction);
}
void LLFloaterInventoryFinder::draw()
@@ -1253,80 +1286,80 @@ void LLFloaterInventoryFinder::draw()
U64 filter = 0xffffffffffffffffULL;
bool filtered_by_all_types = true;
- if (!getChild<LLUICtrl>("check_animation")->getValue())
+ if (!mCheckAnimation->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_ANIMATION);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_calling_card")->getValue())
+ if (!mCheckCallingCard->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_clothing")->getValue())
+ if (!mCheckClothing->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_WEARABLE);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_gesture")->getValue())
+ if (!mCheckGesture->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_GESTURE);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_landmark")->getValue())
+ if (!mCheckLandmark->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_LANDMARK);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_material")->getValue())
+ if (!mCheckMaterial->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_MATERIAL);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_notecard")->getValue())
+ if (!mCheckNotecard->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_NOTECARD);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_object")->getValue())
+ if (!mCheckObject->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_OBJECT);
filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_script")->getValue())
+ if (!mCheckScript->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_LSL);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_sound")->getValue())
+ if (!mCheckSounds->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_SOUND);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_texture")->getValue())
+ if (!mCheckTexture->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_TEXTURE);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_snapshot")->getValue())
+ if (!mCheckSnapshot->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT);
filtered_by_all_types = false;
}
- if (!getChild<LLUICtrl>("check_settings")->getValue())
+ if (!mCheckSettings->getValue())
{
filter &= ~(0x1 << LLInventoryType::IT_SETTINGS);
filtered_by_all_types = false;
@@ -1444,65 +1477,56 @@ void LLFloaterInventoryFinder::onCreatorOtherFilterCommit()
bool LLFloaterInventoryFinder::getCheckShowEmpty()
{
- return getChild<LLUICtrl>("check_show_empty")->getValue();
+ return mCheckShowEmpty->getValue();
}
bool LLFloaterInventoryFinder::getCheckSinceLogoff()
{
- return getChild<LLUICtrl>("check_since_logoff")->getValue();
+ return mCheckSinceLogoff->getValue();
}
U32 LLFloaterInventoryFinder::getDateSearchDirection()
{
- return getChild<LLRadioGroup>("date_search_direction")->getSelectedIndex();
+ return mRadioDateSearchDirection->getSelectedIndex();
}
-void LLFloaterInventoryFinder::onCloseBtn(void* user_data)
+void LLFloaterInventoryFinder::onCloseBtn()
{
- LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data;
- finderp->closeFloater();
+ closeFloater();
}
-// static
-void LLFloaterInventoryFinder::selectAllTypes(void* user_data)
-{
- LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
- if(!self) return;
-
- self->getChild<LLUICtrl>("check_animation")->setValue(true);
- self->getChild<LLUICtrl>("check_calling_card")->setValue(true);
- self->getChild<LLUICtrl>("check_clothing")->setValue(true);
- self->getChild<LLUICtrl>("check_gesture")->setValue(true);
- self->getChild<LLUICtrl>("check_landmark")->setValue(true);
- self->getChild<LLUICtrl>("check_material")->setValue(true);
- self->getChild<LLUICtrl>("check_notecard")->setValue(true);
- self->getChild<LLUICtrl>("check_object")->setValue(true);
- self->getChild<LLUICtrl>("check_script")->setValue(true);
- self->getChild<LLUICtrl>("check_sound")->setValue(true);
- self->getChild<LLUICtrl>("check_texture")->setValue(true);
- self->getChild<LLUICtrl>("check_snapshot")->setValue(true);
- self->getChild<LLUICtrl>("check_settings")->setValue(true);
+void LLFloaterInventoryFinder::selectAllTypes()
+{
+ mCheckAnimation->setValue(true);
+ mCheckCallingCard->setValue(true);
+ mCheckClothing->setValue(true);
+ mCheckGesture->setValue(true);
+ mCheckLandmark->setValue(true);
+ mCheckMaterial->setValue(true);
+ mCheckNotecard->setValue(true);
+ mCheckObject->setValue(true);
+ mCheckScript->setValue(true);
+ mCheckSounds->setValue(true);
+ mCheckTexture->setValue(true);
+ mCheckSnapshot->setValue(true);
+ mCheckSettings->setValue(true);
}
-//static
-void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
-{
- LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
- if(!self) return;
-
- self->getChild<LLUICtrl>("check_animation")->setValue(false);
- self->getChild<LLUICtrl>("check_calling_card")->setValue(false);
- self->getChild<LLUICtrl>("check_clothing")->setValue(false);
- self->getChild<LLUICtrl>("check_gesture")->setValue(false);
- self->getChild<LLUICtrl>("check_landmark")->setValue(false);
- self->getChild<LLUICtrl>("check_material")->setValue(false);
- self->getChild<LLUICtrl>("check_notecard")->setValue(false);
- self->getChild<LLUICtrl>("check_object")->setValue(false);
- self->getChild<LLUICtrl>("check_script")->setValue(false);
- self->getChild<LLUICtrl>("check_sound")->setValue(false);
- self->getChild<LLUICtrl>("check_texture")->setValue(false);
- self->getChild<LLUICtrl>("check_snapshot")->setValue(false);
- self->getChild<LLUICtrl>("check_settings")->setValue(false);
+void LLFloaterInventoryFinder::selectNoTypes()
+{
+ mCheckAnimation->setValue(false);
+ mCheckCallingCard->setValue(false);
+ mCheckClothing->setValue(false);
+ mCheckGesture->setValue(false);
+ mCheckLandmark->setValue(false);
+ mCheckMaterial->setValue(false);
+ mCheckNotecard->setValue(false);
+ mCheckObject->setValue(false);
+ mCheckScript->setValue(false);
+ mCheckSounds->setValue(false);
+ mCheckTexture->setValue(false);
+ mCheckSnapshot->setValue(false);
+ mCheckSettings->setValue(false);
}
//////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp
index 0ce1f0f9d3..0ce9ef7a7a 100644
--- a/indra/newview/llpanelpermissions.cpp
+++ b/indra/newview/llpanelpermissions.cpp
@@ -1175,6 +1175,7 @@ void LLPanelPermissions::onCommitName(LLUICtrl*, void* data)
{
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
new_item->rename(tb->getText());
+ new_item->setComplete(true); // to not err at updateServer
new_item->updateServer(false);
gInventory.updateItem(new_item);
gInventory.notifyObservers();
diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp
index a87ef4f0f9..c9626bf9ea 100644
--- a/indra/newview/llpanelprofilepicks.cpp
+++ b/indra/newview/llpanelprofilepicks.cpp
@@ -248,6 +248,8 @@ void LLPanelProfilePicks::onClickNewBtn()
select_tab(true).
label(pick_panel->getPickName()));
updateButtons();
+
+ pick_panel->addLocationChangedCallbacks();
}
void LLPanelProfilePicks::onClickDelete()
@@ -607,10 +609,12 @@ void LLPanelProfilePick::setAvatarId(const LLUUID& avatar_id)
{
mPickName->setEnabled(true);
mPickDescription->setEnabled(true);
+ mSetCurrentLocationButton->setVisible(true);
}
else
{
mSnapshotCtrl->setEnabled(false);
+ mSetCurrentLocationButton->setVisible(false);
}
}
@@ -621,6 +625,7 @@ bool LLPanelProfilePick::postBuild()
mSaveButton = getChild<LLButton>("save_changes_btn");
mCreateButton = getChild<LLButton>("create_changes_btn");
mCancelButton = getChild<LLButton>("cancel_changes_btn");
+ mSetCurrentLocationButton = getChild<LLButton>("set_to_curr_location_btn");
mSnapshotCtrl = getChild<LLTextureCtrl>("pick_snapshot");
mSnapshotCtrl->setCommitCallback(boost::bind(&LLPanelProfilePick::onSnapshotChanged, this));
@@ -633,6 +638,7 @@ bool LLPanelProfilePick::postBuild()
mSaveButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this));
mCreateButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSave, this));
mCancelButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickCancel, this));
+ mSetCurrentLocationButton->setCommitCallback(boost::bind(&LLPanelProfilePick::onClickSetLocation, this));
mPickName->setKeystrokeCallback(boost::bind(&LLPanelProfilePick::onPickChanged, this, _1), NULL);
mPickName->setEnabled(false);
@@ -811,6 +817,32 @@ bool LLPanelProfilePick::isDirty() const
return false;
}
+void LLPanelProfilePick::onClickSetLocation()
+{
+ // Save location for later use.
+ setPosGlobal(gAgent.getPositionGlobal());
+
+ std::string parcel_name, region_name;
+
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (parcel)
+ {
+ mParcelId = parcel->getID();
+ parcel_name = parcel->getName();
+ }
+
+ LLViewerRegion* region = gAgent.getRegion();
+ if (region)
+ {
+ region_name = region->getName();
+ }
+
+ setPickLocation(createLocationText(getLocationNotice(), parcel_name, region_name, getPosGlobal()));
+
+ mLocationChanged = true;
+ enableSaveButton(true);
+}
+
void LLPanelProfilePick::onClickSave()
{
if (mRegionCallbackConnection.connected())
@@ -821,6 +853,10 @@ void LLPanelProfilePick::onClickSave()
{
mParcelCallbackConnection.disconnect();
}
+ if (mLocationChanged)
+ {
+ onClickSetLocation();
+ }
sendUpdate();
mLocationChanged = false;
@@ -871,6 +907,12 @@ void LLPanelProfilePick::processParcelInfo(const LLParcelData& parcel_data)
}
}
+void LLPanelProfilePick::addLocationChangedCallbacks()
+{
+ mRegionCallbackConnection = gAgent.addRegionChangedCallback([this]() { onClickSetLocation(); });
+ mParcelCallbackConnection = gAgent.addParcelChangedCallback([this]() { onClickSetLocation(); });
+}
+
void LLPanelProfilePick::setParcelID(const LLUUID& parcel_id)
{
if (mParcelId != parcel_id)
diff --git a/indra/newview/llpanelprofilepicks.h b/indra/newview/llpanelprofilepicks.h
index b4d3eb010e..847ac57cea 100644
--- a/indra/newview/llpanelprofilepicks.h
+++ b/indra/newview/llpanelprofilepicks.h
@@ -141,6 +141,8 @@ public:
LLUUID getParcelID() const { return mParcelId; }
void setErrorStatus(S32 status, const std::string& reason) override {};
+ void addLocationChangedCallbacks();
+
protected:
/**
@@ -203,6 +205,11 @@ public:
void resetDirty() override;
/**
+ * Callback for "Set Location" button click
+ */
+ void onClickSetLocation();
+
+ /**
* Callback for "Save" and "Create" button click
*/
void onClickSave();
@@ -224,6 +231,7 @@ protected:
LLTextureCtrl* mSnapshotCtrl;
LLLineEditor* mPickName;
LLTextEditor* mPickDescription;
+ LLButton* mSetCurrentLocationButton;
LLButton* mSaveButton;
LLButton* mCreateButton;
LLButton* mCancelButton;
@@ -241,7 +249,7 @@ protected:
bool mLocationChanged;
bool mNewPick;
- bool mIsEditing;
+ bool mIsEditing;
void onDescriptionFocusReceived();
};
diff --git a/indra/newview/llsky.h b/indra/newview/llsky.h
index 32599dcee2..d06f181357 100644
--- a/indra/newview/llsky.h
+++ b/indra/newview/llsky.h
@@ -28,7 +28,6 @@
#define LL_LLSKY_H
#include "llmath.h"
-//#include "vmath.h"
#include "v3math.h"
#include "v4math.h"
#include "v4color.h"
diff --git a/indra/newview/llsprite.h b/indra/newview/llsprite.h
index 44439bd30c..d6e8e37ec9 100644
--- a/indra/newview/llsprite.h
+++ b/indra/newview/llsprite.h
@@ -27,8 +27,6 @@
#ifndef LL_LLSPRITE_H
#define LL_LLSPRITE_H
-////#include "vmath.h"
-//#include "llmath.h"
#include "v3math.h"
#include "v4math.h"
#include "v4color.h"
diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h
index 10a104730b..fc72ab7db7 100644
--- a/indra/newview/llsurface.h
+++ b/indra/newview/llsurface.h
@@ -27,7 +27,6 @@
#ifndef LL_LLSURFACE_H
#define LL_LLSURFACE_H
-//#include "vmath.h"
#include "v3math.h"
#include "v3dmath.h"
#include "v4math.h"
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 8cdc2e94f4..75b980d358 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -72,6 +72,7 @@
#include "llweb.h"
#include "pipeline.h" // setHighlightObject
#include "lluiusage.h"
+#include "llcallingcard.h"
extern bool gDebugClicks;
@@ -1501,6 +1502,134 @@ static void handle_click_action_play()
}
}
+bool LLToolPie::shouldAllowFirstMediaInteraction(const LLPickInfo& pick, bool moap_flag)
+{
+ // Early failure cases
+ if(!pick.getObject())
+ {
+ LL_WARNS() << "pick.getObject() is NULL" << LL_ENDL;
+ return false;
+ }
+
+ static LLCachedControl<S32> FirstClickPref(gSavedSettings, "MediaFirstClickInteract", 1);
+
+ // Special / early-exit cases first, then checks get more complex and needy as we go down
+ // Feature disabled
+ if(FirstClickPref == MEDIA_FIRST_CLICK_NONE)
+ {
+ LL_DEBUGS_ONCE() << "FirstClickPref == MEDIA_FIRST_CLICK_NONE" << LL_ENDL;
+ return false;
+ }
+ // Every check beyond this point requires PRIM_MEDIA_FIRST_CLICK_INTERACT to be TRUE
+ if(!moap_flag && !(FirstClickPref & MEDIA_FIRST_CLICK_BYPASS_MOAP_FLAG))
+ {
+ LL_DEBUGS_ONCE() << "PRIM_MEDIA_FIRST_CLICK_INTERACT not set" << LL_ENDL;
+ return false;
+ }
+ // Any object with PRIM_MEDIA_FIRST_CLICK_INTERACT set to TRUE
+ if(FirstClickPref & MEDIA_FIRST_CLICK_ANY)
+ {
+ LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_ANY" << LL_ENDL;
+ return true;
+ }
+
+ // The following checks require some object information so we obtain that
+ LLPointer<LLViewerObject> object = pick.getObject();
+ if(object.isNull())
+ {
+ LL_WARNS() << "pick.getObject() is NULL" << LL_ENDL;
+ return false;
+ }
+
+ // Own objects
+ if((FirstClickPref & MEDIA_FIRST_CLICK_OWN) && object->permYouOwner())
+ {
+ LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_OWN" << LL_ENDL;
+ return true;
+ }
+ // HUD attachments
+ if((FirstClickPref & MEDIA_FIRST_CLICK_HUD) && object->isHUDAttachment())
+ {
+ LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_HUD" << LL_ENDL;
+ return true;
+ }
+
+ // Further object detail required beyond this point
+ LLPermissions* perms = LLSelectMgr::getInstance()->getHoverNode()->mPermissions;
+ if(perms == nullptr)
+ {
+ LL_WARNS() << "LLSelectMgr::getInstance()->getHoverNode()->mPermissions is NULL" << LL_ENDL;
+ return false;
+ }
+ LLUUID owner_id = perms->getOwner();
+ LLUUID group_id = perms->getGroup();
+ if(owner_id.isNull() && group_id.isNull())
+ {
+ LL_WARNS() << "Owner information was not reliably obtained" << LL_ENDL;
+ return false;
+ }
+
+ // Check if the object is owned by a friend of the agent
+ if(FirstClickPref & MEDIA_FIRST_CLICK_FRIEND)
+ {
+ LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_FRIEND. id: " << owner_id << LL_ENDL;
+ return LLAvatarTracker::instance().isBuddy(owner_id);
+ }
+
+ // Check for objects set to or owned by the active group
+ if(FirstClickPref & MEDIA_FIRST_CLICK_GROUP)
+ {
+ // Get our active group
+ LLUUID active_group = gAgent.getGroupID();
+ if(active_group.notNull() && (active_group == group_id || active_group == owner_id))
+ {
+ LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_GROUP.Active group: " << active_group << ", group_id:" << group_id << ", owner_id: " << owner_id << LL_ENDL;
+ return true;
+ }
+ }
+
+ // This check ensures that the following conditions are met:
+ // 1. The object is located in the same parcel as the agent.
+ // 2. One of the following is true:
+ // a. The object is owned by the same group as the parcel.
+ // b. The object is set to the same group as the parcel.
+ // c. The object is owned by the same owner as the parcel.
+ // Conditions 2a and 2b are mutually exclusive, our check is the same for both.
+ if(FirstClickPref & MEDIA_FIRST_CLICK_LAND)
+ {
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if(parcel == nullptr)
+ {
+ LL_WARNS() << "LLViewerParcelMgr::getInstance()->getAgentParcel() is NULL" << LL_ENDL;
+ return false;
+ }
+
+ // Same parcel as the agent only
+ if(!LLViewerParcelMgr::getInstance()->inAgentParcel(object->getPositionGlobal()))
+ {
+ LL_WARNS_ONCE() << "Object is not in the same parcel as the agent" << LL_ENDL;
+ return false;
+ }
+
+ LLUUID parcel_owner = parcel->getOwnerID();
+ LLUUID parcel_group = parcel->getGroupID();
+
+ // The parcel owner and group can't both be null
+ if(parcel_owner.isNull() && parcel_group.isNull())
+ {
+ LL_WARNS() << "Parcel owner and group are both null" << LL_ENDL;
+ return false;
+ }
+
+ if(owner_id == parcel_owner || group_id == parcel_group)
+ {
+ LL_DEBUGS_ONCE() << "FirstClickPref & MEDIA_FIRST_CLICK_LAND. Parcel owner: " << parcel_owner << ", group_id:" << group_id << ", owner_id: " << owner_id << LL_ENDL;
+ return true;
+ }
+ }
+ return false;
+}
+
bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
{
//FIXME: how do we handle object in different parcel than us?
@@ -1535,6 +1664,16 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
{
// It's okay to give this a null impl
LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
+ if (shouldAllowFirstMediaInteraction(pick, mep->getFirstClickInteract()))
+ {
+ if (media_impl.notNull())
+ {
+ media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(true));
+ mMediaMouseCaptureID = mep->getMediaID();
+ setMouseCapture(true);
+ return true;
+ }
+ }
}
else
{
@@ -1647,7 +1786,7 @@ bool LLToolPie::handleMediaHover(const LLPickInfo& pick)
}
// If this is the focused media face, send mouse move events.
- if (LLViewerMediaFocus::getInstance()->isFocusedOnFace(objectp, pick.mObjectFace))
+ if (LLViewerMediaFocus::getInstance()->isFocusedOnFace(objectp, pick.mObjectFace) || (shouldAllowFirstMediaInteraction(pick, mep->getFirstClickInteract())))
{
media_impl->mouseMove(pick.mUVCoords, gKeyboard->currentMask(true));
gViewerWindow->setCursor(media_impl->getLastSetCursor());
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index b3884a6bfc..ee7945d16f 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -89,6 +89,22 @@ private:
void showVisualContextMenuEffect();
ECursorType cursorFromObject(LLViewerObject* object);
+ enum MediaFirstClickTypes
+ {
+ MEDIA_FIRST_CLICK_NONE = 0, // Special case: Feature is disabled
+ MEDIA_FIRST_CLICK_HUD = 1 << 0, // 0b00000001 (1)
+ MEDIA_FIRST_CLICK_OWN = 1 << 1, // 0b00000010 (2)
+ MEDIA_FIRST_CLICK_GROUP = 1 << 2, // 0b00000100 (4)
+ MEDIA_FIRST_CLICK_FRIEND = 1 << 3, // 0b00001000 (8)
+ MEDIA_FIRST_CLICK_LAND = 1 << 4, // 0b00010000 (16)
+
+ // Covers any object with PRIM_MEDIA_FIRST_CLICK_INTERACT (combines all previous flags)
+ MEDIA_FIRST_CLICK_ANY = ~(3<<30), // 0b00111111111111111111111111111111
+
+ // Covers all media regardless of other rules or PRIM_MEDIA_FIRST_CLICK_INTERACT
+ MEDIA_FIRST_CLICK_BYPASS_MOAP_FLAG = 1 << 30 // 0b01000000000000000000000000000000 (1073741824)
+ };
+ bool shouldAllowFirstMediaInteraction(const LLPickInfo& info, bool moap_flag);
bool handleMediaClick(const LLPickInfo& info);
bool handleMediaDblClick(const LLPickInfo& info);
bool handleMediaHover(const LLPickInfo& info);
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 10fa0fd3cd..6e790e4fca 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -100,13 +100,13 @@
extern LLPointer<LLViewerTexture> gStartTexture;
extern bool gShiftFrame;
-LLPointer<LLViewerTexture> gDisconnectedImagep = NULL;
+LLPointer<LLViewerTexture> gDisconnectedImagep = nullptr;
// used to toggle renderer back on after teleport
bool gTeleportDisplay = false;
LLFrameTimer gTeleportDisplayTimer;
LLFrameTimer gTeleportArrivalTimer;
-const F32 RESTORE_GL_TIME = 5.f; // Wait this long while reloading textures before we raise the curtain
+constexpr F32 RESTORE_GL_TIME = 5.f; // Wait this long while reloading textures before we raise the curtain
bool gForceRenderLandFence = false;
bool gDisplaySwapBuffers = false;
@@ -120,9 +120,9 @@ bool gSnapshotNoPost = false;
bool gShaderProfileFrame = false;
// This is how long the sim will try to teleport you before giving up.
-const F32 TELEPORT_EXPIRY = 15.0f;
+constexpr F32 TELEPORT_EXPIRY = 15.0f;
// Additional time (in seconds) to wait per attachment
-const F32 TELEPORT_EXPIRY_PER_ATTACHMENT = 3.f;
+constexpr F32 TELEPORT_EXPIRY_PER_ATTACHMENT = 3.f;
U32 gRecentFrameCount = 0; // number of 'recent' frames
LLFrameTimer gRecentFPSTime;
@@ -130,8 +130,6 @@ LLFrameTimer gRecentMemoryTime;
LLFrameTimer gAssetStorageLogTime;
// Rendering stuff
-void pre_show_depth_buffer();
-void post_show_depth_buffer();
void render_ui(F32 zoom_factor = 1.f, int subfield = 0);
void swap();
void render_hud_attachments();
@@ -212,7 +210,8 @@ void display_update_camera()
F32 final_far = gAgentCamera.mDrawDistance;
if (gCubeSnapshot)
{
- final_far = gSavedSettings.getF32("RenderReflectionProbeDrawDistance");
+ static LLCachedControl<F32> reflection_probe_draw_distance(gSavedSettings, "RenderReflectionProbeDrawDistance", 64.f);
+ final_far = reflection_probe_draw_distance();
}
else if (CAMERA_MODE_CUSTOMIZE_AVATAR == gAgentCamera.getCameraMode())
{
@@ -237,7 +236,7 @@ void display_update_camera()
void display_stats()
{
LL_PROFILE_ZONE_SCOPED;
- const F32 FPS_LOG_FREQUENCY = 10.f;
+ constexpr F32 FPS_LOG_FREQUENCY = 10.f;
if (gRecentFPSTime.getElapsedTimeF32() >= FPS_LOG_FREQUENCY)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - FPS");
@@ -246,7 +245,7 @@ void display_stats()
gRecentFrameCount = 0;
gRecentFPSTime.reset();
}
- F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
+ static LLCachedControl<F32> mem_log_freq(gSavedSettings, "MemoryLogFrequency", 600.f);
if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - Memory");
@@ -256,7 +255,7 @@ void display_stats()
LLMemory::logMemoryInfo(true) ;
gRecentMemoryTime.reset();
}
- const F32 ASSET_STORAGE_LOG_FREQUENCY = 60.f;
+ constexpr F32 ASSET_STORAGE_LOG_FREQUENCY = 60.f;
if (gAssetStorageLogTime.getElapsedTimeF32() >= ASSET_STORAGE_LOG_FREQUENCY)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("DS - Asset Storage");
@@ -572,8 +571,10 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot)
LLImageGL::updateStats(gFrameTimeSeconds);
- LLVOAvatar::sRenderName = gSavedSettings.getS32("AvatarNameTagMode");
- LLVOAvatar::sRenderGroupTitles = (gSavedSettings.getBOOL("NameTagShowGroupTitles") && gSavedSettings.getS32("AvatarNameTagMode"));
+ static LLCachedControl<S32> avatar_name_tag_mode(gSavedSettings, "AvatarNameTagMode", 1);
+ static LLCachedControl<bool> name_tag_show_group_titles(gSavedSettings, "NameTagShowGroupTitles", true);
+ LLVOAvatar::sRenderName = avatar_name_tag_mode;
+ LLVOAvatar::sRenderGroupTitles = name_tag_show_group_titles && avatar_name_tag_mode > 0;
gPipeline.mBackfaceCull = true;
gFrameCount++;
@@ -796,7 +797,7 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot)
}
gGL.setColorMask(true, true);
- glClearColor(0,0,0,0);
+ glClearColor(0.f, 0.f, 0.f, 0.f);
LLGLState::checkStates();
@@ -964,7 +965,7 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot)
gPipeline.mRT->deferredScreen.bindTarget();
if (gUseWireframe)
{
- F32 g = 0.5f;
+ constexpr F32 g = 0.5f;
glClearColor(g, g, g, 1.f);
}
else
@@ -983,11 +984,12 @@ void display(bool rebuild, F32 zoom_factor, int subfield, bool for_snapshot)
LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("display - 5")
LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
- if (gSavedSettings.getBOOL("RenderDepthPrePass"))
+ static LLCachedControl<bool> render_depth_pre_pass(gSavedSettings, "RenderDepthPrePass", false);
+ if (render_depth_pre_pass)
{
gGL.setColorMask(false, false);
- static const U32 types[] = {
+ constexpr U32 types[] = {
LLRenderPass::PASS_SIMPLE,
LLRenderPass::PASS_FULLBRIGHT,
LLRenderPass::PASS_SHINY
@@ -1201,7 +1203,7 @@ void display_cube_face()
gGL.setColorMask(true, true);
- glClearColor(0, 0, 0, 0);
+ glClearColor(0.f, 0.f, 0.f, 0.f);
gPipeline.generateSunShadow(*LLViewerCamera::getInstance());
glClear(GL_DEPTH_BUFFER_BIT); // | GL_STENCIL_BUFFER_BIT);
@@ -1237,7 +1239,7 @@ void display_cube_face()
}
else
{
- glClearColor(1, 0, 1, 1);
+ glClearColor(1.f, 0.f, 1.f, 1.f);
}
gPipeline.mRT->deferredScreen.clear();
@@ -1278,11 +1280,12 @@ void render_hud_attachments()
{
LLPipeline::sRenderingHUDs = true;
LLCamera hud_cam = *LLViewerCamera::getInstance();
- hud_cam.setOrigin(-1.f,0,0);
- hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1));
+ hud_cam.setOrigin(-1.f, 0.f, 0.f);
+ hud_cam.setAxes(LLVector3(1.f, 0.f, 0.f), LLVector3(0.f, 1.f, 0.f), LLVector3(0.f, 0.f, 1.f));
LLViewerCamera::updateFrustumPlanes(hud_cam, true);
- bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && gSavedSettings.getBOOL("RenderHUDParticles");
+ static LLCachedControl<bool> render_hud_particles(gSavedSettings, "RenderHUDParticles", false);
+ bool render_particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) && render_hud_particles;
//only render hud objects
gPipeline.pushRenderTypeMask();
@@ -1642,10 +1645,11 @@ void render_ui_3d()
stop_glerror();
gUIProgram.bind();
- gGL.color4f(1, 1, 1, 1);
+ gGL.color4f(1.f, 1.f, 1.f, 1.f);
// Coordinate axes
- if (gSavedSettings.getBOOL("ShowAxes"))
+ static LLCachedControl<bool> show_axes(gSavedSettings, "ShowAxes");
+ if (show_axes())
{
draw_axes();
}
@@ -1707,7 +1711,7 @@ void render_ui_2d()
gGL.pushMatrix();
S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2);
S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2);
- gGL.scalef(LLUI::getScaleFactor().mV[0], LLUI::getScaleFactor().mV[1], 1.f);
+ gGL.scalef(LLUI::getScaleFactor().mV[VX], LLUI::getScaleFactor().mV[VY], 1.f);
gGL.translatef((F32)half_width, (F32)half_height, 0.f);
F32 zoom = gAgentCamera.mHUDCurZoom;
gGL.scalef(zoom,zoom,1.f);
@@ -1729,7 +1733,7 @@ void render_ui_2d()
gPipeline.mUIScreen.bindTarget();
gGL.setColorMask(true, true);
{
- static const S32 pad = 8;
+ constexpr S32 pad = 8;
LLView::sDirtyRect.mLeft -= pad;
LLView::sDirtyRect.mRight += pad;
@@ -1782,8 +1786,6 @@ void render_ui_2d()
gViewerWindow->draw();
}
-
-
// reset current origin for font rendering, in case of tiling render
LLFontGL::sCurOrigin.set(0, 0);
}
@@ -1792,7 +1794,7 @@ void render_disconnected_background()
{
gUIProgram.bind();
- gGL.color4f(1,1,1,1);
+ gGL.color4f(1.f, 1.f, 1.f, 1.f);
if (!gDisconnectedImagep && gDisconnected)
{
LL_INFOS() << "Loading last bitmap..." << LL_ENDL;
@@ -1832,7 +1834,7 @@ void render_disconnected_background()
raw->expandToPowerOfTwo();
- gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), false );
+ gDisconnectedImagep = LLViewerTextureManager::getLocalTexture(raw.get(), false);
gStartTexture = gDisconnectedImagep;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
@@ -1867,6 +1869,5 @@ void render_disconnected_background()
void display_cleanup()
{
- gDisconnectedImagep = NULL;
+ gDisconnectedImagep = nullptr;
}
-
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index da03d3b015..e36ad0e722 100755
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -33,6 +33,7 @@
#include "llfloaterreg.h"
#include "llgl.h"
#include "llrender.h"
+#include "lluicolor.h"
#include "v4color.h"
#include "v2math.h"
@@ -50,8 +51,8 @@
#include "pipeline.h"
-static const U8 OVERLAY_IMG_COMPONENTS = 4;
-static const F32 LINE_WIDTH = 0.0625f;
+static constexpr U8 OVERLAY_IMG_COMPONENTS = 4;
+static constexpr F32 LINE_WIDTH = 0.0625f;
bool LLViewerParcelOverlay::sColorSetInitialized = false;
LLUIColor LLViewerParcelOverlay::sAvailColor;
@@ -91,7 +92,7 @@ LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_
// Initialize the GL texture with empty data.
//
// Create the base texture.
- U8 *raw = mImageRaw->getData();
+ U8* raw = mImageRaw->getData();
const S32 COUNT = mParcelGridsPerEdge * mParcelGridsPerEdge * OVERLAY_IMG_COMPONENTS;
for (S32 i = 0; i < COUNT; i++)
{
@@ -158,10 +159,10 @@ bool LLViewerParcelOverlay::encroachesOwned(const std::vector<LLBBox>& boxes) co
LLVector3 min = boxes[i].getMinAgent();
LLVector3 max = boxes[i].getMaxAgent();
- S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
- S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
- S32 top = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
- S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
+ S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
+ S32 top = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
+ S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
for (S32 row = top; row <= bottom; row++)
{
@@ -186,10 +187,10 @@ bool LLViewerParcelOverlay::encroachesOnUnowned(const std::vector<LLBBox>& boxes
LLVector3 min = boxes[i].getMinAgent();
LLVector3 max = boxes[i].getMaxAgent();
- S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
- S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
- S32 top = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
- S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
+ S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
+ S32 top = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
+ S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
for (S32 row = top; row <= bottom; row++)
{
@@ -223,10 +224,10 @@ bool LLViewerParcelOverlay::encroachesOnNearbyParcel(const std::vector<LLBBox>&
return true;
}
- S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
- S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
- S32 bottom = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
- S32 top = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
+ S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
+ S32 bottom = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
+ S32 top = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1.f));
const S32 GRIDS_PER_EDGE = mParcelGridsPerEdge;
@@ -348,11 +349,11 @@ void LLViewerParcelOverlay::updateOverlayTexture()
const LLColor4U auction = sAuctionColor.get();
// Create the base texture.
- U8 *raw = mImageRaw->getData();
+ U8* raw = mImageRaw->getData();
const S32 COUNT = mParcelGridsPerEdge * mParcelGridsPerEdge;
S32 max = mOverlayTextureIdx + mParcelGridsPerEdge;
if (max > COUNT) max = COUNT;
- S32 pixel_index = mOverlayTextureIdx*OVERLAY_IMG_COMPONENTS;
+ S32 pixel_index = mOverlayTextureIdx * OVERLAY_IMG_COMPONENTS;
S32 i;
for (i = mOverlayTextureIdx; i < max; i++)
{
@@ -361,7 +362,7 @@ void LLViewerParcelOverlay::updateOverlayTexture()
U8 r,g,b,a;
// Color stored in low three bits
- switch( ownership & 0x7 )
+ switch (ownership & 0x7)
{
case PARCEL_PUBLIC:
r = avail.mV[VRED];
@@ -407,10 +408,10 @@ void LLViewerParcelOverlay::updateOverlayTexture()
break;
}
- raw[pixel_index + 0] = (U8)r;
- raw[pixel_index + 1] = (U8)g;
- raw[pixel_index + 2] = (U8)b;
- raw[pixel_index + 3] = (U8)a;
+ raw[pixel_index + VRED] = (U8)r;
+ raw[pixel_index + VGREEN] = (U8)g;
+ raw[pixel_index + VBLUE] = (U8)b;
+ raw[pixel_index + VALPHA] = (U8)a;
pixel_index += OVERLAY_IMG_COMPONENTS;
}
@@ -431,11 +432,10 @@ void LLViewerParcelOverlay::updateOverlayTexture()
}
}
-
-void LLViewerParcelOverlay::uncompressLandOverlay(S32 chunk, U8 *packed_overlay)
+void LLViewerParcelOverlay::uncompressLandOverlay(S32 chunk, U8* packed_overlay)
{
// Unpack the message data into the ownership array
- S32 size = mParcelGridsPerEdge * mParcelGridsPerEdge;
+ S32 size = mParcelGridsPerEdge * mParcelGridsPerEdge;
S32 chunk_size = size / PARCEL_OVERLAY_CHUNKS;
memcpy(mOwnership + chunk*chunk_size, packed_overlay, chunk_size); /*Flawfinder: ignore*/
@@ -460,7 +460,7 @@ void LLViewerParcelOverlay::updatePropertyLines()
mEdges.clear();
- const F32 GRID_STEP = PARCEL_GRID_STEP_METERS;
+ constexpr F32 GRID_STEP = PARCEL_GRID_STEP_METERS;
const S32 GRIDS_PER_EDGE = mParcelGridsPerEdge;
for (S32 row = 0; row < GRIDS_PER_EDGE; row++)
@@ -537,16 +537,16 @@ void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F3
auto split = [&](const LLVector3& start, F32 x, F32 y, F32 z, F32 part)
{
- F32 new_x = start.mV[0] + (x - start.mV[0]) * part;
- F32 new_y = start.mV[1] + (y - start.mV[1]) * part;
- F32 new_z = start.mV[2] + (z - start.mV[2]) * 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);
};
auto checkForSplit = [&]()
{
const LLVector3& last_outside = edge.vertices.back();
- F32 z0 = last_outside.mV[2];
+ F32 z0 = last_outside.mV[VZ];
F32 z1 = outside_z;
if ((z0 >= water_z && z1 >= water_z) || (z0 < water_z && z1 < water_z))
return;
@@ -581,7 +581,7 @@ void LLViewerParcelOverlay::addPropertyLine(F32 start_x, F32 start_y, F32 dx, F3
outside_y += dy * (dy - LINE_WIDTH);
// Middle part, full width
- const S32 GRID_STEP = (S32)PARCEL_GRID_STEP_METERS;
+ constexpr S32 GRID_STEP = (S32)PARCEL_GRID_STEP_METERS;
for (S32 i = 1; i < GRID_STEP; i++)
{
inside_z = land.resolveHeightRegion( inside_x, inside_y );
@@ -711,7 +711,7 @@ void LLViewerParcelOverlay::renderPropertyLines()
bool render_hidden = LLSelectMgr::sRenderHiddenSelections && LLFloaterReg::instanceVisible("build");
- const F32 PROPERTY_LINE_CLIP_DIST_SQUARED = 256.f * 256.f;
+ constexpr F32 PROPERTY_LINE_CLIP_DIST_SQUARED = 256.f * 256.f;
for (const Edge& edge : mEdges)
{
@@ -744,7 +744,7 @@ void LLViewerParcelOverlay::renderPropertyLines()
else
{
LLVector3 visible = vertex;
- visible.mV[2] = water_z;
+ visible.mV[VZ] = water_z;
gGL.vertex3fv(visible.mV);
}
}
@@ -758,7 +758,7 @@ void LLViewerParcelOverlay::renderPropertyLines()
gGL.begin(LLRender::TRIANGLE_STRIP);
LLColor4U color = edge.color;
- color.mV[3] /= 4;
+ color.mV[VALPHA] /= 4;
gGL.color4ubv(color.mV);
for (const LLVector3& vertex : edge.vertices)
@@ -792,7 +792,7 @@ void grid_2d_part_lines(const F32 left, const F32 top, const F32 right, const F3
gGL.end();
}
-void LLViewerParcelOverlay::renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32 *parcel_outline_color)
+void LLViewerParcelOverlay::renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color)
{
static LLCachedControl<bool> show(gSavedSettings, "MiniMapShowPropertyLines");
@@ -803,8 +803,8 @@ void LLViewerParcelOverlay::renderPropertyLinesOnMinimap(F32 scale_pixels_per_me
LLVector3 origin_agent = mRegion->getOriginAgent();
LLVector3 rel_region_pos = origin_agent - gAgentCamera.getCameraPositionAgent();
- F32 region_left = rel_region_pos.mV[0] * scale_pixels_per_meter;
- F32 region_bottom = rel_region_pos.mV[1] * scale_pixels_per_meter;
+ F32 region_left = rel_region_pos.mV[VX] * scale_pixels_per_meter;
+ F32 region_bottom = rel_region_pos.mV[VY] * scale_pixels_per_meter;
F32 map_parcel_width = PARCEL_GRID_STEP_METERS * scale_pixels_per_meter;
const S32 GRIDS_PER_EDGE = mParcelGridsPerEdge;
diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h
index 03ae464cb8..50bef02ddf 100644
--- a/indra/newview/llviewerparceloverlay.h
+++ b/indra/newview/llviewerparceloverlay.h
@@ -34,12 +34,11 @@
#include "llframetimer.h"
#include "lluuid.h"
#include "llviewertexture.h"
-#include "llgl.h"
-#include "lluicolor.h"
class LLViewerRegion;
class LLVector3;
class LLColor4U;
+class LLUIColor;
class LLVector2;
class LLViewerParcelOverlay : public LLGLUpdate
@@ -65,19 +64,18 @@ public:
bool isSoundLocal(const LLVector3& pos) const;
- bool isBuildCameraAllowed(const LLVector3& pos) const;
F32 getOwnedRatio() const;
// Returns the number of vertices drawn
void renderPropertyLines();
void renderPropertyLinesOnMinimap(F32 scale_pixels_per_meter, const F32* parcel_outline_color);
- U8 ownership( const LLVector3& pos) const;
- U8 parcelLineFlags( const LLVector3& pos) const;
+ U8 ownership(const LLVector3& pos) const;
+ U8 parcelLineFlags(const LLVector3& pos) const;
U8 parcelLineFlags(S32 row, S32 col) const;
// MANIPULATE
- void uncompressLandOverlay(S32 chunk, U8 *compressed_overlay);
+ void uncompressLandOverlay(S32 chunk, U8* compressed_overlay);
// Indicate property lines and overlay texture need to be rebuilt.
void setDirty();
@@ -88,8 +86,7 @@ public:
private:
// This is in parcel rows and columns, not grid rows and columns
// Stored in bottom three bits.
- U8 ownership(S32 row, S32 col) const
- { return parcelFlags(row, col, (U8)0x7); }
+ U8 ownership(S32 row, S32 col) const { return parcelFlags(row, col, (U8)0x7); }
U8 parcelFlags(S32 row, S32 col, U8 flags) const;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index b9f52e11aa..a085bc4d91 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -38,7 +38,6 @@
#include "llregionhandle.h"
#include "llsurface.h"
#include "message.h"
-//#include "vmath.h"
#include "v3math.h"
#include "v4math.h"
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index ad503cbac7..b035da1f01 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -220,7 +220,16 @@ SimMeasurement<F64Megabytes > SIM_PHYSICS_MEM("physicsmemoryallocated", "", LL
LLTrace::SampleStatHandle<F64Milliseconds > FRAMETIME_JITTER("frametimejitter", "Average delta between successive frame times"),
FRAMETIME("frametime", "Measured frame time"),
- SIM_PING("simpingstat");
+ SIM_PING("simpingstat"),
+ FRAMETIME_JITTER_99TH("frametimejitter99", "99th percentile of frametime jitter over the last 5 seconds."),
+ FRAMETIME_JITTER_95TH("frametimejitter95", "99th percentile of frametime jitter over the last 5 seconds."),
+ FRAMETIME_99TH("frametime99", "99th percentile of frametime over the last 5 seconds."),
+ FRAMETIME_95TH("frametime95", "99th percentile of frametime over the last 5 seconds."),
+ FRAMETIME_JITTER_CUMULATIVE("frametimejitcumulative", "Cumulative frametime jitter over the session."),
+ FRAMETIME_JITTER_STDDEV("frametimejitterstddev", "Standard deviation of frametime jitter in a 5 second period."),
+ FRAMETIME_STDDEV("frametimestddev", "Standard deviation of frametime in a 5 second period.");
+
+LLTrace::SampleStatHandle<U32> FRAMETIME_JITTER_EVENTS("frametimeevents", "Number of frametime events in the session. Applies when jitter exceeds 10% of the previous frame.");
LLTrace::EventStatHandle<LLUnit<F64, LLUnits::Meters> > AGENT_POSITION_SNAP("agentpositionsnap", "agent position corrections");
@@ -264,6 +273,38 @@ void LLViewerStats::resetStats()
getRecording().reset();
}
+// Helper for calculating Nth percentile with linear interpolation
+template<typename T>
+T calcPercentile(const std::vector<T>& sorted, double percent)
+{
+ if (sorted.empty())
+ return T(0);
+ double idx = percent * (sorted.size() - 1);
+ size_t idx_below = static_cast<size_t>(std::floor(idx));
+ size_t idx_above = static_cast<size_t>(std::ceil(idx));
+ if (idx_below == idx_above)
+ return sorted[idx_below];
+ double weight_above = idx - idx_below;
+ return sorted[idx_below] * (1.0 - weight_above) + sorted[idx_above] * weight_above;
+}
+
+template<typename T>
+T calcStddev(const std::vector<T>& values)
+{
+ if (values.size() < 2)
+ return T(0);
+ double sum = 0, sq_sum = 0;
+ for (const auto& v : values)
+ {
+ double d = v.value();
+ sum += d;
+ sq_sum += d * d;
+ }
+ double mean = sum / values.size();
+ double variance = (sq_sum / values.size()) - (mean * mean);
+ return T(std::sqrt(variance));
+}
+
void LLViewerStats::updateFrameStats(const F64Seconds time_diff)
{
if (gFrameCount && mLastTimeDiff > (F64Seconds)0.0)
@@ -272,8 +313,50 @@ void LLViewerStats::updateFrameStats(const F64Seconds time_diff)
// old stats that were never really used
F64Seconds jit = (F64Seconds)std::fabs((mLastTimeDiff - time_diff));
sample(LLStatViewer::FRAMETIME_JITTER, jit);
- }
+ mTotalFrametimeJitter += jit;
+ sample(LLStatViewer::FRAMETIME_JITTER_CUMULATIVE, mTotalFrametimeJitter);
+ static LLCachedControl<F32> frameTimeEventThreshold(gSavedSettings, "StatsFrametimeEventThreshold", 0.1f);
+
+ if (time_diff - mLastTimeDiff > mLastTimeDiff * frameTimeEventThreshold())
+ {
+ sample(LLStatViewer::FRAMETIME_JITTER_EVENTS, mFrameJitterEvents++);
+ }
+
+ mFrameTimes.push_back(time_diff);
+ mFrameTimesJitter.push_back(jit);
+
+ mLastFrameTimeSample += time_diff;
+
+ static LLCachedControl<S32> frameTimeSampleSeconds(gSavedSettings, "StatsFrametimeSampleSeconds", 5);
+
+ if (mLastFrameTimeSample >= frameTimeSampleSeconds())
+ {
+ std::sort(mFrameTimes.begin(), mFrameTimes.end());
+ std::sort(mFrameTimesJitter.begin(), mFrameTimesJitter.end());
+
+ // Use new helpers for calculations
+ F64Seconds frame_time_stddev = calcStddev(mFrameTimes);
+ sample(LLStatViewer::FRAMETIME_STDDEV, frame_time_stddev);
+
+ F64Seconds ninety_ninth_percentile = calcPercentile(mFrameTimes, 0.99);
+ F64Seconds ninety_fifth_percentile = calcPercentile(mFrameTimes, 0.95);
+ sample(LLStatViewer::FRAMETIME_99TH, ninety_ninth_percentile);
+ sample(LLStatViewer::FRAMETIME_95TH, ninety_fifth_percentile);
+
+ frame_time_stddev = calcStddev(mFrameTimesJitter);
+ sample(LLStatViewer::FRAMETIME_JITTER_STDDEV, frame_time_stddev);
+
+ ninety_ninth_percentile = calcPercentile(mFrameTimesJitter, 0.99);
+ ninety_fifth_percentile = calcPercentile(mFrameTimesJitter, 0.95);
+ sample(LLStatViewer::FRAMETIME_JITTER_99TH, ninety_ninth_percentile);
+ sample(LLStatViewer::FRAMETIME_JITTER_95TH, ninety_fifth_percentile);
+
+ mFrameTimes.clear();
+ mFrameTimesJitter.clear();
+ mLastFrameTimeSample = F64Seconds(0);
+ }
+ }
mLastTimeDiff = time_diff;
}
diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h
index 8aed1c537e..1d84ab9fbc 100644
--- a/indra/newview/llviewerstats.h
+++ b/indra/newview/llviewerstats.h
@@ -275,6 +275,13 @@ private:
LLTrace::Recording mRecording;
F64Seconds mLastTimeDiff; // used for time stat updates
+ F64Seconds mTotalFrametimeJitter;
+
+ U32 mFrameJitterEvents;
+
+ F64Seconds mLastFrameTimeSample; // used for frame time stats
+ std::vector<F64Seconds> mFrameTimes; // used for frame time stats
+ std::vector<F64Seconds> mFrameTimesJitter; // used for frame time jitter stats
};
static const F32 SEND_STATS_PERIOD = 300.0f;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index f174e16624..7e14c621ad 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -921,6 +921,7 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
bool on_screen = false;
U32 face_count = 0;
+ U32 max_faces_to_check = 1024;
// get adjusted bias based on image resolution
LLImageGL* img = imagep->getGLTexture();
@@ -933,13 +934,15 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
{
- for (S32 fi = 0; fi < imagep->getNumFaces(i); ++fi)
+ face_count += imagep->getNumFaces(i);
+ S32 faces_to_check = (face_count > max_faces_to_check) ? 0 : imagep->getNumFaces(i);
+
+ for (S32 fi = 0; fi < faces_to_check; ++fi)
{
LLFace* face = (*(imagep->getFaceList(i)))[fi];
if (face && face->getViewerObject())
{
- ++face_count;
F32 radius;
F32 cos_angle_to_view_dir;
@@ -1002,11 +1005,10 @@ void LLViewerTextureList::updateImageDecodePriority(LLViewerFetchedTexture* imag
}
}
- if (face_count > 1024)
+ if (face_count > max_faces_to_check)
{ // this texture is used in so many places we should just boost it and not bother checking its vsize
// this is especially important because the above is not time sliced and can hit multiple ms for a single texture
- imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_HIGH);
- // Do we ever remove it? This also sets texture nodelete!
+ max_vsize = MAX_IMAGE_AREA;
}
if (imagep->getType() == LLViewerTexture::LOD_TEXTURE && imagep->getBoostLevel() == LLViewerTexture::BOOST_NONE)
@@ -1205,6 +1207,8 @@ F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time)
enditer = iter;
LLViewerFetchedTexture *imagep = *curiter;
imagep->loadFromFastCache();
+ if (timer.getElapsedTimeF32() > max_time)
+ break;
}
mFastCacheList.erase(mFastCacheList.begin(), enditer);
return timer.getElapsedTimeF32();
@@ -1316,7 +1320,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
LLTimer timer;
//loading from fast cache
- updateImagesLoadingFastCache(max_time);
+ max_time -= updateImagesLoadingFastCache(max_time);
// Update texture stats and priorities
std::vector<LLPointer<LLViewerFetchedTexture> > image_list;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 2b02d5165f..a2e77e9257 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -4782,7 +4782,18 @@ void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_save
#else
boost::filesystem::path b_path(lastSnapshotDir);
#endif
- if (!boost::filesystem::is_directory(b_path))
+ boost::system::error_code ec;
+ if (!boost::filesystem::is_directory(b_path, ec) || ec.failed())
+ {
+ LLSD args;
+ args["PATH"] = lastSnapshotDir;
+ LLNotificationsUtil::add("SnapshotToLocalDirNotExist", args);
+ resetSnapshotLoc();
+ failure_cb();
+ return;
+ }
+ boost::filesystem::space_info b_space = boost::filesystem::space(b_path, ec);
+ if (ec.failed())
{
LLSD args;
args["PATH"] = lastSnapshotDir;
@@ -4791,7 +4802,6 @@ void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_save
failure_cb();
return;
}
- boost::filesystem::space_info b_space = boost::filesystem::space(b_path);
if (b_space.free < image->getDataSize())
{
LLSD args;
@@ -4808,6 +4818,8 @@ void LLViewerWindow::saveImageLocal(LLImageFormatted *image, const snapshot_save
LLNotificationsUtil::add("SnapshotToComputerFailed", args);
failure_cb();
+
+ // Shouldn't there be a return here?
}
// Look for an unused file name
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 7ea70a781b..7928c50807 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -6349,13 +6349,13 @@ const LLUUID& LLVOAvatar::getID() const
// getJoint()
//-----------------------------------------------------------------------------
// RN: avatar joints are multi-rooted to include screen-based attachments
-LLJoint *LLVOAvatar::getJoint( const std::string &name )
+LLJoint* LLVOAvatar::getJoint(std::string_view name)
{
joint_map_t::iterator iter = mJointMap.find(name);
- LLJoint* jointp = NULL;
+ LLJoint* jointp = nullptr;
- if (iter == mJointMap.end() || iter->second == NULL)
+ if (iter == mJointMap.end() || iter->second == nullptr)
{ //search for joint and cache found joint in lookup table
if (mJointAliasMap.empty())
{
@@ -6372,7 +6372,7 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )
canonical_name = name;
}
jointp = mRoot->findJoint(canonical_name);
- mJointMap[name] = jointp;
+ mJointMap[std::string(name)] = jointp;
}
else
{ //return cached pointer
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index ab27c5752d..9eb8d3f880 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -202,7 +202,7 @@ public:
void startDefaultMotions();
void dumpAnimationState();
- virtual LLJoint* getJoint(const std::string &name);
+ virtual LLJoint* getJoint(std::string_view name);
LLJoint* getJoint(S32 num);
void initAllJoints();
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 90ff4067f2..ebba9ba291 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -697,17 +697,17 @@ void LLVOAvatarSelf::idleUpdate(LLAgent &agent, const F64 &time)
}
// virtual
-LLJoint *LLVOAvatarSelf::getJoint(const std::string &name)
+LLJoint* LLVOAvatarSelf::getJoint(std::string_view name)
{
std::lock_guard lock(mJointMapMutex);
- LLJoint *jointp = NULL;
+ LLJoint* jointp = nullptr;
jointp = LLVOAvatar::getJoint(name);
if (!jointp && mScreenp)
{
jointp = mScreenp->findJoint(name);
if (jointp)
{
- mJointMap[name] = jointp;
+ mJointMap[std::string(name)] = jointp;
}
}
if (jointp && jointp != mScreenp && jointp != mRoot)
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index f9bea41b1d..f7cd974ab0 100644
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -90,7 +90,7 @@ public:
/*virtual*/ bool hasMotionFromSource(const LLUUID& source_id);
/*virtual*/ void stopMotionFromSource(const LLUUID& source_id);
/*virtual*/ void requestStopMotion(LLMotion* motion);
- /*virtual*/ LLJoint* getJoint(const std::string &name);
+ /*virtual*/ LLJoint* getJoint(std::string_view name);
/*virtual*/ void renderJoints();
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index d0bdcf132f..78e2257e56 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -2643,6 +2643,17 @@ void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool m
}
viewer_media_t media_impl = LLViewerMedia::getInstance()->updateMediaImpl(mep, previous_url, update_from_self);
+ static LLCachedControl<bool> media_autoplay_huds(gSavedSettings, "MediaAutoPlayHuds", true);
+ bool was_loaded = media_impl->hasMedia();
+ if (isHUDAttachment() && media_autoplay_huds && !was_loaded)
+ {
+ std::string url = mep->getCurrentURL();
+ if (media_impl->getCurrentMediaURL() != url)
+ {
+ media_impl->navigateTo(url, "", false, true);
+ }
+ }
+
addMediaImpl(media_impl, texture_index) ;
}
else
diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp
index 0a1d346266..bf171fe954 100644
--- a/indra/newview/llwatchdog.cpp
+++ b/indra/newview/llwatchdog.cpp
@@ -29,7 +29,7 @@
#include "llwatchdog.h"
#include "llthread.h"
-const U32 WATCHDOG_SLEEP_TIME_USEC = 1000000;
+constexpr U32 WATCHDOG_SLEEP_TIME_USEC = 1000000U;
// This class runs the watchdog timing thread.
class LLWatchdogTimerThread : public LLThread
@@ -51,7 +51,7 @@ public:
mSleepMsecs = 1;
}
- /* virtual */ void run()
+ void run() override
{
while(!mStopping)
{
@@ -83,7 +83,7 @@ void LLWatchdogEntry::start()
void LLWatchdogEntry::stop()
{
// this can happen very late in the shutdown sequence
- if (! LLWatchdog::wasDeleted())
+ if (!LLWatchdog::wasDeleted())
{
LLWatchdog::getInstance()->remove(this);
}
@@ -117,7 +117,7 @@ void LLWatchdogTimeout::setTimeout(F32 d)
mTimeout = d;
}
-void LLWatchdogTimeout::start(const std::string& state)
+void LLWatchdogTimeout::start(std::string_view state)
{
if (mTimeout == 0)
{
@@ -139,9 +139,9 @@ void LLWatchdogTimeout::stop()
mTimer.stop();
}
-void LLWatchdogTimeout::ping(const std::string& state)
+void LLWatchdogTimeout::ping(std::string_view state)
{
- if(!state.empty())
+ if (!state.empty())
{
mPingState = state;
}
@@ -151,7 +151,7 @@ void LLWatchdogTimeout::ping(const std::string& state)
// LLWatchdog
LLWatchdog::LLWatchdog()
:mSuspectsAccessMutex()
- ,mTimer(NULL)
+ ,mTimer(nullptr)
,mLastClockCount(0)
{
}
@@ -176,7 +176,7 @@ void LLWatchdog::remove(LLWatchdogEntry* e)
void LLWatchdog::init()
{
- if(!mSuspectsAccessMutex && !mTimer)
+ if (!mSuspectsAccessMutex && !mTimer)
{
mSuspectsAccessMutex = new LLMutex();
mTimer = new LLWatchdogTimerThread();
@@ -191,17 +191,17 @@ void LLWatchdog::init()
void LLWatchdog::cleanup()
{
- if(mTimer)
+ if (mTimer)
{
mTimer->stop();
delete mTimer;
- mTimer = NULL;
+ mTimer = nullptr;
}
- if(mSuspectsAccessMutex)
+ if (mSuspectsAccessMutex)
{
delete mSuspectsAccessMutex;
- mSuspectsAccessMutex = NULL;
+ mSuspectsAccessMutex = nullptr;
}
mLastClockCount = 0;
@@ -214,12 +214,12 @@ void LLWatchdog::run()
// Check the time since the last call to run...
// If the time elapsed is two times greater than the regualr sleep time
// reset the active timeouts.
- const U32 TIME_ELAPSED_MULTIPLIER = 2;
+ constexpr U32 TIME_ELAPSED_MULTIPLIER = 2;
U64 current_time = LLTimer::getTotalTime();
U64 current_run_delta = current_time - mLastClockCount;
mLastClockCount = current_time;
- if(current_run_delta > (WATCHDOG_SLEEP_TIME_USEC * TIME_ELAPSED_MULTIPLIER))
+ if (current_run_delta > (WATCHDOG_SLEEP_TIME_USEC * TIME_ELAPSED_MULTIPLIER))
{
LL_INFOS() << "Watchdog thread delayed: resetting entries." << LL_ENDL;
for (const auto& suspect : mSuspects)
@@ -233,7 +233,7 @@ void LLWatchdog::run()
std::find_if(mSuspects.begin(),
mSuspects.end(),
[](const LLWatchdogEntry* suspect){ return ! suspect->isAlive(); });
- if(result != mSuspects.end())
+ if (result != mSuspects.end())
{
// error!!!
if(mTimer)
@@ -251,7 +251,7 @@ void LLWatchdog::run()
void LLWatchdog::lockThread()
{
- if(mSuspectsAccessMutex != NULL)
+ if (mSuspectsAccessMutex)
{
mSuspectsAccessMutex->lock();
}
@@ -259,7 +259,7 @@ void LLWatchdog::lockThread()
void LLWatchdog::unlockThread()
{
- if(mSuspectsAccessMutex != NULL)
+ if (mSuspectsAccessMutex)
{
mSuspectsAccessMutex->unlock();
}
diff --git a/indra/newview/llwatchdog.h b/indra/newview/llwatchdog.h
index fe8932e298..1931c582b0 100644
--- a/indra/newview/llwatchdog.h
+++ b/indra/newview/llwatchdog.h
@@ -56,14 +56,14 @@ public:
LLWatchdogTimeout();
virtual ~LLWatchdogTimeout();
- /* virtual */ bool isAlive() const;
- /* virtual */ void reset();
- /* virtual */ void start() { start(""); }
- /* virtual */ void stop();
+ bool isAlive() const override;
+ void reset() override;
+ void start() override { start(""); }
+ void stop() override;
- void start(const std::string& state);
+ void start(std::string_view state);
void setTimeout(F32 d);
- void ping(const std::string& state);
+ void ping(std::string_view state);
const std::string& getState() {return mPingState; }
private:
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index 80b6427738..f8543ba1aa 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -14,7 +14,7 @@
legacy_header_height="25">
<string name="status_idle"></string>
- <string name="status_parse_error">Error: Dae parsing issue - see log for details.</string>
+ <string name="status_parse_error">Error: Model parsing issue - see log for details.</string>
<string name="status_bind_shape_orientation">Warning: bind shape matrix is not in standard X-forward orientation.</string>
<string name="status_material_mismatch">Error: Material of model is not a subset of reference model.</string>
<string name="status_reading_file">Loading...</string>
@@ -66,6 +66,7 @@
<string name="NoScenesFound">No scenes defined in GLTF file</string>
<string name="InvalidMeshReference">Node [NODE_NAME] references invalid mesh [MESH_INDEX] (total meshes: [TOTAL_MESHES])</string>
<string name="InvalidGeometryNonTriangulated">Mesh [MESH_NAME] primitive [PRIMITIVE_INDEX]: Invalid geometry with [INDEX_COUNT] indices (must be triangulated)</string>
+ <string name="EmptyVertexArray">Mesh [MESH_NAME] primitive [PRIMITIVE_INDEX]: Empty vertex array</string>
<string name="ErrorIndexLimit">Unable to process mesh [MESH_NAME] due to 65,534 vertex limit. Vertex count: [VERTEX_COUNT]</string>
<string name="TextureFound">Found texture: [TEXTURE_NAME] for material: [MATERIAL_NAME]</string>
<string name="IgnoredExtension">Model uses unsupported extension: [EXT], related material properties are ignored</string>
@@ -74,6 +75,8 @@
<string name="FailedToCreateTempFile">Failed to create temporary file for embedded [TEXTURE_TYPE] texture [TEXTURE_INDEX]: [TEMP_FILE]</string>
<string name="SkinJointsOverLimit">Skin [SKIN_INDEX] defines [JOINT_COUNT] compatible joints, maximum is: [MAX]. Unused joints will be stripped on per model basis.</string>
<string name="ModelTooManyJoint">Model [MODEL_NAME] uses [JOINT_COUNT], maximum: [MAX], upload might fail</string>
+ <string name="ParsingErrorMissingBuffer">Buffer is either missing or empty [BUFFER_NAME].</string>
+ <string name="ParsingErrorMissingBufferBin">Buffer is either missing or empty. Check presence of [BUFFER_URI] file.</string>
<panel
follows="top|left"
@@ -1720,7 +1723,6 @@ Analysed:
height="408"/>
<panel
follows="right|bottom"
- can_resize="false"
height="140"
layout="topleft"
name="right_panel"
diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml
index 6633e25099..84252fe32c 100644
--- a/indra/newview/skins/default/xui/en/floater_stats.xml
+++ b/indra/newview/skins/default/xui/en/floater_stats.xml
@@ -54,6 +54,38 @@
label="jitter"
decimal_digits="1"
stat="frametimejitter"/>
+ <stat_bar name="framet_cumulative"
+ label="jitter cumulative"
+ decimal_digits="1"
+ stat="frametimejitcumulative"/>
+ <stat_bar name="framet_jitter_99th"
+ label="jitter 99th percentile"
+ decimal_digits="1"
+ stat="frametimejitter99"/>
+ <stat_bar name="framet_jitter_95th"
+ label="jitter 95th percentile"
+ decimal_digits="1"
+ stat="frametimejitter95"/>
+ <stat_bar name="framet_jitter_stddev"
+ label="frametime jitter standard deviation"
+ decimal_digits="1"
+ stat="frametimejitterstddev"/>
+ <stat_bar name="framet_99th"
+ label="frametime 99th percentile"
+ decimal_digits="1"
+ stat="frametime99"/>
+ <stat_bar name="framet_95th"
+ label="frametime 95th percentile"
+ decimal_digits="1"
+ stat="frametime95"/>
+ <stat_bar name="framet_stddev"
+ label="frametime standard deviation"
+ decimal_digits="1"
+ stat="frametimestddev"/>
+ <stat_bar name="framet_events"
+ label="frametime events"
+ decimal_digits="1"
+ stat="frametimeevents"/>
<stat_bar name="bandwidth"
label="UDP Data Received"
stat="activemessagedatareceived"
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 08cc9ae19e..7d094ec613 100644
--- a/indra/newview/skins/default/xui/en/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/en/floater_world_map.xml
@@ -455,7 +455,7 @@
<panel
follows="right|top|bottom"
- height="330"
+ height="235"
top_pad="0"
width="238"
name="layout_panel_4">
@@ -532,9 +532,9 @@
width="16" />
<search_editor
follows="top|right"
- search_button_visible="false"
+ search_button_visible="false"
height="22"
- text_readonly_color="DkGray"
+ text_readonly_color="DkGray"
label="Regions by Name"
layout="topleft"
top_delta="-2"
@@ -542,10 +542,7 @@
name="location"
select_on_focus="true"
tool_tip="Type the name of a region"
- width="152">
- <search_editor.commit_callback
- function="WMap.Location" />
- </search_editor>
+ width="152"/>
<button
follows="top|right"
height="23"
@@ -594,6 +591,13 @@
<scroll_list.commit_callback
function="WMap.SearchResult" />
</scroll_list>
+ </panel>
+ <panel
+ follows="right|bottom"
+ height="95"
+ top_pad="0"
+ width="238"
+ name="layout_panel_7">
<text
type="string"
length="1"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
index ec44cc9005..fa70ebe578 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -62,20 +62,9 @@
name="mute_when_minimized"
top_delta="3"
left_pad="5"
- width="20" />
- <!-- *HACK
- After storm-1109 will be fixed: instead of using this text_box, word_wrap should be applied for "mute_when_minimized" check_box's label.-->
- <text
- follows="top|left"
- height="15"
- layout="topleft"
- left_pad="0"
- name="mute_chb_label"
- top_delta="-1"
- width="150"
- wrap="true">
- Mute when minimized
- </text>
+ width="20"
+ label="Mute when minimized"
+ word_wrap="true"/>
<slider
control_name="AudioLevelUI"
disabled_control="MuteAudio"
@@ -321,66 +310,45 @@
left_pad="5"
name="enable_voice_check"
width="110"/>
- <!-- -->
<text
type="string"
length="1"
follows="left|top"
layout="topleft"
left="23"
- top_delta="22"
+ top_delta="25"
name="Listen media from"
height="15"
- word_wrap="true"
- width="112">
- Hear media and sounds from:
+ width="165"
+ halign="right">
+ Hear media and sounds from
</text>
- <radio_group
+ <combo_box
control_name="MediaSoundsEarLocation"
follows="left|top"
- top_delta="-6"
layout="topleft"
- left_pad="10"
- width="360"
- height="40"
- name="media_ear_location">
- <radio_item
- height="19"
- label="Camera position"
- follows="left|top"
- layout="topleft"
- name="0"
- width="200"/>
- <radio_item
- height="19"
- follows="left|top"
- label="Avatar position"
- layout="topleft"
- left_delta="0"
- name="1"
- top_delta ="18"
- width="200" />
- </radio_group>
- <check_box
- name="media_show_on_others_btn"
- control_name="MediaShowOnOthers"
- value="true"
- follows="left|top"
- layout="topleft"
- height="15"
- top_pad="8"
- tool_tip="Uncheck this to hide media attached to other avatars nearby"
- label="Play media attached to other avatars"
- left="20"
- width="230"/>
+ left_pad="5"
+ width="130"
+ height="23"
+ top_delta="-4"
+ name="media_ear_location_combo">
+ <item
+ label="Camera position"
+ name="camera_position"
+ value="0" />
+ <item
+ label="Avatar position"
+ name="avatar_position"
+ value="1" />
+</combo_box>
<text
follows="left|top"
layout="topleft"
height="15"
left="23"
- top_pad="8"
- width="120"
- name="media_autoplay_label">
+ width="165"
+ name="media_autoplay_label"
+ halign="right">
Auto-play media
</text>
<combo_box
@@ -389,10 +357,10 @@
follows="left|top"
layout="topleft"
height="23"
- left_pad="-15"
+ left_delta="170"
top_delta="-4"
name="media_auto_play_combo"
- width="115">
+ width="130">
<item
label="Never"
name="autoplay_disabled"
@@ -433,23 +401,106 @@
name="stream_notification_channel"
top_pad="-15"
width="170" />
+ <text
+ follows="left|top"
+ layout="topleft"
+ height="15"
+ left="23"
+ width="165"
+ name="media_firstinteract_label"
+ halign="right">
+ Media first-interact
+ </text>
+ <combo_box
+ control_name="MediaFirstClickInteract"
+ enabled_control="AudioStreamingMedia"
+ follows="left|top"
+ layout="topleft"
+ height="23"
+ left_delta="170"
+ top_delta="-4"
+ width="130"
+ name="media_first_interact_combo"
+ tool_tip="This setting controls which media (once loaded) does not require a first click to focus before interaction can begin. This allows clicks to be passed directly to media bypassing the focus click requirement. Each option also inherits the previous ones.">
+ <item
+ label="Disabled"
+ name="media_first_click_none"
+ value="0"/>
+ <item
+ label="Worn HUDs only"
+ name="media_first_click_hud"
+ value="1"/>
+ <item
+ label="Owned objects"
+ name="media_first_click_own"
+ value="3"/>
+ <item
+ label="Friends' objects"
+ name="media_first_click_friend"
+ value="11"/>
+ <item
+ label="Group objects"
+ name="media_first_click_group"
+ value="15"/>
+ <item
+ label="Landowner objects"
+ name="media_first_click_land"
+ value="31"/>
+ <item
+ label="Anyone's objects"
+ name="media_first_interact_any"
+ value="1073741823"/>
+ <item
+ label="All MOAP"
+ name="media_first_click_all"
+ value="2147483647"/>
+ </combo_box>
+ <check_box
+ name="media_show_on_others_btn"
+ control_name="MediaShowOnOthers"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|top"
+ tool_tip="Uncheck this to hide media attached to other avatars nearby"
+ label="Play media attached to other avatars"
+ left="23"
+ width="15"
+ top_delta="30"
+ height="15"/>
+ <check_box
+ name="media_huds_autoplay"
+ control_name="MediaAutoPlayHuds"
+ enabled_control="AudioStreamingMedia"
+ value="true"
+ follows="left|top"
+ layout="topleft"
+ tool_tip="Uncheck this to make HUDs follow the standard media auto-play setting"
+ label="Auto-play media attached to your HUD"
+ left="260"
+ top_pad="-15"
+ width="15"
+ height="15"/>
<text
layout="topleft"
+ follows="left"
height="15"
- left="260"
- top_pad="-18"
- width="100"
- name="noise_suppression_label">
- Noise Suppression
+ width="165"
+ name="noise_suppression_label"
+ left="23"
+ top_delta="22"
+ halign="right">
+ Microphone Noise Suppression
</text>
<combo_box
control_name="VoiceNoiseSuppressionLevel"
+ enabled_control="EnableVoiceChat"
+ follows="left|top"
layout="topleft"
+ left_delta="170"
+ top_delta="-6"
+ width="130"
height="23"
- left_pad="10"
- top_pad="-20"
- name="noise_suppression_combo"
- width="80">
+ name="noise_suppression_combo">
<item
label="Off"
name="noise_suppression_none"
@@ -479,48 +530,44 @@
left="23"
top_delta="30"
name="Listen from"
- width="112">
- Hear voice from:
+ width="165"
+ height="15"
+ halign="right">
+ Hear voice from
</text>
- <radio_group
+ <combo_box
enabled_control="EnableVoiceChat"
control_name="VoiceEarLocation"
follows="left|top"
layout="topleft"
- left_pad="10"
+ left_delta="170"
top_delta="-6"
- width="360"
- height="40"
- name="ear_location">
- <radio_item
- height="19"
- label="Camera position"
- follows="left|top"
- layout="topleft"
- name="0"
- width="200"/>
- <radio_item
- height="19"
- follows="left|top"
- label="Avatar position"
- layout="topleft"
- left_delta="0"
- name="1"
- top_delta ="18"
- width="200" />
- </radio_group>
+ width="130"
+ height="23"
+ name="ear_location_combo">
+ <item
+ label="Camera position"
+ name="camera_position"
+ value="0" />
+ <item
+ label="Avatar position"
+ name="avatar_position"
+ value="1" />
+</combo_box>
<check_box
control_name="LipSyncEnabled"
+ enabled_control="EnableVoiceChat"
follows="left|top"
height="15"
label="Move avatar lips when speaking"
layout="topleft"
left="20"
name="enable_lip_sync"
- top_pad="10"
+ top_pad="8"
width="237"/>
<check_box
control_name="VoiceEchoCancellation"
+ enabled_control="EnableVoiceChat"
height="15"
tool_tip="Check to enable voice echo cancellation"
label="Echo Cancellation"
@@ -543,6 +590,7 @@
top_pad="5"/>
<check_box
control_name="VoiceAutomaticGainControl"
+ enabled_control="EnableVoiceChat"
height="15"
tool_tip="Check to enable automatic gain control"
label="Automatic Gain Control"
@@ -564,6 +612,7 @@
left="20"/>
<check_box
control_name="VoiceVisualizerEnabled"
+ enabled_control="EnableVoiceChat"
height="15"
tool_tip="Check to show voice dot indicator above avatars"
label="Show voice dot above avatars"
@@ -574,6 +623,7 @@
width="200"/>
<button
control_name="ShowDeviceSettings"
+ enabled_control="EnableVoiceChat"
follows="left|top"
height="23"
is_toggle="true"
diff --git a/indra/newview/skins/default/xui/en/panel_profile_pick.xml b/indra/newview/skins/default/xui/en/panel_profile_pick.xml
index 024120931f..4f441b9b49 100644
--- a/indra/newview/skins/default/xui/en/panel_profile_pick.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile_pick.xml
@@ -200,6 +200,26 @@
<layout_panel
follows="all"
+ layout="bottomleft"
+ left_pad="2"
+ name="set_to_curr_location_btn_lp"
+ auto_resize="false"
+ width="100">
+ <button
+ name="set_to_curr_location_btn"
+ label="Set Location"
+ tool_tip="Set to Current Location"
+ left="0"
+ top="0"
+ height="23"
+ width="100"
+ follows="left|top"
+ layout="topleft"
+ />
+ </layout_panel>
+
+ <layout_panel
+ follows="all"
layout="topleft"
name="util_resizer_right"
auto_resize="true"
diff --git a/indra/newview/skins/default/xui/en/panel_tools_texture.xml b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
index b7db9dec96..1c70383bf9 100644
--- a/indra/newview/skins/default/xui/en/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/en/panel_tools_texture.xml
@@ -986,6 +986,19 @@
name="gltfTextureScaleV"
width="265" />
<spinner
+ decimal_digits="1"
+ follows="left|top"
+ height="19"
+ initial_value=""
+ label="Repeats per meter"
+ layout="topleft"
+ label_width="205"
+ left="10"
+ max_val="100"
+ min_val="-100"
+ name="gltfRptctrl"
+ width="265" />
+ <spinner
follows="left|top"
height="19"
initial_value="0"