Ansariel 2021-02-03 19:50:18 +01:00
commit bdfa92fb91
224 changed files with 3487 additions and 1105 deletions

2
.gitignore vendored
View File

@ -106,3 +106,5 @@ my_autobuild.xml
*.srctrlprj
compile_commands.json
# ignore tracy for now
indra/tracy

View File

@ -2,7 +2,7 @@
* @file
* @brief
*
* $LicenseInfo:firstyear=2020&license=fsviewerlgpl$
* $LicenseInfo:firstyear=2021&license=fsviewerlgpl$
* Phoenix Firestorm Viewer Source Code
* Copyright (C) 2020, The Phoenix Firestorm Project, Inc.
*

View File

@ -448,9 +448,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>322dd6c45c384d454ae14ef127984a4e</string>
<string>ae90d19cdcddf539f6d0b41cab12f918</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65457/612879/bugsplat-1.0.7.546418-darwin64-546418.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72773/702861/bugsplat-1.0.7.552580-darwin64-552580.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -460,9 +460,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>010a0e73c0fddaa2316411803fad8e69</string>
<string>f5936eceb6a33ff0f1cc31996a40f29c</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65456/612876/bugsplat-3.6.0.8.546418-windows-546418.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72774/702905/bugsplat-3.6.0.8.552580-windows-552580.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -472,16 +472,16 @@
<key>archive</key>
<map>
<key>hash</key>
<string>7e8530762e7b50663708a888c23b8780</string>
<string>9cd940754e53e0670030b3da5ba8f373</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65455/612874/bugsplat-3.6.0.8.546418-windows64-546418.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72775/702906/bugsplat-3.6.0.8.552580-windows64-552580.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>3.6.0.8.546418</string>
<string>3.6.0.8.552580</string>
</map>
<key>colladadom</key>
<map>
@ -964,11 +964,11 @@
<key>archive</key>
<map>
<key>hash</key>
<string>fc2d285da5298b666fc3c54015a8669a</string>
<string>87c4984c2bddcdaf6ca403a06f22ce4e</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>file:///opt/firestorm/fmodstudio-2.01.05-darwin-202981448.tar.bz2</string>
<string>file:///opt/firestorm/fmodstudio-2.01.07-darwin-210010951.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
@ -978,11 +978,11 @@
<key>archive</key>
<map>
<key>hash</key>
<string>ee3c5e3449e06bc3dbb1c9dc29aca53d</string>
<string>d33d848660ca7e4c2de789e325706d24</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>file:///opt/firestorm/fmodstudio-2.01.05-linux64-202931144.tar.bz2</string>
<string>file:///opt/firestorm/fmodstudio-2.01.07-linux64-203630250.tar.bz2</string>
</map>
<key>name</key>
<string>linux64</string>
@ -992,11 +992,11 @@
<key>archive</key>
<map>
<key>hash</key>
<string>b88e70667efc230a00d6a2d982af8fc5</string>
<string>9e9f303912776014519c18a0205250ee</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>file:///c:/cygwin/opt/firestorm/fmodstudio-2.01.05-windows-202860859.tar.bz2</string>
<string>file:///c:/cygwin/opt/firestorm/fmodstudio-2.01.07-windows-203561745.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -1006,18 +1006,18 @@
<key>archive</key>
<map>
<key>hash</key>
<string>401829b65cac61a2f96179fadf7eb015</string>
<string>ae336fe814a6867f6449d0401ea7a9e4</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>file:///c:/cygwin/opt/firestorm/fmodstudio-2.01.05-windows64-202860900.tar.bz2</string>
<string>file:///c:/cygwin/opt/firestorm/fmodstudio-2.01.07-windows64-203561747.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>2.01.05</string>
<string>2.01.07</string>
</map>
<key>fontconfig</key>
<map>
@ -2375,18 +2375,18 @@
<key>archive</key>
<map>
<key>hash</key>
<string>9f4687d7d328b0c13a9e651e805e880a</string>
<string>c541838a933e0714a954e9ef6c89345d</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/71501/691487/llca-202011010215.551526-common-551526.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/73387/708088/llca-202012011600.553112-common-553112.tar.bz2</string>
</map>
<key>name</key>
<string>common</string>
</map>
</map>
<key>version</key>
<string>202011010215.551526</string>
<string>202012011600.553112</string>
</map>
<key>llphysicsextensions_source</key>
<map>
@ -3709,7 +3709,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>canonical_repo</key>
<string>https://bitbucket.org/lindenlab/viewer</string>
<key>copyright</key>
<string>Copyright (c) 2020, The Phoenix Firestorm Project, Inc.</string>
<string>Copyright (c) 2021, The Phoenix Firestorm Project, Inc.</string>
<key>description</key>
<string>Firestorm Viewer</string>
<key>license</key>

View File

@ -477,10 +477,12 @@ then
fi
# Run upload extensions
# Ex: bugsplat
if [ -d ${build_dir}/packages/upload-extensions ]; then
for extension in ${build_dir}/packages/upload-extensions/*.sh; do
begin_section "Upload Extension $extension"
. $extension
[ $? -eq 0 ] || fatal "Upload of extension $extension failed"
end_section "Upload Extension $extension"
done
fi

View File

@ -1358,7 +1358,8 @@ Sovereign Engineer
MAINT-7343
SL-11079
OPEN-343
SL-11625
SL-11625
BUG-229030
SpacedOut Frye
VWR-34
VWR-45

View File

@ -171,10 +171,9 @@ LLAvatarAppearance::LLAvatarXmlInfo::~LLAvatarXmlInfo()
//-----------------------------------------------------------------------------
// Static Data
//-----------------------------------------------------------------------------
LLXmlTree LLAvatarAppearance::sXMLTree;
LLXmlTree LLAvatarAppearance::sSkeletonXMLTree;
LLAvatarSkeletonInfo* LLAvatarAppearance::sAvatarSkeletonInfo = NULL;
LLAvatarAppearance::LLAvatarXmlInfo* LLAvatarAppearance::sAvatarXmlInfo = NULL;
LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* LLAvatarAppearance::sAvatarDictionary = NULL;
LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) :
@ -202,7 +201,7 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) :
mBakedTextureDatas[i].mIsLoaded = false;
mBakedTextureDatas[i].mIsUsed = false;
mBakedTextureDatas[i].mMaskTexName = 0;
mBakedTextureDatas[i].mTextureIndex = LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i);
mBakedTextureDatas[i].mTextureIndex = sAvatarDictionary->bakedToLocalTextureIndex((LLAvatarAppearanceDefines::EBakedTextureIndex)i);
}
}
@ -215,8 +214,8 @@ void LLAvatarAppearance::initInstance()
mRoot = createAvatarJoint();
mRoot->setName( "mRoot" );
for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin();
iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end();
for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = sAvatarDictionary->getMeshEntries().begin();
iter != sAvatarDictionary->getMeshEntries().end();
++iter)
{
const EMeshIndex mesh_index = iter->first;
@ -261,8 +260,8 @@ void LLAvatarAppearance::initInstance()
//-------------------------------------------------------------------------
// associate baked textures with meshes
//-------------------------------------------------------------------------
for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin();
iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end();
for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator iter = sAvatarDictionary->getMeshEntries().begin();
iter != sAvatarDictionary->getMeshEntries().end();
++iter)
{
const EMeshIndex mesh_index = iter->first;
@ -346,6 +345,12 @@ void LLAvatarAppearance::initClass()
//static
void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, const std::string& skeleton_file_name_arg)
{
// init dictionary (don't repeat on second login attempt)
if (!sAvatarDictionary)
{
sAvatarDictionary = new LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary();
}
std::string avatar_file_name;
if (!avatar_file_name_arg.empty())
@ -356,14 +361,15 @@ void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, cons
{
avatar_file_name = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR + "_lad.xml");
}
BOOL success = sXMLTree.parseFile( avatar_file_name, FALSE );
LLXmlTree xml_tree;
BOOL success = xml_tree.parseFile( avatar_file_name, FALSE );
if (!success)
{
LL_ERRS() << "Problem reading avatar configuration file:" << avatar_file_name << LL_ENDL;
}
// now sanity check xml file
LLXmlTreeNode* root = sXMLTree.getRoot();
LLXmlTreeNode* root = xml_tree.getRoot();
if (!root)
{
LL_ERRS() << "No root node found in avatar configuration file: " << avatar_file_name << LL_ENDL;
@ -410,8 +416,9 @@ void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, cons
}
std::string skeleton_path;
LLXmlTree skeleton_xml_tree;
skeleton_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,skeleton_file_name);
if (!parseSkeletonFile(skeleton_path))
if (!parseSkeletonFile(skeleton_path, skeleton_xml_tree))
{
LL_ERRS() << "Error parsing skeleton file: " << skeleton_path << LL_ENDL;
}
@ -424,7 +431,7 @@ void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, cons
delete sAvatarSkeletonInfo;
}
sAvatarSkeletonInfo = new LLAvatarSkeletonInfo;
if (!sAvatarSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot()))
if (!sAvatarSkeletonInfo->parseXml(skeleton_xml_tree.getRoot()))
{
LL_ERRS() << "Error parsing skeleton XML file: " << skeleton_path << LL_ENDL;
}
@ -463,9 +470,8 @@ void LLAvatarAppearance::initClass(const std::string& avatar_file_name_arg, cons
void LLAvatarAppearance::cleanupClass()
{
delete_and_clear(sAvatarXmlInfo);
// *TODO: What about sAvatarSkeletonInfo ???
sSkeletonXMLTree.cleanup();
sXMLTree.cleanup();
delete_and_clear(sAvatarDictionary);
delete_and_clear(sAvatarSkeletonInfo);
}
using namespace LLAvatarAppearanceDefines;
@ -598,12 +604,12 @@ F32 LLAvatarAppearance::getAvatarOffset() /*const*/
//-----------------------------------------------------------------------------
// parseSkeletonFile()
//-----------------------------------------------------------------------------
BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename)
BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree)
{
//-------------------------------------------------------------------------
// parse the file
//-------------------------------------------------------------------------
BOOL parsesuccess = sSkeletonXMLTree.parseFile( filename, FALSE );
BOOL parsesuccess = skeleton_xml_tree.parseFile( filename, FALSE );
if (!parsesuccess)
{
@ -612,7 +618,7 @@ BOOL LLAvatarAppearance::parseSkeletonFile(const std::string& filename)
}
// now sanity check xml file
LLXmlTreeNode* root = sSkeletonXMLTree.getRoot();
LLXmlTreeNode* root = skeleton_xml_tree.getRoot();
if (!root)
{
LL_ERRS() << "No root node found in avatar skeleton file: " << filename << LL_ENDL;
@ -1021,7 +1027,7 @@ BOOL LLAvatarAppearance::loadAvatar()
{
LLAvatarXmlInfo::LLAvatarMorphInfo *info = *iter;
EBakedTextureIndex baked = LLAvatarAppearanceDictionary::findBakedByRegionName(info->mRegion);
EBakedTextureIndex baked = sAvatarDictionary->findBakedByRegionName(info->mRegion);
if (baked != BAKED_NUM_INDICES)
{
LLVisualParam* morph_param;
@ -1157,8 +1163,8 @@ BOOL LLAvatarAppearance::loadMeshNodes()
switch(lod)
case 0:
mesh = &mHairMesh0; */
for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator mesh_iter = LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().begin();
mesh_iter != LLAvatarAppearanceDictionary::getInstance()->getMeshEntries().end();
for (LLAvatarAppearanceDictionary::MeshEntries::const_iterator mesh_iter = sAvatarDictionary->getMeshEntries().begin();
mesh_iter != sAvatarDictionary->getMeshEntries().end();
++mesh_iter)
{
const EMeshIndex mesh_index = mesh_iter->first;
@ -1286,8 +1292,8 @@ BOOL LLAvatarAppearance::loadLayersets()
// scan baked textures and associate the layerset with the appropriate one
EBakedTextureIndex baked_index = BAKED_NUM_INDICES;
for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin();
baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end();
for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = sAvatarDictionary->getBakedTextures().begin();
baked_iter != sAvatarDictionary->getBakedTextures().end();
++baked_iter)
{
const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = baked_iter->second;

View File

@ -162,7 +162,7 @@ public:
protected:
static BOOL parseSkeletonFile(const std::string& filename);
static BOOL parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree);
virtual void buildCharacter();
virtual BOOL loadAvatar();
// [RLVa:KB] - Checked: 2013-03-03 (RLVa-1.4.8)
@ -222,9 +222,6 @@ public:
// XML parse tree
//--------------------------------------------------------------------
protected:
static LLXmlTree sXMLTree; // avatar config file
static LLXmlTree sSkeletonXMLTree; // avatar skeleton file
static LLAvatarSkeletonInfo* sAvatarSkeletonInfo;
static LLAvatarXmlInfo* sAvatarXmlInfo;
@ -272,6 +269,7 @@ public:
public:
virtual void updateMeshTextures() = 0;
virtual void dirtyMesh() = 0; // Dirty the avatar mesh
static const LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary *getDictionary() { return sAvatarDictionary; }
protected:
virtual void dirtyMesh(S32 priority) = 0; // Dirty the avatar mesh, with priority
@ -280,6 +278,9 @@ protected:
polymesh_map_t mPolyMeshes;
avatar_joint_list_t mMeshLOD;
// mesh entries and backed textures
static LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary* sAvatarDictionary;
/** Meshes
** **
*******************************************************************************/

View File

@ -260,19 +260,17 @@ LLAvatarAppearanceDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index,
va_end( argp ); // <FS:ND/> Needs to be freed when done.
}
// static
ETextureIndex LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index)
ETextureIndex LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(EBakedTextureIndex index) const
{
return LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(index)->mTextureIndex;
return getBakedTexture(index)->mTextureIndex;
}
// static
EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::string name)
{
U8 index = 0;
while (index < BAKED_NUM_INDICES)
{
const BakedEntry *be = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index);
const BakedEntry *be = getBakedTexture((EBakedTextureIndex) index);
if (be && be->mName.compare(name) == 0)
{
// baked texture found
@ -284,16 +282,15 @@ EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::stri
return BAKED_NUM_INDICES;
}
// static
EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::string name)
{
U8 index = 0;
while (index < BAKED_NUM_INDICES)
{
const BakedEntry *be = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex) index);
const BakedEntry *be = getBakedTexture((EBakedTextureIndex) index);
if (be)
{
const TextureEntry *te = LLAvatarAppearanceDictionary::getInstance()->getTexture(be->mTextureIndex);
const TextureEntry *te = getTexture(be->mTextureIndex);
if (te && te->mDefaultImageName.compare(name) == 0)
{
// baked texture found
@ -306,10 +303,9 @@ EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::strin
return BAKED_NUM_INDICES;
}
// static
LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIndex index )
LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIndex index ) const
{
return getInstance()->getTexture(index)->mWearableType;
return getTexture(index)->mWearableType;
}
// static

View File

@ -143,13 +143,14 @@ typedef std::vector<LLWearableType::EType> wearables_vec_t;
//
// This holds const data - it is initialized once and the contents never change after that.
//------------------------------------------------------------------------
class LLAvatarAppearanceDictionary : public LLSingleton<LLAvatarAppearanceDictionary>
class LLAvatarAppearanceDictionary
{
//--------------------------------------------------------------------
// Constructors and Destructors
//--------------------------------------------------------------------
LLSINGLETON(LLAvatarAppearanceDictionary);
virtual ~LLAvatarAppearanceDictionary();
public:
LLAvatarAppearanceDictionary();
~LLAvatarAppearanceDictionary();
private:
void createAssociations();
@ -235,14 +236,14 @@ public:
//--------------------------------------------------------------------
public:
// Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED
static ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t);
ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t) const;
// find a baked texture index based on its name
static EBakedTextureIndex findBakedByRegionName(std::string name);
static EBakedTextureIndex findBakedByImageName(std::string name);
EBakedTextureIndex findBakedByRegionName(std::string name);
EBakedTextureIndex findBakedByImageName(std::string name);
// Given a texture entry, determine which wearable type owns it.
static LLWearableType::EType getTEWearableType(ETextureIndex index);
LLWearableType::EType getTEWearableType(ETextureIndex index) const;
static BOOL isBakedImageId(const LLUUID& id);
static EBakedTextureIndex assetIdToBakedTextureIndex(const LLUUID& id);

View File

@ -735,8 +735,8 @@ BOOL LLTexLayerInfo::parseXml(LLXmlTreeNode* node)
/* if ("upper_shirt" == local_texture_name)
mLocalTexture = TEX_UPPER_SHIRT; */
mLocalTexture = TEX_NUM_INDICES;
for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin();
iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end();
for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin();
iter != LLAvatarAppearance::getDictionary()->getTextures().end();
iter++)
{
const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second;
@ -986,7 +986,7 @@ LLWearableType::EType LLTexLayerInterface::getWearableType() const
return type;
}
return LLAvatarAppearanceDictionary::getTEWearableType(te);
return LLAvatarAppearance::getDictionary()->getTEWearableType(te);
}
LLTexLayerInterface::ERenderPass LLTexLayerInterface::getRenderPass() const

View File

@ -186,7 +186,7 @@ void LLWearable::createVisualParams(LLAvatarAppearance *avatarp)
void LLWearable::createLayers(S32 te, LLAvatarAppearance *avatarp)
{
LLTexLayerSet *layer_set = NULL;
const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te);
const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)te);
if (texture_dict && texture_dict->mIsUsedByBakedTexture)
{
const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
@ -613,7 +613,7 @@ void LLWearable::syncImages(te_map_t &src, te_map_t &dst)
// Deep copy of src (copies only those tes that are current, filling in defaults where needed)
for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
{
if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex) te) == mType)
if (LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex) te) == mType)
{
te_map_t::const_iterator iter = src.find(te);
LLUUID image_id;

View File

@ -350,7 +350,7 @@ U32 LLWearableData::getWearableCount(const LLWearableType::EType type) const
U32 LLWearableData::getWearableCount(const U32 tex_index) const
{
const LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index);
const LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((LLAvatarAppearanceDefines::ETextureIndex)tex_index);
return getWearableCount(wearable_type);
}
@ -360,7 +360,7 @@ LLUUID LLWearableData::computeBakedTextureHash(LLAvatarAppearanceDefines::EBaked
LLUUID hash_id;
bool hash_computed = false;
LLMD5 hash;
const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index);
const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearance::getDictionary()->getBakedTexture(baked_index);
for (U8 i=0; i < baked_dict->mWearables.size(); i++)
{

View File

@ -392,6 +392,7 @@ void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol)
Check_FMOD_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume");
}
}
// <DKO> Streamtitle display
// virtual
bool LLStreamingAudio_FMODSTUDIO::getNewMetadata(LLSD& metadata)
@ -404,14 +405,17 @@ bool LLStreamingAudio_FMODSTUDIO::getNewMetadata(LLSD& metadata)
mNewMetadata = false;
return true;
}
return mNewMetadata;
else
{
return false;
}
}
metadata = LLSD();
return false;
}
// </DKO>
///////////////////////////////////////////////////////
// manager of possibly-multiple internet audio streams

View File

@ -1208,7 +1208,9 @@ namespace
{
LLError::RecorderPtr r = *i;
if (!r->enabled())
// <FS:Ansariel> Crash fix
//if (!r->enabled())
if (!r || !r->enabled())
{
continue;
}

View File

@ -388,7 +388,7 @@ LLSingletonBase::vec_t LLSingletonBase::dep_sort()
// extracts just the first (key) element from each sorted_iterator, then
// uses vec_t's range constructor... but frankly this is more
// straightforward, as long as we remember the above reserve() call!
for (const SingletonDeps::sorted_iterator::value_type& pair : sdeps.sort())
for (const SingletonDeps::sorted_iterator::value_type pair : sdeps.sort())
{
ret.push_back(pair.first);
}

View File

@ -359,10 +359,11 @@ void LLThread::setQuitting()
}
// static
LLThread::id_t LLThread::currentID()
{
return std::this_thread::get_id();
}
// <FS:Beq> give this a better chance to inline
// LLThread::id_t LLThread::currentID()
// {
// return std::this_thread::get_id();
// }
// static
void LLThread::yield()

View File

@ -60,8 +60,8 @@ public:
bool isQuitting() const { return (QUITTING == mStatus); }
bool isStopped() const { return (STOPPED == mStatus) || (CRASHED == mStatus); }
bool isCrashed() const { return (CRASHED == mStatus); }
static id_t currentID(); // Return ID of current thread
// <FS:Beq> Try to encourage the inlining
static LL_FORCE_INLINE id_t currentID(){return std::this_thread::get_id();}; // Return ID of current thread
static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
public:

View File

@ -577,16 +577,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
// Use the viewer-based thread-safe API which has a
// fast/safe check for proxy enable. Would like to
// encapsulate this someway...
if (LLProxy::instanceExists())
{
// Make sure proxy won't be initialized from here,
// it might conflict with LLStartUp::startLLProxy()
LLProxy::getInstance()->applyProxySettings(mCurlHandle);
}
else
{
LL_WARNS() << "Proxy is not initialized!" << LL_ENDL;
}
// Make sure proxy won't be getInstance() from here,
// it is not thread safe
LLProxy::applyProxySettings(mCurlHandle);
}
else if (gpolicy.mHttpProxy.size())
@ -827,6 +820,7 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void
const size_t do_size((std::min)(req_size, body_size - op->mCurlBodyPos));
const size_t read_size(op->mReqBody->read(op->mCurlBodyPos, static_cast<char *>(data), do_size));
// FIXME: singleton's instance() is Thread unsafe! Even if stats accumulators inside are.
HTTPStats::instance().recordDataUp(read_size);
op->mCurlBodyPos += read_size;
return read_size;

View File

@ -583,29 +583,39 @@ static void bilinear_scale(const U8 *src, U32 srcW, U32 srcH, U32 srcCh, U32 src
// LLImage
//---------------------------------------------------------------------------
LLImage::LLImage(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent)
//static
std::string LLImage::sLastErrorMessage;
LLMutex* LLImage::sMutex = NULL;
bool LLImage::sUseNewByteRange = false;
S32 LLImage::sMinimalReverseByteRangePercent = 75;
//static
void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent)
{
mMutex = new LLMutex();
mUseNewByteRange = use_new_byte_range;
mMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent;
sUseNewByteRange = use_new_byte_range;
sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent;
sMutex = new LLMutex();
}
LLImage::~LLImage()
//static
void LLImage::cleanupClass()
{
delete mMutex;
mMutex = NULL;
delete sMutex;
sMutex = NULL;
}
const std::string& LLImage::getLastErrorMessage()
//static
const std::string& LLImage::getLastError()
{
static const std::string noerr("No Error");
return mLastErrorMessage.empty() ? noerr : mLastErrorMessage;
return sLastErrorMessage.empty() ? noerr : sLastErrorMessage;
}
void LLImage::setLastErrorMessage(const std::string& message)
//static
void LLImage::setLastError(const std::string& message)
{
LLMutexLock m(mMutex);
mLastErrorMessage = message;
LLMutexLock m(sMutex);
sLastErrorMessage = message;
}
//---------------------------------------------------------------------------

View File

@ -30,7 +30,6 @@
#include "lluuid.h"
#include "llstring.h"
#include "llpointer.h"
#include "llsingleton.h"
#include "lltrace.h"
const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2
@ -88,26 +87,25 @@ typedef enum e_image_codec
//============================================================================
// library initialization class
// LLImage is frequently used in threads so do not convert it to LLSingleton
class LLImage : public LLParamSingleton<LLImage>
class LLImage
{
LLSINGLETON(LLImage, bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75);
~LLImage();
public:
static void initClass(bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75);
static void cleanupClass();
const std::string& getLastErrorMessage();
static const std::string& getLastError() { return getInstance()->getLastErrorMessage(); };
void setLastErrorMessage(const std::string& message);
static void setLastError(const std::string& message) { getInstance()->setLastErrorMessage(message); }
bool useNewByteRange() { return mUseNewByteRange; }
S32 getReverseByteRangePercent() { return mMinimalReverseByteRangePercent; }
private:
LLMutex* mMutex;
std::string mLastErrorMessage;
bool mUseNewByteRange;
S32 mMinimalReverseByteRangePercent;
static const std::string& getLastError();
static void setLastError(const std::string& message);
static bool useNewByteRange() { return sUseNewByteRange; }
static S32 getReverseByteRangePercent() { return sMinimalReverseByteRangePercent; }
protected:
static LLMutex* sMutex;
static std::string sLastErrorMessage;
static bool sUseNewByteRange;
static S32 sMinimalReverseByteRangePercent;
};
//============================================================================

View File

@ -281,7 +281,7 @@ S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 r
S32 bytes;
S32 new_bytes = (S32) (sqrt((F32)(w*h))*(F32)(comp)*rate*1000.f/layer_factor);
S32 old_bytes = (S32)((F32)(w*h*comp)*rate);
bytes = (LLImage::getInstance()->useNewByteRange() && (new_bytes < old_bytes) ? new_bytes : old_bytes);
bytes = (LLImage::useNewByteRange() && (new_bytes < old_bytes) ? new_bytes : old_bytes);
bytes = llmax(bytes, calcHeaderSizeJ2C());
return bytes;
}
@ -322,7 +322,7 @@ S32 LLImageJ2C::calcDiscardLevelBytes(S32 bytes)
{
S32 bytes_needed = calcDataSize(discard_level);
// Use TextureReverseByteRange percent (see settings.xml) of the optimal size to qualify as correct rendering for the given discard level
if (bytes >= (bytes_needed*LLImage::getInstance()->getReverseByteRangePercent()/100))
if (bytes >= (bytes_needed*LLImage::getReverseByteRangePercent()/100))
{
break;
}

View File

@ -306,12 +306,27 @@ void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName&
return;
}
bool updated_account = true; // assume obsolete value for new arrivals by default
std::map<LLUUID, LLAvatarName>::iterator it = mCache.find(agent_id);
if (it != mCache.end()
&& (*it).second.getAccountName() == av_name.getAccountName())
{
updated_account = false;
}
// Add to the cache
mCache[agent_id] = av_name;
// Suppress request from the queue
mPendingQueue.erase(agent_id);
// notify mute list about changes
if (updated_account && mAccountNameChangedCallback)
{
mAccountNameChangedCallback(agent_id, av_name);
}
// Signal everyone waiting on this name
signal_map_t::iterator sig_it = mSignalMap.find(agent_id);
if (sig_it != mSignalMap.end())
@ -324,6 +339,8 @@ void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName&
delete signal;
signal = NULL;
}
}
void LLAvatarNameCache::requestNamesViaCapability()

View File

@ -42,6 +42,7 @@ class LLAvatarNameCache : public LLSingleton<LLAvatarNameCache>
~LLAvatarNameCache();
public:
typedef boost::signals2::signal<void (void)> use_display_name_signal_t;
typedef boost::function<void (const LLUUID id, const LLAvatarName& av_name)> account_name_changed_callback_t;
// Import/export the name cache to file.
bool importFile(std::istream& istr);
@ -113,6 +114,8 @@ public:
void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb);
void setAccountNameChangedCallback(const account_name_changed_callback_t& cb) { mAccountNameChangedCallback = cb; }
// <FS:Ansariel> FIRE-6659: Legacy "Resident" name toggle
void clearCache();
@ -154,6 +157,7 @@ private:
private:
use_display_name_signal_t mUseDisplayNamesSignal;
account_name_changed_callback_t mAccountNameChangedCallback;
// Cache starts in a paused state until we can determine if the
// current region supports display names.

View File

@ -196,6 +196,7 @@ void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpd
// workaround until we get mutex into initializePool
initializePool("VAssetStorage");
initializePool("Upload");
initializePool("ExpCache"); // <FS:Ansariel> FIRE-30731: ExpCache coroutine pool crash
}
//-------------------------------------------------------------------------

View File

@ -40,6 +40,7 @@
// incoming packet just to do a simple bool test. The getter for this
// member is also static
bool LLProxy::sUDPProxyEnabled = false;
LLProxy* LLProxy::sProxyInstance = NULL;
// Some helpful TCP static functions.
static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataout, apr_size_t outlen, char * datain, apr_size_t maxinlen); // Do a TCP data handshake
@ -60,11 +61,21 @@ LLProxy::LLProxy():
LLProxy::~LLProxy()
{
if (ll_apr_is_initialized())
{
stopSOCKSProxy();
disableHTTPProxy();
}
if (ll_apr_is_initialized())
{
// locks mutex
stopSOCKSProxy();
disableHTTPProxy();
}
// The primary safety of sProxyInstance is the fact that by the
// point SUBSYSTEM_CLEANUP(LLProxy) gets called, nothing should
// be capable of using proxy
sProxyInstance = NULL;
}
void LLProxy::initSingleton()
{
sProxyInstance = this;
}
/**
@ -424,28 +435,28 @@ void LLProxy::cleanupClass()
void LLProxy::applyProxySettings(CURL* handle)
{
// Do a faster unlocked check to see if we are supposed to proxy.
if (mHTTPProxyEnabled)
if (sProxyInstance && sProxyInstance->mHTTPProxyEnabled)
{
// We think we should proxy, lock the proxy mutex.
LLMutexLock lock(&mProxyMutex);
// We think we should proxy, lock the proxy mutex. sProxyInstance is not protected by mutex
LLMutexLock lock(&sProxyInstance->mProxyMutex);
// Now test again to verify that the proxy wasn't disabled between the first check and the lock.
if (mHTTPProxyEnabled)
if (sProxyInstance->mHTTPProxyEnabled)
{
LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, mHTTPProxy.getIPString().c_str()), CURLOPT_PROXY);
LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, mHTTPProxy.getPort()), CURLOPT_PROXYPORT);
LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXY, sProxyInstance->mHTTPProxy.getIPString().c_str()), CURLOPT_PROXY);
LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYPORT, sProxyInstance->mHTTPProxy.getPort()), CURLOPT_PROXYPORT);
if (mProxyType == LLPROXY_SOCKS)
if (sProxyInstance->mProxyType == LLPROXY_SOCKS)
{
LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5), CURLOPT_PROXYTYPE);
if (mAuthMethodSelected == METHOD_PASSWORD)
LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5), CURLOPT_PROXYTYPE);
if (sProxyInstance->mAuthMethodSelected == METHOD_PASSWORD)
{
std::string auth_string = mSocksUsername + ":" + mSocksPassword;
LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()), CURLOPT_PROXYUSERPWD);
std::string auth_string = sProxyInstance->mSocksUsername + ":" + sProxyInstance->mSocksPassword;
LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYUSERPWD, auth_string.c_str()), CURLOPT_PROXYUSERPWD);
}
}
else
{
LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP), CURLOPT_PROXYTYPE);
LLCore::LLHttp::check_curl_code(curl_easy_setopt(handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP), CURLOPT_PROXYTYPE);
}
}
}

View File

@ -226,6 +226,8 @@ class LLProxy: public LLSingleton<LLProxy>
LLSINGLETON(LLProxy);
LOG_CLASS(LLProxy);
/*virtual*/ void initSingleton();
public:
// Static check for enabled status for UDP packets. Call from main thread only.
static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; }
@ -251,7 +253,7 @@ public:
// Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false.
// Safe to call from any thread.
void applyProxySettings(CURL* handle);
static void applyProxySettings(CURL* handle);
// Start a connection to the SOCKS 5 proxy. Call from main thread only.
S32 startSOCKSProxy(LLHost host);
@ -344,6 +346,10 @@ private:
/*###########################################################################################
END OF SHARED MEMBERS
###########################################################################################*/
// A hack to get arround getInstance() and capture_dependency() which are unsafe to use inside threads
// set/reset on init/cleanup, strictly for use in applyProxySettings
static LLProxy* sProxyInstance;
};
#endif

View File

@ -154,8 +154,18 @@ void LLPluginProcessParent::shutdown()
mapInstances_t::iterator it;
for (it = sInstances.begin(); it != sInstances.end(); ++it)
{
(*it).second->setState(STATE_GOODBYE);
(*it).second->idle();
EState state = (*it).second->mState;
if (state != STATE_CLEANUP
|| state != STATE_EXITING
|| state != STATE_DONE
|| state != STATE_ERROR)
{
(*it).second->setState(STATE_GOODBYE);
}
if (state != STATE_DONE)
{
(*it).second->idle();
}
}
sInstances.clear();
}
@ -895,16 +905,24 @@ void LLPluginProcessParent::poll(F64 timeout)
{
// timed out with no incoming data. Just return.
}
else if(status == EBADF)
// <FS:Beq> better logging of poll issues
// else if(status == EBADF)
else if(APR_STATUS_IS_EBADF(status))
{
// This happens when one of the file descriptors in the pollset is destroyed, which happens whenever a plugin's socket is closed.
// The pollset has been or will be recreated, so just return.
LL_DEBUGS("PluginPoll") << "apr_pollset_poll returned EBADF" << LL_ENDL;
}
else if(status != APR_SUCCESS)
// <FS:Beq> better logging of poll issues
// else if(status != APR_SUCCESS)
// {
// LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL;
// }
else
{
LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL;
LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << " (" << APR_TO_OS_ERROR(status) << ")" << LL_ENDL;
}
// </FS:Beq>
}
// Remove instances in the done state from the sInstances map.

View File

@ -1535,7 +1535,8 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
std::string lookingForJoint = (*jointIt).c_str();
//Look for the joint xform that we extracted from the skeleton, using the jointIt as the key
//and store it in the alternate bind matrix
if ( mJointMap.find( lookingForJoint ) != mJointMap.end() )
if (mJointMap.find(lookingForJoint) != mJointMap.end()
&& model->mSkinInfo.mInvBindMatrix.size() > i)
{
LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i];
newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() );

View File

@ -45,6 +45,7 @@ bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc);
bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node);
const std::string MACOSX_FONT_PATH_LIBRARY = "/Library/Fonts/";
const std::string MACOSX_FONT_SUPPLEMENTAL = "Supplemental/";
LLFontDescriptor::LLFontDescriptor():
mStyle(0)
@ -512,6 +513,8 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
font_paths.push_back(usr_path + *file_name_it);
#if LL_DARWIN
font_paths.push_back(MACOSX_FONT_PATH_LIBRARY + *file_name_it);
font_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL + *file_name_it);
font_paths.push_back(sys_path + MACOSX_FONT_SUPPLEMENTAL + *file_name_it);
#endif
bool is_ft_collection = (std::find(ft_collection_list.begin(), ft_collection_list.end(), *file_name_it) != ft_collection_list.end());

View File

@ -970,6 +970,80 @@ std::string LLGLManager::getRawGLString()
return gl_string;
}
void LLGLManager::asLLSD(LLSD& info)
{
// Currently these are duplicates of fields in "system".
info["gpu_vendor"] = mGLVendorShort;
info["gpu_version"] = mDriverVersionVendorString;
info["opengl_version"] = mGLVersionString;
info["vram"] = mVRAM;
// Extensions used by everyone
info["has_multitexture"] = mHasMultitexture;
info["has_ati_mem_info"] = mHasATIMemInfo;
info["has_nvx_mem_info"] = mHasNVXMemInfo;
info["num_texture_units"] = mNumTextureUnits;
info["has_mip_map_generation"] = mHasMipMapGeneration;
info["has_compressed_textures"] = mHasCompressedTextures;
info["has_framebuffer_object"] = mHasFramebufferObject;
info["max_samples"] = mMaxSamples;
info["has_blend_func_separate"] = mHasBlendFuncSeparate;
// ARB Extensions
info["has_vertex_buffer_object"] = mHasVertexBufferObject;
info["has_vertex_array_object"] = mHasVertexArrayObject;
info["has_sync"] = mHasSync;
info["has_map_buffer_range"] = mHasMapBufferRange;
info["has_flush_buffer_range"] = mHasFlushBufferRange;
info["has_pbuffer"] = mHasPBuffer;
info["has_shader_objects"] = mHasShaderObjects;
info["has_vertex_shader"] = mHasVertexShader;
info["has_fragment_shader"] = mHasFragmentShader;
info["num_texture_image_units"] = mNumTextureImageUnits;
info["has_occlusion_query"] = mHasOcclusionQuery;
info["has_timer_query"] = mHasTimerQuery;
info["has_occlusion_query2"] = mHasOcclusionQuery2;
info["has_point_parameters"] = mHasPointParameters;
info["has_draw_buffers"] = mHasDrawBuffers;
info["has_depth_clamp"] = mHasDepthClamp;
info["has_texture_rectangle"] = mHasTextureRectangle;
info["has_texture_multisample"] = mHasTextureMultisample;
info["has_transform_feedback"] = mHasTransformFeedback;
info["max_sample_mask_words"] = mMaxSampleMaskWords;
info["max_color_texture_samples"] = mMaxColorTextureSamples;
info["max_depth_texture_samples"] = mMaxDepthTextureSamples;
info["max_integer_samples"] = mMaxIntegerSamples;
// Other extensions.
info["has_anisotropic"] = mHasAnisotropic;
info["has_arb_env_combine"] = mHasARBEnvCombine;
info["has_cube_map"] = mHasCubeMap;
info["has_debug_output"] = mHasDebugOutput;
info["has_srgb_texture"] = mHassRGBTexture;
info["has_srgb_framebuffer"] = mHassRGBFramebuffer;
info["has_texture_srgb_decode"] = mHasTexturesRGBDecode;
// Vendor-specific extensions
info["is_ati"] = mIsATI;
info["is_nvidia"] = mIsNVIDIA;
info["is_intel"] = mIsIntel;
info["is_gf2or4mx"] = mIsGF2or4MX;
info["is_gf3"] = mIsGF3;
info["is_gf_gfx"] = mIsGFFX;
info["ati_offset_vertical_lines"] = mATIOffsetVerticalLines;
info["ati_old_driver"] = mATIOldDriver;
// Other fields
info["has_requirements"] = mHasRequirements;
info["has_separate_specular_color"] = mHasSeparateSpecularColor;
info["debug_gpu"] = mDebugGPU;
info["max_vertex_range"] = mGLMaxVertexRange;
info["max_index_range"] = mGLMaxIndexRange;
info["max_texture_size"] = mGLMaxTextureSize;
info["gl_renderer"] = mGLRenderer;
}
void LLGLManager::shutdownGL()
{
if (mInited)

View File

@ -175,6 +175,8 @@ public:
void printGLInfoString();
void getGLInfo(LLSD& info);
void asLLSD(LLSD& info);
// In ALL CAPS
std::string mGLVendor;
std::string mGLVendorShort;

View File

@ -874,10 +874,11 @@ void LLTexUnit::setTextureColorSpace(eTextureColorSpace space)
}
}
else
#endif
// #endif // <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
{
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
}
#endif // <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
}
LLLightState::LLLightState(S32 index)

View File

@ -32,6 +32,7 @@
#include "llpointer.h" // LLPointer<>
#include "llrect.h"
#include "llsingleton.h"
#include "llglslshader.h"
class LLColor4;

View File

@ -329,12 +329,11 @@ void LLFloater::initFloater(const Params& p)
mButtonsEnabled[BUTTON_CLOSE] = TRUE;
}
// Help button: '?'
if ( !mHelpTopic.empty() )
{
mButtonsEnabled[BUTTON_HELP] = TRUE;
}
// Help button: '?'
//SL-14050 Disable all Help question marks
// <FS:Ansariel> Nope!
mButtonsEnabled[BUTTON_HELP] = !mHelpTopic.empty();// FALSE;
// Minimize button only for top draggers
if ( !mDragOnLeft && mCanMinimize )
{

View File

@ -295,7 +295,7 @@ public:
typedef std::list<LLFolderViewModelItem*> child_list_t;
virtual void addChild(LLFolderViewModelItem* child)
{
{
mChildren.push_back(child);
child->setParent(this);
dirtyFilter();

View File

@ -4202,6 +4202,9 @@ void LLContextMenu::show(S32 x, S32 y, LLView* spawning_view)
{
y += height;
}
// <FS:Ansariel> FIRE-10883: Prevent context menu from going off screen
y = llmin(y, menu_region_rect.mTop);
}
// Open out to the left if menu extends past right edge
@ -4215,6 +4218,9 @@ void LLContextMenu::show(S32 x, S32 y, LLView* spawning_view)
{
x -= width;
}
// <FS:Ansariel> FIRE-10883: Prevent context menu from going off screen
x = llmax(x, menu_region_rect.mLeft);
}
S32 local_x, local_y;

View File

@ -851,16 +851,22 @@ void LLScrollListCtrl::updateColumns(bool force_update)
}
}
bool header_changed_width = false;
// expand last column header we encountered to full list width
// <FS:KC> Fixed last column on LLScrollListCtrl expanding on control resize when column width should be fixed or dynamic
//if (last_header)
if (last_header && last_header->canResize())
{
S32 old_width = last_header->getColumn()->getWidth();
S32 new_width = llmax(0, mItemListRect.mRight - last_header->getRect().mLeft);
last_header->reshape(new_width, last_header->getRect().getHeight());
last_header->setVisible(mDisplayColumnHeaders && new_width > 0);
last_header->getColumn()->setWidth(new_width);
}
if (old_width != new_width)
{
last_header->getColumn()->setWidth(new_width);
header_changed_width = true;
}
}
// propagate column widths to individual cells
if (columns_changed_width || force_update)
@ -879,6 +885,20 @@ void LLScrollListCtrl::updateColumns(bool force_update)
}
}
}
else if (header_changed_width)
{
item_list::iterator iter;
S32 index = last_header->getColumn()->mIndex; // Not always identical to last column!
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
{
LLScrollListItem *itemp = *iter;
LLScrollListCell* cell = itemp->getColumn(index);
if (cell)
{
cell->setWidth(last_header->getColumn()->getWidth());
}
}
}
}
void LLScrollListCtrl::setHeadingHeight(S32 heading_height)
@ -932,6 +952,8 @@ BOOL LLScrollListCtrl::selectFirstItem()
// virtual
BOOL LLScrollListCtrl::selectNthItem( S32 target_index )
{
// <FS:Ansariel> FIRE-30571: Comboboxes select all items then pressing Page-Up
target_index = llclamp(target_index, 0, (S32)mItemList.size() - 1);
return selectItemRange(target_index, target_index);
}
@ -1524,18 +1546,34 @@ BOOL LLScrollListCtrl::setSelectedByValue(const LLSD& value, BOOL selected)
for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
{
LLScrollListItem* item = *iter;
if (item->getEnabled() && (item->getValue().asString() == value.asString()))
if (item->getEnabled())
{
if (selected)
{
selectItem(item);
}
else
{
deselectItem(item);
}
found = TRUE;
break;
if (value.isBinary())
{
if (item->getValue().isBinary())
{
LLSD::Binary data1 = value.asBinary();
LLSD::Binary data2 = item->getValue().asBinary();
found = std::equal(data1.begin(), data1.end(), data2.begin()) ? TRUE : FALSE;
}
}
else
{
found = item->getValue().asString() == value.asString() ? TRUE : FALSE;
}
if (found)
{
if (selected)
{
selectItem(item);
}
else
{
deselectItem(item);
}
break;
}
}
}
@ -2915,8 +2953,16 @@ void LLScrollListCtrl::sortByColumnIndex(U32 column, BOOL ascending)
void LLScrollListCtrl::updateSort() const
{
if (hasSortOrder() && !isSorted())
// <FS:Beq> FIRE-30667 et al. Group hang issues
// if (hasSortOrder() && !isSorted())
// {
static LLUICachedControl<U32> sortDeferFrameCount("FSSortDeferalFrames");
if ( hasSortOrder() && !isSorted() && ( mLastUpdateFrame > 1 && ( LLFrameTimer::getFrameCount() - mLastUpdateFrame ) >= sortDeferFrameCount ) )
// encoding two (unlikely) special values into mLastUpdateFrame 1 means we've sorted and 0 means we've nothing new to do.
// 0 is set after sorting, 1 can be set by a parent for any post sorting action.
{
mLastUpdateFrame=0;
// </FS:Beq>
// do stable sort to preserve any previous sorts
std::stable_sort(
mItemList.begin(),

View File

@ -412,7 +412,9 @@ public:
void sortOnce(S32 column, BOOL ascending);
// manually call this whenever editing list items in place to flag need for resorting
void setNeedsSort(bool val = true) { mSorted = !val; }
// <FS:Beq/> FIRE-30667 et al. Avoid hangs on large list updates
// void setNeedsSort(bool val = true) { mSorted = !val; }
void setNeedsSort(bool val = true) { mSorted = !val; mLastUpdateFrame = LLFrameTimer::getFrameCount(); }
void dirtyColumns(); // some operation has potentially affected column layout or ordering
boost::signals2::connection setSortCallback(sort_signal_t::slot_type cb )
@ -452,6 +454,8 @@ protected:
public:
void updateLineHeight();
// <FS:Beq/> FIRE-30667 et al. Avoid hangs on large list updates
mutable U32 mLastUpdateFrame;
private:
void selectPrevItem(BOOL extend_selection);
@ -478,6 +482,7 @@ private:
static void copyNameToClipboard(std::string id, bool is_group);
static void copySLURLToClipboard(std::string id, bool is_group);
S32 mLineHeight; // the max height of a single line
S32 mScrollLines; // how many lines we've scrolled down
S32 mPageLines; // max number of lines is it possible to see on the screen given mRect and mLineHeight

View File

@ -953,6 +953,30 @@ std::string LLUrlEntryAgentRLVAnonymizedName::getName(const LLAvatarName& avatar
}
// [/RLVa:KB]
// <FS:Ansariel> FIRE-30611: "You" in transcript is underlined
///
/// FSUrlEntryAgentSelf Describes the agent's Second Life agent Url, e.g.,
/// secondlife:///app/agentself/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
FSUrlEntryAgentSelf::FSUrlEntryAgentSelf() : LLUrlEntryAgent()
// </FS:Ansariel>
{
mPattern = boost::regex(APP_HEADER_REGEX "/agentself/[\\da-f-]+/\\w+",
boost::regex::perl|boost::regex::icase);
}
std::string FSUrlEntryAgentSelf::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
if (LLUI::getInstance()->mSettingGroups["config"]->getBOOL("FSChatHistoryShowYou"))
{
return LLTrans::getString("AgentNameSubst");
}
else
{
return LLUrlEntryAgent::getLabel(url, cb);
}
}
// </FS:Ansariel>
//
// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
@ -1696,4 +1720,43 @@ void LLUrlEntryExperienceProfile::onExperienceDetails( const LLSD& experience_de
callObservers(experience_details[LLExperienceCache::EXPERIENCE_ID].asString(), name, LLStringUtil::null);
}
//
// LLUrlEntryEmail Describes an IPv6 address
//
LLUrlEntryIPv6::LLUrlEntryIPv6()
: LLUrlEntryBase()
{
mHostPath = "https?://\\[([a-f0-9:]+:+)+[a-f0-9]+]";
mPattern = boost::regex(mHostPath + "(:\\d{1,5})?(/\\S*)?",
boost::regex::perl | boost::regex::icase);
mMenuName = "menu_url_http.xml";
mTooltip = LLTrans::getString("TooltipHttpUrl");
}
std::string LLUrlEntryIPv6::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
boost::regex regex = boost::regex(mHostPath, boost::regex::perl | boost::regex::icase);
boost::match_results<std::string::const_iterator> matches;
if (boost::regex_search(url, matches, regex))
{
return url.substr(0, matches[0].length());
}
else
{
return url;
}
}
std::string LLUrlEntryIPv6::getQuery(const std::string &url) const
{
boost::regex regex = boost::regex(mHostPath, boost::regex::perl | boost::regex::icase);
boost::match_results<std::string::const_iterator> matches;
return boost::regex_replace(url, regex, "");
}
std::string LLUrlEntryIPv6::getUrl(const std::string &string) const
{
return string;
}

View File

@ -362,6 +362,20 @@ private:
};
// [/RLVa:KB]
// <FS:Ansariel> FIRE-30611: "You" in transcript is underlined
///
/// FSUrlEntryAgentSelf Describes the agent's Second Life agent Url, e.g.,
/// secondlife:///app/agentself/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
class FSUrlEntryAgentSelf : public LLUrlEntryAgent
{
public:
FSUrlEntryAgentSelf();
private:
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
};
// </FS:Ansariel>
///
/// LLUrlEntryExperienceProfile Describes a Second Life experience profile Url, e.g.,
/// secondlife:///app/experience/0e346d8b-4433-4d66-a6b0-fd37083abc4c/profile
@ -598,6 +612,20 @@ public:
/*virtual*/ std::string getUrl(const std::string &string) const;
};
///
/// LLUrlEntryEmail Describes an IPv6 address
///
class LLUrlEntryIPv6 : public LLUrlEntryBase
{
public:
LLUrlEntryIPv6();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
/*virtual*/ std::string getQuery(const std::string &url) const;
std::string mHostPath;
};
///
/// LLUrlEntryJira Describes Jira issue names -KC
///

View File

@ -41,7 +41,7 @@ LLUrlRegistry::LLUrlRegistry()
{
// mUrlEntry.reserve(20);
// [RLVa:KB] - Checked: 2010-11-01 (RLVa-1.2.2a) | Added: RLVa-1.2.2a
mUrlEntry.reserve(28);
mUrlEntry.reserve(29);
// [/RLVa:KB]
// Urls are matched in the order that they were registered
@ -71,6 +71,7 @@ LLUrlRegistry::LLUrlRegistry()
// [RLVa:KB] - Checked: 2010-11-01 (RLVa-1.2.2a) | Added: RLVa-1.2.2a
registerUrl(new LLUrlEntryAgentRLVAnonymizedName());
// [/RLVa:KB]
registerUrl(new FSUrlEntryAgentSelf());// <FS:Ansariel> FIRE-30611: "You" in transcript is underlined
// LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since
// LLUrlEntryAgent is a less specific (catchall for agent urls)
registerUrl(new LLUrlEntryAgent());
@ -95,6 +96,7 @@ LLUrlRegistry::LLUrlRegistry()
// <FS:Ansariel> Allow URLs with no protocol again
registerUrl(new LLUrlEntryHTTPNoProtocol());
registerUrl(new LLUrlEntryEmail());
registerUrl(new LLUrlEntryIPv6());
// parse jira issue names to links -KC
registerUrl(new LLUrlEntryJira());
}

View File

@ -903,4 +903,38 @@ namespace tut
"and even no www something lindenlab.com",
"");
}
template<> template<>
void object::test<16>()
{
//
// test LLUrlEntryIPv6
//
LLUrlEntryIPv6 url;
// Regex tests.
testRegex("match urls with a protocol", url,
"this url should match http://[::1]",
"http://[::1]");
testRegex("match urls with a protocol and query", url,
"this url should match http://[::1]/file.mp3",
"http://[::1]/file.mp3");
testRegex("match urls with a protocol", url,
"this url should match http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]",
"http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]");
testRegex("match urls with port", url,
"let's specify some port http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]:8080",
"http://[2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d]:8080");
testRegex("don't match urls w/o protocol", url,
"looks like an url something [2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d] but no https prefix",
"");
testRegex("don't match incorrect urls", url,
"http://[ 2001:0db8:11a3:09d7:1f34:8a2e:07a0:765d ]",
"");
}
}

View File

@ -175,6 +175,10 @@ public:
virtual void setTitle(const std::string& win_title) {};
// </FS:TT>
// windows only DirectInput8 for joysticks
virtual void* getDirectInput8() { return NULL; };
virtual bool getInputDevices(U32 device_type_filter, void * devices_callback, void* userdata) { return false; };
protected:
LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags);
virtual ~LLWindow();

View File

@ -59,6 +59,9 @@
#include <dinput.h>
#include <Dbt.h.>
#include <InitGuid.h> // needed for llurlentry test to build on some systems
#pragma comment(lib, "dxguid.lib") // needed for llurlentry test to build on some systems
#pragma comment(lib, "dinput8")
const S32 MAX_MESSAGE_PER_UPDATE = 20;
const S32 BITS_PER_PIXEL = 32;
@ -76,6 +79,7 @@ const F32 ICON_FLASH_TIME = 0.5f;
extern BOOL gDebugWindowProc;
LPWSTR gIconResource = IDI_APPLICATION;
LPDIRECTINPUT8 gDirectInput8;
LLW32MsgCallback gAsyncMsgCallback = NULL;
@ -485,6 +489,21 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mhInstance = GetModuleHandle(NULL);
mWndProc = NULL;
// Init Direct Input - needed for joystick / Spacemouse
LPDIRECTINPUT8 di8_interface;
HRESULT status = DirectInput8Create(
mhInstance, // HINSTANCE hinst,
DIRECTINPUT_VERSION, // DWORD dwVersion,
IID_IDirectInput8, // REFIID riidltf,
(LPVOID*)&di8_interface, // LPVOID * ppvOut,
NULL // LPUNKNOWN punkOuter
);
if (status == DI_OK)
{
gDirectInput8 = di8_interface;
}
mSwapMethod = SWAP_METHOD_UNDEFINED;
// No WPARAM yet.
@ -1435,24 +1454,29 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
LL_INFOS("Window") << "pixel formats done." << LL_ENDL ;
S32 swap_method = 0;
S32 cur_format = num_formats-1;
GLint swap_query = WGL_SWAP_METHOD_ARB;
S32 swap_method = 0;
S32 cur_format = 0;
GLint swap_query = WGL_SWAP_METHOD_ARB;
BOOL found_format = FALSE;
while (!found_format && wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
// SL-14705 Fix name tags showing in front of objects with AMD GPUs.
// On AMD hardware we need to iterate from the first pixel format to the end.
// Spec:
// https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_pixel_format.txt
while (wglGetPixelFormatAttribivARB(mhDC, pixel_formats[cur_format], 0, 1, &swap_query, &swap_method))
{
if (swap_method == WGL_SWAP_UNDEFINED_ARB || cur_format <= 0)
if (swap_method == WGL_SWAP_UNDEFINED_ARB)
{
found_format = TRUE;
break;
}
else
else if (cur_format >= (S32)(num_formats - 1))
{
--cur_format;
cur_format = 0;
break;
}
++cur_format;
}
pixel_format = pixel_formats[cur_format];
if (mhDC != 0) // Does The Window Have A Device Context?
@ -4256,6 +4280,28 @@ void LLWindowWin32::setDPIAwareness()
}
}
void* LLWindowWin32::getDirectInput8()
{
return &gDirectInput8;
}
bool LLWindowWin32::getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata)
{
if (gDirectInput8 != NULL)
{
// Enumerate devices
HRESULT status = gDirectInput8->EnumDevices(
(DWORD) device_type_filter, // DWORD dwDevType,
(LPDIENUMDEVICESCALLBACK)di8_devices_callback, // LPDIENUMDEVICESCALLBACK lpCallback, // BOOL DIEnumDevicesCallback( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef ) // BOOL CALLBACK DinputDevice::DevicesCallback
(LPVOID*)userdata, // LPVOID pvRef
DIEDFL_ATTACHEDONLY // DWORD dwFlags
);
return status == DI_OK;
}
return false;
}
F32 LLWindowWin32::getSystemUISize()
{
F32 scale_value = 1.f;

View File

@ -121,6 +121,9 @@ public:
static std::vector<std::string> getDynamicFallbackFontList();
static void setDPIAwareness();
/*virtual*/ void* getDirectInput8();
/*virtual*/ bool getInputDevices(U32 device_type_filter, void * di8_devices_callback, void* userdata);
protected:
LLWindowWin32(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,

View File

@ -743,6 +743,24 @@ LLSD LLControlGroup::getLLSD(const std::string& name)
return get<LLSD>(name);
}
LLSD LLControlGroup::asLLSD(bool diffs_only)
{
// Dump all stored values as LLSD
LLSD result = LLSD::emptyArray();
for (ctrl_name_table_t::iterator iter = mNameTable.begin();
iter != mNameTable.end(); iter++)
{
LLControlVariable *control = iter->second;
if (!control || control->isType(TYPE_STRING) || (diffs_only && control->isDefault()))
{
continue;
}
const std::string& name = iter->first;
result[name] = getLLSD(name);
}
return result;
}
BOOL LLControlGroup::controlExists(const std::string& name)
{
ctrl_name_table_t::iterator iter = mNameTable.find(name);

View File

@ -286,6 +286,8 @@ public:
LLColor4 getColor4(const std::string& name);
LLColor3 getColor3(const std::string& name);
LLSD asLLSD(bool diffs_only);
// generic getter
template<typename T> T get(const std::string& name)
{

View File

@ -2642,7 +2642,7 @@ if (DARWIN)
set(MACOSX_BUNDLE_BUNDLE_NAME "Firestorm")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}")
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2010-2020 The Phoenix Firestorm Project, Inc.")
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2010-2021 The Phoenix Firestorm Project, Inc.")
set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "Firestorm.nib")
set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "LLApplication")

View File

@ -3,4 +3,4 @@
CFBundleName = "Firestorm";
CFBundleShortVersionString = "Firestorm version %%VERSION%%";
CFBundleGetInfoString = "Firestorm version %%VERSION%%, Copyright 2010-2020 The Phoenix Firestorm Project, Inc.";
CFBundleGetInfoString = "Firestorm version %%VERSION%%, Copyright 2010-2021 The Phoenix Firestorm Project, Inc.";

View File

@ -278,10 +278,8 @@
icon="Command_View_Icon"
label_ref="Command_View_Label"
tooltip_ref="Command_View_Tooltip"
execute_function="Floater.Toggle"
execute_parameters="camera"
is_running_function="Floater.IsOpen"
is_running_parameters="camera"
execute_function="View.ToggleCameraFloater"
is_running_function="View.CheckCameraFloater"
/>
<command name="reporter"
available_in_toybox="true"

View File

@ -344,6 +344,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>FSSortDeferalFrames</key>
<map>
<key>Comment</key>
<string>How many frames after an update should we wait before sorting</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>2</integer>
</map>
<key>FSGroupNotifyNoTransparency</key>
<map>
<key>Comment</key>
@ -7444,6 +7455,17 @@
<key>Backup</key>
<integer>0</integer>
</map>
<key>JoystickDeviceUUID</key>
<map>
<key>Comment</key>
<string>Preffered device ID.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string />
</map>
<key>JoystickMouselookYaw</key>
<map>
<key>Comment</key>
@ -25590,5 +25612,16 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<integer>1</integer>
</map>
<key>FSUseSmallCameraFloater</key>
<map>
<key>Comment</key>
<string>If enabled, the camera floater will be smaller and not contain the camera preset controls.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map>
</llsd>

View File

@ -40,6 +40,7 @@ uniform sampler2D specularMap;
VARYING vec2 vary_texcoord0;
vec3 linear_to_srgb(vec3 cl);// <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
void main()
{
vec4 col = texture2D(diffuseMap, vary_texcoord0.xy);
@ -52,6 +53,7 @@ void main()
vec4 norm = texture2D(normalMap, vary_texcoord0.xy);
vec4 spec = texture2D(specularMap, vary_texcoord0.xy);
col.rgb = linear_to_srgb(col.rgb);// <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = spec;
frag_data[2] = vec4(norm.xy,0,0);

View File

@ -405,6 +405,7 @@ void main()
vec3 npos = normalize(-pos.xyz);
vec3 light = vec3(0, 0, 0);
final_specular.rgb = srgb_to_linear(final_specular.rgb);// <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w );

View File

@ -111,7 +111,10 @@ void main()
vec3 n = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
#ifdef HAS_NORMAL_MAP
vec3 t = normalize((mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz);
vec3 b = cross(n, t)*tangent.w;
// <FS:Beq> normalize the bitangent (cross product of two normalised vectors is not itself normalised)
// vec3 b = cross(n, t)*tangent.w;
vec3 b = normalize(cross(n, t)*tangent.w);
// </FS:Beq>
vary_mat0 = vec3(t.x, b.x, n.x);
vary_mat1 = vec3(t.y, b.y, n.y);
@ -122,11 +125,11 @@ vary_normal = n;
#else //HAS_SKIN
vec3 n = normalize(normal_matrix * normal);
#ifdef HAS_NORMAL_MAP
// <FS:Beq> tangents should not use the inv_transpose matrix
// vec3 t = normalize(normal_matrix * tangent.xyz);
vec3 t = normalize((modelview_projection_matrix * vec4(tangent.xyz,0)).xyz);
vec3 t = normalize(normal_matrix * tangent.xyz);
// <FS:Beq> normalize the bitangent (cross product of two normalised vectors is not itself normalised)
// vec3 b = cross(n,t)*tangent.w;
vec3 b = normalize(cross(n,t)*tangent.w);
// </FS:Beq>
vec3 b = cross(n,t)*tangent.w;
//vec3 t = cross(b,n) * binormal.w;
vary_mat0 = vec3(t.x, b.x, n.x);

View File

@ -33,10 +33,10 @@ out vec4 frag_color;
#define frag_color gl_FragColor
#endif
uniform sampler2DRect depthMap;
// uniform sampler2DRect depthMap; // <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform samplerCube environmentMap;
// uniform samplerCube environmentMap;// <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
uniform sampler2D noiseMap;
uniform sampler2D lightFunc;
@ -73,10 +73,10 @@ void main()
vec3 norm = getNorm(frag.xy);
vec4 spec = texture2DRect(specularRect, frag.xy);
spec.rgb = srgb_to_linear(spec.rgb);
// spec.rgb = srgb_to_linear(spec.rgb);// <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb;
diff.rgb = srgb_to_linear(diff.rgb);
// diff.rgb = srgb_to_linear(diff.rgb);// <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
float noise = texture2D(noiseMap, frag.xy / 128.0).b;
vec3 npos = normalize(-pos);

View File

@ -40,9 +40,14 @@ out vec4 frag_color;
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect depthMap;
// <FS:Beq> Colour space and shader fixes for BUG-228586 (Rye)
// uniform sampler2DRect depthMap;
// </FS:Beq>
uniform sampler2DRect normalMap;
uniform samplerCube environmentMap;
// <FS:Beq> Colour space and shader fixes for BUG-228586 (Rye)
// uniform samplerCube environmentMap;
// </FS:Beq>
uniform sampler2D noiseMap;
uniform sampler2D projectionMap;
uniform sampler2D lightFunc;
@ -182,11 +187,12 @@ void main()
vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
// SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space.
// We can't switch to linear here unless we do it everywhere*
// *gbuffer is sRGB, convert to linear whenever sampling from it
diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
// <FS:Beq> Colour space and shader fixes for BUG-228586 (Rye)
// // SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space.
// // We can't switch to linear here unless we do it everywhere*
// // *gbuffer is sRGB, convert to linear whenever sampling from it
// diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
// </FS:Beq>
vec3 dlit = vec3(0, 0, 0);

View File

@ -35,11 +35,13 @@ out vec4 frag_color;
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect normalMap;
uniform samplerCube environmentMap;
// <FS:Beq> Colour space and shader fixes for BUG-228586 (Rye)
//uniform sampler2DRect normalMap;
//uniform samplerCube environmentMap;
// </FS:Beq>
uniform sampler2D noiseMap;
uniform sampler2D lightFunc;
uniform sampler2DRect depthMap;
//uniform sampler2DRect depthMap;// <FS:Beq/> Colour space and shader fixes for BUG-228586 (Rye)
uniform vec3 env_mat[3];
uniform float sun_wash;
@ -90,7 +92,7 @@ void main()
float noise = texture2D(noiseMap, frag.xy/128.0).b;
vec3 col = texture2DRect(diffuseRect, frag.xy).rgb;
col.rgb = srgb_to_linear(col.rgb);
// col.rgb = srgb_to_linear(col.rgb); // <FS:Beq> Colour space and shader fixes for BUG-228586 (Rye)
float fa = falloff+1.0;
float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);

View File

@ -37,7 +37,8 @@ out vec4 frag_color;
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect normalMap;
uniform sampler2DRect lightMap;
// <FS:Beq> Colour space and shader fixes for BUG-228586 (Rye)
// uniform sampler2DRect lightMap;
uniform sampler2DRect depthMap;
uniform samplerCube environmentMap;
uniform sampler2D lightFunc;
@ -90,7 +91,7 @@ void main()
vec4 diffuse = texture2DRect(diffuseRect, tc);
//convert to gamma space
//diffuse.rgb = linear_to_srgb(diffuse.rgb);
diffuse.rgb = linear_to_srgb(diffuse.rgb);// <FS:Beq> Colour space and shader fixes for BUG-228586 (Rye) uniform sampler2DRect depthMap;
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
vec3 color = vec3(0);

View File

@ -177,8 +177,11 @@ void main()
float da = dot(norm, lv);
vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
//light shaders output linear and are gamma corrected later in postDeferredGammaCorrectF.glsl
diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
// <FS:Beq> Colour space and shader fixes for BUG-228586
// This makes the comment below incorrect, it will presumably be removed if/when the lab apply the proper changes)
// // light shaders output linear and are gamma corrected later in postDeferredGammaCorrectF.glsl
// diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
// </FS:Beq>
vec4 spec = texture2DRect(specularRect, frag.xy);

View File

@ -43,13 +43,13 @@ void default_lighting()
{
vec4 color = texture2D(diffuseMap,vary_texcoord0.xy);
color *= vertex_color;
if (color.a < minimum_alpha)
{
discard;
}
color *= vertex_color;
color.rgb = atmosLighting(color.rgb);
color.rgb = scaleSoftClip(color.rgb);

View File

@ -43,13 +43,13 @@ void fullbright_lighting_water()
{
vec4 color = diffuseLookup(vary_texcoord0.xy);
color.rgb *= vertex_color.rgb;
if (color.a < minimum_alpha)
{
discard;
}
color.rgb *= vertex_color.rgb;
color.rgb = fullbrightAtmosTransport(color.rgb);
frag_color = applyWaterFog(color);

View File

@ -41,13 +41,15 @@ VARYING vec2 vary_texcoord0;
void fullbright_lighting_water()
{
vec4 color = texture2D(diffuseMap, vary_texcoord0.xy) * vertex_color;
vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
if (color.a < minimum_alpha)
{
discard;
}
color.rgb *= vertex_color.rgb;
color.rgb = fullbrightAtmosTransport(color.rgb);
frag_color = applyWaterFog(color);

View File

@ -41,13 +41,13 @@ void default_lighting_water()
{
vec4 color = diffuseLookup(vary_texcoord0.xy);
color.rgb *= vertex_color.rgb;
if (color.a < minimum_alpha)
{
discard;
}
color.rgb *= vertex_color.rgb;
color.rgb = atmosLighting(color.rgb);
frag_color = applyWaterFog(color);

View File

@ -43,13 +43,13 @@ void default_lighting_water()
{
vec4 color = texture2D(diffuseMap,vary_texcoord0.xy);
color.rgb *= vertex_color.rgb;
if (color.a < minimum_alpha)
{
discard;
}
color.rgb *= vertex_color.rgb;
color.rgb = atmosLighting(color.rgb);
color = applyWaterFog(color);

View File

@ -191,11 +191,12 @@ void main()
float da = dot(norm, lv);
vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
// SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space.
// We can't switch to linear here unless we do it everywhere*
// *gbuffer IS sRGB, convert to linear since this shader outputs linear
diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
// <FS:Beq> Colour space and shader fixes for BUG-228586
// removing comments as colour space change
// // SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space.
// // We can't switch to linear here unless we do it everywhere*
// // *gbuffer IS sRGB, convert to linear since this shader outputs linear
// diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
vec4 spec = texture2DRect(specularRect, frag.xy);
vec3 dlit = vec3(0, 0, 0);

View File

@ -88,6 +88,10 @@ void main()
da = pow(da, light_gamma);
vec4 diffuse = texture2DRect(diffuseRect, tc);
// <FS:Beq> Colour space and shader fixes for BUG-228586 (Rye)
// convert to gamma space
diffuse.rgb = linear_to_srgb(diffuse.rgb);
// </FS:Beq>
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;

View File

@ -188,8 +188,10 @@ void main()
lv = proj_origin-pos.xyz;
lv = normalize(lv);
float da = dot(norm, lv);
vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb);
// <FS:Beq> Colour space and shader fixes for BUG-228586 (Rye)
// vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb);
vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
// </FS:Beq>
vec4 spec = texture2DRect(specularRect, frag.xy);
vec3 dlit = vec3(0, 0, 0);

View File

@ -1505,17 +1505,10 @@ void FSChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
}
name_params.use_default_link_style = false;
name_params.link_href = LLSLURL("agent", chat.mFromID, "inspect").getSLURLString();
name_params.link_href = LLSLURL(from_me ? "agentself" : "agent", chat.mFromID, "inspect").getSLURLString();
if (from_me && gSavedSettings.getBOOL("FSChatHistoryShowYou"))
{
appendText(LLTrans::getString("AgentNameSubst"), prependNewLineState, name_params);
}
else
{
// Add link to avatar's inspector and delimiter to message.
appendText(std::string(name_params.link_href), prependNewLineState, name_params);
}
// Add link to avatar's inspector and delimiter to message.
appendText(std::string(name_params.link_href), prependNewLineState, name_params);
prependNewLineState = false;

View File

@ -72,6 +72,8 @@ void FSPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
if(!mParticipantList)
{
LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id);
// <FS:Beq/> potential crash avoidance. getSpeakerManager can return NULL, the constructor does not check
if ( speaker_manager == nullptr ){ return;}
mParticipantList = new FSParticipantList(speaker_manager, getChild<LLAvatarList>("grp_speakers_list"), true,false);
}
}

View File

@ -1029,6 +1029,18 @@ boost::signals2::connection LLAgent::addParcelChangedCallback(parcel_changed_cal
return mParcelChangedSignal.connect(cb);
}
// static
void LLAgent::capabilityReceivedCallback(const LLUUID &region_id)
{
LLViewerRegion* region = gAgent.getRegion();
if (region && region->getRegionID() == region_id)
{
region->requestSimulatorFeatures();
LLAppViewer::instance()->updateNameLookupUrl();
}
}
//-----------------------------------------------------------------------------
// setRegion()
//-----------------------------------------------------------------------------
@ -1079,10 +1091,11 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
if (regionp->capabilitiesReceived())
{
regionp->requestSimulatorFeatures();
LLAppViewer::instance()->updateNameLookupUrl();
}
else
{
regionp->setCapabilitiesReceivedCallback(boost::bind(&LLViewerRegion::requestSimulatorFeatures, regionp));
regionp->setCapabilitiesReceivedCallback(LLAgent::capabilityReceivedCallback);
}
}
@ -1101,6 +1114,15 @@ void LLAgent::setRegion(LLViewerRegion *regionp)
// Update all of the regions.
LLWorld::getInstance()->updateAgentOffset(mAgentOriginGlobal);
if (regionp->capabilitiesReceived())
{
LLAppViewer::instance()->updateNameLookupUrl();
}
else
{
regionp->setCapabilitiesReceivedCallback([](const LLUUID &region_id) {LLAppViewer::instance()->updateNameLookupUrl(); });
}
}
// Pass new region along to metrics components that care about this level of detail.
@ -5967,8 +5989,8 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
if ((S32)texture_index < TEX_NUM_INDICES )
{
const LLAvatarAppearanceDictionary::TextureEntry *texture_entry = LLAvatarAppearanceDictionary::instance().getTexture((ETextureIndex)texture_index);
{
const LLAvatarAppearanceDictionary::TextureEntry *texture_entry = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)texture_index);
if (texture_entry)
{
EBakedTextureIndex baked_index = texture_entry->mBakedTextureIndex;
@ -6034,8 +6056,8 @@ void LLAgent::dumpSentAppearance(const std::string& dump_prefix)
F32 value = appearance_version_param->getWeight();
dump_visual_param(file, appearance_version_param, value);
}
for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin();
iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end();
for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin();
iter != LLAvatarAppearance::getDictionary()->getTextures().end();
++iter)
{
const ETextureIndex index = iter->first;
@ -6144,7 +6166,7 @@ void LLAgent::sendAgentSetAppearance()
{
for(U8 baked_index = 0; baked_index < gAgentAvatarp->getNumBakes(); baked_index++ )
{
const ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index);
const ETextureIndex texture_index = LLAvatarAppearance::getDictionary()->bakedToLocalTextureIndex((EBakedTextureIndex)baked_index);
// if we're not wearing a skirt, we don't need the texture to be baked
if (texture_index == TEX_SKIRT_BAKED && !gAgentAvatarp->isWearingWearableType(LLWearableType::WT_SKIRT))
@ -6203,7 +6225,7 @@ void LLAgent::sendAgentSetAppearance()
const LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash);
if (hash.notNull())
{
ETextureIndex texture_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex) baked_index);
ETextureIndex texture_index = LLAvatarAppearance::getDictionary()->bakedToLocalTextureIndex((EBakedTextureIndex) baked_index);
msg->nextBlockFast(_PREHASH_WearableData);
msg->addUUIDFast(_PREHASH_CacheID, hash);
msg->addU8Fast(_PREHASH_TextureIndex, (U8)texture_index);

View File

@ -258,6 +258,8 @@ public:
boost::signals2::connection addParcelChangedCallback(parcel_changed_callback_t);
private:
static void capabilityReceivedCallback(const LLUUID &region_id);
typedef boost::signals2::signal<void()> parcel_changed_signal_t;
parcel_changed_signal_t mParcelChangedSignal;

View File

@ -1323,6 +1323,38 @@ void LLAgentCamera::updateCamera()
gAgentCamera.getPanDownKey() > 0.f); // bottom
}
// <FS:Ansariel> Phototools camera
camera_floater = LLFloaterReg::findTypedInstance<LLFloaterCamera>("phototools_camera");
if (camera_floater)
{
camera_floater->mRotate->setToggleState(gAgentCamera.getOrbitRightKey() > 0.f, // left
gAgentCamera.getOrbitUpKey() > 0.f, // top
gAgentCamera.getOrbitLeftKey() > 0.f, // right
gAgentCamera.getOrbitDownKey() > 0.f); // bottom
camera_floater->mTrack->setToggleState(gAgentCamera.getPanLeftKey() > 0.f, // left
gAgentCamera.getPanUpKey() > 0.f, // top
gAgentCamera.getPanRightKey() > 0.f, // right
gAgentCamera.getPanDownKey() > 0.f); // bottom
}
// </FS:Ansariel>
// <FS:Ansariel> Optional small camera floater
camera_floater = LLFloaterReg::findTypedInstance<LLFloaterCamera>("fs_camera_small");
if (camera_floater)
{
camera_floater->mRotate->setToggleState(gAgentCamera.getOrbitRightKey() > 0.f, // left
gAgentCamera.getOrbitUpKey() > 0.f, // top
gAgentCamera.getOrbitLeftKey() > 0.f, // right
gAgentCamera.getOrbitDownKey() > 0.f); // bottom
camera_floater->mTrack->setToggleState(gAgentCamera.getPanLeftKey() > 0.f, // left
gAgentCamera.getPanUpKey() > 0.f, // top
gAgentCamera.getPanRightKey() > 0.f, // right
gAgentCamera.getPanDownKey() > 0.f); // bottom
}
// </FS:Ansariel>
// Handle camera movement based on keyboard.
const F32 ORBIT_OVER_RATE = 90.f * DEG_TO_RAD; // radians per second
const F32 ORBIT_AROUND_RATE = 90.f * DEG_TO_RAD; // radians per second

View File

@ -2141,7 +2141,7 @@ void LLAgentWearables::queryWearableCache()
num_queries++;
// *NOTE: make sure at least one request gets packed
ETextureIndex te_index = LLAvatarAppearanceDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)baked_index);
ETextureIndex te_index = LLAvatarAppearance::getDictionary()->bakedToLocalTextureIndex((EBakedTextureIndex)baked_index);
//LL_INFOS() << "Requesting texture for hash " << hash << " in baked texture slot " << baked_index << LL_ENDL;
gMessageSystem->nextBlockFast(_PREHASH_WearableData);

View File

@ -2066,7 +2066,7 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id)
}
// Moved from LLWearableList::ContextMenu for wider utility.
bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids)
bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids) const
{
// TODO: investigate wearables may not be loaded at this point EXT-8231
@ -2076,7 +2076,7 @@ bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids)
// Count given clothes (by wearable type) and objects.
for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it)
{
LLViewerInventoryItem* item = gInventory.getItem(*it);
const LLViewerInventoryItem* item = gInventory.getItem(*it);
if (!item)
{
return false;

View File

@ -106,7 +106,7 @@ public:
bool getCanReplaceCOF(const LLUUID& outfit_cat_id);
// Can we add all referenced items to the avatar?
bool canAddWearables(const uuid_vec_t& item_ids);
bool canAddWearables(const uuid_vec_t& item_ids) const;
// Copy all items in a category.
void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id,

View File

@ -316,7 +316,7 @@ extern BOOL gHiDPISupport;
////////////////////////////////////////////////////////////
// All from the last globals push...
F32 gSimLastTime; // Used in LLAppViewer::init and send_stats()
F32 gSimLastTime; // Used in LLAppViewer::init and send_viewer_stats()
F32 gSimFrames;
BOOL gShowObjectUpdates = FALSE;
@ -753,6 +753,7 @@ LLAppViewer::LLAppViewer()
mPurgeCacheOnExit(false),
mPurgeUserDataOnExit(false),
mSecondInstance(false),
mUpdaterNotFound(false),
mSavedFinalSnapshot(false),
mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded.
mQuitRequested(false),
@ -766,6 +767,7 @@ LLAppViewer::LLAppViewer()
mFastTimerLogThread(NULL),
mSettingsLocationList(NULL),
mIsFirstRun(false),
//mMinMicroSecPerFrame(0.f), // <FS:Ansariel> FIRE-22297: FPS limiter not working properly on Mac/Linux
mSaveSettingsOnExit(true), // <FS:Zi> Backup Settings
mPurgeTextures(false) // <FS:Ansariel> FIRE-13066
{
@ -1370,78 +1372,101 @@ bool LLAppViewer::init()
gGLActive = FALSE;
// <FS:Ansariel> Disable updater
// <FS:Ansariel> Disable updater
//#if LL_RELEASE_FOR_DOWNLOAD
// if (!gSavedSettings.getBOOL("CmdLineSkipUpdater"))
// {
// LLProcess::Params updater;
// updater.desc = "updater process";
// // Because it's the updater, it MUST persist beyond the lifespan of the
// // viewer itself.
// updater.autokill = false;
// LLProcess::Params updater;
// updater.desc = "updater process";
// // Because it's the updater, it MUST persist beyond the lifespan of the
// // viewer itself.
// updater.autokill = false;
// std::string updater_file;
//#if LL_WINDOWS
// updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "SLVersionChecker.exe");
// updater_file = "SLVersionChecker.exe";
// updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file);
//#elif LL_DARWIN
// // explicitly run the system Python interpreter on SLVersionChecker.py
// updater.executable = "python";
// updater.args.add(gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", "SLVersionChecker.py"));
// // explicitly run the system Python interpreter on SLVersionChecker.py
// updater.executable = "python";
// updater_file = "SLVersionChecker.py";
// updater.args.add(gDirUtilp->add(gDirUtilp->getAppRODataDir(), "updater", updater_file));
//#else
// updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "SLVersionChecker");
// updater_file = "SLVersionChecker";
// updater.executable = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, updater_file);
//#endif
// // add LEAP mode command-line argument to whichever of these we selected
// updater.args.add("leap");
// // UpdaterServiceSettings
// updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting")));
// // channel
// updater.args.add(LLVersionInfo::getChannel());
// // testok
// updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest")));
// // ForceAddressSize
// updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize")));
//#if LL_WINDOWS && !LL_RELEASE_FOR_DOWNLOAD && !LL_SEND_CRASH_REPORTS
// // This is neither a release package, nor crash-reporting enabled test build
// // try to run version updater, but don't bother if it fails (file might be missing)
// LLLeap *leap_p = LLLeap::create(updater, false);
// if (!leap_p)
// {
// LL_WARNS("LLLeap") << "Failed to run LLLeap" << LL_ENDL;
// // add LEAP mode command-line argument to whichever of these we selected
// updater.args.add("leap");
// // UpdaterServiceSettings
// updater.args.add(stringize(gSavedSettings.getU32("UpdaterServiceSetting")));
// // channel
// updater.args.add(LLVersionInfo::instance().getChannel());
// // testok
// updater.args.add(stringize(gSavedSettings.getBOOL("UpdaterWillingToTest")));
// // ForceAddressSize
// updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize")));
//
// try
// {
// // Run the updater. An exception from launching the updater should bother us.
// LLLeap::create(updater, true);
// mUpdaterNotFound = false;
// }
// catch (...)
// {
// LLUIString details = LLNotifications::instance().getGlobalString("LLLeapUpdaterFailure");
// details.setArg("[UPDATER_APP]", updater_file);
// OSMessageBox(
// details.getString(),
// LLStringUtil::null,
// OSMB_OK);
// mUpdaterNotFound = true;
// }
// }
//#else
// // Run the updater. An exception from launching the updater should bother us.
// LLLeap::create(updater, true);
//#endif
// else
// {
// LL_WARNS("InitInfo") << "Skipping updater check." << LL_ENDL;
// }
//
// if (mUpdaterNotFound)
// {
// LL_WARNS("InitInfo") << "Failed to launch updater. Skipping Leap commands." << LL_ENDL;
// }
// else
// {
// // Iterate over --leap command-line options. But this is a bit tricky: if
// // there's only one, it won't be an array at all.
// LLSD LeapCommand(gSavedSettings.getLLSD("LeapCommand"));
// LL_DEBUGS("InitInfo") << "LeapCommand: " << LeapCommand << LL_ENDL;
// if (LeapCommand.isDefined() && !LeapCommand.isArray())
// {
// // If LeapCommand is actually a scalar value, make an array of it.
// // Have to do it in two steps because LeapCommand.append(LeapCommand)
// // trashes content! :-P
// LLSD item(LeapCommand);
// LeapCommand.append(item);
// }
// BOOST_FOREACH(const std::string& leap, llsd::inArray(LeapCommand))
// {
// LL_INFOS("InitInfo") << "processing --leap \"" << leap << '"' << LL_ENDL;
// // We don't have any better description of this plugin than the
// // user-specified command line. Passing "" causes LLLeap to derive a
// // description from the command line itself.
// // Suppress LLLeap::Error exception: trust LLLeap's own logging. We
// // don't consider any one --leap command mission-critical, so if one
// // fails, log it, shrug and carry on.
// LLLeap::create("", leap, false); // exception=false
// }
// }
//
// if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
// {
// LL_WARNS("InitInfo") << "QAModeEventHostPort DEPRECATED: "
// << "lleventhost no longer supported as a dynamic library"
// << LL_ENDL;
// }
//#endif //LL_RELEASE_FOR_DOWNLOAD
// </FS:Ansariel>
// Iterate over --leap command-line options. But this is a bit tricky: if
// there's only one, it won't be an array at all.
LLSD LeapCommand(gSavedSettings.getLLSD("LeapCommand"));
LL_DEBUGS("InitInfo") << "LeapCommand: " << LeapCommand << LL_ENDL;
if (LeapCommand.isDefined() && ! LeapCommand.isArray())
{
// If LeapCommand is actually a scalar value, make an array of it.
// Have to do it in two steps because LeapCommand.append(LeapCommand)
// trashes content! :-P
LLSD item(LeapCommand);
LeapCommand.append(item);
}
BOOST_FOREACH(const std::string& leap, llsd::inArray(LeapCommand))
{
LL_INFOS("InitInfo") << "processing --leap \"" << leap << '"' << LL_ENDL;
// We don't have any better description of this plugin than the
// user-specified command line. Passing "" causes LLLeap to derive a
// description from the command line itself.
// Suppress LLLeap::Error exception: trust LLLeap's own logging. We
// don't consider any one --leap command mission-critical, so if one
// fails, log it, shrug and carry on.
LLLeap::create("", leap, false); // exception=false
}
if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
{
LL_WARNS("InitInfo") << "QAModeEventHostPort DEPRECATED: "
<< "lleventhost no longer supported as a dynamic library"
<< LL_ENDL;
}
LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
//EXT-7013 - On windows for some locale (Japanese) standard
@ -1495,6 +1520,12 @@ bool LLAppViewer::init()
joystick = LLViewerJoystick::getInstance();
joystick->setNeedsReset(true);
/*----------------------------------------------------------------------*/
// <FS:Ansariel> FIRE-22297: FPS limiter not working properly on Mac/Linux
//gSavedSettings.getControl("FramePerSecondLimit")->getSignal()->connect(boost::bind(&LLAppViewer::onChangeFrameLimit, this, _2));
//onChangeFrameLimit(gSavedSettings.getLLSD("FramePerSecondLimit"));
// </FS:Ansariel>
return true;
}
@ -1772,6 +1803,23 @@ bool LLAppViewer::doFrame()
display();
// <FS:Ansariel> FIRE-22297: FPS limiter not working properly on Mac/Linux
//static U64 last_call = 0;
//if (!gTeleportDisplay)
//{
// // Frame/draw throttling, controlled by FramePerSecondLimit
// U64 elapsed_time = LLTimer::getTotalTime() - last_call;
// if (elapsed_time < mMinMicroSecPerFrame)
// {
// LL_RECORD_BLOCK_TIME(FTM_SLEEP);
// // llclamp for when time function gets funky
// U64 sleep_time = llclamp(mMinMicroSecPerFrame - elapsed_time, (U64)1, (U64)1e6);
// micro_sleep(sleep_time, 0);
// }
//}
//last_call = LLTimer::getTotalTime();
// </FS:Ansariel>
pingMainloopTimeout("Main:Snapshot");
LLFloaterSnapshot::update(); // take snapshots
LLFloaterOutfitSnapshot::update();
@ -2213,9 +2261,6 @@ bool LLAppViewer::cleanup()
SUBSYSTEM_CLEANUP(LLAvatarAppearance);
// <FS:Ansariel> Comment out duplicate clean up
//SUBSYSTEM_CLEANUP(LLAvatarAppearance);
SUBSYSTEM_CLEANUP(LLPostProcess);
LLTracker::cleanupInstance();
@ -2455,6 +2500,7 @@ bool LLAppViewer::cleanup()
LLUIImageList::getInstance()->cleanUp();
// This should eventually be done in LLAppViewer
SUBSYSTEM_CLEANUP(LLImage);
SUBSYSTEM_CLEANUP(LLVFSThread);
SUBSYSTEM_CLEANUP(LLLFSThread);
@ -2498,6 +2544,7 @@ bool LLAppViewer::cleanup()
LLWeb::loadURLExternal( gLaunchFileOnQuit, false );
LL_INFOS() << "File launched." << LL_ENDL;
}
// make sure nothing uses applyProxySettings by this point.
LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL;
SUBSYSTEM_CLEANUP(LLProxy);
LLCore::LLHttp::cleanup();
@ -2553,7 +2600,7 @@ bool LLAppViewer::initThreads()
{
static const bool enable_threads = true;
LLImage::initParamSingleton(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange"));
LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange"));
LLVFSThread::initClass(enable_threads && false);
LLLFSThread::initClass(enable_threads && false);
@ -3782,7 +3829,7 @@ LLSD LLAppViewer::getViewerInfo() const
info["POSITION_LOCAL"] = ll_sd_from_vector3(gAgent.getPosAgentFromGlobal(pos));
info["REGION"] = gAgent.getRegion()->getName();
boost::regex regex("\\.(secondlife|lindenlab)\\..*");
info["HOSTNAME"] = boost::regex_replace(gAgent.getRegion()->getHost().getHostName(), regex, "");
info["HOSTNAME"] = boost::regex_replace(gAgent.getRegion()->getSimHostName(), regex, "");
LLSLURL slurl;
LLAgentUI::buildSLURL(slurl);
info["SLURL"] = slurl.getSLURLString();
@ -4368,7 +4415,7 @@ void LLAppViewer::handleViewerCrash()
if(gAgent.getRegion())
{
gDebugInfo["Dynamic"]["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
gDebugInfo["Dynamic"]["CurrentSimHost"] = gAgent.getRegion()->getSimHostName();
gDebugInfo["Dynamic"]["CurrentRegion"] = gAgent.getRegion()->getName();
const LLVector3& loc = gAgent.getPositionAgent();
@ -4775,7 +4822,11 @@ void LLAppViewer::requestQuit()
gFloaterView->closeAllChildren(true);
}
send_stats();
// Send preferences once, when exiting
// <FS:Ansariel> Don't send all non-default settings which might result in a violation of GDPR
//bool include_preferences = true;
bool include_preferences = false;
send_viewer_stats(include_preferences);
gLogoutTimer.reset();
mQuitRequested = true;
@ -5653,7 +5704,8 @@ void LLAppViewer::idle()
if (viewer_stats_timer.getElapsedTimeF32() >= SEND_STATS_PERIOD && !gDisconnected)
{
LL_INFOS() << "Transmitting sessions stats" << LL_ENDL;
send_stats();
bool include_preferences = false;
send_viewer_stats(include_preferences);
viewer_stats_timer.reset();
}
@ -6074,11 +6126,56 @@ void LLAppViewer::sendLogoutRequest()
}
}
void LLAppViewer::updateNameLookupUrl()
{
LLViewerRegion* region = gAgent.getRegion();
if (!region || !region->capabilitiesReceived())
{
return;
}
LLAvatarNameCache *name_cache = LLAvatarNameCache::getInstance();
bool had_capability = LLAvatarNameCache::getInstance()->hasNameLookupURL();
std::string name_lookup_url;
name_lookup_url.reserve(128); // avoid a memory allocation below
name_lookup_url = region->getCapability("GetDisplayNames");
bool have_capability = !name_lookup_url.empty();
if (have_capability)
{
// we have support for display names, use it
U32 url_size = name_lookup_url.size();
// capabilities require URLs with slashes before query params:
// https://<host>:<port>/cap/<uuid>/?ids=<blah>
// but the caps are granted like:
// https://<host>:<port>/cap/<uuid>
if (url_size > 0 && name_lookup_url[url_size - 1] != '/')
{
name_lookup_url += '/';
}
name_cache->setNameLookupURL(name_lookup_url);
}
else
{
// Display names not available on this region
name_cache->setNameLookupURL(std::string());
}
// Error recovery - did we change state?
if (had_capability != have_capability)
{
// name tags are persistant on screen, so make sure they refresh
LLVOAvatar::invalidateNameTags();
}
}
void LLAppViewer::idleNameCache()
{
// Neither old nor new name cache can function before agent has a region
LLViewerRegion* region = gAgent.getRegion();
if (!region) return;
if (!region)
{
return;
}
// deal with any queued name requests and replies.
gCacheName->processPending();
@ -6086,47 +6183,12 @@ void LLAppViewer::idleNameCache()
// Can't run the new cache until we have the list of capabilities
// for the agent region, and can therefore decide whether to use
// display names or fall back to the old name system.
if (!region->capabilitiesReceived()) return;
if (!region->capabilitiesReceived())
{
return;
}
// Agent may have moved to a different region, so need to update cap URL
// for name lookups. Can't do this in the cap grant code, as caps are
// granted to neighbor regions before the main agent gets there. Can't
// do it in the move-into-region code because cap not guaranteed to be
// granted yet, for example on teleport.
LLAvatarNameCache *name_cache = LLAvatarNameCache::getInstance();
bool had_capability = LLAvatarNameCache::getInstance()->hasNameLookupURL();
std::string name_lookup_url;
name_lookup_url.reserve(128); // avoid a memory allocation below
name_lookup_url = region->getCapability("GetDisplayNames");
bool have_capability = !name_lookup_url.empty();
if (have_capability)
{
// we have support for display names, use it
U32 url_size = name_lookup_url.size();
// capabilities require URLs with slashes before query params:
// https://<host>:<port>/cap/<uuid>/?ids=<blah>
// but the caps are granted like:
// https://<host>:<port>/cap/<uuid>
if (url_size > 0 && name_lookup_url[url_size-1] != '/')
{
name_lookup_url += '/';
}
name_cache->setNameLookupURL(name_lookup_url);
}
else
{
// Display names not available on this region
name_cache->setNameLookupURL( std::string() );
}
// Error recovery - did we change state?
if (had_capability != have_capability)
{
// name tags are persistant on screen, so make sure they refresh
LLVOAvatar::invalidateNameTags();
}
name_cache->idle();
LLAvatarNameCache::getInstance()->idle();
}
//
@ -6137,6 +6199,7 @@ void LLAppViewer::idleNameCache()
#ifdef TIME_THROTTLE_MESSAGES
#define CHECK_MESSAGES_DEFAULT_MAX_TIME .020f // 50 ms = 50 fps (just for messages!)
#define CHECK_MESSAGES_MAX_TIME_LIMIT 1.0f // 1 second, a long time but still able to stay connected
static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
#endif
@ -6202,11 +6265,24 @@ void LLAppViewer::idleNetwork()
#ifdef TIME_THROTTLE_MESSAGES
if (total_time >= CheckMessagesMaxTime)
{
// Increase CheckMessagesMaxTime so that we will eventually catch up
CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames
// <FS:Beq> Don't allow busy network to excessively starve rendering loop
// // Increase CheckMessagesMaxTime so that we will eventually catch up
// CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames
// }
// else
// {
if( CheckMessagesMaxTime < CHECK_MESSAGES_MAX_TIME_LIMIT ) // cap the increase to avoid logout through ping starvation
{// Increase CheckMessagesMaxTime so that we will eventually catch up
CheckMessagesMaxTime *= 1.035f; // 3.5% ~= x2 in 20 frames, ~8x in 60 frames
}
else
{
CheckMessagesMaxTime = CHECK_MESSAGES_MAX_TIME_LIMIT;
}
}
else
{
// </FS:Beq>
// Reset CheckMessagesMaxTime to default value
CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
}
@ -6348,6 +6424,21 @@ void LLAppViewer::disconnectViewer()
LLUrlEntryParcel::setDisconnected(gDisconnected);
}
// <FS:Ansariel> FIRE-22297: FPS limiter not working properly on Mac/Linux
//bool LLAppViewer::onChangeFrameLimit(LLSD const & evt)
//{
// if (evt.asInteger() > 0)
// {
// mMinMicroSecPerFrame = (U64)(1000000.0f / F32(evt.asInteger()));
// }
// else
// {
// mMinMicroSecPerFrame = 0;
// }
// return false;
//}
// </FS:Ansariel>
void LLAppViewer::forceErrorLLError()
{
LL_ERRS() << "This is a deliberate llerror" << LL_ENDL;
@ -6517,7 +6608,7 @@ void LLAppViewer::handleLoginComplete()
/*
if(gAgent.getRegion())
{
gDebugInfo["CurrentSimHost"] = gAgent.getRegionHost().getHostName();
gDebugInfo["CurrentSimHost"] = gAgent.getRegion()->getSimHostName();
gDebugInfo["CurrentRegion"] = gAgent.getRegion()->getName();
}
*/

View File

@ -95,6 +95,7 @@ public:
bool quitRequested() { return mQuitRequested; }
bool logoutRequestSent() { return mLogoutRequestSent; }
bool isSecondInstance() { return mSecondInstance; }
bool isUpdaterMissing() { return mUpdaterNotFound; }
void writeDebugInfo(bool isStatic=true);
@ -217,7 +218,9 @@ public:
// llcorehttp init/shutdown/config information.
LLAppCoreHttp & getAppCoreHttp() { return mAppCoreHttp; }
void updateNameLookupUrl();
protected:
virtual bool initWindow(); // Initialize the viewer's window.
virtual void initLoggingAndGetLastDuration(); // Initialize log files, logging system
@ -266,11 +269,15 @@ private:
void sendLogoutRequest();
void disconnectViewer();
// <FS:Ansariel> FIRE-22297: FPS limiter not working properly on Mac/Linux
//bool onChangeFrameLimit(LLSD const & evt);
// *FIX: the app viewer class should be some sort of singleton, no?
// Perhaps its child class is the singleton and this should be an abstract base.
static LLAppViewer* sInstance;
bool mSecondInstance; // Is this a second instance of the app?
bool mUpdaterNotFound; // True when attempt to start updater failed
std::string mMarkerFileName;
LLAPRFile mMarkerFile; // A file created to indicate the app is running.
@ -332,7 +339,11 @@ private:
// llcorehttp library init/shutdown helper
LLAppCoreHttp mAppCoreHttp;
bool mIsFirstRun;
bool mIsFirstRun;
// <FS:Ansariel> FIRE-22297: FPS limiter not working properly on Mac/Linux
//U64 mMinMicroSecPerFrame; // frame throttling
// <FS:Zi> Backup Settings
public:
void setSaveSettingsOnExit(bool state) {mSaveSettingsOnExit = state; };

View File

@ -543,8 +543,11 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
return false;
}
bool purge_required = false;
char buffer[MAX_STRING];
// <FS:Beq> FIRE-30705 protect against silly display names that cause lines to exceed max string length
// char buffer[MAX_STRING];
static constexpr int BUFFER_1K { 1024 }; // long enough to handle the most extreme Unicode nonsense and some to spare
char buffer[BUFFER_1K];
// </FS:Beq>
char conv_name_buffer[MAX_STRING];
char part_id_buffer[MAX_STRING];
char conv_id_buffer[MAX_STRING];
@ -555,12 +558,21 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
// before CHUI-348 it was a flag of conversation voice state
int prereserved_unused;
while (!feof(fp) && fgets(buffer, MAX_STRING, fp))
// <FS:Beq/> FIRE-30705 protect against silly display names that cause lines to exceed max string length
// while (!feof(fp) && fgets(buffer, MAX_STRING, fp))
// {
// conv_name_buffer[0] = '\0';
// part_id_buffer[0] = '\0';
// conv_id_buffer[0] = '\0';
memset( buffer, '\0', BUFFER_1K );
while (!feof(fp) && fgets(buffer, BUFFER_1K, fp))
{
conv_name_buffer[0] = '\0';
part_id_buffer[0] = '\0';
conv_id_buffer[0] = '\0';
// force blank for added safety
memset( conv_name_buffer, '\0', MAX_STRING );
memset( part_id_buffer, '\0', MAX_STRING );
memset( conv_id_buffer, '\0', MAX_STRING );
memset( history_file_name, '\0', MAX_STRING );
// </FS:Beq>
sscanf(buffer, "[%lld] %d %d %d %[^|]| %s %s %[^|]|",
&time,
&stype,
@ -598,6 +610,7 @@ bool LLConversationLog::loadFromFile(const std::string& filename)
}
mConversations.push_back(conversation);
memset( buffer, '\0', BUFFER_1K ); // <FS:Beq> FIRE-30705 clear buffer down
}
fclose(fp);

View File

@ -1110,7 +1110,7 @@ void LLEnvironment::onRegionChange()
}
if (!cur_region->capabilitiesReceived())
{
cur_region->setCapabilitiesReceivedCallback([](LLUUID region_id) { LLEnvironment::instance().requestRegion(); });
cur_region->setCapabilitiesReceivedCallback([](const LLUUID &region_id) { LLEnvironment::instance().requestRegion(); });
return;
}
requestRegion();

View File

@ -56,7 +56,7 @@ BOOL LLFloaterAvatarTextures::postBuild()
{
for (U32 i=0; i < TEX_NUM_INDICES; i++)
{
const std::string tex_name = LLAvatarAppearanceDictionary::getInstance()->getTexture(ETextureIndex(i))->mName;
const std::string tex_name = LLAvatarAppearance::getDictionary()->getTexture(ETextureIndex(i))->mName;
mTextures[i] = getChild<LLTextureCtrl>(tex_name);
// <FS:Ansariel> Mask avatar textures and disable
mTextures[i]->setIsMasked(TRUE);
@ -85,7 +85,7 @@ static void update_texture_ctrl(LLVOAvatar* avatarp,
ETextureIndex te)
{
LLUUID id = IMG_DEFAULT_AVATAR;
const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture(te);
const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearance::getDictionary()->getTexture(te);
if (tex_entry && tex_entry->mIsLocalTexture)
{
if (avatarp->isSelf())
@ -180,14 +180,14 @@ void LLFloaterAvatarTextures::onClickDump(void* data)
const LLTextureEntry* te = avatarp->getTE(i);
if (!te) continue;
const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)(i));
const LLAvatarAppearanceDictionary::TextureEntry* tex_entry = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)(i));
if (!tex_entry)
continue;
if (LLVOAvatar::isIndexLocalTexture((ETextureIndex)i))
{
LLUUID id = IMG_DEFAULT_AVATAR;
LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getInstance()->getTEWearableType((ETextureIndex)i);
LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)i);
if (avatarp->isSelf())
{
LLViewerWearable *wearable = gAgentWearables.getViewerWearable(wearable_type, 0);

View File

@ -268,6 +268,12 @@ void LLFloaterCamera::resetCameraMode()
if (!floater_camera) return;
floater_camera->switchMode(CAMERA_CTRL_MODE_PAN);
// <FS:Ansariel>
// <FS:Ansariel> Optional small camera floater
floater_camera = LLFloaterCamera::findSmallInstance();
if (!floater_camera) return;
floater_camera->switchMode(CAMERA_CTRL_MODE_PAN);
// </FS:Ansariel>
}
void LLFloaterCamera::onAvatarEditingAppearance(bool editing)
@ -282,6 +288,12 @@ void LLFloaterCamera::onAvatarEditingAppearance(bool editing)
if (!floater_camera) return;
floater_camera->handleAvatarEditingAppearance(editing);
// <FS:Ansariel>
// <FS:Ansariel> Optional small camera floater
floater_camera = LLFloaterCamera::findSmallInstance();
if (!floater_camera) return;
floater_camera->handleAvatarEditingAppearance(editing);
// <FS:Ansariel>
}
void LLFloaterCamera::handleAvatarEditingAppearance(bool editing)
@ -324,6 +336,18 @@ void LLFloaterCamera::toPrevMode()
}
}
// </FS:Ansariel>
// <FS:Ansariel> Optional small camera floater
floater_camera = LLFloaterCamera::findSmallInstance();
if (floater_camera)
{
floater_camera->updateItemsSelection();
if(floater_camera->inFreeCameraMode())
{
activate_camera_tool();
}
}
// </FS:Ansariel>
}
LLFloaterCamera* LLFloaterCamera::findInstance()
@ -338,6 +362,13 @@ LLFloaterCamera* LLFloaterCamera::findPhototoolsInstance()
}
// </FS:Ansariel>
// <FS:Ansariel> Optional small camera floater
LLFloaterCamera* LLFloaterCamera::findSmallInstance()
{
return LLFloaterReg::findTypedInstance<LLFloaterCamera>("fs_camera_small");
}
// </FS:Ansariel>
void LLFloaterCamera::onOpen(const LLSD& key)
{
LLFirstUse::viewPopup();
@ -353,7 +384,9 @@ void LLFloaterCamera::onOpen(const LLSD& key)
toPrevMode();
mClosed = FALSE;
populatePresetCombo();
// <FS:Ansariel> Optional small camera floater
if (mPresetCombo)
populatePresetCombo();
}
void LLFloaterCamera::onClose(bool app_quitting)
@ -381,7 +414,8 @@ LLFloaterCamera::LLFloaterCamera(const LLSD& val)
: LLFloater(val),
mClosed(FALSE),
mCurrMode(CAMERA_CTRL_MODE_PAN),
mPrevMode(CAMERA_CTRL_MODE_PAN)
mPrevMode(CAMERA_CTRL_MODE_PAN),
mPresetCombo(nullptr) // <FS:Ansariel> Optional small camera floater
{
LLHints::getInstance()->registerHintTarget("view_popup", getHandle());
mCommitCallbackRegistrar.add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraItem, _2));
@ -395,7 +429,7 @@ BOOL LLFloaterCamera::postBuild()
mRotate = getChild<LLJoystickCameraRotate>(ORBIT);
mZoom = findChild<LLPanelCameraZoom>(ZOOM);
mTrack = getChild<LLJoystickCameraTrack>(PAN);
mPresetCombo = getChild<LLComboBox>("preset_combo");
mPresetCombo = findChild<LLComboBox>("preset_combo"); // <FS:Ansariel> Optional small camera floater
// <FS:Ansariel> Improved camera floater
//getChild<LLTextBox>("precise_ctrs_label")->setShowCursorHand(false);
@ -421,8 +455,15 @@ BOOL LLFloaterCamera::postBuild()
}
// </FS:Ansariel>
mPresetCombo->setCommitCallback(boost::bind(&LLFloaterCamera::onCustomPresetSelected, this));
LLPresetsManager::getInstance()->setPresetListChangeCameraCallback(boost::bind(&LLFloaterCamera::populatePresetCombo, this));
// <FS:Ansariel> Optional small camera floater
//mPresetCombo->setCommitCallback(boost::bind(&LLFloaterCamera::onCustomPresetSelected, this));
//LLPresetsManager::getInstance()->setPresetListChangeCameraCallback(boost::bind(&LLFloaterCamera::populatePresetCombo, this));
if (mPresetCombo)
{
mPresetCombo->setCommitCallback(boost::bind(&LLFloaterCamera::onCustomPresetSelected, this));
LLPresetsManager::getInstance()->setPresetListChangeCameraCallback(boost::bind(&LLFloaterCamera::populatePresetCombo, this));
}
// </FS:Ansariel>
update();
@ -598,6 +639,19 @@ void LLFloaterCamera::onClickCameraItem(const LLSD& param)
camera_floater->fromFreeToPresets();
}
// </FS:Ansariel>
// <FS:Ansariel> Optional small camera floater
camera_floater = LLFloaterCamera::findSmallInstance();
if (camera_floater)
{
// <FS:Ansariel> FIRE-29950: Re-add weird legacy object view camera toggle
//camera_floater->switchMode(CAMERA_CTRL_MODE_FREE_CAMERA);
camera_floater->mCurrMode == CAMERA_CTRL_MODE_FREE_CAMERA ? camera_floater->switchMode(CAMERA_CTRL_MODE_PAN) : camera_floater->switchMode(CAMERA_CTRL_MODE_FREE_CAMERA);
// </FS:Ansariel>
camera_floater->updateItemsSelection();
camera_floater->fromFreeToPresets();
}
// </FS:Ansariel>
}
// <FS:Ansariel> Improved camera floater
else if ("reset_view" == name)
@ -612,6 +666,12 @@ void LLFloaterCamera::onClickCameraItem(const LLSD& param)
camera_floater->switchMode(CAMERA_CTRL_MODE_PAN);
// </FS:Ansariel>
// <FS:Ansariel> Optional small camera floater
camera_floater = LLFloaterCamera::findSmallInstance();
if (camera_floater)
camera_floater->switchMode(CAMERA_CTRL_MODE_PAN);
// </FS:Ansariel>
gAgentCamera.changeCameraToDefault();
switchToPreset("rear_view");
}
@ -628,6 +688,12 @@ void LLFloaterCamera::onClickCameraItem(const LLSD& param)
camera_floater->switchMode(CAMERA_CTRL_MODE_PAN);
// </FS:Ansariel>
// <FS:Ansariel> Optional small camera floater
camera_floater = LLFloaterCamera::findSmallInstance();
if (camera_floater)
camera_floater->switchMode(CAMERA_CTRL_MODE_PAN);
// </FS:Ansariel>
switchToPreset(name);
}
}
@ -696,6 +762,15 @@ void LLFloaterCamera::switchToPreset(const std::string& name)
camera_floater->fromFreeToPresets();
}
// </FS:Ansariel>
// <FS:Ansariel> Optional small camera floater
camera_floater = LLFloaterCamera::findSmallInstance();
if (camera_floater)
{
camera_floater->updateItemsSelection();
camera_floater->fromFreeToPresets();
}
// </FS:Ansariel>
}
void LLFloaterCamera::fromFreeToPresets()

View File

@ -95,6 +95,8 @@ private:
static LLFloaterCamera* findInstance();
// <FS:Ansariel> Phototools camera
static LLFloaterCamera* findPhototoolsInstance();
// <FS:Ansariel> Optional small camera floater
static LLFloaterCamera* findSmallInstance();
/*virtual*/ BOOL postBuild();

View File

@ -102,11 +102,15 @@ BOOL LLFloaterConversationPreview::postBuild()
file = "chat";
}
mChatHistoryFileName = file;
// <FS:Ansariel> Obsolete because of https://bitbucket.org/lindenlab/viewer/commits/57b32eb01cd35bbac440569df885036eb24f2369
//if (mIsGroup && !LLStringUtil::endsWith(mChatHistoryFileName, GROUP_CHAT_SUFFIX))
//{
// mChatHistoryFileName += GROUP_CHAT_SUFFIX;
//}
// <FS:Ansariel> Broken version got removed in https://bitbucket.org/lindenlab/viewer/commits/57b32eb01cd35bbac440569df885036eb24f2369
// but this is actually needed in the fixed form: If a group chat
// log is stored in conversation.log without the suffix, the filename
// will not be updated until the conversation is removed from the log,
// resulting in the old chat log being displayed.
if (mIsGroup && !LLStringUtil::endsWith(mChatHistoryFileName, GROUP_CHAT_SUFFIX))
{
mChatHistoryFileName += GROUP_CHAT_SUFFIX;
}
// </FS:Ansariel>
LLStringUtil::format_map_t args;
args["[NAME]"] = name;

View File

@ -59,8 +59,17 @@ BOOL LLFloaterDeletePrefPreset::postBuild()
void LLFloaterDeletePrefPreset::onOpen(const LLSD& key)
{
mSubdirectory = key.asString();
std::string floater_title = getString(std::string("title_") + mSubdirectory);
setTitle(floater_title);
std::string title_type = std::string("title_") + mSubdirectory;
if (hasString(title_type))
{
std::string floater_title = getString(title_type);
setTitle(floater_title);
}
else
{
LL_WARNS() << title_type << " not found" << LL_ENDL;
setTitle(title_type);
}
LLComboBox* combo = getChild<LLComboBox>("preset_combo");
EDefaultOptions option = DEFAULT_HIDE;

View File

@ -458,19 +458,23 @@ void LLFloaterIMContainer::idleUpdate()
const LLConversationItem *current_session = getCurSelectedViewModelItem();
if (current_session)
{
// Update moderator options visibility
LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin();
LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd();
bool is_moderator = isGroupModerator();
bool can_ban = haveAbilityToBan();
while (current_participant_model != end_participant_model)
if (current_session->getType() == LLConversationItem::CONV_SESSION_GROUP)
{
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
participant_model->setModeratorOptionsVisible(is_moderator);
participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID);
// Update moderator options visibility
LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin();
LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd();
bool is_moderator = isGroupModerator();
bool can_ban = haveAbilityToBan();
while (current_participant_model != end_participant_model)
{
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
participant_model->setModeratorOptionsVisible(is_moderator);
participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID);
current_participant_model++;
current_participant_model++;
}
}
// Update floater's title as required by the currently selected session or use the default title
LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(current_session->getUUID());
setTitle(conversation_floaterp && conversation_floaterp->needsTitleOverwrite() ? conversation_floaterp->getTitle() : mGeneralTitle);

View File

@ -165,7 +165,6 @@ void LLFloaterIMSession::onClickCloseBtn(bool)
else
{
LL_WARNS() << "Empty session with id: " << (mSessionID.asString()) << LL_ENDL;
return;
}
LLFloaterIMSessionTab::onClickCloseBtn();

View File

@ -40,7 +40,17 @@
#include "llviewercontrol.h"
#include "llappviewer.h"
#include "llviewerjoystick.h"
#include "llviewerwindow.h"
#include "llwindow.h"
#include "llcheckboxctrl.h"
#include "llcombobox.h"
#if LL_WINDOWS && !LL_MESA_HEADLESS
// Require DirectInput version 8
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#endif
static LLTrace::SampleStatHandle<> sJoystickAxis0("Joystick axis 0"),
sJoystickAxis1("Joystick axis 1"),
@ -58,8 +68,33 @@ static LLTrace::SampleStatHandle<>* sJoystickAxes[6] =
&sJoystickAxis5
};
#if LL_WINDOWS && !LL_MESA_HEADLESS
BOOL CALLBACK di8_list_devices_callback(LPCDIDEVICEINSTANCE device_instance_ptr, LPVOID pvRef)
{
// Note: If a single device can function as more than one DirectInput
// device type, it is enumerated as each device type that it supports.
// Capable of detecting devices like Oculus Rift
if (device_instance_ptr && pvRef)
{
std::string product_name = utf16str_to_utf8str(llutf16string(device_instance_ptr->tszProductName));
S32 size = sizeof(GUID);
LLSD::Binary data; //just an std::vector
data.resize(size);
memcpy(&data[0], &device_instance_ptr->guidInstance /*POD _GUID*/, size);
LLFloaterJoystick * floater = (LLFloaterJoystick*)pvRef;
LLSD value = data;
floater->addDevice(product_name, value);
}
return DIENUM_CONTINUE;
}
#endif
LLFloaterJoystick::LLFloaterJoystick(const LLSD& data)
: LLFloater(data)
: LLFloater(data),
mHasDeviceList(false)
{
if (!LLViewerJoystick::getInstance()->isJoystickInitialized())
{
@ -71,14 +106,13 @@ LLFloaterJoystick::LLFloaterJoystick(const LLSD& data)
void LLFloaterJoystick::draw()
{
bool joystick_inited = LLViewerJoystick::getInstance()->isJoystickInitialized();
getChildView("enable_joystick")->setEnabled(joystick_inited);
getChildView("joystick_type")->setEnabled(joystick_inited);
std::string desc = LLViewerJoystick::getInstance()->getDescription();
if (desc.empty()) desc = getString("NoDevice");
getChild<LLUICtrl>("joystick_type")->setValue(desc);
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
bool joystick_inited = joystick->isJoystickInitialized();
if (joystick_inited != mHasDeviceList)
{
refreshListOfDevices();
}
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
for (U32 i = 0; i < 6; i++)
{
F32 value = joystick->getJoystickAxis(i);
@ -117,8 +151,8 @@ BOOL LLFloaterJoystick::postBuild()
}
}
mCheckJoystickEnabled = getChild<LLCheckBoxCtrl>("enable_joystick");
childSetCommitCallback("enable_joystick",onCommitJoystickEnabled,this);
mJoysticksCombo = getChild<LLComboBox>("joystick_combo");
childSetCommitCallback("joystick_combo",onCommitJoystickEnabled,this);
mCheckFlycamEnabled = getChild<LLCheckBoxCtrl>("JoystickFlycamEnabled");
childSetCommitCallback("JoystickFlycamEnabled",onCommitJoystickEnabled,this);
@ -127,6 +161,7 @@ BOOL LLFloaterJoystick::postBuild()
childSetAction("ok_btn", onClickOK, this);
refresh();
refreshListOfDevices();
return TRUE;
}
@ -143,6 +178,7 @@ void LLFloaterJoystick::apply()
void LLFloaterJoystick::initFromSettings()
{
mJoystickEnabled = gSavedSettings.getBOOL("JoystickEnabled");
mJoystickId = gSavedSettings.getLLSD("JoystickDeviceUUID");
mJoystickAxis[0] = gSavedSettings.getS32("JoystickAxis0");
mJoystickAxis[1] = gSavedSettings.getS32("JoystickAxis1");
@ -212,12 +248,80 @@ void LLFloaterJoystick::initFromSettings()
void LLFloaterJoystick::refresh()
{
LLFloater::refresh();
initFromSettings();
}
void LLFloaterJoystick::addDevice(std::string &name, LLSD& value)
{
mJoysticksCombo->add(name, value, ADD_BOTTOM, 1);
}
void LLFloaterJoystick::refreshListOfDevices()
{
mJoysticksCombo->removeall();
std::string no_device = getString("JoystickDisabled");
LLSD value = LLSD::Integer(0);
addDevice(no_device, value);
mHasDeviceList = false;
// di8_devices_callback callback is immediate and happens in scope of getInputDevices()
#if LL_WINDOWS && !LL_MESA_HEADLESS
// space navigator is marked as DI8DEVCLASS_GAMECTRL in ndof lib
U32 device_type = DI8DEVCLASS_GAMECTRL;
void* callback = &di8_list_devices_callback;
#else
// MAC doesn't support device search yet
// On MAC there is an ndof_idsearch and it is possible to specify product
// and manufacturer in NDOF_Device for ndof_init_first to pick specific one
U32 device_type = 0;
void* callback = NULL;
#endif
if (gViewerWindow->getWindow()->getInputDevices(device_type, callback, this))
{
mHasDeviceList = true;
}
bool is_device_id_set = LLViewerJoystick::getInstance()->isDeviceUUIDSet();
if (LLViewerJoystick::getInstance()->isJoystickInitialized() &&
(!mHasDeviceList || !is_device_id_set))
{
#if LL_WINDOWS && !LL_MESA_HEADLESS
LL_WARNS() << "NDOF connected to device without using SL provided handle" << LL_ENDL;
#endif
std::string desc = LLViewerJoystick::getInstance()->getDescription();
if (!desc.empty())
{
LLSD value = LLSD::Integer(0);
addDevice(desc, value);
mHasDeviceList = true;
}
}
if (gSavedSettings.getBOOL("JoystickEnabled") && mHasDeviceList)
{
if (is_device_id_set)
{
LLSD guid = LLViewerJoystick::getInstance()->getDeviceUUID();
mJoysticksCombo->selectByValue(guid);
}
else
{
mJoysticksCombo->selectByValue(LLSD::Integer(1));
}
}
else
{
mJoysticksCombo->selectByValue(LLSD::Integer(0));
}
}
void LLFloaterJoystick::cancel()
{
gSavedSettings.setBOOL("JoystickEnabled", mJoystickEnabled);
gSavedSettings.setLLSD("JoystickDeviceUUID", mJoystickId);
gSavedSettings.setS32("JoystickAxis0", mJoystickAxis[0]);
gSavedSettings.setS32("JoystickAxis1", mJoystickAxis[1]);
@ -287,7 +391,21 @@ void LLFloaterJoystick::cancel()
void LLFloaterJoystick::onCommitJoystickEnabled(LLUICtrl*, void *joy_panel)
{
LLFloaterJoystick* self = (LLFloaterJoystick*)joy_panel;
BOOL joystick_enabled = self->mCheckJoystickEnabled->get();
LLSD value = self->mJoysticksCombo->getValue();
bool joystick_enabled = true;
if (value.isInteger())
{
// ndof already has a device selected, we are just setting it enabled or disabled
joystick_enabled = value.asInteger();
}
else
{
LLViewerJoystick::getInstance()->initDevice(value);
// else joystick is enabled, because combobox holds id of device
joystick_enabled = true;
}
gSavedSettings.setBOOL("JoystickEnabled", joystick_enabled);
BOOL flycam_enabled = self->mCheckFlycamEnabled->get();
if (!joystick_enabled || !flycam_enabled)
@ -299,6 +417,12 @@ void LLFloaterJoystick::onCommitJoystickEnabled(LLUICtrl*, void *joy_panel)
joystick->toggleFlycam();
}
}
std::string device_id = LLViewerJoystick::getInstance()->getDeviceUUIDString();
gSavedSettings.setString("JoystickDeviceUUID", device_id);
LL_DEBUGS("Joystick") << "Selected " << device_id << " as joystick." << LL_ENDL;
self->refreshListOfDevices();
}
void LLFloaterJoystick::onClickRestoreSNDefaults(void *joy_panel)

View File

@ -31,6 +31,7 @@
#include "llstatview.h"
class LLCheckBoxCtrl;
class LLComboBox;
class LLFloaterJoystick : public LLFloater
{
@ -45,8 +46,11 @@ public:
virtual void draw();
static void setSNDefaults();
void addDevice(std::string &name, LLSD& value);
protected:
void refreshListOfDevices();
void onClose(bool app_quitting);
void onClickCloseBtn(bool app_quitting);
@ -65,6 +69,7 @@ private:
private:
// Device prefs
bool mJoystickEnabled;
LLSD mJoystickId;
S32 mJoystickAxis[7];
bool m3DCursor;
bool mAutoLeveling;
@ -85,8 +90,10 @@ private:
F32 mFlycamFeathering;
// Controls that can disable the flycam
LLCheckBoxCtrl *mCheckJoystickEnabled;
LLCheckBoxCtrl *mCheckFlycamEnabled;
LLComboBox *mJoysticksCombo;
bool mHasDeviceList;
// stats view
LLStatBar* mAxisStatsBar[6];

View File

@ -58,9 +58,17 @@ BOOL LLFloaterLoadPrefPreset::postBuild()
void LLFloaterLoadPrefPreset::onOpen(const LLSD& key)
{
mSubdirectory = key.asString();
std::string floater_title = getString(std::string("title_") + mSubdirectory);
setTitle(floater_title);
std::string title_type = std::string("title_") + mSubdirectory;
if (hasString(title_type))
{
std::string floater_title = getString(title_type);
setTitle(floater_title);
}
else
{
LL_WARNS() << title_type << " not found" << LL_ENDL;
setTitle(title_type);
}
LLComboBox* combo = getChild<LLComboBox>("preset_combo");

View File

@ -2513,7 +2513,6 @@ void LLFloaterPreference::disableUnavailableSettings()
LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections");
LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
LLCheckBoxCtrl* ctrl_shader_enable = getChild<LLCheckBoxCtrl>("BasicShaders");
LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail");
@ -2521,39 +2520,6 @@ void LLFloaterPreference::disableUnavailableSettings()
LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
// if vertex shaders off, disable all shader related products
if (!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"))
{
ctrl_shader_enable->setEnabled(FALSE);
ctrl_shader_enable->setValue(FALSE);
ctrl_wind_light->setEnabled(FALSE);
ctrl_wind_light->setValue(FALSE);
sky->setEnabled(FALSE);
ctrl_reflections->setEnabled(FALSE);
ctrl_reflections->setValue(0);
ctrl_avatar_vp->setEnabled(FALSE);
ctrl_avatar_vp->setValue(FALSE);
ctrl_avatar_cloth->setEnabled(FALSE);
ctrl_avatar_cloth->setValue(FALSE);
ctrl_shadows->setEnabled(FALSE);
ctrl_shadows->setValue(0);
ctrl_ssao->setEnabled(FALSE);
ctrl_ssao->setValue(FALSE);
ctrl_dof->setEnabled(FALSE);
ctrl_dof->setValue(FALSE);
ctrl_deferred->setEnabled(FALSE);
ctrl_deferred->setValue(FALSE);
}
// disabled windlight
if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
{

View File

@ -64,7 +64,7 @@ void LLFloaterSidePanelContainer::onOpen(const LLSD& key)
void LLFloaterSidePanelContainer::closeFloater(bool app_quitting)
{
LLPanelOutfitEdit* panel_outfit_edit =
dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit"));
dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::findPanel("appearance", "panel_outfit_edit"));
if (panel_outfit_edit)
{
LLFloater *parent = gFloaterView->getParentFloater(panel_outfit_edit);
@ -171,7 +171,6 @@ LLPanel* LLFloaterSidePanelContainer::getPanel(const std::string& floater_name,
return NULL;
}
// <FS:Ansariel> Convenience method
LLPanel* LLFloaterSidePanelContainer::findPanel(const std::string& floater_name, const std::string& panel_name)
{
LLFloaterSidePanelContainer* floaterp = LLFloaterReg::findTypedInstance<LLFloaterSidePanelContainer>(floater_name);
@ -183,4 +182,3 @@ LLPanel* LLFloaterSidePanelContainer::findPanel(const std::string& floater_name,
return NULL;
}
// </FS:Ansariel>

View File

@ -67,6 +67,8 @@ public:
static void showPanel(const std::string& floater_name, const std::string& panel_name, const LLSD& key);
static LLPanel* getPanel(const std::string& floater_name, const std::string& panel_name = sMainPanelName);
static LLPanel* findPanel(const std::string& floater_name, const std::string& panel_name = sMainPanelName);
/**
* Gets the panel of given type T (doesn't show it or do anything else with it).
@ -86,9 +88,6 @@ public:
return panel;
}
// <FS:Ansariel> Convenience method
static LLPanel* findPanel(const std::string& floater_name, const std::string& panel_name = sMainPanelName);
template <typename T>
static T* findPanel(const std::string& floater_name, const std::string& panel_name = sMainPanelName)
{

View File

@ -136,23 +136,14 @@ bool LLGiveInventory::isInventoryGiveAcceptable(const LLInventoryItem* item)
switch(item->getType())
{
case LLAssetType::AT_OBJECT:
if (get_is_item_worn(item->getUUID()))
{
acceptable = false;
}
break;
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_CLOTHING:
{
BOOL copyable = false;
if (item->getPermissions().allowCopyBy(gAgentID)) copyable = true;
if (!copyable && get_is_item_worn(item->getUUID()))
if (get_is_item_worn(item->getUUID()))
{
// worn no-copy items can't be transfered,
// but it is valid to transfer a copy of a worn item
acceptable = false;
}
break;
}
break;
default:

View File

@ -2536,6 +2536,19 @@ BOOL LLOutgoingCallDialog::postBuild()
// Class LLIncomingCallDialog
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const std::array<std::string, 4> voice_call_types =
{
"VoiceInviteP2P",
"VoiceInviteGroup",
"VoiceInviteAdHoc",
"InviteAdHoc"
};
bool is_voice_call_type(const std::string &value)
{
return std::find(voice_call_types.begin(), voice_call_types.end(), value) != voice_call_types.end();
}
LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) :
LLCallDialog(payload),
mAvatarNameCacheConnection()
@ -2565,9 +2578,28 @@ BOOL LLIncomingCallDialog::postBuild()
{
LLCallDialog::postBuild();
if (!mPayload.isMap() || mPayload.size() == 0)
{
LL_INFOS("IMVIEW") << "IncomingCall: invalid argument" << LL_ENDL;
return TRUE;
}
LLUUID session_id = mPayload["session_id"].asUUID();
LLSD caller_id = mPayload["caller_id"];
std::string caller_name = mPayload["caller_name"].asString();
if (session_id.isNull() && caller_id.asUUID().isNull())
{
LL_INFOS("IMVIEW") << "IncomingCall: invalid ids" << LL_ENDL;
return TRUE;
}
std::string notify_box_type = mPayload["notify_box_type"].asString();
if (!is_voice_call_type(notify_box_type))
{
LL_INFOS("IMVIEW") << "IncomingCall: notify_box_type was not provided" << LL_ENDL;
return TRUE;
}
// init notification's lifetime
std::istringstream ss( getString("lifetime") );
@ -2584,15 +2616,14 @@ BOOL LLIncomingCallDialog::postBuild()
if (gAgent.getGroupData(session_id, data))
{
args["[GROUP]"] = data.mName;
call_type = getString(mPayload["notify_box_type"], args);
call_type = getString(notify_box_type, args);
}
}
else
{
call_type = getString(mPayload["notify_box_type"]);
call_type = getString(notify_box_type);
}
// check to see if this is an Avaline call
bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id);
if (caller_name == "anonymous")
@ -2622,7 +2653,6 @@ BOOL LLIncomingCallDialog::postBuild()
childSetAction("Start IM", onStartIM, this);
setDefaultBtn("Accept");
std::string notify_box_type = mPayload["notify_box_type"].asString();
if(notify_box_type != "VoiceInviteGroup" && notify_box_type != "VoiceInviteAdHoc")
{
// starting notification's timer for P2P and AVALINE invitations
@ -2776,10 +2806,10 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload
correct_session_name.append(ADHOC_NAME_SUFFIX);
}
}
LL_INFOS() << "Corrected session name is " << correct_session_name << LL_ENDL;
LL_INFOS("IMVIEW") << "Corrected session name is " << correct_session_name << LL_ENDL;
break;
default:
LL_WARNS() << "Received an empty session name from a server and failed to generate a new proper session name" << LL_ENDL;
LL_WARNS("IMVIEW") << "Received an empty session name from a server and failed to generate a new proper session name" << LL_ENDL;
break;
}
}
@ -3001,6 +3031,14 @@ void LLIMMgr::addMessage(
if (new_session)
{
// Group chat session was initiated by muted resident, do not start this session viewerside
// do not send leave msg either, so we are able to get group messages from other participants
if ((IM_SESSION_INVITE == dialog) && gAgent.isInGroup(new_session_id) &&
LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !from_linden)
{
return;
}
LLAvatarName av_name;
if (LLAvatarNameCache::get(other_participant_id, &av_name) && !name_is_setted)
{
@ -3083,7 +3121,7 @@ void LLIMMgr::addMessage(
LL_WARNS() << "Leaving IM session from initiating muted resident " << from << LL_ENDL;
if (!gIMMgr->leaveSession(new_session_id))
{
LL_INFOS() << "Session " << new_session_id << " does not exist." << LL_ENDL;
LL_INFOS("IMVIEW") << "Session " << new_session_id << " does not exist." << LL_ENDL;
}
return;
}
@ -3415,7 +3453,7 @@ LLUUID LLIMMgr::addSession(
//we don't need to show notes about online/offline, mute/unmute users' statuses for existing sessions
if (!new_session) return session_id;
LL_INFOS() << "LLIMMgr::addSession, new session added, name = " << name << ", session id = " << session_id << LL_ENDL;
LL_INFOS("IMVIEW") << "LLIMMgr::addSession, new session added, name = " << name << ", session id = " << session_id << LL_ENDL;
//Per Plan's suggestion commented "explicit offline status warning" out to make Dessie happier (see EXT-3609)
//*TODO After February 2010 remove this commented out line if no one will be missing that warning
@ -3475,7 +3513,7 @@ void LLIMMgr::removeSession(const LLUUID& session_id)
LLIMModel::getInstance()->clearSession(session_id);
LL_INFOS() << "LLIMMgr::removeSession, session removed, session id = " << session_id << LL_ENDL;
LL_INFOS("IMVIEW") << "LLIMMgr::removeSession, session removed, session id = " << session_id << LL_ENDL;
notifyObserverSessionRemoved(session_id);
}
@ -3541,13 +3579,13 @@ void LLIMMgr::inviteToSession(
if (LLMuteList::getInstance()->isMuted(caller_id, LLMute::flagVoiceChat)
&& voice_invite && "VoiceInviteQuestionDefault" == question_type)
{
LL_INFOS() << "Rejecting voice call from initiating muted resident " << caller_name << LL_ENDL;
LL_INFOS("IMVIEW") << "Rejecting voice call from initiating muted resident " << caller_name << LL_ENDL;
LLIncomingCallDialog::processCallResponse(1, payload);
return;
}
else if (LLMuteList::getInstance()->isMuted(caller_id, LLMute::flagAll & ~LLMute::flagVoiceChat) && !voice_invite)
{
LL_INFOS() << "Rejecting session invite from initiating muted resident " << caller_name << LL_ENDL;
LL_INFOS("IMVIEW") << "Rejecting session invite from initiating muted resident " << caller_name << LL_ENDL;
return;
}
}

View File

@ -4422,7 +4422,9 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
}
// </FS:Ansariel>
// <FS:Ansariel> Fix "outfits" context menu
if (outfits_id == mUUID)
if (model->isObjectDescendentOf(mUUID, outfits_id) && getCategory() &&
(getCategory()->getPreferredType() == LLFolderType::FT_NONE ||
getCategory()->getPreferredType() == LLFolderType::FT_MY_OUTFITS))
{
items.push_back(std::string("New Outfit"));
}
@ -4530,17 +4532,17 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
// Not sure what the right thing is to do here.
if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT))
{
// <FS:Ansariel> Fix "outfits" context menu
//if (!isInboxFolder()) // don't allow creation in inbox
if (!isInboxFolder() && outfits_id != mUUID) // don't allow creation in inbox
// </FS:Ansariel>
if (!isInboxFolder()) // don't allow creation in inbox
{
// Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
{
items.push_back(std::string("New Folder"));
}
if (!isMarketplaceListingsFolder())
// <FS:Ansariel> Fix "outfits" context menu
//if (!isMarketplaceListingsFolder())
if (!isMarketplaceListingsFolder() && !model->isObjectDescendentOf(mUUID, outfits_id))
// </FS:Ansariel>
{
items.push_back(std::string("New Script"));
items.push_back(std::string("New Note"));
@ -8501,11 +8503,11 @@ void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_dequ
disable_context_entries_if_present(menu, disabled_items);
}
bool LLFolderViewGroupedItemBridge::canWearSelected(uuid_vec_t item_ids)
bool LLFolderViewGroupedItemBridge::canWearSelected(const uuid_vec_t& item_ids) const
{
for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it)
{
LLViewerInventoryItem* item = gInventory.getItem(*it);
const LLViewerInventoryItem* item = gInventory.getItem(*it);
// <FS:Ansariel> Fix broken add wearable check
//if (!item || (item->getType() >= LLAssetType::AT_COUNT) || (item->getType() <= LLAssetType::AT_NONE))
if (!item || (item->getType() != LLAssetType::AT_CLOTHING && item->getType() != LLAssetType::AT_OBJECT && item->getType() != LLAssetType::AT_BODYPART && item->getType() != LLAssetType::AT_GESTURE))

View File

@ -823,7 +823,7 @@ class LLFolderViewGroupedItemBridge: public LLFolderViewGroupedItemModel
public:
LLFolderViewGroupedItemBridge();
virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu);
bool canWearSelected(uuid_vec_t item_ids);
bool canWearSelected(const uuid_vec_t& item_ids) const;
};
#endif // LL_LLINVENTORYBRIDGE_H

View File

@ -2695,24 +2695,19 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
{
bool open_multi_preview = true;
for (std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
if ("open" == action)
{
LLFolderViewItem* folder_item = *set_iter;
if (folder_item)
for (std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
{
LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(folder_item->getViewModelItem());
// <FS:Ansariel> FIRE-30518: Multi-preview not working for contents of rezzed objects
// This should prevent multi-previews of settings, but for object inventory items
// this check is always false, since content items in object inventories
// have LLTaskInvFVBridges instead of LLInvFVBridges. Since settings can't be
// opened from inside objects anyway, so restrict the check for actions performed
// on avatar inventories.
//if (!bridge || !bridge->isMultiPreviewAllowed())
if ("open" == action && (!bridge || !bridge->isMultiPreviewAllowed()))
// </FS:Ansariel>
LLFolderViewItem* folder_item = *set_iter;
if (folder_item)
{
open_multi_preview = false;
break;
LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(folder_item->getViewModelItem());
if (!bridge || !bridge->isMultiPreviewAllowed())
{
open_multi_preview = false;
break;
}
}
}
}

View File

@ -161,7 +161,8 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
mShowEmptyMessage(p.show_empty_message),
mSuppressFolderMenu(p.suppress_folder_menu),
mSuppressOpenItemAction(false),
mViewsInitialized(false),
mBuildViewsOnInit(p.preinitialize_views),
mViewsInitialized(VIEWS_UNINITIALIZED),
mInvFVBridgeBuilder(NULL),
mInventoryViewModel(p.name),
mGroupedItemBridge(new LLFolderViewGroupedItemBridge)
@ -307,14 +308,22 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
mCompletionObserver = new LLInvPanelComplObserver(boost::bind(&LLInventoryPanel::onItemsCompletion, this));
mInventory->addObserver(mCompletionObserver);
// Build view of inventory if we need default full hierarchy and inventory ready, otherwise do in onIdle.
// Initializing views takes a while so always do it onIdle if viewer already loaded.
if (mInventory->isInventoryUsable() && !mViewsInitialized && LLStartUp::getStartupState() <= STATE_WEARABLES_WAIT)
{
initializeViews();
}
gIdleCallbacks.addFunction(onIdle, (void*)this);
if (mBuildViewsOnInit)
{
// Build view of inventory if we need default full hierarchy and inventory is ready, otherwise do in onIdle.
// Initializing views takes a while so always do it onIdle if viewer already loaded.
if (mInventory->isInventoryUsable()
&& mViewsInitialized == VIEWS_UNINITIALIZED
&& LLStartUp::getStartupState() <= STATE_WEARABLES_WAIT)
{
initializeViews();
}
else if (mViewsInitialized != VIEWS_INITIALIZING)
{
mViewsInitialized = VIEWS_INITIALIZING;
gIdleCallbacks.addFunction(onIdle, (void*)this);
}
}
if (mSortOrderSetting != INHERIT_SORT_ORDER)
{
@ -375,6 +384,17 @@ LLInventoryPanel::~LLInventoryPanel()
clearFolderRoot();
}
/*virtual*/
void LLInventoryPanel::onVisibilityChange(BOOL new_visibility)
{
if (new_visibility && mViewsInitialized == VIEWS_UNINITIALIZED)
{
mViewsInitialized = VIEWS_INITIALIZING;
gIdleCallbacks.addFunction(onIdle, (void*)this);
}
LLPanel::onVisibilityChange(new_visibility);
}
void LLInventoryPanel::draw()
{
// Select the desired item (in case it wasn't loaded when the selection was requested)
@ -714,7 +734,7 @@ void LLInventoryPanel::modelChanged(U32 mask)
{
LL_RECORD_BLOCK_TIME(FTM_REFRESH);
if (!mViewsInitialized) return;
if (mViewsInitialized != VIEWS_INITIALIZED) return;
const LLInventoryModel* model = getModel();
if (!model) return;
@ -780,11 +800,11 @@ void LLInventoryPanel::onIdle(void *userdata)
LLInventoryPanel *self = (LLInventoryPanel*)userdata;
// Inventory just initialized, do complete build
if (!self->mViewsInitialized)
if (self->mViewsInitialized != VIEWS_INITIALIZED)
{
self->initializeViews();
}
if (self->mViewsInitialized)
if (self->mViewsInitialized == VIEWS_INITIALIZED)
{
gIdleCallbacks.deleteFunction(onIdle, (void*)self);
}
@ -867,7 +887,7 @@ void LLInventoryPanel::initializeViews()
gIdleCallbacks.addFunction(idle, this);
mViewsInitialized = true;
mViewsInitialized = VIEWS_INITIALIZED;
openStartFolderOrMyInventory();

View File

@ -108,6 +108,10 @@ public:
Optional<LLFolderViewFolder::Params> folder;
Optional<LLFolderViewItem::Params> item;
// All item and folder views will be initialized on init if true (default)
// Will initialize on visibility change otherwise.
Optional<bool> preinitialize_views;
Params()
: sort_order_setting("sort_order_setting"),
inventory("", &gInventory),
@ -126,7 +130,8 @@ public:
accepts_drag_and_drop("accepts_drag_and_drop"),
folder_view("folder_view"),
folder("folder"),
item("item")
item("item"),
preinitialize_views("preinitialize_views", true)
{}
};
@ -154,6 +159,7 @@ public:
LLFolderViewModelInventory& getRootViewModel() { return mInventoryViewModel; }
// LLView methods
/*virtual*/ void onVisibilityChange(BOOL new_visibility);
void draw();
/*virtual*/ BOOL handleKeyHere( KEY key, MASK mask );
BOOL handleHover(S32 x, S32 y, MASK mask);
@ -329,7 +335,7 @@ public:
void addHideFolderType(LLFolderType::EType folder_type);
public:
BOOL getIsViewsInitialized() const { return mViewsInitialized; }
bool getViewsInitialized() const { return mViewsInitialized == VIEWS_INITIALIZED; }
protected:
// Builds the UI. Call this once the inventory is usable.
@ -366,8 +372,15 @@ private:
LLFolderViewItem *target_view,
LLFolderViewFolder *parent_folder_view);
bool mBuildDefaultHierarchy; // default inventory hierarchy should be created in postBuild()
bool mViewsInitialized; // Views have been generated
typedef enum e_views_initialization_state
{
VIEWS_UNINITIALIZED = 0,
VIEWS_INITIALIZING,
VIEWS_INITIALIZED,
} EViewsInitializationState;
bool mBuildViewsOnInit;
EViewsInitializationState mViewsInitialized; // Whether views have been generated
};
class LLInventoryFavoriteItemsPanel : public LLInventoryPanel

View File

@ -308,6 +308,7 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
LLButton::Params maturity_button = p.maturity_button;
mMaturityButton = LLUICtrlFactory::create<LLButton>(maturity_button);
addChild(mMaturityButton);
// <FS:Ansariel> Keep help links
mMaturityButton->setClickedCallback(boost::bind(&LLLocationInputCtrl::onMaturityButtonClicked, this));
LLButton::Params for_sale_button = p.for_sale_button;
@ -705,10 +706,12 @@ void LLLocationInputCtrl::onAgentParcelChange()
refresh();
}
// <FS:Ansariel> Keep help links
void LLLocationInputCtrl::onMaturityButtonClicked()
{
LLUI::getInstance()->mHelpImpl->showTopic(mMaturityHelpTopic);
}
// </FS:Ansariel>
void LLLocationInputCtrl::onRegionBoundaryCrossed()
{

Some files were not shown because too many files have changed in this diff Show More