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:
Siana Gearz
2012-07-03 07:49:22 +02:00
170 changed files with 8686 additions and 5913 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 );

View File

@@ -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; }

View File

@@ -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)

View File

@@ -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());

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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++)
{

View File

@@ -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
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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]);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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.

View File

@@ -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)

View File

@@ -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;

View File

@@ -152,6 +152,7 @@ protected:
U32 mResX;
U32 mResY;
std::vector<U32> mTex;
std::vector<U32> mInternalFormat;
U32 mFBO;
U32 mDepth;
bool mStencil;

View File

@@ -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");

View File

@@ -97,6 +97,8 @@ public:
LIGHT_CENTER,
LIGHT_SIZE,
LIGHT_FALLOFF,
BOX_CENTER,
BOX_SIZE,
GLOW_MIN_LUMINANCE,
GLOW_MAX_EXTRACT_ALPHA,

View File

@@ -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)
{

View File

@@ -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; }

View File

@@ -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 )
{

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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())

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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);

View File

@@ -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);

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}
};

View File

@@ -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);

View File

@@ -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;

View File

@@ -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();

View File

@@ -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():

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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];

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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;

View File

@@ -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)

View File

@@ -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();

View File

@@ -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

View File

@@ -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

View File

@@ -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 ];

View File

@@ -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()

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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());
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -1049,7 +1049,7 @@ void LLFolderViewItem::draw()
}
if ((mIsLoading
&& mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime"))
|| (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()
|| (LLInventoryModelBackgroundFetch::instance().folderFetchActive()
&& root_is_loading
&& mShowLoadStatus))
{

View File

@@ -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);
}

View File

@@ -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) ||

View File

@@ -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)
{

View File

@@ -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());
}
}

View File

@@ -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.

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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(&params);
}
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