Merge branch 'V2MultiWear' of git://github.com/Shyotl/SingularityViewer into V2MultiWear
Conflicts: indra/llrender/llvertexbuffer.h indra/newview/app_settings/settings.xml indra/newview/llface.cpp
This commit is contained in:
@@ -281,6 +281,10 @@ endif (STANDALONE)
|
||||
if(1 EQUAL 1)
|
||||
add_definitions(-DOPENSIM_RULES=1)
|
||||
add_definitions(-DMESH_ENABLED=1)
|
||||
add_definitions(-DENABLE_CLASSIC_CLOUDS=1)
|
||||
if (NOT "$ENV{SHY_MOD}" STREQUAL "")
|
||||
add_definitions(-DSHY_MOD=1)
|
||||
endif (NOT "$ENV{SHY_MOD}" STREQUAL "")
|
||||
endif(1 EQUAL 1)
|
||||
|
||||
SET( CMAKE_EXE_LINKER_FLAGS_RELEASESSE2
|
||||
|
||||
@@ -56,8 +56,7 @@ LLCharacter::LLCharacter()
|
||||
mPreferredPelvisHeight( 0.f ),
|
||||
mSex( SEX_FEMALE ),
|
||||
mAppearanceSerialNum( 0 ),
|
||||
mSkeletonSerialNum( 0 ),
|
||||
mInAppearance( false )
|
||||
mSkeletonSerialNum( 0 )
|
||||
{
|
||||
llassert_always(sAllowInstancesChange) ;
|
||||
sInstances.push_back(this);
|
||||
|
||||
@@ -268,10 +268,6 @@ public:
|
||||
ESex getSex() const { return mSex; }
|
||||
void setSex( ESex sex ) { mSex = sex; }
|
||||
|
||||
// set appearance flag
|
||||
void setAppearanceFlag( bool flag ) { mInAppearance = flag; }
|
||||
bool getAppearanceFlag() { return mInAppearance; }
|
||||
|
||||
U32 getAppearanceSerialNum() const { return mAppearanceSerialNum; }
|
||||
void setAppearanceSerialNum( U32 num ) { mAppearanceSerialNum = num; }
|
||||
|
||||
@@ -293,8 +289,6 @@ protected:
|
||||
U32 mSkeletonSerialNum;
|
||||
LLAnimPauseRequest mPauseRequest;
|
||||
|
||||
BOOL mInAppearance;
|
||||
|
||||
private:
|
||||
// visual parameter stuff
|
||||
typedef std::map<S32, LLVisualParam *> visual_param_index_map_t;
|
||||
|
||||
@@ -510,20 +510,6 @@ BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
vergence_quat.transQuat();
|
||||
right_eye_rot = vergence_quat * eye_jitter_rot * right_eye_rot;
|
||||
|
||||
//if in appearance, set the eyes straight forward
|
||||
if(mCharacter->getAppearanceFlag()) // no idea why this variable is reversed
|
||||
{
|
||||
LLVector3 forward(1.f, 0.0, 0.0);
|
||||
LLVector3 left;
|
||||
LLVector3 up;
|
||||
left.setVec(forward % forward);
|
||||
up.setVec(forward % left);
|
||||
target_eye_rot = LLQuaternion(forward, left, up);
|
||||
mLeftEyeState->setRotation( target_eye_rot );
|
||||
mRightEyeState->setRotation( target_eye_rot );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
mLeftEyeState->setRotation( left_eye_rot );
|
||||
mRightEyeState->setRotation( right_eye_rot );
|
||||
|
||||
|
||||
@@ -50,6 +50,16 @@ public:
|
||||
|
||||
const LLStrider<Object>& operator = (Object *first) { mObjectp = first; return *this;}
|
||||
void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));}
|
||||
|
||||
LLStrider<Object> operator+(const S32& index)
|
||||
{
|
||||
LLStrider<Object> ret;
|
||||
ret.mBytep = mBytep + mSkip*index;
|
||||
ret.mSkip = mSkip;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//void setTypeSize (S32 typeBytes){ mTypeSize = (typeBytes ? typeBytes : sizeof(Object)); }
|
||||
|
||||
//bool isStrided() const { return mTypeSize != mSkip; }
|
||||
|
||||
@@ -1,37 +1,32 @@
|
||||
/**
|
||||
* @file llimagedxt.cpp
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llimagedxt.h"
|
||||
#include "llmemory.h"
|
||||
|
||||
//static
|
||||
void LLImageDXT::checkMinWidthHeight(EFileFormat format, S32& width, S32& height)
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llimagepng.cpp
|
||||
* @brief LLImageFormatted glue to encode / decode PNG files.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2007-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -66,6 +60,12 @@ BOOL LLImagePNG::updateData()
|
||||
|
||||
// Decode the PNG data and extract sizing information
|
||||
LLPngWrapper pngWrapper;
|
||||
if (!pngWrapper.isValidPng(getData()))
|
||||
{
|
||||
setLastError("LLImagePNG data does not have a valid PNG header!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LLPngWrapper::ImageInfo infop;
|
||||
if (! pngWrapper.readPng(getData(), NULL, &infop))
|
||||
{
|
||||
@@ -96,6 +96,12 @@ BOOL LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time)
|
||||
|
||||
// Decode the PNG data into the raw image
|
||||
LLPngWrapper pngWrapper;
|
||||
if (!pngWrapper.isValidPng(getData()))
|
||||
{
|
||||
setLastError("LLImagePNG data does not have a valid PNG header!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (! pngWrapper.readPng(getData(), raw_image))
|
||||
{
|
||||
setLastError(pngWrapper.getErrorMessage());
|
||||
|
||||
@@ -1,40 +1,36 @@
|
||||
/**
|
||||
* @file llimagetga.cpp
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "lldir.h"
|
||||
#include "llimagetga.h"
|
||||
|
||||
#include "lldir.h"
|
||||
#include "llerror.h"
|
||||
#include "llmath.h"
|
||||
#include "llpointer.h"
|
||||
|
||||
// For expanding 5-bit pixel values to 8-bit with best rounding
|
||||
// static
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llimagej2coj.cpp
|
||||
* @brief This is an implementation of JPEG2000 encode/decode using OpenJPEG.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2006-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -37,7 +31,7 @@
|
||||
#include "openjpeg.h"
|
||||
|
||||
#include "lltimer.h"
|
||||
#include "llmemory.h"
|
||||
//#include "llmemory.h"
|
||||
|
||||
const char* fallbackEngineInfoLLImageJ2CImpl()
|
||||
{
|
||||
@@ -96,8 +90,15 @@ void info_callback(const char* msg, void*)
|
||||
lldebugs << "LLImageJ2COJ: " << chomp(msg) << llendl;
|
||||
}
|
||||
|
||||
// Divide a by 2 to the power of b and round upwards
|
||||
int ceildivpow2(int a, int b)
|
||||
{
|
||||
return (a + (1 << b) - 1) >> b;
|
||||
}
|
||||
|
||||
LLImageJ2COJ::LLImageJ2COJ() : LLImageJ2CImpl()
|
||||
|
||||
LLImageJ2COJ::LLImageJ2COJ()
|
||||
: LLImageJ2CImpl()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -180,7 +181,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
|
||||
// dereference the array.
|
||||
if(!image || !image->numcomps)
|
||||
{
|
||||
llwarns << "failed to decode image!" << llendl;
|
||||
LL_WARNS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL;
|
||||
if (image)
|
||||
{
|
||||
opj_image_destroy(image);
|
||||
@@ -195,7 +196,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
|
||||
{
|
||||
if (image->comps[i].factor != base.getRawDiscardLevel())
|
||||
{
|
||||
llwarns << "Expected discard level not reached!" << llendl;
|
||||
LL_WARNS("Texture") << "Expected discard level not reached!" << llendl;
|
||||
// if we didn't get the discard level we're expecting, fail
|
||||
opj_image_destroy(image);
|
||||
base.decodeFailed();
|
||||
@@ -256,7 +257,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
|
||||
}
|
||||
else // Some rare OpenJPEG versions have this bug.
|
||||
{
|
||||
llwarns << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << llendl;
|
||||
LL_WARNS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << llendl;
|
||||
opj_image_destroy(image);
|
||||
|
||||
base.decodeFailed();
|
||||
@@ -391,7 +392,7 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con
|
||||
if (!bSuccess)
|
||||
{
|
||||
opj_cio_close(cio);
|
||||
llinfos << "Failed to encode image." << llendl;
|
||||
LL_WARNS("Texture") << "Failed to encode image." << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
codestream_length = cio_tell(cio);
|
||||
|
||||
@@ -60,6 +60,7 @@ class LLVolumeTriangle;
|
||||
#include "llstrider.h"
|
||||
#include "v4coloru.h"
|
||||
#include "llrefcount.h"
|
||||
#include "llpointer.h"
|
||||
#include "llfile.h"
|
||||
|
||||
//============================================================================
|
||||
@@ -926,6 +927,10 @@ public:
|
||||
LLVector2* mTexCoords;
|
||||
U16* mIndices;
|
||||
|
||||
//vertex buffer filled in by LLFace to cache this volume face geometry in vram
|
||||
// (declared as a LLPointer to LLRefCount to avoid dependency on LLVertexBuffer)
|
||||
mutable LLPointer<LLRefCount> mVertexBuffer;
|
||||
|
||||
std::vector<S32> mEdge;
|
||||
|
||||
//list of skin weights for rigged volumes
|
||||
|
||||
@@ -81,7 +81,7 @@ void LLCubeMap::initGL()
|
||||
{
|
||||
U32 texname = 0;
|
||||
|
||||
LLImageGL::generateTextures(1, &texname);
|
||||
LLImageGL::generateTextures(LLTexUnit::TT_CUBE_MAP, GL_RGB8, 1, &texname);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llgl.cpp
|
||||
* @brief LLGL implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -263,6 +257,12 @@ PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = NULL;
|
||||
PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = NULL;
|
||||
PFNGLSAMPLEMASKIPROC glSampleMaski = NULL;
|
||||
|
||||
//transform feedback (4.0 core)
|
||||
PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL;
|
||||
PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL;
|
||||
PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL;
|
||||
PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL;
|
||||
|
||||
//GL_ARB_debug_output
|
||||
PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL;
|
||||
PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB = NULL;
|
||||
@@ -436,6 +436,7 @@ LLGLManager::LLGLManager() :
|
||||
mHasDrawBuffers(FALSE),
|
||||
mHasTextureRectangle(FALSE),
|
||||
mHasTextureMultisample(FALSE),
|
||||
mHasTransformFeedback(FALSE),
|
||||
mMaxSampleMaskWords(0),
|
||||
mMaxColorTextureSamples(0),
|
||||
mMaxDepthTextureSamples(0),
|
||||
@@ -573,7 +574,8 @@ bool LLGLManager::initGL()
|
||||
parse_gl_version( &mDriverVersionMajor,
|
||||
&mDriverVersionMinor,
|
||||
&mDriverVersionRelease,
|
||||
&mDriverVersionVendorString );
|
||||
&mDriverVersionVendorString,
|
||||
&mGLVersionString);
|
||||
|
||||
mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f;
|
||||
|
||||
@@ -591,7 +593,7 @@ bool LLGLManager::initGL()
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mGLVersion >= 3.f && LLImageGL::sCompressTextures)
|
||||
if (mGLVersion >= 2.1f && LLImageGL::sCompressTextures)
|
||||
{ //use texture compression
|
||||
glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST);
|
||||
}
|
||||
@@ -620,11 +622,8 @@ bool LLGLManager::initGL()
|
||||
#endif // LL_WINDOWS
|
||||
|
||||
#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS
|
||||
// release 7277 is a point at which we verify that ATI OpenGL
|
||||
// drivers get pretty stable with SL, ~Catalyst 8.2,
|
||||
// for both Win32 and Linux.
|
||||
if (mDriverVersionRelease < 7277 &&
|
||||
mDriverVersionRelease != 0) // 0 == Undetectable driver version - these get to pretend to be new ATI drivers, though that decision may be revisited.
|
||||
// count any pre OpenGL 3.0 implementation as an old driver
|
||||
if (mGLVersion < 3.f)
|
||||
{
|
||||
mATIOldDriver = TRUE;
|
||||
}
|
||||
@@ -931,7 +930,6 @@ void LLGLManager::initExtensions()
|
||||
mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");
|
||||
mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts);
|
||||
mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts);
|
||||
mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap");
|
||||
mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color");
|
||||
mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic");
|
||||
glh_init_extensions("GL_ARB_texture_cube_map");
|
||||
@@ -956,11 +954,15 @@ void LLGLManager::initExtensions()
|
||||
ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
|
||||
#endif
|
||||
mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts);
|
||||
|
||||
mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f;
|
||||
|
||||
mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
|
||||
mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
|
||||
mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
|
||||
mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
|
||||
mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts);
|
||||
mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE;
|
||||
#if !LL_DARWIN
|
||||
mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
|
||||
#endif
|
||||
@@ -1202,7 +1204,14 @@ void LLGLManager::initExtensions()
|
||||
glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample");
|
||||
glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");
|
||||
glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");
|
||||
}
|
||||
}
|
||||
if (mHasTransformFeedback)
|
||||
{
|
||||
glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glBeginTransformFeedback");
|
||||
glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback");
|
||||
glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings");
|
||||
glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange");
|
||||
}
|
||||
if (mHasDebugOutput)
|
||||
{
|
||||
glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControlARB");
|
||||
@@ -2040,7 +2049,7 @@ void LLGLManager::initGLStates()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific )
|
||||
void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string )
|
||||
{
|
||||
// GL_VERSION returns a null-terminated string with the format:
|
||||
// <major>.<minor>[.<release>] [<vendor specific>]
|
||||
@@ -2056,6 +2065,8 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor
|
||||
return;
|
||||
}
|
||||
|
||||
version_string->assign(version);
|
||||
|
||||
std::string ver_copy( version );
|
||||
S32 len = (S32)strlen( version ); /* Flawfinder: ignore */
|
||||
S32 i = 0;
|
||||
@@ -2417,3 +2428,63 @@ LLGLSquashToFarClip::~LLGLSquashToFarClip()
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LLGLSyncFence::LLGLSyncFence()
|
||||
{
|
||||
#ifdef GL_ARB_sync
|
||||
mSync = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
LLGLSyncFence::~LLGLSyncFence()
|
||||
{
|
||||
#ifdef GL_ARB_sync
|
||||
if (mSync)
|
||||
{
|
||||
glDeleteSync(mSync);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLGLSyncFence::placeFence()
|
||||
{
|
||||
#ifdef GL_ARB_sync
|
||||
if (mSync)
|
||||
{
|
||||
glDeleteSync(mSync);
|
||||
}
|
||||
mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool LLGLSyncFence::isCompleted()
|
||||
{
|
||||
bool ret = true;
|
||||
#ifdef GL_ARB_sync
|
||||
if (mSync)
|
||||
{
|
||||
GLenum status = glClientWaitSync(mSync, 0, 1);
|
||||
if (status == GL_TIMEOUT_EXPIRED)
|
||||
{
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LLGLSyncFence::wait()
|
||||
{
|
||||
#ifdef GL_ARB_sync
|
||||
if (mSync)
|
||||
{
|
||||
while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
|
||||
{ //track the number of times we've waited here
|
||||
static S32 waits = 0;
|
||||
waits++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llgl.h
|
||||
* @brief LLGL definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -111,6 +105,7 @@ public:
|
||||
BOOL mHasDepthClamp;
|
||||
BOOL mHasTextureRectangle;
|
||||
BOOL mHasTextureMultisample;
|
||||
BOOL mHasTransformFeedback;
|
||||
S32 mMaxSampleMaskWords;
|
||||
S32 mMaxColorTextureSamples;
|
||||
S32 mMaxDepthTextureSamples;
|
||||
@@ -148,6 +143,7 @@ public:
|
||||
S32 mGLSLVersionMajor;
|
||||
S32 mGLSLVersionMinor;
|
||||
std::string mDriverVersionVendorString;
|
||||
std::string mGLVersionString;
|
||||
|
||||
S32 mVRAM; // VRAM in MB
|
||||
S32 mGLMaxVertexRange;
|
||||
@@ -425,13 +421,39 @@ public:
|
||||
virtual void updateGL() = 0;
|
||||
};
|
||||
|
||||
const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000; //1 ms
|
||||
|
||||
class LLGLFence
|
||||
{
|
||||
public:
|
||||
virtual void placeFence() = 0;
|
||||
virtual bool isCompleted() = 0;
|
||||
virtual void wait() = 0;
|
||||
virtual ~LLGLFence() {}
|
||||
};
|
||||
|
||||
class LLGLSyncFence : public LLGLFence
|
||||
{
|
||||
public:
|
||||
#ifdef GL_ARB_sync
|
||||
GLsync mSync;
|
||||
#endif
|
||||
|
||||
LLGLSyncFence();
|
||||
virtual ~LLGLSyncFence();
|
||||
|
||||
void placeFence();
|
||||
bool isCompleted();
|
||||
void wait();
|
||||
};
|
||||
|
||||
extern LLMatrix4 gGLObliqueProjectionInverse;
|
||||
|
||||
#include "llglstates.h"
|
||||
|
||||
void init_glstates();
|
||||
|
||||
void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific );
|
||||
void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string );
|
||||
|
||||
extern BOOL gClothRipple;
|
||||
extern BOOL gNoRender;
|
||||
|
||||
@@ -534,6 +534,13 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
|
||||
extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
|
||||
extern PFNGLSAMPLEMASKIPROC glSampleMaski;
|
||||
|
||||
//transform feedback (4.0 core)
|
||||
extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
|
||||
extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
|
||||
extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
|
||||
extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
|
||||
|
||||
|
||||
#elif LL_WINDOWS
|
||||
//----------------------------------------------------------------------------
|
||||
// LL_WINDOWS
|
||||
@@ -765,6 +772,12 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
|
||||
extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
|
||||
extern PFNGLSAMPLEMASKIPROC glSampleMaski;
|
||||
|
||||
//transform feedback (4.0 core)
|
||||
extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
|
||||
extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
|
||||
extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
|
||||
extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
|
||||
|
||||
//GL_ARB_debug_output
|
||||
extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;
|
||||
extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB;
|
||||
|
||||
@@ -134,7 +134,9 @@ void LLGLSLShader::unload()
|
||||
}
|
||||
|
||||
BOOL LLGLSLShader::createShader(vector<string> * attributes,
|
||||
vector<string> * uniforms)
|
||||
vector<string> * uniforms,
|
||||
U32 varying_count,
|
||||
const char** varyings)
|
||||
{
|
||||
//reloading, reset matrix hash values
|
||||
for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i)
|
||||
@@ -142,6 +144,7 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
|
||||
mMatHash[i] = 0xFFFFFFFF;
|
||||
}
|
||||
mLightHash = 0xFFFFFFFF;
|
||||
|
||||
llassert_always(!mShaderFiles.empty());
|
||||
BOOL success = TRUE;
|
||||
|
||||
@@ -181,6 +184,13 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
|
||||
mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
|
||||
}
|
||||
|
||||
#ifdef GL_INTERLEAVED_ATTRIBS
|
||||
if (varying_count > 0 && varyings)
|
||||
{
|
||||
glTransformFeedbackVaryings(mProgramObject, varying_count, varyings, GL_INTERLEAVED_ATTRIBS);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Map attributes and uniforms
|
||||
if (success)
|
||||
{
|
||||
@@ -228,13 +238,13 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
|
||||
}
|
||||
unbind();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
BOOL LLGLSLShader::attachObject(std::string object)
|
||||
{
|
||||
std::map<std::string, GLhandleARB> &ShaderObjects = LLShaderMgr::instance()->mShaderObjects;
|
||||
if (ShaderObjects.find(object) != ShaderObjects.end())
|
||||
if (LLShaderMgr::instance()->mShaderObjects.count(object) > 0)
|
||||
{
|
||||
stop_glerror();
|
||||
glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mShaderObjects[object]);
|
||||
|
||||
@@ -82,7 +82,9 @@ public:
|
||||
|
||||
void unload();
|
||||
BOOL createShader(std::vector<std::string> * attributes,
|
||||
std::vector<std::string> * uniforms);
|
||||
std::vector<std::string> * uniforms,
|
||||
U32 varying_count = 0,
|
||||
const char** varyings = NULL);
|
||||
BOOL attachObject(std::string object);
|
||||
void attachObject(GLhandleARB object);
|
||||
void attachObjects(GLhandleARB* objects = NULL, S32 count = 0);
|
||||
|
||||
@@ -42,13 +42,17 @@
|
||||
|
||||
#include "llmath.h"
|
||||
#include "llgl.h"
|
||||
#include "llglslshader.h"
|
||||
#include "llrender.h"
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const F32 MIN_TEXTURE_LIFETIME = 10.f;
|
||||
|
||||
//which power of 2 is i?
|
||||
//assumes i is a power of 2 > 0
|
||||
U32 wpo2(U32 i);
|
||||
|
||||
//statics
|
||||
LLGLuint LLImageGL::sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS] = { 0 };
|
||||
|
||||
U32 LLImageGL::sUniqueCount = 0;
|
||||
U32 LLImageGL::sBindCount = 0;
|
||||
@@ -56,7 +60,8 @@ S32 LLImageGL::sGlobalTextureMemoryInBytes = 0;
|
||||
S32 LLImageGL::sBoundTextureMemoryInBytes = 0;
|
||||
S32 LLImageGL::sCurBoundTextureMemory = 0;
|
||||
S32 LLImageGL::sCount = 0;
|
||||
std::list<U32> LLImageGL::sDeadTextureList;
|
||||
LLImageGL::dead_texturelist_t LLImageGL::sDeadTextureList[LLTexUnit::TT_NONE];
|
||||
U32 LLImageGL::sCurTexName = 1;
|
||||
|
||||
BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
|
||||
F32 LLImageGL::sLastFrameTime = 0.f;
|
||||
@@ -79,7 +84,7 @@ std::vector<S32> LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
|
||||
S32 LLImageGL::sCurTexSizeBar = -1 ;
|
||||
S32 LLImageGL::sCurTexPickSize = -1 ;
|
||||
LLPointer<LLImageGL> LLImageGL::sHighlightTexturep = NULL;
|
||||
S32 LLImageGL::sMaxCatagories = 1 ;
|
||||
S32 LLImageGL::sMaxCategories = 1 ;
|
||||
|
||||
std::vector<S32> LLImageGL::sTextureMemByCategory;
|
||||
std::vector<S32> LLImageGL::sTextureMemByCategoryBound ;
|
||||
@@ -181,11 +186,11 @@ BOOL is_little_endian()
|
||||
//static
|
||||
void LLImageGL::initClass(S32 num_catagories)
|
||||
{
|
||||
sMaxCatagories = num_catagories ;
|
||||
sMaxCategories = num_catagories ;
|
||||
|
||||
sTextureMemByCategory.resize(sMaxCatagories);
|
||||
sTextureMemByCategoryBound.resize(sMaxCatagories) ;
|
||||
sTextureCurMemByCategoryBound.resize(sMaxCatagories) ;
|
||||
sTextureMemByCategory.resize(sMaxCategories);
|
||||
sTextureMemByCategoryBound.resize(sMaxCategories) ;
|
||||
sTextureCurMemByCategoryBound.resize(sMaxCategories) ;
|
||||
}
|
||||
|
||||
//static
|
||||
@@ -493,8 +498,9 @@ void LLImageGL::init(BOOL usemipmaps)
|
||||
mAllowCompression = true;
|
||||
|
||||
mTarget = GL_TEXTURE_2D;
|
||||
mBindTarget = LLTexUnit::TT_TEXTURE;
|
||||
mHasMipMaps = false;
|
||||
mBindTarget = LLTexUnit::TT_TEXTURE;
|
||||
mHasMipMaps = false;
|
||||
mMipLevels = -1;
|
||||
|
||||
mIsResident = 0;
|
||||
|
||||
@@ -679,19 +685,32 @@ void LLImageGL::setImage(const LLImageRaw* imageraw)
|
||||
|
||||
void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
{
|
||||
// LLFastTimer t1(FTM_TEMP1);
|
||||
bool is_compressed = false;
|
||||
if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
|
||||
{
|
||||
is_compressed = true;
|
||||
}
|
||||
|
||||
// LLFastTimer t2(FTM_TEMP2);
|
||||
llverify(gGL.getTexUnit(0)->bind(this));
|
||||
|
||||
|
||||
if (mUseMipMaps)
|
||||
{
|
||||
//set has mip maps to true before binding image so tex parameters get set properly
|
||||
gGL.getTexUnit(0)->unbind(mBindTarget);
|
||||
mHasMipMaps = true;
|
||||
mTexOptionsDirty = true;
|
||||
setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
mHasMipMaps = false;
|
||||
}
|
||||
|
||||
llverify(gGL.getTexUnit(0)->bind(this));
|
||||
|
||||
|
||||
if (mUseMipMaps)
|
||||
{
|
||||
// LLFastTimer t2(FTM_TEMP3);
|
||||
if (data_hasmips)
|
||||
{
|
||||
// NOTE: data_in points to largest image; smaller images
|
||||
@@ -702,6 +721,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
S32 w = getWidth(d);
|
||||
S32 h = getHeight(d);
|
||||
S32 gl_level = d-mCurrentDiscardLevel;
|
||||
|
||||
mMipLevels = llmax(mMipLevels, gl_level);
|
||||
|
||||
if (d > mCurrentDiscardLevel)
|
||||
{
|
||||
data_in -= dataFormatBytes(mFormatPrimary, w, h); // see above comment
|
||||
@@ -745,10 +767,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
{
|
||||
if (mAutoGenMips)
|
||||
{
|
||||
if (!gGLManager.mHasFramebufferObject)
|
||||
{
|
||||
glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE);
|
||||
}
|
||||
stop_glerror();
|
||||
{
|
||||
// LLFastTimer t2(FTM_TEMP4);
|
||||
@@ -762,6 +780,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
S32 w = getWidth(mCurrentDiscardLevel);
|
||||
S32 h = getHeight(mCurrentDiscardLevel);
|
||||
|
||||
mMipLevels = wpo2(llmax(w, h));
|
||||
|
||||
//use legacy mipmap generation mode
|
||||
glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
|
||||
LLImageGL::setManualImage(mTarget, 0, mFormatInternal,
|
||||
w, h,
|
||||
mFormatPrimary, mFormatType,
|
||||
@@ -777,17 +800,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
stop_glerror();
|
||||
}
|
||||
}
|
||||
|
||||
if (gGLManager.mHasFramebufferObject)
|
||||
{
|
||||
//GL_EXT_framebuffer_object implies glGenerateMipmap
|
||||
glGenerateMipmap(LLTexUnit::getInternalType(mBindTarget));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create mips by hand
|
||||
// about 30% faster than autogen on ATI 9800, 50% slower on nVidia 4800
|
||||
// ~4x faster than gluBuild2DMipmaps
|
||||
S32 width = getWidth(mCurrentDiscardLevel);
|
||||
S32 height = getHeight(mCurrentDiscardLevel);
|
||||
@@ -797,6 +813,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
const U8* cur_mip_data = 0;
|
||||
S32 prev_mip_size = 0;
|
||||
S32 cur_mip_size = 0;
|
||||
|
||||
mMipLevels = nummips;
|
||||
|
||||
for (int m=0; m<nummips; m++)
|
||||
{
|
||||
if (m==0)
|
||||
@@ -861,11 +880,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
{
|
||||
llerrs << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << llendl;
|
||||
}
|
||||
mHasMipMaps = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// LLFastTimer t2(FTM_TEMP5);
|
||||
mMipLevels = 0;
|
||||
S32 w = getWidth();
|
||||
S32 h = getHeight();
|
||||
if (is_compressed)
|
||||
@@ -897,7 +915,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
||||
}
|
||||
|
||||
}
|
||||
mHasMipMaps = false;
|
||||
}
|
||||
stop_glerror();
|
||||
mGLTextureCreated = true;
|
||||
@@ -1022,23 +1039,65 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_
|
||||
}
|
||||
|
||||
// static
|
||||
void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
|
||||
void LLImageGL::generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures)
|
||||
{
|
||||
glGenTextures(numTextures, (GLuint*)textures);
|
||||
bool empty = true;
|
||||
|
||||
dead_texturelist_t::iterator iter = sDeadTextureList[type].find(format);
|
||||
|
||||
if (iter != sDeadTextureList[type].end())
|
||||
{
|
||||
empty = iter->second.empty();
|
||||
}
|
||||
|
||||
for (S32 i = 0; i < numTextures; ++i)
|
||||
{
|
||||
if (!empty)
|
||||
{
|
||||
textures[i] = iter->second.front();
|
||||
iter->second.pop_front();
|
||||
empty = iter->second.empty();
|
||||
}
|
||||
else
|
||||
{
|
||||
textures[i] = sCurTexName++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate)
|
||||
void LLImageGL::deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate)
|
||||
{
|
||||
for (S32 i = 0; i < numTextures; i++)
|
||||
if (gGLManager.mInited)
|
||||
{
|
||||
sDeadTextureList.push_back(textures[i]);
|
||||
}
|
||||
if (format == 0 || type == LLTexUnit::TT_CUBE_MAP || mip_levels == -1)
|
||||
{ //unknown internal format or unknown number of mip levels, not safe to reuse
|
||||
glDeleteTextures(numTextures, textures);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (S32 i = 0; i < numTextures; ++i)
|
||||
{ //remove texture from VRAM by setting its size to zero
|
||||
for (S32 j = 0; j <= mip_levels; j++)
|
||||
{
|
||||
gGL.getTexUnit(0)->bindManual(type, textures[i]);
|
||||
|
||||
if (immediate)
|
||||
glTexImage2D(LLTexUnit::getInternalType(type), j, format, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
}
|
||||
|
||||
llassert(std::find(sDeadTextureList[type][format].begin(),
|
||||
sDeadTextureList[type][format].end(), textures[i]) ==
|
||||
sDeadTextureList[type][format].end());
|
||||
|
||||
sDeadTextureList[type][format].push_back(textures[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*if (immediate)
|
||||
{
|
||||
LLImageGL::deleteDeadTextures();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -1162,10 +1221,11 @@ BOOL LLImageGL::createGLTexture()
|
||||
|
||||
if(mTexName)
|
||||
{
|
||||
glDeleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ;
|
||||
LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, (reinterpret_cast<GLuint*>(&mTexName))) ;
|
||||
}
|
||||
|
||||
glGenTextures(1, (GLuint*)&mTexName);
|
||||
|
||||
LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName);
|
||||
stop_glerror();
|
||||
if (!mTexName)
|
||||
{
|
||||
@@ -1279,7 +1339,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
|
||||
}
|
||||
else
|
||||
{
|
||||
LLImageGL::generateTextures(1, &mTexName);
|
||||
LLImageGL::generateTextures(mBindTarget, mFormatInternal, 1, &mTexName);
|
||||
stop_glerror();
|
||||
{
|
||||
llverify(gGL.getTexUnit(0)->bind(this));
|
||||
@@ -1329,7 +1389,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
|
||||
decTextureCounter(mTextureMemory, mComponents, mCategory) ;
|
||||
}
|
||||
|
||||
LLImageGL::deleteTextures(1, &old_name);
|
||||
LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &old_name);
|
||||
|
||||
stop_glerror();
|
||||
}
|
||||
@@ -1345,59 +1405,6 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
|
||||
mLastBindTime = sLastFrameTime;
|
||||
return TRUE;
|
||||
}
|
||||
#if 0
|
||||
BOOL LLImageGL::setDiscardLevel(S32 discard_level)
|
||||
{
|
||||
llassert(discard_level >= 0);
|
||||
llassert(mCurrentDiscardLevel >= 0);
|
||||
|
||||
discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
|
||||
|
||||
if (mDontDiscard)
|
||||
{
|
||||
// don't discard!
|
||||
return FALSE;
|
||||
}
|
||||
else if (discard_level == mCurrentDiscardLevel)
|
||||
{
|
||||
// nothing to do
|
||||
return FALSE;
|
||||
}
|
||||
else if (discard_level < mCurrentDiscardLevel)
|
||||
{
|
||||
// larger image
|
||||
dump();
|
||||
llerrs << "LLImageGL::setDiscardLevel() called with larger discard level; use createGLTexture()" << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
else if (mUseMipMaps)
|
||||
{
|
||||
LLPointer<LLImageRaw> imageraw = new LLImageRaw;
|
||||
while(discard_level > mCurrentDiscardLevel)
|
||||
{
|
||||
if (readBackRaw(discard_level, imageraw, false))
|
||||
{
|
||||
break;
|
||||
}
|
||||
discard_level--;
|
||||
}
|
||||
if (discard_level == mCurrentDiscardLevel)
|
||||
{
|
||||
// unable to increase the discard level
|
||||
return FALSE;
|
||||
}
|
||||
return createGLTexture(discard_level, imageraw);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if !LL_LINUX && !LL_SOLARIS
|
||||
// *FIX: This should not be skipped for the linux client.
|
||||
llerrs << "LLImageGL::setDiscardLevel() called on image without mipmaps" << llendl;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok)
|
||||
{
|
||||
@@ -1515,28 +1522,32 @@ void LLImageGL::deleteDeadTextures()
|
||||
{
|
||||
bool reset = false;
|
||||
|
||||
while (!sDeadTextureList.empty())
|
||||
for(U32 i=0;i<LLTexUnit::TT_NONE;++i)
|
||||
{
|
||||
GLuint tex = sDeadTextureList.front();
|
||||
sDeadTextureList.pop_front();
|
||||
for (int i = 0; i < gGLManager.mNumTextureImageUnits; i++)
|
||||
for(dead_texturelist_t::iterator it=sDeadTextureList[i].begin();it!=sDeadTextureList[i].end();++it)
|
||||
{
|
||||
LLTexUnit* tex_unit = gGL.getTexUnit(i);
|
||||
|
||||
if (tex_unit && tex_unit->getCurrTexture() == tex)
|
||||
while(!it->second.empty())
|
||||
{
|
||||
tex_unit->unbind(tex_unit->getCurrType());
|
||||
stop_glerror();
|
||||
|
||||
if (i > 0)
|
||||
GLuint tex = it->second.front();
|
||||
it->second.pop_front();
|
||||
for (int j = 0; j < gGLManager.mNumTextureImageUnits; j++)
|
||||
{
|
||||
reset = true;
|
||||
LLTexUnit* tex_unit = gGL.getTexUnit(j);
|
||||
if (tex_unit && tex_unit->getCurrTexture() == tex)
|
||||
{
|
||||
tex_unit->unbind(tex_unit->getCurrType());
|
||||
stop_glerror();
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
reset = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
glDeleteTextures(1, &tex);
|
||||
stop_glerror();
|
||||
}
|
||||
}
|
||||
|
||||
glDeleteTextures(1, &tex);
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
if (reset)
|
||||
@@ -1559,9 +1570,9 @@ void LLImageGL::destroyGLTexture()
|
||||
mTextureMemory = 0;
|
||||
}
|
||||
|
||||
LLImageGL::deleteTextures(1, &mTexName);
|
||||
mTexName = 0;
|
||||
LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &mTexName);
|
||||
mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
|
||||
mTexName = 0;
|
||||
mGLTextureCreated = FALSE ;
|
||||
}
|
||||
}
|
||||
@@ -1997,7 +2008,7 @@ void LLImageGL::setCategory(S32 category)
|
||||
{
|
||||
sTextureMemByCategory[mCategory] -= mTextureMemory ;
|
||||
}
|
||||
if(category > -1 && category < sMaxCatagories)
|
||||
if(category > -1 && category < sMaxCategories)
|
||||
{
|
||||
sTextureMemByCategory[category] += mTextureMemory ;
|
||||
mCategory = category;
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llimagegl.h
|
||||
* @brief Object for managing images and their textures
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
@@ -51,8 +45,16 @@ class LLImageGL : public LLRefCount
|
||||
{
|
||||
friend class LLTexUnit;
|
||||
public:
|
||||
static std::list<U32> sDeadTextureList;
|
||||
static U32 sCurTexName;
|
||||
|
||||
//previously used but now available texture names
|
||||
// sDeadTextureList[<usage>][<internal format>]
|
||||
typedef std::map<U32, std::list<U32> > dead_texturelist_t;
|
||||
static dead_texturelist_t sDeadTextureList[LLTexUnit::TT_NONE];
|
||||
|
||||
// These 2 functions replace glGenTextures() and glDeleteTextures()
|
||||
static void generateTextures(LLTexUnit::eTextureType type, U32 format, S32 numTextures, U32 *textures);
|
||||
static void deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip_levels, S32 numTextures, U32 *textures, bool immediate = false);
|
||||
static void deleteDeadTextures();
|
||||
|
||||
// Size calculation
|
||||
@@ -102,15 +104,11 @@ public:
|
||||
void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}
|
||||
void setAllowCompression(bool allow) { mAllowCompression = allow; }
|
||||
|
||||
// These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D()
|
||||
// for tracking purposes and will be deprecated in the future
|
||||
static void generateTextures(S32 numTextures, U32 *textures);
|
||||
static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false);
|
||||
static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true);
|
||||
|
||||
BOOL createGLTexture() ;
|
||||
BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE,
|
||||
S32 category = sMaxCatagories - 1);
|
||||
BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE,
|
||||
S32 category = sMaxCategories-1);
|
||||
BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0);
|
||||
void setImage(const LLImageRaw* imageraw);
|
||||
void setImage(const U8* data_in, BOOL data_hasmips = FALSE);
|
||||
@@ -209,7 +207,8 @@ protected:
|
||||
LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps)
|
||||
LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps)
|
||||
bool mHasMipMaps;
|
||||
|
||||
S32 mMipLevels;
|
||||
|
||||
LLGLboolean mIsResident;
|
||||
|
||||
S8 mComponents;
|
||||
@@ -232,8 +231,6 @@ public:
|
||||
|
||||
static F32 sLastFrameTime;
|
||||
|
||||
static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID
|
||||
|
||||
// Global memory statistics
|
||||
static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem
|
||||
static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame
|
||||
@@ -255,7 +252,7 @@ public:
|
||||
static void initClass(S32 num_catagories) ;
|
||||
static void cleanupClass() ;
|
||||
private:
|
||||
static S32 sMaxCatagories ;
|
||||
static S32 sMaxCategories ;
|
||||
|
||||
//the flag to allow to call readBackRaw(...).
|
||||
//can be removed if we do not use that function at all.
|
||||
|
||||
@@ -422,12 +422,14 @@ void LLTexUnit::unbind(eTextureType type)
|
||||
|
||||
if (mIndex < 0) return;
|
||||
|
||||
//always flush and activate for consistency
|
||||
// some code paths assume unbind always flushes and sets the active texture
|
||||
gGL.flush();
|
||||
activate();
|
||||
|
||||
// Disabled caching of binding state.
|
||||
if (mCurrTexType == type)
|
||||
{
|
||||
gGL.flush();
|
||||
|
||||
activate();
|
||||
mCurrTexture = 0;
|
||||
if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE)
|
||||
{
|
||||
@@ -478,11 +480,25 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio
|
||||
}
|
||||
else if (option >= TFO_BILINEAR)
|
||||
{
|
||||
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
if (mHasMipMaps)
|
||||
{
|
||||
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
if (mHasMipMaps)
|
||||
{
|
||||
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
}
|
||||
}
|
||||
|
||||
if (gGLManager.mHasAnisotropic)
|
||||
|
||||
@@ -61,7 +61,6 @@ bool LLRenderTarget::sUseFBO = false;
|
||||
LLRenderTarget::LLRenderTarget() :
|
||||
mResX(0),
|
||||
mResY(0),
|
||||
mTex(0),
|
||||
mFBO(0),
|
||||
mDepth(0),
|
||||
mStencil(0),
|
||||
@@ -149,7 +148,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
|
||||
}
|
||||
|
||||
U32 tex;
|
||||
LLImageGL::generateTextures(1, &tex);
|
||||
LLImageGL::generateTextures(mUsage, color_fmt, 1, &tex);
|
||||
gGL.getTexUnit(0)->bindManual(mUsage, tex);
|
||||
|
||||
stop_glerror();
|
||||
@@ -207,6 +206,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
|
||||
}
|
||||
|
||||
mTex.push_back(tex);
|
||||
mInternalFormat.push_back(color_fmt);
|
||||
|
||||
if (gDebugGL)
|
||||
{ //bind and unbind to validate target
|
||||
@@ -231,7 +231,7 @@ bool LLRenderTarget::allocateDepth()
|
||||
}
|
||||
else
|
||||
{
|
||||
LLImageGL::generateTextures(1, &mDepth);
|
||||
LLImageGL::generateTextures(mUsage, GL_DEPTH_COMPONENT24, 1, &mDepth);
|
||||
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
|
||||
|
||||
U32 internal_type = LLTexUnit::getInternalType(mUsage);
|
||||
@@ -308,7 +308,7 @@ void LLRenderTarget::release()
|
||||
}
|
||||
else
|
||||
{
|
||||
LLImageGL::deleteTextures(1, &mDepth, true);
|
||||
LLImageGL::deleteTextures(mUsage, 0, 0, 1, &mDepth, true);
|
||||
stop_glerror();
|
||||
}
|
||||
mDepth = 0;
|
||||
@@ -340,8 +340,9 @@ void LLRenderTarget::release()
|
||||
if (mTex.size() > 0)
|
||||
{
|
||||
sBytesAllocated -= mResX*mResY*4*mTex.size();
|
||||
LLImageGL::deleteTextures(mTex.size(), &mTex[0], true);
|
||||
LLImageGL::deleteTextures(mUsage, mInternalFormat[0], 0, mTex.size(), &mTex[0], true);
|
||||
mTex.clear();
|
||||
mInternalFormat.clear();
|
||||
}
|
||||
|
||||
mResX = mResY = 0;
|
||||
|
||||
@@ -152,6 +152,7 @@ protected:
|
||||
U32 mResX;
|
||||
U32 mResY;
|
||||
std::vector<U32> mTex;
|
||||
std::vector<U32> mInternalFormat;
|
||||
U32 mFBO;
|
||||
U32 mDepth;
|
||||
bool mStencil;
|
||||
|
||||
@@ -1069,6 +1069,9 @@ void LLShaderMgr::initAttribsAndUniforms()
|
||||
mReservedUniforms.push_back("size");
|
||||
mReservedUniforms.push_back("falloff");
|
||||
|
||||
mReservedUniforms.push_back("box_center");
|
||||
mReservedUniforms.push_back("box_size");
|
||||
|
||||
|
||||
mReservedUniforms.push_back("minLuminance");
|
||||
mReservedUniforms.push_back("maxExtractAlpha");
|
||||
|
||||
@@ -97,6 +97,8 @@ public:
|
||||
LIGHT_CENTER,
|
||||
LIGHT_SIZE,
|
||||
LIGHT_FALLOFF,
|
||||
BOX_CENTER,
|
||||
BOX_SIZE,
|
||||
|
||||
GLOW_MIN_LUMINANCE,
|
||||
GLOW_MAX_EXTRACT_ALPHA,
|
||||
|
||||
@@ -39,8 +39,10 @@
|
||||
#include "llmemory.h"
|
||||
#include "llfasttimer.h"
|
||||
|
||||
#define LL_VBO_POOLING 0
|
||||
|
||||
#if LL_DARWIN
|
||||
#define LL_VBO_POOLING 1
|
||||
#else
|
||||
#endif
|
||||
//Next Highest Power Of Two
|
||||
//helper function, returns first number > v that is a power of 2, or v if v is already a power of 2
|
||||
U32 nhpo2(U32 v)
|
||||
@@ -68,6 +70,7 @@ U32 wpo2(U32 i)
|
||||
|
||||
|
||||
const U32 LL_VBO_BLOCK_SIZE = 2048;
|
||||
const U32 LL_VBO_POOL_MAX_SEED_SIZE = 256*1024;
|
||||
|
||||
U32 vbo_block_size(U32 size)
|
||||
{ //what block size will fit size?
|
||||
@@ -80,6 +83,7 @@ U32 vbo_block_index(U32 size)
|
||||
return vbo_block_size(size)/LL_VBO_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE);
|
||||
|
||||
|
||||
//============================================================================
|
||||
@@ -92,6 +96,11 @@ LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_
|
||||
|
||||
U32 LLVBOPool::sBytesPooled = 0;
|
||||
U32 LLVBOPool::sIndexBytesPooled = 0;
|
||||
U32 LLVBOPool::sCurGLName = 1;
|
||||
|
||||
std::list<U32> LLVertexBuffer::sAvailableVAOName;
|
||||
U32 LLVertexBuffer::sCurVAOName = 1;
|
||||
|
||||
U32 LLVertexBuffer::sAllocatedIndexBytes = 0;
|
||||
U32 LLVertexBuffer::sIndexCount = 0;
|
||||
|
||||
@@ -116,69 +125,55 @@ bool LLVertexBuffer::sUseStreamDraw = true;
|
||||
bool LLVertexBuffer::sUseVAO = false;
|
||||
bool LLVertexBuffer::sPreferStreamDraw = false;
|
||||
|
||||
const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms
|
||||
|
||||
class LLGLSyncFence : public LLGLFence
|
||||
U32 LLVBOPool::genBuffer()
|
||||
{
|
||||
public:
|
||||
#ifdef GL_ARB_sync
|
||||
GLsync mSync;
|
||||
#endif
|
||||
|
||||
LLGLSyncFence()
|
||||
U32 ret = 0;
|
||||
|
||||
if (mGLNamePool.empty())
|
||||
{
|
||||
#ifdef GL_ARB_sync
|
||||
mSync = 0;
|
||||
#endif
|
||||
ret = sCurGLName++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = mGLNamePool.front();
|
||||
mGLNamePool.pop_front();
|
||||
}
|
||||
|
||||
virtual ~LLGLSyncFence()
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LLVBOPool::deleteBuffer(U32 name)
|
||||
{
|
||||
if (gGLManager.mInited)
|
||||
{
|
||||
#ifdef GL_ARB_sync
|
||||
if (mSync)
|
||||
{
|
||||
glDeleteSync(mSync);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void placeFence()
|
||||
{
|
||||
#ifdef GL_ARB_sync
|
||||
if (mSync)
|
||||
{
|
||||
glDeleteSync(mSync);
|
||||
}
|
||||
mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
#ifdef GL_ARB_sync
|
||||
if (mSync)
|
||||
{
|
||||
while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
|
||||
{ //track the number of times we've waited here
|
||||
static S32 waits = 0;
|
||||
waits++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
LLVertexBuffer::unbind();
|
||||
|
||||
glBindBufferARB(mType, name);
|
||||
glBufferDataARB(mType, 0, NULL, mUsage);
|
||||
|
||||
llassert(std::find(mGLNamePool.begin(), mGLNamePool.end(), name) == mGLNamePool.end());
|
||||
|
||||
mGLNamePool.push_back(name);
|
||||
|
||||
glBindBufferARB(mType, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType)
|
||||
: mUsage(vboUsage), mType(vboType)
|
||||
{
|
||||
mMissCount.resize(LL_VBO_POOL_SEED_COUNT);
|
||||
std::fill(mMissCount.begin(), mMissCount.end(), 0);
|
||||
}
|
||||
|
||||
|
||||
volatile U8* LLVBOPool::allocate(U32& name, U32 size)
|
||||
volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)
|
||||
{
|
||||
llassert(vbo_block_size(size) == size);
|
||||
|
||||
volatile U8* ret = NULL;
|
||||
|
||||
#if LL_VBO_POOLING
|
||||
|
||||
U32 i = vbo_block_index(size);
|
||||
|
||||
if (mFreeList.size() <= i)
|
||||
@@ -186,25 +181,31 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)
|
||||
mFreeList.resize(i+1);
|
||||
}
|
||||
|
||||
if (mFreeList[i].empty())
|
||||
if (mFreeList[i].empty() || for_seed)
|
||||
{
|
||||
//make a new buffer
|
||||
glGenBuffersARB(1, &name);
|
||||
name = genBuffer();
|
||||
|
||||
glBindBufferARB(mType, name);
|
||||
|
||||
if (!for_seed && i < LL_VBO_POOL_SEED_COUNT)
|
||||
{ //record this miss
|
||||
mMissCount[i]++;
|
||||
}
|
||||
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
{
|
||||
LLVertexBuffer::sAllocatedBytes += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLVertexBuffer::sAllocatedIndexBytes += size;
|
||||
}
|
||||
{
|
||||
LLVertexBuffer::sAllocatedIndexBytes += size;
|
||||
}
|
||||
|
||||
if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
|
||||
{
|
||||
glBufferDataARB(mType, size, 0, mUsage);
|
||||
ret = (U8*) ll_aligned_malloc_16(size);
|
||||
if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
|
||||
{
|
||||
glBufferDataARB(mType, size, 0, mUsage);
|
||||
ret = (U8*) ll_aligned_malloc_16(size);
|
||||
}
|
||||
else
|
||||
{ //always use a true hint of static draw when allocating non-client-backed buffers
|
||||
@@ -212,6 +213,25 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)
|
||||
}
|
||||
|
||||
glBindBufferARB(mType, 0);
|
||||
|
||||
if (for_seed)
|
||||
{ //put into pool for future use
|
||||
llassert(mFreeList.size() > i);
|
||||
|
||||
Record rec;
|
||||
rec.mGLName = name;
|
||||
rec.mClientData = ret;
|
||||
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
{
|
||||
sBytesPooled += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
sIndexBytesPooled += size;
|
||||
}
|
||||
mFreeList[i].push_back(rec);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -229,33 +249,6 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size)
|
||||
|
||||
mFreeList[i].pop_front();
|
||||
}
|
||||
#else //no pooling
|
||||
|
||||
glGenBuffersARB(1, &name);
|
||||
glBindBufferARB(mType, name);
|
||||
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
{
|
||||
LLVertexBuffer::sAllocatedBytes += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLVertexBuffer::sAllocatedIndexBytes += size;
|
||||
}
|
||||
|
||||
if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
|
||||
{
|
||||
glBufferDataARB(mType, size, 0, mUsage);
|
||||
ret = (U8*) ll_aligned_malloc_16(size);
|
||||
}
|
||||
else
|
||||
{ //always use a true hint of static draw when allocating non-client-backed buffers
|
||||
glBufferDataARB(mType, size, 0, GL_STATIC_DRAW_ARB);
|
||||
}
|
||||
|
||||
glBindBufferARB(mType, 0);
|
||||
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -264,34 +257,7 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
|
||||
{
|
||||
llassert(vbo_block_size(size) == size);
|
||||
|
||||
#if LL_VBO_POOLING
|
||||
|
||||
U32 i = vbo_block_index(size);
|
||||
|
||||
llassert(mFreeList.size() > i);
|
||||
|
||||
Record rec;
|
||||
rec.mGLName = name;
|
||||
rec.mClientData = buffer;
|
||||
|
||||
if (buffer == NULL)
|
||||
{
|
||||
glDeleteBuffersARB(1, &rec.mGLName);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
{
|
||||
sBytesPooled += size;
|
||||
}
|
||||
else
|
||||
{
|
||||
sIndexBytesPooled += size;
|
||||
}
|
||||
mFreeList[i].push_back(rec);
|
||||
}
|
||||
#else //no pooling
|
||||
glDeleteBuffersARB(1, &name);
|
||||
deleteBuffer(name);
|
||||
ll_aligned_free_16((U8*) buffer);
|
||||
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
@@ -302,12 +268,36 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
|
||||
{
|
||||
LLVertexBuffer::sAllocatedIndexBytes -= size;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLVBOPool::seedPool()
|
||||
{
|
||||
U32 dummy_name = 0;
|
||||
|
||||
if (mFreeList.size() < LL_VBO_POOL_SEED_COUNT)
|
||||
{
|
||||
mFreeList.resize(LL_VBO_POOL_SEED_COUNT);
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < LL_VBO_POOL_SEED_COUNT; i++)
|
||||
{
|
||||
if (mMissCount[i] > mFreeList[i].size())
|
||||
{
|
||||
U32 size = i*LL_VBO_BLOCK_SIZE;
|
||||
|
||||
S32 count = mMissCount[i] - mFreeList[i].size();
|
||||
for (S32 j = 0; j < count; ++j)
|
||||
{
|
||||
allocate(dummy_name, size, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLVBOPool::cleanup()
|
||||
{
|
||||
U32 size = 1;
|
||||
U32 size = LL_VBO_BLOCK_SIZE;
|
||||
|
||||
for (U32 i = 0; i < mFreeList.size(); ++i)
|
||||
{
|
||||
@@ -317,8 +307,8 @@ void LLVBOPool::cleanup()
|
||||
{
|
||||
Record& r = l.front();
|
||||
|
||||
glDeleteBuffersARB(1, &r.mGLName);
|
||||
|
||||
deleteBuffer(r.mGLName);
|
||||
|
||||
if (r.mClientData)
|
||||
{
|
||||
ll_aligned_free_16((void*) r.mClientData);
|
||||
@@ -338,8 +328,11 @@ void LLVBOPool::cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
size *= 2;
|
||||
size += LL_VBO_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
//reset miss counts
|
||||
std::fill(mMissCount.begin(), mMissCount.end(), 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -373,6 +366,41 @@ U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
|
||||
GL_LINE_LOOP,
|
||||
};
|
||||
|
||||
//static
|
||||
U32 LLVertexBuffer::getVAOName()
|
||||
{
|
||||
U32 ret = 0;
|
||||
|
||||
if (!sAvailableVAOName.empty())
|
||||
{
|
||||
ret = sAvailableVAOName.front();
|
||||
sAvailableVAOName.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef GL_ARB_vertex_array_object
|
||||
glGenVertexArrays(1, &ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLVertexBuffer::releaseVAOName(U32 name)
|
||||
{
|
||||
sAvailableVAOName.push_back(name);
|
||||
}
|
||||
|
||||
|
||||
//static
|
||||
void LLVertexBuffer::seedPools()
|
||||
{
|
||||
sStreamVBOPool.seedPool();
|
||||
sDynamicVBOPool.seedPool();
|
||||
sStreamIBOPool.seedPool();
|
||||
sDynamicIBOPool.seedPool();
|
||||
}
|
||||
|
||||
//static
|
||||
void LLVertexBuffer::setupClientArrays(U32 data_mask)
|
||||
@@ -982,7 +1010,7 @@ LLVertexBuffer::~LLVertexBuffer()
|
||||
if (mGLArray)
|
||||
{
|
||||
#if GL_ARB_vertex_array_object
|
||||
glDeleteVertexArrays(1, &mGLArray);
|
||||
releaseVAOName(mGLArray);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1267,7 +1295,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
|
||||
if (gGLManager.mHasVertexArrayObject && useVBOs() && (LLRender::sGLCoreProfile || sUseVAO))
|
||||
{
|
||||
#if GL_ARB_vertex_array_object
|
||||
glGenVertexArrays(1, &mGLArray);
|
||||
mGLArray = getVAOName();
|
||||
#endif
|
||||
setupVertexArray();
|
||||
}
|
||||
@@ -2137,6 +2165,16 @@ void LLVertexBuffer::flush()
|
||||
}
|
||||
}
|
||||
|
||||
// bind for transform feedback (quick 'n dirty)
|
||||
void LLVertexBuffer::bindForFeedback(U32 channel, U32 type, U32 index, U32 count)
|
||||
{
|
||||
#ifdef GL_TRANSFORM_FEEDBACK_BUFFER
|
||||
U32 offset = mOffsets[type] + sTypeSize[type]*index;
|
||||
U32 size= (sTypeSize[type]*count);
|
||||
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, channel, mGLBuffer, offset, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set for rendering
|
||||
void LLVertexBuffer::setBuffer(U32 data_mask)
|
||||
{
|
||||
|
||||
@@ -56,24 +56,29 @@ class LLVBOPool
|
||||
public:
|
||||
static U32 sBytesPooled;
|
||||
static U32 sIndexBytesPooled;
|
||||
|
||||
static U32 sCurGLName;
|
||||
|
||||
LLVBOPool(U32 vboUsage, U32 vboType)
|
||||
: mUsage(vboUsage)
|
||||
, mType(vboType)
|
||||
{}
|
||||
|
||||
LLVBOPool(U32 vboUsage, U32 vboType);
|
||||
|
||||
const U32 mUsage;
|
||||
const U32 mType;
|
||||
|
||||
//size MUST be a power of 2
|
||||
volatile U8* allocate(U32& name, U32 size);
|
||||
volatile U8* allocate(U32& name, U32 size, bool for_seed = false);
|
||||
|
||||
//size MUST be the size provided to allocate that returned the given name
|
||||
void release(U32 name, volatile U8* buffer, U32 size);
|
||||
|
||||
//batch allocate buffers to be provided to the application on demand
|
||||
void seedPool();
|
||||
|
||||
//destroy all records in mFreeList
|
||||
void cleanup();
|
||||
|
||||
U32 genBuffer();
|
||||
void deleteBuffer(U32 name);
|
||||
|
||||
class Record
|
||||
{
|
||||
public:
|
||||
@@ -81,16 +86,11 @@ public:
|
||||
volatile U8* mClientData;
|
||||
};
|
||||
|
||||
std::list<U32> mGLNamePool;
|
||||
|
||||
typedef std::list<Record> record_list_t;
|
||||
std::vector<record_list_t> mFreeList;
|
||||
};
|
||||
|
||||
class LLGLFence
|
||||
{
|
||||
public:
|
||||
virtual void placeFence() = 0;
|
||||
virtual void wait() = 0;
|
||||
virtual ~LLGLFence() {}
|
||||
std::vector<U32> mMissCount;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
@@ -126,13 +126,22 @@ public:
|
||||
static LLVBOPool sStreamIBOPool;
|
||||
static LLVBOPool sDynamicIBOPool;
|
||||
|
||||
static std::list<U32> sAvailableVAOName;
|
||||
static U32 sCurVAOName;
|
||||
|
||||
static bool sUseStreamDraw;
|
||||
static bool sUseVAO;
|
||||
static bool sPreferStreamDraw;
|
||||
|
||||
static void seedPools();
|
||||
|
||||
static U32 getVAOName();
|
||||
static void releaseVAOName(U32 name);
|
||||
|
||||
static void initClass(bool use_vbo, bool no_vbo_mapping);
|
||||
static void cleanupClass();
|
||||
static void setupClientArrays(U32 data_mask);
|
||||
static void pushPositions(U32 mode, const LLVector4a* pos, U32 count);
|
||||
static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm);
|
||||
static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp);
|
||||
|
||||
@@ -209,7 +218,6 @@ protected:
|
||||
void destroyGLIndices();
|
||||
void updateNumVerts(S32 nverts);
|
||||
void updateNumIndices(S32 nindices);
|
||||
bool useVBOs() const;
|
||||
void unmapBuffer();
|
||||
|
||||
public:
|
||||
@@ -219,6 +227,8 @@ public:
|
||||
volatile U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
|
||||
volatile U8* mapIndexBuffer(S32 index, S32 count, bool map_range);
|
||||
|
||||
void bindForFeedback(U32 channel, U32 type, U32 index, U32 count);
|
||||
|
||||
// set for rendering
|
||||
virtual void setBuffer(U32 data_mask); // calls setupVertexBuffer() if data_mask is not 0
|
||||
void flush(); //flush pending data to GL memory
|
||||
@@ -241,12 +251,14 @@ public:
|
||||
bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getTextureIndexStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getEmissiveStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false);
|
||||
|
||||
|
||||
bool useVBOs() const;
|
||||
bool isEmpty() const { return mEmpty; }
|
||||
bool isLocked() const { return mVertexLocked || mIndexLocked; }
|
||||
S32 getNumVerts() const { return mNumVerts; }
|
||||
|
||||
@@ -297,8 +297,7 @@ boost::signals2::connection LLButton::setHeldDownCallback(const CommitCallbackPa
|
||||
|
||||
boost::signals2::connection LLButton::setClickedCallback( const commit_signal_t::slot_type& cb )
|
||||
{
|
||||
if (!mCommitSignal) mCommitSignal = new commit_signal_t();
|
||||
return mCommitSignal->connect(cb);
|
||||
return LLUICtrl::setCommitCallback(cb);
|
||||
}
|
||||
boost::signals2::connection LLButton::setMouseDownCallback( const commit_signal_t::slot_type& cb )
|
||||
{
|
||||
|
||||
@@ -280,7 +280,7 @@ void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater,
|
||||
}
|
||||
|
||||
//add the panel, add it to proper maps
|
||||
mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point);
|
||||
mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, 0, FALSE, insertion_point);
|
||||
mFloaterDataMap[floaterp->getHandle()] = floater_data;
|
||||
|
||||
updateResizeLimits();
|
||||
@@ -366,10 +366,10 @@ void LLMultiFloater::removeFloater(LLFloater* floaterp)
|
||||
|
||||
updateResizeLimits();
|
||||
|
||||
tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false);
|
||||
tabOpen((LLFloater*)mTabContainer->getCurrentPanel());
|
||||
}
|
||||
|
||||
void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click)
|
||||
void LLMultiFloater::tabOpen(LLFloater* opened_floater)
|
||||
{
|
||||
// default implementation does nothing
|
||||
}
|
||||
@@ -464,12 +464,9 @@ void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing)
|
||||
mTabContainer->setTabPanelFlashing(floaterp, flashing);
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMultiFloater::onTabSelected(void* userdata, bool from_click)
|
||||
void LLMultiFloater::onTabSelected()
|
||||
{
|
||||
LLMultiFloater* floaterp = (LLMultiFloater*)userdata;
|
||||
|
||||
floaterp->tabOpen((LLFloater*)floaterp->mTabContainer->getCurrentPanel(), from_click);
|
||||
tabOpen((LLFloater*)mTabContainer->getCurrentPanel());
|
||||
}
|
||||
|
||||
void LLMultiFloater::setCanResize(BOOL can_resize)
|
||||
@@ -499,6 +496,7 @@ BOOL LLMultiFloater::postBuild()
|
||||
if (checkRequirements())
|
||||
{
|
||||
mTabContainer = getChild<LLTabContainer>("Preview Tabs");
|
||||
mTabContainer->setCommitCallback(boost::bind(&LLMultiFloater::onTabSelected, this));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
virtual void showFloater(LLFloater* floaterp);
|
||||
virtual void removeFloater(LLFloater* floaterp);
|
||||
|
||||
virtual void tabOpen(LLFloater* opened_floater, bool from_click);
|
||||
virtual void tabOpen(LLFloater* opened_floater);
|
||||
virtual void tabClose();
|
||||
|
||||
virtual BOOL selectFloater(LLFloater* floaterp);
|
||||
@@ -74,7 +74,7 @@ public:
|
||||
virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing);
|
||||
virtual BOOL closeAllFloaters(); //Returns FALSE if the floater could not be closed due to pending confirmation dialogs
|
||||
void setTabContainer(LLTabContainer* tab_container) { if (!mTabContainer) mTabContainer = tab_container; }
|
||||
static void onTabSelected(void* userdata, bool);
|
||||
void onTabSelected();
|
||||
|
||||
virtual void updateResizeLimits();
|
||||
|
||||
|
||||
@@ -931,24 +931,6 @@ LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void LLPanel::childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata, void (*on_precommit)(void*,bool))
|
||||
{
|
||||
LLTabContainer* child = getChild<LLTabContainer>(id);
|
||||
if (child)
|
||||
{
|
||||
LLPanel *panel = child->getPanelByName(tabname);
|
||||
if (panel)
|
||||
{
|
||||
child->setTabChangeCallback(panel, on_tab_clicked);
|
||||
child->setTabUserData(panel, userdata);
|
||||
if (on_precommit)
|
||||
{
|
||||
child->setTabPrecommitChangeCallback(panel, on_precommit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanel::childSetKeystrokeCallback(const std::string& id, void (*keystroke_callback)(LLLineEditor* caller, void* user_data), void *user_data)
|
||||
{
|
||||
LLLineEditor* child = getChild<LLLineEditor>(id);
|
||||
|
||||
@@ -198,7 +198,6 @@ public:
|
||||
// LLTabContainer
|
||||
void childShowTab(const std::string& id, const std::string& tabname, bool visible = true);
|
||||
LLPanel *childGetVisibleTab(const std::string& id) const;
|
||||
void childSetTabChangeCallback(const std::string& id, const std::string& tabname, void (*on_tab_clicked)(void*, bool), void *userdata, void (*on_precommit)(void*,bool) = NULL);
|
||||
|
||||
// LLTextBox
|
||||
void childSetWrappedText(const std::string& id, const std::string& text, bool visible = true);
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLSCROLLINGPANELLIST_H
|
||||
#define LL_LLSCROLLINGPANELLIST_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "llui.h"
|
||||
@@ -56,6 +59,8 @@ public:
|
||||
LLScrollingPanelList(const std::string& name, const LLRect& rect)
|
||||
: LLUICtrl(name, rect, TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_BOTTOM ) {}
|
||||
|
||||
typedef std::deque<LLScrollingPanel*> panel_list_t;
|
||||
|
||||
virtual void setValue(const LLSD& value) {};
|
||||
|
||||
virtual void draw();
|
||||
@@ -64,11 +69,16 @@ public:
|
||||
void addPanel( LLScrollingPanel* panel );
|
||||
void updatePanels(BOOL allow_modify);
|
||||
|
||||
const panel_list_t& getPanelList() { return mPanelList; }
|
||||
|
||||
virtual LLXMLNodePtr getXML(bool save_children = true) const;
|
||||
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
|
||||
|
||||
private:
|
||||
void updatePanelVisiblilty();
|
||||
|
||||
std::deque<LLScrollingPanel*> mPanelList;
|
||||
|
||||
panel_list_t mPanelList;
|
||||
};
|
||||
|
||||
#endif //LL_LLSCROLLINGPANELLIST_H
|
||||
|
||||
@@ -69,19 +69,38 @@ const S32 TABCNTRV_PAD = 0;
|
||||
|
||||
static LLRegisterWidget<LLTabContainer> r("tab_container");
|
||||
|
||||
// Structure used to map tab buttons to and from tab panels
|
||||
class LLTabTuple
|
||||
{
|
||||
public:
|
||||
LLTabTuple( LLTabContainer* c, LLPanel* p, LLButton* b, LLTextBox* placeholder = NULL)
|
||||
:
|
||||
mTabContainer(c),
|
||||
mTabPanel(p),
|
||||
mButton(b),
|
||||
mOldState(FALSE),
|
||||
mPlaceholderText(placeholder),
|
||||
mPadding(0)
|
||||
{}
|
||||
|
||||
LLTabContainer* mTabContainer;
|
||||
LLPanel* mTabPanel;
|
||||
LLButton* mButton;
|
||||
BOOL mOldState;
|
||||
LLTextBox* mPlaceholderText;
|
||||
S32 mPadding;
|
||||
};
|
||||
|
||||
LLTabContainer::LLTabContainer(const std::string& name, const LLRect& rect, TabPosition pos,
|
||||
BOOL bordered, BOOL is_vertical )
|
||||
:
|
||||
LLPanel(name, rect, bordered),
|
||||
mCurrentTabIdx(-1),
|
||||
mNextTabIdx(-1),
|
||||
mTabsHidden(FALSE),
|
||||
mScrolled(FALSE),
|
||||
mScrollPos(0),
|
||||
mScrollPosPixels(0),
|
||||
mMaxScrollPos(0),
|
||||
mCloseCallback( NULL ),
|
||||
mCallbackUserdata( NULL ),
|
||||
mTitleBox(NULL),
|
||||
mTopBorderHeight(LLPANEL_BORDER_WIDTH),
|
||||
mTabPosition(pos),
|
||||
@@ -196,9 +215,9 @@ void LLTabContainer::draw()
|
||||
}
|
||||
}
|
||||
|
||||
setScrollPosPixels((S32)lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f)));
|
||||
setScrollPosPixels(mIsVertical ? target_pixel_scroll : lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f)));
|
||||
|
||||
BOOL has_scroll_arrows = (mMaxScrollPos > 0) || (mScrollPosPixels > 0);
|
||||
BOOL has_scroll_arrows = !getTabsHidden() && ((mMaxScrollPos > 0) || (mScrollPosPixels > 0));
|
||||
if (!mIsVertical)
|
||||
{
|
||||
mJumpPrevArrowBtn->setVisible( has_scroll_arrows );
|
||||
@@ -221,13 +240,22 @@ void LLTabContainer::draw()
|
||||
}
|
||||
|
||||
// Hide all the buttons
|
||||
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
|
||||
if (getTabsHidden() || mIsVertical)
|
||||
{
|
||||
LLTabTuple* tuple = *iter;
|
||||
tuple->mButton->setVisible( FALSE );
|
||||
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
|
||||
{
|
||||
LLTabTuple* tuple = *iter;
|
||||
tuple->mButton->setVisible( FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
LLPanel::draw();
|
||||
{
|
||||
LLRect clip_rect = getLocalRect();
|
||||
clip_rect.mLeft+=(LLPANEL_BORDER_WIDTH + 2);
|
||||
clip_rect.mRight-=(LLPANEL_BORDER_WIDTH + 2);
|
||||
LLLocalClipRect clip(clip_rect);
|
||||
LLPanel::draw();
|
||||
}
|
||||
|
||||
// if tabs are hidden, don't draw them and leave them in the invisible state
|
||||
if (!getTabsHidden())
|
||||
@@ -241,19 +269,10 @@ void LLTabContainer::draw()
|
||||
|
||||
// Draw some of the buttons...
|
||||
LLRect clip_rect = getLocalRect();
|
||||
if (has_scroll_arrows)
|
||||
if (has_scroll_arrows && mIsVertical)
|
||||
{
|
||||
// ...but clip them.
|
||||
if (mIsVertical)
|
||||
{
|
||||
clip_rect.mBottom = mNextArrowBtn->getRect().mTop + 3*TABCNTRV_PAD;
|
||||
clip_rect.mTop = mPrevArrowBtn->getRect().mBottom - 3*TABCNTRV_PAD;
|
||||
}
|
||||
else
|
||||
{
|
||||
clip_rect.mLeft = mPrevArrowBtn->getRect().mRight;
|
||||
clip_rect.mRight = mNextArrowBtn->getRect().mLeft;
|
||||
}
|
||||
clip_rect.mTop = top - getScrollPosPixels();
|
||||
clip_rect.mBottom = TABCNTR_ARROW_BTN_SIZE+1;
|
||||
}
|
||||
LLLocalClipRect clip(clip_rect);
|
||||
|
||||
@@ -285,12 +304,13 @@ void LLTabContainer::draw()
|
||||
}
|
||||
}
|
||||
}
|
||||
LLUI::pushMatrix();
|
||||
else
|
||||
{
|
||||
LLUI::pushMatrix();
|
||||
LLUI::translate((F32)tuple->mButton->getRect().mLeft, (F32)tuple->mButton->getRect().mBottom, 0.f);
|
||||
tuple->mButton->draw();
|
||||
LLUI::popMatrix();
|
||||
}
|
||||
LLUI::popMatrix();
|
||||
|
||||
idx++;
|
||||
}
|
||||
@@ -320,7 +340,7 @@ void LLTabContainer::draw()
|
||||
BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
|
||||
{
|
||||
BOOL handled = FALSE;
|
||||
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
|
||||
BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
|
||||
|
||||
if (has_scroll_arrows)
|
||||
{
|
||||
@@ -355,7 +375,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
|
||||
}
|
||||
|
||||
S32 tab_count = getTabCount();
|
||||
if (tab_count > 0)
|
||||
if (tab_count > 0 && !getTabsHidden())
|
||||
{
|
||||
LLTabTuple* firsttuple = getTab(0);
|
||||
LLRect tab_rect;
|
||||
@@ -379,6 +399,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
|
||||
index = llclamp(index, 0, tab_count-1);
|
||||
LLButton* tab_button = getTab(index)->mButton;
|
||||
gFocusMgr.setMouseCapture(this);
|
||||
tab_button->setFocus(TRUE);
|
||||
gFocusMgr.setKeyboardFocus(tab_button);
|
||||
}
|
||||
}
|
||||
@@ -389,7 +410,7 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask )
|
||||
BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
|
||||
{
|
||||
BOOL handled = FALSE;
|
||||
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
|
||||
BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
|
||||
|
||||
if (has_scroll_arrows)
|
||||
{
|
||||
@@ -431,7 +452,7 @@ BOOL LLTabContainer::handleHover( S32 x, S32 y, MASK mask )
|
||||
BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
|
||||
{
|
||||
BOOL handled = FALSE;
|
||||
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
|
||||
BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden();
|
||||
|
||||
if (has_scroll_arrows)
|
||||
{
|
||||
@@ -487,7 +508,7 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask )
|
||||
BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rect )
|
||||
{
|
||||
BOOL handled = LLPanel::handleToolTip( x, y, msg, sticky_rect );
|
||||
if (!handled && getTabCount() > 0)
|
||||
if (!handled && getTabCount() > 0 && !getTabsHidden())
|
||||
{
|
||||
LLTabTuple* firsttuple = getTab(0);
|
||||
|
||||
@@ -523,12 +544,6 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* stic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
|
||||
{
|
||||
LLTabTuple* tuple = *iter;
|
||||
tuple->mButton->setVisible( FALSE );
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
@@ -552,7 +567,7 @@ BOOL LLTabContainer::handleKeyHere(KEY key, MASK mask)
|
||||
{
|
||||
if (getCurrentPanel())
|
||||
{
|
||||
getCurrentPanel()->setFocus(TRUE);
|
||||
getCurrentPanel()->setFocus(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -633,59 +648,63 @@ LLXMLNodePtr LLTabContainer::getXML(bool save_children) const
|
||||
// virtual
|
||||
BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, std::string &tooltip)
|
||||
{
|
||||
bool const has_scroll_arrows = (getMaxScrollPos() > 0);
|
||||
BOOL has_scroll_arrows = (getMaxScrollPos() > 0);
|
||||
|
||||
LLButton* button = NULL;
|
||||
if (has_scroll_arrows)
|
||||
if(!getTabsHidden())
|
||||
{
|
||||
// We're dragging an inventory item. Check if we're hovering over scroll arrows of this tab container.
|
||||
if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
|
||||
// In that case, we'll open the hovered tab while dragging and dropping items.
|
||||
// This allows for drilling through tabs.
|
||||
if (mDragAndDropDelayTimer.getStarted())
|
||||
{
|
||||
button = mJumpPrevArrowBtn;
|
||||
}
|
||||
else if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y))
|
||||
{
|
||||
button = mJumpNextArrowBtn;
|
||||
}
|
||||
else if (mPrevArrowBtn->getRect().pointInRect(x, y))
|
||||
{
|
||||
button = mPrevArrowBtn;
|
||||
}
|
||||
else if (mNextArrowBtn->getRect().pointInRect(x, y))
|
||||
{
|
||||
button = mNextArrowBtn;
|
||||
}
|
||||
if (button)
|
||||
{
|
||||
if (mDragAndDropDelayTimer.getStarted() && mDragAndDropDelayTimer.hasExpired())
|
||||
if (mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME)
|
||||
{
|
||||
// We've been hovering (another) SCROLL_DELAY_TIME seconds. Emulate a button press.
|
||||
button->onCommit();
|
||||
// Reset the timer.
|
||||
mDragAndDropDelayTimer.start(SCROLL_DELAY_TIME);
|
||||
}
|
||||
else if (!mDragAndDropDelayTimer.getStarted())
|
||||
{
|
||||
// We just entered the arrow. Start the timer.
|
||||
mDragAndDropDelayTimer.start(SCROLL_DELAY_TIME);
|
||||
if (has_scroll_arrows)
|
||||
{
|
||||
if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y))
|
||||
{
|
||||
S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft;
|
||||
S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom;
|
||||
mJumpPrevArrowBtn->handleHover(local_x, local_y, mask);
|
||||
}
|
||||
if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y))
|
||||
{
|
||||
S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft;
|
||||
S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom;
|
||||
mJumpNextArrowBtn->handleHover(local_x, local_y, mask);
|
||||
}
|
||||
if (mPrevArrowBtn->getRect().pointInRect(x, y))
|
||||
{
|
||||
S32 local_x = x - mPrevArrowBtn->getRect().mLeft;
|
||||
S32 local_y = y - mPrevArrowBtn->getRect().mBottom;
|
||||
mPrevArrowBtn->handleHover(local_x, local_y, mask);
|
||||
}
|
||||
else if (mNextArrowBtn->getRect().pointInRect(x, y))
|
||||
{
|
||||
S32 local_x = x - mNextArrowBtn->getRect().mLeft;
|
||||
S32 local_y = y - mNextArrowBtn->getRect().mBottom;
|
||||
mNextArrowBtn->handleHover(local_x, local_y, mask);
|
||||
}
|
||||
}
|
||||
|
||||
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
|
||||
{
|
||||
LLTabTuple* tuple = *iter;
|
||||
tuple->mButton->setVisible( TRUE );
|
||||
S32 local_x = x - tuple->mButton->getRect().mLeft;
|
||||
S32 local_y = y - tuple->mButton->getRect().mBottom;
|
||||
if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible())
|
||||
{
|
||||
tuple->mButton->onCommit();
|
||||
}
|
||||
}
|
||||
// Stop the timer whether successful or not. Don't let it run forever.
|
||||
mDragAndDropDelayTimer.stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
// We're not on an arrow or just left it. Stop the time (in case it was running).
|
||||
mDragAndDropDelayTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
|
||||
{
|
||||
LLTabTuple* tuple = *iter;
|
||||
tuple->mButton->setVisible( TRUE );
|
||||
S32 local_x = x - tuple->mButton->getRect().mLeft;
|
||||
S32 local_y = y - tuple->mButton->getRect().mBottom;
|
||||
if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible())
|
||||
{
|
||||
tuple->mButton->onCommit();
|
||||
// Start a timer so we don't open tabs as soon as we hover on them
|
||||
mDragAndDropDelayTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,12 +714,11 @@ BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDrag
|
||||
void LLTabContainer::addTabPanel(LLPanel* child,
|
||||
const std::string& label,
|
||||
BOOL select,
|
||||
void (*on_tab_clicked)(void*, bool),
|
||||
void* userdata,
|
||||
S32 indent,
|
||||
BOOL placeholder,
|
||||
eInsertionPoint insertion_point)
|
||||
{
|
||||
|
||||
if (child->getParent() == this)
|
||||
{
|
||||
// already a child of mine
|
||||
@@ -722,22 +740,30 @@ void LLTabContainer::addTabPanel(LLPanel* child,
|
||||
// Tab panel
|
||||
S32 tab_panel_top;
|
||||
S32 tab_panel_bottom;
|
||||
if( getTabPosition() == LLTabContainer::TOP )
|
||||
if (!getTabsHidden())
|
||||
{
|
||||
S32 tab_height = mIsVertical ? BTN_HEIGHT : TABCNTR_TAB_HEIGHT;
|
||||
tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - TABCNTR_BUTTON_PANEL_OVERLAP);
|
||||
tab_panel_bottom = LLPANEL_BORDER_WIDTH;
|
||||
if( getTabPosition() == LLTabContainer::TOP )
|
||||
{
|
||||
S32 tab_height = mIsVertical ? BTN_HEIGHT : TABCNTR_TAB_HEIGHT;
|
||||
tab_panel_top = getRect().getHeight() - getTopBorderHeight() - (tab_height - TABCNTR_BUTTON_PANEL_OVERLAP);
|
||||
tab_panel_bottom = LLPANEL_BORDER_WIDTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
tab_panel_top = getRect().getHeight() - getTopBorderHeight();
|
||||
tab_panel_bottom = (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP); // Run to the edge, covering up the border
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tab_panel_top = getRect().getHeight() - getTopBorderHeight();
|
||||
tab_panel_bottom = (TABCNTR_TAB_HEIGHT - TABCNTR_BUTTON_PANEL_OVERLAP); // Run to the edge, covering up the border
|
||||
//Scip tab button space if they are invisible(EXT - 576)
|
||||
tab_panel_top = getRect().getHeight();
|
||||
tab_panel_bottom = LLPANEL_BORDER_WIDTH;
|
||||
}
|
||||
|
||||
LLRect tab_panel_rect;
|
||||
if (mIsVertical)
|
||||
if (!getTabsHidden() && mIsVertical)
|
||||
{
|
||||
tab_panel_rect = LLRect(mMinTabWidth + (LLPANEL_BORDER_WIDTH * 2) + TABCNTRV_PAD,
|
||||
tab_panel_rect = LLRect(mMinTabWidth + mRightTabBtnOffset + (LLPANEL_BORDER_WIDTH * 2) + TABCNTRV_PAD,
|
||||
getRect().getHeight() - LLPANEL_BORDER_WIDTH,
|
||||
getRect().getWidth() - LLPANEL_BORDER_WIDTH,
|
||||
LLPANEL_BORDER_WIDTH);
|
||||
@@ -854,24 +880,33 @@ void LLTabContainer::addTabPanel(LLPanel* child,
|
||||
}
|
||||
}
|
||||
|
||||
LLTabTuple* tuple = new LLTabTuple( this, child, btn, on_tab_clicked, userdata, textbox );
|
||||
LLTabTuple* tuple = new LLTabTuple( this, child, btn, textbox );
|
||||
insertTuple( tuple, insertion_point );
|
||||
|
||||
if (textbox)
|
||||
//Don't add button and textbox if tab buttons are invisible(EXT - 576)
|
||||
if (!getTabsHidden())
|
||||
{
|
||||
textbox->setSaveToXML(false);
|
||||
addChild( textbox, 0 );
|
||||
if (textbox)
|
||||
{
|
||||
textbox->setSaveToXML(false);
|
||||
addChild( textbox, 0 );
|
||||
}
|
||||
}
|
||||
if (btn)
|
||||
{
|
||||
btn->setSaveToXML(false);
|
||||
btn->setClickedCallback(&LLTabContainer::onTabBtn, tuple);
|
||||
btn->setClickedCallback(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
|
||||
addChild( btn, 0 );
|
||||
}
|
||||
if (child)
|
||||
{
|
||||
addChild(child, 1);
|
||||
}
|
||||
|
||||
sendChildToFront(mPrevArrowBtn);
|
||||
sendChildToFront(mNextArrowBtn);
|
||||
sendChildToFront(mJumpPrevArrowBtn);
|
||||
sendChildToFront(mJumpNextArrowBtn);
|
||||
|
||||
if( select )
|
||||
{
|
||||
@@ -883,7 +918,7 @@ void LLTabContainer::addTabPanel(LLPanel* child,
|
||||
|
||||
void LLTabContainer::addPlaceholder(LLPanel* child, const std::string& label)
|
||||
{
|
||||
addTabPanel(child, label, FALSE, NULL, NULL, 0, TRUE);
|
||||
addTabPanel(child, label, FALSE, 0, TRUE);
|
||||
}
|
||||
|
||||
void LLTabContainer::removeTabPanel(LLPanel* child)
|
||||
@@ -984,6 +1019,10 @@ void LLTabContainer::enableTabButton(S32 which, BOOL enable)
|
||||
{
|
||||
mTabList[which]->mButton->setEnabled(enable);
|
||||
}
|
||||
// Stop the DaD timer as it might run forever
|
||||
// enableTabButton() is typically called on refresh and draw when anything changed
|
||||
// in the tab container so it's a good time to reset that.
|
||||
mDragAndDropDelayTimer.stop();
|
||||
}
|
||||
|
||||
void LLTabContainer::deleteAllTabs()
|
||||
@@ -1154,8 +1193,8 @@ BOOL LLTabContainer::selectTabPanel(LLPanel* child)
|
||||
|
||||
BOOL LLTabContainer::selectTab(S32 which)
|
||||
{
|
||||
if (which >= getTabCount()) return FALSE;
|
||||
if (which < 0) return FALSE;
|
||||
if (which >= getTabCount() || which < 0)
|
||||
return FALSE;
|
||||
|
||||
//if( gFocusMgr.childHasKeyboardFocus( this ) )
|
||||
//{
|
||||
@@ -1167,28 +1206,26 @@ BOOL LLTabContainer::selectTab(S32 which)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LLSD cbdata;
|
||||
if (selected_tuple->mTabPanel)
|
||||
cbdata = selected_tuple->mTabPanel->getName();
|
||||
|
||||
if (!selected_tuple->mPrecommitChangeCallback)
|
||||
BOOL res = FALSE;
|
||||
if( !mValidateSignal || (*mValidateSignal)( this, cbdata ) )
|
||||
{
|
||||
return setTab(which);
|
||||
res = setTab(which);
|
||||
if (res && mCommitSignal)
|
||||
{
|
||||
(*mCommitSignal)(this, cbdata);
|
||||
}
|
||||
}
|
||||
|
||||
mNextTabIdx = which;
|
||||
selected_tuple->mPrecommitChangeCallback(selected_tuple->mUserData, false);
|
||||
return TRUE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
BOOL LLTabContainer::setTab(S32 which)
|
||||
{
|
||||
if (which == -1)
|
||||
{
|
||||
if (mNextTabIdx == -1)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
which = mNextTabIdx;
|
||||
mNextTabIdx = -1;
|
||||
}
|
||||
|
||||
LLTabTuple* selected_tuple = getTab(which);
|
||||
if (!selected_tuple)
|
||||
@@ -1212,12 +1249,12 @@ BOOL LLTabContainer::setTab(S32 which)
|
||||
// RN: this limits tab-stops to active button only, which would require arrow keys to switch tabs
|
||||
tuple->mButton->setTabStop( is_selected );
|
||||
|
||||
if( is_selected && (mIsVertical || (getMaxScrollPos() > 0)))
|
||||
if (is_selected)
|
||||
{
|
||||
// Make sure selected tab is within scroll region
|
||||
if (mIsVertical)
|
||||
{
|
||||
S32 num_visible = getTabCount() - getMaxScrollPos();
|
||||
/*S32 num_visible = getTabCount() - getMaxScrollPos();
|
||||
if( i >= getScrollPos() && i <= getScrollPos() + num_visible)
|
||||
{
|
||||
setCurrentPanelIndex(which);
|
||||
@@ -1226,9 +1263,28 @@ BOOL LLTabContainer::setTab(S32 which)
|
||||
else
|
||||
{
|
||||
is_visible = FALSE;
|
||||
}*/
|
||||
if (getMaxScrollPos() > 0)
|
||||
{
|
||||
if( i < getScrollPos() )
|
||||
{
|
||||
setScrollPos(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 available_height_with_arrows = getRect().getHeight() - getTopBorderHeight() - (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
|
||||
S32 min_scroll_pos = llmax(i-llfloor(((F32)available_height_with_arrows)/((F32)BTN_HEIGHT))+1,0);
|
||||
setScrollPos(llclamp(getScrollPos(), min_scroll_pos, i));
|
||||
setScrollPos(llmin(getScrollPos(), getMaxScrollPos()));
|
||||
}
|
||||
is_visible = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_visible = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (getMaxScrollPos() > 0)
|
||||
{
|
||||
if( i < getScrollPos() )
|
||||
{
|
||||
@@ -1259,20 +1315,20 @@ BOOL LLTabContainer::setTab(S32 which)
|
||||
}
|
||||
is_visible = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_visible = TRUE;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if( selected_tuple->mOnChangeCallback )
|
||||
{
|
||||
selected_tuple->mOnChangeCallback( selected_tuple->mUserData, false );
|
||||
}
|
||||
}
|
||||
if (mIsVertical && getCurrentPanelIndex() >= 0)
|
||||
/*if (mIsVertical && getCurrentPanelIndex() >= 0)
|
||||
{
|
||||
LLTabTuple* tuple = getTab(getCurrentPanelIndex());
|
||||
tuple->mTabPanel->setVisible( TRUE );
|
||||
tuple->mButton->setToggleState( TRUE );
|
||||
}
|
||||
}*/
|
||||
return is_visible;
|
||||
}
|
||||
|
||||
@@ -1315,28 +1371,44 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
|
||||
if( tuple )
|
||||
{
|
||||
tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT, color);
|
||||
reshapeTuple(tuple);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mIsVertical)
|
||||
{
|
||||
const LLFontGL* fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL );
|
||||
// remove current width from total tab strip width
|
||||
mTotalTabWidth -= tuple->mButton->getRect().getWidth();
|
||||
void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const LLColor4& color)
|
||||
{
|
||||
LLTabTuple* tuple = getTabByPanel(child);
|
||||
if( tuple )
|
||||
{
|
||||
tuple->mButton->setImageOverlay(image_id, LLFontGL::LEFT, color);
|
||||
reshapeTuple(tuple);
|
||||
}
|
||||
}
|
||||
|
||||
S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
|
||||
tuple->mButton->getImageOverlay()->getImage()->getWidth(0) :
|
||||
0;
|
||||
void LLTabContainer::reshapeTuple(LLTabTuple* tuple)
|
||||
{
|
||||
|
||||
tuple->mPadding = image_overlay_width;
|
||||
if (!mIsVertical)
|
||||
{
|
||||
const LLFontGL* fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL );
|
||||
S32 image_overlay_width = 0;
|
||||
image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
|
||||
tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : 0;
|
||||
// remove current width from total tab strip width
|
||||
mTotalTabWidth -= tuple->mButton->getRect().getWidth();
|
||||
|
||||
tuple->mButton->setRightHPad(6);
|
||||
tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
|
||||
|
||||
|
||||
tuple->mPadding = image_overlay_width;
|
||||
|
||||
tuple->mButton->setRightHPad(6);
|
||||
tuple->mButton->reshape(llclamp(fontp->getWidth(tuple->mButton->getLabelSelected()) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
|
||||
tuple->mButton->getRect().getHeight());
|
||||
// add back in button width to total tab strip width
|
||||
mTotalTabWidth += tuple->mButton->getRect().getWidth();
|
||||
// add back in button width to total tab strip width
|
||||
mTotalTabWidth += tuple->mButton->getRect().getWidth();
|
||||
|
||||
// tabs have changed size, might need to scroll to see current tab
|
||||
updateMaxScrollPos();
|
||||
}
|
||||
// tabs have changed size, might need to scroll to see current tab
|
||||
updateMaxScrollPos();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1368,33 +1440,6 @@ S32 LLTabContainer::getTopBorderHeight() const
|
||||
return mTopBorderHeight;
|
||||
}
|
||||
|
||||
void LLTabContainer::setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*, bool))
|
||||
{
|
||||
LLTabTuple* tuplep = getTabByPanel(tab);
|
||||
if (tuplep)
|
||||
{
|
||||
tuplep->mOnChangeCallback = on_tab_clicked;
|
||||
}
|
||||
}
|
||||
|
||||
void LLTabContainer::setTabPrecommitChangeCallback(LLPanel* tab, void (*on_precommit)(void*, bool))
|
||||
{
|
||||
LLTabTuple* tuplep = getTabByPanel(tab);
|
||||
if (tuplep)
|
||||
{
|
||||
tuplep->mPrecommitChangeCallback = on_precommit;
|
||||
}
|
||||
}
|
||||
|
||||
void LLTabContainer::setTabUserData(LLPanel* tab, void* userdata)
|
||||
{
|
||||
LLTabTuple* tuplep = getTabByPanel(tab);
|
||||
if (tuplep)
|
||||
{
|
||||
tuplep->mUserData = userdata;
|
||||
}
|
||||
}
|
||||
|
||||
void LLTabContainer::setRightTabBtnOffset(S32 offset)
|
||||
{
|
||||
mNextArrowBtn->translate( -offset - mRightTabBtnOffset, 0 );
|
||||
@@ -1408,7 +1453,7 @@ void LLTabContainer::setPanelTitle(S32 index, const std::string& title)
|
||||
{
|
||||
LLTabTuple* tuple = getTab(index);
|
||||
LLButton* tab_button = tuple->mButton;
|
||||
const LLFontGL* fontp = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL );
|
||||
const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall();
|
||||
mTotalTabWidth -= tab_button->getRect().getWidth();
|
||||
tab_button->reshape(llclamp(fontp->getWidth(title) + TAB_PADDING + tuple->mPadding, mMinTabWidth, mMaxTabWidth), tab_button->getRect().getHeight());
|
||||
mTotalTabWidth += tab_button->getRect().getWidth();
|
||||
@@ -1419,84 +1464,62 @@ void LLTabContainer::setPanelTitle(S32 index, const std::string& title)
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void LLTabContainer::onTabBtn( void* userdata )
|
||||
void LLTabContainer::onTabBtn( const LLSD& data, LLPanel* panel )
|
||||
{
|
||||
LLTabTuple* tuple = (LLTabTuple*) userdata;
|
||||
LLTabContainer* self = tuple->mTabContainer;
|
||||
self->selectTabPanel( tuple->mTabPanel );
|
||||
LLTabTuple* tuple = getTabByPanel(panel);
|
||||
selectTabPanel( panel );
|
||||
|
||||
tuple->mTabPanel->setFocus(TRUE);
|
||||
}
|
||||
|
||||
// static
|
||||
void LLTabContainer::onCloseBtn( void* userdata )
|
||||
{
|
||||
LLTabContainer* self = (LLTabContainer*) userdata;
|
||||
if( self->mCloseCallback )
|
||||
if (tuple)
|
||||
{
|
||||
self->mCloseCallback( self->mCallbackUserdata );
|
||||
tuple->mTabPanel->setFocus(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLTabContainer::onNextBtn( void* userdata )
|
||||
void LLTabContainer::onNextBtn( const LLSD& data )
|
||||
{
|
||||
// Scroll tabs to the left
|
||||
LLTabContainer* self = (LLTabContainer*) userdata;
|
||||
if (!self->mScrolled)
|
||||
if (!mScrolled)
|
||||
{
|
||||
self->scrollNext();
|
||||
scrollNext();
|
||||
}
|
||||
self->mScrolled = FALSE;
|
||||
mScrolled = FALSE;
|
||||
}
|
||||
|
||||
// static
|
||||
void LLTabContainer::onNextBtnHeld( void* userdata )
|
||||
void LLTabContainer::onNextBtnHeld( const LLSD& data )
|
||||
{
|
||||
LLTabContainer* self = (LLTabContainer*) userdata;
|
||||
if (self->mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
|
||||
if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
|
||||
{
|
||||
self->mScrollTimer.reset();
|
||||
self->scrollNext();
|
||||
self->mScrolled = TRUE;
|
||||
mScrollTimer.reset();
|
||||
scrollNext();
|
||||
mScrolled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLTabContainer::onPrevBtn( void* userdata )
|
||||
void LLTabContainer::onPrevBtn( const LLSD& data )
|
||||
{
|
||||
LLTabContainer* self = (LLTabContainer*) userdata;
|
||||
if (!self->mScrolled)
|
||||
if (!mScrolled)
|
||||
{
|
||||
self->scrollPrev();
|
||||
scrollPrev();
|
||||
}
|
||||
self->mScrolled = FALSE;
|
||||
mScrolled = FALSE;
|
||||
}
|
||||
|
||||
// static
|
||||
void LLTabContainer::onJumpFirstBtn( void* userdata )
|
||||
void LLTabContainer::onJumpFirstBtn( const LLSD& data )
|
||||
{
|
||||
LLTabContainer* self = (LLTabContainer*) userdata;
|
||||
self->mScrollPos = 0;
|
||||
mScrollPos = 0;
|
||||
}
|
||||
|
||||
// static
|
||||
void LLTabContainer::onJumpLastBtn( void* userdata )
|
||||
void LLTabContainer::onJumpLastBtn( const LLSD& data )
|
||||
{
|
||||
LLTabContainer* self = (LLTabContainer*) userdata;
|
||||
self->mScrollPos = self->mMaxScrollPos;
|
||||
mScrollPos = mMaxScrollPos;
|
||||
}
|
||||
|
||||
// static
|
||||
void LLTabContainer::onPrevBtnHeld( void* userdata )
|
||||
void LLTabContainer::onPrevBtnHeld( const LLSD& data )
|
||||
{
|
||||
LLTabContainer* self = (LLTabContainer*) userdata;
|
||||
if (self->mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
|
||||
if (mScrollTimer.getElapsedTimeF32() > SCROLL_STEP_TIME)
|
||||
{
|
||||
self->mScrollTimer.reset();
|
||||
self->scrollPrev();
|
||||
self->mScrolled = TRUE;
|
||||
mScrollTimer.reset();
|
||||
scrollPrev();
|
||||
mScrolled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1583,8 +1606,7 @@ LLView* LLTabContainer::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
|
||||
}
|
||||
BOOL placeholder = FALSE;
|
||||
child->getAttributeBOOL("placeholder", placeholder);
|
||||
tab_container->addTabPanel(panelp, label, false,
|
||||
NULL, NULL, 0, placeholder);
|
||||
tab_container->addTabPanel(panelp, label, false, 0, placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1614,7 +1636,7 @@ void LLTabContainer::initButtons()
|
||||
{
|
||||
// Left and right scroll arrows (for when there are too many tabs to show all at once).
|
||||
S32 btn_top = getRect().getHeight();
|
||||
S32 btn_top_lower = getRect().mBottom+TABCNTRV_ARROW_BTN_SIZE;
|
||||
S32 btn_top_lower = TABCNTRV_ARROW_BTN_SIZE;
|
||||
|
||||
LLRect up_arrow_btn_rect;
|
||||
up_arrow_btn_rect.setLeftTopAndSize( mMinTabWidth/2 , btn_top, TABCNTRV_ARROW_BTN_SIZE, TABCNTRV_ARROW_BTN_SIZE );
|
||||
@@ -1625,18 +1647,20 @@ void LLTabContainer::initButtons()
|
||||
out_id = "UIImgBtnScrollUpOutUUID";
|
||||
in_id = "UIImgBtnScrollUpInUUID";
|
||||
mPrevArrowBtn = new LLButton(std::string("Up Arrow"), up_arrow_btn_rect,
|
||||
out_id, in_id, LLStringUtil::null,
|
||||
&onPrevBtn, this, NULL );
|
||||
out_id, in_id, LLStringUtil::null, NULL );
|
||||
mPrevArrowBtn->setFollowsTop();
|
||||
mPrevArrowBtn->setFollowsLeft();
|
||||
|
||||
mPrevArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onPrevBtn,this,_2));
|
||||
mPrevArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onPrevBtnHeld, this, _2));
|
||||
|
||||
out_id = "UIImgBtnScrollDownOutUUID";
|
||||
in_id = "UIImgBtnScrollDownInUUID";
|
||||
mNextArrowBtn = new LLButton(std::string("Down Arrow"), down_arrow_btn_rect,
|
||||
out_id, in_id, LLStringUtil::null,
|
||||
&onNextBtn, this, NULL );
|
||||
out_id, in_id, LLStringUtil::null, NULL );
|
||||
mNextArrowBtn->setFollowsBottom();
|
||||
mNextArrowBtn->setFollowsLeft();
|
||||
mNextArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onNextBtn,this,_2));
|
||||
mNextArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onNextBtnHeld, this, _2));
|
||||
}
|
||||
else // Horizontal
|
||||
{
|
||||
@@ -1674,31 +1698,35 @@ void LLTabContainer::initButtons()
|
||||
in_id = "UIImgBtnJumpLeftInUUID";
|
||||
mJumpPrevArrowBtn = new LLButton(std::string("Jump Left Arrow"), jump_left_arrow_btn_rect,
|
||||
out_id, in_id, LLStringUtil::null,
|
||||
&LLTabContainer::onJumpFirstBtn, this, LLFontGL::getFontSansSerif() );
|
||||
NULL, NULL, LLFontGL::getFontSansSerif() );
|
||||
mJumpPrevArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onJumpFirstBtn, this, _2));
|
||||
mJumpPrevArrowBtn->setFollowsLeft();
|
||||
|
||||
out_id = "UIImgBtnScrollLeftOutUUID";
|
||||
in_id = "UIImgBtnScrollLeftInUUID";
|
||||
mPrevArrowBtn = new LLButton(std::string("Left Arrow"), left_arrow_btn_rect,
|
||||
out_id, in_id, LLStringUtil::null,
|
||||
&LLTabContainer::onPrevBtn, this, LLFontGL::getFontSansSerif() );
|
||||
mPrevArrowBtn->setHeldDownCallback(boost::bind(LLTabContainer::onPrevBtnHeld, this));
|
||||
NULL, NULL, LLFontGL::getFontSansSerif() );
|
||||
|
||||
mPrevArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onPrevBtn, this, _2));
|
||||
mPrevArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onPrevBtnHeld, this, _2));
|
||||
mPrevArrowBtn->setFollowsLeft();
|
||||
|
||||
out_id = "UIImgBtnJumpRightOutUUID";
|
||||
in_id = "UIImgBtnJumpRightInUUID";
|
||||
mJumpNextArrowBtn = new LLButton(std::string("Jump Right Arrow"), jump_right_arrow_btn_rect,
|
||||
out_id, in_id, LLStringUtil::null,
|
||||
&LLTabContainer::onJumpLastBtn, this,
|
||||
LLFontGL::getFontSansSerif());
|
||||
NULL, NULL, LLFontGL::getFontSansSerif());
|
||||
mJumpNextArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onJumpLastBtn, this, _2));
|
||||
mJumpNextArrowBtn->setFollowsRight();
|
||||
|
||||
out_id = "UIImgBtnScrollRightOutUUID";
|
||||
in_id = "UIImgBtnScrollRightInUUID";
|
||||
mNextArrowBtn = new LLButton(std::string("Right Arrow"), right_arrow_btn_rect,
|
||||
out_id, in_id, LLStringUtil::null,
|
||||
&LLTabContainer::onNextBtn, this,
|
||||
LLFontGL::getFontSansSerif());
|
||||
NULL, NULL, LLFontGL::getFontSansSerif());
|
||||
mNextArrowBtn->setCommitCallback(boost::bind(&LLTabContainer::onNextBtn, this, _2));
|
||||
mNextArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onNextBtnHeld, this, _2));
|
||||
mNextArrowBtn->setFollowsRight();
|
||||
|
||||
if( getTabPosition() == TOP )
|
||||
@@ -1717,12 +1745,10 @@ void LLTabContainer::initButtons()
|
||||
}
|
||||
}
|
||||
|
||||
mPrevArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onPrevBtnHeld, this));
|
||||
mPrevArrowBtn->setSaveToXML(false);
|
||||
mPrevArrowBtn->setTabStop(FALSE);
|
||||
addChild(mPrevArrowBtn);
|
||||
|
||||
mNextArrowBtn->setHeldDownCallback(boost::bind(&LLTabContainer::onNextBtnHeld, this));
|
||||
|
||||
mNextArrowBtn->setSaveToXML(false);
|
||||
mNextArrowBtn->setTabStop(FALSE);
|
||||
addChild(mNextArrowBtn);
|
||||
@@ -1745,7 +1771,7 @@ void LLTabContainer::initButtons()
|
||||
setDefaultTabGroup(1);
|
||||
}
|
||||
|
||||
LLTabContainer::LLTabTuple* LLTabContainer::getTabByPanel(LLPanel* child)
|
||||
LLTabTuple* LLTabContainer::getTabByPanel(LLPanel* child)
|
||||
{
|
||||
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
|
||||
{
|
||||
@@ -1794,11 +1820,11 @@ void LLTabContainer::updateMaxScrollPos()
|
||||
BOOL no_scroll = TRUE;
|
||||
if (mIsVertical)
|
||||
{
|
||||
S32 tab_total_height = (BTN_HEIGHT + TABCNTRV_PAD) * getTabCount();
|
||||
S32 available_height = getRect().getHeight() - getTopBorderHeight();
|
||||
S32 tab_total_height = (BTN_HEIGHT + TABCNTRV_PAD) * getTabCount() + TABCNTRV_PAD;
|
||||
S32 available_height = getRect().getHeight() - getTopBorderHeight() - 2 * LLPANEL_BORDER_WIDTH;
|
||||
if( tab_total_height > available_height )
|
||||
{
|
||||
S32 available_height_with_arrows = getRect().getHeight() - 2*(TABCNTRV_ARROW_BTN_SIZE + 3*TABCNTRV_PAD);
|
||||
S32 available_height_with_arrows = getRect().getHeight() - getTopBorderHeight() - (LLPANEL_BORDER_WIDTH + TABCNTR_ARROW_BTN_SIZE + TABCNTR_ARROW_BTN_SIZE + 1);
|
||||
S32 additional_needed = tab_total_height - available_height_with_arrows;
|
||||
setMaxScrollPos((S32) ceil(additional_needed / float(BTN_HEIGHT) ) );
|
||||
no_scroll = FALSE;
|
||||
@@ -1846,12 +1872,12 @@ void LLTabContainer::updateMaxScrollPos()
|
||||
|
||||
void LLTabContainer::commitHoveredButton(S32 x, S32 y)
|
||||
{
|
||||
if (hasMouseCapture())
|
||||
if (!getTabsHidden() && hasMouseCapture())
|
||||
{
|
||||
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
|
||||
{
|
||||
LLTabTuple* tuple = *iter;
|
||||
tuple->mButton->setVisible( TRUE );
|
||||
//tuple->mButton->setVisible( TRUE );
|
||||
S32 local_x = x - tuple->mButton->getRect().mLeft;
|
||||
S32 local_y = y - tuple->mButton->getRect().mBottom;
|
||||
if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible())
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "llpanel.h"
|
||||
#include "lltextbox.h"
|
||||
#include "llframetimer.h"
|
||||
class LLTabTuple;
|
||||
|
||||
extern const S32 TABCNTR_HEADER_HEIGHT;
|
||||
|
||||
@@ -79,9 +80,7 @@ public:
|
||||
|
||||
void addTabPanel(LLPanel* child,
|
||||
const std::string& label,
|
||||
BOOL select = FALSE,
|
||||
void (*on_tab_clicked)(void*, bool) = NULL,
|
||||
void* userdata = NULL,
|
||||
BOOL select = FALSE,
|
||||
S32 indent = 0,
|
||||
BOOL placeholder = FALSE,
|
||||
eInsertionPoint insertion_point = END);
|
||||
@@ -108,20 +107,16 @@ public:
|
||||
BOOL selectTabPanel( LLPanel* child );
|
||||
BOOL selectTab(S32 which);
|
||||
BOOL selectTabByName(const std::string& title);
|
||||
BOOL setTab(S32 which);
|
||||
|
||||
BOOL getTabPanelFlashing(LLPanel* child);
|
||||
void setTabPanelFlashing(LLPanel* child, BOOL state);
|
||||
void setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white);
|
||||
void setTabImage(LLPanel* child, const LLUUID& img_id, const LLColor4& color = LLColor4::white);
|
||||
void setTitle( const std::string& title );
|
||||
const std::string getPanelTitle(S32 index);
|
||||
|
||||
void setTopBorderHeight(S32 height);
|
||||
S32 getTopBorderHeight() const;
|
||||
|
||||
void setTabChangeCallback(LLPanel* tab, void (*on_tab_clicked)(void*,bool));
|
||||
void setTabPrecommitChangeCallback(LLPanel* tab, void (*on_precommit)(void*, bool));
|
||||
void setTabUserData(LLPanel* tab, void* userdata);
|
||||
|
||||
void setRightTabBtnOffset( S32 offset );
|
||||
void setPanelTitle(S32 index, const std::string& title);
|
||||
@@ -134,51 +129,22 @@ public:
|
||||
|
||||
void startDragAndDropDelayTimer() { mDragAndDropDelayTimer.start(); }
|
||||
|
||||
static void onCloseBtn(void* userdata);
|
||||
static void onTabBtn(void* userdata);
|
||||
static void onNextBtn(void* userdata);
|
||||
static void onNextBtnHeld(void* userdata);
|
||||
static void onPrevBtn(void* userdata);
|
||||
static void onPrevBtnHeld(void* userdata);
|
||||
static void onJumpFirstBtn( void* userdata );
|
||||
static void onJumpLastBtn( void* userdata );
|
||||
void onTabBtn( const LLSD& data, LLPanel* panel );
|
||||
void onNextBtn(const LLSD& data);
|
||||
void onNextBtnHeld(const LLSD& data);
|
||||
void onPrevBtn(const LLSD& data);
|
||||
void onPrevBtnHeld(const LLSD& data);
|
||||
void onJumpFirstBtn( const LLSD& data );
|
||||
void onJumpLastBtn( const LLSD& data );
|
||||
|
||||
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
|
||||
|
||||
private:
|
||||
// Structure used to map tab buttons to and from tab panels
|
||||
struct LLTabTuple
|
||||
{
|
||||
LLTabTuple( LLTabContainer* c, LLPanel* p, LLButton* b,
|
||||
void (*cb)(void*,bool), void* userdata, LLTextBox* placeholder = NULL,
|
||||
void (*pcb)(void*,bool) = NULL)
|
||||
:
|
||||
mTabContainer(c),
|
||||
mTabPanel(p),
|
||||
mButton(b),
|
||||
mOnChangeCallback( cb ),
|
||||
mPrecommitChangeCallback( pcb ),
|
||||
mUserData( userdata ),
|
||||
mOldState(FALSE),
|
||||
mPlaceholderText(placeholder),
|
||||
mPadding(0)
|
||||
{}
|
||||
|
||||
LLTabContainer* mTabContainer;
|
||||
LLPanel* mTabPanel;
|
||||
LLButton* mButton;
|
||||
void (*mOnChangeCallback)(void*, bool);
|
||||
void (*mPrecommitChangeCallback)(void*,bool); // Precommit callback gets called before tab is changed and
|
||||
// can prevent it from being changed. onChangeCallback is called
|
||||
// immediately after tab is actually changed - Nyx
|
||||
void* mUserData;
|
||||
BOOL mOldState;
|
||||
LLTextBox* mPlaceholderText;
|
||||
S32 mPadding;
|
||||
};
|
||||
|
||||
void initButtons();
|
||||
|
||||
BOOL setTab(S32 which);
|
||||
|
||||
LLTabTuple* getTab(S32 index) { return mTabList[index]; }
|
||||
LLTabTuple* getTabByPanel(LLPanel* child);
|
||||
void insertTuple(LLTabTuple * tuple, eInsertionPoint insertion_point);
|
||||
@@ -201,13 +167,13 @@ private:
|
||||
void updateMaxScrollPos();
|
||||
void commitHoveredButton(S32 x, S32 y);
|
||||
|
||||
void reshapeTuple(LLTabTuple* tuple);
|
||||
// Variables
|
||||
|
||||
typedef std::vector<LLTabTuple*> tuple_list_t;
|
||||
tuple_list_t mTabList;
|
||||
|
||||
S32 mCurrentTabIdx;
|
||||
S32 mNextTabIdx;
|
||||
BOOL mTabsHidden;
|
||||
|
||||
BOOL mScrolled;
|
||||
@@ -216,9 +182,6 @@ private:
|
||||
S32 mScrollPosPixels;
|
||||
S32 mMaxScrollPos;
|
||||
|
||||
void (*mCloseCallback)(void*);
|
||||
void* mCallbackUserdata;
|
||||
|
||||
LLTextBox* mTitleBox;
|
||||
|
||||
S32 mTopBorderHeight;
|
||||
|
||||
@@ -228,7 +228,7 @@ bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNo
|
||||
|
||||
bool LLUICtrlFactory::getLayeredXMLNodeFromBuffer(const std::string &buffer, LLXMLNodePtr& root)
|
||||
{
|
||||
if (!LLXMLNode::parseBuffer(buffer.data(), buffer.size(), root, 0)) {
|
||||
if (!LLXMLNode::parseBuffer((U8*)buffer.data(), buffer.size(), root, 0)) {
|
||||
llwarns << "Error reading UI description from buffer." << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ LLXMLNode::LLXMLNode() :
|
||||
mPrecision(64),
|
||||
mType(TYPE_CONTAINER),
|
||||
mEncoding(ENCODING_DEFAULT),
|
||||
mLineNumber(-1),
|
||||
mParent(NULL),
|
||||
mChildren(NULL),
|
||||
mAttributes(),
|
||||
@@ -85,6 +86,7 @@ LLXMLNode::LLXMLNode(const char* name, BOOL is_attribute) :
|
||||
mPrecision(64),
|
||||
mType(TYPE_CONTAINER),
|
||||
mEncoding(ENCODING_DEFAULT),
|
||||
mLineNumber(-1),
|
||||
mParent(NULL),
|
||||
mChildren(NULL),
|
||||
mAttributes(),
|
||||
@@ -106,6 +108,7 @@ LLXMLNode::LLXMLNode(LLStringTableEntry* name, BOOL is_attribute) :
|
||||
mPrecision(64),
|
||||
mType(TYPE_CONTAINER),
|
||||
mEncoding(ENCODING_DEFAULT),
|
||||
mLineNumber(-1),
|
||||
mParent(NULL),
|
||||
mChildren(NULL),
|
||||
mAttributes(),
|
||||
@@ -127,6 +130,8 @@ LLXMLNode::LLXMLNode(const LLXMLNode& rhs) :
|
||||
mPrecision(rhs.mPrecision),
|
||||
mType(rhs.mType),
|
||||
mEncoding(rhs.mEncoding),
|
||||
mLineNumber(0),
|
||||
mParser(NULL),
|
||||
mParent(NULL),
|
||||
mChildren(NULL),
|
||||
mAttributes(),
|
||||
@@ -226,6 +231,10 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child)
|
||||
{
|
||||
mChildren->head = target_child->mNext;
|
||||
}
|
||||
if (target_child == mChildren->tail)
|
||||
{
|
||||
mChildren->tail = target_child->mPrev;
|
||||
}
|
||||
|
||||
LLXMLNodePtr prev = target_child->mPrev;
|
||||
LLXMLNodePtr next = target_child->mNext;
|
||||
@@ -294,6 +303,22 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child)
|
||||
mChildren->tail = new_child;
|
||||
}
|
||||
}
|
||||
// if after_child == parent, then put new_child at beginning
|
||||
else if (after_child == this)
|
||||
{
|
||||
// add to front of list
|
||||
new_child->mNext = mChildren->head;
|
||||
if (mChildren->head)
|
||||
{
|
||||
mChildren->head->mPrev = new_child;
|
||||
mChildren->head = new_child;
|
||||
}
|
||||
else // no children
|
||||
{
|
||||
mChildren->head = new_child;
|
||||
mChildren->tail = new_child;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (after_child->mNext.notNull())
|
||||
@@ -401,7 +426,8 @@ void XMLCALL StartXMLNode(void *userData,
|
||||
}
|
||||
|
||||
new_node_ptr->mParser = parent->mParser;
|
||||
|
||||
new_node_ptr->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser));
|
||||
|
||||
// Set the current active node to the new node
|
||||
XML_Parser *parser = parent->mParser;
|
||||
XML_SetUserData(*parser, (void *)new_node_ptr);
|
||||
@@ -492,6 +518,7 @@ void XMLCALL StartXMLNode(void *userData,
|
||||
if (!new_node->getAttribute(attr_name.c_str(), attr_node, FALSE))
|
||||
{
|
||||
attr_node = new LLXMLNode(attr_name.c_str(), TRUE);
|
||||
attr_node->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser));
|
||||
}
|
||||
attr_node->setValue(attr_value);
|
||||
new_node->addChild(attr_node);
|
||||
@@ -608,13 +635,14 @@ bool LLXMLNode::updateNode(
|
||||
}
|
||||
|
||||
//update all of node's children with updateNodes children that match name
|
||||
LLXMLNodePtr child;
|
||||
LLXMLNodePtr child = node->getFirstChild();
|
||||
LLXMLNodePtr last_child = child;
|
||||
LLXMLNodePtr updateChild;
|
||||
|
||||
for (updateChild = update_node->getFirstChild(); updateChild.notNull();
|
||||
updateChild = updateChild->getNextSibling())
|
||||
{
|
||||
for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
|
||||
while(child.notNull())
|
||||
{
|
||||
std::string nodeName;
|
||||
std::string updateName;
|
||||
@@ -633,6 +661,22 @@ bool LLXMLNode::updateNode(
|
||||
if ((nodeName != "") && (updateName == nodeName))
|
||||
{
|
||||
updateNode(child, updateChild);
|
||||
last_child = child;
|
||||
child = child->getNextSibling();
|
||||
if (child.isNull())
|
||||
{
|
||||
child = node->getFirstChild();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
child = child->getNextSibling();
|
||||
if (child.isNull())
|
||||
{
|
||||
child = node->getFirstChild();
|
||||
}
|
||||
if (child == last_child)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -670,14 +714,14 @@ bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXML
|
||||
LLFILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
|
||||
if (fp == NULL)
|
||||
{
|
||||
node = new LLXMLNode();
|
||||
node = NULL ;
|
||||
return false;
|
||||
}
|
||||
fseek(fp, 0, SEEK_END);
|
||||
U32 length = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
char *buffer = new char[length+1];
|
||||
U8* buffer = new U8[length+1];
|
||||
size_t nread = fread(buffer, 1, length, fp);
|
||||
buffer[nread] = 0;
|
||||
fclose(fp);
|
||||
@@ -689,7 +733,7 @@ bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXML
|
||||
|
||||
// static
|
||||
bool LLXMLNode::parseBuffer(
|
||||
const char *buffer,
|
||||
U8* buffer,
|
||||
U32 length,
|
||||
LLXMLNodePtr& node,
|
||||
LLXMLNode* defaults)
|
||||
@@ -708,7 +752,7 @@ bool LLXMLNode::parseBuffer(
|
||||
XML_SetUserData(my_parser, (void *)file_node_ptr);
|
||||
|
||||
// Do the parsing
|
||||
if (XML_Parse(my_parser, buffer, length, TRUE) != XML_STATUS_OK)
|
||||
if (XML_Parse(my_parser, (const char *)buffer, length, TRUE) != XML_STATUS_OK)
|
||||
{
|
||||
llwarns << "Error parsing xml error code: "
|
||||
<< XML_ErrorString(XML_GetErrorCode(my_parser))
|
||||
@@ -723,7 +767,7 @@ bool LLXMLNode::parseBuffer(
|
||||
{
|
||||
llwarns << "Parse failure - wrong number of top-level nodes xml."
|
||||
<< llendl;
|
||||
node = new LLXMLNode();
|
||||
node = NULL ;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -761,7 +805,7 @@ bool LLXMLNode::parseStream(
|
||||
while(str.good())
|
||||
{
|
||||
str.read((char*)buffer, BUFSIZE);
|
||||
int count = str.gcount();
|
||||
int count = (int)str.gcount();
|
||||
|
||||
if (XML_Parse(my_parser, (const char *)buffer, count, !str.good()) != XML_STATUS_OK)
|
||||
{
|
||||
@@ -782,7 +826,7 @@ bool LLXMLNode::parseStream(
|
||||
{
|
||||
llwarns << "Parse failure - wrong number of top-level nodes xml."
|
||||
<< llendl;
|
||||
node = new LLXMLNode();
|
||||
node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -836,12 +880,64 @@ BOOL LLXMLNode::isFullyDefault()
|
||||
}
|
||||
|
||||
// static
|
||||
void LLXMLNode::writeHeaderToFile(LLFILE *fOut)
|
||||
bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root,
|
||||
const std::vector<std::string>& paths)
|
||||
{
|
||||
fprintf(fOut, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n");
|
||||
if (paths.empty()) return false;
|
||||
|
||||
std::string filename = paths.front();
|
||||
if (filename.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!LLXMLNode::parseFile(filename, root, NULL))
|
||||
{
|
||||
llwarns << "Problem reading UI description file: " << filename << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
LLXMLNodePtr updateRoot;
|
||||
|
||||
std::vector<std::string>::const_iterator itor;
|
||||
|
||||
for (itor = paths.begin(), ++itor; itor != paths.end(); ++itor)
|
||||
{
|
||||
std::string layer_filename = *itor;
|
||||
if(layer_filename.empty() || layer_filename == filename)
|
||||
{
|
||||
// no localized version of this file, that's ok, keep looking
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!LLXMLNode::parseFile(layer_filename, updateRoot, NULL))
|
||||
{
|
||||
llwarns << "Problem reading localized UI description file: " << layer_filename << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string nodeName;
|
||||
std::string updateName;
|
||||
|
||||
updateRoot->getAttributeString("name", updateName);
|
||||
root->getAttributeString("name", nodeName);
|
||||
|
||||
if (updateName == nodeName)
|
||||
{
|
||||
LLXMLNode::updateNode(root, updateRoot);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLXMLNode::writeToFile(LLFILE *fOut, const std::string& indent)
|
||||
// static
|
||||
void LLXMLNode::writeHeaderToFile(LLFILE *out_file)
|
||||
{
|
||||
fprintf(out_file, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n");
|
||||
}
|
||||
|
||||
void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent, bool use_type_decorations)
|
||||
{
|
||||
if (isFullyDefault())
|
||||
{
|
||||
@@ -850,15 +946,16 @@ void LLXMLNode::writeToFile(LLFILE *fOut, const std::string& indent)
|
||||
}
|
||||
|
||||
std::ostringstream ostream;
|
||||
writeToOstream(ostream, indent);
|
||||
writeToOstream(ostream, indent, use_type_decorations);
|
||||
std::string outstring = ostream.str();
|
||||
if (fwrite(outstring.c_str(), 1, outstring.length(), fOut) != outstring.length())
|
||||
size_t written = fwrite(outstring.c_str(), 1, outstring.length(), out_file);
|
||||
if (written != outstring.length())
|
||||
{
|
||||
llwarns << "Short write" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent)
|
||||
void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& indent, bool use_type_decorations)
|
||||
{
|
||||
if (isFullyDefault())
|
||||
{
|
||||
@@ -872,84 +969,86 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
|
||||
BOOL has_default_length = mDefault.isNull()?FALSE:(mLength == mDefault->mLength);
|
||||
|
||||
// stream the name
|
||||
output_stream << indent << "<" << mName->mString;
|
||||
output_stream << indent << "<" << mName->mString << "\n";
|
||||
|
||||
// ID
|
||||
if (mID != "")
|
||||
if (use_type_decorations)
|
||||
{
|
||||
output_stream << " id=\"" << mID << "\"";
|
||||
}
|
||||
|
||||
// Type
|
||||
if (!has_default_type)
|
||||
{
|
||||
switch (mType)
|
||||
// ID
|
||||
if (mID != "")
|
||||
{
|
||||
case TYPE_BOOLEAN:
|
||||
output_stream << " type=\"boolean\"";
|
||||
break;
|
||||
case TYPE_INTEGER:
|
||||
output_stream << " type=\"integer\"";
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
output_stream << " type=\"float\"";
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
output_stream << " type=\"string\"";
|
||||
break;
|
||||
case TYPE_UUID:
|
||||
output_stream << " type=\"uuid\"";
|
||||
break;
|
||||
case TYPE_NODEREF:
|
||||
output_stream << " type=\"noderef\"";
|
||||
break;
|
||||
default:
|
||||
// default on switch(enum) eliminates a warning on linux
|
||||
break;
|
||||
};
|
||||
}
|
||||
output_stream << indent << " id=\"" << mID << "\"\n";
|
||||
}
|
||||
|
||||
// Encoding
|
||||
if (!has_default_encoding)
|
||||
{
|
||||
switch (mEncoding)
|
||||
// Type
|
||||
if (!has_default_type)
|
||||
{
|
||||
case ENCODING_DECIMAL:
|
||||
output_stream << " encoding=\"decimal\"";
|
||||
break;
|
||||
case ENCODING_HEX:
|
||||
output_stream << " encoding=\"hex\"";
|
||||
break;
|
||||
/*case ENCODING_BASE32:
|
||||
output_stream << " encoding=\"base32\"";
|
||||
break;*/
|
||||
default:
|
||||
// default on switch(enum) eliminates a warning on linux
|
||||
break;
|
||||
};
|
||||
}
|
||||
switch (mType)
|
||||
{
|
||||
case TYPE_BOOLEAN:
|
||||
output_stream << indent << " type=\"boolean\"\n";
|
||||
break;
|
||||
case TYPE_INTEGER:
|
||||
output_stream << indent << " type=\"integer\"\n";
|
||||
break;
|
||||
case TYPE_FLOAT:
|
||||
output_stream << indent << " type=\"float\"\n";
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
output_stream << indent << " type=\"string\"\n";
|
||||
break;
|
||||
case TYPE_UUID:
|
||||
output_stream << indent << " type=\"uuid\"\n";
|
||||
break;
|
||||
case TYPE_NODEREF:
|
||||
output_stream << indent << " type=\"noderef\"\n";
|
||||
break;
|
||||
default:
|
||||
// default on switch(enum) eliminates a warning on linux
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
// Precision
|
||||
if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT))
|
||||
{
|
||||
output_stream << " precision=\"" << mPrecision << "\"";
|
||||
}
|
||||
// Encoding
|
||||
if (!has_default_encoding)
|
||||
{
|
||||
switch (mEncoding)
|
||||
{
|
||||
case ENCODING_DECIMAL:
|
||||
output_stream << indent << " encoding=\"decimal\"\n";
|
||||
break;
|
||||
case ENCODING_HEX:
|
||||
output_stream << indent << " encoding=\"hex\"\n";
|
||||
break;
|
||||
/*case ENCODING_BASE32:
|
||||
output_stream << indent << " encoding=\"base32\"\n";
|
||||
break;*/
|
||||
default:
|
||||
// default on switch(enum) eliminates a warning on linux
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
// Version
|
||||
if (mVersionMajor > 0 || mVersionMinor > 0)
|
||||
{
|
||||
output_stream << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"";
|
||||
}
|
||||
// Precision
|
||||
if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT))
|
||||
{
|
||||
output_stream << indent << " precision=\"" << mPrecision << "\"\n";
|
||||
}
|
||||
|
||||
// Array length
|
||||
if (!has_default_length && mLength > 0)
|
||||
{
|
||||
output_stream << " length=\"" << mLength << "\"";
|
||||
// Version
|
||||
if (mVersionMajor > 0 || mVersionMinor > 0)
|
||||
{
|
||||
output_stream << indent << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"\n";
|
||||
}
|
||||
|
||||
// Array length
|
||||
if (!has_default_length && mLength > 0)
|
||||
{
|
||||
output_stream << indent << " length=\"" << mLength << "\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Write out attributes
|
||||
S32 col_pos = 0;
|
||||
LLXMLAttribList::const_iterator attr_itr;
|
||||
LLXMLAttribList::const_iterator attr_end = mAttributes.end();
|
||||
for (attr_itr = mAttributes.begin(); attr_itr != attr_end; ++attr_itr)
|
||||
@@ -958,12 +1057,13 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
|
||||
if (child->mDefault.isNull() || child->mDefault->mValue != child->mValue)
|
||||
{
|
||||
std::string attr = child->mName->mString;
|
||||
if (attr == "id" ||
|
||||
attr == "type" ||
|
||||
attr == "encoding" ||
|
||||
attr == "precision" ||
|
||||
attr == "version" ||
|
||||
attr == "length")
|
||||
if (use_type_decorations
|
||||
&& (attr == "id" ||
|
||||
attr == "type" ||
|
||||
attr == "encoding" ||
|
||||
attr == "precision" ||
|
||||
attr == "version" ||
|
||||
attr == "length"))
|
||||
{
|
||||
continue; // skip built-in attributes
|
||||
}
|
||||
@@ -971,17 +1071,14 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
|
||||
std::string attr_str = llformat(" %s=\"%s\"",
|
||||
attr.c_str(),
|
||||
escapeXML(child->mValue).c_str());
|
||||
if (col_pos + (S32)attr_str.length() > MAX_COLUMN_WIDTH)
|
||||
{
|
||||
output_stream << "\n" << indent << " ";
|
||||
col_pos = 4;
|
||||
}
|
||||
col_pos += attr_str.length();
|
||||
output_stream << attr_str;
|
||||
output_stream << indent << attr_str << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// erase last \n before attaching final > or />
|
||||
output_stream.seekp(-1, std::ios::cur);
|
||||
|
||||
if (mChildren.isNull() && mValue == "")
|
||||
{
|
||||
output_stream << " />\n";
|
||||
@@ -993,16 +1090,16 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
|
||||
if (mChildren.notNull())
|
||||
{
|
||||
// stream non-attributes
|
||||
std::string next_indent = indent + "\t";
|
||||
std::string next_indent = indent + " ";
|
||||
for (LLXMLNode* child = getFirstChild(); child; child = child->getNextSibling())
|
||||
{
|
||||
child->writeToOstream(output_stream, next_indent);
|
||||
child->writeToOstream(output_stream, next_indent, use_type_decorations);
|
||||
}
|
||||
}
|
||||
if (!mValue.empty())
|
||||
{
|
||||
std::string contents = getTextContents();
|
||||
output_stream << indent << "\t" << escapeXML(contents) << "\n";
|
||||
output_stream << indent << " " << escapeXML(contents) << "\n";
|
||||
}
|
||||
output_stream << indent << "</" << mName->mString << ">\n";
|
||||
}
|
||||
@@ -1130,7 +1227,7 @@ bool LLXMLNode::getChild(const LLStringTableEntry* name, LLXMLNodePtr& node, BOO
|
||||
{
|
||||
return mDefault->getChild(name, node, FALSE);
|
||||
}
|
||||
node = new LLXMLNode();
|
||||
node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1201,7 +1298,7 @@ bool LLXMLNode::getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node,
|
||||
{
|
||||
return mDefault->getAttribute(name, node, FALSE);
|
||||
}
|
||||
node = new LLXMLNode();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2475,14 +2572,15 @@ std::string LLXMLNode::escapeXML(const std::string& xml)
|
||||
return out;
|
||||
}
|
||||
|
||||
void LLXMLNode::setStringValue(U32 length, const std::string *array)
|
||||
void LLXMLNode::setStringValue(U32 length, const std::string *strings)
|
||||
{
|
||||
if (length == 0) return;
|
||||
|
||||
std::string new_value;
|
||||
for (U32 pos=0; pos<length; ++pos)
|
||||
{
|
||||
new_value.append(escapeXML(array[pos]));
|
||||
// *NOTE: Do not escape strings here - do it on output
|
||||
new_value.append( strings[pos] );
|
||||
if (pos < length-1) new_value.append(" ");
|
||||
}
|
||||
|
||||
@@ -3150,6 +3248,19 @@ LLXMLNodePtr LLXMLNode::getNextSibling() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string LLXMLNode::getSanitizedValue() const
|
||||
{
|
||||
if (mIsAttribute)
|
||||
{
|
||||
return getValue() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return getTextContents();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string LLXMLNode::getTextContents() const
|
||||
{
|
||||
std::string msg;
|
||||
@@ -3215,3 +3326,13 @@ std::string LLXMLNode::getTextContents() const
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
void LLXMLNode::setLineNumber(S32 line_number)
|
||||
{
|
||||
mLineNumber = line_number;
|
||||
}
|
||||
|
||||
S32 LLXMLNode::getLineNumber()
|
||||
{
|
||||
return mLineNumber;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#define LL_LLXMLNODE_H
|
||||
|
||||
#ifndef XML_STATIC
|
||||
#define XML_STATIC 1
|
||||
#define XML_STATIC
|
||||
#endif
|
||||
#ifdef LL_STANDALONE
|
||||
#include <expat.h>
|
||||
@@ -44,10 +44,11 @@
|
||||
#include <map>
|
||||
|
||||
#include "indra_constants.h"
|
||||
#include "llmemory.h"
|
||||
#include "llthread.h"
|
||||
#include "llpointer.h"
|
||||
#include "llthread.h" // LLThreadSafeRefCount
|
||||
#include "llstring.h"
|
||||
#include "llstringtable.h"
|
||||
#include "llfile.h"
|
||||
|
||||
|
||||
class LLVector3;
|
||||
@@ -141,7 +142,7 @@ public:
|
||||
LLXMLNodePtr& node,
|
||||
LLXMLNode* defaults_tree);
|
||||
static bool parseBuffer(
|
||||
const char *buffer,
|
||||
U8* buffer,
|
||||
U32 length,
|
||||
LLXMLNodePtr& node,
|
||||
LLXMLNode* defaults);
|
||||
@@ -153,9 +154,18 @@ public:
|
||||
LLXMLNodePtr& node,
|
||||
LLXMLNodePtr& update_node);
|
||||
static LLXMLNodePtr replaceNode(LLXMLNodePtr node, LLXMLNodePtr replacement_node);
|
||||
static void writeHeaderToFile(LLFILE *fOut);
|
||||
void writeToFile(LLFILE *fOut, const std::string& indent = std::string());
|
||||
void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string());
|
||||
|
||||
static bool getLayeredXMLNode(LLXMLNodePtr& root, const std::vector<std::string>& paths);
|
||||
|
||||
|
||||
// Write standard XML file header:
|
||||
// <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
static void writeHeaderToFile(LLFILE *out_file);
|
||||
|
||||
// Write XML to file with one attribute per line.
|
||||
// XML escapes values as they are written.
|
||||
void writeToFile(LLFILE *out_file, const std::string& indent = std::string(), bool use_type_decorations=true);
|
||||
void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string(), bool use_type_decorations=true);
|
||||
|
||||
// Utility
|
||||
void findName(const std::string& name, LLXMLNodeList &results);
|
||||
@@ -207,6 +217,7 @@ public:
|
||||
U32 getLength() const { return mLength; }
|
||||
U32 getPrecision() const { return mPrecision; }
|
||||
const std::string& getValue() const { return mValue; }
|
||||
std::string getSanitizedValue() const;
|
||||
std::string getTextContents() const;
|
||||
const LLStringTableEntry* getName() const { return mName; }
|
||||
BOOL hasName(const char* name) const { return mName == gStringTable.checkStringEntry(name); }
|
||||
@@ -227,6 +238,8 @@ public:
|
||||
bool getAttribute(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE);
|
||||
bool getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE);
|
||||
|
||||
S32 getLineNumber();
|
||||
|
||||
// The following skip over attributes
|
||||
LLXMLNodePtr getFirstChild() const;
|
||||
LLXMLNodePtr getNextSibling() const;
|
||||
@@ -262,6 +275,8 @@ public:
|
||||
void setName(const std::string& name);
|
||||
void setName(LLStringTableEntry* name);
|
||||
|
||||
void setLineNumber(S32 line_number);
|
||||
|
||||
// Escapes " (quot) ' (apos) & (amp) < (lt) > (gt)
|
||||
static std::string escapeXML(const std::string& xml);
|
||||
|
||||
@@ -300,6 +315,7 @@ public:
|
||||
U32 mPrecision; // The number of BITS per array item
|
||||
ValueType mType; // The value type
|
||||
Encoding mEncoding; // The value encoding
|
||||
S32 mLineNumber; // line number in source file, if applicable
|
||||
|
||||
LLXMLNode* mParent; // The parent node
|
||||
LLXMLChildrenPtr mChildren; // The child nodes
|
||||
|
||||
@@ -341,6 +341,7 @@ set(viewer_SOURCE_FILES
|
||||
llpanelavatar.cpp
|
||||
llpanelclassified.cpp
|
||||
llpanelcontents.cpp
|
||||
llpaneleditwearable.cpp
|
||||
llpaneldebug.cpp
|
||||
llpaneldirbrowser.cpp
|
||||
llpaneldirclassified.cpp
|
||||
@@ -404,6 +405,8 @@ set(viewer_SOURCE_FILES
|
||||
llregionposition.cpp
|
||||
llremoteparcelrequest.cpp
|
||||
llsavedsettingsglue.cpp
|
||||
llscrollingpanelparam.cpp
|
||||
llscrollingpanelparambase.cpp
|
||||
llselectmgr.cpp
|
||||
llsky.cpp
|
||||
llspatialpartition.cpp
|
||||
@@ -833,6 +836,7 @@ set(viewer_HEADER_FILES
|
||||
llpanelavatar.h
|
||||
llpanelclassified.h
|
||||
llpanelcontents.h
|
||||
llpaneleditwearable.h
|
||||
llpaneldebug.h
|
||||
llpaneldirbrowser.h
|
||||
llpaneldirclassified.h
|
||||
@@ -898,6 +902,8 @@ set(viewer_HEADER_FILES
|
||||
llremoteparcelrequest.h
|
||||
llresourcedata.h
|
||||
llsavedsettingsglue.h
|
||||
llscrollingpanelparam.h
|
||||
llscrollingpanelparambase.h
|
||||
llselectmgr.h
|
||||
llsky.h
|
||||
llspatialpartition.h
|
||||
|
||||
@@ -783,17 +783,6 @@
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>EmeraldUseProperArc</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enables/Disables a fixed ARC counter</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>EmeraldBoobMass</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -825,17 +814,6 @@
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EmeraldBreastSportsBra</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>allows disabling the physics for 1 av, in case their outfit looks wrong with it on</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>EmeraldBoobVelMax</key>
|
||||
@@ -7245,6 +7223,39 @@
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>InventoryDisplayInbox</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Override received items inventory inbox display</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>InventoryDisplayOutbox</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Override merchant inventory outbox display</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>InventoryOutboxLogging</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable debug output associated with the Merchant Outbox.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>InventoryOutboxMaxFolderCount</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -11172,7 +11183,7 @@
|
||||
<key>Comment</key>
|
||||
<string>Maximum size of a single node's vertex data (in KB).</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
@@ -11553,28 +11564,19 @@
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderUseShaderLOD</key>
|
||||
|
||||
<key>RenderAutoHideSurfaceAreaLimit</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Whether we want to have different shaders for LOD</string>
|
||||
<string>Maximum surface area of a set of proximal objects inworld before automatically hiding geometry to prevent system overload.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderUseShaderNearParticles</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Whether we want to use shaders on near particles</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderVBOEnable</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
@@ -13243,6 +13245,39 @@
|
||||
<key>Value</key>
|
||||
<real>20.0</real>
|
||||
</map>
|
||||
<key>TexelPixelRatio</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>texel pixel ratio = texel / pixel</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>TextureCameraMotionThreshold</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>If the overall motion is lower than this value, textures will be loaded faster</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>0.2</real>
|
||||
</map>
|
||||
<key>TextureCameraMotionBoost</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Progressive discard level decrement when the camera is still</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>3</integer>
|
||||
</map>
|
||||
<key>TextureDecodeDisabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
||||
@@ -31,6 +31,8 @@ out vec4 frag_color;
|
||||
#define frag_color gl_FragColor
|
||||
#endif
|
||||
|
||||
uniform float minimum_alpha;
|
||||
|
||||
uniform sampler2DRect depthMap;
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
@@ -70,9 +72,15 @@ void main()
|
||||
|
||||
vec4 diff= texture2D(diffuseMap,vary_texcoord0.xy);
|
||||
|
||||
if (diff.a < minimum_alpha)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
vec4 col = vec4(vary_ambient + vary_directional.rgb, 1.0);
|
||||
vec4 color = diff * col;
|
||||
|
||||
|
||||
color.rgb = atmosLighting(color.rgb);
|
||||
|
||||
color.rgb = scaleSoftClip(color.rgb);
|
||||
|
||||
@@ -55,8 +55,6 @@ uniform float far_clip;
|
||||
|
||||
uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
|
||||
uniform float sun_wash;
|
||||
uniform int proj_shadow_idx;
|
||||
uniform float shadow_fade;
|
||||
|
||||
uniform vec3 center;
|
||||
uniform vec3 color;
|
||||
@@ -143,7 +141,8 @@ void main()
|
||||
discard;
|
||||
}
|
||||
|
||||
vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
|
||||
vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
|
||||
norm = vec3((norm.xy-0.5)*2.0, norm.z);
|
||||
|
||||
norm = normalize(norm);
|
||||
float l_dist = -dot(lv, proj_n);
|
||||
|
||||
@@ -42,12 +42,13 @@ uniform sampler2DRect depthMap;
|
||||
uniform vec3 env_mat[3];
|
||||
uniform float sun_wash;
|
||||
|
||||
uniform vec3 center;
|
||||
uniform vec3 color;
|
||||
uniform float falloff;
|
||||
uniform float size;
|
||||
|
||||
VARYING vec4 vary_fragcoord;
|
||||
VARYING vec3 trans_center;
|
||||
|
||||
uniform vec2 screen_res;
|
||||
|
||||
uniform mat4 inv_proj;
|
||||
@@ -74,7 +75,7 @@ void main()
|
||||
frag.xy *= screen_res;
|
||||
|
||||
vec3 pos = getPosition(frag.xy).xyz;
|
||||
vec3 lv = center.xyz-pos;
|
||||
vec3 lv = trans_center.xyz-pos;
|
||||
float dist2 = dot(lv,lv);
|
||||
dist2 /= size;
|
||||
if (dist2 > 1.0)
|
||||
|
||||
@@ -24,16 +24,22 @@
|
||||
*/
|
||||
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
uniform mat4 modelview_matrix;
|
||||
|
||||
ATTRIBUTE vec3 position;
|
||||
|
||||
uniform vec3 center;
|
||||
uniform float size;
|
||||
|
||||
VARYING vec4 vary_fragcoord;
|
||||
VARYING vec3 trans_center;
|
||||
|
||||
void main()
|
||||
{
|
||||
//transform vertex
|
||||
vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
|
||||
vec3 p = position*sqrt(size)+center;
|
||||
vec4 pos = modelview_projection_matrix * vec4(p.xyz, 1.0);
|
||||
vary_fragcoord = pos;
|
||||
|
||||
trans_center = (modelview_matrix*vec4(center.xyz, 1.0)).xyz;
|
||||
gl_Position = pos;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* @file shadowCubeV.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2007, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
|
||||
ATTRIBUTE vec3 position;
|
||||
|
||||
VARYING vec4 post_pos;
|
||||
|
||||
uniform vec3 box_center;
|
||||
uniform vec3 box_size;
|
||||
|
||||
void main()
|
||||
{
|
||||
//transform vertex
|
||||
vec3 p = position*box_size+box_center;
|
||||
vec4 pos = modelview_projection_matrix*vec4(p.xyz, 1.0);
|
||||
|
||||
post_pos = pos;
|
||||
|
||||
gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
|
||||
}
|
||||
@@ -24,18 +24,21 @@
|
||||
*/
|
||||
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
|
||||
#ifdef DEFINE_GL_FRAGCOLOR
|
||||
out vec4 frag_color;
|
||||
#else
|
||||
#define frag_color gl_FragColor
|
||||
#endif
|
||||
|
||||
//class 1 -- no shadows
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
|
||||
uniform sampler2DRect diffuseRect;
|
||||
uniform sampler2DRect specularRect;
|
||||
uniform sampler2DRect depthMap;
|
||||
uniform sampler2DRect normalMap;
|
||||
uniform samplerCube environmentMap;
|
||||
uniform sampler2D noiseMap;
|
||||
uniform sampler2D projectionMap;
|
||||
|
||||
@@ -46,6 +49,7 @@ uniform vec3 proj_n;
|
||||
uniform float proj_focus; //distance from plane to begin blurring
|
||||
uniform float proj_lod; //(number of mips in proj map)
|
||||
uniform float proj_range; //range between near clip and far clip plane of projection
|
||||
uniform float proj_ambient_lod;
|
||||
uniform float proj_ambiance;
|
||||
uniform float near_clip;
|
||||
uniform float far_clip;
|
||||
@@ -53,19 +57,66 @@ uniform float far_clip;
|
||||
uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
|
||||
uniform float sun_wash;
|
||||
|
||||
uniform vec3 center;
|
||||
uniform vec3 color;
|
||||
uniform float falloff;
|
||||
uniform float size;
|
||||
|
||||
VARYING vec4 vary_fragcoord;
|
||||
VARYING vec3 trans_center;
|
||||
|
||||
uniform vec2 screen_res;
|
||||
|
||||
uniform mat4 inv_proj;
|
||||
|
||||
vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = tc-vec2(0.5);
|
||||
|
||||
float det = max(1.0-lod/(proj_lod*0.5), 0.0);
|
||||
|
||||
float d = dot(dist,dist);
|
||||
|
||||
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
|
||||
|
||||
float det = min(lod/(proj_lod*0.5), 1.0);
|
||||
|
||||
float d = min(dist.x, dist.y);
|
||||
|
||||
float edge = 0.25*det;
|
||||
|
||||
ret *= clamp(d/edge, 0.0, 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = tc-vec2(0.5);
|
||||
|
||||
float d = dot(dist,dist);
|
||||
|
||||
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
vec4 getPosition(vec2 pos_screen)
|
||||
{
|
||||
float depth = texture2DRect(depthMap, pos_screen.xy).a;
|
||||
float depth = texture2DRect(depthMap, pos_screen.xy).r;
|
||||
vec2 sc = pos_screen.xy*2.0;
|
||||
sc /= screen_res;
|
||||
sc -= vec2(1.0,1.0);
|
||||
@@ -84,16 +135,16 @@ void main()
|
||||
frag.xy *= screen_res;
|
||||
|
||||
vec3 pos = getPosition(frag.xy).xyz;
|
||||
vec3 lv = center.xyz-pos.xyz;
|
||||
vec3 lv = trans_center.xyz-pos.xyz;
|
||||
float dist2 = dot(lv,lv);
|
||||
dist2 /= size;
|
||||
if (dist2 > 1.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
|
||||
vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
|
||||
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
|
||||
norm = vec3((norm.xy-0.5)*2.0, norm.z);
|
||||
|
||||
norm = normalize(norm);
|
||||
float l_dist = -dot(lv, proj_n);
|
||||
@@ -107,7 +158,11 @@ void main()
|
||||
proj_tc.xyz /= proj_tc.w;
|
||||
|
||||
float fa = falloff+1.0;
|
||||
float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
|
||||
float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
|
||||
if (dist_atten <= 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
lv = proj_origin-pos.xyz;
|
||||
lv = normalize(lv);
|
||||
@@ -125,32 +180,32 @@ void main()
|
||||
proj_tc.y > 0.0)
|
||||
{
|
||||
float lit = 0.0;
|
||||
float amb_da = proj_ambiance;
|
||||
|
||||
if (da > 0.0)
|
||||
{
|
||||
float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
|
||||
float lod = diff * proj_lod;
|
||||
|
||||
vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
|
||||
vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
|
||||
|
||||
vec3 lcol = color.rgb * plcol.rgb * plcol.a;
|
||||
|
||||
lit = da * dist_atten * noise;
|
||||
|
||||
col = lcol*lit*diff_tex;
|
||||
amb_da += (da*0.5)*proj_ambiance;
|
||||
}
|
||||
|
||||
float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
|
||||
float lod = diff * proj_lod;
|
||||
vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
|
||||
//float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0));
|
||||
float amb_da = proj_ambiance;
|
||||
|
||||
//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
|
||||
vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
|
||||
|
||||
amb_da += (da*da*0.5+0.5)*proj_ambiance;
|
||||
|
||||
|
||||
amb_da *= dist_atten * noise;
|
||||
|
||||
|
||||
amb_da = min(amb_da, 1.0-lit);
|
||||
|
||||
|
||||
col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
|
||||
}
|
||||
|
||||
@@ -168,18 +223,22 @@ void main()
|
||||
{
|
||||
vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
|
||||
|
||||
vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz;
|
||||
vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
|
||||
|
||||
if (stc.z > 0.0)
|
||||
{
|
||||
stc.xy /= stc.z+proj_near;
|
||||
|
||||
stc.xy /= stc.w;
|
||||
|
||||
float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
|
||||
|
||||
stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
|
||||
|
||||
if (stc.x < 1.0 &&
|
||||
stc.y < 1.0 &&
|
||||
stc.x > 0.0 &&
|
||||
stc.y > 0.0)
|
||||
{
|
||||
vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
|
||||
vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
|
||||
col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @file occlusionCubeV.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2007, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
|
||||
ATTRIBUTE vec3 position;
|
||||
|
||||
uniform vec3 box_center;
|
||||
uniform vec3 box_size;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 p = position*box_size+box_center;
|
||||
gl_Position = modelview_projection_matrix * vec4(p.xyz, 1.0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file binormalV.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2007, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
uniform mat3 normal_matrix;
|
||||
|
||||
ATTRIBUTE vec3 binormal;
|
||||
|
||||
VARYING vec4 binormal_out;
|
||||
|
||||
void main()
|
||||
{
|
||||
binormal_out = vec4(normal_matrix * binormal, 0.0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file colorV.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2007, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
uniform int color_in;
|
||||
|
||||
ATTRIBUTE vec3 position;
|
||||
|
||||
VARYING int color_out;
|
||||
|
||||
void main()
|
||||
{
|
||||
color_out = color_in;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* @file normalV.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2007, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
uniform mat3 normal_matrix;
|
||||
|
||||
ATTRIBUTE vec3 normal;
|
||||
|
||||
VARYING vec4 normal_out;
|
||||
|
||||
void main()
|
||||
{
|
||||
normal_out = vec4(normalize(normal_matrix * normal), 0.0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file positionV.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2007, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
uniform mat4 modelview_matrix;
|
||||
|
||||
uniform int texture_index_in;
|
||||
|
||||
ATTRIBUTE vec3 position;
|
||||
|
||||
VARYING vec3 position_out;
|
||||
VARYING int texture_index_out;
|
||||
|
||||
void main()
|
||||
{
|
||||
texture_index_out = texture_index_in;
|
||||
position_out = (modelview_matrix*vec4(position, 1.0)).xyz;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @file texcoordV.glsl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2007, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
ATTRIBUTE vec2 texcoord0;
|
||||
|
||||
VARYING vec2 texcoord_out;
|
||||
|
||||
void main()
|
||||
{
|
||||
texcoord_out = texcoord0;
|
||||
}
|
||||
|
||||
@@ -58,20 +58,22 @@ uniform float shadow_bias;
|
||||
|
||||
uniform mat4 inv_proj;
|
||||
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc)
|
||||
{
|
||||
stc.xyz /= stc.w;
|
||||
stc.z += shadow_bias;
|
||||
|
||||
stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here
|
||||
|
||||
float cs = shadow2DRect(shadowMap, stc.xyz).x;
|
||||
float shadow = cs;
|
||||
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs);
|
||||
|
||||
return shadow/5.0;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x;
|
||||
|
||||
return shadow*0.2;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +103,7 @@ void main()
|
||||
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
|
||||
shadow += pcfShadow(shadowMap3, lpos, 0.25)*w;
|
||||
shadow += pcfShadow(shadowMap3, lpos)*w;
|
||||
weight += w;
|
||||
shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
|
||||
}
|
||||
@@ -114,7 +116,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
|
||||
w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
|
||||
shadow += pcfShadow(shadowMap2, lpos, 0.75)*w;
|
||||
shadow += pcfShadow(shadowMap2, lpos)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -126,7 +128,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
|
||||
w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
|
||||
shadow += pcfShadow(shadowMap1, lpos, 0.75)*w;
|
||||
shadow += pcfShadow(shadowMap1, lpos)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -138,7 +140,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
|
||||
|
||||
shadow += pcfShadow(shadowMap0, lpos, 1.0)*w;
|
||||
shadow += pcfShadow(shadowMap0, lpos)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,20 +71,22 @@ vec4 getPosition(vec2 pos_screen)
|
||||
return pos;
|
||||
}
|
||||
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc)
|
||||
{
|
||||
stc.xyz /= stc.w;
|
||||
stc.z += shadow_bias;
|
||||
|
||||
stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here
|
||||
|
||||
float cs = shadow2DRect(shadowMap, stc.xyz).x;
|
||||
float shadow = cs;
|
||||
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs);
|
||||
|
||||
return shadow/5.0;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x;
|
||||
|
||||
return shadow*0.2;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +116,7 @@ void main()
|
||||
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
|
||||
shadow += pcfShadow(shadowMap3, lpos, 0.25)*w;
|
||||
shadow += pcfShadow(shadowMap3, lpos)*w;
|
||||
weight += w;
|
||||
shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
|
||||
}
|
||||
@@ -127,7 +129,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
|
||||
w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
|
||||
shadow += pcfShadow(shadowMap2, lpos, 0.75)*w;
|
||||
shadow += pcfShadow(shadowMap2, lpos)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -139,7 +141,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
|
||||
w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
|
||||
shadow += pcfShadow(shadowMap1, lpos, 0.75)*w;
|
||||
shadow += pcfShadow(shadowMap1, lpos)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -151,7 +153,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
|
||||
|
||||
shadow += pcfShadow(shadowMap0, lpos, 1.0)*w;
|
||||
shadow += pcfShadow(shadowMap0, lpos)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ out vec4 frag_color;
|
||||
#define frag_color gl_FragColor
|
||||
#endif
|
||||
|
||||
uniform float minimum_alpha;
|
||||
|
||||
uniform sampler2DRectShadow shadowMap0;
|
||||
uniform sampler2DRectShadow shadowMap1;
|
||||
uniform sampler2DRectShadow shadowMap2;
|
||||
@@ -70,20 +72,22 @@ vec4 getPosition(vec2 pos_screen)
|
||||
return pos;
|
||||
}
|
||||
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc)
|
||||
{
|
||||
stc.xyz /= stc.w;
|
||||
stc.z += shadow_bias;
|
||||
|
||||
stc.x = floor(stc.x + fract(stc.y*12345)); // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here
|
||||
|
||||
float cs = shadow2DRect(shadowMap, stc.xyz).x;
|
||||
float shadow = cs;
|
||||
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs);
|
||||
|
||||
return shadow/5.0;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x;
|
||||
|
||||
return shadow*0.2;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +99,13 @@ void main()
|
||||
float shadow = 0.0;
|
||||
vec4 pos = vec4(vary_position, 1.0);
|
||||
|
||||
vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy);
|
||||
|
||||
if (diff.a < minimum_alpha)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
vec4 spos = pos;
|
||||
|
||||
if (spos.z > -shadow_clip.w)
|
||||
@@ -113,7 +124,7 @@ void main()
|
||||
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
|
||||
shadow += pcfShadow(shadowMap3, lpos, 0.25)*w;
|
||||
shadow += pcfShadow(shadowMap3, lpos)*w;
|
||||
weight += w;
|
||||
shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
|
||||
}
|
||||
@@ -126,7 +137,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
|
||||
w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
|
||||
shadow += pcfShadow(shadowMap2, lpos, 0.75)*w;
|
||||
shadow += pcfShadow(shadowMap2, lpos)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -138,7 +149,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
|
||||
w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
|
||||
shadow += pcfShadow(shadowMap1, lpos, 0.75)*w;
|
||||
shadow += pcfShadow(shadowMap1, lpos)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -150,7 +161,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
|
||||
|
||||
shadow += pcfShadow(shadowMap0, lpos, 1.0)*w;
|
||||
shadow += pcfShadow(shadowMap0, lpos)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -162,8 +173,6 @@ void main()
|
||||
shadow = 1.0;
|
||||
}
|
||||
|
||||
vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy);
|
||||
|
||||
vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, 1.0);
|
||||
vec4 color = diff * col;
|
||||
|
||||
|
||||
@@ -309,11 +309,11 @@ void main()
|
||||
//
|
||||
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
|
||||
float sa = dot(refnormpersp, sun_dir.xyz);
|
||||
vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).r;
|
||||
vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r);
|
||||
|
||||
// add the two types of shiny together
|
||||
vec3 spec_contrib = dumbshiny * spec.rgb;
|
||||
bloom = dot(spec_contrib, spec_contrib);
|
||||
bloom = dot(spec_contrib, spec_contrib) / 4;
|
||||
col += spec_contrib;
|
||||
|
||||
//add environmentmap
|
||||
|
||||
@@ -31,8 +31,6 @@ out vec4 frag_color;
|
||||
#define frag_color gl_FragColor
|
||||
#endif
|
||||
|
||||
VARYING vec4 vertex_color;
|
||||
|
||||
uniform sampler2DRect diffuseRect;
|
||||
uniform sampler2DRect specularRect;
|
||||
uniform sampler2DRect depthMap;
|
||||
@@ -49,6 +47,7 @@ uniform vec3 proj_n;
|
||||
uniform float proj_focus; //distance from plane to begin blurring
|
||||
uniform float proj_lod; //(number of mips in proj map)
|
||||
uniform float proj_range; //range between near clip and far clip plane of projection
|
||||
uniform float proj_ambient_lod;
|
||||
uniform float proj_ambiance;
|
||||
uniform float near_clip;
|
||||
uniform float far_clip;
|
||||
@@ -58,16 +57,65 @@ uniform float sun_wash;
|
||||
uniform int proj_shadow_idx;
|
||||
uniform float shadow_fade;
|
||||
|
||||
VARYING vec4 vary_light;
|
||||
uniform float size;
|
||||
uniform vec3 color;
|
||||
uniform float falloff;
|
||||
|
||||
VARYING vec3 trans_center;
|
||||
VARYING vec4 vary_fragcoord;
|
||||
uniform vec2 screen_res;
|
||||
|
||||
uniform mat4 inv_proj;
|
||||
|
||||
vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = tc-vec2(0.5);
|
||||
|
||||
float det = max(1.0-lod/(proj_lod*0.5), 0.0);
|
||||
|
||||
float d = dot(dist,dist);
|
||||
|
||||
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
|
||||
|
||||
float det = min(lod/(proj_lod*0.5), 1.0);
|
||||
|
||||
float d = min(dist.x, dist.y);
|
||||
|
||||
float edge = 0.25*det;
|
||||
|
||||
ret *= clamp(d/edge, 0.0, 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = tc-vec2(0.5);
|
||||
|
||||
float d = dot(dist,dist);
|
||||
|
||||
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
vec4 getPosition(vec2 pos_screen)
|
||||
{
|
||||
float depth = texture2DRect(depthMap, pos_screen.xy).a;
|
||||
float depth = texture2DRect(depthMap, pos_screen.xy).r;
|
||||
vec2 sc = pos_screen.xy*2.0;
|
||||
sc /= screen_res;
|
||||
sc -= vec2(1.0,1.0);
|
||||
@@ -85,6 +133,15 @@ void main()
|
||||
frag.xyz = frag.xyz*0.5+0.5;
|
||||
frag.xy *= screen_res;
|
||||
|
||||
vec3 pos = getPosition(frag.xy).xyz;
|
||||
vec3 lv = trans_center.xyz-pos.xyz;
|
||||
float dist2 = dot(lv,lv);
|
||||
dist2 /= size;
|
||||
if (dist2 > 1.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
float shadow = 1.0;
|
||||
|
||||
if (proj_shadow_idx >= 0)
|
||||
@@ -96,15 +153,6 @@ void main()
|
||||
shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
|
||||
}
|
||||
|
||||
vec3 pos = getPosition(frag.xy).xyz;
|
||||
vec3 lv = vary_light.xyz-pos.xyz;
|
||||
float dist2 = dot(lv,lv);
|
||||
dist2 /= vary_light.w;
|
||||
if (dist2 > 1.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
|
||||
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
|
||||
|
||||
@@ -119,8 +167,12 @@ void main()
|
||||
|
||||
proj_tc.xyz /= proj_tc.w;
|
||||
|
||||
float fa = vertex_color.a+1.0;
|
||||
float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
|
||||
float fa = falloff+1.0;
|
||||
float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
|
||||
if (dist_atten <= 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
lv = proj_origin-pos.xyz;
|
||||
lv = normalize(lv);
|
||||
@@ -138,37 +190,33 @@ void main()
|
||||
proj_tc.y > 0.0)
|
||||
{
|
||||
float lit = 0.0;
|
||||
float amb_da = proj_ambiance;
|
||||
|
||||
if (da > 0.0)
|
||||
{
|
||||
float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
|
||||
float lod = diff * proj_lod;
|
||||
|
||||
vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
|
||||
vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
|
||||
|
||||
vec3 lcol = vertex_color.rgb * plcol.rgb * plcol.a;
|
||||
vec3 lcol = color.rgb * plcol.rgb * plcol.a;
|
||||
|
||||
lit = da * dist_atten * noise;
|
||||
|
||||
col = lcol*lit*diff_tex*shadow;
|
||||
}
|
||||
|
||||
float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
|
||||
float lod = diff * proj_lod;
|
||||
vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
|
||||
//float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0));
|
||||
float amb_da = proj_ambiance;
|
||||
if (da > 0.0)
|
||||
{
|
||||
amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
|
||||
}
|
||||
|
||||
//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
|
||||
vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
|
||||
|
||||
amb_da += (da*da*0.5+0.5)*proj_ambiance;
|
||||
|
||||
|
||||
amb_da *= dist_atten * noise;
|
||||
|
||||
|
||||
amb_da = min(amb_da, 1.0-lit);
|
||||
|
||||
col += amb_da*vertex_color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
|
||||
|
||||
col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
|
||||
}
|
||||
|
||||
|
||||
@@ -185,19 +233,23 @@ void main()
|
||||
{
|
||||
vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
|
||||
|
||||
vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz;
|
||||
vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
|
||||
|
||||
if (stc.z > 0.0)
|
||||
{
|
||||
stc.xy /= stc.z+proj_near;
|
||||
|
||||
stc.xy /= stc.w;
|
||||
|
||||
float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
|
||||
|
||||
stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
|
||||
|
||||
if (stc.x < 1.0 &&
|
||||
stc.y < 1.0 &&
|
||||
stc.x > 0.0 &&
|
||||
stc.y > 0.0)
|
||||
{
|
||||
vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
|
||||
col += dist_atten*scol.rgb*vertex_color.rgb*scol.a*spec.rgb*shadow;
|
||||
vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
|
||||
col += dist_atten*scol.rgb*color.rgb*scol.a*spec.rgb*shadow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,42 +78,42 @@ vec4 getPosition(vec2 pos_screen)
|
||||
return pos;
|
||||
}
|
||||
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
|
||||
{
|
||||
stc.xyz /= stc.w;
|
||||
stc.z += shadow_bias*scl;
|
||||
|
||||
|
||||
stc.x = floor(stc.x + fract(pos_screen.y*0.666666666)); // add some jitter to X sample pos according to Y to disguise the snapping going on here
|
||||
|
||||
float cs = shadow2DRect(shadowMap, stc.xyz).x;
|
||||
float shadow = cs;
|
||||
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs);
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, 1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, -1.5, 0.0)).x;
|
||||
|
||||
return shadow/5.0;
|
||||
|
||||
//return shadow;
|
||||
return shadow*0.2;
|
||||
}
|
||||
|
||||
float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl)
|
||||
float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
|
||||
{
|
||||
stc.xyz /= stc.w;
|
||||
stc.z += spot_shadow_bias*scl;
|
||||
stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap
|
||||
|
||||
float cs = shadow2D(shadowMap, stc.xyz).x;
|
||||
float shadow = cs;
|
||||
|
||||
vec2 off = 1.5/proj_shadow_res;
|
||||
vec2 off = 1.0/proj_shadow_res;
|
||||
off.y *= 1.5;
|
||||
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs);
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs);
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs);
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs);
|
||||
|
||||
return shadow/5.0;
|
||||
|
||||
//return shadow;
|
||||
shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x;
|
||||
shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x;
|
||||
shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x;
|
||||
shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x;
|
||||
|
||||
return shadow*0.2;
|
||||
}
|
||||
|
||||
void main()
|
||||
@@ -166,7 +166,7 @@ void main()
|
||||
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
|
||||
shadow += pcfShadow(shadowMap3, lpos, 0.25)*w;
|
||||
shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w;
|
||||
weight += w;
|
||||
shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
|
||||
}
|
||||
@@ -179,7 +179,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
|
||||
w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
|
||||
shadow += pcfShadow(shadowMap2, lpos, 0.75)*w;
|
||||
shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
|
||||
w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
|
||||
shadow += pcfShadow(shadowMap1, lpos, 0.75)*w;
|
||||
shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
|
||||
|
||||
shadow += pcfShadow(shadowMap0, lpos, 1.0)*w;
|
||||
shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -237,11 +237,11 @@ void main()
|
||||
|
||||
//spotlight shadow 1
|
||||
vec4 lpos = shadow_matrix[4]*spos;
|
||||
frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8);
|
||||
frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8, pos_screen);
|
||||
|
||||
//spotlight shadow 2
|
||||
lpos = shadow_matrix[5]*spos;
|
||||
frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8);
|
||||
frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8, pos_screen);
|
||||
|
||||
//frag_color.rgb = pos.xyz;
|
||||
//frag_color.b = shadow;
|
||||
|
||||
@@ -139,42 +139,42 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm)
|
||||
return min(ret, 1.0);
|
||||
}
|
||||
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
|
||||
{
|
||||
stc.xyz /= stc.w;
|
||||
stc.z += shadow_bias*scl;
|
||||
|
||||
stc.x = floor(stc.x + fract(pos_screen.y*0.666666666));
|
||||
|
||||
float cs = shadow2DRect(shadowMap, stc.xyz).x;
|
||||
float shadow = cs;
|
||||
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs);
|
||||
|
||||
return shadow/5.0;
|
||||
|
||||
//return shadow;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(2.0, 1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(1.0, -1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-1.0, 1.5, 0.0)).x;
|
||||
shadow += shadow2DRect(shadowMap, stc.xyz+vec3(-2.0, -1.5, 0.0)).x;
|
||||
|
||||
return shadow*0.2;
|
||||
}
|
||||
|
||||
float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl)
|
||||
float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
|
||||
{
|
||||
stc.xyz /= stc.w;
|
||||
stc.z += spot_shadow_bias*scl;
|
||||
stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap
|
||||
|
||||
float cs = shadow2D(shadowMap, stc.xyz).x;
|
||||
float shadow = cs;
|
||||
|
||||
vec2 off = 1.5/proj_shadow_res;
|
||||
vec2 off = 1.0/proj_shadow_res;
|
||||
off.y *= 1.5;
|
||||
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs);
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs);
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs);
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs);
|
||||
|
||||
return shadow/5.0;
|
||||
|
||||
//return shadow;
|
||||
shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x;
|
||||
shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x;
|
||||
shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x;
|
||||
shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x;
|
||||
|
||||
return shadow*0.2;
|
||||
}
|
||||
|
||||
void main()
|
||||
@@ -227,7 +227,7 @@ void main()
|
||||
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
|
||||
shadow += pcfShadow(shadowMap3, lpos, 0.25)*w;
|
||||
shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w;
|
||||
weight += w;
|
||||
shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
|
||||
}
|
||||
@@ -240,7 +240,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
|
||||
w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
|
||||
shadow += pcfShadow(shadowMap2, lpos, 0.75)*w;
|
||||
shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
|
||||
w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
|
||||
shadow += pcfShadow(shadowMap1, lpos, 0.75)*w;
|
||||
shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ void main()
|
||||
float w = 1.0;
|
||||
w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
|
||||
|
||||
shadow += pcfShadow(shadowMap0, lpos, 1.0)*w;
|
||||
shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w;
|
||||
weight += w;
|
||||
}
|
||||
|
||||
@@ -298,11 +298,11 @@ void main()
|
||||
|
||||
//spotlight shadow 1
|
||||
vec4 lpos = shadow_matrix[4]*spos;
|
||||
frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8);
|
||||
frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8, pos_screen);
|
||||
|
||||
//spotlight shadow 2
|
||||
lpos = shadow_matrix[5]*spos;
|
||||
frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8);
|
||||
frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8, pos_screen);
|
||||
|
||||
//frag_color.rgb = pos.xyz;
|
||||
//frag_color.b = shadow;
|
||||
|
||||
@@ -33,8 +33,6 @@ std::ostream &operator<<(std::ostream &os, const EmeraldBoobState &v)
|
||||
os << "frameDuration: " << v.frameDuration << std::endl;
|
||||
os << "chestDisplacement: " << v.chestDisplacement << std::endl;
|
||||
os << "localChestDisplacement: " << v.localChestDisplacement << std::endl;
|
||||
os << "displacementForce: " << v.displacementForce << std::endl;
|
||||
os << "mysteryValue: " << v.mysteryValue << std::endl;
|
||||
os << "Number of bounceStates: " << v.bounceStates.size() << std::endl;
|
||||
return os;
|
||||
}
|
||||
@@ -45,8 +43,6 @@ std::ostream &operator<<(std::ostream &os, const EmeraldBoobInputs &v)
|
||||
os << "chestPosition: " << v.chestPosition << std::endl;
|
||||
os << "chestRotation: " << v.chestRotation << std::endl;
|
||||
os << "elapsedTime: " << v.elapsedTime << std::endl;
|
||||
os << "appearanceFlag: " << v.appearanceFlag << std::endl;
|
||||
os << "appearanceAnimating: " << v.appearanceAnimating << std::endl;
|
||||
return os;
|
||||
}
|
||||
|
||||
@@ -80,27 +76,11 @@ EmeraldBoobState EmeraldBoobUtils::idleUpdate(const EmeraldGlobalBoobConfig &con
|
||||
F32 avatarLocalMass = 0.0f;
|
||||
F32 partMod = 1.f;
|
||||
|
||||
if(!config.enabled || inputs.appearanceFlag || inputs.appearanceAnimating)
|
||||
if(!config.enabled)
|
||||
return newState;
|
||||
|
||||
if(inputs.type == 0)
|
||||
{
|
||||
newState.boobGrav = localConfig.actualBoobGrav;
|
||||
avatarLocalMass = (llclamp(localConfig.boobSize, 0.0f, 0.5f) / 0.5f);
|
||||
}
|
||||
if(inputs.type == 1)
|
||||
{
|
||||
newState.boobGrav = localConfig.actualButtGrav;
|
||||
partMod = 1.5f;
|
||||
avatarLocalMass = llclamp(localConfig.actualButtGrav, 0.0f, 0.5f) / 0.5f;
|
||||
}
|
||||
if(inputs.type == 2)
|
||||
{
|
||||
newState.boobGrav = localConfig.actualFatGrav;
|
||||
partMod = 1.3f;
|
||||
avatarLocalMass = localConfig.actualFatGrav;
|
||||
}
|
||||
|
||||
newState.boobGrav = localConfig.actualBoobGrav;
|
||||
avatarLocalMass = (llclamp(localConfig.boobSize, 0.0f, 0.5f) / 0.5f);
|
||||
|
||||
newState.elapsedTime = inputs.elapsedTime;
|
||||
// seemed to create incorrect amounts of velocity when FPS varied
|
||||
@@ -119,9 +99,10 @@ EmeraldBoobState EmeraldBoobUtils::idleUpdate(const EmeraldGlobalBoobConfig &con
|
||||
boobVel = newState.localChestDisplacement.mV[VZ];
|
||||
boobVel += newState.localChestDisplacement[VX] * config.XYInfluence;
|
||||
boobVel += newState.localChestDisplacement.mV[VY] * config.XYInfluence;
|
||||
boobVel *= newState.frameDuration * 0.3f * 100.f;
|
||||
boobVel = llclamp(boobVel, -config.velMax, config.velMax);
|
||||
if(fabs(boobVel) <= config.velMax * config.velMin * newState.frameDuration * 100.f)
|
||||
boobVel *= newState.frameDuration * 0.3f * 100.f;
|
||||
|
||||
if(fabs(boobVel) <= config.velMin * newState.frameDuration * 100.f)
|
||||
boobVel = 0.0f;
|
||||
else
|
||||
{
|
||||
@@ -135,26 +116,6 @@ EmeraldBoobState EmeraldBoobUtils::idleUpdate(const EmeraldGlobalBoobConfig &con
|
||||
}
|
||||
}
|
||||
|
||||
/*if(fabs(newState.localChestDisplacement.length()) >= 0.f) {
|
||||
LLVector3 displacementInfluence = newState.localChestDisplacement;
|
||||
displacementInfluence *= LLVector3(0.3f, 0.3f, 1.0f);
|
||||
F32 clampedDisplacementInfluenceLength = llclamp(displacementInfluence.length(), 0.0f, config.velMax);
|
||||
if(displacementInfluence[VZ]<0.f)
|
||||
clampedDisplacementInfluenceLength= -clampedDisplacementInfluenceLength;
|
||||
EmeraldBoobBounceState bounceState;
|
||||
bounceState.bounceStart = inputs.elapsedTime;
|
||||
bounceState.bounceStartFrameDuration = newState.frameDuration;
|
||||
bounceState.bounceStartAmplitude = clampedDisplacementInfluenceLength;
|
||||
if(fabs(bounceState.bounceStartAmplitude) < config.velMin * config.velMax)
|
||||
bounceState.bounceStartAmplitude = 0.0f;
|
||||
else
|
||||
{
|
||||
bounceState.bounceStartAmplitude *= config.mass;
|
||||
bounceStates.push_front(bounceState);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
F32 totalNewAmplitude = 0.0f;
|
||||
//std::cout << "Beginning bounce State processing at time " << inputs.elapsedTime << std::endl;
|
||||
while(!bounceStates.empty()) {
|
||||
@@ -170,15 +131,6 @@ EmeraldBoobState EmeraldBoobUtils::idleUpdate(const EmeraldGlobalBoobConfig &con
|
||||
}
|
||||
totalNewAmplitude+=newAmplitude;
|
||||
}
|
||||
//std::cout << "Total new amplitude: " << totalNewAmplitude << std::endl;
|
||||
/*
|
||||
if(inputs.type == 0)
|
||||
newState.boobGrav = localConfig.actualBoobGrav + totalNewAmplitude;
|
||||
if(inputs.type == 1)
|
||||
newState.boobGrav = localConfig.actualButtGrav + totalNewAmplitude;
|
||||
if(inputs.type == 2)
|
||||
newState.boobGrav = localConfig.actualFatGrav + totalNewAmplitude;
|
||||
*/
|
||||
|
||||
newState.boobGrav = totalNewAmplitude;
|
||||
|
||||
|
||||
@@ -32,19 +32,6 @@ struct EmeraldGlobalBoobConfig
|
||||
XYInfluence(0.3f)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const EmeraldGlobalBoobConfig &other) const
|
||||
{
|
||||
return
|
||||
enabled == other.enabled &&
|
||||
mass == other.mass &&
|
||||
zMax == other.zMax &&
|
||||
velMax == other.velMax &&
|
||||
velMin == other.velMin &&
|
||||
zInfluence == other.zInfluence &&
|
||||
XYInfluence == other.XYInfluence &&
|
||||
friction == other.friction;
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const EmeraldGlobalBoobConfig &v);
|
||||
@@ -52,14 +39,10 @@ std::ostream &operator<<(std::ostream &os, const EmeraldGlobalBoobConfig &v);
|
||||
struct EmeraldAvatarLocalBoobConfig
|
||||
{
|
||||
F32 actualBoobGrav;
|
||||
F32 actualButtGrav;
|
||||
F32 actualFatGrav;
|
||||
F32 boobSize;
|
||||
|
||||
EmeraldAvatarLocalBoobConfig()
|
||||
: actualBoobGrav(0.0f),
|
||||
actualButtGrav(0.0f),
|
||||
actualFatGrav(0.0f),
|
||||
boobSize(0.0f)
|
||||
{
|
||||
}
|
||||
@@ -68,8 +51,6 @@ struct EmeraldAvatarLocalBoobConfig
|
||||
{
|
||||
return
|
||||
actualBoobGrav == other.actualBoobGrav &&
|
||||
actualButtGrav == other.actualButtGrav &&
|
||||
actualFatGrav == other.actualFatGrav &&
|
||||
boobSize == other.boobSize;
|
||||
}
|
||||
|
||||
@@ -88,8 +69,6 @@ struct EmeraldBoobState
|
||||
F32 frameDuration;
|
||||
LLVector3 chestDisplacement;
|
||||
LLVector3 localChestDisplacement;
|
||||
LLVector3 displacementForce;
|
||||
F32 mysteryValue;
|
||||
std::list<EmeraldBoobBounceState> bounceStates;
|
||||
|
||||
EmeraldBoobState()
|
||||
@@ -99,9 +78,7 @@ struct EmeraldBoobState
|
||||
elapsedTime(0.0f),
|
||||
frameDuration(0.0f),
|
||||
chestDisplacement(0.0f,0.0f,0.0f),
|
||||
localChestDisplacement(0.0f,0.0f,0.0f),
|
||||
displacementForce(0.0f,0.0f,0.0f),
|
||||
mysteryValue(0.0f)
|
||||
localChestDisplacement(0.0f,0.0f,0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -115,8 +92,6 @@ struct EmeraldBoobState
|
||||
frameDuration == other.frameDuration &&
|
||||
chestDisplacement == other.chestDisplacement &&
|
||||
localChestDisplacement == other.localChestDisplacement &&
|
||||
displacementForce == other.displacementForce &&
|
||||
mysteryValue == other.mysteryValue &&
|
||||
bounceStates == other.bounceStates;
|
||||
}
|
||||
};
|
||||
@@ -128,17 +103,11 @@ struct EmeraldBoobInputs
|
||||
LLVector3 chestPosition;
|
||||
LLQuaternion chestRotation;
|
||||
F32 elapsedTime;
|
||||
bool appearanceFlag;
|
||||
bool appearanceAnimating;
|
||||
S32 type;
|
||||
|
||||
EmeraldBoobInputs()
|
||||
: chestPosition(0.0f,0.0f,0.0f),
|
||||
chestRotation(0.0f,0.0f,0.0f,1.0f),
|
||||
elapsedTime(0.0f),
|
||||
appearanceFlag(false),
|
||||
appearanceAnimating(false),
|
||||
type(0)
|
||||
elapsedTime(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -147,10 +116,7 @@ struct EmeraldBoobInputs
|
||||
return
|
||||
chestPosition == other.chestPosition &&
|
||||
chestRotation == other.chestRotation &&
|
||||
elapsedTime == other.elapsedTime &&
|
||||
appearanceFlag == other.appearanceFlag &&
|
||||
appearanceAnimating == other.appearanceAnimating &&
|
||||
type == other.type;
|
||||
elapsedTime == other.elapsedTime;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3344,13 +3344,12 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void *
|
||||
else
|
||||
{
|
||||
// no cache of this bake. request upload.
|
||||
gAgentAvatarp->requestLayerSetUpload(baked_index);
|
||||
gAgentAvatarp->invalidateComposite(gAgentAvatarp->getLayerSet(baked_index),TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
llinfos << "Received cached texture response for " << num_results << " textures." << llendl;
|
||||
gAgentAvatarp->outputRezTiming("Fetched agent wearables textures from cache. Will now load them");
|
||||
|
||||
@@ -3885,7 +3884,7 @@ void LLAgent::sendAgentSetAppearance()
|
||||
return;
|
||||
}
|
||||
|
||||
llinfos << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << llendl;
|
||||
LL_INFOS("Avatar") << gAgentAvatarp->avString() << "TAT: Sent AgentSetAppearance: " << gAgentAvatarp->getBakedStatusForPrintout() << LL_ENDL;
|
||||
//dumpAvatarTEs( "sendAgentSetAppearance()" );
|
||||
|
||||
LLMessageSystem* msg = gMessageSystem;
|
||||
@@ -3943,14 +3942,14 @@ void LLAgent::sendAgentSetAppearance()
|
||||
// only update cache entries if we have all our baked textures
|
||||
if (textures_current)
|
||||
{
|
||||
llinfos << "TAT: Sending cached texture data" << llendl;
|
||||
LL_INFOS("Avatar") << gAgentAvatarp->avString() << "TAT: Sending cached texture data" << LL_ENDL;
|
||||
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
|
||||
{
|
||||
BOOL generate_valid_hash = TRUE;
|
||||
if (isAgentAvatarValid() && !gAgentAvatarp->isBakedTextureFinal((LLVOAvatarDefines::EBakedTextureIndex)baked_index))
|
||||
{
|
||||
generate_valid_hash = FALSE;
|
||||
llinfos << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << llendl;
|
||||
LL_DEBUGS("Avatar") << gAgentAvatarp->avString() << "Not caching baked texture upload for " << (U32)baked_index << " due to being uploaded at low resolution." << LL_ENDL;
|
||||
}
|
||||
|
||||
const LLUUID hash = gAgentWearables.computeBakedTextureHash((EBakedTextureIndex) baked_index, generate_valid_hash);
|
||||
|
||||
@@ -281,8 +281,6 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const LLWearableType::ETy
|
||||
const LLUUID& item_id,
|
||||
LLWearable* wearable)
|
||||
{
|
||||
//llassert_always(index == 0);
|
||||
|
||||
llinfos << "type " << type << " index " << index << " item " << item_id.asString() << llendl;
|
||||
|
||||
if (item_id.isNull())
|
||||
@@ -472,29 +470,28 @@ void LLAgentWearables::saveWearable(const LLWearableType::EType type, const U32
|
||||
}
|
||||
}
|
||||
|
||||
void LLAgentWearables::saveWearableAs(const LLWearableType::EType type,
|
||||
LLWearable* LLAgentWearables::saveWearableAs(const LLWearableType::EType type,
|
||||
const U32 index,
|
||||
const std::string& new_name,
|
||||
BOOL save_in_lost_and_found)
|
||||
{
|
||||
//llassert_always(index == 0);
|
||||
if (!isWearableCopyable(type, index))
|
||||
{
|
||||
llwarns << "LLAgent::saveWearableAs() not copyable." << llendl;
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
LLWearable* old_wearable = getWearable(type, index);
|
||||
if (!old_wearable)
|
||||
{
|
||||
llwarns << "LLAgent::saveWearableAs() no old wearable." << llendl;
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LLInventoryItem* item = gInventory.getItem(getWearableItemID(type,index));
|
||||
if (!item)
|
||||
{
|
||||
llwarns << "LLAgent::saveWearableAs() no inventory item." << llendl;
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
std::string trunc_name(new_name);
|
||||
LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN);
|
||||
@@ -532,6 +529,7 @@ void LLAgentWearables::saveWearableAs(const LLWearableType::EType type,
|
||||
// unsaved changes so other inventory items aren't affected by the changes
|
||||
// that were just saved.
|
||||
old_wearable->revertValues();
|
||||
return new_wearable;
|
||||
}
|
||||
|
||||
void LLAgentWearables::revertWearable(const LLWearableType::EType type, const U32 index)
|
||||
@@ -755,7 +753,7 @@ void LLAgentWearables::setWearable(const LLWearableType::EType type, U32 index,
|
||||
pushWearable(type,wearable);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
|
||||
if (wearable_iter == mWearableDatas.end())
|
||||
{
|
||||
@@ -831,6 +829,13 @@ void LLAgentWearables::wearableUpdated(LLWearable *wearable)
|
||||
saveWearable(wearable->getType(),index,TRUE);
|
||||
}
|
||||
|
||||
//Needed as wearable 'save' process is a mess and fires superfluous updateScrollingPanelList calls
|
||||
//while the wearable being created has not yet been stuffed into the wearable list.
|
||||
//This results in the param hints being buggered and screwing up the current wearable during LLVisualParamHint::preRender,
|
||||
//thus making the wearable 'dirty'. The code below basically 'forces' a refresh of the panel to fix this.
|
||||
if(gFloaterCustomize)
|
||||
gFloaterCustomize->wearablesChanged(wearable->getType());
|
||||
|
||||
}
|
||||
|
||||
void LLAgentWearables::popWearable(LLWearable *wearable)
|
||||
@@ -1607,7 +1612,16 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
|
||||
{
|
||||
gAgentAvatarp->setCompositeUpdatesEnabled(TRUE);
|
||||
gAgentAvatarp->updateVisualParams();
|
||||
gAgentAvatarp->invalidateAll();
|
||||
|
||||
// If we have not yet declouded, we may want to use
|
||||
// baked texture UUIDs sent from the first objectUpdate message
|
||||
// don't overwrite these. If we have already declouded, we've saved
|
||||
// these ids as the last known good textures and can invalidate without
|
||||
// re-clouding.
|
||||
if (!gAgentAvatarp->getIsCloud())
|
||||
{
|
||||
gAgentAvatarp->invalidateAll();
|
||||
}
|
||||
}
|
||||
|
||||
// Start rendering & update the server
|
||||
@@ -1695,21 +1709,21 @@ bool LLAgentWearables::onSetWearableDialog( const LLSD& notification, const LLSD
|
||||
|
||||
switch( option )
|
||||
{
|
||||
case 0: // "Save"
|
||||
case 0: // "Save"
|
||||
gAgentWearables.saveWearable(wearable->getType(),index);
|
||||
gAgentWearables.setWearableFinal( new_item, wearable );
|
||||
break;
|
||||
gAgentWearables.setWearableFinal( new_item, wearable );
|
||||
break;
|
||||
|
||||
case 1: // "Don't Save"
|
||||
gAgentWearables.setWearableFinal( new_item, wearable );
|
||||
break;
|
||||
case 1: // "Don't Save"
|
||||
gAgentWearables.setWearableFinal( new_item, wearable );
|
||||
break;
|
||||
|
||||
case 2: // "Cancel"
|
||||
break;
|
||||
case 2: // "Cancel"
|
||||
break;
|
||||
|
||||
default:
|
||||
llassert(0);
|
||||
break;
|
||||
default:
|
||||
llassert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
delete wearable;
|
||||
@@ -1725,10 +1739,11 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n
|
||||
if (do_append && getWearableItemID(type,0).notNull())
|
||||
{
|
||||
new_wearable->setItemID(new_item->getUUID());
|
||||
mWearableDatas[type].push_back(new_wearable);
|
||||
/*mWearableDatas[type].push_back(new_wearable);
|
||||
llinfos << "Added additional wearable for type " << type
|
||||
<< " size is now " << mWearableDatas[type].size() << llendl;
|
||||
checkWearableAgainstInventory(new_wearable);
|
||||
checkWearableAgainstInventory(new_wearable);*/
|
||||
pushWearable(type,new_wearable); //To call LLAgentWearables::wearableUpdated
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1808,7 +1823,8 @@ void LLAgentWearables::queryWearableCache()
|
||||
{
|
||||
gAgentAvatarp->outputRezTiming("Fetching textures from cache");
|
||||
}
|
||||
llinfos << "Requesting texture cache entry for " << num_queries << " baked textures" << llendl;
|
||||
|
||||
LL_INFOS("Avatar") << gAgentAvatarp->avString() << "Requesting texture cache entry for " << num_queries << " baked textures" << LL_ENDL;
|
||||
gMessageSystem->sendReliable(gAgent.getRegion()->getHost());
|
||||
gAgentQueryManager.mNumPendingQueries++;
|
||||
gAgentQueryManager.mWearablesCacheQueryID++;
|
||||
@@ -2210,6 +2226,12 @@ bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool clos
|
||||
U32 swap_i = closer_to_body ? i-1 : i+1;
|
||||
wearable_vec[i] = wearable_vec[swap_i];
|
||||
wearable_vec[swap_i] = wearable;
|
||||
|
||||
if(gFloaterCustomize)
|
||||
{
|
||||
gFloaterCustomize->wearablesChanged(item->getWearableType());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2337,6 +2359,11 @@ boost::signals2::connection LLAgentWearables::addInitialWearablesLoadedCallback(
|
||||
}
|
||||
// [/SL:KB]
|
||||
|
||||
bool LLAgentWearables::changeInProgress() const
|
||||
{
|
||||
return mCOFChangeInProgress;
|
||||
}
|
||||
|
||||
void LLAgentWearables::notifyLoadingStarted()
|
||||
{
|
||||
mCOFChangeInProgress = true;
|
||||
|
||||
@@ -205,7 +205,7 @@ private:
|
||||
// Save Wearables
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
void saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, BOOL save_in_lost_and_found);
|
||||
LLWearable* saveWearableAs(const LLWearableType::EType type, const U32 index, const std::string& new_name, BOOL save_in_lost_and_found);
|
||||
void saveWearable(const LLWearableType::EType type, const U32 index, BOOL send_update = TRUE,
|
||||
const std::string new_name = "");
|
||||
void saveAllWearables();
|
||||
@@ -247,6 +247,7 @@ public:
|
||||
boost::signals2::connection addInitialWearablesLoadedCallback(loaded_callback_t cb);
|
||||
// [/SL:KB]
|
||||
|
||||
bool changeInProgress() const;
|
||||
void notifyLoadingStarted();
|
||||
void notifyLoadingFinished();
|
||||
|
||||
|
||||
@@ -54,6 +54,11 @@
|
||||
#include "rlvlocks.h"
|
||||
// [/RLVa:KB]
|
||||
|
||||
std::string self_av_string()
|
||||
{
|
||||
return gAgentAvatarp->avString();
|
||||
}
|
||||
|
||||
// RAII thingy to guarantee that a variable gets reset when the Setter
|
||||
// goes out of scope. More general utility would be handy - TODO:
|
||||
// check boost.
|
||||
@@ -160,6 +165,8 @@ public:
|
||||
{
|
||||
mCatID = cat_id;
|
||||
mAppend = append;
|
||||
|
||||
LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL;
|
||||
}
|
||||
void fire(const LLUUID& item_id)
|
||||
{
|
||||
@@ -171,12 +178,13 @@ public:
|
||||
* after the last item has fired the event and dereferenced it -- if all
|
||||
* the events actually fire!
|
||||
*/
|
||||
LL_DEBUGS("Avatar") << self_av_string() << " fired on copied item, id " << item_id << LL_ENDL;
|
||||
}
|
||||
|
||||
protected:
|
||||
~LLWearInventoryCategoryCallback()
|
||||
{
|
||||
llinfos << "done all inventory callbacks" << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "done all inventory callbacks" << LL_ENDL;
|
||||
|
||||
// Is the destructor called by ordinary dereference, or because the app's shutting down?
|
||||
// If the inventory callback manager goes away, we're shutting down, no longer want the callback.
|
||||
@@ -186,7 +194,7 @@ protected:
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl;
|
||||
llwarns << self_av_string() << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +228,7 @@ LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit
|
||||
|
||||
LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy()
|
||||
{
|
||||
LL_INFOS("Avatar") << self_av_string() << "done update appearance on destroy" << LL_ENDL;
|
||||
llinfos << "done update appearance on destroy" << llendl;
|
||||
|
||||
if (!LLApp::isExiting())
|
||||
@@ -233,7 +242,7 @@ void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item)
|
||||
LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item);
|
||||
const std::string item_name = item ? item->getName() : "ITEM NOT FOUND";
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
llinfos << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << llendl;
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL;
|
||||
#endif
|
||||
mFireCount++;
|
||||
}
|
||||
@@ -399,7 +408,8 @@ void LLWearableHoldingPattern::checkMissingWearables()
|
||||
{
|
||||
if (!isMostRecent())
|
||||
{
|
||||
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
// runway why don't we actually skip here?
|
||||
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
}
|
||||
|
||||
std::vector<S32> found_by_type(LLWearableType::WT_COUNT,0);
|
||||
@@ -417,7 +427,7 @@ void LLWearableHoldingPattern::checkMissingWearables()
|
||||
{
|
||||
if (requested_by_type[type] > found_by_type[type])
|
||||
{
|
||||
llwarns << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl;
|
||||
llwarns << self_av_string() << "got fewer wearables than requested, type " << type << ": requested " << requested_by_type[type] << ", found " << found_by_type[type] << llendl;
|
||||
}
|
||||
if (found_by_type[type] > 0)
|
||||
continue;
|
||||
@@ -434,7 +444,7 @@ void LLWearableHoldingPattern::checkMissingWearables()
|
||||
mTypesToRecover.insert(type);
|
||||
mTypesToLink.insert(type);
|
||||
recoverMissingWearable((LLWearableType::EType)type);
|
||||
llwarns << "need to replace " << type << llendl;
|
||||
llwarns << self_av_string() << "need to replace " << type << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,13 +464,14 @@ void LLWearableHoldingPattern::onAllComplete()
|
||||
|
||||
if (!isMostRecent())
|
||||
{
|
||||
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
// runway need to skip here?
|
||||
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
}
|
||||
|
||||
// Activate all gestures in this folder
|
||||
if (mGestItems.count() > 0)
|
||||
{
|
||||
llinfos << "Activating " << mGestItems.count() << " gestures" << llendl;
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "Activating " << mGestItems.count() << " gestures" << LL_ENDL;
|
||||
|
||||
LLGestureMgr::instance().activateGestures(mGestItems);
|
||||
|
||||
@@ -477,7 +488,7 @@ void LLWearableHoldingPattern::onAllComplete()
|
||||
}
|
||||
|
||||
// Update wearables.
|
||||
llinfos << "Updating agent wearables with " << mResolved << " wearable items " << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "Updating agent wearables with " << mResolved << " wearable items " << LL_ENDL;
|
||||
LLAppearanceMgr::instance().updateAgentWearables(this, false);
|
||||
|
||||
// [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-03-22 (Catznip-3.0.0a) | Added: Catznip-2.1.2a
|
||||
@@ -504,7 +515,8 @@ void LLWearableHoldingPattern::onFetchCompletion()
|
||||
{
|
||||
if (!isMostRecent())
|
||||
{
|
||||
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
// runway skip here?
|
||||
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
}
|
||||
|
||||
checkMissingWearables();
|
||||
@@ -515,7 +527,8 @@ bool LLWearableHoldingPattern::pollFetchCompletion()
|
||||
{
|
||||
if (!isMostRecent())
|
||||
{
|
||||
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
// runway skip here?
|
||||
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
|
||||
// [SL:KB] - Patch: Appearance-COFCorruption | Checked: 2010-04-14 (Catznip-3.0.0a) | Added: Catznip-2.0.0a
|
||||
// If we were signalled to stop then we shouldn't do anything else except poll for when it's safe to delete ourselves
|
||||
@@ -530,14 +543,14 @@ bool LLWearableHoldingPattern::pollFetchCompletion()
|
||||
|
||||
if (done)
|
||||
{
|
||||
llinfos << "polling, done status: " << completed << " timed out " << timed_out
|
||||
<< " elapsed " << mWaitTime.getElapsedTimeF32() << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "polling, done status: " << completed << " timed out " << timed_out
|
||||
<< " elapsed " << mWaitTime.getElapsedTimeF32() << LL_ENDL;
|
||||
|
||||
mFired = true;
|
||||
|
||||
if (timed_out)
|
||||
{
|
||||
llwarns << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl;
|
||||
llwarns << self_av_string() << "Exceeded max wait time for wearables, updating appearance based on what has arrived" << llendl;
|
||||
}
|
||||
|
||||
onFetchCompletion();
|
||||
@@ -585,12 +598,12 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "inventory item not found for recovered wearable" << llendl;
|
||||
llwarns << self_av_string() << "inventory item not found for recovered wearable" << llendl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "inventory link not found for recovered wearable" << llendl;
|
||||
llwarns << self_av_string() << "inventory link not found for recovered wearable" << llendl;
|
||||
}
|
||||
}
|
||||
private:
|
||||
@@ -612,7 +625,8 @@ public:
|
||||
{
|
||||
if (!mHolder->isMostRecent())
|
||||
{
|
||||
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
// runway skip here?
|
||||
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
|
||||
// [SL:KB] - Patch: Appearance-COFCorruption | Checked: 2010-04-14 (Catznip-3.0.0a) | Added: Catznip-2.0.0a
|
||||
// If we were signalled to stop then we shouldn't do anything else except poll for when it's safe to delete ourselves
|
||||
@@ -620,7 +634,7 @@ public:
|
||||
// [/SL:KB]
|
||||
}
|
||||
|
||||
llinfos << "Recovered item for type " << mType << llendl;
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "Recovered item for type " << mType << LL_ENDL;
|
||||
LLViewerInventoryItem *itemp = gInventory.getItem(item_id);
|
||||
mWearable->setItemID(item_id);
|
||||
LLPointer<LLInventoryCallback> cb = new RecoveredItemLinkCB(mType,mWearable,mHolder);
|
||||
@@ -647,7 +661,8 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type
|
||||
{
|
||||
if (!isMostRecent())
|
||||
{
|
||||
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
// runway skip here?
|
||||
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
}
|
||||
|
||||
// Try to recover by replacing missing wearable with a new one.
|
||||
@@ -686,7 +701,7 @@ void LLWearableHoldingPattern::clearCOFLinksForMissingWearables()
|
||||
if ((data.mWearableType < LLWearableType::WT_COUNT) && (!data.mWearable))
|
||||
{
|
||||
// Wearable link that was never resolved; remove links to it from COF
|
||||
llinfos << "removing link for unresolved item " << data.mItemID.asString() << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "removing link for unresolved item " << data.mItemID.asString() << LL_ENDL;
|
||||
LLAppearanceMgr::instance().removeCOFItemLinks(data.mItemID,false);
|
||||
}
|
||||
}
|
||||
@@ -709,7 +724,8 @@ bool LLWearableHoldingPattern::pollMissingWearables()
|
||||
{
|
||||
if (!isMostRecent())
|
||||
{
|
||||
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
// runway skip here?
|
||||
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
|
||||
// [SL:KB] - Patch: Appearance-COFCorruption | Checked: 2010-04-14 (Catznip-3.0.0a) | Added: Catznip-2.0.0a
|
||||
// If we were signalled to stop then we shouldn't do anything else except poll for when it's safe to delete ourselves
|
||||
@@ -724,11 +740,11 @@ bool LLWearableHoldingPattern::pollMissingWearables()
|
||||
|
||||
if (!done)
|
||||
{
|
||||
llinfos << "polling missing wearables, waiting for items " << mTypesToRecover.size()
|
||||
LL_INFOS("Avatar") << self_av_string() << "polling missing wearables, waiting for items " << mTypesToRecover.size()
|
||||
<< " links " << mTypesToLink.size()
|
||||
<< " wearables, timed out " << timed_out
|
||||
<< " elapsed " << mWaitTime.getElapsedTimeF32()
|
||||
<< " done " << done << llendl;
|
||||
<< " done " << done << LL_ENDL;
|
||||
}
|
||||
|
||||
if (done)
|
||||
@@ -762,14 +778,14 @@ void LLWearableHoldingPattern::handleLateArrivals()
|
||||
}
|
||||
if (!isMostRecent())
|
||||
{
|
||||
llwarns << "Late arrivals not handled - outfit change no longer valid" << llendl;
|
||||
llwarns << self_av_string() << "Late arrivals not handled - outfit change no longer valid" << llendl;
|
||||
}
|
||||
if (!mIsAllComplete)
|
||||
{
|
||||
llwarns << "Late arrivals not handled - in middle of missing wearables processing" << llendl;
|
||||
llwarns << self_av_string() << "Late arrivals not handled - in middle of missing wearables processing" << llendl;
|
||||
}
|
||||
|
||||
llinfos << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "Need to handle " << mLateArrivals.size() << " late arriving wearables" << LL_ENDL;
|
||||
|
||||
// Update mFoundList using late-arriving wearables.
|
||||
std::set<LLWearableType::EType> replaced_types;
|
||||
@@ -845,19 +861,19 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable)
|
||||
{
|
||||
if (!isMostRecent())
|
||||
{
|
||||
llwarns << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
llwarns << self_av_string() << "skipping because LLWearableHolding pattern is invalid (superceded by later outfit request)" << llendl;
|
||||
}
|
||||
|
||||
mResolved += 1; // just counting callbacks, not successes.
|
||||
llinfos << "resolved " << mResolved << "/" << getFoundList().size() << llendl;
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "resolved " << mResolved << "/" << getFoundList().size() << LL_ENDL;
|
||||
if (!wearable)
|
||||
{
|
||||
llwarns << "no wearable found" << llendl;
|
||||
llwarns << self_av_string() << "no wearable found" << llendl;
|
||||
}
|
||||
|
||||
if (mFired)
|
||||
{
|
||||
llwarns << "called after holder fired" << llendl;
|
||||
llwarns << self_av_string() << "called after holder fired" << llendl;
|
||||
if (wearable)
|
||||
{
|
||||
mLateArrivals.insert(wearable);
|
||||
@@ -883,7 +899,7 @@ void LLWearableHoldingPattern::onWearableAssetFetch(LLWearable *wearable)
|
||||
// Failing this means inventory or asset server are corrupted in a way we don't handle.
|
||||
if ((data.mWearableType >= LLWearableType::WT_COUNT) || (wearable->getType() != data.mWearableType))
|
||||
{
|
||||
llwarns << "recovered wearable but type invalid. inventory wearable type: " << data.mWearableType << " asset wearable type: " << wearable->getType() << llendl;
|
||||
llwarns << self_av_string() << "recovered wearable but type invalid. inventory wearable type: " << data.mWearableType << " asset wearable type: " << wearable->getType() << llendl;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1554,7 +1570,7 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid,
|
||||
const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid);
|
||||
const std::string cat_name = cat ? cat->getName() : "CAT NOT FOUND";
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
llinfos << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << llendl;
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "Linking Item [ name:" << item->getName() << " UUID:" << item->getUUID() << " ] to Category [ name:" << cat_name << " UUID:" << cat_uuid << " ] " << LL_ENDL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1685,7 +1701,7 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new,
|
||||
removeDuplicateItems(gest_items);
|
||||
|
||||
// Create links to new COF contents.
|
||||
llinfos << "creating LLUpdateAppearanceOnDestroy" << llendl;
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "creating LLUpdateAppearanceOnDestroy" << LL_ENDL;
|
||||
LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(!append);
|
||||
|
||||
// [SL:KB] - Checked: 2010-04-24 (RLVa-1.2.0f) | Added: RLVa-1.2.0f
|
||||
@@ -1696,24 +1712,24 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new,
|
||||
bool keep_outfit_links = append;
|
||||
purgeCategory(cof, keep_outfit_links);
|
||||
gInventory.notifyObservers();
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
llinfos << "Linking body items" << llendl;
|
||||
#endif
|
||||
linkAll(cof, body_items, link_waiter);
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "Linking body items" << LL_ENDL;
|
||||
#endif
|
||||
linkAll(cof, body_items, link_waiter);
|
||||
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
llinfos << "Linking wear items" << llendl;
|
||||
#endif
|
||||
linkAll(cof, wear_items, link_waiter);
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "Linking wear items" << LL_ENDL;
|
||||
#endif
|
||||
linkAll(cof, wear_items, link_waiter);
|
||||
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
llinfos << "Linking obj items" << llendl;
|
||||
#endif
|
||||
linkAll(cof, obj_items, link_waiter);
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "Linking obj items" << LL_ENDL;
|
||||
#endif
|
||||
linkAll(cof, obj_items, link_waiter);
|
||||
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
llinfos << "Linking gesture items" << llendl;
|
||||
#endif
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "Linking gesture items" << LL_ENDL;
|
||||
#endif
|
||||
linkAll(cof, gest_items, link_waiter);
|
||||
// [SL:KB] - Checked: 2010-04-24 (RLVa-1.2.0f) | Added: RLVa-1.2.0f
|
||||
}
|
||||
@@ -1741,7 +1757,7 @@ void LLAppearanceMgr::updateCOF(LLInventoryModel::item_array_t& body_items_new,
|
||||
// createBaseOutfitLink(category, link_waiter);
|
||||
// }
|
||||
|
||||
llinfos << "waiting for LLUpdateAppearanceOnDestroy" << llendl;
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLAppearanceMgr::updatePanelOutfitName(const std::string& name)
|
||||
@@ -1954,7 +1970,7 @@ void LLAppearanceMgr::enforceItemRestrictions()
|
||||
++it)
|
||||
{
|
||||
LLViewerInventoryItem *item = *it;
|
||||
llinfos << "purging duplicate or excess item " << item->getName() << llendl;
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "purging duplicate or excess item " << item->getName() << LL_ENDL;
|
||||
gInventory.purgeObject(item->getUUID());
|
||||
}
|
||||
gInventory.notifyObservers();
|
||||
@@ -1971,7 +1987,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
|
||||
|
||||
BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
|
||||
|
||||
llinfos << "starting" << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL;
|
||||
|
||||
//checking integrity of the COF in terms of ordering of wearables,
|
||||
//checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state)
|
||||
@@ -2125,7 +2141,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering)
|
||||
{
|
||||
LLFoundData& found = *it;
|
||||
|
||||
lldebugs << "waiting for onWearableAssetFetch callback, asset " << found.mAssetID.asString() << llendl;
|
||||
lldebugs << self_av_string() << "waiting for onWearableAssetFetch callback, asset " << found.mAssetID.asString() << llendl;
|
||||
|
||||
// Fetch the wearables about to be worn.
|
||||
LLWearableList::instance().getAsset(found.mAssetID,
|
||||
@@ -2214,8 +2230,8 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
|
||||
|
||||
gAgentWearables.notifyLoadingStarted();
|
||||
|
||||
llinfos << "wearInventoryCategory( " << category->getName()
|
||||
<< " )" << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategory( " << category->getName()
|
||||
<< " )" << LL_ENDL;
|
||||
|
||||
callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
|
||||
&LLAppearanceMgr::instance(),
|
||||
@@ -2224,7 +2240,7 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
|
||||
|
||||
void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool append)
|
||||
{
|
||||
llinfos << "starting" << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL;
|
||||
|
||||
// We now have an outfit ready to be copied to agent inventory. Do
|
||||
// it, and wear that outfit normally.
|
||||
@@ -2307,8 +2323,8 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego
|
||||
// wearables being dirty.
|
||||
if(!category) return;
|
||||
|
||||
llinfos << "wearInventoryCategoryOnAvatar( " << category->getName()
|
||||
<< " )" << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategoryOnAvatar '" << category->getName()
|
||||
<< "'" << LL_ENDL;
|
||||
|
||||
if (gAgentCamera.cameraCustomizeAvatar())
|
||||
{
|
||||
@@ -2321,7 +2337,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego
|
||||
|
||||
void LLAppearanceMgr::wearOutfitByName(const std::string& name)
|
||||
{
|
||||
llinfos << "Wearing category " << name << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "Wearing category " << name << LL_ENDL;
|
||||
//inc_busy_count();
|
||||
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
@@ -2492,7 +2508,21 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update
|
||||
{
|
||||
cb = new ModifiedCOFCallback;
|
||||
}
|
||||
const std::string description = vitem->getIsLinkType() ? vitem->getDescription() : "";
|
||||
std::string description = vitem->getIsLinkType() ? vitem->getDescription() : "";
|
||||
if(description.empty())
|
||||
{
|
||||
LLWearable* wearable = gAgentWearables.getWearableFromItemID(vitem->getLinkedUUID());
|
||||
if(wearable)
|
||||
{
|
||||
U32 index = gAgentWearables.getWearableIndex(wearable);
|
||||
if(index < LLAgentWearables::MAX_CLOTHING_PER_TYPE)
|
||||
{
|
||||
std::ostringstream order_num;
|
||||
order_num << ORDER_NUMBER_SEPARATOR << wearable->getType() * 100 + index;
|
||||
description = order_num.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
link_inventory_item( gAgent.getID(),
|
||||
vitem->getLinkedUUID(),
|
||||
getCOF(),
|
||||
@@ -2651,7 +2681,7 @@ const std::string OTHER_GESTURES_FOLDER = "Other Gestures";
|
||||
|
||||
void LLAppearanceMgr::copyLibraryGestures()
|
||||
{
|
||||
llinfos << "Copying library gestures" << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "Copying library gestures" << LL_ENDL;
|
||||
|
||||
// Copy gestures
|
||||
LLUUID lib_gesture_cat_id =
|
||||
@@ -2707,11 +2737,11 @@ void LLAppearanceMgr::copyLibraryGestures()
|
||||
LLUUID cat_id = findDescendentCategoryIDByName(lib_gesture_cat_id,folder_name);
|
||||
if (cat_id.isNull())
|
||||
{
|
||||
llwarns << "failed to find gesture folder for " << folder_name << llendl;
|
||||
llwarns << self_av_string() << "failed to find gesture folder for " << folder_name << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
llinfos << "initiating fetch and copy for " << folder_name << " cat_id " << cat_id << llendl;
|
||||
LL_DEBUGS("Avatar") << self_av_string() << "initiating fetch and copy for " << folder_name << " cat_id " << cat_id << LL_ENDL;
|
||||
callAfterCategoryFetch(cat_id,
|
||||
boost::bind(&LLAppearanceMgr::shallowCopyCategory,
|
||||
&LLAppearanceMgr::instance(),
|
||||
@@ -2725,7 +2755,7 @@ void LLAppearanceMgr::autopopulateOutfits()
|
||||
// If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account)
|
||||
// then auto-populate outfits from the library into the My Outfits folder.
|
||||
|
||||
llinfos << "avatar fully visible" << llendl;
|
||||
LL_INFOS("Avatar") << self_av_string() << "avatar fully visible" << LL_ENDL;
|
||||
|
||||
static bool check_populate_my_outfits = true;
|
||||
if (check_populate_my_outfits &&
|
||||
@@ -3454,9 +3484,8 @@ void LLAppearanceMgr::dumpItemArray(const LLInventoryModel::item_array_t& items,
|
||||
{
|
||||
asset_id = linked_item->getAssetUUID();
|
||||
}
|
||||
llinfos << msg << " " << i <<" " << (item ? item->getName() : "(nullitem)") << " " << asset_id.asString() << llendl;
|
||||
LL_DEBUGS("Avatar") << self_av_string() << msg << " " << i <<" " << (item ? item->getName() : "(nullitem)") << " " << asset_id.asString() << LL_ENDL;
|
||||
}
|
||||
llinfos << llendl;
|
||||
}
|
||||
|
||||
LLAppearanceMgr::LLAppearanceMgr():
|
||||
|
||||
@@ -4040,7 +4040,9 @@ void LLAppViewer::idle()
|
||||
//
|
||||
if (!gNoRender)
|
||||
{
|
||||
#if ENABLE_CLASSIC_CLOUDS
|
||||
LLWorld::getInstance()->updateClouds(gFrameDTClamped);
|
||||
#endif
|
||||
gSky.propagateHeavenlyBodies(gFrameDTClamped); // moves sun, moon, and planets
|
||||
|
||||
// Update wind vector
|
||||
@@ -4056,9 +4058,10 @@ void LLAppViewer::idle()
|
||||
// Compute average wind and use to drive motion of water
|
||||
|
||||
average_wind = regionp->mWind.getAverage();
|
||||
#if ENABLE_CLASSIC_CLOUDS
|
||||
F32 cloud_density = regionp->mCloudLayer.getDensityRegion(wind_position_region);
|
||||
|
||||
gSky.setCloudDensityAtAgent(cloud_density);
|
||||
#endif
|
||||
gSky.setWind(average_wind);
|
||||
//LLVOWater::setWind(average_wind);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
// Viewer includes
|
||||
#include "llagent.h"
|
||||
#include "llviewergenericmessage.h"
|
||||
#include "llstartup.h"
|
||||
|
||||
// Linden library includes
|
||||
#include "llavatarconstants.h" // AVATAR_TRANSACTED, etc.
|
||||
@@ -111,6 +112,14 @@ void LLAvatarPropertiesProcessor::sendGenericRequest(const LLUUID& avatar_id, EA
|
||||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarPropertiesRequest(const LLUUID& avatar_id)
|
||||
{
|
||||
// this is the startup state when send_complete_agent_movement() message is sent.
|
||||
// Before this, the AvatarPropertiesRequest message
|
||||
// won't work so don't bother trying
|
||||
if (LLStartUp::getStartupState() <= STATE_AGENT_SEND)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPendingRequest(avatar_id, APT_PROPERTIES))
|
||||
{
|
||||
// waiting for a response, don't re-request
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "lldrawpool.h"
|
||||
#include "llworld.h"
|
||||
|
||||
#if ENABLE_CLASSIC_CLOUDS
|
||||
extern LLPipeline gPipeline;
|
||||
|
||||
const F32 CLOUD_UPDATE_RATE = 1.0f; // Global time dilation for clouds
|
||||
@@ -544,3 +545,4 @@ void LLCloudLayer::disconnectAllNeighbors()
|
||||
disconnectNeighbor(i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -89,6 +89,7 @@ class LLCloudLayer;
|
||||
class LLBitPack;
|
||||
class LLGroupHeader;
|
||||
|
||||
#if ENABLE_CLASSIC_CLOUDS
|
||||
const S32 CLOUD_GROUPS_PER_EDGE = 4;
|
||||
|
||||
class LLCloudPuff
|
||||
@@ -201,5 +202,5 @@ protected:
|
||||
LLCloudGroup mCloudGroups[CLOUD_GROUPS_PER_EDGE][CLOUD_GROUPS_PER_EDGE];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -390,7 +390,9 @@ void LLDrawable::makeActive()
|
||||
pcode == LLViewerObject::LL_VO_SURFACE_PATCH ||
|
||||
pcode == LLViewerObject::LL_VO_PART_GROUP ||
|
||||
pcode == LLViewerObject::LL_VO_HUD_PART_GROUP ||
|
||||
#if ENABLE_CLASSIC_CLOUDS
|
||||
pcode == LLViewerObject::LL_VO_CLOUDS ||
|
||||
#endif
|
||||
pcode == LLViewerObject::LL_VO_GROUND ||
|
||||
pcode == LLViewerObject::LL_VO_SKY)
|
||||
{
|
||||
@@ -454,7 +456,7 @@ void LLDrawable::makeStatic(BOOL warning_enabled)
|
||||
{
|
||||
if (isState(ACTIVE))
|
||||
{
|
||||
clearState(ACTIVE);
|
||||
clearState(ACTIVE | ANIMATED_CHILD);
|
||||
|
||||
if (mParent.notNull() && mParent->isActive() && warning_enabled)
|
||||
{
|
||||
@@ -542,9 +544,9 @@ F32 LLDrawable::updateXform(BOOL undamped)
|
||||
target_rot = new_rot;
|
||||
target_scale = new_scale;
|
||||
}
|
||||
else
|
||||
else if (mVObjp->getAngularVelocity().isExactlyZero())
|
||||
{
|
||||
// snap to final position
|
||||
// snap to final position (only if no target omega is applied)
|
||||
dist_squared = 0.0f;
|
||||
if (getVOVolume() && !isRoot())
|
||||
{ //child prim snapping to some position, needs a rebuild
|
||||
@@ -553,15 +555,25 @@ F32 LLDrawable::updateXform(BOOL undamped)
|
||||
}
|
||||
}
|
||||
|
||||
if ((mCurrentScale != target_scale) ||
|
||||
(!isRoot() &&
|
||||
(dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED ||
|
||||
!mVObjp->getAngularVelocity().isExactlyZero() ||
|
||||
target_pos != mXform.getPosition() ||
|
||||
target_rot != mXform.getRotation())))
|
||||
{ //child prim moving or scale change requires immediate rebuild
|
||||
LLVector3 vec = mCurrentScale-target_scale;
|
||||
|
||||
if (vec*vec > MIN_INTERPOLATE_DISTANCE_SQUARED)
|
||||
{ //scale change requires immediate rebuild
|
||||
mCurrentScale = target_scale;
|
||||
gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
|
||||
}
|
||||
else if (!isRoot() &&
|
||||
(!mVObjp->getAngularVelocity().isExactlyZero() ||
|
||||
dist_squared > 0.f))
|
||||
{ //child prim moving relative to parent, tag as needing to be rendered atomically and rebuild
|
||||
dist_squared = 1.f; //keep this object on the move list
|
||||
if (!isState(LLDrawable::ANIMATED_CHILD))
|
||||
{
|
||||
setState(LLDrawable::ANIMATED_CHILD);
|
||||
gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE);
|
||||
mVObjp->dirtySpatialGroup();
|
||||
}
|
||||
}
|
||||
else if (!getVOVolume() && !isAvatar())
|
||||
{
|
||||
movePartition();
|
||||
@@ -572,9 +584,7 @@ F32 LLDrawable::updateXform(BOOL undamped)
|
||||
mXform.setRotation(target_rot);
|
||||
mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!)
|
||||
mXform.updateMatrix();
|
||||
|
||||
mCurrentScale = target_scale;
|
||||
|
||||
|
||||
if (mSpatialBridge)
|
||||
{
|
||||
gPipeline.markMoved(mSpatialBridge, FALSE);
|
||||
@@ -600,7 +610,11 @@ void LLDrawable::moveUpdatePipeline(BOOL moved)
|
||||
// Update the face centers.
|
||||
for (S32 i = 0; i < getNumFaces(); i++)
|
||||
{
|
||||
getFace(i)->updateCenterAgent();
|
||||
LLFace* face = getFace(i);
|
||||
if (face)
|
||||
{
|
||||
face->updateCenterAgent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,7 +745,8 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
|
||||
for (S32 i = 0; i < getNumFaces(); i++)
|
||||
{
|
||||
LLFace* facep = getFace(i);
|
||||
if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA)
|
||||
if (facep &&
|
||||
(force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA))
|
||||
{
|
||||
LLVector4a box;
|
||||
box.setSub(facep->mExtents[1], facep->mExtents[0]);
|
||||
@@ -830,13 +845,16 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector)
|
||||
for (S32 i = 0; i < getNumFaces(); i++)
|
||||
{
|
||||
LLFace *facep = getFace(i);
|
||||
facep->mCenterAgent += LLVector3(shift_vector.getF32ptr());
|
||||
facep->mExtents[0].add(shift_vector);
|
||||
facep->mExtents[1].add(shift_vector);
|
||||
|
||||
if (!volume && facep->hasGeometry())
|
||||
if (facep)
|
||||
{
|
||||
facep->clearVertexBuffer();
|
||||
facep->mCenterAgent += LLVector3(shift_vector.getF32ptr());
|
||||
facep->mExtents[0].add(shift_vector);
|
||||
facep->mExtents[1].add(shift_vector);
|
||||
|
||||
if (!volume && facep->hasGeometry())
|
||||
{
|
||||
facep->clearVertexBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -958,7 +976,10 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp)
|
||||
for (S32 i = 0; i < getNumFaces(); ++i)
|
||||
{
|
||||
LLFace* facep = getFace(i);
|
||||
facep->clearVertexBuffer();
|
||||
if (facep)
|
||||
{
|
||||
facep->clearVertexBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1544,15 +1565,17 @@ BOOL LLDrawable::isAnimating() const
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
#if ENABLE_CLASSIC_CLOUDS
|
||||
if (mVObjp->getPCode() == LLViewerObject::LL_VO_CLOUDS)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero())
|
||||
{
|
||||
/*if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero())
|
||||
{ //target omega
|
||||
return TRUE;
|
||||
}
|
||||
}*/
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -283,6 +283,7 @@ public:
|
||||
HAS_ALPHA = 0x04000000,
|
||||
RIGGED = 0x08000000,
|
||||
PARTITION_MOVE = 0x10000000,
|
||||
ANIMATED_CHILD = 0x20000000,
|
||||
} EDrawableFlags;
|
||||
|
||||
private: //aligned members
|
||||
@@ -339,12 +340,14 @@ inline LLFace* LLDrawable::getFace(const S32 i) const
|
||||
|
||||
if ((U32) i >= mFaces.size())
|
||||
{
|
||||
llerrs << "Invalid face index." << llendl;
|
||||
llwarns << "Invalid face index." << llendl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!mFaces[i])
|
||||
{
|
||||
llerrs << "Null face found." << llendl;
|
||||
llwarns << "Null face found." << llendl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mFaces[i];
|
||||
|
||||
@@ -404,7 +404,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
|
||||
bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow.
|
||||
// All particle systems seem to come off the wire with texture entries which claim that they glow. This is probably a bug in the data. Suppress.
|
||||
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE &&
|
||||
#if ENABLE_CLASSIC_CLOUDS
|
||||
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_CLOUD &&
|
||||
#endif
|
||||
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE;
|
||||
|
||||
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];
|
||||
@@ -413,13 +415,20 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
|
||||
{
|
||||
LLDrawInfo& params = **k;
|
||||
|
||||
if ((params.mVertexBuffer->getTypeMask() & mask) != mask)
|
||||
{ //FIXME!
|
||||
llwarns << "Missing required components, skipping render batch." << llendl;
|
||||
continue;
|
||||
}
|
||||
|
||||
LLRenderPass::applyModelMatrix(params);
|
||||
|
||||
if (params.mFullbright)
|
||||
|
||||
if (params.mFullbright)
|
||||
{
|
||||
// Turn off lighting if it hasn't already been so.
|
||||
if (light_enabled || !initialized_lighting)
|
||||
{
|
||||
// Turn off lighting if it hasn't already been so.
|
||||
if (light_enabled || !initialized_lighting)
|
||||
{
|
||||
initialized_lighting = TRUE;
|
||||
if (use_shaders)
|
||||
{
|
||||
|
||||
@@ -265,7 +265,9 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha()
|
||||
sRenderingSkinned = TRUE;
|
||||
|
||||
gPipeline.bindDeferredShader(*sVertexProgram);
|
||||
|
||||
|
||||
sVertexProgram->setMinimumAlpha(0.2f);
|
||||
|
||||
sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -88,6 +88,8 @@ public:
|
||||
|
||||
static void initClass();
|
||||
|
||||
static void cacheFaceInVRAM(const LLVolumeFace& vf);
|
||||
|
||||
public:
|
||||
LLFace(LLDrawable* drawablep, LLViewerObject* objp) { init(drawablep, objp); }
|
||||
~LLFace() { destroy(); }
|
||||
@@ -245,7 +247,6 @@ public:
|
||||
|
||||
private:
|
||||
LLPointer<LLVertexBuffer> mVertexBuffer;
|
||||
LLPointer<LLVertexBuffer> mLastVertexBuffer;
|
||||
|
||||
U32 mState;
|
||||
LLFacePool* mDrawPoolp;
|
||||
@@ -259,12 +260,6 @@ private:
|
||||
U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!)
|
||||
S32 mIndexInTex ;
|
||||
|
||||
//previous rebuild's geometry info
|
||||
U16 mLastGeomCount;
|
||||
U16 mLastGeomIndex;
|
||||
U32 mLastIndicesCount;
|
||||
U32 mLastIndicesIndex;
|
||||
|
||||
LLXformMatrix* mXform;
|
||||
LLPointer<LLViewerTexture> mTexture;
|
||||
LLPointer<LLDrawable> mDrawablep;
|
||||
|
||||
@@ -368,7 +368,7 @@ void LLVolumeImplFlexible::doFlexibleUpdate()
|
||||
LLPath *path = &volume->getPath();
|
||||
if ((mSimulateRes == 0 || !mInitialized) && mVO->mDrawable->isVisible())
|
||||
{
|
||||
mVO->markForUpdate(TRUE);
|
||||
//mVO->markForUpdate(TRUE);
|
||||
if (!doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0))
|
||||
{
|
||||
return; // we did not get updated or initialized, proceeding without can be dangerous
|
||||
@@ -729,7 +729,11 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
|
||||
else if (!mUpdated || rotated)
|
||||
{
|
||||
volume->mDrawable->setState(LLDrawable::REBUILD_POSITION);
|
||||
volume->dirtyMesh();
|
||||
LLSpatialGroup* group = volume->mDrawable->getSpatialGroup();
|
||||
if (group)
|
||||
{
|
||||
group->dirtyMesh();
|
||||
}
|
||||
volume->genBBoxes(isVolumeGlobal());
|
||||
}
|
||||
|
||||
@@ -814,15 +818,17 @@ LLQuaternion LLVolumeImplFlexible::getEndRotation()
|
||||
}//------------------------------------------------------------------
|
||||
|
||||
|
||||
void LLVolumeImplFlexible::updateRelativeXform()
|
||||
void LLVolumeImplFlexible::updateRelativeXform(bool force_identity)
|
||||
{
|
||||
LLQuaternion delta_rot;
|
||||
LLVector3 delta_pos, delta_scale;
|
||||
LLVOVolume* vo = (LLVOVolume*) mVO;
|
||||
|
||||
bool use_identity = vo->mDrawable->isSpatialRoot() || force_identity;
|
||||
|
||||
//matrix from local space to parent relative/global space
|
||||
delta_rot = vo->mDrawable->isSpatialRoot() ? LLQuaternion() : vo->mDrawable->getRotation();
|
||||
delta_pos = vo->mDrawable->isSpatialRoot() ? LLVector3(0,0,0) : vo->mDrawable->getPosition();
|
||||
delta_rot = use_identity ? LLQuaternion() : vo->mDrawable->getRotation();
|
||||
delta_pos = use_identity ? LLVector3(0,0,0) : vo->mDrawable->getPosition();
|
||||
delta_scale = LLVector3(1,1,1);
|
||||
|
||||
// Vertex transform (4x4)
|
||||
|
||||
@@ -95,7 +95,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface
|
||||
bool isVolumeGlobal() const { return true; }
|
||||
bool isActive() const { return true; }
|
||||
const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const;
|
||||
void updateRelativeXform();
|
||||
void updateRelativeXform(bool force_identity);
|
||||
void doFlexibleUpdate(); // Called to update the simulation
|
||||
void doFlexibleRebuild(); // Called to rebuild the geometry
|
||||
void preRebuild();
|
||||
|
||||
@@ -142,24 +142,16 @@ BOOL LLFloaterAvatarPicker::postBuild()
|
||||
inventory_panel->openDefaultFolderForType(LLAssetType::AT_CALLINGCARD);
|
||||
inventory_panel->setSelectCallback(boost::bind(&LLFloaterAvatarPicker::onCallingCardSelectionChange, _1, _2, (void*)this));
|
||||
|
||||
childSetTabChangeCallback("ResidentChooserTabs", "SearchPanel", onTabChanged, this);
|
||||
childSetTabChangeCallback("ResidentChooserTabs", "CallingCardsPanel", onTabChanged, this);
|
||||
childSetTabChangeCallback("ResidentChooserTabs", "NearMePanel", onTabChanged, this);
|
||||
childSetTabChangeCallback("ResidentChooserTabs", "KeyPanel", onTabChanged, this);
|
||||
getChild<LLTabContainer>("ResidentChooserTabs")->setCommitCallback(boost::bind(&LLFloaterAvatarPicker::onTabChanged,this));
|
||||
|
||||
setAllowMultiple(FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void LLFloaterAvatarPicker::onTabChanged(void* userdata, bool from_click)
|
||||
void LLFloaterAvatarPicker::onTabChanged()
|
||||
{
|
||||
LLFloaterAvatarPicker* self = (LLFloaterAvatarPicker*)userdata;
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->childSetEnabled("Select", self->visibleItemsSelected());
|
||||
childSetEnabled("Select", visibleItemsSelected());
|
||||
}
|
||||
|
||||
// Destroys the object
|
||||
|
||||
@@ -62,7 +62,7 @@ private:
|
||||
static void onRangeAdjust(LLUICtrl* source, void* data);
|
||||
static void onBtnClose(void* userdata);
|
||||
static void onList(class LLUICtrl* ctrl, void* userdata);
|
||||
static void onTabChanged(void* userdata, bool from_click);
|
||||
void onTabChanged();
|
||||
|
||||
void doCallingCardSelectionChange(const std::deque<class LLFolderViewItem*> &items, BOOL user_action, void* data);
|
||||
static void onCallingCardSelectionChange(const std::deque<class LLFolderViewItem*> &items, BOOL user_action, void* data);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -55,7 +55,7 @@ class LLMakeOutfitDialog;
|
||||
class LLRadioGroup;
|
||||
class LLScrollableContainerView;
|
||||
class LLScrollingPanelList;
|
||||
class LLTabContainerVertical;
|
||||
class LLTabContainer;
|
||||
class LLTextBox;
|
||||
class LLTextureCtrl;
|
||||
class LLViewerJointMesh;
|
||||
@@ -71,10 +71,6 @@ class AIFilePicker;
|
||||
|
||||
class LLFloaterCustomize : public LLFloater
|
||||
{
|
||||
public:
|
||||
typedef std::pair<BOOL, LLViewerVisualParam*> editable_param;
|
||||
typedef std::map<F32, editable_param> param_map;
|
||||
|
||||
public:
|
||||
LLFloaterCustomize();
|
||||
virtual ~LLFloaterCustomize();
|
||||
@@ -87,14 +83,9 @@ public:
|
||||
|
||||
|
||||
// New methods
|
||||
void clearScrollingPanelList();
|
||||
void generateVisualParamHints(LLViewerJointMesh* joint_mesh,
|
||||
param_map& params, bool bVisualHint);
|
||||
|
||||
const std::string& getEditGroup();
|
||||
void updateScrollingPanelList(BOOL allow_modify);
|
||||
|
||||
void setWearable(LLWearableType::EType type, LLWearable* wearable, U32 perm_mask, BOOL is_complete);
|
||||
void wearablesChanged(LLWearableType::EType type);
|
||||
void updateScrollingPanelList();
|
||||
LLPanelEditWearable* getCurrentWearablePanel() { return mWearablePanelList[ sCurrentWearableType ]; }
|
||||
|
||||
virtual BOOL isDirty() const;
|
||||
@@ -115,15 +106,15 @@ public:
|
||||
static void onBtnExport( void* userdata );
|
||||
static void onBtnExport_continued(AIFilePicker* filepicker);
|
||||
|
||||
static void onTabChanged( void* userdata, bool from_click );
|
||||
static void onTabPrecommit( void* userdata, bool from_click );
|
||||
static void onTabChanged( const LLSD& param );
|
||||
bool onTabPrecommit( LLUICtrl* ctrl, const LLSD& param );
|
||||
bool onSaveDialog(const LLSD& notification, const LLSD& response);
|
||||
static void onCommitChangeTab(BOOL proceed);
|
||||
static void onCommitChangeTab(BOOL proceed, LLTabContainer* ctrl, std::string panel_name, LLWearableType::EType type);
|
||||
|
||||
void fetchInventory();
|
||||
void updateInventoryUI();
|
||||
void updateScrollingPanelUI();
|
||||
|
||||
LLScrollingPanelList* getScrollingPanelList() const { return mScrollingPanelList; }
|
||||
protected:
|
||||
LLPanelEditWearable* mWearablePanelList[ LLWearableType::WT_COUNT ];
|
||||
|
||||
|
||||
@@ -144,23 +144,7 @@ LLFloaterDirectory::LLFloaterDirectory(const std::string& name)
|
||||
mPanelAvatarp->selectTab(0);
|
||||
}
|
||||
|
||||
childSetTabChangeCallback("Directory Tabs", "classified_panel", onTabChanged, this);
|
||||
childSetTabChangeCallback("Directory Tabs", "events_panel", onTabChanged, this);
|
||||
childSetTabChangeCallback("Directory Tabs", "places_panel", onTabChanged, this);
|
||||
childSetTabChangeCallback("Directory Tabs", "land_sales_panel", onTabChanged, this);
|
||||
childSetTabChangeCallback("Directory Tabs", "people_panel", onTabChanged, this);
|
||||
childSetTabChangeCallback("Directory Tabs", "groups_panel", onTabChanged, this);
|
||||
if (enableWebSearch)
|
||||
{
|
||||
// web search and showcase for SecondLife
|
||||
childSetTabChangeCallback("Directory Tabs", "find_all_panel", onTabChanged, this);
|
||||
childSetTabChangeCallback("Directory Tabs", "showcase_panel", onTabChanged, this);
|
||||
}
|
||||
|
||||
if(enableClassicAllSearch)
|
||||
{
|
||||
childSetTabChangeCallback("Directory Tabs", "find_all_old_panel", onTabChanged, this);
|
||||
}
|
||||
getChild<LLTabContainer>("Directory Tabs")->setCommitCallback(boost::bind(&LLFloaterDirectory::onTabChanged,_2));
|
||||
}
|
||||
|
||||
LLFloaterDirectory::~LLFloaterDirectory()
|
||||
@@ -508,16 +492,9 @@ void LLFloaterDirectory::onClose(bool app_quitting)
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterDirectory::onTabChanged(void* data, bool from_click)
|
||||
void LLFloaterDirectory::onTabChanged( const LLSD& param )
|
||||
{
|
||||
LLFloaterDirectory* self = (LLFloaterDirectory*)data;
|
||||
if (!self) return;
|
||||
|
||||
LLPanel *panel = self->childGetVisibleTab("Directory Tabs");
|
||||
if (panel)
|
||||
{
|
||||
gSavedSettings.setString("LastFindPanel", panel->getName());
|
||||
}
|
||||
gSavedSettings.setString("LastFindPanel", param.asString());
|
||||
}
|
||||
|
||||
void LLFloaterDirectory::hideAllDetailPanels()
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
|
||||
static void toggleEvents(void*);
|
||||
static void toggleFind(void*);
|
||||
static void onTabChanged(void*, bool);
|
||||
static void onTabChanged( const LLSD& param );
|
||||
|
||||
void hideAllDetailPanels();
|
||||
|
||||
|
||||
@@ -130,10 +130,7 @@ LLFloaterGodTools::LLFloaterGodTools()
|
||||
factory_map["request"] = LLCallbackMap(createPanelRequest, this);
|
||||
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_god_tools.xml", &factory_map);
|
||||
|
||||
childSetTabChangeCallback("GodTools Tabs", "grid", onTabChanged, this);
|
||||
childSetTabChangeCallback("GodTools Tabs", "region", onTabChanged, this);
|
||||
childSetTabChangeCallback("GodTools Tabs", "objects", onTabChanged, this);
|
||||
childSetTabChangeCallback("GodTools Tabs", "request", onTabChanged, this);
|
||||
getChild<LLTabContainer>("GodTools Tabs")->setCommitCallback(boost::bind(&LLFloaterGodTools::onTabChanged,_1,_2));
|
||||
|
||||
sendRegionInfoRequest();
|
||||
|
||||
@@ -244,15 +241,12 @@ void LLFloaterGodTools::showPanel(const std::string& panel_name)
|
||||
if (panel) panel->setFocus(TRUE);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void LLFloaterGodTools::onTabChanged(void* data, bool from_click)
|
||||
//static
|
||||
void LLFloaterGodTools::onTabChanged(LLUICtrl* ctrl, const LLSD& param)
|
||||
{
|
||||
LLPanel* panel = (LLPanel*)data;
|
||||
if (panel)
|
||||
{
|
||||
LLPanel* panel = (LLPanel*)ctrl->getChildView(param.asString(),false,false);
|
||||
if(panel)
|
||||
panel->setFocus(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
// Send possibly changed values to simulator.
|
||||
void sendGodUpdateRegionInfo();
|
||||
|
||||
static void onTabChanged(void *data, bool from_click);
|
||||
static void onTabChanged(LLUICtrl* ctrl, const LLSD& param);
|
||||
|
||||
protected:
|
||||
U32 computeRegionFlags() const;
|
||||
|
||||
@@ -144,39 +144,39 @@ LLPreferenceCore::LLPreferenceCore(LLTabContainer* tab_container, LLButton * def
|
||||
mPrefsAscentVan(NULL)
|
||||
{
|
||||
mGeneralPanel = new LLPanelGeneral();
|
||||
mTabContainer->addTabPanel(mGeneralPanel, mGeneralPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mGeneralPanel, mGeneralPanel->getLabel());
|
||||
mGeneralPanel->setDefaultBtn(default_btn);
|
||||
|
||||
mInputPanel = new LLPanelInput();
|
||||
mTabContainer->addTabPanel(mInputPanel, mInputPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mInputPanel, mInputPanel->getLabel());
|
||||
mInputPanel->setDefaultBtn(default_btn);
|
||||
|
||||
mNetworkPanel = new LLPanelNetwork();
|
||||
mTabContainer->addTabPanel(mNetworkPanel, mNetworkPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mNetworkPanel, mNetworkPanel->getLabel());
|
||||
mNetworkPanel->setDefaultBtn(default_btn);
|
||||
|
||||
mWebPanel = new LLPanelWeb();
|
||||
mTabContainer->addTabPanel(mWebPanel, mWebPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mWebPanel, mWebPanel->getLabel());
|
||||
mWebPanel->setDefaultBtn(default_btn);
|
||||
|
||||
mDisplayPanel = new LLPanelDisplay();
|
||||
mTabContainer->addTabPanel(mDisplayPanel, mDisplayPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mDisplayPanel, mDisplayPanel->getLabel());
|
||||
mDisplayPanel->setDefaultBtn(default_btn);
|
||||
|
||||
mAudioPanel = new LLPanelAudioPrefs();
|
||||
mTabContainer->addTabPanel(mAudioPanel, mAudioPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mAudioPanel, mAudioPanel->getLabel());
|
||||
mAudioPanel->setDefaultBtn(default_btn);
|
||||
|
||||
mPrefsChat = new LLPrefsChat();
|
||||
mTabContainer->addTabPanel(mPrefsChat->getPanel(), mPrefsChat->getPanel()->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mPrefsChat->getPanel(), mPrefsChat->getPanel()->getLabel());
|
||||
mPrefsChat->getPanel()->setDefaultBtn(default_btn);
|
||||
|
||||
mPrefsVoice = new LLPrefsVoice();
|
||||
mTabContainer->addTabPanel(mPrefsVoice, mPrefsVoice->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mPrefsVoice, mPrefsVoice->getLabel());
|
||||
mPrefsVoice->setDefaultBtn(default_btn);
|
||||
|
||||
mPrefsIM = new LLPrefsIM();
|
||||
mTabContainer->addTabPanel(mPrefsIM->getPanel(), mPrefsIM->getPanel()->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mPrefsIM->getPanel(), mPrefsIM->getPanel()->getLabel());
|
||||
mPrefsIM->getPanel()->setDefaultBtn(default_btn);
|
||||
|
||||
#if LL_LCD_COMPILE
|
||||
@@ -185,7 +185,7 @@ LLPreferenceCore::LLPreferenceCore(LLTabContainer* tab_container, LLButton * def
|
||||
if (gLcdScreen->Enabled())
|
||||
{
|
||||
mLCDPanel = new LLPanelLCD();
|
||||
mTabContainer->addTabPanel(mLCDPanel, mLCDPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mLCDPanel, mLCDPanel->getLabel());
|
||||
mLCDPanel->setDefaultBtn(default_btn);
|
||||
}
|
||||
|
||||
@@ -194,29 +194,31 @@ LLPreferenceCore::LLPreferenceCore(LLTabContainer* tab_container, LLButton * def
|
||||
#endif
|
||||
|
||||
mMsgPanel = new LLPanelMsgs();
|
||||
mTabContainer->addTabPanel(mMsgPanel, mMsgPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mMsgPanel, mMsgPanel->getLabel());
|
||||
mMsgPanel->setDefaultBtn(default_btn);
|
||||
|
||||
mSkinsPanel = new LLPanelSkins();
|
||||
mTabContainer->addTabPanel(mSkinsPanel, mSkinsPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mSkinsPanel, mSkinsPanel->getLabel());
|
||||
mSkinsPanel->setDefaultBtn(default_btn);
|
||||
|
||||
mGridsPanel = HippoPanelGrids::create();
|
||||
mTabContainer->addTabPanel(mGridsPanel, mGridsPanel->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mGridsPanel, mGridsPanel->getLabel());
|
||||
mGridsPanel->setDefaultBtn(default_btn);
|
||||
|
||||
mPrefsAscentChat = new LLPrefsAscentChat();
|
||||
mTabContainer->addTabPanel(mPrefsAscentChat, mPrefsAscentChat->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mPrefsAscentChat, mPrefsAscentChat->getLabel());
|
||||
mPrefsAscentChat->setDefaultBtn(default_btn);
|
||||
|
||||
mPrefsAscentSys = new LLPrefsAscentSys();
|
||||
mTabContainer->addTabPanel(mPrefsAscentSys, mPrefsAscentSys->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mPrefsAscentSys, mPrefsAscentSys->getLabel());
|
||||
mPrefsAscentSys->setDefaultBtn(default_btn);
|
||||
|
||||
mPrefsAscentVan = new LLPrefsAscentVan();
|
||||
mTabContainer->addTabPanel(mPrefsAscentVan, mPrefsAscentVan->getLabel(), FALSE, onTabChanged, mTabContainer);
|
||||
mTabContainer->addTabPanel(mPrefsAscentVan, mPrefsAscentVan->getLabel());
|
||||
mPrefsAscentVan->setDefaultBtn(default_btn);
|
||||
|
||||
mTabContainer->setCommitCallback(boost::bind(LLPreferenceCore::onTabChanged,_1));
|
||||
|
||||
if (!mTabContainer->selectTab(gSavedSettings.getS32("LastPrefTab")))
|
||||
{
|
||||
mTabContainer->selectFirstTab();
|
||||
@@ -363,9 +365,9 @@ void LLPreferenceCore::cancel()
|
||||
}
|
||||
|
||||
// static
|
||||
void LLPreferenceCore::onTabChanged(void* user_data, bool from_click)
|
||||
void LLPreferenceCore::onTabChanged(LLUICtrl* ctrl)
|
||||
{
|
||||
LLTabContainer* self = (LLTabContainer*)user_data;
|
||||
LLTabContainer* self = (LLTabContainer*)ctrl;
|
||||
|
||||
gSavedSettings.setS32("LastPrefTab", self->getCurrentPanelIndex());
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
|
||||
void setPersonalInfo(const std::string& visibility, bool im_via_email, const std::string& email);
|
||||
|
||||
static void onTabChanged(void* user_data, bool from_click);
|
||||
static void onTabChanged(LLUICtrl* ctrl);
|
||||
|
||||
// refresh all the graphics preferences menus
|
||||
void refreshEnabledGraphics();
|
||||
|
||||
@@ -160,6 +160,8 @@ LLFloaterTestImpl::LLFloaterTestImpl()
|
||||
addChild(tab);
|
||||
mTab = tab;
|
||||
|
||||
tab->setCommitCallback(boost::bind(&LLFloaterTestImpl::onClickTab,_1,_2));
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// First tab container panel
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -167,8 +169,7 @@ LLFloaterTestImpl::LLFloaterTestImpl()
|
||||
LLRect(0, 400, 400, 0), // dummy rect
|
||||
TRUE); // bordered
|
||||
tab->addTabPanel(panel, std::string("First"),
|
||||
TRUE, // select
|
||||
onClickTab, this);
|
||||
TRUE); // select
|
||||
|
||||
y = panel->getRect().getHeight() - VPAD;
|
||||
|
||||
@@ -284,8 +285,7 @@ LLFloaterTestImpl::LLFloaterTestImpl()
|
||||
LLRect(0, 400, 400, 0), // dummy rect
|
||||
TRUE); // bordered
|
||||
tab->addTabPanel(panel, std::string("Second"),
|
||||
FALSE, // select
|
||||
onClickTab, this);
|
||||
FALSE); // select
|
||||
|
||||
y = panel->getRect().getHeight() - VPAD;
|
||||
|
||||
|
||||
@@ -957,7 +957,7 @@ void LLFolderView::draw()
|
||||
else if (mShowEmptyMessage)
|
||||
{
|
||||
static LLCachedControl<LLColor4> sSearchStatusColor(gColors, "InventorySearchStatusColor", LLColor4::white );
|
||||
if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())
|
||||
if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())
|
||||
{
|
||||
mStatusText = std::string("Searching..."); // *TODO:translate
|
||||
}
|
||||
@@ -2003,7 +2003,7 @@ void LLFolderView::scrollToShowSelection()
|
||||
// However we allow scrolling for folder views with mAutoSelectOverride
|
||||
// (used in Places SP) as an exception because the selection in them
|
||||
// is not reset during items filtering. See STORM-133.
|
||||
if ( (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mAutoSelectOverride)
|
||||
if ( (!LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mAutoSelectOverride)
|
||||
&& mSelectedItems.size() )
|
||||
{
|
||||
mNeedsScroll = TRUE;
|
||||
|
||||
@@ -1049,7 +1049,7 @@ void LLFolderViewItem::draw()
|
||||
}
|
||||
if ((mIsLoading
|
||||
&& mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime"))
|
||||
|| (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
|
||||
|| (LLInventoryModelBackgroundFetch::instance().folderFetchActive()
|
||||
&& root_is_loading
|
||||
&& mShowLoadStatus))
|
||||
{
|
||||
|
||||
@@ -1178,7 +1178,7 @@ void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
|
||||
|
||||
group_datap->mChanged = TRUE;
|
||||
#if SHY_MOD //Group title script access
|
||||
gGroupRoleChanger.CheckUpdateRole(group_id,group_data->mRoles);
|
||||
gGroupRoleChanger.CheckUpdateRole(group_id,group_datap->mRoles);
|
||||
#endif //shy_mod
|
||||
LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_DATA);
|
||||
}
|
||||
|
||||
@@ -200,6 +200,42 @@ bool isMarketplaceSendAction(const std::string& action)
|
||||
return ("send_to_marketplace" == action);
|
||||
}
|
||||
|
||||
// Used by LLFolderBridge as callback for directory fetching recursion
|
||||
class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
|
||||
{
|
||||
public:
|
||||
LLRightClickInventoryFetchDescendentsObserver(const uuid_vec_t& ids) : LLInventoryFetchDescendentsObserver(ids) {}
|
||||
~LLRightClickInventoryFetchDescendentsObserver() {}
|
||||
virtual void execute(bool clear_observer = false);
|
||||
virtual void done()
|
||||
{
|
||||
execute(true);
|
||||
}
|
||||
};
|
||||
|
||||
// Used by LLFolderBridge as callback for directory content items fetching
|
||||
class LLRightClickInventoryFetchObserver : public LLInventoryFetchItemsObserver
|
||||
{
|
||||
public:
|
||||
LLRightClickInventoryFetchObserver(const uuid_vec_t& ids) : LLInventoryFetchItemsObserver(ids) { };
|
||||
~LLRightClickInventoryFetchObserver() {}
|
||||
void execute(bool clear_observer = false)
|
||||
{
|
||||
if (clear_observer)
|
||||
{
|
||||
dec_busy_count();
|
||||
gInventory.removeObserver(this);
|
||||
delete this;
|
||||
}
|
||||
// we've downloaded all the items, so repaint the dialog
|
||||
LLFolderBridge::staticFolderOptionsMenu();
|
||||
}
|
||||
virtual void done()
|
||||
{
|
||||
execute(true);
|
||||
}
|
||||
};
|
||||
|
||||
// <edit>
|
||||
void gotImageForSaveItemAs(BOOL success,
|
||||
LLViewerTexture *src_vi,
|
||||
@@ -1050,7 +1086,7 @@ void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
|
||||
const LLUUID& new_parent_id,
|
||||
BOOL restamp)
|
||||
{
|
||||
change_item_parent(model, item, new_parent_id, restamp);
|
||||
model->changeItemParent(item, new_parent_id, restamp);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -1059,7 +1095,7 @@ void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
|
||||
const LLUUID& new_parent_id,
|
||||
BOOL restamp)
|
||||
{
|
||||
change_category_parent(model, cat, new_parent_id, restamp);
|
||||
model->changeCategoryParent(cat, new_parent_id, restamp);
|
||||
}
|
||||
|
||||
LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
|
||||
@@ -1464,7 +1500,8 @@ void LLItemBridge::selectItem()
|
||||
// <edit>
|
||||
if(!(gInventory.isObjectDescendentOf(mUUID, gSystemFolderRoot)))
|
||||
// </edit>
|
||||
item->fetchFromServer();
|
||||
//item->fetchFromServer();
|
||||
LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2498,9 +2535,16 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
|
||||
LLInventoryObject::object_list_t::iterator end = inventory_objects.end();
|
||||
for ( ; it != end; ++it)
|
||||
{
|
||||
LLInventoryItem* item = dynamic_cast<LLInventoryItem*>(it->get());
|
||||
if (!item)
|
||||
{
|
||||
llwarns << "Invalid inventory item for drop" << llendl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// coming from a task. Need to figure out if the person can
|
||||
// move/copy this item.
|
||||
LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions());
|
||||
LLPermissions perm(item->getPermissions());
|
||||
if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
|
||||
&& perm.allowTransferTo(gAgent.getID())))
|
||||
// || gAgent.isGodlike())
|
||||
@@ -2553,121 +2597,114 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
|
||||
return accept;
|
||||
}
|
||||
|
||||
//Used by LLFolderBridge as callback for directory recursion.
|
||||
class LLRightClickInventoryFetchObserver : public LLInventoryFetchItemsObserver
|
||||
void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer)
|
||||
{
|
||||
public:
|
||||
LLRightClickInventoryFetchObserver(const uuid_vec_t& ids) :
|
||||
LLInventoryFetchItemsObserver(ids),
|
||||
mCopyItems(false)
|
||||
{ };
|
||||
LLRightClickInventoryFetchObserver(const uuid_vec_t& ids,
|
||||
const LLUUID& cat_id,
|
||||
bool copy_items) :
|
||||
LLInventoryFetchItemsObserver(ids),
|
||||
mCatID(cat_id),
|
||||
mCopyItems(copy_items)
|
||||
{ };
|
||||
virtual void done()
|
||||
{
|
||||
// we've downloaded all the items, so repaint the dialog
|
||||
LLFolderBridge::staticFolderOptionsMenu();
|
||||
|
||||
gInventory.removeObserver(this);
|
||||
delete this;
|
||||
}
|
||||
|
||||
protected:
|
||||
LLUUID mCatID;
|
||||
bool mCopyItems;
|
||||
|
||||
};
|
||||
|
||||
//Used by LLFolderBridge as callback for directory recursion.
|
||||
class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
|
||||
{
|
||||
public:
|
||||
LLRightClickInventoryFetchDescendentsObserver(const uuid_vec_t& ids,
|
||||
bool copy_items) :
|
||||
LLInventoryFetchDescendentsObserver(ids),
|
||||
mCopyItems(copy_items)
|
||||
{}
|
||||
~LLRightClickInventoryFetchDescendentsObserver() {}
|
||||
virtual void done();
|
||||
protected:
|
||||
bool mCopyItems;
|
||||
};
|
||||
|
||||
void LLRightClickInventoryFetchDescendentsObserver::done()
|
||||
{
|
||||
// Avoid passing a NULL-ref as mCompleteFolders.front() down to
|
||||
// gInventory.collectDescendents()
|
||||
// Bail out immediately if no descendents
|
||||
if( mComplete.empty() )
|
||||
{
|
||||
llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl;
|
||||
if (clear_observer)
|
||||
{
|
||||
dec_busy_count();
|
||||
gInventory.removeObserver(this);
|
||||
delete this;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// What we do here is get the complete information on the items in
|
||||
// the library, and set up an observer that will wait for that to
|
||||
// happen.
|
||||
LLInventoryModel::cat_array_t cat_array;
|
||||
LLInventoryModel::item_array_t item_array;
|
||||
gInventory.collectDescendents(mComplete.front(),
|
||||
cat_array,
|
||||
item_array,
|
||||
LLInventoryModel::EXCLUDE_TRASH);
|
||||
S32 count = item_array.count();
|
||||
#if 0 // HACK/TODO: Why?
|
||||
// This early causes a giant menu to get produced, and doesn't seem to be needed.
|
||||
if(!count)
|
||||
// Copy the list of complete fetched folders while "this" is still valid
|
||||
uuid_vec_t completed_folder = mComplete;
|
||||
|
||||
// Clean up, and remove this as an observer now since recursive calls
|
||||
// could notify observers and throw us into an infinite loop.
|
||||
if (clear_observer)
|
||||
{
|
||||
llwarns << "Nothing fetched in category " << mComplete.front()
|
||||
<< llendl;
|
||||
dec_busy_count();
|
||||
gInventory.removeObserver(this);
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
uuid_vec_t ids;
|
||||
for(S32 i = 0; i < count; ++i)
|
||||
for (uuid_vec_t::iterator current_folder = completed_folder.begin(); current_folder != completed_folder.end(); ++current_folder)
|
||||
{
|
||||
ids.push_back(item_array.get(i)->getUUID());
|
||||
// Get the information on the fetched folder items and subfolders and fetch those
|
||||
LLInventoryModel::cat_array_t* cat_array;
|
||||
LLInventoryModel::item_array_t* item_array;
|
||||
gInventory.getDirectDescendentsOf(*current_folder, cat_array, item_array);
|
||||
|
||||
S32 item_count = item_array->count();
|
||||
S32 cat_count = cat_array->count();
|
||||
|
||||
// Move to next if current folder empty
|
||||
if ((item_count == 0) && (cat_count == 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LLRightClickInventoryFetchObserver* outfit = new LLRightClickInventoryFetchObserver(ids, mComplete.front(), mCopyItems);
|
||||
uuid_vec_t ids;
|
||||
LLRightClickInventoryFetchObserver* outfit = NULL;
|
||||
LLRightClickInventoryFetchDescendentsObserver* categories = NULL;
|
||||
|
||||
// clean up, and remove this as an observer since the call to the
|
||||
// outfit could notify observers and throw us into an infinite
|
||||
// loop.
|
||||
dec_busy_count();
|
||||
gInventory.removeObserver(this);
|
||||
delete this;
|
||||
// Fetch the items
|
||||
if (item_count)
|
||||
{
|
||||
for (S32 i = 0; i < item_count; ++i)
|
||||
{
|
||||
ids.push_back(item_array->get(i)->getUUID());
|
||||
}
|
||||
outfit = new LLRightClickInventoryFetchObserver(ids);
|
||||
}
|
||||
// Fetch the subfolders
|
||||
if (cat_count)
|
||||
{
|
||||
for (S32 i = 0; i < cat_count; ++i)
|
||||
{
|
||||
ids.push_back(cat_array->get(i)->getUUID());
|
||||
}
|
||||
categories = new LLRightClickInventoryFetchDescendentsObserver(ids);
|
||||
}
|
||||
|
||||
// increment busy count and either tell the inventory to check &
|
||||
// call done, or add this object to the inventory for observation.
|
||||
inc_busy_count();
|
||||
|
||||
// do the fetch
|
||||
// Perform the item fetch
|
||||
if (outfit)
|
||||
{
|
||||
outfit->startFetch();
|
||||
outfit->done(); //Not interested in waiting and this will be right 99% of the time.
|
||||
outfit->execute(); // Not interested in waiting and this will be right 99% of the time.
|
||||
delete outfit;
|
||||
//Uncomment the following code for laggy Inventory UI.
|
||||
/* if(outfit->isEverythingComplete())
|
||||
/*
|
||||
if (outfit->isFinished())
|
||||
{
|
||||
// everything is already here - call done.
|
||||
outfit->done();
|
||||
// everything is already here - call done.
|
||||
outfit->execute();
|
||||
delete outfit;
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's all on it's way - add an observer, and the inventory
|
||||
// will call done for us when everything is here.
|
||||
gInventory.addObserver(outfit);
|
||||
}*/
|
||||
// it's all on its way - add an observer, and the inventory
|
||||
// will call done for us when everything is here.
|
||||
inc_busy_count();
|
||||
gInventory.addObserver(outfit);
|
||||
}
|
||||
*/
|
||||
}
|
||||
// Perform the subfolders fetch : this is where we truly recurse down the folder hierarchy
|
||||
if (categories)
|
||||
{
|
||||
categories->startFetch();
|
||||
if (categories->isFinished())
|
||||
{
|
||||
// everything is already here - call done.
|
||||
categories->execute();
|
||||
delete categories;
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's all on its way - add an observer, and the inventory
|
||||
// will call done for us when everything is here.
|
||||
inc_busy_count();
|
||||
gInventory.addObserver(categories);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2980,7 +3017,7 @@ bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& re
|
||||
{
|
||||
// move it to the trash
|
||||
LLPreview::hide(mUUID);
|
||||
remove_category(getInventoryModel(), mUUID);
|
||||
getInventoryModel()->removeCategory(mUUID);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@@ -3336,16 +3373,19 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
folders.push_back(category->getUUID());
|
||||
|
||||
sSelf = getHandle();
|
||||
LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders, FALSE);
|
||||
LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders);
|
||||
fetch->startFetch();
|
||||
inc_busy_count();
|
||||
if (fetch->isFinished())
|
||||
{
|
||||
// Do not call execute() or done() here as if the folder is here, there's likely no point drilling down
|
||||
// This saves lots of time as buildContextMenu() is called a lot
|
||||
delete fetch;
|
||||
buildContextMenuFolderOptions(flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's all on its way - add an observer, and the inventory will call done for us when everything is here.
|
||||
inc_busy_count();
|
||||
gInventory.addObserver(fetch);
|
||||
}
|
||||
}
|
||||
@@ -5543,6 +5583,35 @@ LLUIImagePtr LLWearableBridge::getIcon() const
|
||||
return LLInventoryIcon::getIcon(mAssetType, mInvType, mWearableType, FALSE);
|
||||
}
|
||||
|
||||
//LLAppearanceMgr::moveWearable unfortunately fails for non-link items, so links in CoF must be found for this to work.
|
||||
void move_wearable_item(LLViewerInventoryItem* item, bool closer_to_body)
|
||||
{
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
if(item->getIsLinkType())
|
||||
{
|
||||
if(LLAppearanceMgr::instance().moveWearable(item, closer_to_body))
|
||||
gAgentAvatarp->wearableUpdated(item->getWearableType(),TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLInventoryModel::item_array_t items;
|
||||
LLInventoryModel::cat_array_t cats;
|
||||
LLLinkedItemIDMatches is_linked_item_match(item->getUUID());
|
||||
gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(),
|
||||
cats,
|
||||
items,
|
||||
LLInventoryModel::EXCLUDE_TRASH,
|
||||
is_linked_item_match);
|
||||
if(!items.empty())
|
||||
{
|
||||
if(LLAppearanceMgr::instance().moveWearable(gInventory.getItem(items.front()->getUUID()),closer_to_body))
|
||||
gAgentAvatarp->wearableUpdated(item->getWearableType(),TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLWearableBridge::performAction(LLInventoryModel* model, std::string action)
|
||||
{
|
||||
@@ -5564,6 +5633,15 @@ void LLWearableBridge::performAction(LLInventoryModel* model, std::string action
|
||||
removeFromAvatar();
|
||||
return;
|
||||
}
|
||||
//These move
|
||||
else if("move_forward" == action)
|
||||
{
|
||||
move_wearable_item(getItem(),false);
|
||||
}
|
||||
else if("move_back" == action)
|
||||
{
|
||||
move_wearable_item(getItem(),true);
|
||||
}
|
||||
else LLItemBridge::performAction(model, action);
|
||||
}
|
||||
|
||||
@@ -5686,6 +5764,15 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
if (LLWearableType::getAllowMultiwear(mWearableType))
|
||||
{
|
||||
items.push_back(std::string("Wearable Add"));
|
||||
items.push_back(std::string("Wearable Move Forward"));
|
||||
items.push_back(std::string("Wearable Move Back"));
|
||||
|
||||
bool is_worn = get_is_item_worn(item->getUUID());
|
||||
if(!is_worn || !gAgentWearables.canMoveWearable(item->getUUID(),false))
|
||||
disabled_items.push_back(std::string("Wearable Move Forward"));
|
||||
if(!is_worn || !gAgentWearables.canMoveWearable(item->getUUID(),true))
|
||||
disabled_items.push_back(std::string("Wearable Move Back"));
|
||||
|
||||
// if (gAgentWearables.getWearableCount(mWearableType) >= LLAgentWearables::MAX_CLOTHING_PER_TYPE)
|
||||
// [SL:KB] - Patch: Appearance-WearableDuplicateAssets | Checked: 2011-07-24 (Catznip-2.6.0e) | Added: Catznip-2.6.0e
|
||||
if ( (gAgentWearables.getWearableCount(mWearableType) >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) ||
|
||||
|
||||
@@ -795,7 +795,7 @@ const std::string& LLInventoryFilter::getFilterText()
|
||||
filtered_by_all_types = FALSE;
|
||||
}
|
||||
|
||||
if (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
|
||||
if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive()
|
||||
&& filtered_by_type
|
||||
&& !filtered_by_all_types)
|
||||
{
|
||||
|
||||
@@ -110,97 +110,6 @@ void append_path(const LLUUID& id, std::string& path)
|
||||
path.append(temp);
|
||||
}
|
||||
|
||||
void change_item_parent(LLInventoryModel* model,
|
||||
LLViewerInventoryItem* item,
|
||||
const LLUUID& new_parent_id,
|
||||
BOOL restamp)
|
||||
{
|
||||
// <edit>
|
||||
bool send_parent_update = gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getRootFolderID());
|
||||
// </edit>
|
||||
if(item->getParentUUID() != new_parent_id)
|
||||
{
|
||||
LLInventoryModel::update_list_t update;
|
||||
LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
|
||||
update.push_back(old_folder);
|
||||
LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
|
||||
update.push_back(new_folder);
|
||||
gInventory.accountForUpdate(update);
|
||||
|
||||
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
|
||||
new_item->setParent(new_parent_id);
|
||||
// <edit>
|
||||
if(send_parent_update)
|
||||
// </edit>
|
||||
new_item->updateParentOnServer(restamp);
|
||||
model->updateItem(new_item);
|
||||
model->notifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
void change_category_parent(LLInventoryModel* model,
|
||||
LLViewerInventoryCategory* cat,
|
||||
const LLUUID& new_parent_id,
|
||||
BOOL restamp)
|
||||
{
|
||||
if (!model || !cat)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Can't move a folder into a child of itself.
|
||||
if (model->isObjectDescendentOf(new_parent_id, cat->getUUID()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLInventoryModel::update_list_t update;
|
||||
LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
|
||||
update.push_back(old_folder);
|
||||
LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
|
||||
update.push_back(new_folder);
|
||||
model->accountForUpdate(update);
|
||||
|
||||
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
|
||||
new_cat->setParent(new_parent_id);
|
||||
new_cat->updateParentOnServer(restamp);
|
||||
model->updateCategory(new_cat);
|
||||
model->notifyObservers();
|
||||
}
|
||||
|
||||
void remove_category(LLInventoryModel* model, const LLUUID& cat_id)
|
||||
{
|
||||
if (!model || !get_is_category_removable(model, cat_id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Look for any gestures and deactivate them
|
||||
LLInventoryModel::cat_array_t descendent_categories;
|
||||
LLInventoryModel::item_array_t descendent_items;
|
||||
gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE);
|
||||
|
||||
for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin();
|
||||
iter != descendent_items.end();
|
||||
++iter)
|
||||
{
|
||||
const LLViewerInventoryItem* item = (*iter);
|
||||
const LLUUID& item_id = item->getUUID();
|
||||
if (item->getType() == LLAssetType::AT_GESTURE
|
||||
&& LLGestureMgr::instance().isGestureActive(item_id))
|
||||
{
|
||||
LLGestureMgr::instance().deactivateGesture(item_id);
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
|
||||
if (cat)
|
||||
{
|
||||
const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
change_category_parent(model, cat, trash_id, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name)
|
||||
{
|
||||
LLViewerInventoryCategory* cat;
|
||||
@@ -553,8 +462,7 @@ void move_to_outbox_cb_action(const LLSD& payload)
|
||||
|
||||
LLUUID parent = viitem->getParentUUID();
|
||||
|
||||
change_item_parent(
|
||||
&gInventory,
|
||||
gInventory.changeItemParent(
|
||||
viitem,
|
||||
dest_folder_id,
|
||||
false);
|
||||
@@ -581,7 +489,7 @@ void move_to_outbox_cb_action(const LLSD& payload)
|
||||
|
||||
if (cat_array->empty() && item_array->empty())
|
||||
{
|
||||
remove_category(&gInventory, parent);
|
||||
gInventory.removeCategory(parent);
|
||||
}
|
||||
|
||||
if (parent == top_level_folder)
|
||||
@@ -655,7 +563,7 @@ void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, S32
|
||||
|
||||
LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item;
|
||||
|
||||
change_item_parent(&gInventory,
|
||||
gInventory.changeItemParent(
|
||||
viewer_inv_item,
|
||||
dest_folder,
|
||||
false);
|
||||
@@ -976,20 +884,24 @@ void LLSaveFolderState::setApply(BOOL apply)
|
||||
|
||||
void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)
|
||||
{
|
||||
LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
|
||||
if(!bridge) return;
|
||||
|
||||
if(mApply)
|
||||
{
|
||||
// we're applying the open state
|
||||
LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
|
||||
if(!bridge) return;
|
||||
LLUUID id(bridge->getUUID());
|
||||
if(mOpenFolders.find(id) != mOpenFolders.end())
|
||||
{
|
||||
folder->setOpen(TRUE);
|
||||
if (!folder->isOpen())
|
||||
{
|
||||
folder->setOpen(TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// keep selected filter in its current state, this is less jarring to user
|
||||
if (!folder->isSelected())
|
||||
if (!folder->isSelected() && folder->isOpen())
|
||||
{
|
||||
folder->setOpen(FALSE);
|
||||
}
|
||||
@@ -1000,8 +912,6 @@ void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)
|
||||
// we're recording state at this point
|
||||
if(folder->isOpen())
|
||||
{
|
||||
LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
|
||||
if(!bridge) return;
|
||||
mOpenFolders.insert(bridge->getUUID());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,17 +55,6 @@ BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id)
|
||||
|
||||
void show_item_profile(const LLUUID& item_uuid);
|
||||
|
||||
void change_item_parent(LLInventoryModel* model,
|
||||
LLViewerInventoryItem* item,
|
||||
const LLUUID& new_parent_id,
|
||||
BOOL restamp);
|
||||
|
||||
void change_category_parent(LLInventoryModel* model,
|
||||
LLViewerInventoryCategory* cat,
|
||||
const LLUUID& new_parent_id,
|
||||
BOOL restamp);
|
||||
|
||||
void remove_category(LLInventoryModel* model, const LLUUID& cat_id);
|
||||
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name);
|
||||
|
||||
// Generates a string containing the path to the item specified by item_id.
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#include "llviewerregion.h"
|
||||
#include "llcallbacklist.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llgesturemgr.h"
|
||||
#include <typeinfo>
|
||||
#include "statemachine/aievent.h"
|
||||
|
||||
// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a)
|
||||
@@ -1080,6 +1082,72 @@ void LLInventoryModel::moveObject(const LLUUID& object_id, const LLUUID& cat_id)
|
||||
}
|
||||
}
|
||||
|
||||
// Migrated from llinventoryfunctions
|
||||
void LLInventoryModel::changeItemParent(LLViewerInventoryItem* item,
|
||||
const LLUUID& new_parent_id,
|
||||
BOOL restamp)
|
||||
{
|
||||
// <edit>
|
||||
bool send_parent_update = gInventory.isObjectDescendentOf(item->getUUID(), gInventory.getRootFolderID());
|
||||
// </edit>
|
||||
if (item->getParentUUID() == new_parent_id)
|
||||
{
|
||||
LL_DEBUGS("Inventory") << "'" << item->getName() << "' (" << item->getUUID()
|
||||
<< ") is already in folder " << new_parent_id << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("Inventory") << "Moving '" << item->getName() << "' (" << item->getUUID()
|
||||
<< ") from " << item->getParentUUID() << " to folder "
|
||||
<< new_parent_id << LL_ENDL;
|
||||
LLInventoryModel::update_list_t update;
|
||||
LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
|
||||
update.push_back(old_folder);
|
||||
LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
|
||||
update.push_back(new_folder);
|
||||
accountForUpdate(update);
|
||||
|
||||
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
|
||||
new_item->setParent(new_parent_id);
|
||||
// <edit>
|
||||
if(send_parent_update)
|
||||
// </edit>
|
||||
new_item->updateParentOnServer(restamp);
|
||||
updateItem(new_item);
|
||||
notifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
// Migrated from llinventoryfunctions
|
||||
void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat,
|
||||
const LLUUID& new_parent_id,
|
||||
BOOL restamp)
|
||||
{
|
||||
if (!cat)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Can't move a folder into a child of itself.
|
||||
if (isObjectDescendentOf(new_parent_id, cat->getUUID()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLInventoryModel::update_list_t update;
|
||||
LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
|
||||
update.push_back(old_folder);
|
||||
LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
|
||||
update.push_back(new_folder);
|
||||
accountForUpdate(update);
|
||||
|
||||
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
|
||||
new_cat->setParent(new_parent_id);
|
||||
new_cat->updateParentOnServer(restamp);
|
||||
updateCategory(new_cat);
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
// Delete a particular inventory object by ID.
|
||||
void LLInventoryModel::deleteObject(const LLUUID& id)
|
||||
{
|
||||
@@ -1208,13 +1276,12 @@ void LLInventoryModel::purgeDescendentsOf(const LLUUID& id)
|
||||
items,
|
||||
INCLUDE_TRASH);
|
||||
S32 count = items.count();
|
||||
S32 i;
|
||||
for(i = 0; i < count; ++i)
|
||||
for(S32 i = 0; i < count; ++i)
|
||||
{
|
||||
deleteObject(items.get(i)->getUUID());
|
||||
}
|
||||
count = categories.count();
|
||||
for(i = 0; i < count; ++i)
|
||||
for(S32 i = 0; i < count; ++i)
|
||||
{
|
||||
deleteObject(categories.get(i)->getUUID());
|
||||
}
|
||||
@@ -1729,6 +1796,7 @@ bool LLInventoryModel::loadSkeleton(
|
||||
update_map_t child_counts;
|
||||
cat_array_t categories;
|
||||
item_array_t items;
|
||||
item_array_t possible_broken_links;
|
||||
cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
|
||||
std::string owner_id_str;
|
||||
owner_id.toString(owner_id_str);
|
||||
@@ -1815,6 +1883,8 @@ bool LLInventoryModel::loadSkeleton(
|
||||
// Add all the items loaded which are parented to a
|
||||
// category with a correctly cached parent
|
||||
S32 bad_link_count = 0;
|
||||
S32 good_link_count = 0;
|
||||
S32 recovered_link_count = 0;
|
||||
cat_map_t::iterator unparented = mCategoryMap.end();
|
||||
for(item_array_t::const_iterator item_iter = items.begin();
|
||||
item_iter != items.end();
|
||||
@@ -1831,26 +1901,56 @@ bool LLInventoryModel::loadSkeleton(
|
||||
// This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
|
||||
if (item->getIsBrokenLink())
|
||||
{
|
||||
bad_link_count++;
|
||||
//bad_link_count++;
|
||||
lldebugs << "Attempted to add cached link item without baseobj present ( name: "
|
||||
<< item->getName() << " itemID: " << item->getUUID()
|
||||
<< " assetID: " << item->getAssetUUID()
|
||||
<< " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
|
||||
invalid_categories.insert(cit->second);
|
||||
possible_broken_links.push_back(item);
|
||||
continue;
|
||||
}
|
||||
else if (item->getIsLinkType())
|
||||
{
|
||||
good_link_count++;
|
||||
}
|
||||
addItem(item);
|
||||
cached_item_count += 1;
|
||||
++child_counts[cat->getUUID()];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bad_link_count > 0)
|
||||
if (possible_broken_links.size() > 0)
|
||||
{
|
||||
llinfos << "Attempted to add " << bad_link_count
|
||||
<< " cached link items without baseobj present. "
|
||||
<< "The corresponding categories were invalidated." << llendl;
|
||||
for(item_array_t::const_iterator item_iter = possible_broken_links.begin();
|
||||
item_iter != possible_broken_links.end();
|
||||
++item_iter)
|
||||
{
|
||||
LLViewerInventoryItem *item = (*item_iter).get();
|
||||
const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID());
|
||||
const LLViewerInventoryCategory* cat = cit->second.get();
|
||||
if (item->getIsBrokenLink())
|
||||
{
|
||||
bad_link_count++;
|
||||
invalid_categories.insert(cit->second);
|
||||
//llinfos << "link still broken: " << item->getName() << " in folder " << cat->getName() << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// was marked as broken because of loading order, its actually fine to load
|
||||
addItem(item);
|
||||
cached_item_count += 1;
|
||||
++child_counts[cat->getUUID()];
|
||||
recovered_link_count++;
|
||||
}
|
||||
}
|
||||
|
||||
llinfos << "Attempted to add " << bad_link_count
|
||||
<< " cached link items without baseobj present. "
|
||||
<< good_link_count << " link items were successfully added. "
|
||||
<< recovered_link_count << " links added in recovery. "
|
||||
<< "The corresponding categories were invalidated." << llendl;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3099,27 +3199,62 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderT
|
||||
notifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void LLInventoryModel::removeItem(const LLUUID& item_id)
|
||||
{
|
||||
LLViewerInventoryItem* item = getItem(item_id);
|
||||
const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
if(item && new_parent.notNull() && item->getParentUUID() != new_parent)
|
||||
if (! item)
|
||||
{
|
||||
LLInventoryModel::update_list_t update;
|
||||
LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(), -1);
|
||||
update.push_back(old_folder);
|
||||
LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
|
||||
update.push_back(new_folder);
|
||||
accountForUpdate(update);
|
||||
|
||||
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
|
||||
new_item->setParent(new_parent);
|
||||
new_item->updateParentOnServer(TRUE);
|
||||
updateItem(new_item);
|
||||
notifyObservers();
|
||||
LL_WARNS("Inventory") << "couldn't find inventory item " << item_id << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
if (new_parent.notNull())
|
||||
{
|
||||
LL_INFOS("Inventory") << "Moving to Trash (" << new_parent << "):" << LL_ENDL;
|
||||
changeItemParent(item, new_parent, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryModel::removeCategory(const LLUUID& category_id)
|
||||
{
|
||||
if (! get_is_category_removable(this, category_id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Look for any gestures and deactivate them
|
||||
LLInventoryModel::cat_array_t descendent_categories;
|
||||
LLInventoryModel::item_array_t descendent_items;
|
||||
collectDescendents(category_id, descendent_categories, descendent_items, FALSE);
|
||||
|
||||
for (LLInventoryModel::item_array_t::const_iterator iter = descendent_items.begin();
|
||||
iter != descendent_items.end();
|
||||
++iter)
|
||||
{
|
||||
const LLViewerInventoryItem* item = (*iter);
|
||||
const LLUUID& item_id = item->getUUID();
|
||||
if (item->getType() == LLAssetType::AT_GESTURE
|
||||
&& LLGestureMgr::instance().isGestureActive(item_id))
|
||||
{
|
||||
LLGestureMgr::instance().deactivateGesture(item_id);
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerInventoryCategory* cat = getCategory(category_id);
|
||||
if (cat)
|
||||
{
|
||||
const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
|
||||
if (trash_id.notNull())
|
||||
{
|
||||
changeCategoryParent(cat, trash_id, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
const LLUUID &LLInventoryModel::getRootFolderID() const
|
||||
{
|
||||
return mRootFolderID;
|
||||
|
||||
@@ -316,6 +316,16 @@ public:
|
||||
// observer notification, or server update is performed.
|
||||
void moveObject(const LLUUID& object_id, const LLUUID& cat_id);
|
||||
|
||||
// Migrated from llinventoryfunctions
|
||||
void changeItemParent(LLViewerInventoryItem* item,
|
||||
const LLUUID& new_parent_id,
|
||||
BOOL restamp);
|
||||
|
||||
// Migrated from llinventoryfunctions
|
||||
void changeCategoryParent(LLViewerInventoryCategory* cat,
|
||||
const LLUUID& new_parent_id,
|
||||
BOOL restamp);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Delete
|
||||
//--------------------------------------------------------------------
|
||||
@@ -325,8 +335,13 @@ public:
|
||||
// consistent internal state. No cache accounting, observer
|
||||
// notification, or server update is performed.
|
||||
void deleteObject(const LLUUID& id);
|
||||
/// move Item item_id to Trash
|
||||
void removeItem(const LLUUID& item_id);
|
||||
|
||||
/// move Category category_id to Trash
|
||||
void removeCategory(const LLUUID& category_id);
|
||||
/// removeItem() or removeCategory(), whichever is appropriate
|
||||
void removeObject(const LLUUID& object_id);
|
||||
|
||||
// Delete a particular inventory object by ID, and delete it from
|
||||
// the server. Also updates linked items.
|
||||
void purgeObject(const LLUUID& id);
|
||||
|
||||
@@ -43,6 +43,7 @@ const S32 MAX_FETCH_RETRIES = 10;
|
||||
|
||||
LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() :
|
||||
mBackgroundFetchActive(FALSE),
|
||||
mFolderFetchActive(false),
|
||||
mAllFoldersFetched(FALSE),
|
||||
mRecursiveInventoryFetchStarted(FALSE),
|
||||
mRecursiveLibraryFetchStarted(FALSE),
|
||||
@@ -50,7 +51,7 @@ LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() :
|
||||
mMinTimeBetweenFetches(0.3f),
|
||||
mMaxTimeBetweenFetches(10.f),
|
||||
mTimelyFetchPending(FALSE),
|
||||
mBulkFetchCount(0)
|
||||
mFetchCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -60,7 +61,7 @@ LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch()
|
||||
|
||||
bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() const
|
||||
{
|
||||
return mFetchQueue.empty() && mBulkFetchCount<=0;
|
||||
return mFetchQueue.empty() && mFetchCount<=0;
|
||||
}
|
||||
|
||||
bool LLInventoryModelBackgroundFetch::libraryFetchStarted() const
|
||||
@@ -98,19 +99,21 @@ bool LLInventoryModelBackgroundFetch::isEverythingFetched() const
|
||||
return mAllFoldersFetched;
|
||||
}
|
||||
|
||||
BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive() const
|
||||
BOOL LLInventoryModelBackgroundFetch::folderFetchActive() const
|
||||
{
|
||||
return mBackgroundFetchActive;
|
||||
return mFolderFetchActive;
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive)
|
||||
void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive)
|
||||
{
|
||||
if (!mAllFoldersFetched || cat_id.notNull())
|
||||
{
|
||||
LL_DEBUGS("InventoryFetch") << "Start fetching category: " << cat_id << ", recursive: " << recursive << LL_ENDL;
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(id);
|
||||
if (cat || (id.isNull() && !isEverythingFetched()))
|
||||
{ // it's a folder, do a bulk fetch
|
||||
LL_DEBUGS("InventoryFetch") << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL;
|
||||
|
||||
mBackgroundFetchActive = TRUE;
|
||||
if (cat_id.isNull())
|
||||
mFolderFetchActive = true;
|
||||
if (id.isNull())
|
||||
{
|
||||
if (!mRecursiveInventoryFetchStarted)
|
||||
{
|
||||
@@ -128,42 +131,41 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive
|
||||
else
|
||||
{
|
||||
// Specific folder requests go to front of queue.
|
||||
if (mFetchQueue.empty() || mFetchQueue.front().mCatUUID != cat_id)
|
||||
if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)
|
||||
{
|
||||
mFetchQueue.push_front(FetchQueueInfo(cat_id, recursive));
|
||||
mFetchQueue.push_front(FetchQueueInfo(id, recursive));
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
if (cat_id == gInventory.getLibraryRootFolderID())
|
||||
if (id == gInventory.getLibraryRootFolderID())
|
||||
{
|
||||
mRecursiveLibraryFetchStarted |= recursive;
|
||||
}
|
||||
if (cat_id == gInventory.getRootFolderID())
|
||||
if (id == gInventory.getRootFolderID())
|
||||
{
|
||||
mRecursiveInventoryFetchStarted |= recursive;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (LLViewerInventoryItem* itemp = gInventory.getItem(id))
|
||||
{
|
||||
if (!itemp->mIsComplete && (mFetchQueue.empty() || mFetchQueue.front().mUUID != id))
|
||||
{
|
||||
mBackgroundFetchActive = TRUE;
|
||||
|
||||
mFetchQueue.push_front(FetchQueueInfo(id, false, false));
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLInventoryModelBackgroundFetch::findLostItems()
|
||||
{
|
||||
mBackgroundFetchActive = TRUE;
|
||||
mFolderFetchActive = true;
|
||||
mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, TRUE));
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::stopBackgroundFetch()
|
||||
{
|
||||
if (mBackgroundFetchActive)
|
||||
{
|
||||
mBackgroundFetchActive = FALSE;
|
||||
gIdleCallbacks.deleteFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
mBulkFetchCount=0;
|
||||
mMinTimeBetweenFetches=0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
|
||||
{
|
||||
if (mRecursiveInventoryFetchStarted &&
|
||||
@@ -171,7 +173,7 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched()
|
||||
{
|
||||
mAllFoldersFetched = TRUE;
|
||||
}
|
||||
stopBackgroundFetch();
|
||||
mFolderFetchActive = false;
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *)
|
||||
@@ -185,10 +187,9 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
|
||||
if (mBackgroundFetchActive && gAgent.getRegion())
|
||||
{
|
||||
// If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
|
||||
std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");
|
||||
if (gSavedSettings.getBOOL("UseHTTPInventory") && !url.empty())
|
||||
if (gSavedSettings.getBOOL("UseHTTPInventory"))
|
||||
{
|
||||
bulkFetch(url);
|
||||
bulkFetch();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -203,6 +204,9 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
|
||||
llinfos << "Inventory fetch completed" << llendl;
|
||||
|
||||
setAllFoldersFetched();
|
||||
mBackgroundFetchActive = false;
|
||||
mFolderFetchActive = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -232,79 +236,113 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
|
||||
}
|
||||
|
||||
const FetchQueueInfo info = mFetchQueue.front();
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(info.mCatUUID);
|
||||
|
||||
// category has been deleted, remove from queue.
|
||||
if (!cat)
|
||||
if (info.mIsCategory)
|
||||
{
|
||||
mFetchQueue.pop_front();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches &&
|
||||
LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
|
||||
{
|
||||
// category exists but has no children yet, fetch the descendants
|
||||
// for now, just request every time and rely on retry timer to throttle
|
||||
if (cat->fetch())
|
||||
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(info.mUUID);
|
||||
|
||||
// Category has been deleted, remove from queue.
|
||||
if (!cat)
|
||||
{
|
||||
mFetchQueue.pop_front();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches &&
|
||||
LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
|
||||
{
|
||||
// Category exists but has no children yet, fetch the descendants
|
||||
// for now, just request every time and rely on retry timer to throttle.
|
||||
if (cat->fetch())
|
||||
{
|
||||
mFetchTimer.reset();
|
||||
mTimelyFetchPending = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The catagory also tracks if it has expired and here it says it hasn't
|
||||
// yet. Get out of here because nothing is going to happen until we
|
||||
// update the timers.
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Do I have all my children?
|
||||
else if (gInventory.isCategoryComplete(info.mUUID))
|
||||
{
|
||||
// Finished with this category, remove from queue.
|
||||
mFetchQueue.pop_front();
|
||||
|
||||
// Add all children to queue.
|
||||
LLInventoryModel::cat_array_t* categories;
|
||||
gInventory.getDirectDescendentsOf(cat->getUUID(), categories);
|
||||
for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive));
|
||||
}
|
||||
|
||||
// We received a response in less than the fast time.
|
||||
if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time)
|
||||
{
|
||||
// Shrink timeouts based on success.
|
||||
mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f);
|
||||
mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f);
|
||||
lldebugs << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl;
|
||||
}
|
||||
|
||||
mTimelyFetchPending = FALSE;
|
||||
continue;
|
||||
}
|
||||
else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches)
|
||||
{
|
||||
// Received first packet, but our num descendants does not match db's num descendants
|
||||
// so try again later.
|
||||
mFetchQueue.pop_front();
|
||||
|
||||
if (mNumFetchRetries++ < MAX_FETCH_RETRIES)
|
||||
{
|
||||
// push on back of queue
|
||||
mFetchQueue.push_back(info);
|
||||
}
|
||||
mTimelyFetchPending = FALSE;
|
||||
mFetchTimer.reset();
|
||||
break;
|
||||
}
|
||||
|
||||
// Not enough time has elapsed to do a new fetch
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLViewerInventoryItem* itemp = gInventory.getItem(info.mUUID);
|
||||
|
||||
mFetchQueue.pop_front();
|
||||
if (!itemp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches)
|
||||
{
|
||||
itemp->fetchFromServer();
|
||||
mFetchTimer.reset();
|
||||
mTimelyFetchPending = TRUE;
|
||||
}
|
||||
else
|
||||
else if (itemp->mIsComplete)
|
||||
{
|
||||
// The catagory also tracks if it has expired and here it says it hasn't
|
||||
// yet. Get out of here because nothing is going to happen until we
|
||||
// update the timers.
|
||||
break;
|
||||
mTimelyFetchPending = FALSE;
|
||||
}
|
||||
}
|
||||
// do I have all my children?
|
||||
else if (gInventory.isCategoryComplete(info.mCatUUID))
|
||||
{
|
||||
// finished with this category, remove from queue
|
||||
mFetchQueue.pop_front();
|
||||
|
||||
// Add all children to queue.
|
||||
LLInventoryModel::cat_array_t* categories;
|
||||
gInventory.getDirectDescendentsOf(cat->getUUID(), categories);
|
||||
for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches)
|
||||
{
|
||||
mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive));
|
||||
}
|
||||
|
||||
// we received a response in less than the fast time
|
||||
if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time)
|
||||
{
|
||||
// shrink timeouts based on success
|
||||
mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f);
|
||||
mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f);
|
||||
lldebugs << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl;
|
||||
}
|
||||
|
||||
mTimelyFetchPending = FALSE;
|
||||
continue;
|
||||
}
|
||||
else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches)
|
||||
{
|
||||
// received first packet, but our num descendants does not match db's num descendants
|
||||
// so try again later.
|
||||
mFetchQueue.pop_front();
|
||||
|
||||
if (mNumFetchRetries++ < MAX_FETCH_RETRIES)
|
||||
{
|
||||
// push on back of queue
|
||||
mFetchQueue.push_back(info);
|
||||
mFetchTimer.reset();
|
||||
mTimelyFetchPending = FALSE;
|
||||
}
|
||||
mTimelyFetchPending = FALSE;
|
||||
mFetchTimer.reset();
|
||||
// Not enough time has elapsed to do a new fetch
|
||||
break;
|
||||
}
|
||||
|
||||
// not enough time has elapsed to do a new fetch
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -314,15 +352,35 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()
|
||||
}
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::incrBulkFetch(S16 fetching)
|
||||
void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching)
|
||||
{
|
||||
mBulkFetchCount += fetching;
|
||||
if (mBulkFetchCount < 0)
|
||||
mFetchCount += fetching;
|
||||
if (mFetchCount < 0)
|
||||
{
|
||||
mBulkFetchCount = 0;
|
||||
mFetchCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder
|
||||
{
|
||||
public:
|
||||
LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {};
|
||||
void result(const LLSD& content);
|
||||
void error(U32 status, const std::string& reason);
|
||||
};
|
||||
|
||||
void LLInventoryModelFetchItemResponder::result( const LLSD& content )
|
||||
{
|
||||
LLInventoryModel::fetchInventoryResponder::result(content);
|
||||
LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
|
||||
}
|
||||
|
||||
void LLInventoryModelFetchItemResponder::error( U32 status, const std::string& reason )
|
||||
{
|
||||
LLInventoryModel::fetchInventoryResponder::error(status, reason);
|
||||
LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
|
||||
}
|
||||
|
||||
|
||||
class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
|
||||
{
|
||||
@@ -459,7 +517,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)
|
||||
}
|
||||
}
|
||||
|
||||
fetcher->incrBulkFetch(-1);
|
||||
fetcher->incrFetchCount(-1);
|
||||
|
||||
if (fetcher->isBulkFetchProcessingComplete())
|
||||
{
|
||||
@@ -478,9 +536,9 @@ void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::str
|
||||
llinfos << "LLInventoryModelFetchDescendentsResponder::error "
|
||||
<< status << ": " << reason << llendl;
|
||||
|
||||
fetcher->incrBulkFetch(-1);
|
||||
fetcher->incrFetchCount(-1);
|
||||
|
||||
if (status==499) //timed out. Let's be awesome!
|
||||
if (status==499) // timed out
|
||||
{
|
||||
for(LLSD::array_const_iterator folder_it = mRequestSD["folders"].beginArray();
|
||||
folder_it != mRequestSD["folders"].endArray();
|
||||
@@ -509,27 +567,29 @@ BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat
|
||||
|
||||
// Bundle up a bunch of requests to send all at once.
|
||||
// static
|
||||
void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
|
||||
void LLInventoryModelBackgroundFetch::bulkFetch()
|
||||
{
|
||||
//Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped.
|
||||
//If there are items in sFetchQueue, we want to check the time since the last bulkFetch was
|
||||
//If there are items in mFetchQueue, we want to check the time since the last bulkFetch was
|
||||
//sent. If it exceeds our retry time, go ahead and fire off another batch.
|
||||
//Stopbackgroundfetch will be run from the Responder instead of here.
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
if (!region) return;
|
||||
|
||||
S16 max_concurrent_fetches=8;
|
||||
F32 new_min_time = 0.5f; //HACK! Clean this up when old code goes away entirely.
|
||||
if (mMinTimeBetweenFetches < new_min_time)
|
||||
if (mMinTimeBetweenFetches < new_min_time)
|
||||
{
|
||||
mMinTimeBetweenFetches=new_min_time; //HACK! See above.
|
||||
}
|
||||
|
||||
if (gDisconnected ||
|
||||
(mBulkFetchCount > max_concurrent_fetches) ||
|
||||
(mFetchCount > max_concurrent_fetches) ||
|
||||
(mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches))
|
||||
{
|
||||
return; // just bail if we are disconnected.
|
||||
return; // just bail if we are disconnected
|
||||
}
|
||||
|
||||
U32 item_count=0;
|
||||
U32 folder_count=0;
|
||||
U32 max_batch_size=5;
|
||||
|
||||
@@ -537,86 +597,163 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)
|
||||
|
||||
uuid_vec_t recursive_cats;
|
||||
|
||||
LLSD body;
|
||||
LLSD body_lib;
|
||||
LLSD folder_request_body;
|
||||
LLSD folder_request_body_lib;
|
||||
LLSD item_request_body;
|
||||
LLSD item_request_body_lib;
|
||||
|
||||
while( !(mFetchQueue.empty() ) && (folder_count < max_batch_size) )
|
||||
while (!mFetchQueue.empty()
|
||||
&& (item_count + folder_count) < max_batch_size)
|
||||
{
|
||||
const FetchQueueInfo& fetch_info = mFetchQueue.front();
|
||||
const LLUUID &cat_id = fetch_info.mCatUUID;
|
||||
if (cat_id.isNull()) //DEV-17797
|
||||
{
|
||||
LLSD folder_sd;
|
||||
folder_sd["folder_id"] = LLUUID::null.asString();
|
||||
folder_sd["owner_id"] = gAgent.getID();
|
||||
folder_sd["sort_order"] = (LLSD::Integer)sort_order;
|
||||
folder_sd["fetch_folders"] = (LLSD::Boolean)FALSE;
|
||||
folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
|
||||
body["folders"].append(folder_sd);
|
||||
folder_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
|
||||
if (fetch_info.mIsCategory)
|
||||
{
|
||||
const LLUUID &cat_id = fetch_info.mUUID;
|
||||
if (cat_id.isNull()) //DEV-17797
|
||||
{
|
||||
LLSD folder_sd;
|
||||
folder_sd["folder_id"] = LLUUID::null.asString();
|
||||
folder_sd["owner_id"] = gAgent.getID();
|
||||
folder_sd["sort_order"] = (LLSD::Integer)sort_order;
|
||||
folder_sd["fetch_folders"] = (LLSD::Boolean)FALSE;
|
||||
folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
|
||||
folder_request_body["folders"].append(folder_sd);
|
||||
folder_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
|
||||
|
||||
if (cat)
|
||||
{
|
||||
if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
|
||||
{
|
||||
LLSD folder_sd;
|
||||
folder_sd["folder_id"] = cat->getUUID();
|
||||
folder_sd["owner_id"] = cat->getOwnerID();
|
||||
folder_sd["sort_order"] = (LLSD::Integer)sort_order;
|
||||
folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted;
|
||||
folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
|
||||
|
||||
if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
|
||||
body_lib["folders"].append(folder_sd);
|
||||
else
|
||||
body["folders"].append(folder_sd);
|
||||
folder_count++;
|
||||
}
|
||||
// May already have this folder, but append child folders to list.
|
||||
if (fetch_info.mRecursive)
|
||||
{
|
||||
LLInventoryModel::cat_array_t* categories;
|
||||
gInventory.getDirectDescendentsOf(cat->getUUID(), categories);
|
||||
for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
if (cat)
|
||||
{
|
||||
if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())
|
||||
{
|
||||
mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fetch_info.mRecursive)
|
||||
recursive_cats.push_back(cat_id);
|
||||
LLSD folder_sd;
|
||||
folder_sd["folder_id"] = cat->getUUID();
|
||||
folder_sd["owner_id"] = cat->getOwnerID();
|
||||
folder_sd["sort_order"] = (LLSD::Integer)sort_order;
|
||||
folder_sd["fetch_folders"] = TRUE; //(LLSD::Boolean)sFullFetchStarted;
|
||||
folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
|
||||
|
||||
if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
|
||||
folder_request_body_lib["folders"].append(folder_sd);
|
||||
else
|
||||
folder_request_body["folders"].append(folder_sd);
|
||||
folder_count++;
|
||||
}
|
||||
// May already have this folder, but append child folders to list.
|
||||
if (fetch_info.mRecursive)
|
||||
{
|
||||
LLInventoryModel::cat_array_t* categories;
|
||||
LLInventoryModel::item_array_t* items;
|
||||
gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items);
|
||||
for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fetch_info.mRecursive)
|
||||
recursive_cats.push_back(cat_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLViewerInventoryItem* itemp = gInventory.getItem(fetch_info.mUUID);
|
||||
if (itemp)
|
||||
{
|
||||
LLSD item_sd;
|
||||
item_sd["owner_id"] = itemp->getPermissions().getOwner();
|
||||
item_sd["item_id"] = itemp->getUUID();
|
||||
if (itemp->getPermissions().getOwner() == gAgent.getID())
|
||||
{
|
||||
item_request_body.append(item_sd);
|
||||
}
|
||||
else
|
||||
{
|
||||
item_request_body_lib.append(item_sd);
|
||||
}
|
||||
//itemp->fetchFromServer();
|
||||
item_count++;
|
||||
}
|
||||
}
|
||||
|
||||
mFetchQueue.pop_front();
|
||||
}
|
||||
|
||||
if (folder_count > 0)
|
||||
if (item_count + folder_count > 0)
|
||||
{
|
||||
mBulkFetchCount++;
|
||||
if (body["folders"].size())
|
||||
if (folder_count)
|
||||
{
|
||||
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body, recursive_cats);
|
||||
LLHTTPClient::post(url, body, fetcher, 300.0);
|
||||
std::string url = region->getCapability("FetchInventoryDescendents2");
|
||||
mFetchCount++;
|
||||
if (folder_request_body["folders"].size())
|
||||
{
|
||||
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats);
|
||||
LLHTTPClient::post(url, folder_request_body, fetcher, 300.0);
|
||||
}
|
||||
if (folder_request_body_lib["folders"].size())
|
||||
{
|
||||
std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
|
||||
|
||||
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats);
|
||||
LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0);
|
||||
}
|
||||
}
|
||||
if (body_lib["folders"].size())
|
||||
if (item_count)
|
||||
{
|
||||
std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2");
|
||||
|
||||
LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats);
|
||||
LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0);
|
||||
std::string url;
|
||||
|
||||
if (item_request_body.size())
|
||||
{
|
||||
mFetchCount++;
|
||||
url = region->getCapability("FetchInventory2");
|
||||
if (!url.empty())
|
||||
{
|
||||
LLSD body;
|
||||
body["agent_id"] = gAgent.getID();
|
||||
body["items"] = item_request_body;
|
||||
|
||||
LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// LLMessageSystem* msg = gMessageSystem;
|
||||
// msg->newMessage("FetchInventory");
|
||||
// msg->nextBlock("AgentData");
|
||||
// msg->addUUID("AgentID", gAgent.getID());
|
||||
// msg->addUUID("SessionID", gAgent.getSessionID());
|
||||
// msg->nextBlock("InventoryData");
|
||||
// msg->addUUID("OwnerID", mPermissions.getOwner());
|
||||
// msg->addUUID("ItemID", mUUID);
|
||||
// gAgent.sendReliableMessage();
|
||||
//}
|
||||
}
|
||||
|
||||
if (item_request_body_lib.size())
|
||||
{
|
||||
mFetchCount++;
|
||||
|
||||
url = region->getCapability("FetchLib2");
|
||||
if (!url.empty())
|
||||
{
|
||||
LLSD body;
|
||||
body["agent_id"] = gAgent.getID();
|
||||
body["items"] = item_request_body_lib;
|
||||
|
||||
LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body));
|
||||
}
|
||||
}
|
||||
}
|
||||
mFetchTimer.reset();
|
||||
}
|
||||
|
||||
else if (isBulkFetchProcessingComplete())
|
||||
{
|
||||
setAllFoldersFetched();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const
|
||||
@@ -624,7 +761,7 @@ bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LL
|
||||
for (fetch_queue_t::const_iterator it = mFetchQueue.begin();
|
||||
it != mFetchQueue.end(); ++it)
|
||||
{
|
||||
const LLUUID& fetch_id = (*it).mCatUUID;
|
||||
const LLUUID& fetch_id = (*it).mUUID;
|
||||
if (gInventory.isObjectDescendentOf(fetch_id, cat_id))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
// This gets triggered when performing a filter-search.
|
||||
void start(const LLUUID& cat_id = LLUUID::null, BOOL recursive = TRUE);
|
||||
|
||||
BOOL backgroundFetchActive() const;
|
||||
BOOL folderFetchActive() const;
|
||||
bool isEverythingFetched() const; // completing the fetch once per session should be sufficient
|
||||
|
||||
bool libraryFetchStarted() const;
|
||||
@@ -60,14 +60,13 @@ public:
|
||||
bool inventoryFetchInProgress() const;
|
||||
|
||||
void findLostItems();
|
||||
void incrFetchCount(S16 fetching);
|
||||
protected:
|
||||
void incrBulkFetch(S16 fetching);
|
||||
bool isBulkFetchProcessingComplete() const;
|
||||
void bulkFetch(std::string url);
|
||||
void bulkFetch();
|
||||
|
||||
void backgroundFetch();
|
||||
static void backgroundFetchCB(void*); // background fetch idle function
|
||||
void stopBackgroundFetch(); // stop fetch process
|
||||
|
||||
void setAllFoldersFetched();
|
||||
bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const;
|
||||
@@ -77,7 +76,8 @@ private:
|
||||
BOOL mAllFoldersFetched;
|
||||
|
||||
BOOL mBackgroundFetchActive;
|
||||
S16 mBulkFetchCount;
|
||||
bool mFolderFetchActive;
|
||||
S16 mFetchCount;
|
||||
BOOL mTimelyFetchPending;
|
||||
S32 mNumFetchRetries;
|
||||
|
||||
@@ -87,11 +87,11 @@ private:
|
||||
|
||||
struct FetchQueueInfo
|
||||
{
|
||||
FetchQueueInfo(const LLUUID& id, BOOL recursive) :
|
||||
mCatUUID(id), mRecursive(recursive)
|
||||
{
|
||||
}
|
||||
LLUUID mCatUUID;
|
||||
FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true) :
|
||||
mUUID(id), mRecursive(recursive), mIsCategory(is_category)
|
||||
{}
|
||||
LLUUID mUUID;
|
||||
bool mIsCategory;
|
||||
BOOL mRecursive;
|
||||
};
|
||||
typedef std::deque<FetchQueueInfo> fetch_queue_t;
|
||||
|
||||
@@ -841,7 +841,7 @@ BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)
|
||||
if(handled)
|
||||
{
|
||||
ECursorType cursor = getWindow()->getCursor();
|
||||
if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && cursor == UI_CURSOR_ARROW)
|
||||
if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() && cursor == UI_CURSOR_ARROW)
|
||||
{
|
||||
// replace arrow cursor with arrow and hourglass cursor
|
||||
getWindow()->setCursor(UI_CURSOR_WORKING);
|
||||
|
||||
@@ -1598,7 +1598,11 @@ void LLManipTranslate::renderSnapGuides()
|
||||
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER);
|
||||
LLGLEnable stipple(GL_LINE_STIPPLE);
|
||||
gGL.flush();
|
||||
glLineStipple(1, 0x3333);
|
||||
|
||||
if (!LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
glLineStipple(1, 0x3333);
|
||||
}
|
||||
|
||||
switch (mManipPart)
|
||||
{
|
||||
@@ -1712,16 +1716,20 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,
|
||||
gClipProgram.uniform4fv("clip_plane", 1, plane.v);
|
||||
|
||||
BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
|
||||
#if ENABLE_CLASSIC_CLOUDS
|
||||
BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS);
|
||||
#endif
|
||||
|
||||
if (particles)
|
||||
{
|
||||
LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
|
||||
}
|
||||
#if ENABLE_CLASSIC_CLOUDS
|
||||
if (clouds)
|
||||
{
|
||||
LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS);
|
||||
}
|
||||
#endif
|
||||
|
||||
//stencil in volumes
|
||||
glStencilOp(GL_INCR, GL_INCR, GL_INCR);
|
||||
@@ -1742,10 +1750,12 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,
|
||||
{
|
||||
LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES);
|
||||
}
|
||||
#if ENABLE_CLASSIC_CLOUDS
|
||||
if (clouds)
|
||||
{
|
||||
LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS);
|
||||
}
|
||||
#endif
|
||||
|
||||
gGL.setColorMask(true, false);
|
||||
}
|
||||
|
||||
@@ -521,9 +521,11 @@ void LLMeshRepoThread::run()
|
||||
mLODReqQ.pop();
|
||||
LLMeshRepository::sLODProcessing--;
|
||||
mMutex->unlock();
|
||||
if (fetchMeshLOD(req.mMeshParams, req.mLOD))
|
||||
if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit
|
||||
{
|
||||
count++;
|
||||
mMutex->lock();
|
||||
mLODReqQ.push(req) ;
|
||||
mMutex->unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -536,9 +538,11 @@ void LLMeshRepoThread::run()
|
||||
HeaderRequest req = mHeaderReqQ.front();
|
||||
mHeaderReqQ.pop();
|
||||
mMutex->unlock();
|
||||
if (fetchMeshHeader(req.mMeshParams))
|
||||
if (!fetchMeshHeader(req.mMeshParams, count))//failed, resubmit
|
||||
{
|
||||
count++;
|
||||
mMutex->lock();
|
||||
mHeaderReqQ.push(req) ;
|
||||
mMutex->unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -691,8 +695,9 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = true ;
|
||||
U32 header_size = mMeshHeaderSize[mesh_id];
|
||||
|
||||
|
||||
if (header_size > 0)
|
||||
{
|
||||
S32 version = mMeshHeader[mesh_id]["version"].asInteger();
|
||||
@@ -737,10 +742,13 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
|
||||
|
||||
std::string http_url = constructUrl(mesh_id);
|
||||
if (!http_url.empty())
|
||||
{
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
|
||||
new LLMeshSkinInfoResponder(mesh_id, offset, size));
|
||||
{
|
||||
ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
|
||||
new LLMeshSkinInfoResponder(mesh_id, offset, size));
|
||||
if(ret)
|
||||
{
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -750,7 +758,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
|
||||
}
|
||||
|
||||
//early out was not hit, effectively fetched
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
|
||||
@@ -769,7 +777,8 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
|
||||
}
|
||||
|
||||
U32 header_size = mMeshHeaderSize[mesh_id];
|
||||
|
||||
bool ret = true ;
|
||||
|
||||
if (header_size > 0)
|
||||
{
|
||||
S32 version = mMeshHeader[mesh_id]["version"].asInteger();
|
||||
@@ -814,10 +823,13 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
|
||||
|
||||
std::string http_url = constructUrl(mesh_id);
|
||||
if (!http_url.empty())
|
||||
{
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
mCurlRequest->getByteRange(http_url, headers, offset, size,
|
||||
new LLMeshDecompositionResponder(mesh_id, offset, size));
|
||||
{
|
||||
ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
|
||||
new LLMeshDecompositionResponder(mesh_id, offset, size));
|
||||
if(ret)
|
||||
{
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -827,7 +839,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
|
||||
}
|
||||
|
||||
//early out was not hit, effectively fetched
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
|
||||
@@ -840,12 +852,13 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
|
||||
mHeaderMutex->lock();
|
||||
|
||||
if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
|
||||
{ //we have no header info for this mesh, do nothing
|
||||
{ //we have no header info for this mesh, do nothing
|
||||
mHeaderMutex->unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
U32 header_size = mMeshHeaderSize[mesh_id];
|
||||
bool ret = true ;
|
||||
|
||||
if (header_size > 0)
|
||||
{
|
||||
@@ -891,14 +904,18 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
|
||||
|
||||
std::string http_url = constructUrl(mesh_id);
|
||||
if (!http_url.empty())
|
||||
{
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
mCurlRequest->getByteRange(http_url, headers, offset, size,
|
||||
new LLMeshPhysicsShapeResponder(mesh_id, offset, size));
|
||||
{
|
||||
ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
|
||||
new LLMeshPhysicsShapeResponder(mesh_id, offset, size));
|
||||
|
||||
if(ret)
|
||||
{
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //no physics shape whatsoever, report back NULL
|
||||
{ //no physics shape whatsoever, report back NULL
|
||||
physicsShapeReceived(mesh_id, NULL, 0);
|
||||
}
|
||||
}
|
||||
@@ -908,13 +925,12 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
|
||||
}
|
||||
|
||||
//early out was not hit, effectively fetched
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
|
||||
//return false if failed to get header
|
||||
bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count)
|
||||
{
|
||||
bool retval = false;
|
||||
|
||||
{
|
||||
//look for mesh in asset in vfs
|
||||
LLVFile file(gVFS, mesh_params.getSculptID(), LLAssetType::AT_MESH);
|
||||
@@ -928,32 +944,37 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
|
||||
LLMeshRepository::sCacheBytesRead += bytes;
|
||||
file.read(buffer, bytes);
|
||||
if (headerReceived(mesh_params, buffer, bytes))
|
||||
{ //did not do an HTTP request, return false
|
||||
return false;
|
||||
{ //did not do an HTTP request, return false
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//either cache entry doesn't exist or is corrupt, request header from simulator
|
||||
|
||||
//either cache entry doesn't exist or is corrupt, request header from simulator
|
||||
bool retval = true ;
|
||||
std::vector<std::string> headers;
|
||||
headers.push_back("Accept: application/octet-stream");
|
||||
|
||||
std::string http_url = constructUrl(mesh_params.getSculptID());
|
||||
if (!http_url.empty())
|
||||
{
|
||||
retval = true;
|
||||
//grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits
|
||||
//within the first 4KB
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params));
|
||||
//NOTE -- this will break of headers ever exceed 4KB
|
||||
retval = mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params));
|
||||
if(retval)
|
||||
{
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
|
||||
{ //protected by mMutex
|
||||
//return false if failed to get mesh lod.
|
||||
bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count)
|
||||
{ //protected by mMutex
|
||||
if (!mHeaderMutex)
|
||||
{
|
||||
return false;
|
||||
@@ -961,7 +982,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
|
||||
|
||||
mHeaderMutex->lock();
|
||||
|
||||
bool retval = false;
|
||||
bool retval = true;
|
||||
|
||||
LLUUID mesh_id = mesh_params.getSculptID();
|
||||
|
||||
@@ -998,7 +1019,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
|
||||
if (lodReceived(mesh_params, lod, buffer, size))
|
||||
{
|
||||
delete[] buffer;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1011,11 +1032,15 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
|
||||
|
||||
std::string http_url = constructUrl(mesh_id);
|
||||
if (!http_url.empty())
|
||||
{
|
||||
retval = true;
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
|
||||
{
|
||||
retval = mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
|
||||
new LLMeshLODResponder(mesh_params, lod, offset, size));
|
||||
|
||||
if(retval)
|
||||
{
|
||||
LLMeshRepository::sHTTPRequestCount++;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2212,6 +2237,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
|
||||
//first request for this mesh
|
||||
mLoadingMeshes[detail][mesh_params].insert(vobj->getID());
|
||||
mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail));
|
||||
LLMeshRepository::sLODPending++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3228,7 +3254,6 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
|
||||
|
||||
LLCDMeshData mesh;
|
||||
|
||||
#if 1
|
||||
setMeshData(mesh, true);
|
||||
|
||||
LLCDResult ret = decomp->buildSingleHull() ;
|
||||
@@ -3264,88 +3289,6 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
|
||||
mCurRequest->mHull[0] = p;
|
||||
mMutex->unlock();
|
||||
}
|
||||
#else
|
||||
setMeshData(mesh, false);
|
||||
|
||||
//set all parameters to default
|
||||
std::map<std::string, const LLCDParam*> param_map;
|
||||
|
||||
static const LLCDParam* params = NULL;
|
||||
static S32 param_count = 0;
|
||||
|
||||
if (!params)
|
||||
{
|
||||
param_count = decomp->getParameters(¶ms);
|
||||
}
|
||||
|
||||
for (S32 i = 0; i < param_count; ++i)
|
||||
{
|
||||
decomp->setParam(params[i].mName, params[i].mDefault.mIntOrEnumValue);
|
||||
}
|
||||
|
||||
const S32 STAGE_DECOMPOSE = mStageID["Decompose"];
|
||||
const S32 STAGE_SIMPLIFY = mStageID["Simplify"];
|
||||
const S32 DECOMP_PREVIEW = 0;
|
||||
const S32 SIMPLIFY_RETAIN = 0;
|
||||
|
||||
decomp->setParam("Decompose Quality", DECOMP_PREVIEW);
|
||||
decomp->setParam("Simplify Method", SIMPLIFY_RETAIN);
|
||||
decomp->setParam("Retain%", 0.f);
|
||||
|
||||
LLCDResult ret = LLCD_OK;
|
||||
ret = decomp->executeStage(STAGE_DECOMPOSE);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
llwarns << "Could not execute decomposition stage when attempting to create single hull." << llendl;
|
||||
make_box(mCurRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = decomp->executeStage(STAGE_SIMPLIFY);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
llwarns << "Could not execute simiplification stage when attempting to create single hull." << llendl;
|
||||
make_box(mCurRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 num_hulls =0;
|
||||
if (LLConvexDecomposition::getInstance() != NULL)
|
||||
{
|
||||
num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(STAGE_SIMPLIFY);
|
||||
}
|
||||
|
||||
mMutex->lock();
|
||||
mCurRequest->mHull.clear();
|
||||
mCurRequest->mHull.resize(num_hulls);
|
||||
mCurRequest->mHullMesh.clear();
|
||||
mMutex->unlock();
|
||||
|
||||
for (S32 i = 0; i < num_hulls; ++i)
|
||||
{
|
||||
std::vector<LLVector3> p;
|
||||
LLCDHull hull;
|
||||
// if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code
|
||||
LLConvexDecomposition::getInstance()->getHullFromStage(STAGE_SIMPLIFY, i, &hull);
|
||||
|
||||
const F32* v = hull.mVertexBase;
|
||||
|
||||
for (S32 j = 0; j < hull.mNumVertices; ++j)
|
||||
{
|
||||
LLVector3 vert(v[0], v[1], v[2]);
|
||||
p.push_back(vert);
|
||||
v = (F32*) (((U8*) v) + hull.mVertexStrideBytes);
|
||||
}
|
||||
|
||||
mMutex->lock();
|
||||
mCurRequest->mHull[i] = p;
|
||||
mMutex->unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
completeCurrent();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user